static PixmapPtr
glamor_get_stipple_pixmap(GCPtr gc)
{
    glamor_gc_private *gc_priv = glamor_get_gc_private(gc);
    ScreenPtr   screen = gc->pScreen;
    PixmapPtr   bitmap;
    PixmapPtr   pixmap;
    GCPtr       scratch_gc;
    ChangeGCVal changes[2];

    if (gc_priv->stipple)
        return gc_priv->stipple;

    bitmap = gc->stipple;
    if (!bitmap)
        goto bail;

    pixmap = glamor_create_pixmap(screen,
                                  bitmap->drawable.width,
                                  bitmap->drawable.height,
                                  8, GLAMOR_CREATE_NO_LARGE);
    if (!pixmap)
        goto bail;

    scratch_gc = GetScratchGC(8, screen);
    if (!scratch_gc)
        goto bail_pixmap;

    changes[0].val = 0xff;
    changes[1].val = 0x00;
    if (ChangeGC(NullClient, scratch_gc,
                 GCForeground|GCBackground, changes) != Success)
        goto bail_gc;
    ValidateGC(&pixmap->drawable, scratch_gc);

    (*scratch_gc->ops->CopyPlane)(&bitmap->drawable,
                                  &pixmap->drawable,
                                  scratch_gc,
                                  0, 0,
                                  bitmap->drawable.width,
                                  bitmap->drawable.height,
                                  0, 0, 0x1);

    FreeScratchGC(scratch_gc);
    gc_priv->stipple = pixmap;

    glamor_track_stipple(gc);

    return pixmap;

bail_gc:
    FreeScratchGC(scratch_gc);
bail_pixmap:
    glamor_destroy_pixmap(pixmap);
bail:
    return NULL;
}
Beispiel #2
0
static void
cwFillRegionSolid(DrawablePtr pDrawable, RegionPtr pRegion, unsigned long pixel)
{
    ScreenPtr pScreen = pDrawable->pScreen;
    GCPtr     pGC;
    BoxPtr    pBox;
    int       nbox, i;
    ChangeGCVal v[3];

    pGC = GetScratchGC(pDrawable->depth, pScreen);
    v[0].val = GXcopy;
    v[1].val = pixel;
    v[2].val = FillSolid;
    dixChangeGC(NullClient, pGC, (GCFunction | GCForeground | GCFillStyle),
		NULL, v);
    ValidateGC(pDrawable, pGC);

    pBox = REGION_RECTS(pRegion);
    nbox = REGION_NUM_RECTS(pRegion);

    for (i = 0; i < nbox; i++, pBox++) {
	xRectangle rect;
	rect.x      = pBox->x1;
	rect.y      = pBox->y1;
	rect.width  = pBox->x2 - pBox->x1;
	rect.height = pBox->y2 - pBox->y1;
	(*pGC->ops->PolyFillRect)(pDrawable, pGC, 1, &rect);
    }

   FreeScratchGC(pGC);
}
Beispiel #3
0
void
compRestoreWindow(WindowPtr pWin, PixmapPtr pPixmap)
{
    ScreenPtr pScreen = pWin->drawable.pScreen;
    WindowPtr pParent = pWin->parent;

    if (pParent->drawable.depth == pWin->drawable.depth) {
        GCPtr pGC = GetScratchGC(pWin->drawable.depth, pScreen);
        int bw = (int) pWin->borderWidth;
        int x = bw;
        int y = bw;
        int w = pWin->drawable.width;
        int h = pWin->drawable.height;

        if (pGC) {
            ChangeGCVal val;

            val.val = IncludeInferiors;
            ChangeGC(NullClient, pGC, GCSubwindowMode, &val);
            ValidateGC(&pWin->drawable, pGC);
            (*pGC->ops->CopyArea) (&pPixmap->drawable,
                                   &pWin->drawable, pGC, x, y, w, h, 0, 0);
            FreeScratchGC(pGC);
        }
    }
}
Beispiel #4
0
void
glamor_solid_boxes(PixmapPtr pixmap,
                   BoxPtr box, int nbox, unsigned long fg_pixel)
{
    DrawablePtr drawable = &pixmap->drawable;
    GCPtr gc;
    xRectangle *rect;
    int n;

    rect = xallocarray(nbox, sizeof(xRectangle));
    if (!rect)
        return;
    for (n = 0; n < nbox; n++) {
        rect[n].x = box[n].x1;
        rect[n].y = box[n].y1;
        rect[n].width = box[n].x2 - box[n].x1;
        rect[n].height = box[n].y2 - box[n].y1;
    }

    gc = GetScratchGC(drawable->depth, drawable->pScreen);
    if (gc) {
        ChangeGCVal vals[1];

        vals[0].val = fg_pixel;
        ChangeGC(NullClient, gc, GCForeground, vals);
        ValidateGC(drawable, gc);
        gc->ops->PolyFillRect(drawable, gc, nbox, rect);
        FreeScratchGC(gc);
    }
    free(rect);
}
Beispiel #5
0
static void
miColorRects (PicturePtr    pDst,
	      PicturePtr    pClipPict,
	      xRenderColor  *color,
	      int	    nRect,
	      xRectangle    *rects,
	      int	    xoff,
	      int	    yoff)
{
    ScreenPtr		pScreen = pDst->pDrawable->pScreen;
    CARD32		pixel;
    GCPtr		pGC;
    CARD32		tmpval[5];
    RegionPtr		pClip;
    unsigned long	mask;

    miRenderColorToPixel (pDst->pFormat, color, &pixel);

    pGC = GetScratchGC (pDst->pDrawable->depth, pScreen);
    if (!pGC)
	return;
    tmpval[0] = GXcopy;
    tmpval[1] = pixel;
    tmpval[2] = pDst->subWindowMode;
    mask = GCFunction | GCForeground | GCSubwindowMode;
    if (pClipPict->clientClipType == CT_REGION)
    {
	tmpval[3] = pDst->clipOrigin.x - xoff;
	tmpval[4] = pDst->clipOrigin.y - yoff;
	mask |= GCClipXOrigin|GCClipYOrigin;
	
	pClip = REGION_CREATE (pScreen, NULL, 1);
	REGION_COPY (pScreen, pClip,
		     (RegionPtr) pClipPict->clientClip);
	(*pGC->funcs->ChangeClip) (pGC, CT_REGION, pClip, 0);
    }

    ChangeGC (pGC, mask, tmpval);
    ValidateGC (pDst->pDrawable, pGC);
    if (xoff || yoff)
    {
	int	i;
	for (i = 0; i < nRect; i++)
	{
	    rects[i].x -= xoff;
	    rects[i].y -= yoff;
	}
    }
    (*pGC->ops->PolyFillRect) (pDst->pDrawable, pGC, nRect, rects);
    if (xoff || yoff)
    {
	int	i;
	for (i = 0; i < nRect; i++)
	{
	    rects[i].x += xoff;
	    rects[i].y += yoff;
	}
    }
    FreeScratchGC (pGC);
}
static void
vivante_dri2_CopyRegion(DrawablePtr drawable, RegionPtr pRegion,
	DRI2BufferPtr dstBuf, DRI2BufferPtr srcBuf)
{
	ScreenPtr screen = drawable->pScreen;
	DrawablePtr src = vivante_dri2_get_drawable(srcBuf, drawable);
	DrawablePtr dst = vivante_dri2_get_drawable(dstBuf, drawable);
	RegionPtr clip;
	GCPtr gc;

	gc = GetScratchGC(dst->depth, screen);
	if (!gc)
		return;

	clip = REGION_CREATE(screen, NULL, 0);
	REGION_COPY(screen, clip, pRegion);
	gc->funcs->ChangeClip(gc, CT_REGION, clip, 0);
	ValidateGC(dst, gc);

	/*
	 * FIXME: wait for scanline to be outside the region to be copied...
	 * that is an interesting problem for Dove/GAL stuff because they're
	 * independent, and there's no way for the GPU to know where the
	 * scan position is.  For now, just do the copy anyway.
	 */
	gc->ops->CopyArea(src, dst, gc, 0, 0,
			  drawable->width, drawable->height, 0, 0);

	FreeScratchGC(gc);
}
Beispiel #7
0
static void
cwFillRegionTiled(DrawablePtr pDrawable, RegionPtr pRegion, PixmapPtr pTile,
		  int x_off, int y_off)
{
    ScreenPtr pScreen = pDrawable->pScreen;
    GCPtr     pGC;
    BoxPtr    pBox;
    int       nbox, i;
    ChangeGCVal v[5];

    pGC = GetScratchGC(pDrawable->depth, pScreen);
    v[0].val = GXcopy;
    v[1].val = FillTiled;
    v[2].ptr = (pointer) pTile;
    v[3].val = x_off;
    v[4].val = y_off;
    dixChangeGC(NullClient, pGC, (GCFunction | GCFillStyle | GCTile |
		GCTileStipXOrigin | GCTileStipYOrigin), NULL, v);

    ValidateGC(pDrawable, pGC);

    pBox = REGION_RECTS(pRegion);
    nbox = REGION_NUM_RECTS(pRegion);

    for (i = 0; i < nbox; i++, pBox++) {
	xRectangle rect;
	rect.x      = pBox->x1;
	rect.y      = pBox->y1;
	rect.width  = pBox->x2 - pBox->x1;
	rect.height = pBox->y2 - pBox->y1;
	(*pGC->ops->PolyFillRect)(pDrawable, pGC, 1, &rect);
    }

   FreeScratchGC(pGC);
}
Beispiel #8
0
/*
 * If the given request doesn't exactly match PutImage's constraints,
 * wrap the image in a scratch pixmap header and let CopyArea sort it out.
 */
