1 /*
2 Copyright (c) 2002, Thomas Kurschel
3
4
5 Part of Radeon accelerant
6
7 Public functions to provide 2D hardware acceleration
8 */
9
10
11 #include "radeon_accelerant.h"
12 #include "GlobalData.h"
13 #include "generic.h"
14 #include "3d_regs.h"
15 #include "2d_regs.h"
16 #include "radeon_regs.h"
17 #include "mmio.h"
18 #include "CP.h"
19
20
21 // copy screen to screen
22 // et - ignored
23 // list - list of rectangles
24 // count - number of rectangles
SCREEN_TO_SCREEN_BLIT_DMA(engine_token * et,blit_params * list,uint32 count)25 void SCREEN_TO_SCREEN_BLIT_DMA(engine_token *et, blit_params *list, uint32 count)
26 {
27 virtual_card *vc = ai->vc;
28
29 SHOW_FLOW0( 4, "" );
30
31 (void)et;
32
33 while( count > 0 ) {
34 uint32 sub_count;
35
36 START_IB();
37
38 WRITE_IB_PACKET3_HEAD( RADEON_CP_PACKET3_CNTL_BITBLT_MULTI, count,
39 INDIRECT_BUFFER_SIZE, 3, 2 );
40
41 *buffer++ = RADEON_GMC_BRUSH_NONE
42 | (vc->datatype << RADEON_GMC_DST_DATATYPE_SHIFT)
43 | RADEON_GMC_SRC_DATATYPE_COLOR
44 | RADEON_ROP3_S
45 | RADEON_DP_SRC_SOURCE_MEMORY;
46
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);
51 }
52
53 SUBMIT_IB_VC();
54 }
55
56 ++ai->si->engine.count;
57 }
58
59 #define SRC_DSTCOLOR 0x00030000
60 #define DP_SRC_RECT 0x00000200
61
SCREEN_TO_SCREEN_BLIT_PIO(engine_token * et,blit_params * list,uint32 count)62 void SCREEN_TO_SCREEN_BLIT_PIO(engine_token *et, blit_params *list, uint32 count)
63 {
64 int xdir;
65 int ydir;
66 virtual_card *vc = ai->vc;
67
68 SHOW_FLOW0( 4, "" );
69
70 Radeon_WaitForFifo ( ai , 1 );
71
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
76 | RADEON_ROP3_S
77 | RADEON_DP_SRC_SOURCE_MEMORY
78 | RADEON_GMC_SRC_PITCH_OFFSET_CNTL));
79
80
81 for( ; count > 0; --count, ++list ) {
82
83 // make sure there is space in the FIFO for 4 register writes
84 Radeon_WaitForFifo ( ai , 4 );
85
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;
88
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 ;
91
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)));
94
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);
98
99 // this is the blt initiator.
100 OUTREG( ai->regs, RADEON_DST_HEIGHT_WIDTH, ((list->height + 1) << 16 ) | (list->width + 1));
101
102 }
103
104 ++ai->si->engine.count;
105 (void)et;
106
107 }
108
109
110 // fill rectangles on screen
111 // et - ignored
112 // colorIndex - fill colour
113 // list - list of rectangles
114 // count - number of rectangles
FILL_RECTANGLE_DMA(engine_token * et,uint32 colorIndex,fill_rect_params * list,uint32 count)115 void FILL_RECTANGLE_DMA(engine_token *et, uint32 colorIndex,
116 fill_rect_params *list, uint32 count)
117 {
118 virtual_card *vc = ai->vc;
119
120 SHOW_FLOW0( 4, "" );
121
122 (void)et;
123
124 while( count > 0 ) {
125 uint32 sub_count;
126
127 START_IB();
128
129 WRITE_IB_PACKET3_HEAD( RADEON_CP_PACKET3_CNTL_PAINT_MULTI, count,
130 INDIRECT_BUFFER_SIZE, 2, 3 );
131
132 *buffer++ = RADEON_GMC_BRUSH_SOLID_COLOR
133 | (vc->datatype << RADEON_GMC_DST_DATATYPE_SHIFT)
134 | RADEON_GMC_SRC_DATATYPE_COLOR
135 | RADEON_ROP3_P;
136 *buffer++ = colorIndex;
137
138 for( ; sub_count > 0; --sub_count, ++list ) {
139 *buffer++ = (list->left << 16) | list->top;
140 *buffer++ =
141 ((list->right - list->left + 1) << 16) |
142 (list->bottom - list->top + 1);
143 }
144
145 SUBMIT_IB_VC();
146 }
147
148 ++ai->si->engine.count;
149 }
150
151
152 // fill rectangles on screen
153 // et - ignored
154 // colorIndex - fill colour
155 // list - list of rectangles
156 // count - number of rectangles
157 #define BRUSH_SOLIDCOLOR 0x00000d00
158
FILL_RECTANGLE_PIO(engine_token * et,uint32 colorIndex,fill_rect_params * list,uint32 count)159 void FILL_RECTANGLE_PIO(engine_token *et, uint32 colorIndex, fill_rect_params *list, uint32 count)
160 {
161 virtual_card *vc = ai->vc;
162
163 SHOW_FLOW( 4, "colorIndex", colorIndex);
164
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
169 | RADEON_ROP3_P));
170 // Set brush colour
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));
173
174 for( ; count > 0; --count, ++list )
175 {
176
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));
180
181 }
182 ++ai->si->engine.count;
183 (void)et;
184 }
185
186
187
188 // invert rectangle on screen
189 // et - ignored
190 // list - list of rectangles
191 // count - number of rectangles
INVERT_RECTANGLE_DMA(engine_token * et,fill_rect_params * list,uint32 count)192 void INVERT_RECTANGLE_DMA(engine_token *et, fill_rect_params *list, uint32 count)
193 {
194 virtual_card *vc = ai->vc;
195
196 SHOW_FLOW0( 4, "" );
197
198 (void)et;
199
200 while( count > 0 ) {
201 uint32 sub_count;
202
203 START_IB();
204
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 );
208
209 *buffer++ = RADEON_GMC_BRUSH_NONE
210 | (vc->datatype << RADEON_GMC_DST_DATATYPE_SHIFT)
211 | RADEON_GMC_SRC_DATATYPE_COLOR
212 | RADEON_ROP3_Dn;
213
214 for( ; sub_count > 0; --sub_count, ++list ) {
215 *buffer++ = (list->left << 16) | list->top;
216 *buffer++ =
217 ((list->right - list->left + 1) << 16) |
218 (list->bottom - list->top + 1);
219 }
220
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
232 | RADEON_ROP3_S
233 | RADEON_DP_SRC_SOURCE_MEMORY;
234
235 SUBMIT_IB_VC();
236 }
237
238 ++ai->si->engine.count;
239 }
240
241
INVERT_RECTANGLE_PIO(engine_token * et,fill_rect_params * list,uint32 count)242 void INVERT_RECTANGLE_PIO(engine_token *et, fill_rect_params *list, uint32 count)
243 {
244 virtual_card *vc = ai->vc;
245
246 SHOW_FLOW0( 4, "" );
247
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
252 | RADEON_ROP3_Dn
253 | RADEON_DP_SRC_SOURCE_MEMORY));
254
255 OUTREG(ai->regs, RADEON_DP_CNTL, (RADEON_DST_X_LEFT_TO_RIGHT | RADEON_DST_Y_TOP_TO_BOTTOM));
256
257 for( ; count > 0; --count, ++list )
258 {
259
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));
263 }
264
265 ++ai->si->engine.count;
266 (void)et;
267
268 }
269
270 // fill horizontal spans on screen
271 // et - ignored
272 // colorIndex - fill colour
273 // list - list of spans
274 // count - number of spans
FILL_SPAN_DMA(engine_token * et,uint32 colorIndex,uint16 * list,uint32 count)275 void FILL_SPAN_DMA(engine_token *et, uint32 colorIndex, uint16 *list, uint32 count)
276 {
277 virtual_card *vc = ai->vc;
278
279 SHOW_FLOW0( 4, "" );
280
281 (void)et;
282
283 while( count > 0 ) {
284 uint32 sub_count;
285
286 START_IB();
287
288 WRITE_IB_PACKET3_HEAD( RADEON_CP_PACKET3_CNTL_PAINT_MULTI, count,
289 INDIRECT_BUFFER_SIZE , 2, 3 );
290
291 *buffer++ = RADEON_GMC_BRUSH_SOLID_COLOR
292 | (vc->datatype << RADEON_GMC_DST_DATATYPE_SHIFT)
293 | RADEON_GMC_SRC_DATATYPE_COLOR
294 | RADEON_ROP3_P;
295 *buffer++ = colorIndex;
296
297 for( ; sub_count > 0; --sub_count ) {
298 uint16 y, x, width;
299
300 y = *list++;
301 x = *list++;
302 width = *list++ - x + 1;
303
304 *buffer++ = (x << 16) | y;
305 *buffer++ = (width << 16) | 1;
306 }
307
308 SUBMIT_IB_VC();
309 }
310
311 ++ai->si->engine.count;
312 }
313
314
315 // fill horizontal spans on screen
316 // et - ignored
317 // colorIndex - fill colour
318 // list - list of spans
319 // count - number of spans
FILL_SPAN_PIO(engine_token * et,uint32 colorIndex,uint16 * list,uint32 count)320 void FILL_SPAN_PIO(engine_token *et, uint32 colorIndex, uint16 *list, uint32 count)
321 {
322
323 virtual_card *vc = ai->vc;
324 //int offset = 0;
325 uint16 y, x, width;
326
327 SHOW_FLOW0( 4, "" );
328
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
334 | RADEON_ROP3_P);
335
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);
339 }
340
341 Radeon_WaitForFifo( ai , 1);
342 OUTREG( ai->regs, RADEON_DP_BRUSH_FRGD_CLR, colorIndex);
343
344 for( ; count > 0; --count ) {
345
346 Radeon_WaitForFifo( ai , 2);
347
348 y = *list++;
349 x = *list++;
350 width = *list++ - x + 1;
351
352 OUTREG( ai->regs, RADEON_DST_LINE_START, (y << 16) | x);
353 OUTREG( ai->regs, RADEON_DST_LINE_END, ((y) << 16) | (x + width));
354
355 }
356
357 ++ai->si->engine.count;
358 (void)et;
359 }
360
361
SCREEN_TO_SCREEN_BLIT(engine_token * et,blit_params * list,uint32 count)362 void SCREEN_TO_SCREEN_BLIT(engine_token *et, blit_params *list, uint32 count)
363 {
364 if ( ai->si->acc_dma )
365 SCREEN_TO_SCREEN_BLIT_DMA(et,list,count);
366 else
367 SCREEN_TO_SCREEN_BLIT_PIO(et,list,count);
368 }
369
FILL_RECTANGLE(engine_token * et,uint32 color,fill_rect_params * list,uint32 count)370 void FILL_RECTANGLE(engine_token *et, uint32 color, fill_rect_params *list, uint32 count)
371 {
372 if ( ai->si->acc_dma )
373 FILL_RECTANGLE_DMA(et, color, list, count);
374 else
375 FILL_RECTANGLE_PIO(et, color, list, count);
376 }
377
INVERT_RECTANGLE(engine_token * et,fill_rect_params * list,uint32 count)378 void INVERT_RECTANGLE(engine_token *et, fill_rect_params *list, uint32 count)
379 {
380 if ( ai->si->acc_dma )
381 INVERT_RECTANGLE_DMA(et, list, count);
382 else
383 INVERT_RECTANGLE_PIO(et, list, count);
384 }
385
FILL_SPAN(engine_token * et,uint32 color,uint16 * list,uint32 count)386 void FILL_SPAN(engine_token *et, uint32 color, uint16 *list, uint32 count)
387 {
388 if ( ai->si->acc_dma )
389 FILL_SPAN_DMA(et, color, list, count);
390 else
391 FILL_SPAN_PIO(et, color, list, count);
392
393 }
394
395
396 // prepare 2D acceleration
Radeon_Init2D(accelerator_info * ai)397 void Radeon_Init2D( accelerator_info *ai )
398 {
399 SHOW_FLOW0( 3, "" );
400
401 // forget about 3D
402 if ( ai->si->acc_dma ) {
403 START_IB();
404 WRITE_IB_REG( RADEON_RB3D_CNTL, 0 );
405 SUBMIT_IB();
406 }
407 else {
408 OUTREG( ai->regs, RADEON_RB3D_CNTL, 0 );
409 }
410 }
411
412 // fill state buffer that sets 2D registers up for accelerated operations
Radeon_FillStateBuffer(accelerator_info * ai,uint32 datatype)413 void Radeon_FillStateBuffer( accelerator_info *ai, uint32 datatype )
414 {
415 virtual_card *vc = ai->vc;
416 uint32 pitch_offset;
417 uint32 *buffer = NULL, *buffer_start = NULL;
418
419 SHOW_FLOW0( 4, "" );
420
421 // set offset of frame buffer and pitch
422 pitch_offset =
423 ((ai->si->memory[mt_local].virtual_addr_start + vc->fb_offset) >> 10) |
424 ((vc->pitch >> 6) << 22);
425
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 );
430
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 );
434 // no sissors
435 WRITE_IB_REG( RADEON_DEFAULT_SC_BOTTOM_RIGHT,
436 (RADEON_DEFAULT_SC_RIGHT_MAX | RADEON_DEFAULT_SC_BOTTOM_MAX));
437
438 // general fluff
439 WRITE_IB_REG( RADEON_DP_GUI_MASTER_CNTL,
440 (datatype << RADEON_GMC_DST_DATATYPE_SHIFT)
441 | RADEON_GMC_CLR_CMP_CNTL_DIS
442
443 | RADEON_GMC_BRUSH_SOLID_COLOR
444 | RADEON_GMC_SRC_DATATYPE_COLOR
445
446 | RADEON_ROP3_P
447 | RADEON_DP_SRC_SOURCE_MEMORY
448 | RADEON_GMC_WR_MSK_DIS );
449
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);
457
458 // this is required
459 vc->state_buffer_size = buffer - buffer_start;
460
461 } else {
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 );
466 // no sissors
467 OUTREG( ai->regs, RADEON_DEFAULT_SC_BOTTOM_RIGHT, (RADEON_DEFAULT_SC_RIGHT_MAX
468 | RADEON_DEFAULT_SC_BOTTOM_MAX));
469 // general fluff
470 OUTREG( ai->regs, RADEON_DP_GUI_MASTER_CNTL,
471 (datatype << RADEON_GMC_DST_DATATYPE_SHIFT)
472 | RADEON_GMC_CLR_CMP_CNTL_DIS
473
474 | RADEON_GMC_BRUSH_SOLID_COLOR
475 | RADEON_GMC_SRC_DATATYPE_COLOR
476
477 | RADEON_ROP3_P
478 | RADEON_DP_SRC_SOURCE_MEMORY
479 | RADEON_GMC_WR_MSK_DIS );
480
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);
488
489 }
490
491 ai->si->active_vc = vc->id;
492 }
493
494
495 // allocate indirect buffer to contain state of virtual card
Radeon_AllocateVirtualCardStateBuffer(accelerator_info * ai)496 void Radeon_AllocateVirtualCardStateBuffer( accelerator_info *ai )
497 {
498 virtual_card *vc = ai->vc;
499
500 vc->state_buffer_idx = Radeon_AllocIndirectBuffer( ai, false );
501 // mark as being unused
502 vc->state_buffer_size = -1;
503 }
504
505
506 // free indirect buffer containing state of virtual card
Radeon_FreeVirtualCardStateBuffer(accelerator_info * ai)507 void Radeon_FreeVirtualCardStateBuffer( accelerator_info *ai )
508 {
509 virtual_card *vc = ai->vc;
510
511 // make sure it's not used anymore
512 Radeon_InvalidateStateBuffer( ai, vc->state_buffer_idx );
513
514 // get rid of it
515 Radeon_FreeIndirectBuffer( ai, vc->state_buffer_idx, false );
516 }
517