2 Copyright (c) 2002, Thomas Kurschel
5 Part of Radeon accelerant
7 Public functions to provide 2D hardware acceleration
11 #include "radeon_accelerant.h"
12 #include "GlobalData.h"
16 #include "radeon_regs.h"
21 // copy screen to screen
23 // list - list of rectangles
24 // count - number of rectangles
25 void SCREEN_TO_SCREEN_BLIT_DMA(engine_token
*et
, blit_params
*list
, uint32 count
)
27 virtual_card
*vc
= ai
->vc
;
38 WRITE_IB_PACKET3_HEAD( RADEON_CP_PACKET3_CNTL_BITBLT_MULTI
, count
,
39 INDIRECT_BUFFER_SIZE
, 3, 2 );
41 *buffer
++ = RADEON_GMC_BRUSH_NONE
42 | (vc
->datatype
<< RADEON_GMC_DST_DATATYPE_SHIFT
)
43 | RADEON_GMC_SRC_DATATYPE_COLOR
45 | RADEON_DP_SRC_SOURCE_MEMORY
;
47 for( ; sub_count
> 0; --sub_count
, ++list
) {
48 *buffer
++ = (list
->src_left
<< 16) | list
->src_top
;
49 *buffer
++ = (list
->dest_left
<< 16) | list
->dest_top
;
50 *buffer
++ = ((list
->width
+ 1) << 16) | (list
->height
+ 1);
56 ++ai
->si
->engine
.count
;
59 #define SRC_DSTCOLOR 0x00030000
60 #define DP_SRC_RECT 0x00000200
62 void SCREEN_TO_SCREEN_BLIT_PIO(engine_token
*et
, blit_params
*list
, uint32 count
)
66 virtual_card
*vc
= ai
->vc
;
70 Radeon_WaitForFifo ( ai
, 1 );
72 // Setup for Screen to screen blit
73 OUTREG(ai
->regs
, RADEON_DP_GUI_MASTER_CNTL
, (vc
->datatype
<< RADEON_GMC_DST_DATATYPE_SHIFT
74 | RADEON_GMC_BRUSH_NONE
75 | RADEON_GMC_SRC_DATATYPE_COLOR
77 | RADEON_DP_SRC_SOURCE_MEMORY
78 | RADEON_GMC_SRC_PITCH_OFFSET_CNTL
));
81 for( ; count
> 0; --count
, ++list
) {
83 // make sure there is space in the FIFO for 4 register writes
84 Radeon_WaitForFifo ( ai
, 4 );
86 xdir
= ((list
->src_left
< list
->dest_left
) && (list
->src_top
== list
->dest_top
)) ? -1 : 1;
87 ydir
= (list
->src_top
< list
->dest_top
) ? -1 : 1;
89 if (xdir
< 0) list
->src_left
+= list
->width
, list
->dest_left
+= list
->width
;
90 if (ydir
< 0) list
->src_top
+= list
->height
, list
->dest_top
+= list
->height
;
92 OUTREG(ai
->regs
, RADEON_DP_CNTL
, ((xdir
>= 0 ? RADEON_DST_X_LEFT_TO_RIGHT
: 0)
93 | (ydir
>= 0 ? RADEON_DST_Y_TOP_TO_BOTTOM
: 0)));
95 // Tell the engine where the source data resides.
96 OUTREG( ai
->regs
, RADEON_SRC_Y_X
, (list
->src_top
<< 16 ) | list
->src_left
);
97 OUTREG( ai
->regs
, RADEON_DST_Y_X
, (list
->dest_top
<< 16 ) | list
->dest_left
);
99 // this is the blt initiator.
100 OUTREG( ai
->regs
, RADEON_DST_HEIGHT_WIDTH
, ((list
->height
+ 1) << 16 ) | (list
->width
+ 1));
104 ++ai
->si
->engine
.count
;
110 // fill rectangles on screen
112 // colorIndex - fill colour
113 // list - list of rectangles
114 // count - number of rectangles
115 void FILL_RECTANGLE_DMA(engine_token
*et
, uint32 colorIndex
,
116 fill_rect_params
*list
, uint32 count
)
118 virtual_card
*vc
= ai
->vc
;
129 WRITE_IB_PACKET3_HEAD( RADEON_CP_PACKET3_CNTL_PAINT_MULTI
, count
,
130 INDIRECT_BUFFER_SIZE
, 2, 3 );
132 *buffer
++ = RADEON_GMC_BRUSH_SOLID_COLOR
133 | (vc
->datatype
<< RADEON_GMC_DST_DATATYPE_SHIFT
)
134 | RADEON_GMC_SRC_DATATYPE_COLOR
136 *buffer
++ = colorIndex
;
138 for( ; sub_count
> 0; --sub_count
, ++list
) {
139 *buffer
++ = (list
->left
<< 16) | list
->top
;
141 ((list
->right
- list
->left
+ 1) << 16) |
142 (list
->bottom
- list
->top
+ 1);
148 ++ai
->si
->engine
.count
;
152 // fill rectangles on screen
154 // colorIndex - fill colour
155 // list - list of rectangles
156 // count - number of rectangles
157 #define BRUSH_SOLIDCOLOR 0x00000d00
159 void FILL_RECTANGLE_PIO(engine_token
*et
, uint32 colorIndex
, fill_rect_params
*list
, uint32 count
)
161 virtual_card
*vc
= ai
->vc
;
163 SHOW_FLOW( 4, "colorIndex", colorIndex
);
165 Radeon_WaitForFifo(ai
, 3);
166 OUTREG(ai
->regs
, RADEON_DP_GUI_MASTER_CNTL
, ((vc
->datatype
<< RADEON_GMC_DST_DATATYPE_SHIFT
)
167 | RADEON_GMC_BRUSH_SOLID_COLOR
168 | RADEON_GMC_SRC_DATATYPE_COLOR
171 OUTREG(ai
->regs
, RADEON_DP_BRUSH_FRGD_CLR
, colorIndex
);
172 OUTREG(ai
->regs
, RADEON_DP_CNTL
, (RADEON_DST_X_LEFT_TO_RIGHT
| RADEON_DST_Y_TOP_TO_BOTTOM
));
174 for( ; count
> 0; --count
, ++list
)
177 Radeon_WaitForFifo(ai
, 2);
178 OUTREG(ai
->regs
, RADEON_DST_Y_X
, (list
->top
<< 16) | list
->left
);
179 OUTREG(ai
->regs
, RADEON_DST_WIDTH_HEIGHT
, ((list
->right
- list
->left
+ 1) << 16) | (list
->bottom
- list
->top
+ 1));
182 ++ai
->si
->engine
.count
;
188 // invert rectangle on screen
190 // list - list of rectangles
191 // count - number of rectangles
192 void INVERT_RECTANGLE_DMA(engine_token
*et
, fill_rect_params
*list
, uint32 count
)
194 virtual_card
*vc
= ai
->vc
;
205 // take core to leave space for ROP reset!
206 WRITE_IB_PACKET3_HEAD( RADEON_CP_PACKET3_CNTL_PAINT_MULTI
, count
,
207 INDIRECT_BUFFER_SIZE
- 2, 2, 2 );
209 *buffer
++ = RADEON_GMC_BRUSH_NONE
210 | (vc
->datatype
<< RADEON_GMC_DST_DATATYPE_SHIFT
)
211 | RADEON_GMC_SRC_DATATYPE_COLOR
214 for( ; sub_count
> 0; --sub_count
, ++list
) {
215 *buffer
++ = (list
->left
<< 16) | list
->top
;
217 ((list
->right
- list
->left
+ 1) << 16) |
218 (list
->bottom
- list
->top
+ 1);
221 // we have to reset ROP, else we get garbage during next
222 // CPU access; it looks like some cache coherency/forwarding
223 // problem as it goes away later on; things like flushing the
224 // destination cache or waiting for 2D engine or HDP to become
225 // idle and clean didn't change a thing
226 // (I dont't really understand what exactly happens,
227 // but this code fixes it)
228 *buffer
++ = CP_PACKET0( RADEON_DP_GUI_MASTER_CNTL
, 1 );
229 *buffer
++ = RADEON_GMC_BRUSH_NONE
230 | (vc
->datatype
<< RADEON_GMC_DST_DATATYPE_SHIFT
)
231 | RADEON_GMC_SRC_DATATYPE_COLOR
233 | RADEON_DP_SRC_SOURCE_MEMORY
;
238 ++ai
->si
->engine
.count
;
242 void INVERT_RECTANGLE_PIO(engine_token
*et
, fill_rect_params
*list
, uint32 count
)
244 virtual_card
*vc
= ai
->vc
;
248 Radeon_WaitForFifo(ai
, 3);
249 OUTREG(ai
->regs
, RADEON_DP_GUI_MASTER_CNTL
, ((vc
->datatype
<< RADEON_GMC_DST_DATATYPE_SHIFT
)
250 | RADEON_GMC_BRUSH_NONE
251 | RADEON_GMC_SRC_DATATYPE_COLOR
253 | RADEON_DP_SRC_SOURCE_MEMORY
));
255 OUTREG(ai
->regs
, RADEON_DP_CNTL
, (RADEON_DST_X_LEFT_TO_RIGHT
| RADEON_DST_Y_TOP_TO_BOTTOM
));
257 for( ; count
> 0; --count
, ++list
)
260 Radeon_WaitForFifo(ai
, 2);
261 OUTREG(ai
->regs
, RADEON_DST_Y_X
, (list
->top
<< 16) | list
->left
);
262 OUTREG(ai
->regs
, RADEON_DST_WIDTH_HEIGHT
, ((list
->right
- list
->left
+ 1) << 16) | (list
->bottom
- list
->top
+ 1));
265 ++ai
->si
->engine
.count
;
270 // fill horizontal spans on screen
272 // colorIndex - fill colour
273 // list - list of spans
274 // count - number of spans
275 void FILL_SPAN_DMA(engine_token
*et
, uint32 colorIndex
, uint16
*list
, uint32 count
)
277 virtual_card
*vc
= ai
->vc
;
288 WRITE_IB_PACKET3_HEAD( RADEON_CP_PACKET3_CNTL_PAINT_MULTI
, count
,
289 INDIRECT_BUFFER_SIZE
, 2, 3 );
291 *buffer
++ = RADEON_GMC_BRUSH_SOLID_COLOR
292 | (vc
->datatype
<< RADEON_GMC_DST_DATATYPE_SHIFT
)
293 | RADEON_GMC_SRC_DATATYPE_COLOR
295 *buffer
++ = colorIndex
;
297 for( ; sub_count
> 0; --sub_count
) {
302 width
= *list
++ - x
+ 1;
304 *buffer
++ = (x
<< 16) | y
;
305 *buffer
++ = (width
<< 16) | 1;
311 ++ai
->si
->engine
.count
;
315 // fill horizontal spans on screen
317 // colorIndex - fill colour
318 // list - list of spans
319 // count - number of spans
320 void FILL_SPAN_PIO(engine_token
*et
, uint32 colorIndex
, uint16
*list
, uint32 count
)
323 virtual_card
*vc
= ai
->vc
;
329 Radeon_WaitForFifo( ai
, 1);
330 OUTREG( ai
->regs
, RADEON_DP_GUI_MASTER_CNTL
, 0
331 | RADEON_GMC_BRUSH_SOLID_COLOR
332 | (vc
->datatype
<< RADEON_GMC_DST_DATATYPE_SHIFT
)
333 | RADEON_GMC_SRC_DATATYPE_COLOR
336 if ( ai
->si
->asic
>= rt_rv200
) {
337 Radeon_WaitForFifo( ai
, 1);
338 OUTREG( ai
->regs
, RADEON_DST_LINE_PATCOUNT
, 0x55 << RADEON_BRES_CNTL_SHIFT
);
341 Radeon_WaitForFifo( ai
, 1);
342 OUTREG( ai
->regs
, RADEON_DP_BRUSH_FRGD_CLR
, colorIndex
);
344 for( ; count
> 0; --count
) {
346 Radeon_WaitForFifo( ai
, 2);
350 width
= *list
++ - x
+ 1;
352 OUTREG( ai
->regs
, RADEON_DST_LINE_START
, (y
<< 16) | x
);
353 OUTREG( ai
->regs
, RADEON_DST_LINE_END
, ((y
) << 16) | (x
+ width
));
357 ++ai
->si
->engine
.count
;
362 void SCREEN_TO_SCREEN_BLIT(engine_token
*et
, blit_params
*list
, uint32 count
)
364 if ( ai
->si
->acc_dma
)
365 SCREEN_TO_SCREEN_BLIT_DMA(et
,list
,count
);
367 SCREEN_TO_SCREEN_BLIT_PIO(et
,list
,count
);
370 void FILL_RECTANGLE(engine_token
*et
, uint32 color
, fill_rect_params
*list
, uint32 count
)
372 if ( ai
->si
->acc_dma
)
373 FILL_RECTANGLE_DMA(et
, color
, list
, count
);
375 FILL_RECTANGLE_PIO(et
, color
, list
, count
);
378 void INVERT_RECTANGLE(engine_token
*et
, fill_rect_params
*list
, uint32 count
)
380 if ( ai
->si
->acc_dma
)
381 INVERT_RECTANGLE_DMA(et
, list
, count
);
383 INVERT_RECTANGLE_PIO(et
, list
, count
);
386 void FILL_SPAN(engine_token
*et
, uint32 color
, uint16
*list
, uint32 count
)
388 if ( ai
->si
->acc_dma
)
389 FILL_SPAN_DMA(et
, color
, list
, count
);
391 FILL_SPAN_PIO(et
, color
, list
, count
);
396 // prepare 2D acceleration
397 void Radeon_Init2D( accelerator_info
*ai
)
402 if ( ai
->si
->acc_dma
) {
404 WRITE_IB_REG( RADEON_RB3D_CNTL
, 0 );
408 OUTREG( ai
->regs
, RADEON_RB3D_CNTL
, 0 );
412 // fill state buffer that sets 2D registers up for accelerated operations
413 void Radeon_FillStateBuffer( accelerator_info
*ai
, uint32 datatype
)
415 virtual_card
*vc
= ai
->vc
;
417 uint32
*buffer
= NULL
, *buffer_start
= NULL
;
421 // set offset of frame buffer and pitch
423 ((ai
->si
->memory
[mt_local
].virtual_addr_start
+ vc
->fb_offset
) >> 10) |
424 ((vc
->pitch
>> 6) << 22);
426 if ( ai
->si
->acc_dma
) {
427 // make sure buffer is not used
428 Radeon_InvalidateStateBuffer( ai
, vc
->state_buffer_idx
);
429 buffer
= buffer_start
= Radeon_GetIndirectBufferPtr( ai
, vc
->state_buffer_idx
);
431 WRITE_IB_REG( RADEON_DEFAULT_OFFSET
, pitch_offset
);
432 WRITE_IB_REG( RADEON_DST_PITCH_OFFSET
, pitch_offset
);
433 WRITE_IB_REG( RADEON_SRC_PITCH_OFFSET
, pitch_offset
);
435 WRITE_IB_REG( RADEON_DEFAULT_SC_BOTTOM_RIGHT
,
436 (RADEON_DEFAULT_SC_RIGHT_MAX
| RADEON_DEFAULT_SC_BOTTOM_MAX
));
439 WRITE_IB_REG( RADEON_DP_GUI_MASTER_CNTL
,
440 (datatype
<< RADEON_GMC_DST_DATATYPE_SHIFT
)
441 | RADEON_GMC_CLR_CMP_CNTL_DIS
443 | RADEON_GMC_BRUSH_SOLID_COLOR
444 | RADEON_GMC_SRC_DATATYPE_COLOR
447 | RADEON_DP_SRC_SOURCE_MEMORY
448 | RADEON_GMC_WR_MSK_DIS
);
450 // most of this init is probably not necessary
451 // as we neither draw lines nor use brushes
452 WRITE_IB_REG( RADEON_DP_BRUSH_FRGD_CLR
, 0xffffffff);
453 WRITE_IB_REG( RADEON_DP_BRUSH_BKGD_CLR
, 0x00000000);
454 WRITE_IB_REG( RADEON_DP_SRC_FRGD_CLR
, 0xffffffff);
455 WRITE_IB_REG( RADEON_DP_SRC_BKGD_CLR
, 0x00000000);
456 WRITE_IB_REG( RADEON_DP_WRITE_MASK
, 0xffffffff);
459 vc
->state_buffer_size
= buffer
- buffer_start
;
462 Radeon_WaitForFifo( ai
, 10 );
463 OUTREG( ai
->regs
, RADEON_DEFAULT_OFFSET
, pitch_offset
);
464 OUTREG( ai
->regs
, RADEON_DST_PITCH_OFFSET
, pitch_offset
);
465 OUTREG( ai
->regs
, RADEON_SRC_PITCH_OFFSET
, pitch_offset
);
467 OUTREG( ai
->regs
, RADEON_DEFAULT_SC_BOTTOM_RIGHT
, (RADEON_DEFAULT_SC_RIGHT_MAX
468 | RADEON_DEFAULT_SC_BOTTOM_MAX
));
470 OUTREG( ai
->regs
, RADEON_DP_GUI_MASTER_CNTL
,
471 (datatype
<< RADEON_GMC_DST_DATATYPE_SHIFT
)
472 | RADEON_GMC_CLR_CMP_CNTL_DIS
474 | RADEON_GMC_BRUSH_SOLID_COLOR
475 | RADEON_GMC_SRC_DATATYPE_COLOR
478 | RADEON_DP_SRC_SOURCE_MEMORY
479 | RADEON_GMC_WR_MSK_DIS
);
481 // most of this init is probably not necessary
482 // as we neither draw lines nor use brushes
483 OUTREG( ai
->regs
, RADEON_DP_BRUSH_FRGD_CLR
, 0xffffffff);
484 OUTREG( ai
->regs
, RADEON_DP_BRUSH_BKGD_CLR
, 0x00000000);
485 OUTREG( ai
->regs
, RADEON_DP_SRC_FRGD_CLR
, 0xffffffff);
486 OUTREG( ai
->regs
, RADEON_DP_SRC_BKGD_CLR
, 0x00000000);
487 OUTREG( ai
->regs
, RADEON_DP_WRITE_MASK
, 0xffffffff);
491 ai
->si
->active_vc
= vc
->id
;
495 // allocate indirect buffer to contain state of virtual card
496 void Radeon_AllocateVirtualCardStateBuffer( accelerator_info
*ai
)
498 virtual_card
*vc
= ai
->vc
;
500 vc
->state_buffer_idx
= Radeon_AllocIndirectBuffer( ai
, false );
501 // mark as being unused
502 vc
->state_buffer_size
= -1;
506 // free indirect buffer containing state of virtual card
507 void Radeon_FreeVirtualCardStateBuffer( accelerator_info
*ai
)
509 virtual_card
*vc
= ai
->vc
;
511 // make sure it's not used anymore
512 Radeon_InvalidateStateBuffer( ai
, vc
->state_buffer_idx
);
515 Radeon_FreeIndirectBuffer( ai
, vc
->state_buffer_idx
, false );