vrend: blitter: add option for manual srgb decode/encode

This is needed for bgr* textures backed by eglimages that traditionally
used glTextureView() to mediate colorspace conversions, as that approach
has been determined to cause format misinterpretation issues.

This commit simply adds the capabilty but doesn't enable such manual
encode/decode for any uses yet.

Signed-off-by: Ryan Neph <ryanneph@google.com>
Reviewed-by: Gert Wollny <gert.wollny@collabora.com>
Part-of: <https://gitlab.freedesktop.org/virgl/virglrenderer/-/merge_requests/725>
macos/master
Ryan Neph 2 years ago committed by Marge Bot
parent 719d570cb8
commit 591a80d30a
  1. 66
      src/vrend_blitter.c
  2. 89
      src/vrend_blitter.h
  3. 2
      src/vrend_renderer.h

@ -41,9 +41,11 @@
#define DEST_SWIZZLE_SNIPPET_SIZE 64
#define BLIT_USE_GLES (1 << 0)
#define BLIT_USE_MSAA (1 << 1)
#define BLIT_USE_DEPTH (1 << 2)
#define BLIT_USE_GLES (1 << 0)
#define BLIT_USE_MSAA (1 << 1)
#define BLIT_USE_DEPTH (1 << 2)
#define BLIT_MANUAL_SRGB_DECODE (1 << 3)
#define BLIT_MANUAL_SRGB_ENCODE (1 << 4)
struct vec4 {
GLfloat x,y,z,w;
@ -89,6 +91,8 @@ struct blit_swizzle_and_type {
struct blit_prog_key {
bool is_color: 1;
bool is_msaa: 1;
bool manual_srgb_decode: 1;
bool manual_srgb_encode: 1;
uint8_t num_samples;
int pipe_tex_target;
struct {
@ -251,11 +255,12 @@ static GLuint blit_build_frag_tex_col(struct vrend_blitter_ctx *blit_ctx,
int tgsi_tex_target,
enum tgsi_return_type tgsi_ret,
const uint8_t swizzle[4],
int nr_samples)
int nr_samples,
uint32_t flags)
{
char shader_buf[4096];
struct blit_swizzle_and_type swizzle_and_type;
unsigned flags = 0;
unsigned swizzle_flags = 0;
char dest_swizzle_snippet[DEST_SWIZZLE_SNIPPET_SIZE] = "texel";
const char *ext_str = "";
bool msaa = nr_samples > 0;
@ -271,20 +276,27 @@ static GLuint blit_build_frag_tex_col(struct vrend_blitter_ctx *blit_ctx,
}
if (blit_ctx->use_gles)
flags |= BLIT_USE_GLES;
swizzle_flags |= BLIT_USE_GLES;
if (msaa)
flags |= BLIT_USE_MSAA;
blit_get_swizzle(tgsi_tex_target, flags, &swizzle_and_type);
swizzle_flags |= BLIT_USE_MSAA;
blit_get_swizzle(tgsi_tex_target, swizzle_flags, &swizzle_and_type);
if (swizzle)
create_dest_swizzle_snippet(swizzle, dest_swizzle_snippet);
bool needs_manual_srgb_decode = has_bit(flags, BLIT_MANUAL_SRGB_DECODE);
bool needs_manual_srgb_encode = has_bit(flags, BLIT_MANUAL_SRGB_ENCODE);
if (msaa)
snprintf(shader_buf, 4096, blit_ctx->use_gles ?
(swizzle_and_type.is_array ? FS_TEXFETCH_COL_MSAA_ARRAY_GLES
: FS_TEXFETCH_COL_MSAA_GLES)
: FS_TEXFETCH_COL_MSAA_GL,
ext_str, vec4_type_for_tgsi_ret(tgsi_ret),
needs_manual_srgb_decode ? FS_FUNC_COL_SRGB_DECODE : "",
needs_manual_srgb_encode ? FS_FUNC_COL_SRGB_ENCODE : "",
needs_manual_srgb_decode ? "srgb_decode" : "",
needs_manual_srgb_encode ? "srgb_encode" : "",
vrend_shader_samplerreturnconv(tgsi_ret),
vrend_shader_samplertypeconv(blit_ctx->use_gles, tgsi_tex_target),
nr_samples, swizzle_and_type.type, swizzle_and_type.swizzle, dest_swizzle_snippet);
@ -294,6 +306,10 @@ static GLuint blit_build_frag_tex_col(struct vrend_blitter_ctx *blit_ctx,
FS_TEXFETCH_COL_GLES_1D : FS_TEXFETCH_COL_GLES)
: FS_TEXFETCH_COL_GL,
ext_str, vec4_type_for_tgsi_ret(tgsi_ret),
needs_manual_srgb_decode ? FS_FUNC_COL_SRGB_DECODE : "",
needs_manual_srgb_encode ? FS_FUNC_COL_SRGB_ENCODE : "",
needs_manual_srgb_decode ? "srgb_decode" : "",
needs_manual_srgb_encode ? "srgb_encode" : "",
vrend_shader_samplerreturnconv(tgsi_ret),
vrend_shader_samplertypeconv(blit_ctx->use_gles, tgsi_tex_target),
swizzle_and_type.swizzle, dest_swizzle_snippet);
@ -362,7 +378,8 @@ static GLuint blit_get_frag_tex_col(struct vrend_blitter_ctx *blit_ctx,
int pipe_tex_target,
unsigned nr_samples,
const struct vrend_format_table *src_entry,
const uint8_t swizzle[static 4])
const uint8_t swizzle[static 4],
uint32_t flags)
{
bool needs_swizzle = false;
for (uint i = 0; i < 4; ++i) {
@ -375,6 +392,8 @@ static GLuint blit_get_frag_tex_col(struct vrend_blitter_ctx *blit_ctx,
struct blit_prog_key key = {
.is_color = true,
.is_msaa = nr_samples > 0,
.manual_srgb_decode = has_bit(flags, BLIT_MANUAL_SRGB_DECODE),
.manual_srgb_encode = has_bit(flags, BLIT_MANUAL_SRGB_ENCODE),
.num_samples = nr_samples,
.pipe_tex_target = pipe_tex_target
};
@ -396,7 +415,8 @@ static GLuint blit_get_frag_tex_col(struct vrend_blitter_ctx *blit_ctx,
enum tgsi_return_type tgsi_ret = tgsi_ret_for_format(src_entry->format);
int msaa_samples = nr_samples > 0 ? (tgsi_ret == TGSI_RETURN_TYPE_UNORM ? nr_samples : 1) : 0;
GLuint fs_id = blit_build_frag_tex_col(blit_ctx, tgsi_tex, tgsi_ret, swizzle, msaa_samples);
GLuint fs_id = blit_build_frag_tex_col(blit_ctx, tgsi_tex, tgsi_ret,
swizzle, msaa_samples, flags);
glAttachShader(prog_id, fs_id);
if(!blit_shader_link_and_check(prog_id))
return 0;
@ -789,10 +809,27 @@ void vrend_renderer_blit_gl(ASSERTED struct vrend_context *ctx,
} else {
VREND_DEBUG(dbg_blit, ctx, "BLIT: applying swizzle during blit: (%d %d %d %d)\n",
info->swizzle[0], info->swizzle[1], info->swizzle[2], info->swizzle[3]);
if (info->needs_manual_srgb_decode)
VREND_DEBUG(dbg_blit, ctx,
"BLIT: applying manual srgb->linear conversion for src %s(%s)\n",
util_format_name(src_res->base.format),
util_format_name(info->b.src.format));
if (info->needs_manual_srgb_encode)
VREND_DEBUG(dbg_blit, ctx,
"BLIT: applying manual linear->srgb conversion for dst %s(%s)\n",
util_format_name(dst_res->base.format),
util_format_name(info->b.dst.format));
uint32_t flags = 0;
flags |= info->needs_manual_srgb_decode ? BLIT_MANUAL_SRGB_DECODE : 0;
flags |= info->needs_manual_srgb_encode ? BLIT_MANUAL_SRGB_ENCODE : 0;
prog_id = blit_get_frag_tex_col(blit_ctx, src_res->base.target,
src_res->base.nr_samples,
orig_src_entry,
info->swizzle);
info->swizzle,
flags);
}
if (!prog_id) {
vrend_printf("Blitter: unable to create or find shader program\n");
@ -808,7 +845,9 @@ void vrend_renderer_blit_gl(ASSERTED struct vrend_context *ctx,
glDrawBuffers(1, &buffers);
glBindTexture(src_res->target, info->src_view);
vrend_set_tex_param(src_res, &info->b, info->has_texture_srgb_decode);
vrend_set_tex_param(src_res, &info->b,
info->has_texture_srgb_decode &&
!info->needs_manual_srgb_decode);
vrend_set_vertex_param(prog_id);
set_dsa_write_depth_keep_stencil();
@ -822,7 +861,8 @@ void vrend_renderer_blit_gl(ASSERTED struct vrend_context *ctx,
glDisable(GL_SCISSOR_TEST);
if (info->has_srgb_write_control) {
if (util_format_is_srgb(info->b.dst.format) || util_format_is_srgb(info->b.src.format)) {
if (!info->needs_manual_srgb_encode &&
(util_format_is_srgb(info->b.dst.format) || util_format_is_srgb(info->b.src.format))) {
VREND_DEBUG(dbg_blit, ctx, "%s: Enable GL_FRAMEBUFFER_SRGB\n", __func__);
glEnable(GL_FRAMEBUFFER_SRGB);
} else {

@ -62,6 +62,26 @@
"#extension GL_OES_texture_storage_multisample_2d_array: require\n" \
"precision mediump float;\n" \
#define FS_FUNC_COL_SRGB_DECODE \
"cvec4 srgb_decode(cvec4 col) {\n" \
" vec3 temp = vec3(col.rgb);\n" \
" bvec3 thresh = lessThanEqual(temp, vec3(0.04045));\n" \
" vec3 a = temp / vec3(12.92);\n" \
" vec3 b = pow((temp + vec3(0.055)) / vec3(1.055), vec3(2.4));\n" \
" return cvec4(clamp(mix(b, a, thresh), 0.0, 1.0), col.a);\n" \
"}\n"
#define FS_FUNC_COL_SRGB_ENCODE \
"cvec4 srgb_encode(cvec4 col) {\n" \
" vec3 temp = vec3(col.rgb);\n" \
" bvec3 thresh = lessThanEqual(temp, vec3(0.0031308));\n" \
" vec3 a = temp * vec3(12.92);\n" \
" vec3 b = (vec3(1.055) * pow(temp, vec3(1.0 / 2.4))) - vec3(0.055);\n" \
" return cvec4(mix(b, a, thresh), col.a);\n" \
"}\n"
#define VS_PASSTHROUGH_BODY \
"in vec4 arg0;\n" \
"in vec4 arg1;\n" \
@ -74,43 +94,54 @@
#define VS_PASSTHROUGH_GL HEADER_GL VS_PASSTHROUGH_BODY
#define VS_PASSTHROUGH_GLES HEADER_GLES VS_PASSTHROUGH_BODY
#define FS_TEXFETCH_COL_BODY \
"#define cvec4 %s\n" \
"uniform mediump %csampler%s samp;\n" \
"in vec4 tc;\n" \
"out cvec4 FragColor;\n" \
"void main() {\n" \
" cvec4 texel = texture(samp, tc%s);\n" \
" FragColor = cvec4(%s);\n" \
#define FS_TEXFETCH_COL_BODY \
"#define cvec4 %s\n" \
"%s\n" /* conditional decode() */ \
"%s\n" /* conditional encode() */ \
"#define decode %s\n" \
"#define encode %s\n" \
"uniform mediump %csampler%s samp;\n" \
"in vec4 tc;\n" \
"out cvec4 FragColor;\n" \
"void main() {\n" \
" cvec4 texel = decode(cvec4(texture(samp, tc%s)));\n" \
" FragColor = encode(cvec4(%s));\n" \
"}\n"
#define FS_TEXFETCH_COL_GLES_1D_BODY \
"#define cvec4 %s\n" \
"uniform mediump %csampler%s samp;\n" \
"in vec4 tc;\n" \
"out cvec4 FragColor;\n" \
"void main() {\n" \
" cvec4 texel = texture(samp, vec2(tc%s, 0.5));\n" \
" FragColor = cvec4(%s);\n" \
#define FS_TEXFETCH_COL_GLES_1D_BODY \
"#define cvec4 %s\n" \
"%s\n" /* conditional decode() */ \
"%s\n" /* conditional encode() */ \
"#define decode %s\n" \
"#define encode %s\n" \
"uniform mediump %csampler%s samp;\n" \
"in vec4 tc;\n" \
"out cvec4 FragColor;\n" \
"void main() {\n" \
" cvec4 texel = decode(texture(samp, vec2(tc%s, 0.5)));\n" \
" FragColor = encode(cvec4(%s));\n" \
"}\n"
#define FS_TEXFETCH_COL_GL FS_HEADER_GL FS_TEXFETCH_COL_BODY
#define FS_TEXFETCH_COL_GLES FS_HEADER_GLES FS_TEXFETCH_COL_BODY
#define FS_TEXFETCH_COL_GLES_1D FS_HEADER_GLES FS_TEXFETCH_COL_GLES_1D_BODY
#define FS_TEXFETCH_COL_MSAA_BODY \
"#define cvec4 %s\n" \
"uniform mediump %csampler%s samp;\n" \
"in vec4 tc;\n" \
"out cvec4 FragColor;\n" \
"void main() {\n" \
" const int num_samples = %d;\n" \
" cvec4 texel = cvec4(0);\n" \
" for (int i = 0; i < num_samples; ++i) \n" \
" texel += texelFetch(samp, %s(tc%s), i);\n" \
" texel = texel / cvec4(num_samples);\n" \
" FragColor = cvec4(%s);\n" \
#define FS_TEXFETCH_COL_MSAA_BODY \
"#define cvec4 %s\n" \
"%s\n" /* conditional decode() */ \
"%s\n" /* conditional encode() */ \
"#define decode %s\n" \
"#define encode %s\n" \
"uniform mediump %csampler%s samp;\n" \
"in vec4 tc;\n" \
"out cvec4 FragColor;\n" \
"void main() {\n" \
" const int num_samples = %d;\n" \
" cvec4 texel = cvec4(0);\n" \
" for (int i = 0; i < num_samples; ++i) \n" \
" texel += decode(texelFetch(samp, %s(tc%s), i));\n" \
" texel = texel / cvec4(num_samples);\n" \
" FragColor = encode(cvec4(%s));\n" \
"}\n"
#define FS_TEXFETCH_COL_MSAA_GL FS_HEADER_GL FS_TEXFETCH_COL_MSAA_BODY

@ -469,6 +469,8 @@ struct vrend_blit_info {
bool can_fbo_blit;
bool has_texture_srgb_decode;
bool has_srgb_write_control;
bool needs_manual_srgb_decode;
bool needs_manual_srgb_encode;
};
void vrend_renderer_resource_get_info(struct pipe_resource *pres,

Loading…
Cancel
Save