1 /* 2 * Copyright (c) 2006 Advanced Micro Devices, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 * DEALINGS IN THE SOFTWARE. 21 * 22 * Neither the name of the Advanced Micro Devices, Inc. nor the names of its 23 * contributors may be used to endorse or promote products derived from this 24 * software without specific prior written permission. 25 */ 26 27 /* 28 * Cimarron graphics processor routines. These routines program the graphics 29 * hardware using the graphics command buffer. 30 */ 31 32 /*---------------------*/ 33 /* CIMARRON GP GLOBALS */ 34 /*---------------------*/ 35 36 CIMARRON_STATIC unsigned long gp3_bpp = 0; 37 CIMARRON_STATIC unsigned long gp3_ch3_bpp = 0; 38 CIMARRON_STATIC unsigned long gp3_pat_origin = 0; 39 CIMARRON_STATIC unsigned long gp3_buffer_lead = 0; 40 CIMARRON_STATIC unsigned long gp3_cmd_header; 41 CIMARRON_STATIC unsigned long gp3_cmd_top; 42 CIMARRON_STATIC unsigned long gp3_cmd_bottom; 43 CIMARRON_STATIC unsigned long gp3_cmd_current; 44 CIMARRON_STATIC unsigned long gp3_cmd_next; 45 CIMARRON_STATIC unsigned long gp3_blt_mode; 46 CIMARRON_STATIC unsigned long gp3_vec_mode; 47 CIMARRON_STATIC unsigned long gp3_raster_mode; 48 CIMARRON_STATIC unsigned long gp3_pix_shift; 49 CIMARRON_STATIC unsigned long gp3_ch3_pat; 50 CIMARRON_STATIC unsigned long gp3_blt; 51 CIMARRON_STATIC unsigned long gp3_blt_flags; 52 CIMARRON_STATIC unsigned long gp3_src_stride; 53 CIMARRON_STATIC unsigned long gp3_dst_stride; 54 CIMARRON_STATIC unsigned long gp3_src_format; 55 CIMARRON_STATIC unsigned long gp3_src_pix_shift; 56 CIMARRON_STATIC unsigned long gp3_pat_format; 57 CIMARRON_STATIC unsigned long gp3_pat_pix_shift; 58 CIMARRON_STATIC unsigned long gp3_fb_base; 59 CIMARRON_STATIC unsigned long gp3_vector_pattern_color; 60 CIMARRON_STATIC unsigned long gp3_scratch_base; 61 CIMARRON_STATIC unsigned long gp3_base_register; 62 CIMARRON_STATIC unsigned long gp3_vec_pat; 63 64 /*--------------------------------------------------------------------------- 65 * gp_set_limit_on_buffer_lead 66 * 67 * This routine is used to specify the maximum number of bytes in the command 68 * buffer by which software can lead the graphics processor. When declaring 69 * a BLT with the CIMGP_BLTFLAGS_LIMITBUFFER flag set, Cimarron will wait 70 * until the command buffer read and write pointers differ by no more than 71 * 'lead' bytes. This can be useful to limit the time lag possible when 72 * creating a command buffer full of simple BLT commands. 73 *-------------------------------------------------------------------------*/ 74 75 void 76 gp_set_limit_on_buffer_lead(unsigned long lead) 77 { 78 gp3_buffer_lead = lead; 79 } 80 81 /*--------------------------------------------------------------------------- 82 * gp_set_command_buffer_base 83 * 84 * This routine is used to program the command buffer region in physical 85 * memory. The command buffer start address must be 1MB aligned. start and 86 * stop refer to endpoints within the associated 16MB region. Command buffers 87 * larger than 16MB are not supported. 88 *-------------------------------------------------------------------------*/ 89 90 void 91 gp_set_command_buffer_base(unsigned long address, unsigned long start, 92 unsigned long stop) 93 { 94 Q_WORD msr_value; 95 96 /* WAIT FOR IDLE */ 97 /* Obviously, we cannot change the command buffer pointer while the GP */ 98 /* is currently fetching commands. */ 99 100 gp_wait_until_idle(); 101 102 /* WRITE THE COMMAND BUFFER BASE */ 103 104 msr_read64(MSR_DEVICE_GEODELX_GP, MSR_GEODELINK_CONFIG, &msr_value); 105 msr_value.low &= 0xF000FFFF; 106 msr_value.low |= (address >> 4) & 0x0FFF0000; 107 msr_write64(MSR_DEVICE_GEODELX_GP, MSR_GEODELINK_CONFIG, &msr_value); 108 109 /* WRITE THE BASE OFFSETS */ 110 /* We also reset the write and read pointers. The hardware will */ 111 /* automatically update the write pointer when the read pointer */ 112 /* is updated to prevent the hardware from getting confused when */ 113 /* initializing a new command buffer. */ 114 115 WRITE_GP32(GP3_CMD_TOP, start); 116 WRITE_GP32(GP3_CMD_BOT, stop); 117 WRITE_GP32(GP3_CMD_READ, start); 118 119 /* SAVE THE BASE ADDRESSES */ 120 /* These are used to determine the appropriate wrap point. */ 121 122 gp3_cmd_current = gp3_cmd_top = start; 123 gp3_cmd_bottom = stop; 124 } 125 126 /*--------------------------------------------------------------------------- 127 * gp_set_frame_buffer_base 128 * 129 * This routine is used to program the base address of the frame buffer in 130 * physical memory. The frame buffer address must be 16MB aligned. Cimarron 131 * tracks the base address because the maximum frame buffer size may exceed 132 * 16MB. Any primitive will thus program the corresponding 16MB region into 133 * all base offset registers as well as program the offset into the 16MB 134 * region. The size parameter is provided to allow Cimarron to claim the 135 * last 1MB of space to be used as a scratch area for workarounds or 136 * expanded functionality. 137 *-------------------------------------------------------------------------*/ 138 139 void 140 gp_set_frame_buffer_base(unsigned long address, unsigned long size) 141 { 142 gp3_scratch_base = size - GP3_SCRATCH_BUFFER_SIZE; 143 gp3_fb_base = address >> 24; 144 gp3_base_register = 145 (gp3_fb_base << 24) | (gp3_fb_base << 14) | (gp3_fb_base << 4); 146 WRITE_GP32(GP3_BASE_OFFSET, gp3_base_register); 147 } 148 149 /*--------------------------------------------------------------------------- 150 * gp_set_bpp 151 * 152 * This routine sets the output BPP of the GP. The BPP used by the GP does 153 * not have to match the display BPP, but that is usually the case. The 154 * supported BPP values are as follows: 155 * 156 * 8 - palettized 8BPP 157 * 12 - 4:4:4:4 158 * 15 - 1:5:5:5 159 * 16 - 0:5:6:5 160 * 32 - 8:8:8:8 161 *-------------------------------------------------------------------------*/ 162 163 void 164 gp_set_bpp(int bpp) 165 { 166 /* STORE BPP */ 167 /* The bpp is not updated until the next call to gp_set_raster_mode. */ 168 /* This allows the gp_set_bpp call to happen outside of a BLT. It */ 169 /* also implies that no registers need be written in this routine. */ 170 171 switch (bpp) { 172 case 8: 173 gp3_bpp = GP3_RM_BPPFMT_332; 174 gp3_ch3_bpp = GP3_CH3_SRC_3_3_2; 175 gp3_pix_shift = 0; 176 break; 177 case 12: 178 gp3_bpp = GP3_RM_BPPFMT_4444; 179 gp3_ch3_bpp = GP3_CH3_SRC_4_4_4_4; 180 gp3_pix_shift = 1; 181 break; 182 case 15: 183 gp3_bpp = GP3_RM_BPPFMT_1555; 184 gp3_ch3_bpp = GP3_CH3_SRC_1_5_5_5; 185 gp3_pix_shift = 1; 186 break; 187 case 16: 188 gp3_bpp = GP3_RM_BPPFMT_565; 189 gp3_ch3_bpp = GP3_CH3_SRC_0_5_6_5; 190 gp3_pix_shift = 1; 191 break; 192 case 24: 193 case 32: 194 gp3_bpp = GP3_RM_BPPFMT_8888; 195 gp3_ch3_bpp = GP3_CH3_SRC_8_8_8_8; 196 gp3_pix_shift = 2; 197 break; 198 default: 199 gp3_bpp = GP3_RM_BPPFMT_332; 200 gp3_ch3_bpp = GP3_CH3_SRC_3_3_2; 201 gp3_pix_shift = 0; 202 break; 203 } 204 } 205 206 /*--------------------------------------------------------------------------- 207 * gp_declare_blt 208 * 209 * This routine is used to prepare for a 2D BLT. Its primary function 210 * is to verify that enough room is available in the command buffer 211 * to hold a BLT command. This command can be called multiple times if 212 * necessary. For example, if a function calls this routine on entry, but 213 * later realizes that a LUT load command must be executed before the BLT, 214 * the application could call gp_set_color_pattern and then call 215 * gp_declare_blt to declare the BLT. This is possible because the hardware 216 * buffer pointer is not updated until a new BLT is actually executed. An 217 * application must take care not to call any routines that perform a buffer 218 * command, (such as gp_set_color_pattern) between gp_declare_blt and the 219 * routines used to program the BLT parameters. In addition to checking for 220 * available space, this routine also performs the following actions: 221 * - Sets the wrap bit if this BLT will pass close to the end of the 222 * buffer. 223 * - Writes the command header. 224 * 225 * The available flags are defined as follows: 226 * 0x01 - Preserve the LUT 227 * 0x02 - Preserve the color pattern. 228 * 0x04 - Enable prefetch. 229 *-------------------------------------------------------------------------*/ 230 231 void 232 gp_declare_blt(unsigned long flags) 233 { 234 unsigned long temp; 235 236 gp3_blt = 1; 237 gp3_blt_flags = flags; 238 239 /* SET ADDRESS OF NEXT COMMAND */ 240 /* A summary of the command buffer logic is as follows: */ 241 /* - If after a basic BLT we will not have room for the largest */ 242 /* command (a full line of host source data), we set the wrap */ 243 /* bit. This will waste up to a whopping 8K of command buffer */ 244 /* space, but it simplifies the logic for all commands. */ 245 /* - If we are wrapping, we have extra logic to ensure that we */ 246 /* don't skip over the current GP read pointer. */ 247 248 gp3_cmd_next = gp3_cmd_current + GP3_BLT_COMMAND_SIZE; 249 250 /* CHECK WRAP CONDITION */ 251 252 if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) { 253 gp3_cmd_next = gp3_cmd_top; 254 gp3_cmd_header = GP3_BLT_HDR_TYPE | GP3_BLT_HDR_WRAP; 255 256 /* WAIT FOR HARDWARE */ 257 /* When wrapping, we must take steps to ensure that we do not */ 258 /* wrap over the current hardware read pointer. We do this by */ 259 /* verifying that the hardware is not between us and the end of */ 260 /* the command buffer. We also have a special case to make sure */ 261 /* that the hardware is not currently reading the top of the */ 262 /* command buffer. */ 263 264 GP3_WAIT_WRAP(temp); 265 } 266 else { 267 gp3_cmd_header = GP3_BLT_HDR_TYPE; 268 269 /* WAIT FOR AVAILABLE SPACE */ 270 271 GP3_WAIT_PRIMITIVE(temp); 272 } 273 274 if (flags & CIMGP_BLTFLAGS_LIMITBUFFER) { 275 while (1) { 276 temp = READ_GP32(GP3_CMD_READ); 277 if (((gp3_cmd_current >= temp) 278 && ((gp3_cmd_current - temp) <= gp3_buffer_lead)) 279 || ((gp3_cmd_current < temp) 280 && ((gp3_cmd_current + (gp3_cmd_bottom - temp)) <= 281 gp3_buffer_lead))) { 282 break; 283 } 284 } 285 } 286 287 /* SET THE CURRENT BUFFER POINTER */ 288 /* We initialize a pointer to the current buffer base to avoid an */ 289 /* extra addition for every buffer write. */ 290 291 cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current; 292 293 /* SET THE HAZARD BIT */ 294 295 if (flags & CIMGP_BLTFLAGS_HAZARD) 296 gp3_cmd_header |= GP3_BLT_HDR_HAZARD_ENABLE; 297 } 298 299 /*--------------------------------------------------------------------------- 300 * gp_declare_vector 301 * 302 * This routine is used to prepare for a 2D vector. It has no other function 303 * except to verify that enough room is available in the command buffer 304 * to hold a vector command. The same rules that apply to BLTs apply to 305 * vectors. (See the documentation for gp_declare_blt). 306 *-------------------------------------------------------------------------*/ 307 308 void 309 gp_declare_vector(unsigned long flags) 310 { 311 unsigned long temp; 312 313 gp3_blt = 0; 314 gp3_blt_flags = flags; 315 316 /* SET ADDRESS OF NEXT COMMAND */ 317 /* The logic to force a wrap during a vector is identical */ 318 /* to the BLT logic. */ 319 320 /* ALLOCATE SPACE FOR AN ADDITIONAL VECTOR TO CLEAR THE BYTE ENABLES */ 321 322 gp3_cmd_next = gp3_cmd_current + GP3_VECTOR_COMMAND_SIZE + 323 GP3_VECTOR_COMMAND_SIZE + 32; 324 325 /* CHECK WRAP CONDITION */ 326 327 if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) { 328 gp3_cmd_next = gp3_cmd_top; 329 gp3_cmd_header = GP3_VEC_HDR_TYPE | GP3_VEC_HDR_WRAP; 330 331 /* CHECK WRAP CONDITION */ 332 333 GP3_WAIT_WRAP(temp); 334 } 335 else { 336 gp3_cmd_header = GP3_VEC_HDR_TYPE; 337 338 /* WAIT FOR AVAILABLE SPACE */ 339 340 GP3_WAIT_PRIMITIVE(temp); 341 342 gp3_cmd_next -= GP3_VECTOR_COMMAND_SIZE + 32; 343 } 344 345 if (flags & CIMGP_BLTFLAGS_LIMITBUFFER) { 346 while (1) { 347 temp = READ_GP32(GP3_CMD_READ); 348 if (((gp3_cmd_current >= temp) 349 && ((gp3_cmd_current - temp) <= gp3_buffer_lead)) 350 || ((gp3_cmd_current < temp) 351 && ((gp3_cmd_current + (gp3_cmd_bottom - temp)) <= 352 gp3_buffer_lead))) { 353 break; 354 } 355 } 356 } 357 358 cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current; 359 360 /* SET THE HAZARD BIT */ 361 362 if (flags & CIMGP_BLTFLAGS_HAZARD) 363 gp3_cmd_header |= GP3_VEC_HDR_HAZARD_ENABLE; 364 } 365 366 /*--------------------------------------------------------------------------- 367 * gp_write_parameters 368 * 369 * This routine is called to write all recent parameters to the hardware. 370 * This routine is necessary for any implementation that performs the setup 371 * for a BLT separate from the actual BLT. An example would be a driver 372 * that prepares for multiple pattern fills by programming the ROP, 373 * pattern color and destination stride. The driver might then perform 374 * repeated pattern fills with minimal effort. 375 *-------------------------------------------------------------------------*/ 376 377 void 378 gp_write_parameters(void) 379 { 380 /* WRITE THE COMMAND HEADER */ 381 /* Command header is at offset 0 for BLTs and vectors */ 382 383 WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header); 384 385 /* INCREMENT THE CURRENT WRITE POINTER */ 386 387 gp3_cmd_current = gp3_cmd_next; 388 389 /* UPDATE THE GP WRITE POINTER */ 390 391 WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_current); 392 } 393 394 /*--------------------------------------------------------------------------- 395 * gp_set_raster_operation 396 * 397 * This is generally the first routine called when programming a BLT. This 398 * routine performs the following functions: 399 * - Sets the initial value of the GP3_RASTER_MODE register in the buffer. 400 * - Clears any 8x8 pattern if the ROP does not involve pattern data. 401 *-------------------------------------------------------------------------*/ 402 403 void 404 gp_set_raster_operation(unsigned char ROP) 405 { 406 gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE; 407 408 /* WRITE THE RASTER MODE REGISTER */ 409 /* This register is in the same location in BLT and vector commands */ 410 411 gp3_raster_mode = gp3_bpp | (unsigned long) ROP; 412 WRITE_COMMAND32(GP3_BLT_RASTER_MODE, gp3_raster_mode); 413 414 /* CHECK IF DESTINATION IS REQUIRED */ 415 416 if ((ROP & 0x55) ^ ((ROP >> 1) & 0x55)) { 417 gp3_blt_mode = GP3_BM_DST_REQ; 418 gp3_vec_mode = GP3_VM_DST_REQ; 419 } 420 else { 421 gp3_blt_mode = gp3_vec_mode = 0; 422 } 423 } 424 425 /*---------------------------------------------------------------------------- 426 * gp_set_alpha_operation 427 * 428 * BLTs are generally one of two types, a ROPed BLT or a BLT composited using 429 * alpha blending. For the latter, this routine is used to configure the 430 * mathematical function used to create the blended output. This routine 431 * should generally be called first when programming a BLT. The available 432 * parameters mirror the hardware and are described as follows: 433 * 434 * alpha_operation = 435 * 0 - alpha * A 436 * 1 - (1 - alpha) * B 437 * 2 - A + (1 - alpha)*B 438 * 3 - alpha*A + (1 - alpha)*B 439 * 440 * alpha_type = 441 * 0 - alpha component of channel A 442 * 1 - alpha component of channel B 443 * 2 - Constant alpha 444 * 3 - Constant 1 445 * 4 - The color components of channel A 446 * 5 - The color components of channel B 447 * 6 - Alpha comes from the alpha channel of the source before the source 448 * undergoes color conversion. 449 * 450 * channel = 451 * 0 - Channel A = source, channel B = destination 452 * 1 - Channel B = source, channel A = destination 453 * 454 * apply_alpha = 455 * 1 - Apply alpha blend to only the RGB portion of the pixel. This must be 456 * set when the source or destination format do not include an alpha 457 * channel. 458 * 2 - Apply alpha blend only to the alpha portion of the pixel. This 459 * implies that both destination and source include an alpha channel. 460 * 3 - Apply alpha blend to both the RGB and alpha portions of the pixel. 461 * 462 * Alpha-blended vectors are not currently supported. 463 *-------------------------------------------------------------------------*/ 464 465 void 466 gp_set_alpha_operation(int alpha_operation, int alpha_type, int channel, 467 int apply_alpha, unsigned char alpha) 468 { 469 gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE; 470 471 /* THE AVAILABLE ALPHA DEFINITIONS FOLLOW THE HARDWARE */ 472 /* This allows us to avoid giant switch structures, but it */ 473 /* also implies that there is no mechanism to detect invalid */ 474 /* parameters. */ 475 476 gp3_raster_mode = gp3_bpp | (unsigned long) alpha | 477 ((unsigned long) apply_alpha << 22) | 478 ((unsigned long) alpha_operation << 20) | 479 ((unsigned long) alpha_type << 17) | ((unsigned long) channel << 16); 480 481 WRITE_COMMAND32(GP3_BLT_RASTER_MODE, gp3_raster_mode); 482 483 /* CHECK IF DESTINATION IS REQUIRED */ 484 485 if ((alpha_operation == CIMGP_ALPHA_TIMES_A && 486 channel == CIMGP_CHANNEL_A_SOURCE && 487 alpha_type != CIMGP_CHANNEL_B_ALPHA && 488 alpha_type != CIMGP_ALPHA_FROM_RGB_B) || 489 (alpha_operation == CIMGP_BETA_TIMES_B && 490 channel == CIMGP_CHANNEL_A_DEST && 491 alpha_type != CIMGP_CHANNEL_A_ALPHA && 492 alpha_type != CIMGP_ALPHA_FROM_RGB_A)) { 493 gp3_blt_mode = 0; 494 } 495 else 496 gp3_blt_mode = GP3_BM_DST_REQ; 497 } 498 499 /*--------------------------------------------------------------------------- 500 * gp_set_solid_pattern 501 * 502 * This routine is called to program the hardware for a solid pattern. It 503 * need not be called for any other reason. As a side effect, this routine 504 * will clear any 8x8 pattern data. 505 *-------------------------------------------------------------------------*/ 506 507 void 508 gp_set_solid_pattern(unsigned long color) 509 { 510 /* CHANNEL 3 IS NOT NEEDED FOR SOLID PATTERNS */ 511 512 gp3_ch3_pat = 0; 513 514 /* SET SOLID PATTERN IN COMMAND BUFFER */ 515 /* We are assuming that only one pattern type is ever set for a */ 516 /* BLT. We are also assuming that gp_set_raster_operation will */ 517 /* be called before this routine. With these assumptions, we */ 518 /* will thus never have to change the raster mode register for */ 519 /* solid patterns. */ 520 521 if (gp3_blt) { 522 gp3_cmd_header |= GP3_BLT_HDR_PAT_CLR0_ENABLE; 523 524 WRITE_COMMAND32(GP3_BLT_PAT_COLOR_0, color); 525 } 526 else { 527 gp3_cmd_header |= GP3_VEC_HDR_PAT_CLR0_ENABLE; 528 529 WRITE_COMMAND32(GP3_VECTOR_PAT_COLOR_0, color); 530 } 531 } 532 533 /*--------------------------------------------------------------------------- 534 * gp_set_mono_pattern 535 * 536 * This routine is called to program the hardware for a monochrome pattern. 537 * As a side effect, this routine will clear any 8x8 pattern data. 538 *-------------------------------------------------------------------------*/ 539 540 void 541 gp_set_mono_pattern(unsigned long bgcolor, unsigned long fgcolor, 542 unsigned long data0, unsigned long data1, int transparent, 543 int x, int y) 544 { 545 /* CHANNEL 3 IS NOT NEEDED FOR MONOCHROME PATTERNS */ 546 547 gp3_ch3_pat = 0; 548 549 /* UPDATE RASTER MODE REGISTER */ 550 551 if (transparent) 552 gp3_raster_mode |= GP3_RM_PAT_MONO | GP3_RM_PAT_TRANS; 553 else 554 gp3_raster_mode |= GP3_RM_PAT_MONO; 555 556 gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE; 557 558 WRITE_COMMAND32(GP3_BLT_RASTER_MODE, gp3_raster_mode); 559 560 /* SET MONOCHROME PATTERN DATA AND COLORS */ 561 562 if (gp3_blt) { 563 gp3_cmd_header |= 564 (GP3_BLT_HDR_PAT_CLR0_ENABLE | GP3_BLT_HDR_PAT_CLR1_ENABLE | 565 GP3_BLT_HDR_PAT_DATA0_ENABLE | GP3_BLT_HDR_PAT_DATA1_ENABLE); 566 567 WRITE_COMMAND32(GP3_BLT_PAT_COLOR_0, bgcolor); 568 WRITE_COMMAND32(GP3_BLT_PAT_COLOR_1, fgcolor); 569 WRITE_COMMAND32(GP3_BLT_PAT_DATA_0, data0); 570 WRITE_COMMAND32(GP3_BLT_PAT_DATA_1, data1); 571 } 572 else { 573 gp3_cmd_header |= 574 (GP3_VEC_HDR_PAT_CLR0_ENABLE | GP3_VEC_HDR_PAT_CLR1_ENABLE | 575 GP3_VEC_HDR_PAT_DATA0_ENABLE | GP3_VEC_HDR_PAT_DATA1_ENABLE); 576 577 WRITE_COMMAND32(GP3_VECTOR_PAT_COLOR_0, bgcolor); 578 WRITE_COMMAND32(GP3_VECTOR_PAT_COLOR_1, fgcolor); 579 WRITE_COMMAND32(GP3_VECTOR_PAT_DATA_0, data0); 580 WRITE_COMMAND32(GP3_VECTOR_PAT_DATA_1, data1); 581 } 582 583 /* SAVE PATTERN ORIGIN */ 584 585 gp3_pat_origin = ((unsigned long) y << 29) | 586 (((unsigned long) x & 7) << 26); 587 } 588 589 /*--------------------------------------------------------------------------- 590 * gp_set_pattern_origin 591 * 592 * This routine overrides the pattern origins set in gp_set_mono_pattern or 593 * gp_set_color_pattern. It is generally used to override the original 594 * pattern origin due to a change in clipping. 595 *-------------------------------------------------------------------------*/ 596 597 void 598 gp_set_pattern_origin(int x, int y) 599 { 600 /* SAVE PATTERN ORIGIN */ 601 602 gp3_pat_origin = ((unsigned long) y << 29) | 603 (((unsigned long) x & 7) << 26); 604 } 605 606 /*--------------------------------------------------------------------------- 607 * gp_set_color_pattern 608 * 609 * This routine is called to program a 8x8 color pattern into the LUT 610 * hardware. Unlike the other pattern routines, this routine must be called 611 * before any gp_declare_xxxx routines. The pattern that is programmed into 612 * the hardware will stay persistent for all subsequent primitives until one 613 * of the following conditions happens. 614 * - Another pattern type is programmed. 615 * - A color-conversion BLT rotation BLT. 616 *-------------------------------------------------------------------------*/ 617 618 void 619 gp_set_color_pattern(unsigned long *pattern, int format, int x, int y) 620 { 621 unsigned long size_dwords, temp; 622 623 gp3_ch3_pat = 1; 624 625 /* SAVE COLOR PATTERN SOURCE INFO 626 * Color patterns can be in a format different than the primary display. 627 * 4BPP patterns are not supported. 628 */ 629 630 gp3_pat_pix_shift = (unsigned long) ((format >> 2) & 3); 631 gp3_pat_format = (((unsigned long) format & 0xF) << 24) | 632 (((unsigned long) format & 0x10) << 17) | 633 GP3_CH3_COLOR_PAT_ENABLE | GP3_CH3_C3EN; 634 635 size_dwords = (64 << gp3_pat_pix_shift) >> 2; 636 637 /* CHECK FOR WRAP AFTER LUT LOAD */ 638 /* Primitive size is 12 plus the amount of data. */ 639 640 gp3_cmd_next = gp3_cmd_current + (size_dwords << 2) + 12; 641 642 if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) { 643 gp3_cmd_next = gp3_cmd_top; 644 gp3_cmd_header = GP3_LUT_HDR_TYPE | GP3_LUT_HDR_WRAP | 645 GP3_LUT_HDR_DATA_ENABLE; 646 647 /* WAIT FOR HARDWARE */ 648 /* Same logic as BLT wrapping. */ 649 650 GP3_WAIT_WRAP(temp); 651 } 652 else { 653 gp3_cmd_header = GP3_LUT_HDR_TYPE | GP3_LUT_HDR_DATA_ENABLE; 654 655 /* WAIT FOR AVAILABLE SPACE */ 656 657 GP3_WAIT_PRIMITIVE(temp); 658 } 659 660 /* SAVE CURRENT BUFFER POINTER */ 661 662 cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current; 663 664 /* PREPARE FOR COMMAND BUFFER DATA WRITES */ 665 /* Pattern data is contiguous DWORDs at LUT address 0x100 */ 666 667 WRITE_COMMAND32(0, gp3_cmd_header); 668 WRITE_COMMAND32(4, 0x100); 669 WRITE_COMMAND32(8, size_dwords | GP3_LUT_DATA_TYPE); 670 671 /* WRITE ALL DATA */ 672 673 WRITE_COMMAND_STRING32(12, pattern, 0, size_dwords); 674 675 /* START OPERATION */ 676 677 WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); 678 gp3_cmd_current = gp3_cmd_next; 679 680 /* SAVE PATTERN ORIGIN */ 681 682 gp3_pat_origin = ((unsigned long) y << 29) | 683 (((unsigned long) x & 7) << 26); 684 } 685 686 /*--------------------------------------------------------------------------- 687 * gp_set_mono_source 688 * 689 * This routine is called to program the colors for monochrome source data. 690 *-------------------------------------------------------------------------*/ 691 692 void 693 gp_set_mono_source(unsigned long bgcolor, unsigned long fgcolor, 694 int transparent) 695 { 696 /* UPDATE RASTER MODE REGISTER IF TRANSPARENT */ 697 698 if (transparent) { 699 gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE; 700 gp3_raster_mode |= GP3_RM_SRC_TRANS; 701 702 WRITE_COMMAND32(GP3_BLT_RASTER_MODE, gp3_raster_mode); 703 } 704 705 /* SET MONOCHROME SOURCE COLORS */ 706 /* Note that this routine only sets the colors. The actual */ 707 /* source type is determined by the final output routine */ 708 /* (gp_mono_bitmap_xxx, gp_color_bitmap_xxx, etc.) */ 709 710 gp3_cmd_header |= GP3_BLT_HDR_SRC_FG_ENABLE | GP3_BLT_HDR_SRC_BG_ENABLE; 711 712 WRITE_COMMAND32(GP3_BLT_SRC_COLOR_FG, fgcolor); 713 WRITE_COMMAND32(GP3_BLT_SRC_COLOR_BG, bgcolor); 714 } 715 716 /*--------------------------------------------------------------------------- 717 * gp_set_solid_source 718 * 719 * This routine is called to program a solid source color. A solid source 720 * color is used primarily for vectors or antialiased text. 721 *-------------------------------------------------------------------------*/ 722 723 void 724 gp_set_solid_source(unsigned long color) 725 { 726 /* SET SOLID SOURCE COLOR */ 727 /* The solid source register is in the same place for both BLTs and */ 728 /* vectors. */ 729 730 gp3_cmd_header |= GP3_BLT_HDR_SRC_FG_ENABLE; 731 732 WRITE_COMMAND32(GP3_BLT_SRC_COLOR_FG, color); 733 } 734 735 /*--------------------------------------------------------------------------- 736 * gp_set_source_transparency 737 * 738 * This routine sets the source transparency and mask to be used in future 739 * rendering operations. Transparency is cleared by gp_set_raster_operation, 740 * so this routine should never be called first. 741 *-------------------------------------------------------------------------*/ 742 743 void 744 gp_set_source_transparency(unsigned long color, unsigned long mask) 745 { 746 gp3_raster_mode |= GP3_RM_SRC_TRANS; 747 gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE | GP3_BLT_HDR_SRC_FG_ENABLE | 748 GP3_BLT_HDR_SRC_BG_ENABLE; 749 750 WRITE_COMMAND32(GP3_BLT_RASTER_MODE, gp3_raster_mode); 751 WRITE_COMMAND32(GP3_BLT_SRC_COLOR_FG, color); 752 WRITE_COMMAND32(GP3_BLT_SRC_COLOR_BG, mask); 753 } 754 755 /*--------------------------------------------------------------------------- 756 * gp_program_lut 757 * 758 * This routine is called to program the hardware LUT with color-conversion 759 * information. This routine should be called before any gp_declare_xxxx 760 * routines. 761 * 762 * colors - Pointer to an array of DWORDs for color expansion. 763 * 764 * full_lut - Selector between 4BPP and 8BPP expansion. The hardware is 765 * initialized with 16 dwords for 4BPP expansion and 256 dwords 766 * for 8BPP expansion. 767 *-------------------------------------------------------------------------*/ 768 769 void 770 gp_program_lut(unsigned long *colors, int full_lut) 771 { 772 unsigned long size_dwords, temp; 773 774 /* SIZE IS EITHER 16 DWORDS (4BPP) or 256 DWORDS (8BPP) */ 775 776 if (full_lut) 777 size_dwords = 256; 778 else 779 size_dwords = 16; 780 781 /* CHECK FOR WRAP AFTER LUT LOAD */ 782 /* Primitive size is 12 plus the amount of data. */ 783 784 gp3_cmd_next = gp3_cmd_current + (size_dwords << 2) + 12; 785 786 if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) { 787 gp3_cmd_next = gp3_cmd_top; 788 gp3_cmd_header = GP3_LUT_HDR_TYPE | GP3_LUT_HDR_WRAP | 789 GP3_LUT_HDR_DATA_ENABLE; 790 791 /* WAIT FOR HARDWARE */ 792 /* Same logic as BLT wrapping. */ 793 794 GP3_WAIT_WRAP(temp); 795 } 796 else { 797 gp3_cmd_header = GP3_LUT_HDR_TYPE | GP3_LUT_HDR_DATA_ENABLE; 798 799 /* WAIT FOR AVAILABLE SPACE */ 800 801 GP3_WAIT_PRIMITIVE(temp); 802 } 803 804 /* SAVE CURRENT BUFFER POINTER */ 805 806 cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current; 807 808 /* PREPARE FOR COMMAND BUFFER DATA WRITES */ 809 /* Pattern data is contiguous DWORDs at LUT address 0 */ 810 811 WRITE_COMMAND32(0, gp3_cmd_header); 812 WRITE_COMMAND32(4, 0); 813 WRITE_COMMAND32(8, (size_dwords | GP3_LUT_DATA_TYPE)); 814 815 /* WRITE ALL DATA */ 816 817 WRITE_COMMAND_STRING32(12, colors, 0, size_dwords); 818 819 /* START OPERATION */ 820 821 WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); 822 gp3_cmd_current = gp3_cmd_next; 823 } 824 825 /*--------------------------------------------------------------------------- 826 * gp_set_vector_pattern 827 * 828 * This routine is called to program the hardware LUT with a vector pattern. 829 * A vector pattern is programmed as a 32-bit mask that specifies a 830 * transparency pattern. A length parameter is used to specify patterns 831 * smaller than 32. Note that vectors in Geode LX do not continue across 832 * corners. The beginning of each vector will always begin with bit 0 of the 833 * vector pattern. It is the responsibility of the caller to update the 834 * pattern if an alternate behavior is desired. 835 * 836 * This routine faces the same restrictions of all routines that program 837 * the LUT, in that it must be called before any gp_declare_xxxx routines, 838 * it cannot be combined with an 8x8 color pattern, color conversion or 839 * rotation. 840 *-------------------------------------------------------------------------*/ 841 842 void 843 gp_set_vector_pattern(unsigned long pattern, unsigned long color, int length) 844 { 845 unsigned long temp, mask; 846 847 gp3_ch3_pat = 1; 848 gp3_vector_pattern_color = color; 849 850 /* CREATE SUITABLE PATTERN MASK */ 851 /* The GP requires a minimum of four pixels in a vector pattern. We */ 852 /* can get around this restriction by doubling any patterns smaller */ 853 /* than 4 pixels. */ 854 855 while (length < 4) { 856 mask = 0xFFFFFFFF >> (32 - length); 857 pattern = (pattern << length) | (pattern & mask); 858 length <<= 1; 859 } 860 mask = 0xFFFFFFFF >> (32 - length); 861 862 gp3_vec_pat = pattern; 863 864 /* CHECK FOR WRAP AFTER LUT LOAD */ 865 866 gp3_cmd_next = gp3_cmd_current + GP3_VECTOR_PATTERN_COMMAND_SIZE; 867 868 if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) { 869 gp3_cmd_next = gp3_cmd_top; 870 gp3_cmd_header = GP3_LUT_HDR_TYPE | GP3_LUT_HDR_WRAP | 871 GP3_LUT_HDR_DATA_ENABLE; 872 873 /* WAIT FOR HARDWARE */ 874 /* Same logic as BLT wrapping. */ 875 876 GP3_WAIT_WRAP(temp); 877 } 878 else { 879 gp3_cmd_header = GP3_LUT_HDR_TYPE | GP3_LUT_HDR_DATA_ENABLE; 880 881 /* WAIT FOR AVAILABLE SPACE */ 882 883 GP3_WAIT_PRIMITIVE(temp); 884 } 885 886 /* SAVE CURRENT BUFFER POINTER */ 887 888 cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current; 889 890 /* PREPARE FOR COMMAND BUFFER DATA WRITES */ 891 /* Pattern data is 2 DWORDs at 0x100 and 0x101 */ 892 893 WRITE_COMMAND32(0, gp3_cmd_header); 894 WRITE_COMMAND32(4, 0x100); 895 WRITE_COMMAND32(8, (2 | GP3_LUT_DATA_TYPE)); 896 WRITE_COMMAND32(12, pattern); 897 WRITE_COMMAND32(16, mask); 898 899 /* START OPERATION */ 900 901 WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); 902 gp3_cmd_current = gp3_cmd_next; 903 } 904 905 /*--------------------------------------------------------------------------- 906 * gp_set_strides 907 * 908 * This routine is called to program the pitch between successive lines of 909 * data in the frame buffer. The strides should be DWORD aligned and less 910 * than 64K. These restrictions are not checked by the API. 911 *-------------------------------------------------------------------------*/ 912 913 void 914 gp_set_strides(unsigned long dst_stride, unsigned long src_stride) 915 { 916 /* SAVE STRIDES */ 917 /* The source stride may be needed later for channel 3 source data and */ 918 /* we may need to use these strides in calculations. */ 919 920 gp3_src_stride = src_stride; 921 gp3_dst_stride = dst_stride; 922 923 /* ENABLE STRIDES */ 924 /* The stride register is in the same place for BLTs and vectors */ 925 926 gp3_cmd_header |= GP3_BLT_HDR_STRIDE_ENABLE; 927 928 WRITE_COMMAND32(GP3_BLT_STRIDE, ((src_stride << 16) | dst_stride)); 929 } 930 931 /*--------------------------------------------------------------------------- 932 * gp_set_source_format 933 * 934 * This routine is used to program the format of source data used in 935 * subsequent color-conversion or rotation operations. Note that 4BPP 936 * indexed and 8BPP indexed source formats cannot be used when rotating, as 937 * the LUT will be destroyed. These formats also cannot be combined with an 938 * 8x8 color pattern. The supported formats mirror the hardware and are 939 * described as follows: 940 * 941 * 0 - 8BPP 3:3:2 942 * 1 - 8BPP indexed 943 * 4 - 16BPP 4:4:4:4 944 * 5 - 16BPP 1:5:5:5 945 * 6 - 16BPP 5:6:5 946 * 7 - 16BPP YUV 947 * 8 - 32BPP 8:8:8:8 948 * 13 - 4BPP indexed 949 * 20 - 16BPP 4:4:4:4 BGR 950 * 21 - 16BPP 1:5:5:5 BGR 951 * 22 - 16BPP 0:5:6:5 BGR 952 * 24 - 32BPP 8:8:8:8 BGR 953 *-------------------------------------------------------------------------*/ 954 955 void 956 gp_set_source_format(int format) 957 { 958 /* SAVE FORMAT */ 959 /* We will combine the source format later when doing color conversion. */ 960 /* We also save the pixel size for host source calculations. */ 961 /* Conveniently, the source formats are organized such that the upper */ 962 /* two bits of the nibble represent the pixel shift, with a pixel shift */ 963 /* of 3 being a special case for 4BPP data. Clever, yes? Even more */ 964 /* clever, bit 4 indicates BGR ordering. */ 965 966 gp3_src_pix_shift = (unsigned long) ((format >> 2) & 3); 967 gp3_src_format = (((unsigned long) format & 0xF) << 24) | 968 (((unsigned long) format & 0x10) << 18); 969 } 970 971 /*--------------------------------------------------------------------------- 972 * gp_pattern_fill 973 * 974 * This routine is called to perform a simple pattern fill. The pattern 975 * can be solid, monochrome or a preprogrammed 8x8 color pattern. If 976 * the ROP involves source data, that source data will be constant. 977 *-------------------------------------------------------------------------*/ 978 979 void 980 gp_pattern_fill(unsigned long dstoffset, unsigned long width, 981 unsigned long height) 982 { 983 unsigned long base_register; 984 985 base_register = (gp3_base_register & ~GP3_BASE_OFFSET_DSTMASK) | 986 ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000)); 987 988 /* ENABLE RELEVANT REGISTERS */ 989 /* Note that we always enable and write the channel 3 mode, if only */ 990 /* to turn it off. Cimarron also always writes the base offset */ 991 /* register to allow operation with frame buffers larger than 16MB. */ 992 993 gp3_cmd_header |= GP3_BLT_HDR_DST_OFF_ENABLE | 994 GP3_BLT_HDR_WIDHI_ENABLE | 995 GP3_BLT_HDR_BASE_OFFSET_ENABLE | 996 GP3_BLT_HDR_CH3_STR_ENABLE | 997 GP3_BLT_HDR_CH3_WIDHI_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE; 998 999 /* WRITE THE REGISTERS COMMON TO ALL PATTERN TYPES */ 1000 /* The destination base is the frame buffer base plus whatever */ 1001 /* 4MB segment we happen to be BLTing to. */ 1002 1003 WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, ((width << 16) | height)); 1004 WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base_register); 1005 1006 /* CHECK 8X8 COLOR PATTERN CASE */ 1007 1008 if (gp3_ch3_pat) { 1009 /* SET CHANNEL 3 PATTERN ORIGINS */ 1010 1011 gp3_cmd_header |= GP3_BLT_HDR_CH3_OFF_ENABLE; 1012 1013 /* INITIALIZE CHANNEL 3 PARAMETERS */ 1014 1015 WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, ((width << 16) | height)); 1016 WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, gp3_pat_origin); 1017 WRITE_COMMAND32(GP3_BLT_DST_OFFSET, dstoffset & 0x3FFFFF); 1018 WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, gp3_pat_format); 1019 } 1020 else { 1021 /* DISABLE CHANNEL 3 AND USE NORMAL PATTERN ORIGINS */ 1022 1023 WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, 0); 1024 WRITE_COMMAND32(GP3_BLT_DST_OFFSET, 1025 ((dstoffset & 0x3FFFFF) | gp3_pat_origin)); 1026 } 1027 1028 /* START THE BLT */ 1029 1030 WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header); 1031 WRITE_COMMAND32(GP3_BLT_MODE, gp3_blt_mode); 1032 WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); 1033 gp3_cmd_current = gp3_cmd_next; 1034 } 1035 1036 /*--------------------------------------------------------------------------- 1037 * gp_screen_to_screen_blt 1038 * 1039 * This routine is called to perform a BLT from one location inside video 1040 * memory to another location inside video memory. The source and destination 1041 * formats are assumed to be the current BPP. Whenever possible, this routine 1042 * tries to use channel 3 to fetch source data. The BLT flags can affect this 1043 * behavior in the following ways: 1044 * CIMGP_BLTFLAGS_PRES_COLOR_PAT 1045 * A color pattern is being stored in the channel 3 buffer. It is either 1046 * being stored for a later BLT or being combined with the current source 1047 * data. Channel 3 cannot be used to fetch source data or the pattern 1048 * will be overwritten. 1049 * CIMGP_BLTFLAGS_PRES_LUT 1050 * If the first flag is not set, this flag will limit the use of the 1051 * channel 3 buffer to 1K. 1052 *-------------------------------------------------------------------------*/ 1053 1054 void 1055 gp_screen_to_screen_blt(unsigned long dstoffset, unsigned long srcoffset, 1056 unsigned long width, unsigned long height, int flags) 1057 { 1058 unsigned long base; 1059 unsigned long ch3_flags = 0; 1060 unsigned long blt_mode = gp3_blt_mode; 1061 unsigned long size = ((width << 16) | height); 1062 unsigned long dstbase, srcbase; 1063 1064 /* CALCULATE BASE OFFSETS */ 1065 /* We need to set the 4MB aligned base offsets before we add offsets */ 1066 /* for negative BLTs. */ 1067 1068 srcbase = srcoffset & 0xFFC00000; 1069 dstbase = dstoffset & 0xFFC00000; 1070 srcoffset &= 0x3FFFFF; 1071 dstoffset &= 0x3FFFFF; 1072 1073 /* ADJUST OFFSETS BASED ON FLAGS */ 1074 /* We adjust the source and destination offsets to point to the first */ 1075 /* byte of the first pixel of the BLT. This routine assumes that the */ 1076 /* source and destination regions do not wrap past the end of a 16MB */ 1077 /* region. */ 1078 1079 if (flags & CIMGP_NEGXDIR) { 1080 srcoffset += (width << gp3_pix_shift) - 1; 1081 dstoffset += (width << gp3_pix_shift) - 1; 1082 blt_mode |= GP3_BM_NEG_XDIR; 1083 ch3_flags |= GP3_CH3_NEG_XDIR; 1084 } 1085 if (flags & CIMGP_NEGYDIR) { 1086 srcoffset += (height - 1) * gp3_src_stride; 1087 dstoffset += (height - 1) * gp3_dst_stride; 1088 blt_mode |= GP3_BM_NEG_YDIR; 1089 ch3_flags |= GP3_CH3_NEG_YDIR; 1090 } 1091 1092 /* BRANCH BASED ON CHANNEL 3 */ 1093 /* If a color pattern is not being saved or used, channel 3 will */ 1094 /* be used to fetch source for maximum throughput. Channel 3 */ 1095 /* is not used if transparency or alpha blending is enabled. */ 1096 1097 if (!(gp3_blt_flags & CIMGP_BLTFLAGS_PRES_COLOR_PAT) && 1098 !(gp3_raster_mode & GP3_RM_SRC_TRANS) && !(flags & CIMGP_NEGYDIR)) { 1099 base = ((gp3_fb_base << 24) + dstbase) | 1100 ((gp3_fb_base << 4) + (srcbase >> 20)) | 1101 (gp3_base_register & GP3_BASE_OFFSET_SRCMASK); 1102 1103 gp3_cmd_header |= GP3_BLT_HDR_DST_OFF_ENABLE | 1104 GP3_BLT_HDR_WIDHI_ENABLE | 1105 GP3_BLT_HDR_CH3_STR_ENABLE | 1106 GP3_BLT_HDR_CH3_WIDHI_ENABLE | 1107 GP3_BLT_HDR_CH3_OFF_ENABLE | 1108 GP3_BLT_HDR_BASE_OFFSET_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE; 1109 1110 WRITE_COMMAND32(GP3_BLT_DST_OFFSET, (dstoffset | gp3_pat_origin)); 1111 WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, srcoffset); 1112 WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, size); 1113 WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, size); 1114 WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base); 1115 WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, 1116 GP3_CH3_C3EN | GP3_CH3_REPLACE_SOURCE | 1117 gp3_ch3_bpp | gp3_src_stride | ch3_flags | 1118 ((gp3_blt_flags & CIMGP_ENABLE_PREFETCH) << 17) | 1119 ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT) << 20)); 1120 } 1121 else { 1122 /* CALCULATE BASE OFFSET REGISTER */ 1123 1124 base = ((gp3_fb_base << 24) + dstbase) | 1125 ((gp3_fb_base << 14) + (srcbase >> 10)) | 1126 (gp3_base_register & GP3_BASE_OFFSET_CH3MASK); 1127 1128 /* PROGRAM THE NORMAL SOURCE CHANNEL REGISTERS */ 1129 /* We assume that a color pattern is being ROPed with source */ 1130 /* data if the pattern type is color and the preserve pattern */ 1131 /* was set. */ 1132 1133 blt_mode |= GP3_BM_SRC_FB; 1134 1135 gp3_cmd_header |= GP3_BLT_HDR_SRC_OFF_ENABLE | 1136 GP3_BLT_HDR_DST_OFF_ENABLE | 1137 GP3_BLT_HDR_WIDHI_ENABLE | 1138 GP3_BLT_HDR_CH3_WIDHI_ENABLE | 1139 GP3_BLT_HDR_CH3_STR_ENABLE | 1140 GP3_BLT_HDR_CH3_OFF_ENABLE | 1141 GP3_BLT_HDR_BASE_OFFSET_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE; 1142 1143 if (gp3_ch3_pat) { 1144 WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, gp3_pat_origin); 1145 WRITE_COMMAND32(GP3_BLT_DST_OFFSET, dstoffset); 1146 WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, gp3_pat_format | ch3_flags); 1147 WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, size); 1148 } 1149 else { 1150 WRITE_COMMAND32(GP3_BLT_DST_OFFSET, dstoffset | gp3_pat_origin); 1151 WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, 0); 1152 } 1153 1154 WRITE_COMMAND32(GP3_BLT_SRC_OFFSET, srcoffset); 1155 WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, size); 1156 WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base); 1157 } 1158 1159 /* START THE BLT */ 1160 1161 WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header); 1162 WRITE_COMMAND32(GP3_BLT_MODE, blt_mode); 1163 WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); 1164 gp3_cmd_current = gp3_cmd_next; 1165 } 1166 1167 /*--------------------------------------------------------------------------- 1168 * gp_screen_to_screen_convert 1169 * 1170 * This routine is called to color-convert a rectangular region of the frame 1171 * buffer into the current BPP. The format of the source region is programmed 1172 * by gp_set_source_format. 1173 *-------------------------------------------------------------------------*/ 1174 1175 void 1176 gp_screen_to_screen_convert(unsigned long dstoffset, unsigned long srcoffset, 1177 unsigned long width, unsigned long height, 1178 int nibble) 1179 { 1180 unsigned long size = ((width << 16) | height); 1181 unsigned long ch3_offset = srcoffset & 0x3FFFFF; 1182 unsigned long ch3_size, base; 1183 1184 base = ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000)) | 1185 ((gp3_fb_base << 4) + ((srcoffset & 0xFFC00000) >> 20)) | 1186 (gp3_base_register & GP3_BASE_OFFSET_SRCMASK); 1187 1188 /* SET NIBBLE FOR 4BPP */ 1189 /* 4BPP is a special case in that it requires subpixel addressing. The */ 1190 /* user must supply this information via the nibble parameter. This */ 1191 /* parameter is ignored for every other source format. */ 1192 1193 ch3_size = size; 1194 if (gp3_src_pix_shift == 3) 1195 ch3_offset |= ((nibble & 1) << 25); 1196 else if ((gp3_src_format & GP3_CH3_SRC_MASK) == GP3_CH3_SRC_24BPP_PACKED) 1197 ch3_size = ((((width * 3) + 3) >> 2) << 16) | height; 1198 1199 /* SET APPROPRIATE ENABLES */ 1200 1201 gp3_cmd_header |= GP3_BLT_HDR_DST_OFF_ENABLE | 1202 GP3_BLT_HDR_WIDHI_ENABLE | 1203 GP3_BLT_HDR_CH3_OFF_ENABLE | 1204 GP3_BLT_HDR_CH3_STR_ENABLE | 1205 GP3_BLT_HDR_CH3_WIDHI_ENABLE | 1206 GP3_BLT_HDR_BASE_OFFSET_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE; 1207 1208 /* WRITE ALL BLT REGISTERS */ 1209 1210 WRITE_COMMAND32(GP3_BLT_DST_OFFSET, 1211 (dstoffset & 0x3FFFFF) | gp3_pat_origin); 1212 WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, size); 1213 WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, ch3_size); 1214 WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, ch3_offset); 1215 WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, 1216 GP3_CH3_C3EN | GP3_CH3_REPLACE_SOURCE | gp3_src_format | 1217 ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT) << 20) | 1218 ((gp3_blt_flags & CIMGP_ENABLE_PREFETCH) << 17) | 1219 gp3_src_stride); 1220 WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base); 1221 1222 /* START THE BLT */ 1223 1224 WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header); 1225 WRITE_COMMAND32(GP3_BLT_MODE, gp3_blt_mode); 1226 WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); 1227 gp3_cmd_current = gp3_cmd_next; 1228 } 1229 1230 /*--------------------------------------------------------------------------- 1231 * gp_color_bitmap_to_screen_blt 1232 * 1233 * This routine is called to BLT data from system memory into the frame 1234 * buffer. 'srcy' is deliberately omitted to prevent extra calculations for 1235 * simple applications that have no source indexes. 1236 *-------------------------------------------------------------------------*/ 1237 1238 void 1239 gp_color_bitmap_to_screen_blt(unsigned long dstoffset, unsigned long srcx, 1240 unsigned long width, unsigned long height, 1241 unsigned char *data, long pitch) 1242 { 1243 unsigned long indent, temp; 1244 unsigned long total_dwords, size_dwords; 1245 unsigned long dword_count, byte_count; 1246 unsigned long size = ((width << 16) | height); 1247 unsigned long srcoffset; 1248 1249 /* ASSUME BITMAPS ARE DWORD ALIGNED */ 1250 /* We will offset into the source data in DWORD increments. We */ 1251 /* set the source index to the remaining byte offset and */ 1252 /* increment the size of each line to account for the dont-care */ 1253 /* pixel(s). */ 1254 1255 indent = srcx << gp3_pix_shift; 1256 srcoffset = (indent & ~3L); 1257 indent &= 3; 1258 1259 /* PROGRAM THE NORMAL SOURCE CHANNEL REGISTERS */ 1260 /* We assume that a color pattern is being ROPed with source */ 1261 /* data if the pattern type is color and the preserve pattern */ 1262 /* was set. */ 1263 1264 gp3_cmd_header |= GP3_BLT_HDR_SRC_OFF_ENABLE | 1265 GP3_BLT_HDR_DST_OFF_ENABLE | 1266 GP3_BLT_HDR_WIDHI_ENABLE | 1267 GP3_BLT_HDR_CH3_STR_ENABLE | 1268 GP3_BLT_HDR_BASE_OFFSET_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE; 1269 1270 if (gp3_ch3_pat) { 1271 gp3_cmd_header |= GP3_BLT_HDR_CH3_OFF_ENABLE | 1272 GP3_BLT_HDR_CH3_WIDHI_ENABLE; 1273 1274 WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, gp3_pat_origin); 1275 WRITE_COMMAND32(GP3_BLT_DST_OFFSET, (dstoffset & 0x3FFFFF)); 1276 WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, gp3_pat_format); 1277 WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, size); 1278 } 1279 else { 1280 WRITE_COMMAND32(GP3_BLT_DST_OFFSET, 1281 ((dstoffset & 0x3FFFFF) | gp3_pat_origin)); 1282 WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, 0); 1283 } 1284 1285 WRITE_COMMAND32(GP3_BLT_SRC_OFFSET, indent); 1286 WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, size); 1287 WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, 1288 ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000))); 1289 WRITE_COMMAND32(GP3_BLT_MODE, gp3_blt_mode | GP3_BM_SRC_HOST); 1290 1291 /* START THE BLT */ 1292 1293 WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header); 1294 WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); 1295 gp3_cmd_current = gp3_cmd_next; 1296 1297 /* CALCULATE THE SIZE OF ONE LINE */ 1298 1299 size = (width << gp3_pix_shift) + indent; 1300 total_dwords = (size + 3) >> 2; 1301 size_dwords = (total_dwords << 2) + 8; 1302 dword_count = (size >> 2); 1303 byte_count = (size & 3); 1304 1305 /* CHECK FOR SMALL BLT CASE */ 1306 1307 if (((total_dwords << 2) * height) <= GP3_BLT_1PASS_SIZE && 1308 (gp3_cmd_bottom - gp3_cmd_current) > (GP3_BLT_1PASS_SIZE + 72)) { 1309 /* UPDATE THE COMMAND POINTER */ 1310 1311 cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current; 1312 1313 /* CHECK IF A WRAP WILL BE NEEDED */ 1314 1315 gp3_cmd_next = gp3_cmd_current + ((total_dwords << 2) * height) + 8; 1316 1317 if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) { 1318 gp3_cmd_next = gp3_cmd_top; 1319 1320 GP3_WAIT_WRAP(temp); 1321 WRITE_COMMAND32(0, 1322 GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP | 1323 GP3_DATA_LOAD_HDR_ENABLE); 1324 } 1325 else { 1326 GP3_WAIT_PRIMITIVE(temp); 1327 WRITE_COMMAND32(0, 1328 GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_ENABLE); 1329 } 1330 1331 /* WRITE DWORD COUNT */ 1332 1333 WRITE_COMMAND32(4, GP3_HOST_SOURCE_TYPE | (total_dwords * height)); 1334 1335 while (height--) { 1336 /* WRITE DATA */ 1337 1338 WRITE_COMMAND_STRING32(8, data, srcoffset, dword_count); 1339 WRITE_COMMAND_STRING8(8 + (dword_count << 2), data, 1340 srcoffset + (dword_count << 2), byte_count); 1341 1342 srcoffset += pitch; 1343 cim_cmd_ptr += total_dwords << 2; 1344 } 1345 1346 WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); 1347 gp3_cmd_current = gp3_cmd_next; 1348 } 1349 else { 1350 /* 1351 * Each line will be created as a separate command buffer entry to 1352 * allow line-by-line wrapping and to allow simultaneous rendering 1353 * by the HW. 1354 */ 1355 1356 while (height--) { 1357 /* UPDATE THE COMMAND POINTER 1358 * The WRITE_COMMANDXX macros use a pointer to the current buffer 1359 * space. This is created by adding gp3_cmd_current to the base 1360 * pointer. 1361 */ 1362 1363 cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current; 1364 1365 /* CHECK IF A WRAP WILL BE NEEDED */ 1366 1367 gp3_cmd_next = gp3_cmd_current + size_dwords; 1368 if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) { 1369 gp3_cmd_next = gp3_cmd_top; 1370 1371 /* WAIT FOR HARDWARE */ 1372 1373 GP3_WAIT_WRAP(temp); 1374 WRITE_COMMAND32(0, GP3_DATA_LOAD_HDR_TYPE | 1375 GP3_DATA_LOAD_HDR_WRAP | 1376 GP3_DATA_LOAD_HDR_ENABLE); 1377 } 1378 else { 1379 /* WAIT FOR AVAILABLE SPACE */ 1380 1381 GP3_WAIT_PRIMITIVE(temp); 1382 WRITE_COMMAND32(0, GP3_DATA_LOAD_HDR_TYPE | 1383 GP3_DATA_LOAD_HDR_ENABLE); 1384 } 1385 1386 /* WRITE DWORD COUNT */ 1387 1388 WRITE_COMMAND32(4, GP3_HOST_SOURCE_TYPE | total_dwords); 1389 1390 /* WRITE DATA */ 1391 1392 WRITE_COMMAND_STRING32(8, data, srcoffset, dword_count); 1393 WRITE_COMMAND_STRING8(8 + (dword_count << 2), data, 1394 srcoffset + (dword_count << 2), byte_count); 1395 1396 /* UPDATE POINTERS */ 1397 1398 srcoffset += pitch; 1399 WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); 1400 gp3_cmd_current = gp3_cmd_next; 1401 } 1402 } 1403 } 1404 1405 /*--------------------------------------------------------------------------- 1406 * gp_color_convert_blt 1407 * 1408 * This routine is called to convert data that is stored in system memory 1409 * into the current graphics BPP. The source format is programmed in 1410 * gp_set_source_format. 1411 *-------------------------------------------------------------------------*/ 1412 1413 void 1414 gp_color_convert_blt(unsigned long dstoffset, unsigned long srcx, 1415 unsigned long width, unsigned long height, 1416 unsigned char *data, long pitch) 1417 { 1418 unsigned long indent, temp; 1419 unsigned long total_dwords, size_dwords; 1420 unsigned long dword_count, byte_count; 1421 unsigned long size = ((width << 16) | height); 1422 unsigned long ch3_size; 1423 unsigned long ch3_offset, srcoffset; 1424 unsigned long base; 1425 1426 /* ASSUME BITMAPS ARE DWORD ALIGNED */ 1427 /* We will offset into the source data in DWORD increments. We */ 1428 /* set the source index to the remaining byte offset and */ 1429 /* increment the size of each line to account for the dont-care */ 1430 /* pixel(s). For 4BPP source data, we also set the appropriate */ 1431 /* nibble index. */ 1432 1433 /* CALCULATE THE SIZE OF ONE LINE */ 1434 1435 if ((gp3_src_format & GP3_CH3_SRC_MASK) == GP3_CH3_SRC_24BPP_PACKED) { 1436 /* HANDLE 24BPP 1437 * Note that we do not do anything to guarantee that the source data 1438 * is DWORD aligned. The logic here is that the source data will be 1439 * cacheable, in which case Geode LX will not lose any clocks for 1440 * unaligned moves. Also note that the channel 3 width is 1441 * programmed as the number of dwords, while the normal width is 1442 * programmed as the number of pixels. 1443 */ 1444 1445 srcoffset = srcx * 3; 1446 ch3_offset = 0; 1447 temp = width * 3; 1448 ch3_size = (((temp + 3) >> 2) << 16) | height; 1449 } 1450 else { 1451 ch3_size = size; 1452 1453 if (gp3_src_pix_shift == 3) { 1454 /* CALCULATE INDENT AND SOURCE OFFSET */ 1455 1456 indent = (srcx >> 1); 1457 srcoffset = (indent & ~3L); 1458 indent &= 3; 1459 ch3_offset = indent | ((srcx & 1) << 25); 1460 1461 temp = ((width + (srcx & 1) + 1) >> 1) + indent; 1462 } 1463 else { 1464 indent = (srcx << gp3_src_pix_shift); 1465 srcoffset = (indent & ~3L); 1466 indent &= 3; 1467 ch3_offset = indent; 1468 1469 temp = (width << gp3_src_pix_shift) + indent; 1470 } 1471 } 1472 1473 total_dwords = (temp + 3) >> 2; 1474 size_dwords = (total_dwords << 2) + 8; 1475 dword_count = (temp >> 2); 1476 byte_count = (temp & 3); 1477 1478 base = ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000)) | 1479 (gp3_base_register & ~GP3_BASE_OFFSET_DSTMASK); 1480 1481 /* SET APPROPRIATE ENABLES */ 1482 1483 gp3_cmd_header |= GP3_BLT_HDR_DST_OFF_ENABLE | 1484 GP3_BLT_HDR_WIDHI_ENABLE | 1485 GP3_BLT_HDR_CH3_STR_ENABLE | 1486 GP3_BLT_HDR_CH3_OFF_ENABLE | 1487 GP3_BLT_HDR_CH3_WIDHI_ENABLE | 1488 GP3_BLT_HDR_BASE_OFFSET_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE; 1489 1490 WRITE_COMMAND32(GP3_BLT_DST_OFFSET, 1491 (dstoffset & 0x3FFFFF) | gp3_pat_origin); 1492 WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, ch3_offset); 1493 WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, size); 1494 WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, ch3_size); 1495 WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base); 1496 WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, GP3_CH3_C3EN | 1497 GP3_CH3_REPLACE_SOURCE | GP3_CH3_HST_SRC_ENABLE | 1498 gp3_src_format | ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT) 1499 << 20)); 1500 WRITE_COMMAND32(GP3_BLT_MODE, gp3_blt_mode); 1501 1502 /* START THE BLT */ 1503 1504 WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header); 1505 WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); 1506 gp3_cmd_current = gp3_cmd_next; 1507 1508 if (((total_dwords << 2) * height) <= GP3_BLT_1PASS_SIZE && 1509 (gp3_cmd_bottom - gp3_cmd_current) > (GP3_BLT_1PASS_SIZE + 72)) { 1510 /* UPDATE THE COMMAND POINTER */ 1511 1512 cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current; 1513 1514 /* CHECK IF A WRAP WILL BE NEEDED */ 1515 1516 gp3_cmd_next = gp3_cmd_current + ((total_dwords << 2) * height) + 8; 1517 1518 if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) { 1519 gp3_cmd_next = gp3_cmd_top; 1520 1521 GP3_WAIT_WRAP(temp); 1522 WRITE_COMMAND32(0, GP3_DATA_LOAD_HDR_TYPE | 1523 GP3_DATA_LOAD_HDR_WRAP | GP3_DATA_LOAD_HDR_ENABLE); 1524 } 1525 else { 1526 GP3_WAIT_PRIMITIVE(temp); 1527 WRITE_COMMAND32(0, 1528 GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_ENABLE); 1529 } 1530 1531 /* WRITE DWORD COUNT */ 1532 1533 WRITE_COMMAND32(4, GP3_CH3_HOST_SOURCE_TYPE | (total_dwords * height)); 1534 1535 while (height--) { 1536 /* WRITE DATA */ 1537 1538 WRITE_COMMAND_STRING32(8, data, srcoffset, dword_count); 1539 WRITE_COMMAND_STRING8(8 + (dword_count << 2), data, 1540 srcoffset + (dword_count << 2), byte_count); 1541 1542 srcoffset += pitch; 1543 cim_cmd_ptr += total_dwords << 2; 1544 } 1545 1546 WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); 1547 gp3_cmd_current = gp3_cmd_next; 1548 } 1549 else { 1550 /* WRITE DATA LINE BY LINE 1551 * Each line will be created as a separate command buffer entry to 1552 * allow line-by-line wrapping and to allow simultaneous rendering 1553 * by the HW. 1554 */ 1555 1556 while (height--) { 1557 /* UPDATE THE COMMAND POINTER 1558 * The WRITE_COMMANDXX macros use a pointer to the current buffer 1559 * space. This is created by adding gp3_cmd_current to the base 1560 * pointer. 1561 */ 1562 1563 cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current; 1564 1565 /* CHECK IF A WRAP WILL BE NEEDED */ 1566 1567 gp3_cmd_next = gp3_cmd_current + size_dwords; 1568 if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) { 1569 gp3_cmd_next = gp3_cmd_top; 1570 1571 /* WAIT FOR HARDWARE */ 1572 1573 GP3_WAIT_WRAP(temp); 1574 WRITE_COMMAND32(0, GP3_DATA_LOAD_HDR_TYPE | 1575 GP3_DATA_LOAD_HDR_WRAP | 1576 GP3_DATA_LOAD_HDR_ENABLE); 1577 } 1578 else { 1579 /* WAIT FOR AVAILABLE SPACE */ 1580 1581 GP3_WAIT_PRIMITIVE(temp); 1582 WRITE_COMMAND32(0, GP3_DATA_LOAD_HDR_TYPE | 1583 GP3_DATA_LOAD_HDR_ENABLE); 1584 } 1585 1586 /* WRITE DWORD COUNT */ 1587 1588 WRITE_COMMAND32(4, GP3_CH3_HOST_SOURCE_TYPE | total_dwords); 1589 1590 /* WRITE DATA */ 1591 1592 WRITE_COMMAND_STRING32(8, data, srcoffset, dword_count); 1593 WRITE_COMMAND_STRING8(8 + (dword_count << 2), data, 1594 srcoffset + (dword_count << 2), byte_count); 1595 1596 /* UPDATE POINTERS */ 1597 1598 srcoffset += pitch; 1599 WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); 1600 gp3_cmd_current = gp3_cmd_next; 1601 } 1602 } 1603 } 1604 1605 /*--------------------------------------------------------------------------- 1606 * gp_custom_convert_blt 1607 * 1608 * This routine is identical to gp_color_convert_blt, except that the macro 1609 * to write data to the frame buffer has been replaced with a new macro. This 1610 * allows a user to implement custom behavior when sending data, such as 1611 * manually converting 24BPP to 32BPP, converting 2BPP to 4BPP or 1612 * premultiplying alpha data. 1613 *-------------------------------------------------------------------------*/ 1614 1615 void 1616 gp_custom_convert_blt(unsigned long dstoffset, unsigned long srcx, 1617 unsigned long width, unsigned long height, 1618 unsigned char *data, long pitch) 1619 { 1620 unsigned long indent, temp; 1621 unsigned long total_dwords, size_dwords; 1622 unsigned long dword_count, byte_count; 1623 unsigned long size = ((width << 16) | height); 1624 unsigned long ch3_offset, srcoffset; 1625 unsigned long ch3_size, base; 1626 1627 /* ASSUME BITMAPS ARE DWORD ALIGNED */ 1628 /* We will offset into the source data in DWORD increments. We */ 1629 /* set the source index to the remaining byte offset and */ 1630 /* increment the size of each line to account for the dont-care */ 1631 /* pixel(s). For 4BPP source data, we also set the appropriate */ 1632 /* nibble index. */ 1633 1634 /* CALCULATE THE SIZE OF ONE LINE */ 1635 1636 if ((gp3_src_format & GP3_CH3_SRC_MASK) == GP3_CH3_SRC_24BPP_PACKED) { 1637 /* HANDLE 24BPP 1638 * Note that we do not do anything to guarantee that the source data 1639 * is DWORD aligned. The logic here is that the source data will be 1640 * cacheable, in which case Geode LX will not lose any clocks for 1641 * unaligned moves. Also note that the channel 3 width is programmed 1642 * as the number of dwords, while the normal width is programmed as 1643 * the number of pixels. 1644 */ 1645 1646 srcoffset = srcx * 3; 1647 ch3_offset = 0; 1648 temp = width * 3; 1649 ch3_size = (((temp + 3) >> 2) << 16) | height; 1650 } 1651 else { 1652 ch3_size = size; 1653 1654 if (gp3_src_pix_shift == 3) { 1655 /* CALCULATE INDENT AND SOURCE OFFSET */ 1656 1657 indent = (srcx >> 1); 1658 srcoffset = (indent & ~3L); 1659 indent &= 3; 1660 ch3_offset = indent | ((srcx & 1) << 25); 1661 1662 temp = ((width + (srcx & 1) + 1) >> 1) + indent; 1663 } 1664 else { 1665 indent = (srcx << gp3_src_pix_shift); 1666 srcoffset = (indent & ~3L); 1667 indent &= 3; 1668 ch3_offset = indent; 1669 1670 temp = (width << gp3_src_pix_shift) + indent; 1671 } 1672 } 1673 1674 total_dwords = (temp + 3) >> 2; 1675 size_dwords = (total_dwords << 2) + 8; 1676 dword_count = (temp >> 2); 1677 byte_count = (temp & 3); 1678 1679 base = ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000)) | 1680 (gp3_base_register & ~GP3_BASE_OFFSET_DSTMASK); 1681 1682 /* SET APPROPRIATE ENABLES */ 1683 1684 gp3_cmd_header |= GP3_BLT_HDR_DST_OFF_ENABLE | 1685 GP3_BLT_HDR_WIDHI_ENABLE | 1686 GP3_BLT_HDR_CH3_STR_ENABLE | 1687 GP3_BLT_HDR_CH3_OFF_ENABLE | 1688 GP3_BLT_HDR_CH3_WIDHI_ENABLE | 1689 GP3_BLT_HDR_BASE_OFFSET_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE; 1690 1691 WRITE_COMMAND32(GP3_BLT_DST_OFFSET, 1692 (dstoffset & 0x3FFFFF) | gp3_pat_origin); 1693 WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, ch3_offset); 1694 WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, size); 1695 WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, ch3_size); 1696 WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base); 1697 WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, GP3_CH3_C3EN | 1698 GP3_CH3_REPLACE_SOURCE | GP3_CH3_HST_SRC_ENABLE | 1699 gp3_src_format | ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT) 1700 << 20)); 1701 WRITE_COMMAND32(GP3_BLT_MODE, gp3_blt_mode); 1702 1703 /* START THE BLT */ 1704 1705 WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header); 1706 WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); 1707 gp3_cmd_current = gp3_cmd_next; 1708 1709 if (((total_dwords << 2) * height) <= GP3_BLT_1PASS_SIZE && 1710 (gp3_cmd_bottom - gp3_cmd_current) > (GP3_BLT_1PASS_SIZE + 72)) { 1711 /* UPDATE THE COMMAND POINTER */ 1712 1713 cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current; 1714 1715 /* CHECK IF A WRAP WILL BE NEEDED */ 1716 1717 gp3_cmd_next = gp3_cmd_current + ((total_dwords << 2) * height) + 8; 1718 1719 if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) { 1720 gp3_cmd_next = gp3_cmd_top; 1721 1722 GP3_WAIT_WRAP(temp); 1723 WRITE_COMMAND32(0, 1724 GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP | 1725 GP3_DATA_LOAD_HDR_ENABLE); 1726 } 1727 else { 1728 GP3_WAIT_PRIMITIVE(temp); 1729 WRITE_COMMAND32(0, 1730 GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_ENABLE); 1731 } 1732 1733 /* WRITE DWORD COUNT */ 1734 1735 WRITE_COMMAND32(4, GP3_CH3_HOST_SOURCE_TYPE | (total_dwords * height)); 1736 1737 while (height--) { 1738 /* WRITE DATA */ 1739 1740 WRITE_CUSTOM_COMMAND_STRING32(8, data, srcoffset, dword_count); 1741 WRITE_CUSTOM_COMMAND_STRING8(8 + (dword_count << 2), data, 1742 srcoffset + (dword_count << 2), 1743 byte_count); 1744 1745 srcoffset += pitch; 1746 cim_cmd_ptr += total_dwords << 2; 1747 } 1748 1749 WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); 1750 gp3_cmd_current = gp3_cmd_next; 1751 } 1752 else { 1753 /* WRITE DATA LINE BY LINE 1754 * Each line will be created as a separate command buffer entry to 1755 * allow line-by-line wrapping and to allow simultaneous rendering 1756 * by the HW. 1757 */ 1758 1759 while (height--) { 1760 /* UPDATE THE COMMAND POINTER 1761 * The WRITE_COMMANDXX macros use a pointer to the current buffer 1762 * space. This is created by adding gp3_cmd_current to the base 1763 * pointer. 1764 */ 1765 1766 cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current; 1767 1768 /* CHECK IF A WRAP WILL BE NEEDED */ 1769 1770 gp3_cmd_next = gp3_cmd_current + size_dwords; 1771 if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) { 1772 gp3_cmd_next = gp3_cmd_top; 1773 1774 /* WAIT FOR HARDWARE */ 1775 1776 GP3_WAIT_WRAP(temp); 1777 WRITE_COMMAND32(0, 1778 GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP 1779 | GP3_DATA_LOAD_HDR_ENABLE); 1780 } 1781 else { 1782 /* WAIT FOR AVAILABLE SPACE */ 1783 1784 GP3_WAIT_PRIMITIVE(temp); 1785 WRITE_COMMAND32(0, 1786 GP3_DATA_LOAD_HDR_TYPE | 1787 GP3_DATA_LOAD_HDR_ENABLE); 1788 } 1789 1790 /* WRITE DWORD COUNT */ 1791 1792 WRITE_COMMAND32(4, GP3_CH3_HOST_SOURCE_TYPE | total_dwords); 1793 1794 /* WRITE DATA */ 1795 1796 WRITE_CUSTOM_COMMAND_STRING32(8, data, srcoffset, dword_count); 1797 WRITE_CUSTOM_COMMAND_STRING8(8 + (dword_count << 2), data, 1798 srcoffset + (dword_count << 2), 1799 byte_count); 1800 1801 /* UPDATE POINTERS */ 1802 1803 srcoffset += pitch; 1804 WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); 1805 gp3_cmd_current = gp3_cmd_next; 1806 } 1807 } 1808 } 1809 1810 /*--------------------------------------------------------------------------- 1811 * gp_rotate_blt 1812 * 1813 * This routine is called to rotate a rectangular area of video memory. The 1814 * data may be color converted during the rotation. 'Degrees' must be a 1815 * multiple of 90 and indicates a clockwise rotation. Width and height 1816 * refer to the width and the height of the source. The output 1817 * destinations will be equal to the rotated dimensions. 1818 *-------------------------------------------------------------------------*/ 1819 1820 void 1821 gp_rotate_blt(unsigned long dstoffset, unsigned long srcoffset, 1822 unsigned long width, unsigned long height, int degrees) 1823 { 1824 unsigned long sizein, sizeout; 1825 unsigned long ch3_flags; 1826 unsigned long base; 1827 1828 base = ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000)) | 1829 ((gp3_fb_base << 4) + ((srcoffset & 0xFFC00000) >> 20)) | 1830 (gp3_base_register & GP3_BASE_OFFSET_SRCMASK); 1831 1832 srcoffset &= 0x3FFFFF; 1833 dstoffset &= 0x3FFFFF; 1834 1835 /* SET ROTATION PARAMETERS */ 1836 1837 switch (degrees) { 1838 case 90: 1839 srcoffset += (height - 1) * gp3_src_stride; 1840 sizein = ((width << 16) | height); 1841 sizeout = ((height << 16) | width); 1842 ch3_flags = GP3_CH3_C3EN | GP3_CH3_REPLACE_SOURCE | 1843 GP3_CH3_ROTATE_ENABLE | GP3_CH3_NEG_YDIR; 1844 break; 1845 1846 case 180: 1847 srcoffset += (height - 1) * gp3_src_stride; 1848 srcoffset += (width << gp3_src_pix_shift) - 1; 1849 sizein = sizeout = ((width << 16) | height); 1850 ch3_flags = GP3_CH3_C3EN | GP3_CH3_REPLACE_SOURCE | 1851 GP3_CH3_NEG_YDIR | GP3_CH3_NEG_XDIR; 1852 break; 1853 1854 case 270: 1855 srcoffset += (width << gp3_src_pix_shift) - 1; 1856 sizein = ((width << 16) | height); 1857 sizeout = ((height << 16) | width); 1858 ch3_flags = GP3_CH3_C3EN | GP3_CH3_REPLACE_SOURCE | 1859 GP3_CH3_ROTATE_ENABLE | GP3_CH3_NEG_XDIR; 1860 break; 1861 1862 default: 1863 sizein = sizeout = ((width << 16) | height); 1864 ch3_flags = GP3_CH3_C3EN | GP3_CH3_REPLACE_SOURCE; 1865 break; 1866 } 1867 1868 /* SET APPROPRIATE ENABLES */ 1869 /* We override the raster mode setting with a source */ 1870 /* copy ROP. */ 1871 1872 gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE | 1873 GP3_BLT_HDR_DST_OFF_ENABLE | 1874 GP3_BLT_HDR_WIDHI_ENABLE | 1875 GP3_BLT_HDR_CH3_OFF_ENABLE | 1876 GP3_BLT_HDR_CH3_STR_ENABLE | 1877 GP3_BLT_HDR_CH3_WIDHI_ENABLE | 1878 GP3_BLT_HDR_BASE_OFFSET_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE; 1879 1880 /* WRITE ALL BLT REGISTERS */ 1881 1882 WRITE_COMMAND32(GP3_BLT_RASTER_MODE, gp3_bpp | 0xCC); 1883 WRITE_COMMAND32(GP3_BLT_DST_OFFSET, dstoffset); 1884 WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, sizeout); 1885 WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, sizein); 1886 WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, srcoffset); 1887 WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, ch3_flags | gp3_src_format | 1888 ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT) << 20) | 1889 ((gp3_blt_flags & CIMGP_ENABLE_PREFETCH) << 17) | 1890 gp3_src_stride); 1891 WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base); 1892 1893 /* START THE BLT */ 1894 1895 WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header); 1896 WRITE_COMMAND32(GP3_BLT_MODE, gp3_blt_mode); 1897 WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); 1898 gp3_cmd_current = gp3_cmd_next; 1899 } 1900 1901 /*--------------------------------------------------------------------------- 1902 * gp_mono_bitmap_to_screen_blt 1903 * 1904 * This routine expands and BLTs a monchrome bitmap that is stored in system 1905 * memory into the framebuffer. 'data' points to an array of monochrome data. 1906 * 'stride' indicates the pitch between successive lines of monochrome data. 1907 * 'srcx' indicates the x coordinate within each line of blend data 1908 * corresponding to the first pixel. A y coordinate for the source is 1909 * deliberately omitted to avoid extra calculation for simple cases that have 1910 * no y index. The calling program must adjust the data pointer accordingly. 1911 *-------------------------------------------------------------------------*/ 1912 1913 void 1914 gp_mono_bitmap_to_screen_blt(unsigned long dstoffset, unsigned long srcx, 1915 unsigned long width, unsigned long height, 1916 unsigned char *data, long stride) 1917 { 1918 unsigned long indent, temp; 1919 unsigned long total_dwords, size_dwords; 1920 unsigned long dword_count, byte_count; 1921 unsigned long size = ((width << 16) | height); 1922 unsigned long srcoffset, src_value; 1923 1924 /* ASSUME BITMAPS ARE DWORD ALIGNED */ 1925 /* We will offset into the source data in DWORD increments. We */ 1926 /* set the source index to the remaining byte offset and */ 1927 /* increment the size of each line to account for the dont-care */ 1928 /* pixel(s). */ 1929 1930 indent = (srcx >> 3); 1931 srcoffset = (indent & ~3L); 1932 indent &= 3; 1933 src_value = (indent | ((srcx & 7) << 26)); 1934 1935 /* PROGRAM THE NORMAL SOURCE CHANNEL REGISTERS */ 1936 /* We assume that a color pattern is being ROPed with source */ 1937 /* data if the pattern type is color and the preserve pattern */ 1938 /* was set. */ 1939 1940 gp3_cmd_header |= GP3_BLT_HDR_SRC_OFF_ENABLE | 1941 GP3_BLT_HDR_DST_OFF_ENABLE | 1942 GP3_BLT_HDR_WIDHI_ENABLE | 1943 GP3_BLT_HDR_CH3_STR_ENABLE | 1944 GP3_BLT_HDR_BASE_OFFSET_ENABLE | 1945 GP3_BLT_HDR_RASTER_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE; 1946 1947 if (gp3_ch3_pat) { 1948 gp3_cmd_header |= 1949 GP3_BLT_HDR_CH3_OFF_ENABLE | GP3_BLT_HDR_CH3_WIDHI_ENABLE; 1950 1951 WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, gp3_pat_origin); 1952 WRITE_COMMAND32(GP3_BLT_DST_OFFSET, (dstoffset & 0x3FFFFF)); 1953 WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, gp3_pat_format); 1954 WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, size); 1955 } 1956 else { 1957 WRITE_COMMAND32(GP3_BLT_DST_OFFSET, 1958 ((dstoffset & 0x3FFFFF) | gp3_pat_origin)); 1959 WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, 0); 1960 } 1961 if (gp3_blt_flags & CIMGP_BLTFLAGS_INVERTMONO) { 1962 WRITE_COMMAND32(GP3_BLT_RASTER_MODE, 1963 gp3_raster_mode | GP3_RM_SOURCE_INVERT); 1964 } 1965 else { 1966 WRITE_COMMAND32(GP3_BLT_RASTER_MODE, 1967 gp3_raster_mode & ~GP3_RM_SOURCE_INVERT); 1968 } 1969 WRITE_COMMAND32(GP3_BLT_SRC_OFFSET, src_value); 1970 WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, size); 1971 WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, 1972 ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000))); 1973 WRITE_COMMAND32(GP3_BLT_MODE, 1974 gp3_blt_mode | GP3_BM_SRC_HOST | GP3_BM_SRC_MONO); 1975 1976 /* START THE BLT */ 1977 1978 WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header); 1979 WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); 1980 gp3_cmd_current = gp3_cmd_next; 1981 1982 /* CALCULATE THE SIZE OF ONE LINE */ 1983 1984 size = ((width + (srcx & 7) + 7) >> 3) + indent; 1985 total_dwords = (size + 3) >> 2; 1986 size_dwords = (total_dwords << 2) + 8; 1987 dword_count = (size >> 2); 1988 byte_count = (size & 3); 1989 1990 /* CHECK FOR SMALL BLT CASE */ 1991 /* If the total amount of monochrome data is less than 50K and we have */ 1992 /* room in the command buffer, we will do all data writes in a single */ 1993 /* data packet. */ 1994 1995 if (((total_dwords << 2) * height) <= GP3_BLT_1PASS_SIZE && 1996 (gp3_cmd_bottom - gp3_cmd_current) > (GP3_BLT_1PASS_SIZE + 72)) { 1997 /* UPDATE THE COMMAND POINTER */ 1998 1999 cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current; 2000 2001 /* CHECK IF A WRAP WILL BE NEEDED */ 2002 2003 gp3_cmd_next = gp3_cmd_current + ((total_dwords << 2) * height) + 8; 2004 2005 if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) { 2006 gp3_cmd_next = gp3_cmd_top; 2007 2008 GP3_WAIT_WRAP(temp); 2009 WRITE_COMMAND32(0, 2010 GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP | 2011 GP3_DATA_LOAD_HDR_ENABLE); 2012 } 2013 else { 2014 GP3_WAIT_PRIMITIVE(temp); 2015 WRITE_COMMAND32(0, 2016 GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_ENABLE); 2017 } 2018 2019 /* WRITE DWORD COUNT */ 2020 2021 WRITE_COMMAND32(4, GP3_HOST_SOURCE_TYPE | (total_dwords * height)); 2022 2023 while (height--) { 2024 /* WRITE DATA */ 2025 2026 WRITE_COMMAND_STRING32(8, data, srcoffset, dword_count); 2027 WRITE_COMMAND_STRING8(8 + (dword_count << 2), data, 2028 srcoffset + (dword_count << 2), byte_count); 2029 2030 srcoffset += stride; 2031 cim_cmd_ptr += total_dwords << 2; 2032 } 2033 2034 WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); 2035 gp3_cmd_current = gp3_cmd_next; 2036 } 2037 else { 2038 /* WRITE DATA LINE BY LINE 2039 * Each line will be created as a separate command buffer entry to 2040 * allow line-by-line wrapping and to allow simultaneous rendering 2041 * by the HW. 2042 */ 2043 2044 while (height--) { 2045 /* UPDATE THE COMMAND POINTER 2046 * The WRITE_COMMANDXX macros use a pointer to the current buffer 2047 * space. This is created by adding gp3_cmd_current to the base 2048 * pointer. 2049 */ 2050 2051 cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current; 2052 2053 /* CHECK IF A WRAP WILL BE NEEDED */ 2054 2055 gp3_cmd_next = gp3_cmd_current + size_dwords; 2056 if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) { 2057 gp3_cmd_next = gp3_cmd_top; 2058 2059 /* WAIT FOR HARDWARE */ 2060 2061 GP3_WAIT_WRAP(temp); 2062 WRITE_COMMAND32(0, 2063 GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP 2064 | GP3_DATA_LOAD_HDR_ENABLE); 2065 } 2066 else { 2067 /* WAIT FOR AVAILABLE SPACE */ 2068 2069 GP3_WAIT_PRIMITIVE(temp); 2070 WRITE_COMMAND32(0, 2071 GP3_DATA_LOAD_HDR_TYPE | 2072 GP3_DATA_LOAD_HDR_ENABLE); 2073 } 2074 2075 /* WRITE DWORD COUNT */ 2076 2077 WRITE_COMMAND32(4, GP3_HOST_SOURCE_TYPE | total_dwords); 2078 2079 /* WRITE DATA */ 2080 2081 WRITE_COMMAND_STRING32(8, data, srcoffset, dword_count); 2082 WRITE_COMMAND_STRING8(8 + (dword_count << 2), data, 2083 srcoffset + (dword_count << 2), byte_count); 2084 2085 /* UPDATE POINTERS */ 2086 2087 srcoffset += stride; 2088 WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); 2089 gp3_cmd_current = gp3_cmd_next; 2090 } 2091 } 2092 } 2093 2094 /*--------------------------------------------------------------------------- 2095 * gp_text_blt 2096 * 2097 * This routine expands and BLTs byte-packed monochrome data to the screen. 2098 * There is assumed to be no x clipping involved in the BLT. 2099 *-------------------------------------------------------------------------*/ 2100 2101 void 2102 gp_text_blt(unsigned long dstoffset, unsigned long width, 2103 unsigned long height, unsigned char *data) 2104 { 2105 unsigned long temp, dwords_total; 2106 unsigned long dword_count, byte_count; 2107 unsigned long size = ((width << 16) | height); 2108 unsigned long srcoffset = 0; 2109 2110 /* PROGRAM THE NORMAL SOURCE CHANNEL REGISTERS */ 2111 /* We assume that a color pattern is being ROPed with source */ 2112 /* data if the pattern type is color and the preserve pattern */ 2113 /* was set. */ 2114 2115 gp3_cmd_header |= GP3_BLT_HDR_SRC_OFF_ENABLE | 2116 GP3_BLT_HDR_DST_OFF_ENABLE | 2117 GP3_BLT_HDR_WIDHI_ENABLE | 2118 GP3_BLT_HDR_CH3_STR_ENABLE | 2119 GP3_BLT_HDR_BASE_OFFSET_ENABLE | 2120 GP3_BLT_HDR_RASTER_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE; 2121 2122 if (gp3_ch3_pat) { 2123 gp3_cmd_header |= 2124 GP3_BLT_HDR_CH3_OFF_ENABLE | GP3_BLT_HDR_CH3_WIDHI_ENABLE; 2125 2126 WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, gp3_pat_origin); 2127 WRITE_COMMAND32(GP3_BLT_DST_OFFSET, (dstoffset & 0x3FFFFF)); 2128 WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, gp3_pat_format); 2129 WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, size); 2130 } 2131 else { 2132 WRITE_COMMAND32(GP3_BLT_DST_OFFSET, 2133 ((dstoffset & 0x3FFFFF) | gp3_pat_origin)); 2134 WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, 0); 2135 } 2136 if (gp3_blt_flags & CIMGP_BLTFLAGS_INVERTMONO) { 2137 WRITE_COMMAND32(GP3_BLT_RASTER_MODE, 2138 gp3_raster_mode | GP3_RM_SOURCE_INVERT); 2139 } 2140 else { 2141 WRITE_COMMAND32(GP3_BLT_RASTER_MODE, 2142 gp3_raster_mode & ~GP3_RM_SOURCE_INVERT); 2143 } 2144 2145 WRITE_COMMAND32(GP3_BLT_SRC_OFFSET, 0); 2146 WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, size); 2147 WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, 2148 ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000))); 2149 WRITE_COMMAND32(GP3_BLT_MODE, 2150 gp3_blt_mode | GP3_BM_SRC_HOST | GP3_BM_SRC_BP_MONO); 2151 2152 /* START THE BLT */ 2153 2154 WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header); 2155 WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); 2156 gp3_cmd_current = gp3_cmd_next; 2157 2158 /* CALCULATE THE TOTAL NUMBER OF BYTES */ 2159 2160 size = ((width + 7) >> 3) * height; 2161 2162 /* WRITE ALL DATA IN CHUNKS */ 2163 2164 do { 2165 /* UPDATE THE COMMAND POINTER */ 2166 2167 cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current; 2168 2169 if (size > 8192) { 2170 dword_count = 2048; 2171 byte_count = 0; 2172 dwords_total = 2048; 2173 size -= 8192; 2174 } 2175 else { 2176 dword_count = (size >> 2); 2177 byte_count = (size & 3); 2178 dwords_total = (size + 3) >> 2; 2179 size = 0; 2180 } 2181 gp3_cmd_next = gp3_cmd_current + (dwords_total << 2) + 8; 2182 2183 /* CHECK IF A WRAP WILL BE NEEDED */ 2184 2185 if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) { 2186 gp3_cmd_next = gp3_cmd_top; 2187 2188 /* WAIT FOR HARDWARE */ 2189 2190 GP3_WAIT_WRAP(temp); 2191 WRITE_COMMAND32(0, 2192 GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP | 2193 GP3_DATA_LOAD_HDR_ENABLE); 2194 } 2195 else { 2196 /* WAIT FOR AVAILABLE SPACE */ 2197 2198 GP3_WAIT_PRIMITIVE(temp); 2199 WRITE_COMMAND32(0, 2200 GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_ENABLE); 2201 } 2202 2203 /* WRITE DWORD COUNT */ 2204 2205 WRITE_COMMAND32(4, GP3_HOST_SOURCE_TYPE | dwords_total); 2206 2207 /* WRITE DATA */ 2208 2209 WRITE_COMMAND_STRING32(8, data, srcoffset, dword_count); 2210 WRITE_COMMAND_STRING8(8 + (dword_count << 2), data, 2211 srcoffset + (dword_count << 2), byte_count); 2212 2213 WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); 2214 gp3_cmd_current = gp3_cmd_next; 2215 2216 /* UPDATE THE SOURCE OFFSET */ 2217 /* We add a constant value because the code will loop only if the */ 2218 /* data exceeds 8192 bytes. */ 2219 2220 srcoffset += 8192; 2221 2222 } while (size); 2223 } 2224 2225 /*--------------------------------------------------------------------------- 2226 * gp_mono_expand_blt 2227 * 2228 * This routine expands monochrome data that is stored in video memory into 2229 * the current BPP. The source and destination regions are assumed not to 2230 * overlap. The pitch of the source data is specified in gp_set_strides. 2231 * 'srcy' is deliberately omitted to prevent extra calculations for simple 2232 * applications that have no source indexes. 2233 *-------------------------------------------------------------------------*/ 2234 2235 void 2236 gp_mono_expand_blt(unsigned long dstoffset, unsigned long srcoffset, 2237 unsigned long srcx, unsigned long width, 2238 unsigned long height, int byte_packed) 2239 { 2240 unsigned long base; 2241 unsigned long blt_mode; 2242 unsigned long size = ((width << 16) | height); 2243 2244 /* ADJUST SOURCE OFFSET */ 2245 2246 srcoffset += (srcx >> 3); 2247 srcx &= 7; 2248 2249 /* CALCULATE BASE OFFSET REGISTER */ 2250 2251 base = ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000)) | 2252 ((gp3_fb_base << 14) + ((srcoffset & 0xFFC00000) >> 10)) | 2253 (gp3_base_register & GP3_BASE_OFFSET_CH3MASK); 2254 2255 /* SET THE SOURCE TYPE */ 2256 2257 if (byte_packed) 2258 blt_mode = gp3_blt_mode | GP3_BM_SRC_FB | GP3_BM_SRC_BP_MONO; 2259 else 2260 blt_mode = gp3_blt_mode | GP3_BM_SRC_FB | GP3_BM_SRC_MONO; 2261 2262 /* SET HEADER ENABLES */ 2263 2264 gp3_cmd_header |= GP3_BLT_HDR_SRC_OFF_ENABLE | 2265 GP3_BLT_HDR_DST_OFF_ENABLE | 2266 GP3_BLT_HDR_WIDHI_ENABLE | 2267 GP3_BLT_HDR_CH3_STR_ENABLE | 2268 GP3_BLT_HDR_BASE_OFFSET_ENABLE | 2269 GP3_BLT_HDR_RASTER_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE; 2270 2271 /* ENABLE COLOR PATTERN IF APPLICABLE */ 2272 2273 if (gp3_ch3_pat) { 2274 gp3_cmd_header |= 2275 GP3_BLT_HDR_CH3_OFF_ENABLE | GP3_BLT_HDR_CH3_WIDHI_ENABLE; 2276 2277 WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, gp3_pat_origin); 2278 WRITE_COMMAND32(GP3_BLT_DST_OFFSET, (dstoffset & 0x3FFFFF)); 2279 WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, gp3_pat_format); 2280 WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, size); 2281 } 2282 else { 2283 WRITE_COMMAND32(GP3_BLT_DST_OFFSET, 2284 ((dstoffset & 0x3FFFFF) | gp3_pat_origin)); 2285 WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, 0); 2286 } 2287 if (gp3_blt_flags & CIMGP_BLTFLAGS_INVERTMONO) { 2288 WRITE_COMMAND32(GP3_BLT_RASTER_MODE, 2289 gp3_raster_mode | GP3_RM_SOURCE_INVERT); 2290 } 2291 else { 2292 WRITE_COMMAND32(GP3_BLT_RASTER_MODE, 2293 gp3_raster_mode & ~GP3_RM_SOURCE_INVERT); 2294 } 2295 2296 WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base); 2297 WRITE_COMMAND32(GP3_BLT_SRC_OFFSET, (srcoffset & 0x3FFFFF) | (srcx << 26)); 2298 WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, size); 2299 2300 /* WORKAROUND FOR SIBZ #3744 2301 * Under extremely rare conditions, very narrow byte-packed mono BLTs 2302 * can hang the GP. Even under the rare case, the bad condition will 2303 * only happen once every 16 lines. The workaround is to break the 2304 * offending BLT into a series of safer BLTs. This method is preferred 2305 * over a two-pass approach because it does not require saving and 2306 * restoring any GP state, such as the ROP or mono colors. 2307 */ 2308 2309 if ((gp3_blt_mode & GP3_BM_DST_REQ) && byte_packed && (gp3_pix_shift < 2) 2310 && (width < 5) && ((srcoffset & 0x1F) == 0x1F) 2311 && ((srcx + width) > 8)) { 2312 unsigned long dstoff1, size1, org1; 2313 unsigned long dstoff2, size2, org2; 2314 unsigned long tempheight; 2315 2316 size1 = ((8 - srcx) << 16) | 1; 2317 size2 = ((width + srcx - 8) << 16) | 1; 2318 org1 = gp3_pat_origin; 2319 org2 = (org1 & 0xE0000000) | ((org1 + ((8 - srcx) << 26)) & 0x1C000000); 2320 dstoff1 = dstoffset & 0x3FFFFF; 2321 dstoff2 = (dstoff1 + 8 - srcx) << gp3_pix_shift; 2322 2323 while (height) { 2324 /* DIVIDE THE FIRST LINE INTO TWO SINGLE LINE BLTS */ 2325 2326 WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, size1); 2327 WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, size1); 2328 WRITE_COMMAND32(GP3_BLT_SRC_OFFSET, 2329 (srcoffset & 0x3FFFFF) | (srcx << 26)); 2330 WRITE_COMMAND32(GP3_BLT_DST_OFFSET, dstoff1 | org1); 2331 WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, org1); 2332 WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header); 2333 WRITE_COMMAND32(GP3_BLT_MODE, blt_mode); 2334 WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); 2335 gp3_cmd_current = gp3_cmd_next; 2336 gp_wait_until_idle(); 2337 2338 gp_declare_blt(gp3_blt_flags); 2339 gp3_cmd_header |= GP3_BLT_HDR_SRC_OFF_ENABLE | 2340 GP3_BLT_HDR_DST_OFF_ENABLE | 2341 GP3_BLT_HDR_WIDHI_ENABLE | 2342 GP3_BLT_HDR_BLT_MODE_ENABLE | 2343 GP3_BLT_HDR_CH3_OFF_ENABLE | GP3_BLT_HDR_CH3_WIDHI_ENABLE; 2344 WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, size2); 2345 WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, size2); 2346 WRITE_COMMAND32(GP3_BLT_SRC_OFFSET, ((srcoffset + 1) & 0x3FFFFF)); 2347 WRITE_COMMAND32(GP3_BLT_DST_OFFSET, dstoff2 | org2); 2348 WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, org2); 2349 WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header); 2350 WRITE_COMMAND32(GP3_BLT_MODE, blt_mode); 2351 WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); 2352 gp3_cmd_current = gp3_cmd_next; 2353 gp_wait_until_idle(); 2354 2355 if (--height) { 2356 org1 += 0x20000000; 2357 org2 += 0x20000000; 2358 dstoff1 += gp3_dst_stride; 2359 dstoff2 += gp3_dst_stride; 2360 srcoffset += 2; 2361 2362 /* THE NEXT 15 LINES ARE NOW 'SAFE' - THEY DO NOT SHOW THE 2363 * PROBLEM */ 2364 2365 tempheight = 15; 2366 if (tempheight > height) 2367 tempheight = height; 2368 2369 gp_declare_blt(gp3_blt_flags); 2370 gp3_cmd_header |= GP3_BLT_HDR_SRC_OFF_ENABLE | 2371 GP3_BLT_HDR_DST_OFF_ENABLE | 2372 GP3_BLT_HDR_WIDHI_ENABLE | 2373 GP3_BLT_HDR_BLT_MODE_ENABLE | 2374 GP3_BLT_HDR_CH3_OFF_ENABLE | GP3_BLT_HDR_CH3_WIDHI_ENABLE; 2375 WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, (width << 16) | tempheight); 2376 WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, (width << 16) | tempheight); 2377 WRITE_COMMAND32(GP3_BLT_SRC_OFFSET, 2378 (srcoffset & 0x3FFFFF) | (srcx << 26)); 2379 WRITE_COMMAND32(GP3_BLT_DST_OFFSET, dstoff1 | org1); 2380 WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, org1); 2381 WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header); 2382 WRITE_COMMAND32(GP3_BLT_MODE, blt_mode); 2383 WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); 2384 gp3_cmd_current = gp3_cmd_next; 2385 gp_wait_until_idle(); 2386 2387 height -= tempheight; 2388 2389 if (height) { 2390 gp_declare_blt(gp3_blt_flags); 2391 gp3_cmd_header |= GP3_BLT_HDR_SRC_OFF_ENABLE | 2392 GP3_BLT_HDR_DST_OFF_ENABLE | 2393 GP3_BLT_HDR_WIDHI_ENABLE | 2394 GP3_BLT_HDR_BLT_MODE_ENABLE | 2395 GP3_BLT_HDR_CH3_OFF_ENABLE | 2396 GP3_BLT_HDR_CH3_WIDHI_ENABLE; 2397 2398 /* ADJUST ORIGIN */ 2399 /* If we get here, we added a full 15 lines which is 2400 * equivalent to subtracting one from the pattern y origin 2401 * (adding 15). */ 2402 2403 org1 -= 0x20000000; 2404 org2 -= 0x20000000; 2405 dstoff1 += (gp3_dst_stride * 15); 2406 dstoff2 += (gp3_dst_stride * 15); 2407 srcoffset += 30; 2408 } 2409 } 2410 } 2411 return; 2412 } 2413 2414 /* START THE BLT */ 2415 2416 WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header); 2417 WRITE_COMMAND32(GP3_BLT_MODE, blt_mode); 2418 WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); 2419 gp3_cmd_current = gp3_cmd_next; 2420 } 2421 2422 /*--------------------------------------------------------------------------- 2423 * gp_antialiased_text 2424 * 2425 * This routine implements alpha blending between a constant source color and 2426 * a destination region. The degree of the blend is controlled by an array 2427 * of 4BPP/8BPP values specified in 'data'. 'stride' indicates the pitch 2428 * between successive lines of blend data. 'srcx' indicates the x 2429 * coordinate within each line of blend data corresponding to the first 2430 * pixel. A y coordinate for the source is deliberately omitted to avoid 2431 * extra calculation for simple cases that have no y index. The calling 2432 * program must adjust the data pointer accordingly. 'fourbpp' selects 2433 * between 4BPP and 8BPP alpha. 2434 *-------------------------------------------------------------------------*/ 2435 2436 void 2437 gp_antialiased_text(unsigned long dstoffset, unsigned long srcx, 2438 unsigned long width, unsigned long height, 2439 unsigned char *data, long stride, int fourbpp) 2440 { 2441 unsigned long indent, temp; 2442 unsigned long total_dwords, size_dwords; 2443 unsigned long dword_count, byte_count; 2444 unsigned long size = ((width << 16) | height); 2445 unsigned long ch3_offset, srcoffset; 2446 unsigned long base, depth_flag; 2447 2448 base = ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000)) | 2449 (gp3_base_register & ~GP3_BASE_OFFSET_DSTMASK); 2450 2451 /* ENABLE ALL RELEVANT REGISTERS */ 2452 /* We override the raster mode register to force the */ 2453 /* correct alpha blend */ 2454 2455 gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE | 2456 GP3_BLT_HDR_DST_OFF_ENABLE | 2457 GP3_BLT_HDR_WIDHI_ENABLE | 2458 GP3_BLT_HDR_CH3_OFF_ENABLE | 2459 GP3_BLT_HDR_CH3_STR_ENABLE | 2460 GP3_BLT_HDR_CH3_WIDHI_ENABLE | 2461 GP3_BLT_HDR_BASE_OFFSET_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE; 2462 2463 /* CALCULATIONS BASED ON ALPHA DEPTH */ 2464 /* Although most antialiased text is 4BPP, the hardware supports */ 2465 /* a full 8BPP. Either case is supported by this routine. */ 2466 2467 if (fourbpp) { 2468 depth_flag = GP3_CH3_SRC_4BPP_ALPHA; 2469 indent = (srcx >> 1); 2470 srcoffset = (indent & ~3L); 2471 indent &= 3; 2472 ch3_offset = indent | ((srcx & 1) << 25); 2473 2474 temp = ((width + (srcx & 1) + 1) >> 1) + indent; 2475 } 2476 else { 2477 depth_flag = GP3_CH3_SRC_8BPP_ALPHA; 2478 indent = srcx; 2479 srcoffset = (indent & ~3L); 2480 indent &= 3; 2481 ch3_offset = indent; 2482 2483 temp = width + indent; 2484 } 2485 2486 total_dwords = (temp + 3) >> 2; 2487 size_dwords = (total_dwords << 2) + 8; 2488 dword_count = (temp >> 2); 2489 byte_count = (temp & 3); 2490 2491 /* SET RASTER MODE REGISTER */ 2492 /* Alpha blending will only apply to RGB when no alpha component is present. */ 2493 /* As 8BPP is not supported for this routine, the only alpha-less mode is */ 2494 /* 5:6:5. */ 2495 2496 if (gp3_bpp == GP3_RM_BPPFMT_565) { 2497 WRITE_COMMAND32(GP3_BLT_RASTER_MODE, 2498 gp3_bpp | 2499 GP3_RM_ALPHA_TO_RGB | 2500 GP3_RM_ALPHA_A_PLUS_BETA_B | 2501 GP3_RM_SELECT_ALPHA_CHAN_3); 2502 } 2503 else { 2504 WRITE_COMMAND32(GP3_BLT_RASTER_MODE, 2505 gp3_bpp | 2506 GP3_RM_ALPHA_ALL | 2507 GP3_RM_ALPHA_A_PLUS_BETA_B | 2508 GP3_RM_SELECT_ALPHA_CHAN_3); 2509 } 2510 2511 /* WRITE ALL REMAINING REGISTERS */ 2512 2513 WRITE_COMMAND32(GP3_BLT_DST_OFFSET, (dstoffset & 0x3FFFFF)); 2514 WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, ch3_offset); 2515 WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, size); 2516 WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, size); 2517 WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base); 2518 WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, GP3_CH3_C3EN | 2519 GP3_CH3_HST_SRC_ENABLE | 2520 depth_flag | ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT) << 2521 20)); 2522 WRITE_COMMAND32(GP3_BLT_MODE, gp3_blt_mode | GP3_BM_DST_REQ); 2523 2524 /* START THE BLT */ 2525 2526 WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header); 2527 WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); 2528 gp3_cmd_current = gp3_cmd_next; 2529 2530 /* WRITE DATA LINE BY LINE 2531 * Each line will be created as a separate command buffer entry to allow 2532 * line-by-line wrapping and to allow simultaneous rendering by the HW. 2533 */ 2534 2535 if (((total_dwords << 2) * height) <= GP3_BLT_1PASS_SIZE && 2536 (gp3_cmd_bottom - gp3_cmd_current) > (GP3_BLT_1PASS_SIZE + 72)) { 2537 /* UPDATE THE COMMAND POINTER */ 2538 2539 cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current; 2540 2541 /* CHECK IF A WRAP WILL BE NEEDED */ 2542 2543 gp3_cmd_next = gp3_cmd_current + ((total_dwords << 2) * height) + 8; 2544 2545 if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) { 2546 gp3_cmd_next = gp3_cmd_top; 2547 2548 GP3_WAIT_WRAP(temp); 2549 WRITE_COMMAND32(0, 2550 GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP | 2551 GP3_DATA_LOAD_HDR_ENABLE); 2552 } 2553 else { 2554 GP3_WAIT_PRIMITIVE(temp); 2555 WRITE_COMMAND32(0, 2556 GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_ENABLE); 2557 } 2558 2559 /* WRITE DWORD COUNT */ 2560 2561 WRITE_COMMAND32(4, GP3_CH3_HOST_SOURCE_TYPE | (total_dwords * height)); 2562 2563 while (height--) { 2564 /* WRITE DATA */ 2565 2566 WRITE_COMMAND_STRING32(8, data, srcoffset, dword_count); 2567 WRITE_COMMAND_STRING8(8 + (dword_count << 2), data, 2568 srcoffset + (dword_count << 2), byte_count); 2569 2570 srcoffset += stride; 2571 cim_cmd_ptr += total_dwords << 2; 2572 } 2573 2574 WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); 2575 gp3_cmd_current = gp3_cmd_next; 2576 } 2577 else { 2578 while (height--) { 2579 /* UPDATE THE COMMAND POINTER 2580 * The WRITE_COMMANDXX macros use a pointer to the current buffer 2581 * space. This is created by adding gp3_cmd_current to the base 2582 * pointer. 2583 */ 2584 2585 cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current; 2586 2587 /* CHECK IF A WRAP WILL BE NEEDED */ 2588 2589 gp3_cmd_next = gp3_cmd_current + size_dwords; 2590 if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) { 2591 gp3_cmd_next = gp3_cmd_top; 2592 2593 /* WAIT FOR HARDWARE */ 2594 2595 GP3_WAIT_WRAP(temp); 2596 WRITE_COMMAND32(0, 2597 GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP 2598 | GP3_DATA_LOAD_HDR_ENABLE); 2599 } 2600 else { 2601 /* WAIT FOR AVAILABLE SPACE */ 2602 2603 GP3_WAIT_PRIMITIVE(temp); 2604 WRITE_COMMAND32(0, 2605 GP3_DATA_LOAD_HDR_TYPE | 2606 GP3_DATA_LOAD_HDR_ENABLE); 2607 } 2608 2609 /* WRITE DWORD COUNT */ 2610 2611 WRITE_COMMAND32(4, GP3_CH3_HOST_SOURCE_TYPE | total_dwords); 2612 2613 /* WRITE DATA */ 2614 2615 WRITE_COMMAND_STRING32(8, data, srcoffset, dword_count); 2616 WRITE_COMMAND_STRING8(8 + (dword_count << 2), data, 2617 srcoffset + (dword_count << 2), byte_count); 2618 2619 /* UPDATE POINTERS */ 2620 2621 srcoffset += stride; 2622 WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); 2623 gp3_cmd_current = gp3_cmd_next; 2624 } 2625 } 2626 } 2627 2628 /*--------------------------------------------------------------------------- 2629 * gp_masked_blt 2630 * 2631 * This routine copies source data to the screen. A monochrome mask is used 2632 * to specify source transparency. 2633 *-------------------------------------------------------------------------*/ 2634 2635 void 2636 gp_masked_blt(unsigned long dstoffset, unsigned long width, 2637 unsigned long height, unsigned long mono_srcx, 2638 unsigned long color_srcx, unsigned char *mono_mask, 2639 unsigned char *color_data, long mono_pitch, long color_pitch) 2640 { 2641 unsigned long indent, temp; 2642 unsigned long total_dwords, size_dwords; 2643 unsigned long dword_count, byte_count; 2644 unsigned long srcoffset, size; 2645 unsigned long i, ch3_offset, base; 2646 unsigned long flags = 0; 2647 2648 if (gp3_blt_flags & CIMGP_BLTFLAGS_INVERTMONO) 2649 flags = GP3_RM_SOURCE_INVERT; 2650 2651 /* MONO CALCULATIONS */ 2652 2653 indent = (mono_srcx >> 3); 2654 srcoffset = (indent & ~3L); 2655 indent &= 3; 2656 2657 size = ((width + (mono_srcx & 7) + 7) >> 3) + indent; 2658 total_dwords = (size + 3) >> 2; 2659 size_dwords = (total_dwords << 2) + 8; 2660 dword_count = (size >> 2); 2661 byte_count = (size & 3); 2662 2663 base = ((gp3_fb_base << 24) + (gp3_scratch_base & 0xFFC00000)) | 2664 (gp3_base_register & ~GP3_BASE_OFFSET_DSTMASK); 2665 2666 gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE | 2667 GP3_BLT_HDR_STRIDE_ENABLE | GP3_BLT_HDR_DST_OFF_ENABLE | 2668 GP3_BLT_HDR_WIDHI_ENABLE | GP3_BLT_HDR_CH3_STR_ENABLE | 2669 GP3_BLT_HDR_CH3_OFF_ENABLE | GP3_BLT_HDR_CH3_WIDHI_ENABLE | 2670 GP3_BLT_HDR_BASE_OFFSET_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE; 2671 2672 WRITE_COMMAND32(GP3_BLT_RASTER_MODE, GP3_RM_BPPFMT_8888 | 0xCC); 2673 WRITE_COMMAND32(GP3_BLT_STRIDE, (total_dwords << 2)); 2674 WRITE_COMMAND32(GP3_BLT_DST_OFFSET, gp3_scratch_base & 0x3FFFFF); 2675 WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, (total_dwords << 16) | height); 2676 WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, (total_dwords << 16) | height); 2677 WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, 0); 2678 WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base); 2679 WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, GP3_CH3_C3EN | 2680 GP3_CH3_REPLACE_SOURCE | GP3_CH3_HST_SRC_ENABLE | 2681 GP3_CH3_SRC_8_8_8_8 | 2682 ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT) << 20)); 2683 WRITE_COMMAND32(GP3_BLT_MODE, 0); 2684 WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header); 2685 2686 /* START THE BLT */ 2687 2688 WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); 2689 gp3_cmd_current = gp3_cmd_next; 2690 2691 for (i = 0; i < height; i++) { 2692 /* UPDATE THE COMMAND POINTER 2693 * The WRITE_COMMANDXX macros use a pointer to the current buffer 2694 * space. This is created by adding gp3_cmd_current to the base 2695 * pointer. 2696 */ 2697 2698 cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current; 2699 2700 /* CHECK IF A WRAP WILL BE NEEDED */ 2701 2702 gp3_cmd_next = gp3_cmd_current + size_dwords; 2703 if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) { 2704 gp3_cmd_next = gp3_cmd_top; 2705 2706 /* WAIT FOR HARDWARE */ 2707 2708 GP3_WAIT_WRAP(temp); 2709 WRITE_COMMAND32(0, 2710 GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP | 2711 GP3_DATA_LOAD_HDR_ENABLE); 2712 } 2713 else { 2714 /* WAIT FOR AVAILABLE SPACE */ 2715 2716 GP3_WAIT_PRIMITIVE(temp); 2717 WRITE_COMMAND32(0, GP3_DATA_LOAD_HDR_TYPE | 2718 GP3_DATA_LOAD_HDR_ENABLE); 2719 } 2720 2721 /* WRITE DWORD COUNT */ 2722 2723 WRITE_COMMAND32(4, GP3_CH3_HOST_SOURCE_TYPE | total_dwords); 2724 2725 /* WRITE DATA */ 2726 2727 WRITE_COMMAND_STRING32(8, mono_mask, srcoffset, dword_count); 2728 WRITE_COMMAND_STRING8(8 + (dword_count << 2), mono_mask, 2729 srcoffset + (dword_count << 2), byte_count); 2730 2731 /* UPDATE POINTERS */ 2732 2733 srcoffset += mono_pitch; 2734 WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); 2735 gp3_cmd_current = gp3_cmd_next; 2736 } 2737 2738 /* SECOND BLT */ 2739 2740 gp_declare_blt(gp3_blt_flags | CIMGP_BLTFLAGS_HAZARD); 2741 2742 base = ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000)) | 2743 ((gp3_fb_base << 14) + (((gp3_scratch_base + 2744 indent) & 0xFFC00000) >> 10)) | 2745 (gp3_base_register & GP3_BASE_OFFSET_CH3MASK); 2746 2747 gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE | 2748 GP3_BLT_HDR_STRIDE_ENABLE | GP3_BLT_HDR_DST_OFF_ENABLE | 2749 GP3_BLT_HDR_SRC_OFF_ENABLE | GP3_BLT_HDR_WIDHI_ENABLE | 2750 GP3_BLT_HDR_CH3_STR_ENABLE | 2751 GP3_BLT_HDR_CH3_WIDHI_ENABLE | 2752 GP3_BLT_HDR_BASE_OFFSET_ENABLE | 2753 GP3_BLT_HDR_CH3_OFF_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE; 2754 2755 /* ENABLE TRANSPARENCY AND PATTERN COPY ROP 2756 * The monochrome data is used as a mask but is otherwise not involved in 2757 * the BLT. The color data is routed through the pattern channel. 2758 */ 2759 2760 WRITE_COMMAND32(GP3_BLT_RASTER_MODE, 2761 gp3_bpp | 0xF0 | GP3_RM_SRC_TRANS | flags); 2762 WRITE_COMMAND32(GP3_BLT_STRIDE, (total_dwords << 18) | gp3_dst_stride); 2763 WRITE_COMMAND32(GP3_BLT_DST_OFFSET, dstoffset & 0x3FFFFF); 2764 WRITE_COMMAND32(GP3_BLT_SRC_OFFSET, 2765 ((gp3_scratch_base + 2766 indent) & 0x3FFFFF) | ((mono_srcx & 7) << 26)); 2767 WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, (width << 16) | height); 2768 WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, (width << 16) | height); 2769 WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base); 2770 2771 /* PROGRAM PARAMETERS FOR COLOR SOURCE DATA */ 2772 /* Data may be color converted along the way. */ 2773 2774 if ((gp3_src_format & GP3_CH3_SRC_MASK) == GP3_CH3_SRC_24BPP_PACKED) { 2775 srcoffset = color_srcx * 3; 2776 ch3_offset = 0; 2777 size = width * 3; 2778 2779 WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, (((size + 3) >> 2) << 16) | height); 2780 } 2781 else if (gp3_src_pix_shift == 3) { 2782 /* CALCULATE INDENT AND SOURCE OFFSET */ 2783 2784 indent = (color_srcx >> 1); 2785 srcoffset = (indent & ~3L); 2786 indent &= 3; 2787 ch3_offset = indent | ((color_srcx & 1) << 25); 2788 2789 size = ((width + (color_srcx & 1) + 1) >> 1) + indent; 2790 } 2791 else { 2792 indent = (color_srcx << gp3_src_pix_shift); 2793 srcoffset = (indent & ~3L); 2794 indent &= 3; 2795 ch3_offset = indent; 2796 2797 size = (width << gp3_src_pix_shift) + indent; 2798 } 2799 2800 total_dwords = (size + 3) >> 2; 2801 size_dwords = (total_dwords << 2) + 8; 2802 dword_count = (size >> 2); 2803 byte_count = (size & 3); 2804 2805 WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, ch3_offset); 2806 WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, GP3_CH3_C3EN | 2807 GP3_CH3_HST_SRC_ENABLE | 2808 gp3_src_format | ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT) 2809 << 20)); 2810 WRITE_COMMAND32(GP3_BLT_MODE, 2811 gp3_blt_mode | GP3_BM_SRC_MONO | GP3_BM_SRC_FB); 2812 2813 /* START THE BLT */ 2814 2815 WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header); 2816 WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); 2817 gp3_cmd_current = gp3_cmd_next; 2818 2819 /* WRITE DATA LINE BY LINE */ 2820 2821 while (height--) { 2822 /* UPDATE THE COMMAND POINTER */ 2823 2824 cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current; 2825 2826 /* CHECK IF A WRAP WILL BE NEEDED */ 2827 2828 gp3_cmd_next = gp3_cmd_current + size_dwords; 2829 if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) { 2830 gp3_cmd_next = gp3_cmd_top; 2831 2832 GP3_WAIT_WRAP(temp); 2833 WRITE_COMMAND32(0, 2834 GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP | 2835 GP3_DATA_LOAD_HDR_ENABLE); 2836 } 2837 else { 2838 GP3_WAIT_PRIMITIVE(temp); 2839 WRITE_COMMAND32(0, 2840 GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_ENABLE); 2841 } 2842 2843 /* WRITE DWORD COUNT */ 2844 2845 WRITE_COMMAND32(4, GP3_CH3_HOST_SOURCE_TYPE | total_dwords); 2846 2847 /* WRITE COLOR DATA TO THE COMMAND BUFFER */ 2848 2849 WRITE_COMMAND_STRING32(8, color_data, srcoffset, dword_count); 2850 WRITE_COMMAND_STRING8(8 + (dword_count << 2), color_data, 2851 srcoffset + (dword_count << 2), byte_count); 2852 2853 /* UPDATE COMMAND BUFFER POINTERS */ 2854 /* We do this before writing the monochrome data because otherwise */ 2855 /* the GP could throttle the writes to the host source register */ 2856 /* waiting for color data. If the command buffer has not been */ 2857 /* updated to load the color data... */ 2858 2859 srcoffset += color_pitch; 2860 WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); 2861 gp3_cmd_current = gp3_cmd_next; 2862 } 2863 } 2864 2865 /*--------------------------------------------------------------------------- 2866 * gp_screen_to_screen_masked 2867 * 2868 * This routine performs a screen to screen BLT, using a monochrome mask to 2869 * specify source transparency. The source data is assumed to be in the 2870 * current destination format and to not overlap the destination. 2871 *-------------------------------------------------------------------------*/ 2872 2873 void 2874 gp_screen_to_screen_masked(unsigned long dstoffset, unsigned long srcoffset, 2875 unsigned long width, unsigned long height, 2876 unsigned long mono_srcx, unsigned char *mono_mask, 2877 long mono_pitch) 2878 { 2879 unsigned long indent, temp; 2880 unsigned long total_dwords, size_dwords; 2881 unsigned long dword_count, byte_count; 2882 unsigned long srcoff, size; 2883 unsigned long i, base; 2884 unsigned long flags = 0; 2885 2886 if (gp3_blt_flags & CIMGP_BLTFLAGS_INVERTMONO) 2887 flags = GP3_RM_SOURCE_INVERT; 2888 2889 /* MONO CALCULATIONS */ 2890 2891 indent = (mono_srcx >> 3); 2892 srcoff = (indent & ~3L); 2893 indent &= 3; 2894 2895 size = ((width + (mono_srcx & 7) + 7) >> 3) + indent; 2896 total_dwords = (size + 3) >> 2; 2897 size_dwords = (total_dwords << 2) + 8; 2898 dword_count = (size >> 2); 2899 byte_count = (size & 3); 2900 2901 base = ((gp3_fb_base << 24) + (gp3_scratch_base & 0xFFC00000)) | 2902 (gp3_base_register & ~GP3_BASE_OFFSET_DSTMASK); 2903 2904 gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE | GP3_BLT_HDR_STRIDE_ENABLE | 2905 GP3_BLT_HDR_DST_OFF_ENABLE | GP3_BLT_HDR_WIDHI_ENABLE | 2906 GP3_BLT_HDR_CH3_STR_ENABLE | GP3_BLT_HDR_CH3_OFF_ENABLE | 2907 GP3_BLT_HDR_CH3_WIDHI_ENABLE | 2908 GP3_BLT_HDR_BASE_OFFSET_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE; 2909 2910 WRITE_COMMAND32(GP3_BLT_RASTER_MODE, GP3_RM_BPPFMT_8888 | 0xCC); 2911 WRITE_COMMAND32(GP3_BLT_STRIDE, (total_dwords << 2)); 2912 WRITE_COMMAND32(GP3_BLT_DST_OFFSET, gp3_scratch_base & 0x3FFFFF); 2913 WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, (total_dwords << 16) | height); 2914 WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, (total_dwords << 16) | height); 2915 WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, 0); 2916 WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base); 2917 WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, GP3_CH3_C3EN | 2918 GP3_CH3_REPLACE_SOURCE | GP3_CH3_HST_SRC_ENABLE | 2919 GP3_CH3_SRC_8_8_8_8 | 2920 ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT) << 20)); 2921 WRITE_COMMAND32(GP3_BLT_MODE, 0); 2922 WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header); 2923 2924 /* START THE BLT */ 2925 2926 WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); 2927 gp3_cmd_current = gp3_cmd_next; 2928 2929 for (i = 0; i < height; i++) { 2930 /* UPDATE THE COMMAND POINTER 2931 * The WRITE_COMMANDXX macros use a pointer to the current buffer 2932 * space. This is created by adding gp3_cmd_current to the base 2933 * pointer. 2934 */ 2935 2936 cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current; 2937 2938 /* CHECK IF A WRAP WILL BE NEEDED */ 2939 2940 gp3_cmd_next = gp3_cmd_current + size_dwords; 2941 if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) { 2942 gp3_cmd_next = gp3_cmd_top; 2943 2944 /* WAIT FOR HARDWARE */ 2945 2946 GP3_WAIT_WRAP(temp); 2947 WRITE_COMMAND32(0, GP3_DATA_LOAD_HDR_TYPE | 2948 GP3_DATA_LOAD_HDR_WRAP | GP3_DATA_LOAD_HDR_ENABLE); 2949 } 2950 else { 2951 /* WAIT FOR AVAILABLE SPACE */ 2952 2953 GP3_WAIT_PRIMITIVE(temp); 2954 WRITE_COMMAND32(0, GP3_DATA_LOAD_HDR_TYPE | 2955 GP3_DATA_LOAD_HDR_ENABLE); 2956 } 2957 2958 /* WRITE DWORD COUNT */ 2959 2960 WRITE_COMMAND32(4, GP3_CH3_HOST_SOURCE_TYPE | total_dwords); 2961 2962 /* WRITE DATA */ 2963 2964 WRITE_COMMAND_STRING32(8, mono_mask, srcoff, dword_count); 2965 WRITE_COMMAND_STRING8(8 + (dword_count << 2), mono_mask, 2966 srcoff + (dword_count << 2), byte_count); 2967 2968 /* UPDATE POINTERS */ 2969 2970 srcoff += mono_pitch; 2971 WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); 2972 gp3_cmd_current = gp3_cmd_next; 2973 } 2974 2975 /* SECOND BLT */ 2976 2977 gp_declare_blt(gp3_blt_flags | CIMGP_BLTFLAGS_HAZARD); 2978 2979 base = ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000)) | 2980 ((gp3_fb_base << 14) + (((gp3_scratch_base + 2981 indent) & 0xFFC00000) >> 10)) | ((gp3_fb_base 2982 << 4) + 2983 ((srcoffset & 2984 0xFFC00000) 2985 >> 20)); 2986 2987 gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE | 2988 GP3_BLT_HDR_STRIDE_ENABLE | GP3_BLT_HDR_DST_OFF_ENABLE | 2989 GP3_BLT_HDR_SRC_OFF_ENABLE | GP3_BLT_HDR_WIDHI_ENABLE | 2990 GP3_BLT_HDR_CH3_STR_ENABLE | 2991 GP3_BLT_HDR_CH3_WIDHI_ENABLE | 2992 GP3_BLT_HDR_BASE_OFFSET_ENABLE | 2993 GP3_BLT_HDR_CH3_OFF_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE; 2994 2995 /* ENABLE TRANSPARENCY AND PATTERN COPY ROP 2996 * The monochrome data is used as a mask but is otherwise not involved 2997 * in the BLT. The color data is routed through the pattern channel. 2998 */ 2999 3000 WRITE_COMMAND32(GP3_BLT_RASTER_MODE, 3001 gp3_bpp | 0xF0 | GP3_RM_SRC_TRANS | flags); 3002 WRITE_COMMAND32(GP3_BLT_STRIDE, (total_dwords << 18) | gp3_dst_stride); 3003 WRITE_COMMAND32(GP3_BLT_DST_OFFSET, dstoffset & 0x3FFFFF); 3004 WRITE_COMMAND32(GP3_BLT_SRC_OFFSET, 3005 ((gp3_scratch_base + 3006 indent) & 0x3FFFFF) | ((mono_srcx & 7) << 26)); 3007 WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, (width << 16) | height); 3008 WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, (width << 16) | height); 3009 WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base); 3010 3011 /* PROGRAM PARAMETERS FOR COLOR SOURCE DATA */ 3012 3013 WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, srcoffset & 0x3FFFFF); 3014 WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, GP3_CH3_C3EN | gp3_ch3_bpp | 3015 gp3_src_stride | ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT) 3016 << 20)); 3017 WRITE_COMMAND32(GP3_BLT_MODE, 3018 gp3_blt_mode | GP3_BM_SRC_MONO | GP3_BM_SRC_FB); 3019 3020 /* START THE BLT */ 3021 3022 WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header); 3023 WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); 3024 gp3_cmd_current = gp3_cmd_next; 3025 } 3026 3027 /*--------------------------------------------------------------------------- 3028 * gp_bresenham_line 3029 * 3030 * This routine draws a vector using the specified Bresenham parameters. 3031 * Currently this file does not support a routine that accepts the two 3032 * endpoints of a vector and calculates the Bresenham parameters. If it 3033 * ever does, this routine is still required for vectors that have been 3034 * clipped. 3035 *-------------------------------------------------------------------------*/ 3036 3037 void 3038 gp_bresenham_line(unsigned long dstoffset, unsigned short length, 3039 unsigned short initerr, unsigned short axialerr, 3040 unsigned short diagerr, unsigned long flags) 3041 { 3042 unsigned long base; 3043 long offset; 3044 3045 /* HANDLE NEGATIVE VECTORS */ 3046 /* We have to be very careful with vectors that increment negatively */ 3047 /* Our framebuffer scheme tries to align the destination of every */ 3048 /* BLT or vector to the nearest 4MB-aligned boundary. This is */ 3049 /* necessary because the GP only supports offsets up to 16MB, but the */ 3050 /* framebuffer can be over 128MB. To solve this problem, the GP */ 3051 /* base address registers are alignable to 4MB regions. However, we */ 3052 /* cannot simply align the dest offset when the vector goes negative. */ 3053 /* The vector offset could underflow, causing the offset to jump from */ 3054 /* near 0 to 16MB. As we cannot accurately determine the last address */ 3055 /* that will be written in a vector short of walking the algorithm in */ 3056 /* software, we do a worst case approximation. */ 3057 3058 offset = dstoffset; 3059 if (!(flags & CIMGP_POSMAJOR)) { 3060 if (flags & CIMGP_YMAJOR) 3061 offset -= length * gp3_dst_stride; 3062 else 3063 offset -= (length << gp3_pix_shift); 3064 3065 if (offset < 0) 3066 offset = 0; 3067 } 3068 if (!(flags & CIMGP_POSMINOR)) { 3069 if (flags & CIMGP_YMAJOR) 3070 offset -= (length << gp3_pix_shift); 3071 else 3072 offset -= length * gp3_dst_stride; 3073 3074 if (offset < 0) 3075 offset = 0; 3076 } 3077 3078 offset &= 0xFFC00000; 3079 dstoffset -= offset; 3080 3081 base = ((gp3_fb_base << 24) + offset) | 3082 (gp3_base_register & ~GP3_BASE_OFFSET_DSTMASK); 3083 3084 /* ENABLE RELEVANT REGISTERS */ 3085 /* Note that we always enable and write the channel 3 mode, if only */ 3086 /* to turn it off. Cimarron also always writes the base offset */ 3087 /* register to allow operation with frame buffers larger than 16MB. */ 3088 3089 gp3_cmd_header |= GP3_VEC_HDR_DST_OFF_ENABLE | 3090 GP3_VEC_HDR_VEC_ERR_ENABLE | 3091 GP3_VEC_HDR_VEC_LEN_ENABLE | 3092 GP3_VEC_HDR_BASE_OFFSET_ENABLE | 3093 GP3_VEC_HDR_CH3_STR_ENABLE | GP3_VEC_HDR_VEC_MODE_ENABLE; 3094 3095 /* WRITE THE REGISTERS COMMON TO ALL PATTERN TYPES */ 3096 /* The destination base is the frame buffer base plus whatever */ 3097 /* 4MB segment we happen to be drawing to. */ 3098 3099 WRITE_COMMAND32(GP3_VECTOR_VEC_ERR, 3100 (((unsigned long) axialerr << 16) | (unsigned long) 3101 diagerr)); 3102 WRITE_COMMAND32(GP3_VECTOR_VEC_LEN, 3103 (((unsigned long) length << 16) | (unsigned long) initerr)); 3104 WRITE_COMMAND32(GP3_VECTOR_BASE_OFFSET, base); 3105 3106 /* CHECK VECTOR PATTERN CASE */ 3107 3108 if (gp3_ch3_pat) { 3109 /* SET THE SOLID COLOR */ 3110 /* The color for vector patterns from channel 3 comes from */ 3111 /* the regular pattern registers. */ 3112 3113 gp3_cmd_header |= GP3_VEC_HDR_PAT_CLR0_ENABLE; 3114 3115 WRITE_COMMAND32(GP3_VECTOR_PAT_COLOR_0, gp3_vector_pattern_color); 3116 3117 /* INITIALIZE CHANNEL 3 PARAMETERS 3118 * We route the channel 3 output to the old source channel. If the 3119 * user sets a ROP that involves source, they will get unexpected 3120 * results. 3121 */ 3122 3123 WRITE_COMMAND32(GP3_VECTOR_DST_OFFSET, dstoffset); 3124 WRITE_COMMAND32(GP3_VECTOR_CH3_MODE_STR, 3125 GP3_CH3_C3EN | GP3_CH3_REPLACE_SOURCE | 3126 GP3_CH3_COLOR_PAT_ENABLE | GP3_CH3_SRC_8_8_8_8); 3127 } 3128 else { 3129 /* DISABLE CHANNEL 3 AND USE NORMAL PATTERN ORIGINS */ 3130 3131 WRITE_COMMAND32(GP3_VECTOR_CH3_MODE_STR, 0); 3132 WRITE_COMMAND32(GP3_VECTOR_DST_OFFSET, (dstoffset | gp3_pat_origin)); 3133 } 3134 3135 /* START THE VECTOR */ 3136 3137 WRITE_COMMAND32(GP3_VEC_CMD_HEADER, gp3_cmd_header); 3138 WRITE_COMMAND32(GP3_VECTOR_MODE, (gp3_vec_mode | flags)); 3139 WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); 3140 3141 gp3_cmd_current = gp3_cmd_next; 3142 3143 /* ADD A SECOND VECTOR TO CLEAR THE BYTE ENABLES */ 3144 /* We set a transparent pattern to clear the byte enables. */ 3145 /* We then restore the previous pattern. (SiBZ #4001) */ 3146 3147 if (gp3_ch3_pat) { 3148 cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current; 3149 3150 WRITE_COMMAND32(0, GP3_LUT_HDR_TYPE | GP3_LUT_HDR_DATA_ENABLE); 3151 WRITE_COMMAND32(4, 0x100); 3152 WRITE_COMMAND32(8, (1 | GP3_LUT_DATA_TYPE)); 3153 WRITE_COMMAND32(12, 0); 3154 3155 /* DUMMY VECTOR */ 3156 /* We shouldn't need to write anything but vector mode and the length 3157 */ 3158 3159 WRITE_COMMAND32(16, GP3_VEC_HDR_TYPE | GP3_VEC_HDR_VEC_MODE_ENABLE | 3160 GP3_VEC_HDR_VEC_LEN_ENABLE); 3161 WRITE_COMMAND32(16 + GP3_VECTOR_MODE, (gp3_vec_mode | flags)); 3162 WRITE_COMMAND32(16 + GP3_VECTOR_VEC_LEN, 3163 (1 << 16) | (unsigned long) initerr); 3164 3165 WRITE_COMMAND32(16 + GP3_VECTOR_COMMAND_SIZE, 3166 GP3_LUT_HDR_TYPE | GP3_LUT_HDR_DATA_ENABLE); 3167 WRITE_COMMAND32(20 + GP3_VECTOR_COMMAND_SIZE, 0x100); 3168 WRITE_COMMAND32(24 + GP3_VECTOR_COMMAND_SIZE, (1 | GP3_LUT_DATA_TYPE)); 3169 WRITE_COMMAND32(28 + GP3_VECTOR_COMMAND_SIZE, gp3_vec_pat); 3170 3171 gp3_cmd_current += 32 + GP3_VECTOR_COMMAND_SIZE; 3172 } 3173 } 3174 3175 /*--------------------------------------------------------------------------- 3176 * gp_line_from_endpoints 3177 * 3178 * This routine draws a vector from a set of rectangular coordinates. The 3179 * rectangle is assumed to use the currently specified destination stride. 3180 *-------------------------------------------------------------------------*/ 3181 3182 void 3183 gp_line_from_endpoints(unsigned long dstoffset, unsigned long x0, 3184 unsigned long y0, unsigned long x1, unsigned long y1, 3185 int inclusive) 3186 { 3187 unsigned long base; 3188 unsigned long length; 3189 unsigned long flags; 3190 unsigned short initerr, axialerr, diagerr; 3191 long dx, dy, dmaj, dmin; 3192 long offset; 3193 3194 /* ADJUST DESTINATION OFFSET BASED ON STARTING COORDINATE */ 3195 3196 dstoffset += (x0 << gp3_pix_shift) + (y0 * gp3_dst_stride); 3197 3198 /* CALCULATE BRESENHAM TERMS */ 3199 3200 dx = (long) x1 - (long) x0; 3201 dy = (long) y1 - (long) y0; 3202 if (dx < 0) 3203 dx = -dx; 3204 if (dy < 0) 3205 dy = -dy; 3206 3207 if (dx >= dy) { 3208 dmaj = dx; 3209 dmin = dy; 3210 flags = 0; 3211 if (x1 > x0) 3212 flags |= CIMGP_POSMAJOR; 3213 if (y1 > y0) 3214 flags |= CIMGP_POSMINOR; 3215 } 3216 else { 3217 dmaj = dy; 3218 dmin = dx; 3219 flags = CIMGP_YMAJOR; 3220 if (x1 > x0) 3221 flags |= CIMGP_POSMINOR; 3222 if (y1 > y0) 3223 flags |= CIMGP_POSMAJOR; 3224 } 3225 3226 axialerr = (unsigned short) (dmin << 1); 3227 diagerr = (unsigned short) ((dmin - dmaj) << 1); 3228 initerr = (unsigned short) ((dmin << 1) - dmaj); 3229 if (!(flags & CIMGP_POSMINOR)) 3230 initerr--; 3231 3232 /* CHECK FOR NO WORK */ 3233 3234 if (!dmaj) 3235 return; 3236 3237 /* CHECK INCLUSIVE OR EXCLUSIVE */ 3238 /* An inclusive line can be accomplished by simply adding 1 to the */ 3239 /* line length. */ 3240 3241 length = dmaj; 3242 if (inclusive) 3243 length++; 3244 3245 /* HANDLE NEGATIVE VECTORS */ 3246 3247 offset = dstoffset; 3248 if (!(flags & CIMGP_POSMAJOR)) { 3249 if (flags & CIMGP_YMAJOR) 3250 offset -= length * gp3_dst_stride; 3251 else 3252 offset -= (length << gp3_pix_shift); 3253 3254 if (offset < 0) 3255 offset = 0; 3256 } 3257 if (!(flags & CIMGP_POSMINOR)) { 3258 if (flags & CIMGP_YMAJOR) 3259 offset -= (length << gp3_pix_shift); 3260 else 3261 offset -= length * gp3_dst_stride; 3262 3263 if (offset < 0) 3264 offset = 0; 3265 } 3266 3267 offset &= 0xFFC00000; 3268 dstoffset -= offset; 3269 3270 base = ((gp3_fb_base << 24) + offset) | 3271 (gp3_base_register & ~GP3_BASE_OFFSET_DSTMASK); 3272 3273 /* ENABLE RELEVANT REGISTERS */ 3274 /* Note that we always enable and write the channel 3 mode, if only */ 3275 /* to turn it off. Cimarron also always writes the base offset */ 3276 /* register to allow operation with frame buffers larger than 16MB. */ 3277 3278 gp3_cmd_header |= GP3_VEC_HDR_DST_OFF_ENABLE | 3279 GP3_VEC_HDR_VEC_ERR_ENABLE | 3280 GP3_VEC_HDR_VEC_LEN_ENABLE | 3281 GP3_VEC_HDR_BASE_OFFSET_ENABLE | 3282 GP3_VEC_HDR_CH3_STR_ENABLE | GP3_VEC_HDR_VEC_MODE_ENABLE; 3283 3284 /* WRITE THE REGISTERS COMMON TO ALL PATTERN TYPES */ 3285 /* The destination base is the frame buffer base plus whatever */ 3286 /* 4MB segment we happen to be drawing to. */ 3287 3288 WRITE_COMMAND32(GP3_VECTOR_VEC_ERR, 3289 (((unsigned long) axialerr << 16) | (unsigned long) 3290 diagerr)); 3291 WRITE_COMMAND32(GP3_VECTOR_VEC_LEN, 3292 (((unsigned long) length << 16) | (unsigned long) initerr)); 3293 WRITE_COMMAND32(GP3_VECTOR_BASE_OFFSET, base); 3294 3295 /* CHECK VECTOR PATTERN CASE */ 3296 3297 if (gp3_ch3_pat) { 3298 /* SET THE SOLID COLOR */ 3299 /* The color for vector patterns from channel 3 comes from */ 3300 /* the regular pattern registers. */ 3301 3302 gp3_cmd_header |= GP3_VEC_HDR_PAT_CLR0_ENABLE; 3303 3304 WRITE_COMMAND32(GP3_VECTOR_PAT_COLOR_0, gp3_vector_pattern_color); 3305 3306 /* INITIALIZE CHANNEL 3 PARAMETERS */ 3307 /* We route the channel 3 output to the old source channel. If the 3308 * user sets a ROP that involves source, they will get unexpected 3309 * results. 3310 */ 3311 3312 WRITE_COMMAND32(GP3_VECTOR_DST_OFFSET, dstoffset); 3313 WRITE_COMMAND32(GP3_VECTOR_CH3_MODE_STR, 3314 GP3_CH3_C3EN | GP3_CH3_REPLACE_SOURCE | 3315 GP3_CH3_COLOR_PAT_ENABLE | GP3_CH3_SRC_8_8_8_8); 3316 } 3317 else { 3318 /* DISABLE CHANNEL 3 AND USE NORMAL PATTERN ORIGINS */ 3319 3320 WRITE_COMMAND32(GP3_VECTOR_CH3_MODE_STR, 0); 3321 WRITE_COMMAND32(GP3_VECTOR_DST_OFFSET, (dstoffset | gp3_pat_origin)); 3322 } 3323 3324 /* START THE VECTOR */ 3325 3326 WRITE_COMMAND32(GP3_VEC_CMD_HEADER, gp3_cmd_header); 3327 WRITE_COMMAND32(GP3_VECTOR_MODE, (gp3_vec_mode | flags)); 3328 WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); 3329 gp3_cmd_current = gp3_cmd_next; 3330 3331 /* ADD A SECOND VECTOR TO CLEAR THE BYTE ENABLES */ 3332 /* We set a transparent pattern to clear the byte enables. */ 3333 /* We then restore the previous pattern. (SiBZ #4001) */ 3334 3335 if (gp3_ch3_pat) { 3336 cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current; 3337 3338 WRITE_COMMAND32(0, GP3_LUT_HDR_TYPE | GP3_LUT_HDR_DATA_ENABLE); 3339 WRITE_COMMAND32(4, 0x100); 3340 WRITE_COMMAND32(8, (1 | GP3_LUT_DATA_TYPE)); 3341 WRITE_COMMAND32(12, 0); 3342 3343 /* DUMMY VECTOR */ 3344 /* We shouldn't need to write anything but vector mode and the length 3345 */ 3346 3347 WRITE_COMMAND32(16, GP3_VEC_HDR_TYPE | GP3_VEC_HDR_VEC_MODE_ENABLE | 3348 GP3_VEC_HDR_VEC_LEN_ENABLE); 3349 WRITE_COMMAND32(16 + GP3_VECTOR_MODE, (gp3_vec_mode | flags)); 3350 WRITE_COMMAND32(16 + GP3_VECTOR_VEC_LEN, 3351 (1 << 16) | (unsigned long) initerr); 3352 3353 WRITE_COMMAND32(16 + GP3_VECTOR_COMMAND_SIZE, 3354 GP3_LUT_HDR_TYPE | GP3_LUT_HDR_DATA_ENABLE); 3355 WRITE_COMMAND32(20 + GP3_VECTOR_COMMAND_SIZE, 0x100); 3356 WRITE_COMMAND32(24 + GP3_VECTOR_COMMAND_SIZE, (1 | GP3_LUT_DATA_TYPE)); 3357 WRITE_COMMAND32(28 + GP3_VECTOR_COMMAND_SIZE, gp3_vec_pat); 3358 3359 gp3_cmd_current += 32 + GP3_VECTOR_COMMAND_SIZE; 3360 } 3361 } 3362 3363 /*--------------------------------------------------------------------------- 3364 * gp_wait_until_idle 3365 * 3366 * This routine stalls execution until the GP is no longer actively rendering. 3367 *-------------------------------------------------------------------------*/ 3368 3369 void 3370 gp_wait_until_idle(void) 3371 { 3372 unsigned long temp; 3373 3374 while (((temp = READ_GP32(GP3_BLT_STATUS)) & GP3_BS_BLT_BUSY) || 3375 !(temp & GP3_BS_CB_EMPTY)) { 3376 ; 3377 } 3378 } 3379 3380 /*--------------------------------------------------------------------------- 3381 * gp_test_blt_busy 3382 *-------------------------------------------------------------------------*/ 3383 3384 int 3385 gp_test_blt_busy(void) 3386 { 3387 unsigned long temp; 3388 3389 if (((temp = READ_GP32(GP3_BLT_STATUS)) & GP3_BS_BLT_BUSY) || 3390 !(temp & GP3_BS_CB_EMPTY)) 3391 return 1; 3392 3393 return 0; 3394 } 3395 3396 /*--------------------------------------------------------------------------- 3397 * gp_test_blt_pending 3398 *-------------------------------------------------------------------------*/ 3399 3400 int 3401 gp_test_blt_pending(void) 3402 { 3403 if ((READ_GP32(GP3_BLT_STATUS)) & GP3_BS_BLT_PENDING) 3404 return 1; 3405 3406 return 0; 3407 } 3408 3409 /*--------------------------------------------------------------------------- 3410 * gp_wait_blt_pending 3411 *-------------------------------------------------------------------------*/ 3412 3413 void 3414 gp_wait_blt_pending(void) 3415 { 3416 while ((READ_GP32(GP3_BLT_STATUS)) & GP3_BS_BLT_PENDING); 3417 } 3418 3419 /*--------------------------------------------------------------------------- 3420 * gp_save_state 3421 * 3422 * This routine saves all persistent GP information. 3423 *-------------------------------------------------------------------------*/ 3424 3425 void 3426 gp_save_state(GP_SAVE_RESTORE * gp_state) 3427 { 3428 Q_WORD msr_value; 3429 3430 gp_wait_until_idle(); 3431 3432 msr_read64(MSR_DEVICE_GEODELX_GP, MSR_GEODELINK_CONFIG, &msr_value); 3433 gp_state->cmd_bottom = READ_GP32(GP3_CMD_BOT) & 0xFFFFFF; 3434 gp_state->cmd_top = READ_GP32(GP3_CMD_TOP) & 0xFFFFFF; 3435 gp_state->cmd_base = (msr_value.low << 4) & 0xFFF00000; 3436 gp_state->base_offset = READ_GP32(GP3_BASE_OFFSET); 3437 3438 /* RESET THE READ POINTER */ 3439 3440 gp_set_command_buffer_base(gp_state->cmd_base, gp_state->cmd_top, 3441 gp_state->cmd_bottom); 3442 } 3443 3444 /*--------------------------------------------------------------------------- 3445 * gp_restore_state 3446 * 3447 * This routine restores all persistent GP information. 3448 *-------------------------------------------------------------------------*/ 3449 3450 void 3451 gp_restore_state(GP_SAVE_RESTORE * gp_state) 3452 { 3453 gp_wait_until_idle(); 3454 3455 WRITE_GP32(GP3_BASE_OFFSET, gp_state->base_offset); 3456 3457 gp_set_command_buffer_base(gp_state->cmd_base, gp_state->cmd_top, 3458 gp_state->cmd_bottom); 3459 } 3460 3461 /* This is identical to gp_antialiased_text, except we support all one 3462 pass alpha operations similar to gp_set_alpha_operation */ 3463 3464 void 3465 gp_blend_mask_blt(unsigned long dstoffset, unsigned long srcx, 3466 unsigned long width, unsigned long height, 3467 unsigned long dataoffset, long stride, int operation, 3468 int fourbpp) 3469 { 3470 unsigned long indent; 3471 unsigned long size = ((width << 16) | height); 3472 unsigned long base, depth_flag; 3473 3474 base = ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000)) | 3475 ((gp3_fb_base << 4) + (dataoffset >> 20)) | 3476 (gp3_base_register & GP3_BASE_OFFSET_SRCMASK); 3477 3478 /* ENABLE ALL RELEVANT REGISTERS */ 3479 /* We override the raster mode register to force the */ 3480 /* correct alpha blend */ 3481 3482 gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE | 3483 GP3_BLT_HDR_DST_OFF_ENABLE | 3484 GP3_BLT_HDR_WIDHI_ENABLE | 3485 GP3_BLT_HDR_CH3_OFF_ENABLE | 3486 GP3_BLT_HDR_CH3_STR_ENABLE | 3487 GP3_BLT_HDR_CH3_WIDHI_ENABLE | 3488 GP3_BLT_HDR_BASE_OFFSET_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE; 3489 3490 /* CALCULATIONS BASED ON ALPHA DEPTH */ 3491 /* Although most antialiased text is 4BPP, the hardware supports */ 3492 /* a full 8BPP. Either case is supported by this routine. */ 3493 3494 if (fourbpp) { 3495 depth_flag = GP3_CH3_SRC_4BPP_ALPHA; 3496 indent = (srcx >> 1) & 3; 3497 dataoffset += indent | ((srcx & 1) << 25); 3498 } 3499 else { 3500 depth_flag = GP3_CH3_SRC_8BPP_ALPHA; 3501 indent = srcx & 3; 3502 dataoffset += indent; 3503 } 3504 3505 /* SET RASTER MODE REGISTER */ 3506 /* Alpha blending will only apply to RGB when no alpha component is present. */ 3507 /* As 8BPP is not supported for this routine, the only alpha-less mode is */ 3508 /* 5:6:5. */ 3509 3510 if (gp3_bpp == GP3_RM_BPPFMT_565) { 3511 WRITE_COMMAND32(GP3_BLT_RASTER_MODE, 3512 gp3_bpp | 3513 GP3_RM_ALPHA_TO_RGB | 3514 ((unsigned long) (operation << 20)) | 3515 GP3_RM_SELECT_ALPHA_CHAN_3); 3516 } 3517 else { 3518 WRITE_COMMAND32(GP3_BLT_RASTER_MODE, 3519 gp3_bpp | 3520 GP3_RM_ALPHA_ALL | ((unsigned long) (operation << 20)) | 3521 GP3_RM_SELECT_ALPHA_CHAN_3); 3522 } 3523 3524 /* WRITE ALL REMAINING REGISTERS */ 3525 3526 WRITE_COMMAND32(GP3_BLT_DST_OFFSET, (dstoffset & 0x3FFFFF)); 3527 3528 /* Set the offset of the CH3 data in memory */ 3529 WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, dataoffset & 0x3FFFFF); 3530 3531 WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, size); 3532 WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, size); 3533 WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base); 3534 3535 WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, GP3_CH3_C3EN | (stride & 0xFFFF) | 3536 depth_flag | ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT) << 3537 20)); 3538 3539 WRITE_COMMAND32(GP3_BLT_MODE, GP3_BM_DST_REQ); 3540 3541 /* START THE BLT */ 3542 3543 WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header); 3544 WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); 3545 gp3_cmd_current = gp3_cmd_next; 3546 } 3547