If possible, we want to match the hardware format to what the app uses. By
doing so, we avoid the need for pixel conversions and therefore greatly speed
up texture uploads.
---
 src/mesa/state_tracker/st_atom_pixeltransfer.c |    2 +-
 src/mesa/state_tracker/st_cb_drawpixels.c      |   10 ++-
 src/mesa/state_tracker/st_format.c             |   94 +++++++++++++++++++++++-
 src/mesa/state_tracker/st_format.h             |    1 +
 4 files changed, 99 insertions(+), 8 deletions(-)

diff --git a/src/mesa/state_tracker/st_atom_pixeltransfer.c 
b/src/mesa/state_tracker/st_atom_pixeltransfer.c
index 95b706c..1f833d2 100644
--- a/src/mesa/state_tracker/st_atom_pixeltransfer.c
+++ b/src/mesa/state_tracker/st_atom_pixeltransfer.c
@@ -94,7 +94,7 @@ create_color_map_texture(struct gl_context *ctx)
    const uint texSize = 256; /* simple, and usually perfect */
 
    /* find an RGBA texture format */
-   format = st_choose_format(pipe->screen, GL_RGBA,
+   format = st_choose_format(pipe->screen, GL_RGBA, GL_NONE, GL_NONE,
                              PIPE_TEXTURE_2D, 0, PIPE_BIND_SAMPLER_VIEW);
 
    /* create texture for color map/table */
diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c 
b/src/mesa/state_tracker/st_cb_drawpixels.c
index 965fbcd..c730975 100644
--- a/src/mesa/state_tracker/st_cb_drawpixels.c
+++ b/src/mesa/state_tracker/st_cb_drawpixels.c
@@ -989,8 +989,9 @@ st_DrawPixels(struct gl_context *ctx, GLint x, GLint y,
       /* can we write to stencil if not fallback */
       if (!pipe->screen->get_param(pipe->screen, 
PIPE_CAP_SHADER_STENCIL_EXPORT))
         goto stencil_fallback;
-      
+
       tex_format = st_choose_format(st->pipe->screen, base_format(format),
+                                    GL_NONE, GL_NONE,
                                     PIPE_TEXTURE_2D,
                                    0, PIPE_BIND_SAMPLER_VIEW);
       if (tex_format == PIPE_FORMAT_Z24_UNORM_S8_USCALED)
@@ -1399,13 +1400,14 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint 
srcy,
       /* srcFormat can't be used as a texture format */
       if (type == GL_DEPTH) {
          texFormat = st_choose_format(screen, GL_DEPTH_COMPONENT,
-                                      st->internal_target, sample_count,
-                                      PIPE_BIND_DEPTH_STENCIL);
+                                      st->internal_target, GL_NONE, GL_NONE,
+                                     sample_count, PIPE_BIND_DEPTH_STENCIL);
          assert(texFormat != PIPE_FORMAT_NONE);
       }
       else {
          /* default color format */
-         texFormat = st_choose_format(screen, GL_RGBA, st->internal_target,
+         texFormat = st_choose_format(screen, GL_RGBA,
+                                      st->internal_target, GL_NONE, GL_NONE,
                                       sample_count, PIPE_BIND_SAMPLER_VIEW);
          assert(texFormat != PIPE_FORMAT_NONE);
       }
diff --git a/src/mesa/state_tracker/st_format.c 
b/src/mesa/state_tracker/st_format.c
index 45e4766..6f43c03 100644
--- a/src/mesa/state_tracker/st_format.c
+++ b/src/mesa/state_tracker/st_format.c
@@ -1124,6 +1124,87 @@ find_supported_format(struct pipe_screen *screen,
    return PIPE_FORMAT_NONE;
 }
 
+struct exact_format_mapping
+{
+   GLenum format;
+   GLenum type;
+   enum pipe_format pformat;
+};
+
+static struct exact_format_mapping rgba8888_tbl[] =
+{
+   { GL_RGBA,     GL_UNSIGNED_INT_8_8_8_8,        PIPE_FORMAT_A8B8G8R8_UNORM },
+   { GL_ABGR_EXT, GL_UNSIGNED_INT_8_8_8_8_REV,    PIPE_FORMAT_A8B8G8R8_UNORM },
+   { GL_RGBA,     GL_UNSIGNED_INT_8_8_8_8_REV,    PIPE_FORMAT_R8G8B8A8_UNORM },
+   { GL_ABGR_EXT, GL_UNSIGNED_INT_8_8_8_8,        PIPE_FORMAT_R8G8B8A8_UNORM },
+   { GL_BGRA,     GL_UNSIGNED_INT_8_8_8_8,        PIPE_FORMAT_A8R8G8B8_UNORM },
+   { GL_BGRA,     GL_UNSIGNED_INT_8_8_8_8_REV,    PIPE_FORMAT_B8G8R8A8_UNORM },
+   { GL_RGBA,     GL_UNSIGNED_BYTE,               PIPE_FORMAT_R8G8B8A8_UNORM },
+   { GL_ABGR_EXT, GL_UNSIGNED_BYTE,               PIPE_FORMAT_A8B8G8R8_UNORM },
+   { GL_BGRA,     GL_UNSIGNED_BYTE,               PIPE_FORMAT_B8G8R8A8_UNORM },
+   { 0,           0,                              0                          }
+};
+
+static struct exact_format_mapping rgbx8888_tbl[] =
+{
+   { GL_RGBA,     GL_UNSIGNED_INT_8_8_8_8,        PIPE_FORMAT_X8B8G8R8_UNORM },
+   { GL_ABGR_EXT, GL_UNSIGNED_INT_8_8_8_8_REV,    PIPE_FORMAT_X8B8G8R8_UNORM },
+   { GL_RGBA,     GL_UNSIGNED_INT_8_8_8_8_REV,    PIPE_FORMAT_R8G8B8X8_UNORM },
+   { GL_ABGR_EXT, GL_UNSIGNED_INT_8_8_8_8,        PIPE_FORMAT_R8G8B8X8_UNORM },
+   { GL_BGRA,     GL_UNSIGNED_INT_8_8_8_8,        PIPE_FORMAT_X8R8G8B8_UNORM },
+   { GL_BGRA,     GL_UNSIGNED_INT_8_8_8_8_REV,    PIPE_FORMAT_B8G8R8X8_UNORM },
+   { GL_RGBA,     GL_UNSIGNED_BYTE,               PIPE_FORMAT_R8G8B8X8_UNORM },
+   { GL_ABGR_EXT, GL_UNSIGNED_BYTE,               PIPE_FORMAT_X8B8G8R8_UNORM },
+   { GL_BGRA,     GL_UNSIGNED_BYTE,               PIPE_FORMAT_B8G8R8X8_UNORM },
+   { 0,           0,                              0                          }
+};
+
+static struct exact_format_mapping rgba1010102_tbl[] =
+{
+   { GL_BGRA,     GL_UNSIGNED_INT_2_10_10_10_REV, 
PIPE_FORMAT_B10G10R10A2_UNORM },
+   { GL_RGBA,     GL_UNSIGNED_INT_2_10_10_10_REV, 
PIPE_FORMAT_R10G10B10A2_UNORM },
+   { GL_ABGR_EXT, GL_UNSIGNED_INT_10_10_10_2,     
PIPE_FORMAT_R10G10B10A2_UNORM },
+   { GL_ABGR_EXT, GL_UNSIGNED_INT,                
PIPE_FORMAT_R10G10B10A2_UNORM },
+   { 0,           0,                              0                            
 }
+};
+
+/**
+ * If there is an exact pipe_format match for {internalFormat, format, type}
+ * return that, otherwise return PIPE_FORMAT_NONE so we can do fuzzy matching.
+ */
+static enum pipe_format
+find_exact_format(GLint internalFormat, GLenum format, GLenum type)
+{
+   uint i;
+   struct exact_format_mapping* tbl;
+
+   if ( format == GL_NONE || type == GL_NONE )
+      return PIPE_FORMAT_NONE;
+
+   switch (internalFormat) {
+   case 4:
+   case GL_RGBA:
+   case GL_RGBA8:
+      tbl = rgba8888_tbl;
+      break;
+   case 3:
+   case GL_RGB:
+   case GL_RGB8:
+      tbl = rgbx8888_tbl;
+      break;
+   case GL_RGB10_A2:
+      tbl = rgba1010102_tbl;
+      break;
+   default:
+      return PIPE_FORMAT_NONE;
+   }
+
+   for(i = 0; tbl[i].format; i++)
+      if (tbl[i].format == format && tbl[i].type == type)
+         return tbl[i].pformat;
+
+   return PIPE_FORMAT_NONE;
+}
 
 /**
  * Given an OpenGL internalFormat value for a texture or surface, return
@@ -1140,11 +1221,13 @@ find_supported_format(struct pipe_screen *screen,
  */
 enum pipe_format
 st_choose_format(struct pipe_screen *screen, GLenum internalFormat,
+                 GLenum format, GLenum type,
                  enum pipe_texture_target target, unsigned sample_count,
                  unsigned bindings)
 {
    GET_CURRENT_CONTEXT(ctx); /* XXX this should be a function parameter */
    int i, j;
+   enum pipe_format pf;
 
    /* can't render to compressed formats at this time */
    if (_mesa_is_compressed_format(ctx, internalFormat)
@@ -1152,6 +1235,11 @@ st_choose_format(struct pipe_screen *screen, GLenum 
internalFormat,
       return PIPE_FORMAT_NONE;
    }
 
+   /* search for exact matches */
+   pf = find_exact_format(internalFormat, format, type);
+   if (pf != PIPE_FORMAT_NONE)
+      return pf;
+
    /* search table for internalFormat */
    for (i = 0; i < Elements(format_map); i++) {
       const struct format_mapping *mapping = &format_map[i];
@@ -1183,7 +1271,7 @@ st_choose_renderbuffer_format(struct pipe_screen *screen,
       usage = PIPE_BIND_DEPTH_STENCIL;
    else
       usage = PIPE_BIND_RENDER_TARGET;
-   return st_choose_format(screen, internalFormat, PIPE_TEXTURE_2D,
+   return st_choose_format(screen, internalFormat, GL_NONE, GL_NONE, 
PIPE_TEXTURE_2D,
                            sample_count, usage);
 }
 
@@ -1210,12 +1298,12 @@ st_ChooseTextureFormat_renderable(struct gl_context 
*ctx, GLint internalFormat,
         bindings |= PIPE_BIND_RENDER_TARGET;
    }
 
-   pFormat = st_choose_format(screen, internalFormat,
+   pFormat = st_choose_format(screen, internalFormat, format, type,
                               PIPE_TEXTURE_2D, 0, bindings);
 
    if (pFormat == PIPE_FORMAT_NONE) {
       /* try choosing format again, this time without render target bindings */
-      pFormat = st_choose_format(screen, internalFormat,
+      pFormat = st_choose_format(screen, internalFormat, format, type,
                                  PIPE_TEXTURE_2D, 0, PIPE_BIND_SAMPLER_VIEW);
    }
 
diff --git a/src/mesa/state_tracker/st_format.h 
b/src/mesa/state_tracker/st_format.h
index 0fb570f..7bda785 100644
--- a/src/mesa/state_tracker/st_format.h
+++ b/src/mesa/state_tracker/st_format.h
@@ -52,6 +52,7 @@ st_pipe_format_to_mesa_format(enum pipe_format pipeFormat);
 
 extern enum pipe_format
 st_choose_format(struct pipe_screen *screen, GLenum internalFormat,
+                 GLenum format, GLenum type,
                  enum pipe_texture_target target, unsigned sample_count,
                  unsigned tex_usage);
 
-- 
1.7.5.3.367.ga9930

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to