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