sna/gen2+: Approximate expensive gradients when using imprecise rendering
If we lack the ability to use a shader to compute the gradients per-pixel, we need to use pixman to render a fallback texture. We can reduce the size of this texture and upsample to reduce the cost with hopefully imperceptible loss of quality. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
parent
25807f472d
commit
62f9833298
|
|
@ -1310,7 +1310,8 @@ gen2_composite_picture(struct sna *sna,
|
|||
struct sna_composite_channel *channel,
|
||||
int x, int y,
|
||||
int w, int h,
|
||||
int dst_x, int dst_y)
|
||||
int dst_x, int dst_y,
|
||||
bool precise)
|
||||
{
|
||||
PixmapPtr pixmap;
|
||||
uint32_t color;
|
||||
|
|
@ -1343,6 +1344,8 @@ gen2_composite_picture(struct sna *sna,
|
|||
}
|
||||
|
||||
if (picture->pDrawable == NULL) {
|
||||
int ret;
|
||||
|
||||
if (picture->pSourcePict->type == SourcePictTypeLinear)
|
||||
return gen2_composite_linear_init(sna, picture, channel,
|
||||
x, y,
|
||||
|
|
@ -1351,8 +1354,14 @@ gen2_composite_picture(struct sna *sna,
|
|||
|
||||
DBG(("%s -- fallback, unhandled source %d\n",
|
||||
__FUNCTION__, picture->pSourcePict->type));
|
||||
return sna_render_picture_fixup(sna, picture, channel,
|
||||
x, y, w, h, dst_x, dst_y);
|
||||
ret = -1;
|
||||
if (!precise)
|
||||
ret = sna_render_picture_approximate_gradient(sna, picture, channel,
|
||||
x, y, w, h, dst_x, dst_y);
|
||||
if (ret == -1)
|
||||
ret = sna_render_picture_fixup(sna, picture, channel,
|
||||
x, y, w, h, dst_x, dst_y);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (picture->alphaMap) {
|
||||
|
|
@ -1765,7 +1774,8 @@ gen2_render_composite(struct sna *sna,
|
|||
switch (gen2_composite_picture(sna, src, &tmp->src,
|
||||
src_x, src_y,
|
||||
width, height,
|
||||
dst_x, dst_y)) {
|
||||
dst_x, dst_y,
|
||||
dst->polyMode == PolyModePrecise)) {
|
||||
case -1:
|
||||
goto cleanup_dst;
|
||||
case 0:
|
||||
|
|
@ -1781,7 +1791,8 @@ gen2_render_composite(struct sna *sna,
|
|||
switch (gen2_composite_picture(sna, mask, &tmp->mask,
|
||||
mask_x, mask_y,
|
||||
width, height,
|
||||
dst_x, dst_y)) {
|
||||
dst_x, dst_y,
|
||||
dst->polyMode == PolyModePrecise)) {
|
||||
case -1:
|
||||
goto cleanup_src;
|
||||
case 0:
|
||||
|
|
@ -2229,7 +2240,8 @@ gen2_render_composite_spans(struct sna *sna,
|
|||
switch (gen2_composite_picture(sna, src, &tmp->base.src,
|
||||
src_x, src_y,
|
||||
width, height,
|
||||
dst_x, dst_y)) {
|
||||
dst_x, dst_y,
|
||||
dst->polyMode == PolyModePrecise)) {
|
||||
case -1:
|
||||
goto cleanup_dst;
|
||||
case 0:
|
||||
|
|
|
|||
|
|
@ -2194,7 +2194,7 @@ gen3_init_linear(struct sna *sna,
|
|||
op->u.gen3.constants[n++] = 0;
|
||||
|
||||
if (!gen3_gradient_setup(sna, picture, channel, ox, oy))
|
||||
return 0;
|
||||
return -1;
|
||||
|
||||
channel->u.gen3.type = SHADER_LINEAR;
|
||||
op->u.gen3.num_constants = n;
|
||||
|
|
@ -2250,7 +2250,7 @@ gen3_init_radial(struct sna *sna,
|
|||
}
|
||||
|
||||
if (!gen3_gradient_setup(sna, picture, channel, ox, oy))
|
||||
return 0;
|
||||
return -1;
|
||||
|
||||
channel->u.gen3.type = SHADER_RADIAL;
|
||||
op->u.gen3.num_constants = n;
|
||||
|
|
@ -2285,7 +2285,8 @@ gen3_composite_picture(struct sna *sna,
|
|||
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)
|
||||
int16_t dst_x, int16_t dst_y,
|
||||
bool precise)
|
||||
{
|
||||
PixmapPtr pixmap;
|
||||
uint32_t color;
|
||||
|
|
@ -2298,7 +2299,7 @@ gen3_composite_picture(struct sna *sna,
|
|||
|
||||
if (picture->pDrawable == NULL) {
|
||||
SourcePict *source = picture->pSourcePict;
|
||||
int ret = 0;
|
||||
int ret = -1;
|
||||
|
||||
switch (source->type) {
|
||||
case SourcePictTypeSolidFill:
|
||||
|
|
@ -2316,9 +2317,14 @@ gen3_composite_picture(struct sna *sna,
|
|||
break;
|
||||
}
|
||||
|
||||
if (ret == 0)
|
||||
ret = sna_render_picture_fixup(sna, picture, channel,
|
||||
x, y, w, h, dst_x, dst_y);
|
||||
if (ret == -1) {
|
||||
if (!precise)
|
||||
ret = sna_render_picture_approximate_gradient(sna, picture, channel,
|
||||
x, y, w, h, dst_x, dst_y);
|
||||
if (ret == -1)
|
||||
ret = sna_render_picture_fixup(sna, picture, channel,
|
||||
x, y, w, h, dst_x, dst_y);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -2815,7 +2821,8 @@ gen3_render_composite(struct sna *sna,
|
|||
switch (gen3_composite_picture(sna, src, tmp, &tmp->src,
|
||||
src_x, src_y,
|
||||
width, height,
|
||||
dst_x, dst_y)) {
|
||||
dst_x, dst_y,
|
||||
dst->polyMode == PolyModePrecise)) {
|
||||
case -1:
|
||||
goto cleanup_dst;
|
||||
case 0:
|
||||
|
|
@ -2840,7 +2847,8 @@ gen3_render_composite(struct sna *sna,
|
|||
switch (gen3_composite_picture(sna, mask, tmp, &tmp->mask,
|
||||
mask_x, mask_y,
|
||||
width, height,
|
||||
dst_x, dst_y)) {
|
||||
dst_x, dst_y,
|
||||
dst->polyMode == PolyModePrecise)) {
|
||||
case -1:
|
||||
goto cleanup_src;
|
||||
case 0:
|
||||
|
|
@ -3379,7 +3387,8 @@ gen3_render_composite_spans(struct sna *sna,
|
|||
switch (gen3_composite_picture(sna, src, &tmp->base, &tmp->base.src,
|
||||
src_x, src_y,
|
||||
width, height,
|
||||
dst_x, dst_y)) {
|
||||
dst_x, dst_y,
|
||||
dst->polyMode == PolyModePrecise)) {
|
||||
case -1:
|
||||
goto cleanup_dst;
|
||||
case 0:
|
||||
|
|
|
|||
|
|
@ -1957,7 +1957,8 @@ gen4_composite_picture(struct sna *sna,
|
|||
struct sna_composite_channel *channel,
|
||||
int x, int y,
|
||||
int w, int h,
|
||||
int dst_x, int dst_y)
|
||||
int dst_x, int dst_y,
|
||||
bool precise)
|
||||
{
|
||||
PixmapPtr pixmap;
|
||||
uint32_t color;
|
||||
|
|
@ -1973,6 +1974,8 @@ gen4_composite_picture(struct sna *sna,
|
|||
return gen4_composite_solid_init(sna, channel, color);
|
||||
|
||||
if (picture->pDrawable == NULL) {
|
||||
int ret;
|
||||
|
||||
if (picture->pSourcePict->type == SourcePictTypeLinear)
|
||||
return gen4_composite_linear_init(sna, picture, channel,
|
||||
x, y,
|
||||
|
|
@ -1980,8 +1983,14 @@ gen4_composite_picture(struct sna *sna,
|
|||
dst_x, dst_y);
|
||||
|
||||
DBG(("%s -- fixup, gradient\n", __FUNCTION__));
|
||||
return sna_render_picture_fixup(sna, picture, channel,
|
||||
x, y, w, h, dst_x, dst_y);
|
||||
ret = -1;
|
||||
if (!precise)
|
||||
ret = sna_render_picture_approximate_gradient(sna, picture, channel,
|
||||
x, y, w, h, dst_x, dst_y);
|
||||
if (ret == -1)
|
||||
ret = sna_render_picture_fixup(sna, picture, channel,
|
||||
x, y, w, h, dst_x, dst_y);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (picture->alphaMap) {
|
||||
|
|
@ -2404,7 +2413,8 @@ gen4_render_composite(struct sna *sna,
|
|||
switch (gen4_composite_picture(sna, src, &tmp->src,
|
||||
src_x, src_y,
|
||||
width, height,
|
||||
dst_x, dst_y)) {
|
||||
dst_x, dst_y,
|
||||
dst->polyMode == PolyModePrecise)) {
|
||||
case -1:
|
||||
DBG(("%s: failed to prepare source\n", __FUNCTION__));
|
||||
goto cleanup_dst;
|
||||
|
|
@ -2449,7 +2459,8 @@ gen4_render_composite(struct sna *sna,
|
|||
switch (gen4_composite_picture(sna, mask, &tmp->mask,
|
||||
msk_x, msk_y,
|
||||
width, height,
|
||||
dst_x, dst_y)) {
|
||||
dst_x, dst_y,
|
||||
dst->polyMode == PolyModePrecise)) {
|
||||
case -1:
|
||||
DBG(("%s: failed to prepare mask\n", __FUNCTION__));
|
||||
goto cleanup_src;
|
||||
|
|
|
|||
|
|
@ -1990,7 +1990,8 @@ gen5_composite_picture(struct sna *sna,
|
|||
struct sna_composite_channel *channel,
|
||||
int x, int y,
|
||||
int w, int h,
|
||||
int dst_x, int dst_y)
|
||||
int dst_x, int dst_y,
|
||||
bool precise)
|
||||
{
|
||||
PixmapPtr pixmap;
|
||||
uint32_t color;
|
||||
|
|
@ -2006,6 +2007,8 @@ gen5_composite_picture(struct sna *sna,
|
|||
return gen5_composite_solid_init(sna, channel, color);
|
||||
|
||||
if (picture->pDrawable == NULL) {
|
||||
int ret;
|
||||
|
||||
if (picture->pSourcePict->type == SourcePictTypeLinear)
|
||||
return gen5_composite_linear_init(sna, picture, channel,
|
||||
x, y,
|
||||
|
|
@ -2013,8 +2016,14 @@ gen5_composite_picture(struct sna *sna,
|
|||
dst_x, dst_y);
|
||||
|
||||
DBG(("%s -- fixup, gradient\n", __FUNCTION__));
|
||||
return sna_render_picture_fixup(sna, picture, channel,
|
||||
x, y, w, h, dst_x, dst_y);
|
||||
ret = -1;
|
||||
if (!precise)
|
||||
ret = sna_render_picture_approximate_gradient(sna, picture, channel,
|
||||
x, y, w, h, dst_x, dst_y);
|
||||
if (ret == -1)
|
||||
ret = sna_render_picture_fixup(sna, picture, channel,
|
||||
x, y, w, h, dst_x, dst_y);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (picture->alphaMap) {
|
||||
|
|
@ -2444,7 +2453,8 @@ gen5_render_composite(struct sna *sna,
|
|||
switch (gen5_composite_picture(sna, src, &tmp->src,
|
||||
src_x, src_y,
|
||||
width, height,
|
||||
dst_x, dst_y)) {
|
||||
dst_x, dst_y,
|
||||
dst->polyMode == PolyModePrecise)) {
|
||||
case -1:
|
||||
DBG(("%s: failed to prepare source picture\n", __FUNCTION__));
|
||||
goto cleanup_dst;
|
||||
|
|
@ -2488,7 +2498,8 @@ gen5_render_composite(struct sna *sna,
|
|||
switch (gen5_composite_picture(sna, mask, &tmp->mask,
|
||||
msk_x, msk_y,
|
||||
width, height,
|
||||
dst_x, dst_y)) {
|
||||
dst_x, dst_y,
|
||||
dst->polyMode == PolyModePrecise)) {
|
||||
case -1:
|
||||
DBG(("%s: failed to prepare mask picture\n", __FUNCTION__));
|
||||
goto cleanup_src;
|
||||
|
|
@ -2800,7 +2811,8 @@ gen5_render_composite_spans(struct sna *sna,
|
|||
switch (gen5_composite_picture(sna, src, &tmp->base.src,
|
||||
src_x, src_y,
|
||||
width, height,
|
||||
dst_x, dst_y)) {
|
||||
dst_x, dst_y,
|
||||
dst->polyMode == PolyModePrecise)) {
|
||||
case -1:
|
||||
goto cleanup_dst;
|
||||
case 0:
|
||||
|
|
|
|||
|
|
@ -2165,7 +2165,8 @@ gen6_composite_picture(struct sna *sna,
|
|||
struct sna_composite_channel *channel,
|
||||
int x, int y,
|
||||
int w, int h,
|
||||
int dst_x, int dst_y)
|
||||
int dst_x, int dst_y,
|
||||
bool precise)
|
||||
{
|
||||
PixmapPtr pixmap;
|
||||
uint32_t color;
|
||||
|
|
@ -2181,6 +2182,8 @@ gen6_composite_picture(struct sna *sna,
|
|||
return gen6_composite_solid_init(sna, channel, color);
|
||||
|
||||
if (picture->pDrawable == NULL) {
|
||||
int ret;
|
||||
|
||||
if (picture->pSourcePict->type == SourcePictTypeLinear)
|
||||
return gen6_composite_linear_init(sna, picture, channel,
|
||||
x, y,
|
||||
|
|
@ -2188,8 +2191,14 @@ gen6_composite_picture(struct sna *sna,
|
|||
dst_x, dst_y);
|
||||
|
||||
DBG(("%s -- fixup, gradient\n", __FUNCTION__));
|
||||
return sna_render_picture_fixup(sna, picture, channel,
|
||||
x, y, w, h, dst_x, dst_y);
|
||||
ret = -1;
|
||||
if (!precise)
|
||||
ret = sna_render_picture_approximate_gradient(sna, picture, channel,
|
||||
x, y, w, h, dst_x, dst_y);
|
||||
if (ret == -1)
|
||||
ret = sna_render_picture_fixup(sna, picture, channel,
|
||||
x, y, w, h, dst_x, dst_y);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (picture->alphaMap) {
|
||||
|
|
@ -2646,7 +2655,8 @@ gen6_render_composite(struct sna *sna,
|
|||
switch (gen6_composite_picture(sna, src, &tmp->src,
|
||||
src_x, src_y,
|
||||
width, height,
|
||||
dst_x, dst_y)) {
|
||||
dst_x, dst_y,
|
||||
dst->polyMode == PolyModePrecise)) {
|
||||
case -1:
|
||||
goto cleanup_dst;
|
||||
case 0:
|
||||
|
|
@ -2702,7 +2712,8 @@ gen6_render_composite(struct sna *sna,
|
|||
switch (gen6_composite_picture(sna, mask, &tmp->mask,
|
||||
msk_x, msk_y,
|
||||
width, height,
|
||||
dst_x, dst_y)) {
|
||||
dst_x, dst_y,
|
||||
dst->polyMode == PolyModePrecise)) {
|
||||
case -1:
|
||||
goto cleanup_src;
|
||||
case 0:
|
||||
|
|
@ -3089,7 +3100,8 @@ gen6_render_composite_spans(struct sna *sna,
|
|||
switch (gen6_composite_picture(sna, src, &tmp->base.src,
|
||||
src_x, src_y,
|
||||
width, height,
|
||||
dst_x, dst_y)) {
|
||||
dst_x, dst_y,
|
||||
dst->polyMode == PolyModePrecise)) {
|
||||
case -1:
|
||||
goto cleanup_dst;
|
||||
case 0:
|
||||
|
|
|
|||
|
|
@ -2270,7 +2270,8 @@ gen7_composite_picture(struct sna *sna,
|
|||
struct sna_composite_channel *channel,
|
||||
int x, int y,
|
||||
int w, int h,
|
||||
int dst_x, int dst_y)
|
||||
int dst_x, int dst_y,
|
||||
bool precise)
|
||||
{
|
||||
PixmapPtr pixmap;
|
||||
uint32_t color;
|
||||
|
|
@ -2286,6 +2287,8 @@ gen7_composite_picture(struct sna *sna,
|
|||
return gen7_composite_solid_init(sna, channel, color);
|
||||
|
||||
if (picture->pDrawable == NULL) {
|
||||
int ret;
|
||||
|
||||
if (picture->pSourcePict->type == SourcePictTypeLinear)
|
||||
return gen7_composite_linear_init(sna, picture, channel,
|
||||
x, y,
|
||||
|
|
@ -2293,8 +2296,14 @@ gen7_composite_picture(struct sna *sna,
|
|||
dst_x, dst_y);
|
||||
|
||||
DBG(("%s -- fixup, gradient\n", __FUNCTION__));
|
||||
return sna_render_picture_fixup(sna, picture, channel,
|
||||
x, y, w, h, dst_x, dst_y);
|
||||
ret = -1;
|
||||
if (!precise)
|
||||
ret = sna_render_picture_approximate_gradient(sna, picture, channel,
|
||||
x, y, w, h, dst_x, dst_y);
|
||||
if (ret == -1)
|
||||
ret = sna_render_picture_fixup(sna, picture, channel,
|
||||
x, y, w, h, dst_x, dst_y);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (picture->alphaMap) {
|
||||
|
|
@ -2732,7 +2741,8 @@ gen7_render_composite(struct sna *sna,
|
|||
switch (gen7_composite_picture(sna, src, &tmp->src,
|
||||
src_x, src_y,
|
||||
width, height,
|
||||
dst_x, dst_y)) {
|
||||
dst_x, dst_y,
|
||||
dst->polyMode == PolyModePrecise)) {
|
||||
case -1:
|
||||
goto cleanup_dst;
|
||||
case 0:
|
||||
|
|
@ -2788,7 +2798,8 @@ gen7_render_composite(struct sna *sna,
|
|||
switch (gen7_composite_picture(sna, mask, &tmp->mask,
|
||||
msk_x, msk_y,
|
||||
width, height,
|
||||
dst_x, dst_y)) {
|
||||
dst_x, dst_y,
|
||||
dst->polyMode == PolyModePrecise)) {
|
||||
case -1:
|
||||
goto cleanup_src;
|
||||
case 0:
|
||||
|
|
@ -3185,7 +3196,8 @@ gen7_render_composite_spans(struct sna *sna,
|
|||
switch (gen7_composite_picture(sna, src, &tmp->base.src,
|
||||
src_x, src_y,
|
||||
width, height,
|
||||
dst_x, dst_y)) {
|
||||
dst_x, dst_y,
|
||||
dst->polyMode == PolyModePrecise)) {
|
||||
case -1:
|
||||
goto cleanup_dst;
|
||||
case 0:
|
||||
|
|
|
|||
|
|
@ -1368,6 +1368,92 @@ sna_render_picture_flatten(struct sna *sna,
|
|||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
sna_render_picture_approximate_gradient(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)
|
||||
{
|
||||
pixman_image_t *dst, *src;
|
||||
pixman_transform_t t;
|
||||
int w2 = w/2, h2 = h/2;
|
||||
int dx, dy;
|
||||
void *ptr;
|
||||
|
||||
#if NO_FIXUP
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
DBG(("%s: (%d, %d)x(%d, %d)\n", __FUNCTION__, x, y, w, h));
|
||||
|
||||
if (w2 == 0 || h2 == 0) {
|
||||
DBG(("%s: fallback - unknown bounds\n", __FUNCTION__));
|
||||
return -1;
|
||||
}
|
||||
if (w2 > sna->render.max_3d_size || h2 > sna->render.max_3d_size) {
|
||||
DBG(("%s: fallback - too large (%dx%d)\n", __FUNCTION__, w, h));
|
||||
return -1;
|
||||
}
|
||||
|
||||
channel->pict_format = PIXMAN_a8r8g8b8;
|
||||
channel->bo = kgem_create_buffer_2d(&sna->kgem,
|
||||
w2, h2, 32,
|
||||
KGEM_BUFFER_WRITE_INPLACE,
|
||||
&ptr);
|
||||
if (!channel->bo) {
|
||||
DBG(("%s: failed to create upload buffer, using clear\n",
|
||||
__FUNCTION__));
|
||||
return 0;
|
||||
}
|
||||
|
||||
dst = pixman_image_create_bits(PIXMAN_a8r8g8b8,
|
||||
w2, h2, ptr, channel->bo->pitch);
|
||||
if (!dst) {
|
||||
kgem_bo_destroy(&sna->kgem, channel->bo);
|
||||
return 0;
|
||||
}
|
||||
|
||||
src = image_from_pict(picture, FALSE, &dx, &dy);
|
||||
if (src == NULL) {
|
||||
pixman_image_unref(dst);
|
||||
kgem_bo_destroy(&sna->kgem, channel->bo);
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(&t, 0, sizeof(t));
|
||||
t.matrix[0][0] = (w << 16) / w2;
|
||||
t.matrix[1][1] = (h << 16) / h2;
|
||||
t.matrix[2][2] = 1 << 16;
|
||||
if (picture->transform)
|
||||
pixman_transform_multiply(&t, picture->transform, &t);
|
||||
pixman_image_set_transform(src, &t);
|
||||
|
||||
pixman_image_composite(PictOpSrc, src, NULL, dst,
|
||||
x + dx, y + dy,
|
||||
0, 0,
|
||||
0, 0,
|
||||
w2, h2);
|
||||
free_pixman_pict(picture, src);
|
||||
pixman_image_unref(dst);
|
||||
|
||||
channel->width = w2;
|
||||
channel->height = h2;
|
||||
|
||||
channel->filter = PictFilterNearest;
|
||||
channel->repeat = RepeatNone;
|
||||
channel->is_affine = TRUE;
|
||||
|
||||
channel->scale[0] = 1.f/w;
|
||||
channel->scale[1] = 1.f/h;
|
||||
channel->offset[0] = -dst_x;
|
||||
channel->offset[1] = -dst_y;
|
||||
channel->transform = NULL;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
sna_render_picture_fixup(struct sna *sna,
|
||||
PicturePtr picture,
|
||||
|
|
|
|||
|
|
@ -614,6 +614,14 @@ sna_render_picture_extract(struct sna *sna,
|
|||
int16_t w, int16_t h,
|
||||
int16_t dst_x, int16_t dst_y);
|
||||
|
||||
int
|
||||
sna_render_picture_approximate_gradient(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);
|
||||
|
||||
int
|
||||
sna_render_picture_fixup(struct sna *sna,
|
||||
PicturePtr picture,
|
||||
|
|
|
|||
Loading…
Reference in New Issue