formats: Check and enable implementation specific readback formats on GLES

With 6a3cd2bd  vrend: send list of readback-formats to guest

stricter format checks were introduced on GLES. This may lead to format
conversions in guest and host that can be avoided for additional
implementation specific readback formats. So when we build the format list
also check whether a bound texture format can also be read back from the
fbo and report the standard and additional formats also to the guest.

v2: Make things simpler and more correct (Erik) i.e.:
    - default to false in the check for readback formats
    - rename test function to indicate that we test color formats only
    - don't pass the gl_version, instead use the epoxy functions
      to get the platform info

v3: - check for DS readback support (Thanks to Erik for pointing out that this
      is not available in unextended GLES)
    - drop some superfluous braces (Erik)

v4: - move DS checks to separate commit (Erik)

v5: - split patch to move preparations that don't change
      functionality to preceeding patches
    - reduce the amount of error checking (Erik)
    - only check readback for formats that can actually be used as
      render targets
    - remove some temporary variables (Erik)

Signed-off-by: Gert Wollny <gert.wollny@collabora.com>
Reviewed-by: Erik Faye-Lund <erik.faye-lund@collabora.com>
macos/master
Gert Wollny 6 years ago
parent 2cee6cf5d7
commit 108ef814a4
  1. 36
      src/vrend_formats.c
  2. 32
      src/vrend_renderer.c
  3. 1
      src/vrend_renderer.h

@ -294,10 +294,37 @@ static struct vrend_format_table gles_bit10_formats[] = {
{ VIRGL_FORMAT_B10G10R10A2_UNORM, GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, NO_SWIZZLE },
};
static bool color_format_can_readback(struct vrend_format_table *virgl_format, int gles_ver)
{
GLint imp = 0;
if (virgl_format->format == VIRGL_FORMAT_R8G8B8A8_UNORM)
return true;
if (gles_ver >= 30 &&
(virgl_format->format == VIRGL_FORMAT_R32G32B32A32_SINT ||
virgl_format->format == VIRGL_FORMAT_R32G32B32A32_UINT))
return true;
if ((virgl_format->format == VIRGL_FORMAT_R32G32B32A32_FLOAT) &&
(gles_ver >= 32 || epoxy_has_gl_extension("GL_EXT_color_buffer_float")))
return true;
/* Check implementation specific readback formats */
glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &imp);
if (imp == (GLint)virgl_format->gltype) {
glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &imp);
if (imp == (GLint)virgl_format->glformat)
return true;
}
return false;
}
static void vrend_add_formats(struct vrend_format_table *table, int num_entries)
{
int i;
const bool is_desktop_gl = epoxy_is_desktop_gl();
const int gles_ver = is_desktop_gl ? 0 : epoxy_gl_version();
for (i = 0; i < num_entries; i++) {
GLenum status;
@ -402,8 +429,13 @@ static void vrend_add_formats(struct vrend_format_table *table, int num_entries)
status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
binding = VIRGL_BIND_SAMPLER_VIEW;
if (status == GL_FRAMEBUFFER_COMPLETE)
binding |= (is_depth ? VIRGL_BIND_DEPTH_STENCIL : VIRGL_BIND_RENDER_TARGET);
if (status == GL_FRAMEBUFFER_COMPLETE) {
binding |= is_depth ? VIRGL_BIND_DEPTH_STENCIL : VIRGL_BIND_RENDER_TARGET;
if (is_desktop_gl ||
color_format_can_readback(&table[i], gles_ver))
flags |= VIRGL_TEXTURE_CAN_READBACK;
}
glDeleteTextures(1, &tex_id);
glDeleteFramebuffers(1, &fb_id);

@ -648,6 +648,12 @@ static inline bool vrend_format_can_sample(enum virgl_formats format)
{
return tex_conv_table[format].bindings & VIRGL_BIND_SAMPLER_VIEW;
}
static inline bool vrend_format_can_readback(enum virgl_formats format)
{
return tex_conv_table[format].flags & VIRGL_TEXTURE_CAN_READBACK;
}
static inline bool vrend_format_can_render(enum virgl_formats format)
{
return tex_conv_table[format].bindings & VIRGL_BIND_RENDER_TARGET;
@ -9027,24 +9033,14 @@ static void vrend_renderer_fill_caps_v2(int gl_ver, int gles_ver, union virgl_c
if (has_feature(feat_indirect_params))
caps->v2.capability_bits |= VIRGL_CAP_INDIRECT_PARAMS;
if (gl_ver > 0) {
for (int i = 0; i < VIRGL_FORMAT_MAX; i++) {
if (tex_conv_table[i].internalformat != 0) {
enum virgl_formats fmt = (enum virgl_formats)i;
if (vrend_format_can_sample(fmt))
set_format_bit(&caps->v2.supported_readback_formats, fmt);
}
}
} else {
assert(gles_ver > 0);
set_format_bit(&caps->v2.supported_readback_formats, VIRGL_FORMAT_R8G8B8A8_UNORM);
if (gles_ver >= 30) {
set_format_bit(&caps->v2.supported_readback_formats, VIRGL_FORMAT_R32G32B32A32_SINT);
set_format_bit(&caps->v2.supported_readback_formats, VIRGL_FORMAT_R32G32B32A32_UINT);
if (gles_ver >= 32 || epoxy_has_gl_extension("GL_EXT_color_buffer_float"))
set_format_bit(&caps->v2.supported_readback_formats, VIRGL_FORMAT_R32G32B32A32_FLOAT);
for (int i = 0; i < VIRGL_FORMAT_MAX; i++) {
if (tex_conv_table[i].internalformat != 0) {
enum virgl_formats fmt = (enum virgl_formats)i;
if (vrend_format_can_readback(fmt)) {
VREND_DEBUG(dbg_features, NULL, "Support readback of %s\n",
util_format_name(fmt));
set_format_bit(&caps->v2.supported_readback_formats, fmt);
}
}
}

@ -79,6 +79,7 @@ struct vrend_resource {
#define VIRGL_TEXTURE_NEED_SWIZZLE (1 << 0)
#define VIRGL_TEXTURE_CAN_TEXTURE_STORAGE (1 << 1)
#define VIRGL_TEXTURE_CAN_READBACK (1 << 2)
struct vrend_format_table {
enum virgl_formats format;

Loading…
Cancel
Save