Example #1
0
static RegionPtr
uxa_copy_plane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
	       int srcx, int srcy, int w, int h, int dstx, int dsty,
	       unsigned long bitPlane)
{
	ScreenPtr screen = pDst->pScreen;
	uxa_screen_t *uxa_screen = uxa_get_screen(screen);

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

		if (uxa_prepare_access(pDst, UXA_GLAMOR_ACCESS_RW)) {
			if (uxa_prepare_access(pSrc, UXA_GLAMOR_ACCESS_RO)) {
				ok = glamor_copy_plane_nf(pSrc, pDst, pGC, srcx, srcy, w, h,
							  dstx, dsty, bitPlane, &region);
				uxa_finish_access(pSrc, UXA_GLAMOR_ACCESS_RO);
			}
			uxa_finish_access(pDst, UXA_GLAMOR_ACCESS_RW);
		}
		if (!ok)
			goto fallback;
		return region;
	}

fallback:
	return uxa_check_copy_plane(pSrc, pDst, pGC, srcx, srcy, w, h,
				    dstx, dsty, bitPlane);
}
Example #2
0
static void
uxa_set_spans(DrawablePtr pDrawable, GCPtr gc, char *src,
                 DDXPointPtr points, int *widths, int n, int sorted)
{
	ScreenPtr screen = pDrawable->pScreen;
	uxa_screen_t *uxa_screen = uxa_get_screen(screen);

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

		if (uxa_prepare_access(pDrawable, UXA_GLAMOR_ACCESS_RW)) {
			ok = glamor_set_spans_nf(pDrawable, gc, src,
						 points, widths, n, sorted);
			uxa_finish_access(pDrawable, UXA_GLAMOR_ACCESS_RW);
		}

		if (!ok)
			goto fallback;

		return;
	}

fallback:
	uxa_check_set_spans(pDrawable, gc, src, points, widths, n, sorted);
}
Example #3
0
static void
uxa_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
	      int w, int h, int leftPad, int format, char *bits)
{
	uxa_screen_t *uxa_screen = uxa_get_screen(pDrawable->pScreen);

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

		if (uxa_prepare_access(pDrawable, UXA_GLAMOR_ACCESS_RW)) {
			ok = glamor_put_image_nf(pDrawable,
						 pGC, depth, x, y, w, h,
						 leftPad, format, bits);
			uxa_finish_access(pDrawable, UXA_GLAMOR_ACCESS_RW);
		}
		if (!ok)
			goto fallback;

		return;
	}

	if (!uxa_do_put_image(pDrawable, pGC, depth, x, y, w, h, format, bits,
			      PixmapBytePad(w, pDrawable->depth))) {
fallback:
		uxa_check_put_image(pDrawable, pGC, depth, x, y, w, h, leftPad,
				    format, bits);
	}
}
Example #4
0
static void
uxa_push_pixels(GCPtr pGC, PixmapPtr pBitmap,
		DrawablePtr pDrawable, int w, int h, int x, int y)
{
	ScreenPtr screen = pDrawable->pScreen;
	uxa_screen_t *uxa_screen = uxa_get_screen(screen);

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

		if (uxa_prepare_access(pDrawable, UXA_GLAMOR_ACCESS_RW)) {
			if (uxa_prepare_access(&pBitmap->drawable, UXA_GLAMOR_ACCESS_RO)) {
				ok = glamor_push_pixels_nf(pGC, pBitmap, pDrawable, w, h, x, y);
				uxa_finish_access(&pBitmap->drawable, UXA_GLAMOR_ACCESS_RO);
			}
			uxa_prepare_access(pDrawable, UXA_GLAMOR_ACCESS_RW);
		}
		if (!ok)
			goto fallback;
		return;
	}

fallback:
	uxa_check_push_pixels(pGC, pBitmap, pDrawable, w, h, x, y);
}
Example #5
0
void
uxa_get_spans(DrawablePtr pDrawable,
	      int wMax,
	      DDXPointPtr ppt, int *pwidth, int nspans, char *pdstStart)
{
	ScreenPtr screen = pDrawable->pScreen;
	uxa_screen_t *uxa_screen = uxa_get_screen(screen);

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

		if (uxa_prepare_access(pDrawable, UXA_GLAMOR_ACCESS_RW)) {
			ok = glamor_get_spans_nf(pDrawable, wMax, ppt,
						 pwidth, nspans, pdstStart);
			uxa_finish_access(pDrawable, UXA_GLAMOR_ACCESS_RW);
		}

		if (!ok)
			goto fallback;

		return;
	}

