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