summaryrefslogtreecommitdiff
path: root/uxa
diff options
context:
space:
mode:
Diffstat (limited to 'uxa')
-rw-r--r--uxa/uxa-accel.c473
-rw-r--r--uxa/uxa-glyphs.c1527
-rw-r--r--uxa/uxa-priv.h117
-rw-r--r--uxa/uxa-render.c1214
-rw-r--r--uxa/uxa.c73
-rw-r--r--uxa/uxa.h45
6 files changed, 2262 insertions, 1187 deletions
diff --git a/uxa/uxa-accel.c b/uxa/uxa-accel.c
index bede1f41..245738a6 100644
--- a/uxa/uxa-accel.c
+++ b/uxa/uxa-accel.c
@@ -34,33 +34,185 @@
#include <X11/fonts/fontstruct.h>
#include "dixfontstr.h"
#include "uxa.h"
+#include "mipict.h"
+
+static CARD32
+format_for_depth(int depth)
+{
+ switch (depth) {
+ case 1: return PICT_a1;
+ case 4: return PICT_a4;
+ case 8: return PICT_a8;
+ case 15: return PICT_x1r5g5b5;
+ case 16: return PICT_r5g6b5;
+ default:
+ case 24: return PICT_x8r8g8b8;
+#if 0
+ case 30: return PICT_x2r10g10b10;
+#endif
+ case 32: return PICT_a8r8g8b8;
+ }
+}
static void
uxa_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int n,
DDXPointPtr ppt, int *pwidth, int fSorted)
{
- ScreenPtr pScreen = pDrawable->pScreen;
- uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
+ ScreenPtr screen = pDrawable->pScreen;
+ uxa_screen_t *uxa_screen = uxa_get_screen(screen);
RegionPtr pClip = fbGetCompositeClip(pGC);
- PixmapPtr pPixmap = uxa_get_drawable_pixmap(pDrawable);
+ PixmapPtr dst_pixmap, src_pixmap = NULL;
BoxPtr pextent, pbox;
int nbox;
int extentX1, extentX2, extentY1, extentY2;
int fullX1, fullX2, fullY1;
int partX1, partX2;
int off_x, off_y;
+ xRenderColor color;
+ PictFormatPtr format;
+ PicturePtr dst, src;
+ int error;
+
+ if (uxa_screen->swappedOut)
+ 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 (pGC->alu != GXcopy || pGC->planemask != FB_ALLONES)
+ goto solid;
+
+ format = PictureMatchFormat(screen,
+ dst_pixmap->drawable.depth,
+ format_for_depth(dst_pixmap->drawable.depth));
+ dst = CreatePicture(0, &dst_pixmap->drawable, format, 0, 0, serverClient, &error);
+ if (!dst)
+ goto solid;
+
+ ValidatePicture(dst);
+
+ uxa_get_rgba_from_pixel(pGC->fgPixel,
+ &color.red,
+ &color.green,
+ &color.blue,
+ &color.alpha,
+ format_for_depth(dst_pixmap->drawable.depth));
+ src = CreateSolidPicture(0, &color, &error);
+ if (!src) {
+ FreePicture(dst, 0);
+ goto solid;
+ }
+
+ if (!uxa_screen->info->check_composite(PictOpSrc, src, NULL, dst, 0, 0)) {
+ FreePicture(src, 0);
+ FreePicture(dst, 0);
+ goto solid;
+ }
+
+ if (!uxa_screen->info->check_composite_texture ||
+ !uxa_screen->info->check_composite_texture(screen, src)) {
+ PicturePtr solid;
+ int src_off_x, src_off_y;
+
+ solid = uxa_acquire_solid(screen, src->pSourcePict);
+ FreePicture(src, 0);
+
+ src = solid;
+ src_pixmap = uxa_get_offscreen_pixmap(src->pDrawable,
+ &src_off_x, &src_off_y);
+ if (!src_pixmap) {
+ FreePicture(src, 0);
+ FreePicture(dst, 0);
+ goto solid;
+ }
+ }
- if (uxa_screen->swappedOut || pGC->fillStyle != FillSolid ||
- !(pPixmap = uxa_get_offscreen_pixmap(pDrawable, &off_x, &off_y)) ||
- !(*uxa_screen->info->prepare_solid) (pPixmap,
+ if (!uxa_screen->info->prepare_composite(PictOpSrc, src, NULL, dst, src_pixmap, NULL, dst_pixmap)) {
+ FreePicture(src, 0);
+ FreePicture(dst, 0);
+ goto solid;
+ }
+
+ pextent = REGION_EXTENTS(pGC->screen, pClip);
+ extentX1 = pextent->x1;
+ extentY1 = pextent->y1;
+ extentX2 = pextent->x2;
+ extentY2 = pextent->y2;
+ while (n--) {
+ fullX1 = ppt->x;
+ fullY1 = ppt->y;
+ fullX2 = fullX1 + (int)*pwidth;
+ ppt++;
+ pwidth++;
+
+ if (fullY1 < extentY1 || extentY2 <= fullY1)
+ continue;
+
+ if (fullX1 < extentX1)
+ fullX1 = extentX1;
+
+ if (fullX2 > extentX2)
+ fullX2 = extentX2;
+
+ if (fullX1 >= fullX2)
+ continue;
+
+ nbox = REGION_NUM_RECTS(pClip);
+ if (nbox == 1) {
+ uxa_screen->info->composite(dst_pixmap,
+ 0, 0, 0, 0,
+ fullX1 + off_x,
+ fullY1 + off_y,
+ fullX2 - fullX1, 1);
+ } else {
+ pbox = REGION_RECTS(pClip);
+ while (nbox--) {
+ if (pbox->y1 > fullY1)
+ break;
+
+ if (pbox->y1 <= fullY1) {
+ partX1 = pbox->x1;
+ if (partX1 < fullX1)
+ partX1 = fullX1;
+
+ partX2 = pbox->x2;
+ if (partX2 > fullX2)
+ partX2 = fullX2;
+
+ if (partX2 > partX1) {
+ uxa_screen->info->composite(dst_pixmap,
+ 0, 0, 0, 0,
+ partX1 + off_x,
+ fullY1 + off_y,
+ partX2 - partX1, 1);
+ }
+ }
+ pbox++;
+ }
+ }
+ }
+
+ uxa_screen->info->done_composite(dst_pixmap);
+ FreePicture(src, 0);
+ FreePicture(dst, 0);
+ return;
+
+solid:
+ 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)) {
- uxa_check_fill_spans(pDrawable, pGC, n, ppt, pwidth, fSorted);
- return;
- }
+ pGC->fgPixel))
+ goto fallback;
- pextent = REGION_EXTENTS(pGC->pScreen, pClip);
+ pextent = REGION_EXTENTS(pGC->screen, pClip);
extentX1 = pextent->x1;
extentY1 = pextent->y1;
extentX2 = pextent->x2;
@@ -86,7 +238,7 @@ uxa_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int n,
nbox = REGION_NUM_RECTS(pClip);
if (nbox == 1) {
- (*uxa_screen->info->solid) (pPixmap,
+ (*uxa_screen->info->solid) (dst_pixmap,
fullX1 + off_x,
fullY1 + off_y,
fullX2 + off_x,
@@ -103,7 +255,7 @@ uxa_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int n,
partX2 = fullX2;
if (partX2 > partX1) {
(*uxa_screen->info->
- solid) (pPixmap,
+ solid) (dst_pixmap,
partX1 + off_x,
fullY1 + off_y,
partX2 + off_x,
@@ -114,7 +266,12 @@ uxa_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int n,
}
}
}
- (*uxa_screen->info->done_solid) (pPixmap);
+ (*uxa_screen->info->done_solid) (dst_pixmap);
+
+ return;
+
+fallback:
+ uxa_check_fill_spans(pDrawable, pGC, n, ppt, pwidth, fSorted);
}
static Bool
@@ -204,92 +361,12 @@ uxa_do_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
return TRUE;
}
-#ifdef MITSHM
-
-#include "xorgVersion.h"
-
-static Bool
-uxa_do_shm_put_image(DrawablePtr pDrawable, 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)
-{
- int src_stride = PixmapBytePad(w, depth);
-
- if (uxa_do_put_image
- (pDrawable, pGC, depth, dx, dy, sw, sh, format,
- data + sy * src_stride + sx * BitsPerPixel(depth) / 8, src_stride))
- return TRUE;
-
- if (format == ZPixmap) {
- PixmapPtr pPixmap;
-
- pPixmap =
- GetScratchPixmapHeader(pDrawable->pScreen, w, h, depth,
- BitsPerPixel(depth), PixmapBytePad(w,
- depth),
- (pointer) data);
- if (!pPixmap)
- return FALSE;
-
- if (!uxa_prepare_access(pDrawable, UXA_ACCESS_RW)) {
- FreeScratchPixmapHeader(pPixmap);
- return FALSE;
- }
-
- fbCopyArea((DrawablePtr) pPixmap, pDrawable, pGC, sx, sy, sw,
- sh, dx, dy);
- uxa_finish_access(pDrawable);
-
- FreeScratchPixmapHeader(pPixmap);
-
- return TRUE;
- }
-
- return FALSE;
-}
-
-#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,5,99,0,0)
-
-/* The actual ShmPutImage isn't wrapped by the damage layer, so we need to
- * inform any interested parties of the damage incurred to the drawable.
- *
- * We also need to set the pending damage to ensure correct migration in all
- * cases.
- */
-void
-uxa_shm_put_image(DrawablePtr pDrawable, 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)
-{
- if (!uxa_do_shm_put_image
- (pDrawable, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy,
- data)) {
- if (!uxa_prepare_access(pDrawable, UXA_ACCESS_RW))
- return;
- fbShmPutImage(pDrawable, pGC, depth, format, w, h, sx, sy, sw,
- sh, dx, dy, data);
- uxa_finish_access(pDrawable);
- }
-}
-#else
-#define uxa_shm_put_image NULL
-#endif
-
-ShmFuncs uxa_shm_funcs = { NULL, uxa_shm_put_image };
-
-#endif
-
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)
{
-#ifdef MITSHM
- if (!uxa_do_shm_put_image
- (pDrawable, pGC, depth, format, w, h, 0, 0, w, h, x, y, bits))
-#else
if (!uxa_do_put_image(pDrawable, pGC, depth, x, y, w, h, format, bits,
PixmapBytePad(w, pDrawable->depth)))
-#endif
uxa_check_put_image(pDrawable, pGC, depth, x, y, w, h, leftPad,
format, bits);
}
@@ -435,6 +512,14 @@ uxa_copy_n_to_n(DrawablePtr pSrcDrawable,
pSrcPixmap = uxa_get_drawable_pixmap(pSrcDrawable);
pDstPixmap = uxa_get_drawable_pixmap(pDstDrawable);
+ if (!pSrcPixmap || !pDstPixmap)
+ goto fallback;
+
+ if (uxa_screen->info->check_copy &&
+ !uxa_screen->info->check_copy(pSrcPixmap, pDstPixmap,
+ pGC ? pGC->alu : GXcopy,
+ pGC ? pGC->planemask : FB_ALLONES))
+ goto fallback;
uxa_get_drawable_deltas(pSrcDrawable, pSrcPixmap, &src_off_x,
&src_off_y);
@@ -450,8 +535,45 @@ uxa_copy_n_to_n(DrawablePtr pSrcDrawable,
goto fallback;
}
- if (!uxa_pixmap_is_offscreen(pDstPixmap))
- goto fallback;
+ if (!uxa_pixmap_is_offscreen(pDstPixmap)) {
+ int stride, bpp;
+ char *dst;
+
+ if (!uxa_pixmap_is_offscreen(pSrcPixmap))
+ goto fallback;
+
+ if (!uxa_screen->info->get_image)
+ goto fallback;
+
+ /* Don't bother with under 8bpp, XYPixmaps. */
+ bpp = pSrcPixmap->drawable.bitsPerPixel;
+ if (bpp != pDstDrawable->bitsPerPixel || bpp < 8)
+ goto fallback;
+
+ /* Only accelerate copies: no rop or planemask. */
+ if (pGC && (!UXA_PM_IS_SOLID(pSrcDrawable, pGC->planemask) || pGC->alu != GXcopy))
+ goto fallback;
+
+ dst = pDstPixmap->devPrivate.ptr;
+ stride = pDstPixmap->devKind;
+ bpp /= 8;
+ while (nbox--) {
+ if (!uxa_screen->info->get_image(pSrcPixmap,
+ pbox->x1 + dx + src_off_x,
+ pbox->y1 + dy + src_off_y,
+ pbox->x2 - pbox->x1,
+ pbox->y2 - pbox->y1,
+ (char *) dst +
+ (pbox->y1 + dst_off_y) * stride +
+ (pbox->x1 + dst_off_x) * bpp,
+ stride))
+ goto fallback;
+
+ pbox++;
+ }
+
+ return;
+ }
if (uxa_pixmap_is_offscreen(pSrcPixmap)) {
if (!(*uxa_screen->info->prepare_copy) (pSrcPixmap, pDstPixmap,
@@ -558,7 +680,7 @@ uxa_poly_point(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
return;
}
- prect = xalloc(sizeof(xRectangle) * npt);
+ prect = malloc(sizeof(xRectangle) * npt);
if (!prect)
return;
for (i = 0; i < npt; i++) {
@@ -572,7 +694,7 @@ uxa_poly_point(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
prect[i].height = 1;
}
pGC->ops->PolyFillRect(pDrawable, pGC, npt, prect);
- xfree(prect);
+ free(prect);
}
/**
@@ -595,7 +717,7 @@ uxa_poly_lines(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
return;
}
- prect = xalloc(sizeof(xRectangle) * (npt - 1));
+ prect = malloc(sizeof(xRectangle) * (npt - 1));
if (!prect)
return;
x1 = ppt[0].x;
@@ -611,7 +733,7 @@ uxa_poly_lines(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
}
if (x1 != x2 && y1 != y2) {
- xfree(prect);
+ free(prect);
uxa_check_poly_lines(pDrawable, pGC, mode, npt, ppt);
return;
}
@@ -635,7 +757,7 @@ uxa_poly_lines(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
y1 = y2;
}
pGC->ops->PolyFillRect(pDrawable, pGC, npt - 1, prect);
- xfree(prect);
+ free(prect);
}
/**
@@ -664,7 +786,7 @@ uxa_poly_segment(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment * pSeg)
}
}
- prect = xalloc(sizeof(xRectangle) * nseg);
+ prect = malloc(sizeof(xRectangle) * nseg);
if (!prect)
return;
for (i = 0; i < nseg; i++) {
@@ -692,7 +814,7 @@ uxa_poly_segment(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment * pSeg)
}
}
pGC->ops->PolyFillRect(pDrawable, pGC, nseg, prect);
- xfree(prect);
+ free(prect);
}
static Bool uxa_fill_region_solid(DrawablePtr pDrawable, RegionPtr pRegion,
@@ -704,7 +826,7 @@ uxa_poly_fill_rect(DrawablePtr pDrawable,
{
uxa_screen_t *uxa_screen = uxa_get_screen(pDrawable->pScreen);
RegionPtr pClip = fbGetCompositeClip(pGC);
- PixmapPtr pPixmap = uxa_get_drawable_pixmap(pDrawable);
+ PixmapPtr pPixmap;
register BoxPtr pbox;
BoxPtr pextent;
int extentX1, extentX2, extentY1, extentY2;
@@ -722,11 +844,13 @@ uxa_poly_fill_rect(DrawablePtr pDrawable,
if (!REGION_NUM_RECTS(pReg))
goto out;
- uxa_get_drawable_deltas(pDrawable, pPixmap, &xoff, &yoff);
-
if (uxa_screen->swappedOut)
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}.
*/
@@ -752,8 +876,12 @@ uxa_poly_fill_rect(DrawablePtr pDrawable,
goto fallback;
}
- if (!uxa_pixmap_is_offscreen(pPixmap) ||
- !(*uxa_screen->info->prepare_solid) (pPixmap,
+ 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)) {
@@ -896,35 +1024,121 @@ uxa_fill_region_solid(DrawablePtr pDrawable,
RegionPtr pRegion,
Pixel pixel, CARD32 planemask, CARD32 alu)
{
- uxa_screen_t *uxa_screen = uxa_get_screen(pDrawable->pScreen);
- PixmapPtr pPixmap = uxa_get_drawable_pixmap(pDrawable);
+ ScreenPtr screen = pDrawable->pScreen;
+ uxa_screen_t *uxa_screen = uxa_get_screen(screen);
+ PixmapPtr pixmap;
int xoff, yoff;
+ int nbox;
+ BoxPtr pBox, extents;
Bool ret = FALSE;
- uxa_get_drawable_deltas(pDrawable, pPixmap, &xoff, &yoff);
- REGION_TRANSLATE(pScreen, pRegion, xoff, yoff);
+ pixmap = uxa_get_offscreen_pixmap(pDrawable, &xoff, &yoff);
+ if (!pixmap)
+ return FALSE;
- if (uxa_pixmap_is_offscreen(pPixmap) &&
- (*uxa_screen->info->prepare_solid) (pPixmap, alu, planemask, pixel))
- {
- int nbox;
- BoxPtr pBox;
+ REGION_TRANSLATE(screen, pRegion, xoff, yoff);
- nbox = REGION_NUM_RECTS(pRegion);
- pBox = REGION_RECTS(pRegion);
+ nbox = REGION_NUM_RECTS(pRegion);
+ pBox = REGION_RECTS(pRegion);
+ extents = REGION_EXTENTS(screen, pRegion);
+
+ /* Using GEM, the relocation costs outweigh the advantages of the blitter */
+ if (nbox == 1 || (alu != GXcopy && alu != GXclear) || planemask != FB_ALLONES) {
+try_solid:
+ 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) (pPixmap, pBox->x1, pBox->y1,
- pBox->x2, pBox->y2);
+ uxa_screen->info->solid(pixmap,
+ pBox->x1, pBox->y1,
+ pBox->x2, pBox->y2);
pBox++;
}
- (*uxa_screen->info->done_solid) (pPixmap);
- ret = TRUE;
+ uxa_screen->info->done_solid(pixmap);
+ } else {
+ PicturePtr dst, src;
+ PixmapPtr src_pixmap = NULL;
+ xRenderColor color;
+ int error;
+
+ dst = CreatePicture(0, &pixmap->drawable,
+ PictureMatchFormat(screen,
+ pixmap->drawable.depth,
+ format_for_depth(pixmap->drawable.depth)),
+ 0, 0, serverClient, &error);
+ if (!dst)
+ goto err;
+
+ ValidatePicture(dst);
+
+ uxa_get_rgba_from_pixel(pixel,
+ &color.red,
+ &color.green,
+ &color.blue,
+ &color.alpha,
+ format_for_depth(pixmap->drawable.depth));
+ src = CreateSolidPicture(0, &color, &error);
+ if (!src) {
+ FreePicture(dst, 0);
+ goto err;
+ }
+
+ if (!uxa_screen->info->check_composite(PictOpSrc, src, NULL, dst,
+ extents->x2 - extents->x1,
+ extents->y2 - extents->y1)) {
+ FreePicture(src, 0);
+ FreePicture(dst, 0);
+ goto try_solid;
+ }
+
+ if (!uxa_screen->info->check_composite_texture ||
+ !uxa_screen->info->check_composite_texture(screen, src)) {
+ PicturePtr solid;
+ int src_off_x, src_off_y;
+
+ solid = uxa_acquire_solid(screen, src->pSourcePict);
+ FreePicture(src, 0);
+
+ src = solid;
+ src_pixmap = uxa_get_offscreen_pixmap(src->pDrawable,
+ &src_off_x, &src_off_y);
+ if (!src_pixmap) {
+ FreePicture(src, 0);
+ FreePicture(dst, 0);
+ goto err;
+ }
+ }
+
+ if (!uxa_screen->info->prepare_composite(PictOpSrc, src, NULL, dst, src_pixmap, NULL, pixmap)) {
+ FreePicture(src, 0);
+ FreePicture(dst, 0);
+ goto err;
+ }
+
+ while (nbox--) {
+ uxa_screen->info->composite(pixmap,
+ 0, 0, 0, 0,
+ pBox->x1,
+ pBox->y1,
+ pBox->x2 - pBox->x1,
+ pBox->y2 - pBox->y1);
+ pBox++;
+ }
+
+ uxa_screen->info->done_composite(pixmap);
+ FreePicture(src, 0);
+ FreePicture(dst, 0);
}
- REGION_TRANSLATE(pScreen, pRegion, -xoff, -yoff);
+ ret = TRUE;
+err:
+ REGION_TRANSLATE(screen, pRegion, -xoff, -yoff);
return ret;
}
@@ -956,15 +1170,16 @@ uxa_fill_region_tiled(DrawablePtr pDrawable,
uxa_get_pixmap_first_pixel(pTile),
planemask, alu);
- pPixmap = uxa_get_drawable_pixmap(pDrawable);
- uxa_get_drawable_deltas(pDrawable, pPixmap, &xoff, &yoff);
- REGION_TRANSLATE(pScreen, pRegion, xoff, yoff);
-
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--) {
diff --git a/uxa/uxa-glyphs.c b/uxa/uxa-glyphs.c
index 5c233216..823cf82f 100644
--- a/uxa/uxa-glyphs.c
+++ b/uxa/uxa-glyphs.c
@@ -1,11 +1,29 @@
/*
- * Copyright © 2008 Red Hat, Inc.
+ * Copyright © 2010 Intel Corporation
+ * Partly based on code Copyright © 2008 Red Hat, Inc.
* Partly based on code Copyright © 2000 SuSE, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Intel not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Intel makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL INTEL
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
* documentation, and that the name of Red Hat not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. Red Hat makes no representations about the
@@ -16,7 +34,7 @@
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL Red Hat
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Permission to use, copy, modify, distribute, and sell this software and its
@@ -33,11 +51,11 @@
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * Author: Owen Taylor <otaylor@fishsoup.net>
- * Based on code by: Keith Packard
+ * Author: Chris Wilson <chris@chris-wilson.co.uk>
+ * Based on code by: Keith Packard <keithp@keithp.com> and Owen Taylor <otaylor@fishsoup.net>
*/
#ifdef HAVE_DIX_CONFIG_H
@@ -51,99 +69,63 @@
#include "mipict.h"
-#if DEBUG_GLYPH_CACHE
-#define DBG_GLYPH_CACHE(a) ErrorF a
-#else
-#define DBG_GLYPH_CACHE(a)
-#endif
-
/* Width of the pixmaps we use for the caches; this should be less than
* max texture size of the driver; this may need to actually come from
* the driver.
*/
-#define CACHE_PICTURE_WIDTH 1024
-
-/* Maximum number of glyphs we buffer on the stack before flushing
- * rendering to the mask or destination surface.
- */
-#define GLYPH_BUFFER_SIZE 256
-
-typedef struct {
- PicturePtr source;
- uxa_composite_rect_t rects[GLYPH_BUFFER_SIZE];
- int count;
-} uxa_glyph_buffer_t;
-
-typedef enum {
- UXA_GLYPH_SUCCESS, /* Glyph added to render buffer */
- UXA_GLYPH_FAIL, /* out of memory, etc */
- UXA_GLYPH_NEED_FLUSH, /* would evict a glyph already in the buffer */
-} uxa_glyph_cache_result_t;
+#define CACHE_PICTURE_SIZE 1024
+#define GLYPH_MIN_SIZE 8
+#define GLYPH_MAX_SIZE 64
+#define GLYPH_CACHE_SIZE (CACHE_PICTURE_SIZE * CACHE_PICTURE_SIZE / (GLYPH_MIN_SIZE * GLYPH_MIN_SIZE))
+
+struct uxa_glyph {
+ uxa_glyph_cache_t *cache;
+ uint16_t x, y;
+ uint16_t size, pos;
+};
+
+#if HAS_DEVPRIVATEKEYREC
+static DevPrivateKeyRec uxa_glyph_key;
+#else
+static int uxa_glyph_key;
+#endif
-void uxa_glyphs_init(ScreenPtr pScreen)
+static inline struct uxa_glyph *uxa_glyph_get_private(GlyphPtr glyph)
{
- uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
- int i = 0;
-
- memset(uxa_screen->glyphCaches, 0, sizeof(uxa_screen->glyphCaches));
+#if HAS_DEVPRIVATEKEYREC
+ return dixGetPrivate(&glyph->devPrivates, &uxa_glyph_key);
+#else
+ return dixLookupPrivate(&glyph->devPrivates, &uxa_glyph_key);
+#endif
+}
- uxa_screen->glyphCaches[i].format = PICT_a8;
- uxa_screen->glyphCaches[i].glyphWidth =
- uxa_screen->glyphCaches[i].glyphHeight = 16;
- i++;
- uxa_screen->glyphCaches[i].format = PICT_a8;
- uxa_screen->glyphCaches[i].glyphWidth =
- uxa_screen->glyphCaches[i].glyphHeight = 32;
- i++;
- uxa_screen->glyphCaches[i].format = PICT_a8r8g8b8;
- uxa_screen->glyphCaches[i].glyphWidth =
- uxa_screen->glyphCaches[i].glyphHeight = 16;
- i++;
- uxa_screen->glyphCaches[i].format = PICT_a8r8g8b8;
- uxa_screen->glyphCaches[i].glyphWidth =
- uxa_screen->glyphCaches[i].glyphHeight = 32;
- i++;
-
- assert(i == UXA_NUM_GLYPH_CACHES);
-
- for (i = 0; i < UXA_NUM_GLYPH_CACHES; i++) {
- uxa_screen->glyphCaches[i].columns =
- CACHE_PICTURE_WIDTH / uxa_screen->glyphCaches[i].glyphWidth;
- uxa_screen->glyphCaches[i].size = 256;
- uxa_screen->glyphCaches[i].hashSize = 557;
- }
+static inline void uxa_glyph_set_private(GlyphPtr glyph, struct uxa_glyph *priv)
+{
+ dixSetPrivate(&glyph->devPrivates, &uxa_glyph_key, priv);
}
-static void uxa_unrealize_glyph_caches(ScreenPtr pScreen, unsigned int format)
+#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0)
+
+static void uxa_unrealize_glyph_caches(ScreenPtr pScreen)
{
uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
int i;
- for (i = 0; i < UXA_NUM_GLYPH_CACHES; i++) {
+ for (i = 0; i < UXA_NUM_GLYPH_CACHE_FORMATS; i++) {
uxa_glyph_cache_t *cache = &uxa_screen->glyphCaches[i];
- if (cache->format != format)
- continue;
-
- if (cache->picture) {
- FreePicture((pointer) cache->picture, (XID) 0);
- cache->picture = NULL;
- }
-
- if (cache->hashEntries) {
- xfree(cache->hashEntries);
- cache->hashEntries = NULL;
- }
+ if (cache->picture)
+ FreePicture(cache->picture, 0);
- if (cache->glyphs) {
- xfree(cache->glyphs);
- cache->glyphs = NULL;
- }
- cache->glyphCount = 0;
+ if (cache->glyphs)
+ free(cache->glyphs);
}
}
-#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0)
+void uxa_glyphs_fini(ScreenPtr pScreen)
+{
+ uxa_unrealize_glyph_caches(pScreen);
+}
/* All caches for a single format share a single pixmap for glyph storage,
* allowing mixing glyphs of different sizes without paying a penalty
@@ -154,460 +136,176 @@ static void uxa_unrealize_glyph_caches(ScreenPtr pScreen, unsigned int format)
* 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, unsigned int format)
+static Bool uxa_realize_glyph_caches(ScreenPtr pScreen)
{
uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
- int depth = PIXMAN_FORMAT_DEPTH(format);
- PictFormatPtr pPictFormat;
- PixmapPtr pPixmap;
- PicturePtr pPicture;
- CARD32 component_alpha;
- int height;
+ unsigned int formats[] = {
+ PIXMAN_a8,
+ PIXMAN_a8r8g8b8,
+ };
int i;
- int error;
- pPictFormat = PictureMatchFormat(pScreen, depth, format);
- if (!pPictFormat)
- return FALSE;
-
- /* Compute the total vertical size needed for the format */
+ memset(uxa_screen->glyphCaches, 0, sizeof(uxa_screen->glyphCaches));
- height = 0;
- for (i = 0; i < UXA_NUM_GLYPH_CACHES; i++) {
+ for (i = 0; i < sizeof(formats)/sizeof(formats[0]); i++) {
uxa_glyph_cache_t *cache = &uxa_screen->glyphCaches[i];
- int rows;
-
- if (cache->format != format)
- continue;
-
- cache->yOffset = height;
-
- rows = (cache->size + cache->columns - 1) / cache->columns;
- height += rows * cache->glyphHeight;
- }
-
- /* Now allocate the pixmap and picture */
-
- pPixmap = (*pScreen->CreatePixmap) (pScreen,
- CACHE_PICTURE_WIDTH,
- height, depth,
- INTEL_CREATE_PIXMAP_TILING_X);
- if (!pPixmap)
- return FALSE;
-
- component_alpha = NeedsComponent(pPictFormat->format);
- pPicture = CreatePicture(0, &pPixmap->drawable, pPictFormat,
- CPComponentAlpha, &component_alpha,
- serverClient, &error);
-
- (*pScreen->DestroyPixmap) (pPixmap); /* picture holds a refcount */
+ 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;
- if (!pPicture)
- return FALSE;
+ /* 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;
+ assert (uxa_pixmap_is_offscreen(pixmap));
- /* And store the picture in all the caches for the format */
+ component_alpha = NeedsComponent(pPictFormat->format);
+ picture = CreatePicture(0, &pixmap->drawable, pPictFormat,
+ CPComponentAlpha, &component_alpha,
+ serverClient, &error);
- for (i = 0; i < UXA_NUM_GLYPH_CACHES; i++) {
- uxa_glyph_cache_t *cache = &uxa_screen->glyphCaches[i];
- int j;
+ pScreen->DestroyPixmap(pixmap);
- if (cache->format != format)
- continue;
+ if (!picture)
+ goto bail;
- cache->picture = pPicture;
- cache->picture->refcnt++;
- cache->hashEntries = xalloc(sizeof(int) * cache->hashSize);
- cache->glyphs =
- xalloc(sizeof(uxa_cached_glyph_t) * cache->size);
- cache->glyphCount = 0;
+ ValidatePicture(picture);
- if (!cache->hashEntries || !cache->glyphs)
+ cache->picture = picture;
+ cache->glyphs = calloc(sizeof(GlyphPtr), GLYPH_CACHE_SIZE);
+ if (!cache->glyphs)
goto bail;
- for (j = 0; j < cache->hashSize; j++)
- cache->hashEntries[j] = -1;
-
- cache->evictionPosition = rand() % cache->size;
+ cache->evict = rand() % GLYPH_CACHE_SIZE;
}
+ assert(i == UXA_NUM_GLYPH_CACHE_FORMATS);
- /* Each cache references the picture individually */
- FreePicture((pointer) pPicture, (XID) 0);
return TRUE;
bail:
- uxa_unrealize_glyph_caches(pScreen, format);
+ uxa_unrealize_glyph_caches(pScreen);
return FALSE;
}
-void uxa_glyphs_fini(ScreenPtr pScreen)
-{
- uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
- int i;
-
- for (i = 0; i < UXA_NUM_GLYPH_CACHES; i++) {
- uxa_glyph_cache_t *cache = &uxa_screen->glyphCaches[i];
- if (cache->picture)
- uxa_unrealize_glyph_caches(pScreen, cache->format);
- }
-}
-
-static int
-uxa_glyph_cache_hash_lookup(uxa_glyph_cache_t * cache, GlyphPtr pGlyph)
+Bool uxa_glyphs_init(ScreenPtr pScreen)
{
- int slot;
-
- slot = (*(CARD32 *) pGlyph->sha1) % cache->hashSize;
-
- while (TRUE) { /* hash table can never be full */
- int entryPos = cache->hashEntries[slot];
- if (entryPos == -1)
- return -1;
-
- if (memcmp
- (pGlyph->sha1, cache->glyphs[entryPos].sha1,
- sizeof(pGlyph->sha1)) == 0) {
- return entryPos;
- }
-
- slot--;
- if (slot < 0)
- slot = cache->hashSize - 1;
- }
-}
-
-static void
-uxa_glyph_cache_hash_insert(uxa_glyph_cache_t * cache, GlyphPtr pGlyph, int pos)
-{
- int slot;
-
- memcpy(cache->glyphs[pos].sha1, pGlyph->sha1, sizeof(pGlyph->sha1));
-
- slot = (*(CARD32 *) pGlyph->sha1) % cache->hashSize;
-
- while (TRUE) { /* hash table can never be full */
- if (cache->hashEntries[slot] == -1) {
- cache->hashEntries[slot] = pos;
- return;
- }
-
- slot--;
- if (slot < 0)
- slot = cache->hashSize - 1;
- }
-}
-
-static void uxa_glyph_cache_hash_remove(uxa_glyph_cache_t * cache, int pos)
-{
- int slot;
- int emptiedSlot = -1;
-
- slot = (*(CARD32 *) cache->glyphs[pos].sha1) % cache->hashSize;
-
- while (TRUE) { /* hash table can never be full */
- int entryPos = cache->hashEntries[slot];
+ /* We are trying to initialise per screen resources prior to the
+ * complete initialisation of the screen. So ensure the components
+ * that we depend upon are initialsed prior to our use.
+ */
+ if (!CreateScratchPixmapsForScreen(pScreen->myNum))
+ return FALSE;
- if (entryPos == -1)
- return;
+#if HAS_DIXREGISTERPRIVATEKEY
+ if (!dixRegisterPrivateKey(&uxa_glyph_key, PRIVATE_GLYPH, 0))
+ return FALSE;
+#else
+ if (!dixRequestPrivate(&uxa_glyph_key, 0))
+ return FALSE;
+#endif
- if (entryPos == pos) {
- cache->hashEntries[slot] = -1;
- emptiedSlot = slot;
- } else if (emptiedSlot != -1) {
- /* See if we can move this entry into the emptied slot,
- * we can't do that if if entry would have hashed
- * between the current position and the emptied slot.
- * (taking wrapping into account). Bad positions
- * are:
- *
- * | XXXXXXXXXX |
- * i j
- *
- * |XXX XXXX|
- * j i
- *
- * i - slot, j - emptiedSlot
- *
- * (Knuth 6.4R)
- */
-
- int entrySlot =
- (*(CARD32 *) cache->glyphs[entryPos].sha1) %
- cache->hashSize;
-
- if (!((entrySlot >= slot && entrySlot < emptiedSlot) ||
- (emptiedSlot < slot
- && (entrySlot < emptiedSlot
- || entrySlot >= slot)))) {
- cache->hashEntries[emptiedSlot] = entryPos;
- cache->hashEntries[slot] = -1;
- emptiedSlot = slot;
- }
- }
+ if (!uxa_realize_glyph_caches(pScreen))
+ return FALSE;
- slot--;
- if (slot < 0)
- slot = cache->hashSize - 1;
- }
+ return TRUE;
}
-#define CACHE_X(pos) (((pos) % cache->columns) * cache->glyphWidth)
-#define CACHE_Y(pos) (cache->yOffset + ((pos) / cache->columns) * cache->glyphHeight)
-
/* The most efficient thing to way to upload the glyph to the screen
* is to use CopyArea; uxa pixmaps are always offscreen.
*/
-static Bool
-uxa_glyph_cache_upload_glyph(ScreenPtr pScreen,
+static void
+uxa_glyph_cache_upload_glyph(ScreenPtr screen,
uxa_glyph_cache_t * cache,
- int pos, GlyphPtr pGlyph)
+ GlyphPtr glyph,
+ int x, int y)
{
- PicturePtr pGlyphPicture = GlyphPicture(pGlyph)[pScreen->myNum];
+ PicturePtr pGlyphPicture = GlyphPicture(glyph)[screen->myNum];
PixmapPtr pGlyphPixmap = (PixmapPtr) pGlyphPicture->pDrawable;
PixmapPtr pCachePixmap = (PixmapPtr) cache->picture->pDrawable;
PixmapPtr scratch;
- GCPtr pGC;
+ GCPtr gc;
- /* UploadToScreen only works if bpp match */
- if (pGlyphPixmap->drawable.bitsPerPixel !=
- pCachePixmap->drawable.bitsPerPixel)
- return FALSE;
+ gc = GetScratchGC(pCachePixmap->drawable.depth, screen);
+ if (!gc)
+ return;
- pGC = GetScratchGC(pCachePixmap->drawable.depth, pScreen);
- ValidateGC(&pCachePixmap->drawable, pGC);
+ ValidateGC(&pCachePixmap->drawable, gc);
+ scratch = pGlyphPixmap;
/* Create a temporary bo to stream the updates to the cache */
- scratch = (*pScreen->CreatePixmap)(pScreen,
- pGlyph->info.width,
- pGlyph->info.height,
- pGlyphPixmap->drawable.depth,
- UXA_CREATE_PIXMAP_FOR_MAP);
- if (scratch) {
- (void)uxa_copy_area(&pGlyphPixmap->drawable,
- &scratch->drawable,
- pGC,
- 0, 0,
- pGlyph->info.width, pGlyph->info.height,
- 0, 0);
- } else {
- scratch = pGlyphPixmap;
- }
-
- (void)uxa_copy_area(&scratch->drawable,
- &pCachePixmap->drawable,
- pGC,
- 0, 0, pGlyph->info.width, pGlyph->info.height,
- CACHE_X(pos), CACHE_Y(pos));
-
- if (scratch != pGlyphPixmap)
- (*pScreen->DestroyPixmap)(scratch);
-
- FreeScratchGC(pGC);
-
- return TRUE;
-}
-
-static uxa_glyph_cache_result_t
-uxa_glyph_cache_buffer_glyph(ScreenPtr pScreen,
- uxa_glyph_cache_t * cache,
- uxa_glyph_buffer_t * buffer,
- GlyphPtr pGlyph, int xGlyph, int yGlyph)
-{
- uxa_composite_rect_t *rect;
- int pos;
-
- if (buffer->source && buffer->source != cache->picture)
- return UXA_GLYPH_NEED_FLUSH;
-
- if (!cache->picture) {
- if (!uxa_realize_glyph_caches(pScreen, cache->format))
- return UXA_GLYPH_FAIL;
- }
-
- DBG_GLYPH_CACHE(("(%d,%d,%s): buffering glyph %lx\n",
- cache->glyphWidth, cache->glyphHeight,
- cache->format == PICT_a8 ? "A" : "ARGB",
- (long)*(CARD32 *) pGlyph->sha1));
-
- pos = uxa_glyph_cache_hash_lookup(cache, pGlyph);
- if (pos != -1) {
- DBG_GLYPH_CACHE((" found existing glyph at %d\n", pos));
- } else {
- if (cache->glyphCount < cache->size) {
- /* Space remaining; we fill from the start */
- pos = cache->glyphCount;
- cache->glyphCount++;
- DBG_GLYPH_CACHE((" storing glyph in free space at %d\n", pos));
-
- uxa_glyph_cache_hash_insert(cache, pGlyph, pos);
-
- } else {
- /* Need to evict an entry. We have to see if any glyphs
- * already in the output buffer were at this position in
- * the cache
- */
-
- pos = cache->evictionPosition;
- DBG_GLYPH_CACHE((" evicting glyph at %d\n", pos));
- if (buffer->count) {
- int x, y;
- int i;
-
- x = CACHE_X(pos);
- y = CACHE_Y(pos);
-
- for (i = 0; i < buffer->count; i++) {
- if (buffer->rects[i].xSrc == x
- && buffer->rects[i].ySrc == y) {
- DBG_GLYPH_CACHE((" must flush buffer\n"));
- return UXA_GLYPH_NEED_FLUSH;
- }
+ if (pGlyphPixmap->drawable.depth != pCachePixmap->drawable.depth ||
+ !uxa_pixmap_is_offscreen(scratch)) {
+ scratch = screen->CreatePixmap(screen,
+ glyph->info.width,
+ glyph->info.height,
+ pCachePixmap->drawable.depth,
+ UXA_CREATE_PIXMAP_FOR_MAP);
+ if (scratch) {
+ if (pGlyphPixmap->drawable.depth != pCachePixmap->drawable.depth) {
+ PicturePtr picture;
+ int error;
+
+ picture = CreatePicture(0, &scratch->drawable,
+ PictureMatchFormat(screen,
+ pCachePixmap->drawable.depth,
+ cache->picture->format),
+ 0, NULL,
+ serverClient, &error);
+ if (picture) {
+ ValidatePicture(picture);
+ uxa_composite(PictOpSrc, pGlyphPicture, NULL, picture,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ glyph->info.width, glyph->info.height);
+ FreePicture(picture, 0);
}
+ } else {
+ uxa_copy_area(&pGlyphPixmap->drawable,
+ &scratch->drawable,
+ gc,
+ 0, 0,
+ glyph->info.width, glyph->info.height,
+ 0, 0);
}
-
- /* OK, we're all set, swap in the new glyph */
- uxa_glyph_cache_hash_remove(cache, pos);
- uxa_glyph_cache_hash_insert(cache, pGlyph, pos);
-
- /* And pick a new eviction position */
- cache->evictionPosition = rand() % cache->size;
- }
-
- /* Now actually upload the glyph into the cache picture; if
- * we can't do it with UploadToScreen (because the glyph is
- * offscreen, etc), we fall back to CompositePicture.
- */
- if (!uxa_glyph_cache_upload_glyph(pScreen, cache, pos, pGlyph)) {
- CompositePicture(PictOpSrc,
- GlyphPicture(pGlyph)[pScreen->myNum],
- None,
- cache->picture,
- 0, 0,
- 0, 0,
- CACHE_X(pos),
- CACHE_Y(pos),
- pGlyph->info.width,
- pGlyph->info.height);
- }
-
- }
-
- buffer->source = cache->picture;
-
- rect = &buffer->rects[buffer->count];
- rect->xSrc = CACHE_X(pos);
- rect->ySrc = CACHE_Y(pos);
- rect->xDst = xGlyph - pGlyph->info.x;
- rect->yDst = yGlyph - pGlyph->info.y;
- rect->width = pGlyph->info.width;
- rect->height = pGlyph->info.height;
-
- buffer->count++;
-
- return UXA_GLYPH_SUCCESS;
-}
-
-#undef CACHE_X
-#undef CACHE_Y
-
-static uxa_glyph_cache_result_t
-uxa_buffer_glyph(ScreenPtr pScreen,
- uxa_glyph_buffer_t * buffer,
- GlyphPtr pGlyph, int xGlyph, int yGlyph)
-{
- uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
- unsigned int format = (GlyphPicture(pGlyph)[pScreen->myNum])->format;
- int width = pGlyph->info.width;
- int height = pGlyph->info.height;
- uxa_composite_rect_t *rect;
- PicturePtr source;
- int i;
-
- if (buffer->count == GLYPH_BUFFER_SIZE)
- return UXA_GLYPH_NEED_FLUSH;
-
- if (PICT_FORMAT_BPP(format) == 1)
- format = PICT_a8;
-
- for (i = 0; i < UXA_NUM_GLYPH_CACHES; i++) {
- uxa_glyph_cache_t *cache = &uxa_screen->glyphCaches[i];
-
- if (format == cache->format &&
- width <= cache->glyphWidth &&
- height <= cache->glyphHeight) {
- uxa_glyph_cache_result_t result =
- uxa_glyph_cache_buffer_glyph(pScreen,
- &uxa_screen->
- glyphCaches[i],
- buffer,
- pGlyph, xGlyph,
- yGlyph);
- switch (result) {
- case UXA_GLYPH_FAIL:
- break;
- case UXA_GLYPH_SUCCESS:
- case UXA_GLYPH_NEED_FLUSH:
- return result;
- }
+ } else {
+ scratch = pGlyphPixmap;
}
}
- /* Couldn't find the glyph in the cache, use the glyph picture directly */
-
- source = GlyphPicture(pGlyph)[pScreen->myNum];
- if (buffer->source && buffer->source != source)
- return UXA_GLYPH_NEED_FLUSH;
+ uxa_copy_area(&scratch->drawable, &pCachePixmap->drawable, gc,
+ 0, 0,
+ glyph->info.width, glyph->info.height,
+ x, y);
- buffer->source = source;
-
- rect = &buffer->rects[buffer->count];
- rect->xSrc = 0;
- rect->ySrc = 0;
- rect->xDst = xGlyph - pGlyph->info.x;
- rect->yDst = yGlyph - pGlyph->info.y;
- rect->width = pGlyph->info.width;
- rect->height = pGlyph->info.height;
-
- buffer->count++;
+ if (scratch != pGlyphPixmap)
+ screen->DestroyPixmap(scratch);
- return UXA_GLYPH_SUCCESS;
+ FreeScratchGC(gc);
}
-static void uxa_glyphs_to_mask(PicturePtr pMask, uxa_glyph_buffer_t * buffer)
+void
+uxa_glyph_unrealize(ScreenPtr pScreen,
+ GlyphPtr pGlyph)
{
- uxa_composite_rects(PictOpAdd, buffer->source, pMask,
- buffer->count, buffer->rects);
-
- buffer->count = 0;
- buffer->source = NULL;
-}
+ struct uxa_glyph *priv;
-static void
-uxa_glyphs_to_dst(CARD8 op,
- PicturePtr pSrc,
- PicturePtr pDst,
- uxa_glyph_buffer_t * buffer,
- INT16 xSrc, INT16 ySrc, INT16 xDst, INT16 yDst)
-{
- int i;
+ priv = uxa_glyph_get_private(pGlyph);
+ if (priv == NULL)
+ return;
- for (i = 0; i < buffer->count; i++) {
- uxa_composite_rect_t *rect = &buffer->rects[i];
-
- CompositePicture(op,
- pSrc,
- buffer->source,
- pDst,
- xSrc + rect->xDst - xDst,
- ySrc + rect->yDst - yDst,
- rect->xSrc,
- rect->ySrc,
- rect->xDst,
- rect->yDst, rect->width, rect->height);
- }
+ priv->cache->glyphs[priv->pos] = NULL;
- buffer->count = 0;
- buffer->source = NULL;
+ uxa_glyph_set_private(pGlyph, NULL);
+ free(priv);
}
/* Cut and paste from render/glyph.c - probably should export it instead */
@@ -616,47 +314,43 @@ uxa_glyph_extents(int nlist,
GlyphListPtr list, GlyphPtr * glyphs, BoxPtr extents)
{
int x1, x2, y1, y2;
- int n;
- GlyphPtr glyph;
- int x, y;
+ int x, y, n;
- x = 0;
- y = 0;
- extents->x1 = MAXSHORT;
- extents->x2 = MINSHORT;
- extents->y1 = MAXSHORT;
- extents->y2 = MINSHORT;
+ x1 = y1 = MAXSHORT;
+ x2 = y2 = MINSHORT;
+ x = y = 0;
while (nlist--) {
x += list->xOff;
y += list->yOff;
n = list->len;
list++;
while (n--) {
- glyph = *glyphs++;
- x1 = x - glyph->info.x;
- if (x1 < MINSHORT)
- x1 = MINSHORT;
- y1 = y - glyph->info.y;
- if (y1 < MINSHORT)
- y1 = MINSHORT;
- x2 = x1 + glyph->info.width;
- if (x2 > MAXSHORT)
- x2 = MAXSHORT;
- y2 = y1 + glyph->info.height;
- if (y2 > MAXSHORT)
- y2 = MAXSHORT;
- if (x1 < extents->x1)
- extents->x1 = x1;
- if (x2 > extents->x2)
- extents->x2 = x2;
- if (y1 < extents->y1)
- extents->y1 = y1;
- if (y2 > extents->y2)
- extents->y2 = y2;
+ GlyphPtr glyph = *glyphs++;
+ int v;
+
+ v = x - glyph->info.x;
+ if (v < x1)
+ x1 = v;
+ v += glyph->info.width;
+ if (v > x2)
+ x2 = v;
+
+ v = y - glyph->info.y;
+ if (v < y1)
+ y1 = v;
+ v += glyph->info.height;
+ if (v > y2)
+ y2 = v;
+
x += glyph->info.xOff;
y += glyph->info.yOff;
}
}
+
+ extents->x1 = x1 < MINSHORT ? MINSHORT : x1;
+ extents->x2 = x2 > MAXSHORT ? MAXSHORT : x2;
+ extents->y1 = y1 < MINSHORT ? MINSHORT : y1;
+ extents->y2 = y2 > MAXSHORT ? MAXSHORT : y2;
}
/**
@@ -668,7 +362,6 @@ uxa_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr * glyphs)
{
int x1, x2, y1, y2;
int n;
- GlyphPtr glyph;
int x, y;
BoxRec extents;
Bool first = TRUE;
@@ -685,7 +378,7 @@ uxa_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr * glyphs)
n = list->len;
list++;
while (n--) {
- glyph = *glyphs++;
+ GlyphPtr glyph = *glyphs++;
if (glyph->info.width == 0 || glyph->info.height == 0) {
x += glyph->info.xOff;
@@ -735,121 +428,98 @@ uxa_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr * glyphs)
return FALSE;
}
-void
-uxa_glyphs(CARD8 op,
- PicturePtr pSrc,
- PicturePtr pDst,
- PictFormatPtr maskFormat,
- INT16 xSrc,
- INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr * glyphs)
+static void
+uxa_check_glyphs(CARD8 op,
+ PicturePtr src,
+ PicturePtr dst,
+ PictFormatPtr maskFormat,
+ INT16 xSrc,
+ INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr * glyphs)
{
- PicturePtr pPicture;
- PixmapPtr pMaskPixmap = 0;
- PicturePtr pMask;
- ScreenPtr pScreen = pDst->pDrawable->pScreen;
+ int screen = dst->pDrawable->pScreen->myNum;
+ pixman_image_t *image;
+ PixmapPtr scratch;
+ PicturePtr mask;
int width = 0, height = 0;
- int x, y;
+ int x, y, n;
int xDst = list->xOff, yDst = list->yOff;
- int n;
- GlyphPtr glyph;
- int error;
BoxRec extents = { 0, 0, 0, 0 };
- CARD32 component_alpha;
- uxa_glyph_buffer_t buffer;
-
- /* If we don't have a mask format but all the glyphs have the same format
- * and don't intersect, use the glyph format as mask format for the full
- * benefits of the glyph cache.
- */
- if (!maskFormat) {
- 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 || (maskFormat->depth != 1 &&
- uxa_glyphs_intersect(nlist, list,
- glyphs))) {
- maskFormat = NULL;
- }
- }
if (maskFormat) {
- GCPtr pGC;
- xRectangle rect;
+ pixman_format_code_t format;
+ CARD32 component_alpha;
+ int error;
uxa_glyph_extents(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);
+ format = maskFormat->format |
+ (BitsPerPixel(maskFormat->depth) << 24);
+ image =
+ pixman_image_create_bits(format, width, height, NULL, 0);
+ if (!image)
+ return;
- if (a8Format)
- maskFormat = a8Format;
- }
+ scratch = GetScratchPixmapHeader(dst->pDrawable->pScreen, width, height,
+ PIXMAN_FORMAT_DEPTH(format),
+ PIXMAN_FORMAT_BPP(format),
+ pixman_image_get_stride(image),
+ pixman_image_get_data(image));
- pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height,
- maskFormat->depth,
- CREATE_PIXMAP_USAGE_SCRATCH);
- if (!pMaskPixmap)
+ if (!scratch) {
+ pixman_image_unref(image);
return;
+ }
+
component_alpha = NeedsComponent(maskFormat->format);
- pMask = CreatePicture(0, &pMaskPixmap->drawable,
- maskFormat, CPComponentAlpha,
- &component_alpha, serverClient, &error);
- if (!pMask) {
- (*pScreen->DestroyPixmap) (pMaskPixmap);
+ mask = CreatePicture(0, &scratch->drawable,
+ maskFormat, CPComponentAlpha,
+ &component_alpha, serverClient, &error);
+ if (!mask) {
+ FreeScratchPixmapHeader(scratch);
+ pixman_image_unref(image);
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);
+ ValidatePicture(mask);
+
x = -extents.x1;
y = -extents.y1;
} else {
- pMask = pDst;
+ mask = dst;
x = 0;
y = 0;
}
- buffer.count = 0;
- buffer.source = NULL;
+
while (nlist--) {
x += list->xOff;
y += list->yOff;
n = list->len;
while (n--) {
- glyph = *glyphs++;
- pPicture = GlyphPicture(glyph)[pScreen->myNum];
-
- if (glyph->info.width > 0 && glyph->info.height > 0 &&
- uxa_buffer_glyph(pScreen, &buffer, glyph, x,
- y) == UXA_GLYPH_NEED_FLUSH) {
- if (maskFormat)
- uxa_glyphs_to_mask(pMask, &buffer);
- else
- uxa_glyphs_to_dst(op, pSrc, pDst,
- &buffer, xSrc, ySrc,
- xDst, yDst);
-
- uxa_buffer_glyph(pScreen, &buffer, glyph, x, y);
+ GlyphPtr glyph = *glyphs++;
+ PicturePtr g = GlyphPicture(glyph)[screen];
+ if (g) {
+ if (maskFormat) {
+ CompositePicture(PictOpAdd, g, NULL, mask,
+ 0, 0,
+ 0, 0,
+ x - glyph->info.x,
+ y - glyph->info.y,
+ glyph->info.width,
+ glyph->info.height);
+ } else {
+ CompositePicture(op, src, g, dst,
+ xSrc + (x - glyph->info.x) - xDst,
+ ySrc + (y - glyph->info.y) - yDst,
+ 0, 0,
+ x - glyph->info.x,
+ y - glyph->info.y,
+ glyph->info.width,
+ glyph->info.height);
+ }
}
x += glyph->info.xOff;
@@ -858,24 +528,659 @@ uxa_glyphs(CARD8 op,
list++;
}
- if (buffer.count) {
- if (maskFormat)
- uxa_glyphs_to_mask(pMask, &buffer);
- else
- uxa_glyphs_to_dst(op, pSrc, pDst, &buffer,
- xSrc, ySrc, xDst, yDst);
- }
-
if (maskFormat) {
x = extents.x1;
y = extents.y1;
- CompositePicture(op,
- pSrc,
- pMask,
- pDst,
+ CompositePicture(op, src, mask, dst,
xSrc + x - xDst,
- ySrc + y - yDst, 0, 0, x, y, width, height);
- FreePicture((pointer) pMask, (XID) 0);
- (*pScreen->DestroyPixmap) (pMaskPixmap);
+ ySrc + y - yDst,
+ 0, 0,
+ x, y,
+ width, height);
+ FreePicture(mask, 0);
+ FreeScratchPixmapHeader(scratch);
+ pixman_image_unref(image);
+ }
+}
+
+static inline unsigned int
+uxa_glyph_size_to_count(int size)
+{
+ size /= GLYPH_MIN_SIZE;
+ return size * size;
+}
+
+static inline unsigned int
+uxa_glyph_count_to_mask(int count)
+{
+ return ~(count - 1);
+}
+
+static inline unsigned int
+uxa_glyph_size_to_mask(int size)
+{
+ return uxa_glyph_count_to_mask(uxa_glyph_size_to_count(size));
+}
+
+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 = GlyphPicture(glyph)[screen->myNum];
+ 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;
+}
+
+static int
+uxa_glyphs_to_dst(CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pDst,
+ INT16 src_x, INT16 src_y,
+ INT16 xDst, INT16 yDst,
+ int nlist, GlyphListPtr list, GlyphPtr * glyphs,
+ BoxPtr extents)
+{
+ ScreenPtr screen = pDst->pDrawable->pScreen;
+ uxa_screen_t *uxa_screen = uxa_get_screen(screen);
+ PixmapPtr src_pixmap, dst_pixmap;
+ PicturePtr localSrc, glyph_atlas;
+ int x, y, n;
+ BoxRec box;
+
+ if (uxa_screen->info->check_composite_texture &&
+ uxa_screen->info->check_composite_texture(screen, pSrc)) {
+ if (pSrc->pDrawable) {
+ int src_off_x, src_off_y;
+
+ src_pixmap = uxa_get_offscreen_pixmap(pSrc->pDrawable, &src_off_x, &src_off_y);
+ if (src_pixmap == NULL)
+ return -1;
+
+ src_x += pSrc->pDrawable->x + src_off_x;
+ src_y += pSrc->pDrawable->y + src_off_y;
+ } else {
+ src_pixmap = NULL;
+ }
+ localSrc = pSrc;
+ } else {
+ int width, height;
+
+ if (extents == NULL) {
+ uxa_glyph_extents(nlist, list, glyphs, &box);
+ extents = &box;
+ }
+
+ width = extents->x2 - extents->x1;
+ height = extents->y2 - extents->y1;
+ if (width == 0 || height == 0)
+ return 0;
+
+ if (pSrc->pDrawable) {
+ int src_off_x, src_off_y;
+
+ src_off_x = extents->x1 - xDst;
+ src_off_y = extents->y1 - yDst;
+ localSrc = uxa_acquire_drawable(screen, pSrc,
+ src_x + src_off_x, src_y + src_off_y,
+ width, height,
+ &src_x, &src_y);
+ if (uxa_screen->info->check_composite_texture &&
+ !uxa_screen->info->check_composite_texture(screen, localSrc)) {
+ if (localSrc != pSrc)
+ FreePicture(localSrc, 0);
+ return -1;
+ }
+
+ src_pixmap = uxa_get_offscreen_pixmap(localSrc->pDrawable, &src_off_x, &src_off_y);
+ if (src_pixmap == NULL) {
+ if (localSrc != pSrc)
+ FreePicture(localSrc, 0);
+ return -1;
+ }
+
+ src_x += localSrc->pDrawable->x + src_off_x;
+ src_y += localSrc->pDrawable->y + src_off_y;
+ } else {
+ localSrc = uxa_acquire_pattern(screen, pSrc,
+ PICT_a8r8g8b8, x, y, width, height);
+ if (!localSrc)
+ return 1;
+
+ src_pixmap = uxa_get_drawable_pixmap(localSrc->pDrawable);
+ if (src_pixmap == NULL) {
+ FreePicture(localSrc, 0);
+ return -1;
+ }
+
+ src_x = src_y = 0;
+ }
+ }
+
+ dst_pixmap = uxa_get_offscreen_pixmap(pDst->pDrawable, &x, &y);
+ x += xDst + pDst->pDrawable->x - list->xOff;
+ y += yDst + pDst->pDrawable->y - list->yOff;
+
+ glyph_atlas = NULL;
+ while (nlist--) {
+ x += list->xOff;
+ y += list->yOff;
+ n = list->len;
+ while (n--) {
+ GlyphPtr glyph = *glyphs++;
+ PicturePtr this_atlas;
+ int mask_x, mask_y, nrect;
+ struct uxa_glyph *priv;
+ BoxPtr rects;
+
+ if (glyph->info.width == 0 || glyph->info.height == 0)
+ goto next_glyph;
+
+ priv = uxa_glyph_get_private(glyph);
+ if (priv != NULL) {
+ mask_x = priv->x;
+ mask_y = priv->y;
+ this_atlas = priv->cache->picture;
+ } else {
+ if (glyph_atlas) {
+ uxa_screen->info->done_composite(dst_pixmap);
+ glyph_atlas = NULL;
+ }
+ this_atlas = uxa_glyph_cache(screen, glyph, &mask_x, &mask_y);
+ if (this_atlas == NULL) {
+ /* no cache for this glyph */
+ this_atlas = GlyphPicture(glyph)[screen->myNum];
+ mask_x = mask_y = 0;
+ }
+ }
+
+ if (this_atlas != glyph_atlas) {
+ PixmapPtr mask_pixmap;
+
+ if (glyph_atlas)
+ uxa_screen->info->done_composite(dst_pixmap);
+
+ mask_pixmap =
+ uxa_get_drawable_pixmap(this_atlas->pDrawable);
+ assert (uxa_pixmap_is_offscreen(mask_pixmap));
+
+ if (!uxa_screen->info->prepare_composite(op,
+ localSrc, this_atlas, pDst,
+ src_pixmap, mask_pixmap, dst_pixmap))
+ return -1;
+
+ glyph_atlas = this_atlas;
+ }
+
+ rects = REGION_RECTS(pDst->pCompositeClip);
+ nrect = REGION_NUM_RECTS(pDst->pCompositeClip);
+ while (nrect--) {
+ int x1 = x - glyph->info.x, dx = 0;
+ int y1 = y - glyph->info.y, dy = 0;
+ int x2 = x1 + glyph->info.width;
+ int y2 = y1 + glyph->info.height;
+
+ if (rects->y1 >= y2)
+ break;
+
+ if (x1 < rects->x1)
+ dx = rects->x1 - x1, x1 = rects->x1;
+ if (x2 > rects->x2)
+ x2 = rects->x2;
+ if (y1 < rects->y1)
+ dy = rects->y1 - y1, y1 = rects->y1;
+ if (y2 > rects->y2)
+ y2 = rects->y2;
+
+ if (x1 < x2 && y1 < y2) {
+ uxa_screen->info->composite(dst_pixmap,
+ x1 + src_x, y1 + src_y,
+ dx + mask_x, dy + mask_y,
+ x1, y1,
+ x2 - x1, y2 - y1);
+ }
+ rects++;
+ }
+
+next_glyph:
+ x += glyph->info.xOff;
+ y += glyph->info.yOff;
+ }
+ list++;
+ }
+ if (glyph_atlas)
+ uxa_screen->info->done_composite(dst_pixmap);
+
+ if (localSrc != pSrc)
+ FreePicture(localSrc, 0);
+
+ return 0;
+}
+
+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);
+ }
+ }
+}
+
+static int
+uxa_glyphs_via_mask(CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pDst,
+ PictFormatPtr maskFormat,
+ INT16 xSrc, INT16 ySrc,
+ INT16 xDst, INT16 yDst,
+ int nlist, GlyphListPtr list, GlyphPtr * glyphs,
+ BoxPtr extents)
+{
+ ScreenPtr screen = pDst->pDrawable->pScreen;
+ uxa_screen_t *uxa_screen = uxa_get_screen(screen);
+ CARD32 component_alpha;
+ PixmapPtr pixmap;
+ PicturePtr glyph_atlas, mask;
+ int x, y, width, height;
+ int dst_off_x, dst_off_y;
+ int n, error;
+ BoxRec box;
+
+ if (!extents) {
+ uxa_glyph_extents(nlist, list, glyphs, &box);
+
+ if (box.x2 <= box.x1 || box.y2 <= box.y1)
+ return 0;
+
+ extents = &box;
+ dst_off_x = box.x1;
+ dst_off_y = box.y1;
+ } else {
+ dst_off_x = dst_off_y = 0;
+ }
+
+ width = extents->x2 - extents->x1;
+ height = extents->y2 - extents->y1;
+ x = -extents->x1;
+ y = -extents->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;
+
+ 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)
+ 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 src_x, src_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) {
+ src_x = priv->x;
+ src_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, &src_x, &src_y);
+ if (this_atlas == NULL) {
+ /* no cache for this glyph */
+ this_atlas = GlyphPicture(glyph)[screen->myNum];
+ src_x = src_y = 0;
+ }
+ }
+
+ if (this_atlas != glyph_atlas) {
+ PixmapPtr src_pixmap;
+
+ if (glyph_atlas)
+ uxa_screen->info->done_composite(pixmap);
+
+ src_pixmap =
+ uxa_get_drawable_pixmap(this_atlas->pDrawable);
+ assert (uxa_pixmap_is_offscreen(src_pixmap));
+
+ if (!uxa_screen->info->prepare_composite(PictOpAdd,
+ this_atlas, NULL, mask,
+ src_pixmap, NULL, pixmap))
+ return -1;
+
+ glyph_atlas = this_atlas;
+ }
+
+ uxa_screen->info->composite(pixmap,
+ src_x, src_y,
+ 0, 0,
+ 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(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);
+ int xDst = list->xOff, yDst = list->yOff;
+ BoxRec extents = { 0, 0, 0, 0 };
+ Bool have_extents = FALSE;
+ int width, height, ret;
+ PicturePtr localDst = pDst;
+
+ if (!uxa_screen->info->prepare_composite ||
+ uxa_screen->swappedOut ||
+ !uxa_drawable_is_offscreen(pDst->pDrawable) ||
+ pDst->alphaMap || pSrc->alphaMap) {
+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 &&
+ uxa_screen->info->check_composite_target &&
+ !uxa_screen->info->check_composite_target(uxa_get_drawable_pixmap(pDst->pDrawable))) {
+ int depth = pDst->pDrawable->depth;
+ PixmapPtr pixmap;
+ int x, y, error;
+ GCPtr gc;
+
+ pixmap = uxa_get_drawable_pixmap(pDst->pDrawable);
+ if (uxa_screen->info->check_copy &&
+ !uxa_screen->info->check_copy(pixmap, pixmap, GXcopy, FB_ALLONES))
+ goto fallback;
+
+ uxa_glyph_extents(nlist, list, glyphs, &extents);
+
+ /* clip against dst bounds */
+ if (extents.x1 < 0)
+ extents.x1 = 0;
+ if (extents.y1 < 0)
+ extents.y1 = 0;
+ if (extents.x2 > pDst->pDrawable->width)
+ extents.x2 = pDst->pDrawable->width;
+ if (extents.y2 > pDst->pDrawable->height)
+ extents.y2 = pDst->pDrawable->height;
+
+ if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1)
+ return;
+ width = extents.x2 - extents.x1;
+ height = extents.y2 - extents.y1;
+ x = -extents.x1;
+ y = -extents.y1;
+ have_extents = TRUE;
+
+ xDst += x;
+ yDst += y;
+
+ pixmap = screen->CreatePixmap(screen,
+ width, height, depth,
+ CREATE_PIXMAP_USAGE_SCRATCH);
+ if (!pixmap)
+ return;
+
+ gc = GetScratchGC(depth, screen);
+ if (!gc) {
+ screen->DestroyPixmap(pixmap);
+ return;
+ }
+
+ ValidateGC(&pixmap->drawable, gc);
+ gc->ops->CopyArea(pDst->pDrawable, &pixmap->drawable, gc,
+ extents.x1, extents.y1,
+ width, height,
+ 0, 0);
+ FreeScratchGC(gc);
+
+ localDst = CreatePicture(0, &pixmap->drawable,
+ PictureMatchFormat(screen, depth, pDst->format),
+ 0, 0, serverClient, &error);
+ screen->DestroyPixmap(pixmap);
+
+ if (!localDst)
+ return;
+
+ ValidatePicture(localDst);
+ }
+
+ if (maskFormat) {
+ ret = uxa_glyphs_via_mask(op,
+ pSrc, localDst, maskFormat,
+ xSrc, ySrc,
+ xDst, yDst,
+ nlist, list, glyphs,
+ have_extents ? &extents : NULL);
+ } else {
+ ret = uxa_glyphs_to_dst(op,
+ pSrc, localDst,
+ xSrc, ySrc,
+ xDst, yDst,
+ nlist, list, glyphs,
+ have_extents ? &extents : NULL);
+ }
+ if (ret) {
+ if (localDst != pDst)
+ FreePicture(localDst, 0);
+
+ goto fallback;
+ }
+
+ if (localDst != pDst) {
+ GCPtr gc;
+
+ gc = GetScratchGC(pDst->pDrawable->depth, screen);
+ if (gc) {
+ ValidateGC(pDst->pDrawable, gc);
+ gc->ops->CopyArea(localDst->pDrawable, pDst->pDrawable, gc,
+ 0, 0,
+ width, height,
+ extents.x1, extents.y1);
+ FreeScratchGC(gc);
+ }
+
+ FreePicture(localDst, 0);
}
}
diff --git a/uxa/uxa-priv.h b/uxa/uxa-priv.h
index c1f3688c..4b988f4e 100644
--- a/uxa/uxa-priv.h
+++ b/uxa/uxa-priv.h
@@ -41,14 +41,6 @@
#include <X11/X.h>
#define NEED_EVENTS
#include <X11/Xproto.h>
-#ifdef MITSHM
-#ifdef HAVE_XEXTPROTO_71
-#include <X11/extensions/shm.h>
-#else
-#define _XSHM_SERVER_
-#include <X11/extensions/shmstr.h>
-#endif
-#endif
#include "scrnintstr.h"
#include "pixmapstr.h"
#include "windowstr.h"
@@ -103,37 +95,13 @@ char uxa_drawable_location(DrawablePtr pDrawable);
#endif
typedef struct {
- unsigned char sha1[20];
-} uxa_cached_glyph_t;
-
-typedef struct {
- /* The identity of the cache, statically configured at initialization */
- unsigned int format;
- int glyphWidth;
- int glyphHeight;
-
- /* Size of cache; eventually this should be dynamically determined */
- int size;
-
- /* Hash table mapping from glyph sha1 to position in the glyph; we use
- * open addressing with a hash table size determined based on size and large
- * enough so that we always have a good amount of free space, so we can
- * use linear probing. (Linear probing is preferrable to double hashing
- * here because it allows us to easily remove entries.)
- */
- int *hashEntries;
- int hashSize;
-
- uxa_cached_glyph_t *glyphs;
- int glyphCount; /* Current number of glyphs */
-
PicturePtr picture; /* Where the glyphs of the cache are stored */
- int yOffset; /* y location within the picture where the cache starts */
- int columns; /* Number of columns the glyphs are layed out in */
- int evictionPosition; /* Next random position to evict a glyph */
+ GlyphPtr *glyphs;
+ uint16_t count;
+ uint16_t evict;
} uxa_glyph_cache_t;
-#define UXA_NUM_GLYPH_CACHES 4
+#define UXA_NUM_GLYPH_CACHE_FORMATS 2
typedef struct {
uint32_t color;
@@ -156,10 +124,12 @@ typedef struct {
BitmapToRegionProcPtr SavedBitmapToRegion;
#ifdef RENDER
CompositeProcPtr SavedComposite;
+ CompositeRectsProcPtr SavedCompositeRects;
TrianglesProcPtr SavedTriangles;
GlyphsProcPtr SavedGlyphs;
TrapezoidsProcPtr SavedTrapezoids;
AddTrapsProcPtr SavedAddTraps;
+ UnrealizeGlyphProcPtr SavedUnrealizeGlyph;
#endif
EnableDisableFBAccessProcPtr SavedEnableDisableFBAccess;
@@ -168,7 +138,7 @@ typedef struct {
unsigned disableFbCount;
unsigned offScreenCounter;
- uxa_glyph_cache_t glyphCaches[UXA_NUM_GLYPH_CACHES];
+ uxa_glyph_cache_t glyphCaches[UXA_NUM_GLYPH_CACHE_FORMATS];
PicturePtr solid_clear, solid_black, solid_white;
uxa_solid_cache_t solid_cache[UXA_NUM_SOLID_CACHE];
@@ -187,11 +157,19 @@ typedef struct {
(PixmapWidthPaddingInfo[d].padRoundUp+1)))
#endif
+#if HAS_DEVPRIVATEKEYREC
+extern DevPrivateKeyRec uxa_screen_index;
+#else
extern int uxa_screen_index;
+#endif
+
static inline uxa_screen_t *uxa_get_screen(ScreenPtr screen)
{
- return (uxa_screen_t *) dixLookupPrivate(&screen->devPrivates,
- &uxa_screen_index);
+#if HAS_DEVPRIVATEKEYREC
+ return dixGetPrivate(&screen->devPrivates, &uxa_screen_index);
+#else
+ return dixLookupPrivate(&screen->devPrivates, &uxa_screen_index);
+#endif
}
/** Align an offset to an arbitrary alignment */
@@ -307,11 +285,6 @@ Bool
uxa_fill_region_tiled(DrawablePtr pDrawable, RegionPtr pRegion, PixmapPtr pTile,
DDXPointPtr pPatOrg, CARD32 planemask, CARD32 alu);
-void
-uxa_shm_put_image(DrawablePtr pDrawable, 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);
-
void uxa_paint_window(WindowPtr pWin, RegionPtr pRegion, int what);
void
@@ -320,24 +293,6 @@ uxa_get_image(DrawablePtr pDrawable, int x, int y, int w, int h,
extern const GCOps uxa_ops;
-#ifdef MITSHM
-/* XXX these come from shmint.h, which isn't exported by the server */
-
-#ifdef HAVE_XEXTPROTO_71
-#include "shmint.h"
-#else
-
-void ShmRegisterFuncs(ScreenPtr pScreen, ShmFuncsPtr funcs);
-
-void ShmSetPixmapFormat(ScreenPtr pScreen, int format);
-
-void fbShmPutImage(XSHM_PUT_IMAGE_ARGS);
-#endif
-
-extern ShmFuncs uxa_shm_funcs;
-
-#endif
-
#ifdef RENDER
/* XXX these are in fbpict.h, which is not installed */
@@ -417,6 +372,13 @@ uxa_composite_rects(CARD8 op,
PicturePtr pDst, int nrect, uxa_composite_rect_t * rects);
void
+uxa_solid_rects (CARD8 op,
+ PicturePtr dst,
+ xRenderColor *color,
+ int num_rects,
+ xRectangle *rects);
+
+void
uxa_trapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
int ntrap, xTrapezoid * traps);
@@ -426,8 +388,33 @@ uxa_triangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
int ntri, xTriangle * tris);
+PicturePtr
+uxa_acquire_solid(ScreenPtr screen, SourcePict *source);
+
+PicturePtr
+uxa_acquire_drawable(ScreenPtr pScreen,
+ PicturePtr pSrc,
+ INT16 x, INT16 y,
+ CARD16 width, CARD16 height,
+ INT16 * out_x, INT16 * out_y);
+
+PicturePtr
+uxa_acquire_pattern(ScreenPtr pScreen,
+ PicturePtr pSrc,
+ pixman_format_code_t format,
+ INT16 x, INT16 y,
+ CARD16 width, CARD16 height);
+
+Bool
+uxa_get_rgba_from_pixel(CARD32 pixel,
+ CARD16 * red,
+ CARD16 * green,
+ CARD16 * blue,
+ CARD16 * alpha,
+ CARD32 format);
+
/* uxa_glyph.c */
-void uxa_glyphs_init(ScreenPtr pScreen);
+Bool uxa_glyphs_init(ScreenPtr pScreen);
void uxa_glyphs_fini(ScreenPtr pScreen);
@@ -439,4 +426,8 @@ uxa_glyphs(CARD8 op,
INT16 xSrc,
INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr * glyphs);
+void
+uxa_glyph_unrealize(ScreenPtr pScreen,
+ GlyphPtr pGlyph);
+
#endif /* UXAPRIV_H */
diff --git a/uxa/uxa-render.c b/uxa/uxa-render.c
index 30934d0d..056b60a4 100644
--- a/uxa/uxa-render.c
+++ b/uxa/uxa-render.c
@@ -85,29 +85,88 @@ static void uxa_composite_fallback_pict_desc(PicturePtr pict, char *string,
pict->alphaMap ? " with alpha map" :"");
}
+static const char *
+op_to_string(CARD8 op)
+{
+ switch (op) {
+#define C(x) case PictOp##x: return #x
+ C(Clear);
+ C(Src);
+ C(Dst);
+ C(Over);
+ C(OverReverse);
+ C(In);
+ C(InReverse);
+ C(Out);
+ C(OutReverse);
+ C(Atop);
+ C(AtopReverse);
+ C(Xor);
+ C(Add);
+ C(Saturate);
+
+ /*
+ * Operators only available in version 0.2
+ */
+ C(DisjointClear);
+ C(DisjointSrc);
+ C(DisjointDst);
+ C(DisjointOver);
+ C(DisjointOverReverse);
+ C(DisjointIn);
+ C(DisjointInReverse);
+ C(DisjointOut);
+ C(DisjointOutReverse);
+ C(DisjointAtop);
+ C(DisjointAtopReverse);
+ C(DisjointXor);
+
+ C(ConjointClear);
+ C(ConjointSrc);
+ C(ConjointDst);
+ C(ConjointOver);
+ C(ConjointOverReverse);
+ C(ConjointIn);
+ C(ConjointInReverse);
+ C(ConjointOut);
+ C(ConjointOutReverse);
+ C(ConjointAtop);
+ C(ConjointAtopReverse);
+ C(ConjointXor);
+
+ /*
+ * Operators only available in version 0.11
+ */
+ C(Multiply);
+ C(Screen);
+ C(Overlay);
+ C(Darken);
+ C(Lighten);
+ C(ColorDodge);
+ C(ColorBurn);
+ C(HardLight);
+ C(SoftLight);
+ C(Difference);
+ C(Exclusion);
+ C(HSLHue);
+ C(HSLSaturation);
+ C(HSLColor);
+ C(HSLLuminosity);
+ default: return "garbage";
+#undef C
+ }
+}
+
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 sop[20];
char srcdesc[40], maskdesc[40], dstdesc[40];
if (! uxa_screen->fallback_debug)
return;
- switch (op) {
- case PictOpSrc:
- sprintf(sop, "Src");
- break;
- case PictOpOver:
- sprintf(sop, "Over");
- break;
- default:
- sprintf(sop, "0x%x", (int)op);
- break;
- }
-
uxa_composite_fallback_pict_desc(pSrc, srcdesc, 40);
uxa_composite_fallback_pict_desc(pMask, maskdesc, 40);
uxa_composite_fallback_pict_desc(pDst, dstdesc, 40);
@@ -118,7 +177,7 @@ uxa_print_composite_fallback(const char *func, CARD8 op,
" mask %s, \n"
" dst %s, \n"
" screen %s\n",
- func, sop, srcdesc, maskdesc, dstdesc,
+ func, op_to_string (op), srcdesc, maskdesc, dstdesc,
uxa_screen->swappedOut ? "swapped out" : "normal");
}
@@ -182,7 +241,7 @@ uxa_get_pixel_from_rgba(CARD32 * pixel,
return TRUE;
}
-static Bool
+Bool
uxa_get_rgba_from_pixel(CARD32 pixel,
CARD16 * red,
CARD16 * green,
@@ -290,7 +349,12 @@ uxa_try_driver_solid_fill(PicturePtr pSrc,
PixmapPtr pSrcPix = NULL, pDstPix;
CARD32 pixel;
- pDstPix = uxa_get_drawable_pixmap(pDst->pDrawable);
+ if (uxa_screen->info->check_solid && !uxa_screen->info->check_solid(pDst->pDrawable, GXcopy, FB_ALLONES))
+ return -1;
+
+ pDstPix = uxa_get_offscreen_pixmap(pDst->pDrawable, &dst_off_x, &dst_off_y);
+ if (!pDstPix)
+ return -1;
xDst += pDst->pDrawable->x;
yDst += pDst->pDrawable->y;
@@ -306,16 +370,6 @@ uxa_try_driver_solid_fill(PicturePtr pSrc,
width, height))
return 1;
- uxa_get_drawable_deltas(pDst->pDrawable, pDstPix, &dst_off_x,
- &dst_off_y);
-
- REGION_TRANSLATE(pScreen, &region, dst_off_x, dst_off_y);
-
- if (!uxa_pixmap_is_offscreen(pDstPix)) {
- REGION_UNINIT(pDst->pDrawable->pScreen, &region);
- return 0;
- }
-
if (pSrcPix) {
if (! uxa_get_color_for_pixmap (pSrcPix, pSrc->format, pDst->format, &pixel)) {
REGION_UNINIT(pDst->pDrawable->pScreen, &region);
@@ -334,11 +388,13 @@ uxa_try_driver_solid_fill(PicturePtr pSrc,
}
if (!(*uxa_screen->info->prepare_solid)
- (pDstPix, GXcopy, 0xffffffff, pixel)) {
+ (pDstPix, GXcopy, FB_ALLONES, pixel)) {
REGION_UNINIT(pDst->pDrawable->pScreen, &region);
return -1;
}
+ REGION_TRANSLATE(pScreen, &region, dst_off_x, dst_off_y);
+
nbox = REGION_NUM_RECTS(&region);
pbox = REGION_RECTS(&region);
@@ -391,74 +447,84 @@ uxa_picture_for_pixman_format(ScreenPtr pScreen,
}
static PicturePtr
-uxa_picture_from_pixman_image(ScreenPtr pScreen,
+uxa_picture_from_pixman_image(ScreenPtr screen,
pixman_image_t * image,
pixman_format_code_t format)
{
- PicturePtr pPicture;
- PixmapPtr pPixmap;
+ uxa_screen_t *uxa_screen = uxa_get_screen(screen);
+ PicturePtr picture;
+ PixmapPtr pixmap;
int width, height;
width = pixman_image_get_width(image);
height = pixman_image_get_height(image);
- pPicture = uxa_picture_for_pixman_format(pScreen, format,
- width, height);
- if (!pPicture)
+ picture = uxa_picture_for_pixman_format(screen, format,
+ width, height);
+ if (!picture)
return 0;
- pPixmap = GetScratchPixmapHeader(pScreen, width, height,
- PIXMAN_FORMAT_DEPTH(format),
- PIXMAN_FORMAT_BPP(format),
- pixman_image_get_stride(image),
- pixman_image_get_data(image));
- if (!pPixmap) {
- FreePicture(pPicture, 0);
+ if (uxa_screen->info->put_image &&
+ ((picture->pDrawable->depth << 24) | picture->format) == format &&
+ uxa_screen->info->put_image((PixmapPtr)picture->pDrawable,
+ 0, 0,
+ width, height,
+ (char *)pixman_image_get_data(image),
+ pixman_image_get_stride(image)))
+ return picture;
+
+ pixmap = GetScratchPixmapHeader(screen, width, height,
+ PIXMAN_FORMAT_DEPTH(format),
+ PIXMAN_FORMAT_BPP(format),
+ pixman_image_get_stride(image),
+ pixman_image_get_data(image));
+ if (!pixmap) {
+ FreePicture(picture, 0);
return 0;
}
- if (((pPicture->pDrawable->depth << 24) | pPicture->format) == format) {
- GCPtr pGC;
+ if (((picture->pDrawable->depth << 24) | picture->format) == format) {
+ GCPtr gc;
- pGC = GetScratchGC(PIXMAN_FORMAT_DEPTH(format), pScreen);
- if (!pGC) {
- FreeScratchPixmapHeader(pPixmap);
- FreePicture(pPicture, 0);
- return 0;
- }
- ValidateGC(pPicture->pDrawable, pGC);
+ gc = GetScratchGC(PIXMAN_FORMAT_DEPTH(format), screen);
+ if (!gc) {
+ FreeScratchPixmapHeader(pixmap);
+ FreePicture(picture, 0);
+ return 0;
+ }
+ ValidateGC(picture->pDrawable, gc);
- (*pGC->ops->CopyArea) (&pPixmap->drawable, pPicture->pDrawable,
- pGC, 0, 0, width, height, 0, 0);
+ (*gc->ops->CopyArea) (&pixmap->drawable, picture->pDrawable,
+ gc, 0, 0, width, height, 0, 0);
- FreeScratchGC(pGC);
+ FreeScratchGC(gc);
} else {
- PicturePtr pSrc;
- int error;
-
- pSrc = CreatePicture(0, &pPixmap->drawable,
- PictureMatchFormat(pScreen,
- PIXMAN_FORMAT_DEPTH(format),
- format),
- 0, 0, serverClient, &error);
- if (!pSrc) {
- FreeScratchPixmapHeader(pPixmap);
- FreePicture(pPicture, 0);
- return 0;
- }
- ValidatePicture(pSrc);
+ PicturePtr src;
+ int error;
+
+ src = CreatePicture(0, &pixmap->drawable,
+ PictureMatchFormat(screen,
+ PIXMAN_FORMAT_DEPTH(format),
+ format),
+ 0, 0, serverClient, &error);
+ if (!src) {
+ FreeScratchPixmapHeader(pixmap);
+ FreePicture(picture, 0);
+ return 0;
+ }
+ ValidatePicture(src);
- if (uxa_prepare_access(pPicture->pDrawable, UXA_ACCESS_RW)) {
- fbComposite(PictOpSrc, pSrc, NULL, pPicture,
- 0, 0, 0, 0, 0, 0, width, height);
- uxa_finish_access(pPicture->pDrawable);
- }
+ if (uxa_prepare_access(picture->pDrawable, UXA_ACCESS_RW)) {
+ fbComposite(PictOpSrc, src, NULL, picture,
+ 0, 0, 0, 0, 0, 0, width, height);
+ uxa_finish_access(picture->pDrawable);
+ }
- FreePicture(pSrc, 0);
+ FreePicture(src, 0);
}
- FreeScratchPixmapHeader(pPixmap);
+ FreeScratchPixmapHeader(pixmap);
- return pPicture;
+ return picture;
}
static PicturePtr
@@ -490,6 +556,21 @@ uxa_create_solid(ScreenPtr screen, uint32_t color)
}
static PicturePtr
+uxa_solid_clear(ScreenPtr screen)
+{
+ uxa_screen_t *uxa_screen = uxa_get_screen(screen);
+ PicturePtr picture;
+
+ if (!uxa_screen->solid_clear) {
+ uxa_screen->solid_clear = uxa_create_solid(screen, 0);
+ if (!uxa_screen->solid_clear)
+ return 0;
+ }
+ picture = uxa_screen->solid_clear;
+ return picture;
+}
+
+PicturePtr
uxa_acquire_solid(ScreenPtr screen, SourcePict *source)
{
uxa_screen_t *uxa_screen = uxa_get_screen(screen);
@@ -498,12 +579,10 @@ uxa_acquire_solid(ScreenPtr screen, SourcePict *source)
int i;
if ((solid->color >> 24) == 0) {
- if (!uxa_screen->solid_clear) {
- uxa_screen->solid_clear = uxa_create_solid(screen, 0);
- if (!uxa_screen->solid_clear)
- return 0;
- }
- picture = uxa_screen->solid_clear;
+ picture = uxa_solid_clear(screen);
+ if (!picture)
+ return 0;
+
goto DONE;
} else if (solid->color == 0xff000000) {
if (!uxa_screen->solid_black) {
@@ -548,7 +627,7 @@ DONE:
return picture;
}
-static PicturePtr
+PicturePtr
uxa_acquire_pattern(ScreenPtr pScreen,
PicturePtr pSrc,
pixman_format_code_t format,
@@ -577,158 +656,398 @@ uxa_acquire_pattern(ScreenPtr pScreen,
}
}
-static PicturePtr
-uxa_acquire_source(ScreenPtr pScreen,
- PicturePtr pPict,
- INT16 x, INT16 y,
- CARD16 width, CARD16 height, INT16 * out_x, INT16 * out_y)
+static Bool
+transform_is_integer_translation(PictTransformPtr t, int *tx, int *ty)
{
- if (pPict->pDrawable) {
- *out_x = x + pPict->pDrawable->x;
- *out_y = y + pPict->pDrawable->y;
- return pPict;
+ if (t == NULL) {
+ *tx = *ty = 0;
+ return TRUE;
}
- *out_x = 0;
- *out_y = 0;
- return uxa_acquire_pattern(pScreen, pPict,
- PICT_a8r8g8b8, x, y, width, height);
+ if (t->matrix[0][0] != IntToxFixed(1) ||
+ t->matrix[0][1] != 0 ||
+ t->matrix[1][0] != 0 ||
+ t->matrix[1][1] != IntToxFixed(1) ||
+ t->matrix[2][0] != 0 ||
+ t->matrix[2][1] != 0 ||
+ t->matrix[2][2] != IntToxFixed(1))
+ return FALSE;
+
+ if (xFixedFrac(t->matrix[0][2]) != 0 ||
+ xFixedFrac(t->matrix[1][2]) != 0)
+ return FALSE;
+
+ *tx = xFixedToInt(t->matrix[0][2]);
+ *ty = xFixedToInt(t->matrix[1][2]);
+ return TRUE;
}
static PicturePtr
-uxa_acquire_mask(ScreenPtr pScreen,
- PicturePtr pPict,
- INT16 x, INT16 y,
- INT16 width, INT16 height, INT16 * out_x, INT16 * out_y)
+uxa_render_picture(ScreenPtr screen,
+ PicturePtr src,
+ pixman_format_code_t format,
+ INT16 x, INT16 y,
+ CARD16 width, CARD16 height)
{
- if (pPict->pDrawable) {
- *out_x = x + pPict->pDrawable->x;
- *out_y = y + pPict->pDrawable->y;
- return pPict;
+ PicturePtr picture;
+ int ret = 0;
+
+ /* XXX we need a mechanism for the card to choose the fallback format */
+
+ /* force alpha channel in case source does not entirely cover the extents */
+ if (PIXMAN_FORMAT_A(format) == 0)
+ format = PIXMAN_a8r8g8b8; /* available on all hardware */
+
+ picture = uxa_picture_for_pixman_format(screen, format, width, height);
+ if (!picture)
+ return 0;
+
+ if (uxa_prepare_access(picture->pDrawable, UXA_ACCESS_RW)) {
+ if (uxa_prepare_access(src->pDrawable, UXA_ACCESS_RO)) {
+ ret = 1;
+ fbComposite(PictOpSrc, src, NULL, picture,
+ x, y, 0, 0, 0, 0, width, height);
+ uxa_finish_access(src->pDrawable);
+ }
+ uxa_finish_access(picture->pDrawable);
}
- *out_x = 0;
- *out_y = 0;
- return uxa_acquire_pattern(pScreen, pPict,
- PICT_a8, x, y, width, height);
+ if (!ret) {
+ FreePicture(picture, 0);
+ return 0;
+ }
+
+ return picture;
}
static int
-uxa_try_driver_composite_rects(CARD8 op,
- PicturePtr pSrc,
- PicturePtr pDst,
- int nrect, uxa_composite_rect_t * rects)
+drawable_contains (DrawablePtr drawable, int x, int y, int w, int h)
{
- uxa_screen_t *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen);
- int src_off_x, src_off_y, dst_off_x, dst_off_y;
- PixmapPtr pSrcPix, pDstPix;
+ if (x < 0 || y < 0)
+ return FALSE;
- if (!uxa_screen->info->prepare_composite || uxa_screen->swappedOut)
- return -1;
+ if (x + w > drawable->width)
+ return FALSE;
- if (uxa_screen->info->check_composite &&
- !(*uxa_screen->info->check_composite) (op, pSrc, NULL, pDst)) {
- return -1;
+ if (y + h > drawable->height)
+ return FALSE;
+
+ return TRUE;
+}
+
+PicturePtr
+uxa_acquire_drawable(ScreenPtr pScreen,
+ PicturePtr pSrc,
+ INT16 x, INT16 y,
+ CARD16 width, CARD16 height,
+ INT16 * out_x, INT16 * out_y)
+{
+ PixmapPtr pPixmap;
+ PicturePtr pDst;
+ int depth, error;
+ int tx, ty;
+ GCPtr pGC;
+
+ depth = pSrc->pDrawable->depth;
+ if (!transform_is_integer_translation(pSrc->transform, &tx, &ty) ||
+ !drawable_contains(pSrc->pDrawable, x + tx, y + ty, width, height) ||
+ depth == 1 ||
+ pSrc->filter == PictFilterConvolution) {
+ /* XXX extract the sample extents and do the transformation on the GPU */
+ pDst = uxa_render_picture(pScreen, pSrc,
+ pSrc->format | (BitsPerPixel(pSrc->pDrawable->depth) << 24),
+ x, y, width, height);
+
+ goto done;
+ } else {
+ if (width == pSrc->pDrawable->width && height == pSrc->pDrawable->height) {
+ *out_x = x + pSrc->pDrawable->x;
+ *out_y = y + pSrc->pDrawable->y;
+ return pSrc;
+ }
}
- pDstPix =
- uxa_get_offscreen_pixmap(pDst->pDrawable, &dst_off_x, &dst_off_y);
- if (!pDstPix)
+ pPixmap = pScreen->CreatePixmap(pScreen,
+ width, height, depth,
+ CREATE_PIXMAP_USAGE_SCRATCH);
+ if (!pPixmap)
return 0;
- pSrcPix =
- uxa_get_offscreen_pixmap(pSrc->pDrawable, &src_off_x, &src_off_y);
- if (!pSrcPix)
+ /* Skip the copy if the result remains in memory and not a bo */
+ if (!uxa_pixmap_is_offscreen(pPixmap)) {
+ pScreen->DestroyPixmap(pPixmap);
return 0;
+ }
- if (!(*uxa_screen->info->prepare_composite)
- (op, pSrc, NULL, pDst, pSrcPix, NULL, pDstPix))
- return -1;
+ pGC = GetScratchGC(depth, pScreen);
+ if (!pGC) {
+ pScreen->DestroyPixmap(pPixmap);
+ return 0;
+ }
+
+ ValidateGC(&pPixmap->drawable, pGC);
+ pGC->ops->CopyArea(pSrc->pDrawable, &pPixmap->drawable, pGC,
+ x + tx, y + ty, width, height, 0, 0);
+ FreeScratchGC(pGC);
+
+ pDst = CreatePicture(0, &pPixmap->drawable,
+ PictureMatchFormat(pScreen, depth, pSrc->format),
+ 0, 0, serverClient, &error);
+ pScreen->DestroyPixmap(pPixmap);
+ ValidatePicture(pDst);
+
+done:
+ pDst->componentAlpha = pSrc->componentAlpha;
+ *out_x = 0;
+ *out_y = 0;
+ return pDst;
+}
- while (nrect--) {
- INT16 xDst = rects->xDst + pDst->pDrawable->x;
- INT16 yDst = rects->yDst + pDst->pDrawable->y;
- INT16 xSrc = rects->xSrc + pSrc->pDrawable->x;
- INT16 ySrc = rects->ySrc + pSrc->pDrawable->y;
-
- RegionRec region;
- BoxPtr pbox;
- int nbox;
-
- if (!miComputeCompositeRegion(&region, pSrc, NULL, pDst,
- xSrc, ySrc, 0, 0, xDst, yDst,
- rects->width, rects->height))
- goto next_rect;
-
- REGION_TRANSLATE(pScreen, &region, dst_off_x, dst_off_y);
-
- nbox = REGION_NUM_RECTS(&region);
- pbox = REGION_RECTS(&region);
-
- xSrc = xSrc + src_off_x - xDst - dst_off_x;
- ySrc = ySrc + src_off_y - yDst - dst_off_y;
-
- while (nbox--) {
- (*uxa_screen->info->composite) (pDstPix,
- pbox->x1 + xSrc,
- pbox->y1 + ySrc,
- 0, 0,
- pbox->x1,
- pbox->y1,
- pbox->x2 - pbox->x1,
- pbox->y2 - pbox->y1);
- pbox++;
+static PicturePtr
+uxa_acquire_picture(ScreenPtr screen,
+ PicturePtr src,
+ pixman_format_code_t format,
+ INT16 x, INT16 y,
+ CARD16 width, CARD16 height,
+ INT16 * out_x, INT16 * out_y)
+{
+ uxa_screen_t *uxa_screen = uxa_get_screen(screen);
+
+ if (uxa_screen->info->check_composite_texture &&
+ uxa_screen->info->check_composite_texture(screen, src)) {
+ if (src->pDrawable) {
+ *out_x = x + src->pDrawable->x;
+ *out_y = y + src->pDrawable->y;
+ } else {
+ *out_x = x;
+ *out_y = y;
}
+ return src;
+ }
-next_rect:
- REGION_UNINIT(pDst->pDrawable->pScreen, &region);
+ if (src->pDrawable) {
+ PicturePtr dst;
- rects++;
+ dst = uxa_acquire_drawable(screen, src,
+ x, y, width, height,
+ out_x, out_y);
+ if (!dst)
+ return 0;
+
+ if (uxa_screen->info->check_composite_texture &&
+ !uxa_screen->info->check_composite_texture(screen, dst)) {
+ if (dst != src)
+ FreePicture(dst, 0);
+ return 0;
+ }
+
+ return dst;
}
- (*uxa_screen->info->done_composite) (pDstPix);
- return 1;
+ *out_x = 0;
+ *out_y = 0;
+ return uxa_acquire_pattern(screen, src,
+ format, x, y, width, height);
+}
+
+static PicturePtr
+uxa_acquire_source(ScreenPtr screen,
+ PicturePtr pict,
+ INT16 x, INT16 y,
+ CARD16 width, CARD16 height,
+ INT16 * out_x, INT16 * out_y)
+{
+ return uxa_acquire_picture (screen, pict,
+ PICT_a8r8g8b8,
+ x, y,
+ width, height,
+ out_x, out_y);
+}
+
+static PicturePtr
+uxa_acquire_mask(ScreenPtr screen,
+ PicturePtr pict,
+ INT16 x, INT16 y,
+ INT16 width, INT16 height,
+ INT16 * out_x, INT16 * out_y)
+{
+ return uxa_acquire_picture (screen, pict,
+ PICT_a8,
+ x, y,
+ width, height,
+ out_x, out_y);
+}
+
+static Bool
+_pixman_region_init_rectangles(pixman_region16_t *region,
+ int num_rects,
+ xRectangle *rects,
+ int tx, int ty)
+{
+ pixman_box16_t stack_boxes[64], *boxes = stack_boxes;
+ pixman_bool_t ret;
+ int i;
+
+ if (num_rects > sizeof(stack_boxes) / sizeof(stack_boxes[0])) {
+ boxes = malloc(sizeof(pixman_box16_t) * num_rects);
+ if (boxes == NULL)
+ return FALSE;
+ }
+
+ for (i = 0; i < num_rects; i++) {
+ boxes[i].x1 = rects[i].x + tx;
+ boxes[i].y1 = rects[i].y + ty;
+ boxes[i].x2 = rects[i].x + tx + rects[i].width;
+ boxes[i].y2 = rects[i].y + ty + rects[i].height;
+ }
+
+ ret = pixman_region_init_rects(region, boxes, num_rects);
+
+ if (boxes != stack_boxes)
+ free(boxes);
+
+ return ret;
}
-/**
- * Copy a number of rectangles from source to destination in a single
- * operation. This is specialized for building a glyph mask: we don'y
- * have a mask argument because we don't need it for that, and we
- * don't have he special-case fallbacks found in uxa_composite() - if the
- * driver can support it, we use the driver functionality, otherwise we
- * fallback straight to software.
- */
void
-uxa_composite_rects(CARD8 op,
- PicturePtr pSrc,
- PicturePtr pDst, int nrect, uxa_composite_rect_t * rects)
+uxa_solid_rects (CARD8 op,
+ PicturePtr dst,
+ xRenderColor *color,
+ int num_rects,
+ xRectangle *rects)
{
- int n;
- uxa_composite_rect_t *r;
+ ScreenPtr screen = dst->pDrawable->pScreen;
+ uxa_screen_t *uxa_screen = uxa_get_screen(screen);
+ PixmapPtr dst_pixmap, src_pixmap = NULL;
+ pixman_region16_t region;
+ pixman_box16_t *boxes, *extents;
+ PicturePtr src;
+ int dst_x, dst_y;
+ int num_boxes;
+
+ if (!pixman_region_not_empty(dst->pCompositeClip))
+ return;
- /************************************************************/
+ if (dst->alphaMap)
+ goto fallback;
- ValidatePicture(pSrc);
- ValidatePicture(pDst);
+ dst_pixmap = uxa_get_offscreen_pixmap(dst->pDrawable, &dst_x, &dst_y);
+ if (!dst_pixmap)
+ goto fallback;
+
+ if (!_pixman_region_init_rectangles(&region,
+ num_rects, rects,
+ dst->pDrawable->x, dst->pDrawable->y))
+ goto fallback;
+
+ if (!pixman_region_intersect(&region, &region, dst->pCompositeClip)) {
+ pixman_region_fini(&region);
+ return;
+ }
+
+ /* XXX xserver-1.8: CompositeRects is not tracked by Damage, so we must
+ * manually append the damaged regions ourselves.
+ */
+ DamageRegionAppend(dst->pDrawable, &region);
+
+ pixman_region_translate(&region, dst_x, dst_y);
+ boxes = pixman_region_rectangles(&region, &num_boxes);
+ extents = pixman_region_extents (&region);
+
+ if (op == PictOpClear)
+ color->red = color->green = color->blue = color->alpha = 0;
+ if (color->alpha >= 0xff00 && op == PictOpOver) {
+ color->alpha = 0xffff;
+ op = PictOpSrc;
+ }
+
+ /* Using GEM, the relocation costs outweigh the advantages of the blitter */
+ if (num_boxes == 1 && (op == PictOpSrc || op == PictOpClear)) {
+ CARD32 pixel;
+
+try_solid:
+ if (uxa_screen->info->check_solid &&
+ !uxa_screen->info->check_solid(&dst_pixmap->drawable, GXcopy, FB_ALLONES))
+ goto err_region;
+
+ if (!uxa_get_pixel_from_rgba(&pixel,
+ color->red,
+ color->green,
+ color->blue,
+ color->alpha,
+ dst->format))
+ goto err_region;
+
+ if (!uxa_screen->info->prepare_solid(dst_pixmap, GXcopy, FB_ALLONES, pixel))
+ goto err_region;
+
+ while (num_boxes--) {
+ uxa_screen->info->solid(dst_pixmap,
+ boxes->x1, boxes->y1,
+ boxes->x2, boxes->y2);
+ boxes++;
+ }
+
+ uxa_screen->info->done_solid(dst_pixmap);
+ } else {
+ int error;
+
+ src = CreateSolidPicture(0, color, &error);
+ if (!src)
+ goto err_region;
+
+ if (!uxa_screen->info->check_composite(op, src, NULL, dst,
+ extents->x2 - extents->x1,
+ extents->y2 - extents->y1)) {
+ if (op == PictOpSrc || op == PictOpClear) {
+ FreePicture(src, 0);
+ goto try_solid;
+ }
+
+ goto err_src;
+ }
- if (uxa_try_driver_composite_rects(op, pSrc, pDst, nrect, rects) != 1) {
- uxa_print_composite_fallback("uxa_composite_rects",
- op, pSrc, NULL, pDst);
-
- n = nrect;
- r = rects;
- while (n--) {
- uxa_check_composite(op, pSrc, NULL, pDst,
- r->xSrc, r->ySrc,
- 0, 0,
- r->xDst, r->yDst,
- r->width, r->height);
- r++;
+ if (!uxa_screen->info->check_composite_texture ||
+ !uxa_screen->info->check_composite_texture(screen, src)) {
+ PicturePtr solid;
+ int src_off_x, src_off_y;
+
+ solid = uxa_acquire_solid(screen, src->pSourcePict);
+ FreePicture(src, 0);
+
+ src = solid;
+ src_pixmap = uxa_get_offscreen_pixmap(src->pDrawable,
+ &src_off_x, &src_off_y);
+ if (!src_pixmap)
+ goto err_src;
}
+
+ if (!uxa_screen->info->prepare_composite(op, src, NULL, dst, src_pixmap, NULL, dst_pixmap))
+ goto err_src;
+
+ while (num_boxes--) {
+ uxa_screen->info->composite(dst_pixmap,
+ 0, 0, 0, 0,
+ boxes->x1,
+ boxes->y1,
+ boxes->x2 - boxes->x1,
+ boxes->y2 - boxes->y1);
+ boxes++;
+ }
+
+ uxa_screen->info->done_composite(dst_pixmap);
+ FreePicture(src, 0);
}
- /************************************************************/
+ pixman_region_fini(&region);
+ return;
+err_src:
+ FreePicture(src, 0);
+err_region:
+ pixman_region_fini(&region);
+fallback:
+ uxa_screen->SavedCompositeRects(op, dst, color, num_rects, rects);
}
static int
@@ -736,130 +1055,217 @@ uxa_try_driver_composite(CARD8 op,
PicturePtr pSrc,
PicturePtr pMask,
PicturePtr pDst,
- INT16 xSrc,
- INT16 ySrc,
- INT16 xMask,
- INT16 yMask,
- INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
+ INT16 xSrc, INT16 ySrc,
+ INT16 xMask, INT16 yMask,
+ INT16 xDst, INT16 yDst,
+ CARD16 width, CARD16 height)
{
- uxa_screen_t *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen);
+ ScreenPtr screen = pDst->pDrawable->pScreen;
+ uxa_screen_t *uxa_screen = uxa_get_screen(screen);
RegionRec region;
BoxPtr pbox;
int nbox;
+ int xDst_copy, yDst_copy;
int src_off_x, src_off_y, mask_off_x, mask_off_y, dst_off_x, dst_off_y;
PixmapPtr pSrcPix, pMaskPix = NULL, pDstPix;
PicturePtr localSrc, localMask = NULL;
+ PicturePtr localDst = pDst;
- xDst += pDst->pDrawable->x;
- yDst += pDst->pDrawable->y;
+ if (uxa_screen->info->check_composite &&
+ !(*uxa_screen->info->check_composite) (op, pSrc, pMask, pDst, width, height))
+ return -1;
+
+ if (uxa_screen->info->check_composite_target &&
+ !uxa_screen->info->check_composite_target(uxa_get_drawable_pixmap(pDst->pDrawable))) {
+ int depth = pDst->pDrawable->depth;
+ PixmapPtr pixmap;
+ int error;
+ GCPtr gc;
+
+ pixmap = uxa_get_drawable_pixmap(pDst->pDrawable);
+ if (uxa_screen->info->check_copy &&
+ !uxa_screen->info->check_copy(pixmap, pixmap, GXcopy, FB_ALLONES))
+ return -1;
+
+ pixmap = screen->CreatePixmap(screen,
+ width, height, depth,
+ CREATE_PIXMAP_USAGE_SCRATCH);
+ if (!pixmap)
+ return 0;
+
+ gc = GetScratchGC(depth, screen);
+ if (!gc) {
+ screen->DestroyPixmap(pixmap);
+ return 0;
+ }
+
+ ValidateGC(&pixmap->drawable, gc);
+ gc->ops->CopyArea(pDst->pDrawable, &pixmap->drawable, gc,
+ xDst, yDst, width, height, 0, 0);
+ FreeScratchGC(gc);
- localSrc = uxa_acquire_source(pDst->pDrawable->pScreen,
- pSrc, xSrc, ySrc, width, height,
+ xDst_copy = xDst; xDst = 0;
+ yDst_copy = yDst; yDst = 0;
+
+ localDst = CreatePicture(0, &pixmap->drawable,
+ PictureMatchFormat(screen, depth, pDst->format),
+ 0, 0, serverClient, &error);
+ screen->DestroyPixmap(pixmap);
+
+ if (!localDst)
+ return 0;
+
+ ValidatePicture(localDst);
+ }
+
+ pDstPix =
+ uxa_get_offscreen_pixmap(localDst->pDrawable, &dst_off_x, &dst_off_y);
+ if (!pDstPix) {
+ if (localDst != pDst)
+ FreePicture(localDst, 0);
+ return -1;
+ }
+
+ xDst += localDst->pDrawable->x;
+ yDst += localDst->pDrawable->y;
+
+ localSrc = uxa_acquire_source(screen, pSrc,
+ xSrc, ySrc,
+ width, height,
&xSrc, &ySrc);
- if (!localSrc)
+ if (!localSrc) {
+ if (localDst != pDst)
+ FreePicture(localDst, 0);
return 0;
+ }
if (pMask) {
- localMask = uxa_acquire_mask(pDst->pDrawable->pScreen,
- pMask, xMask, yMask, width, height,
+ localMask = uxa_acquire_mask(screen, pMask,
+ xMask, yMask,
+ width, height,
&xMask, &yMask);
if (!localMask) {
if (localSrc != pSrc)
FreePicture(localSrc, 0);
+ if (localDst != pDst)
+ FreePicture(localDst, 0);
return 0;
}
}
- if (uxa_screen->info->check_composite &&
- !(*uxa_screen->info->check_composite) (op, localSrc, localMask,
- pDst)) {
- if (localSrc != pSrc)
- FreePicture(localSrc, 0);
- if (localMask && localMask != pMask)
- FreePicture(localMask, 0);
-
- return -1;
- }
-
- if (!miComputeCompositeRegion(&region, localSrc, localMask, pDst,
+ if (!miComputeCompositeRegion(&region, localSrc, localMask, localDst,
xSrc, ySrc, xMask, yMask, xDst, yDst,
width, height)) {
if (localSrc != pSrc)
FreePicture(localSrc, 0);
if (localMask && localMask != pMask)
FreePicture(localMask, 0);
+ if (localDst != pDst)
+ FreePicture(localDst, 0);
return 1;
}
- pDstPix =
- uxa_get_offscreen_pixmap(pDst->pDrawable, &dst_off_x, &dst_off_y);
+ if (localSrc->pDrawable) {
+ pSrcPix = uxa_get_offscreen_pixmap(localSrc->pDrawable,
+ &src_off_x, &src_off_y);
+ if (!pSrcPix) {
+ REGION_UNINIT(screen, &region);
- pSrcPix = uxa_get_offscreen_pixmap(localSrc->pDrawable,
- &src_off_x, &src_off_y);
+ if (localSrc != pSrc)
+ FreePicture(localSrc, 0);
+ if (localMask && localMask != pMask)
+ FreePicture(localMask, 0);
+ if (localDst != pDst)
+ FreePicture(localDst, 0);
- if (localMask)
- pMaskPix = uxa_get_offscreen_pixmap(localMask->pDrawable,
- &mask_off_x, &mask_off_y);
+ return 0;
+ }
+ } else {
+ pSrcPix = NULL;
+ }
- if (!pDstPix || !pSrcPix || (localMask && !pMaskPix)) {
- REGION_UNINIT(pDst->pDrawable->pScreen, &region);
+ if (localMask) {
+ if (localMask->pDrawable) {
+ pMaskPix = uxa_get_offscreen_pixmap(localMask->pDrawable,
+ &mask_off_x, &mask_off_y);
+ if (!pMaskPix) {
+ REGION_UNINIT(screen, &region);
- if (localSrc != pSrc)
- FreePicture(localSrc, 0);
- if (localMask && localMask != pMask)
- FreePicture(localMask, 0);
+ if (localSrc != pSrc)
+ FreePicture(localSrc, 0);
+ if (localMask && localMask != pMask)
+ FreePicture(localMask, 0);
+ if (localDst != pDst)
+ FreePicture(localDst, 0);
- return 0;
+ return 0;
+ }
+ } else {
+ pMaskPix = NULL;
+ }
}
- REGION_TRANSLATE(pScreen, &region, dst_off_x, dst_off_y);
-
if (!(*uxa_screen->info->prepare_composite)
- (op, localSrc, localMask, pDst, pSrcPix, pMaskPix, pDstPix)) {
- REGION_UNINIT(pDst->pDrawable->pScreen, &region);
+ (op, localSrc, localMask, localDst, pSrcPix, pMaskPix, pDstPix)) {
+ REGION_UNINIT(screen, &region);
if (localSrc != pSrc)
FreePicture(localSrc, 0);
if (localMask && localMask != pMask)
FreePicture(localMask, 0);
+ if (localDst != pDst)
+ FreePicture(localDst, 0);
return -1;
}
- nbox = REGION_NUM_RECTS(&region);
- pbox = REGION_RECTS(&region);
-
if (pMask) {
- xMask = xMask + mask_off_x - xDst - dst_off_x;
- yMask = yMask + mask_off_y - yDst - dst_off_y;
+ xMask = xMask + mask_off_x - xDst;
+ yMask = yMask + mask_off_y - yDst;
}
- xSrc = xSrc + src_off_x - xDst - dst_off_x;
- ySrc = ySrc + src_off_y - yDst - dst_off_y;
+ xSrc = xSrc + src_off_x - xDst;
+ ySrc = ySrc + src_off_y - yDst;
+ nbox = REGION_NUM_RECTS(&region);
+ pbox = REGION_RECTS(&region);
while (nbox--) {
(*uxa_screen->info->composite) (pDstPix,
pbox->x1 + xSrc,
pbox->y1 + ySrc,
pbox->x1 + xMask,
pbox->y1 + yMask,
- pbox->x1,
- pbox->y1,
+ pbox->x1 + dst_off_x,
+ pbox->y1 + dst_off_y,
pbox->x2 - pbox->x1,
pbox->y2 - pbox->y1);
pbox++;
}
(*uxa_screen->info->done_composite) (pDstPix);
- REGION_UNINIT(pDst->pDrawable->pScreen, &region);
+ REGION_UNINIT(screen, &region);
if (localSrc != pSrc)
FreePicture(localSrc, 0);
if (localMask && localMask != pMask)
FreePicture(localMask, 0);
+ if (localDst != pDst) {
+ GCPtr gc;
+
+ gc = GetScratchGC(pDst->pDrawable->depth, screen);
+ if (gc) {
+ ValidateGC(pDst->pDrawable, gc);
+ gc->ops->CopyArea(localDst->pDrawable, pDst->pDrawable, gc,
+ 0, 0, width, height, xDst_copy, yDst_copy);
+ FreeScratchGC(gc);
+ }
+
+ FreePicture(localDst, 0);
+ }
+
return 1;
}
@@ -917,36 +1323,100 @@ uxa_try_magic_two_pass_composite_helper(CARD8 op,
PicturePtr pSrc,
PicturePtr pMask,
PicturePtr pDst,
- INT16 xSrc,
- INT16 ySrc,
- INT16 xMask,
- INT16 yMask,
- INT16 xDst,
- INT16 yDst, CARD16 width, CARD16 height)
+ INT16 xSrc, INT16 ySrc,
+ INT16 xMask, INT16 yMask,
+ INT16 xDst, INT16 yDst,
+ CARD16 width, CARD16 height)
{
- uxa_screen_t *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen);
+ ScreenPtr screen = pDst->pDrawable->pScreen;
+ uxa_screen_t *uxa_screen = uxa_get_screen(screen);
+ PicturePtr localDst = pDst;
+ int xDst_copy, yDst_copy;
assert(op == PictOpOver);
if (uxa_screen->info->check_composite &&
(!(*uxa_screen->info->check_composite) (PictOpOutReverse, pSrc,
- pMask, pDst)
+ pMask, pDst, width, height)
|| !(*uxa_screen->info->check_composite) (PictOpAdd, pSrc, pMask,
- pDst))) {
+ pDst, width, height))) {
return -1;
}
+ if (uxa_screen->info->check_composite_target &&
+ !uxa_screen->info->check_composite_target(uxa_get_drawable_pixmap(pDst->pDrawable))) {
+ int depth = pDst->pDrawable->depth;
+ PixmapPtr pixmap;
+ int error;
+ GCPtr gc;
+
+ pixmap = uxa_get_drawable_pixmap(pDst->pDrawable);
+ if (uxa_screen->info->check_copy &&
+ !uxa_screen->info->check_copy(pixmap, pixmap, GXcopy, FB_ALLONES))
+ return -1;
+
+ pixmap = screen->CreatePixmap(screen,
+ width, height, depth,
+ CREATE_PIXMAP_USAGE_SCRATCH);
+ if (!pixmap)
+ return 0;
+
+ gc = GetScratchGC(depth, screen);
+ if (!gc) {
+ screen->DestroyPixmap(pixmap);
+ return 0;
+ }
+
+ ValidateGC(&pixmap->drawable, gc);
+ gc->ops->CopyArea(pDst->pDrawable, &pixmap->drawable, gc,
+ xDst, yDst, width, height, 0, 0);
+ FreeScratchGC(gc);
+
+ xDst_copy = xDst; xDst = 0;
+ yDst_copy = yDst; yDst = 0;
+
+ localDst = CreatePicture(0, &pixmap->drawable,
+ PictureMatchFormat(screen, depth, pDst->format),
+ 0, 0, serverClient, &error);
+ screen->DestroyPixmap(pixmap);
+
+ if (!localDst)
+ return 0;
+
+ ValidatePicture(localDst);
+ }
+
/* Now, we think we should be able to accelerate this operation. First,
* composite the destination to be the destination times the source alpha
* factors.
*/
- uxa_composite(PictOpOutReverse, pSrc, pMask, pDst, xSrc, ySrc, xMask,
- yMask, xDst, yDst, width, height);
+ uxa_composite(PictOpOutReverse, pSrc, pMask, localDst,
+ xSrc, ySrc,
+ xMask, yMask,
+ xDst, yDst,
+ width, height);
/* Then, add in the source value times the destination alpha factors (1.0).
*/
- uxa_composite(PictOpAdd, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask,
- xDst, yDst, width, height);
+ uxa_composite(PictOpAdd, pSrc, pMask, localDst,
+ xSrc, ySrc,
+ xMask, yMask,
+ xDst, yDst,
+ width, height);
+
+ if (localDst != pDst) {
+ GCPtr gc;
+
+ gc = GetScratchGC(pDst->pDrawable->depth, screen);
+ if (gc) {
+ ValidateGC(pDst->pDrawable, gc);
+ gc->ops->CopyArea(localDst->pDrawable, pDst->pDrawable, gc,
+ 0, 0, width, height, xDst_copy, yDst_copy);
+ FreeScratchGC(gc);
+ }
+
+ FreePicture(localDst, 0);
+ }
return 1;
}
@@ -958,99 +1428,113 @@ compatible_formats (CARD8 op, PicturePtr dst, PicturePtr src)
if (src->format == dst->format)
return 1;
- if (src->format == PICT_a8r8g8b8 && dst->format == PICT_x8r8g8b8)
+ /* Is the destination an alpha-less version of source? */
+ if (dst->format == PICT_FORMAT(PICT_FORMAT_BPP(src->format),
+ PICT_FORMAT_TYPE(src->format),
+ 0,
+ PICT_FORMAT_R(src->format),
+ PICT_FORMAT_G(src->format),
+ PICT_FORMAT_B(src->format)))
return 1;
- if (src->format == PICT_a8b8g8r8 && dst->format == PICT_x8b8g8r8)
- return 1;
-
- /* xrgb is promoted to argb during image upload... */
+ /* XXX xrgb is promoted to argb during image upload... */
+#if 0
if (dst->format == PICT_a8r8g8b8 && src->format == PICT_x8r8g8b8)
return 1;
+#endif
} else if (op == PictOpOver) {
- if (src->alphaMap || dst->alphaMap)
- return 0;
-
- if (src->format != dst->format)
+ if (PICT_FORMAT_A(src->format))
return 0;
- if (src->format == PICT_x8r8g8b8 || src->format == PICT_x8b8g8r8)
- return 1;
+ return src->format == dst->format;
}
return 0;
}
-static int
-drawable_contains (DrawablePtr drawable, int x1, int y1, int x2, int y2)
-{
- if (x1 < 0 || y1 < 0)
- return FALSE;
-
- if (x2 > drawable->width)
- return FALSE;
-
- if (y2 > drawable->height)
- return FALSE;
-
- return TRUE;
-}
-
void
uxa_composite(CARD8 op,
PicturePtr pSrc,
PicturePtr pMask,
PicturePtr pDst,
- INT16 xSrc,
- INT16 ySrc,
- INT16 xMask,
- INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
+ INT16 xSrc, INT16 ySrc,
+ INT16 xMask, INT16 yMask,
+ INT16 xDst, INT16 yDst,
+ CARD16 width, CARD16 height)
{
uxa_screen_t *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen);
int ret = -1;
Bool saveSrcRepeat = pSrc->repeat;
Bool saveMaskRepeat = pMask ? pMask->repeat : 0;
RegionRec region;
+ int tx, ty;
if (uxa_screen->swappedOut)
goto fallback;
+ if (!uxa_drawable_is_offscreen(pDst->pDrawable))
+ goto fallback;
+
+
+ if (pDst->alphaMap || pSrc->alphaMap || (pMask && pMask->alphaMap))
+ goto fallback;
+
+
/* Remove repeat in source if useless */
- if (pSrc->pDrawable && pSrc->repeat && !pSrc->transform &&
+ if (pSrc->pDrawable && pSrc->repeat && pSrc->filter != PictFilterConvolution &&
+ transform_is_integer_translation(pSrc->transform, &tx, &ty) &&
(pSrc->pDrawable->width > 1 || pSrc->pDrawable->height > 1) &&
- xSrc >= 0 && (xSrc + width) <= pSrc->pDrawable->width &&
- ySrc >= 0 && (ySrc + height) <= pSrc->pDrawable->height)
+ drawable_contains(pSrc->pDrawable, xSrc + tx, ySrc + ty, width, height))
pSrc->repeat = 0;
if (!pMask) {
+ if (op == PictOpClear) {
+ PicturePtr clear = uxa_solid_clear(pDst->pDrawable->pScreen);
+ if (clear &&
+ uxa_try_driver_solid_fill(clear, pDst,
+ xSrc, ySrc,
+ xDst, yDst,
+ width, height) == 1)
+ goto done;
+ }
+
if (pSrc->pDrawable == NULL) {
if (pSrc->pSourcePict) {
SourcePict *source = pSrc->pSourcePict;
if (source->type == SourcePictTypeSolidFill) {
- ret = uxa_try_driver_solid_fill(pSrc, pDst,
- xSrc, ySrc,
- xDst, yDst,
- width, height);
- if (ret == 1)
- goto done;
+ if (op == PictOpSrc ||
+ (op == PictOpOver &&
+ (source->solidFill.color & 0xff000000) == 0xff000000)) {
+ ret = uxa_try_driver_solid_fill(pSrc, pDst,
+ xSrc, ySrc,
+ xDst, yDst,
+ width, height);
+ if (ret == 1)
+ goto done;
+ }
}
}
- } else if (compatible_formats (op, pDst, pSrc)) {
- if (pSrc->pDrawable->width == 1 &&
- pSrc->pDrawable->height == 1 &&
- pSrc->repeat) {
- ret = uxa_try_driver_solid_fill(pSrc, pDst,
- xSrc, ySrc,
- xDst, yDst,
- width, height);
- if (ret == 1)
- goto done;
- } else if (!pSrc->repeat && !pSrc->transform &&
- drawable_contains(pSrc->pDrawable, xSrc, ySrc, xSrc + width, ySrc + height)) {
+ } else if (pSrc->pDrawable->width == 1 &&
+ pSrc->pDrawable->height == 1 &&
+ pSrc->repeat &&
+ (op == PictOpSrc || (op == PictOpOver && !PICT_FORMAT_A(pSrc->format)))) {
+ ret = uxa_try_driver_solid_fill(pSrc, pDst,
+ xSrc, ySrc,
+ xDst, yDst,
+ width, height);
+ if (ret == 1)
+ goto done;
+ } else if (compatible_formats (op, pDst, pSrc) &&
+ pSrc->filter != PictFilterConvolution &&
+ transform_is_integer_translation(pSrc->transform, &tx, &ty)) {
+ if (!pSrc->repeat &&
+ drawable_contains(pSrc->pDrawable,
+ xSrc + tx, ySrc + ty,
+ width, height)) {
xDst += pDst->pDrawable->x;
yDst += pDst->pDrawable->y;
- xSrc += pSrc->pDrawable->x;
- ySrc += pSrc->pDrawable->y;
+ xSrc += pSrc->pDrawable->x + tx;
+ ySrc += pSrc->pDrawable->y + ty;
if (!miComputeCompositeRegion
(&region, pSrc, pMask, pDst, xSrc, ySrc,
@@ -1066,16 +1550,14 @@ uxa_composite(CARD8 op,
REGION_UNINIT(pDst->pDrawable->pScreen,
&region);
goto done;
- } else if (pSrc->pDrawable->type == DRAWABLE_PIXMAP &&
- !pSrc->transform &&
- pSrc->repeatType == RepeatNormal) {
+ } else if (pSrc->repeat && pSrc->repeatType == RepeatNormal &&
+ pSrc->pDrawable->type == DRAWABLE_PIXMAP) {
DDXPointRec patOrg;
/* Let's see if the driver can do the repeat
* in one go
*/
- if (uxa_screen->info->prepare_composite
- && !pSrc->alphaMap && !pDst->alphaMap) {
+ if (uxa_screen->info->prepare_composite) {
ret = uxa_try_driver_composite(op, pSrc,
pMask, pDst,
xSrc, ySrc,
@@ -1091,8 +1573,8 @@ uxa_composite(CARD8 op,
*/
xDst += pDst->pDrawable->x;
yDst += pDst->pDrawable->y;
- xSrc += pSrc->pDrawable->x;
- ySrc += pSrc->pDrawable->y;
+ xSrc += pSrc->pDrawable->x + tx;
+ ySrc += pSrc->pDrawable->y + ty;
if (!miComputeCompositeRegion
(&region, pSrc, pMask, pDst, xSrc, ySrc,
@@ -1121,15 +1603,14 @@ uxa_composite(CARD8 op,
}
/* Remove repeat in mask if useless */
- if (pMask && pMask->repeat && !pMask->transform && pMask->pDrawable &&
+ if (pMask && pMask->pDrawable && pMask->repeat &&
+ pMask->filter != PictFilterConvolution &&
+ transform_is_integer_translation(pMask->transform, &tx, &ty) &&
(pMask->pDrawable->width > 1 || pMask->pDrawable->height > 1) &&
- xMask >= 0 && (xMask + width) <= pMask->pDrawable->width &&
- yMask >= 0 && (yMask + height) <= pMask->pDrawable->height)
+ drawable_contains(pMask->pDrawable, xMask + tx, yMask + ty, width, height))
pMask->repeat = 0;
- if (uxa_screen->info->prepare_composite &&
- !pSrc->alphaMap && (!pMask || !pMask->alphaMap) && !pDst->alphaMap)
- {
+ if (uxa_screen->info->prepare_composite) {
Bool isSrcSolid;
ret =
@@ -1142,9 +1623,15 @@ uxa_composite(CARD8 op,
/* For generic masks and solid src pictures, mach64 can do
* Over in two passes, similar to the component-alpha case.
*/
- isSrcSolid = pSrc->pDrawable &&
- pSrc->pDrawable->width == 1 &&
- pSrc->pDrawable->height == 1 && pSrc->repeat;
+
+ isSrcSolid =
+ pSrc->pDrawable ?
+ pSrc->pDrawable->width == 1 &&
+ pSrc->pDrawable->height == 1 &&
+ pSrc->repeat :
+ pSrc->pSourcePict ?
+ pSrc->pSourcePict->type == SourcePictTypeSolidFill :
+ 0;
/* If we couldn't do the Composite in a single pass, and it
* was a component-alpha Over, see if we can do it in two
@@ -1156,13 +1643,13 @@ uxa_composite(CARD8 op,
uxa_try_magic_two_pass_composite_helper(op, pSrc,
pMask, pDst,
xSrc, ySrc,
- xMask,
- yMask, xDst,
- yDst, width,
- height);
+ xMask, yMask,
+ xDst, yDst,
+ width, height);
if (ret == 1)
goto done;
}
+
}
fallback:
@@ -1232,15 +1719,15 @@ uxa_create_alpha_picture(ScreenPtr pScreen,
* uxa_check_poly_fill_rect to initialize the contents.
*/
void
-uxa_trapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+uxa_trapezoids(CARD8 op, PicturePtr src, PicturePtr dst,
PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
int ntrap, xTrapezoid * traps)
{
- ScreenPtr pScreen = pDst->pDrawable->pScreen;
- PictureScreenPtr ps = GetPictureScreen(pScreen);
+ ScreenPtr screen = dst->pDrawable->pScreen;
BoxRec bounds;
- Bool direct = op == PictOpAdd && miIsSolidAlpha(pSrc);
+ Bool direct;
+ direct = op == PictOpAdd && miIsSolidAlpha(src);
if (maskFormat || direct) {
miTrapezoidBounds(ntrap, traps, &bounds);
@@ -1252,7 +1739,7 @@ uxa_trapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
* Check for solid alpha add
*/
if (direct) {
- DrawablePtr pDraw = pDst->pDrawable;
+ DrawablePtr pDraw = dst->pDrawable;
PixmapPtr pixmap = uxa_get_drawable_pixmap(pDraw);
int xoff, yoff;
@@ -1262,12 +1749,15 @@ uxa_trapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
yoff += pDraw->y;
if (uxa_prepare_access(pDraw, UXA_ACCESS_RW)) {
+ PictureScreenPtr ps = GetPictureScreen(screen);
+
for (; ntrap; ntrap--, traps++)
- (*ps->RasterizeTrapezoid) (pDst, traps, 0, 0);
+ (*ps->RasterizeTrapezoid) (dst, traps, 0, 0);
uxa_finish_access(pDraw);
}
} else if (maskFormat) {
- PicturePtr pPicture;
+ PixmapPtr scratch = NULL;
+ PicturePtr mask;
INT16 xDst, yDst;
INT16 xRel, yRel;
int width, height;
@@ -1291,28 +1781,48 @@ uxa_trapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
pixman_rasterize_trapezoid(image,
(pixman_trapezoid_t *) traps,
-bounds.x1, -bounds.y1);
-
- pPicture =
- uxa_picture_from_pixman_image(pScreen, image, format);
- pixman_image_unref(image);
- if (!pPicture)
+ if (uxa_drawable_is_offscreen(dst->pDrawable)) {
+ mask = uxa_picture_from_pixman_image(screen, image, format);
+ } else {
+ int error;
+
+ scratch = GetScratchPixmapHeader(screen, width, height,
+ PIXMAN_FORMAT_DEPTH(format),
+ PIXMAN_FORMAT_BPP(format),
+ pixman_image_get_stride(image),
+ pixman_image_get_data(image));
+ mask = CreatePicture(0, &scratch->drawable,
+ PictureMatchFormat(screen,
+ PIXMAN_FORMAT_DEPTH(format),
+ format),
+ 0, 0, serverClient, &error);
+ }
+ if (!mask) {
+ if (scratch)
+ FreeScratchPixmapHeader(scratch);
+ pixman_image_unref(image);
return;
+ }
xRel = bounds.x1 + xSrc - xDst;
yRel = bounds.y1 + ySrc - yDst;
- CompositePicture(op, pSrc, pPicture, pDst,
+ CompositePicture(op, src, mask, dst,
xRel, yRel,
0, 0,
bounds.x1, bounds.y1,
width, height);
- FreePicture(pPicture, 0);
+ FreePicture(mask, 0);
+
+ if (scratch)
+ FreeScratchPixmapHeader(scratch);
+ pixman_image_unref(image);
} else {
- if (pDst->polyEdge == PolyEdgeSharp)
- maskFormat = PictureMatchFormat(pScreen, 1, PICT_a1);
+ if (dst->polyEdge == PolyEdgeSharp)
+ maskFormat = PictureMatchFormat(screen, 1, PICT_a1);
else
- maskFormat = PictureMatchFormat(pScreen, 8, PICT_a8);
+ maskFormat = PictureMatchFormat(screen, 8, PICT_a8);
for (; ntrap; ntrap--, traps++)
- uxa_trapezoids(op, pSrc, pDst, maskFormat, xSrc, ySrc,
+ uxa_trapezoids(op, src, dst, maskFormat, xSrc, ySrc,
1, traps);
}
}
diff --git a/uxa/uxa.c b/uxa/uxa.c
index d6ad5a63..37546dc3 100644
--- a/uxa/uxa.c
+++ b/uxa/uxa.c
@@ -39,7 +39,11 @@
#include "dixfontstr.h"
#include "uxa.h"
+#if HAS_DEVPRIVATEKEYREC
+DevPrivateKeyRec uxa_screen_index;
+#else
int uxa_screen_index;
+#endif
/**
* uxa_get_drawable_pixmap() returns a backing pixmap for a given drawable.
@@ -388,14 +392,17 @@ static Bool uxa_close_screen(int i, ScreenPtr pScreen)
#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
- xfree(uxa_screen);
+ free(uxa_screen);
return (*pScreen->CloseScreen) (i, pScreen);
}
@@ -406,13 +413,13 @@ static Bool uxa_close_screen(int i, ScreenPtr pScreen)
* without breaking ABI between UXA and the drivers. The driver's
* responsibility is to check beforehand that the UXA module has a matching
* major number and sufficient minor. Drivers are responsible for freeing the
- * driver structure using xfree().
+ * driver structure using free().
*
* @return a newly allocated, zero-filled driver structure
*/
uxa_driver_t *uxa_driver_alloc(void)
{
- return xcalloc(1, sizeof(uxa_driver_t));
+ return calloc(1, sizeof(uxa_driver_t));
}
/**
@@ -429,9 +436,6 @@ Bool uxa_driver_init(ScreenPtr screen, uxa_driver_t * uxa_driver)
{
uxa_screen_t *uxa_screen;
ScrnInfoPtr scrn = xf86Screens[screen->myNum];
-#ifdef RENDER
- PictureScreenPtr ps;
-#endif
if (!uxa_driver)
return FALSE;
@@ -460,11 +464,11 @@ Bool uxa_driver_init(ScreenPtr screen, uxa_driver_t * uxa_driver)
"non-NULL\n", screen->myNum);
return FALSE;
}
-#ifdef RENDER
- ps = GetPictureScreenIfSet(screen);
+#if HAS_DIXREGISTERPRIVATEKEY
+ if (!dixRegisterPrivateKey(&uxa_screen_index, PRIVATE_SCREEN, 0))
+ return FALSE;
#endif
-
- uxa_screen = xcalloc(sizeof(uxa_screen_t), 1);
+ uxa_screen = calloc(sizeof(uxa_screen_t), 1);
if (!uxa_screen) {
LogMessage(X_WARNING,
@@ -513,33 +517,32 @@ Bool uxa_driver_init(ScreenPtr screen, uxa_driver_t * uxa_driver)
scrn->EnableDisableFBAccess = uxa_xorg_enable_disable_fb_access;
#ifdef RENDER
- if (ps) {
- uxa_screen->SavedComposite = ps->Composite;
- ps->Composite = uxa_composite;
+ {
+ PictureScreenPtr ps = GetPictureScreenIfSet(screen);
+ if (ps) {
+ uxa_screen->SavedComposite = ps->Composite;
+ ps->Composite = uxa_composite;
- uxa_screen->SavedGlyphs = ps->Glyphs;
- ps->Glyphs = uxa_glyphs;
+ uxa_screen->SavedCompositeRects = ps->CompositeRects;
+ ps->CompositeRects = uxa_solid_rects;
- uxa_screen->SavedTriangles = ps->Triangles;
- ps->Triangles = uxa_triangles;
+ uxa_screen->SavedGlyphs = ps->Glyphs;
+ ps->Glyphs = uxa_glyphs;
- uxa_screen->SavedTrapezoids = ps->Trapezoids;
- ps->Trapezoids = uxa_trapezoids;
+ uxa_screen->SavedUnrealizeGlyph = ps->UnrealizeGlyph;
+ ps->UnrealizeGlyph = uxa_glyph_unrealize;
- uxa_screen->SavedAddTraps = ps->AddTraps;
- ps->AddTraps = uxa_check_add_traps;
- }
-#endif
+ uxa_screen->SavedTriangles = ps->Triangles;
+ ps->Triangles = uxa_triangles;
-#ifdef MITSHM
- /* Re-register with the MI funcs, which don't allow shared pixmaps.
- * Shared pixmaps are almost always a performance loss for us, but this
- * still allows for SHM PutImage.
- */
- ShmRegisterFuncs(screen, &uxa_shm_funcs);
-#endif
+ uxa_screen->SavedTrapezoids = ps->Trapezoids;
+ ps->Trapezoids = uxa_trapezoids;
- uxa_glyphs_init(screen);
+ uxa_screen->SavedAddTraps = ps->AddTraps;
+ ps->AddTraps = uxa_check_add_traps;
+ }
+ }
+#endif
LogMessage(X_INFO,
"UXA(%d): Driver registered support for the following"
@@ -561,6 +564,14 @@ Bool uxa_driver_init(ScreenPtr screen, uxa_driver_t * uxa_driver)
return TRUE;
}
+Bool uxa_resources_init(ScreenPtr screen)
+{
+ if (!uxa_glyphs_init(screen))
+ return FALSE;
+
+ return TRUE;
+}
+
/**
* uxa_driver_fini tears down UXA on a given screen.
*
diff --git a/uxa/uxa.h b/uxa/uxa.h
index c7e5566a..efadfdaa 100644
--- a/uxa/uxa.h
+++ b/uxa/uxa.h
@@ -74,6 +74,17 @@ typedef struct _UxaDriver {
* @{
*/
/**
+ * check_solid() checks whether the driver can do a solid fill to this drawable.
+ * @param pDrawable Destination drawable
+ * @param alu raster operation
+ * @param planemask write mask for the fill
+ *
+ * The check_solid() call is recommended if prepare_solid() is
+ * implemented, but is not required.
+ */
+ Bool(*check_solid) (DrawablePtr pDrawable, int alu, Pixel planemask);
+
+ /**
* prepare_solid() sets up the driver for doing a solid fill.
* @param pPixmap Destination pixmap
* @param alu raster operation
@@ -138,6 +149,10 @@ typedef struct _UxaDriver {
* @{
*/
/**
+ * check_copy() checks whether the driver can blit between the two Pictures
+ */
+ Bool(*check_copy) (PixmapPtr pSrc, PixmapPtr pDst, int alu, Pixel planemask);
+ /**
* prepare_copy() sets up the driver for doing a copy within video
* memory.
- *
@@ -232,6 +247,8 @@ typedef struct _UxaDriver {
* @param pSrcPicture source Picture
* @param pMaskPicture mask picture
* @param pDstPicture destination Picture
+ * @param width The width of the composite operation
+ * @param height The height of the composite operation
*
* The check_composite() call checks if the driver could handle
* acceleration of op with the given source, mask, and destination
@@ -249,7 +266,32 @@ typedef struct _UxaDriver {
Bool(*check_composite) (int op,
PicturePtr pSrcPicture,
PicturePtr pMaskPicture,
- PicturePtr pDstPicture);
+ PicturePtr pDstPicture,
+ int width, int height);
+
+ /**
+ * check_composite_target() checks to see if the destination of the composite
+ * operation can be used without midification.
+ *
+ * @param pixmap Destination Pixmap
+ *
+ * The check_composite_target() call is recommended if prepare_composite() is
+ * implemented, but is not required.
+ */
+ Bool(*check_composite_target) (PixmapPtr pixmap);
+
+ /**
+ * check_composite_texture() checks to see if a source to the composite
+ * operation can be used without midification.
+ *
+ * @param pScreen Screen
+ * @param pPicture Picture
+ *
+ * The check_composite_texture() call is recommended if prepare_composite() is
+ * implemented, but is not required.
+ */
+ Bool(*check_composite_texture) (ScreenPtr pScreen,
+ PicturePtr pPicture);
/**
* prepare_composite() sets up the driver for doing a composite
@@ -516,6 +558,7 @@ typedef struct _UxaDriver {
uxa_driver_t *uxa_driver_alloc(void);
Bool uxa_driver_init(ScreenPtr screen, uxa_driver_t * uxa_driver);
+Bool uxa_resources_init(ScreenPtr screen);
void uxa_driver_fini(ScreenPtr pScreen);