summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2012-06-17 10:50:31 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2012-06-17 10:59:55 +0100
commit41aff56a1f452e409c7a49512a1d2824b74f3838 (patch)
tree6d0049fc2699b7ac97a8ea783df1610ea4ec4740 /src
parent222e6ff43ef683e82101fb360911fc01fbe00597 (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.c21
-rw-r--r--src/sna/gen3_render.c13
-rw-r--r--src/sna/gen5_render.c18
-rw-r--r--src/sna/gen6_render.c18
-rw-r--r--src/sna/gen7_render.c18
-rw-r--r--src/sna/sna_render.h8
-rw-r--r--src/sna/sna_tiling.c262
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,