mirror of
https://gitlab.freedesktop.org/wayland/weston.git
synced 2026-05-08 05:28:05 +02:00
gl-renderer: Add EXT_texture_format_BGRA8888 support to utilities
EXT_texture_format_BGRA8888 allows OpenGL ES implementations to support GL_BGRA8_EXT FBO and texture format. OpenGL implementations handle the spec differently regarding the use of GL_BGRA8_EXT or GL_BGRA_EXT with TexStorage*D(), TexImage*D() and RenderbufferStorage(). A recent revision of the spec (and Mesa) clarifies all that, but in order to support most drivers we simply check which method is supported by order of preference. Co-authored-by: Daniel Stone <daniels@collabora.com> Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
This commit is contained in:
parent
dcee21f02f
commit
85dd477466
3 changed files with 163 additions and 5 deletions
|
|
@ -182,6 +182,11 @@ enum gl_feature_flag {
|
|||
|
||||
/* GL renderer can create two-component red-green textures. */
|
||||
FEATURE_TEXTURE_RG = 1ull << 7,
|
||||
|
||||
/* GL renderer supports the GL_EXT_texture_format_BGRA8888 extension
|
||||
* with the GL_BGRA8_EXT sized internal format revision (23/06/2024) for
|
||||
* renderbuffer objects. */
|
||||
FEATURE_SIZED_BGRA8_RENDERBUFFER = 1ull << 8,
|
||||
};
|
||||
|
||||
/* Keep the following in sync with vertex.glsl. */
|
||||
|
|
@ -237,6 +242,13 @@ static_assert(TEX_UNIT_LAST < 8, "OpenGL ES 2.0 requires at least 8 texture "
|
|||
"GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS check at display creation "
|
||||
"to require more.");
|
||||
|
||||
enum gl_bgra8_texture_support {
|
||||
BGRA8_TEXTURE_SUPPORT_STORAGE = 0,
|
||||
BGRA8_TEXTURE_SUPPORT_IMAGE_REVISED,
|
||||
BGRA8_TEXTURE_SUPPORT_IMAGE_ORIGINAL,
|
||||
BGRA8_TEXTURE_SUPPORT_NONE,
|
||||
};
|
||||
|
||||
struct gl_extension_table {
|
||||
const char *str;
|
||||
size_t len;
|
||||
|
|
@ -428,6 +440,7 @@ struct gl_renderer {
|
|||
uint64_t features;
|
||||
|
||||
GLenum pbo_usage;
|
||||
enum gl_bgra8_texture_support bgra8_texture_support;
|
||||
|
||||
struct wl_list dmabuf_images;
|
||||
struct wl_list dmabuf_formats;
|
||||
|
|
@ -506,6 +519,12 @@ gl_features_has(struct gl_renderer *gr,
|
|||
return (bool) (gr->features & ((uint64_t) flag));
|
||||
}
|
||||
|
||||
enum gl_bgra8_texture_support
|
||||
gl_get_bgra8_texture_support(struct gl_renderer *gr);
|
||||
|
||||
bool
|
||||
gl_has_sized_bgra8_renderbuffer(struct gl_renderer *gr);
|
||||
|
||||
bool
|
||||
gl_texture_is_format_supported(struct gl_renderer *gr,
|
||||
GLenum format);
|
||||
|
|
|
|||
|
|
@ -4845,6 +4845,12 @@ gl_renderer_setup(struct weston_compositor *ec)
|
|||
gl_extensions_has(gr, EXTENSION_EXT_TEXTURE_RG))
|
||||
gr->features |= FEATURE_TEXTURE_RG;
|
||||
|
||||
/* Sized BGRA renderbuffer feature. */
|
||||
if (gl_has_sized_bgra8_renderbuffer(gr))
|
||||
gr->features |= FEATURE_SIZED_BGRA8_RENDERBUFFER;
|
||||
|
||||
gr->bgra8_texture_support = gl_get_bgra8_texture_support(gr);
|
||||
|
||||
wl_list_init(&gr->pending_capture_list);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
|
|
|||
|
|
@ -101,6 +101,7 @@
|
|||
* │ GL_RGBA16F │ 3.0 │ 3.0 │ 3.2 │ GL_RGBA │ GL_HALF_FLOAT, │
|
||||
* │ │ │ │ │ │ GL_FLOAT │
|
||||
* │ GL_RGBA32F │ 3.0 │ │ 3.2 │ GL_RGBA │ GL_FLOAT │
|
||||
* │ GL_BGRA8_EXT │ E⁶ │ E⁶ │ E⁶ │ GL_BGRA_EXT │ GL_UNSIGNED_BYTE │
|
||||
* │ GL_RGBA8UI │ 3.0 │ │ 3.0 │ GL_RGBA_INTEGER │ GL_UNSIGNED_BYTE │
|
||||
* │ GL_RGBA8I │ 3.0 │ │ 3.0 │ GL_RGBA_INTEGER │ GL_BYTE │
|
||||
* │ GL_RGB10_A2UI │ 3.0 │ │ 3.0 │ GL_RGBA_INTEGER │ GL_UNSIGNED_INT_2_10_10_10_REV │
|
||||
|
|
@ -224,6 +225,13 @@ is_valid_format_es3(struct gl_renderer *gr,
|
|||
return gl_extensions_has(gr, EXTENSION_EXT_TEXTURE_NORM16) &&
|
||||
external_format == GL_RGBA;
|
||||
|
||||
/* GL_BGRA_EXT must be here even though it's not a proper sized internal
|
||||
* format to crrectly support EXT_texture_format_BGRA8888. */
|
||||
case GL_BGRA8_EXT:
|
||||
case GL_BGRA_EXT:
|
||||
return gl_extensions_has(gr, EXTENSION_EXT_TEXTURE_FORMAT_BGRA8888) &&
|
||||
external_format == GL_BGRA_EXT;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
|
@ -260,6 +268,12 @@ is_valid_type_es3(struct gl_renderer *gr,
|
|||
return gl_extensions_has(gr, EXTENSION_EXT_TEXTURE_SRGB_RG8) &&
|
||||
type == GL_UNSIGNED_BYTE;
|
||||
|
||||
/* See comment in is_valid_format_es3(). */
|
||||
case GL_BGRA8_EXT:
|
||||
case GL_BGRA_EXT:
|
||||
return gl_extensions_has(gr, EXTENSION_EXT_TEXTURE_FORMAT_BGRA8888) &&
|
||||
type == GL_UNSIGNED_BYTE;
|
||||
|
||||
case GL_R8I:
|
||||
case GL_R8_SNORM:
|
||||
case GL_RG8I:
|
||||
|
|
@ -451,6 +465,14 @@ is_valid_combination_es3(struct gl_renderer *gr,
|
|||
return false;
|
||||
}
|
||||
|
||||
case GL_BGRA_EXT:
|
||||
switch (type) {
|
||||
case GL_UNSIGNED_BYTE:
|
||||
return gl_extensions_has(gr, EXTENSION_EXT_TEXTURE_FORMAT_BGRA8888);
|
||||
default:
|
||||
return false;
|
||||
};
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
|
@ -544,6 +566,14 @@ is_valid_combination_es2(struct gl_renderer *gr,
|
|||
return false;
|
||||
}
|
||||
|
||||
case GL_BGRA_EXT:
|
||||
switch (type) {
|
||||
case GL_UNSIGNED_BYTE:
|
||||
return gl_extensions_has(gr, EXTENSION_EXT_TEXTURE_FORMAT_BGRA8888);
|
||||
default:
|
||||
return false;
|
||||
};
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
|
@ -551,6 +581,83 @@ is_valid_combination_es2(struct gl_renderer *gr,
|
|||
|
||||
#endif /* !defined(NDEBUG) */
|
||||
|
||||
/* Get the supported BGRA8 texture creation method. This is needed to correctly
|
||||
* handle the behaviour of different drivers. This function should only be used
|
||||
* at renderer setup once the extensions have been initialised.
|
||||
*/
|
||||
enum gl_bgra8_texture_support
|
||||
gl_get_bgra8_texture_support(struct gl_renderer *gr)
|
||||
{
|
||||
enum gl_bgra8_texture_support support;
|
||||
GLuint tex;
|
||||
|
||||
if (!gl_extensions_has(gr, EXTENSION_EXT_TEXTURE_FORMAT_BGRA8888))
|
||||
return BGRA8_TEXTURE_SUPPORT_NONE;
|
||||
|
||||
/* Empty error queue. */
|
||||
while (glGetError() != GL_NO_ERROR);
|
||||
|
||||
glGenTextures(1, &tex);
|
||||
glBindTexture(GL_TEXTURE_2D, tex);
|
||||
|
||||
if (gl_features_has(gr, FEATURE_TEXTURE_IMMUTABILITY)) {
|
||||
gr->tex_storage_2d(GL_TEXTURE_2D, 1, GL_BGRA8_EXT, 16, 16);
|
||||
if (glGetError() == GL_NO_ERROR) {
|
||||
support = BGRA8_TEXTURE_SUPPORT_STORAGE;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA8_EXT, 16, 16, 0, GL_BGRA_EXT,
|
||||
GL_UNSIGNED_BYTE, NULL);
|
||||
if (glGetError() == GL_NO_ERROR) {
|
||||
support = BGRA8_TEXTURE_SUPPORT_IMAGE_REVISED;
|
||||
goto done;
|
||||
}
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, 16, 16, 0, GL_BGRA_EXT,
|
||||
GL_UNSIGNED_BYTE, NULL);
|
||||
if (glGetError() == GL_NO_ERROR) {
|
||||
support = BGRA8_TEXTURE_SUPPORT_IMAGE_ORIGINAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
support = BGRA8_TEXTURE_SUPPORT_NONE;
|
||||
|
||||
done:
|
||||
glDeleteTextures(1, &tex);
|
||||
|
||||
return support;
|
||||
}
|
||||
|
||||
/* Check whether the sized BGRA8 renderbuffer feature is available. This
|
||||
* function should only be used at renderer setup once the extensions have been
|
||||
* initialised.
|
||||
*/
|
||||
bool
|
||||
gl_has_sized_bgra8_renderbuffer(struct gl_renderer *gr)
|
||||
{
|
||||
bool available = false;
|
||||
GLuint rb;
|
||||
|
||||
if (!gl_extensions_has(gr, EXTENSION_EXT_TEXTURE_FORMAT_BGRA8888))
|
||||
return false;
|
||||
|
||||
/* Empty error queue. */
|
||||
while (glGetError() != GL_NO_ERROR);
|
||||
|
||||
glGenRenderbuffers(1, &rb);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, rb);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_BGRA8_EXT, 16, 16);
|
||||
|
||||
if (glGetError() == GL_NO_ERROR)
|
||||
available = true;
|
||||
|
||||
glDeleteRenderbuffers(1, &rb);
|
||||
|
||||
return available;
|
||||
}
|
||||
|
||||
/* Check whether gl_texture_2d_init() supports texture creation for a given
|
||||
* coloured sized internal format or not.
|
||||
*/
|
||||
|
|
@ -574,6 +681,9 @@ gl_texture_is_format_supported(struct gl_renderer *gr,
|
|||
case GL_SRG8_EXT:
|
||||
return gl_extensions_has(gr, EXTENSION_EXT_TEXTURE_SRGB_RG8);
|
||||
|
||||
case GL_BGRA8_EXT:
|
||||
return gr->bgra8_texture_support != BGRA8_TEXTURE_SUPPORT_NONE;
|
||||
|
||||
case GL_R16F:
|
||||
case GL_RG16F:
|
||||
case GL_RGB16F:
|
||||
|
|
@ -660,8 +770,8 @@ gl_texture_is_format_supported(struct gl_renderer *gr,
|
|||
* Implementations support at least this subset of formats: GL_R8, GL_RG8,
|
||||
* GL_RGB8, GL_RGB565, GL_RGBA8, GL_RGBA4 and GL_RGB5_A1. Additional formats are
|
||||
* supported depending on extensions: GL_R16F, GL_RG16F, GL_RGB16F, GL_RGBA16F,
|
||||
* GL_R32F, GL_RG32F, GL_RGB32F, GL_RGBA32F, GL_R11F_G11F_B10F, GL_RGB9_E5 and
|
||||
* GL_RGB10_A2.
|
||||
* GL_R32F, GL_RG32F, GL_RGB32F, GL_RGBA32F, GL_R11F_G11F_B10F, GL_RGB9_E5,
|
||||
* GL_RGB10_A2 and GL_BGRA8_EXT.
|
||||
*
|
||||
* This is implemented by implicitly converting 'format' into an external
|
||||
* format. If the red and red-green texture formats aren't supported
|
||||
|
|
@ -680,6 +790,7 @@ gl_texture_2d_init(struct gl_renderer *gr,
|
|||
int height,
|
||||
GLuint *tex_out)
|
||||
{
|
||||
bool bgra_fallback;
|
||||
GLuint tex;
|
||||
|
||||
assert(width > 0);
|
||||
|
|
@ -694,7 +805,13 @@ gl_texture_2d_init(struct gl_renderer *gr,
|
|||
glGenTextures(1, &tex);
|
||||
glBindTexture(GL_TEXTURE_2D, tex);
|
||||
|
||||
if (gl_features_has(gr, FEATURE_TEXTURE_IMMUTABILITY)) {
|
||||
/* Fallback to TexImage*D() when GL_BGRA8_EXT isn't supported by
|
||||
* TexStorage*D(). */
|
||||
bgra_fallback = format == GL_BGRA8_EXT &&
|
||||
gr->bgra8_texture_support != BGRA8_TEXTURE_SUPPORT_STORAGE;
|
||||
|
||||
if (gl_features_has(gr, FEATURE_TEXTURE_IMMUTABILITY) &&
|
||||
!bgra_fallback) {
|
||||
if (!gl_features_has(gr, FEATURE_TEXTURE_RG)) {
|
||||
switch (format) {
|
||||
case GL_R8:
|
||||
|
|
@ -824,6 +941,13 @@ gl_texture_2d_init(struct gl_renderer *gr,
|
|||
type = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
|
||||
case GL_BGRA8_EXT:
|
||||
if (gr->bgra8_texture_support == BGRA8_TEXTURE_SUPPORT_IMAGE_ORIGINAL)
|
||||
format = GL_BGRA_EXT;
|
||||
external_format = GL_BGRA_EXT;
|
||||
type = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
|
||||
case GL_RGBA4:
|
||||
if (!gl_extensions_has(gr, EXTENSION_OES_REQUIRED_INTERNALFORMAT))
|
||||
format = GL_RGBA;
|
||||
|
|
@ -994,6 +1118,9 @@ gl_fbo_is_format_supported(struct gl_renderer *gr,
|
|||
gl_extensions_has(gr, EXTENSION_OES_RGB8_RGBA8) ||
|
||||
gl_extensions_has(gr, EXTENSION_OES_REQUIRED_INTERNALFORMAT);
|
||||
|
||||
case GL_BGRA8_EXT:
|
||||
return gl_extensions_has(gr, EXTENSION_EXT_TEXTURE_FORMAT_BGRA8888);
|
||||
|
||||
case GL_SRGB8_ALPHA8:
|
||||
case GL_R8I:
|
||||
case GL_R8UI:
|
||||
|
|
@ -1079,8 +1206,8 @@ gl_fbo_is_format_supported(struct gl_renderer *gr,
|
|||
*
|
||||
* Implementations support at least these formats: GL_RGBA4, GL_RGB5_A1 and
|
||||
* GL_RGB565. Additional formats are supported depending on extensions: GL_R8,
|
||||
* GL_RG8, GL_RGB8, GL_RGBA8, GL_R16F, GL_RG16F, GL_RGB16F, GL_RGBA16F and
|
||||
* GL_R11F_G11F_B10F.
|
||||
* GL_RG8, GL_RGB8, GL_RGBA8, GL_R16F, GL_RG16F, GL_RGB16F, GL_RGBA16F,
|
||||
* GL_R11F_G11F_B10F and GL_BGRA8_EXT.
|
||||
*
|
||||
* See gl_fbo_is_format_supported().
|
||||
*/
|
||||
|
|
@ -1100,6 +1227,10 @@ gl_fbo_init(struct gl_renderer *gr,
|
|||
return false;
|
||||
}
|
||||
|
||||
if (format == GL_BGRA8_EXT &&
|
||||
!gl_features_has(gr, FEATURE_SIZED_BGRA8_RENDERBUFFER))
|
||||
format = GL_BGRA_EXT;
|
||||
|
||||
glGenFramebuffers(1, &fb);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fb);
|
||||
glGenRenderbuffers(1, &rb);
|
||||
|
|
@ -1194,6 +1325,8 @@ gl_fbo_texture_init(GLenum internal_format,
|
|||
GLenum status;
|
||||
GLuint fb, tex;
|
||||
|
||||
/* XXX Port to new texture utilities and had sized BGRA8 support. */
|
||||
|
||||
glGenTextures(1, &tex);
|
||||
glBindTexture(GL_TEXTURE_2D, tex);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, internal_format, width, height, 0,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue