[gtk/matthiasc/color-profiles: 1/3] ngl: Apply gamma to frames




commit da3e439905a773eaf7e663c5a479ac92b4ca7532
Author: Matthias Clasen <mclasen redhat com>
Date:   Wed Sep 29 22:15:40 2021 -0400

    ngl: Apply gamma to frames
    
    Use a shader to go from linear sRGB to sRGB when
    we are done with a frame.

 gsk/meson.build                       |  1 +
 gsk/ngl/gsknglprograms.defs           |  4 ++++
 gsk/ngl/gsknglrenderjob.c             | 31 +++++++++++++++++++++++++-
 gsk/ngl/resources/postprocessing.glsl | 42 +++++++++++++++++++++++++++++++++++
 4 files changed, 77 insertions(+), 1 deletion(-)
---
diff --git a/gsk/meson.build b/gsk/meson.build
index 20fd33185d..eb33866da5 100644
--- a/gsk/meson.build
+++ b/gsk/meson.build
@@ -19,6 +19,7 @@ gsk_private_ngl_shaders = [
   'ngl/resources/repeat.glsl',
   'ngl/resources/custom.glsl',
   'ngl/resources/filled_border.glsl',
+  'ngl/resources/postprocessing.glsl',
 ]
 
 gsk_public_sources = files([
diff --git a/gsk/ngl/gsknglprograms.defs b/gsk/ngl/gsknglprograms.defs
index f4f4a0dfe5..72b383b8fa 100644
--- a/gsk/ngl/gsknglprograms.defs
+++ b/gsk/ngl/gsknglprograms.defs
@@ -82,3 +82,7 @@ GSK_NGL_DEFINE_PROGRAM (unblurred_outset_shadow,
                         GSK_NGL_ADD_UNIFORM (1, UNBLURRED_OUTSET_SHADOW_SPREAD, u_spread)
                         GSK_NGL_ADD_UNIFORM (2, UNBLURRED_OUTSET_SHADOW_OFFSET, u_offset)
                         GSK_NGL_ADD_UNIFORM (3, UNBLURRED_OUTSET_SHADOW_OUTLINE_RECT, u_outline_rect))
+
+GSK_NGL_DEFINE_PROGRAM (postprocessing,
+                        "/org/gtk/libgsk/ngl/postprocessing.glsl",
+                        GSK_NGL_NO_UNIFORMS)
diff --git a/gsk/ngl/gsknglrenderjob.c b/gsk/ngl/gsknglrenderjob.c
index 7cfe98fa01..4237756675 100644
--- a/gsk/ngl/gsknglrenderjob.c
+++ b/gsk/ngl/gsknglrenderjob.c
@@ -3993,6 +3993,22 @@ gsk_ngl_render_job_render_flipped (GskNglRenderJob *job,
   glDeleteTextures (1, &texture_id);
 }
 
+static void
+gsk_ngl_render_job_postprocess (GskNglRenderJob *job,
+                                guint            texture_id)
+{
+  GskNglProgram *program = job->driver->postprocessing_no_clip;
+
+  gsk_ngl_command_queue_bind_framebuffer (job->command_queue, job->framebuffer);
+
+  gsk_ngl_render_job_begin_draw (job, program);
+  gsk_ngl_program_set_uniform_texture (job->current_program,
+                                       UNIFORM_SHARED_SOURCE, 0,
+                                       GL_TEXTURE_2D, GL_TEXTURE0, texture_id);
+  gsk_ngl_render_job_draw_offscreen_rect (job, &job->viewport);
+  gsk_ngl_render_job_end_draw (job);
+}
+
 void
 gsk_ngl_render_job_render (GskNglRenderJob *job,
                            GskRenderNode   *root)
@@ -4000,6 +4016,8 @@ gsk_ngl_render_job_render (GskNglRenderJob *job,
   G_GNUC_UNUSED gint64 start_time;
   guint scale_factor;
   guint surface_height;
+  GskNglRenderTarget *render_target;
+  guint texture_id;
 
   g_return_if_fail (job != NULL);
   g_return_if_fail (root != NULL);
@@ -4010,15 +4028,26 @@ gsk_ngl_render_job_render (GskNglRenderJob *job,
 
   gsk_ngl_command_queue_make_current (job->command_queue);
 
+  gsk_ngl_driver_create_render_target (job->driver,
+                                       job->viewport.size.width,
+                                       job->viewport.size.height,
+                                       GL_NEAREST,
+                                       GL_NEAREST,
+                                       &render_target);
+
   /* 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_ngl_command_queue_bind_framebuffer (job->command_queue, job->framebuffer);
+  gsk_ngl_command_queue_bind_framebuffer (job->command_queue, render_target->framebuffer_id);
   gsk_ngl_command_queue_clear (job->command_queue, 0, &job->viewport);
   gsk_ngl_render_job_visit_node (job, root);
   gdk_gl_context_pop_debug_group (job->command_queue->context);
+
+  texture_id = gsk_ngl_driver_release_render_target (job->driver, render_target, FALSE);
+  gsk_ngl_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/ngl/resources/postprocessing.glsl b/gsk/ngl/resources/postprocessing.glsl
new file mode 100644
index 0000000000..904da6ef2b
--- /dev/null
+++ b/gsk/ngl/resources/postprocessing.glsl
@@ -0,0 +1,42 @@
+
+// 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
+float u_gamma = 2.2;
+
+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(u_gamma));
+  return vec4(linear_rgb, srgb.a);
+}
+
+vec4 gsk_linear_to_srgb(vec4 linear_rgba)
+{
+  vec3 srgb = pow(linear_rgba.rgb , vec3(1/u_gamma));
+  return vec4(srgb, linear_rgba.a);
+}
+void main() {
+  vec4 diffuse = GskTexture(u_source, vUv);
+
+  diffuse = gsk_unpremultiply(diffuse);
+  diffuse = gsk_linear_to_srgb(diffuse);
+  diffuse = gsk_premultiply(diffuse);
+
+  gskSetOutputColor(diffuse);
+}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]