Merge branch 'straight-alpha-dmabuf' into 'main'

memoryformat: Expand docs

See merge request GNOME/gtk!6669
This commit is contained in:
Matthias Clasen
2023-12-16 13:05:13 +00:00
8 changed files with 93 additions and 19 deletions

View File

@@ -1123,20 +1123,32 @@ gdk_memory_format_alignment (GdkMemoryFormat format)
*
* Gets a list of fallback formats to use for @format.
*
* These formats are RGBA formats that ideally have a
* higher depth than the given format. They will always
* include a guaranteed supported format though, even
* if it is of lower quality.
* These formats are RGBA formats that ideally have a higher depth
* than the given format. They will always include a guaranteed
* supported format though, even if it is of lower quality (unless
* @format is already guaranteed supported).
*
* Fallbacks will use the same alpha format, ie a premultiplied
* format will never fall back to a straight alpha format and
* vice versa.
* Either may fall back to an opaque format.
* Opaque formats will fall back to premultiplied formats only.
* vice versa. Either may fall back to an opaque format. Opaque
* formats will fall back to premultiplied formats only.
*
* Use gdk_memory_format_get_premultiplied_formats() to transition
* between premultiplied and straight alpha if you need to.
* Use gdk_memory_format_get_premultiplied() and
* gdk_memory_format_get_straight() to transition between
* premultiplied and straight alpha if you need to.
*
* Use gdk_memory_format_gl_rgba_format() to get an equivalent RGBA
* format and swizzle.
*
* The expected order of operation when looking for supported formats
* is the following:
*
* 1. Try the format itself
* 2. If swizzling is supported, try the RGBA format with swizzling
* 3. If swizzling is not supported, try the RGBA without swizzling,
* and with CPU conversion
* 4. Try fallback formats
*
* Returns: A list of fallbacks, terminated with -1
**/
const GdkMemoryFormat *

View File

@@ -1605,7 +1605,6 @@ gsk_gl_command_queue_do_upload_texture_chunk (GskGLCommandQueue *self,
start_time = GDK_PROFILER_CURRENT_TIME;
}
glPixelStorei (GL_UNPACK_ALIGNMENT, gdk_memory_format_alignment (data_format));
/* GL_UNPACK_ROW_LENGTH is available on desktop GL, OpenGL ES >= 3.0, or if

View File

@@ -807,6 +807,8 @@ gsk_gl_driver_import_dmabuf_texture (GskGLDriver *self,
GskGLRenderTarget *render_target;
guint prev_fbo;
gboolean external;
GdkMemoryFormat format;
gboolean premultiply;
gdk_gl_context_make_current (context);
@@ -822,6 +824,8 @@ gsk_gl_driver_import_dmabuf_texture (GskGLDriver *self,
}
dmabuf = gdk_dmabuf_texture_get_dmabuf (texture);
format = gdk_texture_get_format (GDK_TEXTURE (texture));
premultiply = gdk_memory_format_alpha (format) == GDK_MEMORY_ALPHA_STRAIGHT;
texture_id = gdk_gl_context_import_dmabuf (context,
width, height,
@@ -830,12 +834,15 @@ gsk_gl_driver_import_dmabuf_texture (GskGLDriver *self,
if (texture_id == 0)
return 0;
if (!external)
if (!external && !premultiply)
return texture_id;
gsk_gl_driver_autorelease_texture (self, texture_id);
program = self->external;
if (external)
program = self->external;
else
program = self->premultiply;
if (!gsk_gl_driver_create_render_target (self, width, height, GL_RGBA8, &render_target))
return texture_id;
@@ -849,9 +856,20 @@ gsk_gl_driver_import_dmabuf_texture (GskGLDriver *self,
set_viewport_for_size (self, program, width, height);
reset_modelview (self, program);
gsk_gl_program_set_uniform_texture (program,
UNIFORM_EXTERNAL_SOURCE, 0,
GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE0, texture_id);
if (external)
{
gsk_gl_program_set_uniform_texture (program,
UNIFORM_EXTERNAL_SOURCE, 0,
GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE0, texture_id);
gsk_gl_program_set_uniform1i (program, UNIFORM_PREMULTIPLY, 0, premultiply);
}
else
{
gsk_gl_program_set_uniform_texture (program,
UNIFORM_SHARED_SOURCE, 0,
GL_TEXTURE_2D, GL_TEXTURE0, texture_id);
}
draw_rect (self->command_queue, 0, 0, width, height);

View File

@@ -96,4 +96,9 @@ GSK_GL_DEFINE_PROGRAM (unblurred_outset_shadow,
GSK_GL_DEFINE_PROGRAM_NO_CLIP (external,
GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("external.glsl")),
GSK_GL_ADD_UNIFORM (1, EXTERNAL_SOURCE, u_external_source))
GSK_GL_ADD_UNIFORM (1, EXTERNAL_SOURCE, u_external_source)
GSK_GL_ADD_UNIFORM (2, PREMULTIPLY, u_premultiply))
GSK_GL_DEFINE_PROGRAM_NO_CLIP (premultiply,
GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("premultiply.glsl")),
GSK_GL_NO_UNIFORMS)

View File

@@ -17,6 +17,8 @@ uniform samplerExternalOES u_external_source;
uniform sampler2D u_external_source;
#endif
uniform int u_premultiply;
void main() {
/* Open-code this here, since GskTexture() expects a sampler2D */
#if defined(GSK_GLES) || defined(GSK_LEGACY)
@@ -24,5 +26,9 @@ void main() {
#else
vec4 color = texture(u_external_source, vUv);
#endif
if (u_premultiply == 1)
color.rgb *= color.a;
gskSetOutputColor(color);
}

