/* $XFree86: xc/programs/Xserver/hw/xfree86/xaa/xaaFillRect.c,v 1.15tsi Exp $ */ #include #include "xf86.h" #include "xf86_ansic.h" #include "xf86_OSproc.h" #include #include "scrnintstr.h" #include "pixmapstr.h" #include "xf86str.h" #include "xaa.h" #include "xaalocal.h" static void XAARenderSolidRects(GCPtr, int, BoxPtr, int, int); static void XAARenderColor8x8Rects(GCPtr, int, BoxPtr, int, int); static void XAARenderMono8x8Rects(GCPtr, int, BoxPtr, int, int); static void XAARenderColorExpandRects(GCPtr, int, BoxPtr, int, int); static void XAARenderCacheExpandRects(GCPtr, int, BoxPtr, int, int); static void XAARenderCacheBltRects(GCPtr, int, BoxPtr, int, int); static void XAARenderImageWriteRects(GCPtr, int, BoxPtr, int, int); static void XAARenderPixmapCopyRects(GCPtr, int, BoxPtr, int, int); void XAAPolyFillRect( DrawablePtr pDraw, GCPtr pGC, int nrectFill, /* number of rectangles to fill */ xRectangle *prectInit /* Pointer to first rectangle to fill */ ){ XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); int xorg = pDraw->x; int yorg = pDraw->y; int type = 0; ClipAndRenderRectsFunc function; if((nrectFill <= 0) || !pGC->planemask) return; if(!REGION_NUM_RECTS(pGC->pCompositeClip)) return; switch(pGC->fillStyle) { case FillSolid: type = DO_SOLID; break; case FillStippled: type = (*infoRec->StippledFillChooser)(pGC); break; case FillOpaqueStippled: if((pGC->fgPixel == pGC->bgPixel) && infoRec->FillSolidRects && CHECK_PLANEMASK(pGC,infoRec->FillSolidRectsFlags) && CHECK_ROP(pGC,infoRec->FillSolidRectsFlags) && CHECK_ROPSRC(pGC,infoRec->FillSolidRectsFlags) && CHECK_FG(pGC,infoRec->FillSolidRectsFlags)) type = DO_SOLID; else type = (*infoRec->OpaqueStippledFillChooser)(pGC); break; case FillTiled: type = (*infoRec->TiledFillChooser)(pGC); break; } switch(type) { case DO_SOLID: function = XAARenderSolidRects; break; case DO_COLOR_8x8: function = XAARenderColor8x8Rects; break; case DO_MONO_8x8: function = XAARenderMono8x8Rects; break; case DO_CACHE_BLT: function = XAARenderCacheBltRects; break; case DO_COLOR_EXPAND: function = XAARenderColorExpandRects; break; case DO_CACHE_EXPAND: function = XAARenderCacheExpandRects; break; case DO_IMAGE_WRITE: function = XAARenderImageWriteRects; break; case DO_PIXMAP_COPY: function = XAARenderPixmapCopyRects; break; default: (*XAAFallbackOps.PolyFillRect)(pDraw, pGC, nrectFill, prectInit); return; } if(xorg | yorg) { int n = nrectFill; xRectangle *prect = prectInit; while(n--) { prect->x += xorg; prect->y += yorg; prect++; } } XAAClipAndRenderRects(pGC, function, nrectFill, prectInit, xorg, yorg); } /*********************\ | Solid Rects | \*********************/ static void XAARenderSolidRects( GCPtr pGC, int nboxes, BoxPtr pClipBoxes, int xorg, int yorg ){ XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); (*infoRec->FillSolidRects) (infoRec->pScrn, pGC->fgPixel, pGC->alu, pGC->planemask, nboxes, pClipBoxes); } /************************\ | Mono 8x8 Rects | \************************/ static void XAARenderMono8x8Rects( GCPtr pGC, int nboxes, BoxPtr pClipBoxes, int xorg, int yorg ){ XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); XAAPixmapPtr pPriv; int fg, bg; switch(pGC->fillStyle) { case FillStippled: pPriv = XAA_GET_PIXMAP_PRIVATE(pGC->stipple); fg = pGC->fgPixel; bg = -1; break; case FillOpaqueStippled: pPriv = XAA_GET_PIXMAP_PRIVATE(pGC->stipple); fg = pGC->fgPixel; bg = pGC->bgPixel; break; case FillTiled: pPriv = XAA_GET_PIXMAP_PRIVATE(pGC->tile.pixmap); fg = pPriv->fg; bg = pPriv->bg; break; default: /* Muffle compiler */ pPriv = NULL; /* Kaboom */ fg = -1; bg = -1; break; } (*infoRec->FillMono8x8PatternRects) (infoRec->pScrn, fg, bg, pGC->alu, pGC->planemask, nboxes, pClipBoxes, pPriv->pattern0, pPriv->pattern1, (xorg + pGC->patOrg.x), (yorg + pGC->patOrg.y)); } /*************************\ | Color 8x8 Rects | \*************************/ static void XAARenderColor8x8Rects( GCPtr pGC, int nboxes, BoxPtr pClipBoxes, int xorg, int yorg ){ XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); XAACacheInfoPtr pCache; PixmapPtr pPix; int fg, bg; switch(pGC->fillStyle) { case FillStippled: pPix = pGC->stipple; fg = pGC->fgPixel; bg = -1; break; case FillOpaqueStippled: pPix = pGC->stipple; fg = pGC->fgPixel; bg = pGC->bgPixel; break; case FillTiled: pPix = pGC->tile.pixmap; fg = -1; bg = -1; break; default: /* Muffle compiler */ pPix = NULL; fg = -1; bg = -1; break; } pCache = (*infoRec->CacheColor8x8Pattern)(infoRec->pScrn, pPix, fg, bg); (*infoRec->FillColor8x8PatternRects) (infoRec->pScrn, pGC->alu, pGC->planemask, nboxes, pClipBoxes, (xorg + pGC->patOrg.x), (yorg + pGC->patOrg.y), pCache); } /****************************\ | Color Expand Rects | \****************************/ static void XAARenderColorExpandRects( GCPtr pGC, int nboxes, BoxPtr pClipBoxes, int xorg, int yorg ){ XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); int fg, bg; switch(pGC->fillStyle) { case FillStippled: fg = pGC->fgPixel; bg = -1; break; case FillOpaqueStippled: fg = pGC->fgPixel; bg = pGC->bgPixel; break; default: /* Muffle compiler */ fg = -1; bg = -1; break; } (*infoRec->FillColorExpandRects) (infoRec->pScrn, fg, bg, pGC->alu, pGC->planemask, nboxes, pClipBoxes, (xorg + pGC->patOrg.x), (yorg + pGC->patOrg.y), pGC->stipple); } /*************************\ | Cache Blt Rects | \*************************/ static void XAARenderCacheBltRects( GCPtr pGC, int nboxes, BoxPtr pClipBoxes, int xorg, int yorg ){ XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); XAACacheInfoPtr pCache; switch(pGC->fillStyle) { case FillStippled: pCache = (*infoRec->CacheStipple)(infoRec->pScrn, pGC->stipple, pGC->fgPixel, -1); break; case FillOpaqueStippled: pCache = (*infoRec->CacheStipple)(infoRec->pScrn, pGC->stipple, pGC->fgPixel, pGC->bgPixel); break; case FillTiled: pCache = (*infoRec->CacheTile)(infoRec->pScrn, pGC->tile.pixmap); break; default: /* Muffle compiler */ pCache = NULL; break; } (*infoRec->FillCacheBltRects) (infoRec->pScrn, pGC->alu, pGC->planemask, nboxes, pClipBoxes, (xorg + pGC->patOrg.x), (yorg + pGC->patOrg.y), pCache); } /****************************\ | Cache Expand Rects | \****************************/ static void XAARenderCacheExpandRects( GCPtr pGC, int nboxes, BoxPtr pClipBoxes, int xorg, int yorg ){ XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); int fg, bg; switch(pGC->fillStyle) { case FillStippled: fg = pGC->fgPixel; bg = -1; break; case FillOpaqueStippled: fg = pGC->fgPixel; bg = pGC->bgPixel; break; default: /* Muffle compiler */ fg = -1; bg = -1; break; } (*infoRec->FillCacheExpandRects) (infoRec->pScrn, fg, bg, pGC->alu, pGC->planemask, nboxes, pClipBoxes, (xorg + pGC->patOrg.x), (yorg + pGC->patOrg.y), pGC->stipple); } /***************************\ | Image Write Rects | \***************************/ static void XAARenderImageWriteRects( GCPtr pGC, int nboxes, BoxPtr pClipBoxes, int xorg, int yorg ){ XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); (*infoRec->FillImageWriteRects) (infoRec->pScrn, pGC->alu, pGC->planemask, nboxes, pClipBoxes, (xorg + pGC->patOrg.x), (yorg + pGC->patOrg.y), pGC->tile.pixmap); } /***************************\ | Pixmap Copy Rects | \***************************/ static void XAARenderPixmapCopyRects( GCPtr pGC, int nboxes, BoxPtr pClipBoxes, int xorg, int yorg ){ XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); XAACacheInfoPtr pCache = &(infoRec->ScratchCacheInfoRec); XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pGC->tile.pixmap); pCache->x = pPriv->offscreenArea->box.x1; pCache->y = pPriv->offscreenArea->box.y1; pCache->w = pCache->orig_w = pPriv->offscreenArea->box.x2 - pCache->x; pCache->h = pCache->orig_h = pPriv->offscreenArea->box.y2 - pCache->y; pCache->trans_color = -1; (*infoRec->FillCacheBltRects) (infoRec->pScrn, pGC->alu, pGC->planemask, nboxes, pClipBoxes, (xorg + pGC->patOrg.x), (yorg + pGC->patOrg.y), pCache); } /************\ | Solid | \************/ void XAAFillSolidRects( ScrnInfoPtr pScrn, int fg, int rop, unsigned int planemask, int nBox, /* number of rectangles to fill */ BoxPtr pBox /* Pointer to first rectangle to fill */ ){ XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); (*infoRec->SetupForSolidFill)(pScrn, fg, rop, planemask); while(nBox--) { (*infoRec->SubsequentSolidFillRect)(pScrn, pBox->x1, pBox->y1, pBox->x2 - pBox->x1, pBox->y2 - pBox->y1); pBox++; } SET_SYNC_FLAG(infoRec); } /*********************\ | 8x8 Mono Patterns | \*********************/ void XAAFillMono8x8PatternRectsScreenOrigin( ScrnInfoPtr pScrn, int fg, int bg, int rop, unsigned int planemask, int nBox, BoxPtr pBox, int pattern0, int pattern1, int xorigin, int yorigin ) { XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); int patx = pattern0, paty = pattern1; int xorg = (-xorigin) & 0x07; int yorg = (-yorigin) & 0x07; if(infoRec->Mono8x8PatternFillFlags & HARDWARE_PATTERN_PROGRAMMED_BITS) { if(!(infoRec->Mono8x8PatternFillFlags & HARDWARE_PATTERN_PROGRAMMED_ORIGIN)){ XAARotateMonoPattern(&patx, &paty, xorg, yorg, (infoRec->Mono8x8PatternFillFlags & BIT_ORDER_IN_BYTE_MSBFIRST)); xorg = patx; yorg = paty; } } else { XAACacheInfoPtr pCache = (*infoRec->CacheMono8x8Pattern)(pScrn, pattern0, pattern1); patx = pCache->x; paty = pCache->y; if(!(infoRec->Mono8x8PatternFillFlags & HARDWARE_PATTERN_PROGRAMMED_ORIGIN)){ int slot = (yorg << 3) + xorg; patx += pCache->offsets[slot].x; paty += pCache->offsets[slot].y; xorg = patx; yorg = paty; } } (*infoRec->SetupForMono8x8PatternFill)(pScrn, patx, paty, fg, bg, rop, planemask); while(nBox--) { (*infoRec->SubsequentMono8x8PatternFillRect)(pScrn, xorg, yorg, pBox->x1, pBox->y1, pBox->x2 - pBox->x1, pBox->y2 - pBox->y1); pBox++; } SET_SYNC_FLAG(infoRec); } void XAAFillMono8x8PatternRects( ScrnInfoPtr pScrn, int fg, int bg, int rop, unsigned int planemask, int nBox, BoxPtr pBox, int pattern0, int pattern1, int xorigin, int yorigin ) { XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); int patx = pattern0, paty = pattern1; int xorg, yorg; XAACacheInfoPtr pCache = NULL; if(!(infoRec->Mono8x8PatternFillFlags & HARDWARE_PATTERN_PROGRAMMED_BITS)){ pCache = (*infoRec->CacheMono8x8Pattern)(pScrn, pattern0, pattern1); patx = pCache->x; paty = pCache->y; } (*infoRec->SetupForMono8x8PatternFill)(pScrn, patx, paty, fg, bg, rop, planemask); while(nBox--) { xorg = (pBox->x1 - xorigin) & 0x07; yorg = (pBox->y1 - yorigin) & 0x07; if(!(infoRec->Mono8x8PatternFillFlags & HARDWARE_PATTERN_PROGRAMMED_ORIGIN)){ if(infoRec->Mono8x8PatternFillFlags & HARDWARE_PATTERN_PROGRAMMED_BITS) { patx = pattern0; paty = pattern1; XAARotateMonoPattern(&patx, &paty, xorg, yorg, (infoRec->Mono8x8PatternFillFlags & BIT_ORDER_IN_BYTE_MSBFIRST)); xorg = patx; yorg = paty; } else { int slot = (yorg << 3) + xorg; xorg = patx + pCache->offsets[slot].x; yorg = paty + pCache->offsets[slot].y; } } (*infoRec->SubsequentMono8x8PatternFillRect)(pScrn, xorg, yorg, pBox->x1, pBox->y1, pBox->x2 - pBox->x1, pBox->y2 - pBox->y1); pBox++; } SET_SYNC_FLAG(infoRec); } /**********************\ | 8x8 Color Patterns | \**********************/ void XAAFillColor8x8PatternRectsScreenOrigin( ScrnInfoPtr pScrn, int rop, unsigned int planemask, int nBox, BoxPtr pBox, int xorigin, int yorigin, XAACacheInfoPtr pCache ){ XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); int patx = pCache->x, paty = pCache->y; int xorg = (-xorigin) & 0x07; int yorg = (-yorigin) & 0x07; if(!(infoRec->Color8x8PatternFillFlags & HARDWARE_PATTERN_PROGRAMMED_ORIGIN)){ int slot = (yorg << 3) + xorg; paty += pCache->offsets[slot].y; patx += pCache->offsets[slot].x; xorg = patx; yorg = paty; } (*infoRec->SetupForColor8x8PatternFill)(pScrn, patx, paty, rop, planemask, pCache->trans_color); while(nBox--) { (*infoRec->SubsequentColor8x8PatternFillRect)(pScrn, xorg, yorg, pBox->x1, pBox->y1, pBox->x2 - pBox->x1, pBox->y2 - pBox->y1); pBox++; } SET_SYNC_FLAG(infoRec); } void XAAFillColor8x8PatternRects( ScrnInfoPtr pScrn, int rop, unsigned int planemask, int nBox, BoxPtr pBox, int xorigin, int yorigin, XAACacheInfoPtr pCache ){ XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); int xorg, yorg; (*infoRec->SetupForColor8x8PatternFill)(pScrn, pCache->x, pCache->y, rop, planemask, pCache->trans_color); while(nBox--) { xorg = (pBox->x1 - xorigin) & 0x07; yorg = (pBox->y1 - yorigin) & 0x07; if(!(infoRec->Color8x8PatternFillFlags & HARDWARE_PATTERN_PROGRAMMED_ORIGIN)){ int slot = (yorg << 3) + xorg; yorg = pCache->y + pCache->offsets[slot].y; xorg = pCache->x + pCache->offsets[slot].x; } (*infoRec->SubsequentColor8x8PatternFillRect)(pScrn, xorg, yorg, pBox->x1, pBox->y1, pBox->x2 - pBox->x1, pBox->y2 - pBox->y1); pBox++; } SET_SYNC_FLAG(infoRec); } /***************\ | Cache Blits | \***************/ void XAAFillCacheBltRects( ScrnInfoPtr pScrn, int rop, unsigned int planemask, int nBox, BoxPtr pBox, int xorg, int yorg, XAACacheInfoPtr pCache ){ XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); int x, y, phaseY, phaseX, skipleft, height, width, w, blit_w, blit_h; (*infoRec->SetupForScreenToScreenCopy)(pScrn, 1, 1, rop, planemask, pCache->trans_color); while(nBox--) { y = pBox->y1; phaseY = (y - yorg) % pCache->orig_h; if(phaseY < 0) phaseY += pCache->orig_h; phaseX = (pBox->x1 - xorg) % pCache->orig_w; if(phaseX < 0) phaseX += pCache->orig_w; height = pBox->y2 - y; width = pBox->x2 - pBox->x1; #if 0 if (rop == GXcopy) { while(1) { w = width; skipleft = phaseX; x = pBox->x1; blit_h = pCache->h - phaseY; if(blit_h > height) blit_h = height; while(1) { blit_w = pCache->w - skipleft; if(blit_w > w) blit_w = w; (*infoRec->SubsequentScreenToScreenCopy)(pScrn, pCache->x + skipleft, pCache->y + phaseY, x, y, blit_w, blit_h); w -= blit_w; if(!w) break; x += blit_w; skipleft = (skipleft + blit_w) % pCache->orig_w; if(blit_w >= pCache->orig_w) break; } /* Expand horizontally */ if (w) { skipleft -= phaseX; if (skipleft < 0) skipleft += pCache->orig_w; blit_w = x - pBox->x1 - skipleft; while(w) { if (blit_w > w) blit_w = w; (*infoRec->SubsequentScreenToScreenCopy)(pScrn, pBox->x1 + skipleft, y, x, y, blit_w, blit_h); w -= blit_w; x += blit_w; blit_w <<= 1; } } height -= blit_h; if(!height) break; y += blit_h; phaseY = (phaseY + blit_h) % pCache->orig_h; if(blit_h >= pCache->orig_h) break; } /* Expand vertically */ if (height) { blit_w = pBox->x2 - pBox->x1; phaseY -= (pBox->y1 - yorg) % pCache->orig_h; if (phaseY < 0) phaseY += pCache->orig_h; blit_h = y - pBox->y1 - phaseY; while(height) { if (blit_h > height) blit_h = height; (*infoRec->SubsequentScreenToScreenCopy)(pScrn, pBox->x1, pBox->y1 + phaseY, pBox->x1, y, blit_w, blit_h); height -= blit_h; y += blit_h; blit_h <<= 1; } } } else #endif { while(1) { w = width; skipleft = phaseX; x = pBox->x1; blit_h = pCache->h - phaseY; if(blit_h > height) blit_h = height; while(1) { blit_w = pCache->w - skipleft; if(blit_w > w) blit_w = w; (*infoRec->SubsequentScreenToScreenCopy)(pScrn, pCache->x + skipleft, pCache->y + phaseY, x, y, blit_w, blit_h); w -= blit_w; if(!w) break; x += blit_w; skipleft = (skipleft + blit_w) % pCache->orig_w; } height -= blit_h; if(!height) break; y += blit_h; phaseY = (phaseY + blit_h) % pCache->orig_h; } } pBox++; } SET_SYNC_FLAG(infoRec); } /*******************\ | Cache Expansion | \*******************/ void XAAFillCacheExpandRects( ScrnInfoPtr pScrn, int fg, int bg, int rop, unsigned int planemask, int nBox, BoxPtr pBox, int xorg, int yorg, PixmapPtr pPix ){ XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); int x, y, phaseY, phaseX, skipleft, height, width, w, blit_w, blit_h; int cacheWidth; XAACacheInfoPtr pCache; pCache = (*infoRec->CacheMonoStipple)(pScrn, pPix); cacheWidth = (pCache->w * pScrn->bitsPerPixel) / infoRec->CacheColorExpandDensity; (*infoRec->SetupForScreenToScreenColorExpandFill)(pScrn, fg, bg, rop, planemask); while(nBox--) { y = pBox->y1; phaseY = (y - yorg) % pCache->orig_h; if(phaseY < 0) phaseY += pCache->orig_h; phaseX = (pBox->x1 - xorg) % pCache->orig_w; if(phaseX < 0) phaseX += pCache->orig_w; height = pBox->y2 - y; width = pBox->x2 - pBox->x1; while(1) { w = width; skipleft = phaseX; x = pBox->x1; blit_h = pCache->h - phaseY; if(blit_h > height) blit_h = height; while(1) { blit_w = cacheWidth - skipleft; if(blit_w > w) blit_w = w; (*infoRec->SubsequentScreenToScreenColorExpandFill)( pScrn, x, y, blit_w, blit_h, pCache->x, pCache->y + phaseY, skipleft); w -= blit_w; if(!w) break; x += blit_w; skipleft = (skipleft + blit_w) % pCache->orig_w; } height -= blit_h; if(!height) break; y += blit_h; phaseY = (phaseY + blit_h) % pCache->orig_h; } pBox++; } SET_SYNC_FLAG(infoRec); } /******************\ | Image Writes | \******************/ /* This requires all LEFT_EDGE clipping. You get too many problems with reading past the edge of the pattern otherwise */ static void WriteColumn( ScrnInfoPtr pScrn, unsigned char *pSrc, int x, int y, int w, int h, int xoff, int yoff, int pHeight, int srcwidth, int Bpp ) { XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); unsigned char *src; Bool PlusOne = FALSE; int skipleft, dwords; pSrc += (Bpp * xoff); if((skipleft = (long)pSrc & 0x03L)) { if(Bpp == 3) skipleft = 4 - skipleft; else skipleft /= Bpp; x -= skipleft; w += skipleft; if(Bpp == 3) pSrc -= 3 * skipleft; else /* is this Alpha friendly ? */ pSrc = (unsigned char*)((long)pSrc & ~0x03L); } src = pSrc + (yoff * srcwidth); dwords = ((w * Bpp) + 3) >> 2; if((infoRec->ImageWriteFlags & CPU_TRANSFER_PAD_QWORD) && ((dwords * h) & 0x01)) { PlusOne = TRUE; } (*infoRec->SubsequentImageWriteRect)(pScrn, x, y, w, h, skipleft); if(dwords > infoRec->ImageWriteRange) { while(h--) { XAAMoveDWORDS_FixedBase((CARD32*)infoRec->ImageWriteBase, (CARD32*)src, dwords); src += srcwidth; yoff++; if(yoff >= pHeight) { yoff = 0; src = pSrc; } } } else { if(srcwidth == (dwords << 2)) { int maxLines = infoRec->ImageWriteRange/dwords; int step; while(h) { step = pHeight - yoff; if(step > maxLines) step = maxLines; if(step > h) step = h; XAAMoveDWORDS((CARD32*)infoRec->ImageWriteBase, (CARD32*)src, dwords * step); src += (srcwidth * step); yoff += step; if(yoff >= pHeight) { yoff = 0; src = pSrc; } h -= step; } } else { while(h--) { XAAMoveDWORDS((CARD32*)infoRec->ImageWriteBase, (CARD32*)src, dwords); src += srcwidth; yoff++; if(yoff >= pHeight) { yoff = 0; src = pSrc; } } } } if(PlusOne) { CARD32* base = (CARD32*)infoRec->ImageWriteBase; *base = 0x00000000; } } void XAAFillImageWriteRects( ScrnInfoPtr pScrn, int rop, unsigned int planemask, int nBox, BoxPtr pBox, int xorg, int yorg, PixmapPtr pPix ){ XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); int x, phaseY, phaseX, height, width, blit_w; int pHeight = pPix->drawable.height; int pWidth = pPix->drawable.width; int Bpp = pPix->drawable.bitsPerPixel >> 3; int srcwidth = pPix->devKind; (*infoRec->SetupForImageWrite)(pScrn, rop, planemask, -1, pPix->drawable.bitsPerPixel, pPix->drawable.depth); while(nBox--) { x = pBox->x1; phaseY = (pBox->y1 - yorg) % pHeight; if(phaseY < 0) phaseY += pHeight; phaseX = (x - xorg) % pWidth; if(phaseX < 0) phaseX += pWidth; height = pBox->y2 - pBox->y1; width = pBox->x2 - x; while(1) { blit_w = pWidth - phaseX; if(blit_w > width) blit_w = width; WriteColumn(pScrn, pPix->devPrivate.ptr, x, pBox->y1, blit_w, height, phaseX, phaseY, pHeight, srcwidth, Bpp); width -= blit_w; if(!width) break; x += blit_w; phaseX = (phaseX + blit_w) % pWidth; } pBox++; } if(infoRec->ImageWriteFlags & SYNC_AFTER_IMAGE_WRITE) (*infoRec->Sync)(pScrn); else SET_SYNC_FLAG(infoRec); } /*************\ | Utilities | \*************/ void XAAClipAndRenderRects( GCPtr pGC, ClipAndRenderRectsFunc BoxFunc, int nrectFill, xRectangle *prect, int xorg, int yorg ){ XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); int Right, Bottom, MaxBoxes; BoxPtr pextent, pboxClipped, pboxClippedBase; MaxBoxes = infoRec->PreAllocSize/sizeof(BoxRec); pboxClippedBase = (BoxPtr)infoRec->PreAllocMem; pboxClipped = pboxClippedBase; if (REGION_NUM_RECTS(pGC->pCompositeClip) == 1) { pextent = REGION_RECTS(pGC->pCompositeClip); while (nrectFill--) { pboxClipped->x1 = max(pextent->x1, prect->x); pboxClipped->y1 = max(pextent->y1, prect->y); Right = (int)prect->x + (int)prect->width; pboxClipped->x2 = min(pextent->x2, Right); Bottom = (int)prect->y + (int)prect->height; pboxClipped->y2 = min(pextent->y2, Bottom); prect++; if ((pboxClipped->x1 < pboxClipped->x2) && (pboxClipped->y1 < pboxClipped->y2)) { pboxClipped++; if(pboxClipped >= (pboxClippedBase + MaxBoxes)) { (*BoxFunc)(pGC, MaxBoxes, pboxClippedBase, xorg, yorg); pboxClipped = pboxClippedBase; } } } } else { pextent = REGION_EXTENTS(pGC->pScreen, pGC->pCompositeClip); while (nrectFill--) { int n; BoxRec box, *pbox; box.x1 = max(pextent->x1, prect->x); box.y1 = max(pextent->y1, prect->y); Right = (int)prect->x + (int)prect->width; box.x2 = min(pextent->x2, Right); Bottom = (int)prect->y + (int)prect->height; box.y2 = min(pextent->y2, Bottom); prect++; if ((box.x1 >= box.x2) || (box.y1 >= box.y2)) continue; n = REGION_NUM_RECTS (pGC->pCompositeClip); pbox = REGION_RECTS(pGC->pCompositeClip); /* clip the rectangle to each box in the clip region this is logically equivalent to calling Intersect() */ while(n--) { pboxClipped->x1 = max(box.x1, pbox->x1); pboxClipped->y1 = max(box.y1, pbox->y1); pboxClipped->x2 = min(box.x2, pbox->x2); pboxClipped->y2 = min(box.y2, pbox->y2); pbox++; /* see if clipping left anything */ if(pboxClipped->x1 < pboxClipped->x2 && pboxClipped->y1 < pboxClipped->y2) { pboxClipped++; if(pboxClipped >= (pboxClippedBase + MaxBoxes)) { (*BoxFunc)(pGC, MaxBoxes, pboxClippedBase, xorg, yorg); pboxClipped = pboxClippedBase; } } } } } if(pboxClipped != pboxClippedBase) (*BoxFunc)(pGC, pboxClipped - pboxClippedBase, pboxClippedBase, xorg, yorg); } int XAAGetRectClipBoxes( GCPtr pGC, BoxPtr pboxClippedBase, int nrectFill, xRectangle *prectInit ){ int Right, Bottom; BoxPtr pextent, pboxClipped = pboxClippedBase; xRectangle *prect = prectInit; RegionPtr prgnClip = pGC->pCompositeClip; if (REGION_NUM_RECTS(prgnClip) == 1) { pextent = REGION_RECTS(prgnClip); while (nrectFill--) { pboxClipped->x1 = max(pextent->x1, prect->x); pboxClipped->y1 = max(pextent->y1, prect->y); Right = (int)prect->x + (int)prect->width; pboxClipped->x2 = min(pextent->x2, Right); Bottom = (int)prect->y + (int)prect->height; pboxClipped->y2 = min(pextent->y2, Bottom); prect++; if ((pboxClipped->x1 < pboxClipped->x2) && (pboxClipped->y1 < pboxClipped->y2)) { pboxClipped++; } } } else { pextent = REGION_EXTENTS(pGC->pScreen, prgnClip); while (nrectFill--) { int n; BoxRec box, *pbox; box.x1 = max(pextent->x1, prect->x); box.y1 = max(pextent->y1, prect->y); Right = (int)prect->x + (int)prect->width; box.x2 = min(pextent->x2, Right); Bottom = (int)prect->y + (int)prect->height; box.y2 = min(pextent->y2, Bottom); prect++; if ((box.x1 >= box.x2) || (box.y1 >= box.y2)) continue; n = REGION_NUM_RECTS (prgnClip); pbox = REGION_RECTS(prgnClip); /* clip the rectangle to each box in the clip region this is logically equivalent to calling Intersect() */ while(n--) { pboxClipped->x1 = max(box.x1, pbox->x1); pboxClipped->y1 = max(box.y1, pbox->y1); pboxClipped->x2 = min(box.x2, pbox->x2); pboxClipped->y2 = min(box.y2, pbox->y2); pbox++; /* see if clipping left anything */ if(pboxClipped->x1 < pboxClipped->x2 && pboxClipped->y1 < pboxClipped->y2) { pboxClipped++; } } } } return(pboxClipped - pboxClippedBase); }