2 Copyright (c) 2002-2004, Thomas Kurschel
4 Part of Radeon accelerant
6 Hardware access routines for overlays
9 #include "GlobalData.h"
10 #include "radeon_interface.h"
12 #include "overlay_regs.h"
14 #include "capture_regs.h"
16 #include "pll_access.h"
22 void Radeon_TempHideOverlay( accelerator_info
*ai
);
24 // standard (linear) gamma
31 { RADEON_OV0_GAMMA_0_F
, false, 0x100, 0x0000 },
32 { RADEON_OV0_GAMMA_10_1F
, false, 0x100, 0x0020 },
33 { RADEON_OV0_GAMMA_20_3F
, false, 0x100, 0x0040 },
34 { RADEON_OV0_GAMMA_40_7F
, false, 0x100, 0x0080 },
35 { RADEON_OV0_GAMMA_80_BF
, true, 0x100, 0x0100 },
36 { RADEON_OV0_GAMMA_C0_FF
, true, 0x100, 0x0100 },
37 { RADEON_OV0_GAMMA_100_13F
, true, 0x100, 0x0200 },
38 { RADEON_OV0_GAMMA_140_17F
, true, 0x100, 0x0200 },
39 { RADEON_OV0_GAMMA_180_1BF
, true, 0x100, 0x0300 },
40 { RADEON_OV0_GAMMA_1C0_1FF
, true, 0x100, 0x0300 },
41 { RADEON_OV0_GAMMA_200_23F
, true, 0x100, 0x0400 },
42 { RADEON_OV0_GAMMA_240_27F
, true, 0x100, 0x0400 },
43 { RADEON_OV0_GAMMA_280_2BF
, true, 0x100, 0x0500 },
44 { RADEON_OV0_GAMMA_2C0_2FF
, true, 0x100, 0x0500 },
45 { RADEON_OV0_GAMMA_300_33F
, true, 0x100, 0x0600 },
46 { RADEON_OV0_GAMMA_340_37F
, true, 0x100, 0x0600 },
47 { RADEON_OV0_GAMMA_380_3BF
, false, 0x100, 0x0700 },
48 { RADEON_OV0_GAMMA_3C0_3FF
, false, 0x100, 0x0700 }
52 // setup overlay unit before first use
53 void Radeon_InitOverlay(
54 accelerator_info
*ai
, int crtc_idx
)
56 vuint8
*regs
= ai
->regs
;
57 shared_info
*si
= ai
->si
;
63 // make sure we really write this value as the "toggle" bit
64 // contained in it (which is zero initially) is edge-sensitive!
65 // for capturing, we need to select "software" video port
66 si
->overlay_mgr
.auto_flip_reg
= RADEON_OV0_VID_PORT_SELECT_SOFTWARE
;
68 OUTREG( regs
, RADEON_OV0_SCALE_CNTL
, RADEON_SCALER_SOFT_RESET
);
69 OUTREG( regs
, RADEON_OV0_AUTO_FLIP_CNTRL
, si
->overlay_mgr
.auto_flip_reg
);
70 OUTREG( regs
, RADEON_OV0_FILTER_CNTL
, // use fixed filter coefficients
71 RADEON_OV0_HC_COEF_ON_HORZ_Y
|
72 RADEON_OV0_HC_COEF_ON_HORZ_UV
|
73 RADEON_OV0_HC_COEF_ON_VERT_Y
|
74 RADEON_OV0_HC_COEF_ON_VERT_UV
);
75 OUTREG( regs
, RADEON_OV0_KEY_CNTL
, RADEON_GRAPHIC_KEY_FN_EQ
|
76 RADEON_VIDEO_KEY_FN_FALSE
|
78 OUTREG( regs
, RADEON_OV0_TEST
, 0 );
79 // OUTREG( regs, RADEON_FCP_CNTL, RADEON_FCP_CNTL_GND ); // disable capture clock
80 // OUTREG( regs, RADEON_CAP0_TRIG_CNTL, 0 ); // disable capturing
81 OUTREG( regs
, RADEON_OV0_REG_LOAD_CNTL
, 0 );
82 // tell deinterlacer to always show recent field
83 OUTREG( regs
, RADEON_OV0_DEINTERLACE_PATTERN
,
84 0xaaaaa | (9 << RADEON_OV0_DEINT_PAT_LEN_M1_SHIFT
) );
87 for( i
= 0; i
< sizeof( std_gamma
) / sizeof( std_gamma
[0] ); ++i
) {
88 if( !std_gamma
[i
].r200_or_above
|| si
->asic
>= rt_r200
) {
89 OUTREG( regs
, std_gamma
[i
].reg
,
90 (std_gamma
[i
].slope
<< 16) | std_gamma
[i
].offset
);
94 // overlay unit can only handle up to 175 MHz, if pixel clock is higher,
95 // only every second pixel is handled
96 if( si
->crtc
[crtc_idx
].mode
.timing
.pixel_clock
< 175000 )
101 Radeon_OUTPLLP( regs
, si
->asic
, RADEON_VCLK_ECP_CNTL
,
102 ecp_div
<< RADEON_ECP_DIV_SHIFT
, ~RADEON_ECP_DIV_MASK
);
104 // Force the overlay clock on for integrated chips
105 if ((si
->asic
== rt_rs100
) ||
106 (si
->asic
== rt_rs200
) ||
107 (si
->asic
== rt_rs300
)) {
108 Radeon_OUTPLL( regs
, si
->asic
, RADEON_VCLK_ECP_CNTL
,
109 (Radeon_INPLL( regs
, si
->asic
, RADEON_VCLK_ECP_CNTL
) | (1<<18)));
112 si
->active_overlay
.crtc_idx
= si
->pending_overlay
.crtc_idx
;
114 // invalidate active colour space
115 si
->active_overlay
.ob
.space
= -1;
117 // invalidate position/scaling
118 si
->active_overlay
.ob
.width
= -1;
121 // colour space transformation matrix
122 typedef struct space_transform
124 float RefLuma
; // scaling of luma to use full RGB range
125 float RefRCb
; // b/u -> r
126 float RefRY
; // g/y -> r
127 float RefRCr
; // r/v -> r
137 // Parameters for ITU-R BT.601 and ITU-R BT.709 colour spaces
138 space_transform trans_yuv
[2] =
140 { 1.1678, 0.0, 1, 1.6007, -0.3929, 1, -0.8154, 2.0232, 1, 0.0 }, /* BT.601 */
141 { 1.1678, 0.0, 1, 1.7980, -0.2139, 1, -0.5345, 2.1186, 1, 0.0 } /* BT.709 */
145 // RGB is a pass through
146 space_transform trans_rgb
=
147 { 1, 0, 0, 1, 0, 1, 0, 1, 0, 0 };
150 // set overlay colour space transformation matrix
151 static void Radeon_SetTransform(
152 accelerator_info
*ai
,
158 float green_intensity
,
159 float blue_intensity
,
162 vuint8
*regs
= ai
->regs
;
163 shared_info
*si
= ai
->si
;
164 float OvHueSin
, OvHueCos
;
166 float CAdjRY
, CAdjGY
, CAdjBY
;
167 float CAdjRCb
, CAdjRCr
;
168 float CAdjGCb
, CAdjGCr
;
169 float CAdjBCb
, CAdjBCr
;
170 float RedAdj
,GreenAdj
,BlueAdj
;
171 float OvROff
, OvGOff
, OvBOff
;
172 float OvRY
, OvGY
, OvBY
;
179 uint32 dwOvROff
, dwOvGOff
, dwOvBOff
;
180 uint32 dwOvRY
, dwOvGY
, dwOvBY
;
181 uint32 dwOvRCb
, dwOvRCr
;
182 uint32 dwOvGCb
, dwOvGCr
;
183 uint32 dwOvBCb
, dwOvBCr
;
185 space_transform
*trans
;
189 // get proper conversion formula
190 switch( si
->pending_overlay
.ob
.space
) {
193 Loff
= 16 * 4; // internal representation is 10 Bits
199 trans
= &trans_yuv
[ref
];
214 // get matrix values to convert overlay colour space to RGB
215 // applying colour adjustment, saturation and luma scaling
216 // (saturation doesn't work with RGB input, perhaps it did with some
217 // maths; this is left to the reader :)
218 CAdjRY
= cont
* trans
->RefLuma
* trans
->RefRY
;
219 CAdjGY
= cont
* trans
->RefLuma
* trans
->RefGY
;
220 CAdjBY
= cont
* trans
->RefLuma
* trans
->RefBY
;
222 CAdjRCb
= sat
* -OvHueSin
* trans
->RefRCr
;
223 CAdjRCr
= sat
* OvHueCos
* trans
->RefRCr
;
224 CAdjGCb
= sat
* (OvHueCos
* trans
->RefGCb
- OvHueSin
* trans
->RefGCr
);
225 CAdjGCr
= sat
* (OvHueSin
* trans
->RefGCb
+ OvHueCos
* trans
->RefGCr
);
226 CAdjBCb
= sat
* OvHueCos
* trans
->RefBCb
;
227 CAdjBCr
= sat
* OvHueSin
* trans
->RefBCb
;
229 // adjust black level
230 CAdjOff
= cont
* trans
[ref
].RefLuma
* bright
* 1023.0;
231 RedAdj
= cont
* trans
[ref
].RefLuma
* red_intensity
* 1023.0;
232 GreenAdj
= cont
* trans
[ref
].RefLuma
* green_intensity
* 1023.0;
233 BlueAdj
= cont
* trans
[ref
].RefLuma
* blue_intensity
* 1023.0;
245 OvROff
= RedAdj
+ CAdjOff
- CAdjRY
* Loff
- (OvRCb
+ OvRCr
) * Coff
;
246 OvGOff
= GreenAdj
+ CAdjOff
- CAdjGY
* Loff
- (OvGCb
+ OvGCr
) * Coff
;
247 OvBOff
= BlueAdj
+ CAdjOff
- CAdjBY
* Loff
- (OvBCb
+ OvBCr
) * Coff
;
249 dwOvROff
= ((int32
)(OvROff
* 2.0)) & 0x1fff;
250 dwOvGOff
= ((int32
)(OvGOff
* 2.0)) & 0x1fff;
251 dwOvBOff
= ((int32
)(OvBOff
* 2.0)) & 0x1fff;
253 dwOvRY
= (((int32
)(OvRY
* 2048.0))&0x7fff)<<17;
254 dwOvGY
= (((int32
)(OvGY
* 2048.0))&0x7fff)<<17;
255 dwOvBY
= (((int32
)(OvBY
* 2048.0))&0x7fff)<<17;
256 dwOvRCb
= (((int32
)(OvRCb
* 2048.0))&0x7fff)<<1;
257 dwOvRCr
= (((int32
)(OvRCr
* 2048.0))&0x7fff)<<17;
258 dwOvGCb
= (((int32
)(OvGCb
* 2048.0))&0x7fff)<<1;
259 dwOvGCr
= (((int32
)(OvGCr
* 2048.0))&0x7fff)<<17;
260 dwOvBCb
= (((int32
)(OvBCb
* 2048.0))&0x7fff)<<1;
261 dwOvBCr
= (((int32
)(OvBCr
* 2048.0))&0x7fff)<<17;
263 OUTREG( regs
, RADEON_OV0_LIN_TRANS_A
, dwOvRCb
| dwOvRY
);
264 OUTREG( regs
, RADEON_OV0_LIN_TRANS_B
, dwOvROff
| dwOvRCr
);
265 OUTREG( regs
, RADEON_OV0_LIN_TRANS_C
, dwOvGCb
| dwOvGY
);
266 OUTREG( regs
, RADEON_OV0_LIN_TRANS_D
, dwOvGOff
| dwOvGCr
);
267 OUTREG( regs
, RADEON_OV0_LIN_TRANS_E
, dwOvBCb
| dwOvBY
);
268 OUTREG( regs
, RADEON_OV0_LIN_TRANS_F
, dwOvBOff
| dwOvBCr
);
270 si
->active_overlay
.ob
.space
= si
->pending_overlay
.ob
.space
;
274 // convert Be colour key to rgb value
275 static uint32
colourKey2RGB32(
276 uint32 space
, uint8 red
, uint8 green
, uint8 blue
)
282 // the way Be defines colour keys may be convinient to some driver developers,
283 // but it's not well defined - took me some time to find out the format used
284 // and still I have no idea how alpha is defined; Rudolf told me that alpha is
289 ((uint32
)(red
>> 0) << (16+3)) |
290 ((uint32
)(green
>> 0) << (8+3)) |
295 ((uint32
)(red
>> 0) << (16+3)) |
296 ((uint32
)(green
>> 0) << (8+2)) |
301 res
= ((uint32
)(red
) << 16) | ((uint32
)(green
) << 8) | blue
;
307 SHOW_FLOW( 3, "key=%lx", res
);
312 // set colour key of overlay
313 static void Radeon_SetColourKey(
314 accelerator_info
*ai
, const overlay_window
*ow
)
316 virtual_card
*vc
= ai
->vc
;
317 vuint8
*regs
= ai
->regs
;
318 uint32 rgb32
, mask32
, min32
, max32
;
320 /*SHOW_FLOW( 0, "value=%02x %02x %02x, mask=%02x %02x %02x",
321 ow->red.value, ow->green.value, ow->blue.value,
322 ow->red.mask, ow->green.mask, ow->blue.mask );*/
324 // Radeons don't support value and mask as colour key but colour range
325 rgb32
= colourKey2RGB32( vc
->mode
.space
,
326 ow
->red
.value
, ow
->green
.value
, ow
->blue
.value
);
327 mask32
= colourKey2RGB32( vc
->mode
.space
,
328 ow
->red
.mask
, ow
->green
.mask
, ow
->blue
.mask
);
330 // ~mask32 are all unimportant (usually low order) bits
331 // oring this to the colour should give us the highest valid colour value
332 // (add would be more precise but may lead to overflows)
334 max32
= rgb32
| ~mask32
;
336 OUTREG( regs
, RADEON_OV0_GRAPHICS_KEY_CLR_LOW
, min32
);
337 OUTREG( regs
, RADEON_OV0_GRAPHICS_KEY_CLR_HIGH
, max32
);
338 OUTREG( regs
, RADEON_OV0_KEY_CNTL
,
339 RADEON_GRAPHIC_KEY_FN_EQ
|
340 RADEON_VIDEO_KEY_FN_FALSE
|
345 uint max_scale
; // maximum src_width/dest_width,
346 // i.e. source increment per screen pixel
347 uint8 group_size
; // size of one filter group in pixels
348 uint8 p1_step_by
, p23_step_by
; // > 0: log(source pixel increment)+1, 2-tap filter
349 // = 0: source pixel increment = 1, 4-tap filter
353 // scaling/filter tables depending on overlay colour space:
354 // magnifying pixels is no problem, but minifying can lead to overload,
355 // so we have to skip pixels and/or use 2-tap filters
356 static hscale_factor scale_RGB16
[] = {
357 { (2 << 12), 2, 1, 1 },
358 { (4 << 12), 2, 2, 2 },
359 { (8 << 12), 2, 3, 3 },
360 { (16 << 12), 2, 4, 4 },
361 { (32 << 12), 2, 5, 5 }
364 static hscale_factor scale_RGB32
[] = {
365 { (2 << 12) / 3, 2, 0, 0 },
366 { (4 << 12) / 3, 4, 1, 1 },
367 { (8 << 12) / 3, 4, 2, 2 },
368 { (4 << 12), 4, 2, 3 },
369 { (16 << 12) / 3, 4, 3, 3 },
370 { (8 << 12), 4, 3, 4 },
371 { (32 << 12) / 3, 4, 4, 4 },
372 { (16 << 12), 4, 5, 5 }
375 static hscale_factor scale_YUV
[] = {
376 { (16 << 12) / 16, 2, 0, 0 },
377 { (16 << 12) / 12, 2, 0, 1 }, // mode 4, 1, 0 (as used by YUV12) is impossible
378 { (16 << 12) / 8, 4, 1, 1 },
379 { (16 << 12) / 6, 4, 1, 2 },
380 { (16 << 12) / 4, 4, 2, 2 },
381 { (16 << 12) / 3, 4, 2, 3 },
382 { (16 << 12) / 2, 4, 3, 3 },
383 { (16 << 12) / 1, 4, 4, 4 }
386 static hscale_factor scale_YUV12
[] = {
387 { (16 << 12) / 16, 2, 0, 0 },
388 { (16 << 12) / 12, 4, 1, 0 },
389 { (16 << 12) / 12, 2, 0, 1 },
390 { (16 << 12) / 8, 4, 1, 1 },
391 { (16 << 12) / 6, 4, 1, 2 },
392 { (16 << 12) / 4, 4, 2, 2 },
393 { (16 << 12) / 3, 4, 2, 3 },
394 { (16 << 12) / 2, 4, 3, 3 },
395 { (int)((16 << 12) / 1.5), 4, 3, 4 },
396 { (int)((16 << 12) / 1.0), 4, 4, 4 },
397 { (int)((16 << 12) / 0.75), 4, 4, 5 },
398 { (int)((16 << 12) / 0.5), 4, 5, 5 }
401 #define min3( a, b, c ) (min( (a), min( (b), (c) )))
403 static hscale_factor scale_YUV9
[] = {
404 { min3( (16 << 12) / 12, (3 << 12) * 1, (2 << 12) * 4 * 1 ), 2, 0, 0 },
405 { min3( (16 << 12) / 8, (3 << 12) * 1, (2 << 12) * 4 * 1 ), 4, 1, 0 },
406 { min3( (16 << 12) / 10, (3 << 12) * 1, (2 << 12) * 4 * 1 ), 2, 0, 1 },
407 { min3( (16 << 12) / 6, (3 << 12) * 1, (2 << 12) * 4 * 1 ), 4, 1, 1 },
408 { min3( (16 << 12) / 5, (3 << 12) * 1, (2 << 12) * 4 * 2 ), 4, 1, 2 },
409 { min3( (16 << 12) / 3, (3 << 12) * 2, (2 << 12) * 4 * 2 ), 4, 2, 2 },
410 { min3( (int)((16 << 12) / 2.5), (3 << 12) * 1, (2 << 12) * 4 * 4 ), 4, 2, 3 }, // probably, it should be (3 << 12) * 2
411 { min3( (int)((16 << 12) / 1.5), (3 << 12) * 4, (2 << 12) * 4 * 4 ), 4, 3, 3 },
412 { min3( (int)((16 << 12) / 0.75), (3 << 12) * 8, (2 << 12) * 4 * 8 ), 4, 4, 4 },
413 { min3( (int)((16 << 12) / 0.625), (3 << 12) * 8, (2 << 12) * 4 * 16 ), 4, 4, 5 },
414 { min3( (int)((16 << 12) / 0.375), (3 << 12) * 16, (2 << 12) * 4 * 16 ), 4, 5, 5 }
418 // parameters of an overlay colour space
420 uint8 bpp_shift
; // log2( bytes per pixel (main plain) )
421 uint8 bpuv_shift
; // log2( bytes per pixel (uv-plane) );
422 // if there is one plane only: bpp=bpuv
423 uint8 num_planes
; // number of planes
424 uint8 h_uv_sub_sample_shift
; // log2( horizontal pixels per uv pair )
425 uint8 v_uv_sub_sample_shift
; // log2( vertical pixels per uv pair )
426 hscale_factor
*factors
; // scaling/filter table
430 static space_params space_params_table
[16] = {
431 { 0, 0, 0, 0, 0, NULL
, 0 }, // reserved
432 { 0, 0, 0, 0, 0, NULL
, 0 }, // reserved
433 { 0, 0, 0, 0, 0, NULL
, 0 }, // reserved
434 { 1, 1, 1, 0, 0, scale_RGB16
, B_COUNT_OF( scale_RGB16
) }, // RGB15
435 { 1, 1, 1, 0, 0, scale_RGB16
, B_COUNT_OF( scale_RGB16
) }, // RGB16
436 { 0, 0, 0, 0, 0, NULL
, 0 }, // reserved
437 { 2, 2, 1, 0, 0, scale_RGB32
, B_COUNT_OF( scale_RGB32
) }, // RGB32
438 { 0, 0, 0, 0, 0, NULL
, 0 }, // reserved
439 { 0, 0, 0, 0, 0, NULL
, 0 }, // reserved
440 { 0, 0, 3, 2, 2, scale_YUV9
, B_COUNT_OF( scale_YUV9
) }, // YUV9
441 { 0, 0, 3, 1, 1, scale_YUV12
, B_COUNT_OF( scale_YUV12
) }, // YUV12, three-plane
442 { 1, 1, 1, 1, 0, scale_YUV
, B_COUNT_OF( scale_YUV
) }, // VYUY422
443 { 1, 1, 1, 1, 0, scale_YUV
, B_COUNT_OF( scale_YUV
) }, // YVYU422
444 { 0, 1, 2, 1, 1, scale_YUV12
, B_COUNT_OF( scale_YUV12
) }, // YUV12, two-plane
445 { 0, 1, 2, 1, 1, NULL
, 0 }, // ???
446 { 0, 0, 0, 0, 0, NULL
, 0 } // reserved
449 // get appropriate scaling/filter parameters
450 static hscale_factor
*getHScaleFactor(
451 accelerator_info
*ai
,
452 space_params
*params
,
453 uint32 src_left
, uint32 src_right
, uint32
*h_inc
)
455 uint words_per_p1_line
, words_per_p23_line
, max_words_per_line
;
456 bool p1_4tap_allowed
, p23_4tap_allowed
;
459 hscale_factor
*factors
;
463 // check whether fifo is large enough to feed vertical 4-tap-filter
466 ceilShiftDiv( (src_right
- 1) << params
->bpp_shift
, 4 ) -
467 ((src_left
<< params
->bpp_shift
) >> 4) + 1;
469 ceilShiftDiv( (src_right
- 1) << params
->bpuv_shift
, 4 ) -
470 ((src_left
<< params
->bpuv_shift
) >> 4) + 1;
472 // overlay scaler line length differs for different revisions
473 // this needs to be maintained by hand
474 if (ai
->si
->asic
== rt_r200
|| ai
->si
->asic
>= rt_r300
)
475 max_words_per_line
= 1920 / 16;
477 max_words_per_line
= 1536 / 16;
479 switch (params
->num_planes
) {
481 p1_4tap_allowed
= words_per_p1_line
< max_words_per_line
/ 2;
482 p23_4tap_allowed
= words_per_p23_line
< max_words_per_line
/ 4;
485 p1_4tap_allowed
= words_per_p1_line
< max_words_per_line
/ 2;
486 p23_4tap_allowed
= words_per_p23_line
< max_words_per_line
/ 2;
490 p1_4tap_allowed
= p23_4tap_allowed
= words_per_p1_line
< max_words_per_line
;
494 SHOW_FLOW( 3, "p1_4tap_allowed=%d, p23_4t_allowed=%d",
495 (int)p1_4tap_allowed
, (int)p23_4tap_allowed
);
497 // search for proper scaling/filter entry
498 factors
= params
->factors
;
499 num_factors
= params
->num_factors
;
501 if (factors
== NULL
|| num_factors
== 0)
504 for (i
= 0; i
< num_factors
; ++i
, ++factors
) {
505 if (*h_inc
<= factors
->max_scale
506 && (factors
->p1_step_by
> 0 || p1_4tap_allowed
)
507 && (factors
->p23_step_by
> 0 || p23_4tap_allowed
))
511 if (i
== num_factors
) {
512 // overlay is asked to be scaled down more than allowed,
513 // so use least scaling factor supported
515 *h_inc
= factors
->max_scale
;
518 SHOW_FLOW( 3, "group_size=%d, p1_step_by=%d, p23_step_by=%d",
519 factors
->group_size
, factors
->p1_step_by
, factors
->p23_step_by
);
525 #define I2FF( a, shift ) ((uint32)((a) * (1 << (shift))))
528 // show overlay on screen
529 static status_t
Radeon_ShowOverlay(
530 accelerator_info
*ai
, int crtc_idx
)
532 virtual_card
*vc
= ai
->vc
;
533 shared_info
*si
= ai
->si
;
534 vuint8
*regs
= ai
->regs
;
535 overlay_info
*overlay
= &si
->pending_overlay
;
536 overlay_buffer_node
*node
= overlay
->on
;
537 crtc_info
*crtc
= &si
->crtc
[crtc_idx
];
541 uint32 src_v_inc
, src_h_inc
;
542 uint32 src_left
, src_top
, src_right
, src_bottom
;
543 int32 dest_left
, dest_top
, dest_right
, dest_bottom
;
546 uint32 p1_h_accum_init
, p23_h_accum_init
, p1_v_accum_init
, p23_v_accum_init
;
547 uint32 p1_active_lines
, p23_active_lines
;
548 hscale_factor
*factors
;
549 space_params
*params
;
551 uint32 p1_h_inc
, p23_h_inc
;
552 uint32 p1_x_start
, p1_x_end
;
553 uint32 p23_x_start
, p23_x_end
;
557 /*uint32 buffer[20*2];
562 Radeon_SetColourKey( ai
, &overlay
->ow
);
564 // overlay unit can only handle up to 175 MHz; if pixel clock is higher,
565 // only every second pixel is handled
566 // (this devider is gets written into PLL by InitOverlay,
567 // so we don't need to do it ourself)
568 if( crtc
->mode
.timing
.pixel_clock
< 175000 )
574 // scaling is independant of clipping, get this first
576 uint32 src_width
, src_height
;
578 src_width
= overlay
->ov
.width
;
579 src_height
= overlay
->ov
.height
;
581 // this is for graphics card
582 v_inc
= (src_height
<< 20) / overlay
->ow
.height
;
583 h_inc
= (src_width
<< (12 + ecp_div
)) / overlay
->ow
.width
;
587 src_v_inc
= (src_height
<< 16) / overlay
->ow
.height
;
588 src_h_inc
= (src_width
<< 16) / overlay
->ow
.width
;
591 // calculate unclipped position/size
592 // TBD: I assume that overlay_window.offset_xyz is only a hint where
593 // no overlay is visible; another interpretation were to zoom
594 // the overlay so it fits into remaining space
595 src_left
= (overlay
->ov
.h_start
<< 16) + overlay
->ow
.offset_left
* src_h_inc
;
596 src_top
= (overlay
->ov
.v_start
<< 16) + overlay
->ow
.offset_top
* src_v_inc
;
597 src_right
= ((overlay
->ov
.h_start
+ overlay
->ov
.width
) << 16) -
598 overlay
->ow
.offset_right
* src_h_inc
;
599 src_bottom
= ((overlay
->ov
.v_start
+ overlay
->ov
.height
) << 16) -
600 overlay
->ow
.offset_top
* src_v_inc
;
601 dest_left
= overlay
->ow
.h_start
+ overlay
->ow
.offset_left
;
602 dest_top
= overlay
->ow
.v_start
+ overlay
->ow
.offset_top
;
603 dest_right
= overlay
->ow
.h_start
+ overlay
->ow
.width
- overlay
->ow
.offset_right
;
604 dest_bottom
= overlay
->ow
.v_start
+ overlay
->ow
.height
- overlay
->ow
.offset_bottom
;
606 SHOW_FLOW( 3, "ow: h=%d, v=%d, width=%d, height=%d",
607 overlay
->ow
.h_start
, overlay
->ow
.v_start
,
608 overlay
->ow
.width
, overlay
->ow
.height
);
610 SHOW_FLOW( 3, "offset_left=%d, offset_right=%d, offset_top=%d, offset_bottom=%d",
611 overlay
->ow
.offset_left
, overlay
->ow
.offset_right
,
612 overlay
->ow
.offset_top
, overlay
->ow
.offset_bottom
);
615 // apply virtual screen
616 dest_left
-= vc
->mode
.h_display_start
+ crtc
->rel_x
;
617 dest_top
-= vc
->mode
.v_display_start
+ crtc
->rel_y
;
618 dest_right
-= vc
->mode
.h_display_start
+ crtc
->rel_x
;
619 dest_bottom
-= vc
->mode
.v_display_start
+ crtc
->rel_y
;
621 // clip to visible area
622 if( dest_left
< 0 ) {
623 src_left
+= -dest_left
* src_h_inc
;
627 src_top
+= -dest_top
* src_v_inc
;
631 SHOW_FLOW( 3, "mode: w=%d, h=%d",
632 crtc
->mode
.timing
.h_display
, crtc
->mode
.timing
.v_display
);
634 if( dest_right
> crtc
->mode
.timing
.h_display
)
635 dest_right
= crtc
->mode
.timing
.h_display
;
636 if( dest_bottom
> crtc
->mode
.timing
.v_display
)
637 dest_bottom
= crtc
->mode
.timing
.v_display
;
639 SHOW_FLOW( 3, "src=(%d, %d, %d, %d)",
640 src_left
, src_top
, src_right
, src_bottom
);
641 SHOW_FLOW( 3, "dest=(%d, %d, %d, %d)",
642 dest_left
, dest_top
, dest_right
, dest_bottom
);
645 // especially with multi-screen modes the overlay may not be on screen at all
646 if( dest_left
>= dest_right
|| dest_top
>= dest_bottom
||
647 src_left
>= src_right
|| src_top
>= src_bottom
)
649 Radeon_TempHideOverlay( ai
);
654 // let's calculate all those nice register values
655 SHOW_FLOW( 3, "ati_space=%d", node
->ati_space
);
656 params
= &space_params_table
[node
->ati_space
];
658 // choose proper scaler
660 factors
= getHScaleFactor( ai
, params
, src_left
>> 16, src_right
>> 16, &h_inc
);
661 if( factors
== NULL
)
664 p1_h_inc
= factors
->p1_step_by
> 0 ?
665 h_inc
>> (factors
->p1_step_by
- 1) : h_inc
;
667 (factors
->p23_step_by
> 0 ? h_inc
>> (factors
->p23_step_by
- 1) : h_inc
)
668 >> params
->h_uv_sub_sample_shift
;
670 SHOW_FLOW( 3, "p1_h_inc=%x, p23_h_inc=%x", p1_h_inc
, p23_h_inc
);
673 // get register value for start/end position of overlay image (pixel-precise only)
675 uint32 p1_step_size
, p23_step_size
;
676 uint32 p1_left
, p1_right
, p1_width
;
677 uint32 p23_left
, p23_right
, p23_width
;
679 p1_left
= src_left
>> 16;
680 p1_right
= src_right
>> 16;
681 p1_width
= p1_right
- p1_left
;
683 p1_step_size
= factors
->p1_step_by
> 0 ? (1 << (factors
->p1_step_by
- 1)) : 1;
684 p1_x_start
= p1_left
% (16 >> params
->bpp_shift
);
685 p1_x_end
= ((p1_x_start
+ p1_width
- 1) / p1_step_size
) * p1_step_size
;
687 SHOW_FLOW( 3, "p1_x_start=%d, p1_x_end=%d", p1_x_start
, p1_x_end
);
689 p23_left
= (src_left
>> 16) >> params
->h_uv_sub_sample_shift
;
690 p23_right
= (src_right
>> 16) >> params
->h_uv_sub_sample_shift
;
691 p23_width
= p23_right
- p23_left
;
693 p23_step_size
= factors
->p23_step_by
> 0 ? (1 << (factors
->p23_step_by
- 1)) : 1;
694 // if resolution of Y and U/V differs but YUV are stored in one
695 // plane then UV alignment depends on Y data, therefore the hack
696 // (you are welcome to replace this with some cleaner code ;)
697 p23_x_start
= p23_left
%
698 ((16 >> params
->bpuv_shift
) /
699 (node
->ati_space
== 11 || node
->ati_space
== 12 ? 2 : 1));
700 p23_x_end
= (int)((p23_x_start
+ p23_width
- 1) / p23_step_size
) * p23_step_size
;
702 SHOW_FLOW( 3, "p23_x_start=%d, p23_x_end=%d", p23_x_start
, p23_x_end
);
704 // get memory location of first word to be read by scaler
705 // (save relative offset for fast update)
706 si
->active_overlay
.rel_offset
= (src_top
>> 16) * node
->buffer
.bytes_per_row
+
707 ((p1_left
<< params
->bpp_shift
) & ~0xf);
708 offset
= node
->mem_offset
+ si
->active_overlay
.rel_offset
;
710 SHOW_FLOW( 3, "rel_offset=%x", si
->active_overlay
.rel_offset
);
713 // get active lines for scaler
714 // (we could add additional blank lines for DVD letter box mode,
715 // but this is not supported by API; additionally, this only makes
716 // sense if want to put subtitles onto the black border, which is
717 // supported neither)
719 uint16 int_top
, int_bottom
;
721 int_top
= src_top
>> 16;
722 int_bottom
= (src_bottom
>> 16);
724 p1_active_lines
= int_bottom
- int_top
- 1;
726 ceilShiftDiv( int_bottom
- 1, params
->v_uv_sub_sample_shift
) -
727 (int_top
>> params
->v_uv_sub_sample_shift
);
729 SHOW_FLOW( 3, "p1_active_lines=%d, p23_active_lines=%d",
730 p1_active_lines
, p23_active_lines
);
733 // if picture is stretched for flat panel, we need to scale all
734 // vertical values accordingly
735 // TBD: there is no description at all concerning this, so v_accum_init may
736 // need to be initialized based on original value
738 if( (crtc
->active_displays
& (dd_lvds
| dd_dvi
)) != 0 ) {
741 // convert 32.32 format to 16.16 format; else we
742 // cannot multiply two fixed point values without
744 v_ratio
= si
->flatpanels
[crtc
->flatpanel_port
].v_ratio
>> (FIX_SHIFT
- 16);
746 v_inc
= (v_inc
* v_ratio
) >> 16;
749 SHOW_FLOW( 3, "v_inc=%x", v_inc
);
752 // get initial horizontal scaler values, taking care of precharge
753 // don't ask questions about formulas - take them as is
754 // (TBD: home-brewed sub-pixel source clipping may be wrong,
755 // especially for uv-planes)
757 uint32 p23_group_size
;
759 tmp
= ((src_left
& 0xffff) >> 11) + (
761 I2FF( p1_x_start
% factors
->group_size
, 12 ) +
764 I2FF( 0.5, 12-5 ) // rounding
765 ) >> (12 - 5)); // scaled by 1 << 5
767 SHOW_FLOW( 3, "p1_h_accum_init=%x", tmp
);
770 ((tmp
<< 15) & RADEON_OV0_P1_H_ACCUM_INIT_MASK
) |
771 ((tmp
<< 23) & RADEON_OV0_P1_PRESHIFT_MASK
);
776 tmp
= ((src_left
& 0xffff) >> 11) + (
778 I2FF( p23_x_start
% p23_group_size
, 12 ) +
781 I2FF( 0.5, 12-5 ) // rounding
782 ) >> (12 - 5)); // scaled by 1 << 5
784 SHOW_FLOW( 3, "p23_h_accum_init=%x", tmp
);
787 ((tmp
<< 15) & RADEON_OV0_P23_H_ACCUM_INIT_MASK
) |
788 ((tmp
<< 23) & RADEON_OV0_P23_PRESHIFT_MASK
);
791 // get initial vertical scaler values, taking care of precharge
793 uint extra_full_line
;
795 extra_full_line
= factors
->p1_step_by
== 0 ? 1 : 0;
797 tmp
= ((src_top
& 0x0000ffff) >> 11) + (
799 I2FF( 1.5, 20 ) + I2FF( extra_full_line
, 20 ) + v_inc
/ 2,
800 I2FF( 2.5, 20 ) + 2 * I2FF( extra_full_line
, 20 )
801 ) + I2FF( 0.5, 20-5 )) // rounding
802 >> (20 - 5)); // scaled by 1 << 5
804 SHOW_FLOW( 3, "p1_v_accum_init=%x", tmp
);
807 ((tmp
<< 15) & RADEON_OV0_P1_V_ACCUM_INIT_MASK
) | 0x00000001;
810 extra_full_line
= factors
->p23_step_by
== 0 ? 1 : 0;
812 if( params
->v_uv_sub_sample_shift
> 0 ) {
813 tmp
= ((src_top
& 0x0000ffff) >> 11) + (
816 I2FF( extra_full_line
, 20 ) +
817 ((v_inc
/ 2) >> params
->v_uv_sub_sample_shift
),
819 2 * I2FF( extra_full_line
, 20 )
820 ) + I2FF( 0.5, 20-5 )) // rounding
821 >> (20 - 5)); // scaled by 1 << 5
823 tmp
= ((src_top
& 0x0000ffff) >> 11) + (
826 2 * I2FF( extra_full_line
, 20 ) +
827 I2FF( 0.5, 20-5 ) // rounding
828 ) >> (20 - 5)); // scaled by 1 << 5
831 SHOW_FLOW( 3, "p23_v_accum_init=%x", tmp
);
834 ((tmp
<< 15) & RADEON_OV0_P23_V_ACCUM_INIT_MASK
) | 0x00000001;
837 // show me what you've got!
838 // we could lock double buffering of overlay unit during update
839 // (new values are copied during vertical blank, so if we've updated
840 // only some of them, you get a whole frame of mismatched values)
841 // but during tests I couldn't get the artifacts go away, so
842 // we use the dangerous way which has the pro to not require any
845 // let's try to lock overlay unit
846 // we had to wait now until the lock takes effect, but this is
847 // impossible with CCE; perhaps we have to convert this code to
848 // direct register access; did that - let's see what happens...
849 OUTREG( regs
, RADEON_OV0_REG_LOAD_CNTL
, RADEON_REG_LD_CTL_LOCK
);
851 // wait until register access is locked
852 while( (INREG( regs
, RADEON_OV0_REG_LOAD_CNTL
)
853 & RADEON_REG_LD_CTL_LOCK_READBACK
) == 0 )
856 OUTREG( regs
, RADEON_OV0_VID_BUF0_BASE_ADRS
, offset
);
857 OUTREG( regs
, RADEON_OV0_VID_BUF_PITCH0_VALUE
, node
->buffer
.bytes_per_row
);
858 OUTREG( regs
, RADEON_OV0_H_INC
, p1_h_inc
| (p23_h_inc
<< 16) );
859 OUTREG( regs
, RADEON_OV0_STEP_BY
, factors
->p1_step_by
| (factors
->p23_step_by
<< 8) );
860 OUTREG( regs
, RADEON_OV0_V_INC
, v_inc
);
863 crtc
->crtc_idx
== 0 ? RADEON_OV0_Y_X_START
: RADEON_OV1_Y_X_START
,
864 (dest_left
) | (dest_top
<< 16) );
866 crtc
->crtc_idx
== 0 ? RADEON_OV0_Y_X_END
: RADEON_OV1_Y_X_END
,
867 (dest_right
- 1) | ((dest_bottom
- 1) << 16) );
869 OUTREG( regs
, RADEON_OV0_P1_BLANK_LINES_AT_TOP
,
870 RADEON_P1_BLNK_LN_AT_TOP_M1_MASK
| (p1_active_lines
<< 16) );
871 OUTREG( regs
, RADEON_OV0_P1_X_START_END
, p1_x_end
| (p1_x_start
<< 16) );
872 OUTREG( regs
, RADEON_OV0_P1_H_ACCUM_INIT
, p1_h_accum_init
);
873 OUTREG( regs
, RADEON_OV0_P1_V_ACCUM_INIT
, p1_v_accum_init
);
875 OUTREG( regs
, RADEON_OV0_P23_BLANK_LINES_AT_TOP
,
876 RADEON_P23_BLNK_LN_AT_TOP_M1_MASK
| (p23_active_lines
<< 16) );
877 OUTREG( regs
, RADEON_OV0_P2_X_START_END
,
878 p23_x_end
| (p23_x_start
<< 16) );
879 OUTREG( regs
, RADEON_OV0_P3_X_START_END
,
880 p23_x_end
| (p23_x_start
<< 16) );
881 OUTREG( regs
, RADEON_OV0_P23_H_ACCUM_INIT
, p23_h_accum_init
);
882 OUTREG( regs
, RADEON_OV0_P23_V_ACCUM_INIT
, p23_v_accum_init
);
884 OUTREG( regs
, RADEON_OV0_TEST
, node
->test_reg
);
886 scale_ctrl
= RADEON_SCALER_ENABLE
|
887 RADEON_SCALER_DOUBLE_BUFFER
|
888 (node
->ati_space
<< 8) |
889 /* RADEON_SCALER_ADAPTIVE_DEINT | */
890 RADEON_SCALER_BURST_PER_PLANE
|
891 (crtc
->crtc_idx
== 0 ? 0 : RADEON_SCALER_CRTC_SEL
);
893 switch (node
->ati_space
<< 8) {
894 case RADEON_SCALER_SOURCE_15BPP
: // RGB15
895 case RADEON_SCALER_SOURCE_16BPP
:
896 case RADEON_SCALER_SOURCE_32BPP
:
897 OUTREG( regs
, RADEON_OV0_SCALE_CNTL
, scale_ctrl
|
898 RADEON_SCALER_LIN_TRANS_BYPASS
);
900 case RADEON_SCALER_SOURCE_VYUY422
: // VYUY422
901 case RADEON_SCALER_SOURCE_YVYU422
: // YVYU422
902 OUTREG( regs
, RADEON_OV0_SCALE_CNTL
, scale_ctrl
);
905 SHOW_FLOW(4, "What overlay format is this??? %d", node
->ati_space
);
906 OUTREG( regs
, RADEON_OV0_SCALE_CNTL
, scale_ctrl
|
907 (( ai
->si
->asic
>= rt_r200
) ? R200_SCALER_TEMPORAL_DEINT
: 0));
911 si
->overlay_mgr
.auto_flip_reg
^= RADEON_OV0_SOFT_EOF_TOGGLE
;
913 OUTREG( regs
, RADEON_OV0_AUTO_FLIP_CNTRL
,
914 si
->overlay_mgr
.auto_flip_reg
);
916 OUTREG( regs
, RADEON_OV0_REG_LOAD_CNTL
, 0 );
919 ai
->si
->active_overlay
.on
= ai
->si
->pending_overlay
.on
;
920 ai
->si
->active_overlay
.ow
= ai
->si
->pending_overlay
.ow
;
921 ai
->si
->active_overlay
.ov
= ai
->si
->pending_overlay
.ov
;
922 ai
->si
->active_overlay
.ob
= ai
->si
->pending_overlay
.ob
;
923 ai
->si
->active_overlay
.h_display_start
= vc
->mode
.h_display_start
;
924 ai
->si
->active_overlay
.v_display_start
= vc
->mode
.v_display_start
;
930 // hide overlay, but not permanently
931 void Radeon_TempHideOverlay(
932 accelerator_info
*ai
)
936 OUTREG( ai
->regs
, RADEON_OV0_SCALE_CNTL
, 0 );
940 // hide overlay (can be called even if there is none visible)
941 void Radeon_HideOverlay(
942 accelerator_info
*ai
)
944 shared_info
*si
= ai
->si
;
946 Radeon_TempHideOverlay( ai
);
948 // remember that there is no overlay to be shown
949 si
->active_overlay
.on
= NULL
;
950 si
->active_overlay
.prev_on
= NULL
;
951 si
->pending_overlay
.on
= NULL
;
953 // invalidate active head so it will be setup again once
954 // a new overlay is shown
955 si
->active_overlay
.crtc_idx
= -1;
959 // show new overlay buffer with same parameters as last one
960 static void Radeon_ReplaceOverlayBuffer(
961 accelerator_info
*ai
)
964 shared_info
*si
= ai
->si
;
965 vuint8
*regs
= ai
->regs
;
967 int /*old_buf, */new_buf
;
969 offset
= si
->pending_overlay
.on
->mem_offset
+ si
->active_overlay
.rel_offset
;
971 /*old_buf = si->overlay_mgr.auto_flip_reg & RADEON_OV0_SOFT_BUF_NUM_MASK;
972 new_buf = old_buf == 0 ? 3 : 0;
973 si->overlay_mgr.auto_flip_reg &= ~RADEON_OV0_SOFT_BUF_NUM_MASK;
974 si->overlay_mgr.auto_flip_reg |= new_buf;*/
977 // lock overlay registers
978 /* OUTREG( regs, RADEON_OV0_REG_LOAD_CNTL, RADEON_REG_LD_CTL_LOCK );
980 // wait until register access is locked
981 while( (INREG( regs, RADEON_OV0_REG_LOAD_CNTL)
982 & RADEON_REG_LD_CTL_LOCK_READBACK) == 0 )
987 new_buf == 0 ? RADEON_OV0_VID_BUF_PITCH0_VALUE : RADEON_OV0_VID_BUF_PITCH1_VALUE,
988 si->pending_overlay.on->buffer.bytes_per_row );*/
990 new_buf
== 0 ? RADEON_OV0_VID_BUF0_BASE_ADRS
: RADEON_OV0_VID_BUF3_BASE_ADRS
,
991 offset
| (new_buf
== 0 ? 0 : RADEON_VIF_BUF0_PITCH_SEL
));
993 // make changes visible
994 si
->overlay_mgr
.auto_flip_reg
^= RADEON_OV0_SOFT_EOF_TOGGLE
;
996 OUTREG( regs
, RADEON_OV0_AUTO_FLIP_CNTRL
, si
->overlay_mgr
.auto_flip_reg
);
998 // unlock overlay registers
999 // OUTREG( regs, RADEON_OV0_REG_LOAD_CNTL, 0 );
1001 ai
->si
->active_overlay
.on
= ai
->si
->pending_overlay
.on
;
1003 shared_info
*si
= ai
->si
;
1006 if ( ai
->si
->acc_dma
)
1010 offset
= si
->pending_overlay
.on
->mem_offset
+ si
->active_overlay
.rel_offset
;
1012 WRITE_IB_REG( RADEON_OV0_VID_BUF0_BASE_ADRS
, offset
);
1014 si
->overlay_mgr
.auto_flip_reg
^= RADEON_OV0_SOFT_EOF_TOGGLE
;
1015 WRITE_IB_REG( RADEON_OV0_AUTO_FLIP_CNTRL
, si
->overlay_mgr
.auto_flip_reg
);
1019 Radeon_WaitForFifo( ai
, 2 );
1020 offset
= si
->pending_overlay
.on
->mem_offset
+ si
->active_overlay
.rel_offset
;
1022 OUTREG( ai
->regs
, RADEON_OV0_VID_BUF0_BASE_ADRS
, offset
);
1024 si
->overlay_mgr
.auto_flip_reg
^= RADEON_OV0_SOFT_EOF_TOGGLE
;
1025 OUTREG( ai
->regs
, RADEON_OV0_AUTO_FLIP_CNTRL
, si
->overlay_mgr
.auto_flip_reg
);
1027 ai
->si
->active_overlay
.on
= ai
->si
->pending_overlay
.on
;
1032 // get number of pixels of overlay shown on virtual port
1033 static int getIntersectArea(
1034 accelerator_info
*ai
, overlay_window
*ow
, crtc_info
*crtc
)
1036 virtual_card
*vc
= ai
->vc
;
1037 int left
, top
, right
, bottom
;
1039 left
= ow
->h_start
- (vc
->mode
.h_display_start
+ crtc
->rel_x
);
1040 top
= ow
->v_start
- (vc
->mode
.v_display_start
+ crtc
->rel_y
);
1041 right
= left
+ ow
->width
;
1042 bottom
= top
+ ow
->height
;
1048 if( right
> crtc
->mode
.timing
.h_display
)
1049 right
= crtc
->mode
.timing
.h_display
;
1050 if( bottom
> crtc
->mode
.timing
.v_display
)
1051 bottom
= crtc
->mode
.timing
.v_display
;
1053 if( right
< left
|| bottom
< top
)
1056 return (right
- left
) * (bottom
- top
);
1060 // update overlay, to be called whenever something in terms of
1061 // overlay have or can have been changed
1062 status_t
Radeon_UpdateOverlay(
1063 accelerator_info
*ai
)
1065 virtual_card
*vc
= ai
->vc
;
1066 shared_info
*si
= ai
->si
;
1069 float brightness
= 0.0f
;
1070 float contrast
= 1.0f
;
1071 float saturation
= 1.0f
;
1075 SHOW_FLOW0( 3, "" );
1077 // don't mess around with overlay of someone else
1078 if ( !vc
->uses_overlay
)
1081 // make sure there really is an overlay
1082 if ( si
->pending_overlay
.on
== NULL
)
1085 // verify that the overlay is still valid
1086 if ((uintptr_t)si
->pending_overlay
.ot
!= si
->overlay_mgr
.token
)
1089 if ( vc
->different_heads
> 1 ) {
1092 // determine on which port most of the overlay is shown
1093 area0
= getIntersectArea( ai
, &si
->pending_overlay
.ow
, &si
->crtc
[0] );
1094 area1
= getIntersectArea( ai
, &si
->pending_overlay
.ow
, &si
->crtc
[0] );
1096 SHOW_FLOW( 3, "area0=%d, area1=%d", area0
, area1
);
1098 if (area0
>= area1
)
1103 } else if ( vc
->independant_heads
> 1 ) {
1104 // both ports show the same, use "swap displays" to decide
1105 // where to show the overlay (to be improved as this flag isn't
1106 // really designed for that)
1107 if ( vc
->swap_displays
)
1114 // one crtc used only - pick the one that we use
1115 crtc_idx
= vc
->used_crtc
[0] ? 0 : 1;
1118 si
->pending_overlay
.crtc_idx
= crtc_idx
;
1120 // only update registers that have been changed to minimize work
1121 if( si
->active_overlay
.crtc_idx
!= si
->pending_overlay
.crtc_idx
) {
1122 Radeon_InitOverlay( ai
, crtc_idx
);
1125 if( si
->active_overlay
.ob
.space
!= si
->pending_overlay
.ob
.space
) {
1126 Radeon_SetTransform( ai
, brightness
, contrast
, saturation
, hue
, 0, 0, 0, ref
);
1129 if( memcmp( &si
->active_overlay
.ow
, &si
->pending_overlay
.ow
, sizeof( si
->active_overlay
.ow
)) != 0 ||
1130 memcmp( &si
->active_overlay
.ov
, &si
->pending_overlay
.ov
, sizeof( si
->active_overlay
.ov
)) != 0 ||
1131 si
->active_overlay
.h_display_start
!= vc
->mode
.h_display_start
||
1132 si
->active_overlay
.v_display_start
!= vc
->mode
.v_display_start
||
1133 si
->active_overlay
.ob
.width
!= si
->pending_overlay
.ob
.width
||
1134 si
->active_overlay
.ob
.height
!= si
->pending_overlay
.ob
.height
||
1135 si
->active_overlay
.ob
.bytes_per_row
!= si
->pending_overlay
.ob
.bytes_per_row
)
1136 Radeon_ShowOverlay( ai
, crtc_idx
);
1138 else if( si
->active_overlay
.on
!= si
->pending_overlay
.on
)
1139 Radeon_ReplaceOverlayBuffer( ai
);
1141 SHOW_FLOW0( 3, "success" );