[Mesa-dev] [PATCH 2/2] st/mesa: accelerate glGetTexImage for all formats using a blit

Marek Olšák maraeo at gmail.com
Sun Feb 10 18:38:42 PST 2013


FYI, I am squashing the following diff with the patch, because I
realized desc->channel[i].type wasn't correct, because it's always
UTIL_FORMAT_TYPE_VOID. (please ignore any line wrapping caused by my
email client, thanks)

diff --git a/src/mesa/state_tracker/st_cb_texture.c
b/src/mesa/state_tracker/st_cb_texture.c
index 3b6a9bb..ac70e92 100644
--- a/src/mesa/state_tracker/st_cb_texture.c
+++ b/src/mesa/state_tracker/st_cb_texture.c
@@ -687,9 +687,7 @@ st_GetTexImage(struct gl_context * ctx,
                                        ctx->Pack.SwapBytes);

    if (dst_format == PIPE_FORMAT_NONE) {
-      const struct util_format_description *desc;
       GLenum dst_glformat;
-      int i;

       /* Fall back to _mesa_get_teximage except for compressed formats,
        * where decompression with a blit is always preferred. */
@@ -697,31 +695,32 @@ st_GetTexImage(struct gl_context * ctx,
          goto fallback;
       }

-      /* Set the appropriate format for the decompressed texture. */
-      desc = util_format_description(src->format);
-      i = util_format_get_first_non_void_channel(src->format);
-
-      switch (desc->channel[i].type) {
-      case UTIL_FORMAT_TYPE_UNSIGNED: /* DXTC or RGTC or BPTC */
+      /* Set the appropriate format for the decompressed texture.
+       * Luminance and sRGB formats shouldn't appear here.*/
+      switch (src_format) {
+      case PIPE_FORMAT_DXT1_RGB:
+      case PIPE_FORMAT_DXT1_RGBA:
+      case PIPE_FORMAT_DXT3_RGBA:
+      case PIPE_FORMAT_DXT5_RGBA:
+      case PIPE_FORMAT_RGTC1_UNORM:
+      case PIPE_FORMAT_RGTC2_UNORM:
+      case PIPE_FORMAT_ETC1_RGB8:
          dst_glformat = GL_RGBA8;
          break;
-      case UTIL_FORMAT_TYPE_SIGNED: /* RGTC */
+      case PIPE_FORMAT_RGTC1_SNORM:
+      case PIPE_FORMAT_RGTC2_SNORM:
          if (!ctx->Extensions.EXT_texture_snorm)
             goto fallback;
          dst_glformat = GL_RGBA8_SNORM;
          break;
-      case UTIL_FORMAT_TYPE_FLOAT: /* BPTC */
-         if (!ctx->Extensions.ARB_texture_float)
-            goto fallback;
-         dst_glformat = GL_RGBA32F;
-         break;
+      /* TODO: for BPTC_*FLOAT, set RGBA32F and check for ARB_texture_float */
       default:
          assert(0);
          goto fallback;
       }

       dst_format = st_choose_format(st, dst_glformat, format, type,
-                                     pipe_target, 0, bind, FALSE);
+                                    pipe_target, 0, bind, FALSE);

       if (dst_format == PIPE_FORMAT_NONE) {
          /* unable to get an rgba format!?! */

Marek

On Fri, Feb 8, 2013 at 1:57 AM, Brian Paul <brianp at vmware.com> wrote:
> On 02/07/2013 01:13 PM, Marek Olšák wrote:
>>
>> This commit allows using glGetTexImage during rendering and still
>> maintain interactive framerates.
>>
>> This improves performance of WarCraft 3 under Wine. The framerate is
>> improved
>> from 25 fps to 39 fps in the main menu, and from 0.5 fps to 32 fps in the
>> game.
>> ---
>>   src/mesa/state_tracker/st_cb_texture.c |  201
>> ++++++++++++++++++++++++--------
>>   src/mesa/state_tracker/st_format.c     |    1 -
>>   2 files changed, 153 insertions(+), 49 deletions(-)
>>
>> diff --git a/src/mesa/state_tracker/st_cb_texture.c
>> b/src/mesa/state_tracker/st_cb_texture.c
>> index ab5ff27..3b6a9bb 100644
>> --- a/src/mesa/state_tracker/st_cb_texture.c
>> +++ b/src/mesa/state_tracker/st_cb_texture.c
>> @@ -560,15 +560,52 @@ st_CompressedTexImage(struct gl_context *ctx, GLuint
>> dims,
>>   }
>>
>>
>> +static enum pipe_format
>> +choose_matching_format(struct pipe_screen *screen, unsigned bind,
>> +                       GLenum format, GLenum type, GLboolean swapBytes)
>> +{
>> +   gl_format mesa_format;
>> +
>> +   for (mesa_format = 1; mesa_format<  MESA_FORMAT_COUNT; mesa_format++)
>> {
>> +      if (_mesa_get_format_color_encoding(mesa_format) == GL_SRGB) {
>> +         continue;
>> +      }
>> +
>> +      if (_mesa_format_matches_format_and_type(mesa_format, format, type,
>> +                                               swapBytes)) {
>> +         enum pipe_format format =
>> st_mesa_format_to_pipe_format(mesa_format);
>> +
>> +         if (format&&
>> +             screen->is_format_supported(screen, format, PIPE_TEXTURE_2D,
>> 0,
>> +                                         bind)) {
>> +            return format;
>> +         }
>> +         /* It's unlikely to find 2 matching Mesa formats. */
>> +         break;
>> +      }
>> +   }
>> +   return PIPE_FORMAT_NONE;
>> +}
>
>
> This seems like kind of an inefficient function.  If we find that the app is
> calling glGetTexImage() over and over with the same format/type, perhaps we
> could cache the result of this function to avoid calling it the next time.
> Maybe that's not a big deal though.
>
> The st_cb_drawpixels.c file has some similar code that tries to find a
> pipe_format that matches a GL format/type combo.  Your new code is more
> sophisticated.  Maybe it could be used for glDrawPixels too.
>
> [...]
>
> Otherwise, this all looks good to me.
>
> Reviewed-by: Brian Paul <brianp at vmware.com>


More information about the mesa-dev mailing list