From 4749e8791ba60f7b8e9b37bd0372ea00fba64139 Mon Sep 17 00:00:00 2001 From: Gert Wollny Date: Mon, 27 May 2019 15:19:50 +0200 Subject: [PATCH] formats: Add emulated versions of some BGRA formats On GLES B8G8R8A8_SRGB is not available and B8G8R8A8_UNORM can not be created as immutable. In order to have versions of these formats that can be created immutable on GLES provide the formats R8G8B8A8_SRGB and _UNORM with swizzling to BGRA that can then be used instead of the BGRA formats. Since this may break things these swizzled versions will later be only enabled when the guest requests them. v2: Check the base swizzled BGRA format only on GL v3: Correct type in method name (Gurchetan) v4: Add PREFER_EMULATED_BRGA to according format binding flags (Gurchetan) v5: Add comment about formats nou to be used in the guest (Gurchetan) Signed-off-by: Gert Wollny Reviewed-by: Gurchetan Singh --- src/virgl_hw.h | 7 +++- src/vrend_formats.c | 97 +++++++++++++++++++++++++++++--------------- src/vrend_renderer.c | 2 +- 3 files changed, 71 insertions(+), 35 deletions(-) diff --git a/src/virgl_hw.h b/src/virgl_hw.h index 91e4259..37ae2ba 100644 --- a/src/virgl_hw.h +++ b/src/virgl_hw.h @@ -222,7 +222,12 @@ enum virgl_formats { VIRGL_FORMAT_A4B4G4R4_UNORM = 311, VIRGL_FORMAT_R8_SRGB = 312, - VIRGL_FORMAT_MAX, + VIRGL_FORMAT_MAX /* = PIPE_FORMAT_COUNT */, + + /* Below formats must not be used in the guest. */ + VIRGL_FORMAT_B8G8R8X8_UNORM_EMULATED, + VIRGL_FORMAT_B8G8R8A8_UNORM_EMULATED, + VIRGL_FORMAT_MAX_EXTENDED }; /* These are used by the capability_bits field in virgl_caps_v2. */ diff --git a/src/vrend_formats.c b/src/vrend_formats.c index 9f88bfc..1e5c4b0 100644 --- a/src/vrend_formats.c +++ b/src/vrend_formats.c @@ -32,6 +32,9 @@ #define RRR1_SWIZZLE { PIPE_SWIZZLE_RED, PIPE_SWIZZLE_RED, PIPE_SWIZZLE_RED, PIPE_SWIZZLE_ONE } #define RGB1_SWIZZLE { PIPE_SWIZZLE_RED, PIPE_SWIZZLE_GREEN, PIPE_SWIZZLE_BLUE, PIPE_SWIZZLE_ONE } +#define BGR1_SWIZZLE { PIPE_SWIZZLE_BLUE, PIPE_SWIZZLE_GREEN, PIPE_SWIZZLE_RED, PIPE_SWIZZLE_ONE } +#define BGRA_SWIZZLE { PIPE_SWIZZLE_BLUE, PIPE_SWIZZLE_GREEN, PIPE_SWIZZLE_RED, PIPE_SWIZZLE_ALPHA } + #ifdef __GNUC__ /* The warning missing-field-initializers is misleading: If at least one field * is initialized, then the un-initialized fields will be filled with zero. @@ -50,9 +53,6 @@ /* fill the format table */ static struct vrend_format_table base_rgba_formats[] = { - { VIRGL_FORMAT_B8G8R8X8_UNORM, GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE, RGB1_SWIZZLE }, - { VIRGL_FORMAT_B8G8R8A8_UNORM, GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE, NO_SWIZZLE }, - { VIRGL_FORMAT_R8G8B8X8_UNORM, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, RGB1_SWIZZLE }, { VIRGL_FORMAT_R8G8B8A8_UNORM, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, NO_SWIZZLE }, @@ -280,11 +280,25 @@ static struct vrend_format_table bptc_formats[] = { { VIRGL_FORMAT_BPTC_RGB_UFLOAT, GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT, GL_RGB, GL_UNSIGNED_BYTE, NO_SWIZZLE }, }; +static struct vrend_format_table gl_bgra_formats[] = { + { VIRGL_FORMAT_B8G8R8X8_UNORM, GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE, RGB1_SWIZZLE }, + { VIRGL_FORMAT_B8G8R8A8_UNORM, GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE, NO_SWIZZLE }, +}; + + static struct vrend_format_table gles_bgra_formats[] = { { VIRGL_FORMAT_B8G8R8X8_UNORM, GL_BGRA_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE, RGB1_SWIZZLE }, { VIRGL_FORMAT_B8G8R8A8_UNORM, GL_BGRA_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE, NO_SWIZZLE }, }; +static struct vrend_format_table gles_bgra_formats_emulation[] = { + { VIRGL_FORMAT_B8G8R8X8_UNORM_EMULATED, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, BGR1_SWIZZLE }, + { VIRGL_FORMAT_B8G8R8A8_UNORM_EMULATED, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, BGRA_SWIZZLE }, + { VIRGL_FORMAT_B8G8R8X8_SRGB, GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, BGR1_SWIZZLE }, + { VIRGL_FORMAT_B8G8R8A8_SRGB, GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, BGRA_SWIZZLE }, +}; + + static struct vrend_format_table gles_z32_format[] = { { VIRGL_FORMAT_Z32_UNORM, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NO_SWIZZLE }, }; @@ -378,33 +392,35 @@ static void vrend_add_formats(struct vrend_format_table *table, int num_entries) /* we can't probe compressed formats, as we'd need valid payloads to * glCompressedTexImage2D. Let's just check for extensions instead. */ - const struct util_format_description *desc = util_format_description(table[i].format); - switch (desc->layout) { - case UTIL_FORMAT_LAYOUT_S3TC: - if (epoxy_has_gl_extension("GL_S3_s3tc") || - epoxy_has_gl_extension("GL_EXT_texture_compression_s3tc")) - vrend_insert_format(&table[i], VIRGL_BIND_SAMPLER_VIEW, flags); - continue; - - case UTIL_FORMAT_LAYOUT_RGTC: - if (epoxy_has_gl_extension("GL_ARB_texture_compression_rgtc") || - epoxy_has_gl_extension("GL_EXT_texture_compression_rgtc") ) - vrend_insert_format(&table[i], VIRGL_BIND_SAMPLER_VIEW, flags); - continue; - - case UTIL_FORMAT_LAYOUT_ETC: - if (epoxy_has_gl_extension("GL_OES_compressed_ETC1_RGB8_texture")) - vrend_insert_format(&table[i], VIRGL_BIND_SAMPLER_VIEW, flags); - continue; - - case UTIL_FORMAT_LAYOUT_BPTC: - if (epoxy_has_gl_extension("GL_ARB_texture_compression_bptc") || - epoxy_has_gl_extension("GL_EXT_texture_compression_bptc")) - vrend_insert_format(&table[i], VIRGL_BIND_SAMPLER_VIEW, flags); - continue; - - default: - ;/* do logic below */ + if (table[i].format < VIRGL_FORMAT_MAX) { + const struct util_format_description *desc = util_format_description(table[i].format); + switch (desc->layout) { + case UTIL_FORMAT_LAYOUT_S3TC: + if (epoxy_has_gl_extension("GL_S3_s3tc") || + epoxy_has_gl_extension("GL_EXT_texture_compression_s3tc")) + vrend_insert_format(&table[i], VIRGL_BIND_SAMPLER_VIEW, flags); + continue; + + case UTIL_FORMAT_LAYOUT_RGTC: + if (epoxy_has_gl_extension("GL_ARB_texture_compression_rgtc") || + epoxy_has_gl_extension("GL_EXT_texture_compression_rgtc") ) + vrend_insert_format(&table[i], VIRGL_BIND_SAMPLER_VIEW, flags); + continue; + + case UTIL_FORMAT_LAYOUT_ETC: + if (epoxy_has_gl_extension("GL_OES_compressed_ETC1_RGB8_texture")) + vrend_insert_format(&table[i], VIRGL_BIND_SAMPLER_VIEW, flags); + continue; + + case UTIL_FORMAT_LAYOUT_BPTC: + if (epoxy_has_gl_extension("GL_ARB_texture_compression_bptc") || + epoxy_has_gl_extension("GL_EXT_texture_compression_bptc")) + vrend_insert_format(&table[i], VIRGL_BIND_SAMPLER_VIEW, flags); + continue; + + default: + ;/* do logic below */ + } } /* The error state should be clear here */ @@ -441,7 +457,7 @@ static void vrend_add_formats(struct vrend_format_table *table, int num_entries) continue; } - if (util_format_is_depth_or_stencil(table[i].format)) { + if (table[i].format < VIRGL_FORMAT_MAX && util_format_is_depth_or_stencil(table[i].format)) { GLenum attachment; if (table[i].format == VIRGL_FORMAT_Z24X8_UNORM || table[i].format == VIRGL_FORMAT_Z32_UNORM || table[i].format == VIRGL_FORMAT_Z16_UNORM || table[i].format == VIRGL_FORMAT_Z32_FLOAT) @@ -472,6 +488,14 @@ static void vrend_add_formats(struct vrend_format_table *table, int num_entries) flags |= VIRGL_TEXTURE_CAN_READBACK; } + if (i == VIRGL_FORMAT_B8G8R8A8_UNORM_EMULATED) { + table[VIRGL_FORMAT_B8G8R8A8_UNORM].flags |= VIRGL_TEXTURE_CAN_READBACK; + binding |= VIRGL_BIND_PREFER_EMULATED_BGRA; + } else if (i == VIRGL_FORMAT_B8G8R8X8_UNORM_EMULATED) { + table[VIRGL_FORMAT_B8G8R8X8_UNORM].flags |= VIRGL_TEXTURE_CAN_READBACK; + binding |= VIRGL_BIND_PREFER_EMULATED_BGRA; + } + glDeleteTextures(1, &tex_id); glDeleteFramebuffers(1, &fb_id); @@ -533,6 +557,7 @@ void vrend_build_format_list_gl(void) * transfer operations. So we only register support for it in GL. */ add_formats(gl_base_rgba_formats); + add_formats(gl_bgra_formats); add_formats(gl_srgb_formats); } @@ -553,6 +578,11 @@ void vrend_build_format_list_gles(void) add_formats(gles_bit10_formats); } +void vrend_build_emulated_format_list_gles(void) +{ + add_formats(gles_bgra_formats_emulation); +} + /* glTexStorage may not support all that is supported by glTexImage, * so add a flag to indicate when it can be used. */ @@ -560,9 +590,10 @@ void vrend_check_texture_storage(struct vrend_format_table *table) { int i; GLuint tex_id; - for (i = 0; i < VIRGL_FORMAT_MAX; i++) { + for (i = 0; i < VIRGL_FORMAT_MAX_EXTENDED; i++) { - if (table[i].internalformat != 0) { + if (table[i].internalformat != 0 && + !(table[i].flags & VIRGL_TEXTURE_CAN_TEXTURE_STORAGE)) { glGenTextures(1, &tex_id); glBindTexture(GL_TEXTURE_2D, tex_id); glTexStorage2D(GL_TEXTURE_2D, 1, table[i].internalformat, 32, 32); diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c index 5d8f68f..8f2ff8d 100644 --- a/src/vrend_renderer.c +++ b/src/vrend_renderer.c @@ -646,7 +646,7 @@ static GLenum tgsitargettogltarget(const enum pipe_texture_target target, int nr void vrend_update_stencil_state(struct vrend_context *ctx); -static struct vrend_format_table tex_conv_table[VIRGL_FORMAT_MAX]; +static struct vrend_format_table tex_conv_table[VIRGL_FORMAT_MAX_EXTENDED]; static inline bool vrend_format_can_sample(enum virgl_formats format) {