static void
doShmPutImage(DrawablePtr dst, GCPtr pGC,
              int depth, unsigned int format,
              int w, int h, int sx, int sy, int sw, int sh, int dx, int dy,
              char *data)
{
    PixmapPtr pPixmap;

    if (format == ZPixmap || (format == XYPixmap && depth == 1)) {
        pPixmap = GetScratchPixmapHeader(dst->pScreen, w, h, depth,
                                         BitsPerPixel(depth),
                                         PixmapBytePad(w, depth), data);
        if (!pPixmap)
            return;
        pGC->ops->CopyArea((DrawablePtr) pPixmap, dst, pGC, sx, sy, sw, sh, dx,
                           dy);
        FreeScratchPixmapHeader(pPixmap);
    }
    else {
        GCPtr putGC = GetScratchGC(depth, dst->pScreen);

        if (!putGC)
            return;

        pPixmap = (*dst->pScreen->CreatePixmap) (dst->pScreen, sw, sh, depth,
                                                 CREATE_PIXMAP_USAGE_SCRATCH);
        if (!pPixmap) {
            FreeScratchGC(putGC);
            return;
        }
        ValidateGC(&pPixmap->drawable, putGC);
        (*putGC->ops->PutImage) (&pPixmap->drawable, putGC, depth, -sx, -sy, w,
                                 h, 0,
                                 (format == XYPixmap) ? XYPixmap : ZPixmap,
                                 data);
        FreeScratchGC(putGC);
        if (format == XYBitmap)
            (void) (*pGC->ops->CopyPlane) (&pPixmap->drawable, dst, pGC, 0, 0,
                                           sw, sh, dx, dy, 1L);
        else
            (void) (*pGC->ops->CopyArea) (&pPixmap->drawable, dst, pGC, 0, 0,
                                          sw, sh, dx, dy);
        (*pPixmap->drawable.pScreen->DestroyPixmap) (pPixmap);
    }
}
Beispiel #9
0
/* XXX LARGE pixmap? */
Bool
glamor_fixup_pixmap_priv(ScreenPtr screen, glamor_pixmap_private *pixmap_priv)
{
    glamor_pixmap_fbo *old_fbo;
    glamor_pixmap_fbo *new_fbo = NULL;
    PixmapPtr scratch = NULL;
    glamor_pixmap_private *scratch_priv;
    DrawablePtr drawable;
    GCPtr gc = NULL;
    int ret = FALSE;

    drawable = &pixmap_priv->base.pixmap->drawable;

    if (!GLAMOR_PIXMAP_FBO_NOT_EXACT_SIZE(pixmap_priv))
        return TRUE;

    old_fbo = pixmap_priv->base.fbo;

    if (!old_fbo)
        return FALSE;

    gc = GetScratchGC(drawable->depth, screen);
    if (!gc)
        goto fail;

    scratch = glamor_create_pixmap(screen, drawable->width, drawable->height,
                                   drawable->depth, GLAMOR_CREATE_PIXMAP_FIXUP);

    scratch_priv = glamor_get_pixmap_private(scratch);

    if (!scratch_priv->base.fbo)
        goto fail;

    ValidateGC(&scratch->drawable, gc);
    glamor_copy_area(drawable,
                     &scratch->drawable,
                     gc, 0, 0, drawable->width, drawable->height, 0, 0);
    old_fbo = glamor_pixmap_detach_fbo(pixmap_priv);
    new_fbo = glamor_pixmap_detach_fbo(scratch_priv);
    glamor_pixmap_attach_fbo(pixmap_priv->base.pixmap, new_fbo);
    glamor_pixmap_attach_fbo(scratch, old_fbo);

    DEBUGF("old %dx%d type %d\n",
           drawable->width, drawable->height, pixmap_priv->type);
    DEBUGF("copy tex %d  %dx%d to tex %d %dx%d \n",
           old_fbo->tex, old_fbo->width, old_fbo->height, new_fbo->tex,
           new_fbo->width, new_fbo->height);
    ret = TRUE;
 fail:
    if (gc)
        FreeScratchGC(gc);
    if (scratch)
        glamor_destroy_pixmap(scratch);

    return ret;
}
Beispiel #10
0
static Bool
CreateDefaultTile (GCPtr pGC)
{
    XID		tmpval[3];
    PixmapPtr 	pTile;
    GCPtr	pgcScratch;
    xRectangle	rect;
    CARD16	w, h;

    w = 1;
    h = 1;
    (*pGC->pScreen->QueryBestSize)(TileShape, &w, &h, pGC->pScreen);
    pTile = (PixmapPtr)
	    (*pGC->pScreen->CreatePixmap)(pGC->pScreen,
					  w, h, pGC->depth);
    pgcScratch = GetScratchGC(pGC->depth, pGC->pScreen);
    if (!pTile || !pgcScratch)
    {
	if (pTile)
	    (*pTile->drawable.pScreen->DestroyPixmap)(pTile);
	if (pgcScratch)
	    FreeScratchGC(pgcScratch);
	return FALSE;
    }
    tmpval[0] = GXcopy;
    tmpval[1] = pGC->tile.pixel;
    tmpval[2] = FillSolid;
    (void)ChangeGC(pgcScratch, GCFunction | GCForeground | GCFillStyle, 
		   tmpval);
    ValidateGC((DrawablePtr)pTile, pgcScratch);
    rect.x = 0;
    rect.y = 0;
    rect.width = w;
    rect.height = h;
    (*pgcScratch->ops->PolyFillRect)((DrawablePtr)pTile, pgcScratch, 1, &rect);
    /* Always remember to free the scratch graphics context after use. */
    FreeScratchGC(pgcScratch);

    pGC->tileIsPixel = FALSE;
    pGC->tile.pixmap = pTile;
    return TRUE;
}
Beispiel #11
0
static PixmapPtr
glamor_get_dash_pixmap(GCPtr gc)
{
    glamor_gc_private *gc_priv = glamor_get_gc_private(gc);
    ScreenPtr   screen = gc->pScreen;
    PixmapPtr   pixmap;
    int         offset;
    int         d;
    uint32_t    pixel;
    GCPtr       scratch_gc;

    if (gc_priv->dash)
        return gc_priv->dash;

    offset = 0;
    for (d = 0; d < gc->numInDashList; d++)
        offset += gc->dash[d];

    pixmap = glamor_create_pixmap(screen, offset, 1, 8, 0);
    if (!pixmap)
        goto bail;

    scratch_gc = GetScratchGC(8, screen);
    if (!scratch_gc)
        goto bail_pixmap;

    pixel = 0xffffffff;
    offset = 0;
    for (d = 0; d < gc->numInDashList; d++) {
        xRectangle      rect;
        ChangeGCVal     changes;

        changes.val = pixel;
        (void) ChangeGC(NullClient, scratch_gc,
                        GCForeground, &changes);
        ValidateGC(&pixmap->drawable, scratch_gc);
        rect.x = offset;
        rect.y = 0;
        rect.width = gc->dash[d];
        rect.height = 1;
        scratch_gc->ops->PolyFillRect (&pixmap->drawable, scratch_gc, 1, &rect);
        offset += gc->dash[d];
        pixel = ~pixel;
    }
    FreeScratchGC(scratch_gc);

    gc_priv->dash = pixmap;
    return pixmap;

bail_pixmap:
    glamor_destroy_pixmap(pixmap);
bail:
    return NULL;
}
Beispiel #12
0
/**
 * Cleans up the scratch GC created in ephyrPrepareSolid.
 */
static void
ephyrDoneSolid(PixmapPtr pPix)
{
    ScreenPtr pScreen = pPix->drawable.pScreen;
    KdScreenPriv(pScreen);
    KdScreenInfo *screen = pScreenPriv->screen;
    EphyrScrPriv *scrpriv = screen->driver;
    EphyrFakexaPriv *fakexa = scrpriv->fakexa;

    FreeScratchGC(fakexa->pGC);

    ephyrFinishPipelinedAccess(pPix, EXA_PREPARE_DEST);
}
Beispiel #13
0
static void
MSMDRI2CopyRegion(DrawablePtr pDraw, RegionPtr pRegion,
		DRI2BufferPtr pDstBuffer, DRI2BufferPtr pSrcBuffer)
{
	ScreenPtr pScreen = pDraw->pScreen;
	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
	DrawablePtr pSrcDraw = dri2draw(pDraw, pSrcBuffer);
	DrawablePtr pDstDraw = dri2draw(pDraw, pDstBuffer);
	RegionPtr pCopyClip;
	GCPtr pGC;

	DEBUG_MSG("pDraw=%p, pDstBuffer=%p (%p), pSrcBuffer=%p (%p)",
			pDraw, pDstBuffer, pSrcDraw, pSrcBuffer, pDstDraw);

	/* hack.. since we don't have proper fencing / kernel synchronization
	 * we can get in a scenario where we get many frames ahead of the gpu,
	 * with queued up cmd sequence like: render -> blit -> render -> blit ..
	 * This hack makes sure the previous blit has completed.
	 */
	{
	MSMPtr pMsm = MSMPTR(pScrn);
	MSMDRI2BufferPtr buf = MSMBUF(pDstBuffer);
	pMsm->pExa->PrepareAccess(buf->pPixmap, 0);
	pMsm->pExa->FinishAccess(buf->pPixmap, 0);
	}

	pGC = GetScratchGC(pDstDraw->depth, pScreen);
	if (!pGC) {
		return;
	}

	pCopyClip = REGION_CREATE(pScreen, NULL, 0);
	RegionCopy(pCopyClip, pRegion);
	(*pGC->funcs->ChangeClip) (pGC, CT_REGION, pCopyClip, 0);
	ValidateGC(pDstDraw, pGC);

	/* If the dst is the framebuffer, and we had a way to
	 * schedule a deferred blit synchronized w/ vsync, that
	 * would be a nice thing to do utilize here to avoid
	 * tearing..  when we have sync object support for GEM
	 * buffers, I think we could do something more clever
	 * here.
	 */

	pGC->ops->CopyArea(pSrcDraw, pDstDraw, pGC,
			0, 0, pDraw->width, pDraw->height, 0, 0);

	FreeScratchGC(pGC);

	MSMFlushAccel(pScreen);
}
Beispiel #14
0
/**
 * Cleans up the scratch GC created in ephyrPrepareCopy.
 */
