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