#ifdef HAVE_XORG_CONFIG_H
#include <xorg-config.h>
#endif
#include <stdlib.h>
#include "xf4bpp.h"
#include "mfbmap.h"
#define PSZ 8
#include "mfb.h"
#include "mergerop.h"
#include "mi.h"
#include "pixmapstr.h"
#include "scrnintstr.h"
static void
vga16DoBitblt
(
DrawablePtr pSrc,
DrawablePtr pDst,
int alu,
RegionPtr prgnDst,
DDXPointPtr pptSrc,
unsigned long planemask
)
{
int widthSrc, widthDst;
BoxPtr pbox;
int nbox;
BoxPtr pboxTmp, pboxNext, pboxBase, pboxNew1, pboxNew2;
DDXPointPtr pptTmp, pptNew1, pptNew2;
int w, h;
int careful;
widthSrc = mfbGetPixelWidth(pSrc);
widthDst = mfbGetPixelWidth(pDst);
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))
{
widthSrc = -widthSrc;
widthDst = -widthDst;
if (nbox > 1)
{
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;
}
}
if (careful && (pptSrc->x < pbox->x1))
{
if (nbox > 1)
{
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;
}
}
while(nbox--)
{
w = pbox->x2 - pbox->x1;
h = pbox->y2 - pbox->y1;
if( pSrc->type == DRAWABLE_WINDOW )
xf4bppBitBlt( (WindowPtr)pDst, alu, planemask,
pptSrc->x,
pptSrc->y,
pbox->x1,
pbox->y1,
w, h );
else
xf4bppDrawColorImage( (WindowPtr)pDst,
pbox->x1, pbox->y1,
w,
h,
((unsigned char *)((PixmapPtr)pSrc)->devPrivate.ptr
+ pptSrc->x + (pptSrc->y*((PixmapPtr)pSrc)->devKind)),
((PixmapPtr)pSrc)->devKind,
alu, planemask ) ;
pbox++;
pptSrc++;
}
if (pboxNew2)
{
DEALLOCATE_LOCAL(pptNew2);
DEALLOCATE_LOCAL(pboxNew2);
}
if (pboxNew1)
{
DEALLOCATE_LOCAL(pptNew1);
DEALLOCATE_LOCAL(pboxNew1);
}
}
RegionPtr
xf4bppCopyArea(pSrcDrawable, pDstDrawable,
pGC, srcx, srcy, width, height, dstx, dsty)
register DrawablePtr pSrcDrawable;
register DrawablePtr pDstDrawable;
register GC *pGC;
int srcx, srcy;
int width, height;
int dstx, dsty;
{
RegionPtr prgnSrcClip = NULL;
Bool freeSrcClip = FALSE;
RegionPtr prgnExposed;
RegionRec rgnDst;
DDXPointPtr pptSrc;
register DDXPointPtr ppt;
register BoxPtr pbox;
int i;
register int dx;
register int dy;
xRectangle origSource;
DDXPointRec origDest;
int numRects;
BoxRec fastBox;
int fastClip = 0;
int fastExpose = 0;
if ( pDstDrawable->type != DRAWABLE_WINDOW )
return miCopyArea( pSrcDrawable, pDstDrawable, pGC,
srcx, srcy, width, height, dstx, dsty ) ;
origSource.x = srcx;
origSource.y = srcy;
origSource.width = width;
origSource.height = height;
origDest.x = dstx;
origDest.y = dsty;
if ((pSrcDrawable != pDstDrawable) &&
pSrcDrawable->pScreen->SourceValidate)
{
(*pSrcDrawable->pScreen->SourceValidate) (pSrcDrawable, srcx, srcy, width, height);
}
srcx += pSrcDrawable->x;
srcy += pSrcDrawable->y;
if (pSrcDrawable->type == DRAWABLE_PIXMAP)
{
if ((pSrcDrawable == pDstDrawable) &&
(pGC->clientClipType == CT_NONE))
{
prgnSrcClip = pGC->pCompositeClip;
}
else
{
fastClip = 1;
}
}
else
{
if (pGC->subWindowMode == IncludeInferiors)
{
if (!((WindowPtr) pSrcDrawable)->parent)
{
fastClip = 1;
}
else if ((pSrcDrawable == pDstDrawable) &&
(pGC->clientClipType == CT_NONE))
{
prgnSrcClip = pGC->pCompositeClip;
}
else
{
prgnSrcClip = NotClippedByChildren((WindowPtr)pSrcDrawable);
freeSrcClip = TRUE;
}
}
else
{
prgnSrcClip = &((WindowPtr)pSrcDrawable)->clipList;
}
}
fastBox.x1 = srcx;
fastBox.y1 = srcy;
fastBox.x2 = srcx + width;
fastBox.y2 = srcy + height;
if (fastClip)
{
fastExpose = 1;
if (fastBox.x1 < pSrcDrawable->x)
{
fastBox.x1 = pSrcDrawable->x;
fastExpose = 0;
}
if (fastBox.y1 < pSrcDrawable->y)
{
fastBox.y1 = pSrcDrawable->y;
fastExpose = 0;
}
if (fastBox.x2 > pSrcDrawable->x + (int) pSrcDrawable->width)
{
fastBox.x2 = pSrcDrawable->x + (int) pSrcDrawable->width;
fastExpose = 0;
}
if (fastBox.y2 > pSrcDrawable->y + (int) pSrcDrawable->height)
{
fastBox.y2 = pSrcDrawable->y + (int) pSrcDrawable->height;
fastExpose = 0;
}
}
else
{
REGION_INIT(pGC->pScreen, &rgnDst, &fastBox, 1);
REGION_INTERSECT(pGC->pScreen, &rgnDst, &rgnDst, prgnSrcClip);
}
dstx += pDstDrawable->x;
dsty += pDstDrawable->y;
if (pDstDrawable->type == DRAWABLE_WINDOW)
{
if (!((WindowPtr)pDstDrawable)->realized)
{
if (!fastClip)
REGION_UNINIT(pGC->pScreen, &rgnDst);
if (freeSrcClip)
REGION_DESTROY(pGC->pScreen, prgnSrcClip);
return NULL;
}
}
dx = srcx - dstx;
dy = srcy - dsty;
if (fastClip)
{
RegionPtr cclip;
fastBox.x1 -= dx;
fastBox.x2 -= dx;
fastBox.y1 -= dy;
fastBox.y2 -= dy;
cclip = pGC->pCompositeClip;
if (REGION_NUM_RECTS(cclip) == 1)
{
BoxPtr pBox = REGION_RECTS(cclip);
if (fastBox.x1 < pBox->x1) fastBox.x1 = pBox->x1;
if (fastBox.x2 > pBox->x2) fastBox.x2 = pBox->x2;
if (fastBox.y1 < pBox->y1) fastBox.y1 = pBox->y1;
if (fastBox.y2 > pBox->y2) fastBox.y2 = pBox->y2;
if (fastBox.x1 >= fastBox.x2 || fastBox.y1 >= fastBox.y2)
{
REGION_NULL(pGC->pScreen, &rgnDst);
}
else
{
REGION_INIT(pGC->pScreen, &rgnDst, &fastBox, 1);
}
}
else
{
fastClip = 0;
REGION_INIT(pGC->pScreen, &rgnDst, &fastBox, 1);
}
}
else
{
REGION_TRANSLATE(pGC->pScreen, &rgnDst, -dx, -dy);
}
if (!fastClip)
{
REGION_INTERSECT(pGC->pScreen, &rgnDst, &rgnDst, pGC->pCompositeClip);
}
numRects = REGION_NUM_RECTS(&rgnDst);
if (numRects && width && height)
{
if(!(pptSrc = (DDXPointPtr)ALLOCATE_LOCAL(numRects *
sizeof(DDXPointRec))))
{
REGION_UNINIT(pGC->pScreen, &rgnDst);
if (freeSrcClip)
REGION_DESTROY(pGC->pScreen, prgnSrcClip);
return NULL;
}
pbox = REGION_RECTS(&rgnDst);
ppt = pptSrc;
for (i = numRects; --i >= 0; pbox++, ppt++)
{
ppt->x = pbox->x1 + dx;
ppt->y = pbox->y1 + dy;
}
vga16DoBitblt(pSrcDrawable, pDstDrawable, pGC->alu,
&rgnDst, pptSrc, pGC->planemask );
DEALLOCATE_LOCAL(pptSrc);
}
prgnExposed = NULL;
if (pGC->fExpose)
{
if (!fastExpose)
prgnExposed =
miHandleExposures(pSrcDrawable, pDstDrawable, pGC,
origSource.x, origSource.y,
(int)origSource.width,
(int)origSource.height,
origDest.x, origDest.y, (unsigned long)0);
}
REGION_UNINIT(pGC->pScreen, &rgnDst);
if (freeSrcClip)
REGION_DESTROY(pGC->pScreen, prgnSrcClip);
return prgnExposed;
}