diff --git a/src/virgl_protocol.h b/src/virgl_protocol.h index 15a2c4a..8523926 100644 --- a/src/virgl_protocol.h +++ b/src/virgl_protocol.h @@ -600,6 +600,7 @@ enum virgl_context_cmd { enum vrend_tweak_type { virgl_tweak_gles_brga_emulate, + virgl_tweak_gles_brga_apply_dest_swizzle, virgl_tweak_undefined }; diff --git a/src/vrend_blitter.c b/src/vrend_blitter.c index 139cdec..907a6a0 100644 --- a/src/vrend_blitter.c +++ b/src/vrend_blitter.c @@ -406,11 +406,12 @@ static GLuint blit_get_frag_tex_col(struct vrend_blitter_ctx *blit_ctx, int pipe_tex_target, unsigned nr_samples, const struct vrend_format_table *src_entry, - const struct vrend_format_table *dst_entry) + const struct vrend_format_table *dst_entry, + bool skip_dest_swizzle) { assert(pipe_tex_target < PIPE_MAX_TEXTURE_TYPES); - bool needs_swizzle = dst_entry->flags & VIRGL_TEXTURE_NEED_SWIZZLE; + bool needs_swizzle = !skip_dest_swizzle && (dst_entry->flags & VIRGL_TEXTURE_NEED_SWIZZLE); if (needs_swizzle || nr_samples > 1) { const uint8_t *swizzle = needs_swizzle ? dst_entry->swizzle : NULL; @@ -711,7 +712,8 @@ void vrend_renderer_blit_gl(struct vrend_context *ctx, GLenum blit_views[2], const struct pipe_blit_info *info, bool has_texture_srgb_decode, - bool has_srgb_write_control) + bool has_srgb_write_control, + bool skip_dest_swizzle) { struct vrend_blitter_ctx *blit_ctx = &vrend_blit_ctx; GLuint buffers; @@ -731,9 +733,10 @@ void vrend_renderer_blit_gl(struct vrend_context *ctx, const struct util_format_description *dst_desc = util_format_description(dst_res->base.format); const struct vrend_format_table *src_entry = - vrend_get_format_table_entry(info->src.format); + vrend_get_format_table_entry_with_emulation(src_res->base.bind, 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 = - vrend_get_format_table_entry(info->dst.format); + vrend_get_format_table_entry_with_emulation(dst_res->base.bind, info->dst.format); has_depth = util_format_has_depth(src_desc) && util_format_has_depth(dst_desc); @@ -779,7 +782,8 @@ void vrend_renderer_blit_gl(struct vrend_context *ctx, } else { fs_id = blit_get_frag_tex_col(blit_ctx, src_res->base.target, src_res->base.nr_samples, - src_entry, dst_entry); + orig_src_entry, dst_entry, + skip_dest_swizzle); } glAttachShader(prog_id, fs_id); diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c index f064a5c..4b1b8d2 100644 --- a/src/vrend_renderer.c +++ b/src/vrend_renderer.c @@ -596,6 +596,7 @@ struct vrend_sub_context { struct vrend_abo abo[PIPE_MAX_HW_ATOMIC_BUFFERS]; uint32_t abo_used_mask; struct vrend_context_tweaks tweaks; + uint8_t swizzle_output_rgb_to_bgr; }; struct vrend_context { @@ -2259,6 +2260,22 @@ static void vrend_hw_emit_framebuffer_state(struct vrend_context *ctx) glDisable(GL_FRAMEBUFFER_SRGB_EXT); } } + + if (vrend_state.use_gles && + vrend_get_tweak_is_active(&ctx->sub->tweaks, virgl_tweak_gles_brga_apply_dest_swizzle)) { + ctx->sub->swizzle_output_rgb_to_bgr = 0; + for (int i = 0; i < ctx->sub->nr_cbufs; i++) { + if (ctx->sub->surf[i]) { + struct vrend_surface *surf = ctx->sub->surf[i]; + if (surf->texture->base.bind & VIRGL_BIND_PREFER_EMULATED_BGRA) { + VREND_DEBUG(dbg_tweak, ctx, "Swizzled BGRA output for 0x%x (%s)\n", i, util_format_name(surf->format)); + ctx->sub->swizzle_output_rgb_to_bgr |= 1 << i; + } + } + } + + } + glDrawBuffers(ctx->sub->nr_cbufs, buffers); } @@ -3044,6 +3061,9 @@ static inline void vrend_fill_shader_key(struct vrend_context *ctx, key->coord_replace = ctx->sub->rs_state.point_quad_rasterization ? ctx->sub->rs_state.sprite_coord_enable : 0; key->winsys_adjust_y_emitted = false; + if (type == PIPE_SHADER_FRAGMENT) + key->fs_swizzle_output_rgb_to_bgr = ctx->sub->swizzle_output_rgb_to_bgr; + if (ctx->sub->shaders[PIPE_SHADER_GEOMETRY]) key->gs_present = true; if (ctx->sub->shaders[PIPE_SHADER_TESS_CTRL]) @@ -4177,7 +4197,7 @@ int vrend_draw_vbo(struct vrend_context *ctx, if (ctx->sub->blend_state_dirty) vrend_patch_blend_state(ctx); - if (ctx->sub->shader_dirty) { + if (ctx->sub->shader_dirty || ctx->sub->swizzle_output_rgb_to_bgr) { struct vrend_linked_shader_program *prog; bool fs_dirty, vs_dirty, gs_dirty, tcs_dirty, tes_dirty; bool dual_src = util_blend_state_is_dual(&ctx->sub->blend_state, 0); @@ -7864,6 +7884,7 @@ static void vrend_renderer_blit_int(struct vrend_context *ctx, int n_layers = 1, i; bool use_gl = false; bool make_intermediate_copy = false; + bool skip_dest_swizzle = false; GLuint intermediate_fbo = 0; struct vrend_resource *intermediate_copy = 0; @@ -7946,9 +7967,17 @@ static void vrend_renderer_blit_int(struct vrend_context *ctx, if (info->src.box.depth != info->dst.box.depth) use_gl = true; - if (vrend_blit_needs_swizzle(info->dst.format, info->src.format)) + if (vrend_blit_needs_swizzle(vrend_format_replace_emulated(dst_res->base.bind, info->dst.format), + vrend_format_replace_emulated(src_res->base.bind, info->src.format))) { 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 ((src_res->base.format != info->src.format) && has_feature(feat_texture_view)) blitter_views[0] = vrend_make_view(src_res, info->src.format); @@ -7960,7 +7989,8 @@ static void vrend_renderer_blit_int(struct vrend_context *ctx, VREND_DEBUG(dbg_blit, ctx, "BLIT_INT: use GL fallback\n"); vrend_renderer_blit_gl(ctx, src_res, dst_res, blitter_views, info, has_feature(feat_texture_srgb_decode), - has_feature(feat_srgb_write_control)); + has_feature(feat_srgb_write_control), + skip_dest_swizzle); vrend_clicbs->make_current(ctx->sub->gl_context); goto cleanup; } diff --git a/src/vrend_renderer.h b/src/vrend_renderer.h index b557b88..b1b0ce8 100644 --- a/src/vrend_renderer.h +++ b/src/vrend_renderer.h @@ -440,7 +440,8 @@ void vrend_renderer_blit_gl(struct vrend_context *ctx, GLenum blit_views[2], const struct pipe_blit_info *info, bool has_texture_srgb_decode, - bool has_srgb_write_control); + bool has_srgb_write_control, + bool skip_dest_swizzle); void vrend_blitter_fini(void); void vrend_renderer_reset(void); diff --git a/src/vrend_shader.c b/src/vrend_shader.c index e120006..1378809 100644 --- a/src/vrend_shader.c +++ b/src/vrend_shader.c @@ -2030,6 +2030,15 @@ static void emit_fragment_logicop(struct dump_ctx *ctx) } } +static void emit_cbuf_swizzle(struct dump_ctx *ctx) +{ + for (uint i = 0; i < ctx->num_outputs; i++) { + if (ctx->key->fs_swizzle_output_rgb_to_bgr & (1 << i)) { + emit_buff(ctx, "fsout_c%d = fsout_c%d.zyxw;\n", i, i); + } + } +} + static void handle_fragment_proc_exit(struct dump_ctx *ctx) { if (ctx->key->pstipple_tex) @@ -2041,9 +2050,13 @@ static void handle_fragment_proc_exit(struct dump_ctx *ctx) if (ctx->key->add_alpha_test) emit_alpha_test(ctx); + if (ctx->key->fs_logicop_enabled) emit_fragment_logicop(ctx); + if (ctx->key->fs_swizzle_output_rgb_to_bgr) + emit_cbuf_swizzle(ctx); + if (ctx->write_all_cbufs) emit_cbuf_writes(ctx); diff --git a/src/vrend_shader.h b/src/vrend_shader.h index 07ab19d..ca7008e 100644 --- a/src/vrend_shader.h +++ b/src/vrend_shader.h @@ -124,6 +124,7 @@ struct vrend_shader_key { uint8_t num_indirect_generic_inputs; uint8_t num_indirect_patch_inputs; uint32_t generic_outputs_expected_mask; + uint8_t fs_swizzle_output_rgb_to_bgr; }; struct vrend_shader_cfg { diff --git a/src/vrend_tweaks.c b/src/vrend_tweaks.c index ed0d3bf..c5abeeb 100644 --- a/src/vrend_tweaks.c +++ b/src/vrend_tweaks.c @@ -49,6 +49,10 @@ const char *tweak_debug_table[] = { [virgl_tweak_gles_brga_emulate] = "GLES: Skip linearization in blits to BGRA_UNORM surfaces", + [virgl_tweak_gles_brga_apply_dest_swizzle] = + "GLES: Apply dest swizzle when a BGRA surface is emulated by an RGBA surface", + + [virgl_tweak_gles_tf3_samples_passes_multiplier] = [virgl_tweak_undefined] = "Undefined tweak" }; @@ -83,6 +87,11 @@ struct { } tweak_table [] = { { virgl_tweak_gles_brga_emulate, "emu-bgra", "Emulate BGRA_UNORM and BGRA_SRB by using swizzled RGBA formats" }, + + { virgl_tweak_gles_brga_apply_dest_swizzle, "bgra-dest-swz", + "Apply the destination swizzle of emulated BGRA surfaces in blits"}, + + { virgl_tweak_gles_tf3_samples_passes_multiplier, "samples-passed", { virgl_tweak_undefined, NULL, NULL} };