xref: /haiku/src/add-ons/accelerants/skeleton/Overlay.c (revision 9d063f00a525a89cea1e915e0c2bfb9879e20f03)
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