168353368SRudolf Cornelissen /* Written by Rudolf Cornelissen 05/2002-9/2004 */ 268353368SRudolf Cornelissen 368353368SRudolf Cornelissen /* Note on 'missing features' in BeOS 5.0.3 and DANO: 468353368SRudolf Cornelissen * BeOS needs to define more colorspaces! It would be nice if BeOS would support the FourCC 'definitions' 568353368SRudolf Cornelissen * of colorspaces. These colorspaces are 32bit words, so it could be simply done (or is it already so?) 668353368SRudolf Cornelissen */ 768353368SRudolf Cornelissen 868353368SRudolf Cornelissen #define MODULE_BIT 0x00000400 968353368SRudolf Cornelissen 1068353368SRudolf Cornelissen #include "acc_std.h" 1168353368SRudolf Cornelissen 1268353368SRudolf Cornelissen /* define the supported overlay input colorspaces */ 1368353368SRudolf Cornelissen /* It would be nice to have the YUV4:2:0 2-plane mode implemented also later on, but the Be colorspace 1468353368SRudolf Cornelissen * definitions (in GraphicsDefs.h, R5.0.3 and DANO5.1d0) do not include this one... */ 1568353368SRudolf Cornelissen static uint32 overlay_colorspaces [] = { (uint32)B_YCbCr422, (uint32)B_NO_COLOR_SPACE }; 1668353368SRudolf Cornelissen 1768353368SRudolf Cornelissen uint32 OVERLAY_COUNT(const display_mode *dm) 1868353368SRudolf Cornelissen // This method is never used AFAIK though it *is* exported on R5.0.3 and DANO. 1968353368SRudolf Cornelissen // Does someone know howto invoke it? 2068353368SRudolf Cornelissen { 2168353368SRudolf Cornelissen LOG(4,("Overlay: count called\n")); 2268353368SRudolf Cornelissen 2368353368SRudolf Cornelissen /* check for NULL pointer */ 2468353368SRudolf Cornelissen if (dm == NULL) 2568353368SRudolf Cornelissen { 2668353368SRudolf Cornelissen LOG(4,("Overlay: No display mode specified!\n")); 2768353368SRudolf Cornelissen } 2868353368SRudolf Cornelissen /* apparantly overlay count should report the number of 'overlay units' on the card */ 2968353368SRudolf Cornelissen return 1; 3068353368SRudolf Cornelissen } 3168353368SRudolf Cornelissen 3268353368SRudolf Cornelissen const uint32 *OVERLAY_SUPPORTED_SPACES(const display_mode *dm) 3368353368SRudolf Cornelissen // This method is never used AFAIK though it *is* exported on R5.0.3 and DANO. 3468353368SRudolf Cornelissen // Does someone know howto invoke it? 3568353368SRudolf Cornelissen { 3668353368SRudolf Cornelissen LOG(4,("Overlay: supported_spaces called.\n")); 3768353368SRudolf Cornelissen 3868353368SRudolf Cornelissen /* check for NULL pointer */ 3968353368SRudolf Cornelissen if (dm == NULL) 4068353368SRudolf Cornelissen { 4168353368SRudolf Cornelissen LOG(4,("Overlay: No display mode specified!\n")); 4268353368SRudolf Cornelissen return NULL; 4368353368SRudolf Cornelissen } 4468353368SRudolf Cornelissen 4568353368SRudolf Cornelissen /* assuming interlaced VGA is not supported */ 4668353368SRudolf Cornelissen if (dm->timing.flags && B_TIMING_INTERLACED) 4768353368SRudolf Cornelissen { 4868353368SRudolf Cornelissen return NULL; 4968353368SRudolf Cornelissen } 5068353368SRudolf Cornelissen /* return a B_NO_COLOR_SPACE terminated list */ 5168353368SRudolf Cornelissen return &overlay_colorspaces[0]; 5268353368SRudolf Cornelissen } 5368353368SRudolf Cornelissen 5468353368SRudolf Cornelissen uint32 OVERLAY_SUPPORTED_FEATURES(uint32 a_color_space) 5568353368SRudolf Cornelissen // This method is never used AFAIK. On R5.0.3 and DANO it is not even exported! 5668353368SRudolf Cornelissen { 5768353368SRudolf Cornelissen LOG(4,("Overlay: supported_features: color_space $%08x\n",a_color_space)); 5868353368SRudolf Cornelissen 5968353368SRudolf Cornelissen /* check what features are supported for the current overlaybitmap colorspace */ 6068353368SRudolf Cornelissen switch (a_color_space) 6168353368SRudolf Cornelissen { 6268353368SRudolf Cornelissen default: 6368353368SRudolf Cornelissen return 6468353368SRudolf Cornelissen ( B_OVERLAY_KEYING_USES_ALPHA | 6568353368SRudolf Cornelissen B_OVERLAY_COLOR_KEY | 6668353368SRudolf Cornelissen B_OVERLAY_HORIZONTAL_FILTERING | 6768353368SRudolf Cornelissen B_OVERLAY_VERTICAL_FILTERING ); 6868353368SRudolf Cornelissen } 6968353368SRudolf Cornelissen } 7068353368SRudolf Cornelissen 7168353368SRudolf Cornelissen const overlay_buffer *ALLOCATE_OVERLAY_BUFFER(color_space cs, uint16 width, uint16 height) 7268353368SRudolf Cornelissen { 7368353368SRudolf Cornelissen int offset = 0; /* used to determine next buffer to create */ 7468353368SRudolf Cornelissen uint32 adress, adress2, temp32; /* used to calculate buffer adresses */ 7568353368SRudolf Cornelissen uint32 oldsize = 0; /* used to 'squeeze' new buffers between already existing ones */ 7668353368SRudolf Cornelissen int cnt; /* loopcounter */ 7768353368SRudolf Cornelissen 7868353368SRudolf Cornelissen /* acquire the shared benaphore */ 7968353368SRudolf Cornelissen AQUIRE_BEN(si->overlay.lock) 8068353368SRudolf Cornelissen 8168353368SRudolf Cornelissen LOG(4,("Overlay: cardRAM_start = $%08x\n",(uint32)((uint8*)si->framebuffer))); 8268353368SRudolf Cornelissen LOG(4,("Overlay: cardRAM_start_DMA = $%08x\n",(uint32)((uint8*)si->framebuffer_pci))); 8368353368SRudolf Cornelissen LOG(4,("Overlay: cardRAM_size = %3.3fMb\n",(si->ps.memory_size / (1024.0 * 1024.0)))); 8468353368SRudolf Cornelissen 8568353368SRudolf Cornelissen /* find first empty slot (room for another buffer?) */ 8668353368SRudolf Cornelissen for (offset = 0; offset < MAXBUFFERS; offset++) 8768353368SRudolf Cornelissen { 8868353368SRudolf Cornelissen if (si->overlay.myBuffer[offset].buffer == NULL) break; 8968353368SRudolf Cornelissen } 9068353368SRudolf Cornelissen 9168353368SRudolf Cornelissen LOG(4,("Overlay: Allocate_buffer offset = %d\n",offset)); 9268353368SRudolf Cornelissen 9368353368SRudolf Cornelissen if (offset < MAXBUFFERS) 9468353368SRudolf Cornelissen /* setup new scaler input buffer */ 9568353368SRudolf Cornelissen { 9668353368SRudolf Cornelissen switch (cs) 9768353368SRudolf Cornelissen { 9868353368SRudolf Cornelissen case B_YCbCr422: 9968353368SRudolf Cornelissen if (si->ps.card_arch < NV10A) 10068353368SRudolf Cornelissen { 10168353368SRudolf Cornelissen /* check if slopspace is needed: RIVA128 and TNT need ~0x000f. */ 10268353368SRudolf Cornelissen si->overlay.myBuffer[offset].width = ((width + 0x000f) & ~0x000f); 10368353368SRudolf Cornelissen } 10468353368SRudolf Cornelissen else 10568353368SRudolf Cornelissen { 10668353368SRudolf Cornelissen /* check if slopspace is needed: GeForce need ~0x001f. */ 10768353368SRudolf Cornelissen /* fixme: 10868353368SRudolf Cornelissen * update needed for GF DVDmax support to adhere to CRTC2 constraints?? */ 10968353368SRudolf Cornelissen si->overlay.myBuffer[offset].width = ((width + 0x001f) & ~0x001f); 11068353368SRudolf Cornelissen } 11168353368SRudolf Cornelissen si->overlay.myBuffer[offset].bytes_per_row = 2 * si->overlay.myBuffer[offset].width; 11268353368SRudolf Cornelissen 11368353368SRudolf Cornelissen /* check if the requested horizontal pitch is supported: */ 11468353368SRudolf Cornelissen //fixme: tune for GF and TNT... 11568353368SRudolf Cornelissen if (si->overlay.myBuffer[offset].width > 4088) 11668353368SRudolf Cornelissen { 11768353368SRudolf Cornelissen LOG(4,("Overlay: Sorry, requested buffer pitch not supported, aborted\n")); 11868353368SRudolf Cornelissen 11968353368SRudolf Cornelissen /* release the shared benaphore */ 12068353368SRudolf Cornelissen RELEASE_BEN(si->overlay.lock) 12168353368SRudolf Cornelissen 12268353368SRudolf Cornelissen return NULL; 12368353368SRudolf Cornelissen } 12468353368SRudolf Cornelissen break; 12568353368SRudolf Cornelissen default: 12668353368SRudolf Cornelissen /* unsupported colorspace! */ 12768353368SRudolf Cornelissen LOG(4,("Overlay: Sorry, colorspace $%08x not supported, aborted\n",cs)); 12868353368SRudolf Cornelissen 12968353368SRudolf Cornelissen /* release the shared benaphore */ 13068353368SRudolf Cornelissen RELEASE_BEN(si->overlay.lock) 13168353368SRudolf Cornelissen 13268353368SRudolf Cornelissen return NULL; 13368353368SRudolf Cornelissen break; 13468353368SRudolf Cornelissen } 13568353368SRudolf Cornelissen 13668353368SRudolf Cornelissen /* check if the requested buffer width is supported */ 13768353368SRudolf Cornelissen if (si->overlay.myBuffer[offset].width > 1024) 13868353368SRudolf Cornelissen { 13968353368SRudolf Cornelissen LOG(4,("Overlay: Sorry, requested buffer width not supported, aborted\n")); 14068353368SRudolf Cornelissen 14168353368SRudolf Cornelissen /* release the shared benaphore */ 14268353368SRudolf Cornelissen RELEASE_BEN(si->overlay.lock) 14368353368SRudolf Cornelissen 14468353368SRudolf Cornelissen return NULL; 14568353368SRudolf Cornelissen } 14668353368SRudolf Cornelissen /* check if the requested buffer height is supported */ 14768353368SRudolf Cornelissen if (height > 1024) 14868353368SRudolf Cornelissen { 14968353368SRudolf Cornelissen LOG(4,("Overlay: Sorry, requested buffer height not supported, aborted\n")); 15068353368SRudolf Cornelissen 15168353368SRudolf Cornelissen /* release the shared benaphore */ 15268353368SRudolf Cornelissen RELEASE_BEN(si->overlay.lock) 15368353368SRudolf Cornelissen 15468353368SRudolf Cornelissen return NULL; 15568353368SRudolf Cornelissen } 15668353368SRudolf Cornelissen 15768353368SRudolf Cornelissen /* store slopspace (in pixels) for each bitmap for use by 'overlay unit' (BES) */ 15868353368SRudolf Cornelissen si->overlay.myBufInfo[offset].slopspace = si->overlay.myBuffer[offset].width - width; 15968353368SRudolf Cornelissen 16068353368SRudolf Cornelissen si->overlay.myBuffer[offset].space = cs; 16168353368SRudolf Cornelissen si->overlay.myBuffer[offset].height = height; 16268353368SRudolf Cornelissen 16368353368SRudolf Cornelissen /* we define the overlay buffers to reside 'in the back' of the cards RAM */ 16468353368SRudolf Cornelissen /* NOTE to app programmers: 16568353368SRudolf Cornelissen * Beware that an app using overlay needs to track workspace switches and screenprefs 16668353368SRudolf Cornelissen * changes. If such an action is detected, the app needs to reset it's pointers to the 16768353368SRudolf Cornelissen * newly created overlay bitmaps, which will be assigned by BeOS automatically after such 16868353368SRudolf Cornelissen * an event. (Also the app needs to respect the new overlay_constraints that will be applicable!) 16968353368SRudolf Cornelissen * 17068353368SRudolf Cornelissen * It is entirely possible that new bitmaps may *not* be re-setup at all, or less of them 17168353368SRudolf Cornelissen * than previously setup by the app might be re-setup. This is due to cardRAM restraints then. 17268353368SRudolf Cornelissen * This means that the app should also check for NULL pointers returned by the bitmaps, 17368353368SRudolf Cornelissen * and if this happens, it needs to fallback to single buffered overlay or even fallback to 17468353368SRudolf Cornelissen * bitmap output for the new situation. */ 17568353368SRudolf Cornelissen 17668353368SRudolf Cornelissen /* Another NOTE for app programmers: 17768353368SRudolf Cornelissen * A *positive* side-effect of assigning the first overlay buffer exactly at the end of the 17868353368SRudolf Cornelissen * cardRAM is that apps that try to write beyond the buffer's space get a segfault immediately. 17968353368SRudolf Cornelissen * This *greatly* simplifies tracking such errors! 18068353368SRudolf Cornelissen * Of course such errors may lead to strange effects in the app or driver behaviour if they are 18168353368SRudolf Cornelissen * not hunted down and removed.. */ 18268353368SRudolf Cornelissen 18368353368SRudolf Cornelissen /* calculate first free RAM adress in card: 18468353368SRudolf Cornelissen * Driver setup is as follows: 18568353368SRudolf Cornelissen * card base: - hardware cursor bitmap (if used), 18668353368SRudolf Cornelissen * directly above - screen memory for both heads */ 18768353368SRudolf Cornelissen adress2 = (((uint32)((uint8*)si->fbc.frame_buffer)) + /* cursor already included here */ 18868353368SRudolf Cornelissen (si->fbc.bytes_per_row * si->dm.virtual_height)); /* size in bytes of screen(s) */ 18968353368SRudolf Cornelissen LOG(4,("Overlay: first free cardRAM virtual adress $%08x\n", adress2)); 19068353368SRudolf Cornelissen 19168353368SRudolf Cornelissen /* calculate 'preliminary' buffer size including slopspace */ 19268353368SRudolf Cornelissen oldsize = si->overlay.myBufInfo[offset].size; 19368353368SRudolf Cornelissen si->overlay.myBufInfo[offset].size = 19468353368SRudolf Cornelissen si->overlay.myBuffer[offset].bytes_per_row * si->overlay.myBuffer[offset].height; 19568353368SRudolf Cornelissen 19668353368SRudolf Cornelissen /* calculate virtual memory adress that would be needed for a new bitmap */ 19768353368SRudolf Cornelissen /* NOTE to app programmers: 19868353368SRudolf Cornelissen * For testing app behaviour regarding workspace switches or screen prefs changes to settings 19968353368SRudolf Cornelissen * that do not have enough cardRAM left for allocation of overlay bitmaps, you need a card with 200*9d063f00SRudolf Cornelissen * a low amount of RAM. Or you can set in the file skel.settings for example: 20168353368SRudolf Cornelissen * memory 8 #8Mb RAM on card 20268353368SRudolf Cornelissen * and reboot (this simulates 8Mb RAM on the card). 20368353368SRudolf Cornelissen * 20468353368SRudolf Cornelissen * If you switch now to settings: 1600x1200x32bit (single head) the app needs to fallback to 20568353368SRudolf Cornelissen * bitmap output or maybe single buffered overlay output if small bitmaps are used. */ 20668353368SRudolf Cornelissen 20768353368SRudolf Cornelissen adress = (((uint32)((uint8*)si->framebuffer)) + si->ps.memory_size); 20868353368SRudolf Cornelissen for (cnt = 0; cnt <= offset; cnt++) 20968353368SRudolf Cornelissen { 21068353368SRudolf Cornelissen adress -= si->overlay.myBufInfo[cnt].size; 21168353368SRudolf Cornelissen } 21268353368SRudolf Cornelissen 21368353368SRudolf Cornelissen /* the > G200 scalers require buffers to be aligned to 16 byte pages cardRAM offset, G200 can do with 21468353368SRudolf Cornelissen * 8 byte pages cardRAM offset. Compatible settings used, has no real downside consequences here */ 21568353368SRudolf Cornelissen 21668353368SRudolf Cornelissen /* Check if we need to modify the buffers starting adress and thus the size */ 21768353368SRudolf Cornelissen /* calculate 'would be' cardRAM offset */ 21868353368SRudolf Cornelissen temp32 = (adress - ((uint32)((vuint32 *)si->framebuffer))); 21968353368SRudolf Cornelissen /* check if it is aligned */ 22068353368SRudolf Cornelissen if (temp32 != (temp32 & 0xfffffff0)) 22168353368SRudolf Cornelissen { 22268353368SRudolf Cornelissen /* update the (already calculated) buffersize to get it aligned */ 22368353368SRudolf Cornelissen si->overlay.myBufInfo[offset].size += (temp32 - (temp32 & 0xfffffff0)); 22468353368SRudolf Cornelissen /* update the (already calculated) adress to get it aligned */ 22568353368SRudolf Cornelissen adress -= (temp32 - (temp32 & 0xfffffff0)); 22668353368SRudolf Cornelissen } 22768353368SRudolf Cornelissen LOG(4,("Overlay: new buffer needs virtual adress $%08x\n", adress)); 22868353368SRudolf Cornelissen 22968353368SRudolf Cornelissen /* First check now if buffer to be defined is 'last one' in memory (speaking backwards): 23068353368SRudolf Cornelissen * this is done to prevent a large buffer getting created in the space a small buffer 23168353368SRudolf Cornelissen * occupied earlier, if not all buffers created were deleted. 23268353368SRudolf Cornelissen * Note also that the app can delete the buffers in any order desired. */ 23368353368SRudolf Cornelissen 23468353368SRudolf Cornelissen /* NOTE to app programmers: 23568353368SRudolf Cornelissen * If you are going to delete a overlay buffer you created, you should delete them *all* and 23668353368SRudolf Cornelissen * then re-create only the new ones needed. This way you are sure not to get unused memory- 23768353368SRudolf Cornelissen * space in between your overlay buffers for instance, so cardRAM is used 'to the max'. 23868353368SRudolf Cornelissen * If you don't, you might not get a buffer at all if you are trying to set up a larger one 23968353368SRudolf Cornelissen * than before. 24068353368SRudolf Cornelissen * (Indeed: not all buffers *have* to be of the same type and size...) */ 24168353368SRudolf Cornelissen 24268353368SRudolf Cornelissen for (cnt = offset; cnt < MAXBUFFERS; cnt++) 24368353368SRudolf Cornelissen { 24468353368SRudolf Cornelissen if (si->overlay.myBuffer[cnt].buffer != NULL) 24568353368SRudolf Cornelissen { 24668353368SRudolf Cornelissen /* Check if the new buffer would fit into the space the single old one used here */ 24768353368SRudolf Cornelissen if (si->overlay.myBufInfo[offset].size <= oldsize) 24868353368SRudolf Cornelissen { 24968353368SRudolf Cornelissen /* It does, so we reset to the old size and adresses to prevent the space from shrinking 25068353368SRudolf Cornelissen * if we get here again... */ 25168353368SRudolf Cornelissen adress -= (oldsize - si->overlay.myBufInfo[offset].size); 25268353368SRudolf Cornelissen si->overlay.myBufInfo[offset].size = oldsize; 25368353368SRudolf Cornelissen LOG(4,("Overlay: 'squeezing' in buffer:\n" 25468353368SRudolf Cornelissen "Overlay: resetting it to virtual adress $%08x and size $%08x\n", adress,oldsize)); 25568353368SRudolf Cornelissen /* force exiting the FOR loop */ 25668353368SRudolf Cornelissen cnt = MAXBUFFERS; 25768353368SRudolf Cornelissen } 25868353368SRudolf Cornelissen else 25968353368SRudolf Cornelissen { 26068353368SRudolf Cornelissen /* nogo, sorry */ 26168353368SRudolf Cornelissen LOG(4,("Overlay: Other buffer(s) exist after this one:\n" 26268353368SRudolf Cornelissen "Overlay: not enough space to 'squeeze' this one in, aborted\n")); 26368353368SRudolf Cornelissen 26468353368SRudolf Cornelissen /* Reset to the old size to prevent the space from 'growing' if we get here again... */ 26568353368SRudolf Cornelissen si->overlay.myBufInfo[offset].size = oldsize; 26668353368SRudolf Cornelissen 26768353368SRudolf Cornelissen /* release the shared benaphore */ 26868353368SRudolf Cornelissen RELEASE_BEN(si->overlay.lock) 26968353368SRudolf Cornelissen 27068353368SRudolf Cornelissen return NULL; 27168353368SRudolf Cornelissen } 27268353368SRudolf Cornelissen } 27368353368SRudolf Cornelissen } 27468353368SRudolf Cornelissen 27568353368SRudolf Cornelissen /* check if we have enough space to setup this new bitmap 27668353368SRudolf Cornelissen * (preventing overlap of desktop RAMspace & overlay bitmap RAMspace here) */ 27768353368SRudolf Cornelissen if (adress < adress2) 27868353368SRudolf Cornelissen /* nope, sorry */ 27968353368SRudolf Cornelissen { 28068353368SRudolf Cornelissen LOG(4,("Overlay: Sorry, no more space for buffers: aborted\n")); 28168353368SRudolf Cornelissen 28268353368SRudolf Cornelissen /* release the shared benaphore */ 28368353368SRudolf Cornelissen RELEASE_BEN(si->overlay.lock) 28468353368SRudolf Cornelissen 28568353368SRudolf Cornelissen return NULL; 28668353368SRudolf Cornelissen } 28768353368SRudolf Cornelissen /* continue buffer setup */ 28868353368SRudolf Cornelissen si->overlay.myBuffer[offset].buffer = (void *) adress; 28968353368SRudolf Cornelissen 29068353368SRudolf Cornelissen /* calculate physical memory adress (for dma use) */ 29168353368SRudolf Cornelissen adress = (((uint32)((uint8*)si->framebuffer_pci)) + si->ps.memory_size); 29268353368SRudolf Cornelissen for (cnt = 0; cnt <= offset; cnt++) 29368353368SRudolf Cornelissen { 29468353368SRudolf Cornelissen adress -= si->overlay.myBufInfo[cnt].size; 29568353368SRudolf Cornelissen } 29668353368SRudolf Cornelissen /* this adress is already aligned to the scaler's requirements (via the already modified sizes) */ 29768353368SRudolf Cornelissen si->overlay.myBuffer[offset].buffer_dma = (void *) adress; 29868353368SRudolf Cornelissen 29968353368SRudolf Cornelissen LOG(4,("Overlay: New buffer: addr $%08x, dma_addr $%08x, color space $%08x\n", 30068353368SRudolf Cornelissen (uint32)((uint8*)si->overlay.myBuffer[offset].buffer), 30168353368SRudolf Cornelissen (uint32)((uint8*)si->overlay.myBuffer[offset].buffer_dma), cs)); 30268353368SRudolf Cornelissen LOG(4,("Overlay: New buffer's size is $%08x\n", si->overlay.myBufInfo[offset].size)); 30368353368SRudolf Cornelissen 30468353368SRudolf Cornelissen /* release the shared benaphore */ 30568353368SRudolf Cornelissen RELEASE_BEN(si->overlay.lock) 30668353368SRudolf Cornelissen 30768353368SRudolf Cornelissen return &si->overlay.myBuffer[offset]; 30868353368SRudolf Cornelissen } 30968353368SRudolf Cornelissen else 31068353368SRudolf Cornelissen /* sorry, no more room for buffers */ 31168353368SRudolf Cornelissen { 31268353368SRudolf Cornelissen LOG(4,("Overlay: Sorry, no more space for buffers: aborted\n")); 31368353368SRudolf Cornelissen 31468353368SRudolf Cornelissen /* release the shared benaphore */ 31568353368SRudolf Cornelissen RELEASE_BEN(si->overlay.lock) 31668353368SRudolf Cornelissen 31768353368SRudolf Cornelissen return NULL; 31868353368SRudolf Cornelissen } 31968353368SRudolf Cornelissen } 32068353368SRudolf Cornelissen 32168353368SRudolf Cornelissen status_t RELEASE_OVERLAY_BUFFER(const overlay_buffer *ob) 32268353368SRudolf Cornelissen /* Note that the user can delete the buffers in any order desired! */ 32368353368SRudolf Cornelissen { 32468353368SRudolf Cornelissen int offset = 0; 32568353368SRudolf Cornelissen 32668353368SRudolf Cornelissen if (ob != NULL) 32768353368SRudolf Cornelissen { 32868353368SRudolf Cornelissen /* find the buffer */ 32968353368SRudolf Cornelissen for (offset = 0; offset < MAXBUFFERS; offset++) 33068353368SRudolf Cornelissen { 33168353368SRudolf Cornelissen if (si->overlay.myBuffer[offset].buffer == ob->buffer) break; 33268353368SRudolf Cornelissen } 33368353368SRudolf Cornelissen 33468353368SRudolf Cornelissen if (offset < MAXBUFFERS) 33568353368SRudolf Cornelissen /* delete current buffer */ 33668353368SRudolf Cornelissen { 33768353368SRudolf Cornelissen si->overlay.myBuffer[offset].buffer = NULL; 33868353368SRudolf Cornelissen si->overlay.myBuffer[offset].buffer_dma = NULL; 33968353368SRudolf Cornelissen 34068353368SRudolf Cornelissen LOG(4,("Overlay: Release_buffer offset = %d, buffer released\n",offset)); 34168353368SRudolf Cornelissen 34268353368SRudolf Cornelissen return B_OK; 34368353368SRudolf Cornelissen } 34468353368SRudolf Cornelissen else 34568353368SRudolf Cornelissen { 34668353368SRudolf Cornelissen /* this is no buffer of ours! */ 34768353368SRudolf Cornelissen LOG(4,("Overlay: Release_overlay_buffer: not ours, aborted!\n")); 34868353368SRudolf Cornelissen 34968353368SRudolf Cornelissen return B_ERROR; 35068353368SRudolf Cornelissen } 35168353368SRudolf Cornelissen } 35268353368SRudolf Cornelissen else 35368353368SRudolf Cornelissen /* no buffer specified! */ 35468353368SRudolf Cornelissen { 35568353368SRudolf Cornelissen LOG(4,("Overlay: Release_overlay_buffer: no buffer specified, aborted!\n")); 35668353368SRudolf Cornelissen 35768353368SRudolf Cornelissen return B_ERROR; 35868353368SRudolf Cornelissen } 35968353368SRudolf Cornelissen } 36068353368SRudolf Cornelissen 36168353368SRudolf Cornelissen status_t GET_OVERLAY_CONSTRAINTS 36268353368SRudolf Cornelissen (const display_mode *dm, const overlay_buffer *ob, overlay_constraints *oc) 36368353368SRudolf Cornelissen { 36468353368SRudolf Cornelissen int offset = 0; 36568353368SRudolf Cornelissen 36668353368SRudolf Cornelissen LOG(4,("Overlay: Get_overlay_constraints called\n")); 36768353368SRudolf Cornelissen 36868353368SRudolf Cornelissen /* check for NULL pointers */ 36968353368SRudolf Cornelissen if ((dm == NULL) || (ob == NULL) || (oc == NULL)) 37068353368SRudolf Cornelissen { 37168353368SRudolf Cornelissen LOG(4,("Overlay: Get_overlay_constraints: Null pointer(s) detected!\n")); 37268353368SRudolf Cornelissen return B_ERROR; 37368353368SRudolf Cornelissen } 37468353368SRudolf Cornelissen 37568353368SRudolf Cornelissen /* find the buffer */ 37668353368SRudolf Cornelissen for (offset = 0; offset < MAXBUFFERS; offset++) 37768353368SRudolf Cornelissen { 37868353368SRudolf Cornelissen if (si->overlay.myBuffer[offset].buffer == ob->buffer) break; 37968353368SRudolf Cornelissen } 38068353368SRudolf Cornelissen 38168353368SRudolf Cornelissen if (offset < MAXBUFFERS) 38268353368SRudolf Cornelissen { 38368353368SRudolf Cornelissen /* scaler input (values are in pixels) */ 38468353368SRudolf Cornelissen oc->view.h_alignment = 0; 38568353368SRudolf Cornelissen oc->view.v_alignment = 0; 38668353368SRudolf Cornelissen 38768353368SRudolf Cornelissen switch (ob->space) 38868353368SRudolf Cornelissen { 38968353368SRudolf Cornelissen case B_YCbCr422: 39068353368SRudolf Cornelissen if (si->ps.card_arch < NV10A) 39168353368SRudolf Cornelissen { 39268353368SRudolf Cornelissen /* RIVA128 and TNT need 15. 39368353368SRudolf Cornelissen * Note: this has to be in sync with the slopspace setup during buffer allocation.. */ 39468353368SRudolf Cornelissen oc->view.width_alignment = 15; 39568353368SRudolf Cornelissen } 39668353368SRudolf Cornelissen else 39768353368SRudolf Cornelissen { 39868353368SRudolf Cornelissen /* GeForce need 31. 39968353368SRudolf Cornelissen * Note: this has to be in sync with the slopspace setup during buffer allocation.. */ 40068353368SRudolf Cornelissen oc->view.width_alignment = 31; 40168353368SRudolf Cornelissen } 40268353368SRudolf Cornelissen break; 40368353368SRudolf Cornelissen default: 40468353368SRudolf Cornelissen /* we should not be here, but set the worst-case value just to be safe anyway */ 40568353368SRudolf Cornelissen oc->view.width_alignment = 31; 40668353368SRudolf Cornelissen break; 40768353368SRudolf Cornelissen } 40868353368SRudolf Cornelissen 40968353368SRudolf Cornelissen oc->view.height_alignment = 0; 41068353368SRudolf Cornelissen oc->view.width.min = 1; 41168353368SRudolf Cornelissen oc->view.height.min = 2; /* two fields */ 41268353368SRudolf Cornelissen oc->view.width.max = ob->width; 41368353368SRudolf Cornelissen oc->view.height.max = ob->height; 41468353368SRudolf Cornelissen 41568353368SRudolf Cornelissen /* scaler output restrictions */ 41668353368SRudolf Cornelissen oc->window.h_alignment = 0; 41768353368SRudolf Cornelissen oc->window.v_alignment = 0; 41868353368SRudolf Cornelissen oc->window.width_alignment = 0; 41968353368SRudolf Cornelissen oc->window.height_alignment = 0; 42068353368SRudolf Cornelissen oc->window.width.min = 2; 42168353368SRudolf Cornelissen /* GeForce cards can output upto and including 2046 pixels in width */ 42268353368SRudolf Cornelissen //fixme: how about TNT? 42368353368SRudolf Cornelissen if (dm->virtual_width > 2046) 42468353368SRudolf Cornelissen { 42568353368SRudolf Cornelissen oc->window.width.max = 2046; 42668353368SRudolf Cornelissen } 42768353368SRudolf Cornelissen else 42868353368SRudolf Cornelissen { 42968353368SRudolf Cornelissen oc->window.width.max = dm->virtual_width; 43068353368SRudolf Cornelissen } 43168353368SRudolf Cornelissen oc->window.height.min = 2; 43268353368SRudolf Cornelissen /* GeForce cards can output upto and including 2046 pixels in height */ 43368353368SRudolf Cornelissen //fixme: how about TNT? 43468353368SRudolf Cornelissen if (dm->virtual_height > 2046) 43568353368SRudolf Cornelissen { 43668353368SRudolf Cornelissen oc->window.height.max = 2046; 43768353368SRudolf Cornelissen } 43868353368SRudolf Cornelissen else 43968353368SRudolf Cornelissen { 44068353368SRudolf Cornelissen oc->window.height.max = dm->virtual_height; 44168353368SRudolf Cornelissen } 44268353368SRudolf Cornelissen 44368353368SRudolf Cornelissen /* GeForce scaling restrictions */ 44468353368SRudolf Cornelissen switch (si->ps.card_arch) 44568353368SRudolf Cornelissen { 44668353368SRudolf Cornelissen case NV04A: 44768353368SRudolf Cornelissen /* Riva128-TNT2 series have an old BES engine... */ 44868353368SRudolf Cornelissen oc->h_scale.min = 1.0; 44968353368SRudolf Cornelissen oc->v_scale.min = 1.0; 45068353368SRudolf Cornelissen break; 45168353368SRudolf Cornelissen case NV30A: 45268353368SRudolf Cornelissen case NV40A: 45368353368SRudolf Cornelissen /* GeForceFX series and up have a new BES engine... */ 45468353368SRudolf Cornelissen oc->h_scale.min = 0.5; 45568353368SRudolf Cornelissen oc->v_scale.min = 0.5; 45668353368SRudolf Cornelissen /* NV31 (confirmed GeForceFX 5600) has NV20A scaling limits! 45768353368SRudolf Cornelissen * So let it fall through... */ 45868353368SRudolf Cornelissen if (si->ps.card_type != NV31) break; 45968353368SRudolf Cornelissen default: 46068353368SRudolf Cornelissen /* the rest in between... */ 46168353368SRudolf Cornelissen oc->h_scale.min = 0.125; 46268353368SRudolf Cornelissen oc->v_scale.min = 0.125; 46368353368SRudolf Cornelissen break; 46468353368SRudolf Cornelissen } 46568353368SRudolf Cornelissen /* all cards have a upscaling limit of 8.0 (see official nVidia specsheets) */ 46668353368SRudolf Cornelissen oc->h_scale.max = 8.0; 46768353368SRudolf Cornelissen oc->v_scale.max = 8.0; 46868353368SRudolf Cornelissen 46968353368SRudolf Cornelissen return B_OK; 47068353368SRudolf Cornelissen } 47168353368SRudolf Cornelissen else 47268353368SRudolf Cornelissen { 47368353368SRudolf Cornelissen /* this is no buffer of ours! */ 47468353368SRudolf Cornelissen LOG(4,("Overlay: Get_overlay_constraints: buffer is not ours, aborted!\n")); 47568353368SRudolf Cornelissen 47668353368SRudolf Cornelissen return B_ERROR; 47768353368SRudolf Cornelissen } 47868353368SRudolf Cornelissen } 47968353368SRudolf Cornelissen 48068353368SRudolf Cornelissen overlay_token ALLOCATE_OVERLAY(void) 48168353368SRudolf Cornelissen { 48268353368SRudolf Cornelissen uint32 tmpToken; 48368353368SRudolf Cornelissen LOG(4,("Overlay: Allocate_overlay called: ")); 48468353368SRudolf Cornelissen 48568353368SRudolf Cornelissen /* come up with a token */ 48668353368SRudolf Cornelissen tmpToken = 0x12345678; 48768353368SRudolf Cornelissen 48868353368SRudolf Cornelissen /* acquire the shared benaphore */ 48968353368SRudolf Cornelissen AQUIRE_BEN(si->overlay.lock) 49068353368SRudolf Cornelissen 49168353368SRudolf Cornelissen /* overlay unit already in use? */ 49268353368SRudolf Cornelissen if (si->overlay.myToken == NULL) 49368353368SRudolf Cornelissen /* overlay unit is available */ 49468353368SRudolf Cornelissen { 49568353368SRudolf Cornelissen LOG(4,("succesfull\n")); 49668353368SRudolf Cornelissen 49768353368SRudolf Cornelissen si->overlay.myToken = &tmpToken; 49868353368SRudolf Cornelissen 49968353368SRudolf Cornelissen /* release the shared benaphore */ 50068353368SRudolf Cornelissen RELEASE_BEN(si->overlay.lock) 50168353368SRudolf Cornelissen 50268353368SRudolf Cornelissen return si->overlay.myToken; 50368353368SRudolf Cornelissen } 50468353368SRudolf Cornelissen else 50568353368SRudolf Cornelissen /* sorry, overlay unit is occupied */ 50668353368SRudolf Cornelissen { 50768353368SRudolf Cornelissen LOG(4,("failed: already in use!\n")); 50868353368SRudolf Cornelissen 50968353368SRudolf Cornelissen /* release the shared benaphore */ 51068353368SRudolf Cornelissen RELEASE_BEN(si->overlay.lock) 51168353368SRudolf Cornelissen 51268353368SRudolf Cornelissen return NULL; 51368353368SRudolf Cornelissen } 51468353368SRudolf Cornelissen } 51568353368SRudolf Cornelissen 51668353368SRudolf Cornelissen status_t RELEASE_OVERLAY(overlay_token ot) 51768353368SRudolf Cornelissen { 51868353368SRudolf Cornelissen LOG(4,("Overlay: Release_overlay called: ")); 51968353368SRudolf Cornelissen 52068353368SRudolf Cornelissen /* is this call for real? */ 52168353368SRudolf Cornelissen if ((ot == NULL) || (si->overlay.myToken == NULL) || (ot != si->overlay.myToken)) 52268353368SRudolf Cornelissen /* nope, abort */ 52368353368SRudolf Cornelissen { 52468353368SRudolf Cornelissen LOG(4,("failed, not in use!\n")); 52568353368SRudolf Cornelissen 52668353368SRudolf Cornelissen return B_ERROR; 52768353368SRudolf Cornelissen } 52868353368SRudolf Cornelissen else 52968353368SRudolf Cornelissen /* call is for real */ 53068353368SRudolf Cornelissen { 53168353368SRudolf Cornelissen 532*9d063f00SRudolf Cornelissen eng_release_bes(); 53368353368SRudolf Cornelissen 53468353368SRudolf Cornelissen LOG(4,("succesfull\n")); 53568353368SRudolf Cornelissen 53668353368SRudolf Cornelissen si->overlay.myToken = NULL; 53768353368SRudolf Cornelissen return B_OK; 53868353368SRudolf Cornelissen } 53968353368SRudolf Cornelissen } 54068353368SRudolf Cornelissen 54168353368SRudolf Cornelissen status_t CONFIGURE_OVERLAY 54268353368SRudolf Cornelissen (overlay_token ot, const overlay_buffer *ob, const overlay_window *ow, const overlay_view *ov) 54368353368SRudolf Cornelissen { 54468353368SRudolf Cornelissen int offset = 0; /* used for buffer index */ 54568353368SRudolf Cornelissen 54668353368SRudolf Cornelissen LOG(4,("Overlay: Configure_overlay called: ")); 54768353368SRudolf Cornelissen 54868353368SRudolf Cornelissen /* Note: 54968353368SRudolf Cornelissen * When a Workspace switch, screen prefs change, or overlay app shutdown occurs, BeOS will 55068353368SRudolf Cornelissen * release all overlay buffers. The buffer currently displayed at that moment, may need some 55168353368SRudolf Cornelissen * 'hardware releasing' in the CONFIGURE_OVERLAY routine. This is why CONFIGURE_OVERLAY gets 55268353368SRudolf Cornelissen * called one more time then, with a null pointer for overlay_window and overlay_view, while 55368353368SRudolf Cornelissen * the currently displayed overlay_buffer is given. 55468353368SRudolf Cornelissen * The G200-G550 do not need to do anything on such an occasion, so we simply return if we 55568353368SRudolf Cornelissen * get called then. */ 55668353368SRudolf Cornelissen if ((ow == NULL) || (ov == NULL)) 55768353368SRudolf Cornelissen { 55868353368SRudolf Cornelissen LOG(4,("output properties changed\n")); 55968353368SRudolf Cornelissen 56068353368SRudolf Cornelissen return B_OK; 56168353368SRudolf Cornelissen } 56268353368SRudolf Cornelissen 56368353368SRudolf Cornelissen /* Note: 56468353368SRudolf Cornelissen * If during overlay use the screen prefs are changed, or the workspace has changed, it 56568353368SRudolf Cornelissen * may be that we were not able to re-allocate the requested overlay buffers (or only partly) 56668353368SRudolf Cornelissen * due to lack of cardRAM. If the app does not respond properly to this, we might end up 56768353368SRudolf Cornelissen * with a NULL pointer instead of a overlay_buffer to work with here. 56868353368SRudolf Cornelissen * Of course, we need to abort then to prevent the system from 'going down'. 56968353368SRudolf Cornelissen * The app will probably crash because it will want to write into this non-existant buffer 57068353368SRudolf Cornelissen * at some point. */ 57168353368SRudolf Cornelissen if (ob == NULL) 57268353368SRudolf Cornelissen { 57368353368SRudolf Cornelissen LOG(4,("no overlay buffer specified\n")); 57468353368SRudolf Cornelissen 57568353368SRudolf Cornelissen return B_ERROR; 57668353368SRudolf Cornelissen } 57768353368SRudolf Cornelissen 57868353368SRudolf Cornelissen /* is this call done by the app that owns us? */ 57968353368SRudolf Cornelissen if ((ot == NULL) || (si->overlay.myToken == NULL) || (ot != si->overlay.myToken)) 58068353368SRudolf Cornelissen /* nope, abort */ 58168353368SRudolf Cornelissen { 58268353368SRudolf Cornelissen LOG(4,("failed\n")); 58368353368SRudolf Cornelissen 58468353368SRudolf Cornelissen return B_ERROR; 58568353368SRudolf Cornelissen } 58668353368SRudolf Cornelissen else 58768353368SRudolf Cornelissen /* call is for real */ 58868353368SRudolf Cornelissen { 58968353368SRudolf Cornelissen /* find the buffer's offset */ 59068353368SRudolf Cornelissen for (offset = 0; offset < MAXBUFFERS; offset++) 59168353368SRudolf Cornelissen { 59268353368SRudolf Cornelissen if (si->overlay.myBuffer[offset].buffer == ob->buffer) break; 59368353368SRudolf Cornelissen } 59468353368SRudolf Cornelissen 59568353368SRudolf Cornelissen if (offset < MAXBUFFERS) 59668353368SRudolf Cornelissen { 59768353368SRudolf Cornelissen LOG(4,("succesfull, switching to buffer %d\n", offset)); 59868353368SRudolf Cornelissen 59968353368SRudolf Cornelissen /* program overlay hardware */ 600*9d063f00SRudolf Cornelissen eng_configure_bes(ob, ow, ov, offset); 60168353368SRudolf Cornelissen 60268353368SRudolf Cornelissen return B_OK; 60368353368SRudolf Cornelissen } 60468353368SRudolf Cornelissen else 60568353368SRudolf Cornelissen { 60668353368SRudolf Cornelissen /* this is no buffer of ours! */ 60768353368SRudolf Cornelissen LOG(4,("buffer is not ours, aborted!\n")); 60868353368SRudolf Cornelissen 60968353368SRudolf Cornelissen return B_ERROR; 61068353368SRudolf Cornelissen } 61168353368SRudolf Cornelissen } 61268353368SRudolf Cornelissen } 613