fallback:
	uxa_check_get_spans(pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
}
Example #6
0
static void
uxa_print_composite_fallback(const char *func, CARD8 op,
			     PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst)
{
	uxa_screen_t *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen);
	char srcdesc[40], maskdesc[40], dstdesc[40];

	if (! uxa_screen->fallback_debug)
		return;

	/* Limit the noise if fallbacks are expected. */
	if (uxa_screen->force_fallback)
		return;

	uxa_composite_fallback_pict_desc(pSrc, srcdesc, 40);
	uxa_composite_fallback_pict_desc(pMask, maskdesc, 40);
	uxa_composite_fallback_pict_desc(pDst, dstdesc, 40);

	ErrorF("Composite fallback at %s:\n"
	       "  op   %s, \n"
	       "  src  %s, \n"
	       "  mask %s, \n"
	       "  dst  %s, \n",
	       func, op_to_string (op), srcdesc, maskdesc, dstdesc);
}
Example #7
0
/**
 * uxa_close_screen() unwraps its wrapped screen functions and tears down UXA's
 * screen private, before calling down to the next CloseSccreen.
 */
static Bool uxa_close_screen(int i, ScreenPtr pScreen)
{
	uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
	ScrnInfoPtr scrn = xf86Screens[pScreen->myNum];
#ifdef RENDER
	PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
#endif
	int n;

	if (uxa_screen->solid_clear)
		FreePicture(uxa_screen->solid_clear, 0);
	if (uxa_screen->solid_black)
		FreePicture(uxa_screen->solid_black, 0);
	if (uxa_screen->solid_white)
		FreePicture(uxa_screen->solid_white, 0);
	for (n = 0; n < uxa_screen->solid_cache_size; n++)
		FreePicture(uxa_screen->solid_cache[n].picture, 0);

	uxa_glyphs_fini(pScreen);

	if (pScreen->devPrivate) {
		/* Destroy the pixmap created by miScreenInit() *before*
		 * chaining up as we finalize ourselves here and so this
		 * is the last chance we have of releasing our resources
		 * associated with the Pixmap. So do it first.
		 */
		(void) (*pScreen->DestroyPixmap) (pScreen->devPrivate);
		pScreen->devPrivate = NULL;
	}

	pScreen->CreateGC = uxa_screen->SavedCreateGC;
	pScreen->CloseScreen = uxa_screen->SavedCloseScreen;
	pScreen->GetImage = uxa_screen->SavedGetImage;
	pScreen->GetSpans = uxa_screen->SavedGetSpans;
	pScreen->CreatePixmap = uxa_screen->SavedCreatePixmap;
	pScreen->DestroyPixmap = uxa_screen->SavedDestroyPixmap;
	pScreen->CopyWindow = uxa_screen->SavedCopyWindow;
	pScreen->ChangeWindowAttributes =
	    uxa_screen->SavedChangeWindowAttributes;
	pScreen->BitmapToRegion = uxa_screen->SavedBitmapToRegion;
	scrn->EnableDisableFBAccess = uxa_screen->SavedEnableDisableFBAccess;
#ifdef RENDER
	if (ps) {
		ps->Composite = uxa_screen->SavedComposite;
		ps->CompositeRects = uxa_screen->SavedCompositeRects;
		ps->Glyphs = uxa_screen->SavedGlyphs;
		ps->Trapezoids = uxa_screen->SavedTrapezoids;
		ps->AddTraps = uxa_screen->SavedAddTraps;
		ps->Triangles = uxa_screen->SavedTriangles;

		ps->UnrealizeGlyph = uxa_screen->SavedUnrealizeGlyph;
	}
#endif

	free(uxa_screen);

	return (*pScreen->CloseScreen) (i, pScreen);
}
Example #8
0
/**
 * uxa_pixmap_is_offscreen() is used to determine if a pixmap is in offscreen
 * memory, meaning that acceleration could probably be done to it, and that it
 * will need to be wrapped by PrepareAccess()/FinishAccess() when accessing it
 * with the CPU.
 *
 * Note that except for UploadToScreen()/DownloadFromScreen() (which explicitly
 * deal with moving pixmaps in and out of system memory), UXA will give drivers
 * pixmaps as arguments for which uxa_pixmap_is_offscreen() is TRUE.
 *
 * @return TRUE if the given drawable is in framebuffer memory.
 */
Bool uxa_pixmap_is_offscreen(PixmapPtr p)
{
	ScreenPtr pScreen = p->drawable.pScreen;
	uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);

	if (uxa_screen->info->pixmap_is_offscreen)
		return uxa_screen->info->pixmap_is_offscreen(p);

	return FALSE;
}
Bool uxa_glyphs_init(ScreenPtr pScreen)
{

	uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);

	if (uxa_screen->info->flags & UXA_USE_GLAMOR)
		return TRUE;
