diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2012-06-17 10:50:31 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2012-06-17 10:59:55 +0100 |
commit | 41aff56a1f452e409c7a49512a1d2824b74f3838 (patch) | |
tree | 6d0049fc2699b7ac97a8ea783df1610ea4ec4740 /src | |
parent | 222e6ff43ef683e82101fb360911fc01fbe00597 (diff) |
sna: Add tiling for spans
Semmingly only advisable when already committed to using the GPU. This
first pass is still a little naive as it makes no attempt to avoid empty
tiles, nor aims to be efficient.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'src')
-rw-r--r-- | src/sna/gen2_render.c | 21 | ||||
-rw-r--r-- | src/sna/gen3_render.c | 13 | ||||
-rw-r--r-- | src/sna/gen5_render.c | 18 | ||||
-rw-r--r-- | src/sna/gen6_render.c | 18 | ||||
-rw-r--r-- | src/sna/gen7_render.c | 18 | ||||
-rw-r--r-- | src/sna/sna_render.h | 8 | ||||
-rw-r--r-- | src/sna/sna_tiling.c | 262 |
7 files changed, 341 insertions, 17 deletions
diff --git a/src/sna/gen2_render.c b/src/sna/gen2_render.c index e67dd95a..5fd995b3 100644 --- a/src/sna/gen2_render.c +++ b/src/sna/gen2_render.c @@ -2220,14 +2220,23 @@ gen2_render_composite_spans(struct sna *sna, return FALSE; } - if (!gen2_check_dst_format(dst->format)) { - DBG(("%s: fallback due to unhandled dst format: %x\n", - __FUNCTION__, dst->format)); + if (gen2_composite_fallback(sna, src, NULL, dst)) return FALSE; - } - if (need_tiling(sna, width, height)) - return FALSE; + if (need_tiling(sna, width, height)) { + DBG(("%s: tiling, operation (%dx%d) too wide for pipeline\n", + __FUNCTION__, width, height)); + + if (!is_gpu(dst->pDrawable)) { + DBG(("%s: fallback, tiled operation not on GPU\n", + __FUNCTION__)); + return FALSE; + } + + return sna_tiling_composite_spans(op, src, dst, + src_x, src_y, dst_x, dst_y, + width, height, flags, tmp); + } if (!gen2_composite_set_target(sna, &tmp->base, dst)) { DBG(("%s: unable to set render target\n", diff --git a/src/sna/gen3_render.c b/src/sna/gen3_render.c index 62b3a8e8..54ec9b29 100644 --- a/src/sna/gen3_render.c +++ b/src/sna/gen3_render.c @@ -3392,9 +3392,18 @@ gen3_render_composite_spans(struct sna *sna, return FALSE; if (need_tiling(sna, width, height)) { - DBG(("%s: fallback, operation (%dx%d) too wide for pipeline\n", + DBG(("%s: tiling, operation (%dx%d) too wide for pipeline\n", __FUNCTION__, width, height)); - return FALSE; + + if (!is_gpu(dst->pDrawable)) { + DBG(("%s: fallback, tiled operation not on GPU\n", + __FUNCTION__)); + return FALSE; + } + + return sna_tiling_composite_spans(op, src, dst, + src_x, src_y, dst_x, dst_y, + width, height, flags, tmp); } if (!gen3_composite_set_target(sna, &tmp->base, dst)) { diff --git a/src/sna/gen5_render.c b/src/sna/gen5_render.c index e31ac5c1..65c21c36 100644 --- a/src/sna/gen5_render.c +++ b/src/sna/gen5_render.c @@ -2785,12 +2785,24 @@ gen5_render_composite_spans(struct sna *sna, if (op >= ARRAY_SIZE(gen5_blend_op)) return FALSE; - if (need_tiling(sna, width, height)) - return FALSE; - if (gen5_composite_fallback(sna, src, NULL, dst)) return FALSE; + if (need_tiling(sna, width, height)) { + DBG(("%s: tiling, operation (%dx%d) too wide for pipeline\n", + __FUNCTION__, width, height)); + + if (!is_gpu(dst->pDrawable)) { + DBG(("%s: fallback, tiled operation not on GPU\n", + __FUNCTION__)); + return FALSE; + } + + return sna_tiling_composite_spans(op, src, dst, + src_x, src_y, dst_x, dst_y, + width, height, flags, tmp); + } + tmp->base.op = op; if (!gen5_composite_set_target(dst, &tmp->base)) return FALSE; diff --git a/src/sna/gen6_render.c b/src/sna/gen6_render.c index d613fe16..b927d08e 100644 --- a/src/sna/gen6_render.c +++ b/src/sna/gen6_render.c @@ -3088,12 +3088,24 @@ gen6_render_composite_spans(struct sna *sna, if (op >= ARRAY_SIZE(gen6_blend_op)) return FALSE; - if (need_tiling(sna, width, height)) - return FALSE; - if (gen6_composite_fallback(sna, src, NULL, dst)) return FALSE; + if (need_tiling(sna, width, height)) { + DBG(("%s: tiling, operation (%dx%d) too wide for pipeline\n", + __FUNCTION__, width, height)); + + if (!is_gpu(dst->pDrawable)) { + DBG(("%s: fallback, tiled operation not on GPU\n", + __FUNCTION__)); + return FALSE; + } + + return sna_tiling_composite_spans(op, src, dst, + src_x, src_y, dst_x, dst_y, + width, height, flags, tmp); + } + tmp->base.op = op; if (!gen6_composite_set_target(sna, &tmp->base, dst)) return FALSE; diff --git a/src/sna/gen7_render.c b/src/sna/gen7_render.c index a7c498e9..46425493 100644 --- a/src/sna/gen7_render.c +++ b/src/sna/gen7_render.c @@ -3172,12 +3172,24 @@ gen7_render_composite_spans(struct sna *sna, if (op >= ARRAY_SIZE(gen7_blend_op)) return FALSE; - if (need_tiling(sna, width, height)) - return FALSE; - if (gen7_composite_fallback(sna, src, NULL, dst)) return FALSE; + if (need_tiling(sna, width, height)) { + DBG(("%s: tiling, operation (%dx%d) too wide for pipeline\n", + __FUNCTION__, width, height)); + + if (!is_gpu(dst->pDrawable)) { + DBG(("%s: fallback, tiled operation not on GPU\n", + __FUNCTION__)); + return FALSE; + } + + return sna_tiling_composite_spans(op, src, dst, + src_x, src_y, dst_x, dst_y, + width, height, flags, tmp); + } + tmp->base.op = op; if (!gen7_composite_set_target(sna, &tmp->base, dst)) return FALSE; diff --git a/src/sna/sna_render.h b/src/sna/sna_render.h index 48982238..fd42b217 100644 --- a/src/sna/sna_render.h +++ b/src/sna/sna_render.h @@ -517,6 +517,14 @@ Bool sna_tiling_composite(uint32_t op, int16_t dst_x, int16_t dst_y, int16_t width, int16_t height, struct sna_composite_op *tmp); +Bool sna_tiling_composite_spans(uint32_t op, + PicturePtr src, + PicturePtr dst, + int16_t src_x, int16_t src_y, + int16_t dst_x, int16_t dst_y, + int16_t width, int16_t height, + unsigned flags, + struct sna_composite_spans_op *tmp); Bool sna_tiling_fill_boxes(struct sna *sna, CARD8 op, PictFormat format, diff --git a/src/sna/sna_tiling.c b/src/sna/sna_tiling.c index 33fee42e..16b90cad 100644 --- a/src/sna/sna_tiling.c +++ b/src/sna/sna_tiling.c @@ -39,6 +39,11 @@ #define DBG(x) ErrorF x #endif +struct sna_tile_span { + BoxRec box; + float opacity; +}; + struct sna_tile_state { int op; PicturePtr src, mask, dst; @@ -48,6 +53,7 @@ struct sna_tile_state { int16_t mask_x, mask_y; int16_t dst_x, dst_y; int16_t width, height; + unsigned flags; int rect_count; int rect_size; @@ -318,6 +324,262 @@ sna_tiling_composite(uint32_t op, return TRUE; } +fastcall static void +sna_tiling_composite_spans_box(struct sna *sna, + const struct sna_composite_spans_op *op, + const BoxRec *box, float opacity) +{ + struct sna_tile_state *tile = op->base.priv; + struct sna_tile_span *a; + + if (tile->rect_count == tile->rect_size) { + int newsize = tile->rect_size * 2; + + if (tile->rects == tile->rects_embedded) { + a = malloc (sizeof(struct sna_tile_span) * newsize); + if (a == NULL) + return; + + memcpy(a, + tile->rects_embedded, + sizeof(struct sna_tile_span) * tile->rect_count); + } else { + a = realloc(tile->rects, + sizeof(struct sna_tile_span) * newsize); + if (a == NULL) + return; + } + + tile->rects = (void *)a; + tile->rect_size = newsize; + } else + a = (void *)tile->rects; + + a[tile->rect_count].box = *box; + a[tile->rect_count].opacity = opacity; + tile->rect_count++; + (void)sna; +} + +static void +sna_tiling_composite_spans_boxes(struct sna *sna, + const struct sna_composite_spans_op *op, + const BoxRec *box, int nbox, float opacity) +{ + while (nbox--) + sna_tiling_composite_spans_box(sna, op->base.priv, box++, opacity); + (void)sna; +} + +fastcall static void +sna_tiling_composite_spans_done(struct sna *sna, + const struct sna_composite_spans_op *op) +{ + struct sna_tile_state *tile = op->base.priv; + struct sna_composite_spans_op tmp; + int x, y, n, step; + bool force_fallback = false; + + /* Use a small step to accommodate enlargement through tile alignment */ + step = sna->render.max_3d_size; + if (tile->dst_x & (8*512 / tile->dst->pDrawable->bitsPerPixel - 1) || + tile->dst_y & 63) + step /= 2; + while (step * step * 4 > sna->kgem.max_copy_tile_size) + step /= 2; + + DBG(("%s -- %dx%d, count=%d, step size=%d\n", __FUNCTION__, + tile->width, tile->height, tile->rect_count, step)); + + if (tile->rect_count == 0) + goto done; + + for (y = 0; y < tile->height; y += step) { + int height = step; + if (y + height > tile->height) + height = tile->height - y; + for (x = 0; x < tile->width; x += step) { + const struct sna_tile_span *r = (void *)tile->rects; + int width = step; + if (x + width > tile->width) + width = tile->width - x; + if (!force_fallback && + sna->render.composite_spans(sna, tile->op, + tile->src, tile->dst, + tile->src_x + x, tile->src_y + y, + tile->dst_x + x, tile->dst_y + y, + width, height, tile->flags, + memset(&tmp, 0, sizeof(tmp)))) { + for (n = 0; n < tile->rect_count; n++) { + BoxRec b; + + b.x1 = r->box.x1 - tile->dst_x; + if (b.x1 < x) + b.x1 = x; + + b.y1 = r->box.y1 - tile->dst_y; + if (b.y1 < y) + b.y1 = y; + + b.x2 = r->box.x2 - tile->dst_x; + if (b.x2 > x + width) + b.x2 = x + width; + + b.y2 = r->box.y2 - tile->dst_y; + if (b.y2 > y + height) + b.y2 = y + height; + + DBG(("%s: rect[%d] = (%d, %d)x(%d,%d), tile=(%d,%d)x(%d, %d), blt=(%d,%d),(%d,%d)\n", + __FUNCTION__, n, + r->dst.x, r->dst.y, + r->width, r->height, + x, y, width, height, + b.x1, b.y1, b.x2, b.y2)); + + if (b.y2 > b.y1 && b.x2 > b.x1) + tmp.box(sna, &tmp, &b, r->opacity); + r++; + } + tmp.done(sna, &tmp); + } else { + unsigned int flags; + + DBG(("%s -- falback\n", __FUNCTION__)); + + if (tile->op <= PictOpSrc) + flags = MOVE_WRITE; + else + flags = MOVE_WRITE | MOVE_READ; + if (!sna_drawable_move_to_cpu(tile->dst->pDrawable, + flags)) + goto done; + if (tile->dst->alphaMap && + !sna_drawable_move_to_cpu(tile->dst->alphaMap->pDrawable, + flags)) + goto done; + + if (tile->src->pDrawable && + !sna_drawable_move_to_cpu(tile->src->pDrawable, + MOVE_READ)) + goto done; + if (tile->src->alphaMap && + !sna_drawable_move_to_cpu(tile->src->alphaMap->pDrawable, + MOVE_READ)) + goto done; + + for (n = 0; n < tile->rect_count; n++) { + BoxRec b; + + b.x1 = r->box.x1 - tile->dst_x; + if (b.x1 < x) + b.x1 = x; + + b.y1 = r->box.y1 - tile->dst_y; + if (b.y1 < y) + b.y1 = y; + + b.x2 = r->box.x2 - tile->dst_x; + if (b.x2 > x + width) + b.x2 = x + width; + + b.y2 = r->box.y2 - tile->dst_y; + if (b.y2 > y + height) + b.y2 = y + height; + + DBG(("%s: rect[%d] = (%d, %d)x(%d,%d), tile=(%d,%d)x(%d, %d), blt=(%d,%d),(%d,%d)\n", + __FUNCTION__, n, + r->dst.x, r->dst.y, + r->width, r->height, + x, y, width, height, + b.x1, b.y1, b.x2, b.y2)); + + if (b.y2 > b.y1 && b.x2 > b.x1) { + xRenderColor alpha; + PicturePtr mask; + int error; + + alpha.red = alpha.green = alpha.blue = 0; + alpha.alpha = r->opacity * 0xffff; + + mask = CreateSolidPicture(0, &alpha, &error); + if (!mask) + goto done; + + fbComposite(tile->op, + tile->src, mask, tile->dst, + tile->src_x + x, tile->src_y + y, + 0, 0, + tile->dst_x + x, tile->dst_y + y, + width, height); + + FreePicture(mask, 0); + } + r++; + } + + force_fallback = true; + } + } + } + +done: + if (tile->rects != tile->rects_embedded) + free(tile->rects); + free(tile); +} + +Bool +sna_tiling_composite_spans(uint32_t op, + PicturePtr src, + PicturePtr dst, + int16_t src_x, int16_t src_y, + int16_t dst_x, int16_t dst_y, + int16_t width, int16_t height, + unsigned flags, + struct sna_composite_spans_op *tmp) +{ + struct sna_tile_state *tile; + struct sna_pixmap *priv; + + DBG(("%s size=(%d, %d), tile=%d\n", + __FUNCTION__, width, height, + to_sna_from_drawable(dst->pDrawable)->render.max_3d_size)); + + priv = sna_pixmap(get_drawable_pixmap(dst->pDrawable)); + if (priv == NULL || priv->gpu_bo == NULL) + return FALSE; + + tile = malloc(sizeof(*tile)); + if (!tile) + return FALSE; + + tile->op = op; + tile->flags = flags; + + tile->src = src; + tile->mask = NULL; + tile->dst = dst; + + tile->src_x = src_x; + tile->src_y = src_y; + tile->mask_x = 0; + tile->mask_y = 0; + tile->dst_x = dst_x; + tile->dst_y = dst_y; + tile->width = width; + tile->height = height; + tile->rects = tile->rects_embedded; + tile->rect_count = 0; + tile->rect_size = ARRAY_SIZE(tile->rects_embedded); + + tmp->box = sna_tiling_composite_spans_box; + tmp->boxes = sna_tiling_composite_spans_boxes; + tmp->done = sna_tiling_composite_spans_done; + + tmp->base.priv = tile; + return TRUE; +} + Bool sna_tiling_fill_boxes(struct sna *sna, CARD8 op, |