[Mesa-dev] [PATCH 2/4] i965: Push the format checks to intel_tiled_memcpy

Chris Wilson chris at chris-wilson.co.uk
Fri May 25 23:33:57 UTC 2018


Allow the tiled_memcpy backend to determine if it is able to copy
between the source and destination pixel buffer. This allows us to
eliminate some duplication in the callers, and permits us to be more
flexible in checking for compatible formats.

(Hmm, is sRGB handling right?)
---
 src/mesa/drivers/dri/i965/intel_pixel_read.c  |  16 +--
 src/mesa/drivers/dri/i965/intel_tex_image.c   |  46 +++-----
 .../drivers/dri/i965/intel_tiled_memcpy.c     | 108 +++++++++++-------
 .../drivers/dri/i965/intel_tiled_memcpy.h     |  17 ++-
 4 files changed, 102 insertions(+), 85 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/intel_pixel_read.c b/src/mesa/drivers/dri/i965/intel_pixel_read.c
index 6ed7895bc76..a545d215ad6 100644
--- a/src/mesa/drivers/dri/i965/intel_pixel_read.c
+++ b/src/mesa/drivers/dri/i965/intel_pixel_read.c
@@ -86,15 +86,12 @@ intel_readpixels_tiled_memcpy(struct gl_context * ctx,
    /* The miptree's buffer. */
    struct brw_bo *bo;
 
-   uint32_t cpp;
-   mem_copy_fn mem_copy = NULL;
 
    /* This fastpath is restricted to specific renderbuffer types:
     * a 2D BGRA, RGBA, L8 or A8 texture. It could be generalized to support
     * more types.
     */
    if (!devinfo->has_llc ||
-       !(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_INT_8_8_8_8_REV) ||
        pixels == NULL ||
        _mesa_is_bufferobj(pack->BufferObj) ||
        pack->Alignment > 4 ||
@@ -117,15 +114,9 @@ intel_readpixels_tiled_memcpy(struct gl_context * ctx,
    if (rb->NumSamples > 1)
       return false;
 
-   /* We can't handle copying from RGBX or BGRX because the tiled_memcpy
-    * function doesn't set the last channel to 1. Note this checks BaseFormat
-    * rather than TexFormat in case the RGBX format is being simulated with an
-    * RGBA format.
-    */
-   if (rb->_BaseFormat == GL_RGB)
-      return false;
-
-   if (!intel_get_memcpy(rb->Format, format, type, &mem_copy, &cpp))
+   mem_copy_fn mem_copy =
+      intel_get_memcpy(rb->Format, format, type, INTEL_DOWNLOAD);
+   if (mem_copy == NULL)
       return false;
 
    if (!irb->mt ||
@@ -198,6 +189,7 @@ intel_readpixels_tiled_memcpy(struct gl_context * ctx,
        pack->Alignment, pack->RowLength, pack->SkipPixels,
        pack->SkipRows);
 
+   uint32_t cpp = _mesa_get_format_bytes(rb->Format);
    tiled_to_linear(
       xoffset * cpp, (xoffset + width) * cpp,
       yoffset, yoffset + height,
diff --git a/src/mesa/drivers/dri/i965/intel_tex_image.c b/src/mesa/drivers/dri/i965/intel_tex_image.c
index fae179214dd..de8832812c1 100644
--- a/src/mesa/drivers/dri/i965/intel_tex_image.c
+++ b/src/mesa/drivers/dri/i965/intel_tex_image.c
@@ -186,13 +186,6 @@ intel_texsubimage_tiled_memcpy(struct gl_context * ctx,
    struct brw_context *brw = brw_context(ctx);
    const struct gen_device_info *devinfo = &brw->screen->devinfo;
    struct intel_texture_image *image = intel_texture_image(texImage);
-   int src_pitch;
-
-   /* The miptree's buffer. */
-   struct brw_bo *bo;
-
-   uint32_t cpp;
-   mem_copy_fn mem_copy = NULL;
 
    /* This fastpath is restricted to specific texture types:
     * a 2D BGRA, RGBA, L8 or A8 texture. It could be generalized to support
@@ -204,7 +197,6 @@ intel_texsubimage_tiled_memcpy(struct gl_context * ctx,
     * we need tests.
     */
    if (!devinfo->has_llc ||
-       !(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_INT_8_8_8_8_REV) ||
        !(texImage->TexObject->Target == GL_TEXTURE_2D ||
          texImage->TexObject->Target == GL_TEXTURE_RECTANGLE) ||
        pixels == NULL ||
@@ -222,7 +214,12 @@ intel_texsubimage_tiled_memcpy(struct gl_context * ctx,
    if (ctx->_ImageTransferState)
       return false;
 
-   if (!intel_get_memcpy(texImage->TexFormat, format, type, &mem_copy, &cpp))
+   if (format == GL_COLOR_INDEX)
+      return false;
+
+   mem_copy_fn mem_copy =
+      intel_get_memcpy(texImage->TexFormat, format, type, INTEL_UPLOAD);
+   if (mem_copy == NULL)
       return false;
 
    /* If this is a nontrivial texture view, let another path handle it instead. */
@@ -257,7 +254,7 @@ intel_texsubimage_tiled_memcpy(struct gl_context * ctx,
 
    intel_miptree_access_raw(brw, image->mt, level, 0, true);
 
-   bo = image->mt->bo;
+   struct brw_bo *bo = image->mt->bo;
 
    if (brw_batch_references(&brw->batch, bo)) {
       perf_debug("Flushing before mapping a referenced bo.\n");
@@ -270,7 +267,7 @@ intel_texsubimage_tiled_memcpy(struct gl_context * ctx,
       return false;
    }
 
-   src_pitch = _mesa_image_row_stride(packing, width, format, type);
+   int src_pitch = _mesa_image_row_stride(packing, width, format, type);
 
    /* We postponed printing this message until having committed to executing
     * the function.
@@ -289,6 +286,8 @@ intel_texsubimage_tiled_memcpy(struct gl_context * ctx,
    xoffset += level_x;
    yoffset += level_y;
 
+   uint32_t cpp = _mesa_get_format_bytes(texImage->TexFormat);
+
    linear_to_tiled(
       xoffset * cpp, (xoffset + width) * cpp,
       yoffset, yoffset + height,
@@ -691,13 +690,6 @@ intel_gettexsubimage_tiled_memcpy(struct gl_context *ctx,
    struct brw_context *brw = brw_context(ctx);
    const struct gen_device_info *devinfo = &brw->screen->devinfo;
    struct intel_texture_image *image = intel_texture_image(texImage);
-   int dst_pitch;
-
-   /* The miptree's buffer. */
-   struct brw_bo *bo;
-
-   uint32_t cpp;
-   mem_copy_fn mem_copy = NULL;
 
    /* This fastpath is restricted to specific texture types:
     * a 2D BGRA, RGBA, L8 or A8 texture. It could be generalized to support
@@ -709,7 +701,6 @@ intel_gettexsubimage_tiled_memcpy(struct gl_context *ctx,
     * we need tests.
     */
    if (!devinfo->has_llc ||
-       !(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_INT_8_8_8_8_REV) ||
        !(texImage->TexObject->Target == GL_TEXTURE_2D ||
          texImage->TexObject->Target == GL_TEXTURE_RECTANGLE) ||
        pixels == NULL ||
@@ -723,15 +714,9 @@ intel_gettexsubimage_tiled_memcpy(struct gl_context *ctx,
        packing->Invert)
       return false;
 
-   /* We can't handle copying from RGBX or BGRX because the tiled_memcpy
-    * function doesn't set the last channel to 1. Note this checks BaseFormat
-    * rather than TexFormat in case the RGBX format is being simulated with an
-    * RGBA format.
-    */
-   if (texImage->_BaseFormat == GL_RGB)
-      return false;
-
-   if (!intel_get_memcpy(texImage->TexFormat, format, type, &mem_copy, &cpp))
+   mem_copy_fn mem_copy =
+      intel_get_memcpy(texImage->TexFormat, format, type, INTEL_DOWNLOAD);
+   if (mem_copy == NULL)
       return false;
 
    /* If this is a nontrivial texture view, let another path handle it instead. */
@@ -766,7 +751,7 @@ intel_gettexsubimage_tiled_memcpy(struct gl_context *ctx,
 
    intel_miptree_access_raw(brw, image->mt, level, 0, true);
 
-   bo = image->mt->bo;
+   struct brw_bo *bo = image->mt->bo;
 
    if (brw_batch_references(&brw->batch, bo)) {
       perf_debug("Flushing before mapping a referenced bo.\n");
@@ -779,7 +764,7 @@ intel_gettexsubimage_tiled_memcpy(struct gl_context *ctx,
       return false;
    }
 
-   dst_pitch = _mesa_image_row_stride(packing, width, format, type);
+   int dst_pitch = _mesa_image_row_stride(packing, width, format, type);
 
    DBG("%s: level=%d x,y=(%d,%d) (w,h)=(%d,%d) format=0x%x type=0x%x "
        "mesa_format=0x%x tiling=%d "
@@ -795,6 +780,7 @@ intel_gettexsubimage_tiled_memcpy(struct gl_context *ctx,
    xoffset += level_x;
    yoffset += level_y;
 
+   uint32_t cpp = _mesa_get_format_bytes(texImage->TexFormat);
    tiled_to_linear(
       xoffset * cpp, (xoffset + width) * cpp,
       yoffset, yoffset + height,
diff --git a/src/mesa/drivers/dri/i965/intel_tiled_memcpy.c b/src/mesa/drivers/dri/i965/intel_tiled_memcpy.c
index 6440dceac36..abe0f804f37 100644
--- a/src/mesa/drivers/dri/i965/intel_tiled_memcpy.c
+++ b/src/mesa/drivers/dri/i965/intel_tiled_memcpy.c
@@ -33,6 +33,11 @@
 
 #include "util/macros.h"
 
+#include "main/glheader.h"
+#include "main/enums.h"
+#include "main/mtypes.h"
+#include "main/glformats.h"
+
 #include "brw_context.h"
 #include "intel_tiled_memcpy.h"
 
@@ -994,51 +999,72 @@ tiled_to_linear(uint32_t xt1, uint32_t xt2,
  * \param[in]  tiledFormat The format of the tiled image
  * \param[in]  format      The GL format of the client data
  * \param[in]  type        The GL type of the client data
- * \param[out] mem_copy    Will be set to one of either the standard
- *                         library's memcpy or a different copy function
- *                         that performs an RGBA to BGRA conversion
- * \param[out] cpp         Number of bytes per channel
  *
- * \return true if the format and type combination are valid
+ * \return the mem_copy_fn if the format and type combination are valid
  */
-bool intel_get_memcpy(mesa_format tiledFormat, GLenum format,
-                      GLenum type, mem_copy_fn *mem_copy, uint32_t *cpp)
+mem_copy_fn intel_get_memcpy(mesa_format tiledFormat,
+                             GLenum format, GLenum type,
+                             enum intel_memcpy_direction direction)
 {
-   if (type == GL_UNSIGNED_INT_8_8_8_8_REV &&
-       !(format == GL_RGBA || format == GL_BGRA))
-      return false; /* Invalid type/format combination */
-
-   if ((tiledFormat == MESA_FORMAT_L_UNORM8 && format == GL_LUMINANCE) ||
-       (tiledFormat == MESA_FORMAT_A_UNORM8 && format == GL_ALPHA)) {
-      *cpp = 1;
-      *mem_copy = memcpy;
-   } else if ((tiledFormat == MESA_FORMAT_B8G8R8A8_UNORM) ||
-              (tiledFormat == MESA_FORMAT_B8G8R8X8_UNORM) ||
-              (tiledFormat == MESA_FORMAT_B8G8R8A8_SRGB) ||
-              (tiledFormat == MESA_FORMAT_B8G8R8X8_SRGB)) {
-      *cpp = 4;
-      if (format == GL_BGRA) {
-         *mem_copy = memcpy;
-      } else if (format == GL_RGBA) {
-         *mem_copy = rgba8_copy;
-      }
-   } else if ((tiledFormat == MESA_FORMAT_R8G8B8A8_UNORM) ||
-              (tiledFormat == MESA_FORMAT_R8G8B8X8_UNORM) ||
-              (tiledFormat == MESA_FORMAT_R8G8B8A8_SRGB) ||
-              (tiledFormat == MESA_FORMAT_R8G8B8X8_SRGB)) {
-      *cpp = 4;
-      if (format == GL_BGRA) {
-         /* Copying from RGBA to BGRA is the same as BGRA to RGBA so we can
-          * use the same function.
-          */
-         *mem_copy = rgba8_copy;
-      } else if (format == GL_RGBA) {
-         *mem_copy = memcpy;
-      }
+   mesa_format user_format;
+   mem_copy_fn fn = NULL;
+
+   if (type == GL_BITMAP)
+      return NULL;
+
+   /* Stencil tiling is a lie, though we could do similar manual detiling */
+   switch ((int)tiledFormat) {
+   case MESA_FORMAT_S_UINT8:
+   case MESA_FORMAT_Z32_FLOAT_S8X24_UINT:
+   case MESA_FORMAT_Z24_UNORM_X8_UINT:
+   case MESA_FORMAT_Z24_UNORM_S8_UINT:
+      return NULL;
    }
 
-   if (!(*mem_copy))
-      return false;
+   if (_mesa_is_format_compressed(tiledFormat))
+      return NULL;
+
+   user_format = _mesa_format_from_format_and_type(format, type);
+   if (_mesa_format_is_mesa_array_format(user_format))
+      user_format = _mesa_format_from_array_format(user_format);
+
+   if (user_format == tiledFormat) {
+      fn = memcpy;
+   } else switch ((int)tiledFormat) {
+   case MESA_FORMAT_B8G8R8A8_UNORM:
+      if (user_format == MESA_FORMAT_R8G8B8A8_UNORM)
+         fn = rgba8_copy;
+      else if (user_format == MESA_FORMAT_R8G8B8X8_UNORM)
+         fn = direction == INTEL_UPLOAD ? NULL : rgba8_copy;
+      else if (user_format == MESA_FORMAT_B8G8R8X8_UNORM)
+         fn = direction == INTEL_UPLOAD ? NULL : memcpy;
+      break;
+   case MESA_FORMAT_B8G8R8X8_UNORM:
+      if (user_format == MESA_FORMAT_R8G8B8X8_UNORM)
+         fn = rgba8_copy;
+      else if (user_format == MESA_FORMAT_R8G8B8A8_UNORM)
+         fn = direction == INTEL_UPLOAD ? rgba8_copy : NULL;
+      else if (user_format == MESA_FORMAT_B8G8R8A8_UNORM)
+         fn = direction == INTEL_UPLOAD ? memcpy : NULL;
+      break;
+
+   case MESA_FORMAT_R8G8B8A8_UNORM:
+      if (user_format == MESA_FORMAT_B8G8R8A8_UNORM)
+         fn = rgba8_copy;
+      else if (user_format == MESA_FORMAT_B8G8R8X8_UNORM)
+         fn = direction == INTEL_UPLOAD ? NULL : rgba8_copy;
+      else if (user_format == MESA_FORMAT_R8G8B8X8_UNORM)
+         fn = direction == INTEL_UPLOAD ? NULL : memcpy;
+      break;
+   case MESA_FORMAT_R8G8B8X8_UNORM:
+         if (user_format == MESA_FORMAT_B8G8R8X8_UNORM)
+         fn = rgba8_copy;
+      else if (user_format == MESA_FORMAT_B8G8R8X8_UNORM)
+         fn = direction == INTEL_UPLOAD ? rgba8_copy : NULL;
+      else if (user_format == MESA_FORMAT_R8G8B8A8_UNORM)
+         fn = direction == INTEL_UPLOAD ? memcpy : NULL;
+      break;
+   }
 
-   return true;
+   return fn;
 }
diff --git a/src/mesa/drivers/dri/i965/intel_tiled_memcpy.h b/src/mesa/drivers/dri/i965/intel_tiled_memcpy.h
index 62ec8847fbc..e9c43920a17 100644
--- a/src/mesa/drivers/dri/i965/intel_tiled_memcpy.h
+++ b/src/mesa/drivers/dri/i965/intel_tiled_memcpy.h
@@ -55,7 +55,20 @@ tiled_to_linear(uint32_t xt1, uint32_t xt2,
                 enum isl_tiling tiling,
                 mem_copy_fn mem_copy);
 
-bool intel_get_memcpy(mesa_format tiledFormat, GLenum format,
-                      GLenum type, mem_copy_fn *mem_copy, uint32_t *cpp);
+/* Tells intel_get_memcpy() whether the memcpy() is
+ *
+ *  - an upload to the GPU with an aligned destination and a potentially
+ *    unaligned source; or
+ *  - a download from the GPU with an aligned source and a potentially
+ *    unaligned destination.
+ */
+enum intel_memcpy_direction {
+   INTEL_UPLOAD,
+   INTEL_DOWNLOAD
+};
+
+mem_copy_fn intel_get_memcpy(mesa_format tiledFormat,
+                             GLenum format, GLenum type,
+                             enum intel_memcpy_direction direction);
 
 #endif /* INTEL_TILED_MEMCPY */
-- 
2.17.0



More information about the mesa-dev mailing list