#if HAS_DIXREGISTERPRIVATEKEY
	if (!dixRegisterPrivateKey(&uxa_glyph_key, PRIVATE_GLYPH, 0))
		return FALSE;
#else
	if (!dixRequestPrivate(&uxa_glyph_key, 0))
		return FALSE;
#endif

	/* Skip pixmap creation if we don't intend to use it. */
	if (uxa_get_screen(pScreen)->force_fallback)
		return TRUE;

	return uxa_realize_glyph_caches(pScreen);
}
Example #10
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, uxa_access_t access)
{
	ScreenPtr pScreen = pDrawable->pScreen;
	uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
	PixmapPtr pPixmap = uxa_get_drawable_pixmap(pDrawable);
	Bool offscreen = uxa_pixmap_is_offscreen(pPixmap);

	if (!offscreen)
		return TRUE;

	if (uxa_screen->info->prepare_access)
		return (*uxa_screen->info->prepare_access) (pPixmap, access);
	return TRUE;
}
Example #11
0
static void uxa_xorg_enable_disable_fb_access(int index, Bool enable)
{
	ScreenPtr screen = screenInfo.screens[index];
	uxa_screen_t *uxa_screen = uxa_get_screen(screen);

	if (!enable && uxa_screen->disableFbCount++ == 0)
		uxa_screen->swappedOut = TRUE;

	if (enable && --uxa_screen->disableFbCount == 0)
		uxa_screen->swappedOut = FALSE;

	if (uxa_screen->SavedEnableDisableFBAccess)
		uxa_screen->SavedEnableDisableFBAccess(index, enable);
}
Example #12
0
/**
 * uxa_finish_access() is UXA's wrapper for the driver's finish_access() handler.
 *
 * It deals with calling the driver's finish_access() only if necessary.
 */
void uxa_finish_access(DrawablePtr pDrawable)
{
	ScreenPtr pScreen = pDrawable->pScreen;
	uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
	PixmapPtr pPixmap = uxa_get_drawable_pixmap(pDrawable);

	if (uxa_screen->info->finish_access == NULL)
		return;

	if (!uxa_pixmap_is_offscreen(pPixmap))
		return;

	(*uxa_screen->info->finish_access) (pPixmap);
}
Example #13
0
/**
 * uxa_close_screen() unwraps its wrapped screen functions and tears down UXA's
 * screen private, before calling down to the next CloseSccreen.
 */
