Example #1
0
static Bool
uxa_fill_region_solid(DrawablePtr pDrawable,
		      RegionPtr pRegion,
		      Pixel pixel, CARD32 planemask, CARD32 alu)
{
	ScreenPtr screen = pDrawable->pScreen;
	uxa_screen_t *uxa_screen = uxa_get_screen(screen);
	PixmapPtr pixmap;
	int xoff, yoff;
	int nbox;
	BoxPtr pBox;
	Bool ret = FALSE;

	pixmap = uxa_get_offscreen_pixmap(pDrawable, &xoff, &yoff);
	if (!pixmap)
		return FALSE;

	REGION_TRANSLATE(screen, pRegion, xoff, yoff);

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

	if (uxa_screen->info->check_solid &&
	    !uxa_screen->info->check_solid(&pixmap->drawable, alu, planemask))
		goto err;

	if (!uxa_screen->info->prepare_solid(pixmap, alu, planemask, pixel))
		goto err;

	while (nbox--) {
		uxa_screen->info->solid(pixmap,
					pBox->x1, pBox->y1,
					pBox->x2, pBox->y2);
		pBox++;
	}
	uxa_screen->info->done_solid(pixmap);
	ret = TRUE;

err:
	REGION_TRANSLATE(screen, pRegion, -xoff, -yoff);
	return ret;
}
Example #2
0
/**
 * uxa_prepare_access() is UXA's wrapper for the driver's PrepareAccess() handler.
 *
 * It deals with waiting for synchronization with the card, determining if
 * PrepareAccess() is necessary, and working around PrepareAccess() failure.
 */
