st/mesa: use a generic varying to pass the clear color to the FS
[mesa.git] / src / mesa / state_tracker / st_cb_texture.c
index 28fdaa573f9958f20d300f89213de94479522a44..7f07b741ee0e81908a327b3f3ce5afcc11d978d0 100644 (file)
@@ -201,7 +201,7 @@ st_MapTextureImage(struct gl_context *ctx,
    if (mode & GL_MAP_INVALIDATE_RANGE_BIT)
       pipeMode |= PIPE_TRANSFER_DISCARD_RANGE;
 
-   map = st_texture_image_map(st, stImage, slice, pipeMode, x, y, w, h);
+   map = st_texture_image_map(st, stImage, pipeMode, x, y, slice, w, h, 1);
    if (map) {
       *mapOut = map;
       *rowStrideOut = stImage->transfer->stride;
@@ -633,7 +633,7 @@ decompress_with_blit(struct gl_context * ctx,
    blit.dst.box.z = 0;
    blit.src.box.width = blit.dst.box.width = width;
    blit.src.box.height = blit.dst.box.height = height;
-   blit.src.box.depth = blit.dst.box.depth = 1;
+   blit.src.box.depth = blit.dst.box.depth = depth;
    blit.mask = PIPE_MASK_RGBA;
    blit.filter = PIPE_TEX_FILTER_NEAREST;
    blit.scissor_enable = FALSE;
@@ -643,9 +643,8 @@ decompress_with_blit(struct gl_context * ctx,
 
    pixels = _mesa_map_pbo_dest(ctx, &ctx->Pack, pixels);
 
-   map = pipe_transfer_map(pipe, dst, 0, 0,
-                           PIPE_TRANSFER_READ,
-                           0, 0, width, height, &tex_xfer);
+   map = pipe_transfer_map_3d(pipe, dst, 0, PIPE_TRANSFER_READ,
+                              0, 0, 0, width, height, depth, &tex_xfer);
    if (!map) {
       goto end;
    }
@@ -657,18 +656,24 @@ decompress_with_blit(struct gl_context * ctx,
                                             ctx->Pack.SwapBytes)) {
       /* memcpy */
       const uint bytesPerRow = width * util_format_get_blocksize(pipe_format);
-      /* map the dst_surface so we can read from it */
-      GLuint row;
-      for (row = 0; row < height; row++) {
-         GLvoid *dest = _mesa_image_address2d(&ctx->Pack, pixels, width,
-                                              height, format, type, row, 0);
-         memcpy(dest, map, bytesPerRow);
-         map += tex_xfer->stride;
+      GLuint row, slice;
+
+      for (slice = 0; slice < depth; slice++) {
+         ubyte *slice_map = map;
+
+         for (row = 0; row < height; row++) {
+            GLvoid *dest = _mesa_image_address3d(&ctx->Pack, pixels,
+                                                 width, height, format,
+                                                 type, slice, row, 0);
+            memcpy(dest, slice_map, bytesPerRow);
+            slice_map += tex_xfer->stride;
+         }
+         map += tex_xfer->layer_stride;
       }
    }
    else {
       /* format translation via floats */
-      GLuint row;
+      GLuint row, slice;
       enum pipe_format pformat = util_format_linear(dst->format);
       GLfloat *rgba;
 
@@ -678,20 +683,24 @@ decompress_with_blit(struct gl_context * ctx,
          goto end;
       }
 
-      for (row = 0; row < height; row++) {
-         const GLbitfield transferOps = 0x0; /* bypassed for glGetTexImage() */
-         GLvoid *dest = _mesa_image_address2d(&ctx->Pack, pixels, width,
-                                              height, format, type, row, 0);
+      for (slice = 0; slice < depth; slice++) {
+         for (row = 0; row < height; row++) {
+            const GLbitfield transferOps = 0x0; /* bypassed for glGetTexImage() */
+            GLvoid *dest = _mesa_image_address3d(&ctx->Pack, pixels,
+                                                 width, height, format,
+                                                 type, slice, row, 0);
 
-         if (ST_DEBUG & DEBUG_FALLBACK)
-            debug_printf("%s: fallback format translation\n", __FUNCTION__);
+            if (ST_DEBUG & DEBUG_FALLBACK)
+               debug_printf("%s: fallback format translation\n", __FUNCTION__);
 
-         /* get float[4] rgba row from surface */
-         pipe_get_tile_rgba_format(tex_xfer, map, 0, row, width, 1,
-                                   pformat, rgba);
+            /* get float[4] rgba row from surface */
+            pipe_get_tile_rgba_format(tex_xfer, map, 0, row, width, 1,
+                                      pformat, rgba);
 
-         _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba, format,
-                                    type, dest, &ctx->Pack, transferOps);
+            _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba, format,
+                                       type, dest, &ctx->Pack, transferOps);
+         }
+         map += tex_xfer->layer_stride;
       }
 
       free(rgba);
@@ -750,9 +759,12 @@ fallback_copy_texsubimage(struct gl_context *ctx,
    struct st_context *st = st_context(ctx);
    struct pipe_context *pipe = st->pipe;
    struct pipe_transfer *src_trans;
-   GLvoid *texDest;
+   GLubyte *texDest;
    enum pipe_transfer_usage transfer_usage;
    void *map;
+   unsigned dst_width = width;
+   unsigned dst_height = height;
+   unsigned dst_depth = 1;
 
    if (ST_DEBUG & DEBUG_FALLBACK)
       debug_printf("%s: fallback processing\n", __FUNCTION__);
@@ -761,6 +773,14 @@ 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,
@@ -776,9 +796,9 @@ fallback_copy_texsubimage(struct gl_context *ctx,
    else
       transfer_usage = PIPE_TRANSFER_WRITE;
 
-   /* XXX this used to ignore destZ param */
-   texDest = st_texture_image_map(st, stImage, destZ, transfer_usage,
-                                  destX, destY, width, height);
+   texDest = st_texture_image_map(st, stImage, transfer_usage,
+                                  destX, destY, destZ,
+                                  dst_width, dst_height, dst_depth);
 
    if (baseFormat == GL_DEPTH_COMPONENT ||
        baseFormat == GL_DEPTH_STENCIL) {
@@ -806,8 +826,16 @@ fallback_copy_texsubimage(struct gl_context *ctx,
             if (scaleOrBias) {
                _mesa_scale_and_bias_depth_uint(ctx, width, data);
             }
-            pipe_put_tile_z(stImage->transfer, texDest, 0, row, width, 1,
-                            data);
+
+            if (stImage->pt->target == PIPE_TEXTURE_1D_ARRAY) {
+               pipe_put_tile_z(stImage->transfer,
+                               texDest + row*stImage->transfer->layer_stride,
+                               0, 0, width, 1, data);
+            }
+            else {
+               pipe_put_tile_z(stImage->transfer, texDest, 0, row, width, 1,
+                               data);
+            }
          }
       }
       else {
@@ -823,7 +851,7 @@ fallback_copy_texsubimage(struct gl_context *ctx,
 
       if (tempSrc && texDest) {
          const GLint dims = 2;
-         const GLint dstRowStride = stImage->transfer->stride;
+         GLint dstRowStride;
          struct gl_texture_image *texImage = &stImage->base;
          struct gl_pixelstore_attrib unpack = ctx->DefaultPacking;
 
@@ -831,6 +859,13 @@ fallback_copy_texsubimage(struct gl_context *ctx,
             unpack.Invert = GL_TRUE;
          }
 
+         if (stImage->pt->target == PIPE_TEXTURE_1D_ARRAY) {
+            dstRowStride = stImage->transfer->layer_stride;
+         }
+         else {
+            dstRowStride = stImage->transfer->stride;
+         }
+
          /* get float/RGBA image from framebuffer */
          /* XXX this usually involves a lot of int/float conversion.
           * try to avoid that someday.
@@ -849,7 +884,7 @@ fallback_copy_texsubimage(struct gl_context *ctx,
                         texImage->_BaseFormat, 
                         texImage->TexFormat, 
                         dstRowStride,
-                        (GLubyte **) &texDest,
+                        &texDest,
                         width, height, 1,
                         GL_RGBA, GL_FLOAT, tempSrc, /* src */
                         &unpack);
@@ -932,6 +967,43 @@ compatible_src_dst_formats(struct gl_context *ctx,
 }
 
 
+/**
+ * Do pipe->blit. Return FALSE if the blitting is unsupported
+ * for the given formats.
+ */
+static GLboolean
+st_pipe_blit(struct pipe_context *pipe, struct pipe_blit_info *blit)
+{
+   struct pipe_screen *screen = pipe->screen;
+   unsigned dst_usage;
+
+   if (util_format_is_depth_or_stencil(blit->dst.format)) {
+      dst_usage = PIPE_BIND_DEPTH_STENCIL;
+   }
+   else {
+      dst_usage = PIPE_BIND_RENDER_TARGET;
+   }
+
+   /* try resource_copy_region in case the format is not supported
+    * for rendering */
+   if (util_try_blit_via_copy_region(pipe, blit)) {
+      return GL_TRUE; /* done */
+   }
+
+   /* check the format support */
+   if (!screen->is_format_supported(screen, blit->src.format,
+                                    PIPE_TEXTURE_2D, 0,
+                                    PIPE_BIND_SAMPLER_VIEW) ||
+       !screen->is_format_supported(screen, blit->dst.format,
+                                    PIPE_TEXTURE_2D, 0,
+                                    dst_usage)) {
+      return GL_FALSE;
+   }
+
+   pipe->blit(pipe, blit);
+   return GL_TRUE;
+}
+
 
 /**
  * Do a CopyTex[Sub]Image1/2/3D() using a hardware (blit) path if possible.
@@ -960,7 +1032,7 @@ st_CopyTexSubImage(struct gl_context *ctx, GLuint dims,
    struct pipe_surface surf_tmpl;
    unsigned dst_usage;
    unsigned blit_mask;
-   GLint srcY0, srcY1;
+   GLint srcY0, srcY1, yStep;
 
    /* make sure finalize_textures has been called? 
     */
@@ -981,10 +1053,12 @@ 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;
    }
 
    if (ctx->_ImageTransferState) {
@@ -996,16 +1070,6 @@ st_CopyTexSubImage(struct gl_context *ctx, GLuint dims,
       goto fallback;
    }
 
-   if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY) {
-      /* 1D arrays might be thought of as 2D images but the actual layout
-       * might not be that way.  At some points, we convert OpenGL's 1D
-       * array 'height' into gallium 'layers' and that prevents the blit
-       * utility code from doing the right thing.  Simpy use the memcpy-based
-       * fallback.
-       */
-      goto fallback;
-   }
-
    /* Set the blit writemask. */
    switch (texBaseFormat) {
    case GL_DEPTH_STENCIL:
@@ -1086,27 +1150,38 @@ st_CopyTexSubImage(struct gl_context *ctx, GLuint dims,
       blit.mask = blit_mask;
       blit.filter = PIPE_TEX_FILTER_NEAREST;
 
-      /* try resource_copy_region in case the format is not supported
-       * for rendering */
-      if (util_try_blit_via_copy_region(pipe, &blit)) {
-         return; /* done */
-      }
+      /* 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;
 
-      /* check the format support */
-      if (!screen->is_format_supported(screen, src_format,
-                                       PIPE_TEXTURE_2D, 0,
-                                       PIPE_BIND_SAMPLER_VIEW) ||
-          !screen->is_format_supported(screen, dest_format,
-                                       PIPE_TEXTURE_2D, 0,
-                                       dst_usage)) {
-         goto fallback;
-      }
+         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);
+            if (!st_pipe_blit(pipe, &blit)) {
+               goto fallback;
+            }
+         }
+      }
+      else {
+         /* All the other texture targets. */
+         if (!st_pipe_blit(pipe, &blit)) {
+            goto fallback;
+         }
+      }
       return;
    }
 
    /* try u_blit */
+   if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY) {
+      /* u_blit cannot copy 1D array textures as required by CopyTexSubImage */
+      goto fallback;
+   }
+
    color_writemask = compatible_src_dst_formats(ctx, &strb->Base, texImage);
 
    if (!color_writemask ||