xref: /haiku/src/add-ons/accelerants/matrox/engine/mga_bes.c (revision 9eb55bc1d104b8fda80898f8b25c94d8000c8255)
1 /* G200-G550 Back End Scaler functions */
2 /* Written by Rudolf Cornelissen 05/2002-1/2004 */
3 
4 #define MODULE_BIT 0x00000200
5 
6 #include "mga_std.h"
7 
8 //fixme: implement: (used for virtual screens!)
9 //void move_overlay(uint16 hdisp_start, uint16 vdisp_start);
10 
11 status_t gx00_configure_bes
12 	(const overlay_buffer *ob, const overlay_window *ow, const overlay_view *ov, int offset)
13 {
14 	/* yuy2 (4:2:2) colorspace calculations */
15 	/* Note: Some calculations will have to be modified for other colorspaces if they are incorporated. */
16 
17 	/* Note:
18 	 * in BeOS R5.0.3 and DANO:
19 	 * 'ow->offset_xxx' is always 0, so not used;
20 	 * 'ow->width' and 'ow->height' are the output window size: does not change
21 	 * if window is clipping;
22 	 * 'ow->h_start' and 'ow->v_start' are the left-top position of the output
23 	 * window. These values can be negative: this means the window is clipping
24 	 * at the left or the top of the display, respectively. */
25 
26 	/* 'ov' is the view in the source bitmap, so which part of the bitmap is actually
27 	 * displayed on screen. This is used for the 'hardware zoom' function. */
28 
29 	/* calculated BES register values */
30 	uint32 	hcoordv, vcoordv, hiscalv, hsrcstv, hsrcendv, hsrclstv,
31 			viscalv, a1orgv, v1wghtv, v1srclstv, globctlv, ctlv;
32 	/* misc used variables */
33 	uint16 temp1, temp2;
34 	/* interval representation, used for scaling calculations */
35 	uint16 intrep, crtc_hstart, crtc_vstart, crtc_hend, crtc_vend;
36 	/* inverse scaling factor, used for source positioning */
37 	uint32 ifactor;
38 	/* used for vertical weight starting value */
39 	uint32 weight;
40 	/* copy of overlay view which has checked valid values */
41 	overlay_view my_ov;
42 
43 	/* Slowdown the G200-G550 BES if the pixelclock is too high for it to cope.
44 	 * This will in fact half the horizontal resolution of the BES with high
45 	 * pixelclocks (by setting a BES hardware 'zoom' = 2x).
46 	 * If you want optimal output quality better make sure you set the refreshrate/resolution
47 	 * of your monitor not too high ... */
48 	uint16 acczoom = 1;
49 	LOG(4,("Overlay: pixelclock is %dkHz, ", si->dm.timing.pixel_clock));
50 	if (si->dm.timing.pixel_clock > BESMAXSPEED)
51 	{
52 		/* BES running at half speed and resolution */
53 		/* This is how it works (BES slowing down):
54 		 * - Activate BES internal horizontal hardware scaling = 4x (in GLOBCTL below),
55 		 * - This also sets up BES only getting half the amount of pixels per line from
56 		 *   the input picture buffer (in effect half-ing the BES pixelclock input speed).
57 		 * Now in order to get the picture back to original size, we need to also double
58 		 * the inverse horizontal scaling factor here (x4 /2 /2 = 1x again).
59 		 * Note that every other pixel is now doubled or interpolated, according to another
60 		 * GLOBCTL bit. */
61 		acczoom = 2;
62 		LOG(4,("slowing down BES!\n"));
63 	}
64 	else
65 	{
66 		/* BES running at full speed and resolution */
67 		LOG(4,("BES is running at full speed\n"));
68 	}
69 
70 
71 	/**************************************************************************************
72 	 *** copy, check and limit if needed the user-specified view into the intput bitmap ***
73 	 **************************************************************************************/
74 	my_ov = *ov;
75 	/* check for valid 'coordinates' */
76 	if (my_ov.width == 0) my_ov.width++;
77 	if (my_ov.height == 0) my_ov.height++;
78 	if (my_ov.h_start > ((ob->width - si->overlay.myBufInfo[offset].slopspace) - 1))
79 		my_ov.h_start = ((ob->width - si->overlay.myBufInfo[offset].slopspace) - 1);
80 	if (((my_ov.h_start + my_ov.width) - 1) > ((ob->width - si->overlay.myBufInfo[offset].slopspace) - 1))
81 		my_ov.width = ((((ob->width - si->overlay.myBufInfo[offset].slopspace) - 1) - my_ov.h_start) + 1);
82 	if (my_ov.v_start > (ob->height - 1))
83 		my_ov.v_start = (ob->height - 1);
84 	if (((my_ov.v_start + my_ov.height) - 1) > (ob->height - 1))
85 		my_ov.height = (((ob->height - 1) - my_ov.v_start) + 1);
86 
87 	LOG(6,("Overlay: inputbuffer view (zoom) left %d, top %d, width %d, height %d\n",
88 		my_ov.h_start, my_ov.v_start, my_ov.width, my_ov.height));
89 
90 	/* the BES does not respect virtual_workspaces, but adheres to CRTC
91 	 * constraints only */
92 	crtc_hstart = si->dm.h_display_start;
93 	/* make dualhead switch mode with TVout enabled work while we're at it.. */
94 	if (si->switched_crtcs)
95 	{
96 		crtc_hstart += si->dm.timing.h_display;
97 	}
98 	/* horizontal end is the first position beyond the displayed range on the CRTC */
99 	crtc_hend = crtc_hstart + si->dm.timing.h_display;
100 	crtc_vstart = si->dm.v_display_start;
101 	/* vertical end is the first position beyond the displayed range on the CRTC */
102 	crtc_vend = crtc_vstart + si->dm.timing.v_display;
103 
104 
105 	/****************************************
106 	 *** setup all edges of output window ***
107 	 ****************************************/
108 
109 	/* setup left and right edges of output window */
110 	hcoordv = 0;
111 	/* left edge coordinate of output window, must be inside desktop */
112 	/* clipping on the left side */
113 	if (ow->h_start < crtc_hstart)
114 	{
115 		temp1 = 0;
116 	}
117 	else
118 	{
119 		/* clipping on the right side */
120 		if (ow->h_start >= (crtc_hend - 1))
121 		{
122 			/* width < 2 is not allowed */
123 			temp1 = (crtc_hend - crtc_hstart - 2) & 0x7ff;
124 		}
125 		else
126 		/* no clipping here */
127 		{
128 			temp1 = (ow->h_start - crtc_hstart) & 0x7ff;
129 		}
130 	}
131 	hcoordv |= temp1 << 16;
132 	/* right edge coordinate of output window, must be inside desktop */
133 	/* width < 2 is not allowed */
134 	if (ow->width < 2)
135 	{
136 		temp2 = (temp1 + 1) & 0x7ff;
137 	}
138 	else
139 	{
140 		/* clipping on the right side */
141 		if ((ow->h_start + ow->width - 1) > (crtc_hend - 1))
142 		{
143 			temp2 = (crtc_hend - crtc_hstart - 1) & 0x7ff;
144 		}
145 		else
146 		{
147 			/* clipping on the left side */
148 			if ((ow->h_start + ow->width - 1) < (crtc_hstart + 1))
149 			{
150 				/* width < 2 is not allowed */
151 				temp2 = 1;
152 			}
153 			else
154 			/* no clipping here */
155 			{
156 				temp2 = ((uint16)(ow->h_start + ow->width - crtc_hstart - 1)) & 0x7ff;
157 			}
158 		}
159 	}
160 	hcoordv |= temp2 << 0;
161 	LOG(4,("Overlay: CRTC left-edge output %d, right-edge output %d\n",temp1, temp2));
162 
163 	/* setup top and bottom edges of output window */
164 	vcoordv = 0;
165 	/* top edge coordinate of output window, must be inside desktop */
166 	/* clipping on the top side */
167 	if (ow->v_start < crtc_vstart)
168 	{
169 		temp1 = 0;
170 	}
171 	else
172 	{
173 		/* clipping on the bottom side */
174 		if (ow->v_start >= (crtc_vend - 1))
175 		{
176 			/* height < 2 is not allowed */
177 			temp1 = (crtc_vend - crtc_vstart - 2) & 0x7ff;
178 		}
179 		else
180 		/* no clipping here */
181 		{
182 			temp1 = (ow->v_start - crtc_vstart) & 0x7ff;
183 		}
184 	}
185 	vcoordv |= temp1 << 16;
186 	/* bottom edge coordinate of output window, must be inside desktop */
187 	/* height < 2 is not allowed */
188 	if (ow->height < 2)
189 	{
190 		temp2 = (temp1 + 1) & 0x7ff;
191 	}
192 	else
193 	{
194 		/* clipping on the bottom side */
195 		if ((ow->v_start + ow->height - 1) > (crtc_vend - 1))
196 		{
197 			temp2 = (crtc_vend - crtc_vstart - 1) & 0x7ff;
198 		}
199 		else
200 		{
201 			/* clipping on the top side */
202 			if ((ow->v_start + ow->height - 1) < (crtc_vstart + 1))
203 			{
204 				/* height < 2 is not allowed */
205 				temp2 = 1;
206 			}
207 			else
208 			/* no clipping here */
209 			{
210 				temp2 = ((uint16)(ow->v_start + ow->height - crtc_vstart - 1)) & 0x7ff;
211 			}
212 		}
213 	}
214 	vcoordv |= temp2 << 0;
215 	LOG(4,("Overlay: CRTC top-edge output %d, bottom-edge output %d\n",temp1, temp2));
216 
217 
218 	/*********************************************
219 	 *** setup horizontal scaling and clipping ***
220 	 *********************************************/
221 
222 	LOG(6,("Overlay: total input picture width = %d, height = %d\n",
223 			(ob->width - si->overlay.myBufInfo[offset].slopspace), ob->height));
224 	LOG(6,("Overlay: output picture width = %d, height = %d\n", ow->width, ow->height));
225 
226 	/* do horizontal scaling... */
227 	/* determine interval representation value, taking zoom into account */
228 	if (ow->flags & B_OVERLAY_HORIZONTAL_FILTERING)
229 	{
230 		/* horizontal filtering is ON */
231 		if ((my_ov.width == ow->width) | (ow->width < 2))
232 		{
233 			/* no horizontal scaling used, OR destination width < 2 */
234 			intrep = 0;
235 		}
236 		else
237 		{
238 			intrep = 1;
239 		}
240 	}
241 	else
242 	{
243 		/* horizontal filtering is OFF */
244 		if ((ow->width < my_ov.width) & (ow->width >= 2))
245 		{
246 			/* horizontal downscaling used AND destination width >= 2 */
247 			intrep = 1;
248 		}
249 		else
250 		{
251 			intrep = 0;
252 		}
253 	}
254 	LOG(4,("Overlay: horizontal interval representation value is %d\n",intrep));
255 
256 	/* calculate inverse horizontal scaling factor, taking zoom into account */
257 	/* standard scaling formula: */
258 	ifactor = (((uint32)(my_ov.width - intrep)) << 16) / (ow->width - intrep);
259 
260 	/* correct factor to prevent most-right visible 'line' from distorting */
261 	ifactor -= (1 << 2);
262 	LOG(4,("Overlay: horizontal scaling factor is %f\n", (float)65536 / ifactor));
263 
264 	/* compensate for accelerated 2x zoom (slowdown BES if pixelclock is too high) */
265 	hiscalv = ifactor * acczoom;
266 	LOG(4,("Overlay: horizontal speed compensated factor is %f\n", (float)65536 / hiscalv));
267 
268 	/* check scaling factor (and modify if needed) to be within scaling limits */
269 	if (((((uint32)my_ov.width) << 16) / 16384) > hiscalv)
270 	{
271 		/* (non-inverse) factor too large, set factor to max. valid value */
272 		hiscalv = ((((uint32)my_ov.width) << 16) / 16384);
273 		LOG(4,("Overlay: horizontal scaling factor too large, clamping at %f\n", (float)65536 / hiscalv));
274 	}
275 	if (hiscalv >= (32 << 16))
276 	{
277 		/* (non-inverse) factor too small, set factor to min. valid value */
278 		hiscalv = 0x1ffffc;
279 		LOG(4,("Overlay: horizontal scaling factor too small, clamping at %f\n", (float)65536 / hiscalv));
280 	}
281 	/* AND below is required by hardware */
282 	hiscalv &= 0x001ffffc;
283 
284 
285 	/* do horizontal clipping... */
286 	/* Setup horizontal source start: first (sub)pixel contributing to output picture */
287 	/* Note:
288 	 * The method is to calculate, based on 1:1 scaling, based on the output window.
289 	 * After this is done, include the scaling factor so you get a value based on the input bitmap.
290 	 * Then add the left starting position of the bitmap's view (zoom function) to get the final value needed.
291 	 * Note: The input bitmaps slopspace is automatically excluded from the calculations this way! */
292 	/* Note also:
293 	 * Even if the scaling factor is clamping we instruct the BES to use the correct source start pos.! */
294 	hsrcstv = 0;
295 	/* check for destination horizontal clipping at left side */
296 	if (ow->h_start < crtc_hstart)
297 	{
298 		/* check if entire destination picture is clipping left:
299 		 * (2 pixels will be clamped onscreen at least) */
300 		if ((ow->h_start + ow->width - 1) < (crtc_hstart + 1))
301 		{
302 			/* increase 'first contributing pixel' with 'fixed value': (total dest. width - 2) */
303 			hsrcstv += (ow->width - 2);
304 		}
305 		else
306 		{
307 			/* increase 'first contributing pixel' with actual number of dest. clipping pixels */
308 			hsrcstv += (crtc_hstart - ow->h_start);
309 		}
310 		LOG(4,("Overlay: clipping left...\n"));
311 
312 		/* The calculated value is based on scaling = 1x. So we now compensate for scaling.
313 		 * Note that this also already takes care of aligning the value to the BES register! */
314 		hsrcstv *= ifactor;
315 	}
316 	/* take zoom into account */
317 	hsrcstv += ((uint32)my_ov.h_start) << 16;
318 	/* AND below required by hardware */
319 	hsrcstv &= 0x03fffffc;
320 	LOG(4,("Overlay: first hor. (sub)pixel of input bitmap contributing %f\n", hsrcstv / (float)65536));
321 
322 
323 	/* Setup horizontal source end: last (sub)pixel contributing to output picture */
324 	/* Note:
325 	 * The method is to calculate, based on 1:1 scaling, based on the output window.
326 	 * After this is done, include the scaling factor so you get a value based on the input bitmap.
327 	 * Then add the right ending position of the bitmap's view (zoom function) to get the final value needed. */
328 	/* Note also:
329 	 * Even if the scaling factor is clamping we instruct the BES to use the correct source end pos.! */
330 
331 	hsrcendv = 0;
332 	/* check for destination horizontal clipping at right side */
333 	if ((ow->h_start + ow->width - 1) > (crtc_hend - 1))
334 	{
335 		/* check if entire destination picture is clipping right:
336 		 * (2 pixels will be clamped onscreen at least) */
337 		if (ow->h_start > (crtc_hend - 2))
338 		{
339 			/* increase 'number of clipping pixels' with 'fixed value': (total dest. width - 2) */
340 			hsrcendv += (ow->width - 2);
341 		}
342 		else
343 		{
344 			/* increase 'number of clipping pixels' with actual number of dest. clipping pixels */
345 			hsrcendv += ((ow->h_start + ow->width - 1) - (crtc_hend - 1));
346 		}
347 		LOG(4,("Overlay: clipping right...\n"));
348 
349 		/* The calculated value is based on scaling = 1x. So we now compensate for scaling.
350 		 * Note that this also already takes care of aligning the value to the BES register! */
351 		hsrcendv *= ifactor;
352 		/* now subtract this value from the last used pixel in (zoomed) inputbuffer, aligned to BES */
353 		hsrcendv = (((uint32)((my_ov.h_start + my_ov.width) - 1)) << 16) - hsrcendv;
354 	}
355 	else
356 	{
357 		/* set last contributing pixel to last used pixel in (zoomed) inputbuffer, aligned to BES */
358 		hsrcendv = (((uint32)((my_ov.h_start + my_ov.width) - 1)) << 16);
359 	}
360 	/* AND below required by hardware */
361 	hsrcendv &= 0x03fffffc;
362 	LOG(4,("Overlay: last horizontal (sub)pixel of input bitmap contributing %f\n", hsrcendv / (float)65536));
363 
364 
365 	/* setup horizontal source last position excluding slopspace:
366 	 * this is the last pixel that will be used for calculating interpolated pixels */
367 	hsrclstv = ((ob->width - 1) - si->overlay.myBufInfo[offset].slopspace) << 16;
368 	/* AND below required by hardware */
369 	hsrclstv &= 0x03ff0000;
370 
371 
372 	/*******************************************
373 	 *** setup vertical scaling and clipping ***
374 	 *******************************************/
375 
376 	/* do vertical scaling... */
377 	/* determine interval representation value, taking zoom into account */
378 	if (ow->flags & B_OVERLAY_VERTICAL_FILTERING)
379 	{
380 		/* vertical filtering is ON */
381 		if ((my_ov.height == ow->height) | (ow->height < 2))
382 		{
383 			/* no vertical scaling used, OR destination height < 2 */
384 			intrep = 0;
385 		}
386 		else
387 		{
388 			intrep = 1;
389 		}
390 	}
391 	else
392 	{
393 		/* vertical filtering is OFF */
394 		if ((ow->height < my_ov.height) & (ow->height >= 2))
395 		{
396 			/* vertical downscaling used AND destination height >= 2 */
397 			intrep = 1;
398 		}
399 		else
400 		{
401 			intrep = 0;
402 		}
403 	}
404 	LOG(4,("Overlay: vertical interval representation value is %d\n",intrep));
405 
406 	/* calculate inverse vertical scaling factor, taking zoom into account */
407 	/* standard scaling formula: */
408 	ifactor = (((uint32)(my_ov.height - intrep)) << 16) / (ow->height - intrep);
409 
410 	/* correct factor to prevent lowest visible line from distorting */
411 	ifactor -= (1 << 2);
412 	LOG(4,("Overlay: vertical scaling factor is %f\n", (float)65536 / ifactor));
413 
414 	/* preserve ifactor for source positioning calculations later on */
415 	viscalv = ifactor;
416 
417 	/* check scaling factor (and modify if needed) to be within scaling limits */
418 	if (((((uint32)my_ov.height) << 16) / 16384) > viscalv)
419 	{
420 		/* (non-inverse) factor too large, set factor to max. valid value */
421 		viscalv = ((((uint32)my_ov.height) << 16) / 16384);
422 		LOG(4,("Overlay: vertical scaling factor too large, clamping at %f\n", (float)65536 / viscalv));
423 	}
424 	if (viscalv >= (32 << 16))
425 	{
426 		/* (non-inverse) factor too small, set factor to min. valid value */
427 		viscalv = 0x1ffffc;
428 		LOG(4,("Overlay: vertical scaling factor too small, clamping at %f\n", (float)65536 / viscalv));
429 	}
430 	/* AND below is required by hardware */
431 	viscalv &= 0x001ffffc;
432 
433 
434 	/* do vertical clipping... */
435 	/* Setup vertical source start: first (sub)pixel contributing to output picture.
436 	 * Note: this exists of two parts:
437 	 * 1. setup fractional part (sign is always 'positive');
438 	 * 2. setup relative base_adress, taking clipping on top (and zoom) into account.
439 	 * Both parts are done intertwined below. */
440 	/* Note:
441 	 * The method is to calculate, based on 1:1 scaling, based on the output window.
442 	 * 'After' this is done, include the scaling factor so you get a value based on the input bitmap.
443 	 * Then add the top starting position of the bitmap's view (zoom function) to get the final value needed. */
444 	/* Note also:
445 	 * Even if the scaling factor is clamping we instruct the BES to use the correct source start pos.! */
446 
447 	/* calculate relative base_adress and 'vertical weight fractional part' */
448 	weight = 0;
449 	a1orgv = (uint32)((vuint32 *)ob->buffer);
450 	a1orgv -= (uint32)((vuint32 *)si->framebuffer);
451 	/* calculate origin adress */
452 	LOG(4,("Overlay: topleft corner of input bitmap (cardRAM offset) $%08x\n",a1orgv));
453 	/* check for destination vertical clipping at top side */
454 	if (ow->v_start < crtc_vstart)
455 	{
456 		/* check if entire destination picture is clipping at top:
457 		 * (2 pixels will be clamped onscreen at least) */
458 		if ((ow->v_start + ow->height - 1) < (crtc_vstart + 1))
459 		{
460 			/* increase source buffer origin with 'fixed value':
461 			 * (integer part of ('total height - 2' of dest. picture in pixels * inverse scaling factor)) *
462 			 * bytes per row source picture */
463 			a1orgv += ((((ow->height - 2) * ifactor) >> 16) * ob->bytes_per_row);
464 			weight = (ow->height - 2) * ifactor;
465 		}
466 		else
467 		{
468 			/* increase source buffer origin with:
469 			 * (integer part of (number of destination picture clipping pixels * inverse scaling factor)) *
470 			 * bytes per row source picture */
471 			a1orgv += ((((crtc_vstart - ow->v_start) * ifactor) >> 16) * ob->bytes_per_row);
472 			weight = (crtc_vstart - ow->v_start) * ifactor;
473 		}
474 		LOG(4,("Overlay: clipping at top...\n"));
475 	}
476 	/* take zoom into account */
477 	a1orgv += (my_ov.v_start * ob->bytes_per_row);
478 	weight += (((uint32)my_ov.v_start) << 16);
479 	LOG(4,("Overlay: 'contributing part of buffer' origin is (cardRAM offset) $%08x\n",a1orgv));
480 	LOG(4,("Overlay: first vert. (sub)pixel of input bitmap contributing %f\n", weight / (float)65536));
481 
482 	/* Note:
483 	 * Because all > G200 overlay units will ignore b0-3 of the calculated adress,
484 	 * we do not use the above way for horizontal source positioning.
485 	 * (G200 cards ignore b0-2.)
486 	 * If we did, 8 source-image pixel jumps (in 4:2:2 colorspace) will occur if the picture
487 	 * is shifted horizontally during left clipping on all > G200 cards, while G200 cards
488 	 * will have 4 source-image pixel jumps occuring. */
489 
490 	/* AND below is required by G200-G550 hardware. > G200 cards can have max. 32Mb RAM on board
491 	 * (16Mb on G200 cards). Compatible setting used (between G200 and the rest), this has no
492 	 * downside consequences here. */
493 	/* Buffer A topleft corner of field 1 (origin)(field 1 contains our full frames) */
494 	a1orgv &= 0x01fffff0;
495 
496 	/* field 1 weight: AND below required by hardware, also make sure 'sign' is always 'positive' */
497 	v1wghtv = weight & 0x0000fffc;
498 
499 
500 	/* setup field 1 (is our complete frame) vertical source last position.
501 	 * this is the last pixel that will be used for calculating interpolated pixels */
502 	v1srclstv = (ob->height - 1);
503 	/* AND below required by hardware */
504 	v1srclstv &= 0x000003ff;
505 
506 
507 	/*****************************
508 	 *** log color keying info ***
509 	 *****************************/
510 
511 	LOG(6,("Overlay: key_red %d, key_green %d, key_blue %d, key_alpha %d\n",
512 		ow->red.value, ow->green.value, ow->blue.value, ow->alpha.value));
513 	LOG(6,("Overlay: mask_red %d, mask_green %d, mask_blue %d, mask_alpha %d\n",
514 		ow->red.mask, ow->green.mask, ow->blue.mask, ow->alpha.mask));
515 
516 
517 	/*************************
518 	 *** setup BES control ***
519 	 *************************/
520 
521 	/* BES global control: setup functions */
522 	globctlv = 0;
523 
524 	/* slowdown BES if nessesary */
525 	if (acczoom == 1)
526 	{
527 		/* run at full speed and resolution */
528 		globctlv |= 0 << 0;
529 		/* disable filtering for half speed interpolation */
530 		globctlv |= 0 << 1;
531 	}
532 	else
533 	{
534 		/* run at half speed and resolution */
535 		globctlv |= 1 << 0;
536 		/* enable filtering for half speed interpolation */
537 		globctlv |= 1 << 1;
538 	}
539 
540 	/* 4:2:0 specific setup: not needed here */
541 	globctlv |= 0 << 3;
542 	/* BES testregister: keep zero */
543 	globctlv |= 0 << 4;
544 	/* the following bits marked (> G200) *must* be zero on G200: */
545 	/* 4:2:0 specific setup: not needed here (> G200) */
546 	globctlv |= 0 << 5;
547 	/* select yuy2 byte-order to B_YCbCr422 (> G200) */
548 	globctlv |= 0 << 6;
549 	/* BES internal contrast and brighness controls are not used, disabled (> G200) */
550 	globctlv |= 0 << 7;
551 	/* RGB specific setup: not needed here, so disabled (> G200) */
552 	globctlv |= 0 << 8;
553 	globctlv |= 0 << 9;
554 	/* 4:2:0 specific setup: not needed here (> G200) */
555 	globctlv |= 0 << 10;
556 	/* Tell BES when to copy the new register values to the actual active registers.
557 	 * bits 16-27 (12 bits) are the CRTC vert. count value at which copying takes
558 	 * place.
559 	 * (This is the double buffering feature: programming must be completed *before*
560 	 *  the CRTC vert count value set here!) */
561 	/* CRTC vert count for copying = $000, so during retrace, line 0. */
562 	globctlv |= 0x000 << 16;
563 
564 	/* BES control: enable scaler and setup functions */
565 	/* pre-reset all bits */
566 	ctlv = 0;
567 	/* enable BES */
568 	ctlv |= 1 << 0;
569 	/* we start displaying at an even startline (zero) in 'field 1' (no hardware de-interlacing is used) */
570 	ctlv |= 0 << 6;
571 	/* we don't use field 2, so its startline is not important */
572 	ctlv |= 0 << 7;
573 
574 	LOG(6,("Overlay: ow->flags is $%08x\n",ow->flags));
575 	/* enable horizontal filtering on scaling if asked for: if we *are* actually scaling */
576 	if ((ow->flags & B_OVERLAY_HORIZONTAL_FILTERING) && (hiscalv != (0x01 << 16)))
577 	{
578 		ctlv |= 1 << 10;
579 		LOG(6,("Overlay: using horizontal interpolation on scaling\n"));
580 	}
581 	else
582 	{
583 		ctlv |= 0 << 10;
584 		LOG(6,("Overlay: using horizontal dropping or replication on scaling\n"));
585 	}
586 	/* enable vertical filtering on scaling if asked for: if we are *upscaling* only */
587 	if ((ow->flags & B_OVERLAY_VERTICAL_FILTERING) && (viscalv < (0x01 << 16)))
588 	{
589 		ctlv |= 1 << 11;
590 		LOG(6,("Overlay: using vertical interpolation on scaling\n"));
591 	}
592 	else
593 	{
594 		ctlv |= 0 << 11;
595 		LOG(6,("Overlay: using vertical dropping or replication on scaling\n"));
596 	}
597 
598 	/* use actual calculated weight for horizontal interpolation */
599 	ctlv |= 0 << 12;
600 	/* use horizontal chroma interpolation upsampling on BES input picture */
601 	ctlv |= 1 << 16;
602 	/* select 4:2:2 BES input format */
603 	ctlv |= 0 << 17;
604 	/* dithering is enabled */
605 	ctlv |= 1 << 18;
606 	/* horizontal mirroring is not used */
607 	ctlv |= 0 << 19;
608 	/* BES output should be in color */
609 	ctlv |= 0 << 20;
610 	/* BES output blanking is disabled: we want a picture, no 'black box'! */
611 	ctlv |= 0 << 21;
612 	/* we do software field select (field select is not used) */
613 	ctlv |= 0 << 24;
614 	/* we always display field 1 in buffer A, this contains our full frames */
615 	/* select field 1 */
616 	ctlv |= 0 << 25;
617 	/* select buffer A */
618 	ctlv |= 0 << 26;
619 
620 
621 	/*************************************
622 	 *** sync to BES (Back End Scaler) ***
623 	 *************************************/
624 
625 	/* Make sure reprogramming the BES completes before the next retrace occurs,
626 	 * to prevent register-update glitches (double buffer feature). */
627 
628 	LOG(3,("Overlay: starting register programming beyond Vcount %d\n", CR1R(VCOUNT)));
629 	/* Even at 1600x1200x90Hz, a single line still takes about 9uS to complete:
630 	 * this resolution will generate about 180Mhz pixelclock while we can do
631 	 * upto 360Mhz. So snooze about 4uS to prevent bus-congestion...
632 	 * Appr. 200 lines time will provide enough room even on a 100Mhz CPU if it's
633 	 * screen is set to the highest refreshrate/resolution possible. */
634 	while ((uint16)CR1R(VCOUNT) > (si->dm.timing.v_total - 200)) snooze(4);
635 
636 
637 	/**************************************
638 	 *** actually program the registers ***
639 	 **************************************/
640 
641 	BESW(HCOORD, hcoordv);
642 	BESW(VCOORD, vcoordv);
643 	BESW(HISCAL, hiscalv);
644 	BESW(HSRCST, hsrcstv);
645 	BESW(HSRCEND, hsrcendv);
646 	BESW(HSRCLST, hsrclstv);
647 	BESW(VISCAL, viscalv);
648 	BESW(A1ORG, a1orgv);
649 	BESW(V1WGHT, v1wghtv);
650 	BESW(V1SRCLST, v1srclstv);
651 	BESW(GLOBCTL, globctlv);
652 	BESW(CTL, ctlv);
653 
654 
655 	/**************************
656 	 *** setup color keying ***
657 	 **************************/
658 
659 	/* setup colorkeying */
660 	DXIW(COLKEY, (ow->alpha.value & ow->alpha.mask));
661 
662 	DXIW(COLKEY0RED, (ow->red.value & ow->red.mask));
663 	DXIW(COLKEY0GREEN, (ow->green.value & ow->green.mask));
664 	DXIW(COLKEY0BLUE, (ow->blue.value & ow->blue.mask));
665 
666 	DXIW(COLMSK, ow->alpha.mask);
667 
668 	DXIW(COLMSK0RED, ow->red.mask);
669 	DXIW(COLMSK0GREEN, ow->green.mask);
670 	DXIW(COLMSK0BLUE, ow->blue.mask);
671 
672 	/* enable colorkeying */
673 	DXIW(KEYOPMODE,0x01);
674 
675 
676 	/*************************
677 	 *** setup misc. stuff ***
678 	 *************************/
679 
680 	/* setup brightness and contrast to be 'neutral' (this is not implemented on G200) */
681 	BESW(LUMACTL, 0x00000080);
682 
683 	/* setup source pitch including slopspace (in pixels); AND is required by hardware */
684 	BESW(PITCH, (ob->width & 0x00000fff));
685 
686 	/* on a 500Mhz P3 CPU just logging a line costs 400uS (18-19 vcounts at 1024x768x60Hz)!
687 	 * programming the registers above actually costs 180uS here */
688 	LOG(3,("Overlay: completed at Vcount %d\n", CR1R(VCOUNT)));
689 
690 	return B_OK;
691 }
692 
693 status_t gx00_release_bes()
694 {
695 	/* setup BES control: disable scaler */
696 	BESW(CTL, 0x00000000);
697 
698 	return B_OK;
699 }
700