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