1 /* Written by Rudolf Cornelissen 05/2002-5/2009 */ 2 3 /* Note on 'missing features' in BeOS 5.0.3 and DANO: 4 * BeOS needs to define more colorspaces! It would be nice if BeOS would support the FourCC 'definitions' 5 * of colorspaces. These colorspaces are 32bit words, so it could be simply done (or is it already so?) 6 */ 7 8 #define MODULE_BIT 0x00000400 9 10 #include "acc_std.h" 11 12 /* define the supported overlay input colorspaces */ 13 /* It would be nice to have the YUV4:2:0 2-plane mode implemented also later on, but the Be colorspace 14 * definitions (in GraphicsDefs.h, R5.0.3 and DANO5.1d0) do not include this one... */ 15 static uint32 overlay_colorspaces [] = { (uint32)B_YCbCr422, (uint32)B_NO_COLOR_SPACE }; 16 17 uint32 OVERLAY_COUNT(const display_mode *dm) 18 // This method is never used AFAIK though it *is* exported on R5.0.3 and DANO. 19 // Does someone know howto invoke it? 20 { 21 LOG(4,("Overlay: count called\n")); 22 23 /* check for NULL pointer */ 24 if (dm == NULL) 25 { 26 LOG(4,("Overlay: No display mode specified!\n")); 27 } 28 /* apparantly overlay count should report the number of 'overlay units' on the card */ 29 return 1; 30 } 31 32 const uint32 *OVERLAY_SUPPORTED_SPACES(const display_mode *dm) 33 // This method is never used AFAIK though it *is* exported on R5.0.3 and DANO. 34 // Does someone know howto invoke it? 35 { 36 LOG(4,("Overlay: supported_spaces called.\n")); 37 38 /* check for NULL pointer */ 39 if (dm == NULL) 40 { 41 LOG(4,("Overlay: No display mode specified!\n")); 42 return NULL; 43 } 44 45 /* assuming interlaced VGA is not supported */ 46 if (dm->timing.flags & B_TIMING_INTERLACED) 47 { 48 return NULL; 49 } 50 /* return a B_NO_COLOR_SPACE terminated list */ 51 return &overlay_colorspaces[0]; 52 } 53 54 uint32 OVERLAY_SUPPORTED_FEATURES(uint32 a_color_space) 55 // This method is never used AFAIK. On R5.0.3 and DANO it is not even exported! 56 { 57 LOG(4,("Overlay: supported_features: color_space $%08x\n",a_color_space)); 58 59 /* check what features are supported for the current overlaybitmap colorspace */ 60 switch (a_color_space) 61 { 62 default: 63 return 64 ( B_OVERLAY_KEYING_USES_ALPHA | 65 B_OVERLAY_COLOR_KEY | 66 B_OVERLAY_HORIZONTAL_FILTERING | 67 B_OVERLAY_VERTICAL_FILTERING ); 68 } 69 } 70 71 72 const overlay_buffer *ALLOCATE_OVERLAY_BUFFER(color_space cs, uint16 width, 73 uint16 height) 74 { 75 int offset = 0; /* used to determine next buffer to create */ 76 uintptr_t adress, adress2, temp32; /* used to calculate buffer adresses */ 77 uint32 oldsize = 0; /* used to 'squeeze' new buffers between already existing ones */ 78 int cnt; /* loopcounter */ 79 80 /* acquire the shared benaphore */ 81 AQUIRE_BEN(si->overlay.lock) 82 83 LOG(4, ("Overlay: cardRAM_start = $%p\n", (uint8*)si->framebuffer)); 84 LOG(4, ("Overlay: cardRAM_start_DMA = $%p\n", (uint8*)si->framebuffer_pci)); 85 LOG(4, ("Overlay: cardRAM_size = %3.3fMb\n", (si->ps.memory_size / (1024.0 * 1024.0)))); 86 87 /* find first empty slot (room for another buffer?) */ 88 for (offset = 0; offset < MAXBUFFERS; offset++) 89 { 90 if (si->overlay.myBuffer[offset].buffer == NULL) break; 91 } 92 93 LOG(4, ("Overlay: Allocate_buffer offset = %d\n", offset)); 94 95 if (offset < MAXBUFFERS) 96 /* setup new scaler input buffer */ 97 { 98 switch (cs) 99 { 100 case B_YCbCr422: 101 if (si->ps.card_arch < NV10A) 102 { 103 /* check if slopspace is needed: RIVA128 and TNT need ~0x000f. */ 104 si->overlay.myBuffer[offset].width = ((width + 0x000f) & ~0x000f); 105 } else { 106 /* check if slopspace is needed: GeForce need ~0x001f. */ 107 /* fixme: 108 * update needed for GF DVDmax support to adhere to CRTC2 constraints?? */ 109 si->overlay.myBuffer[offset].width = ((width + 0x001f) & ~0x001f); 110 } 111 si->overlay.myBuffer[offset].bytes_per_row = 2 * si->overlay.myBuffer[offset].width; 112 113 /* check if the requested horizontal pitch is supported: */ 114 //fixme: tune for GF and TNT... 115 if (si->overlay.myBuffer[offset].width > 4088) 116 { 117 LOG(4, ("Overlay: Sorry, requested buffer pitch not supported, aborted\n")); 118 119 /* release the shared benaphore */ 120 RELEASE_BEN(si->overlay.lock) 121 122 return NULL; 123 } 124 break; 125 default: 126 /* unsupported colorspace! */ 127 LOG(4, ("Overlay: Sorry, colorspace $%08x not supported, aborted\n",cs)); 128 129 /* release the shared benaphore */ 130 RELEASE_BEN(si->overlay.lock) 131 132 return NULL; 133 break; 134 } 135 136 /* checkout input picture size */ 137 switch (si->ps.card_arch) { 138 case NV04A: 139 /* all DVD's are OK, but HDTV 1280x720p is not: it displays ghost images 140 * (still find exact limit..) */ 141 142 /* check if the requested buffer width is supported */ 143 if (si->overlay.myBuffer[offset].width > 1024) { 144 LOG(4, ("Overlay: Sorry, requested buffer width not supported, aborted\n")); 145 146 /* release the shared benaphore */ 147 RELEASE_BEN(si->overlay.lock) 148 return NULL; 149 } 150 /* check if the requested buffer height is supported */ 151 if (height > 1024) { 152 LOG(4, ("Overlay: Sorry, requested buffer height not supported, aborted\n")); 153 154 /* release the shared benaphore */ 155 RELEASE_BEN(si->overlay.lock) 156 return NULL; 157 } 158 break; 159 default: 160 /* HDTV 1920x1080p is confirmed OK on NV11 and higher cards */ 161 162 /* check if the requested buffer width is supported */ 163 if (si->overlay.myBuffer[offset].width > 1920) { 164 LOG(4, ("Overlay: Sorry, requested buffer width not supported, aborted\n")); 165 166 /* release the shared benaphore */ 167 RELEASE_BEN(si->overlay.lock) 168 return NULL; 169 } 170 /* check if the requested buffer height is supported */ 171 if (height > 1080) { 172 LOG(4, ("Overlay: Sorry, requested buffer height not supported, aborted\n")); 173 174 /* release the shared benaphore */ 175 RELEASE_BEN(si->overlay.lock) 176 return NULL; 177 } 178 break; 179 } 180 181 /* store slopspace (in pixels) for each bitmap for use by 'overlay unit' (BES) */ 182 si->overlay.myBufInfo[offset].slopspace = si->overlay.myBuffer[offset].width - width; 183 184 si->overlay.myBuffer[offset].space = cs; 185 si->overlay.myBuffer[offset].height = height; 186 187 /* we define the overlay buffers to reside 'in the back' of the cards RAM */ 188 /* NOTE to app programmers: 189 * Beware that an app using overlay needs to track workspace switches and screenprefs 190 * changes. If such an action is detected, the app needs to reset it's pointers to the 191 * newly created overlay bitmaps, which will be assigned by BeOS automatically after such 192 * an event. (Also the app needs to respect the new overlay_constraints that will be applicable!) 193 * 194 * It is entirely possible that new bitmaps may *not* be re-setup at all, or less of them 195 * than previously setup by the app might be re-setup. This is due to cardRAM restraints then. 196 * This means that the app should also check for NULL pointers returned by the bitmaps, 197 * and if this happens, it needs to fallback to single buffered overlay or even fallback to 198 * bitmap output for the new situation. */ 199 200 /* Another NOTE for app programmers: 201 * A *positive* side-effect of assigning the first overlay buffer exactly at the end of the 202 * cardRAM is that apps that try to write beyond the buffer's space get a segfault immediately. 203 * This *greatly* simplifies tracking such errors! 204 * Of course such errors may lead to strange effects in the app or driver behaviour if they are 205 * not hunted down and removed.. */ 206 207 /* calculate first free RAM adress in card: 208 * Driver setup is as follows: 209 * card base: - hardware cursor bitmap (if used), 210 * directly above - screen memory for both heads */ 211 adress2 = (((uintptr_t)((uint8*)si->fbc.frame_buffer)) + /* cursor already included here */ 212 (si->fbc.bytes_per_row * si->dm.virtual_height)); /* size in bytes of screen(s) */ 213 LOG(4, ("Overlay: first free cardRAM virtual adress $%08x\n", adress2)); 214 215 /* calculate 'preliminary' buffer size including slopspace */ 216 oldsize = si->overlay.myBufInfo[offset].size; 217 si->overlay.myBufInfo[offset].size 218 = si->overlay.myBuffer[offset].bytes_per_row * si->overlay.myBuffer[offset].height; 219 220 /* calculate virtual memory adress that would be needed for a new bitmap */ 221 /* NOTE to app programmers: 222 * For testing app behaviour regarding workspace switches or screen prefs changes to settings 223 * that do not have enough cardRAM left for allocation of overlay bitmaps, you need a card with 224 * a low amount of RAM. Or you can set in the file nv.settings for example: 225 * memory 8 #8Mb RAM on card 226 * and reboot (this simulates 8Mb RAM on the card). 227 * 228 * If you switch now to settings: 1600x1200x32bit (single head) the app needs to fallback to 229 * bitmap output or maybe single buffered overlay output if small bitmaps are used. */ 230 231 adress = (((uintptr_t)((uint8*)si->framebuffer)) + si->ps.memory_size); 232 /* Keep some extra distance as a workaround for certain bugs (see 233 * DriverInterface.h for an explanation). */ 234 if (si->ps.card_arch < NV40A) 235 adress -= PRE_NV40_OFFSET; 236 else 237 adress -= NV40_PLUS_OFFSET; 238 239 for (cnt = 0; cnt <= offset; cnt++) 240 { 241 adress -= si->overlay.myBufInfo[cnt].size; 242 } 243 244 /* the > G200 scalers require buffers to be aligned to 16 byte pages cardRAM offset, G200 can do with 245 * 8 byte pages cardRAM offset. Compatible settings used, has no real downside consequences here */ 246 247 /* Check if we need to modify the buffers starting adress and thus the size */ 248 /* calculate 'would be' cardRAM offset */ 249 temp32 = (adress - ((uintptr_t)((vuint32 *)si->framebuffer))); 250 /* check if it is aligned */ 251 if (temp32 != (temp32 & 0xfffffff0)) 252 { 253 /* update the (already calculated) buffersize to get it aligned */ 254 si->overlay.myBufInfo[offset].size += (temp32 - (temp32 & 0xfffffff0)); 255 /* update the (already calculated) adress to get it aligned */ 256 adress -= (temp32 - (temp32 & 0xfffffff0)); 257 } 258 LOG(4, ("Overlay: new buffer needs virtual adress $%08x\n", adress)); 259 260 /* First check now if buffer to be defined is 'last one' in memory (speaking backwards): 261 * this is done to prevent a large buffer getting created in the space a small buffer 262 * occupied earlier, if not all buffers created were deleted. 263 * Note also that the app can delete the buffers in any order desired. */ 264 265 /* NOTE to app programmers: 266 * If you are going to delete a overlay buffer you created, you should delete them *all* and 267 * then re-create only the new ones needed. This way you are sure not to get unused memory- 268 * space in between your overlay buffers for instance, so cardRAM is used 'to the max'. 269 * If you don't, you might not get a buffer at all if you are trying to set up a larger one 270 * than before. 271 * (Indeed: not all buffers *have* to be of the same type and size...) */ 272 273 for (cnt = offset; cnt < MAXBUFFERS; cnt++) 274 { 275 if (si->overlay.myBuffer[cnt].buffer != NULL) 276 { 277 /* Check if the new buffer would fit into the space the single old one used here */ 278 if (si->overlay.myBufInfo[offset].size <= oldsize) 279 { 280 /* It does, so we reset to the old size and adresses to prevent the space from shrinking 281 * if we get here again... */ 282 adress -= (oldsize - si->overlay.myBufInfo[offset].size); 283 si->overlay.myBufInfo[offset].size = oldsize; 284 LOG(4,("Overlay: 'squeezing' in buffer:\n" 285 "Overlay: resetting it to virtual adress $%08x and size $%08x\n", adress,oldsize)); 286 /* force exiting the FOR loop */ 287 cnt = MAXBUFFERS; 288 } else { 289 /* nogo, sorry */ 290 LOG(4, ("Overlay: Other buffer(s) exist after this one:\n" 291 "Overlay: not enough space to 'squeeze' this one in, aborted\n")); 292 293 /* Reset to the old size to prevent the space from 'growing' if we get here again... */ 294 si->overlay.myBufInfo[offset].size = oldsize; 295 296 /* release the shared benaphore */ 297 RELEASE_BEN(si->overlay.lock) 298 299 return NULL; 300 } 301 } 302 } 303 304 /* check if we have enough space to setup this new bitmap 305 * (preventing overlap of desktop RAMspace & overlay bitmap RAMspace here) */ 306 if (adress < adress2) 307 /* nope, sorry */ 308 { 309 LOG(4, ("Overlay: Sorry, no more space for buffers: aborted\n")); 310 311 /* release the shared benaphore */ 312 RELEASE_BEN(si->overlay.lock) 313 314 return NULL; 315 } 316 /* continue buffer setup */ 317 si->overlay.myBuffer[offset].buffer = (void *) adress; 318 319 /* calculate physical memory adress (for dma use) */ 320 adress = (((uintptr_t)((uint8*)si->framebuffer_pci)) + si->ps.memory_size); 321 /* Keep some extra distance as a workaround for certain bugs (see 322 * DriverInterface.h for an explanation). */ 323 if (si->ps.card_arch < NV40A) 324 adress -= PRE_NV40_OFFSET; 325 else 326 adress -= NV40_PLUS_OFFSET; 327 328 for (cnt = 0; cnt <= offset; cnt++) 329 { 330 adress -= si->overlay.myBufInfo[cnt].size; 331 } 332 /* this adress is already aligned to the scaler's requirements (via the already modified sizes) */ 333 si->overlay.myBuffer[offset].buffer_dma = (void *) adress; 334 335 LOG(4, ("Overlay: New buffer: addr $%p, dma_addr $%p, color space $%08x\n", 336 (uint8*)si->overlay.myBuffer[offset].buffer, 337 (uint8*)si->overlay.myBuffer[offset].buffer_dma, cs)); 338 LOG(4, ("Overlay: New buffer's size is $%08x\n", si->overlay.myBufInfo[offset].size)); 339 340 /* release the shared benaphore */ 341 RELEASE_BEN(si->overlay.lock) 342 343 return &si->overlay.myBuffer[offset]; 344 } else { 345 /* sorry, no more room for buffers */ 346 LOG(4, ("Overlay: Sorry, no more space for buffers: aborted\n")); 347 348 /* release the shared benaphore */ 349 RELEASE_BEN(si->overlay.lock) 350 351 return NULL; 352 } 353 } 354 355 356 status_t RELEASE_OVERLAY_BUFFER(const overlay_buffer *ob) 357 /* Note that the user can delete the buffers in any order desired! */ 358 { 359 int offset = 0; 360 361 if (ob != NULL) 362 { 363 /* find the buffer */ 364 for (offset = 0; offset < MAXBUFFERS; offset++) 365 { 366 if (si->overlay.myBuffer[offset].buffer == ob->buffer) break; 367 } 368 369 if (offset < MAXBUFFERS) 370 /* delete current buffer */ 371 { 372 si->overlay.myBuffer[offset].buffer = NULL; 373 si->overlay.myBuffer[offset].buffer_dma = NULL; 374 375 LOG(4,("Overlay: Release_buffer offset = %d, buffer released\n",offset)); 376 377 return B_OK; 378 } 379 else 380 { 381 /* this is no buffer of ours! */ 382 LOG(4,("Overlay: Release_overlay_buffer: not ours, aborted!\n")); 383 384 return B_ERROR; 385 } 386 } 387 else 388 /* no buffer specified! */ 389 { 390 LOG(4,("Overlay: Release_overlay_buffer: no buffer specified, aborted!\n")); 391 392 return B_ERROR; 393 } 394 } 395 396 status_t GET_OVERLAY_CONSTRAINTS 397 (const display_mode *dm, const overlay_buffer *ob, overlay_constraints *oc) 398 { 399 int offset = 0; 400 401 LOG(4,("Overlay: Get_overlay_constraints called\n")); 402 403 /* check for NULL pointers */ 404 if ((dm == NULL) || (ob == NULL) || (oc == NULL)) 405 { 406 LOG(4,("Overlay: Get_overlay_constraints: Null pointer(s) detected!\n")); 407 return B_ERROR; 408 } 409 410 /* find the buffer */ 411 for (offset = 0; offset < MAXBUFFERS; offset++) 412 { 413 if (si->overlay.myBuffer[offset].buffer == ob->buffer) break; 414 } 415 416 if (offset < MAXBUFFERS) 417 { 418 /* scaler input (values are in pixels) */ 419 oc->view.h_alignment = 0; 420 oc->view.v_alignment = 0; 421 422 switch (ob->space) 423 { 424 case B_YCbCr422: 425 if (si->ps.card_arch < NV10A) 426 { 427 /* RIVA128 and TNT need 15. 428 * Note: this has to be in sync with the slopspace setup during buffer allocation.. */ 429 oc->view.width_alignment = 15; 430 } 431 else 432 { 433 /* GeForce need 31. 434 * Note: this has to be in sync with the slopspace setup during buffer allocation.. */ 435 oc->view.width_alignment = 31; 436 } 437 break; 438 default: 439 /* we should not be here, but set the worst-case value just to be safe anyway */ 440 oc->view.width_alignment = 31; 441 break; 442 } 443 444 oc->view.height_alignment = 0; 445 oc->view.width.min = 1; 446 oc->view.height.min = 2; /* two fields */ 447 oc->view.width.max = ob->width; 448 oc->view.height.max = ob->height; 449 450 /* scaler output restrictions */ 451 oc->window.h_alignment = 0; 452 oc->window.v_alignment = 0; 453 oc->window.width_alignment = 0; 454 oc->window.height_alignment = 0; 455 oc->window.width.min = 2; 456 /* GeForce cards can output upto and including 2046 pixels in width */ 457 //fixme: how about TNT? 458 if (dm->virtual_width > 2046) 459 { 460 oc->window.width.max = 2046; 461 } 462 else 463 { 464 oc->window.width.max = dm->virtual_width; 465 } 466 oc->window.height.min = 2; 467 /* GeForce cards can output upto and including 2046 pixels in height */ 468 //fixme: how about TNT? 469 if (dm->virtual_height > 2046) 470 { 471 oc->window.height.max = 2046; 472 } 473 else 474 { 475 oc->window.height.max = dm->virtual_height; 476 } 477 478 /* GeForce scaling restrictions */ 479 switch (si->ps.card_arch) 480 { 481 case NV04A: 482 /* Riva128-TNT2 series have an old BES engine... */ 483 oc->h_scale.min = 1.0; 484 oc->v_scale.min = 1.0; 485 break; 486 case NV30A: 487 case NV40A: 488 /* GeForceFX series and up have a new BES engine... */ 489 oc->h_scale.min = 0.5; 490 oc->v_scale.min = 0.5; 491 /* NV31 (confirmed GeForceFX 5600) has NV20A scaling limits! 492 * So let it fall through... */ 493 if (si->ps.card_type != NV31) break; 494 default: 495 /* the rest in between... */ 496 oc->h_scale.min = 0.125; 497 oc->v_scale.min = 0.125; 498 break; 499 } 500 /* all cards have a upscaling limit of 8.0 (see official nVidia specsheets) */ 501 oc->h_scale.max = 8.0; 502 oc->v_scale.max = 8.0; 503 504 return B_OK; 505 } 506 else 507 { 508 /* this is no buffer of ours! */ 509 LOG(4,("Overlay: Get_overlay_constraints: buffer is not ours, aborted!\n")); 510 511 return B_ERROR; 512 } 513 } 514 515 overlay_token ALLOCATE_OVERLAY(void) 516 { 517 uint32 tmpToken; 518 LOG(4,("Overlay: Allocate_overlay called: ")); 519 520 /* come up with a token */ 521 tmpToken = 0x12345678; 522 523 /* acquire the shared benaphore */ 524 AQUIRE_BEN(si->overlay.lock) 525 526 /* overlay unit already in use? */ 527 if (si->overlay.myToken == NULL) 528 /* overlay unit is available */ 529 { 530 LOG(4,("succesfull\n")); 531 532 si->overlay.myToken = &tmpToken; 533 534 /* release the shared benaphore */ 535 RELEASE_BEN(si->overlay.lock) 536 537 return si->overlay.myToken; 538 } 539 else 540 /* sorry, overlay unit is occupied */ 541 { 542 LOG(4,("failed: already in use!\n")); 543 544 /* release the shared benaphore */ 545 RELEASE_BEN(si->overlay.lock) 546 547 return NULL; 548 } 549 } 550 551 status_t RELEASE_OVERLAY(overlay_token ot) 552 { 553 LOG(4,("Overlay: Release_overlay called: ")); 554 555 /* is this call for real? */ 556 if ((ot == NULL) || (si->overlay.myToken == NULL) || (ot != si->overlay.myToken)) 557 /* nope, abort */ 558 { 559 LOG(4,("failed, not in use!\n")); 560 561 return B_ERROR; 562 } 563 else 564 /* call is for real */ 565 { 566 567 nv_release_bes(); 568 569 LOG(4,("succesfull\n")); 570 571 si->overlay.myToken = NULL; 572 return B_OK; 573 } 574 } 575 576 status_t CONFIGURE_OVERLAY 577 (overlay_token ot, const overlay_buffer *ob, const overlay_window *ow, const overlay_view *ov) 578 { 579 int offset = 0; /* used for buffer index */ 580 581 LOG(4,("Overlay: Configure_overlay called: ")); 582 583 /* Note: 584 * When a Workspace switch, screen prefs change, or overlay app shutdown occurs, BeOS will 585 * release all overlay buffers. The buffer currently displayed at that moment, may need some 586 * 'hardware releasing' in the CONFIGURE_OVERLAY routine. This is why CONFIGURE_OVERLAY gets 587 * called one more time then, with a null pointer for overlay_window and overlay_view, while 588 * the currently displayed overlay_buffer is given. 589 * The G200-G550 do not need to do anything on such an occasion, so we simply return if we 590 * get called then. */ 591 if ((ow == NULL) || (ov == NULL)) 592 { 593 LOG(4,("output properties changed\n")); 594 595 return B_OK; 596 } 597 598 /* Note: 599 * If during overlay use the screen prefs are changed, or the workspace has changed, it 600 * may be that we were not able to re-allocate the requested overlay buffers (or only partly) 601 * due to lack of cardRAM. If the app does not respond properly to this, we might end up 602 * with a NULL pointer instead of a overlay_buffer to work with here. 603 * Of course, we need to abort then to prevent the system from 'going down'. 604 * The app will probably crash because it will want to write into this non-existant buffer 605 * at some point. */ 606 if (ob == NULL) 607 { 608 LOG(4,("no overlay buffer specified\n")); 609 610 return B_ERROR; 611 } 612 613 /* is this call done by the app that owns us? */ 614 if ((ot == NULL) || (si->overlay.myToken == NULL) || (ot != si->overlay.myToken)) 615 /* nope, abort */ 616 { 617 LOG(4,("failed\n")); 618 619 return B_ERROR; 620 } 621 else 622 /* call is for real */ 623 { 624 /* find the buffer's offset */ 625 for (offset = 0; offset < MAXBUFFERS; offset++) 626 { 627 if (si->overlay.myBuffer[offset].buffer == ob->buffer) break; 628 } 629 630 if (offset < MAXBUFFERS) 631 { 632 LOG(4,("succesfull, switching to buffer %d\n", offset)); 633 634 /* program overlay hardware */ 635 nv_configure_bes(ob, ow, ov, offset); 636 637 return B_OK; 638 } 639 else 640 { 641 /* this is no buffer of ours! */ 642 LOG(4,("buffer is not ours, aborted!\n")); 643 644 return B_ERROR; 645 } 646 } 647 } 648