static Bool uxa_close_screen(int i, ScreenPtr pScreen)
{
	uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
	ScrnInfoPtr scrn = xf86Screens[pScreen->myNum];
#ifdef RENDER
	PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
#endif
	int n;

	if (uxa_screen->solid_clear)
		FreePicture(uxa_screen->solid_clear, 0);
	if (uxa_screen->solid_black)
		FreePicture(uxa_screen->solid_black, 0);
	if (uxa_screen->solid_white)
		FreePicture(uxa_screen->solid_white, 0);
	for (n = 0; n < uxa_screen->solid_cache_size; n++)
		FreePicture(uxa_screen->solid_cache[n].picture, 0);

	uxa_glyphs_fini(pScreen);

	pScreen->CreateGC = uxa_screen->SavedCreateGC;
	pScreen->CloseScreen = uxa_screen->SavedCloseScreen;
	pScreen->GetImage = uxa_screen->SavedGetImage;
	pScreen->GetSpans = uxa_screen->SavedGetSpans;
	pScreen->CreatePixmap = uxa_screen->SavedCreatePixmap;
	pScreen->DestroyPixmap = uxa_screen->SavedDestroyPixmap;
	pScreen->CopyWindow = uxa_screen->SavedCopyWindow;
	pScreen->ChangeWindowAttributes =
	    uxa_screen->SavedChangeWindowAttributes;
	pScreen->BitmapToRegion = uxa_screen->SavedBitmapToRegion;
	scrn->EnableDisableFBAccess = uxa_screen->SavedEnableDisableFBAccess;
#ifdef RENDER
	if (ps) {
		ps->Composite = uxa_screen->SavedComposite;
		ps->CompositeRects = uxa_screen->SavedCompositeRects;
		ps->Glyphs = uxa_screen->SavedGlyphs;
		ps->Trapezoids = uxa_screen->SavedTrapezoids;
		ps->AddTraps = uxa_screen->SavedAddTraps;
		ps->Triangles = uxa_screen->SavedTriangles;

		ps->UnrealizeGlyph = uxa_screen->SavedUnrealizeGlyph;
	}
#endif

	free(uxa_screen);

	return (*pScreen->CloseScreen) (i, pScreen);
}
Example #14
0
RegionPtr
uxa_copy_area(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC,
	      int srcx, int srcy, int width, int height, int dstx, int dsty)
{
	uxa_screen_t *uxa_screen = uxa_get_screen(pDstDrawable->pScreen);

	if (uxa_screen->force_fallback) {
		return uxa_check_copy_area(pSrcDrawable, pDstDrawable, pGC,
					   srcx, srcy, width, height, dstx,
					   dsty);
	}

	return miDoCopy(pSrcDrawable, pDstDrawable, pGC,
			srcx, srcy, width, height,
			dstx, dsty, uxa_copy_n_to_n, 0, NULL);
}
Example #15
0
static void
uxa_poly_point(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
	       DDXPointPtr ppt)
{
	int i;
	xRectangle *prect;
	uxa_screen_t *uxa_screen = uxa_get_screen(pDrawable->pScreen);

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

		if (uxa_prepare_access(pDrawable, UXA_GLAMOR_ACCESS_RW)) {
			ok = glamor_poly_point_nf(pDrawable, pGC, mode, npt, ppt);
			uxa_finish_access(pDrawable, UXA_GLAMOR_ACCESS_RW);
		}

		if (ok)
			return;
	}

	/* If we can't reuse the current GC as is, don't bother accelerating the
	 * points.
	 */
	if (pGC->fillStyle != FillSolid) {
		uxa_check_poly_point(pDrawable, pGC, mode, npt, ppt);
		return;
	}

	prect = malloc(sizeof(xRectangle) * npt);
	if (!prect)
		return;
	for (i = 0; i < npt; i++) {
		prect[i].x = ppt[i].x;
		prect[i].y = ppt[i].y;
		if (i > 0 && mode == CoordModePrevious) {
			prect[i].x += prect[i - 1].x;
			prect[i].y += prect[i - 1].y;
		}
		prect[i].width = 1;
		prect[i].height = 1;
	}
	pGC->ops->PolyFillRect(pDrawable, pGC, npt, prect);
	free(prect);
}
static void uxa_unrealize_glyph_caches(ScreenPtr pScreen)
{
	uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
	int i;

	if (!uxa_screen->glyph_cache_initialized)
		return;

	for (i = 0; i < UXA_NUM_GLYPH_CACHE_FORMATS; i++) {
		uxa_glyph_cache_t *cache = &uxa_screen->glyphCaches[i];

		if (cache->picture)
			FreePicture(cache->picture, 0);

		if (cache->glyphs)
			free(cache->glyphs);
	}
	uxa_screen->glyph_cache_initialized = FALSE;
}
Example #17
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 #18
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;
}
void
uxa_glyph_unrealize(ScreenPtr screen,
		    GlyphPtr glyph)
{
	struct uxa_glyph *priv;
	uxa_screen_t *uxa_screen = uxa_get_screen(screen);

	if (uxa_screen->info->flags & UXA_USE_GLAMOR) {
		glamor_glyph_unrealize(screen, glyph);
		return;
	}

	/* Use Lookup in case we have not attached to this glyph. */
	priv = dixLookupPrivate(&glyph->devPrivates, &uxa_glyph_key);
	if (priv == NULL)
		return;

	priv->cache->glyphs[priv->pos] = NULL;

	uxa_glyph_set_private(glyph, NULL);
	free(priv);
}
Example #20
0
static void
uxa_poly_glyph_blt(DrawablePtr pDrawable, GCPtr pGC,
		   int x, int y, unsigned int nglyph,
		   CharInfoPtr * ppci, pointer pglyphBase)
{
	ScreenPtr screen = pDrawable->pScreen;
	uxa_screen_t *uxa_screen = uxa_get_screen(screen);

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

		if (uxa_prepare_access(pDrawable, UXA_GLAMOR_ACCESS_RW)) {
			ok = glamor_poly_glyph_blt_nf(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
			uxa_finish_access(pDrawable, UXA_GLAMOR_ACCESS_RW);
		}
		if (!ok)
			goto fallback;
		return;
	}

fallback:
	uxa_check_poly_glyph_blt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
}
Example #21
0
void uxa_set_force_fallback(ScreenPtr screen, Bool value)
{
	uxa_screen_t *uxa_screen = uxa_get_screen(screen);

	uxa_screen->force_fallback = value;
}
Example #22
0
void uxa_set_fallback_debug(ScreenPtr screen, Bool enable)
{
	uxa_screen_t *uxa_screen = uxa_get_screen(screen);

	uxa_screen->fallback_debug = enable;
}
Example #23
0
/**
 * uxa_poly_segment() checks if it can accelerate the lines as a group of
 * horizontal or vertical lines (rectangles), and uses existing rectangle fill
 * acceleration if so.
 */
