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