[Mesa-dev] [PATCH] u_blitter: Do blits in linear color space.

Henri Verbeet hverbeet at gmail.com
Wed Mar 9 12:31:41 PST 2011


Blits between sRGB and linear formats should happen in linear color space.
This fixes piglit fbo/fbo-srgb-blit.
---
 src/gallium/auxiliary/util/u_blit.c    |   57 ++++++++++++++++++++------------
 src/gallium/auxiliary/util/u_blitter.c |    3 +-
 src/mesa/state_tracker/st_cb_texture.c |    2 +-
 3 files changed, 39 insertions(+), 23 deletions(-)

diff --git a/src/gallium/auxiliary/util/u_blit.c b/src/gallium/auxiliary/util/u_blit.c
index 76bd7ac..3618353 100644
--- a/src/gallium/auxiliary/util/u_blit.c
+++ b/src/gallium/auxiliary/util/u_blit.c
@@ -304,8 +304,10 @@ util_blit_pixels_writemask(struct blit_state *ctx,
 {
    struct pipe_context *pipe = ctx->pipe;
    struct pipe_screen *screen = pipe->screen;
+   enum pipe_format src_format, dst_format;
    struct pipe_sampler_view *sampler_view = NULL;
    struct pipe_sampler_view sv_templ;
+   struct pipe_surface *dst_surface;
    struct pipe_framebuffer_state fb;
    const int srcW = abs(srcX1 - srcX0);
    const int srcH = abs(srcY1 - srcY0);
@@ -326,12 +328,15 @@ util_blit_pixels_writemask(struct blit_state *ctx,
       regions_overlap(srcX0, srcY0, srcX1, srcY1,
                       dstX0, dstY0, dstX1, dstY1);
 
+   src_format = util_format_linear(src_tex->format);
+   dst_format = util_format_linear(dst->format);
+
    /*
     * Check for simple case:  no format conversion, no flipping, no stretching,
     * no overlapping.
     * Filter mode should not matter since there's no stretching.
     */
-   if (dst->format == src_tex->format &&
+   if (dst_format == src_format &&
        srcX0 < srcX1 &&
        dstX0 < dstX1 &&
        srcY0 < srcY1 &&
@@ -354,6 +359,14 @@ util_blit_pixels_writemask(struct blit_state *ctx,
        return;
    }
 
+   if (dst_format == dst->format) {
+      dst_surface = dst;
+   } else {
+      struct pipe_surface templ = *dst;
+      templ.format = dst_format;
+      dst_surface = pipe->create_surface(pipe, dst->texture, &templ);
+   }
+
    /* Create a temporary texture when src and dest alias or when src
     * is anything other than a 2d texture.
     * XXX should just use appropriate shader to access 1d / 3d slice / cube face,
@@ -361,9 +374,9 @@ util_blit_pixels_writemask(struct blit_state *ctx,
     * 
     * This can still be improved upon.
     */
-   if ((src_tex == dst->texture &&
-       dst->u.tex.level == src_level &&
-       dst->u.tex.first_layer == srcZ0) ||
+   if ((src_tex == dst_surface->texture &&
+       dst_surface->u.tex.level == src_level &&
+       dst_surface->u.tex.first_layer == srcZ0) ||
        (src_tex->target != PIPE_TEXTURE_2D &&
        src_tex->target != PIPE_TEXTURE_2D &&
        src_tex->target != PIPE_TEXTURE_RECT))
@@ -392,7 +405,7 @@ util_blit_pixels_writemask(struct blit_state *ctx,
       /* create temp texture */
       memset(&texTemp, 0, sizeof(texTemp));
       texTemp.target = ctx->internal_target;
-      texTemp.format = src_tex->format;
+      texTemp.format = src_format;
       texTemp.last_level = 0;
       texTemp.width0 = srcW;
       texTemp.height0 = srcH;
@@ -439,7 +452,7 @@ util_blit_pixels_writemask(struct blit_state *ctx,
       pipe_resource_reference(&tex, NULL);
    }
    else {
-      u_sampler_view_default_template(&sv_templ, src_tex, src_tex->format);
+      u_sampler_view_default_template(&sv_templ, src_tex, src_format);
       sampler_view = pipe->create_sampler_view(pipe, src_tex, &sv_templ);
 
       if (!sampler_view) {
@@ -460,13 +473,13 @@ util_blit_pixels_writemask(struct blit_state *ctx,
       }
    }
 
-   dst_is_depth = util_format_is_depth_or_stencil(dst->format);
+   dst_is_depth = util_format_is_depth_or_stencil(dst_format);
 
    assert(screen->is_format_supported(screen, sampler_view->format, ctx->internal_target,
                                       sampler_view->texture->nr_samples,
                                       PIPE_BIND_SAMPLER_VIEW, 0));
-   assert(screen->is_format_supported(screen, dst->format, ctx->internal_target,
-                                      dst->texture->nr_samples,
+   assert(screen->is_format_supported(screen, dst_format, ctx->internal_target,
+                                      dst_surface->texture->nr_samples,
                                       dst_is_depth ? PIPE_BIND_DEPTH_STENCIL :
                                                      PIPE_BIND_RENDER_TARGET, 0));
    /* save state (restored below) */
@@ -502,12 +515,12 @@ util_blit_pixels_writemask(struct blit_state *ctx,
    cso_single_sampler_done(ctx->cso);
 
    /* viewport */
-   ctx->viewport.scale[0] = 0.5f * dst->width;
-   ctx->viewport.scale[1] = 0.5f * dst->height;
+   ctx->viewport.scale[0] = 0.5f * dst_surface->width;
+   ctx->viewport.scale[1] = 0.5f * dst_surface->height;
    ctx->viewport.scale[2] = 0.5f;
    ctx->viewport.scale[3] = 1.0f;
-   ctx->viewport.translate[0] = 0.5f * dst->width;
-   ctx->viewport.translate[1] = 0.5f * dst->height;
+   ctx->viewport.translate[0] = 0.5f * dst_surface->width;
+   ctx->viewport.translate[1] = 0.5f * dst_surface->height;
    ctx->viewport.translate[2] = 0.5f;
    ctx->viewport.translate[3] = 0.0f;
    cso_set_viewport(ctx->cso, &ctx->viewport);
@@ -536,22 +549,22 @@ util_blit_pixels_writemask(struct blit_state *ctx,
 
    /* drawing dest */
    memset(&fb, 0, sizeof(fb));
-   fb.width = dst->width;
-   fb.height = dst->height;
+   fb.width = dst_surface->width;
+   fb.height = dst_surface->height;
    if (dst_is_depth) {
-      fb.zsbuf = dst;
+      fb.zsbuf = dst_surface;
    } else {
       fb.nr_cbufs = 1;
-      fb.cbufs[0] = dst;
+      fb.cbufs[0] = dst_surface;
    }
    cso_set_framebuffer(ctx->cso, &fb);
 
    /* draw quad */
    offset = setup_vertex_data_tex(ctx,
-                                  (float) dstX0 / dst->width * 2.0f - 1.0f,
-                                  (float) dstY0 / dst->height * 2.0f - 1.0f,
-                                  (float) dstX1 / dst->width * 2.0f - 1.0f,
-                                  (float) dstY1 / dst->height * 2.0f - 1.0f,
+                                  (float) dstX0 / dst_surface->width * 2.0f - 1.0f,
+                                  (float) dstY0 / dst_surface->height * 2.0f - 1.0f,
+                                  (float) dstX1 / dst_surface->width * 2.0f - 1.0f,
+                                  (float) dstY1 / dst_surface->height * 2.0f - 1.0f,
                                   s0, t0,
                                   s1, t1,
                                   z);
@@ -576,6 +589,8 @@ util_blit_pixels_writemask(struct blit_state *ctx,
    cso_restore_vertex_buffers(ctx->cso);
 
    pipe_sampler_view_reference(&sampler_view, NULL);
+   if (dst_surface != dst)
+      pipe_surface_reference(&dst_surface, NULL);
 }
 
 
diff --git a/src/gallium/auxiliary/util/u_blitter.c b/src/gallium/auxiliary/util/u_blitter.c
index fd1c2b7..287f5da 100644
--- a/src/gallium/auxiliary/util/u_blitter.c
+++ b/src/gallium/auxiliary/util/u_blitter.c
@@ -785,6 +785,7 @@ void util_blitter_copy_region(struct blitter_context *blitter,
    /* Get surface. */
    memset(&surf_templ, 0, sizeof(surf_templ));
    u_surface_default_template(&surf_templ, dst, bind);
+   surf_templ.format = util_format_linear(dst->format);
    surf_templ.u.tex.level = dstlevel;
    surf_templ.u.tex.first_layer = dstz;
    surf_templ.u.tex.last_layer = dstz;
@@ -823,7 +824,7 @@ void util_blitter_copy_region(struct blitter_context *blitter,
    normalized = src->target != PIPE_TEXTURE_RECT;
 
    /* Initialize sampler view. */
-   u_sampler_view_default_template(&viewTempl, src, src->format);
+   u_sampler_view_default_template(&viewTempl, src, util_format_linear(src->format));
    view = pipe->create_sampler_view(pipe, src, &viewTempl);
 
    /* Set rasterizer state, shaders, and textures. */
diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c
index 3f98ffd..ab2d645 100644
--- a/src/mesa/state_tracker/st_cb_texture.c
+++ b/src/mesa/state_tracker/st_cb_texture.c
@@ -1533,7 +1533,7 @@ st_copy_texsubimage(struct gl_context *ctx,
          GLint srcY0, srcY1;
          struct pipe_surface surf_tmpl;
          memset(&surf_tmpl, 0, sizeof(surf_tmpl));
-         surf_tmpl.format = stImage->pt->format;
+         surf_tmpl.format = util_format_linear(stImage->pt->format);
          surf_tmpl.usage = PIPE_BIND_RENDER_TARGET;
          surf_tmpl.u.tex.level = stImage->level;
          surf_tmpl.u.tex.first_layer = stImage->face + destZ;
-- 
1.7.2.3



More information about the mesa-dev mailing list