Bool uxa_prepare_access(DrawablePtr pDrawable, RegionPtr region, uxa_access_t access)
{
	ScreenPtr pScreen = pDrawable->pScreen;
	uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
	int xoff, yoff;
	PixmapPtr pPixmap = uxa_get_offscreen_pixmap(pDrawable, &xoff, &yoff);
	BoxRec box;
	RegionRec region_rec;
	Bool result;

	if (!pPixmap)
	    return TRUE;

	if (!region)
	{
	    box.x1 = 0;
	    box.y1 = 0;
	    box.x2 = pDrawable->width;
	    box.y2 = pDrawable->height;

	    REGION_INIT (pScreen, &region_rec, &box, 1);
	    region = &region_rec;
	}
	else
	{
	    /* The driver expects a region in drawable coordinates */
	    REGION_TRANSLATE (pScreen, region, xoff, yoff);
	}
	
	result = TRUE;

	if (uxa_screen->info->prepare_access)
	    result = (*uxa_screen->info->prepare_access) (pPixmap, region, access);

	if (region == &region_rec)
	    REGION_UNINIT (pScreen, &region_rec);
	
	return result;
}
Example #3
0
static void
uxa_poly_fill_rect(DrawablePtr pDrawable,
		   GCPtr pGC, int nrect, xRectangle * prect)
{
	uxa_screen_t *uxa_screen = uxa_get_screen(pDrawable->pScreen);
	RegionPtr pClip = fbGetCompositeClip(pGC);
	PixmapPtr pPixmap;
	RegionPtr pReg;
	BoxPtr pbox;
	int fullX1, fullX2, fullY1, fullY2;
	int xoff, yoff;
	int xorg, yorg;
	int n;

	if (uxa_screen->info->flags & UXA_USE_GLAMOR) {
		int ok = 0;

		if (uxa_prepare_access(pDrawable, UXA_GLAMOR_ACCESS_RW)) {
			ok = glamor_poly_fill_rect_nf(pDrawable, pGC, nrect, prect);
			uxa_finish_access(pDrawable, UXA_GLAMOR_ACCESS_RW);
		}

		if (!ok)
			uxa_check_poly_fill_rect(pDrawable, pGC, nrect, prect);

		return;
	}

	/* Compute intersection of rects and clip region */
	pReg = RECTS_TO_REGION(pScreen, nrect, prect, CT_UNSORTED);
	REGION_TRANSLATE(pScreen, pReg, pDrawable->x, pDrawable->y);
	REGION_INTERSECT(pScreen, pReg, pClip, pReg);

	if (!REGION_NUM_RECTS(pReg))
		goto out;

	if (uxa_screen->force_fallback)
		goto fallback;

	pPixmap = uxa_get_offscreen_pixmap (pDrawable, &xoff, &yoff);
	if (!pPixmap)
		goto fallback;

	/* For ROPs where overlaps don't matter, convert rectangles to region
	 * and call uxa_fill_region_{solid,tiled}.
	 */
	if ((pGC->fillStyle == FillSolid || pGC->fillStyle == FillTiled) &&
	    (nrect == 1 || pGC->alu == GXcopy || pGC->alu == GXclear ||
	     pGC->alu == GXnoop || pGC->alu == GXcopyInverted ||
	     pGC->alu == GXset)) {
		if (((pGC->fillStyle == FillSolid || pGC->tileIsPixel) &&
		     uxa_fill_region_solid(pDrawable, pReg,
					   pGC->fillStyle ==
					   FillSolid ? pGC->fgPixel : pGC->tile.
					   pixel, pGC->planemask, pGC->alu))
		    || (pGC->fillStyle == FillTiled && !pGC->tileIsPixel
			&& uxa_fill_region_tiled(pDrawable, pReg,
						 pGC->tile.pixmap, &pGC->patOrg,
						 pGC->planemask, pGC->alu))) {
			goto out;
		}
	}

	if (pGC->fillStyle != FillSolid &&
	    !(pGC->tileIsPixel && pGC->fillStyle == FillTiled)) {
		goto fallback;
	}

	if (uxa_screen->info->check_solid &&
	    !uxa_screen->info->check_solid(pDrawable, pGC->alu, pGC->planemask)) {
		goto fallback;
	}

	if (!(*uxa_screen->info->prepare_solid) (pPixmap,
						 pGC->alu,
						 pGC->planemask,
						 pGC->fgPixel)) {
fallback:
		uxa_check_poly_fill_rect(pDrawable, pGC, nrect, prect);
		goto out;
	}

	xorg = pDrawable->x;
	yorg = pDrawable->y;

	while (nrect--) {
		fullX1 = prect->x + xorg;
		fullY1 = prect->y + yorg;
		fullX2 = fullX1 + (int)prect->width;
		fullY2 = fullY1 + (int)prect->height;
		prect++;

		n = REGION_NUM_RECTS(pClip);
		pbox = REGION_RECTS(pClip);
		/*
		 * clip the rectangle to each box in the clip region
		 * this is logically equivalent to calling Intersect(),
		 * but rectangles may overlap each other here.
		 */
		while (n--) {
			int x1 = fullX1;
			int x2 = fullX2;
			int y1 = fullY1;
			int y2 = fullY2;

			if (pbox->x1 > x1)
				x1 = pbox->x1;
			if (pbox->x2 < x2)
				x2 = pbox->x2;
			if (pbox->y1 > y1)
				y1 = pbox->y1;
			if (pbox->y2 < y2)
				y2 = pbox->y2;
			pbox++;

			if (x1 >= x2 || y1 >= y2)
				continue;

			(*uxa_screen->info->solid) (pPixmap,
						    x1 + xoff,
						    y1 + yoff,
						    x2 + xoff,
						    y2 + yoff);
		}
	}
	(*uxa_screen->info->done_solid) (pPixmap);

out:
	REGION_UNINIT(pScreen, pReg);
	REGION_DESTROY(pScreen, pReg);
}
Example #4
0
static void
uxa_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int n,
	       DDXPointPtr ppt, int *pwidth, int fSorted)
{
	ScreenPtr screen = pDrawable->pScreen;
	uxa_screen_t *uxa_screen = uxa_get_screen(screen);
	RegionPtr pClip = fbGetCompositeClip(pGC);
	PixmapPtr dst_pixmap;
	BoxPtr pbox;
	int nbox;
	int x1, x2, y;
	int off_x, off_y;

	if (uxa_screen->info->flags & UXA_USE_GLAMOR) {
		int ok = 0;

		if (uxa_prepare_access(pDrawable, UXA_GLAMOR_ACCESS_RW)) {
			ok = glamor_fill_spans_nf(pDrawable,
						  pGC, n, ppt, pwidth, fSorted);
			uxa_finish_access(pDrawable, UXA_GLAMOR_ACCESS_RW);
		}

		if (!ok)
			goto fallback;

		return;
	}

	if (uxa_screen->force_fallback)
		goto fallback;

	if (pGC->fillStyle != FillSolid)
		goto fallback;

	dst_pixmap = uxa_get_offscreen_pixmap(pDrawable, &off_x, &off_y);
	if (!dst_pixmap)
		goto fallback;

	if (uxa_screen->info->check_solid &&
	    !uxa_screen->info->check_solid(pDrawable, pGC->alu, pGC->planemask))
		goto fallback;

	if (!(*uxa_screen->info->prepare_solid) (dst_pixmap,
						 pGC->alu,
						 pGC->planemask,
						 pGC->fgPixel))
		goto fallback;

	while (n--) {
		x1 = ppt->x;
		y = ppt->y;
		x2 = x1 + (int)*pwidth;
		ppt++;
		pwidth++;

		nbox = REGION_NUM_RECTS(pClip);
		pbox = REGION_RECTS(pClip);
		while (nbox--) {
			int X1 = x1, X2 = x2;
			if (X1 < pbox->x1)
				X1 = pbox->x1;

			if (X2 > pbox->x2)
				X2 = pbox->x2;

			if (X2 > X1 && pbox->y1 <= y && pbox->y2 > y)
				(*uxa_screen->info->solid) (dst_pixmap,
							    X1 + off_x, y + off_y,
							    X2 + off_x, y + 1 + off_y);
			pbox++;
		}
	}
	(*uxa_screen->info->done_solid) (dst_pixmap);

	return;

fallback:
	uxa_check_fill_spans(pDrawable, pGC, n, ppt, pwidth, fSorted);
}
Example #5
0
static Bool inline
uxa_copy_n_to_n_two_dir(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
			GCPtr pGC, BoxPtr pbox, int nbox, int dx, int dy)
{
	uxa_screen_t *uxa_screen = uxa_get_screen(pDstDrawable->pScreen);
	PixmapPtr pSrcPixmap, pDstPixmap;
	int src_off_x, src_off_y, dst_off_x, dst_off_y;
	int dirsetup;

	/* Need to get both pixmaps to call the driver routines */
	pSrcPixmap =
	    uxa_get_offscreen_pixmap(pSrcDrawable, &src_off_x, &src_off_y);
	pDstPixmap =
	    uxa_get_offscreen_pixmap(pDstDrawable, &dst_off_x, &dst_off_y);
	if (!pSrcPixmap || !pDstPixmap)
		return FALSE;

	/*
	 * Now the case of a chip that only supports xdir = ydir = 1 or
	 * xdir = ydir = -1, but we have xdir != ydir.
	 */
	dirsetup = 0;		/* No direction set up yet. */
	for (; nbox; pbox++, nbox--) {
		if (dx >= 0 && (src_off_y + pbox->y1 + dy) != pbox->y1) {
			/* Do a xdir = ydir = -1 blit instead. */
			if (dirsetup != -1) {
				if (dirsetup != 0)
					uxa_screen->info->done_copy(pDstPixmap);
				dirsetup = -1;
				if (!(*uxa_screen->info->prepare_copy)
				    (pSrcPixmap, pDstPixmap, -1, -1,
				     pGC ? pGC->alu : GXcopy,
				     pGC ? pGC->planemask : FB_ALLONES))
					return FALSE;
			}
			(*uxa_screen->info->copy) (pDstPixmap,
						   src_off_x + pbox->x1 + dx,
						   src_off_y + pbox->y1 + dy,
						   dst_off_x + pbox->x1,
						   dst_off_y + pbox->y1,
						   pbox->x2 - pbox->x1,
						   pbox->y2 - pbox->y1);
		} else if (dx < 0 && (src_off_y + pbox->y1 + dy) != pbox->y1) {
			/* Do a xdir = ydir = 1 blit instead. */
			if (dirsetup != 1) {
				if (dirsetup != 0)
					uxa_screen->info->done_copy(pDstPixmap);
				dirsetup = 1;
				if (!(*uxa_screen->info->prepare_copy)
				    (pSrcPixmap, pDstPixmap, 1, 1,
				     pGC ? pGC->alu : GXcopy,
				     pGC ? pGC->planemask : FB_ALLONES))
					return FALSE;
			}
			(*uxa_screen->info->copy) (pDstPixmap,
						   src_off_x + pbox->x1 + dx,
						   src_off_y + pbox->y1 + dy,
						   dst_off_x + pbox->x1,
						   dst_off_y + pbox->y1,
						   pbox->x2 - pbox->x1,
						   pbox->y2 - pbox->y1);
		} else if (dx >= 0) {
			/*
			 * xdir = 1, ydir = -1.
			 * Perform line-by-line xdir = ydir = 1 blits, going up.
			 */
			int i;
			if (dirsetup != 1) {
				if (dirsetup != 0)
					uxa_screen->info->done_copy(pDstPixmap);
				dirsetup = 1;
				if (!(*uxa_screen->info->prepare_copy)
				    (pSrcPixmap, pDstPixmap, 1, 1,
				     pGC ? pGC->alu : GXcopy,
				     pGC ? pGC->planemask : FB_ALLONES))
					return FALSE;
			}
			for (i = pbox->y2 - pbox->y1 - 1; i >= 0; i--)
				(*uxa_screen->info->copy) (pDstPixmap,
							   src_off_x +
							   pbox->x1 + dx,
							   src_off_y +
							   pbox->y1 + dy + i,
							   dst_off_x + pbox->x1,
							   dst_off_y +
							   pbox->y1 + i,
							   pbox->x2 - pbox->x1,
							   1);
		} else {
			/*
			 * xdir = -1, ydir = 1.
			 * Perform line-by-line xdir = ydir = -1 blits,
			 * going down.
			 */
			int i;
			if (dirsetup != -1) {
				if (dirsetup != 0)
					uxa_screen->info->done_copy(pDstPixmap);
				dirsetup = -1;
				if (!(*uxa_screen->info->prepare_copy)
				    (pSrcPixmap, pDstPixmap, -1, -1,
				     pGC ? pGC->alu : GXcopy,
				     pGC ? pGC->planemask : FB_ALLONES))
					return FALSE;
			}
			for (i = 0; i < pbox->y2 - pbox->y1; i++)
				(*uxa_screen->info->copy) (pDstPixmap,
							   src_off_x +
							   pbox->x1 + dx,
							   src_off_y +
							   pbox->y1 + dy + i,
							   dst_off_x + pbox->x1,
							   dst_off_y +
							   pbox->y1 + i,
							   pbox->x2 - pbox->x1,
							   1);
		}
	}
	if (dirsetup != 0)
		uxa_screen->info->done_copy(pDstPixmap);
	return TRUE;
}
Example #6
0
/**
 * Accelerates GetImage for solid ZPixmap downloads from framebuffer memory.
 *
 * This is probably the only case we actually care about.  The rest fall through
 * to migration and fbGetImage, which hopefully will result in migration pushing
 * the pixmap out of framebuffer.
 */
