st/mesa: add support for layered framebuffers and consolidate code
authorMarek Olšák <marek.olsak@amd.com>
Thu, 21 Nov 2013 14:31:32 +0000 (15:31 +0100)
committerMarek Olšák <marek.olsak@amd.com>
Tue, 3 Dec 2013 18:39:13 +0000 (19:39 +0100)
This is a subset of geometry shaders. It's all about setting first_layer and
last_layer correctly.

Also some code between st_render_texture and update_framebuffer_state is
consolidated. It doesn't use rtt_level and derives the level from dimensions
instead as the code in st_atom_framebuffer.c did.

src/mesa/state_tracker/st_atom_framebuffer.c
src/mesa/state_tracker/st_cb_drawpixels.c
src/mesa/state_tracker/st_cb_fbo.c
src/mesa/state_tracker/st_cb_fbo.h
src/mesa/state_tracker/st_cb_readpixels.c
src/mesa/state_tracker/st_cb_texture.c

index c752640f49d9a5da1a6daeeea84c2882fd8c2001..51f079cdad560b024a91227b4d887c8949b030b9 100644 (file)
 #include "util/u_format.h"
 
 
-/**
- * When doing GL render to texture, we have to be sure that finalize_texture()
- * didn't yank out the pipe_resource that we earlier created a surface for.
- * Check for that here and create a new surface if needed.
- */
-static void
-update_renderbuffer_surface(struct st_context *st,
-                            struct st_renderbuffer *strb)
-{
-   struct pipe_context *pipe = st->pipe;
-   struct pipe_resource *resource = strb->rtt ? strb->rtt->pt : strb->texture;
-   int rtt_width = strb->Base.Width;
-   int rtt_height = strb->Base.Height;
-   enum pipe_format format = st->ctx->Color.sRGBEnabled ? resource->format : util_format_linear(resource->format);
-
-   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) {
-      GLuint level;
-      /* find matching mipmap level size */
-      for (level = 0; level <= resource->last_level; level++) {
-         if (u_minify(resource->width0, level) == rtt_width &&
-             u_minify(resource->height0, level) == rtt_height) {
-            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 = strb->rtt_face + strb->rtt_slice;
-            surf_tmpl.u.tex.last_layer = strb->rtt_face + strb->rtt_slice;
-
-            pipe_surface_reference(&strb->surface, NULL);
-
-            strb->surface = pipe->create_surface(pipe,
-                                                 resource,
-                                                 &surf_tmpl);
-#if 0
-            printf("-- alloc new surface %d x %d into tex %p\n",
-                   strb->surface->width, strb->surface->height,
-                   texture);
-#endif
-            break;
-         }
-      }
-   }
-}
-
-
 /**
  * Update framebuffer state (color, depth, stencil, etc. buffers)
  */
