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... */
19static uint32 overlay_colorspaces [] = { (uint32)B_YCbCr422, (uint32)B_NO_COLOR_SPACE };
20
21uint32 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
36const 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
58uint32 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
78const 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
392status_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
432status_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
537overlay_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
573status_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
598status_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