summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2011-12-21 21:35:06 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2011-12-22 11:51:58 +0000
commit354dc3c65b9cb86885b6927ee2b80cd2ee6a82ff (patch)
tree0832fed023663ea8d28d12722d226d328300a9b0
parent34cfa15e522ba486d591d37f37d494e399f70354 (diff)
sna: Avoid fallbacks for convolutions by rendering the convolved texture
If we have no shader support for generic convolutions, we currently create the convolved texture using pixman. A multipass accumulation algorithm can be implemented on top of CompositePicture, so try it! Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--src/sna/sna_accel.c5
-rw-r--r--src/sna/sna_render.c104
2 files changed, 109 insertions, 0 deletions
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 33a75c10..b3fc05ba 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -491,6 +491,11 @@ sna_pixmap_create_scratch(ScreenPtr screen,
if (tiling == I915_TILING_Y && !sna->have_render)
tiling = I915_TILING_X;
+ if (tiling == I915_TILING_Y &&
+ (width > sna->render.max_3d_size ||
+ height > sna->render.max_3d_size))
+ tiling = I915_TILING_X;
+
bpp = BitsPerPixel(depth);
tiling = kgem_choose_tiling(&sna->kgem, tiling, width, height, bpp);
if (!kgem_can_create_2d(&sna->kgem, width, height, bpp, tiling))
diff --git a/src/sna/sna_render.c b/src/sna/sna_render.c
index 341cf2c8..72b3f78f 100644
--- a/src/sna/sna_render.c
+++ b/src/sna/sna_render.c
@@ -921,6 +921,99 @@ sna_render_picture_extract(struct sna *sna,
return 1;
}
+static int
+sna_render_picture_convolve(struct sna *sna,
+ PicturePtr picture,
+ struct sna_composite_channel *channel,
+ int16_t x, int16_t y,
+ int16_t w, int16_t h,
+ int16_t dst_x, int16_t dst_y)
+{
+ ScreenPtr screen = picture->pDrawable->pScreen;
+ PixmapPtr pixmap;
+ PicturePtr tmp;
+ pixman_fixed_t *params = picture->filter_params;
+ int x_off = (params[0] - pixman_fixed_1) >> 1;
+ int y_off = (params[1] - pixman_fixed_1) >> 1;
+ int cw = pixman_fixed_to_int(params[0]);
+ int ch = pixman_fixed_to_int(params[1]);
+ int i, j, error, depth;
+
+ /* Lame multi-pass accumulation implementation of a general convolution
+ * that works everywhere.
+ */
+
+ assert(picture->pDrawable);
+ assert(picture->filter == PictFilterConvolution);
+ assert(w <= sna->render.max_3d_size && h <= sna->render.max_3d_size);
+
+ if (PICT_FORMAT_RGB(picture->format) == 0) {
+ channel->pict_format = PIXMAN_a8;
+ depth = 8;
+ } else {
+ channel->pict_format = PIXMAN_a8r8g8b8;
+ depth = 32;
+ }
+
+ pixmap = screen->CreatePixmap(screen, w, h, depth, SNA_CREATE_SCRATCH);
+ if (pixmap == NullPixmap)
+ return 0;
+
+ tmp = CreatePicture(0, &pixmap->drawable,
+ PictureMatchFormat(screen, depth, channel->pict_format),
+ 0, NULL, serverClient, &error);
+ screen->DestroyPixmap(pixmap);
+ if (tmp == NULL)
+ return 0;
+
+ if (!sna->render.fill_one(sna, pixmap, sna_pixmap_get_bo(pixmap), 0,
+ 0, 0, w, h, GXclear)) {
+ FreePicture(tmp, 0);
+ return 0;
+ }
+
+ picture->filter = PictFilterBilinear;
+ params += 2;
+ for (j = 0; j < ch; j++) {
+ for (i = 0; i < cw; i++) {
+ xRenderColor color;
+ PicturePtr alpha;
+
+ color.alpha = *params++;
+ color.red = color.green = color.blue = 0;
+
+ if (color.alpha <= 0x00ff)
+ continue;
+
+ alpha = CreateSolidPicture(0, &color, &error);
+ if (alpha) {
+ sna_composite(PictOpAdd, picture, alpha, tmp,
+ x, y,
+ 0, 0,
+ x_off-i, y_off-j,
+ w, h);
+ FreePicture(alpha, 0);
+ }
+ }
+ }
+ picture->filter = PictFilterConvolution;
+
+ channel->height = h;
+ channel->width = w;
+ channel->filter = PictFilterNearest;
+ channel->repeat = RepeatNone;
+ channel->is_affine = TRUE;
+ channel->transform = NULL;
+ channel->scale[0] = 1.f / w;
+ channel->scale[1] = 1.f / h;
+ channel->offset[0] = -dst_x;
+ channel->offset[1] = -dst_y;
+ channel->bo = kgem_bo_reference(sna_pixmap_get_bo(pixmap));
+ FreePicture(tmp, 0);
+
+ return 1;
+}
+
int
sna_render_picture_fixup(struct sna *sna,
PicturePtr picture,
@@ -949,6 +1042,17 @@ sna_render_picture_fixup(struct sna *sna,
return -1;
}
+ if (picture->filter == PictFilterConvolution) {
+ DBG(("%s: convolution\n", __FUNCTION__));
+ if (picture->pDrawable && is_gpu(picture->pDrawable)) {
+ return sna_render_picture_convolve(sna, picture, channel,
+ x, y, w, y, dst_x, dst_y);
+ }
+
+ goto do_fixup;
+ }
+
+do_fixup:
if (PICT_FORMAT_RGB(picture->format) == 0) {
pitch = ALIGN(w, 4);
channel->pict_format = PIXMAN_a8;