gsk: Handle straight-alpha dmabufs

This omission was noticed by Benjamin Otte. Add a premultiply
uniform to the external shader, and add a separate premultiply
shader for the non-external case.
This commit is contained in:
Matthias Clasen 2023-12-14 09:46:51 -05:00
parent c48a3152f0
commit 79009d4158
6 changed files with 55 additions and 7 deletions

View File

@ -1605,7 +1605,6 @@ gsk_gl_command_queue_do_upload_texture_chunk (GskGLCommandQueue *self,
start_time = GDK_PROFILER_CURRENT_TIME; start_time = GDK_PROFILER_CURRENT_TIME;
} }
glPixelStorei (GL_UNPACK_ALIGNMENT, gdk_memory_format_alignment (data_format)); 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 /* 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; GskGLRenderTarget *render_target;
guint prev_fbo; guint prev_fbo;
gboolean external; gboolean external;
GdkMemoryFormat format;
gboolean premultiply;
gdk_gl_context_make_current (context); 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); 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, texture_id = gdk_gl_context_import_dmabuf (context,
width, height, width, height,
@ -830,12 +834,15 @@ gsk_gl_driver_import_dmabuf_texture (GskGLDriver *self,
if (texture_id == 0) if (texture_id == 0)
return 0; return 0;
if (!external) if (!external && !premultiply)
return texture_id; return texture_id;
gsk_gl_driver_autorelease_texture (self, texture_id); gsk_gl_driver_autorelease_texture (self, texture_id);
if (external)
program = self->external; program = self->external;
else
program = self->premultiply;
if (!gsk_gl_driver_create_render_target (self, width, height, GL_RGBA8, &render_target)) if (!gsk_gl_driver_create_render_target (self, width, height, GL_RGBA8, &render_target))
return texture_id; return texture_id;
@ -849,10 +856,21 @@ gsk_gl_driver_import_dmabuf_texture (GskGLDriver *self,
set_viewport_for_size (self, program, width, height); set_viewport_for_size (self, program, width, height);
reset_modelview (self, program); reset_modelview (self, program);
if (external)
{
gsk_gl_program_set_uniform_texture (program, gsk_gl_program_set_uniform_texture (program,
UNIFORM_EXTERNAL_SOURCE, 0, UNIFORM_EXTERNAL_SOURCE, 0,
GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE0, texture_id); 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); draw_rect (self->command_queue, 0, 0, width, height);
gsk_gl_command_queue_end_draw (self->command_queue); gsk_gl_command_queue_end_draw (self->command_queue);

View File

@ -96,4 +96,9 @@ GSK_GL_DEFINE_PROGRAM (unblurred_outset_shadow,
GSK_GL_DEFINE_PROGRAM_NO_CLIP (external, GSK_GL_DEFINE_PROGRAM_NO_CLIP (external,
GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("external.glsl")), 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; uniform sampler2D u_external_source;
#endif #endif
uniform int u_premultiply;
void main() { void main() {
/* Open-code this here, since GskTexture() expects a sampler2D */ /* Open-code this here, since GskTexture() expects a sampler2D */
#if defined(GSK_GLES) || defined(GSK_LEGACY) #if defined(GSK_GLES) || defined(GSK_LEGACY)
@ -24,5 +26,9 @@ void main() {
#else #else
vec4 color = texture(u_external_source, vUv); vec4 color = texture(u_external_source, vUv);
#endif #endif
if (u_premultiply == 1)
color.rgb *= color.a;
gskSetOutputColor(color); 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/filled_border.glsl',
'gl/resources/mask.glsl', 'gl/resources/mask.glsl',
'gl/resources/external.glsl', 'gl/resources/external.glsl',
'gl/resources/premultiply.glsl',
] ]
gsk_public_sources = files([ gsk_public_sources = files([