コード例 #1
0
ファイル: miwindow.c プロジェクト: mmaruska/xserver
/*****
 *  miHandleValidateExposures(pWin)
 *    starting at pWin, draw background in any windows that have exposure
 *    regions, translate the regions, restore any backing store,
 *    and then send any regions still exposed to the client
 *****/
void
miHandleValidateExposures(WindowPtr pWin)
{
    WindowPtr pChild;
    ValidatePtr val;
    WindowExposuresProcPtr WindowExposures;

    pChild = pWin;
    WindowExposures = pChild->drawable.pScreen->WindowExposures;
    while (1) {
        if ((val = pChild->valdata)) {
            if (RegionNotEmpty(&val->after.borderExposed))
                miPaintWindow(pChild, &val->after.borderExposed, PW_BORDER);
            RegionUninit(&val->after.borderExposed);
            (*WindowExposures) (pChild, &val->after.exposed, NullRegion);
            RegionUninit(&val->after.exposed);
            free(val);
            pChild->valdata = NULL;
            if (pChild->firstChild) {
                pChild = pChild->firstChild;
                continue;
            }
        }
        while (!pChild->nextSib && (pChild != pWin))
            pChild = pChild->parent;
        if (pChild == pWin)
            break;
        pChild = pChild->nextSib;
    }
}
コード例 #2
0
ファイル: ephyr.c プロジェクト: AmesianX/xorg-server
static void
ephyrInternalDamageRedisplay(ScreenPtr pScreen)
{
    KdScreenPriv(pScreen);
    KdScreenInfo *screen = pScreenPriv->screen;
    EphyrScrPriv *scrpriv = screen->driver;
    RegionPtr pRegion;

    if (!scrpriv || !scrpriv->pDamage)
        return;

    pRegion = DamageRegion(scrpriv->pDamage);

    if (RegionNotEmpty(pRegion)) {
        int nbox;
        BoxPtr pbox;

        if (ephyr_glamor) {
            ephyr_glamor_damage_redisplay(scrpriv->glamor, pRegion);
        } else {
            nbox = RegionNumRects(pRegion);
            pbox = RegionRects(pRegion);

            while (nbox--) {
                hostx_paint_rect(screen,
                                 pbox->x1, pbox->y1,
                                 pbox->x1, pbox->y1,
                                 pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
                pbox++;
            }
        }
        DamageEmpty(scrpriv->pDamage);
    }
}
コード例 #3
0
ファイル: xf86Rotate.c プロジェクト: AmesianX/xorg-server
static Bool
xf86RotateRedisplay(ScreenPtr pScreen)
{
    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
    DamagePtr damage = xf86_config->rotation_damage;
    RegionPtr region;

    if (!damage)
        return FALSE;
    xf86RotatePrepare(pScreen);
    region = DamageRegion(damage);
    if (RegionNotEmpty(region)) {
        int c;
        SourceValidateProcPtr SourceValidate;

        /*
         * SourceValidate is used by the software cursor code
         * to pull the cursor off of the screen when reading
         * bits from the frame buffer. Bypassing this function
         * leaves the software cursor in place
         */
        SourceValidate = pScreen->SourceValidate;
        pScreen->SourceValidate = NULL;

        for (c = 0; c < xf86_config->num_crtc; c++) {
            xf86CrtcPtr crtc = xf86_config->crtc[c];

            if (crtc->transform_in_use && crtc->enabled) {
                RegionRec crtc_damage;

                /* compute portion of damage that overlaps crtc */
                RegionInit(&crtc_damage, &crtc->bounds, 1);
                RegionIntersect(&crtc_damage, &crtc_damage, region);

                /* update damaged region */
                if (RegionNotEmpty(&crtc_damage))
                    xf86RotateCrtcRedisplay(crtc, &crtc_damage);

                RegionUninit(&crtc_damage);
            }
        }
        pScreen->SourceValidate = SourceValidate;
        DamageEmpty(damage);
    }
    return TRUE;
}
コード例 #4
0
ファイル: shadow.c プロジェクト: MrKepzie/xserver
static void
shadowRedisplay(ScreenPtr pScreen)
{
    shadowBuf(pScreen);
    RegionPtr pRegion;

    if (!pBuf || !pBuf->pDamage || !pBuf->update)
        return;
    pRegion = DamageRegion(pBuf->pDamage);
    if (RegionNotEmpty(pRegion)) {
        (*pBuf->update) (pScreen, pBuf);
        DamageEmpty(pBuf->pDamage);
    }
}
コード例 #5
0
/**
 * Returns TRUE if the pixmap is dirty (has been modified in its current
 * location compared to the other), or lacks a private for tracking
 * dirtiness.
 */
static Bool
exaPixmapIsDirty(PixmapPtr pPix)
{
    ExaPixmapPriv(pPix);

    if (pExaPixmap == NULL)
        EXA_FatalErrorDebugWithRet(("EXA bug: exaPixmapIsDirty was called on a non-exa pixmap.\n"), TRUE);

    if (!pExaPixmap->pDamage)
        return FALSE;

    return RegionNotEmpty(DamageRegion(pExaPixmap->pDamage)) ||
           !RegionEqual(&pExaPixmap->validSys, &pExaPixmap->validFB);
}
コード例 #6
0
ファイル: rdpdraw.c プロジェクト: piccolo/xrdp
static void
rdpValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr d)
{
    rdpGCRec *priv;
    int wrap;
    RegionPtr pRegion;

    LLOGLN(10, ("rdpValidateGC:"));
    GC_FUNC_PROLOGUE(pGC);
    pGC->funcs->ValidateGC(pGC, changes, d);

    if (g_wrapPixmap)
    {
        wrap = 1;
    }
    else
    {
        wrap = (d->type == DRAWABLE_WINDOW) && ((WindowPtr)d)->viewable;

        if (wrap)
        {
            if (pGC->subWindowMode == IncludeInferiors)
            {
                pRegion = &(((WindowPtr)d)->borderClip);
            }
            else
            {
                pRegion = &(((WindowPtr)d)->clipList);
            }

            wrap = RegionNotEmpty(pRegion);
        }
    }

    priv->ops = 0;

    if (wrap)
    {
        priv->ops = pGC->ops;
    }

    GC_FUNC_EPILOGUE(pGC);
}
コード例 #7
0
ファイル: micopy.c プロジェクト: mirror/xserver
RegionPtr
miDoCopy(DrawablePtr pSrcDrawable,
         DrawablePtr pDstDrawable,
         GCPtr pGC,
         int xIn,
         int yIn,
         int widthSrc,
         int heightSrc,
         int xOut, int yOut, miCopyProc copyProc, Pixel bitPlane, void *closure)
{
    RegionPtr prgnSrcClip = NULL;       /* may be a new region, or just a copy */
    Bool freeSrcClip = FALSE;
    RegionPtr prgnExposed = NULL;
    RegionRec rgnDst;
    int dx;
    int dy;
    int numRects;
    int box_x1;
    int box_y1;
    int box_x2;
    int box_y2;
    Bool fastSrc = FALSE;       /* for fast clipping with pixmap source */
    Bool fastDst = FALSE;       /* for fast clipping with one rect dest */
    Bool fastExpose = FALSE;    /* for fast exposures with pixmap source */

    /* Short cut for unmapped or fully clipped windows */
    if (pDstDrawable->type == DRAWABLE_WINDOW &&
        RegionNil(&((WindowPtr)pDstDrawable)->clipList)) {
        return NULL;
    }

    if (pSrcDrawable->pScreen->SourceValidate) {
        (*pSrcDrawable->pScreen->SourceValidate) (pSrcDrawable, xIn, yIn,
                                                  widthSrc, heightSrc,
                                                  pGC->subWindowMode);
    }

    /* Compute source clip region */
    if (pSrcDrawable->type == DRAWABLE_PIXMAP) {
        if ((pSrcDrawable == pDstDrawable) && (!pGC->clientClip))
            prgnSrcClip = miGetCompositeClip(pGC);
        else
            fastSrc = TRUE;
    }
    else {
        if (pGC->subWindowMode == IncludeInferiors) {
            /*
             * XFree86 DDX empties the border clip when the
             * VT is inactive, make sure the region isn't empty
             */
            if (!((WindowPtr) pSrcDrawable)->parent &&
                RegionNotEmpty(&((WindowPtr) pSrcDrawable)->borderClip)) {
                /*
                 * special case bitblt from root window in
                 * IncludeInferiors mode; just like from a pixmap
                 */
                fastSrc = TRUE;
            }
            else if ((pSrcDrawable == pDstDrawable) && (!pGC->clientClip)) {
                prgnSrcClip = miGetCompositeClip(pGC);
            }
            else {
                prgnSrcClip = NotClippedByChildren((WindowPtr) pSrcDrawable);
                freeSrcClip = TRUE;
            }
        }
        else {
            prgnSrcClip = &((WindowPtr) pSrcDrawable)->clipList;
        }
    }

    xIn += pSrcDrawable->x;
    yIn += pSrcDrawable->y;

    xOut += pDstDrawable->x;
    yOut += pDstDrawable->y;

    box_x1 = xIn;
    box_y1 = yIn;
    box_x2 = xIn + widthSrc;
    box_y2 = yIn + heightSrc;

    dx = xIn - xOut;
    dy = yIn - yOut;

    /* Don't create a source region if we are doing a fast clip */
    if (fastSrc) {
        RegionPtr cclip;

        fastExpose = TRUE;
        /*
         * clip the source; if regions extend beyond the source size,
         * make sure exposure events get sent
         */
        if (box_x1 < pSrcDrawable->x) {
            box_x1 = pSrcDrawable->x;
            fastExpose = FALSE;
        }
        if (box_y1 < pSrcDrawable->y) {
            box_y1 = pSrcDrawable->y;
            fastExpose = FALSE;
        }
        if (box_x2 > pSrcDrawable->x + (int) pSrcDrawable->width) {
            box_x2 = pSrcDrawable->x + (int) pSrcDrawable->width;
            fastExpose = FALSE;
        }
        if (box_y2 > pSrcDrawable->y + (int) pSrcDrawable->height) {
            box_y2 = pSrcDrawable->y + (int) pSrcDrawable->height;
            fastExpose = FALSE;
        }

        /* Translate and clip the dst to the destination composite clip */
        box_x1 -= dx;
        box_x2 -= dx;
        box_y1 -= dy;
        box_y2 -= dy;

        /* If the destination composite clip is one rectangle we can
           do the clip directly.  Otherwise we have to create a full
           blown region and call intersect */

        cclip = miGetCompositeClip(pGC);
        if (RegionNumRects(cclip) == 1) {
            BoxPtr pBox = RegionRects(cclip);

            if (box_x1 < pBox->x1)
                box_x1 = pBox->x1;
            if (box_x2 > pBox->x2)
                box_x2 = pBox->x2;
            if (box_y1 < pBox->y1)
                box_y1 = pBox->y1;
            if (box_y2 > pBox->y2)
                box_y2 = pBox->y2;
            fastDst = TRUE;
        }
    }

    /* Check to see if the region is empty */
    if (box_x1 >= box_x2 || box_y1 >= box_y2) {
        RegionNull(&rgnDst);
    }
    else {
        BoxRec box;

        box.x1 = box_x1;
        box.y1 = box_y1;
        box.x2 = box_x2;
        box.y2 = box_y2;
        RegionInit(&rgnDst, &box, 1);
    }

    /* Clip against complex source if needed */
    if (!fastSrc) {
        RegionIntersect(&rgnDst, &rgnDst, prgnSrcClip);
        RegionTranslate(&rgnDst, -dx, -dy);
    }

    /* Clip against complex dest if needed */
    if (!fastDst) {
        RegionIntersect(&rgnDst, &rgnDst, miGetCompositeClip(pGC));
    }

    /* Do bit blitting */
    numRects = RegionNumRects(&rgnDst);
    if (numRects && widthSrc && heightSrc)
        miCopyRegion(pSrcDrawable, pDstDrawable, pGC,
                     &rgnDst, dx, dy, copyProc, bitPlane, closure);

    /* Pixmap sources generate a NoExposed (we return NULL to do this) */
    if (!fastExpose && pGC->fExpose)
        prgnExposed = miHandleExposures(pSrcDrawable, pDstDrawable, pGC,
                                        xIn - pSrcDrawable->x,
                                        yIn - pSrcDrawable->y,
                                        widthSrc, heightSrc,
                                        xOut - pDstDrawable->x,
                                        yOut - pDstDrawable->y);
    RegionUninit(&rgnDst);
    if (freeSrcClip)
        RegionDestroy(prgnSrcClip);
    return prgnExposed;
}
コード例 #8
0
ファイル: rdpdraw.c プロジェクト: mehulsbhatt/xrdp
/* return 2, draw using clip */
int
rdp_get_clip(RegionPtr pRegion, DrawablePtr pDrawable, GCPtr pGC)
{
  WindowPtr pWindow;
  RegionPtr temp;
  BoxRec box;
  int rv;

  rv = 0;
  if (pDrawable->type == DRAWABLE_PIXMAP)
  {
    switch (pGC->clientClipType)
    {
      case CT_NONE:
        rv = 1;
        break;
      case CT_REGION:
        rv = 2;
        RegionCopy(pRegion, pGC->clientClip);
        break;
      default:
        rdpLog("unimp clip type %d\n", pGC->clientClipType);
        break;
    }
    if (rv == 2) /* check if the clip is the entire pixmap */
    {
      box.x1 = 0;
      box.y1 = 0;
      box.x2 = pDrawable->width;
      box.y2 = pDrawable->height;
      if (RegionContainsRect(pRegion, &box) == rgnIN)
      {
        rv = 1;
      }
    }
  }
  else if (pDrawable->type == DRAWABLE_WINDOW)
  {
    pWindow = (WindowPtr)pDrawable;
    if (pWindow->viewable)
    {
      if (pGC->subWindowMode == IncludeInferiors)
      {
        temp = &pWindow->borderClip;
      }
      else
      {
        temp = &pWindow->clipList;
      }
      if (RegionNotEmpty(temp))
      {
        switch (pGC->clientClipType)
        {
          case CT_NONE:
            rv = 2;
            RegionCopy(pRegion, temp);
            break;
          case CT_REGION:
            rv = 2;
            RegionCopy(pRegion, pGC->clientClip);
            RegionTranslate(pRegion,
                            pDrawable->x + pGC->clipOrg.x,
                            pDrawable->y + pGC->clipOrg.y);
            RegionIntersect(pRegion, pRegion, temp);
            break;
          default:
            rdpLog("unimp clip type %d\n", pGC->clientClipType);
            break;
        }
        if (rv == 2) /* check if the clip is the entire screen */
        {
          box.x1 = 0;
          box.y1 = 0;
          box.x2 = g_rdpScreen.width;
          box.y2 = g_rdpScreen.height;
          if (RegionContainsRect(pRegion, &box) == rgnIN)
          {
            rv = 1;
          }
        }
      }
    }
  }
  return rv;
}
コード例 #9
0
ファイル: rdpdraw.c プロジェクト: piccolo/xrdp
int
draw_item_pack(PixmapPtr pix, rdpPixmapRec *priv)
{
    struct rdp_draw_item *di;
    struct rdp_draw_item *di_prev;

#if 1

    /* look for repeating draw types */
    if (priv->draw_item_head != 0)
    {
        if (priv->draw_item_head->next != 0)
        {
            di_prev = priv->draw_item_head;
            di = priv->draw_item_head->next;

            while (di != 0)
            {
                if ((di_prev->type == RDI_IMGLL) && (di->type == RDI_IMGLL))
                {
                    LLOGLN(10, ("draw_item_pack: packing RDI_IMGLL"));
                    RegionUnion(di_prev->reg, di_prev->reg, di->reg);
                    draw_item_remove(priv, di);
                    di = di_prev->next;
                }
                else if ((di_prev->type == RDI_IMGLY) && (di->type == RDI_IMGLY))
                {
                    LLOGLN(10, ("draw_item_pack: packing RDI_IMGLY"));
                    RegionUnion(di_prev->reg, di_prev->reg, di->reg);
                    draw_item_remove(priv, di);
                    di = di_prev->next;
                }
                else
                {
                    di_prev = di;
                    di = di_prev->next;
                }
            }
        }
    }

#endif
#if 1

    /* subtract regions */
    if (priv->draw_item_tail != 0)
    {
        if (priv->draw_item_tail->prev != 0)
        {
            di = priv->draw_item_tail;

            while (di->prev != 0)
            {
                /* skip subtract flag
                 * draw items like line can't be used to clear(subtract) previous
                 * draw items since they are not opaque
                 * eg they can not be the 'S' in 'D = M - S'
                 * the region for line draw items is the clip region */
                if ((di->flags & 1) == 0)
                {
                    di_prev = di->prev;

                    while (di_prev != 0)
                    {
                        /* D = M - S */
                        RegionSubtract(di_prev->reg, di_prev->reg, di->reg);
                        di_prev = di_prev->prev;
                    }
                }

                di = di->prev;
            }
        }
    }

#endif
#if 1
    /* remove draw items with empty regions */
    di = priv->draw_item_head;
    di_prev = 0;

    while (di != 0)
    {
        if (!RegionNotEmpty(di->reg))
        {
            LLOGLN(10, ("draw_item_pack: removing empty item type %d", di->type));
            draw_item_remove(priv, di);
            di = di_prev == 0 ? priv->draw_item_head : di_prev->next;
        }
        else
        {
            di_prev = di;
            di = di->next;
        }
    }

#endif
    return 0;
}
コード例 #10
0
ファイル: xaaOverlayDF.c プロジェクト: csulmone/X11
void
XAAOverCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
{
    ScreenPtr pScreen = pWin->drawable.pScreen;
    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen);
    XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pScreen);
    ScrnInfoPtr pScrn = infoRec->pScrn;
    DDXPointPtr ppt, pptSrc;
    RegionRec rgnDst;
    BoxPtr pbox;
    int i, nbox, dx, dy;
    WindowPtr pRoot = pScreen->root;

    if (!pScrn->vtSema || !infoRec->ScreenToScreenBitBlt) {
        XAA_SCREEN_PROLOGUE(pScreen, CopyWindow);
        if (pScrn->vtSema && infoRec->NeedToSync) {
            (*infoRec->Sync) (pScrn);
            infoRec->NeedToSync = FALSE;
        }
        (*pScreen->CopyWindow) (pWin, ptOldOrg, prgnSrc);
        XAA_SCREEN_EPILOGUE(pScreen, CopyWindow, XAAOverCopyWindow);
        return;
    }

    infoRec->ScratchGC.alu = GXcopy;
    infoRec->ScratchGC.planemask = ~0;

    RegionNull(&rgnDst);

    dx = ptOldOrg.x - pWin->drawable.x;
    dy = ptOldOrg.y - pWin->drawable.y;
    RegionTranslate(prgnSrc, -dx, -dy);
    RegionIntersect(&rgnDst, &pWin->borderClip, prgnSrc);

    nbox = RegionNumRects(&rgnDst);
    if (nbox && (pptSrc = (DDXPointPtr) malloc(nbox * sizeof(DDXPointRec)))) {

        pbox = RegionRects(&rgnDst);
        for (i = nbox, ppt = pptSrc; i--; ppt++, pbox++) {
            ppt->x = pbox->x1 + dx;
            ppt->y = pbox->y1 + dy;
        }

        SWITCH_DEPTH(8);
        XAADoBitBlt((DrawablePtr) pRoot, (DrawablePtr) pRoot,
                    &(infoRec->ScratchGC), &rgnDst, pptSrc);

        if (pWin->drawable.bitsPerPixel != 8) {
            SWITCH_DEPTH(pScrn->depth);
            XAADoBitBlt((DrawablePtr) pRoot, (DrawablePtr) pRoot,
                        &(infoRec->ScratchGC), &rgnDst, pptSrc);
        }

        free(pptSrc);
    }

    RegionUninit(&rgnDst);

    if (pWin->drawable.depth == 8) {
        RegionNull(&rgnDst);
        miSegregateChildren(pWin, &rgnDst, pScrn->depth);
        if (RegionNotEmpty(&rgnDst)) {
            RegionIntersect(&rgnDst, &rgnDst, prgnSrc);
            nbox = RegionNumRects(&rgnDst);
            if (nbox &&
                (pptSrc = (DDXPointPtr) malloc(nbox * sizeof(DDXPointRec)))) {

                pbox = RegionRects(&rgnDst);
                for (i = nbox, ppt = pptSrc; i--; ppt++, pbox++) {
                    ppt->x = pbox->x1 + dx;
                    ppt->y = pbox->y1 + dy;
                }

                SWITCH_DEPTH(pScrn->depth);
                XAADoBitBlt((DrawablePtr) pRoot, (DrawablePtr) pRoot,
                            &(infoRec->ScratchGC), &rgnDst, pptSrc);
                free(pptSrc);
            }
        }
        RegionUninit(&rgnDst);
    }
}
コード例 #11
0
ファイル: sna_tiling.c プロジェクト: sgh/xf86-video-intel
bool sna_tiling_blt_copy_boxes(struct sna *sna, uint8_t alu,
			       struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
			       struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
			       int bpp, const BoxRec *box, int nbox)
{
	RegionRec region, tile, this;
	struct kgem_bo *bo;
	int step;
	bool ret = false;

	if (!kgem_bo_can_blt(&sna->kgem, src_bo) ||
	    !kgem_bo_can_blt(&sna->kgem, dst_bo)) {
		/* XXX */
		DBG(("%s: tiling blt fail: src?=%d, dst?=%d\n",
		     __FUNCTION__,
		     kgem_bo_can_blt(&sna->kgem, src_bo),
		     kgem_bo_can_blt(&sna->kgem, dst_bo)));
		return false;
	}

	pixman_region_init_rects(&region, box, nbox);

	/* Use a small step to accommodate enlargement through tile alignment */
	step = sna->render.max_3d_size;
	if (region.extents.x1 & (8*512 / bpp - 1) || region.extents.y1 & 63)
		step /= 2;
	while (step * step * 4 > sna->kgem.max_copy_tile_size)
		step /= 2;

	DBG(("%s (alu=%d), tile.size=%d, box=%dx[(%d, %d), (%d, %d)])\n",
	     __FUNCTION__, alu, step, nbox,
	     region.extents.x1, region.extents.y1,
	     region.extents.x2, region.extents.y2));

	for (tile.extents.y1 = tile.extents.y2 = region.extents.y1;
	     tile.extents.y2 < region.extents.y2;
	     tile.extents.y1 = tile.extents.y2) {
		tile.extents.y2 = tile.extents.y1 + step;
		if (tile.extents.y2 > region.extents.y2)
			tile.extents.y2 = region.extents.y2;

		for (tile.extents.x1 = tile.extents.x2 = region.extents.x1;
		     tile.extents.x2 < region.extents.x2;
		     tile.extents.x1 = tile.extents.x2) {
			int w, h;

			tile.extents.x2 = tile.extents.x1 + step;
			if (tile.extents.x2 > region.extents.x2)
				tile.extents.x2 = region.extents.x2;

			tile.data = NULL;

			RegionNull(&this);
			RegionIntersect(&this, &region, &tile);
			if (!RegionNotEmpty(&this))
				continue;

			w = this.extents.x2 - this.extents.x1;
			h = this.extents.y2 - this.extents.y1;
			bo = kgem_create_2d(&sna->kgem, w, h, bpp,
					    kgem_choose_tiling(&sna->kgem,
							       I915_TILING_X,
							       w, h, bpp),
					    CREATE_TEMPORARY);
			if (bo) {
				int16_t dx = this.extents.x1;
				int16_t dy = this.extents.y1;

				assert(bo->pitch <= 8192);
				assert(bo->tiling != I915_TILING_Y);

				if (!sna_blt_copy_boxes(sna, alu,
							src_bo, src_dx, src_dy,
							bo, -dx, -dy,
							bpp, REGION_RECTS(&this), REGION_NUM_RECTS(&this)))
					goto err;

				if (!sna_blt_copy_boxes(sna, alu,
							bo, -dx, -dy,
							dst_bo, dst_dx, dst_dy,
							bpp, REGION_RECTS(&this), REGION_NUM_RECTS(&this)))
					goto err;

				kgem_bo_destroy(&sna->kgem, bo);
			}
			RegionUninit(&this);
		}
	}

	ret = true;
	goto done;
err:
	kgem_bo_destroy(&sna->kgem, bo);
	RegionUninit(&this);
done:
	pixman_region_fini(&region);
	return ret;
}
コード例 #12
0
ファイル: sna_tiling.c プロジェクト: sgh/xf86-video-intel
bool
sna_tiling_fill_boxes(struct sna *sna,
		      CARD8 op,
		      PictFormat format,
		      const xRenderColor *color,
		      PixmapPtr dst, struct kgem_bo *dst_bo,
		      const BoxRec *box, int n)
{
	RegionRec region, tile, this;
	struct kgem_bo *bo;
	int step;
	bool ret = false;

	pixman_region_init_rects(&region, box, n);

	/* Use a small step to accommodate enlargement through tile alignment */
	step = sna->render.max_3d_size;
	if (region.extents.x1 & (8*512 / dst->drawable.bitsPerPixel - 1) ||
	    region.extents.y1 & 63)
		step /= 2;
	while (step * step * 4 > sna->kgem.max_copy_tile_size)
		step /= 2;

	DBG(("%s (op=%d, format=%x, color=(%04x,%04x,%04x, %04x), tile.size=%d, box=%dx[(%d, %d), (%d, %d)])\n",
	     __FUNCTION__, op, (int)format,
	     color->red, color->green, color->blue, color->alpha,
	     step, n,
	     region.extents.x1, region.extents.y1,
	     region.extents.x2, region.extents.y2));

	for (tile.extents.y1 = tile.extents.y2 = region.extents.y1;
	     tile.extents.y2 < region.extents.y2;
	     tile.extents.y1 = tile.extents.y2) {
		tile.extents.y2 = tile.extents.y1 + step;
		if (tile.extents.y2 > region.extents.y2)
			tile.extents.y2 = region.extents.y2;

		for (tile.extents.x1 = tile.extents.x2 = region.extents.x1;
		     tile.extents.x2 < region.extents.x2;
		     tile.extents.x1 = tile.extents.x2) {
			PixmapRec tmp;

			tile.extents.x2 = tile.extents.x1 + step;
			if (tile.extents.x2 > region.extents.x2)
				tile.extents.x2 = region.extents.x2;

			tile.data = NULL;

			RegionNull(&this);
			RegionIntersect(&this, &region, &tile);
			if (!RegionNotEmpty(&this))
				continue;

			tmp.drawable.width  = this.extents.x2 - this.extents.x1;
			tmp.drawable.height = this.extents.y2 - this.extents.y1;
			tmp.drawable.depth  = dst->drawable.depth;
			tmp.drawable.bitsPerPixel = dst->drawable.bitsPerPixel;
			tmp.devPrivate.ptr = NULL;

			bo = kgem_create_2d(&sna->kgem,
					    tmp.drawable.width,
					    tmp.drawable.height,
					    dst->drawable.bitsPerPixel,
					    kgem_choose_tiling(&sna->kgem,
							       I915_TILING_X,
							       tmp.drawable.width,
							       tmp.drawable.height,
							       dst->drawable.bitsPerPixel),
					    CREATE_TEMPORARY);
			if (bo) {
				int16_t dx = this.extents.x1;
				int16_t dy = this.extents.y1;

				assert(kgem_bo_can_blt(&sna->kgem, bo));

				if (!sna->render.copy_boxes(sna, GXcopy,
							     dst, dst_bo, 0, 0,
							     &tmp, bo, -dx, -dy,
							     REGION_RECTS(&this), REGION_NUM_RECTS(&this), 0))
					goto err;

				RegionTranslate(&this, -dx, -dy);
				if (!sna->render.fill_boxes(sna, op, format, color,
							     &tmp, bo,
							     REGION_RECTS(&this), REGION_NUM_RECTS(&this)))
					goto err;

				if (!sna->render.copy_boxes(sna, GXcopy,
							     &tmp, bo, 0, 0,
							     dst, dst_bo, dx, dy,
							     REGION_RECTS(&this), REGION_NUM_RECTS(&this), 0))
					goto err;

				kgem_bo_destroy(&sna->kgem, bo);
			}
			RegionUninit(&this);
		}
	}

	ret = true;
	goto done;
err:
	kgem_bo_destroy(&sna->kgem, bo);
	RegionUninit(&this);
done:
	pixman_region_fini(&region);
	return ret;
}