diff --git a/src/virgl_hw.h b/src/virgl_hw.h index 37ae2ba..94e1d5e 100644 --- a/src/virgl_hw.h +++ b/src/virgl_hw.h @@ -261,6 +261,7 @@ enum virgl_formats { #define VIRGL_CAP_COPY_TRANSFER (1 << 26) #define VIRGL_CAP_CLIP_HALFZ (1 << 27) #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. * 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_SHARED (1 << 20) +#define VIRGL_BIND_PREFER_EMULATED_BGRA (1 << 21) + struct virgl_caps_bool_set1 { unsigned indep_blend_enable:1; unsigned indep_blend_func:1; @@ -419,6 +422,7 @@ enum virgl_ctx_errors { VIRGL_ERROR_CTX_ILLEGAL_VERTEX_FORMAT, VIRGL_ERROR_CTX_ILLEGAL_CMD_BUFFER, VIRGL_ERROR_CTX_GLES_HAVE_TES_BUT_MISS_TCS, + VIRGL_ERROR_GL_ANY_SAMPLES_PASSED, }; #define VIRGL_RESOURCE_Y_0_TOP (1 << 0) diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c index 8f2ff8d..f064a5c 100644 --- a/src/vrend_renderer.c +++ b/src/vrend_renderer.c @@ -279,6 +279,8 @@ struct global_renderer_state { /* Needed on GLES to inject a TCS */ float tess_factors[6]; + bool bgra_srgb_emulation_loaded; + }; 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]; } +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 * vrend_get_format_table_entry(enum virgl_formats 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) { return gltype == GL_TIMESTAMP || @@ -1644,13 +1678,15 @@ int vrend_create_surface(struct vrend_context *ctx, surf->res_handle = res_handle; surf->format = format; + format = vrend_format_replace_emulated(res->base.bind, format); + surf->val0 = val0; surf->val1 = val1; surf->id = res->id; if (has_feature(feat_texture_view) && 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. * Otherwise we only need a texture view if the * 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 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(surf->format)); + util_format_name(surf->format), + surf->format != format); if ((first_layer != last_layer && (first_layer != 0 || (last_layer != (int)util_max_layer(&res->base, surf->val0)))) || surf->format != res->base.format) { - GLenum internalformat = tex_conv_table[surf->format].internalformat; 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 (target == GL_TEXTURE_RECTANGLE_NV || target == GL_TEXTURE_1D) @@ -5619,6 +5656,7 @@ int vrend_renderer_init(struct vrend_if_cbs *cbs, uint32_t flags) glDisable(GL_DEBUG_OUTPUT); } + vrend_state.bgra_srgb_emulation_loaded = false; vrend_build_format_list_common(); if (vrend_state.use_gles) { @@ -5996,6 +6034,7 @@ vrend_renderer_resource_copy_args(struct vrend_renderer_resource_create_args *ar assert(args); gr->handle = args->handle; + gr->base.bind = args->bind; gr->base.width0 = args->width; gr->base.height0 = args->height; gr->base.depth0 = args->depth; @@ -6017,8 +6056,9 @@ static int vrend_renderer_resource_allocate_texture(struct vrend_resource *gr, if (pr->width0 == 0) 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) && - (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->storage = VREND_RESOURCE_STORAGE_TEXTURE; @@ -6044,9 +6084,9 @@ static int vrend_renderer_resource_allocate_texture(struct vrend_resource *gr, debug_texture(__func__, gr); - internalformat = tex_conv_table[pr->format].internalformat; - glformat = tex_conv_table[pr->format].glformat; - gltype = tex_conv_table[pr->format].gltype; + internalformat = tex_conv_table[format].internalformat; + glformat = tex_conv_table[format].glformat; + gltype = tex_conv_table[format].gltype; if (internalformat == 0) { 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); - format = tex_conv_table[res->base.format].glformat; - type = tex_conv_table[res->base.format].gltype; + enum virgl_formats fmt = vrend_format_replace_emulated(res->base.bind, res->base.format); + 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 */ 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; 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 (!(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; - 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(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; 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; /* 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_BGRA_SRGB_IS_EMULATED; + } if (has_feature(feat_indirect_draw)) caps->v2.capability_bits |= VIRGL_CAP_BIND_COMMAND_ARGS; diff --git a/src/vrend_renderer.h b/src/vrend_renderer.h index 13b26f9..b557b88 100644 --- a/src/vrend_renderer.h +++ b/src/vrend_renderer.h @@ -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, 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_with_emulation(uint32_t bind, enum virgl_formats format); + int vrend_create_shader(struct vrend_context *ctx, uint32_t handle, 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_gl(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); int vrend_renderer_resource_attach_iov(int res_handle, struct iovec *iov,