summaryrefslogtreecommitdiff
path: root/uxa
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2010-05-18 22:16:17 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2010-05-23 18:43:29 +0100
commite5c971e7639095d38da3518a5dc404b708d45cfb (patch)
treee63d12aec9842acc42480064a6e4924f045fc402 /uxa
parent509df27c7401e96d3062890da73f6af6629adef4 (diff)
uxa: Spans! OMG!
Use composite rather than solid blits in order to bring performance on a par with the CPU when using GEM and relocations. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'uxa')
-rw-r--r--uxa/uxa-accel.c181
-rw-r--r--uxa/uxa-priv.h11
-rw-r--r--uxa/uxa-render.c22
3 files changed, 187 insertions, 27 deletions
diff --git a/uxa/uxa-accel.c b/uxa/uxa-accel.c
index cfc2d381..0528d796 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)) {
+ 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
diff --git a/uxa/uxa-priv.h b/uxa/uxa-priv.h
index a4763b41..8ff2c9c6 100644
--- a/uxa/uxa-priv.h
+++ b/uxa/uxa-priv.h
@@ -434,6 +434,17 @@ 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);
+
+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..68e36515 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,
@@ -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);
@@ -974,17 +974,13 @@ uxa_solid_rects (CARD8 op,
!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;