diff options
author | Brian Paul <brianp@vmware.com> | 2015-10-15 11:54:06 -0600 |
---|---|---|
committer | Brian Paul <brianp@vmware.com> | 2015-10-20 12:52:40 -0600 |
commit | d11fefa96165836ffeed531a74319a64aa98a696 (patch) | |
tree | 8d5df86bf97d91a5d142e0844954b6b535f2cbe1 | |
parent | cf405922eb2bd4d1dfae896caa9d58980875e7ec (diff) | |
download | external_mesa3d-d11fefa96165836ffeed531a74319a64aa98a696.zip external_mesa3d-d11fefa96165836ffeed531a74319a64aa98a696.tar.gz external_mesa3d-d11fefa96165836ffeed531a74319a64aa98a696.tar.bz2 |
st/mesa: optimize 4-component ubyte glDrawPixels
If we didn't find a gallium surface format that exactly matched the
glDrawPixels format/type combination, we used some other 32-bit packed
RGBA format and swizzled the whole image in the mesa texstore/format code.
That slow path can be avoided in some common cases by using the
pipe_samper_view's swizzle terms to do the swizzling at texture sampling
time instead.
For now, only GL_RGBA/ubyte and GL_BGRA/ubyte combinations are supported.
In the future other formats and types like GL_UNSIGNED_INT_8_8_8_8 could
be added.
v2: fix incorrect swizzle setup (need to invert the tex format's swizzle)
Reviewed by: Jose Fonseca <jfonseca@vmware.com>
-rw-r--r-- | src/mesa/state_tracker/st_cb_drawpixels.c | 104 |
1 files changed, 95 insertions, 9 deletions
diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c index de7d1f6..262ad80 100644 --- a/src/mesa/state_tracker/st_cb_drawpixels.c +++ b/src/mesa/state_tracker/st_cb_drawpixels.c @@ -395,15 +395,35 @@ make_texture(struct st_context *st, * Note that the image is actually going to be upside down in * the texture. We deal with that with texcoords. */ - success = _mesa_texstore(ctx, 2, /* dims */ - baseInternalFormat, /* baseInternalFormat */ - mformat, /* mesa_format */ - transfer->stride, /* dstRowStride, bytes */ - &dest, /* destSlices */ - width, height, 1, /* size */ - format, type, /* src format/type */ - pixels, /* data source */ - unpack); + if ((format == GL_RGBA || format == GL_BGRA) + && type == GL_UNSIGNED_BYTE) { + /* Use a memcpy-based texstore to avoid software pixel swizzling. + * We'll do the necessary swizzling with the pipe_sampler_view to + * give much better performance. + * XXX in the future, expand this to accomodate more format and + * type combinations. + */ + _mesa_memcpy_texture(ctx, 2, + mformat, /* mesa_format */ + transfer->stride, /* dstRowStride, bytes */ + &dest, /* destSlices */ + width, height, 1, /* size */ + format, type, /* src format/type */ + pixels, /* data source */ + unpack); + success = GL_TRUE; + } + else { + success = _mesa_texstore(ctx, 2, /* dims */ + baseInternalFormat, /* baseInternalFormat */ + mformat, /* mesa_format */ + transfer->stride, /* dstRowStride, bytes */ + &dest, /* destSlices */ + width, height, 1, /* size */ + format, type, /* src format/type */ + pixels, /* data source */ + unpack); + } /* unmap */ pipe_transfer_unmap(pipe, transfer); @@ -958,6 +978,69 @@ clamp_size(struct pipe_context *pipe, GLsizei *width, GLsizei *height, /** + * Search the array of 4 swizzle components for the named component and return + * its position. + */ +static unsigned +search_swizzle(const unsigned char swizzle[4], unsigned component) +{ + unsigned i; + for (i = 0; i < 4; i++) { + if (swizzle[i] == component) + return i; + } + assert(!"search_swizzle() failed"); + return 0; +} + + +/** + * Set the sampler view's swizzle terms. This is used to handle RGBA + * swizzling when the incoming image format isn't an exact match for + * the actual texture format. For example, if we have glDrawPixels( + * GL_RGBA, GL_UNSIGNED_BYTE) and we chose the texture format + * PIPE_FORMAT_B8G8R8A8 then we can do use the sampler view swizzle to + * avoid swizzling all the pixels in software in the texstore code. + */ +static void +setup_sampler_swizzle(struct pipe_sampler_view *sv, GLenum format, GLenum type) +{ + if ((format == GL_RGBA || format == GL_BGRA) && type == GL_UNSIGNED_BYTE) { + const struct util_format_description *desc = + util_format_description(sv->texture->format); + unsigned c0, c1, c2, c3; + + /* Every gallium driver supports at least one 32-bit packed RGBA format. + * We must have chosen one for (GL_RGBA, GL_UNSIGNED_BYTE). + */ + assert(desc->block.bits == 32); + + /* invert the format's swizzle to setup the sampler's swizzle */ + if (format == GL_RGBA) { + c0 = UTIL_FORMAT_SWIZZLE_X; + c1 = UTIL_FORMAT_SWIZZLE_Y; + c2 = UTIL_FORMAT_SWIZZLE_Z; + c3 = UTIL_FORMAT_SWIZZLE_W; + } + else { + assert(format == GL_BGRA); + c0 = UTIL_FORMAT_SWIZZLE_Z; + c1 = UTIL_FORMAT_SWIZZLE_Y; + c2 = UTIL_FORMAT_SWIZZLE_X; + c3 = UTIL_FORMAT_SWIZZLE_W; + } + sv->swizzle_r = search_swizzle(desc->swizzle, c0); + sv->swizzle_g = search_swizzle(desc->swizzle, c1); + sv->swizzle_b = search_swizzle(desc->swizzle, c2); + sv->swizzle_a = search_swizzle(desc->swizzle, c3); + } + else { + /* use the default sampler swizzle */ + } +} + + +/** * Called via ctx->Driver.DrawPixels() */ static void @@ -1046,6 +1129,9 @@ st_DrawPixels(struct gl_context *ctx, GLint x, GLint y, return; } + /* Set up the sampler view's swizzle */ + setup_sampler_swizzle(sv[0], format, type); + /* Create a second sampler view to read stencil. The stencil is * written using the shader stencil export functionality. */ |