View File

@@ -0,0 +1,19 @@
// VERTEX_SHADER:
// premultiply.glsl
void main() {
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
vUv = vec2(aUv.x, aUv.y);
}
// FRAGMENT_SHADER:
// premultiply.glsl
void main() {
vec4 color = GskTexture(u_source, vUv);
color.rgb *= color.a;
gskSetOutputColor(color);
}

View File

@@ -21,6 +21,7 @@ gsk_private_gl_shaders = [
'gl/resources/filled_border.glsl',
'gl/resources/mask.glsl',
'gl/resources/external.glsl',
'gl/resources/premultiply.glsl',
]
gsk_public_sources = files([

View File

@@ -433,9 +433,11 @@ texture_builder_set_planes (GdkDmabufTextureBuilder *builder,
static GdkTexture *
make_dmabuf_texture (const char *filename,
guint32 format,
gboolean disjoint)
gboolean disjoint,
gboolean premultiplied)
{
GdkTexture *texture;
GdkTextureDownloader *downloader;
int width, height;
gsize rgb_stride, rgb_size;
guchar *rgb_data;
@@ -459,7 +461,15 @@ make_dmabuf_texture (const char *filename,
rgb_data = g_new0 (guchar, rgb_size);
gdk_texture_download (texture, rgb_data, rgb_stride);
downloader = gdk_texture_downloader_new (texture);
if (premultiplied)
gdk_texture_downloader_set_format (downloader, GDK_MEMORY_B8G8R8A8_PREMULTIPLIED);
else
gdk_texture_downloader_set_format (downloader, GDK_MEMORY_B8G8R8A8);
gdk_texture_downloader_download_into (downloader, rgb_data, rgb_stride);
gdk_texture_downloader_free (downloader);
g_object_unref (texture);
@@ -470,6 +480,7 @@ make_dmabuf_texture (const char *filename,
gdk_dmabuf_texture_builder_set_height (builder, height);
gdk_dmabuf_texture_builder_set_fourcc (builder, format);
gdk_dmabuf_texture_builder_set_modifier (builder, DRM_FORMAT_MOD_LINEAR);
gdk_dmabuf_texture_builder_set_premultiplied (builder, premultiplied);
if (format == DRM_FORMAT_XRGB8888 ||
format == DRM_FORMAT_ARGB8888)
@@ -627,6 +638,7 @@ main (int argc, char *argv[])
char *filename;
guint32 format;
gboolean disjoint = FALSE;
gboolean premultiplied = TRUE;
gboolean decorated = TRUE;
unsigned int i;
const char *save_filename = NULL;
@@ -637,6 +649,8 @@ main (int argc, char *argv[])
disjoint = TRUE;
else if (g_str_equal (argv[i], "--undecorated"))
decorated = FALSE;
else if (g_str_equal (argv[i], "--unpremultiplied"))
premultiplied = FALSE;
else if (g_str_equal (argv[i], "--download-to"))
{
i++;
@@ -663,7 +677,7 @@ main (int argc, char *argv[])
/* Get the list of supported formats with GDK_DEBUG=opengl */
gdk_display_get_dmabuf_formats (gdk_display_get_default ());
texture = make_dmabuf_texture (filename, format, disjoint);
texture = make_dmabuf_texture (filename, format, disjoint, premultiplied);
if (save_filename)
gdk_texture_save_to_png (texture, save_filename);