Compare commits

...

3 Commits

Author SHA1 Message Date
Emmanuele Bassi
0d01e12acb gsk: Render nodes with solid colors
GskRenderNodes with solid colors should be handled differently than
nodes with texturing data.

The Cairo renderer just emits a rectangle with the color information
stored inside the node; the GL renderer, on the other hand, needs to use
a white texture which gets rendered using a color uniform inside the
fragment shader.
2016-11-17 17:43:24 +00:00
Emmanuele Bassi
cd2c20251e gsk: Allocate a white 1px texture target
This allows us to efficiently render things like solid colors.
2016-11-17 17:43:24 +00:00
Emmanuele Bassi
54fe34f94a gsk: Store a solid color inside GskRenderNode
Some nodes render a solid color, and can be optimized depending on the
rendering operation.
2016-11-17 17:43:24 +00:00
11 changed files with 122 additions and 3 deletions

View File

@@ -100,6 +100,16 @@ gsk_cairo_renderer_render_node (GskCairoRenderer *self,
cairo_paint (cr);
cairo_surface_destroy (surface);
}
else if (gsk_render_node_has_solid_color (node))
{
GdkRGBA color;
gsk_render_node_get_solid_color (node, &color);
cairo_set_source_rgba (cr, color.red, color.green, color.blue, color.alpha);
cairo_rectangle (cr, frame.origin.x, frame.origin.y, frame.size.width, frame.size.height);
cairo_fill (cr);
}
else
{
cairo_set_source_surface (cr, gsk_render_node_get_surface (node), frame.origin.x, frame.origin.y);

View File

@@ -42,6 +42,8 @@ struct _GskGLDriver
Fbo default_fbo;
Texture white_texture;
GHashTable *textures;
GHashTable *vaos;
@@ -219,6 +221,22 @@ gsk_gl_driver_begin_frame (GskGLDriver *driver)
GSK_NOTE (OPENGL, g_print ("GL max texture size: %d\n", driver->max_texture_size));
}
if (driver->white_texture.texture_id == 0)
{
const float white_pixel[4] = { 1, 1, 1, 1, };
glGenTextures (1, &(driver->white_texture.texture_id));
driver->white_texture.width = 1;
driver->white_texture.height = 1;
driver->white_texture.min_filter = GL_NEAREST;
driver->white_texture.mag_filter = GL_NEAREST;
driver->white_texture.in_use = TRUE;
glBindTexture (GL_TEXTURE_2D, driver->white_texture.texture_id);
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_FLOAT, white_pixel);
}
glGetIntegerv (GL_FRAMEBUFFER_BINDING, (GLint *) &(driver->default_fbo.fbo_id));
driver->bound_fbo = &driver->default_fbo;
@@ -848,3 +866,11 @@ gsk_gl_driver_init_texture_with_surface (GskGLDriver *driver,
glBindTexture (GL_TEXTURE_2D, 0);
}
int
gsk_gl_driver_get_white_texture (GskGLDriver *driver)
{
g_return_val_if_fail (GSK_IS_GL_DRIVER (driver), -1);
return driver->white_texture.texture_id;
}

View File

