[gtk/matthiasc/color-profile-rebased: 6/22] Add crude color management impl for cairo




commit 708474d39a1db17698a826eda306efe3efff5143
Author: Benjamin Otte <otte redhat com>
Date:   Sun Sep 26 02:44:54 2021 +0200

    Add crude color management impl for cairo

 gsk/gskcairorenderer.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 71 insertions(+), 4 deletions(-)
---
diff --git a/gsk/gskcairorenderer.c b/gsk/gskcairorenderer.c
index 24675ce35f..52adecfdeb 100644
--- a/gsk/gskcairorenderer.c
+++ b/gsk/gskcairorenderer.c
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2016  Endless 
+ * Copyright © 2016  Endless
  *             2018  Benjamin Otte
  *
  * This library is free software; you can redistribute it and/or
@@ -25,6 +25,9 @@
 #include "gskdebugprivate.h"
 #include "gskrendererprivate.h"
 #include "gskrendernodeprivate.h"
+
+#include "gdk/gdkcolorprofileprivate.h"
+#include "gdk/gdkmemorytextureprivate.h"
 #include "gdk/gdktextureprivate.h"
 
 #ifdef G_ENABLE_DEBUG
@@ -40,6 +43,7 @@ struct _GskCairoRenderer
 
   GdkCairoContext *cairo_context;
 
+  gboolean color_managed;
 #ifdef G_ENABLE_DEBUG
   ProfileTimers profile_timers;
 #endif
@@ -78,8 +82,8 @@ gsk_cairo_renderer_do_render (GskRenderer   *renderer,
                               cairo_t       *cr,
                               GskRenderNode *root)
 {
-#ifdef G_ENABLE_DEBUG
   GskCairoRenderer *self = GSK_CAIRO_RENDERER (renderer);
+#ifdef G_ENABLE_DEBUG
   GskProfiler *profiler;
   gint64 cpu_time;
 #endif
@@ -104,6 +108,7 @@ gsk_cairo_renderer_render_texture (GskRenderer           *renderer,
                                    GskRenderNode         *root,
                                    const graphene_rect_t *viewport)
 {
+  GskCairoRenderer *self = GSK_CAIRO_RENDERER (renderer);
   GdkTexture *texture;
   cairo_surface_t *surface;
   cairo_t *cr;
@@ -127,7 +132,7 @@ gsk_cairo_renderer_render_texture (GskRenderer           *renderer,
         {
           for (x = 0; x < width; x += MAX_IMAGE_SIZE)
             {
-              texture = gsk_cairo_renderer_render_texture (renderer, root, 
+              texture = gsk_cairo_renderer_render_texture (renderer, root,
                                                            &GRAPHENE_RECT_INIT (x, y,
                                                                                 MIN (MAX_IMAGE_SIZE, 
viewport->size.width - x),
                                                                                 MIN (MAX_IMAGE_SIZE, 
viewport->size.height - y)));
@@ -145,6 +150,9 @@ gsk_cairo_renderer_render_texture (GskRenderer           *renderer,
     }
 
   surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
+  if (self->color_managed)
+      gdk_cairo_surface_set_color_profile (surface, gdk_color_profile_get_srgb_linear ());
+
   cr = cairo_create (surface);
 
   cairo_translate (cr, - viewport->origin.x, - viewport->origin.y);
@@ -189,7 +197,64 @@ gsk_cairo_renderer_render (GskRenderer          *renderer,
     }
 #endif
 
-  gsk_cairo_renderer_do_render (renderer, cr, root);
+  if (!self->color_managed ||
+      gdk_color_profile_is_linear (gdk_cairo_get_color_profile (cr)))
+    {
+      gsk_cairo_renderer_do_render (renderer, cr, root);
+    }
+  else
+    {
+      GdkSurface *surface = gsk_renderer_get_surface (renderer);
+      GdkColorProfile *target_profile = gdk_cairo_get_color_profile (cr);
+      cairo_surface_t *cairo_surface;
+      cairo_t *cr2;
+      GdkTexture *color_correct;
+      const cairo_region_t *frame_region;
+      cairo_rectangle_int_t extents;
+      guint i, n;
+
+      frame_region = gdk_draw_context_get_frame_region (GDK_DRAW_CONTEXT (self->cairo_context));
+      cairo_region_get_extents (frame_region, &extents);
+      /* We can't use cairo_push_group() here, because we'd lose the
+       * color profile information.
+       */
+      cairo_surface = gdk_surface_create_similar_surface (surface,
+                                                          CAIRO_CONTENT_COLOR_ALPHA,
+                                                          extents.width,
+                                                          extents.height);
+      gdk_cairo_surface_set_color_profile (cairo_surface,
+                                           gdk_color_profile_get_srgb_linear ());
+
+      cr2 = cairo_create (cairo_surface);
+      cairo_translate (cr2, -extents.x, -extents.y);
+      gdk_cairo_region (cr2, frame_region);
+      cairo_clip (cr2);
+      gsk_cairo_renderer_do_render (renderer, cr2, root);
+      cairo_destroy (cr2);
+
+      color_correct = gdk_texture_new_for_surface (cairo_surface);
+      cairo_surface_destroy (cairo_surface);
+      n = cairo_region_num_rectangles (frame_region);
+      for (i = 0; i < n; i++)
+        {
+          cairo_rectangle_int_t rect;
+          GdkTexture *sub;
+
+          cairo_region_get_rectangle (frame_region, i, &rect);
+          rect.x -= extents.x;
+          rect.y -= extents.y;
+
+          sub = gdk_memory_texture_new_subtexture (GDK_MEMORY_TEXTURE (color_correct),
+                                                   rect.x, rect.y, rect.width, rect.height);
+          cairo_surface = gdk_texture_download_surface (sub, target_profile);
+          cairo_set_source_surface (cr, cairo_surface, rect.x + extents.x, rect.y + extents.y);
+          cairo_paint (cr);
+          cairo_surface_destroy (cairo_surface);
+          g_object_unref (sub);
+        }
+      g_object_unref (color_correct);
+
+    }
 
   cairo_destroy (cr);
 
@@ -210,6 +275,8 @@ gsk_cairo_renderer_class_init (GskCairoRendererClass *klass)
 static void
 gsk_cairo_renderer_init (GskCairoRenderer *self)
 {
+  self->color_managed = TRUE;
+
 #ifdef G_ENABLE_DEBUG
   GskProfiler *profiler = gsk_renderer_get_profiler (GSK_RENDERER (self));
 


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