void
uxa_get_image(DrawablePtr pDrawable, int x, int y, int w, int h,
	      unsigned int format, unsigned long planeMask, char *d)
{
	ScreenPtr screen = pDrawable->pScreen;
	uxa_screen_t *uxa_screen = uxa_get_screen(screen);
	BoxRec Box;
	PixmapPtr pPix = uxa_get_drawable_pixmap(pDrawable);
	int xoff, yoff;
	Bool ok;

	uxa_get_drawable_deltas(pDrawable, pPix, &xoff, &yoff);

	Box.x1 = pDrawable->y + x + xoff;
	Box.y1 = pDrawable->y + y + yoff;
	Box.x2 = Box.x1 + w;
	Box.y2 = Box.y1 + h;

	if (uxa_screen->info->flags & UXA_USE_GLAMOR) {
		ok = 0;
		if (uxa_prepare_access(pDrawable, UXA_GLAMOR_ACCESS_RW)) {
			ok = glamor_get_image_nf(pDrawable, x, y, w, h,
						 format, planeMask, d);
			uxa_finish_access(pDrawable, UXA_GLAMOR_ACCESS_RW);
		}

		if (!ok)
			goto fallback;

		return;
	}

	if (uxa_screen->force_fallback)
		goto fallback;

	pPix = uxa_get_offscreen_pixmap(pDrawable, &xoff, &yoff);

	if (pPix == NULL || uxa_screen->info->get_image == NULL)
		goto fallback;

	/* Only cover the ZPixmap, solid copy case. */
	if (format != ZPixmap || !UXA_PM_IS_SOLID(pDrawable, planeMask))
		goto fallback;

	/* Only try to handle the 8bpp and up cases, since we don't want to
	 * think about <8bpp.
	 */
	if (pDrawable->bitsPerPixel < 8)
		goto fallback;

	ok = uxa_screen->info->get_image(pPix, pDrawable->x + x + xoff,
					 pDrawable->y + y + yoff, w, h, d,
					 PixmapBytePad(w, pDrawable->depth));
	if (ok)
		return;

fallback:
	UXA_FALLBACK(("from %p (%c)\n", pDrawable,
		      uxa_drawable_location(pDrawable)));

	if (uxa_prepare_access(pDrawable, UXA_ACCESS_RO)) {
		fbGetImage(pDrawable, x, y, w, h, format, planeMask, d);
		uxa_finish_access(pDrawable, UXA_ACCESS_RO);
	}

	return;
}
Example #7
0
static Bool
uxa_do_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
		 int w, int h, int format, char *bits, int src_stride)
{
	uxa_screen_t *uxa_screen = uxa_get_screen(pDrawable->pScreen);
	PixmapPtr pPix;
	RegionPtr pClip;
	BoxPtr pbox;
	int nbox;
	int xoff, yoff;
	int bpp = pDrawable->bitsPerPixel;

	/* Don't bother with under 8bpp, XYPixmaps. */
	if (format != ZPixmap || bpp < 8)
		return FALSE;

	if (uxa_screen->force_fallback)
		return FALSE;

	if (!uxa_screen->info->put_image)
		return FALSE;

	/* Only accelerate copies: no rop or planemask. */
	if (!UXA_PM_IS_SOLID(pDrawable, pGC->planemask) || pGC->alu != GXcopy)
		return FALSE;

	pPix = uxa_get_offscreen_pixmap(pDrawable, &xoff, &yoff);
	if (!pPix)
		return FALSE;

	x += pDrawable->x;
	y += pDrawable->y;

	pClip = fbGetCompositeClip(pGC);
	for (nbox = REGION_NUM_RECTS(pClip),
	     pbox = REGION_RECTS(pClip); nbox--; pbox++) {
		int x1 = x;
		int y1 = y;
		int x2 = x + w;
		int y2 = y + h;
		char *src;
		Bool ok;

		if (x1 < pbox->x1)
			x1 = pbox->x1;
		if (y1 < pbox->y1)
			y1 = pbox->y1;
		if (x2 > pbox->x2)
			x2 = pbox->x2;
		if (y2 > pbox->y2)
			y2 = pbox->y2;
		if (x1 >= x2 || y1 >= y2)
			continue;

		src = bits + (y1 - y) * src_stride + (x1 - x) * (bpp / 8);
		ok = uxa_screen->info->put_image(pPix, x1 + xoff, y1 + yoff,
						 x2 - x1, y2 - y1, src,
						 src_stride);
		/* If we fail to accelerate the upload, fall back to using
		 * unaccelerated fb calls.
		 */
		if (!ok) {
			FbStip *dst;
			FbStride dst_stride;
			int dstBpp;
			int dstXoff, dstYoff;

			if (!uxa_prepare_access(pDrawable, UXA_ACCESS_RW))
				return FALSE;

			fbGetStipDrawable(pDrawable, dst, dst_stride, dstBpp,
					  dstXoff, dstYoff);

			fbBltStip((FbStip *) bits +
				  (y1 - y) * (src_stride / sizeof(FbStip)),
				  src_stride / sizeof(FbStip),
				  (x1 - x) * dstBpp,
				  dst + (y1 + dstYoff) * dst_stride, dst_stride,
				  (x1 + dstXoff) * dstBpp, (x2 - x1) * dstBpp,
				  y2 - y1, GXcopy, FB_ALLONES, dstBpp);

			uxa_finish_access(pDrawable, UXA_ACCESS_RW);
		}
	}


	return TRUE;
}
Example #8
0
/* Try to do an accelerated tile of the pTile into pRegion of pDrawable.
 * Based on fbFillRegionTiled(), fbTile().
 */