static void
ephyrDoneCopy(PixmapPtr pDst)
{
    ScreenPtr pScreen = pDst->drawable.pScreen;
    KdScreenPriv(pScreen);
    KdScreenInfo *screen = pScreenPriv->screen;
    EphyrScrPriv *scrpriv = screen->driver;
    EphyrFakexaPriv *fakexa = scrpriv->fakexa;

    FreeScratchGC (fakexa->pGC);

    ephyrFinishPipelinedAccess(fakexa->pSrc, EXA_PREPARE_SRC);
    ephyrFinishPipelinedAccess(fakexa->pDst, EXA_PREPARE_DEST);
}
Beispiel #15
0
/* Do ordinary copy */
static void MaliDRI2CopyRegion_copy(DrawablePtr pDraw,
                                    RegionPtr pRegion,
                                    DRI2BufferPtr pDstBuffer,
                                    DRI2BufferPtr pSrcBuffer)
{
    GCPtr pGC;
    RegionPtr copyRegion;
    ScreenPtr pScreen = pDraw->pScreen;
    MaliDRI2BufferPrivatePtr privates;
    PixmapPtr pScratchPixmap;
    privates = (MaliDRI2BufferPrivatePtr)pSrcBuffer->driverPrivate;

//    DebugMsg("Enter MaliDRI2CopyRegion    buf_name:%d\n",pSrcBuffer->name);
/*
#ifdef HAVE_LIBUMP_CACHE_CONTROL
    if (privates->handle != UMP_INVALID_MEMORY_HANDLE) {
//        That's a normal UMP allocation, not a wrapped framebuffer
        ump_cache_operations_control(UMP_CACHE_OP_START);
        ump_switch_hw_usage_secure_id(pSrcBuffer->name, UMP_USED_BY_CPU);
        ump_cache_operations_control(UMP_CACHE_OP_FINISH);
    }
#endif
*/
    pGC = GetScratchGC(pDraw->depth, pScreen);
    pScratchPixmap = GetScratchPixmapHeader(pScreen,
                                            privates->width, privates->height,
                                            privates->depth, pSrcBuffer->cpp * 8,
                                            pSrcBuffer->pitch,
                                            privates->addr + pSrcBuffer->flags);
    copyRegion = REGION_CREATE(pScreen, NULL, 0);
    REGION_COPY(pScreen, copyRegion, pRegion);
    (*pGC->funcs->ChangeClip)(pGC, CT_REGION, copyRegion, 0);
    ValidateGC(pDraw, pGC);
    (*pGC->ops->CopyArea)((DrawablePtr)pScratchPixmap, pDraw, pGC, 0, 0,
                          pDraw->width, pDraw->height, 0, 0);
    FreeScratchPixmapHeader(pScratchPixmap);
    FreeScratchGC(pGC);
/*
#ifdef HAVE_LIBUMP_CACHE_CONTROL
    if (privates->handle != UMP_INVALID_MEMORY_HANDLE) {
//        That's a normal UMP allocation, not a wrapped framebuffer
        ump_cache_operations_control(UMP_CACHE_OP_START);
        ump_switch_hw_usage_secure_id(pSrcBuffer->name, UMP_USED_BY_MALI);
        ump_cache_operations_control(UMP_CACHE_OP_FINISH);
    }
#endif
*/
}
Beispiel #16
0
PicturePtr
miCreateAlphaPicture (ScreenPtr	    pScreen, 
		      PicturePtr    pDst,
		      PictFormatPtr pPictFormat,
		      CARD16	    width,
		      CARD16	    height)
{
    PixmapPtr	    pPixmap;
    PicturePtr	    pPicture;
    GCPtr	    pGC;
    int		    error;
    xRectangle	    rect;

    if (width > 32767 || height > 32767)
	return 0;

    if (!pPictFormat)
    {
	if (pDst->polyEdge == PolyEdgeSharp)
	    pPictFormat = PictureMatchFormat (pScreen, 1, PICT_a1);
	else
	    pPictFormat = PictureMatchFormat (pScreen, 8, PICT_a8);
	if (!pPictFormat)
	    return 0;
    }

    pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, 
					pPictFormat->depth);
    if (!pPixmap)
	return 0;
    pGC = GetScratchGC (pPixmap->drawable.depth, pScreen);
    if (!pGC)
    {
	(*pScreen->DestroyPixmap) (pPixmap);
	return 0;
    }
    ValidateGC (&pPixmap->drawable, pGC);
    rect.x = 0;
    rect.y = 0;
    rect.width = width;
    rect.height = height;
    (*pGC->ops->PolyFillRect)(&pPixmap->drawable, pGC, 1, &rect);
    FreeScratchGC (pGC);
    pPicture = CreatePicture (0, &pPixmap->drawable, pPictFormat,
			      0, 0, serverClient, &error);
    (*pScreen->DestroyPixmap) (pPixmap);
    return pPicture;
}
void sgx_exa_copy_region(DrawablePtr draw, RegionPtr reg, DrawablePtr src_draw,
			DrawablePtr dst_draw)
{
        ScreenPtr screen = dst_draw->pScreen;
	RegionPtr copy_clip = RegionCreate(NULL, 0);
        GCPtr gc;

        gc = GetScratchGC(dst_draw->depth, screen);
	RegionCopy(copy_clip, reg);
        (*gc->funcs->ChangeClip)(gc, CT_REGION, copy_clip, 0);
        ValidateGC(dst_draw, gc);

        (*gc->ops->CopyArea)(src_draw, dst_draw, gc, 0, 0, draw->width,
                                draw->height, 0, 0);

        FreeScratchGC(gc);
}
static void
ARMSOCDRI2CopyRegion(DrawablePtr pDraw, RegionPtr pRegion,
		DRI2BufferPtr pDstBuffer, DRI2BufferPtr pSrcBuffer)
{
	ScreenPtr pScreen = pDraw->pScreen;
	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
	RegionPtr pCopyClip;
	GCPtr pGC;
        PixmapPtr pScratchPixmap;
        struct ARMSOCDRI2BufferRec *src = ARMSOCBUF(pSrcBuffer);

	DEBUG_MSG("pDraw=%p, pDstBuffer=%p pSrcBuffer=%p",
			pDraw, pDstBuffer, pSrcBuffer);

	pGC = GetScratchGC(pDraw->depth, pScreen);
	if (!pGC)
		return;

	pCopyClip = REGION_CREATE(pScreen, NULL, 0);
	RegionCopy(pCopyClip, pRegion);
	(*pGC->funcs->ChangeClip) (pGC, CT_REGION, pCopyClip, 0);
	ValidateGC(pDraw, pGC);

	/* If the dst is the framebuffer, and we had a way to
	 * schedule a deferred blit synchronized w/ vsync, that
	 * would be a nice thing to do utilize here to avoid
	 * tearing..  when we have sync object support for GEM
	 * buffers, I think we could do something more clever
	 * here.
	 */

        pScratchPixmap = GetScratchPixmapHeader(pScreen,
		armsoc_bo_width(src->bo), armsoc_bo_height(src->bo),
		armsoc_bo_depth(src->bo), armsoc_bo_bpp(src->bo),
		armsoc_bo_pitch(src->bo), armsoc_bo_map(src->bo));
		

	pGC->ops->CopyArea((DrawablePtr) pScratchPixmap, pDraw, pGC,
			0, 0, pDraw->width, pDraw->height, 0, 0);
	FreeScratchPixmapHeader(pScratchPixmap);
	FreeScratchGC(pGC);
}
Beispiel #19
0
static void MaliDRI2CopyRegion(DrawablePtr   pDraw,
                               RegionPtr     pRegion,
                               DRI2BufferPtr pDstBuffer,
                               DRI2BufferPtr pSrcBuffer)
{
    GCPtr pGC;
    RegionPtr copyRegion;
    ScreenPtr pScreen = pDraw->pScreen;
    MaliDRI2BufferPrivatePtr privates;
    PixmapPtr pScratchPixmap;
    privates = (MaliDRI2BufferPrivatePtr)pSrcBuffer->driverPrivate;

    if (privates->depth != pDraw->depth) {
        ErrorF("MaliDRI2CopyRegion: privates->depth != pDraw->depth (%d vs. %d)\n",
               privates->depth, pDraw->depth);
        return;
    }

    //ErrorF("MaliDRI2CopyRegion dstbuf=%p srcbuf=%p, depth=%d\n", pDstBuffer, pSrcBuffer, privates->depth);

    ump_cache_operations_control(UMP_CACHE_OP_START);
    ump_switch_hw_usage_secure_id(pSrcBuffer->name, UMP_USED_BY_CPU);
    ump_cache_operations_control(UMP_CACHE_OP_FINISH);

    pGC = GetScratchGC(pDraw->depth, pScreen);
    pScratchPixmap = GetScratchPixmapHeader(pScreen, privates->width, privates->height,
                                            privates->depth, pSrcBuffer->cpp * 8,
                                            pSrcBuffer->pitch, privates->addr);
    copyRegion = REGION_CREATE(pScreen, NULL, 0);
    REGION_COPY(pScreen, copyRegion, pRegion);
    (*pGC->funcs->ChangeClip)(pGC, CT_REGION, copyRegion, 0);
    ValidateGC(pDraw, pGC);
    (*pGC->ops->CopyArea)(pScratchPixmap, pDraw, pGC, 0, 0,
                          pDraw->width, pDraw->height, 0, 0);
    FreeScratchPixmapHeader(pScratchPixmap);
    FreeScratchGC(pGC);

    ump_cache_operations_control(UMP_CACHE_OP_START);
    ump_switch_hw_usage_secure_id(pSrcBuffer->name, UMP_USED_BY_MALI);
    ump_cache_operations_control(UMP_CACHE_OP_FINISH);
}
static void
uxa_clear_pixmap(ScreenPtr screen,
		 uxa_screen_t *uxa_screen,
		 PixmapPtr pixmap)
{
	if (uxa_screen->info->check_solid &&
	    !uxa_screen->info->check_solid(&pixmap->drawable, GXcopy, FB_ALLONES))
		goto fallback;

	if (!uxa_screen->info->prepare_solid(pixmap, GXcopy, FB_ALLONES, 0))
		goto fallback;

	uxa_screen->info->solid(pixmap,
				0, 0,
				pixmap->drawable.width,
				pixmap->drawable.height);

	uxa_screen->info->done_solid(pixmap);
	return;

fallback:
	{
		GCPtr gc;

		gc = GetScratchGC(pixmap->drawable.depth, screen);
		if (gc) {
			xRectangle rect;

			ValidateGC(&pixmap->drawable, gc);

			rect.x = 0;
			rect.y = 0;
			rect.width  = pixmap->drawable.width;
			rect.height = pixmap->drawable.height;
			gc->ops->PolyFillRect(&pixmap->drawable, gc, 1, &rect);

			FreeScratchGC(gc);
		}
	}
}
Beispiel #21
0
void
glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height,
             unsigned long fg_pixel)
{
    DrawablePtr drawable = &pixmap->drawable;
    GCPtr gc;
    ChangeGCVal vals[1];
    xRectangle rect;

    vals[0].val = fg_pixel;
    gc = GetScratchGC(drawable->depth, drawable->pScreen);
    if (!gc)
        return;
    ChangeGC(NullClient, gc, GCForeground, vals);
    ValidateGC(drawable, gc);
    rect.x = x;
    rect.y = y;
    rect.width = width;
    rect.height = height;
    gc->ops->PolyFillRect(drawable, gc, 1, &rect);
    FreeScratchGC(gc);
}
Beispiel #22
0
Bool
CreateDefaultStipple(int screenNum)
{
    ScreenPtr pScreen;
    ChangeGCVal tmpval[3];
    xRectangle rect;
    CARD16 w, h;
    GCPtr pgcScratch;

    pScreen = screenInfo.screens[screenNum];

    w = 16;
    h = 16;
    (*pScreen->QueryBestSize) (StippleShape, &w, &h, pScreen);
    if (!(pScreen->defaultStipple = pScreen->CreatePixmap(pScreen, w, h, 1, 0)))
        return FALSE;
    /* fill stipple with 1 */
    tmpval[0].val = GXcopy;
    tmpval[1].val = 1;
    tmpval[2].val = FillSolid;
    pgcScratch = GetScratchGC(1, pScreen);
    if (!pgcScratch) {
        (*pScreen->DestroyPixmap) (pScreen->defaultStipple);
        return FALSE;
    }
    (void) ChangeGC(NullClient, pgcScratch,
                    GCFunction | GCForeground | GCFillStyle, tmpval);
    ValidateGC((DrawablePtr) pScreen->defaultStipple, pgcScratch);
    rect.x = 0;
    rect.y = 0;
    rect.width = w;
    rect.height = h;
    (*pgcScratch->ops->PolyFillRect) ((DrawablePtr) pScreen->defaultStipple,
                                      pgcScratch, 1, &rect);
    FreeScratchGC(pgcScratch);
    return TRUE;
}
static void
ARMSOCDRI2CopyRegion(DrawablePtr pDraw, RegionPtr pRegion,
		DRI2BufferPtr pDstBuffer, DRI2BufferPtr pSrcBuffer)
{
	ScreenPtr pScreen = pDraw->pScreen;
	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
	DrawablePtr pSrcDraw = dri2draw(pDraw, pSrcBuffer);
	DrawablePtr pDstDraw = dri2draw(pDraw, pDstBuffer);
	RegionPtr pCopyClip;
	GCPtr pGC;

	DEBUG_MSG("pDraw=%p, pDstBuffer=%p (%p), pSrcBuffer=%p (%p)",
			pDraw, pDstBuffer, pSrcDraw, pSrcBuffer, pDstDraw);

	pGC = GetScratchGC(pDstDraw->depth, pScreen);
	if (!pGC)
		return;

	pCopyClip = REGION_CREATE(pScreen, NULL, 0);
	RegionCopy(pCopyClip, pRegion);
	(*pGC->funcs->ChangeClip) (pGC, CT_REGION, pCopyClip, 0);
	ValidateGC(pDstDraw, pGC);

	/* If the dst is the framebuffer, and we had a way to
	 * schedule a deferred blit synchronized w/ vsync, that
	 * would be a nice thing to do utilize here to avoid
	 * tearing..  when we have sync object support for GEM
	 * buffers, I think we could do something more clever
	 * here.
	 */

	pGC->ops->CopyArea(pSrcDraw, pDstDraw, pGC,
			0, 0, pDraw->width, pDraw->height, 0, 0);

	FreeScratchGC(pGC);
}
static inline void
glamor_copy_glyph(PixmapPtr     glyph_pixmap,
                  DrawablePtr   atlas_draw,
                  int16_t x,
                  int16_t y)
{
    DrawablePtr glyph_draw = &glyph_pixmap->drawable;
    BoxRec      box = {
        .x1 = 0,
        .y1 = 0,
        .x2 = glyph_draw->width,
        .y2 = glyph_draw->height,
    };
    PixmapPtr upload_pixmap = glyph_pixmap;

    if (glyph_pixmap->drawable.bitsPerPixel != atlas_draw->bitsPerPixel) {

        /* If we're dealing with 1-bit glyphs, we copy them to a
         * temporary 8-bit pixmap and upload them from there, since
         * that's what GL can handle.
         */
        ScreenPtr       screen = atlas_draw->pScreen;
        GCPtr           scratch_gc;
        ChangeGCVal     changes[2];

        upload_pixmap = glamor_create_pixmap(screen,
                                             glyph_draw->width,
                                             glyph_draw->height,
                                             atlas_draw->depth,
                                             GLAMOR_CREATE_PIXMAP_CPU);
        if (!upload_pixmap)
            return;

        scratch_gc = GetScratchGC(upload_pixmap->drawable.depth, screen);
        if (!scratch_gc) {
            glamor_destroy_pixmap(upload_pixmap);
            return;
        }
        changes[0].val = 0xff;
        changes[1].val = 0x00;
        if (ChangeGC(NullClient, scratch_gc,
                     GCForeground|GCBackground, changes) != Success) {
            glamor_destroy_pixmap(upload_pixmap);
            FreeScratchGC(scratch_gc);
            return;
        }
        ValidateGC(&upload_pixmap->drawable, scratch_gc);

        (*scratch_gc->ops->CopyPlane)(glyph_draw,
                                      &upload_pixmap->drawable,
                                      scratch_gc,
                                      0, 0,
                                      glyph_draw->width,
                                      glyph_draw->height,
                                      0, 0, 0x1);
    }
    glamor_upload_boxes((PixmapPtr) atlas_draw,
                        &box, 1,
                        0, 0,
                        x, y,
                        upload_pixmap->devPrivate.ptr,
                        upload_pixmap->devKind);

    if (upload_pixmap != glyph_pixmap)
        glamor_destroy_pixmap(upload_pixmap);
}