static void
uxa_poly_segment(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment * pSeg)
{
	xRectangle *prect;
	int i;
	uxa_screen_t *uxa_screen = uxa_get_screen(pDrawable->pScreen);

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

		if (uxa_prepare_access(pDrawable, UXA_GLAMOR_ACCESS_RW)) {
			ok = glamor_poly_segment_nf(pDrawable, pGC, nseg, pSeg);
			uxa_finish_access(pDrawable, UXA_GLAMOR_ACCESS_RW);
		}

		if (ok)
			return;
	}

	/* Don't try to do wide lines or non-solid fill style. */
	if (pGC->lineWidth != 0 || pGC->lineStyle != LineSolid ||
	    pGC->fillStyle != FillSolid) {
		uxa_check_poly_segment(pDrawable, pGC, nseg, pSeg);
		return;
	}

	/* If we have any non-horizontal/vertical, fall back. */
	for (i = 0; i < nseg; i++) {
		if (pSeg[i].x1 != pSeg[i].x2 && pSeg[i].y1 != pSeg[i].y2) {
			uxa_check_poly_segment(pDrawable, pGC, nseg, pSeg);
			return;
		}
	}

	prect = malloc(sizeof(xRectangle) * nseg);
	if (!prect)
		return;
	for (i = 0; i < nseg; i++) {
		if (pSeg[i].x1 < pSeg[i].x2) {
			prect[i].x = pSeg[i].x1;
			prect[i].width = pSeg[i].x2 - pSeg[i].x1 + 1;
		} else {
			prect[i].x = pSeg[i].x2;
			prect[i].width = pSeg[i].x1 - pSeg[i].x2 + 1;
		}
		if (pSeg[i].y1 < pSeg[i].y2) {
			prect[i].y = pSeg[i].y1;
			prect[i].height = pSeg[i].y2 - pSeg[i].y1 + 1;
		} else {
			prect[i].y = pSeg[i].y2;
			prect[i].height = pSeg[i].y1 - pSeg[i].y2 + 1;
		}

		/* don't paint last pixel */
		if (pGC->capStyle == CapNotLast) {
			if (prect[i].width == 1)
				prect[i].height--;
			else
				prect[i].width--;
		}
	}
	pGC->ops->PolyFillRect(pDrawable, pGC, nseg, prect);
	free(prect);
}
static PicturePtr
uxa_glyph_cache(ScreenPtr screen, GlyphPtr glyph, int *out_x, int *out_y)
{
	uxa_screen_t *uxa_screen = uxa_get_screen(screen);
	PicturePtr glyph_picture = GetGlyphPicture(glyph, screen);
	uxa_glyph_cache_t *cache = &uxa_screen->glyphCaches[PICT_FORMAT_RGB(glyph_picture->format) != 0];
	struct uxa_glyph *priv = NULL;
	int size, mask, pos, s;

	if (glyph->info.width > GLYPH_MAX_SIZE || glyph->info.height > GLYPH_MAX_SIZE)
		return NULL;

	for (size = GLYPH_MIN_SIZE; size <= GLYPH_MAX_SIZE; size *= 2)
		if (glyph->info.width <= size && glyph->info.height <= size)
			break;

	s = uxa_glyph_size_to_count(size);
	mask = uxa_glyph_count_to_mask(s);
	pos = (cache->count + s - 1) & mask;
	if (pos < GLYPH_CACHE_SIZE) {
		cache->count = pos + s;
	} else {
		for (s = size; s <= GLYPH_MAX_SIZE; s *= 2) {
			int i = cache->evict & uxa_glyph_size_to_mask(s);
			GlyphPtr evicted = cache->glyphs[i];
			if (evicted == NULL)
				continue;

			priv = uxa_glyph_get_private(evicted);
			if (priv->size >= s) {
				cache->glyphs[i] = NULL;
				uxa_glyph_set_private(evicted, NULL);
				pos = cache->evict & uxa_glyph_size_to_mask(size);
			} else
				priv = NULL;
			break;
		}
		if (priv == NULL) {
			int count = uxa_glyph_size_to_count(size);
			mask = uxa_glyph_count_to_mask(count);
			pos = cache->evict & mask;
			for (s = 0; s < count; s++) {
				GlyphPtr evicted = cache->glyphs[pos + s];
				if (evicted != NULL) {
					if (priv != NULL)
						free(priv);

					priv = uxa_glyph_get_private(evicted);
					uxa_glyph_set_private(evicted, NULL);
					cache->glyphs[pos + s] = NULL;
				}
			}
		}

		/* And pick a new eviction position */
		cache->evict = rand() % GLYPH_CACHE_SIZE;
	}

	if (priv == NULL) {
		priv = malloc(sizeof(struct uxa_glyph));
		if (priv == NULL)
			return NULL;
	}

	uxa_glyph_set_private(glyph, priv);
	cache->glyphs[pos] = glyph;

	priv->cache = cache;
	priv->size = size;
	priv->pos = pos;
	s = pos / ((GLYPH_MAX_SIZE / GLYPH_MIN_SIZE) * (GLYPH_MAX_SIZE / GLYPH_MIN_SIZE));
	priv->x = s % (CACHE_PICTURE_SIZE / GLYPH_MAX_SIZE) * GLYPH_MAX_SIZE;
	priv->y = (s / (CACHE_PICTURE_SIZE / GLYPH_MAX_SIZE)) * GLYPH_MAX_SIZE;
	for (s = GLYPH_MIN_SIZE; s < GLYPH_MAX_SIZE; s *= 2) {
		if (pos & 1)
			priv->x += s;
		if (pos & 2)
			priv->y += s;
		pos >>= 2;
	}

	uxa_glyph_cache_upload_glyph(screen, cache, glyph, priv->x, priv->y);

	*out_x = priv->x;
	*out_y = priv->y;
	return cache->picture;
}
Example #25
0
/**
 * uxa_poly_lines() checks if it can accelerate the lines as a group of
 * horizontal or vertical lines (rectangles), and uses existing rectangle fill
 * acceleration if so.
 */
