vrend: remove old BGRA emulation on GLES hosts

BGRA emulation was added to address rendering artifacts when GL guest
apps are run on a GLES host with virglrenderer's use_gles == true.

Due to tenuous compatibility of EXT_texture_format_BGRA8888 with
gamma correction (sRGB formats/views) and multisampled rendering on
GLES hosts, it is best to represent BGR* resourcs with RGB* internal
format and add necessary byte re-ordering on to/from transfers instead.

Note, however, that removing the existing BGR* emulation will cause
problems for externally stored resources such as EGL images, and GBM
allocated buffers, which may actually be stored with BGR* byte-order.
This is addressed in the commits immediately following this one.

Signed-off-by: Ryan Neph <ryanneph@google.com>
Reviewed-by: Gert Wollny <gert.wollny@collabora.com>
macos/master
Ryan Neph 3 years ago
parent dd6e7c85d2
commit 8bb939b174
  1. 2
      src/virgl_hw.h
  2. 4
      src/vrend_blitter.c
  3. 37
      src/vrend_formats.c
  4. 198
      src/vrend_renderer.c
  5. 2
      src/vrend_renderer.h
  6. 2
      src/vrend_winsys_gbm.c

@ -466,7 +466,7 @@ enum virgl_formats {
#define VIRGL_BIND_STAGING (1 << 19) #define VIRGL_BIND_STAGING (1 << 19)
#define VIRGL_BIND_SHARED (1 << 20) #define VIRGL_BIND_SHARED (1 << 20)
#define VIRGL_BIND_PREFER_EMULATED_BGRA (1 << 21) /* bit (1<<21) reserved for non-functional VIRGL_BIND_PREFER_EMULATED_BGRA */
#define VIRGL_BIND_LINEAR (1 << 22) #define VIRGL_BIND_LINEAR (1 << 22)

@ -642,7 +642,7 @@ static void vrend_set_tex_param(struct vrend_resource *src_res,
bool has_texture_srgb_decode) bool has_texture_srgb_decode)
{ {
const struct vrend_format_table *src_entry = const struct vrend_format_table *src_entry =
vrend_get_format_table_entry_with_emulation(src_res->base.bind, info->src.format); vrend_get_format_table_entry(info->src.format);
if (src_entry->flags & VIRGL_TEXTURE_NEED_SWIZZLE) { if (src_entry->flags & VIRGL_TEXTURE_NEED_SWIZZLE) {
glTexParameteri(src_res->target, GL_TEXTURE_SWIZZLE_R, glTexParameteri(src_res->target, GL_TEXTURE_SWIZZLE_R,
@ -715,7 +715,7 @@ void vrend_renderer_blit_gl(MAYBE_UNUSED struct vrend_context *ctx,
util_format_description(dst_res->base.format); util_format_description(dst_res->base.format);
const struct vrend_format_table *orig_src_entry = vrend_get_format_table_entry(info->src.format); const struct vrend_format_table *orig_src_entry = vrend_get_format_table_entry(info->src.format);
const struct vrend_format_table *dst_entry = const struct vrend_format_table *dst_entry =
vrend_get_format_table_entry_with_emulation(dst_res->base.bind, info->dst.format); vrend_get_format_table_entry(info->dst.format);
has_depth = util_format_has_depth(src_desc) && has_depth = util_format_has_depth(src_desc) &&
util_format_has_depth(dst_desc); util_format_has_depth(dst_desc);

@ -328,18 +328,13 @@ static struct vrend_format_table gl_bgra_formats[] = {
{ VIRGL_FORMAT_B8G8R8A8_UNORM, GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE, NO_SWIZZLE }, { VIRGL_FORMAT_B8G8R8A8_UNORM, GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE, NO_SWIZZLE },
}; };
static struct vrend_format_table gles_bgra_formats[] = { 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_B8G8R8X8_UNORM, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, RGB1_SWIZZLE },
{ VIRGL_FORMAT_B8G8R8A8_UNORM, GL_BGRA_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE, NO_SWIZZLE }, { VIRGL_FORMAT_B8G8R8A8_UNORM, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, NO_SWIZZLE },
{ VIRGL_FORMAT_B8G8R8X8_SRGB, GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, RGB1_SWIZZLE },
{ VIRGL_FORMAT_B8G8R8A8_SRGB, GL_SRGB8_ALPHA8, GL_RGBA, 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[] = { static struct vrend_format_table gles_z32_format[] = {
@ -537,14 +532,6 @@ static void vrend_add_formats(struct vrend_format_table *table, int num_entries)
flags |= VIRGL_TEXTURE_CAN_READBACK; 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); glDeleteTextures(1, &tex_id);
glDeleteFramebuffers(1, &fb_id); glDeleteFramebuffers(1, &fb_id);
@ -614,9 +601,11 @@ void vrend_build_format_list_gl(void)
void vrend_build_format_list_gles(void) void vrend_build_format_list_gles(void)
{ {
/* The BGR[A|X] formats is required but OpenGL ES does not /* The BGR[A|X] formats is required but OpenGL ES does not
* support rendering to it. Try to use GL_BGRA_EXT from the * support it as nicely as OpenGL. We could try to use BGRA_EXT from
* GL_EXT_texture_format_BGRA8888 extension. But the * EXT_texture_format_BGRA8888, but it becomes error prone when mixed
* GL_BGRA_EXT format is not supported by OpenGL Desktop. * with BGR*_SRGB formats and framebuffer multisampling. Instead, on
* GLES hosts, we always emulate BGR* as GL_RGB* with a swizzle on
* transfers to/from the host.
*/ */
add_formats(gles_bgra_formats); add_formats(gles_bgra_formats);
@ -629,11 +618,6 @@ void vrend_build_format_list_gles(void)
add_formats(astc_formats); add_formats(astc_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, /* glTexStorage may not support all that is supported by glTexImage,
* so add a flag to indicate when it can be used. * so add a flag to indicate when it can be used.
*/ */
@ -882,8 +866,7 @@ boolean format_is_copy_compatible(enum virgl_formats src, enum virgl_formats dst
* So the formats do not match when Mesa checks them internally. * So the formats do not match when Mesa checks them internally.
*/ */
if (flags & VREND_COPY_COMPAT_FLAG_ONE_IS_EGL_IMAGE && if (flags & VREND_COPY_COMPAT_FLAG_ONE_IS_EGL_IMAGE &&
(src == VIRGL_FORMAT_B8G8R8X8_UNORM || src == VIRGL_FORMAT_B8G8R8X8_UNORM)
src == VIRGL_FORMAT_B8G8R8X8_UNORM_EMULATED))
return false; return false;
return true; return true;
} }

@ -352,7 +352,6 @@ struct global_renderer_state {
/* Needed on GLES to inject a TCS */ /* Needed on GLES to inject a TCS */
float tess_factors[6]; float tess_factors[6];
bool bgra_srgb_emulation_loaded;
/* inferred GL caching type */ /* inferred GL caching type */
uint32_t inferred_gl_caching_type; uint32_t inferred_gl_caching_type;
@ -845,6 +844,13 @@ bool vrend_format_is_emulated_alpha(enum virgl_formats format)
format == VIRGL_FORMAT_A16_UNORM); format == VIRGL_FORMAT_A16_UNORM);
} }
bool vrend_format_is_bgra(enum virgl_formats format) {
return (format == VIRGL_FORMAT_B8G8R8X8_UNORM ||
format == VIRGL_FORMAT_B8G8R8A8_UNORM ||
format == VIRGL_FORMAT_B8G8R8X8_SRGB ||
format == VIRGL_FORMAT_B8G8R8A8_SRGB);
}
static bool vrend_blit_needs_swizzle(enum virgl_formats src, static bool vrend_blit_needs_swizzle(enum virgl_formats src,
enum virgl_formats dst) enum virgl_formats dst)
{ {
@ -1192,45 +1198,12 @@ vrend_insert_format_swizzle(int override_format, struct vrend_format_table *entr
tex_conv_table[override_format].swizzle[i] = swizzle[i]; tex_conv_table[override_format].swizzle[i] = swizzle[i];
} }
static inline enum virgl_formats
vrend_format_replace_emulated(uint32_t bind, enum virgl_formats format)
{
enum virgl_formats retval = format;
if (vrend_state.use_gles && (bind & VIRGL_BIND_PREFER_EMULATED_BGRA)) {
VREND_DEBUG(dbg_tweak, vrend_state.current_ctx, "Check tweak for format %s", util_format_name(format));
if (!vrend_state.bgra_srgb_emulation_loaded) {
GLint err = glGetError();
if (err != GL_NO_ERROR)
vrend_printf("Warning: stale error state when calling %s\n", __func__);
VREND_DEBUG_NOCTX(dbg_tweak, vrend_state.current_ctx, " ... add swizzled formats\n");
vrend_build_emulated_format_list_gles();
vrend_check_texture_storage(tex_conv_table);
vrend_state.bgra_srgb_emulation_loaded = true;
}
if (format == VIRGL_FORMAT_B8G8R8A8_UNORM)
retval = VIRGL_FORMAT_B8G8R8A8_UNORM_EMULATED;
else if (format == VIRGL_FORMAT_B8G8R8X8_UNORM)
retval = VIRGL_FORMAT_B8G8R8X8_UNORM_EMULATED;
VREND_DEBUG_NOCTX(dbg_tweak, vrend_state.current_ctx,
"%s\n", (retval != format ? "... replace" : ""));
}
return retval;
}
const struct vrend_format_table * const struct vrend_format_table *
vrend_get_format_table_entry(enum virgl_formats format) vrend_get_format_table_entry(enum virgl_formats format)
{ {
return &tex_conv_table[format]; return &tex_conv_table[format];
} }
const struct vrend_format_table *
vrend_get_format_table_entry_with_emulation(uint32_t bind, enum virgl_formats format)
{
return vrend_get_format_table_entry(vrend_format_replace_emulated(bind, format));
}
static bool vrend_is_timer_query(GLenum gltype) static bool vrend_is_timer_query(GLenum gltype)
{ {
return gltype == GL_TIMESTAMP || return gltype == GL_TIMESTAMP ||
@ -1877,7 +1850,6 @@ int vrend_create_surface(struct vrend_context *ctx,
surf->res_handle = res_handle; surf->res_handle = res_handle;
surf->format = format; surf->format = format;
format = vrend_format_replace_emulated(res->base.bind, format);
surf->val0 = val0; surf->val0 = val0;
surf->val1 = val1; surf->val1 = val1;
@ -1897,10 +1869,9 @@ int vrend_create_surface(struct vrend_context *ctx,
int first_layer = surf->val1 & 0xffff; int first_layer = surf->val1 & 0xffff;
int last_layer = (surf->val1 >> 16) & 0xffff; int last_layer = (surf->val1 >> 16) & 0xffff;
VREND_DEBUG(dbg_tex, ctx, "Create texture view from %s for %s (emulated:%d)\n", VREND_DEBUG(dbg_tex, ctx, "Create texture view from %s for %s\n",
util_format_name(res->base.format), util_format_name(res->base.format),
util_format_name(surf->format), util_format_name(surf->format));
surf->format != format);
if ((first_layer != last_layer && if ((first_layer != last_layer &&
(first_layer != 0 || (last_layer != (int)util_max_layer(&res->base, surf->val0)))) || (first_layer != 0 || (last_layer != (int)util_max_layer(&res->base, surf->val0)))) ||
@ -2534,21 +2505,6 @@ static void vrend_hw_emit_framebuffer_state(struct vrend_sub_context *sub_ctx)
sub_ctx->framebuffer_srgb_enabled = use_srgb; sub_ctx->framebuffer_srgb_enabled = use_srgb;
} }
if (vrend_state.use_gles &&
vrend_get_tweak_is_active(&sub_ctx->tweaks, virgl_tweak_gles_brga_apply_dest_swizzle)) {
sub_ctx->swizzle_output_rgb_to_bgr = 0;
for (int i = 0; i < sub_ctx->nr_cbufs; i++) {
if (sub_ctx->surf[i]) {
struct vrend_surface *surf = sub_ctx->surf[i];
if (surf->texture->base.bind & VIRGL_BIND_PREFER_EMULATED_BGRA) {
VREND_DEBUG(dbg_tweak, sub_ctx->parent, "Swizzled BGRA output for 0x%x (%s)\n", i, util_format_name(surf->format));
sub_ctx->swizzle_output_rgb_to_bgr |= 1 << i;
}
}
}
}
glDrawBuffers(sub_ctx->nr_cbufs, buffers); glDrawBuffers(sub_ctx->nr_cbufs, buffers);
} }
@ -3942,7 +3898,7 @@ void vrend_clear_texture(struct vrend_context* ctx,
return; return;
} }
enum virgl_formats fmt = vrend_format_replace_emulated(res->base.bind, res->base.format); enum virgl_formats fmt = res->base.format;
format = tex_conv_table[fmt].glformat; format = tex_conv_table[fmt].glformat;
type = tex_conv_table[fmt].gltype; type = tex_conv_table[fmt].gltype;
@ -5762,30 +5718,6 @@ void vrend_bind_sampler_states(struct vrend_context *ctx,
ctx->sub->sampler_views_dirty[shader_type] |= dirty; ctx->sub->sampler_views_dirty[shader_type] |= dirty;
} }
static bool get_swizzled_border_color(enum virgl_formats fmt,
union pipe_color_union *in_border_color,
union pipe_color_union *out_border_color)
{
const struct vrend_format_table *fmt_entry = vrend_get_format_table_entry(fmt);
if (vrend_state.use_gles &&
(fmt_entry->flags & VIRGL_TEXTURE_CAN_TEXTURE_STORAGE) &&
(fmt_entry->bindings & VIRGL_BIND_PREFER_EMULATED_BGRA)) {
for (int i = 0; i < 4; ++i) {
int swz = fmt_entry->swizzle[i];
switch (swz) {
case PIPE_SWIZZLE_ZERO: out_border_color->ui[i] = 0;
break;
case PIPE_SWIZZLE_ONE: out_border_color->ui[i] = 1;
break;
default:
out_border_color->ui[i] = in_border_color->ui[swz];
}
}
return true;
}
return false;
}
static void vrend_apply_sampler_state(struct vrend_sub_context *sub_ctx, static void vrend_apply_sampler_state(struct vrend_sub_context *sub_ctx,
struct vrend_resource *res, struct vrend_resource *res,
uint32_t shader_type, uint32_t shader_type,
@ -5827,10 +5759,6 @@ static void vrend_apply_sampler_state(struct vrend_sub_context *sub_ctx,
border_color.ui[0] = border_color.ui[3]; border_color.ui[0] = border_color.ui[3];
border_color.ui[3] = 0; border_color.ui[3] = 0;
apply_sampler_border_color(sampler, border_color.ui); apply_sampler_border_color(sampler, border_color.ui);
} else {
union pipe_color_union border_color;
if (get_swizzled_border_color(tview->format, &state->border_color, &border_color))
apply_sampler_border_color(sampler, border_color.ui);
} }
glBindSampler(sampler_id, sampler); glBindSampler(sampler_id, sampler);
@ -5894,11 +5822,7 @@ static void vrend_apply_sampler_state(struct vrend_sub_context *sub_ctx,
border_color.ui[3] = 0; border_color.ui[3] = 0;
glTexParameterIuiv(target, GL_TEXTURE_BORDER_COLOR, border_color.ui); glTexParameterIuiv(target, GL_TEXTURE_BORDER_COLOR, border_color.ui);
} else { } else {
union pipe_color_union border_color; glTexParameterIuiv(target, GL_TEXTURE_BORDER_COLOR, state->border_color.ui);
if (get_swizzled_border_color(tview->format, &state->border_color, &border_color))
glTexParameterIuiv(target, GL_TEXTURE_BORDER_COLOR, border_color.ui);
else
glTexParameterIuiv(target, GL_TEXTURE_BORDER_COLOR, state->border_color.ui);
} }
} }
@ -6290,7 +6214,6 @@ int vrend_renderer_init(const struct vrend_if_cbs *cbs, uint32_t flags)
glDisable(GL_DEBUG_OUTPUT); glDisable(GL_DEBUG_OUTPUT);
} }
vrend_state.bgra_srgb_emulation_loaded = false;
vrend_build_format_list_common(); vrend_build_format_list_common();
if (vrend_state.use_gles) { if (vrend_state.use_gles) {
@ -6958,35 +6881,6 @@ static void vrend_resource_gbm_init(struct vrend_resource *gr, uint32_t format)
#endif #endif
} }
static enum virgl_formats vrend_resource_fixup_emulated_bgra(struct vrend_resource *gr,
bool imported)
{
const struct pipe_resource *pr = &gr->base;
const enum virgl_formats format = pr->format;
const bool format_can_texture_storage = has_feature(feat_texture_storage) &&
(tex_conv_table[format].flags & VIRGL_TEXTURE_CAN_TEXTURE_STORAGE);
/* On GLES there is no support for glTexImage*DMultisample and
* BGRA surfaces are also unlikely to support glTexStorage2DMultisample
* so we try to emulate here
*/
if (vrend_state.use_gles && pr->nr_samples > 0 && !format_can_texture_storage) {
VREND_DEBUG(dbg_tex, NULL, "Apply VIRGL_BIND_PREFER_EMULATED_BGRA because GLES+MS+noTS\n");
gr->base.bind |= VIRGL_BIND_PREFER_EMULATED_BGRA;
}
if (imported && !has_feature(feat_egl_image_storage))
gr->base.bind &= ~VIRGL_BIND_PREFER_EMULATED_BGRA;
#ifdef ENABLE_MINIGBM_ALLOCATION
if (virgl_gbm_external_allocation_preferred(gr->base.bind) &&
!has_feature(feat_egl_image_storage))
gr->base.bind &= ~VIRGL_BIND_PREFER_EMULATED_BGRA;
#endif
return vrend_format_replace_emulated(gr->base.bind, format);
}
static int vrend_resource_alloc_texture(struct vrend_resource *gr, static int vrend_resource_alloc_texture(struct vrend_resource *gr,
enum virgl_formats format, enum virgl_formats format,
void *image_oes) void *image_oes)
@ -7211,8 +7105,7 @@ vrend_renderer_resource_create(const struct vrend_renderer_resource_create_args
if (args->target == PIPE_BUFFER) { if (args->target == PIPE_BUFFER) {
ret = vrend_resource_alloc_buffer(gr, args->flags); ret = vrend_resource_alloc_buffer(gr, args->flags);
} else { } else {
const enum virgl_formats format = const enum virgl_formats format = gr->base.format;
vrend_resource_fixup_emulated_bgra(gr, image_oes);
ret = vrend_resource_alloc_texture(gr, format, image_oes); ret = vrend_resource_alloc_texture(gr, format, image_oes);
} }
@ -7537,6 +7430,17 @@ static void get_current_texture(GLenum target, GLint* tex) {
} }
} }
static void vrend_swizzle_data_bgra(uint64_t size, void *data) {
const size_t bpp = 4;
const size_t num_pixels = size / bpp;
for (size_t i = 0; i < num_pixels; ++i) {
unsigned char *pixel = ((unsigned char*)data) + i * bpp;
unsigned char first = *pixel;
*pixel = *(pixel + 2);
*(pixel + 2) = first;
}
}
static int vrend_renderer_transfer_write_iov(struct vrend_context *ctx, static int vrend_renderer_transfer_write_iov(struct vrend_context *ctx,
struct vrend_resource *res, struct vrend_resource *res,
const struct iovec *iov, int num_iovs, const struct iovec *iov, int num_iovs,
@ -7706,6 +7610,12 @@ static int vrend_renderer_transfer_write_iov(struct vrend_context *ctx,
x = info->box->x; x = info->box->x;
y = invert ? (int)res->base.height0 - info->box->y - info->box->height : info->box->y; y = invert ? (int)res->base.height0 - info->box->y - info->box->height : info->box->y;
/* GLES doesn't allow format conversions, which we need for BGRA resources with RGBA
* internal format. So we fallback to performing a CPU swizzle before uploading. */
if (vrend_state.use_gles && vrend_format_is_bgra(res->base.format)) {
VREND_DEBUG(dbg_bgra, ctx, "manually swizzling bgra->rgba on upload since gles+bgra\n");
vrend_swizzle_data_bgra(send_size, data);
}
/* mipmaps are usually passed in one iov, and we need to keep the offset /* mipmaps are usually passed in one iov, and we need to keep the offset
* into the data in case we want to read back the data of a surface * into the data in case we want to read back the data of a surface
@ -7960,17 +7870,7 @@ static int vrend_transfer_send_readpixels(struct vrend_context *ctx,
else else
glUseProgram(0); glUseProgram(0);
/* If the emubgra tweak is active then reading back the BGRA format emulated
* by swizzling a RGBA format will take a performance hit because mesa will
* manually swizzling the RGBA data. This can be avoided by setting the
* tweak bgraswz that does this swizzling already on the GPU when blitting
* or rendering to an emulated BGRA surface and reading back the data as
* RGBA. The check whether we are on gles and emugbra is active is done
* in vrend_format_replace_emulated, so no need to repeat the test here */
enum virgl_formats fmt = res->base.format; enum virgl_formats fmt = res->base.format;
if (vrend_get_tweak_is_active(&ctx->sub->tweaks,
virgl_tweak_gles_brga_apply_dest_swizzle))
fmt = vrend_format_replace_emulated(res->base.bind, res->base.format);
format = tex_conv_table[fmt].glformat; format = tex_conv_table[fmt].glformat;
type = tex_conv_table[fmt].gltype; type = tex_conv_table[fmt].gltype;
@ -8043,6 +7943,16 @@ static int vrend_transfer_send_readpixels(struct vrend_context *ctx,
do_readpixels(res, 0, info->level, info->box->z, info->box->x, y1, do_readpixels(res, 0, info->level, info->box->z, info->box->x, y1,
info->box->width, info->box->height, format, type, send_size, data); info->box->width, info->box->height, format, type, send_size, data);
/* on GLES, texture-backed BGR* resources are always stored with RGBA internal format, but
* the guest will expect to readback the data in BGRA format.
* Since the GLES API doesn't allow format conversions like GL, we CPU-swizzle the data
* on upload and need to do the same on readback.
*/
if (vrend_state.use_gles && vrend_format_is_bgra(res->base.format)) {
VREND_DEBUG(dbg_bgra, ctx, "manually swizzling rgba->bgra on readback since gles+bgra\n");
vrend_swizzle_data_bgra(send_size, data);
}
if (res->base.format == VIRGL_FORMAT_Z24X8_UNORM) { if (res->base.format == VIRGL_FORMAT_Z24X8_UNORM) {
if (!vrend_state.use_core_profile) if (!vrend_state.use_core_profile)
glPixelTransferf(GL_DEPTH_SCALE, 1.0); glPixelTransferf(GL_DEPTH_SCALE, 1.0);
@ -8619,6 +8529,13 @@ static void vrend_resource_copy_fallback(struct vrend_resource *src_res,
float depth_scale = 256.0; float depth_scale = 256.0;
vrend_scale_depth(tptr, total_size, depth_scale); vrend_scale_depth(tptr, total_size, depth_scale);
} }
/* if this is a BGR* resource on GLES, the data needs to be manually swizzled to RGB* before
* storing in a texture. Iovec data is assumed to have the original byte-order, namely BGR*,
* and needs to be reordered when storing in the host's texture memory as RGB*.
*/
if (vrend_format_is_bgra(dst_res->base.format))
vrend_swizzle_data_bgra(total_size, tptr);
} else { } else {
uint32_t read_chunk_size; uint32_t read_chunk_size;
switch (elsize) { switch (elsize) {
@ -8874,10 +8791,7 @@ static GLuint vrend_make_view(struct vrend_resource *res, enum virgl_formats for
{ {
GLuint view_id; GLuint view_id;
glGenTextures(1, &view_id); glGenTextures(1, &view_id);
#ifndef NDEBUG enum virgl_formats dst_fmt = format;
enum virgl_formats src_fmt = vrend_format_replace_emulated(res->base.bind, res->base.format);
#endif
enum virgl_formats dst_fmt = vrend_format_replace_emulated(res->base.bind, format);
GLenum fmt = tex_conv_table[dst_fmt].internalformat; GLenum fmt = tex_conv_table[dst_fmt].internalformat;
@ -8885,11 +8799,9 @@ static GLuint vrend_make_view(struct vrend_resource *res, enum virgl_formats for
if (!has_bit(res->storage_bits, VREND_STORAGE_GL_IMMUTABLE)) if (!has_bit(res->storage_bits, VREND_STORAGE_GL_IMMUTABLE))
return res->id; return res->id;
VREND_DEBUG(dbg_blit, NULL, "Create texture view from %s%s as %s%s\n", VREND_DEBUG(dbg_blit, NULL, "Create texture view from %s as %s\n",
util_format_name(res->base.format), util_format_name(res->base.format),
res->base.format != src_fmt ? "(emulated)" : "", util_format_name(format));
util_format_name(format),
format != dst_fmt ? "(emulated)" : "");
if (vrend_state.use_gles) { if (vrend_state.use_gles) {
assert(res->target != GL_TEXTURE_RECTANGLE_NV); assert(res->target != GL_TEXTURE_RECTANGLE_NV);
@ -8996,17 +8908,9 @@ static void vrend_renderer_blit_int(struct vrend_context *ctx,
if (info->src.box.depth != info->dst.box.depth) if (info->src.box.depth != info->dst.box.depth)
use_gl = true; use_gl = true;
if (vrend_blit_needs_swizzle(vrend_format_replace_emulated(dst_res->base.bind, info->dst.format), if (vrend_blit_needs_swizzle(info->dst.format, info->src.format))
vrend_format_replace_emulated(src_res->base.bind, info->src.format))) {
use_gl = true; use_gl = true;
if (vrend_state.use_gles &&
(dst_res->base.bind & VIRGL_BIND_PREFER_EMULATED_BGRA) &&
!vrend_get_tweak_is_active(&ctx->sub->tweaks, virgl_tweak_gles_brga_apply_dest_swizzle)) {
skip_dest_swizzle = true;
}
}
if (has_feature(feat_texture_view)) if (has_feature(feat_texture_view))
blitter_views[0] = vrend_make_view(src_res, info->src.format); blitter_views[0] = vrend_make_view(src_res, info->src.format);
@ -10437,7 +10341,6 @@ static void vrend_renderer_fill_caps_v2(int gl_ver, int gles_ver, union virgl_c
/* We want to expose ARB_gpu_shader_fp64 when running on top of ES */ /* We want to expose ARB_gpu_shader_fp64 when running on top of ES */
if (vrend_state.use_gles) { if (vrend_state.use_gles) {
caps->v2.capability_bits |= VIRGL_CAP_FAKE_FP64; caps->v2.capability_bits |= VIRGL_CAP_FAKE_FP64;
caps->v2.capability_bits |= VIRGL_CAP_BGRA_SRGB_IS_EMULATED;
} }
if (has_feature(feat_indirect_draw)) if (has_feature(feat_indirect_draw))
@ -11054,7 +10957,6 @@ vrend_renderer_pipe_resource_set_type(struct vrend_context *ctx,
if (!gr) if (!gr)
return ENOMEM; return ENOMEM;
virgl_format = vrend_resource_fixup_emulated_bgra(gr, true);
drm_format = 0; drm_format = 0;
if (virgl_gbm_convert_format(&virgl_format, &drm_format)) { if (virgl_gbm_convert_format(&virgl_format, &drm_format)) {
vrend_printf("%s: unsupported format %d\n", __func__, virgl_format); vrend_printf("%s: unsupported format %d\n", __func__, virgl_format);

@ -136,7 +136,6 @@ bool vrend_check_framebuffer_mixed_color_attachements(void);
void vrend_insert_format_swizzle(int override_format, struct vrend_format_table *entry, void vrend_insert_format_swizzle(int override_format, struct vrend_format_table *entry,
uint32_t bindings, uint8_t swizzle[4], uint32_t flags); uint32_t bindings, uint8_t swizzle[4], uint32_t flags);
const struct vrend_format_table *vrend_get_format_table_entry(enum virgl_formats format); const struct vrend_format_table *vrend_get_format_table_entry(enum virgl_formats format);
const struct vrend_format_table *vrend_get_format_table_entry_with_emulation(uint32_t bind, enum virgl_formats format);
int vrend_create_shader(struct vrend_context *ctx, int vrend_create_shader(struct vrend_context *ctx,
uint32_t handle, uint32_t handle,
@ -468,6 +467,7 @@ void vrend_fb_bind_texture(struct vrend_resource *res,
int idx, int idx,
uint32_t level, uint32_t layer); uint32_t level, uint32_t layer);
bool vrend_format_is_emulated_alpha(enum virgl_formats format); bool vrend_format_is_emulated_alpha(enum virgl_formats format);
bool vrend_format_is_bgra(enum virgl_formats format);
#define VREND_COPY_COMPAT_FLAG_ALLOW_COMPRESSED (1u << 0) #define VREND_COPY_COMPAT_FLAG_ALLOW_COMPRESSED (1u << 0)
#define VREND_COPY_COMPAT_FLAG_ONE_IS_EGL_IMAGE (1u << 1) #define VREND_COPY_COMPAT_FLAG_ONE_IS_EGL_IMAGE (1u << 1)

@ -107,8 +107,6 @@ static const struct format_conversion conversions[] = {
{ GBM_FORMAT_XBGR8888, VIRGL_FORMAT_R8G8B8X8_UNORM}, { GBM_FORMAT_XBGR8888, VIRGL_FORMAT_R8G8B8X8_UNORM},
{ GBM_FORMAT_R8, VIRGL_FORMAT_R8_UNORM}, { GBM_FORMAT_R8, VIRGL_FORMAT_R8_UNORM},
{ GBM_FORMAT_YVU420, VIRGL_FORMAT_YV12}, { GBM_FORMAT_YVU420, VIRGL_FORMAT_YV12},
{ GBM_FORMAT_ABGR8888, VIRGL_FORMAT_B8G8R8A8_UNORM_EMULATED},
{ GBM_FORMAT_XBGR8888, VIRGL_FORMAT_B8G8R8X8_UNORM_EMULATED},
}; };
static int rendernode_open(void) static int rendernode_open(void)

Loading…
Cancel
Save