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 4 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 // Parameters related to the creation of fs_texfetch_col_swizzle
unsigned fs_texfetch_col_swizzle_nr_samples; unsigned fs_texfetch_col_swizzle_nr_samples;
bool fs_texfetch_col_swizzle_has_swizzle; bool fs_texfetch_col_swizzle_has_swizzle;
uint8_t fs_texfetch_col_swizzle_swizzle[4];
unsigned dst_width; unsigned dst_width;
unsigned dst_height; unsigned dst_height;
@ -319,23 +320,31 @@ static GLuint blit_get_frag_tex_col(struct vrend_blitter_ctx *blit_ctx,
int pipe_tex_target, int pipe_tex_target,
unsigned nr_samples, unsigned nr_samples,
const struct vrend_format_table *src_entry, const struct vrend_format_table *src_entry,
const struct vrend_format_table *dst_entry, uint8_t swizzle[static 4])
bool skip_dest_swizzle)
{ {
assert(pipe_tex_target < PIPE_MAX_TEXTURE_TYPES); 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; GLuint *shader;
if (needs_swizzle || nr_samples > 1) { if (needs_swizzle || nr_samples > 1) {
shader = &blit_ctx->fs_texfetch_col_swizzle; shader = &blit_ctx->fs_texfetch_col_swizzle;
if (*shader && (blit_ctx->fs_texfetch_col_swizzle_has_swizzle != needs_swizzle if (*shader &&
|| blit_ctx->fs_texfetch_col_swizzle_nr_samples != nr_samples)) { (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); glDeleteShader(*shader);
*shader = 0; *shader = 0;
} }
blit_ctx->fs_texfetch_col_swizzle_has_swizzle = needs_swizzle; 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; blit_ctx->fs_texfetch_col_swizzle_nr_samples = nr_samples;
} else { } else {
shader = &blit_ctx->fs_texfetch_col[pipe_tex_target]; 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); 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); 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 // Integer textures are resolved using just one sample
int msaa_samples = nr_samples > 0 ? (tgsi_ret == TGSI_RETURN_TYPE_UNORM ? nr_samples : 1) : 0; 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, const struct pipe_blit_info *info,
bool has_texture_srgb_decode, bool has_texture_srgb_decode,
bool has_srgb_write_control, bool has_srgb_write_control,
bool skip_dest_swizzle) uint8_t swizzle[static 4])
{ {
struct vrend_blitter_ctx *blit_ctx = &vrend_blit_ctx; struct vrend_blitter_ctx *blit_ctx = &vrend_blit_ctx;
GLuint buffers; GLuint buffers;
@ -714,8 +721,6 @@ void vrend_renderer_blit_gl(MAYBE_UNUSED struct vrend_context *ctx,
const struct util_format_description *dst_desc = const struct util_format_description *dst_desc =
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 =
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);
@ -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, fs_id = blit_get_frag_tex_writedepth(blit_ctx, src_res->base.target,
src_res->base.nr_samples); src_res->base.nr_samples);
} else { } 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, fs_id = blit_get_frag_tex_col(blit_ctx, src_res->base.target,
src_res->base.nr_samples, src_res->base.nr_samples,
orig_src_entry, dst_entry, orig_src_entry,
skip_dest_swizzle); swizzle);
} }
glAttachShader(prog_id, fs_id); glAttachShader(prog_id, fs_id);

@ -8877,8 +8877,8 @@ static void vrend_renderer_blit_int(struct vrend_context *ctx,
GLenum filter; GLenum filter;
int n_layers = 1, i; int n_layers = 1, i;
bool use_gl = false; bool use_gl = false;
bool needs_swizzle = false;
bool make_intermediate_copy = false; bool make_intermediate_copy = false;
bool skip_dest_swizzle = false;
GLuint intermediate_fbo = 0; GLuint intermediate_fbo = 0;
struct vrend_resource *intermediate_copy = 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 */ /* for 3D mipmapped blits - hand roll time */
else if (info->src.box.depth != info->dst.box.depth) else if (info->src.box.depth != info->dst.box.depth)
use_gl = true; 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; use_gl = true;
needs_swizzle = true;
}
if ((src_res->base.format != info->src.format) && has_feature(feat_texture_view)) if ((src_res->base.format != info->src.format) && 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);
@ -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)) if ((dst_res->base.format != info->dst.format) && has_feature(feat_texture_view))
blitter_views[1] = vrend_make_view(dst_res, info->dst.format); 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) { if (use_gl) {
VREND_DEBUG(dbg_blit, ctx, "BLIT_INT: use GL fallback\n"); VREND_DEBUG(dbg_blit, ctx, "BLIT_INT: use GL fallback\n");
vrend_renderer_blit_gl(ctx, src_res, dst_res, blitter_views, info, vrend_renderer_blit_gl(ctx, src_res, dst_res, blitter_views, info,
has_feature(feat_texture_srgb_decode), has_feature(feat_texture_srgb_decode),
has_feature(feat_srgb_write_control), has_feature(feat_srgb_write_control),
skip_dest_swizzle); blit_swizzle);
vrend_sync_make_current(ctx->sub->gl_context); vrend_sync_make_current(ctx->sub->gl_context);
goto cleanup; goto cleanup;
} }
@ -9176,19 +9209,23 @@ void vrend_renderer_blit(struct vrend_context *ctx,
vrend_pause_render_condition(ctx, true); vrend_pause_render_condition(ctx, true);
VREND_DEBUG(dbg_blit, ctx, "BLIT: rc:%d scissor:%d filter:%d alpha:%d mask:0x%x\n" 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" " From %s(%s) ms:%d egl:%d gbm:%d [%d, %d, %d]+[%d, %d, %d] lvl:%d\n"
" To %s(%s) ms:%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->render_condition_enable, info->scissor_enable,
info->filter, info->alpha_blend, info->mask, info->filter, info->alpha_blend, info->mask,
util_format_name(src_res->base.format), util_format_name(src_res->base.format),
util_format_name(info->src.format), util_format_name(info->src.format),
src_res->base.nr_samples, 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.x, info->src.box.y, info->src.box.z,
info->src.box.width, info->src.box.height, info->src.box.depth, info->src.box.width, info->src.box.height, info->src.box.depth,
info->src.level, info->src.level,
util_format_name(dst_res->base.format), util_format_name(dst_res->base.format),
util_format_name(info->dst.format), util_format_name(info->dst.format),
dst_res->base.nr_samples, 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.x, info->dst.box.y, info->dst.box.z,
info->dst.box.width, info->dst.box.height, info->dst.box.depth, info->dst.box.width, info->dst.box.height, info->dst.box.depth,
info->dst.level); info->dst.level);

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

Loading…
Cancel
Save