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>
This commit is contained in:
@@ -395,15 +395,35 @@ make_texture(struct st_context *st,
|
|||||||
* Note that the image is actually going to be upside down in
|
* Note that the image is actually going to be upside down in
|
||||||
* the texture. We deal with that with texcoords.
|
* the texture. We deal with that with texcoords.
|
||||||
*/
|
*/
|
||||||
success = _mesa_texstore(ctx, 2, /* dims */
|
if ((format == GL_RGBA || format == GL_BGRA)
|
||||||
baseInternalFormat, /* baseInternalFormat */
|
&& type == GL_UNSIGNED_BYTE) {
|
||||||
mformat, /* mesa_format */
|
/* Use a memcpy-based texstore to avoid software pixel swizzling.
|
||||||
transfer->stride, /* dstRowStride, bytes */
|
* We'll do the necessary swizzling with the pipe_sampler_view to
|
||||||
&dest, /* destSlices */
|
* give much better performance.
|
||||||
width, height, 1, /* size */
|
* XXX in the future, expand this to accomodate more format and
|
||||||
format, type, /* src format/type */
|
* type combinations.
|
||||||
pixels, /* data source */
|
*/
|
||||||
unpack);
|
_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 */
|
/* unmap */
|
||||||
pipe_transfer_unmap(pipe, transfer);
|
pipe_transfer_unmap(pipe, transfer);
|
||||||
@@ -957,6 +977,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()
|
* Called via ctx->Driver.DrawPixels()
|
||||||
*/
|
*/
|
||||||
@@ -1046,6 +1129,9 @@ st_DrawPixels(struct gl_context *ctx, GLint x, GLint y,
|
|||||||
return;
|
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
|
/* Create a second sampler view to read stencil. The stencil is
|
||||||
* written using the shader stencil export functionality.
|
* written using the shader stencil export functionality.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user