summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2010-05-21 09:55:55 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2010-05-24 18:31:16 +0100
commit80a9e64f50aeda6004e3aba1fbfdda50bb1f1c82 (patch)
treea9e39dec68ff4fd3b4d61a5c26cd7fc18b88a3b0
parent91f560034fc2695680d1208a78fc56d814b0da79 (diff)
uxa: Use temporary dest when target is too large for compositor
If the destination cannot fit into the 3D pipeline when we need to composite, we fallback to doing the operation on the CPU. This is very slow, and quite easy to trigger on i915 by plugging in an external display. An alternative is to extract the extents of the operation from the destination using the blitter which can usually handle much larger operations. This gives us a temporary target that can fit into the 3D pipeline and thus be accelerated, before copying back into the larger real destination. For x11perf this boosts glyph rendering on PineView, from 38kglyphs/s to 480kglyphs/s. Just a little shy of the native performance of 601kglyphs/s Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--src/i830.h17
-rw-r--r--src/i830_render.c24
-rw-r--r--src/i830_uxa.c22
-rw-r--r--src/i915_render.c18
-rw-r--r--src/i965_render.c7
-rw-r--r--uxa/uxa-accel.c28
-rw-r--r--uxa/uxa-glyphs.c185
-rw-r--r--uxa/uxa-render.c233
-rw-r--r--uxa/uxa.h20
9 files changed, 431 insertions, 123 deletions
diff --git a/src/i830.h b/src/i830.h
index f8aa824e..229a4e68 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -469,8 +469,10 @@ void i830_set_gem_max_sizes(ScrnInfoPtr scrn);
drm_intel_bo *i830_allocate_framebuffer(ScrnInfoPtr scrn);
/* i830_render.c */
-Bool i830_check_composite(int op, PicturePtr source, PicturePtr mask,
- PicturePtr dest);
+Bool i830_check_composite(int op,
+ PicturePtr sourcec, PicturePtr mask, PicturePtr dest,
+ int width, int height);
+Bool i830_check_composite_target(PixmapPtr pixmap);
Bool i830_check_composite_texture(ScreenPtr screen, PicturePtr picture);
Bool i830_prepare_composite(int op, PicturePtr sourcec, PicturePtr mask,
PicturePtr dest, PixmapPtr sourcecPixmap,
@@ -481,8 +483,10 @@ void i830_composite(PixmapPtr dest, int srcX, int srcY,
int maskX, int maskY, int dstX, int dstY, int w, int h);
void i830_done_composite(PixmapPtr dest);
/* i915_render.c */
-Bool i915_check_composite(int op, PicturePtr sourcec, PicturePtr mask,
- PicturePtr dest);
+Bool i915_check_composite(int op,
+ PicturePtr sourcec, PicturePtr mask, PicturePtr dest,
+ int width, int height);
+Bool i915_check_composite_target(PixmapPtr pixmap);
Bool i915_check_composite_texture(ScreenPtr screen, PicturePtr picture);
Bool i915_prepare_composite(int op, PicturePtr sourcec, PicturePtr mask,
PicturePtr dest, PixmapPtr sourcecPixmap,
@@ -496,8 +500,9 @@ void i830_batch_flush_notify(ScrnInfoPtr scrn);
unsigned int gen4_render_state_size(ScrnInfoPtr scrn);
void gen4_render_state_init(ScrnInfoPtr scrn);
void gen4_render_state_cleanup(ScrnInfoPtr scrn);
-Bool i965_check_composite(int op, PicturePtr sourcec, PicturePtr mask,
- PicturePtr dest);
+Bool i965_check_composite(int op,
+ PicturePtr sourcec, PicturePtr mask, PicturePtr dest,
+ int width, int height);
Bool i965_check_composite_texture(ScreenPtr screen, PicturePtr picture);
Bool i965_prepare_composite(int op, PicturePtr sourcec, PicturePtr mask,
PicturePtr dest, PixmapPtr sourcecPixmap,
diff --git a/src/i830_render.c b/src/i830_render.c
index b0413c58..cba65eb3 100644
--- a/src/i830_render.c
+++ b/src/i830_render.c
@@ -340,8 +340,11 @@ static void i830_texture_setup(PicturePtr picture, PixmapPtr pixmap, int unit)
}
Bool
-i830_check_composite(int op, PicturePtr source_picture, PicturePtr mask_picture,
- PicturePtr dest_picture)
+i830_check_composite(int op,
+ PicturePtr source_picture,
+ PicturePtr mask_picture,
+ PicturePtr dest_picture,
+ int width, int height)
{
ScrnInfoPtr scrn = xf86Screens[dest_picture->pDrawable->pScreen->myNum];
uint32_t tmp1;
@@ -373,6 +376,23 @@ i830_check_composite(int op, PicturePtr source_picture, PicturePtr mask_picture,
return FALSE;
}
+ if (width > 2048 || height > 2048) {
+ intel_debug_fallback(scrn, "Operation is too large (%d, %d)\n", width, height);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+Bool
+i830_check_composite_target(PixmapPtr pixmap)
+{
+ if (pixmap->drawable.width > 2048 || pixmap->drawable.height > 2048)
+ return FALSE;
+
+ if(!intel_check_pitch_3d(pixmap))
+ return FALSE;
+
return TRUE;
}
diff --git a/src/i830_uxa.c b/src/i830_uxa.c
index a79dde17..0a6b6f80 100644
--- a/src/i830_uxa.c
+++ b/src/i830_uxa.c
@@ -323,10 +323,10 @@ static void i830_uxa_done_solid(PixmapPtr pixmap)
* - support planemask using FULL_BLT_CMD?
*/
static Bool
-i830_uxa_check_copy(DrawablePtr source, DrawablePtr dest,
+i830_uxa_check_copy(PixmapPtr source, PixmapPtr dest,
int alu, Pixel planemask)
{
- ScrnInfoPtr scrn = xf86Screens[dest->pScreen->myNum];
+ ScrnInfoPtr scrn = xf86Screens[dest->drawable.pScreen->myNum];
intel_screen_private *intel = intel_get_screen_private(scrn);
if (IS_GEN6(intel)) {
@@ -335,16 +335,16 @@ i830_uxa_check_copy(DrawablePtr source, DrawablePtr dest,
return FALSE;
}
- if (!UXA_PM_IS_SOLID(source, planemask)) {
+ if (!UXA_PM_IS_SOLID(&source->drawable, planemask)) {
intel_debug_fallback(scrn, "planemask is not solid");
return FALSE;
}
- if (source->bitsPerPixel != dest->bitsPerPixel) {
+ if (source->drawable.bitsPerPixel != dest->drawable.bitsPerPixel) {
intel_debug_fallback(scrn, "mixed bpp copies unsupported\n");
return FALSE;
}
- switch (source->bitsPerPixel) {
+ switch (source->drawable.bitsPerPixel) {
case 8:
case 16:
case 32:
@@ -353,6 +353,11 @@ i830_uxa_check_copy(DrawablePtr source, DrawablePtr dest,
return FALSE;
}
+ if (!intel_check_pitch_2d(source))
+ return FALSE;
+ if (!intel_check_pitch_2d(dest))
+ return FALSE;
+
return TRUE;
}
@@ -368,11 +373,6 @@ i830_uxa_prepare_copy(PixmapPtr source, PixmapPtr dest, int xdir,
i830_get_pixmap_bo(dest),
};
- if (!intel_check_pitch_2d(source))
- return FALSE;
- if (!intel_check_pitch_2d(dest))
- return FALSE;
-
if (!i830_get_aperture_space(scrn, bo_table, ARRAY_SIZE(bo_table)))
return FALSE;
@@ -1076,6 +1076,7 @@ Bool i830_uxa_init(ScreenPtr screen)
/* Composite */
if (!IS_I9XX(intel)) {
intel->uxa_driver->check_composite = i830_check_composite;
+ intel->uxa_driver->check_composite_target = i830_check_composite_target;
intel->uxa_driver->check_composite_texture = i830_check_composite_texture;
intel->uxa_driver->prepare_composite = i830_prepare_composite;
intel->uxa_driver->composite = i830_composite;
@@ -1083,6 +1084,7 @@ Bool i830_uxa_init(ScreenPtr screen)
} else if (IS_I915G(intel) || IS_I915GM(intel) ||
IS_I945G(intel) || IS_I945GM(intel) || IS_G33CLASS(intel)) {
intel->uxa_driver->check_composite = i915_check_composite;
+ intel->uxa_driver->check_composite_target = i915_check_composite_target;
intel->uxa_driver->check_composite_texture = i915_check_composite_texture;
intel->uxa_driver->prepare_composite = i915_prepare_composite;
intel->uxa_driver->composite = i915_composite;
diff --git a/src/i915_render.c b/src/i915_render.c
index f9988b91..4eb40466 100644
--- a/src/i915_render.c
+++ b/src/i915_render.c
@@ -184,7 +184,8 @@ Bool
i915_check_composite(int op,
PicturePtr source_picture,
PicturePtr mask_picture,
- PicturePtr dest_picture)
+ PicturePtr dest_picture,
+ int width, int height)
{
ScrnInfoPtr scrn = xf86Screens[dest_picture->pDrawable->pScreen->myNum];
uint32_t tmp1;
@@ -216,6 +217,21 @@ i915_check_composite(int op,
return FALSE;
}
+ if (width > 2048 || height > 2048)
+ return FALSE;
+
+ return TRUE;
+}
+
+Bool
+i915_check_composite_target(PixmapPtr pixmap)
+{
+ if (pixmap->drawable.width > 2048 || pixmap->drawable.height > 2048)
+ return FALSE;
+
+ if(!intel_check_pitch_3d(pixmap))
+ return FALSE;
+
return TRUE;
}
diff --git a/src/i965_render.c b/src/i965_render.c
index ccfc0088..ed4b4d90 100644
--- a/src/i965_render.c
+++ b/src/i965_render.c
@@ -196,8 +196,11 @@ static Bool i965_get_dest_format(PicturePtr dest_picture, uint32_t * dst_format)
}
Bool
-i965_check_composite(int op, PicturePtr source_picture, PicturePtr mask_picture,
- PicturePtr dest_picture)
+i965_check_composite(int op,
+ PicturePtr source_picture,
+ PicturePtr mask_picture,
+ PicturePtr dest_picture,
+ int width, int height)
{
ScrnInfoPtr scrn = xf86Screens[dest_picture->pDrawable->pScreen->myNum];
intel_screen_private *intel = intel_get_screen_private(scrn);
diff --git a/uxa/uxa-accel.c b/uxa/uxa-accel.c
index 0528d796..77963f39 100644
--- a/uxa/uxa-accel.c
+++ b/uxa/uxa-accel.c
@@ -103,7 +103,7 @@ uxa_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int n,
goto solid;
}
- if (!uxa_screen->info->check_composite(PictOpSrc, src, NULL, dst)) {
+ if (!uxa_screen->info->check_composite(PictOpSrc, src, NULL, dst, 0, 0)) {
FreePicture(src, 0);
FreePicture(dst, 0);
goto solid;
@@ -586,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,
@@ -1121,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 921297a5..93a738ed 100644
--- a/uxa/uxa-glyphs.c
+++ b/uxa/uxa-glyphs.c
@@ -656,7 +656,7 @@ uxa_glyphs_try_driver_composite(CARD8 op,
int nrect;
if (uxa_screen->info->check_composite &&
- !(*uxa_screen->info->check_composite) (op, pSrc, buffer->source, pDst)) {
+ !(*uxa_screen->info->check_composite) (op, pSrc, buffer->source, pDst, 0, 0)) {
return -1;
}
@@ -787,7 +787,7 @@ uxa_glyphs_try_driver_add_to_mask(PicturePtr pDst,
int nrect;
if (uxa_screen->info->check_composite &&
- !(*uxa_screen->info->check_composite) (PictOpAdd, buffer->source, NULL, pDst)) {
+ !(*uxa_screen->info->check_composite) (PictOpAdd, buffer->source, NULL, pDst, 0, 0)) {
return -1;
}
@@ -1109,13 +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)
{
- ScreenPtr pScreen = pDst->pDrawable->pScreen;
- uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
- PixmapPtr pMaskPixmap = 0;
- PicturePtr pMask;
+ 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;
@@ -1123,13 +1122,16 @@ 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_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;
}
@@ -1161,55 +1163,129 @@ uxa_glyphs(CARD8 op,
}
}
- 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;
ValidatePicture(pMask);
- } else {
- pMask = pDst;
- x = 0;
- y = 0;
}
buffer.count = 0;
@@ -1222,19 +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);
buffer.count = 0;
buffer.source = NULL;
- uxa_buffer_glyph(pScreen, &buffer, glyph, x, y);
+ uxa_buffer_glyph(screen, &buffer, glyph, x, y);
}
x += glyph->info.xOff;
@@ -1247,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-render.c b/uxa/uxa-render.c
index c866b854..ec59871b 100644
--- a/uxa/uxa-render.c
+++ b/uxa/uxa-render.c
@@ -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,6 +973,7 @@ 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;
@@ -985,9 +989,12 @@ uxa_solid_rects (CARD8 op,
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 {
@@ -997,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)) {
@@ -1053,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;
}
@@ -1108,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;
}
@@ -1126,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;
}
@@ -1141,13 +1216,15 @@ uxa_try_driver_composite(CARD8 op,
}
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;
}
@@ -1176,13 +1253,27 @@ uxa_try_driver_composite(CARD8 op,
}
(*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;
}
@@ -1240,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;
}
@@ -1325,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;
@@ -1343,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