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 "cp_regs.h" 15 #include "3d_regs.h" 16 #include "2d_regs.h" 17 #include "mmio.h" 18 19 20 // currently, an CP instruction stream is written to 21 // a buffer on stack and then copied into the official 22 // CP buffer 23 24 #define PACKET_BUFFER_LEN 0x100 25 26 // copy screen to screen 27 // et - ignored 28 // list - list of rectangles 29 // count - number of rectangles 30 void SCREEN_TO_SCREEN_BLIT(engine_token *et, blit_params *list, uint32 count) 31 { 32 virtual_card *vc = ai->vc; 33 int offset = 0; 34 uint32 buffer[PACKET_BUFFER_LEN]; 35 36 SHOW_FLOW0( 4, "" ); 37 38 for( ; count > 0; --count, ++list ) { 39 if( offset == 0 ) { 40 buffer[offset++] = RADEON_CP_PACKET3_CNTL_BITBLT_MULTI; 41 buffer[offset++] = 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 48 buffer[offset++] = (list->src_left << 16) | list->src_top; 49 buffer[offset++] = (list->dest_left << 16) | list->dest_top; 50 buffer[offset++] = ((list->width + 1) << 16) | (list->height + 1); 51 52 if( offset + 3 > PACKET_BUFFER_LEN ) { 53 buffer[0] |= (offset - 2) << 16; 54 55 Radeon_SendCP( ai, buffer, offset ); 56 57 offset = 0; 58 } 59 } 60 61 if( offset > 0 ) { 62 buffer[0] |= (offset - 2) << 16; 63 64 Radeon_SendCP( ai, buffer, offset ); 65 } 66 67 ++ai->si->engine.count; 68 } 69 70 71 // fill rectangles on screen 72 // et - ignored 73 // colorIndex - fill colour 74 // list - list of rectangles 75 // count - number of rectangles 76 void FILL_RECTANGLE(engine_token *et, uint32 colorIndex, 77 fill_rect_params *list, uint32 count) 78 { 79 virtual_card *vc = ai->vc; 80 int offset = 0; 81 uint32 buffer[PACKET_BUFFER_LEN]; 82 83 SHOW_FLOW0( 4, "" ); 84 85 for( ; count > 0; --count, ++list ) { 86 if( offset == 0 ) { 87 buffer[offset++] = RADEON_CP_PACKET3_CNTL_PAINT_MULTI; 88 buffer[offset++] = RADEON_GMC_BRUSH_SOLID_COLOR 89 | (vc->datatype << RADEON_GMC_DST_DATATYPE_SHIFT) 90 | RADEON_GMC_SRC_DATATYPE_COLOR 91 | RADEON_ROP3_P; 92 buffer[offset++] = colorIndex; 93 } 94 95 buffer[offset++] = (list->left << 16) | list->top; 96 buffer[offset++] = 97 ((list->right - list->left + 1) << 16) | 98 (list->bottom - list->top + 1); 99 100 if( offset + 2 > PACKET_BUFFER_LEN ) { 101 buffer[0] |= (offset - 2) << 16; 102 103 Radeon_SendCP( ai, buffer, offset ); 104 105 offset = 0; 106 } 107 } 108 109 if( offset > 0 ) { 110 buffer[0] |= (offset - 2) << 16; 111 112 Radeon_SendCP( ai, buffer, offset ); 113 } 114 115 ++ai->si->engine.count; 116 } 117 118 119 // invert rectangle on screen 120 // et - ignored 121 // list - list of rectangles 122 // count - number of rectangles 123 void INVERT_RECTANGLE(engine_token *et, fill_rect_params *list, uint32 count) 124 { 125 virtual_card *vc = ai->vc; 126 int offset = 0; 127 uint32 buffer[PACKET_BUFFER_LEN]; 128 129 SHOW_FLOW0( 4, "" ); 130 131 for( ; count > 0; --count, ++list ) { 132 if( offset == 0 ) { 133 buffer[offset++] = RADEON_CP_PACKET3_CNTL_PAINT_MULTI; 134 buffer[offset++] = RADEON_GMC_BRUSH_NONE 135 | (vc->datatype << RADEON_GMC_DST_DATATYPE_SHIFT) 136 | RADEON_GMC_SRC_DATATYPE_COLOR 137 | RADEON_ROP3_Dn; 138 } 139 140 buffer[offset++] = (list->left << 16) | list->top; 141 buffer[offset++] = 142 ((list->right - list->left + 1) << 16) | 143 (list->bottom - list->top + 1); 144 145 // always leave 2 extra bytes for fix (see below) 146 if( offset + 2 > PACKET_BUFFER_LEN - 2 ) { 147 buffer[0] |= (offset - 2) << 16; 148 149 Radeon_SendCP( ai, buffer, offset ); 150 151 offset = 0; 152 } 153 } 154 155 buffer[0] |= (offset - 2) << 16; 156 157 // we have to reset ROP, else we get garbage during next 158 // CPU access; it looks like some cache coherency/forwarding 159 // problem as it goes away later on; things like flushing the 160 // destination cache or waiting for 2D engine or HDP to become 161 // idle and clean didn't change a thing 162 // (I dont't really understand what exactly happens, 163 // but this code fixes it) 164 buffer[offset++] = CP_PACKET0( RADEON_DP_GUI_MASTER_CNTL, 0 ); 165 buffer[offset++] = RADEON_GMC_BRUSH_NONE 166 | (vc->datatype << RADEON_GMC_DST_DATATYPE_SHIFT) 167 | RADEON_GMC_SRC_DATATYPE_COLOR 168 | RADEON_ROP3_S 169 | RADEON_DP_SRC_SOURCE_MEMORY; 170 171 if( offset > 0 ) 172 Radeon_SendCP( ai, buffer, offset ); 173 174 ++ai->si->engine.count; 175 } 176 177 // fill horizontal spans on screen 178 // et - ignored 179 // colorIndex - fill colour 180 // list - list of spans 181 // count - number of spans 182 void FILL_SPAN(engine_token *et, uint32 colorIndex, uint16 *list, uint32 count) 183 { 184 virtual_card *vc = ai->vc; 185 int offset = 0; 186 uint32 buffer[PACKET_BUFFER_LEN]; 187 188 SHOW_FLOW0( 4, "" ); 189 190 for( ; count > 0; --count ) { 191 uint16 y, x, width; 192 193 if( offset == 0 ) { 194 buffer[offset++] = RADEON_CP_PACKET3_CNTL_PAINT_MULTI; 195 buffer[offset++] = RADEON_GMC_BRUSH_SOLID_COLOR 196 | (vc->datatype << RADEON_GMC_DST_DATATYPE_SHIFT) 197 | RADEON_GMC_SRC_DATATYPE_COLOR 198 | RADEON_ROP3_P; 199 buffer[offset++] = colorIndex; 200 } 201 202 y = *list++; 203 x = *list++; 204 width = *list++ - x + 1; 205 206 buffer[offset++] = (x << 16) | y; 207 buffer[offset++] = (width << 16) | 1; 208 209 if( offset + 2 > PACKET_BUFFER_LEN ) { 210 buffer[0] |= (offset - 2) << 16; 211 212 Radeon_SendCP( ai, buffer, offset ); 213 214 offset = 0; 215 } 216 } 217 218 if( offset > 0 ) { 219 buffer[0] |= (offset - 2) << 16; 220 221 Radeon_SendCP( ai, buffer, offset ); 222 } 223 224 ++ai->si->engine.count; 225 } 226 227 228 // prepare 2D acceleration 229 void Radeon_Init2D( accelerator_info *ai, uint32 datatype ) 230 { 231 SHOW_FLOW0( 3, "" ); 232 233 // forget about 3D 234 OUTREG( ai->regs, RADEON_RB3D_CNTL, 0 ); 235 236 //Radeon_ResetEngine( ai ); 237 238 // no siccors 239 Radeon_WaitForFifo( ai, 1 ); 240 OUTREG( ai->regs, RADEON_DEFAULT_SC_BOTTOM_RIGHT, (RADEON_DEFAULT_SC_RIGHT_MAX 241 | RADEON_DEFAULT_SC_BOTTOM_MAX)); 242 243 // setup general flags - perhaps this is not needed as all 244 // 2D commands contain this register 245 Radeon_WaitForFifo( ai, 1 ); 246 OUTREG( ai->regs, RADEON_DP_GUI_MASTER_CNTL, 247 (datatype << RADEON_GMC_DST_DATATYPE_SHIFT) 248 | RADEON_GMC_CLR_CMP_CNTL_DIS 249 250 | RADEON_GMC_BRUSH_SOLID_COLOR 251 | RADEON_GMC_SRC_DATATYPE_COLOR 252 253 | RADEON_ROP3_P 254 | RADEON_DP_SRC_SOURCE_MEMORY 255 | RADEON_GMC_WR_MSK_DIS ); 256 257 258 // most of this init is probably not nessacary 259 // as we neither draw lines nor use brushes 260 Radeon_WaitForFifo( ai, 7 ); 261 OUTREG( ai->regs, RADEON_DST_LINE_START, 0); 262 OUTREG( ai->regs, RADEON_DST_LINE_END, 0); 263 OUTREG( ai->regs, RADEON_DP_BRUSH_FRGD_CLR, 0xffffffff); 264 OUTREG( ai->regs, RADEON_DP_BRUSH_BKGD_CLR, 0x00000000); 265 OUTREG( ai->regs, RADEON_DP_SRC_FRGD_CLR, 0xffffffff); 266 OUTREG( ai->regs, RADEON_DP_SRC_BKGD_CLR, 0x00000000); 267 OUTREG( ai->regs, RADEON_DP_WRITE_MASK, 0xffffffff); 268 269 Radeon_WaitForIdle( ai ); 270 } 271 272 // switch to virtual card, i.e. setup all specific engine registers 273 void Radeon_ActivateVirtualCard( accelerator_info *ai ) 274 { 275 virtual_card *vc = ai->vc; 276 uint32 buffer[3*2]; 277 uint32 pitch_offset; 278 int idx = 0; 279 280 SHOW_FLOW0( 4, "" ); 281 282 pitch_offset = (vc->fb_offset >> 10) | ((vc->pitch >> 6) << 22); 283 buffer[idx++] = CP_PACKET0( RADEON_DEFAULT_OFFSET, 0 ); 284 buffer[idx++] = pitch_offset; 285 buffer[idx++] = CP_PACKET0( RADEON_DST_PITCH_OFFSET, 0 ); 286 buffer[idx++] = pitch_offset; 287 buffer[idx++] = CP_PACKET0( RADEON_SRC_PITCH_OFFSET, 0 ); 288 buffer[idx++] = pitch_offset; 289 290 Radeon_SendCP( ai, buffer, idx ); 291 292 ai->si->active_vc = vc->id; 293 } 294