mesa: Hide weirdness of 1D_ARRAY textures from Driver.CopyTexSubImage().
authorEric Anholt <eric@anholt.net>
Mon, 3 Jun 2013 22:12:49 +0000 (15:12 -0700)
committerEric Anholt <eric@anholt.net>
Mon, 17 Jun 2013 22:26:20 +0000 (15:26 -0700)
Intel had brokenness here, and I'd like to continue moving Mesa toward
hiding 1D_ARRAY's ridiculousness inside of the core, like we did with
MapTextureImage.  Fixes copyteximage 1D_ARRAY on intel.

There's still an impedance mismatch in meta when falling back to read and
texsubimage, since texsubimage expects coordinates into 1D_ARRAY as
(width, slice, 0) instead of (width, 0, slice).

v2: Fix offset of scanline reads from the source. (Thanks Brian!), replace
    dd.h comment with Paul's text and replace early exit with an assert.

Reviewed-by: Brian Paul <brianp@vmware.com> (v1)
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org> (v1)
Reviewed-by: Paul Berry <stereotype441@gmail.com> (v1)
src/mesa/drivers/common/meta.c
src/mesa/drivers/common/meta.h
src/mesa/drivers/dri/intel/intel_tex_copy.c
src/mesa/drivers/dri/radeon/radeon_tex_copy.c
src/mesa/main/dd.h
src/mesa/main/teximage.c
src/mesa/state_tracker/st_cb_texture.c

index ce5b87b0be1d95cf2496f17b6bf309228c2e3681..f7dd06aebf0e7e567af6046f7db802545420b1c6 100644 (file)
@@ -3851,9 +3851,16 @@ _mesa_meta_CopyTexSubImage(struct gl_context *ctx, GLuint dims,
     */
    _mesa_meta_begin(ctx, MESA_META_PIXEL_STORE);
 
-   ctx->Driver.TexSubImage(ctx, dims, texImage,
-                           xoffset, yoffset, zoffset, width, height, 1,
-                           format, type, buf, &ctx->Unpack);
+   if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY) {
+      assert(yoffset == 0);
+      ctx->Driver.TexSubImage(ctx, dims, texImage,
+                              xoffset, zoffset, 0, width, 1, 1,
+                              format, type, buf, &ctx->Unpack);
+   } else {
+      ctx->Driver.TexSubImage(ctx, dims, texImage,
+                              xoffset, yoffset, zoffset, width, height, 1,
+                              format, type, buf, &ctx->Unpack);
+   }
 
    _mesa_meta_end(ctx);
 
index a3617f4fad8162313a5c55a82a590d7a4c8e47d2..53d7b8ab5a8efe13c8da0797d243e78b6aa8f98a 100644 (file)
@@ -116,7 +116,7 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target,
 extern void
 _mesa_meta_CopyTexSubImage(struct gl_context *ctx, GLuint dims,
                            struct gl_texture_image *texImage,
-                           GLint xoffset, GLint yoffset, GLint zoffset,
+                           GLint xoffset, GLint yoffset, GLint slice,
                            struct gl_renderbuffer *rb,
                            GLint x, GLint y,
                            GLsizei width, GLsizei height);
