[gtk/matthiasc/color-profile-rebased: 30/51] gsk: Apply gamma to frames
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/matthiasc/color-profile-rebased: 30/51] gsk: Apply gamma to frames
- Date: Sat, 1 Oct 2022 01:36:43 +0000 (UTC)
commit 7e91c156fec5a7f4812625e5155fab8690c9dd1e
Author: Matthias Clasen <mclasen redhat com>
Date: Sun May 8 13:17:31 2022 -0400
gsk: Apply gamma to frames
Use a shader to go from linear sRGB to sRGB when
we are done with a frame.
gsk/gl/gskglprograms.defs | 5 +++++
gsk/gl/gskglrenderjob.c | 31 ++++++++++++++++++++++++++++++-
gsk/gl/resources/postprocessing.glsl | 22 ++++++++++++++++++++++
gsk/gl/resources/preamble.glsl | 20 ++++++++++++++++++++
gsk/meson.build | 1 +
5 files changed, 78 insertions(+), 1 deletion(-)
---
diff --git a/gsk/gl/gskglprograms.defs b/gsk/gl/gskglprograms.defs
index 1ff99fab89..db85f77cc2 100644
--- a/gsk/gl/gskglprograms.defs
+++ b/gsk/gl/gskglprograms.defs
@@ -82,3 +82,8 @@ GSK_GL_DEFINE_PROGRAM (unblurred_outset_shadow,
GSK_GL_ADD_UNIFORM (1, UNBLURRED_OUTSET_SHADOW_SPREAD, u_spread)
GSK_GL_ADD_UNIFORM (2, UNBLURRED_OUTSET_SHADOW_OFFSET, u_offset)
GSK_GL_ADD_UNIFORM (3, UNBLURRED_OUTSET_SHADOW_OUTLINE_RECT, u_outline_rect))
+
+GSK_GL_DEFINE_PROGRAM (postprocessing,
+ GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("postprocessing.glsl")),
+ GSK_GL_NO_UNIFORMS)
+
diff --git a/gsk/gl/gskglrenderjob.c b/gsk/gl/gskglrenderjob.c
index 699a809d81..5cfa7863ba 100644
--- a/gsk/gl/gskglrenderjob.c
+++ b/gsk/gl/gskglrenderjob.c
@@ -4053,6 +4053,21 @@ gsk_gl_render_job_render_flipped (GskGLRenderJob *job,
glDeleteTextures (1, &texture_id);
}
+static void
+gsk_gl_render_job_postprocess (GskGLRenderJob *job,
+ guint texture_id)
+{
+ gsk_gl_command_queue_bind_framebuffer (job->command_queue, job->framebuffer);
+ gsk_gl_command_queue_clear (job->command_queue, 0, &job->viewport);
+
+ gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, postprocessing));
+ gsk_gl_program_set_uniform_texture (job->current_program,
+ UNIFORM_SHARED_SOURCE, 0,
+ GL_TEXTURE_2D, GL_TEXTURE0, texture_id);
+ gsk_gl_render_job_draw_offscreen_rect (job, &job->viewport);
+ gsk_gl_render_job_end_draw (job);
+}
+
void
gsk_gl_render_job_render (GskGLRenderJob *job,
GskRenderNode *root)
@@ -4060,6 +4075,8 @@ gsk_gl_render_job_render (GskGLRenderJob *job,
G_GNUC_UNUSED gint64 start_time;
guint scale_factor;
guint surface_height;
+ GskGLRenderTarget *render_target;
+ guint texture_id;
g_return_if_fail (job != NULL);
g_return_if_fail (root != NULL);
@@ -4070,16 +4087,28 @@ gsk_gl_render_job_render (GskGLRenderJob *job,
gsk_gl_command_queue_make_current (job->command_queue);
+ if (!gsk_gl_driver_create_render_target (job->driver,
+ job->viewport.size.width,
+ job->viewport.size.height,
+ job->target_format,
+ GL_NEAREST, GL_NEAREST,
+ &render_target))
+ g_assert_not_reached ();
+
/* Build the command queue using the shared GL context for all renderers
* on the same display.
*/
start_time = GDK_PROFILER_CURRENT_TIME;
gdk_gl_context_push_debug_group (job->command_queue->context, "Building command queue");
- gsk_gl_command_queue_bind_framebuffer (job->command_queue, job->framebuffer);
+ gsk_gl_command_queue_bind_framebuffer (job->command_queue, render_target->framebuffer_id);
if (job->clear_framebuffer)
gsk_gl_command_queue_clear (job->command_queue, 0, &job->viewport);
gsk_gl_render_job_visit_node (job, root);
gdk_gl_context_pop_debug_group (job->command_queue->context);
+
+ texture_id = gsk_gl_driver_release_render_target (job->driver, render_target, FALSE);
+ gsk_gl_render_job_postprocess (job, texture_id);
+
gdk_profiler_add_mark (start_time, GDK_PROFILER_CURRENT_TIME-start_time, "Build GL command queue", "");
#if 0
diff --git a/gsk/gl/resources/postprocessing.glsl b/gsk/gl/resources/postprocessing.glsl
new file mode 100644
index 0000000000..c381beccef
--- /dev/null
+++ b/gsk/gl/resources/postprocessing.glsl
@@ -0,0 +1,22 @@
+
+// VERTEX_SHADER:
+// postprocessing.glsl
+
+void main() {
+ gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
+
+ vUv = vec2(aUv.x, aUv.y);
+}
+
+// FRAGMENT_SHADER:
+// postprocessing.glsl
+
+void main() {
+ vec4 diffuse = GskTexture(u_source, vUv);
+
+ diffuse = gsk_unpremultiply(diffuse);
+ diffuse = gsk_linear_to_srgb(diffuse);
+ diffuse = gsk_premultiply(diffuse);
+
+ gskSetOutputColor(diffuse);
+}
diff --git a/gsk/gl/resources/preamble.glsl b/gsk/gl/resources/preamble.glsl
index 5f5d2b780a..68a89552e9 100644
--- a/gsk/gl/resources/preamble.glsl
+++ b/gsk/gl/resources/preamble.glsl
@@ -46,6 +46,26 @@ vec4 gsk_premultiply(vec4 c) {
return vec4(c.rgb * c.a, c.a);
}
+vec4 gsk_unpremultiply(vec4 c)
+{
+ if (c.a != 0)
+ return vec4(c.rgb / c.a, c.a);
+ else
+ return c;
+}
+
+vec4 gsk_srgb_to_linear(vec4 srgb)
+{
+ vec3 linear_rgb = pow(srgb.rgb, vec3(2.2));
+ return vec4(linear_rgb, srgb.a);
+}
+
+vec4 gsk_linear_to_srgb(vec4 linear_rgba)
+{
+ vec3 srgb = pow(linear_rgba.rgb , vec3(1/2.2));
+ return vec4(srgb, linear_rgba.a);
+}
+
vec4 gsk_scaled_premultiply(vec4 c, float s) {
// Fast version of gsk_premultiply(c) * s
// 4 muls instead of 7
diff --git a/gsk/meson.build b/gsk/meson.build
index 02e9c58954..2e7fa1a3be 100644
--- a/gsk/meson.build
+++ b/gsk/meson.build
@@ -19,6 +19,7 @@ gsk_private_gl_shaders = [
'gl/resources/repeat.glsl',
'gl/resources/custom.glsl',
'gl/resources/filled_border.glsl',
+ 'gl/resources/postprocessing.glsl',
]
gsk_public_sources = files([
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]