summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Paul <[email protected]>2015-10-15 11:54:06 -0600
committerBrian Paul <[email protected]>2015-10-20 12:52:40 -0600
commitd11fefa96165836ffeed531a74319a64aa98a696 (patch)
tree8d5df86bf97d91a5d142e0844954b6b535f2cbe1
parentcf405922eb2bd4d1dfae896caa9d58980875e7ec (diff)
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 <[email protected]>
-rw-r--r--src/mesa/state_tracker/st_cb_drawpixels.c104
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 de7d1f6489a..262ad809c58 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.
*/