static Bool
glamor_glyph_atlas_init(ScreenPtr screen, struct glamor_glyph_atlas *atlas)
{
    glamor_screen_private       *glamor_priv = glamor_get_screen_private(screen);
    PictFormatPtr               format = atlas->format;

    atlas->atlas = glamor_create_pixmap(screen, glamor_priv->glyph_atlas_dim,
                                        glamor_priv->glyph_atlas_dim, format->depth,
                                        GLAMOR_CREATE_FBO_NO_FBO);
    if (!glamor_pixmap_has_fbo(atlas->atlas)) {
        glamor_destroy_pixmap(atlas->atlas);
        atlas->atlas = NULL;
    }
    atlas->x = 0;
    atlas->y = 0;
    atlas->row_height = 0;
    atlas->serial++;
    atlas->nglyph = 0;
    return TRUE;
}
Beispiel #25
0
static PixmapPtr
compNewPixmap (WindowPtr pWin, int x, int y, int w, int h)
{
    ScreenPtr	    pScreen = pWin->drawable.pScreen;
    WindowPtr	    pParent = pWin->parent;
    PixmapPtr	    pPixmap;

    pPixmap = (*pScreen->CreatePixmap) (pScreen, w, h, pWin->drawable.depth,
					CREATE_PIXMAP_USAGE_BACKING_PIXMAP);

    if (!pPixmap)
	return 0;
    
    pPixmap->screen_x = x;
    pPixmap->screen_y = y;
    
    if (pParent->drawable.depth == pWin->drawable.depth)
    {
	GCPtr	pGC = GetScratchGC (pWin->drawable.depth, pScreen);
	
	/*
	 * Copy bits from the parent into the new pixmap so that it will
	 * have "reasonable" contents in case for background None areas.
	 */
	if (pGC)
	{
	    ChangeGCVal val;
	    val.val = IncludeInferiors;
	    
	    ValidateGC(&pPixmap->drawable, pGC);
	    ChangeGC (serverClient, pGC, GCSubwindowMode, &val);
	    (*pGC->ops->CopyArea) (&pParent->drawable,
				   &pPixmap->drawable,
				   pGC,
				   x - pParent->drawable.x,
				   y - pParent->drawable.y,
				   w, h, 0, 0);
	    FreeScratchGC (pGC);
	}
    }
    else
    {
	PictFormatPtr	pSrcFormat = compWindowFormat (pParent);
	PictFormatPtr	pDstFormat = compWindowFormat (pWin);
	XID		inferiors = IncludeInferiors;
	int		error;

	PicturePtr	pSrcPicture = CreatePicture (None,
						     &pParent->drawable,
						     pSrcFormat,
						     CPSubwindowMode,
						     &inferiors,
						     serverClient, &error);
						    
	PicturePtr	pDstPicture = CreatePicture (None,
						     &pPixmap->drawable,
						     pDstFormat,
						     0, 0,
						     serverClient, &error);

	if (pSrcPicture && pDstPicture)
	{
	    CompositePicture (PictOpSrc,
			      pSrcPicture,
			      NULL,
			      pDstPicture,
			      x - pParent->drawable.x,
			      y - pParent->drawable.y,
			      0, 0, 0, 0, w, h);
	}
	if (pSrcPicture)
	    FreePicture (pSrcPicture, 0);
	if (pDstPicture)
	    FreePicture (pDstPicture, 0);
    }
    return pPixmap;
}
Beispiel #26
0
void
I915DisplayVideoTextured(ScrnInfoPtr scrn,
			 intel_adaptor_private *adaptor_priv, int id,
			 RegionPtr dstRegion,
			 short width, short height, int video_pitch,
			 int video_pitch2,
			 short src_w, short src_h, short drw_w, short drw_h,
			 PixmapPtr pixmap)
{
	intel_screen_private *intel = intel_get_screen_private(scrn);
	uint32_t format, ms3, s5, tiling;
	BoxPtr pbox = REGION_RECTS(dstRegion);
	int nbox_total = REGION_NUM_RECTS(dstRegion);
	int nbox_this_time;
	int dxo, dyo, pix_xoff, pix_yoff;
	PixmapPtr target;

#if 0
	ErrorF("I915DisplayVideo: %dx%d (pitch %d)\n", width, height,
	       video_pitch);
#endif

	dxo = dstRegion->extents.x1;
	dyo = dstRegion->extents.y1;

	if (pixmap->drawable.width > 2048 || pixmap->drawable.height > 2048 ||
	    !intel_uxa_check_pitch_3d(pixmap)) {
		ScreenPtr screen = pixmap->drawable.pScreen;

		target = screen->CreatePixmap(screen,
					      dstRegion->extents.x2 - dxo,
					      dstRegion->extents.y2 - dyo,
					      pixmap->drawable.depth,
					      CREATE_PIXMAP_USAGE_SCRATCH);
		if (target == NULL)
			return;

		if (intel_uxa_get_pixmap_bo(target) == NULL) {
			screen->DestroyPixmap(target);
			return;
		}

		pix_xoff = -dxo;
		pix_yoff = -dyo;
	} else {
		target = pixmap;

		/* Set up the offset for translating from the given region
		 * (in screen coordinates) to the backing pixmap.
		 */
#ifdef COMPOSITE
		pix_xoff = -target->screen_x + target->drawable.x;
		pix_yoff = -target->screen_y + target->drawable.y;
#else
		pix_xoff = 0;
		pix_yoff = 0;
#endif
	}

#define BYTES_FOR_BOXES(n)	((200 + (n) * 20) * 4)
#define BOXES_IN_BYTES(s)	((((s)/4) - 200) / 20)
#define BATCH_BYTES(p)		((p)->batch_bo->size - 16)

	while (nbox_total) {
		nbox_this_time = nbox_total;
		if (BYTES_FOR_BOXES(nbox_this_time) > BATCH_BYTES(intel))
			nbox_this_time = BOXES_IN_BYTES(BATCH_BYTES(intel));
		nbox_total -= nbox_this_time;

		intel_batch_start_atomic(scrn, 200 + 20 * nbox_this_time);

		IntelEmitInvarientState(scrn);
		intel->last_3d = LAST_3D_VIDEO;

		/* draw rect -- just clipping */
		OUT_BATCH(_3DSTATE_DRAW_RECT_CMD);
		OUT_BATCH(DRAW_DITHER_OFS_X(pixmap->drawable.x & 3) |
			  DRAW_DITHER_OFS_Y(pixmap->drawable.y & 3));
		OUT_BATCH(0x00000000);	/* ymin, xmin */
		/* ymax, xmax */
		OUT_BATCH((target->drawable.width - 1) |
			  (target->drawable.height - 1) << 16);
		OUT_BATCH(0x00000000);	/* yorigin, xorigin */

		OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(2) |
			  I1_LOAD_S(5) | I1_LOAD_S(6) | 2);
		OUT_BATCH(S2_TEXCOORD_FMT(0, TEXCOORDFMT_2D) |
			  S2_TEXCOORD_FMT(1, TEXCOORDFMT_NOT_PRESENT) |
			  S2_TEXCOORD_FMT(2, TEXCOORDFMT_NOT_PRESENT) |
			  S2_TEXCOORD_FMT(3, TEXCOORDFMT_NOT_PRESENT) |
			  S2_TEXCOORD_FMT(4, TEXCOORDFMT_NOT_PRESENT) |
			  S2_TEXCOORD_FMT(5, TEXCOORDFMT_NOT_PRESENT) |
			  S2_TEXCOORD_FMT(6, TEXCOORDFMT_NOT_PRESENT) |
			  S2_TEXCOORD_FMT(7, TEXCOORDFMT_NOT_PRESENT));
		s5 = 0x0;
		if (intel->cpp == 2)
			s5 |= S5_COLOR_DITHER_ENABLE;
		OUT_BATCH(s5);	/* S5 - enable bits */
		OUT_BATCH((2 << S6_DEPTH_TEST_FUNC_SHIFT) |
			  (2 << S6_CBUF_SRC_BLEND_FACT_SHIFT) |
			  (1 << S6_CBUF_DST_BLEND_FACT_SHIFT) |
			  S6_COLOR_WRITE_ENABLE | (2 << S6_TRISTRIP_PV_SHIFT));

		OUT_BATCH(_3DSTATE_CONST_BLEND_COLOR_CMD);
		OUT_BATCH(0x00000000);

		OUT_BATCH(_3DSTATE_DST_BUF_VARS_CMD);
		if (intel->cpp == 2)
			format = COLR_BUF_RGB565;
		else
			format =
			    COLR_BUF_ARGB8888 | DEPTH_FRMT_24_FIXED_8_OTHER;

		OUT_BATCH(LOD_PRECLAMP_OGL |
			  DSTORG_HORT_BIAS(0x8) |
			  DSTORG_VERT_BIAS(0x8) | format);

		/* front buffer, pitch, offset */
		if (intel_uxa_pixmap_tiled(target)) {
			tiling = BUF_3D_TILED_SURFACE;
			if (intel_uxa_get_pixmap_private(target)->tiling == I915_TILING_Y)
				tiling |= BUF_3D_TILE_WALK_Y;
		} else
			tiling = 0;
		OUT_BATCH(_3DSTATE_BUF_INFO_CMD);
		OUT_BATCH(BUF_3D_ID_COLOR_BACK | tiling |
			  BUF_3D_PITCH(intel_pixmap_pitch(target)));
		OUT_RELOC_PIXMAP(target, I915_GEM_DOMAIN_RENDER,
				 I915_GEM_DOMAIN_RENDER, 0);

		if (!is_planar_fourcc(id)) {
			FS_LOCALS();

			OUT_BATCH(_3DSTATE_PIXEL_SHADER_CONSTANTS | 4);
			OUT_BATCH(0x0000001);	/* constant 0 */
			/* constant 0: brightness/contrast */
			OUT_BATCH_F(adaptor_priv->brightness / 128.0);
			OUT_BATCH_F(adaptor_priv->contrast / 255.0);
			OUT_BATCH_F(0.0);
			OUT_BATCH_F(0.0);

			OUT_BATCH(_3DSTATE_SAMPLER_STATE | 3);
			OUT_BATCH(0x00000001);
			OUT_BATCH(SS2_COLORSPACE_CONVERSION |
				  (FILTER_LINEAR << SS2_MAG_FILTER_SHIFT) |
				  (FILTER_LINEAR << SS2_MIN_FILTER_SHIFT));
			OUT_BATCH((TEXCOORDMODE_CLAMP_EDGE <<
				   SS3_TCX_ADDR_MODE_SHIFT) |
				  (TEXCOORDMODE_CLAMP_EDGE <<
				   SS3_TCY_ADDR_MODE_SHIFT) |
				  (0 << SS3_TEXTUREMAP_INDEX_SHIFT) |
				  SS3_NORMALIZED_COORDS);
			OUT_BATCH(0x00000000);

			OUT_BATCH(_3DSTATE_MAP_STATE | 3);
			OUT_BATCH(0x00000001);	/* texture map #1 */
			if (adaptor_priv->buf)
				OUT_RELOC(adaptor_priv->buf,
					  I915_GEM_DOMAIN_SAMPLER, 0,
					  adaptor_priv->YBufOffset);
			else
				OUT_BATCH(adaptor_priv->YBufOffset);

			ms3 = MAPSURF_422;
			switch (id) {
			case FOURCC_YUY2:
				ms3 |= MT_422_YCRCB_NORMAL;
				break;
			case FOURCC_UYVY:
				ms3 |= MT_422_YCRCB_SWAPY;
				break;
			}
			ms3 |= (height - 1) << MS3_HEIGHT_SHIFT;
			ms3 |= (width - 1) << MS3_WIDTH_SHIFT;
			OUT_BATCH(ms3);
			OUT_BATCH(((video_pitch / 4) - 1) << MS4_PITCH_SHIFT);

			FS_BEGIN();
			i915_fs_dcl(FS_S0);
			i915_fs_dcl(FS_T0);
			i915_fs_texld(FS_OC, FS_S0, FS_T0);
			if (adaptor_priv->brightness != 0) {
				i915_fs_add(FS_OC,
					    i915_fs_operand_reg(FS_OC),
					    i915_fs_operand(FS_C0, X, X, X,
							    ZERO));
			}
			FS_END();
		} else {
			FS_LOCALS();

			/* For the planar formats, we set up three samplers --
			 * one for each plane, in a Y8 format.  Because I
			 * couldn't get the special PLANAR_TO_PACKED
			 * shader setup to work, I did the manual pixel shader:
			 *
			 * y' = y - .0625
			 * u' = u - .5
			 * v' = v - .5;
			 *
			 * r = 1.1643 * y' + 0.0     * u' + 1.5958  * v'
			 * g = 1.1643 * y' - 0.39173 * u' - 0.81290 * v'
			 * b = 1.1643 * y' + 2.017   * u' + 0.0     * v'
			 *
			 * register assignment:
			 * r0 = (y',u',v',0)
			 * r1 = (y,y,y,y)
			 * r2 = (u,u,u,u)
			 * r3 = (v,v,v,v)
			 * OC = (r,g,b,1)
			 */
			OUT_BATCH(_3DSTATE_PIXEL_SHADER_CONSTANTS | (22 - 2));
			OUT_BATCH(0x000001f);	/* constants 0-4 */
			/* constant 0: normalization offsets */
			OUT_BATCH_F(-0.0625);
			OUT_BATCH_F(-0.5);
			OUT_BATCH_F(-0.5);
			OUT_BATCH_F(0.0);
			/* constant 1: r coefficients */
			OUT_BATCH_F(1.1643);
			OUT_BATCH_F(0.0);
			OUT_BATCH_F(1.5958);
			OUT_BATCH_F(0.0);
			/* constant 2: g coefficients */
			OUT_BATCH_F(1.1643);
			OUT_BATCH_F(-0.39173);
			OUT_BATCH_F(-0.81290);
			OUT_BATCH_F(0.0);
			/* constant 3: b coefficients */
			OUT_BATCH_F(1.1643);
			OUT_BATCH_F(2.017);
			OUT_BATCH_F(0.0);
			OUT_BATCH_F(0.0);
			/* constant 4: brightness/contrast */
			OUT_BATCH_F(adaptor_priv->brightness / 128.0);
			OUT_BATCH_F(adaptor_priv->contrast / 255.0);
			OUT_BATCH_F(0.0);
			OUT_BATCH_F(0.0);

			OUT_BATCH(_3DSTATE_SAMPLER_STATE | 9);
			OUT_BATCH(0x00000007);
			/* sampler 0 */
			OUT_BATCH((FILTER_LINEAR << SS2_MAG_FILTER_SHIFT) |
				  (FILTER_LINEAR << SS2_MIN_FILTER_SHIFT));
			OUT_BATCH((TEXCOORDMODE_CLAMP_EDGE <<
				   SS3_TCX_ADDR_MODE_SHIFT) |
				  (TEXCOORDMODE_CLAMP_EDGE <<
				   SS3_TCY_ADDR_MODE_SHIFT) |
				  (0 << SS3_TEXTUREMAP_INDEX_SHIFT) |
				  SS3_NORMALIZED_COORDS);
			OUT_BATCH(0x00000000);
			/* sampler 1 */
			OUT_BATCH((FILTER_LINEAR << SS2_MAG_FILTER_SHIFT) |
				  (FILTER_LINEAR << SS2_MIN_FILTER_SHIFT));
			OUT_BATCH((TEXCOORDMODE_CLAMP_EDGE <<
				   SS3_TCX_ADDR_MODE_SHIFT) |
				  (TEXCOORDMODE_CLAMP_EDGE <<
				   SS3_TCY_ADDR_MODE_SHIFT) |
				  (1 << SS3_TEXTUREMAP_INDEX_SHIFT) |
				  SS3_NORMALIZED_COORDS);
			OUT_BATCH(0x00000000);
			/* sampler 2 */
			OUT_BATCH((FILTER_LINEAR << SS2_MAG_FILTER_SHIFT) |
				  (FILTER_LINEAR << SS2_MIN_FILTER_SHIFT));
			OUT_BATCH((TEXCOORDMODE_CLAMP_EDGE <<
				   SS3_TCX_ADDR_MODE_SHIFT) |
				  (TEXCOORDMODE_CLAMP_EDGE <<
				   SS3_TCY_ADDR_MODE_SHIFT) |
				  (2 << SS3_TEXTUREMAP_INDEX_SHIFT) |
				  SS3_NORMALIZED_COORDS);
			OUT_BATCH(0x00000000);

			OUT_BATCH(_3DSTATE_MAP_STATE | 9);
			OUT_BATCH(0x00000007);

			if (adaptor_priv->buf)
				OUT_RELOC(adaptor_priv->buf,
					  I915_GEM_DOMAIN_SAMPLER, 0,
					  adaptor_priv->YBufOffset);
			else
				OUT_BATCH(adaptor_priv->YBufOffset);

			ms3 = MAPSURF_8BIT | MT_8BIT_I8;
			ms3 |= (height - 1) << MS3_HEIGHT_SHIFT;
			ms3 |= (width - 1) << MS3_WIDTH_SHIFT;
			OUT_BATCH(ms3);
			/* check to see if Y has special pitch than normal
			 * double u/v pitch, e.g i915 XvMC hw requires at
			 * least 1K alignment, so Y pitch might
			 * be same as U/V's.*/
			if (video_pitch2)
				OUT_BATCH(((video_pitch2 / 4) -
					   1) << MS4_PITCH_SHIFT);
			else
				OUT_BATCH(((video_pitch * 2 / 4) -
					   1) << MS4_PITCH_SHIFT);

			if (adaptor_priv->buf)
				OUT_RELOC(adaptor_priv->buf,
					  I915_GEM_DOMAIN_SAMPLER, 0,
					  adaptor_priv->UBufOffset);
			else
				OUT_BATCH(adaptor_priv->UBufOffset);

			ms3 = MAPSURF_8BIT | MT_8BIT_I8;
			ms3 |= (height / 2 - 1) << MS3_HEIGHT_SHIFT;
			ms3 |= (width / 2 - 1) << MS3_WIDTH_SHIFT;
			OUT_BATCH(ms3);
			OUT_BATCH(((video_pitch / 4) - 1) << MS4_PITCH_SHIFT);

			if (adaptor_priv->buf)
				OUT_RELOC(adaptor_priv->buf,
					  I915_GEM_DOMAIN_SAMPLER, 0,
					  adaptor_priv->VBufOffset);
			else
				OUT_BATCH(adaptor_priv->VBufOffset);

			ms3 = MAPSURF_8BIT | MT_8BIT_I8;
			ms3 |= (height / 2 - 1) << MS3_HEIGHT_SHIFT;
			ms3 |= (width / 2 - 1) << MS3_WIDTH_SHIFT;
			OUT_BATCH(ms3);
			OUT_BATCH(((video_pitch / 4) - 1) << MS4_PITCH_SHIFT);

			FS_BEGIN();
			/* Declare samplers */
			i915_fs_dcl(FS_S0);	/* Y */
			i915_fs_dcl(FS_S1);	/* U */
			i915_fs_dcl(FS_S2);	/* V */
			i915_fs_dcl(FS_T0);	/* normalized coords */

			/* Load samplers to temporaries. */
			i915_fs_texld(FS_R1, FS_S0, FS_T0);
			i915_fs_texld(FS_R2, FS_S1, FS_T0);
			i915_fs_texld(FS_R3, FS_S2, FS_T0);

			/* Move the sampled YUV data in R[123] to the first
			 * 3 channels of R0.
			 */
			i915_fs_mov_masked(FS_R0, MASK_X,
					   i915_fs_operand_reg(FS_R1));
			i915_fs_mov_masked(FS_R0, MASK_Y,
					   i915_fs_operand_reg(FS_R2));
			i915_fs_mov_masked(FS_R0, MASK_Z,
					   i915_fs_operand_reg(FS_R3));

			/* Normalize the YUV data */
			i915_fs_add(FS_R0, i915_fs_operand_reg(FS_R0),
				    i915_fs_operand_reg(FS_C0));
			/* dot-product the YUV data in R0 by the vectors of
			 * coefficients for calculating R, G, and B, storing
			 * the results in the R, G, or B channels of the output
			 * color.  The OC results are implicitly clamped
			 * at the end of the program.
			 */
			i915_fs_dp3(FS_OC, MASK_X,
				    i915_fs_operand_reg(FS_R0),
				    i915_fs_operand_reg(FS_C1));
			i915_fs_dp3(FS_OC, MASK_Y,
				    i915_fs_operand_reg(FS_R0),
				    i915_fs_operand_reg(FS_C2));
			i915_fs_dp3(FS_OC, MASK_Z,
				    i915_fs_operand_reg(FS_R0),
				    i915_fs_operand_reg(FS_C3));
			/* Set alpha of the output to 1.0, by wiring W to 1
			 * and not actually using the source.
			 */
			i915_fs_mov_masked(FS_OC, MASK_W,
					   i915_fs_operand_one());

			if (adaptor_priv->brightness != 0) {
				i915_fs_add(FS_OC,
					    i915_fs_operand_reg(FS_OC),
					    i915_fs_operand(FS_C4, X, X, X,
							    ZERO));
			}
			FS_END();
		}

		OUT_BATCH(PRIM3D_RECTLIST | (12 * nbox_this_time - 1));
		while (nbox_this_time--) {
			int box_x1 = pbox->x1;
			int box_y1 = pbox->y1;
			int box_x2 = pbox->x2;
			int box_y2 = pbox->y2;
			float src_scale_x, src_scale_y;

			pbox++;

			src_scale_x = ((float)src_w / width) / drw_w;
			src_scale_y = ((float)src_h / height) / drw_h;

			/* vertex data - rect list consists of bottom right,
			 * bottom left, and top left vertices.
			 */

			/* bottom right */
			OUT_BATCH_F(box_x2 + pix_xoff);
			OUT_BATCH_F(box_y2 + pix_yoff);
			OUT_BATCH_F((box_x2 - dxo) * src_scale_x);
			OUT_BATCH_F((box_y2 - dyo) * src_scale_y);

			/* bottom left */
			OUT_BATCH_F(box_x1 + pix_xoff);
			OUT_BATCH_F(box_y2 + pix_yoff);
			OUT_BATCH_F((box_x1 - dxo) * src_scale_x);
			OUT_BATCH_F((box_y2 - dyo) * src_scale_y);

			/* top left */
			OUT_BATCH_F(box_x1 + pix_xoff);
			OUT_BATCH_F(box_y1 + pix_yoff);
			OUT_BATCH_F((box_x1 - dxo) * src_scale_x);
			OUT_BATCH_F((box_y1 - dyo) * src_scale_y);
		}

		intel_batch_end_atomic(scrn);
	}

	if (target != pixmap) {
		GCPtr gc;

		gc = GetScratchGC(pixmap->drawable.depth,
				  pixmap->drawable.pScreen);
		if (gc) {
			gc->subWindowMode = ClipByChildren;

			if (REGION_NUM_RECTS(dstRegion) > 1) {
				RegionPtr tmp;

				tmp = REGION_CREATE(pixmap->drawable.pScreen, NULL, 0);
				if (tmp) {
					REGION_COPY(pixmap->drawable.pScreen, tmp, dstRegion);
					gc->funcs->ChangeClip(gc, CT_REGION, tmp, 0);
				}
			}

			ValidateGC(&pixmap->drawable, gc);
			gc->ops->CopyArea(&target->drawable, &pixmap->drawable, gc,
					  0, 0,
					  target->drawable.width,
					  target->drawable.height,
					  -pix_xoff, -pix_yoff);
			FreeScratchGC(gc);
		}

		target->drawable.pScreen->DestroyPixmap(target);
	}

	intel_uxa_debug_flush(scrn);
}
void
miPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
	       unsigned int nglyph, CharInfoPtr *ppci, pointer pglyphBase)
{
    int width, height;
    PixmapPtr pPixmap;
    int nbyLine;			/* bytes per line of padded pixmap */
    FontPtr pfont;
    GCPtr pGCtmp;
    int i;
    int j;
    unsigned char *pbits;		/* buffer for PutImage */
    unsigned char *pb;		/* temp pointer into buffer */
    CharInfoPtr pci;		/* currect char info */
    unsigned char *pglyph;	/* pointer bits in glyph */
    int gWidth, gHeight;		/* width and height of glyph */
    int nbyGlyphWidth;		/* bytes per scanline of glyph */
    int nbyPadGlyph;			/* server padded line of glyph */

    XID gcvals[3];

    if (pGC->miTranslate)
    {
	x += pDrawable->x;
	y += pDrawable->y;
    }

    pfont = pGC->font;
    width = FONTMAXBOUNDS(pfont,rightSideBearing) - 
	    FONTMINBOUNDS(pfont,leftSideBearing);
    height = FONTMAXBOUNDS(pfont,ascent) +
	     FONTMAXBOUNDS(pfont,descent);

    pPixmap = (*pDrawable->pScreen->CreatePixmap)(pDrawable->pScreen,
						  width, height, 1);
    if (!pPixmap)
	return;

    pGCtmp = GetScratchGC(1, pDrawable->pScreen);
    if (!pGCtmp)
    {
	(*pDrawable->pScreen->DestroyPixmap)(pPixmap);
	return;
    }

    gcvals[0] = GXcopy;
    gcvals[1] = 1;
    gcvals[2] = 0;

    DoChangeGC(pGCtmp, GCFunction|GCForeground|GCBackground, gcvals, 0);

    nbyLine = BitmapBytePad(width);
    pbits = (unsigned char *)ALLOCATE_LOCAL(height*nbyLine);
    if (!pbits)
    {
	(*pDrawable->pScreen->DestroyPixmap)(pPixmap);
	FreeScratchGC(pGCtmp);
        return;
    }
    while(nglyph--)
    {
	pci = *ppci++;
	pglyph = FONTGLYPHBITS(pglyphBase, pci);
	gWidth = GLYPHWIDTHPIXELS(pci);
	gHeight = GLYPHHEIGHTPIXELS(pci);
	if (gWidth && gHeight)
	{
	    nbyGlyphWidth = GLYPHWIDTHBYTESPADDED(pci);
	    nbyPadGlyph = BitmapBytePad(gWidth);

	    if (nbyGlyphWidth == nbyPadGlyph
#if GLYPHPADBYTES != 4
	        && (((int) pglyph) & 3) == 0
#endif
		)
	    {
		pb = pglyph;
	    }
	    else
	    {
		for (i=0, pb = pbits; i<gHeight; i++, pb = pbits+(i*nbyPadGlyph))
		    for (j = 0; j < nbyGlyphWidth; j++)
			*pb++ = *pglyph++;
		pb = pbits;
	    }

	    if ((pGCtmp->serialNumber) != (pPixmap->drawable.serialNumber))
		ValidateGC((DrawablePtr)pPixmap, pGCtmp);
	    (*pGCtmp->ops->PutImage)((DrawablePtr)pPixmap, pGCtmp,
				pPixmap->drawable.depth,
				0, 0, gWidth, gHeight, 
				0, XYBitmap, (char *)pb);

	    if ((pGC->serialNumber) != (pDrawable->serialNumber))
		ValidateGC(pDrawable, pGC);
	    (*pGC->ops->PushPixels)(pGC, pPixmap, pDrawable,
			       gWidth, gHeight,
			       x + pci->metrics.leftSideBearing,
			       y - pci->metrics.ascent);
	}
	x += pci->metrics.characterWidth;
    }
    (*pDrawable->pScreen->DestroyPixmap)(pPixmap);
    DEALLOCATE_LOCAL(pbits);
    FreeScratchGC(pGCtmp);
}
/* XaceCensorImage
 *
 * Called after pScreen->GetImage to prevent pieces or trusted windows from
 * being returned in image data from an untrusted window.
 *
 * Arguments:
 *	client is the client doing the GetImage.
 *      pVisibleRegion is the visible region of the window.
 *	widthBytesLine is the width in bytes of one horizontal line in pBuf.
 *	pDraw is the source window.
 *	x, y, w, h is the rectangle of image data from pDraw in pBuf.
 *	format is the format of the image data in pBuf: ZPixmap or XYPixmap.
 *	pBuf is the image data.
 *
 * Returns: nothing.
 *
 * Side Effects:
 *	Any part of the rectangle (x, y, w, h) that is outside the visible
 *	region of the window will be destroyed (overwritten) in pBuf.
 */