static void
uxa_poly_lines(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
	       DDXPointPtr ppt)
{
	xRectangle *prect;
	int x1, x2, y1, y2;
	int i;
	uxa_screen_t *uxa_screen = uxa_get_screen(pDrawable->pScreen);

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

		if (uxa_prepare_access(pDrawable, UXA_GLAMOR_ACCESS_RW)) {
			ok = glamor_poly_lines_nf(pDrawable, pGC, mode, npt, ppt);
			uxa_finish_access(pDrawable, UXA_GLAMOR_ACCESS_RW);
		}

		if (ok)
			return;
	}

	/* Don't try to do wide lines or non-solid fill style. */
	if (pGC->lineWidth != 0 || pGC->lineStyle != LineSolid ||
	    pGC->fillStyle != FillSolid) {
		uxa_check_poly_lines(pDrawable, pGC, mode, npt, ppt);
		return;
	}

	prect = malloc(sizeof(xRectangle) * (npt - 1));
	if (!prect)
		return;
	x1 = ppt[0].x;
	y1 = ppt[0].y;
	/* If we have any non-horizontal/vertical, fall back. */
	for (i = 0; i < npt - 1; i++) {
		if (mode == CoordModePrevious) {
			x2 = x1 + ppt[i + 1].x;
			y2 = y1 + ppt[i + 1].y;
		} else {
			x2 = ppt[i + 1].x;
			y2 = ppt[i + 1].y;
		}

		if (x1 != x2 && y1 != y2) {
			free(prect);
			uxa_check_poly_lines(pDrawable, pGC, mode, npt, ppt);
			return;
		}

		if (x1 < x2) {
			prect[i].x = x1;
			prect[i].width = x2 - x1 + 1;
		} else {
			prect[i].x = x2;
			prect[i].width = x1 - x2 + 1;
		}
		if (y1 < y2) {
			prect[i].y = y1;
			prect[i].height = y2 - y1 + 1;
		} else {
			prect[i].y = y2;
			prect[i].height = y1 - y2 + 1;
		}

		x1 = x2;
		y1 = y2;
	}
	pGC->ops->PolyFillRect(pDrawable, pGC, npt - 1, prect);
	free(prect);
}
Example #26
0
Bool uxa_swapped_out(ScreenPtr screen)
{
	uxa_screen_t *uxa_screen = uxa_get_screen (screen);

	return uxa_screen->swappedOut;
}
static int
uxa_glyphs_via_mask(CARD8 op,
		    PicturePtr pSrc,
		    PicturePtr pDst,
		    PictFormatPtr maskFormat,
		    INT16 xSrc, INT16 ySrc,
		    int nlist, GlyphListPtr list, GlyphPtr * glyphs)
{
	ScreenPtr screen = pDst->pDrawable->pScreen;
	uxa_screen_t *uxa_screen = uxa_get_screen(screen);
	CARD32 component_alpha;
	PixmapPtr pixmap, white_pixmap;
	PicturePtr glyph_atlas, mask, white;
	int xDst = list->xOff, yDst = list->yOff;
	int x, y, width, height;
	int dst_off_x, dst_off_y;
	int n, error;
	BoxRec box;

	uxa_glyph_extents(nlist, list, glyphs, &box);
	if (box.x2 <= box.x1 || box.y2 <= box.y1)
		return 0;

	dst_off_x = box.x1;
	dst_off_y = box.y1;

	width  = box.x2 - box.x1;
	height = box.y2 - box.y1;
	x = -box.x1;
	y = -box.y1;

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

		if (!a8Format)
			return -1;

		maskFormat = a8Format;
	}

	pixmap = screen->CreatePixmap(screen, width, height,
				      maskFormat->depth,
				      CREATE_PIXMAP_USAGE_SCRATCH);
	if (!pixmap)
		return 1;

	if (!uxa_pixmap_is_offscreen(pixmap)) {
		screen->DestroyPixmap(pixmap);
		return -1;
	}

	white_pixmap = NULL;
	white = create_white_solid(screen);
	if (white)
		white_pixmap = uxa_get_drawable_pixmap(white->pDrawable);
	if (!white_pixmap) {
		if (white)
			FreePicture(white, 0);
		screen->DestroyPixmap(pixmap);
		return -1;
	}

	uxa_clear_pixmap(screen, uxa_screen, pixmap);

	component_alpha = NeedsComponent(maskFormat->format);
	mask = CreatePicture(0, &pixmap->drawable,
			      maskFormat, CPComponentAlpha,
			      &component_alpha, serverClient, &error);
	screen->DestroyPixmap(pixmap);

	if (!mask) {
		FreePicture(white, 0);
		return 1;
	}

	ValidatePicture(mask);

	glyph_atlas = NULL;
	while (nlist--) {
		x += list->xOff;
		y += list->yOff;
		n = list->len;
		while (n--) {
			GlyphPtr glyph = *glyphs++;
			PicturePtr this_atlas;
			int glyph_x, glyph_y;
			struct uxa_glyph *priv;

			if (glyph->info.width == 0 || glyph->info.height == 0)
				goto next_glyph;

			priv = uxa_glyph_get_private(glyph);
			if (priv != NULL) {
				glyph_x = priv->x;
				glyph_y = priv->y;
				this_atlas = priv->cache->picture;
			} else {
				if (glyph_atlas) {
					uxa_screen->info->done_composite(pixmap);
					glyph_atlas = NULL;
				}
				this_atlas = uxa_glyph_cache(screen, glyph, &glyph_x, &glyph_y);
				if (this_atlas == NULL) {
					/* no cache for this glyph */
					this_atlas = GetGlyphPicture(glyph, screen);
					glyph_x = glyph_y = 0;
				}
			}

			if (this_atlas != glyph_atlas) {
				PixmapPtr glyph_pixmap;

				if (glyph_atlas)
					uxa_screen->info->done_composite(pixmap);

				glyph_pixmap =
					uxa_get_drawable_pixmap(this_atlas->pDrawable);
				if (!uxa_pixmap_is_offscreen(glyph_pixmap) ||
				    !uxa_screen->info->prepare_composite(PictOpAdd,
									 white, this_atlas, mask,
									 white_pixmap, glyph_pixmap, pixmap)) {
					FreePicture(white, 0);
					FreePicture(mask, 0);
					return -1;
				}

				glyph_atlas = this_atlas;
			}

			uxa_screen->info->composite(pixmap,
						    0, 0,
						    glyph_x, glyph_y,
						    x - glyph->info.x,
						    y - glyph->info.y,
						    glyph->info.width,
						    glyph->info.height);

next_glyph:
			x += glyph->info.xOff;
			y += glyph->info.yOff;
		}
		list++;
	}
	if (glyph_atlas)
		uxa_screen->info->done_composite(pixmap);

	uxa_composite(op,
		      pSrc, mask, pDst,
		      dst_off_x + xSrc - xDst,
		      dst_off_y + ySrc - yDst,
		      0, 0,
		      dst_off_x, dst_off_y,
		      width, height);

	FreePicture(white, 0);
	FreePicture(mask, 0);
	return 0;
}
void
uxa_glyphs(CARD8 op,
	   PicturePtr pSrc,
	   PicturePtr pDst,
	   PictFormatPtr maskFormat,
	   INT16 xSrc, INT16 ySrc,
	   int nlist, GlyphListPtr list, GlyphPtr * glyphs)
{
	ScreenPtr screen = pDst->pDrawable->pScreen;
	uxa_screen_t *uxa_screen = uxa_get_screen(screen);

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

		uxa_picture_prepare_access(pDst, UXA_GLAMOR_ACCESS_RW);
		uxa_picture_prepare_access(pSrc, UXA_GLAMOR_ACCESS_RO);
		ok = glamor_glyphs_nf(op,
				     pSrc, pDst, maskFormat,
				     xSrc, ySrc, nlist, list, glyphs);
		uxa_picture_finish_access(pSrc, UXA_GLAMOR_ACCESS_RO);
		uxa_picture_finish_access(pDst, UXA_GLAMOR_ACCESS_RW);

		if (!ok)
			goto fallback;

		return;
	}

	if (!uxa_screen->info->prepare_composite ||
	    uxa_screen->force_fallback ||
	    !uxa_drawable_is_offscreen(pDst->pDrawable) ||
	    pDst->alphaMap || pSrc->alphaMap ||
	    /* XXX we fail to handle (rare) non-solid sources correctly. */
	    !is_solid(pSrc)) {
fallback:
	    uxa_check_glyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs);
	    return;
	}

	/* basic sanity check */
	if (uxa_screen->info->check_composite &&
	    !uxa_screen->info->check_composite(op, pSrc, NULL, pDst, 0, 0)) {
		goto fallback;
	}

	ValidatePicture(pSrc);
	ValidatePicture(pDst);

	if (!maskFormat) {
		/* If we don't have a mask format but all the glyphs have the same format,
		 * require ComponentAlpha and don't intersect, use the glyph format as mask
		 * format for the full benefits of the glyph cache.
		 */
		if (NeedsComponent(list[0].format->format)) {
			Bool sameFormat = TRUE;
			int i;

			maskFormat = list[0].format;

			for (i = 0; i < nlist; i++) {
				if (maskFormat->format != list[i].format->format) {
					sameFormat = FALSE;
					break;
				}
			}

			if (!sameFormat ||
			    uxa_glyphs_intersect(nlist, list, glyphs))
				maskFormat = NULL;
		}
	}

	if (!maskFormat) {
		if (uxa_glyphs_to_dst(op, pSrc, pDst,
				      xSrc, ySrc,
				      nlist, list, glyphs))
			goto fallback;
	} else {
		if (uxa_glyphs_via_mask(op,
					pSrc, pDst, maskFormat,
					xSrc, ySrc,
					nlist, list, glyphs))
			goto fallback;
	}
}
/* All caches for a single format share a single pixmap for glyph storage,
 * allowing mixing glyphs of different sizes without paying a penalty
 * for switching between source pixmaps. (Note that for a size of font
 * right at the border between two sizes, we might be switching for almost
 * every glyph.)
 *
 * This function allocates the storage pixmap, and then fills in the
 * rest of the allocated structures for all caches with the given format.
 */