index d8e65baad5b7561b10b610601de812a2f79789f7..3ab66d97b542df285fd660a12719988d1d039e0e 100644 (file)
@@ -135,13 +135,14 @@ intel_copy_texsubimage(struct intel_context *intel,
 static void
 intelCopyTexSubImage(struct gl_context *ctx, GLuint dims,
                      struct gl_texture_image *texImage,
-                     GLint xoffset, GLint yoffset, GLint zoffset,
+                     GLint xoffset, GLint yoffset, GLint slice,
                      struct gl_renderbuffer *rb,
                      GLint x, GLint y,
                      GLsizei width, GLsizei height)
 {
    struct intel_context *intel = intel_context(ctx);
-   if (dims != 3) {
+
+   if (slice == 0) {
 #ifndef I915
       /* Try BLORP first.  It can handle almost everything. */
       if (brw_blorp_copytexsubimage(intel, rb, texImage, x, y,
@@ -160,7 +161,7 @@ intelCopyTexSubImage(struct gl_context *ctx, GLuint dims,
    /* Finally, fall back to meta.  This will likely be slow. */
    perf_debug("%s - fallback to swrast\n", __FUNCTION__);
    _mesa_meta_CopyTexSubImage(ctx, dims, texImage,
-                              xoffset, yoffset, zoffset,
+                              xoffset, yoffset, slice,
                               rb, x, y, width, height);
 }
 
index a6c406b2bffc97e72ee80a18d35f5e548cea27e5..675eb78ec5c554962a610e15d0884a3f72074574 100644 (file)
@@ -136,7 +136,7 @@ do_copy_texsubimage(struct gl_context *ctx,
 void
 radeonCopyTexSubImage(struct gl_context *ctx, GLuint dims,
                       struct gl_texture_image *texImage,
-                      GLint xoffset, GLint yoffset, GLint zoffset,
+                      GLint xoffset, GLint yoffset, GLint slice,
                       struct gl_renderbuffer *rb,
                       GLint x, GLint y,
                       GLsizei width, GLsizei height)
@@ -144,7 +144,7 @@ radeonCopyTexSubImage(struct gl_context *ctx, GLuint dims,
     radeonContextPtr radeon = RADEON_CONTEXT(ctx);
     radeon_prepare_render(radeon);
 
-    if (dims != 2 || !do_copy_texsubimage(ctx,
+    if (slice != 0 || !do_copy_texsubimage(ctx,
                              radeon_tex_obj(texImage->TexObject),
                              (radeon_texture_image *)texImage,
                              xoffset, yoffset,
@@ -154,7 +154,7 @@ radeonCopyTexSubImage(struct gl_context *ctx, GLuint dims,
                      "Falling back to sw for glCopyTexSubImage2D\n");
 
         _mesa_meta_CopyTexSubImage(ctx, dims, texImage,
-                                   xoffset, yoffset, zoffset,
+                                   xoffset, yoffset, slice,
                                      rb, x, y, width, height);
     }
 }
index 6d564b25274804187e2dc6b889e1cf13f619e4fa..e2519780ab295b68c5d4166eec1113dc0776d8c1 100644 (file)
@@ -248,10 +248,16 @@ struct dd_function_table {
 
    /**
     * Called by glCopyTex[Sub]Image[123]D().
+    *
+    * This function should copy a rectangular region in the rb to a single
+    * destination slice, specified by @slice.  In the case of 1D array
+    * textures (where one GL call can potentially affect multiple destination
+    * slices), core mesa takes care of calling this function multiple times,
+    * once for each scanline to be copied.
     */
    void (*CopyTexSubImage)(struct gl_context *ctx, GLuint dims,
                            struct gl_texture_image *texImage,
-                           GLint xoffset, GLint yoffset, GLint zoffset,
+                           GLint xoffset, GLint yoffset, GLint slice,
                            struct gl_renderbuffer *rb,
                            GLint x, GLint y,
                            GLsizei width, GLsizei height);
index 6f7fbc0d2a15a894723a70f4c82c806e62b0e098..5226687ff924c5b50fdc57637608dd70e2a50fd4 100644 (file)
@@ -3429,6 +3429,35 @@ get_copy_tex_image_source(struct gl_context *ctx, gl_format texFormat)
    }
 }
 
+static void
+copytexsubimage_by_slice(struct gl_context *ctx,
+                         struct gl_texture_image *texImage,
+                         GLuint dims,
+                         GLint xoffset, GLint yoffset, GLint zoffset,
+                         struct gl_renderbuffer *rb,
+                         GLint x, GLint y,
+                         GLsizei width, GLsizei height)
+{
+   if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY) {
+      int slice;
+
+      /* For 1D arrays, we copy each scanline of the source rectangle into the
+       * next array slice.
+       */
+      assert(zoffset == 0);
+
+      for (slice = 0; slice < height; slice++) {
+         assert(yoffset + slice < texImage->Height);
+         ctx->Driver.CopyTexSubImage(ctx, 2, texImage,
+                                     xoffset, 0, yoffset + slice,
+                                     rb, x, y + slice, width, 1);
+      }
+   } else {
+      ctx->Driver.CopyTexSubImage(ctx, dims, texImage,
+                                  xoffset, yoffset, zoffset,
+                                  rb, x, y, width, height);
+   }
+}
 
 
 /**
@@ -3517,8 +3546,9 @@ copyteximage(struct gl_context *ctx, GLuint dims,
                struct gl_renderbuffer *srcRb =
                   get_copy_tex_image_source(ctx, texImage->TexFormat);
 
-               ctx->Driver.CopyTexSubImage(ctx, dims, texImage, dstX, dstY, dstZ,
-                                           srcRb, srcX, srcY, width, height);
+               copytexsubimage_by_slice(ctx, texImage, dims,
+                                        dstX, dstY, dstZ,
+                                        srcRb, srcX, srcY, width, height);
             }
 
             check_gen_mipmap(ctx, target, texObj, level);
@@ -3610,9 +3640,9 @@ copytexsubimage(struct gl_context *ctx, GLuint dims, GLenum target, GLint level,
          struct gl_renderbuffer *srcRb =
             get_copy_tex_image_source(ctx, texImage->TexFormat);
 
-         ctx->Driver.CopyTexSubImage(ctx, dims, texImage,
-                                     xoffset, yoffset, zoffset,
-                                     srcRb, x, y, width, height);
+         copytexsubimage_by_slice(ctx, texImage, dims,
+                                  xoffset, yoffset, zoffset,
+                                  srcRb, x, y, width, height);
 
          check_gen_mipmap(ctx, target, texObj, level);
 
index 56dbe85c03a0ffb7dd67eb112b59a39b3bf4fcd4..68c334ed8a0b7da85cdff975e2e6c7d66e4d7c10 100644 (file)
@@ -1133,7 +1133,7 @@ fallback_copy_texsubimage(struct gl_context *ctx,
                           struct st_renderbuffer *strb,
                           struct st_texture_image *stImage,
                           GLenum baseFormat,
-                          GLint destX, GLint destY, GLint destZ,
+                          GLint destX, GLint destY, GLint slice,
                           GLint srcX, GLint srcY,
                           GLsizei width, GLsizei height)
 {
@@ -1154,14 +1154,6 @@ fallback_copy_texsubimage(struct gl_context *ctx,
       srcY = strb->Base.Height - srcY - height;
    }
 
-   if (stImage->pt->target == PIPE_TEXTURE_1D_ARRAY) {
-      /* Move y/height to z/depth for 1D array textures.  */
-      destZ = destY;
-      destY = 0;
-      dst_depth = dst_height;
-      dst_height = 1;
-   }
-
    map = pipe_transfer_map(pipe,
                            strb->texture,
                            strb->rtt_level,
@@ -1178,7 +1170,7 @@ fallback_copy_texsubimage(struct gl_context *ctx,
       transfer_usage = PIPE_TRANSFER_WRITE;
 
    texDest = st_texture_image_map(st, stImage, transfer_usage,
-                                  destX, destY, destZ,
+                                  destX, destY, slice,
                                   dst_width, dst_height, dst_depth);
 
    if (baseFormat == GL_DEPTH_COMPONENT ||
@@ -1292,7 +1284,7 @@ fallback_copy_texsubimage(struct gl_context *ctx,
 static void
 st_CopyTexSubImage(struct gl_context *ctx, GLuint dims,
                    struct gl_texture_image *texImage,
-                   GLint destX, GLint destY, GLint destZ,
+                   GLint destX, GLint destY, GLint slice,
                    struct gl_renderbuffer *rb,
                    GLint srcX, GLint srcY, GLsizei width, GLsizei height)
 {
@@ -1306,7 +1298,7 @@ st_CopyTexSubImage(struct gl_context *ctx, GLuint dims,
    enum pipe_format dst_format;
    GLboolean do_flip = (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP);
    unsigned bind;
-   GLint srcY0, srcY1, yStep;
+   GLint srcY0, srcY1;
 
    if (!strb || !strb->surface || !stImage->pt) {
       debug_printf("%s: null strb or stImage\n", __FUNCTION__);
@@ -1351,12 +1343,10 @@ st_CopyTexSubImage(struct gl_context *ctx, GLuint dims,
    if (do_flip) {
       srcY1 = strb->Base.Height - srcY - height;
       srcY0 = srcY1 + height;
-      yStep = -1;
    }
    else {
       srcY0 = srcY;
       srcY1 = srcY0 + height;
-      yStep = 1;
    }
 
    /* Blit the texture.
@@ -1377,39 +1367,20 @@ st_CopyTexSubImage(struct gl_context *ctx, GLuint dims,
    blit.dst.level = stObj->pt != stImage->pt ? 0 : texImage->Level;
    blit.dst.box.x = destX;
    blit.dst.box.y = destY;
-   blit.dst.box.z = stImage->base.Face + destZ;
+   blit.dst.box.z = stImage->base.Face + slice;
    blit.dst.box.width = width;
    blit.dst.box.height = height;
    blit.dst.box.depth = 1;
    blit.mask = st_get_blit_mask(rb->_BaseFormat, texImage->_BaseFormat);
    blit.filter = PIPE_TEX_FILTER_NEAREST;
-
-   /* 1D array textures need special treatment.
-    * Blit rows from the source to layers in the destination. */
-   if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY) {
-      int y, layer;
-
-      for (y = srcY0, layer = 0; layer < height; y += yStep, layer++) {
-         blit.src.box.y = y;
-         blit.src.box.height = 1;
-         blit.dst.box.y = 0;
-         blit.dst.box.height = 1;
-         blit.dst.box.z = destY + layer;
-
-         pipe->blit(pipe, &blit);
-      }
-   }
-   else {
-      /* All the other texture targets. */
-      pipe->blit(pipe, &blit);
-   }
+   pipe->blit(pipe, &blit);
    return;
 
 fallback:
    /* software fallback */
    fallback_copy_texsubimage(ctx,
                              strb, stImage, texImage->_BaseFormat,
-                             destX, destY, destZ,
+                             destX, destY, slice,
                              srcX, srcY, width, height);
 }