@@ -67,6 +67,8 @@ void gsk_gl_driver_destroy_vao (GskGLDriver *driver
int gsk_gl_driver_collect_textures (GskGLDriver *driver);
int gsk_gl_driver_collect_vaos (GskGLDriver *driver);
int gsk_gl_driver_get_white_texture (GskGLDriver *driver);
G_END_DECLS
#endif /* __GSK_GL_DRIVER_PRIVATE_H__ */

View File

@@ -36,6 +36,7 @@ typedef struct {
int position_location;
int alpha_location;
int blendMode_location;
int color_location;
} RenderData;
typedef struct {
@@ -53,6 +54,8 @@ typedef struct {
float opacity;
float z;
graphene_vec4_t color;
const char *name;
GskBlendMode blend_mode;
@@ -69,6 +72,7 @@ enum {
MASK,
ALPHA,
BLEND_MODE,
COLOR,
N_UNIFORMS
};
@@ -202,7 +206,8 @@ gsk_gl_renderer_create_programs (GskGLRenderer *self)
self->uniforms[MASK] = gsk_shader_builder_add_uniform (builder, "uMask");
self->uniforms[ALPHA] = gsk_shader_builder_add_uniform (builder, "uAlpha");
self->uniforms[BLEND_MODE] = gsk_shader_builder_add_uniform (builder, "uBlendMode");
self->uniforms[COLOR] = gsk_shader_builder_add_uniform (builder, "uColor");
self->attributes[POSITION] = gsk_shader_builder_add_attribute (builder, "aPosition");
self->attributes[UV] = gsk_shader_builder_add_attribute (builder, "aUv");
@@ -402,6 +407,7 @@ render_item (GskGLRenderer *self,
RenderItem *item)
{
float mvp[16];
float color[4];
float opacity;
if (item->children != NULL)
@@ -451,6 +457,12 @@ render_item (GskGLRenderer *self,
graphene_matrix_to_float (&item->mvp, mvp);
glUniformMatrix4fv (item->render_data.mvp_location, 1, GL_FALSE, mvp);
graphene_vec4_to_float (&item->color, color);
glUniform4fv (item->render_data.color_location, 1, color);
GSK_NOTE (OPENGL, g_print ("%*sColor <%g,%g,%g,%g>\n",
2 * node_depth (item->node), "",
color[0], color[1], color[2], color[3]));
/* Draw the quad */
GSK_NOTE2 (OPENGL, TRANSFORMS,
g_print ("%*sDrawing item <%s>[%p] (w:%g, h:%g) with opacity: %g blend mode: %d\n",
@@ -508,6 +520,9 @@ render_item (GskGLRenderer *self,
graphene_matrix_to_float (&item->mvp, mvp);
glUniformMatrix4fv (item->render_data.mvp_location, 1, GL_FALSE, mvp);
graphene_vec4_to_float (&item->color, color);
glUniform4fv (item->render_data.color_location, 1, color);
/* Draw the quad */
GSK_NOTE2 (OPENGL, TRANSFORMS,
g_print ("%*sDrawing offscreen item <%s>[%p] (w:%g, h:%g) with opacity: %g\n",
@@ -685,6 +700,8 @@ gsk_gl_renderer_add_render_item (GskGLRenderer *self,
gsk_shader_builder_get_uniform_location (self->shader_builder, program_id, self->uniforms[ALPHA]);
item.render_data.blendMode_location =
gsk_shader_builder_get_uniform_location (self->shader_builder, program_id, self->uniforms[BLEND_MODE]);
item.render_data.color_location =
gsk_shader_builder_get_uniform_location (self->shader_builder, program_id, self->uniforms[COLOR]);
item.render_data.position_location =
gsk_shader_builder_get_attribute_location (self->shader_builder, program_id, self->attributes[POSITION]);
@@ -707,7 +724,19 @@ gsk_gl_renderer_add_render_item (GskGLRenderer *self,
item.children = NULL;
}
if (gsk_render_node_has_texture (node))
if (gsk_render_node_has_solid_color (node))
{
GdkRGBA color;
gsk_render_node_get_solid_color (node, &color);
color.red = color.red * color.alpha;
color.green = color.green * color.alpha;
color.blue = color.blue * color.alpha;
item.render_data.texture_id = gsk_gl_driver_get_white_texture (self->gl_driver);
graphene_vec4_init (&item.color, color.red, color.green, color.blue, color.alpha);
}
else if (gsk_render_node_has_texture (node))
{
GskTexture *texture = gsk_render_node_get_texture (node);
int gl_min_filter = GL_NEAREST, gl_mag_filter = GL_NEAREST;
@@ -718,6 +747,7 @@ gsk_gl_renderer_add_render_item (GskGLRenderer *self,
texture,
gl_min_filter,
gl_mag_filter);
graphene_vec4_init_from_vec4 (&item.color, graphene_vec4_one ());
}
else if (gsk_render_node_has_surface (node))
{
@@ -736,6 +766,8 @@ gsk_gl_renderer_add_render_item (GskGLRenderer *self,
surface,
gl_min_filter,
gl_mag_filter);
graphene_vec4_init_from_vec4 (&item.color, graphene_vec4_one ());
}
else
{

View File

@@ -1228,6 +1228,14 @@ gsk_render_node_has_texture (GskRenderNode *node)
return node->texture != NULL;
}
gboolean
gsk_render_node_has_solid_color (GskRenderNode *node)
{
g_return_val_if_fail (GSK_IS_RENDER_NODE (node), FALSE);
return node->solid_color_set;
}
GskTexture *
gsk_render_node_get_texture (GskRenderNode *node)
{
@@ -1236,6 +1244,15 @@ gsk_render_node_get_texture (GskRenderNode *node)
return node->texture;
}
void
gsk_render_node_get_solid_color (GskRenderNode *node,
GdkRGBA *color)
{
g_return_if_fail (GSK_IS_RENDER_NODE (node));
*color = node->solid_color;
}
/**
* gsk_render_node_set_texture:
* @node: a #GskRenderNode
@@ -1263,6 +1280,24 @@ gsk_render_node_set_texture (GskRenderNode *node,
gsk_texture_ref (texture);
}
void
gsk_render_node_set_solid_color (GskRenderNode *node,
const GdkRGBA *color)
{
g_return_if_fail (GSK_IS_RENDER_NODE (node));
if (color != NULL)
{
if (gdk_rgba_equal (color, &node->solid_color))
return;
node->solid_color = *color;
node->solid_color_set = TRUE;
}
else
node->solid_color_set = FALSE;
}
/*< private >
* gsk_render_node_get_surface:
* @node: a #GskRenderNode

View File

@@ -125,6 +125,10 @@ void gsk_render_node_set_scaling_filter (GskRenderNode *
GskScalingFilter min_filter,
GskScalingFilter mag_filter);
GDK_AVAILABLE_IN_3_90
void gsk_render_node_set_solid_color (GskRenderNode *node,
const GdkRGBA *color);
GDK_AVAILABLE_IN_3_90
void gsk_render_node_set_name (GskRenderNode *node,
const char *name);

View File

@@ -37,6 +37,8 @@ struct _GskRenderNode
/* The contents of the node as a texture */
GskTexture *texture;
GdkRGBA solid_color;
/* Paint opacity */
double opacity;
@@ -63,6 +65,7 @@ struct _GskRenderNode
gboolean hidden : 1;
gboolean opaque : 1;
gboolean transform_set : 1;
gboolean solid_color_set : 1;
gboolean needs_world_matrix_update : 1;
};
@@ -87,8 +90,12 @@ cairo_surface_t *gsk_render_node_get_surface (GskRenderNode *node);
GskTexture *gsk_render_node_get_texture (GskRenderNode *node);
void gsk_render_node_get_solid_color (GskRenderNode *node,
GdkRGBA *color);
gboolean gsk_render_node_has_surface (GskRenderNode *node);
gboolean gsk_render_node_has_texture (GskRenderNode *node);
gboolean gsk_render_node_has_solid_color (GskRenderNode *node);
GskBlendMode gsk_render_node_get_blend_mode (GskRenderNode *node);

View File

@@ -1,5 +1,5 @@
void main() {
vec4 diffuse = Texture(uSource, vUv);
vec4 diffuse = Texture(uSource, vUv) * uColor;
setOutputColor(vec4(diffuse.xyz, diffuse.a * uAlpha));
}

View File

@@ -5,6 +5,7 @@ uniform sampler2D uSource;
uniform sampler2D uMask;
uniform float uAlpha;
uniform int uBlendMode;
uniform vec4 uColor;
varying vec2 vUv;

View File

@@ -5,6 +5,7 @@ uniform sampler2D uMask;
uniform mat4 uMVP;
uniform float uAlpha;
uniform int uBlendMode;
uniform vec4 uColor;
in vec2 vUv;

View File

@@ -3,6 +3,7 @@ uniform sampler2D uSource;
uniform sampler2D uMask;
uniform float uAlpha;
uniform int uBlendMode;
uniform vec4 uColor;
varying vec2 vUv;