Bool
uxa_fill_region_tiled(DrawablePtr pDrawable,
		      RegionPtr pRegion,
		      PixmapPtr pTile,
		      DDXPointPtr pPatOrg, CARD32 planemask, CARD32 alu)
{
	uxa_screen_t *uxa_screen = uxa_get_screen(pDrawable->pScreen);
	PixmapPtr pPixmap;
	int xoff, yoff;
	int tileWidth, tileHeight;
	int nbox = REGION_NUM_RECTS(pRegion);
	BoxPtr pBox = REGION_RECTS(pRegion);
	Bool ret = FALSE;

	tileWidth = pTile->drawable.width;
	tileHeight = pTile->drawable.height;

	/* If we're filling with a solid color, grab it out and go to
	 * FillRegionsolid, saving numerous copies.
	 */
	if (tileWidth == 1 && tileHeight == 1)
		return uxa_fill_region_solid(pDrawable, pRegion,
					     uxa_get_pixmap_first_pixel(pTile),
					     planemask, alu);

	pPixmap = uxa_get_offscreen_pixmap(pDrawable, &xoff, &yoff);
	if (!pPixmap || !uxa_pixmap_is_offscreen(pTile))
		goto out;

	if (uxa_screen->info->check_copy &&
	    !uxa_screen->info->check_copy(pTile, pPixmap, alu, planemask))
		return FALSE;

	REGION_TRANSLATE(pScreen, pRegion, xoff, yoff);

	if ((*uxa_screen->info->prepare_copy) (pTile, pPixmap, 1, 1, alu,
					       planemask)) {
		while (nbox--) {
			int height = pBox->y2 - pBox->y1;
			int dstY = pBox->y1;
			int tileY;

			modulus(dstY - yoff - pDrawable->y - pPatOrg->y,
				tileHeight, tileY);

			while (height > 0) {
				int width = pBox->x2 - pBox->x1;
				int dstX = pBox->x1;
				int tileX;
				int h = tileHeight - tileY;

				if (h > height)
					h = height;
				height -= h;

				modulus(dstX - xoff - pDrawable->x - pPatOrg->x,
					tileWidth, tileX);

				while (width > 0) {
					int w = tileWidth - tileX;
					if (w > width)
						w = width;
					width -= w;

					(*uxa_screen->info->copy) (pPixmap,
								   tileX, tileY,
								   dstX, dstY,
								   w, h);
					dstX += w;
					tileX = 0;
				}
				dstY += h;
				tileY = 0;
			}
			pBox++;
		}
		(*uxa_screen->info->done_copy) (pPixmap);

		ret = TRUE;
	}

out:
	REGION_TRANSLATE(pScreen, pRegion, -xoff, -yoff);

	return ret;
}