vrend: Add handling for swizzled BGRA formats

v2: - Clear stale error state before testing emulation formats
    - correct typos (Gurchetan)

Signed-off-by: Gert Wollny <gert.wollny@collabora.com>
Reviewed-by: Gurchetan Singh <gurchetansingh@chromium.org>
macos/master
Gert Wollny 6 years ago
parent 4749e8791b
commit 0977e48e24
  1. 4
      src/virgl_hw.h
  2. 81
      src/vrend_renderer.c
  3. 3
      src/vrend_renderer.h

@ -261,6 +261,7 @@ enum virgl_formats {
#define VIRGL_CAP_COPY_TRANSFER (1 << 26) #define VIRGL_CAP_COPY_TRANSFER (1 << 26)
#define VIRGL_CAP_CLIP_HALFZ (1 << 27) #define VIRGL_CAP_CLIP_HALFZ (1 << 27)
#define VIRGL_CAP_APP_TWEAK_SUPPORT (1 << 28) #define VIRGL_CAP_APP_TWEAK_SUPPORT (1 << 28)
#define VIRGL_CAP_BGRA_SRGB_IS_EMULATED (1 << 29)
/* virgl bind flags - these are compatible with mesa 10.5 gallium. /* virgl bind flags - these are compatible with mesa 10.5 gallium.
* but are fixed, no other should be passed to virgl either. * but are fixed, no other should be passed to virgl either.
@ -285,6 +286,8 @@ 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)
struct virgl_caps_bool_set1 { struct virgl_caps_bool_set1 {
unsigned indep_blend_enable:1; unsigned indep_blend_enable:1;
unsigned indep_blend_func:1; unsigned indep_blend_func:1;
@ -419,6 +422,7 @@ enum virgl_ctx_errors {
VIRGL_ERROR_CTX_ILLEGAL_VERTEX_FORMAT, VIRGL_ERROR_CTX_ILLEGAL_VERTEX_FORMAT,
VIRGL_ERROR_CTX_ILLEGAL_CMD_BUFFER, VIRGL_ERROR_CTX_ILLEGAL_CMD_BUFFER,
VIRGL_ERROR_CTX_GLES_HAVE_TES_BUT_MISS_TCS, VIRGL_ERROR_CTX_GLES_HAVE_TES_BUT_MISS_TCS,
VIRGL_ERROR_GL_ANY_SAMPLES_PASSED,
}; };
#define VIRGL_RESOURCE_Y_0_TOP (1 << 0) #define VIRGL_RESOURCE_Y_0_TOP (1 << 0)

@ -279,6 +279,8 @@ 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;
}; };
static struct global_renderer_state vrend_state; static struct global_renderer_state vrend_state;
@ -988,12 +990,44 @@ 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 pipe_format format)
{
enum virgl_formats retval = (enum virgl_formats)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 == PIPE_FORMAT_B8G8R8A8_UNORM)
retval = VIRGL_FORMAT_B8G8R8A8_UNORM_EMULATED;
else if (format == PIPE_FORMAT_B8G8R8X8_UNORM)
retval = VIRGL_FORMAT_B8G8R8X8_UNORM_EMULATED;
VREND_DEBUG_NOCTX(dbg_tweak, vrend_state.current_ctx,
"%s\n", (retval != (enum virgl_formats)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 ||
@ -1644,13 +1678,15 @@ 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;
surf->id = res->id; surf->id = res->id;
if (has_feature(feat_texture_view) && if (has_feature(feat_texture_view) &&
res->storage != VREND_RESOURCE_STORAGE_BUFFER && res->storage != VREND_RESOURCE_STORAGE_BUFFER &&
(tex_conv_table[res->base.format].flags & VIRGL_TEXTURE_CAN_TEXTURE_STORAGE)) { (tex_conv_table[format].flags & VIRGL_TEXTURE_CAN_TEXTURE_STORAGE)) {
/* We don't need texture views for buffer objects. /* We don't need texture views for buffer objects.
* Otherwise we only need a texture view if the * Otherwise we only need a texture view if the
* a) formats differ between the surface and base texture * a) formats differ between the surface and base texture
@ -1662,17 +1698,18 @@ 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\n", VREND_DEBUG(dbg_tex, ctx, "Create texture view from %s for %s (emulated:%d)\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)))) ||
surf->format != res->base.format) { surf->format != res->base.format) {
GLenum internalformat = tex_conv_table[surf->format].internalformat;
GLenum target = res->target; GLenum target = res->target;
glGenTextures(1, &surf->id); GLenum internalformat = tex_conv_table[format].internalformat;
glGenTextures(1, &surf->id);
if (vrend_state.use_gles) { if (vrend_state.use_gles) {
if (target == GL_TEXTURE_RECTANGLE_NV || if (target == GL_TEXTURE_RECTANGLE_NV ||
target == GL_TEXTURE_1D) target == GL_TEXTURE_1D)
@ -5619,6 +5656,7 @@ int vrend_renderer_init(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) {
@ -5996,6 +6034,7 @@ vrend_renderer_resource_copy_args(struct vrend_renderer_resource_create_args *ar
assert(args); assert(args);
gr->handle = args->handle; gr->handle = args->handle;
gr->base.bind = args->bind;
gr->base.width0 = args->width; gr->base.width0 = args->width;
gr->base.height0 = args->height; gr->base.height0 = args->height;
gr->base.depth0 = args->depth; gr->base.depth0 = args->depth;
@ -6017,8 +6056,9 @@ static int vrend_renderer_resource_allocate_texture(struct vrend_resource *gr,
if (pr->width0 == 0) if (pr->width0 == 0)
return EINVAL; return EINVAL;
enum virgl_formats format = vrend_format_replace_emulated(gr->base.bind, gr->base.format);
bool format_can_texture_storage = has_feature(feat_texture_storage) && bool format_can_texture_storage = has_feature(feat_texture_storage) &&
(tex_conv_table[pr->format].flags & VIRGL_TEXTURE_CAN_TEXTURE_STORAGE); (tex_conv_table[format].flags & VIRGL_TEXTURE_CAN_TEXTURE_STORAGE);
gr->target = tgsitargettogltarget(pr->target, pr->nr_samples); gr->target = tgsitargettogltarget(pr->target, pr->nr_samples);
gr->storage = VREND_RESOURCE_STORAGE_TEXTURE; gr->storage = VREND_RESOURCE_STORAGE_TEXTURE;
@ -6044,9 +6084,9 @@ static int vrend_renderer_resource_allocate_texture(struct vrend_resource *gr,
debug_texture(__func__, gr); debug_texture(__func__, gr);
internalformat = tex_conv_table[pr->format].internalformat; internalformat = tex_conv_table[format].internalformat;
glformat = tex_conv_table[pr->format].glformat; glformat = tex_conv_table[format].glformat;
gltype = tex_conv_table[pr->format].gltype; gltype = tex_conv_table[format].gltype;
if (internalformat == 0) { if (internalformat == 0) {
vrend_printf("unknown format is %d\n", pr->format); vrend_printf("unknown format is %d\n", pr->format);
@ -6921,8 +6961,9 @@ static int vrend_transfer_send_readpixels(struct vrend_resource *res,
glUseProgram(0); glUseProgram(0);
format = tex_conv_table[res->base.format].glformat; enum virgl_formats fmt = vrend_format_replace_emulated(res->base.bind, res->base.format);
type = tex_conv_table[res->base.format].gltype; format = tex_conv_table[fmt].glformat;
type = tex_conv_table[fmt].gltype;
/* if we are asked to invert and reading from a front then don't */ /* if we are asked to invert and reading from a front then don't */
actually_invert = res->y_0_top; actually_invert = res->y_0_top;
@ -7781,15 +7822,21 @@ static GLuint vrend_make_view(struct vrend_resource *res, enum pipe_format forma
{ {
GLuint view_id; GLuint view_id;
glGenTextures(1, &view_id); glGenTextures(1, &view_id);
GLenum fmt = tex_conv_table[format].internalformat;
enum virgl_formats src_fmt = vrend_format_replace_emulated(res->base.bind, res->base.format);
enum virgl_formats dst_fmt = vrend_format_replace_emulated(res->base.bind, format);
GLenum fmt = tex_conv_table[dst_fmt].internalformat;
/* If the format doesn't support TextureStorage it is not immutable, so no TextureView*/ /* If the format doesn't support TextureStorage it is not immutable, so no TextureView*/
if (!(tex_conv_table[format].flags & VIRGL_TEXTURE_CAN_TEXTURE_STORAGE)) if (!(tex_conv_table[src_fmt].flags & VIRGL_TEXTURE_CAN_TEXTURE_STORAGE))
return res->id; return res->id;
VREND_DEBUG(dbg_blit, NULL, "Create texture view from %s for %s\n", VREND_DEBUG(dbg_blit, NULL, "Create texture view from %s%s as %s%s\n",
util_format_name(res->base.format), util_format_name(res->base.format),
util_format_name(format)); (enum virgl_formats)res->base.format != src_fmt ? "(emulated)" : "",
util_format_name(format),
(enum virgl_formats)format != dst_fmt ? "(emulated)" : "");
unsigned layers_factor = 1; unsigned layers_factor = 1;
if (res->target == GL_TEXTURE_CUBE_MAP || res->target == GL_TEXTURE_CUBE_MAP_ARRAY) if (res->target == GL_TEXTURE_CUBE_MAP || res->target == GL_TEXTURE_CUBE_MAP_ARRAY)
@ -9145,8 +9192,10 @@ static void vrend_renderer_fill_caps_v2(int gl_ver, int gles_ver, union virgl_c
caps->v2.capability_bits |= VIRGL_CAP_FBO_MIXED_COLOR_FORMATS; caps->v2.capability_bits |= VIRGL_CAP_FBO_MIXED_COLOR_FORMATS;
/* 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))
caps->v2.capability_bits |= VIRGL_CAP_BIND_COMMAND_ARGS; caps->v2.capability_bits |= VIRGL_CAP_BIND_COMMAND_ARGS;

@ -132,6 +132,8 @@ 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,
const struct pipe_stream_output_info *stream_output, const struct pipe_stream_output_info *stream_output,
@ -370,6 +372,7 @@ GLint64 vrend_renderer_get_timestamp(void);
void vrend_build_format_list_common(void); void vrend_build_format_list_common(void);
void vrend_build_format_list_gl(void); void vrend_build_format_list_gl(void);
void vrend_build_format_list_gles(void); void vrend_build_format_list_gles(void);
void vrend_build_emulated_format_list_gles(void);
void vrend_check_texture_storage(struct vrend_format_table *table); void vrend_check_texture_storage(struct vrend_format_table *table);
int vrend_renderer_resource_attach_iov(int res_handle, struct iovec *iov, int vrend_renderer_resource_attach_iov(int res_handle, struct iovec *iov,

Loading…
Cancel
Save