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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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