[Mesa-dev] [PATCH 3/5] st/mesa: cache pipe_surface for GL_FRAMEBUFFER_SRGB changes

Marek Olšák maraeo at gmail.com
Mon Jun 5 16:50:24 UTC 2017


From: Marek Olšák <marek.olsak at amd.com>

---
 src/mesa/state_tracker/st_cb_eglimage.c |  7 ++++-
 src/mesa/state_tracker/st_cb_fbo.c      | 49 ++++++++++++++++-----------------
 src/mesa/state_tracker/st_cb_fbo.h      |  7 ++++-
 src/mesa/state_tracker/st_manager.c     |  7 ++++-
 4 files changed, 41 insertions(+), 29 deletions(-)

diff --git a/src/mesa/state_tracker/st_cb_eglimage.c b/src/mesa/state_tracker/st_cb_eglimage.c
index a104b64..0f649f4 100644
--- a/src/mesa/state_tracker/st_cb_eglimage.c
+++ b/src/mesa/state_tracker/st_cb_eglimage.c
@@ -151,21 +151,26 @@ st_egl_image_target_renderbuffer_storage(struct gl_context *ctx,
 
    ps = st_egl_image_get_surface(ctx, image_handle, PIPE_BIND_RENDER_TARGET,
 				 "glEGLImageTargetRenderbufferStorage");
    if (ps) {
       strb->Base.Width = ps->width;
       strb->Base.Height = ps->height;
       strb->Base.Format = st_pipe_format_to_mesa_format(ps->format);
       strb->Base._BaseFormat = st_pipe_format_to_base_format(ps->format);
       strb->Base.InternalFormat = strb->Base._BaseFormat;
 
-      pipe_surface_reference(&strb->surface, ps);
+      struct pipe_surface **psurf =
+         util_format_is_srgb(ps->format) ? &strb->surface_srgb :
+                                           &strb->surface_linear;
+
+      pipe_surface_reference(psurf, ps);
+      strb->surface = *psurf;
       pipe_resource_reference(&strb->texture, ps->texture);
 
       pipe_surface_reference(&ps, NULL);
    }
 }
 
 static void
 st_bind_surface(struct gl_context *ctx, GLenum target,
                 struct gl_texture_object *texObj,
                 struct gl_texture_image *texImage,
diff --git a/src/mesa/state_tracker/st_cb_fbo.c b/src/mesa/state_tracker/st_cb_fbo.c
index f908225..ac8d665 100644
--- a/src/mesa/state_tracker/st_cb_fbo.c
+++ b/src/mesa/state_tracker/st_cb_fbo.c
@@ -105,41 +105,41 @@ st_renderbuffer_alloc_sw_storage(struct gl_context * ctx,
  * This is called to allocate the original drawing surface, and
  * during window resize.
  */
 static GLboolean
 st_renderbuffer_alloc_storage(struct gl_context * ctx,
                               struct gl_renderbuffer *rb,
                               GLenum internalFormat,
                               GLuint width, GLuint height)
 {
    struct st_context *st = st_context(ctx);
-   struct pipe_context *pipe = st->pipe;
    struct pipe_screen *screen = st->pipe->screen;
    struct st_renderbuffer *strb = st_renderbuffer(rb);
    enum pipe_format format = PIPE_FORMAT_NONE;
-   struct pipe_surface surf_tmpl;
    struct pipe_resource templ;
 
    /* init renderbuffer fields */
    strb->Base.Width  = width;
    strb->Base.Height = height;
    strb->Base._BaseFormat = _mesa_base_fbo_format(ctx, internalFormat);
    strb->defined = GL_FALSE;  /* undefined contents now */
 
    if (strb->software) {
       return st_renderbuffer_alloc_sw_storage(ctx, rb, internalFormat,
                                               width, height);
    }
 
    /* Free the old surface and texture
     */
-   pipe_surface_reference( &strb->surface, NULL );
+   pipe_surface_reference(&strb->surface_srgb, NULL);
+   pipe_surface_reference(&strb->surface_linear, NULL);
+   strb->surface = NULL;
    pipe_resource_reference( &strb->texture, NULL );
 
    /* If an sRGB framebuffer is unsupported, sRGB formats behave like linear
     * formats.
     */
    if (!ctx->Extensions.EXT_framebuffer_sRGB) {
       internalFormat = _mesa_get_linear_internalformat(internalFormat);
    }
 
    /* Handle multisample renderbuffers first.
@@ -208,45 +208,37 @@ st_renderbuffer_alloc_storage(struct gl_context * ctx,
       /* this is a window-system buffer */
       templ.bind = (PIPE_BIND_DISPLAY_TARGET |
                     PIPE_BIND_RENDER_TARGET);
    }
 
    strb->texture = screen->resource_create(screen, &templ);
 
    if (!strb->texture)
       return FALSE;
 
-   u_surface_default_template(&surf_tmpl, strb->texture);
-   strb->surface = pipe->create_surface(pipe,
-                                        strb->texture,
-                                        &surf_tmpl);
-   if (strb->surface) {
-      assert(strb->surface->texture);
-      assert(strb->surface->format);
-      assert(strb->surface->width == width);
-      assert(strb->surface->height == height);
-   }
-
+   st_update_renderbuffer_surface(st, strb);
    return strb->surface != NULL;
 }
 
 
 /**
  * gl_renderbuffer::Delete()
  */
 static void
 st_renderbuffer_delete(struct gl_context *ctx, struct gl_renderbuffer *rb)
 {
    struct st_renderbuffer *strb = st_renderbuffer(rb);
    if (ctx) {
       struct st_context *st = st_context(ctx);
-      pipe_surface_release(st->pipe, &strb->surface);
+      pipe_surface_release(st->pipe, &strb->surface_srgb);
+      pipe_surface_release(st->pipe, &strb->surface_linear);
+      strb->surface = NULL;
    }
    pipe_resource_reference(&strb->texture, NULL);
    free(strb->data);
    _mesa_delete_renderbuffer(ctx, rb);
 }
 
 
 /**
  * Called via ctx->Driver.NewRenderbuffer()
  */
@@ -443,41 +435,46 @@ st_update_renderbuffer_surface(struct st_context *st,
    if (strb->is_rtt && resource->array_size > 1 &&
        stTexObj->base.Immutable) {
       const struct gl_texture_object *tex = &stTexObj->base;
       first_layer += tex->MinLayer;
       if (!strb->rtt_layered)
          last_layer += tex->MinLayer;
       else
          last_layer = MIN2(first_layer + tex->NumLayers - 1, last_layer);
    }
 
-   if (!strb->surface ||
-       strb->surface->texture->nr_samples != strb->Base.NumSamples ||
-       strb->surface->format != format ||
-       strb->surface->texture != resource ||
-       strb->surface->width != rtt_width ||
-       strb->surface->height != rtt_height ||
-       strb->surface->u.tex.level != level ||
-       strb->surface->u.tex.first_layer != first_layer ||
-       strb->surface->u.tex.last_layer != last_layer) {
+   struct pipe_surface **psurf =
+      enable_srgb ? &strb->surface_srgb : &strb->surface_linear;
+   struct pipe_surface *surf = *psurf;
+
+   if (!surf ||
+       surf->texture->nr_samples != strb->Base.NumSamples ||
+       surf->format != format ||
+       surf->texture != resource ||
+       surf->width != rtt_width ||
+       surf->height != rtt_height ||
+       surf->u.tex.level != level ||
+       surf->u.tex.first_layer != first_layer ||
+       surf->u.tex.last_layer != last_layer) {
       /* create a new pipe_surface */
       struct pipe_surface surf_tmpl;
       memset(&surf_tmpl, 0, sizeof(surf_tmpl));
       surf_tmpl.format = format;
       surf_tmpl.u.tex.level = level;
       surf_tmpl.u.tex.first_layer = first_layer;
       surf_tmpl.u.tex.last_layer = last_layer;
 
-      pipe_surface_release(pipe, &strb->surface);
+      pipe_surface_release(pipe, psurf);
 
-      strb->surface = pipe->create_surface(pipe, resource, &surf_tmpl);
+      *psurf = pipe->create_surface(pipe, resource, &surf_tmpl);
    }
+   strb->surface = *psurf;
 }
 
 /**
  * Called by ctx->Driver.RenderTexture
  */
 static void
 st_render_texture(struct gl_context *ctx,
                   struct gl_framebuffer *fb,
                   struct gl_renderbuffer_attachment *att)
 {
diff --git a/src/mesa/state_tracker/st_cb_fbo.h b/src/mesa/state_tracker/st_cb_fbo.h
index 351fb9a..239bfd9 100644
--- a/src/mesa/state_tracker/st_cb_fbo.h
+++ b/src/mesa/state_tracker/st_cb_fbo.h
@@ -41,21 +41,26 @@ struct dd_function_table;
 struct pipe_context;
 
 /**
  * Derived renderbuffer class.  Just need to add a pointer to the
  * pipe surface.
  */
 struct st_renderbuffer
 {
    struct gl_renderbuffer Base;
    struct pipe_resource *texture;
-   struct pipe_surface *surface; /* temporary view into texture */
+   /* This points to either "surface_linear" or "surface_srgb".
+    * It doesn't hold the pipe_surface reference. The other two do.
+    */
+   struct pipe_surface *surface;
+   struct pipe_surface *surface_linear;
+   struct pipe_surface *surface_srgb;
    GLboolean defined;        /**< defined contents? */
 
    struct pipe_transfer *transfer; /**< only used when mapping the resource */
 
    /**
     * Used only when hardware accumulation buffers are not supported.
     */
    boolean software;
    void *data;
 
diff --git a/src/mesa/state_tracker/st_manager.c b/src/mesa/state_tracker/st_manager.c
index cc781f4..d0f32ff 100644
--- a/src/mesa/state_tracker/st_manager.c
+++ b/src/mesa/state_tracker/st_manager.c
@@ -210,21 +210,26 @@ st_framebuffer_validate(struct st_framebuffer *stfb,
       strb = st_renderbuffer(stfb->Base.Attachment[idx].Renderbuffer);
       assert(strb);
       if (strb->texture == textures[i]) {
          pipe_resource_reference(&textures[i], NULL);
          continue;
       }
 
       u_surface_default_template(&surf_tmpl, textures[i]);
       ps = st->pipe->create_surface(st->pipe, textures[i], &surf_tmpl);
       if (ps) {
-         pipe_surface_reference(&strb->surface, ps);
+         struct pipe_surface **psurf =
+            util_format_is_srgb(ps->format) ? &strb->surface_srgb :
+                                              &strb->surface_linear;
+
+         pipe_surface_reference(psurf, ps);
+         strb->surface = *psurf;
          pipe_resource_reference(&strb->texture, ps->texture);
          /* ownership transfered */
          pipe_surface_reference(&ps, NULL);
 
          changed = TRUE;
 
          strb->Base.Width = strb->surface->width;
          strb->Base.Height = strb->surface->height;
 
          width = strb->Base.Width;
-- 
2.7.4



More information about the mesa-dev mailing list