diff options
author | Zhigang Gong <zhigang.gong@linux.intel.com> | 2012-06-27 12:53:40 +0800 |
---|---|---|
committer | Zhigang Gong <zhigang.gong@linux.intel.com> | 2012-07-03 18:30:16 +0800 |
commit | 4c368b12c1af317c79469f8b6b809997d1769080 (patch) | |
tree | 3af126874a159a8f6f128259473927527af40970 /src | |
parent | ecc70624ca77478a46e9fb9487d76c74c6be1d8f (diff) |
glamor_compositerects: Implement optimized version.
Don't call miCompositeRects. Use glamor_composite_clipped_region
to render those boxes at once.
Also add a new function glamor_solid_boxes to fill boxes at once.
Signed-off-by: Zhigang Gong <zhigang.gong@linux.intel.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 1 | ||||
-rw-r--r-- | src/glamor.c | 8 | ||||
-rw-r--r-- | src/glamor_compositerects.c | 278 | ||||
-rw-r--r-- | src/glamor_fill.c | 181 | ||||
-rw-r--r-- | src/glamor_priv.h | 14 | ||||
-rw-r--r-- | src/glamor_utils.h | 6 |
6 files changed, 439 insertions, 49 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index e29f918..766aac7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -48,6 +48,7 @@ libglamor_la_SOURCES = \ glamor_window.c\ glamor_gl_dispatch.c\ glamor_fbo.c\ + glamor_compositerects.c\ glamor.h sdk_HEADERS = glamor.h diff --git a/src/glamor.c b/src/glamor.c index a0046f9..01f6a9a 100644 --- a/src/glamor.c +++ b/src/glamor.c @@ -383,6 +383,7 @@ glamor_init(ScreenPtr screen, unsigned int flags) glamor_priv->saved_procs.composite = ps->Composite; ps->Composite = glamor_composite; + glamor_priv->saved_procs.trapezoids = ps->Trapezoids; ps->Trapezoids = glamor_trapezoids; @@ -395,6 +396,9 @@ glamor_init(ScreenPtr screen, unsigned int flags) } + glamor_priv->saved_procs.composite_rects = ps->CompositeRects; + ps->CompositeRects = glamor_composite_rectangles; + glamor_priv->saved_procs.glyphs = ps->Glyphs; ps->Glyphs = glamor_glyphs; @@ -510,10 +514,12 @@ glamor_close_screen(int idx, ScreenPtr screen) ps->Composite = glamor_priv->saved_procs.composite; ps->Trapezoids = glamor_priv->saved_procs.trapezoids; - ps->Glyphs = glamor_priv->saved_procs.glyphs; ps->Triangles = glamor_priv->saved_procs.triangles; ps->CreatePicture = glamor_priv->saved_procs.create_picture; } + ps->CompositeRects = glamor_priv->saved_procs.composite_rects; + ps->Glyphs = glamor_priv->saved_procs.glyphs; + ps->UnrealizeGlyph = glamor_priv->saved_procs.unrealize_glyph; #endif screen_pixmap = screen->GetScreenPixmap(screen); glamor_set_pixmap_private(screen_pixmap, NULL); diff --git a/src/glamor_compositerects.c b/src/glamor_compositerects.c new file mode 100644 index 0000000..5fe1bbf --- /dev/null +++ b/src/glamor_compositerects.c @@ -0,0 +1,278 @@ +/* + * Copyright © 2009 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Zhigang Gong <zhigang.gong@linux.intel.com> + * + * original author is Chris Wilson at sna. + * + */ + +#include "glamor_priv.h" +#include "mipict.h" +#include "damage.h" + +/** @file glamor_compositerects. + * + * compositeRects acceleration implementation + */ + +static int16_t bound(int16_t a, uint16_t b) +{ + int v = (int)a + (int)b; + if (v > MAXSHORT) + return MAXSHORT; + return v; +} + +static Bool +_pixman_region_init_clipped_rectangles(pixman_region16_t *region, + unsigned int num_rects, + xRectangle *rects, + int tx, int ty, + BoxPtr extents) +{ + pixman_box16_t stack_boxes[64], *boxes = stack_boxes; + pixman_bool_t ret; + unsigned int i, j; + + if (num_rects > ARRAY_SIZE(stack_boxes)) { + boxes = malloc(sizeof(pixman_box16_t) * num_rects); + if (boxes == NULL) + return FALSE; + } + + for (i = j = 0; i < num_rects; i++) { + boxes[j].x1 = rects[i].x + tx; + if (boxes[j].x1 < extents->x1) + boxes[j].x1 = extents->x1; + + boxes[j].y1 = rects[i].y + ty; + if (boxes[j].y1 < extents->y1) + boxes[j].y1 = extents->y1; + + boxes[j].x2 = bound(rects[i].x + tx, rects[i].width); + if (boxes[j].x2 > extents->x2) + boxes[j].x2 = extents->x2; + + boxes[j].y2 = bound(rects[i].y + ty, rects[i].height); + if (boxes[j].y2 > extents->y2) + boxes[j].y2 = extents->y2; + + if (boxes[j].x2 > boxes[j].x1 && boxes[j].y2 > boxes[j].y1) + j++; + } + + ret = FALSE; + if (j) + ret = pixman_region_init_rects(region, boxes, j); + + if (boxes != stack_boxes) + free(boxes); + + DEBUGF("%s: nrects=%d, region=(%d, %d), (%d, %d) x %d\n", + __FUNCTION__, num_rects, + region->extents.x1, region->extents.y1, + region->extents.x2, region->extents.y2, + j); + return ret; +} + + +void +glamor_composite_rectangles(CARD8 op, + PicturePtr dst, + xRenderColor *color, + int num_rects, + xRectangle *rects) +{ + PixmapPtr pixmap; + struct glamor_pixmap_private *priv; + pixman_region16_t region; + pixman_box16_t *boxes; + int dst_x, dst_y; + int num_boxes; + PicturePtr source = NULL; + Bool need_free_region = FALSE; + + DEBUGF("%s(op=%d, %08x x %d [(%d, %d)x(%d, %d) ...])\n", + __FUNCTION__, op, + (color->alpha >> 8 << 24) | + (color->red >> 8 << 16) | + (color->green >> 8 << 8) | + (color->blue >> 8 << 0), + num_rects, + rects[0].x, rects[0].y, rects[0].width, rects[0].height); + + if (!num_rects) + return; + + if (region_is_empty(dst->pCompositeClip)) { + DEBUGF("%s: empty clip, skipping\n", __FUNCTION__); + return; + } + + pixmap = glamor_get_drawable_pixmap(dst->pDrawable); + priv = glamor_get_pixmap_private(pixmap); + + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(priv)) + goto fallback; + if (dst->alphaMap) { + DEBUGF("%s: fallback, dst has an alpha-map\n", __FUNCTION__); + goto fallback; + } + + if ((color->red|color->green|color->blue|color->alpha) <= 0x00ff) { + switch (op) { + case PictOpOver: + case PictOpOutReverse: + case PictOpAdd: + return; + case PictOpInReverse: + case PictOpSrc: + op = PictOpClear; + break; + case PictOpAtopReverse: + op = PictOpOut; + break; + case PictOpXor: + op = PictOpOverReverse; + break; + } + } + if (color->alpha <= 0x00ff) { + switch (op) { + case PictOpOver: + case PictOpOutReverse: + return; + case PictOpInReverse: + op = PictOpClear; + break; + case PictOpAtopReverse: + op = PictOpOut; + break; + case PictOpXor: + op = PictOpOverReverse; + break; + } + } else if (color->alpha >= 0xff00) { + switch (op) { + case PictOpOver: + op = PictOpSrc; + break; + case PictOpInReverse: + return; + case PictOpOutReverse: + op = PictOpClear; + break; + case PictOpAtopReverse: + op = PictOpOverReverse; + break; + case PictOpXor: + op = PictOpOut; + break; + } + } + DEBUGF("%s: converted to op %d\n", __FUNCTION__, op); + + if (!_pixman_region_init_clipped_rectangles(®ion, + num_rects, rects, + dst->pDrawable->x, + dst->pDrawable->y, + &dst->pCompositeClip->extents)) + { + DEBUGF("%s: allocation failed for region\n", __FUNCTION__); + return; + } + + need_free_region = TRUE; + + DEBUGF("%s: drawable extents (%d, %d),(%d, %d) x %d\n", + __FUNCTION__, + RegionExtents(®ion)->x1, RegionExtents(®ion)->y1, + RegionExtents(®ion)->x2, RegionExtents(®ion)->y2, + RegionNumRects(®ion)); + + if (dst->pCompositeClip->data && + (!pixman_region_intersect(®ion, ®ion, dst->pCompositeClip) || + region_is_empty(®ion))) { + DEBUGF(("%s: zero-intersection between rectangles and clip\n", + __FUNCTION__)); + pixman_region_fini(®ion); + return; + } + + DEBUGF("%s: clipped extents (%d, %d),(%d, %d) x %d\n", + __FUNCTION__, + RegionExtents(®ion)->x1, RegionExtents(®ion)->y1, + RegionExtents(®ion)->x2, RegionExtents(®ion)->y2, + RegionNumRects(®ion)); + + glamor_get_drawable_deltas(dst->pDrawable, pixmap, &dst_x, &dst_y); + pixman_region_translate(®ion, dst_x, dst_y); + + DEBUGF("%s: pixmap +(%d, %d) extents (%d, %d),(%d, %d)\n", + __FUNCTION__, dst_x, dst_y, + RegionExtents(®ion)->x1, RegionExtents(®ion)->y1, + RegionExtents(®ion)->x2, RegionExtents(®ion)->y2); + + + boxes = pixman_region_rectangles(®ion, &num_boxes); + if (op == PictOpSrc || op == PictOpClear) { + CARD32 pixel; + if (op == PictOpClear) + pixel = 0; + else + miRenderColorToPixel(dst->pFormat, color, &pixel); + glamor_solid_boxes(pixmap, boxes, num_boxes, pixel); + + goto done; + } else { + if (likely(priv->type != GLAMOR_TEXTURE_LARGE)) { + int error; + + source = CreateSolidPicture(0, color, &error); + if (!source) + goto done; + if (glamor_composite_clipped_region(op, source, + NULL, dst, + NULL, NULL, priv, + ®ion, + 0,0,0,0,0,0)) + goto done; + } + } +fallback: + miCompositeRects(op, dst, color, num_rects, rects); +done: + /* XXX xserver-1.8: CompositeRects is not tracked by Damage, so we must + * manually append the damaged regions ourselves. + */ + DamageRegionAppend(&pixmap->drawable, ®ion); + DamageRegionProcessPending(&pixmap->drawable); + + if (need_free_region) + pixman_region_fini(®ion); + if (source) + FreePicture(source, 0); + return; +} diff --git a/src/glamor_fill.c b/src/glamor_fill.c index e371148..2163c94 100644 --- a/src/glamor_fill.c +++ b/src/glamor_fill.c @@ -181,6 +181,87 @@ glamor_fini_solid_shader(ScreenPtr screen) } static void +_glamor_solid_boxes(PixmapPtr pixmap, BoxPtr box, int nbox, float *color) +{ + ScreenPtr screen = pixmap->drawable.pScreen; + glamor_screen_private *glamor_priv = + glamor_get_screen_private(screen); + glamor_pixmap_private *pixmap_priv = + glamor_get_pixmap_private(pixmap); + glamor_gl_dispatch *dispatch; + GLfloat xscale, yscale; + float vertices[32]; + float *pvertices = vertices; + int valid_nbox = ARRAY_SIZE(vertices); + + glamor_set_destination_pixmap_priv_nc(pixmap_priv); + + dispatch = glamor_get_dispatch(glamor_priv); + dispatch->glUseProgram(glamor_priv->solid_prog); + + dispatch->glUniform4fv(glamor_priv->solid_color_uniform_location, + 1, color); + + pixmap_priv_get_dest_scale(pixmap_priv, &xscale, &yscale); + + if (unlikely(nbox*4*2 > ARRAY_SIZE(vertices))) { + int allocated_box; + + if (nbox * 6 > GLAMOR_COMPOSITE_VBO_VERT_CNT) { + allocated_box = GLAMOR_COMPOSITE_VBO_VERT_CNT / 6; + } else + allocated_box = nbox; + pvertices = malloc(allocated_box * 4 * 2 * sizeof(float)); + if (pvertices) + valid_nbox = allocated_box; + else { + pvertices = vertices; + valid_nbox = ARRAY_SIZE(vertices) / (4*2); + } + } + +#define GLAMOR_COMPOSITE_VBO_VERT_CNT 1024 + if (unlikely(nbox > 1)) + dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ebo); + + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, + GL_FALSE, 2 * sizeof(float), + pvertices); + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); + + while(nbox) { + int box_cnt, i; + float *valid_vertices; + valid_vertices = pvertices; + box_cnt = nbox > valid_nbox ? valid_nbox : nbox; + for (i = 0; i < box_cnt; i++) { + glamor_set_normalize_vcoords(pixmap_priv, xscale, yscale, + box[i].x1, box[i].y1, + box[i].x2, box[i].y2, + glamor_priv->yInverted, + valid_vertices); + valid_vertices += 4*2; + } + if (box_cnt == 1) + dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, box_cnt * 4); + else + dispatch->glDrawElements(GL_TRIANGLES, + box_cnt * 6, + GL_UNSIGNED_SHORT, + NULL); + nbox -= box_cnt; + box += box_cnt; + } + + if (pvertices != vertices) + free(pvertices); + + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glUseProgram(0); + glamor_put_dispatch(glamor_priv); +} + +static void _glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, float *color) { @@ -222,15 +303,11 @@ _glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, } Bool -glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, - unsigned char alu, unsigned long planemask, - unsigned long fg_pixel) +glamor_solid_boxes(PixmapPtr pixmap, + BoxPtr box, int nbox, + unsigned long fg_pixel) { - ScreenPtr screen = pixmap->drawable.pScreen; - glamor_screen_private *glamor_priv = - glamor_get_screen_private(screen); glamor_pixmap_private *pixmap_priv; - glamor_gl_dispatch *dispatch; GLfloat color[4]; pixmap_priv = glamor_get_pixmap_private(pixmap); @@ -238,69 +315,81 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) return FALSE; - if (!glamor_set_planemask(pixmap, planemask)) { - glamor_fallback - ("Failedto set planemask in glamor_solid.\n"); - return FALSE; - } - glamor_get_rgba_from_pixel(fg_pixel, &color[0], &color[1], &color[2], &color[3], format_for_pixmap(pixmap)); - dispatch = glamor_get_dispatch(glamor_priv); - if (!glamor_set_alu(dispatch, alu)) { - if (alu == GXclear) - color[0] = color[1] = color[2] = color[3] = 0.0; - else { - glamor_fallback("unsupported alu %x\n", alu); - glamor_put_dispatch(glamor_priv); - return FALSE; - } - } - if (pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { RegionRec region; - BoxRec box; int n_region; glamor_pixmap_clipped_regions *clipped_regions; - int i,j; + int i; - box.x1 = x; - box.y1 = y; - box.x2 = x + width; - box.y2 = y + height; - RegionInitBoxes(®ion, &box, 1); + RegionInitBoxes(®ion, box, nbox); clipped_regions = glamor_compute_clipped_regions(pixmap_priv, ®ion, &n_region, 0, 0, 0); for(i = 0; i < n_region; i++) { - BoxPtr boxes; - int nbox; + BoxPtr inner_box; + int inner_nbox; SET_PIXMAP_FBO_CURRENT(pixmap_priv, clipped_regions[i].block_idx); - boxes = RegionRects(clipped_regions[i].region); - nbox = RegionNumRects(clipped_regions[i].region); - for(j = 0; j < nbox; j++) - { - _glamor_solid(pixmap, boxes[j].x1, boxes[j].y1, - boxes[j].x2 - boxes[j].x1, - boxes[j].y2 - boxes[j].y1, color); - } + inner_box = RegionRects(clipped_regions[i].region); + inner_nbox = RegionNumRects(clipped_regions[i].region); + _glamor_solid_boxes(pixmap, inner_box, inner_nbox, color); RegionDestroy(clipped_regions[i].region); } free(clipped_regions); RegionUninit(®ion); } else - _glamor_solid(pixmap, - x, - y, - width, height, - color); + _glamor_solid_boxes(pixmap, box, nbox, color); + + return TRUE; +} + +Bool +glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, + unsigned char alu, unsigned long planemask, + unsigned long fg_pixel) +{ + ScreenPtr screen = pixmap->drawable.pScreen; + glamor_screen_private *glamor_priv = + glamor_get_screen_private(screen); + glamor_pixmap_private *pixmap_priv; + glamor_gl_dispatch *dispatch; + BoxRec box; + + pixmap_priv = glamor_get_pixmap_private(pixmap); + + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) + return FALSE; + + if (!glamor_set_planemask(pixmap, planemask)) { + glamor_fallback + ("Failedto set planemask in glamor_solid.\n"); + return FALSE; + } + + dispatch = glamor_get_dispatch(glamor_priv); + if (!glamor_set_alu(dispatch, alu)) { + if (alu == GXclear) + fg_pixel = 0; + else { + glamor_fallback("unsupported alu %x\n", alu); + glamor_put_dispatch(glamor_priv); + return FALSE; + } + } + box.x1 = x; + box.y1 = y; + box.x2 = x + width; + box.y2 = y + height; + glamor_solid_boxes(pixmap, &box, 1, fg_pixel); glamor_set_alu(dispatch, GXcopy); glamor_put_dispatch(glamor_priv); return TRUE; } + diff --git a/src/glamor_priv.h b/src/glamor_priv.h index 61551df..a7d4fe7 100644 --- a/src/glamor_priv.h +++ b/src/glamor_priv.h @@ -210,6 +210,7 @@ struct glamor_saved_procs { GetSpansProcPtr get_spans; GetImageProcPtr get_image; CompositeProcPtr composite; + CompositeRectsProcPtr composite_rects; TrapezoidsProcPtr trapezoids; GlyphsProcPtr glyphs; ChangeWindowAttributesProcPtr change_window_attributes; @@ -644,8 +645,10 @@ Bool glamor_fill(DrawablePtr drawable, Bool glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, unsigned char alu, unsigned long planemask, unsigned long fg_pixel); -void glamor_solid_fail_region(PixmapPtr pixmap, - int x, int y, int width, int height); +Bool +glamor_solid_boxes(PixmapPtr pixmap, + BoxPtr box, int nbox, + unsigned long fg_pixel); /* glamor_fillspans.c */ void glamor_fill_spans(DrawablePtr drawable, @@ -988,6 +991,13 @@ void glamor_poly_line(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, DDXPointPtr ppt); +void +glamor_composite_rectangles(CARD8 op, + PicturePtr dst, + xRenderColor *color, + int num_rects, + xRectangle *rects); + #include"glamor_utils.h" /* Dynamic pixmap upload to texture if needed. diff --git a/src/glamor_utils.h b/src/glamor_utils.h index 88c6616..a282985 100644 --- a/src/glamor_utils.h +++ b/src/glamor_utils.h @@ -792,6 +792,12 @@ glamor_translate_boxes(BoxPtr boxes, int nbox, int dx, int dy) } } +static inline Bool +region_is_empty(pixman_region16_t *region) +{ + return region->data && region->data->numRects == 0; +} + #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) #define ALIGN(i,m) (((i) + (m) - 1) & ~((m) - 1)) #define MIN(a,b) ((a) < (b) ? (a) : (b)) |