#ifdef HAVE_XORG_CONFIG_H #include #endif #include #include #include #include "servermd.h" #include "scrnintstr.h" #include "pixmapstr.h" #include "resource.h" #include "colormap.h" #include "colormapst.h" #define PSZ 8 #include "cfb.h" #undef PSZ #include "cfb32.h" #include "cfb8_32.h" #include "mi.h" #include "mistruct.h" #include "dix.h" #include "mibstore.h" RegionPtr cfb8_32CopyArea( DrawablePtr pSrcDraw, DrawablePtr pDstDraw, GC *pGC, int srcx, int srcy, int width, int height, int dstx, int dsty ){ if(pSrcDraw->bitsPerPixel == 32) { if(pDstDraw->bitsPerPixel == 32) { if((pGC->alu == GXcopy) && (pGC->planemask == 0xff000000)) { return cfb32BitBlt (pSrcDraw, pDstDraw, pGC, srcx, srcy, width, height, dstx, dsty, cfbDoBitblt8To8GXcopy, 0L); } return(cfb32CopyArea(pSrcDraw, pDstDraw, pGC, srcx, srcy, width, height, dstx, dsty)); } else { /* have to translate 32 -> 8 copies */ return cfb32BitBlt (pSrcDraw, pDstDraw, pGC, srcx, srcy, width, height, dstx, dsty, cfbDoBitblt32To8, 0L); } } else { if(pDstDraw->bitsPerPixel == 32) { /* have to translate 8 -> 32 copies */ return cfb32BitBlt (pSrcDraw, pDstDraw, pGC, srcx, srcy, width, height, dstx, dsty, cfbDoBitblt8To32, 0L); } else { return(cfbCopyArea(pSrcDraw, pDstDraw, pGC, srcx, srcy, width, height, dstx, dsty)); } } } void cfbDoBitblt8To32( DrawablePtr pSrc, DrawablePtr pDst, int rop, RegionPtr prgnDst, DDXPointPtr pptSrc, unsigned long pm ){ BoxPtr pbox = REGION_RECTS(prgnDst); int nbox = REGION_NUM_RECTS(prgnDst); unsigned char *ptr8, *ptr32; unsigned char *data8, *data32; int pitch8, pitch32; int height, width, i; cfbGetByteWidthAndPointer(pSrc, pitch8, ptr8); cfbGetByteWidthAndPointer(pDst, pitch32, ptr32); ptr32 += 3; /* point to the top byte */ pm >>= 24; if((pm == 0xff) && (rop == GXcopy)) { for(;nbox; pbox++, pptSrc++, nbox--) { data8 = ptr8 + (pptSrc->y * pitch8) + pptSrc->x; data32 = ptr32 + (pbox->y1 * pitch32) + (pbox->x1 << 2); width = pbox->x2 - pbox->x1; height = pbox->y2 - pbox->y1; while(height--) { for(i = 0; i < width; i++) data32[i << 2] = data8[i]; data8 += pitch8; data32 += pitch32; } } } else { /* it ain't pretty, but hey */ for(;nbox; pbox++, pptSrc++, nbox--) { data8 = ptr8 + (pptSrc->y * pitch8) + pptSrc->x; data32 = ptr32 + (pbox->y1 * pitch32) + (pbox->x1 << 2); width = pbox->x2 - pbox->x1; height = pbox->y2 - pbox->y1; while(height--) { switch(rop) { case GXcopy: for(i = 0; i < width; i++) data32[i<<2] = (data8[i] & pm) | (data32[i<<2] & ~pm); break; case GXor: for(i = 0; i < width; i++) data32[i<<2] |= data8[i] & pm; break; case GXclear: for(i = 0; i < width; i++) data32[i<<2] &= ~pm; break; case GXand: for(i = 0; i < width; i++) data32[i<<2] &= data8[i] | ~pm; break; case GXandReverse: for(i = 0; i < width; i++) data32[i<<2] = ~data32[i<<2] & (data8[i] | ~pm); break; case GXandInverted: for(i = 0; i < width; i++) data32[i<<2] &= ~data8[i] | ~pm; break; case GXnoop: return; case GXxor: for(i = 0; i < width; i++) data32[i<<2] ^= data8[i] & pm; break; case GXnor: for(i = 0; i < width; i++) data32[i<<2] = ~(data32[i<<2] | (data8[i] & pm)); break; case GXequiv: for(i = 0; i < width; i++) data32[i<<2] = ~(data32[i<<2] ^ (data8[i] & pm)); break; case GXinvert: for(i = 0; i < width; i++) data32[i<<2] ^= pm; break; case GXorReverse: for(i = 0; i < width; i++) data32[i<<2] = ~data32[i<<2] | (data8[i] & pm); break; case GXcopyInverted: for(i = 0; i < width; i++) data32[i<<2] = (~data8[i] & pm) | (data32[i<<2] & ~pm); break; case GXorInverted: for(i = 0; i < width; i++) data32[i<<2] |= ~data8[i] & pm; break; case GXnand: for(i = 0; i < width; i++) data32[i<<2] = ~(data32[i<<2] & (data8[i] | ~pm)); break; case GXset: for(i = 0; i < width; i++) data32[i<<2] |= pm; break; } data8 += pitch8; data32 += pitch32; } } } } void cfbDoBitblt32To8( DrawablePtr pSrc, DrawablePtr pDst, int rop, RegionPtr prgnDst, DDXPointPtr pptSrc, unsigned long pm ){ BoxPtr pbox = REGION_RECTS(prgnDst); int nbox = REGION_NUM_RECTS(prgnDst); unsigned char *ptr8, *ptr32; unsigned char *data8, *data32; int pitch8, pitch32; int height, width, i; cfbGetByteWidthAndPointer(pDst, pitch8, ptr8); cfbGetByteWidthAndPointer(pSrc, pitch32, ptr32); ptr32 += 3; /* point to the top byte */ if(((pm & 0xff) == 0xff) && (rop == GXcopy)) { for(;nbox; pbox++, pptSrc++, nbox--) { data8 = ptr8 + (pbox->y1 * pitch8) + pbox->x1; data32 = ptr32 + (pptSrc->y * pitch32) + (pptSrc->x << 2); width = pbox->x2 - pbox->x1; height = pbox->y2 - pbox->y1; while(height--) { for(i = 0; i < width; i++) data8[i] = data32[i << 2]; data8 += pitch8; data32 += pitch32; } } } else { for(;nbox; pbox++, pptSrc++, nbox--) { data8 = ptr8 + (pbox->y1 * pitch8) + pbox->x1; data32 = ptr32 + (pptSrc->y * pitch32) + (pptSrc->x << 2); width = pbox->x2 - pbox->x1; height = pbox->y2 - pbox->y1; while(height--) { switch(rop) { case GXcopy: for(i = 0; i < width; i++) data8[i] = (data32[i<<2] & pm) | (data8[i] & ~pm); break; case GXor: for(i = 0; i < width; i++) data8[i] |= data32[i<<2] & pm; break; case GXclear: for(i = 0; i < width; i++) data8[i] &= ~pm; break; case GXand: for(i = 0; i < width; i++) data8[i] &= data32[i<<2] | ~pm; break; case GXandReverse: for(i = 0; i < width; i++) data8[i] = ~data8[i] & (data32[i<<2] | ~pm); break; case GXandInverted: for(i = 0; i < width; i++) data8[i] &= ~data32[i<<2] | ~pm; break; case GXnoop: return; case GXxor: for(i = 0; i < width; i++) data8[i] ^= data32[i<<2] & pm; break; case GXnor: for(i = 0; i < width; i++) data8[i] = ~(data8[i] | (data32[i<<2] & pm)); break; case GXequiv: for(i = 0; i < width; i++) data8[i] = ~(data8[i] ^ (data32[i<<2] & pm)); break; case GXinvert: for(i = 0; i < width; i++) data8[i] ^= pm; break; case GXorReverse: for(i = 0; i < width; i++) data8[i] = ~data8[i] | (data32[i<<2] & pm); break; case GXcopyInverted: for(i = 0; i < width; i++) data8[i] = (~data32[i<<2] & pm) | (data8[i] & ~pm); break; case GXorInverted: for(i = 0; i < width; i++) data8[i] |= ~data32[i<<2] & pm; break; case GXnand: for(i = 0; i < width; i++) data8[i] = ~(data8[i] & (data32[i<<2] | ~pm)); break; case GXset: for(i = 0; i < width; i++) data8[i] |= pm; break; } data8 += pitch8; data32 += pitch32; } } } } static void Do8To8Blt( unsigned char *SrcPtr, int SrcPitch, unsigned char *DstPtr, int DstPitch, int nbox, DDXPointPtr pptSrc, BoxPtr pbox, int xdir, int ydir ){ int i, j, width, height, ydir2; CARD8 *src, *dst; SrcPtr += 3; DstPtr += 3; xdir *= 4; ydir2 = ydir * DstPitch; ydir *= SrcPitch; for(;nbox; pbox++, pptSrc++, nbox--) { src = SrcPtr + (pptSrc->y * SrcPitch) + (pptSrc->x << 2); dst = DstPtr + (pbox->y1 * DstPitch) + (pbox->x1 << 2); width = pbox->x2 - pbox->x1; height = pbox->y2 - pbox->y1; if(ydir < 0) { src += (height - 1) * SrcPitch; dst += (height - 1) * DstPitch; } if(xdir < 0) { register int tmp = (width - 1) << 2; src += tmp; dst += tmp; } while(height--) { for(i = width, j = 0; i--; j+=xdir) dst[j] = src[j]; src += ydir; dst += ydir2; } } } static void Do24To24Blt( unsigned char *SrcPtr, int SrcPitch, unsigned char *DstPtr, int DstPitch, int nbox, DDXPointPtr pptSrc, BoxPtr pbox, int xdir, int ydir ){ int i, j, width, height, ydir2; CARD8 *src, *dst; xdir *= 4; ydir2 = ydir * DstPitch; ydir *= SrcPitch; for(;nbox; pbox++, pptSrc++, nbox--) { src = SrcPtr + (pptSrc->y * SrcPitch) + (pptSrc->x << 2); dst = DstPtr + (pbox->y1 * DstPitch) + (pbox->x1 << 2); width = pbox->x2 - pbox->x1; height = pbox->y2 - pbox->y1; if(ydir < 0) { src += (height - 1) * SrcPitch; dst += (height - 1) * DstPitch; } if(xdir < 0) { register int tmp = (width - 1) << 2; src += tmp; dst += tmp; } while(height--) { for(i = width, j = 0; i--; j+=xdir) { *((CARD16*)(dst + j)) = *((CARD32*)(src + j)); dst[j + 2] = src[j + 2]; } src += ydir; dst += ydir2; } } } static void cfb8_32DoBitBlt( DrawablePtr pSrc, DrawablePtr pDst, RegionPtr prgnDst, DDXPointPtr pptSrc, void (*DoBlt)( unsigned char *SrcPtr, int SrcPitch, unsigned char *DstPtr, int DstPitch, int nbox, DDXPointPtr pptSrc, BoxPtr pbox, int xdir, int ydir) ){ int nbox, careful, SrcPitch, DstPitch; BoxPtr pbox, pboxTmp, pboxNext, pboxBase, pboxNew1, pboxNew2; DDXPointPtr pptTmp, pptNew1, pptNew2; int xdir, ydir; unsigned char *SrcPtr, *DstPtr; /* XXX we have to err on the side of safety when both are windows, * because we don't know if IncludeInferiors is being used. */ careful = ((pSrc == pDst) || ((pSrc->type == DRAWABLE_WINDOW) && (pDst->type == DRAWABLE_WINDOW))); pbox = REGION_RECTS(prgnDst); nbox = REGION_NUM_RECTS(prgnDst); pboxNew1 = NULL; pptNew1 = NULL; pboxNew2 = NULL; pptNew2 = NULL; if (careful && (pptSrc->y < pbox->y1)) { /* walk source botttom to top */ ydir = -1; if (nbox > 1) { /* keep ordering in each band, reverse order of bands */ pboxNew1 = (BoxPtr)ALLOCATE_LOCAL(sizeof(BoxRec) * nbox); if(!pboxNew1) return; pptNew1 = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec) * nbox); if(!pptNew1) { DEALLOCATE_LOCAL(pboxNew1); return; } pboxBase = pboxNext = pbox+nbox-1; while (pboxBase >= pbox) { while ((pboxNext >= pbox) && (pboxBase->y1 == pboxNext->y1)) pboxNext--; pboxTmp = pboxNext+1; pptTmp = pptSrc + (pboxTmp - pbox); while (pboxTmp <= pboxBase) { *pboxNew1++ = *pboxTmp++; *pptNew1++ = *pptTmp++; } pboxBase = pboxNext; } pboxNew1 -= nbox; pbox = pboxNew1; pptNew1 -= nbox; pptSrc = pptNew1; } } else { /* walk source top to bottom */ ydir = 1; } if (careful && (pptSrc->x < pbox->x1)) { /* walk source right to left */ xdir = -1; if (nbox > 1) { /* reverse order of rects in each band */ pboxNew2 = (BoxPtr)ALLOCATE_LOCAL(sizeof(BoxRec) * nbox); pptNew2 = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec) * nbox); if(!pboxNew2 || !pptNew2) { if (pptNew2) DEALLOCATE_LOCAL(pptNew2); if (pboxNew2) DEALLOCATE_LOCAL(pboxNew2); if (pboxNew1) { DEALLOCATE_LOCAL(pptNew1); DEALLOCATE_LOCAL(pboxNew1); } return; } pboxBase = pboxNext = pbox; while (pboxBase < pbox+nbox) { while ((pboxNext < pbox+nbox) && (pboxNext->y1 == pboxBase->y1)) pboxNext++; pboxTmp = pboxNext; pptTmp = pptSrc + (pboxTmp - pbox); while (pboxTmp != pboxBase) { *pboxNew2++ = *--pboxTmp; *pptNew2++ = *--pptTmp; } pboxBase = pboxNext; } pboxNew2 -= nbox; pbox = pboxNew2; pptNew2 -= nbox; pptSrc = pptNew2; } } else { /* walk source left to right */ xdir = 1; } cfbGetByteWidthAndPointer(pSrc, SrcPitch, SrcPtr); cfbGetByteWidthAndPointer(pDst, DstPitch, DstPtr); (*DoBlt)(SrcPtr,SrcPitch,DstPtr,DstPitch,nbox,pptSrc,pbox,xdir,ydir); if (pboxNew2) { DEALLOCATE_LOCAL(pptNew2); DEALLOCATE_LOCAL(pboxNew2); } if (pboxNew1) { DEALLOCATE_LOCAL(pptNew1); DEALLOCATE_LOCAL(pboxNew1); } } /* A couple routines to speed up full planemask copies */ void cfbDoBitblt8To8GXcopy( DrawablePtr pSrc, DrawablePtr pDst, int rop, RegionPtr prgnDst, DDXPointPtr pptSrc, unsigned long pm ){ cfb8_32DoBitBlt(pSrc, pDst, prgnDst, pptSrc, Do8To8Blt); } void cfbDoBitblt24To24GXcopy( DrawablePtr pSrc, DrawablePtr pDst, int rop, RegionPtr prgnDst, DDXPointPtr pptSrc, unsigned long pm ){ cfb8_32DoBitBlt(pSrc, pDst, prgnDst, pptSrc, Do24To24Blt); }