void
XaceCensorImage(
	ClientPtr client,
	RegionPtr pVisibleRegion,
	long widthBytesLine,
	DrawablePtr pDraw,
	int x, int y, int w, int h,
	unsigned int format,
	char *pBuf)
{
    ScreenPtr pScreen;
    RegionRec imageRegion;  /* region representing x,y,w,h */
    RegionRec censorRegion; /* region to obliterate */
    BoxRec imageBox;
    int nRects;

    pScreen = pDraw->pScreen;

    imageBox.x1 = x;
    imageBox.y1 = y;
    imageBox.x2 = x + w;
    imageBox.y2 = y + h;
    REGION_INIT(pScreen, &imageRegion, &imageBox, 1);
    REGION_NULL(pScreen, &censorRegion);

    /* censorRegion = imageRegion - visibleRegion */
    REGION_SUBTRACT(pScreen, &censorRegion, &imageRegion, pVisibleRegion);
    nRects = REGION_NUM_RECTS(&censorRegion);
    if (nRects > 0)
    { /* we have something to censor */
	GCPtr pScratchGC = NULL;
	PixmapPtr pPix = NULL;
	xRectangle *pRects = NULL;
	Bool failed = FALSE;
	int depth = 1;
	int bitsPerPixel = 1;
	int i;
	BoxPtr pBox;

	/* convert region to list-of-rectangles for PolyFillRect */

	pRects = xalloc(nRects * sizeof(xRectangle));
	if (!pRects)
	{
	    failed = TRUE;
	    goto failSafe;
	}
	for (pBox = REGION_RECTS(&censorRegion), i = 0;
	     i < nRects;
	     i++, pBox++)
	{
	    pRects[i].x = pBox->x1;
	    pRects[i].y = pBox->y1 - imageBox.y1;
	    pRects[i].width  = pBox->x2 - pBox->x1;
	    pRects[i].height = pBox->y2 - pBox->y1;
	}

	/* use pBuf as a fake pixmap */

	if (format == ZPixmap)
	{
	    depth = pDraw->depth;
	    bitsPerPixel = pDraw->bitsPerPixel;
	}

	pPix = GetScratchPixmapHeader(pDraw->pScreen, w, h,
		    depth, bitsPerPixel,
		    widthBytesLine, (pointer)pBuf);
	if (!pPix)
	{
	    failed = TRUE;
	    goto failSafe;
	}

	pScratchGC = GetScratchGC(depth, pPix->drawable.pScreen);
	if (!pScratchGC)
	{
	    failed = TRUE;
	    goto failSafe;
	}

	ValidateGC(&pPix->drawable, pScratchGC);
	(* pScratchGC->ops->PolyFillRect)(&pPix->drawable,
			    pScratchGC, nRects, pRects);

    failSafe:
	if (failed)
	{
	    /* Censoring was not completed above.  To be safe, wipe out
	     * all the image data so that nothing trusted gets out.
	     */
	    bzero(pBuf, (int)(widthBytesLine * h));
	}
	if (pRects)     xfree(pRects);
	if (pScratchGC) FreeScratchGC(pScratchGC);
	if (pPix)       FreeScratchPixmapHeader(pPix);
    }
    REGION_UNINIT(pScreen, &imageRegion);
    REGION_UNINIT(pScreen, &censorRegion);
} /* XaceCensorImage */
Beispiel #29
0
void
exaGlyphs(CARD8 op,
          PicturePtr pSrc,
          PicturePtr pDst,
          PictFormatPtr maskFormat,
          INT16 xSrc,
          INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr * glyphs)
{
    PixmapPtr pMaskPixmap = 0;
    PicturePtr pMask = NULL;
    ScreenPtr pScreen = pDst->pDrawable->pScreen;
    int width = 0, height = 0;
    int x, y;
    int first_xOff = list->xOff, first_yOff = list->yOff;
    int n;
    GlyphPtr glyph;
    int error;
    BoxRec extents = { 0, 0, 0, 0 };
    CARD32 component_alpha;
    ExaGlyphBuffer buffer;

    if (maskFormat) {
        ExaScreenPriv(pScreen);
        GCPtr pGC;
        xRectangle rect;

        GlyphExtents(nlist, list, glyphs, &extents);

        if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1)
            return;
        width = extents.x2 - extents.x1;
        height = extents.y2 - extents.y1;

        if (maskFormat->depth == 1) {
            PictFormatPtr a8Format = PictureMatchFormat(pScreen, 8, PICT_a8);

            if (a8Format)
                maskFormat = a8Format;
        }

        pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height,
                                                maskFormat->depth,
                                                CREATE_PIXMAP_USAGE_SCRATCH);
        if (!pMaskPixmap)
            return;
        component_alpha = NeedsComponent(maskFormat->format);
        pMask = CreatePicture(0, &pMaskPixmap->drawable,
                              maskFormat, CPComponentAlpha, &component_alpha,
                              serverClient, &error);
        if (!pMask ||
            (!component_alpha && pExaScr->info->CheckComposite &&
             !(*pExaScr->info->CheckComposite) (PictOpAdd, pSrc, NULL, pMask)))
        {
            PictFormatPtr argbFormat;

            (*pScreen->DestroyPixmap) (pMaskPixmap);

            if (!pMask)
                return;

            /* The driver can't seem to composite to a8, let's try argb (but
             * without component-alpha) */
            FreePicture((pointer) pMask, (XID) 0);

            argbFormat = PictureMatchFormat(pScreen, 32, PICT_a8r8g8b8);

            if (argbFormat)
                maskFormat = argbFormat;

            pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height,
                                                    maskFormat->depth,
                                                    CREATE_PIXMAP_USAGE_SCRATCH);
            if (!pMaskPixmap)
                return;

            pMask = CreatePicture(0, &pMaskPixmap->drawable, maskFormat, 0, 0,
                                  serverClient, &error);
            if (!pMask) {
                (*pScreen->DestroyPixmap) (pMaskPixmap);
                return;
            }
        }
        pGC = GetScratchGC(pMaskPixmap->drawable.depth, pScreen);
        ValidateGC(&pMaskPixmap->drawable, pGC);
        rect.x = 0;
        rect.y = 0;
        rect.width = width;
        rect.height = height;
        (*pGC->ops->PolyFillRect) (&pMaskPixmap->drawable, pGC, 1, &rect);
        FreeScratchGC(pGC);
        x = -extents.x1;
        y = -extents.y1;
    }
    else {
        x = 0;
        y = 0;
    }
    buffer.count = 0;
    buffer.mask = NULL;
    while (nlist--) {
        x += list->xOff;
        y += list->yOff;
        n = list->len;
        while (n--) {
            glyph = *glyphs++;

            if (glyph->info.width > 0 && glyph->info.height > 0) {
                /* pGlyph->info.{x,y} compensate for empty space in the glyph. */
                if (maskFormat) {
                    if (exaBufferGlyph(pScreen, &buffer, glyph, NULL, pMask,
                                       0, 0, 0, 0, x - glyph->info.x,
                                       y - glyph->info.y) ==
                        ExaGlyphNeedFlush) {
                        exaGlyphsToMask(pMask, &buffer);
                        exaBufferGlyph(pScreen, &buffer, glyph, NULL, pMask,
                                       0, 0, 0, 0, x - glyph->info.x,
                                       y - glyph->info.y);
                    }
                }
                else {
                    if (exaBufferGlyph(pScreen, &buffer, glyph, pSrc, pDst,
                                       xSrc + (x - glyph->info.x) - first_xOff,
                                       ySrc + (y - glyph->info.y) - first_yOff,
                                       0, 0, x - glyph->info.x,
                                       y - glyph->info.y)
                        == ExaGlyphNeedFlush) {
                        exaGlyphsToDst(pSrc, pDst, &buffer);
                        exaBufferGlyph(pScreen, &buffer, glyph, pSrc, pDst,
                                       xSrc + (x - glyph->info.x) - first_xOff,
                                       ySrc + (y - glyph->info.y) - first_yOff,
                                       0, 0, x - glyph->info.x,
                                       y - glyph->info.y);
                    }
                }
            }

            x += glyph->info.xOff;
            y += glyph->info.yOff;
        }
        list++;
    }

    if (buffer.count) {
        if (maskFormat)
            exaGlyphsToMask(pMask, &buffer);
        else
            exaGlyphsToDst(pSrc, pDst, &buffer);
    }

    if (maskFormat) {
        x = extents.x1;
        y = extents.y1;
        CompositePicture(op,
                         pSrc,
                         pMask,
                         pDst,
                         xSrc + x - first_xOff,
                         ySrc + y - first_yOff, 0, 0, x, y, width, height);
        FreePicture((pointer) pMask, (XID) 0);
        (*pScreen->DestroyPixmap) (pMaskPixmap);
    }
}
Beispiel #30
0
void
PsPaintWindow(
  WindowPtr pWin,
  RegionPtr pRegion,
  int       what)
{
  int       status;
  WindowPtr pRoot;

#define FUNCTION        0
#define FOREGROUND      1
#define TILE            2
#define FILLSTYLE       3
#define ABSX            4
#define ABSY            5
#define CLIPMASK        6
#define SUBWINDOW       7
#define COUNT_BITS      8

  pointer              gcval[7];
  pointer              newValues [COUNT_BITS];

  BITS32               gcmask, index, mask;
  RegionRec            prgnWin;
  DDXPointRec          oldCorner;
  BoxRec               box;
  WindowPtr            pBgWin;
  GCPtr                pGC;
  register int         i;
  register BoxPtr      pbox;
  register ScreenPtr   pScreen = pWin->drawable.pScreen;
  register xRectangle *prect;
  int                  numRects;

  gcmask = 0;

  /*
   * We don't want to paint a window that has no place to put the
   * PS output.
   */
  if( PsGetContextFromWindow(pWin)==(XpContextPtr)NULL ) return;

  if( what==PW_BACKGROUND )
  {
    switch(pWin->backgroundState)
    {
      case None: return;
      case ParentRelative:
        (*pWin->parent->drawable.pScreen->PaintWindowBackground)
          (pWin->parent, pRegion, what);
        return;
      case BackgroundPixel:
        newValues[FOREGROUND] = (pointer)pWin->background.pixel;
        newValues[FILLSTYLE] = (pointer)FillSolid;
        gcmask |= GCForeground | GCFillStyle;
        break;
      case BackgroundPixmap:
        newValues[TILE] = (pointer)pWin->background.pixmap;
        newValues[FILLSTYLE] = (pointer)FillTiled;
        gcmask |= GCTile | GCFillStyle | GCTileStipXOrigin | GCTileStipYOrigin;
        break;
    }
  }
  else
  {
    if( pWin->borderIsPixel )
    {
      newValues[FOREGROUND] = (pointer)pWin->border.pixel;
      newValues[FILLSTYLE] = (pointer)FillSolid;
      gcmask |= GCForeground | GCFillStyle;
    }
    else
    {
      newValues[TILE] = (pointer)pWin->border.pixmap;
      newValues[FILLSTYLE] = (pointer)FillTiled;
      gcmask |= GCTile | GCFillStyle | GCTileStipXOrigin | GCTileStipYOrigin;
    }
  }

  prect = (xRectangle *)ALLOCATE_LOCAL(REGION_NUM_RECTS(pRegion) *
                                         sizeof(xRectangle));
  if( !prect ) return;

  newValues[FUNCTION] = (pointer)GXcopy;
  gcmask |= GCFunction | GCClipMask;

  i = pScreen->myNum;
  pRoot = WindowTable[i];

  pBgWin = pWin;
  if (what == PW_BORDER)
  {
    while( pBgWin->backgroundState==ParentRelative ) pBgWin = pBgWin->parent;
  }

  pGC = GetScratchGC(pWin->drawable.depth, pWin->drawable.pScreen);
  if( !pGC )
  {
    DEALLOCATE_LOCAL(prect);
    return;
  }
  /*
   * mash the clip list so we can paint the border by
   * mangling the window in place, pretending it
   * spans the entire screen
   */
  if( what==PW_BORDER )
  {
    prgnWin = pWin->clipList;
    oldCorner.x = pWin->drawable.x;
    oldCorner.y = pWin->drawable.y;
    pWin->drawable.x = pWin->drawable.y = 0;
    box.x1 = 0;
    box.y1 = 0;
    box.x2 = pScreen->width;
    box.y2 = pScreen->height;
    REGION_INIT(pScreen, &pWin->clipList, &box, 1);
    pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER;
    newValues[ABSX] = (pointer)(long)pBgWin->drawable.x;
    newValues[ABSY] = (pointer)(long)pBgWin->drawable.y;
  }
  else
  {
    newValues[ABSX] = (pointer)0;
    newValues[ABSY] = (pointer)0;
  }

/*
 * XXX Backing store is turned off for the PS driver

  if( pWin->backStorage )
    (*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeVisBack);
 */

  mask = gcmask;
  gcmask = 0;
  i = 0;
  while( mask )
  {
    index = lowbit (mask);
    mask &= ~index;
    switch(index)
    {
      case GCFunction:
        if( (pointer)(long)pGC->alu!=newValues[FUNCTION] )
        {
          gcmask |= index;
          gcval[i++] = newValues[FUNCTION];
        }
        break;
      case GCTileStipXOrigin:
        if( (pointer)(long)pGC->patOrg.x!=newValues[ABSX] )
        {
          gcmask |= index;
          gcval[i++] = newValues[ABSX];
        }
        break;
      case GCTileStipYOrigin:
        if( (pointer)(long)pGC->patOrg.y!=newValues[ABSY] )
        {
          gcmask |= index;
          gcval[i++] = newValues[ABSY];
        }
        break;
      case GCClipMask:
        if( (pointer)pGC->clientClipType!=(pointer)CT_NONE )
        {
          gcmask |= index;
          gcval[i++] = (pointer)CT_NONE;
        }
        break;
      case GCSubwindowMode:
        if( (pointer)pGC->subWindowMode!=newValues[SUBWINDOW] )
        {
          gcmask |= index;
          gcval[i++] = newValues[SUBWINDOW];
        }
        break;
      case GCTile:
        if( pGC->tileIsPixel || (pointer)pGC->tile.pixmap!=newValues[TILE] )
        {
          gcmask |= index;
          gcval[i++] = newValues[TILE];
        }
        break;
      case GCFillStyle:
        if( (pointer)pGC->fillStyle!=newValues[FILLSTYLE] )
        {
          gcmask |= index;
          gcval[i++] = newValues[FILLSTYLE];
        }
        break;
      case GCForeground:
        if( (pointer)pGC->fgPixel!=newValues[FOREGROUND] )
        {
          gcmask |= index;
          gcval[i++] = newValues[FOREGROUND];
        }
        break;
    }
  }

  if( gcmask ) DoChangeGC(pGC, gcmask, (XID *)gcval, 1);

  if( pWin->drawable.serialNumber!=pGC->serialNumber )
    ValidateGC((DrawablePtr)pWin, pGC);

  numRects = REGION_NUM_RECTS(pRegion);
  pbox = REGION_RECTS(pRegion);
  for( i=numRects ; --i >= 0 ; pbox++,prect++ )
  {
    prect->x = pbox->x1 - pWin->drawable.x;
    prect->y = pbox->y1 - pWin->drawable.y;
    prect->width = pbox->x2 - pbox->x1;
    prect->height = pbox->y2 - pbox->y1;
  }
  prect -= numRects;
  (*pGC->ops->PolyFillRect)((DrawablePtr)pWin, pGC, numRects, prect);
  DEALLOCATE_LOCAL(prect);

/*
 * XXX Backing store is turned off for the PS driver

  if( pWin->backStorage )
    (*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeNothing);
 */

  if( what==PW_BORDER )
  {
    REGION_UNINIT(pScreen, &pWin->clipList);
    pWin->clipList = prgnWin;
    pWin->drawable.x = oldCorner.x;
    pWin->drawable.y = oldCorner.y;
    pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER;
  }
  FreeScratchGC(pGC);
}