static Bool uxa_realize_glyph_caches(ScreenPtr pScreen)
{
	uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
	unsigned int formats[] = {
		PIXMAN_a8,
		PIXMAN_a8r8g8b8,
	};
	int i;

	if (uxa_screen->glyph_cache_initialized)
		return TRUE;

	uxa_screen->glyph_cache_initialized = TRUE;
	memset(uxa_screen->glyphCaches, 0, sizeof(uxa_screen->glyphCaches));

	for (i = 0; i < sizeof(formats)/sizeof(formats[0]); i++) {
		uxa_glyph_cache_t *cache = &uxa_screen->glyphCaches[i];
		PixmapPtr pixmap;
		PicturePtr picture;
		CARD32 component_alpha;
		int depth = PIXMAN_FORMAT_DEPTH(formats[i]);
		int error;
		PictFormatPtr pPictFormat = PictureMatchFormat(pScreen, depth, formats[i]);
		if (!pPictFormat)
			goto bail;

		/* Now allocate the pixmap and picture */
		pixmap = pScreen->CreatePixmap(pScreen,
					       CACHE_PICTURE_SIZE, CACHE_PICTURE_SIZE, depth,
					       INTEL_CREATE_PIXMAP_TILING_X);
		if (!pixmap)
			goto bail;
		if (!uxa_pixmap_is_offscreen(pixmap)) {
			/* Presume shadow is in-effect */
			pScreen->DestroyPixmap(pixmap);
			uxa_unrealize_glyph_caches(pScreen);
			return TRUE;
		}

		component_alpha = NeedsComponent(pPictFormat->format);
		picture = CreatePicture(0, &pixmap->drawable, pPictFormat,
					CPComponentAlpha, &component_alpha,
					serverClient, &error);

		pScreen->DestroyPixmap(pixmap);

		if (!picture)
			goto bail;

		ValidatePicture(picture);

		cache->picture = picture;
		cache->glyphs = calloc(sizeof(GlyphPtr), GLYPH_CACHE_SIZE);
		if (!cache->glyphs)
			goto bail;

		cache->evict = rand() % GLYPH_CACHE_SIZE;
	}
	assert(i == UXA_NUM_GLYPH_CACHE_FORMATS);

	return TRUE;

bail:
	uxa_unrealize_glyph_caches(pScreen);
	return FALSE;
}
Example #30
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);
}