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 3 years ago committed by Marge Bot
parent 719d570cb8
commit 591a80d30a
  1. 60
      src/vrend_blitter.c
  2. 45
      src/vrend_blitter.h
  3. 2
      src/vrend_renderer.h

@ -44,6 +44,8 @@
#define BLIT_USE_GLES (1 << 0) #define BLIT_USE_GLES (1 << 0)
#define BLIT_USE_MSAA (1 << 1) #define BLIT_USE_MSAA (1 << 1)
#define BLIT_USE_DEPTH (1 << 2) #define BLIT_USE_DEPTH (1 << 2)
#define BLIT_MANUAL_SRGB_DECODE (1 << 3)
#define BLIT_MANUAL_SRGB_ENCODE (1 << 4)
struct vec4 { struct vec4 {
GLfloat x,y,z,w; GLfloat x,y,z,w;
@ -89,6 +91,8 @@ struct blit_swizzle_and_type {
struct blit_prog_key { struct blit_prog_key {
bool is_color: 1; bool is_color: 1;
bool is_msaa: 1; bool is_msaa: 1;
bool manual_srgb_decode: 1;
bool manual_srgb_encode: 1;
uint8_t num_samples; uint8_t num_samples;
int pipe_tex_target; int pipe_tex_target;
struct { struct {
@ -251,11 +255,12 @@ static GLuint blit_build_frag_tex_col(struct vrend_blitter_ctx *blit_ctx,
int tgsi_tex_target, int tgsi_tex_target,
enum tgsi_return_type tgsi_ret, enum tgsi_return_type tgsi_ret,
const uint8_t swizzle[4], const uint8_t swizzle[4],
int nr_samples) int nr_samples,
uint32_t flags)
{ {
char shader_buf[4096]; char shader_buf[4096];
struct blit_swizzle_and_type swizzle_and_type; struct blit_swizzle_and_type swizzle_and_type;
unsigned flags = 0; unsigned swizzle_flags = 0;
char dest_swizzle_snippet[DEST_SWIZZLE_SNIPPET_SIZE] = "texel"; char dest_swizzle_snippet[DEST_SWIZZLE_SNIPPET_SIZE] = "texel";
const char *ext_str = ""; const char *ext_str = "";
bool msaa = nr_samples > 0; 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) if (blit_ctx->use_gles)
flags |= BLIT_USE_GLES; swizzle_flags |= BLIT_USE_GLES;
if (msaa) if (msaa)
flags |= BLIT_USE_MSAA; swizzle_flags |= BLIT_USE_MSAA;
blit_get_swizzle(tgsi_tex_target, flags, &swizzle_and_type); blit_get_swizzle(tgsi_tex_target, swizzle_flags, &swizzle_and_type);
if (swizzle) if (swizzle)
create_dest_swizzle_snippet(swizzle, dest_swizzle_snippet); 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) if (msaa)
snprintf(shader_buf, 4096, blit_ctx->use_gles ? snprintf(shader_buf, 4096, blit_ctx->use_gles ?
(swizzle_and_type.is_array ? FS_TEXFETCH_COL_MSAA_ARRAY_GLES (swizzle_and_type.is_array ? FS_TEXFETCH_COL_MSAA_ARRAY_GLES
: FS_TEXFETCH_COL_MSAA_GLES) : FS_TEXFETCH_COL_MSAA_GLES)
: FS_TEXFETCH_COL_MSAA_GL, : FS_TEXFETCH_COL_MSAA_GL,
ext_str, vec4_type_for_tgsi_ret(tgsi_ret), 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_samplerreturnconv(tgsi_ret),
vrend_shader_samplertypeconv(blit_ctx->use_gles, tgsi_tex_target), vrend_shader_samplertypeconv(blit_ctx->use_gles, tgsi_tex_target),
nr_samples, swizzle_and_type.type, swizzle_and_type.swizzle, dest_swizzle_snippet); 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_GLES_1D : FS_TEXFETCH_COL_GLES)
: FS_TEXFETCH_COL_GL, : FS_TEXFETCH_COL_GL,
ext_str, vec4_type_for_tgsi_ret(tgsi_ret), 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_samplerreturnconv(tgsi_ret),
vrend_shader_samplertypeconv(blit_ctx->use_gles, tgsi_tex_target), vrend_shader_samplertypeconv(blit_ctx->use_gles, tgsi_tex_target),
swizzle_and_type.swizzle, dest_swizzle_snippet); 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, int pipe_tex_target,
unsigned nr_samples, unsigned nr_samples,
const struct vrend_format_table *src_entry, 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; bool needs_swizzle = false;
for (uint i = 0; i < 4; ++i) { 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 = { struct blit_prog_key key = {
.is_color = true, .is_color = true,
.is_msaa = nr_samples > 0, .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, .num_samples = nr_samples,
.pipe_tex_target = pipe_tex_target .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); 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; 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); glAttachShader(prog_id, fs_id);
if(!blit_shader_link_and_check(prog_id)) if(!blit_shader_link_and_check(prog_id))
return 0; return 0;
@ -789,10 +809,27 @@ void vrend_renderer_blit_gl(ASSERTED struct vrend_context *ctx,
} else { } else {
VREND_DEBUG(dbg_blit, ctx, "BLIT: applying swizzle during blit: (%d %d %d %d)\n", 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]); 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, prog_id = blit_get_frag_tex_col(blit_ctx, src_res->base.target,
src_res->base.nr_samples, src_res->base.nr_samples,
orig_src_entry, orig_src_entry,
info->swizzle); info->swizzle,
flags);
} }
if (!prog_id) { if (!prog_id) {
vrend_printf("Blitter: unable to create or find shader program\n"); 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); glDrawBuffers(1, &buffers);
glBindTexture(src_res->target, info->src_view); 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); vrend_set_vertex_param(prog_id);
set_dsa_write_depth_keep_stencil(); set_dsa_write_depth_keep_stencil();
@ -822,7 +861,8 @@ void vrend_renderer_blit_gl(ASSERTED struct vrend_context *ctx,
glDisable(GL_SCISSOR_TEST); glDisable(GL_SCISSOR_TEST);
if (info->has_srgb_write_control) { 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__); VREND_DEBUG(dbg_blit, ctx, "%s: Enable GL_FRAMEBUFFER_SRGB\n", __func__);
glEnable(GL_FRAMEBUFFER_SRGB); glEnable(GL_FRAMEBUFFER_SRGB);
} else { } else {

@ -62,6 +62,26 @@
"#extension GL_OES_texture_storage_multisample_2d_array: require\n" \ "#extension GL_OES_texture_storage_multisample_2d_array: require\n" \
"precision mediump float;\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 \ #define VS_PASSTHROUGH_BODY \
"in vec4 arg0;\n" \ "in vec4 arg0;\n" \
"in vec4 arg1;\n" \ "in vec4 arg1;\n" \
@ -74,25 +94,32 @@
#define VS_PASSTHROUGH_GL HEADER_GL VS_PASSTHROUGH_BODY #define VS_PASSTHROUGH_GL HEADER_GL VS_PASSTHROUGH_BODY
#define VS_PASSTHROUGH_GLES HEADER_GLES VS_PASSTHROUGH_BODY #define VS_PASSTHROUGH_GLES HEADER_GLES VS_PASSTHROUGH_BODY
#define FS_TEXFETCH_COL_BODY \ #define FS_TEXFETCH_COL_BODY \
"#define cvec4 %s\n" \ "#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" \ "uniform mediump %csampler%s samp;\n" \
"in vec4 tc;\n" \ "in vec4 tc;\n" \
"out cvec4 FragColor;\n" \ "out cvec4 FragColor;\n" \
"void main() {\n" \ "void main() {\n" \
" cvec4 texel = texture(samp, tc%s);\n" \ " cvec4 texel = decode(cvec4(texture(samp, tc%s)));\n" \
" FragColor = cvec4(%s);\n" \ " FragColor = encode(cvec4(%s));\n" \
"}\n" "}\n"
#define FS_TEXFETCH_COL_GLES_1D_BODY \ #define FS_TEXFETCH_COL_GLES_1D_BODY \
"#define cvec4 %s\n" \ "#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" \ "uniform mediump %csampler%s samp;\n" \
"in vec4 tc;\n" \ "in vec4 tc;\n" \
"out cvec4 FragColor;\n" \ "out cvec4 FragColor;\n" \
"void main() {\n" \ "void main() {\n" \
" cvec4 texel = texture(samp, vec2(tc%s, 0.5));\n" \ " cvec4 texel = decode(texture(samp, vec2(tc%s, 0.5)));\n" \
" FragColor = cvec4(%s);\n" \ " FragColor = encode(cvec4(%s));\n" \
"}\n" "}\n"
#define FS_TEXFETCH_COL_GL FS_HEADER_GL FS_TEXFETCH_COL_BODY #define FS_TEXFETCH_COL_GL FS_HEADER_GL FS_TEXFETCH_COL_BODY
@ -101,6 +128,10 @@
#define FS_TEXFETCH_COL_MSAA_BODY \ #define FS_TEXFETCH_COL_MSAA_BODY \
"#define cvec4 %s\n" \ "#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" \ "uniform mediump %csampler%s samp;\n" \
"in vec4 tc;\n" \ "in vec4 tc;\n" \
"out cvec4 FragColor;\n" \ "out cvec4 FragColor;\n" \
@ -108,9 +139,9 @@
" const int num_samples = %d;\n" \ " const int num_samples = %d;\n" \
" cvec4 texel = cvec4(0);\n" \ " cvec4 texel = cvec4(0);\n" \
" for (int i = 0; i < num_samples; ++i) \n" \ " for (int i = 0; i < num_samples; ++i) \n" \
" texel += texelFetch(samp, %s(tc%s), i);\n" \ " texel += decode(texelFetch(samp, %s(tc%s), i));\n" \
" texel = texel / cvec4(num_samples);\n" \ " texel = texel / cvec4(num_samples);\n" \
" FragColor = cvec4(%s);\n" \ " FragColor = encode(cvec4(%s));\n" \
"}\n" "}\n"
#define FS_TEXFETCH_COL_MSAA_GL FS_HEADER_GL FS_TEXFETCH_COL_MSAA_BODY #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 can_fbo_blit;
bool has_texture_srgb_decode; bool has_texture_srgb_decode;
bool has_srgb_write_control; 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, void vrend_renderer_resource_get_info(struct pipe_resource *pres,

Loading…
Cancel
Save