gl: Do linear compositing
This commit is contained in:
@@ -30,6 +30,13 @@
|
||||
|
||||
#include "gskdebugprivate.h"
|
||||
|
||||
#ifdef HAVE_PANGOFT
|
||||
#include <pango/pangofc-font.h>
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
#include FT_PARAMETER_TAGS_H
|
||||
#endif
|
||||
|
||||
#define MAX_GLYPH_SIZE 128
|
||||
|
||||
G_DEFINE_TYPE (GskGLGlyphLibrary, gsk_gl_glyph_library, GSK_TYPE_GL_TEXTURE_LIBRARY)
|
||||
@@ -218,6 +225,16 @@ render_glyph (cairo_surface_t *surface,
|
||||
cairo_t *cr;
|
||||
PangoGlyphString glyph_string;
|
||||
PangoGlyphInfo glyph_info;
|
||||
#ifdef HAVE_PANGOFT
|
||||
FT_Face face;
|
||||
FT_Bool darken = 1;
|
||||
FT_Parameter property = { FT_PARAM_TAG_STEM_DARKENING, &darken };
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
face = pango_fc_font_lock_face (PANGO_FC_FONT (key->font));
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||
FT_Face_Properties (face, 1, &property);
|
||||
#endif
|
||||
|
||||
g_assert (surface != NULL);
|
||||
|
||||
@@ -236,6 +253,12 @@ render_glyph (cairo_surface_t *surface,
|
||||
cairo_destroy (cr);
|
||||
|
||||
cairo_surface_flush (surface);
|
||||
|
||||
#ifdef HAVE_PANGOFT
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
pango_fc_font_unlock_face (PANGO_FC_FONT (key->font));
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -102,3 +102,8 @@ GSK_GL_DEFINE_PROGRAM_NO_CLIP (external,
|
||||
GSK_GL_DEFINE_PROGRAM_NO_CLIP (premultiply,
|
||||
GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("premultiply.glsl")),
|
||||
GSK_GL_NO_UNIFORMS)
|
||||
|
||||
GSK_GL_DEFINE_PROGRAM (colorconvert,
|
||||
GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("colorconvert.glsl")),
|
||||
GSK_GL_ADD_UNIFORM (1, TO_LINEAR, u_to_linear))
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <gdk/gdkglcontextprivate.h>
|
||||
#include <gdk/gdksurfaceprivate.h>
|
||||
#include <gdk/gdksubsurfaceprivate.h>
|
||||
#include <gdk/gdkcolorstateprivate.h>
|
||||
#include <glib/gi18n-lib.h>
|
||||
#include <gsk/gskdebugprivate.h>
|
||||
#include <gsk/gskrendererprivate.h>
|
||||
@@ -362,6 +363,7 @@ gsk_gl_renderer_render (GskRenderer *renderer,
|
||||
GdkSurface *surface;
|
||||
gboolean clear_framebuffer;
|
||||
float scale;
|
||||
GdkColorState *target_color_state;
|
||||
|
||||
g_assert (GSK_IS_GL_RENDERER (renderer));
|
||||
g_assert (root != NULL);
|
||||
@@ -384,6 +386,17 @@ gsk_gl_renderer_render (GskRenderer *renderer,
|
||||
gsk_render_node_get_preferred_depth (root),
|
||||
update_area);
|
||||
|
||||
if (gdk_surface_get_gl_is_srgb (surface))
|
||||
{
|
||||
g_debug ("Relying on GL to do srgb-linear->srgb conversion");
|
||||
target_color_state = GDK_COLOR_STATE_SRGB_LINEAR;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_debug ("Using an offscreen for srgb-linear->srgb conversion");
|
||||
target_color_state = GDK_COLOR_STATE_SRGB;
|
||||
}
|
||||
|
||||
gdk_gl_context_make_current (self->context);
|
||||
|
||||
/* Must be called *AFTER* gdk_draw_context_begin_frame() */
|
||||
@@ -392,7 +405,7 @@ gsk_gl_renderer_render (GskRenderer *renderer,
|
||||
|
||||
gsk_gl_driver_begin_frame (self->driver, self->command_queue);
|
||||
job = gsk_gl_render_job_new (self->driver, &viewport, scale, render_region, 0, clear_framebuffer);
|
||||
gsk_gl_render_job_render (job, root);
|
||||
gsk_gl_render_job_render (job, root, target_color_state);
|
||||
gsk_gl_driver_end_frame (self->driver);
|
||||
gsk_gl_render_job_free (job);
|
||||
|
||||
@@ -476,7 +489,7 @@ gsk_gl_renderer_render_texture (GskRenderer *renderer,
|
||||
{
|
||||
gsk_gl_driver_begin_frame (self->driver, self->command_queue);
|
||||
job = gsk_gl_render_job_new (self->driver, viewport, 1, NULL, render_target->framebuffer_id, TRUE);
|
||||
gsk_gl_render_job_render_flipped (job, root);
|
||||
gsk_gl_render_job_render_flipped (job, root, GDK_COLOR_STATE_SRGB);
|
||||
texture_id = gsk_gl_driver_release_render_target (self->driver, render_target, FALSE);
|
||||
texture = gsk_gl_driver_create_gdk_texture (self->driver, texture_id, gdk_format);
|
||||
gsk_gl_driver_end_frame (self->driver);
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <gdk/gdkdmabuftexture.h>
|
||||
#include <gdk/gdksurfaceprivate.h>
|
||||
#include <gdk/gdksubsurfaceprivate.h>
|
||||
#include <gdk/gdkcolorstateprivate.h>
|
||||
#include <gsk/gsktransformprivate.h>
|
||||
#include <gsk/gskroundedrectprivate.h>
|
||||
#include <gsk/gskrectprivate.h>
|
||||
@@ -972,11 +973,28 @@ gsk_gl_render_job_update_clip (GskGLRenderJob *job,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static inline float
|
||||
srgb_inverse_transfer_function (float v)
|
||||
{
|
||||
if (v >= 0.04045)
|
||||
return powf (((v + 0.055)/(1 + 0.055)), 2.4);
|
||||
else
|
||||
return v / 12.92;
|
||||
}
|
||||
|
||||
static inline void
|
||||
rgba_to_half (const GdkRGBA *rgba,
|
||||
guint16 h[4])
|
||||
{
|
||||
float_to_half4 ((const float *)rgba, h);
|
||||
float v[4];
|
||||
|
||||
v[0] = srgb_inverse_transfer_function (rgba->red);
|
||||
v[1] = srgb_inverse_transfer_function (rgba->green);
|
||||
v[2] = srgb_inverse_transfer_function (rgba->blue);
|
||||
v[3] = rgba->alpha;
|
||||
|
||||
float_to_half4 (v, h);
|
||||
}
|
||||
|
||||
/* fill_vertex_data */
|
||||
@@ -3677,8 +3695,11 @@ gsk_gl_render_job_visit_texture (GskGLRenderJob *job,
|
||||
g_assert (offscreen.texture_id);
|
||||
g_assert (offscreen.was_offscreen == FALSE);
|
||||
|
||||
if (gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, blit)))
|
||||
if (gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, colorconvert)))
|
||||
{
|
||||
gsk_gl_program_set_uniform1i (job->current_program,
|
||||
UNIFORM_TO_LINEAR, 0,
|
||||
1);
|
||||
gsk_gl_program_set_uniform_texture_with_sync (job->current_program,
|
||||
UNIFORM_SHARED_SOURCE, 0,
|
||||
GL_TEXTURE_2D,
|
||||
@@ -3704,7 +3725,7 @@ gsk_gl_render_job_visit_texture (GskGLRenderJob *job,
|
||||
g_assert (slices != NULL);
|
||||
g_assert (n_slices > 0);
|
||||
|
||||
if (gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, blit)))
|
||||
if (gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, colorconvert)))
|
||||
{
|
||||
for (unsigned int i = 0; i < n_slices; i++)
|
||||
{
|
||||
@@ -3718,6 +3739,9 @@ gsk_gl_render_job_visit_texture (GskGLRenderJob *job,
|
||||
|
||||
if (i > 0)
|
||||
gsk_gl_render_job_split_draw (job);
|
||||
gsk_gl_program_set_uniform1i (job->current_program,
|
||||
UNIFORM_TO_LINEAR, 0,
|
||||
1);
|
||||
gsk_gl_program_set_uniform_texture_with_filter (job->current_program,
|
||||
UNIFORM_SHARED_SOURCE, 0,
|
||||
GL_TEXTURE_2D,
|
||||
@@ -3832,8 +3856,11 @@ gsk_gl_render_job_visit_texture_scale_node (GskGLRenderJob *job,
|
||||
u1 = (clip_rect.origin.x + clip_rect.size.width - bounds->origin.x) / bounds->size.width;
|
||||
v1 = (clip_rect.origin.y + clip_rect.size.height - bounds->origin.y) / bounds->size.height;
|
||||
|
||||
if (gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, blit)))
|
||||
if (gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, colorconvert)))
|
||||
{
|
||||
gsk_gl_program_set_uniform1i (job->current_program,
|
||||
UNIFORM_TO_LINEAR, 0,
|
||||
1);
|
||||
gsk_gl_program_set_uniform_texture_with_sync (job->current_program,
|
||||
UNIFORM_SHARED_SOURCE, 0,
|
||||
GL_TEXTURE_2D,
|
||||
@@ -3859,7 +3886,7 @@ gsk_gl_render_job_visit_texture_scale_node (GskGLRenderJob *job,
|
||||
|
||||
gsk_gl_driver_slice_texture (job->driver, texture, need_mipmap, &slices, &n_slices);
|
||||
|
||||
if (gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, blit)))
|
||||
if (gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, colorconvert)))
|
||||
{
|
||||
for (guint i = 0; i < n_slices; i++)
|
||||
{
|
||||
@@ -3877,6 +3904,9 @@ gsk_gl_render_job_visit_texture_scale_node (GskGLRenderJob *job,
|
||||
if (i > 0)
|
||||
gsk_gl_render_job_split_draw (job);
|
||||
|
||||
gsk_gl_program_set_uniform1i (job->current_program,
|
||||
UNIFORM_TO_LINEAR, 0,
|
||||
1);
|
||||
gsk_gl_program_set_uniform_texture_with_filter (job->current_program,
|
||||
UNIFORM_SHARED_SOURCE, 0,
|
||||
GL_TEXTURE_2D,
|
||||
@@ -3910,8 +3940,11 @@ gsk_gl_render_job_visit_texture_scale_node (GskGLRenderJob *job,
|
||||
gsk_gl_driver_cache_texture (job->driver, &key, texture_id);
|
||||
|
||||
render_texture:
|
||||
if (gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, blit)))
|
||||
if (gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, colorconvert)))
|
||||
{
|
||||
gsk_gl_program_set_uniform1i (job->current_program,
|
||||
UNIFORM_TO_LINEAR, 0,
|
||||
1);
|
||||
gsk_gl_program_set_uniform_texture (job->current_program,
|
||||
UNIFORM_SHARED_SOURCE, 0,
|
||||
GL_TEXTURE_2D,
|
||||
@@ -4464,7 +4497,8 @@ gsk_gl_render_job_visit_node_with_offscreen (GskGLRenderJob *job,
|
||||
|
||||
void
|
||||
gsk_gl_render_job_render_flipped (GskGLRenderJob *job,
|
||||
GskRenderNode *root)
|
||||
GskRenderNode *root,
|
||||
GdkColorState *target_color_state)
|
||||
{
|
||||
graphene_matrix_t proj;
|
||||
guint framebuffer_id;
|
||||
@@ -4506,8 +4540,17 @@ gsk_gl_render_job_render_flipped (GskGLRenderJob *job,
|
||||
gsk_gl_render_job_set_alpha (job, 1.0f);
|
||||
gsk_gl_command_queue_bind_framebuffer (job->command_queue, job->framebuffer);
|
||||
gsk_gl_command_queue_clear (job->command_queue, 0, &job->viewport);
|
||||
if (gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, blit)))
|
||||
|
||||
GskGLProgram *program;
|
||||
if (target_color_state == GDK_COLOR_STATE_SRGB)
|
||||
program = CHOOSE_PROGRAM (job, colorconvert);
|
||||
else
|
||||
program = CHOOSE_PROGRAM (job, blit);
|
||||
|
||||
if (gsk_gl_render_job_begin_draw (job, program))
|
||||
{
|
||||
if (target_color_state == GDK_COLOR_STATE_SRGB)
|
||||
gsk_gl_program_set_uniform1i (job->current_program, UNIFORM_TO_LINEAR, 0, 0);
|
||||
gsk_gl_program_set_uniform_texture (job->current_program,
|
||||
UNIFORM_SHARED_SOURCE, 0,
|
||||
GL_TEXTURE_2D,
|
||||
@@ -4528,7 +4571,8 @@ gsk_gl_render_job_render_flipped (GskGLRenderJob *job,
|
||||
|
||||
void
|
||||
gsk_gl_render_job_render (GskGLRenderJob *job,
|
||||
GskRenderNode *root)
|
||||
GskRenderNode *root,
|
||||
GdkColorState *target_color_state)
|
||||
{
|
||||
G_GNUC_UNUSED gint64 start_time;
|
||||
float scale;
|
||||
@@ -4551,7 +4595,38 @@ gsk_gl_render_job_render (GskGLRenderJob *job,
|
||||
gsk_gl_command_queue_bind_framebuffer (job->command_queue, job->framebuffer);
|
||||
if (job->clear_framebuffer)
|
||||
gsk_gl_command_queue_clear (job->command_queue, 0, &job->viewport);
|
||||
gsk_gl_render_job_visit_node (job, root);
|
||||
|
||||
if (target_color_state == GDK_COLOR_STATE_SRGB_LINEAR)
|
||||
{
|
||||
gsk_gl_render_job_visit_node (job, root);
|
||||
}
|
||||
else
|
||||
{
|
||||
GskGLRenderOffscreen offscreen = {0};
|
||||
|
||||
offscreen.bounds = &root->bounds;
|
||||
offscreen.force_offscreen = TRUE;
|
||||
offscreen.reset_clip = TRUE;
|
||||
offscreen.do_not_cache = TRUE;
|
||||
|
||||
gsk_gl_render_job_visit_node_with_offscreen (job, root, &offscreen);
|
||||
|
||||
g_assert (offscreen.texture_id);
|
||||
|
||||
if (gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, colorconvert)))
|
||||
{
|
||||
gsk_gl_program_set_uniform1i (job->current_program, UNIFORM_TO_LINEAR, 0, 0);
|
||||
gsk_gl_program_set_uniform_texture (job->current_program,
|
||||
UNIFORM_SHARED_SOURCE, 0,
|
||||
GL_TEXTURE_2D,
|
||||
GL_TEXTURE0,
|
||||
offscreen.texture_id);
|
||||
job->source_is_glyph_atlas = FALSE;
|
||||
gsk_gl_render_job_draw_offscreen_rect (job, &root->bounds);
|
||||
gsk_gl_render_job_end_draw (job);
|
||||
}
|
||||
}
|
||||
|
||||
gdk_gl_context_pop_debug_group (job->command_queue->context);
|
||||
|
||||
gdk_profiler_end_mark (start_time, "Build GL command queue", "");
|
||||
|
||||
@@ -30,7 +30,9 @@ GskGLRenderJob *gsk_gl_render_job_new (GskGLDriver *dri
|
||||
gboolean clear_framebuffer);
|
||||
void gsk_gl_render_job_free (GskGLRenderJob *job);
|
||||
void gsk_gl_render_job_render (GskGLRenderJob *job,
|
||||
GskRenderNode *root);
|
||||
GskRenderNode *root,
|
||||
GdkColorState *color_state);
|
||||
void gsk_gl_render_job_render_flipped (GskGLRenderJob *job,
|
||||
GskRenderNode *root);
|
||||
GskRenderNode *root,
|
||||
GdkColorState *color_state);
|
||||
|
||||
|
||||
63
gsk/gl/resources/colorconvert.glsl
Normal file
63
gsk/gl/resources/colorconvert.glsl
Normal file
@@ -0,0 +1,63 @@
|
||||
// VERTEX_SHADER:
|
||||
// colorconvert.glsl
|
||||
|
||||
void main() {
|
||||
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
|
||||
|
||||
vUv = vec2(aUv.x, aUv.y);
|
||||
}
|
||||
|
||||
// FRAGMENT_SHADER:
|
||||
// colorconvert.glsl
|
||||
|
||||
uniform int u_to_linear;
|
||||
|
||||
float
|
||||
srgb_transfer_function (float v)
|
||||
{
|
||||
if (v >= 0.04045)
|
||||
return pow (((v + 0.055)/(1.0 + 0.055)), 2.4);
|
||||
else
|
||||
return v / 12.92;
|
||||
}
|
||||
|
||||
float
|
||||
srgb_inverse_transfer_function (float v)
|
||||
{
|
||||
if (v > 0.0031308)
|
||||
return 1.055 * pow (v, 1.0/2.4) - 0.055;
|
||||
else
|
||||
return 12.92 * v;
|
||||
}
|
||||
|
||||
vec4
|
||||
srgb_to_linear_srgb (vec4 color)
|
||||
{
|
||||
return vec4 (srgb_transfer_function (color.r),
|
||||
srgb_transfer_function (color.g),
|
||||
srgb_transfer_function (color.b),
|
||||
color.a);
|
||||
}
|
||||
|
||||
vec4
|
||||
linear_srgb_to_srgb (vec4 color)
|
||||
{
|
||||
return vec4 (srgb_inverse_transfer_function (color.r),
|
||||
srgb_inverse_transfer_function (color.g),
|
||||
srgb_inverse_transfer_function (color.b),
|
||||
color.a);
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec4 color = GskTexture(u_source, vUv);
|
||||
|
||||
if (color.a != 0.0)
|
||||
color.rgb /= color.a;
|
||||
|
||||
if (u_to_linear != 0)
|
||||
color = srgb_to_linear_srgb (color);
|
||||
else
|
||||
color = linear_srgb_to_srgb (color);
|
||||
|
||||
gskSetOutputColor(gsk_scaled_premultiply(color, u_alpha));
|
||||
}
|
||||
@@ -4,6 +4,7 @@ gsk_private_gl_shaders = [
|
||||
'gl/resources/preamble.vs.glsl',
|
||||
'gl/resources/border.glsl',
|
||||
'gl/resources/blit.glsl',
|
||||
'gl/resources/colorconvert.glsl',
|
||||
'gl/resources/coloring.glsl',
|
||||
'gl/resources/color.glsl',
|
||||
'gl/resources/linear_gradient.glsl',
|
||||
|
||||
Reference in New Issue
Block a user