vrend: support custom blitting on emulated BGRA resources

Since externally-stored BGRA resource buffers must remain with
BGRA byte ordering, there are several special cases in the custom
blitter that need to be handled, based on the source and destination
resource formats, as well as the views requested on each by the caller.

This change gives the caller more control over the swizzling operation
to perform during the shader-based blit, so the caller can reconcile the
special cases more concisely.

Fixes #225
Signed-off-by: Ryan Neph <ryanneph@google.com>
Reviewed-by: Gert Wollny <gert.wollny@collabora.com>
macos/master
Ryan Neph 3 years ago
parent 981038e25b
commit 695e7d411a
  1. 33
      src/vrend_blitter.c
  2. 47
      src/vrend_renderer.c
  3. 2
      src/vrend_renderer.h

@ -58,6 +58,7 @@ struct vrend_blitter_ctx {
// Parameters related to the creation of fs_texfetch_col_swizzle
unsigned fs_texfetch_col_swizzle_nr_samples;
bool fs_texfetch_col_swizzle_has_swizzle;
uint8_t fs_texfetch_col_swizzle_swizzle[4];
unsigned dst_width;
unsigned dst_height;
@ -319,23 +320,31 @@ 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,
bool skip_dest_swizzle)
uint8_t swizzle[static 4])
{
assert(pipe_tex_target < PIPE_MAX_TEXTURE_TYPES);
bool needs_swizzle = !skip_dest_swizzle && (dst_entry->flags & VIRGL_TEXTURE_NEED_SWIZZLE);
bool needs_swizzle = false;
for (uint i = 0; i < 4; ++i) {
if (swizzle[i] != i) {
needs_swizzle = true;
break;
}
}
GLuint *shader;
if (needs_swizzle || nr_samples > 1) {
shader = &blit_ctx->fs_texfetch_col_swizzle;
if (*shader && (blit_ctx->fs_texfetch_col_swizzle_has_swizzle != needs_swizzle
|| blit_ctx->fs_texfetch_col_swizzle_nr_samples != nr_samples)) {
if (*shader &&
(blit_ctx->fs_texfetch_col_swizzle_nr_samples != nr_samples ||
blit_ctx->fs_texfetch_col_swizzle_has_swizzle != needs_swizzle ||
(needs_swizzle && memcmp(blit_ctx->fs_texfetch_col_swizzle_swizzle, swizzle, 4)))) {
glDeleteShader(*shader);
*shader = 0;
}
blit_ctx->fs_texfetch_col_swizzle_has_swizzle = needs_swizzle;
if (needs_swizzle)
memcpy(blit_ctx->fs_texfetch_col_swizzle_swizzle, swizzle, 4);
blit_ctx->fs_texfetch_col_swizzle_nr_samples = nr_samples;
} else {
shader = &blit_ctx->fs_texfetch_col[pipe_tex_target];
@ -346,8 +355,6 @@ static GLuint blit_get_frag_tex_col(struct vrend_blitter_ctx *blit_ctx,
unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(pipe_tex_target, nr_samples);
enum tgsi_return_type tgsi_ret = tgsi_ret_for_format(src_entry->format);
const uint8_t *swizzle = needs_swizzle ? dst_entry->swizzle : NULL;
// Integer textures are resolved using just one sample
int msaa_samples = nr_samples > 0 ? (tgsi_ret == TGSI_RETURN_TYPE_UNORM ? nr_samples : 1) : 0;
@ -699,7 +706,7 @@ void vrend_renderer_blit_gl(MAYBE_UNUSED struct vrend_context *ctx,
const struct pipe_blit_info *info,
bool has_texture_srgb_decode,
bool has_srgb_write_control,
bool skip_dest_swizzle)
uint8_t swizzle[static 4])
{
struct vrend_blitter_ctx *blit_ctx = &vrend_blit_ctx;
GLuint buffers;
@ -714,8 +721,6 @@ void vrend_renderer_blit_gl(MAYBE_UNUSED struct vrend_context *ctx,
const struct util_format_description *dst_desc =
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 *dst_entry =
vrend_get_format_table_entry(info->dst.format);
has_depth = util_format_has_depth(src_desc) &&
util_format_has_depth(dst_desc);
@ -735,10 +740,12 @@ void vrend_renderer_blit_gl(MAYBE_UNUSED struct vrend_context *ctx,
fs_id = blit_get_frag_tex_writedepth(blit_ctx, src_res->base.target,
src_res->base.nr_samples);
} else {
VREND_DEBUG(dbg_blit, ctx, "BLIT: applying swizzle during blit: (%d %d %d %d)\n",
swizzle[0], swizzle[1], swizzle[2], swizzle[3]);
fs_id = blit_get_frag_tex_col(blit_ctx, src_res->base.target,
src_res->base.nr_samples,
orig_src_entry, dst_entry,
skip_dest_swizzle);
orig_src_entry,
swizzle);
}
glAttachShader(prog_id, fs_id);

@ -8877,8 +8877,8 @@ static void vrend_renderer_blit_int(struct vrend_context *ctx,
GLenum filter;
int n_layers = 1, i;
bool use_gl = false;
bool needs_swizzle = false;
bool make_intermediate_copy = false;
bool skip_dest_swizzle = false;
GLuint intermediate_fbo = 0;
struct vrend_resource *intermediate_copy = 0;
@ -8960,8 +8960,10 @@ static void vrend_renderer_blit_int(struct vrend_context *ctx,
/* for 3D mipmapped blits - hand roll time */
else if (info->src.box.depth != info->dst.box.depth)
use_gl = true;
else if (vrend_blit_needs_swizzle(info->dst.format, info->src.format))
else if (vrend_blit_needs_swizzle(info->dst.format, info->src.format)) {
use_gl = true;
needs_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);
@ -8969,13 +8971,44 @@ static void vrend_renderer_blit_int(struct vrend_context *ctx,
if ((dst_res->base.format != info->dst.format) && has_feature(feat_texture_view))
blitter_views[1] = vrend_make_view(dst_res, info->dst.format);
/* Virgl's BGR* formats always use GL_RGBA8 internal format so texture views have no format
* conversion effects. Swizzling during blits is required instead.
* Also, GBM/EGL-backed (i.e. external) BGR* resources are always stored with BGR* internal
* format, despite Virgl's use of the GL_RGBA8 internal format, so special care must be taken
* when determining the swizzling.
*/
bool needs_redblue_swizzle = false;
if (vrend_resource_is_emulated_bgra(src_res) ^ vrend_resource_is_emulated_bgra(dst_res))
needs_redblue_swizzle = !needs_redblue_swizzle;
/* Virgl blits support "views" on source/dest resources, allowing another level of format
* conversion on top of the host's GL API. These views need to be reconciled manually when
* any BGR* resources are involved, since they are internally stored with RGB* byte-ordering,
* and externally stored with BGR* byte-ordering.
*/
if (vrend_format_is_bgra(src_res->base.format) ^ vrend_format_is_bgra(info->src.format))
needs_redblue_swizzle = !needs_redblue_swizzle;
if (vrend_format_is_bgra(dst_res->base.format) ^ vrend_format_is_bgra(info->dst.format))
needs_redblue_swizzle = !needs_redblue_swizzle;
uint8_t blit_swizzle[4] = {0, 1, 2, 3};
if (needs_swizzle && vrend_get_format_table_entry(dst_res->base.format)->flags & VIRGL_TEXTURE_NEED_SWIZZLE)
memcpy(blit_swizzle, tex_conv_table[dst_res->base.format].swizzle, sizeof(blit_swizzle));
if (needs_redblue_swizzle) {
VREND_DEBUG(dbg_blit, ctx, "Applying red/blue swizzle during blit involving an external BGR* resource\n");
use_gl = true;
uint8_t temp = blit_swizzle[0];
blit_swizzle[0] = blit_swizzle[2];
blit_swizzle[2] = temp;
}
if (use_gl) {
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),
skip_dest_swizzle);
blit_swizzle);
vrend_sync_make_current(ctx->sub->gl_context);
goto cleanup;
}
@ -9176,19 +9209,23 @@ void vrend_renderer_blit(struct vrend_context *ctx,
vrend_pause_render_condition(ctx, true);
VREND_DEBUG(dbg_blit, ctx, "BLIT: rc:%d scissor:%d filter:%d alpha:%d mask:0x%x\n"
" From %s(%s) ms:%d [%d, %d, %d]+[%d, %d, %d] lvl:%d\n"
" To %s(%s) ms:%d [%d, %d, %d]+[%d, %d, %d] lvl:%d\n",
" From %s(%s) ms:%d egl:%d gbm:%d [%d, %d, %d]+[%d, %d, %d] lvl:%d\n"
" To %s(%s) ms:%d egl:%d gbm:%d [%d, %d, %d]+[%d, %d, %d] lvl:%d\n",
info->render_condition_enable, info->scissor_enable,
info->filter, info->alpha_blend, info->mask,
util_format_name(src_res->base.format),
util_format_name(info->src.format),
src_res->base.nr_samples,
has_bit(src_res->storage_bits, VREND_STORAGE_EGL_IMAGE),
has_bit(src_res->storage_bits, VREND_STORAGE_GBM_BUFFER),
info->src.box.x, info->src.box.y, info->src.box.z,
info->src.box.width, info->src.box.height, info->src.box.depth,
info->src.level,
util_format_name(dst_res->base.format),
util_format_name(info->dst.format),
dst_res->base.nr_samples,
has_bit(dst_res->storage_bits, VREND_STORAGE_EGL_IMAGE),
has_bit(dst_res->storage_bits, VREND_STORAGE_GBM_BUFFER),
info->dst.box.x, info->dst.box.y, info->dst.box.z,
info->dst.box.width, info->dst.box.height, info->dst.box.depth,
info->dst.level);

@ -482,7 +482,7 @@ void vrend_renderer_blit_gl(struct vrend_context *ctx,
const struct pipe_blit_info *info,
bool has_texture_srgb_decode,
bool has_srgb_write_control,
bool skip_dest_swizzle);
uint8_t swizzle[static 4]);
void vrend_blitter_fini(void);
void vrend_renderer_prepare_reset(void);

Loading…
Cancel
Save