pnozz_accel.c revision a6b33934
1/* 2 * SBus Weitek P9100 hardware acceleration support 3 * 4 * Copyright (C) 2005 Michael Lorenz 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 * copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * MICHAEL LORENZ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 */ 23/* $NetBSD: pnozz_accel.c,v 1.1 2009/08/26 22:28:26 macallan Exp $ */ 24 25#include <fcntl.h> 26#include <sys/time.h> 27#include <sys/types.h> 28#include <dev/sun/fbio.h> 29#include <dev/wscons/wsconsio.h> 30 31#include "pnozz.h" 32 33static CARD32 PnozzCopyROP[] = { 34 /*GXclear*/ 0, 35 /*GXand*/ ROP_SRC & ROP_DST, 36 /*GXandReverse*/ ROP_SRC & (~ROP_DST), 37 /*GXcopy*/ ROP_SRC, 38 /*GXandInverted*/ (~ROP_SRC) & ROP_DST, 39 /*GXnoop*/ ROP_DST, 40 /*GXxor*/ ROP_SRC ^ ROP_DST, 41 /*GXor*/ ROP_SRC | ROP_DST, 42 /*GXnor*/ (~ROP_SRC) & (~ROP_DST), 43 /*GXequiv*/ (~ROP_SRC) ^ ROP_DST, 44 /*GXinvert*/ (~ROP_DST), 45 /*GXorReverse*/ ROP_SRC | (~ROP_DST), 46 /*GXcopyInverted*/ (~ROP_SRC), 47 /*GXorInverted*/ (~ROP_SRC) | ROP_DST, 48 /*GXnand*/ (~ROP_SRC) | (~ROP_DST), 49 /*GXset*/ ROP_SET 50}; 51 52static CARD32 PnozzDrawROP[] = { 53 /*GXclear*/ 0, 54 /*GXand*/ ROP_PAT & ROP_DST, 55 /*GXandReverse*/ ROP_PAT & (~ROP_DST), 56 /*GXcopy*/ ROP_PAT, 57 /*GXandInverted*/ (~ROP_PAT) & ROP_DST, 58 /*GXnoop*/ ROP_DST, 59 /*GXxor*/ ROP_PAT ^ ROP_DST, 60 /*GXor*/ ROP_PAT | ROP_DST, 61 /*GXnor*/ (~ROP_PAT) & (~ROP_DST), 62 /*GXequiv*/ (~ROP_PAT) ^ ROP_DST, 63 /*GXinvert*/ (~ROP_DST), 64 /*GXorReverse*/ ROP_PAT | (~ROP_DST), 65 /*GXcopyInverted*/ (~ROP_PAT), 66 /*GXorInverted*/ (~ROP_PAT) | ROP_DST, 67 /*GXnand*/ (~ROP_PAT) | (~ROP_DST), 68 /*GXset*/ ROP_PAT 69}; 70 71CARD32 MaxClip, junk; 72 73void 74PnozzSync(ScrnInfoPtr pScrn) 75{ 76 PnozzPtr pPnozz = GET_PNOZZ_FROM_SCRN(pScrn); 77 while((pnozz_read_4(pPnozz, ENGINE_STATUS) & 78 (ENGINE_BUSY | BLITTER_BUSY)) !=0 ); 79} 80 81/* 82 * Both the framebuffer and the colour registers are apparently little endian. 83 * For framebuffer accesses we can just turn on byte swapping, for the colour 84 * registers we need to juggle bytes ourselves. 85 */ 86 87static void 88pnozz_write_colour(PnozzPtr pPnozz, int reg, CARD32 colour) 89{ 90 CARD32 c2; 91 92 switch(pPnozz->depthshift) 93 { 94 case 0: 95 c2 = (colour << 8 | colour); 96 pnozz_write_4(pPnozz, reg, c2 << 16 | c2); 97 break; 98 case 1: 99 c2 = ((colour & 0xff) << 8) | ((colour & 0xff00) >> 8); 100 c2 |= c2 << 16; 101 pnozz_write_4(pPnozz, reg, c2); 102 break; 103 case 2: 104 c2 = ((colour & 0x00ff00ff) << 8) | ((colour & 0xff00ff00) >> 8); 105 c2 = (( c2 & 0xffff0000) >> 16) | ((c2 & 0x0000ffff) << 16); 106 pnozz_write_4(pPnozz, reg, c2); 107 break; 108 } 109} 110 111static void unClip(PnozzPtr pPnozz) 112{ 113 pnozz_write_4(pPnozz, WINDOW_OFFSET, 0); 114 pnozz_write_4(pPnozz, WINDOW_MIN, 0); 115 pnozz_write_4(pPnozz, WINDOW_MAX, MaxClip); 116 pnozz_write_4(pPnozz, BYTE_CLIP_MIN, 0); 117 pnozz_write_4(pPnozz, BYTE_CLIP_MAX, MaxClip); 118} 119 120static void 121PnozzInitEngine(PnozzPtr pPnozz) 122{ 123 unClip(pPnozz); 124 pnozz_write_4(pPnozz, DRAW_MODE, 0); 125 pnozz_write_4(pPnozz, PLANE_MASK, 0xffffffff); 126 pnozz_write_4(pPnozz, PATTERN0, 0xffffffff); 127 pnozz_write_4(pPnozz, PATTERN1, 0xffffffff); 128 pnozz_write_4(pPnozz, PATTERN2, 0xffffffff); 129 pnozz_write_4(pPnozz, PATTERN3, 0xffffffff); 130} 131 132static void 133PnozzSetupForScreenToScreenCopy( 134 ScrnInfoPtr pScrn, 135 int xdir, 136 int ydir, 137 int rop, 138 unsigned int planemask, 139 int TransparencyColour 140) 141{ 142 PnozzPtr pPnozz = GET_PNOZZ_FROM_SCRN(pScrn); 143 PnozzSync(pScrn); 144 145 pnozz_write_4(pPnozz, RASTER_OP, (PnozzCopyROP[rop] & 0xff)); 146 pnozz_write_4(pPnozz, PLANE_MASK, planemask); 147} 148 149/* 150 * the drawing engine is weird. Even though BLIT and QUAD commands use the 151 * same registers to program coordinates there's an important difference - 152 * horizontal coordinates for QUAD commands are in pixels, for BLIT commands 153 * and the byte clipping registers they're IN BYTES. 154 */ 155static void 156PnozzSubsequentScreenToScreenCopy 157( 158 ScrnInfoPtr pScrn, 159 int xSrc, 160 int ySrc, 161 int xDst, 162 int yDst, 163 int w, 164 int h 165) 166{ 167 PnozzPtr pPnozz = GET_PNOZZ_FROM_SCRN(pScrn); 168 CARD32 src, dst, srcw, dstw; 169 170 src = (((xSrc << pPnozz->depthshift) & 0x1fff) << 16) | (ySrc & 0x1fff); 171 dst = (((xDst << pPnozz->depthshift) & 0x1fff) << 16) | (yDst & 0x1fff); 172 srcw = ((((xSrc + w) << pPnozz->depthshift) - 1) << 16) | 173 ((ySrc + h - 1) & 0x1fff); 174 dstw = ((((xDst + w) << pPnozz->depthshift) - 1) << 16) | 175 ((yDst + h - 1) & 0x1fff); 176 177 PnozzSync(pScrn); 178 179 pnozz_write_4(pPnozz, ABS_XY0, src); 180 pnozz_write_4(pPnozz, ABS_XY1, srcw); 181 pnozz_write_4(pPnozz, ABS_XY2, dst); 182 pnozz_write_4(pPnozz, ABS_XY3, dstw); 183 junk = pnozz_read_4(pPnozz, COMMAND_BLIT); 184} 185 186static void 187PnozzSetupForSolidFill 188( 189 ScrnInfoPtr pScrn, 190 int colour, 191 int rop, 192 unsigned int planemask 193) 194{ 195 PnozzPtr pPnozz = GET_PNOZZ_FROM_SCRN(pScrn); 196 CARD32 c2; 197 198 PnozzSync(pScrn); 199 200 pnozz_write_colour(pPnozz, FOREGROUND_COLOR, colour); 201 pnozz_write_4(pPnozz, RASTER_OP, PnozzDrawROP[rop] & 0xff); 202 pnozz_write_4(pPnozz, PLANE_MASK, planemask); 203 pnozz_write_4(pPnozz, COORD_INDEX, 0); 204} 205 206static void 207PnozzSubsequentSolidFillRect 208( 209 ScrnInfoPtr pScrn, 210 int x, 211 int y, 212 int w, 213 int h 214) 215{ 216 PnozzPtr pPnozz = GET_PNOZZ_FROM_SCRN(pScrn); 217 218 PnozzSync(pScrn); 219 pnozz_write_4(pPnozz, RECT_RTW_XY, ((x & 0x1fff) << 16) | 220 (y & 0x1fff)); 221 pnozz_write_4(pPnozz, RECT_RTP_XY, (((w & 0x1fff) << 16) | 222 (h & 0x1fff))); 223 junk = pnozz_read_4(pPnozz, COMMAND_QUAD); 224} 225 226static void 227PnozzSetupForCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, 228 int fg, int bg, 229 int rop, 230 unsigned int planemask) 231{ 232 PnozzPtr pPnozz = GET_PNOZZ_FROM_SCRN(pScrn); 233 234 PnozzSync(pScrn); 235 236 if (bg == -1) { 237 /* transparent */ 238 pnozz_write_colour(pPnozz, FOREGROUND_COLOR, fg); 239 pnozz_write_4(pPnozz, RASTER_OP, PnozzDrawROP[rop] | ROP_PIX1_TRANS); 240 } else { 241 /* 242 * this doesn't make any sense to me either, but for some reason the 243 * chip applies the foreground colour to 0 pixels and background to 1 244 * when set to this sort of ROP. The old XF 3.3 driver source claimed 245 * that the chip doesn't support opaque colour expansion at all. 246 */ 247 pnozz_write_colour(pPnozz, FOREGROUND_COLOR, bg); 248 pnozz_write_colour(pPnozz, BACKGROUND_COLOR, fg); 249 250 pnozz_write_4(pPnozz, RASTER_OP, PnozzCopyROP[rop] & 0xff); 251 } 252 253 pnozz_write_4(pPnozz, PLANE_MASK, planemask); 254 pnozz_write_4(pPnozz, COORD_INDEX, 0); 255} 256 257static void 258PnozzSubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, 259 int x, int y, int w, int h, 260 int skipleft ) 261{ 262 PnozzPtr pPnozz = GET_PNOZZ_FROM_SCRN(pScrn); 263 CARD32 rest = w & 0x1f; 264 265 pnozz_write_4(pPnozz, ABS_X0, x); 266 pnozz_write_4(pPnozz, ABS_XY1, (x << 16) | (y & 0xFFFFL)); 267 pnozz_write_4(pPnozz, ABS_X2, (x + w)); 268 pnozz_write_4(pPnozz, ABS_Y3, 1); 269 270 pPnozz->words = (w >> 5); /* whole words to write */ 271 272 if (rest > 0) { 273 pPnozz->last_word = (rest - 1) << 2; 274 } else 275 pPnozz->last_word = -1; 276} 277 278static void 279PnozzSubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno) 280{ 281 PnozzPtr pPnozz = GET_PNOZZ_FROM_SCRN(pScrn); 282#define PIXEL_1_FULL (PIXEL_1 + (31 << 2)) 283 CARD32 *buf; 284 volatile CARD32 *pix = ((volatile CARD32 *)(pPnozz->fbc + PIXEL_1_FULL)); 285 int i = 0; 286 287 PnozzSync(pScrn); 288 buf = (CARD32 *)pPnozz->buffers[bufno]; 289 junk = *(volatile CARD32 *)(pPnozz->fb + PIXEL_1_FULL); 290 for (i = 0; i < pPnozz->words; i++) 291 *pix = buf[i]; 292 if (pPnozz->last_word >= 0) 293 *(volatile CARD32 *)(pPnozz->fbc + PIXEL_1 + pPnozz->last_word) = 294 buf[i]; 295} 296 297static void 298PnozzSetupForSolidLine(ScrnInfoPtr pScrn, int color, int rop, 299 unsigned int planemask) 300{ 301 PnozzPtr pPnozz = GET_PNOZZ_FROM_SCRN(pScrn); 302 303 PnozzSync(pScrn); 304 305 pnozz_write_colour(pPnozz, FOREGROUND_COLOR, color); 306 pnozz_write_4(pPnozz, RASTER_OP, (PnozzDrawROP[rop] & 0xff) | ROP_OVERSIZE); 307 308 pnozz_write_4(pPnozz, PLANE_MASK, planemask); 309 pnozz_write_4(pPnozz, COORD_INDEX, 0); 310 311} 312 313static void 314PnozzSubsequentSolidTwoPointLine(ScrnInfoPtr pScrn, int x1, int y1, int x2, 315 int y2, int flags) 316{ 317 PnozzPtr pPnozz = GET_PNOZZ_FROM_SCRN(pScrn); 318 319 PnozzSync(pScrn); 320 321 /* 322 * XXX we're blatantly ignoring the flags parameter which could tell us not 323 * to draw the last point. Xsun simply reads it from the framebuffer and 324 * puts it back after drawing the line but that would mean we have to wait 325 * until the line is actually drawn. On the other hand - line drawing is 326 * pretty fast so we won't lose too much speed 327 */ 328 pnozz_write_4(pPnozz, LINE_RTW_XY, (x1 << 16) | y1); 329 pnozz_write_4(pPnozz, LINE_RTW_XY, (x2 << 16) | y2); 330 junk = pnozz_read_4(pPnozz, COMMAND_QUAD); 331} 332 333static void 334PnozzSetupForMono8x8PatternFill(ScrnInfoPtr pScrn, int pat0, int pat1, 335 int fg, int bg, int rop, unsigned int planemask) 336{ 337 PnozzPtr pPnozz = GET_PNOZZ_FROM_SCRN(pScrn); 338 CARD32 pat; 339 340 PnozzSync(pScrn); 341 342 if (bg == -1) { 343 pnozz_write_4(pPnozz, RASTER_OP, 344 (PnozzDrawROP[rop] & 0xff) | ROP_NO_SOLID | ROP_TRANS); 345 } else { 346 pnozz_write_colour(pPnozz, COLOR_0, bg); 347 pnozz_write_4(pPnozz, RASTER_OP, 348 (PnozzDrawROP[rop] & 0xff) | ROP_NO_SOLID); 349 } 350 pnozz_write_colour(pPnozz, COLOR_1, fg); 351 pnozz_write_4(pPnozz, PLANE_MASK, planemask); 352 pat = (pat0 & 0xff000000) | ((pat0 >> 8) & 0x00ffff00) | 353 ((pat0 >> 16) & 0x000000ff); 354 pnozz_write_4(pPnozz, PATTERN0, pat); 355 pat = ((pat0 << 8) & 0x00ffff00) | ((pat0 << 16) & 0xff000000) | 356 (pat0 & 0x000000ff); 357 pnozz_write_4(pPnozz, PATTERN1, pat); 358 pat = (pat1 & 0xff000000) | ((pat1 >> 8) & 0x00ffff00) | 359 ((pat1 >> 16) & 0x000000ff); 360 pnozz_write_4(pPnozz, PATTERN2, pat); 361 pat = ((pat1 << 8) & 0x00ffff00) | ((pat1 << 16) & 0xff000000) | 362 (pat1 & 0x000000ff); 363 pnozz_write_4(pPnozz, PATTERN3, pat); 364 pnozz_write_4(pPnozz, COORD_INDEX, 0); 365} 366 367static void 368PnozzSubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, 369 int patx, int paty, int x, int y, int w, int h) 370{ 371 PnozzPtr pPnozz = GET_PNOZZ_FROM_SCRN(pScrn); 372 373 PnozzSync(pScrn); 374 pnozz_write_4(pPnozz, PATTERN_ORIGIN_X, patx); 375 pnozz_write_4(pPnozz, PATTERN_ORIGIN_Y, paty); 376 pnozz_write_4(pPnozz, RECT_RTW_XY, ((x & 0x1fff) << 16) | 377 (y & 0x1fff)); 378 pnozz_write_4(pPnozz, RECT_RTP_XY, (((w & 0x1fff) << 16) | 379 (h & 0x1fff))); 380 junk = pnozz_read_4(pPnozz, COMMAND_QUAD); 381 382} 383 384static void 385PnozzSetClippingRectangle(ScrnInfoPtr pScrn, int left, int top, int right, 386 int bottom) 387{ 388 PnozzPtr pPnozz = GET_PNOZZ_FROM_SCRN(pScrn); 389 CARD32 cmin, cmax; 390 391 cmin = (left << 16) | top; 392 cmax = (right << 16) | bottom; 393 394 pnozz_write_4(pPnozz, WINDOW_MIN, cmin); 395 pnozz_write_4(pPnozz, WINDOW_MAX, cmax); 396 397 cmin = ((left << pPnozz->depthshift) << 16) | top; 398 cmax = ((right << pPnozz->depthshift) << 16) | bottom; 399 400 pnozz_write_4(pPnozz, BYTE_CLIP_MIN, cmin); 401 pnozz_write_4(pPnozz, BYTE_CLIP_MAX, cmax); 402} 403 404static void 405PnozzDisableClipping(ScrnInfoPtr pScrn) 406{ 407 PnozzPtr pPnozz = GET_PNOZZ_FROM_SCRN(pScrn); 408 409 pnozz_write_4(pPnozz, WINDOW_MIN, 0); 410 pnozz_write_4(pPnozz, WINDOW_MAX, MaxClip); 411 pnozz_write_4(pPnozz, BYTE_CLIP_MIN, 0); 412 pnozz_write_4(pPnozz, BYTE_CLIP_MAX, MaxClip); 413} 414 415static void 416PnozzSetupForImageWrite(ScrnInfoPtr pScrn, int rop, unsigned int planemask, 417 int trans_color, int depth, int bpp) 418{ 419 PnozzPtr pPnozz = GET_PNOZZ_FROM_SCRN(pScrn); 420 421 pnozz_write_4(pPnozz, RASTER_OP, PnozzCopyROP[rop] & 0xff); 422 pnozz_write_4(pPnozz, PLANE_MASK, planemask); 423 pnozz_write_4(pPnozz, COORD_INDEX, 0); 424 425 Xf86Msg(X_ERROR, "setup for image write\n"); 426} 427 428static void 429PnozzImageWriteRect(ScrnInfoPtr pScrn, int x, int y, int wi, int he, int skip) 430{ 431 PnozzPtr pPnozz = GET_PNOZZ_FROM_SCRN(pScrn); 432 volatile CARD32 junk; 433 434 pnozz_write_4(pPnozz, ABS_X0, x); 435 pnozz_write_4(pPnozz, ABS_XY1, (x << 16) | y); 436 pnozz_write_4(pPnozz, ABS_X2, x + wi); 437 pnozz_write_4(pPnozz, ABS_Y3, 1); 438 junk = *(volatile CARD32 *)(pPnozz->fb + PIXEL_8); 439} 440 441/* 442 * TODO: 443 * - CPU to VRAM colour blits 444 * - DGA support 445 */ 446 447int 448PnozzAccelInit(ScrnInfoPtr pScrn) 449{ 450 PnozzPtr pPnozz = GET_PNOZZ_FROM_SCRN(pScrn); 451 XAAInfoRecPtr pXAAInfo = pPnozz->pXAA; 452 453 pXAAInfo->Flags = LINEAR_FRAMEBUFFER | PIXMAP_CACHE | OFFSCREEN_PIXMAPS; 454 pXAAInfo->maxOffPixWidth = pPnozz->width; 455 pXAAInfo->maxOffPixHeight = pPnozz->maxheight; 456 MaxClip = ((pPnozz->scanlinesize & 0xffff) << 16) | (pPnozz->maxheight); 457 458 PnozzInitEngine(pPnozz); 459 460#if 1 461 { 462 CARD32 src, srcw, junk; 463 src = 0; 464 srcw = pPnozz->width << 16 | pPnozz->height; 465 466 /* Blit the screen black. For aesthetic reasons. */ 467 468 PnozzSync(pScrn); 469 pnozz_write_4(pPnozz, FOREGROUND_COLOR, 0x00000000); 470 pnozz_write_4(pPnozz, BACKGROUND_COLOR, 0xffffffff); 471 pnozz_write_4(pPnozz, RASTER_OP, ROP_PAT); 472 pnozz_write_4(pPnozz, COORD_INDEX, 0); 473 pnozz_write_4(pPnozz, RECT_RTW_XY, src); 474 pnozz_write_4(pPnozz, RECT_RTW_XY, srcw); 475 junk = pnozz_read_4(pPnozz, COMMAND_QUAD); 476 PnozzSync(pScrn); 477 } 478#endif 479 480 /* Sync */ 481 pXAAInfo->Sync = PnozzSync; 482 483 /* Screen-to-screen copy */ 484 pXAAInfo->ScreenToScreenCopyFlags = NO_TRANSPARENCY; 485 pXAAInfo->SetupForScreenToScreenCopy = PnozzSetupForScreenToScreenCopy; 486 pXAAInfo->SubsequentScreenToScreenCopy = 487 PnozzSubsequentScreenToScreenCopy; 488 489 /* Solid fills */ 490 pXAAInfo->SetupForSolidFill = PnozzSetupForSolidFill; 491 pXAAInfo->SubsequentSolidFillRect = PnozzSubsequentSolidFillRect; 492 493 /* colour expansion */ 494 pXAAInfo->ScanlineCPUToScreenColorExpandFillFlags = 495 /*LEFT_EDGE_CLIPPING|*/SCANLINE_PAD_DWORD; 496 pXAAInfo->NumScanlineColorExpandBuffers = 2; 497 pPnozz->buffers[0] = (unsigned char *)pPnozz->Buffer; 498 pPnozz->buffers[1] = (unsigned char *)&pPnozz->Buffer[pPnozz->scanlinesize]; 499 pXAAInfo->ScanlineColorExpandBuffers = pPnozz->buffers; 500 pXAAInfo->SetupForScanlineCPUToScreenColorExpandFill = 501 PnozzSetupForCPUToScreenColorExpandFill; 502 pXAAInfo->SubsequentScanlineCPUToScreenColorExpandFill = 503 PnozzSubsequentScanlineCPUToScreenColorExpandFill; 504 pXAAInfo->SubsequentColorExpandScanline = 505 PnozzSubsequentColorExpandScanline; 506 507 /* line drawing */ 508 pXAAInfo->SetupForSolidLine = PnozzSetupForSolidLine; 509 pXAAInfo->SubsequentSolidTwoPointLine = PnozzSubsequentSolidTwoPointLine; 510 pXAAInfo->SolidLineFlags = BIT_ORDER_IN_BYTE_MSBFIRST; 511 512 /* clipping */ 513 pXAAInfo->SetClippingRectangle = PnozzSetClippingRectangle; 514 pXAAInfo->DisableClipping = PnozzDisableClipping; 515 pXAAInfo->ClippingFlags = HARDWARE_CLIP_SCREEN_TO_SCREEN_COPY | 516 HARDWARE_CLIP_SOLID_FILL | 517 HARDWARE_CLIP_MONO_8x8_FILL | 518 /*HARDWARE_CLIP_COLOR_8x8_FILL |*/ 519 HARDWARE_CLIP_SOLID_LINE; 520 521 /* 8x8 mono pattern fills */ 522 pXAAInfo->Mono8x8PatternFillFlags = HARDWARE_PATTERN_PROGRAMMED_BITS | 523 HARDWARE_PATTERN_SCREEN_ORIGIN | HARDWARE_PATTERN_PROGRAMMED_ORIGIN; 524 pXAAInfo->SetupForMono8x8PatternFill = PnozzSetupForMono8x8PatternFill; 525 pXAAInfo->SubsequentMono8x8PatternFillRect = 526 PnozzSubsequentMono8x8PatternFillRect; 527 528 /* image uploads */ 529 pXAAInfo->ImageWriteBase = pPnozz->fbc + PIXEL_8; 530 pXAAInfo->ImageWriteRange = 4; 531 pXAAInfo->ImageWriteFlags = /*CPU_TRANSFER_BASE_FIXED |*/ CPU_TRANSFER_PAD_DWORD | 532 NO_TRANSPARENCY; 533 pXAAInfo->SetupForImageWrite = PnozzSetupForImageWrite; 534 pXAAInfo->SubsequentImageWriteRect = PnozzImageWriteRect; 535 536 return 0; 537} 538