@@ -121,10 +71,10 @@ update_framebuffer_state( struct st_context *st )
 
       if (strb) {
          /*printf("--------- framebuffer surface rtt %p\n", strb->rtt);*/
-         if (strb->rtt ||
+         if (strb->is_rtt ||
              (strb->texture && util_format_is_srgb(strb->texture->format))) {
             /* rendering to a GL texture, may have to update surface */
-            update_renderbuffer_surface(st, strb);
+            st_update_renderbuffer_surface(st, strb);
          }
 
          if (strb->surface) {
@@ -144,9 +94,9 @@ update_framebuffer_state( struct st_context *st )
     */
    strb = st_renderbuffer(fb->Attachment[BUFFER_DEPTH].Renderbuffer);
    if (strb) {
-      if (strb->rtt) {
+      if (strb->is_rtt) {
          /* rendering to a GL texture, may have to update surface */
-         update_renderbuffer_surface(st, strb);
+         st_update_renderbuffer_surface(st, strb);
       }
       pipe_surface_reference(&framebuffer->zsbuf, strb->surface);
    }
index 2ce4728ad8dffc975978d366d35745830982b4dc..3058dfb5bc7353c95d7cd5db97d51e31da43ad36 100644 (file)
@@ -878,7 +878,8 @@ draw_stencil_pixels(struct gl_context *ctx, GLint x, GLint y,
    }
 
    stmap = pipe_transfer_map(pipe, strb->texture,
-                             strb->rtt_level, strb->rtt_face + strb->rtt_slice,
+                             strb->surface->u.tex.level,
+                             strb->surface->u.tex.first_layer,
                              usage, x, y,
                              width, height, &pt);
 
@@ -1263,8 +1264,8 @@ copy_stencil_pixels(struct gl_context *ctx, GLint srcx, GLint srcy,
    /* map the stencil buffer */
    drawMap = pipe_transfer_map(pipe,
                                rbDraw->texture,
-                               rbDraw->rtt_level,
-                               rbDraw->rtt_face + rbDraw->rtt_slice,
+                               rbDraw->surface->u.tex.level,
+                               rbDraw->surface->u.tex.first_layer,
                                usage, dstx, dsty,
                                width, height, &ptDraw);
 
@@ -1422,20 +1423,20 @@ blit_copy_pixels(struct gl_context *ctx, GLint srcx, GLint srcy,
 
          memset(&blit, 0, sizeof(blit));
          blit.src.resource = rbRead->texture;
-         blit.src.level = rbRead->rtt_level;
+         blit.src.level = rbRead->surface->u.tex.level;
          blit.src.format = rbRead->texture->format;
          blit.src.box.x = readX;
          blit.src.box.y = readY;
-         blit.src.box.z = rbRead->rtt_face + rbRead->rtt_slice;
+         blit.src.box.z = rbRead->surface->u.tex.first_layer;
          blit.src.box.width = readW;
          blit.src.box.height = readH;
          blit.src.box.depth = 1;
          blit.dst.resource = rbDraw->texture;
-         blit.dst.level = rbDraw->rtt_level;
+         blit.dst.level = rbDraw->surface->u.tex.level;
          blit.dst.format = rbDraw->texture->format;
          blit.dst.box.x = drawX;
          blit.dst.box.y = drawY;
-         blit.dst.box.z = rbDraw->rtt_face + rbDraw->rtt_slice;
+         blit.dst.box.z = rbDraw->surface->u.tex.first_layer;
          blit.dst.box.width = drawW;
          blit.dst.box.height = drawH;
          blit.dst.box.depth = 1;
@@ -1633,11 +1634,11 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy,
 
       memset(&blit, 0, sizeof(blit));
       blit.src.resource = rbRead->texture;
-      blit.src.level = rbRead->rtt_level;
+      blit.src.level = rbRead->surface->u.tex.level;
       blit.src.format = rbRead->texture->format;
       blit.src.box.x = readX;
       blit.src.box.y = readY;
-      blit.src.box.z = rbRead->rtt_face + rbRead->rtt_slice;
+      blit.src.box.z = rbRead->surface->u.tex.first_layer;
       blit.src.box.width = readW;
       blit.src.box.height = readH;
       blit.src.box.depth = 1;
index 20894825f7fd5a8f0098f61087d08788b381ee0d..70baa9965decf8fcffd8226485199cbbcc8400cf 100644 (file)
@@ -388,6 +388,72 @@ st_bind_framebuffer(struct gl_context *ctx, GLenum target,
 }
 
 
+/**
+ * Create or update the pipe_surface of a FBO renderbuffer.
+ * This is usually called after st_finalize_texture.
+ */
+void
+st_update_renderbuffer_surface(struct st_context *st,
+                               struct st_renderbuffer *strb)
+{
+   struct pipe_context *pipe = st->pipe;
+   struct pipe_resource *resource = strb->texture;
+   int rtt_width = strb->Base.Width;
+   int rtt_height = strb->Base.Height;
+   int rtt_depth = strb->Base.Depth;
+   enum pipe_format format = st->ctx->Color.sRGBEnabled ? resource->format :
+         util_format_linear(resource->format);
+   unsigned first_layer, last_layer, level;
+
+   if (resource->target == PIPE_TEXTURE_1D_ARRAY) {
+      rtt_depth = rtt_height;
+      rtt_height = 1;
+   }
+
+   /* find matching mipmap level size */
+   for (level = 0; level <= resource->last_level; level++) {
+      if (u_minify(resource->width0, level) == rtt_width &&
+          u_minify(resource->height0, level) == rtt_height &&
+          (resource->target != PIPE_TEXTURE_3D ||
+           u_minify(resource->depth0, level) == rtt_depth)) {
+         break;
+      }
+   }
+   assert(level <= resource->last_level);
+
+   /* determine the layer bounds */
+   if (strb->rtt_layered) {
+      first_layer = 0;
+      last_layer = util_max_layer(strb->texture, level);
+   }
+   else {
+      first_layer =
+      last_layer = strb->rtt_face + strb->rtt_slice;
+   }
+
+   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) {
+      /* 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_reference(&strb->surface, NULL);
+
+      strb->surface = pipe->create_surface(pipe, resource, &surf_tmpl);
+   }
+}
+
 /**
  * Called by ctx->Driver.RenderTexture
  */
@@ -401,8 +467,6 @@ st_render_texture(struct gl_context *ctx,
    struct gl_renderbuffer *rb = att->Renderbuffer;
    struct st_renderbuffer *strb = st_renderbuffer(rb);
    struct pipe_resource *pt;
-   struct st_texture_object *stObj;
-   struct pipe_surface surf_tmpl;
 
    if (!st_finalize_texture(ctx, pipe, att->Texture))
       return;
@@ -410,31 +474,16 @@ st_render_texture(struct gl_context *ctx,
    pt = st_get_texobj_resource(att->Texture);
    assert(pt);
 
-   /* get the texture for the texture object */
-   stObj = st_texture_object(att->Texture);
-
    /* point renderbuffer at texobject */
-   strb->rtt = stObj;
-   strb->rtt_level = att->TextureLevel;
+   strb->is_rtt = TRUE;
    strb->rtt_face = att->CubeMapFace;
    strb->rtt_slice = att->Zoffset;
-
-   pipe_resource_reference( &strb->texture, pt );
+   strb->rtt_layered = att->Layered;
+   pipe_resource_reference(&strb->texture, pt);
 
    pipe_surface_release(pipe, &strb->surface);
 
-   assert(strb->rtt_level <= strb->texture->last_level);
-
-   /* new surface for rendering into the texture */
-   memset(&surf_tmpl, 0, sizeof(surf_tmpl));
-   surf_tmpl.format = ctx->Color.sRGBEnabled
-      ? strb->texture->format : util_format_linear(strb->texture->format);
-   surf_tmpl.u.tex.level = strb->rtt_level;
-   surf_tmpl.u.tex.first_layer = strb->rtt_face + strb->rtt_slice;
-   surf_tmpl.u.tex.last_layer = strb->rtt_face + strb->rtt_slice;
-   strb->surface = pipe->create_surface(pipe,
-                                        strb->texture,
-                                        &surf_tmpl);
+   st_update_renderbuffer_surface(st, strb);
 
    strb->Base.Format = st_pipe_format_to_mesa_format(pt->format);
 
@@ -464,7 +513,7 @@ st_finish_render_texture(struct gl_context *ctx, struct gl_renderbuffer *rb)
    if (!strb)
       return;
 
-   strb->rtt = NULL;
+   strb->is_rtt = FALSE;
 
    /* restore previous framebuffer state */
    st_invalidate_state(ctx, _NEW_BUFFERS);
@@ -706,8 +755,8 @@ st_MapRenderbuffer(struct gl_context *ctx,
 
     map = pipe_transfer_map(pipe,
                             strb->texture,
-                            strb->rtt_level,
-                            strb->rtt_face + strb->rtt_slice,
+                            strb->surface->u.tex.level,
+                            strb->surface->u.tex.first_layer,
                             usage, x, y2, w, h, &strb->transfer);
    if (map) {
       if (invert) {
index f335c371b0b84cc59d2f2e37db0008fa037ac991..88fccc298792c555776901f83a969ad38da6f5a7 100644 (file)
@@ -58,8 +58,10 @@ struct st_renderbuffer
    boolean software;
    void *data;
 
-   struct st_texture_object *rtt;  /**< GL render to texture's texture */
-   unsigned rtt_level, rtt_face, rtt_slice;
+   /* Inputs from Driver.RenderTexture, don't use directly. */
+   boolean is_rtt; /**< whether Driver.RenderTexture was called */
+   unsigned rtt_face, rtt_slice;
+   boolean rtt_layered; /**< whether glFramebufferTexture was called */
 };
 
 
@@ -73,6 +75,10 @@ st_renderbuffer(struct gl_renderbuffer *rb)
 extern struct gl_renderbuffer *
 st_new_renderbuffer_fb(enum pipe_format format, int samples, boolean sw);
 
+extern void
+st_update_renderbuffer_surface(struct st_context *st,
+                               struct st_renderbuffer *strb);
+
 extern void
 st_init_fbo_functions(struct dd_function_table *functions);
 
index b5df58c033f9391167e647e35bb5d48f788cda94..7547dfd8baf682d32f631f0c07b035f8eef187fb 100644 (file)
@@ -166,7 +166,7 @@ st_readpixels(struct gl_context *ctx, GLint x, GLint y,
    }
 
    blit.src.resource = src;
-   blit.src.level = strb->rtt_level;
+   blit.src.level = strb->surface->u.tex.level;
    blit.src.format = src_format;
    blit.dst.resource = dst;
    blit.dst.level = 0;
@@ -175,7 +175,7 @@ st_readpixels(struct gl_context *ctx, GLint x, GLint y,
    blit.dst.box.x = 0;
    blit.src.box.y = y;
    blit.dst.box.y = 0;
-   blit.src.box.z = strb->rtt_face + strb->rtt_slice;
+   blit.src.box.z = strb->surface->u.tex.first_layer;
    blit.dst.box.z = 0;
    blit.src.box.width = blit.dst.box.width = width;
    blit.src.box.height = blit.dst.box.height = height;
index faa9ee3f6c7686a48d9e31675226f2d52c03a219..10eaeb9c6ec0e67d30cdbed2217238bfa28b4872 100644 (file)
@@ -1156,8 +1156,8 @@ fallback_copy_texsubimage(struct gl_context *ctx,
 
    map = pipe_transfer_map(pipe,
                            strb->texture,
-                           strb->rtt_level,
-                           strb->rtt_face + strb->rtt_slice,
+                           strb->surface->u.tex.level,
+                           strb->surface->u.tex.first_layer,
                            PIPE_TRANSFER_READ,
                            srcX, srcY,
                            width, height, &src_trans);