void cfbDoBitblt8To32( DrawablePtr pSrc, DrawablePtr pDst, int rop, RegionPtr prgnDst, DDXPointPtr pptSrc, unsigned long pm, unsigned long bitPlane ){ 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; } } } }
RegionPtr CreatorCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, int srcx, int srcy, int width, int height, int dstx, int dsty) { FFBPtr pFfb = GET_FFB_FROM_SCREEN (pDstDrawable->pScreen); ffb_fbcPtr ffb = pFfb->regs; RegionPtr ret; unsigned char *dptr, *sptr, *sfb; int garbage, all_planes; cfbGetByteWidthAndPointer (pDstDrawable, garbage, dptr); cfbGetByteWidthAndPointer (pSrcDrawable, garbage, sptr); if (pSrcDrawable->bitsPerPixel == 8) { sfb = (unsigned char *) pFfb->sfb8r; all_planes = 0xff; } else { sfb = (unsigned char *) pFfb->sfb32; all_planes = 0xffffff; } FFBLOG(("CreatorCopyArea: SFB(%p) s(%p) d(%p) alu(%x) pmsk(%08x) " "src(%08x:%08x) dst(%08x:%08x)\n", sfb, sptr, dptr, pGC->alu, pGC->planemask, srcx, srcy, dstx, dsty)); if (((pGC->planemask & all_planes) != all_planes || pGC->alu != GXcopy) && dptr != sfb) { if(sptr == sfb) { WindowPtr pWin = (WindowPtr) pSrcDrawable; FFB_ATTR_SFB_VAR_WIN(pFfb, pGC->planemask, pGC->alu, pWin); FFBWait(pFfb, ffb); } if (pSrcDrawable->bitsPerPixel == 8) return cfbCopyArea (pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty); else return cfb32CopyArea (pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty); } /* Try to use hw VSCROLL if possible */ if (!pFfb->disable_vscroll && /* must not be ffb1 in hires */ pGC->alu == GXcopy && /* it must be a copy */ dstx == srcx && /* X must be unchanging */ dsty != srcy && /* Y must be changing */ sptr == dptr && /* src and dst must be the framebuffer */ dptr == sfb) { WindowPtr pWin = (WindowPtr) pSrcDrawable; CreatorPrivWinPtr pFfbPrivWin = CreatorGetWindowPrivate(pWin); unsigned int fbc = pFfbPrivWin->fbc_base; int same_buffer; /* One last check, the read buffer and the write buffer * must be the same. VSCROLL only allows to move pixels * within the same buffer. */ if (!pFfb->has_double_buffer) { same_buffer = 1; } else { same_buffer = 0; if ((((fbc & FFB_FBC_WB_MASK) == FFB_FBC_WB_A) && ((fbc & FFB_FBC_RB_MASK) == FFB_FBC_RB_A)) || (((fbc & FFB_FBC_WB_MASK) == FFB_FBC_WB_B) && ((fbc & FFB_FBC_RB_MASK) == FFB_FBC_RB_B))) same_buffer = 1; } if (same_buffer != 0) { FFB_ATTR_VSCROLL_WIN(pFfb, pGC->planemask, pWin); if (pSrcDrawable->bitsPerPixel == 8) ret = cfbBitBlt (pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty, (void (*)())CreatorDoVertBitblt, 0); else ret = cfb32BitBlt (pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty, (void (*)())CreatorDoVertBitblt, 0); FFBLOG(("CreatorCopyArea: Done, returning %p\n", ret)); return ret; } } /* OK, we have to use GCOPY. */ /* Even when we are only reading from the framebuffer, we must * set the SFB_VAR attributes to handle double-buffering correctly. */ if(dptr == sfb || sptr == sfb) { WindowPtr pWin; if (dptr == sfb) pWin = (WindowPtr) pDstDrawable; else pWin = (WindowPtr) pSrcDrawable; FFB_ATTR_SFB_VAR_WIN(pFfb, pGC->planemask, pGC->alu, pWin); FFBWait(pFfb, ffb); } if (pSrcDrawable->bitsPerPixel == 8) ret = cfbBitBlt (pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty, (void (*)())CreatorDoBitblt, 0); else ret = cfb32BitBlt (pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty, (void (*)())CreatorDoBitblt, 0); FFBLOG(("CreatorCopyArea: Done, returning %p\n", ret)); return ret; }
static void cfb8_32DoBitBlt( DrawablePtr pSrc, DrawablePtr pDst, RegionPtr prgnDst, DDXPointPtr pptSrc, void (*DoBlt)() ){ 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); } }
/* The hw attributes have been set by someone higher up in the call * chain. */ void CreatorDoBitblt(DrawablePtr pSrc, DrawablePtr pDst, int alu, RegionPtr prgnDst, DDXPointPtr pptSrc, unsigned long planemask) { FFBPtr pFfb = GET_FFB_FROM_SCREEN (pDst->pScreen); BoxPtr pboxTmp, pboxNext, pboxBase, pbox; DDXPointPtr pptTmp; unsigned char *psrcBase, *pdstBase; int nbox, widthSrc, widthDst, careful, use_prefetch; int psz_shift; cfbGetByteWidthAndPointer (pSrc, widthSrc, psrcBase) cfbGetByteWidthAndPointer (pDst, widthDst, pdstBase) careful = ((pSrc == pDst) || ((pSrc->type == DRAWABLE_WINDOW) && (pDst->type == DRAWABLE_WINDOW))); use_prefetch = (pFfb->use_blkread_prefetch && (psrcBase == (unsigned char *)pFfb->sfb32 || psrcBase == (unsigned char *)pFfb->sfb8r)); pbox = REGION_RECTS(prgnDst); nbox = REGION_NUM_RECTS(prgnDst); pptTmp = pptSrc; pboxTmp = pbox; FFBLOG(("GCOPY(%d): ", nbox)); if (pSrc->bitsPerPixel == 8) psz_shift = 0; else psz_shift = 2; if (careful && pptSrc->y < pbox->y1) { if (pptSrc->x < pbox->x1) { /* reverse order of bands and rects in each band */ pboxTmp=pbox+nbox; pptTmp=pptSrc+nbox; while (nbox--){ pboxTmp--; pptTmp--; FFBLOG(("[%08x:%08x:%08x:%08x:%08x:%08x] ", pptTmp->x, pptTmp->y, pboxTmp->x1, pboxTmp->y1, pboxTmp->x2, pboxTmp->y2)); if (pptTmp->x < pbox->x2) { if (use_prefetch) { FFBFifo(pFfb, 1); pFfb->regs->mer = FFB_MER_EDRA; pFfb->rp_active = 1; FFBWait(pFfb, pFfb->regs); } VISmoveImageRL ((psrcBase + ((pptTmp->y + pboxTmp->y2 - pboxTmp->y1 - 1) * widthSrc) + (pptTmp->x << psz_shift)), (pdstBase + ((pboxTmp->y2 - 1) * widthDst) + (pboxTmp->x1 << psz_shift)), (pboxTmp->x2 - pboxTmp->x1) << psz_shift, (pboxTmp->y2 - pboxTmp->y1), -widthSrc, -widthDst); } else { if (use_prefetch) { FFBFifo(pFfb, 1); pFfb->regs->mer = FFB_MER_EIRA; pFfb->rp_active = 1; FFBWait(pFfb, pFfb->regs); } VISmoveImageLR ((psrcBase + ((pptTmp->y + pboxTmp->y2 - pboxTmp->y1 - 1) * widthSrc) + (pptTmp->x << psz_shift)), (pdstBase + ((pboxTmp->y2 - 1) * widthDst) + (pboxTmp->x1 << psz_shift)), (pboxTmp->x2 - pboxTmp->x1) << psz_shift, (pboxTmp->y2 - pboxTmp->y1), -widthSrc, -widthDst); } } } else { /* keep ordering in each band, reverse order of bands */ pboxBase = pboxNext = pbox+nbox-1; while (pboxBase >= pbox) { /* for each band */ /* find first box in band */ while (pboxNext >= pbox && pboxBase->y1 == pboxNext->y1) pboxNext--; pboxTmp = pboxNext+1; /* first box in band */ pptTmp = pptSrc + (pboxTmp - pbox); /* first point in band */ FFBLOG(("[%08x:%08x:%08x:%08x:%08x:%08x] ", pptTmp->x, pptTmp->y, pboxTmp->x1, pboxTmp->y1, pboxTmp->x2, pboxTmp->y2)); while (pboxTmp <= pboxBase) { /* for each box in band */ if (use_prefetch) { FFBFifo(pFfb, 1); pFfb->regs->mer = FFB_MER_EIRA; pFfb->rp_active = 1; FFBWait(pFfb, pFfb->regs); } VISmoveImageLR ((psrcBase + ((pptTmp->y + pboxTmp->y2 - pboxTmp->y1 - 1) * widthSrc) + (pptTmp->x << psz_shift)), (pdstBase + ((pboxTmp->y2 - 1) * widthDst) + (pboxTmp->x1 << psz_shift)), (pboxTmp->x2 - pboxTmp->x1) << psz_shift, (pboxTmp->y2 - pboxTmp->y1), -widthSrc, -widthDst); ++pboxTmp; ++pptTmp; } pboxBase = pboxNext; } } } else { if (careful && pptSrc->x < pbox->x1) { /* reverse order of rects in each band */ pboxBase = pboxNext = pbox; while (pboxBase < pbox+nbox) { /* for each band */ /* find last box in band */ while (pboxNext < pbox+nbox && pboxNext->y1 == pboxBase->y1) pboxNext++; pboxTmp = pboxNext; /* last box in band */ pptTmp = pptSrc + (pboxTmp - pbox); /* last point in band */ while (pboxTmp != pboxBase) { /* for each box in band */ --pboxTmp; --pptTmp; FFBLOG(("[%08x:%08x:%08x:%08x:%08x:%08x] ", pptTmp->x, pptTmp->y, pboxTmp->x1, pboxTmp->y1, pboxTmp->x2, pboxTmp->y2)); if (pptTmp->x < pbox->x2) { if (use_prefetch) { FFBFifo(pFfb, 1); pFfb->regs->mer = FFB_MER_EDRA; pFfb->regs->mer = FFB_MER_EIRA; pFfb->rp_active = 1; } VISmoveImageRL ((psrcBase + (pptTmp->y * widthSrc) + (pptTmp->x << psz_shift)), (pdstBase + (pboxTmp->y1 * widthDst) + (pboxTmp->x1 << psz_shift)), (pboxTmp->x2 - pboxTmp->x1) << psz_shift, (pboxTmp->y2 - pboxTmp->y1), widthSrc, widthDst); } else { if (use_prefetch) { FFBFifo(pFfb, 1); pFfb->regs->mer = FFB_MER_EIRA; pFfb->rp_active = 1; FFBWait(pFfb, pFfb->regs); } VISmoveImageLR ((psrcBase + (pptTmp->y * widthSrc) + (pptTmp->x << psz_shift)), (pdstBase + (pboxTmp->y1 * widthDst) + (pboxTmp->x1 << psz_shift)), (pboxTmp->x2 - pboxTmp->x1) << psz_shift, (pboxTmp->y2 - pboxTmp->y1), widthSrc, widthDst); } } pboxBase = pboxNext; } } else { while (nbox--) { FFBLOG(("[%08x:%08x:%08x:%08x:%08x:%08x] ", pptTmp->x, pptTmp->y, pboxTmp->x1, pboxTmp->y1, pboxTmp->x2, pboxTmp->y2)); if (use_prefetch) { FFBFifo(pFfb, 1); pFfb->regs->mer = FFB_MER_EIRA; pFfb->rp_active = 1; FFBWait(pFfb, pFfb->regs); } VISmoveImageLR ((psrcBase + (pptTmp->y * widthSrc) + (pptTmp->x << psz_shift)), (pdstBase + (pboxTmp->y1 * widthDst) + (pboxTmp->x1 << psz_shift)), (pboxTmp->x2 - pboxTmp->x1) << psz_shift, (pboxTmp->y2 - pboxTmp->y1), widthSrc, widthDst); pboxTmp++; pptTmp++; } } } if (use_prefetch) { FFBFifo(pFfb, 1); pFfb->regs->mer = FFB_MER_DRA; pFfb->rp_active = 1; FFBWait(pFfb, pFfb->regs); } FFBLOG(("done\n")); }