summaryrefslogtreecommitdiff
path: root/uxa
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2010-05-21 11:01:30 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2010-05-24 18:31:45 +0100
commit9d8ac271404ff219c3d40ae8f829e8b76ac7c359 (patch)
tree34d5d5ba34da6dfb40255a3627e0b4387242c1a8 /uxa
parent509df27c7401e96d3062890da73f6af6629adef4 (diff)
parentea07535240dafc4c6ef55b4b7a2eeaa595febe86 (diff)
Merge branch 'glyphs'
Tweak glyphs to improve x11perf on i915 by about 33%. PineView, aa10text: 460 -> 617 kglyphs/s. PineView, rgb10text: 434 -> 610 kglyphs/s. Speedups ======== xcb poppler 18.636 -> 13.958: 1.34x speedup xlib firefox-talos-gfx 71.905 -> 56.232: 1.28x speedup xcb firefox-talos-gfx 72.882 -> 57.969: 1.26x speedup xlib gnome-terminal-vim 38.126 -> 34.472: 1.11x speedup xcb gnome-terminal-vim 35.164 -> 32.573: 1.08x speedup xlib poppler 19.634 -> 18.246: 1.08x speedup Note the lack of significant improvement for firefox-planet-gnome.
Diffstat (limited to 'uxa')
-rw-r--r--uxa/uxa-accel.c207
-rw-r--r--uxa/uxa-glyphs.c529
-rw-r--r--uxa/uxa-priv.h25
-rw-r--r--uxa/uxa-render.c400
-rw-r--r--uxa/uxa.h20
5 files changed, 882 insertions, 299 deletions
diff --git a/uxa/uxa-accel.c b/uxa/uxa-accel.c
index cfc2d381..77963f39 100644
--- a/uxa/uxa-accel.c
+++ b/uxa/uxa-accel.c
@@ -34,33 +34,181 @@
#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 8: return PICT_a8;
+ case 15: return PICT_x1r5g5b5;
+ case 16: return PICT_r5g6b5;
+ default:
+ case 24: return PICT_x8r8g8b8;
+ 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 || pGC->fillStyle != FillSolid ||
- !(pPixmap = uxa_get_offscreen_pixmap(pDrawable, &off_x, &off_y)) ||
- !(*uxa_screen->info->prepare_solid) (pPixmap,
+ 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->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->y2 >= 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 +234,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 +251,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 +262,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
@@ -433,17 +586,17 @@ uxa_copy_n_to_n(DrawablePtr pSrcDrawable,
int dst_off_x, dst_off_y;
PixmapPtr pSrcPixmap, pDstPixmap;
- if (uxa_screen->info->check_copy &&
- !uxa_screen->info->check_copy(pSrcDrawable, pDstDrawable,
- pGC ? pGC->alu : GXcopy,
- pGC ? pGC->planemask : FB_ALLONES))
- goto fallback;
-
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);
uxa_get_drawable_deltas(pDstDrawable, pDstPixmap, &dst_off_x,
@@ -968,20 +1121,16 @@ uxa_fill_region_tiled(DrawablePtr pDrawable,
uxa_get_pixmap_first_pixel(pTile),
planemask, alu);
+ pPixmap = uxa_get_offscreen_pixmap(pDrawable, &xoff, &yoff);
+ if (!pPixmap || !uxa_pixmap_is_offscreen(pTile))
+ goto out;
+
if (uxa_screen->info->check_copy &&
- !uxa_screen->info->check_copy(&pTile->drawable, pDrawable, alu, planemask))
+ !uxa_screen->info->check_copy(pTile, pPixmap, alu, planemask))
return FALSE;
-
- 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->prepare_copy) (pTile, pPixmap, 1, 1, alu,
planemask)) {
while (nbox--) {
diff --git a/uxa/uxa-glyphs.c b/uxa/uxa-glyphs.c
index f8bb7f54..93a738ed 100644
--- a/uxa/uxa-glyphs.c
+++ b/uxa/uxa-glyphs.c
@@ -205,6 +205,8 @@ static Bool uxa_realize_glyph_caches(ScreenPtr pScreen, unsigned int format)
if (!pPicture)
return FALSE;
+ ValidatePicture(pPicture);
+
/* And store the picture in all the caches for the format */
for (i = 0; i < UXA_NUM_GLYPH_CACHES; i++) {
@@ -573,41 +575,294 @@ uxa_buffer_glyph(ScreenPtr pScreen,
return UXA_GLYPH_SUCCESS;
}
-static void uxa_glyphs_to_mask(PicturePtr pMask, uxa_glyph_buffer_t * buffer)
+static PicturePtr
+uxa_glyphs_acquire_source(ScreenPtr screen,
+ PicturePtr src,
+ INT16 x, INT16 y,
+ const uxa_glyph_buffer_t * buffer,
+ INT16 * out_x, INT16 * out_y)
+{
+ uxa_screen_t *uxa_screen = uxa_get_screen(screen);
+ int x1, y1, x2, y2;
+ int width, height;
+ int i;
+
+ 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;
+ }
+
+ for (i = 0; i < buffer->count; i++) {
+ const uxa_composite_rect_t *r = &buffer->rects[i];
+
+ if (r->xDst < x1)
+ x1 = r->xDst;
+ if (r->xDst + r->width > x2)
+ x2 = r->xDst + r->width;
+
+ if (r->yDst < y1)
+ y1 = r->yDst;
+ if (r->yDst + r->height > y2)
+ y2 = r->yDst + r->height;
+ }
+
+ width = x2 - x1;
+ height = y2 - y1;
+
+ if (src->pDrawable) {
+ PicturePtr dst;
+
+ dst = uxa_acquire_drawable(screen, src,
+ x, y,
+ width, height,
+ out_x, out_y);
+ 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;
+ }
+
+ *out_x = 0;
+ *out_y = 0;
+ return uxa_acquire_pattern(screen, src,
+ PICT_a8r8g8b8, x, y, width, height);
+}
+
+static int
+uxa_glyphs_try_driver_composite(CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pDst,
+ const uxa_glyph_buffer_t * buffer,
+ INT16 xSrc, INT16 ySrc,
+ INT16 xDst, INT16 yDst)
{
- uxa_composite_rects(PictOpAdd, buffer->source, pMask,
- buffer->count, buffer->rects);
+ ScreenPtr screen = pDst->pDrawable->pScreen;
+ uxa_screen_t *uxa_screen = uxa_get_screen(screen);
+ PicturePtr localSrc;
+ int src_off_x = 0, src_off_y = 0, mask_off_x, mask_off_y, dst_off_x, dst_off_y;
+ PixmapPtr pSrcPix = NULL, pMaskPix, pDstPix;
+ const uxa_composite_rect_t *rects;
+ int nrect;
+
+ if (uxa_screen->info->check_composite &&
+ !(*uxa_screen->info->check_composite) (op, pSrc, buffer->source, pDst, 0, 0)) {
+ return -1;
+ }
+
+ pDstPix =
+ uxa_get_offscreen_pixmap(pDst->pDrawable, &dst_off_x, &dst_off_y);
+
+ pMaskPix =
+ uxa_get_offscreen_pixmap(buffer->source->pDrawable, &mask_off_x, &mask_off_y);
+ if(!pMaskPix)
+ return -1;
+
+ localSrc = uxa_glyphs_acquire_source(screen, pSrc,
+ xSrc, ySrc,
+ buffer,
+ &xSrc, &ySrc);
+ if (!localSrc)
+ return 0;
+
+ if (localSrc->pDrawable) {
+ pSrcPix =
+ uxa_get_offscreen_pixmap(localSrc->pDrawable, &src_off_x, &src_off_y);
+ if (!pSrcPix) {
+ if (localSrc != pSrc)
+ FreePicture(localSrc, 0);
+ return 0;
+ }
+
+ xSrc += localSrc->pDrawable->x;
+ ySrc += localSrc->pDrawable->y;
+ }
+
+ if (!(*uxa_screen->info->prepare_composite)
+ (op, localSrc, buffer->source, pDst, pSrcPix, pMaskPix, pDstPix)) {
+ if (localSrc != pSrc)
+ FreePicture(localSrc, 0);
+ return -1;
+ }
+
+ nrect = buffer->count;
+ rects = buffer->rects;
+ do {
+ INT16 _xDst = rects->xDst + pDst->pDrawable->x;
+ INT16 _yDst = rects->yDst + pDst->pDrawable->y;
+ INT16 _xMask = rects->xSrc + buffer->source->pDrawable->x;
+ INT16 _yMask = rects->ySrc + buffer->source->pDrawable->y;
+ INT16 _xSrc = xSrc, _ySrc = ySrc;
+
+ RegionRec region;
+ BoxPtr pbox;
+ int nbox;
+
+ if (!miComputeCompositeRegion(&region,
+ localSrc, buffer->source, pDst,
+ _xSrc, _ySrc,
+ _xMask, _yMask,
+ _xDst, _yDst,
+ rects->width, rects->height))
+ goto next_rect;
+
+ _xSrc += src_off_x - _xDst;
+ _ySrc += src_off_y - _yDst;
+ _xMask += mask_off_x - _xDst;
+ _yMask += mask_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 + dst_off_x,
+ pbox->y1 + dst_off_y,
+ pbox->x2 - pbox->x1,
+ pbox->y2 - pbox->y1);
+ pbox++;
+ }
+
+next_rect:
+ REGION_UNINIT(screen, &region);
- buffer->count = 0;
- buffer->source = NULL;
+ rects++;
+ } while (--nrect);
+ (*uxa_screen->info->done_composite) (pDstPix);
+
+ if (localSrc != pSrc)
+ FreePicture(localSrc, 0);
+
+ return 1;
}
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)
+ const uxa_glyph_buffer_t * buffer,
+ INT16 xSrc, INT16 ySrc,
+ INT16 xDst, INT16 yDst)
{
- int i;
+ if (uxa_glyphs_try_driver_composite(op, pSrc, pDst, buffer,
+ xSrc, ySrc,
+ xDst, yDst) != 1) {
+ int i;
- for (i = 0; i < buffer->count; i++) {
- uxa_composite_rect_t *rect = &buffer->rects[i];
+ for (i = 0; i < buffer->count; i++) {
+ const 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);
- }
-
- buffer->count = 0;
- buffer->source = NULL;
+ 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);
+ }
+ }
+}
+
+static int
+uxa_glyphs_try_driver_add_to_mask(PicturePtr pDst,
+ const uxa_glyph_buffer_t *buffer)
+{
+ 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;
+ const uxa_composite_rect_t *rects;
+ int nrect;
+
+ if (uxa_screen->info->check_composite &&
+ !(*uxa_screen->info->check_composite) (PictOpAdd, buffer->source, NULL, pDst, 0, 0)) {
+ return -1;
+ }
+
+ pDstPix =
+ uxa_get_offscreen_pixmap(pDst->pDrawable, &dst_off_x, &dst_off_y);
+
+ pSrcPix =
+ uxa_get_offscreen_pixmap(buffer->source->pDrawable, &src_off_x, &src_off_y);
+ if(!pSrcPix)
+ return -1;
+
+ if (!(*uxa_screen->info->prepare_composite)
+ (PictOpAdd, buffer->source, NULL, pDst, pSrcPix, NULL, pDstPix))
+ return -1;
+
+ rects = buffer->rects;
+ nrect = buffer->count;
+ do {
+ INT16 xDst = rects->xDst + pDst->pDrawable->x;
+ INT16 yDst = rects->yDst + pDst->pDrawable->y;
+ INT16 xSrc = rects->xSrc + buffer->source->pDrawable->x;
+ INT16 ySrc = rects->ySrc + buffer->source->pDrawable->y;
+
+ RegionRec region;
+ BoxPtr pbox;
+ int nbox;
+
+ if (!miComputeCompositeRegion(&region, buffer->source, NULL, pDst,
+ xSrc, ySrc, 0, 0, xDst, yDst,
+ rects->width, rects->height))
+ goto next_rect;
+
+ xSrc += src_off_x - xDst;
+ 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,
+ 0, 0,
+ pbox->x1 + dst_off_x,
+ pbox->y1 + dst_off_y,
+ pbox->x2 - pbox->x1,
+ pbox->y2 - pbox->y1);
+ pbox++;
+ }
+
+next_rect:
+ REGION_UNINIT(pDst->pDrawable->pScreen, &region);
+
+ rects++;
+ } while (--nrect);
+ (*uxa_screen->info->done_composite) (pDstPix);
+
+ return 1;
+}
+
+static void uxa_glyphs_to_mask(PicturePtr pDst, const uxa_glyph_buffer_t *buffer)
+{
+ if (uxa_glyphs_try_driver_add_to_mask(pDst, buffer) != 1) {
+ int i;
+
+ for (i = 0; i < buffer->count; i++) {
+ const uxa_composite_rect_t *r = &buffer->rects[i];
+
+ uxa_check_composite(PictOpAdd, buffer->source, NULL, pDst,
+ r->xSrc, r->ySrc,
+ 0, 0,
+ r->xDst, r->yDst,
+ r->width, r->height);
+ }
+ }
}
/* Cut and paste from render/glyph.c - probably should export it instead */
@@ -854,12 +1109,12 @@ uxa_glyphs(CARD8 op,
PicturePtr pSrc,
PicturePtr pDst,
PictFormatPtr maskFormat,
- INT16 xSrc,
- INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr * glyphs)
+ INT16 xSrc, INT16 ySrc,
+ int nlist, GlyphListPtr list, GlyphPtr * glyphs)
{
- PixmapPtr pMaskPixmap = 0;
- PicturePtr pMask;
- ScreenPtr pScreen = pDst->pDrawable->pScreen;
+ ScreenPtr screen = pDst->pDrawable->pScreen;
+ uxa_screen_t *uxa_screen = uxa_get_screen(screen);
+ PicturePtr pMask = NULL;
int width = 0, height = 0;
int x, y;
int xDst = list->xOff, yDst = list->yOff;
@@ -867,86 +1122,172 @@ uxa_glyphs(CARD8 op,
GlyphPtr glyph;
int error;
BoxRec extents = { 0, 0, 0, 0 };
+ Bool have_extents = FALSE;
CARD32 component_alpha;
uxa_glyph_buffer_t buffer;
+ PicturePtr localDst = pDst;
- if (!uxa_drawable_is_offscreen(pDst->pDrawable)) {
+ 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;
}
- /* 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.
- */
+ ValidatePicture(pSrc);
+ ValidatePicture(pDst);
+
if (!maskFormat) {
- Bool sameFormat = TRUE;
- int i;
+ /* 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;
+ maskFormat = list[0].format;
- for (i = 0; i < nlist; i++) {
- if (maskFormat->format != list[i].format->format) {
- sameFormat = FALSE;
- break;
+ 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 (!sameFormat ||
+ uxa_glyphs_intersect(nlist, list, glyphs))
+ maskFormat = NULL;
}
}
- if (maskFormat) {
- GCPtr pGC;
- xRectangle rect;
+ x = y = 0;
+ 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 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;
+ 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) {
+ PixmapPtr pixmap;
+ GCPtr gc;
+ xRectangle rect;
+
+ if (!have_extents) {
+ 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;
+ x = -extents.x1;
+ y = -extents.y1;
+ have_extents = TRUE;
+ }
if (maskFormat->depth == 1) {
PictFormatPtr a8Format =
- PictureMatchFormat(pScreen, 8, PICT_a8);
+ PictureMatchFormat(screen, 8, PICT_a8);
if (a8Format)
maskFormat = a8Format;
}
- pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height,
- maskFormat->depth,
- CREATE_PIXMAP_USAGE_SCRATCH);
- if (!pMaskPixmap)
+ pixmap = screen->CreatePixmap(screen, width, height,
+ maskFormat->depth,
+ CREATE_PIXMAP_USAGE_SCRATCH);
+ if (!pixmap) {
+ if (localDst != pDst)
+ FreePicture(localDst, 0);
return;
+ }
+
+ gc = GetScratchGC(pixmap->drawable.depth, screen);
+ ValidateGC(&pixmap->drawable, gc);
+ rect.x = 0;
+ rect.y = 0;
+ rect.width = width;
+ rect.height = height;
+ gc->ops->PolyFillRect(&pixmap->drawable, gc, 1, &rect);
+ FreeScratchGC(gc);
+
component_alpha = NeedsComponent(maskFormat->format);
- pMask = CreatePicture(0, &pMaskPixmap->drawable,
+ pMask = CreatePicture(0, &pixmap->drawable,
maskFormat, CPComponentAlpha,
&component_alpha, serverClient, &error);
+ screen->DestroyPixmap(pixmap);
+
if (!pMask) {
- (*pScreen->DestroyPixmap) (pMaskPixmap);
+ if (localDst != pDst)
+ FreePicture(localDst, 0);
return;
}
- pGC = GetScratchGC(pMaskPixmap->drawable.depth, pScreen);
- ValidateGC(&pMaskPixmap->drawable, pGC);
- rect.x = 0;
- rect.y = 0;
- rect.width = width;
- rect.height = height;
- (*pGC->ops->PolyFillRect) (&pMaskPixmap->drawable, pGC, 1,
- &rect);
- FreeScratchGC(pGC);
- x = -extents.x1;
- y = -extents.y1;
- } else {
- pMask = pDst;
- x = 0;
- y = 0;
+
+ ValidatePicture(pMask);
}
+
buffer.count = 0;
buffer.source = NULL;
while (nlist--) {
@@ -957,16 +1298,19 @@ uxa_glyphs(CARD8 op,
glyph = *glyphs++;
if (glyph->info.width > 0 && glyph->info.height > 0 &&
- uxa_buffer_glyph(pScreen, &buffer, glyph, x,
+ uxa_buffer_glyph(screen, &buffer, glyph, x,
y) == UXA_GLYPH_NEED_FLUSH) {
if (maskFormat)
uxa_glyphs_to_mask(pMask, &buffer);
else
- uxa_glyphs_to_dst(op, pSrc, pDst,
+ uxa_glyphs_to_dst(op, pSrc, localDst,
&buffer, xSrc, ySrc,
xDst, yDst);
- uxa_buffer_glyph(pScreen, &buffer, glyph, x, y);
+ buffer.count = 0;
+ buffer.source = NULL;
+
+ uxa_buffer_glyph(screen, &buffer, glyph, x, y);
}
x += glyph->info.xOff;
@@ -979,20 +1323,41 @@ uxa_glyphs(CARD8 op,
if (maskFormat)
uxa_glyphs_to_mask(pMask, &buffer);
else
- uxa_glyphs_to_dst(op, pSrc, pDst, &buffer,
+ uxa_glyphs_to_dst(op, pSrc, localDst, &buffer,
xSrc, ySrc, xDst, yDst);
}
if (maskFormat) {
- x = extents.x1;
- y = extents.y1;
+ if (localDst == pDst) {
+ x = extents.x1;
+ y = extents.y1;
+ } else
+ x = y = 0;
CompositePicture(op,
pSrc,
pMask,
- pDst,
+ localDst,
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(pMask, 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,
+ extents.x1, extents.y1);
+ FreeScratchGC(gc);
+ }
+
+ FreePicture(localDst, 0);
}
}
diff --git a/uxa/uxa-priv.h b/uxa/uxa-priv.h
index a4763b41..bace6798 100644
--- a/uxa/uxa-priv.h
+++ b/uxa/uxa-priv.h
@@ -434,6 +434,31 @@ 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);
diff --git a/uxa/uxa-render.c b/uxa/uxa-render.c
index 726079a5..ec59871b 100644
--- a/uxa/uxa-render.c
+++ b/uxa/uxa-render.c
@@ -251,7 +251,7 @@ uxa_get_pixel_from_rgba(CARD32 * pixel,
return TRUE;
}
-static Bool
+Bool
uxa_get_rgba_from_pixel(CARD32 pixel,
CARD16 * red,
CARD16 * green,
@@ -391,8 +391,6 @@ uxa_try_driver_solid_fill(PicturePtr pSrc,
width, height))
return 1;
- REGION_TRANSLATE(pScreen, &region, dst_off_x, dst_off_y);
-
if (pSrcPix) {
if (! uxa_get_color_for_pixmap (pSrcPix, pSrc->format, pDst->format, &pixel)) {
REGION_UNINIT(pDst->pDrawable->pScreen, &region);
@@ -432,6 +430,8 @@ uxa_try_driver_solid_fill(PicturePtr pSrc,
return -1;
}
+ REGION_TRANSLATE(pScreen, &region, dst_off_x, dst_off_y);
+
nbox = REGION_NUM_RECTS(&region);
pbox = REGION_RECTS(&region);
@@ -607,7 +607,7 @@ uxa_solid_clear(ScreenPtr screen)
return picture;
}
-static PicturePtr
+PicturePtr
uxa_acquire_solid(ScreenPtr screen, SourcePict *source)
{
uxa_screen_t *uxa_screen = uxa_get_screen(screen);
@@ -664,7 +664,7 @@ DONE:
return picture;
}
-static PicturePtr
+PicturePtr
uxa_acquire_pattern(ScreenPtr pScreen,
PicturePtr pSrc,
pixman_format_code_t format,
@@ -757,7 +757,7 @@ uxa_render_picture(ScreenPtr screen,
return picture;
}
-static PicturePtr
+PicturePtr
uxa_acquire_drawable(ScreenPtr pScreen,
PicturePtr pSrc,
INT16 x, INT16 y,
@@ -788,7 +788,9 @@ uxa_acquire_drawable(ScreenPtr pScreen,
}
}
- pPixmap = pScreen->CreatePixmap(pScreen, width, height, depth, 0);
+ pPixmap = pScreen->CreatePixmap(pScreen,
+ width, height, depth,
+ CREATE_PIXMAP_USAGE_SCRATCH);
if (!pPixmap)
return 0;
@@ -935,7 +937,7 @@ uxa_solid_rects (CARD8 op,
uxa_screen_t *uxa_screen = uxa_get_screen(screen);
PixmapPtr dst_pixmap, src_pixmap = NULL;
pixman_region16_t region;
- pixman_box16_t *boxes;
+ pixman_box16_t *boxes, *extents;
PicturePtr src;
int dst_x, dst_y;
int num_boxes;
@@ -960,6 +962,7 @@ uxa_solid_rects (CARD8 op,
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;
@@ -970,28 +973,28 @@ uxa_solid_rects (CARD8 op,
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 (op == PictOpClear) {
- pixel = 0;
- } else {
- if (!uxa_get_pixel_from_rgba(&pixel,
- color->red,
- color->green,
- color->blue,
- color->alpha,
- dst->format))
- 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;
- uxa_screen->info->solid(dst_pixmap,
- boxes->x1, boxes->y1,
- boxes->x2, boxes->y2);
+ 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 {
@@ -1001,8 +1004,16 @@ uxa_solid_rects (CARD8 op,
if (!src)
goto err_region;
- if (!uxa_screen->info->check_composite(op, src, NULL, dst))
+ 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_screen->info->check_composite_texture ||
!uxa_screen->info->check_composite_texture(screen, src)) {
@@ -1048,124 +1059,6 @@ fallback:
}
static int
-uxa_try_driver_composite_rects(CARD8 op,
- PicturePtr pSrc,
- PicturePtr pDst,
- int nrect, uxa_composite_rect_t * rects)
-{
- 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 (!uxa_screen->info->prepare_composite || uxa_screen->swappedOut)
- return -1;
-
- if (uxa_screen->info->check_composite &&
- !(*uxa_screen->info->check_composite) (op, pSrc, NULL, pDst)) {
- return -1;
- }
-
- pDstPix =
- uxa_get_offscreen_pixmap(pDst->pDrawable, &dst_off_x, &dst_off_y);
- if (!pDstPix)
- return 0;
-
- pSrcPix =
- uxa_get_offscreen_pixmap(pSrc->pDrawable, &src_off_x, &src_off_y);
- if (!pSrcPix)
- return 0;
-
- if (!(*uxa_screen->info->prepare_composite)
- (op, pSrc, NULL, pDst, pSrcPix, NULL, pDstPix))
- return -1;
-
- 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++;
- }
-
-next_rect:
- REGION_UNINIT(pDst->pDrawable->pScreen, &region);
-
- rects++;
- }
- (*uxa_screen->info->done_composite) (pDstPix);
-
- return 1;
-}
-
-/**
- * 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)
-{
- int n;
- uxa_composite_rect_t *r;
-
- /************************************************************/
-
- ValidatePicture(pSrc);
- ValidatePicture(pDst);
-
- 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++;
- }
- }
-
- /************************************************************/
-
-}
-
-static int
uxa_try_driver_composite(CARD8 op,
PicturePtr pSrc,
PicturePtr pMask,
@@ -1175,53 +1068,109 @@ uxa_try_driver_composite(CARD8 op,
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;
if (uxa_screen->info->check_composite &&
- !(*uxa_screen->info->check_composite) (op, pSrc, pMask, pDst))
+ !(*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);
+
+ 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(pDst->pDrawable, &dst_off_x, &dst_off_y);
- if (!pDstPix)
+ uxa_get_offscreen_pixmap(localDst->pDrawable, &dst_off_x, &dst_off_y);
+ if (!pDstPix) {
+ if (localDst != pDst)
+ FreePicture(localDst, 0);
return -1;
+ }
- xDst += pDst->pDrawable->x;
- yDst += pDst->pDrawable->y;
+ xDst += localDst->pDrawable->x;
+ yDst += localDst->pDrawable->y;
- localSrc = uxa_acquire_source(pDst->pDrawable->pScreen, pSrc,
+ 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,
+ 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 (!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;
}
@@ -1230,12 +1179,14 @@ uxa_try_driver_composite(CARD8 op,
pSrcPix = uxa_get_offscreen_pixmap(localSrc->pDrawable,
&src_off_x, &src_off_y);
if (!pSrcPix) {
- 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)
+ FreePicture(localDst, 0);
return 0;
}
@@ -1248,12 +1199,14 @@ uxa_try_driver_composite(CARD8 op,
pMaskPix = uxa_get_offscreen_pixmap(localMask->pDrawable,
&mask_off_x, &mask_off_y);
if (!pMaskPix) {
- 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)
+ FreePicture(localDst, 0);
return 0;
}
@@ -1262,52 +1215,65 @@ uxa_try_driver_composite(CARD8 op,
}
}
- 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;
}
@@ -1365,36 +1331,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;
}
@@ -1450,10 +1480,10 @@ 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;
@@ -1468,9 +1498,11 @@ uxa_composite(CARD8 op,
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->filter != PictFilterConvolution &&
transform_is_integer_translation(pSrc->transform, &tx, &ty) &&
diff --git a/uxa/uxa.h b/uxa/uxa.h
index bf7ec0b5..23f9465b 100644
--- a/uxa/uxa.h
+++ b/uxa/uxa.h
@@ -151,9 +151,7 @@ typedef struct _UxaDriver {
/**
* check_copy() checks whether the driver can blit between the two Pictures
*/
- Bool(*check_copy) (DrawablePtr pSrcDrawable,
- DrawablePtr pDstDrawable,
- int alu, Pixel planemask);
+ Bool(*check_copy) (PixmapPtr pSrc, PixmapPtr pDst, int alu, Pixel planemask);
/**
* prepare_copy() sets up the driver for doing a copy within video
* memory.
@@ -249,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
@@ -266,7 +266,19 @@ 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