diff --git a/gsk/meson.build b/gsk/meson.build index 8f9a6281c0..8e2b0f1782 100644 --- a/gsk/meson.build +++ b/gsk/meson.build @@ -40,6 +40,7 @@ gsk_private_ngl_shaders = [ 'ngl/resources/blend.glsl', 'ngl/resources/repeat.glsl', 'ngl/resources/custom.glsl', + 'ngl/resources/filled_border.glsl', ] gsk_public_sources = files([ diff --git a/gsk/ngl/gsknglcommandqueue.c b/gsk/ngl/gsknglcommandqueue.c index aff201cb4a..bebd315823 100644 --- a/gsk/ngl/gsknglcommandqueue.c +++ b/gsk/ngl/gsknglcommandqueue.c @@ -1010,6 +1010,12 @@ gsk_ngl_command_queue_execute (GskNglCommandQueue *self, sizeof (GskNglDrawVertex), (void *) G_STRUCT_OFFSET (GskNglDrawVertex, color)); + /* 3 = color2 location */ + glEnableVertexAttribArray (3); + glVertexAttribPointer (3, 4, GL_FLOAT, GL_FALSE, + sizeof (GskNglDrawVertex), + (void *) G_STRUCT_OFFSET (GskNglDrawVertex, color2)); + /* Setup initial scissor clip */ if (scissor != NULL) { diff --git a/gsk/ngl/gskngldriver.c b/gsk/ngl/gskngldriver.c index 3d910e5d51..93763dbb12 100644 --- a/gsk/ngl/gskngldriver.c +++ b/gsk/ngl/gskngldriver.c @@ -348,6 +348,7 @@ gsk_ngl_driver_load_programs (GskNglDriver *self, gsk_ngl_compiler_bind_attribute (compiler, "aPosition", 0); gsk_ngl_compiler_bind_attribute (compiler, "aUv", 1); gsk_ngl_compiler_bind_attribute (compiler, "aColor", 2); + gsk_ngl_compiler_bind_attribute (compiler, "aColor2", 3); /* Use XMacros to register all of our programs and their uniforms */ #define GSK_NGL_NO_UNIFORMS @@ -1046,6 +1047,7 @@ gsk_ngl_driver_lookup_shader (GskNglDriver *self, gsk_ngl_compiler_bind_attribute (compiler, "aPosition", 0); gsk_ngl_compiler_bind_attribute (compiler, "aUv", 1); gsk_ngl_compiler_bind_attribute (compiler, "aColor", 2); + gsk_ngl_compiler_bind_attribute (compiler, "aColor2", 3); if ((program = gsk_ngl_compiler_compile (compiler, NULL, "", error))) { diff --git a/gsk/ngl/gsknglprograms.defs b/gsk/ngl/gsknglprograms.defs index e20cca2fa9..f4f4a0dfe5 100644 --- a/gsk/ngl/gsknglprograms.defs +++ b/gsk/ngl/gsknglprograms.defs @@ -15,8 +15,8 @@ GSK_NGL_DEFINE_PROGRAM (blur, GSK_NGL_DEFINE_PROGRAM (border, "/org/gtk/libgsk/ngl/border.glsl", - GSK_NGL_ADD_UNIFORM (2, BORDER_WIDTHS, u_widths) - GSK_NGL_ADD_UNIFORM (3, BORDER_OUTLINE_RECT, u_outline_rect)) + GSK_NGL_ADD_UNIFORM (1, BORDER_WIDTHS, u_widths) + GSK_NGL_ADD_UNIFORM (2, BORDER_OUTLINE_RECT, u_outline_rect)) GSK_NGL_DEFINE_PROGRAM (color, "/org/gtk/libgsk/ngl/color.glsl", @@ -42,11 +42,16 @@ GSK_NGL_DEFINE_PROGRAM (cross_fade, GSK_NGL_ADD_UNIFORM (1, CROSS_FADE_PROGRESS, u_progress) GSK_NGL_ADD_UNIFORM (2, CROSS_FADE_SOURCE2, u_source2)) +GSK_NGL_DEFINE_PROGRAM (filled_border, + "/org/gtk/libgsk/ngl/filled_border.glsl", + GSK_NGL_ADD_UNIFORM (1, FILLED_BORDER_WIDTHS, u_widths) + GSK_NGL_ADD_UNIFORM (2, FILLED_BORDER_OUTLINE_RECT, u_outline_rect)) + GSK_NGL_DEFINE_PROGRAM (inset_shadow, "/org/gtk/libgsk/ngl/inset_shadow.glsl", - GSK_NGL_ADD_UNIFORM (2, INSET_SHADOW_SPREAD, u_spread) - GSK_NGL_ADD_UNIFORM (3, INSET_SHADOW_OFFSET, u_offset) - GSK_NGL_ADD_UNIFORM (4, INSET_SHADOW_OUTLINE_RECT, u_outline_rect)) + GSK_NGL_ADD_UNIFORM (1, INSET_SHADOW_SPREAD, u_spread) + GSK_NGL_ADD_UNIFORM (2, INSET_SHADOW_OFFSET, u_offset) + GSK_NGL_ADD_UNIFORM (3, INSET_SHADOW_OUTLINE_RECT, u_outline_rect)) GSK_NGL_DEFINE_PROGRAM (linear_gradient, "/org/gtk/libgsk/ngl/linear_gradient.glsl", @@ -57,7 +62,7 @@ GSK_NGL_DEFINE_PROGRAM (linear_gradient, GSK_NGL_DEFINE_PROGRAM (outset_shadow, "/org/gtk/libgsk/ngl/outset_shadow.glsl", - GSK_NGL_ADD_UNIFORM (2, OUTSET_SHADOW_OUTLINE_RECT, u_outline_rect)) + GSK_NGL_ADD_UNIFORM (1, OUTSET_SHADOW_OUTLINE_RECT, u_outline_rect)) GSK_NGL_DEFINE_PROGRAM (radial_gradient, "/org/gtk/libgsk/ngl/radial_gradient.glsl", @@ -74,6 +79,6 @@ GSK_NGL_DEFINE_PROGRAM (repeat, GSK_NGL_DEFINE_PROGRAM (unblurred_outset_shadow, "/org/gtk/libgsk/ngl/unblurred_outset_shadow.glsl", - GSK_NGL_ADD_UNIFORM (2, UNBLURRED_OUTSET_SHADOW_SPREAD, u_spread) - GSK_NGL_ADD_UNIFORM (3, UNBLURRED_OUTSET_SHADOW_OFFSET, u_offset) - GSK_NGL_ADD_UNIFORM (4, UNBLURRED_OUTSET_SHADOW_OUTLINE_RECT, u_outline_rect)) + 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)) diff --git a/gsk/ngl/gsknglrenderjob.c b/gsk/ngl/gsknglrenderjob.c index 8f67575564..dc7935b699 100644 --- a/gsk/ngl/gsknglrenderjob.c +++ b/gsk/ngl/gsknglrenderjob.c @@ -142,9 +142,6 @@ struct _GskNglRenderJob /* Our current alpha state as we process nodes */ float alpha; - /* Our current color state as we process nodes */ - GdkRGBA color; - /* Offset (delta x,y) as we process nodes. Occasionally this is merged into * a transform that is referenced from child transform nodes. */ @@ -398,13 +395,6 @@ gsk_ngl_render_job_set_alpha (GskNglRenderJob *job, return alpha; } -static inline void -gsk_ngl_render_job_set_color (GskNglRenderJob *job, - const GdkRGBA *color) -{ - job->color = *color; -} - static void extract_matrix_metadata (GskNglRenderModelview *modelview) { @@ -894,70 +884,25 @@ gsk_ngl_render_job_draw_coords (GskNglRenderJob *job, float min_u, float min_v, float max_u, - float max_v) + float max_v, + const GdkRGBA *color) { GskNglDrawVertex *vertices = gsk_ngl_command_queue_add_vertices (job->command_queue); - vertices[0].position[0] = min_x; - vertices[0].position[1] = min_y; - vertices[0].uv[0] = min_u; - vertices[0].uv[1] = min_v; - vertices[0].color[0] = job->color.red; - vertices[0].color[1] = job->color.green; - vertices[0].color[2] = job->color.blue; - vertices[0].color[3] = job->color.alpha; - - vertices[1].position[0] = min_x; - vertices[1].position[1] = max_y; - vertices[1].uv[0] = min_u; - vertices[1].uv[1] = max_v; - vertices[1].color[0] = job->color.red; - vertices[1].color[1] = job->color.green; - vertices[1].color[2] = job->color.blue; - vertices[1].color[3] = job->color.alpha; - - vertices[2].position[0] = max_x; - vertices[2].position[1] = min_y; - vertices[2].uv[0] = max_u; - vertices[2].uv[1] = min_v; - vertices[2].color[0] = job->color.red; - vertices[2].color[1] = job->color.green; - vertices[2].color[2] = job->color.blue; - vertices[2].color[3] = job->color.alpha; - - vertices[3].position[0] = max_x; - vertices[3].position[1] = max_y; - vertices[3].uv[0] = max_u; - vertices[3].uv[1] = max_v; - vertices[3].color[0] = job->color.red; - vertices[3].color[1] = job->color.green; - vertices[3].color[2] = job->color.blue; - vertices[3].color[3] = job->color.alpha; - - vertices[4].position[0] = min_x; - vertices[4].position[1] = max_y; - vertices[4].uv[0] = min_u; - vertices[4].uv[1] = max_v; - vertices[4].color[0] = job->color.red; - vertices[4].color[1] = job->color.green; - vertices[4].color[2] = job->color.blue; - vertices[4].color[3] = job->color.alpha; - - vertices[5].position[0] = max_x; - vertices[5].position[1] = min_y; - vertices[5].uv[0] = max_u; - vertices[5].uv[1] = min_v; - vertices[5].color[0] = job->color.red; - vertices[5].color[1] = job->color.green; - vertices[5].color[2] = job->color.blue; - vertices[5].color[3] = job->color.alpha; + vertices[0] = (GskNglDrawVertex) { { min_x, min_y }, { min_u, min_v }, { color->red, color->green, color->blue, color->alpha } }; + vertices[1] = (GskNglDrawVertex) { { min_x, max_y }, { min_u, max_v }, { color->red, color->green, color->blue, color->alpha } }; + vertices[2] = (GskNglDrawVertex) { { max_x, min_y }, { max_u, min_v }, { color->red, color->green, color->blue, color->alpha } }; + vertices[3] = (GskNglDrawVertex) { { max_x, max_y }, { max_u, max_v }, { color->red, color->green, color->blue, color->alpha } }; + vertices[4] = (GskNglDrawVertex) { { min_x, max_y }, { min_u, max_v }, { color->red, color->green, color->blue, color->alpha } }; + vertices[5] = (GskNglDrawVertex) { { max_x, min_y }, { max_u, min_v }, { color->red, color->green, color->blue, color->alpha } }; } /* load_vertex_data_with_region */ static inline void -gsk_ngl_render_job_load_vertices_from_offscreen (GskNglRenderJob *job, - const graphene_rect_t *bounds, - const GskNglRenderOffscreen *offscreen) +gsk_ngl_render_job_draw_offscreen_with_color (GskNglRenderJob *job, + const graphene_rect_t *bounds, + const GskNglRenderOffscreen *offscreen, + const GdkRGBA *color) { float min_x = job->offset_x + bounds->origin.x; float min_y = job->offset_y + bounds->origin.y; @@ -968,10 +913,35 @@ gsk_ngl_render_job_load_vertices_from_offscreen (GskNglRenderJob *jo gsk_ngl_render_job_draw_coords (job, min_x, min_y, max_x, max_y, - offscreen->area.x, y1, offscreen->area.x2, y2); + offscreen->area.x, y1, offscreen->area.x2, y2, + color); +} + +static inline void +gsk_ngl_render_job_draw_offscreen (GskNglRenderJob *job, + const graphene_rect_t *bounds, + const GskNglRenderOffscreen *offscreen) +{ + gsk_ngl_render_job_draw_offscreen_with_color (job, bounds, offscreen, &(GdkRGBA) { 0.f, 0.f, 0.f, 0.f }); } /* load_float_vertex_data */ +static inline void +gsk_ngl_render_job_draw_with_color (GskNglRenderJob *job, + float x, + float y, + float width, + float height, + const GdkRGBA *color) +{ + float min_x = job->offset_x + x; + float min_y = job->offset_y + y; + float max_x = min_x + width; + float max_y = min_y + height; + + gsk_ngl_render_job_draw_coords (job, min_x, min_y, max_x, max_y, 0, 0, 1, 1, color); +} + static inline void gsk_ngl_render_job_draw (GskNglRenderJob *job, float x, @@ -979,16 +949,23 @@ gsk_ngl_render_job_draw (GskNglRenderJob *job, float width, float height) { - float min_x = job->offset_x + x; - float min_y = job->offset_y + y; - float max_x = min_x + width; - float max_y = min_y + height; - - gsk_ngl_render_job_draw_coords (job, min_x, min_y, max_x, max_y, 0, 0, 1, 1); + gsk_ngl_render_job_draw_with_color (job, x, y, width, height, &(GdkRGBA) { 0.f, 0.f, 0.f, 0.f }); } /* load_vertex_data */ static inline void +gsk_ngl_render_job_draw_rect_with_color (GskNglRenderJob *job, + const graphene_rect_t *bounds, + const GdkRGBA *color) +{ + gsk_ngl_render_job_draw_with_color (job, + bounds->origin.x, + bounds->origin.y, + bounds->size.width, + bounds->size.height, + color); +} +static inline void gsk_ngl_render_job_draw_rect (GskNglRenderJob *job, const graphene_rect_t *bounds) { @@ -1009,7 +986,10 @@ gsk_ngl_render_job_draw_offscreen_rect (GskNglRenderJob *job, float max_x = min_x + bounds->size.width; float max_y = min_y + bounds->size.height; - gsk_ngl_render_job_draw_coords (job, min_x, min_y, max_x, max_y, 0, 1, 1, 0); + gsk_ngl_render_job_draw_coords (job, + min_x, min_y, max_x, max_y, + 0, 1, 1, 0, + &(GdkRGBA) { 0.f, 0.f, 0.f, 0.f } ); } static inline void @@ -1265,7 +1245,10 @@ blur_offscreen (GskNglRenderJob *job, gsk_ngl_program_set_uniform2f (job->current_program, UNIFORM_BLUR_DIR, 0, 1, 0); - gsk_ngl_render_job_draw_coords (job, 0, 0, texture_to_blur_width, texture_to_blur_height, 0, 1, 1, 0); + gsk_ngl_render_job_draw_coords (job, + 0, 0, texture_to_blur_width, texture_to_blur_height, + 0, 1, 1, 0, + &(GdkRGBA) { 0.f, 0.f, 0.f, 0.f }); gsk_ngl_render_job_end_draw (job); /* Bind second pass framebuffer and clear it */ @@ -1289,7 +1272,10 @@ blur_offscreen (GskNglRenderJob *job, gsk_ngl_program_set_uniform2f (job->current_program, UNIFORM_BLUR_DIR, 0, 0, 1); - gsk_ngl_render_job_draw_coords (job, 0, 0, texture_to_blur_width, texture_to_blur_height, 0, 1, 1, 0); + gsk_ngl_render_job_draw_coords (job, + 0, 0, texture_to_blur_width, texture_to_blur_height, + 0, 1, 1, 0, + &(GdkRGBA) { 0.f, 0.f, 0.f, 0.f }); gsk_ngl_render_job_end_draw (job); gsk_ngl_render_job_pop_modelview (job); @@ -1363,8 +1349,9 @@ gsk_ngl_render_job_visit_color_node (GskNglRenderJob *job, const GskRenderNode *node) { gsk_ngl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, color)); - gsk_ngl_render_job_set_color (job, gsk_color_node_get_color (node)); - gsk_ngl_render_job_draw_rect (job, &node->bounds); + gsk_ngl_render_job_draw_rect_with_color (job, + &node->bounds, + gsk_color_node_get_color (node)); gsk_ngl_render_job_end_draw (job); } @@ -1627,7 +1614,7 @@ gsk_ngl_render_job_visit_rounded_clip_node (GskNglRenderJob *job, GL_TEXTURE_2D, GL_TEXTURE0, offscreen.texture_id); - gsk_ngl_render_job_load_vertices_from_offscreen (job, &node->bounds, &offscreen); + gsk_ngl_render_job_draw_offscreen (job, &node->bounds, &offscreen); gsk_ngl_render_job_end_draw (job); } } @@ -1674,58 +1661,26 @@ gsk_ngl_render_job_visit_rect_border_node (GskNglRenderJob *job, gsk_ngl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, color)); - gsk_ngl_render_job_set_color (job, &colors[0]); + if (widths[0] > 0) + gsk_ngl_render_job_draw_rect_with_color (job, + &GRAPHENE_RECT_INIT (origin->x, origin->y, size->width - widths[1], widths[0]), + &colors[0]); - gsk_ngl_render_job_draw_rect (job, - &GRAPHENE_RECT_INIT (origin->x, - origin->y, - size->width - widths[1], - widths[0])); + if (widths[1] > 0) + gsk_ngl_render_job_draw_rect_with_color (job, + &GRAPHENE_RECT_INIT (origin->x + size->width - widths[1], origin->y, widths[1], size->height - widths[2]), + &colors[0]); - gsk_ngl_render_job_draw_rect (job, - &GRAPHENE_RECT_INIT (origin->x + size->width - widths[1], - origin->y, - widths[1], - size->height - widths[2])); + if (widths[2] > 0) + gsk_ngl_render_job_draw_rect_with_color (job, + &GRAPHENE_RECT_INIT (origin->x + widths[3], origin->y + size->height - widths[2], size->width - widths[1], widths[2]), + &colors[0]); - gsk_ngl_render_job_draw_rect (job, - &GRAPHENE_RECT_INIT (origin->x + widths[3], - origin->y + size->height - widths[2], - size->width - widths[1], - widths[2])); + if (widths[3] > 0) + gsk_ngl_render_job_draw_rect_with_color (job, + &GRAPHENE_RECT_INIT (origin->x, origin->y + widths[0], widths[3], size->height - widths[0]), + &colors[0]); - gsk_ngl_render_job_draw_rect (job, - &GRAPHENE_RECT_INIT (origin->x, - origin->y + widths[0], - widths[3], - size->height - widths[0])); - - gsk_ngl_render_job_end_draw (job); -} - -static inline void -gsk_ngl_render_job_visit_uniform_border_node (GskNglRenderJob *job, - const GskRenderNode *node) -{ - const GskRoundedRect *rounded_outline = gsk_border_node_get_outline (node); - const GdkRGBA *colors = gsk_border_node_get_colors (node); - const float *widths = gsk_border_node_get_widths (node); - GskRoundedRect outline; - - gsk_ngl_render_job_transform_rounded_rect (job, rounded_outline, &outline); - - gsk_ngl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, inset_shadow)); - gsk_ngl_render_job_set_color (job, &colors[0]); - gsk_ngl_program_set_uniform_rounded_rect (job->current_program, - UNIFORM_INSET_SHADOW_OUTLINE_RECT, 0, - &outline); - gsk_ngl_program_set_uniform1f (job->current_program, - UNIFORM_INSET_SHADOW_SPREAD, 0, - widths[0]); - gsk_ngl_program_set_uniform2f (job->current_program, - UNIFORM_INSET_SHADOW_OFFSET, 0, - 0, 0); - gsk_ngl_render_job_draw_rect (job, &node->bounds); gsk_ngl_render_job_end_draw (job); } @@ -1740,128 +1695,153 @@ gsk_ngl_render_job_visit_border_node (GskNglRenderJob *job, float w; float h; } sizes[4]; + float min_x = job->offset_x + node->bounds.origin.x; + float min_y = job->offset_y + node->bounds.origin.y; + float max_x = min_x + node->bounds.size.width; + float max_y = min_y + node->bounds.size.height; + GskRoundedRect outline; - /* Top left */ - if (widths[3] > 0) - sizes[0].w = MAX (widths[3], rounded_outline->corner[0].width); - else - sizes[0].w = 0; + memset (sizes, 0, sizeof sizes); if (widths[0] > 0) - sizes[0].h = MAX (widths[0], rounded_outline->corner[0].height); - else - sizes[0].h = 0; + { + sizes[0].h = MAX (widths[0], rounded_outline->corner[0].height); + sizes[1].h = MAX (widths[0], rounded_outline->corner[1].height); + } - /* Top right */ if (widths[1] > 0) - sizes[1].w = MAX (widths[1], rounded_outline->corner[1].width); - else - sizes[1].w = 0; + { + sizes[1].w = MAX (widths[1], rounded_outline->corner[1].width); + sizes[2].w = MAX (widths[1], rounded_outline->corner[2].width); + } + + if (widths[2] > 0) + { + sizes[2].h = MAX (widths[2], rounded_outline->corner[2].height); + sizes[3].h = MAX (widths[2], rounded_outline->corner[3].height); + } + + if (widths[3] > 0) + { + sizes[0].w = MAX (widths[3], rounded_outline->corner[0].width); + sizes[3].w = MAX (widths[3], rounded_outline->corner[3].width); + } + + gsk_ngl_render_job_transform_rounded_rect (job, rounded_outline, &outline); + + gsk_ngl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, border)); + + gsk_ngl_program_set_uniform4fv (job->current_program, + UNIFORM_BORDER_WIDTHS, 0, + 1, + widths); + gsk_ngl_program_set_uniform_rounded_rect (job->current_program, + UNIFORM_BORDER_OUTLINE_RECT, 0, + &outline); if (widths[0] > 0) - sizes[1].h = MAX (widths[0], rounded_outline->corner[1].height); - else - sizes[1].h = 0; + { + GskNglDrawVertex *vertices = gsk_ngl_command_queue_add_vertices (job->command_queue); + + vertices[0] = (GskNglDrawVertex) { { min_x, min_y }, { 0, 1 }, { c[0].red, c[0].green, c[0].blue, c[0].alpha } }; + vertices[1] = (GskNglDrawVertex) { { min_x + sizes[0].w, min_y + sizes[0].h }, { 0, 0 }, { c[0].red, c[0].green, c[0].blue, c[0].alpha } }; + vertices[2] = (GskNglDrawVertex) { { max_x, min_y }, { 1, 1 }, { c[0].red, c[0].green, c[0].blue, c[0].alpha } }; + + vertices[3] = (GskNglDrawVertex) { { max_x - sizes[1].w, min_y + sizes[1].h }, { 1, 0 }, { c[0].red, c[0].green, c[0].blue, c[0].alpha } }; + vertices[4] = (GskNglDrawVertex) { { min_x + sizes[0].w, min_y + sizes[0].h }, { 0, 0 }, { c[0].red, c[0].green, c[0].blue, c[0].alpha } }; + vertices[5] = (GskNglDrawVertex) { { max_x, min_y }, { 1, 1 }, { c[0].red, c[0].green, c[0].blue, c[0].alpha } }; + } - /* Bottom right */ if (widths[1] > 0) - sizes[2].w = MAX (widths[1], rounded_outline->corner[2].width); - else - sizes[2].w = 0; + { + GskNglDrawVertex *vertices = gsk_ngl_command_queue_add_vertices (job->command_queue); + + vertices[0] = (GskNglDrawVertex) { { max_x - sizes[1].w, min_y + sizes[1].h }, { 0, 1 }, { c[1].red, c[1].green, c[1].blue, c[1].alpha } }; + vertices[1] = (GskNglDrawVertex) { { max_x - sizes[2].w, max_y - sizes[2].h }, { 0, 0 }, { c[1].red, c[1].green, c[1].blue, c[1].alpha } }; + vertices[2] = (GskNglDrawVertex) { { max_x, min_y }, { 1, 1 }, { c[1].red, c[1].green, c[1].blue, c[1].alpha } }; + + vertices[3] = (GskNglDrawVertex) { { max_x, max_y }, { 1, 0 }, { c[1].red, c[1].green, c[1].blue, c[1].alpha } }; + vertices[4] = (GskNglDrawVertex) { { max_x - sizes[2].w, max_y - sizes[2].h }, { 0, 0 }, { c[1].red, c[1].green, c[1].blue, c[1].alpha } }; + vertices[5] = (GskNglDrawVertex) { { max_x, min_y }, { 1, 1 }, { c[1].red, c[1].green, c[1].blue, c[1].alpha } }; + } if (widths[2] > 0) - sizes[2].h = MAX (widths[2], rounded_outline->corner[2].height); - else - sizes[2].h = 0; + { + GskNglDrawVertex *vertices = gsk_ngl_command_queue_add_vertices (job->command_queue); + vertices[0] = (GskNglDrawVertex) { { min_x + sizes[3].w, max_y - sizes[3].h }, { 0, 1 }, { c[2].red, c[2].green, c[2].blue, c[2].alpha } }; + vertices[1] = (GskNglDrawVertex) { { min_x, max_y }, { 0, 0 }, { c[2].red, c[2].green, c[2].blue, c[2].alpha } }; + vertices[2] = (GskNglDrawVertex) { { max_x - sizes[2].w, max_y - sizes[2].h }, { 1, 1 }, { c[2].red, c[2].green, c[2].blue, c[2].alpha } }; + + vertices[3] = (GskNglDrawVertex) { { max_x, max_y }, { 1, 0 }, { c[2].red, c[2].green, c[2].blue, c[2].alpha } }; + vertices[4] = (GskNglDrawVertex) { { min_x , max_y }, { 0, 0 }, { c[2].red, c[2].green, c[2].blue, c[2].alpha } }; + vertices[5] = (GskNglDrawVertex) { { max_x - sizes[2].w, max_y - sizes[2].h }, { 1, 1 }, { c[2].red, c[2].green, c[2].blue, c[2].alpha } }; + } - /* Bottom left */ if (widths[3] > 0) - sizes[3].w = MAX (widths[3], rounded_outline->corner[3].width); - else - sizes[3].w = 0; + { + GskNglDrawVertex *vertices = gsk_ngl_command_queue_add_vertices (job->command_queue); - if (widths[2] > 0) - sizes[3].h = MAX (widths[2], rounded_outline->corner[3].height); - else - sizes[3].h = 0; + vertices[0] = (GskNglDrawVertex) { { min_x, min_y }, { 0, 1 }, { c[3].red, c[3].green, c[3].blue, c[3].alpha } }; + vertices[1] = (GskNglDrawVertex) { { min_x, max_y }, { 0, 0 }, { c[3].red, c[3].green, c[3].blue, c[3].alpha } }; + vertices[2] = (GskNglDrawVertex) { { min_x + sizes[0].w, min_y + sizes[0].h }, { 1, 1 }, { c[3].red, c[3].green, c[3].blue, c[3].alpha } }; - { - float min_x = job->offset_x + node->bounds.origin.x; - float min_y = job->offset_y + node->bounds.origin.y; - float max_x = min_x + node->bounds.size.width; - float max_y = min_y + node->bounds.size.height; - const GskNglDrawVertex side_data[4][6] = { - /* Top */ - { - { { min_x, min_y }, { 0, 1 }, { c[0].red, c[0].green, c[0].blue, c[0].alpha } }, /* Upper left */ - { { min_x + sizes[0].w, min_y + sizes[0].h }, { 0, 0 }, { c[0].red, c[0].green, c[0].blue, c[0].alpha } }, /* Lower left */ - { { max_x, min_y }, { 1, 1 }, { c[0].red, c[0].green, c[0].blue, c[0].alpha } }, /* Upper right */ + vertices[3] = (GskNglDrawVertex) { { min_x + sizes[3].w, max_y - sizes[3].h }, { 1, 0 }, { c[3].red, c[3].green, c[3].blue, c[3].alpha } }; + vertices[4] = (GskNglDrawVertex) { { min_x, max_y }, { 0, 0 }, { c[3].red, c[3].green, c[3].blue, c[3].alpha } }; + vertices[5] = (GskNglDrawVertex) { { min_x + sizes[0].w, min_y + sizes[0].h }, { 1, 1 }, { c[3].red, c[3].green, c[3].blue, c[3].alpha } }; + } - { { max_x - sizes[1].w, min_y + sizes[1].h }, { 1, 0 }, { c[0].red, c[0].green, c[0].blue, c[0].alpha } }, /* Lower right */ - { { min_x + sizes[0].w, min_y + sizes[0].h }, { 0, 0 }, { c[0].red, c[0].green, c[0].blue, c[0].alpha } }, /* Lower left */ - { { max_x, min_y }, { 1, 1 }, { c[0].red, c[0].green, c[0].blue, c[0].alpha } }, /* Upper right */ - }, - /* Right */ - { - { { max_x - sizes[1].w, min_y + sizes[1].h }, { 0, 1 }, { c[1].red, c[1].green, c[1].blue, c[1].alpha } }, /* Upper left */ - { { max_x - sizes[2].w, max_y - sizes[2].h }, { 0, 0 }, { c[1].red, c[1].green, c[1].blue, c[1].alpha } }, /* Lower left */ - { { max_x, min_y }, { 1, 1 }, { c[1].red, c[1].green, c[1].blue, c[1].alpha } }, /* Upper right */ + gsk_ngl_render_job_end_draw (job); +} - { { max_x, max_y }, { 1, 0 }, { c[1].red, c[1].green, c[1].blue, c[1].alpha } }, /* Lower right */ - { { max_x - sizes[2].w, max_y - sizes[2].h }, { 0, 0 }, { c[1].red, c[1].green, c[1].blue, c[1].alpha } }, /* Lower left */ - { { max_x, min_y }, { 1, 1 }, { c[1].red, c[1].green, c[1].blue, c[1].alpha } }, /* Upper right */ - }, - /* Bottom */ - { - { { min_x + sizes[3].w, max_y - sizes[3].h }, { 0, 1 }, { c[2].red, c[2].green, c[2].blue, c[2].alpha } }, /* Upper left */ - { { min_x, max_y }, { 0, 0 }, { c[2].red, c[2].green, c[2].blue, c[2].alpha } }, /* Lower left */ - { { max_x - sizes[2].w, max_y - sizes[2].h }, { 1, 1 }, { c[2].red, c[2].green, c[2].blue, c[2].alpha } }, /* Upper right */ +/* A special case for a pattern that occurs frequently with CSS + * backgrounds: two sibling nodes, the first of which is a rounded + * clip node with a color node as child, and the second one is a + * border node, with the same outline as the clip node. We render + * this using the filled_border shader. + */ +static void +gsk_ngl_render_job_visit_css_background (GskNglRenderJob *job, + const GskRenderNode *node, + const GskRenderNode *node2) +{ + const GskRenderNode *child = gsk_rounded_clip_node_get_child (node); + const GdkRGBA *c2 = gsk_color_node_get_color (child); + const GdkRGBA *c = gsk_border_node_get_colors (node2); + const GskRoundedRect *rounded_outline = gsk_border_node_get_outline (node2); + const float *widths = gsk_border_node_get_widths (node2); + float min_x = job->offset_x + node2->bounds.origin.x; + float min_y = job->offset_y + node2->bounds.origin.y; + float max_x = min_x + node2->bounds.size.width; + float max_y = min_y + node2->bounds.size.height; + GskRoundedRect outline; + GskNglDrawVertex *vertices; - { { max_x, max_y }, { 1, 0 }, { c[2].red, c[2].green, c[2].blue, c[2].alpha } }, /* Lower right */ - { { min_x , max_y }, { 0, 0 }, { c[2].red, c[2].green, c[2].blue, c[2].alpha } }, /* Lower left */ - { { max_x - sizes[2].w, max_y - sizes[2].h }, { 1, 1 }, { c[2].red, c[2].green, c[2].blue, c[2].alpha } }, /* Upper right */ - }, - /* Left */ - { - { { min_x, min_y }, { 0, 1 }, { c[3].red, c[3].green, c[3].blue, c[3].alpha } }, /* Upper left */ - { { min_x, max_y }, { 0, 0 }, { c[3].red, c[3].green, c[3].blue, c[3].alpha } }, /* Lower left */ - { { min_x + sizes[0].w, min_y + sizes[0].h }, { 1, 1 }, { c[3].red, c[3].green, c[3].blue, c[3].alpha } }, /* Upper right */ + if (node_is_invisible (node2)) + return; - { { min_x + sizes[3].w, max_y - sizes[3].h }, { 1, 0 }, { c[3].red, c[3].green, c[3].blue, c[3].alpha } }, /* Lower right */ - { { min_x, max_y }, { 0, 0 }, { c[3].red, c[3].green, c[3].blue, c[3].alpha } }, /* Lower left */ - { { min_x + sizes[0].w, min_y + sizes[0].h }, { 1, 1 }, { c[3].red, c[3].green, c[3].blue, c[3].alpha } }, /* Upper right */ - } - }; - GskRoundedRect outline; - GskNglProgram *program; + gsk_ngl_render_job_transform_rounded_rect (job, rounded_outline, &outline); - /* Prepare outline */ - gsk_ngl_render_job_transform_rounded_rect (job, rounded_outline, &outline); + gsk_ngl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, filled_border)); - program = CHOOSE_PROGRAM (job, border); + gsk_ngl_program_set_uniform4fv (job->current_program, + UNIFORM_FILLED_BORDER_WIDTHS, 0, + 1, + widths); + gsk_ngl_program_set_uniform_rounded_rect (job->current_program, + UNIFORM_FILLED_BORDER_OUTLINE_RECT, 0, + &outline); - gsk_ngl_program_set_uniform4fv (program, - UNIFORM_BORDER_WIDTHS, 0, - 1, - widths); - gsk_ngl_program_set_uniform_rounded_rect (program, - UNIFORM_BORDER_OUTLINE_RECT, 0, - &outline); + vertices = gsk_ngl_command_queue_add_vertices (job->command_queue); - for (guint i = 0; i < 4; i++) - { - GskNglDrawVertex *vertices; + vertices[0] = (GskNglDrawVertex) { { min_x, min_y }, { 0, 0 }, { c[0].red, c[0].green, c[0].blue, c[0].alpha }, { c2->red, c2->green, c2->blue, c2->alpha } }; + vertices[1] = (GskNglDrawVertex) { { min_x, max_y }, { 0, 0 }, { c[0].red, c[0].green, c[0].blue, c[0].alpha }, { c2->red, c2->green, c2->blue, c2->alpha } }; + vertices[2] = (GskNglDrawVertex) { { max_x, min_y }, { 0, 0 }, { c[0].red, c[0].green, c[0].blue, c[0].alpha }, { c2->red, c2->green, c2->blue, c2->alpha } }; + vertices[3] = (GskNglDrawVertex) { { max_x, max_y }, { 0, 0 }, { c[0].red, c[0].green, c[0].blue, c[0].alpha }, { c2->red, c2->green, c2->blue, c2->alpha } }; + vertices[4] = (GskNglDrawVertex) { { min_x, max_y }, { 0, 0 }, { c[0].red, c[0].green, c[0].blue, c[0].alpha }, { c2->red, c2->green, c2->blue, c2->alpha } }; + vertices[5] = (GskNglDrawVertex) { { max_x, min_y }, { 0, 0 }, { c[0].red, c[0].green, c[0].blue, c[0].alpha }, { c2->red, c2->green, c2->blue, c2->alpha } }; - if (widths[i] <= 0) - continue; - - gsk_ngl_render_job_begin_draw (job, program); - vertices = gsk_ngl_command_queue_add_vertices (job->command_queue); - memcpy (vertices, side_data[i], sizeof (GskNglDrawVertex) * GSK_NGL_N_VERTICES); - gsk_ngl_render_job_end_draw (job); - } - } + gsk_ngl_render_job_end_draw (job); } /* Returns TRUE if applying @transform to @bounds @@ -1964,7 +1944,7 @@ gsk_ngl_render_job_visit_transform_node (GskNglRenderJob *job, GL_TEXTURE_2D, GL_TEXTURE0, offscreen.texture_id); - gsk_ngl_render_job_load_vertices_from_offscreen (job, &child->bounds, &offscreen); + gsk_ngl_render_job_draw_offscreen (job, &child->bounds, &offscreen); gsk_ngl_render_job_end_draw (job); gsk_ngl_render_job_pop_modelview (job); @@ -1987,7 +1967,6 @@ gsk_ngl_render_job_visit_unblurred_inset_shadow_node (GskNglRenderJob *job, gsk_ngl_render_job_transform_rounded_rect (job, outline, &transformed_outline); gsk_ngl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, inset_shadow)); - gsk_ngl_render_job_set_color (job, gsk_inset_shadow_node_get_color (node)); gsk_ngl_program_set_uniform_rounded_rect (job->current_program, UNIFORM_INSET_SHADOW_OUTLINE_RECT, 0, &transformed_outline); @@ -1998,7 +1977,7 @@ gsk_ngl_render_job_visit_unblurred_inset_shadow_node (GskNglRenderJob *job, UNIFORM_INSET_SHADOW_OFFSET, 0, gsk_inset_shadow_node_get_dx (node), gsk_inset_shadow_node_get_dy (node)); - gsk_ngl_render_job_draw_rect (job, &node->bounds); + gsk_ngl_render_job_draw_rect_with_color (job, &node->bounds, gsk_inset_shadow_node_get_color (node)); gsk_ngl_render_job_end_draw (job); } @@ -2088,7 +2067,6 @@ gsk_ngl_render_job_visit_blurred_inset_shadow_node (GskNglRenderJob *job, /* Actual inset shadow outline drawing */ gsk_ngl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, inset_shadow)); - gsk_ngl_render_job_set_color (job, gsk_inset_shadow_node_get_color (node)); gsk_ngl_program_set_uniform_rounded_rect (job->current_program, UNIFORM_INSET_SHADOW_OUTLINE_RECT, 0, &transformed_outline); @@ -2099,7 +2077,9 @@ gsk_ngl_render_job_visit_blurred_inset_shadow_node (GskNglRenderJob *job, UNIFORM_INSET_SHADOW_OFFSET, 0, offset_x * scale_x, offset_y * scale_y); - gsk_ngl_render_job_draw (job, 0, 0, texture_width, texture_height); + gsk_ngl_render_job_draw_with_color (job, + 0, 0, texture_width, texture_height, + gsk_inset_shadow_node_get_color (node)); gsk_ngl_render_job_end_draw (job); gsk_ngl_render_job_pop_modelview (job); @@ -2161,7 +2141,7 @@ gsk_ngl_render_job_visit_blurred_inset_shadow_node (GskNglRenderJob *job, GL_TEXTURE_2D, GL_TEXTURE0, blurred_texture_id); - gsk_ngl_render_job_load_vertices_from_offscreen (job, &node->bounds, &offscreen); + gsk_ngl_render_job_draw_offscreen (job, &node->bounds, &offscreen); gsk_ngl_render_job_end_draw (job); if (needs_clip) @@ -2182,6 +2162,7 @@ gsk_ngl_render_job_visit_unblurred_outset_shadow_node (GskNglRenderJob *job, float spread = gsk_outset_shadow_node_get_spread (node); float dx = gsk_outset_shadow_node_get_dx (node); float dy = gsk_outset_shadow_node_get_dy (node); + const GdkRGBA *color = gsk_outset_shadow_node_get_color (node); const float edge_sizes[] = { // Top, right, bottom, left spread - dy, spread + dx, spread + dy, spread - dx }; @@ -2195,7 +2176,6 @@ gsk_ngl_render_job_visit_unblurred_outset_shadow_node (GskNglRenderJob *job, gsk_ngl_render_job_transform_rounded_rect (job, outline, &transformed_outline); gsk_ngl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, unblurred_outset_shadow)); - gsk_ngl_render_job_set_color (job, gsk_outset_shadow_node_get_color (node)); gsk_ngl_program_set_uniform_rounded_rect (job->current_program, UNIFORM_UNBLURRED_OUTSET_SHADOW_OUTLINE_RECT, 0, &transformed_outline); @@ -2208,38 +2188,45 @@ gsk_ngl_render_job_visit_unblurred_outset_shadow_node (GskNglRenderJob *job, /* Corners... */ if (corner_sizes[0][0] > 0 && corner_sizes[0][1] > 0) /* Top left */ - gsk_ngl_render_job_draw (job, - x, y, - corner_sizes[0][0], corner_sizes[0][1]); + gsk_ngl_render_job_draw_with_color (job, + x, y, corner_sizes[0][0], corner_sizes[0][1], + color); if (corner_sizes[1][0] > 0 && corner_sizes[1][1] > 0) /* Top right */ - gsk_ngl_render_job_draw (job, - x + w - corner_sizes[1][0], y, - corner_sizes[1][0], corner_sizes[1][1]); + gsk_ngl_render_job_draw_with_color (job, + x + w - corner_sizes[1][0], y, + corner_sizes[1][0], corner_sizes[1][1], + color); if (corner_sizes[2][0] > 0 && corner_sizes[2][1] > 0) /* Bottom right */ - gsk_ngl_render_job_draw (job, - x + w - corner_sizes[2][0], y + h - corner_sizes[2][1], - corner_sizes[2][0], corner_sizes[2][1]); + gsk_ngl_render_job_draw_with_color (job, + x + w - corner_sizes[2][0], y + h - corner_sizes[2][1], + corner_sizes[2][0], corner_sizes[2][1], + color); if (corner_sizes[3][0] > 0 && corner_sizes[3][1] > 0) /* Bottom left */ - gsk_ngl_render_job_draw (job, - x, y + h - corner_sizes[3][1], - corner_sizes[3][0], corner_sizes[3][1]); + gsk_ngl_render_job_draw_with_color (job, + x, y + h - corner_sizes[3][1], + corner_sizes[3][0], corner_sizes[3][1], + color); /* Edges... */; if (edge_sizes[0] > 0) /* Top */ - gsk_ngl_render_job_draw (job, - x + corner_sizes[0][0], y, - w - corner_sizes[0][0] - corner_sizes[1][0], edge_sizes[0]); + gsk_ngl_render_job_draw_with_color (job, + x + corner_sizes[0][0], y, + w - corner_sizes[0][0] - corner_sizes[1][0], edge_sizes[0], + color); if (edge_sizes[1] > 0) /* Right */ - gsk_ngl_render_job_draw (job, - x + w - edge_sizes[1], y + corner_sizes[1][1], - edge_sizes[1], h - corner_sizes[1][1] - corner_sizes[2][1]); + gsk_ngl_render_job_draw_with_color (job, + x + w - edge_sizes[1], y + corner_sizes[1][1], + edge_sizes[1], h - corner_sizes[1][1] - corner_sizes[2][1], + color); if (edge_sizes[2] > 0) /* Bottom */ - gsk_ngl_render_job_draw (job, - x + corner_sizes[3][0], y + h - edge_sizes[2], - w - corner_sizes[3][0] - corner_sizes[2][0], edge_sizes[2]); + gsk_ngl_render_job_draw_with_color (job, + x + corner_sizes[3][0], y + h - edge_sizes[2], + w - corner_sizes[3][0] - corner_sizes[2][0], edge_sizes[2], + color); if (edge_sizes[3] > 0) /* Left */ - gsk_ngl_render_job_draw (job, - x, y + corner_sizes[0][1], - edge_sizes[3], h - corner_sizes[0][1] - corner_sizes[3][1]); + gsk_ngl_render_job_draw_with_color (job, + x, y + corner_sizes[0][1], + edge_sizes[3], h - corner_sizes[0][1] - corner_sizes[3][1], + color); gsk_ngl_render_job_end_draw (job); } @@ -2349,8 +2336,7 @@ gsk_ngl_render_job_visit_blurred_outset_shadow_node (GskNglRenderJob *job, /* Draw the outline using color program */ gsk_ngl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, color)); - gsk_ngl_render_job_set_color (job, &white); - gsk_ngl_render_job_draw (job, 0, 0, texture_width, texture_height); + gsk_ngl_render_job_draw_with_color (job, 0, 0, texture_width, texture_height, &white); gsk_ngl_render_job_end_draw (job); /* Reset state from offscreen */ @@ -2393,7 +2379,6 @@ gsk_ngl_render_job_visit_blurred_outset_shadow_node (GskNglRenderJob *job, init_full_texture_region (&offscreen); gsk_ngl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, outset_shadow)); - gsk_ngl_render_job_set_color (job, color); gsk_ngl_program_set_uniform_texture (job->current_program, UNIFORM_SHARED_SOURCE, 0, GL_TEXTURE_2D, @@ -2402,19 +2387,19 @@ gsk_ngl_render_job_visit_blurred_outset_shadow_node (GskNglRenderJob *job, gsk_ngl_program_set_uniform_rounded_rect (job->current_program, UNIFORM_OUTSET_SHADOW_OUTLINE_RECT, 0, &transformed_outline); - gsk_ngl_render_job_load_vertices_from_offscreen (job, - &GRAPHENE_RECT_INIT (min_x, - min_y, - texture_width / scale_x, - texture_height / scale_y), - &offscreen); + gsk_ngl_render_job_draw_offscreen_with_color (job, + &GRAPHENE_RECT_INIT (min_x, + min_y, + texture_width / scale_x, + texture_height / scale_y), + &offscreen, + color); gsk_ngl_render_job_end_draw (job); return; } gsk_ngl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, outset_shadow)); - gsk_ngl_render_job_set_color (job, color); gsk_ngl_program_set_uniform_texture (job->current_program, UNIFORM_SHARED_SOURCE, 0, GL_TEXTURE_2D, @@ -2446,11 +2431,12 @@ gsk_ngl_render_job_visit_blurred_outset_shadow_node (GskNglRenderJob *job, if (nine_slice_is_visible (&slices[NINE_SLICE_TOP_LEFT])) { memcpy (&offscreen.area, &slices[NINE_SLICE_TOP_LEFT].area, sizeof offscreen.area); - gsk_ngl_render_job_load_vertices_from_offscreen (job, - &GRAPHENE_RECT_INIT (min_x, min_y, - slices[NINE_SLICE_TOP_LEFT].rect.width / scale_x, - slices[NINE_SLICE_TOP_LEFT].rect.height / scale_y), - &offscreen); + gsk_ngl_render_job_draw_offscreen_with_color (job, + &GRAPHENE_RECT_INIT (min_x, min_y, + slices[NINE_SLICE_TOP_LEFT].rect.width / scale_x, + slices[NINE_SLICE_TOP_LEFT].rect.height / scale_y), + &offscreen, + color); } /* Top center */ @@ -2459,48 +2445,52 @@ gsk_ngl_render_job_visit_blurred_outset_shadow_node (GskNglRenderJob *job, memcpy (&offscreen.area, &slices[NINE_SLICE_TOP_CENTER].area, sizeof offscreen.area); float width = (max_x - min_x) - (slices[NINE_SLICE_TOP_LEFT].rect.width / scale_x + slices[NINE_SLICE_TOP_RIGHT].rect.width / scale_x); - gsk_ngl_render_job_load_vertices_from_offscreen (job, - &GRAPHENE_RECT_INIT (min_x + (slices[NINE_SLICE_TOP_LEFT].rect.width / scale_x), - min_y, - width, - slices[NINE_SLICE_TOP_CENTER].rect.height / scale_y), - &offscreen); + gsk_ngl_render_job_draw_offscreen_with_color (job, + &GRAPHENE_RECT_INIT (min_x + (slices[NINE_SLICE_TOP_LEFT].rect.width / scale_x), + min_y, + width, + slices[NINE_SLICE_TOP_CENTER].rect.height / scale_y), + &offscreen, + color); } /* Top right */ if (nine_slice_is_visible (&slices[NINE_SLICE_TOP_RIGHT])) { memcpy (&offscreen.area, &slices[NINE_SLICE_TOP_RIGHT].area, sizeof offscreen.area); - gsk_ngl_render_job_load_vertices_from_offscreen (job, - &GRAPHENE_RECT_INIT (max_x - (slices[NINE_SLICE_TOP_RIGHT].rect.width / scale_x), - min_y, - slices[NINE_SLICE_TOP_RIGHT].rect.width / scale_x, - slices[NINE_SLICE_TOP_RIGHT].rect.height / scale_y), - &offscreen); + gsk_ngl_render_job_draw_offscreen_with_color (job, + &GRAPHENE_RECT_INIT (max_x - (slices[NINE_SLICE_TOP_RIGHT].rect.width / scale_x), + min_y, + slices[NINE_SLICE_TOP_RIGHT].rect.width / scale_x, + slices[NINE_SLICE_TOP_RIGHT].rect.height / scale_y), + &offscreen, + color); } /* Bottom right */ if (nine_slice_is_visible (&slices[NINE_SLICE_BOTTOM_RIGHT])) { memcpy (&offscreen.area, &slices[NINE_SLICE_BOTTOM_RIGHT].area, sizeof offscreen.area); - gsk_ngl_render_job_load_vertices_from_offscreen (job, - &GRAPHENE_RECT_INIT (max_x - (slices[NINE_SLICE_BOTTOM_RIGHT].rect.width / scale_x), - max_y - (slices[NINE_SLICE_BOTTOM_RIGHT].rect.height / scale_y), - slices[NINE_SLICE_BOTTOM_RIGHT].rect.width / scale_x, - slices[NINE_SLICE_BOTTOM_RIGHT].rect.height / scale_y), - &offscreen); + gsk_ngl_render_job_draw_offscreen_with_color (job, + &GRAPHENE_RECT_INIT (max_x - (slices[NINE_SLICE_BOTTOM_RIGHT].rect.width / scale_x), + max_y - (slices[NINE_SLICE_BOTTOM_RIGHT].rect.height / scale_y), + slices[NINE_SLICE_BOTTOM_RIGHT].rect.width / scale_x, + slices[NINE_SLICE_BOTTOM_RIGHT].rect.height / scale_y), + &offscreen, + color); } /* Bottom left */ if (nine_slice_is_visible (&slices[NINE_SLICE_BOTTOM_LEFT])) { memcpy (&offscreen.area, &slices[NINE_SLICE_BOTTOM_LEFT].area, sizeof offscreen.area); - gsk_ngl_render_job_load_vertices_from_offscreen (job, - &GRAPHENE_RECT_INIT (min_x, - max_y - (slices[NINE_SLICE_BOTTOM_LEFT].rect.height / scale_y), - slices[NINE_SLICE_BOTTOM_LEFT].rect.width / scale_x, - slices[NINE_SLICE_BOTTOM_LEFT].rect.height / scale_y), - &offscreen); + gsk_ngl_render_job_draw_offscreen_with_color (job, + &GRAPHENE_RECT_INIT (min_x, + max_y - (slices[NINE_SLICE_BOTTOM_LEFT].rect.height / scale_y), + slices[NINE_SLICE_BOTTOM_LEFT].rect.width / scale_x, + slices[NINE_SLICE_BOTTOM_LEFT].rect.height / scale_y), + &offscreen, + color); } /* Left side */ @@ -2509,12 +2499,13 @@ gsk_ngl_render_job_visit_blurred_outset_shadow_node (GskNglRenderJob *job, memcpy (&offscreen.area, &slices[NINE_SLICE_LEFT_CENTER].area, sizeof offscreen.area); float height = (max_y - min_y) - (slices[NINE_SLICE_TOP_LEFT].rect.height / scale_y + slices[NINE_SLICE_BOTTOM_LEFT].rect.height / scale_y); - gsk_ngl_render_job_load_vertices_from_offscreen (job, - &GRAPHENE_RECT_INIT (min_x, - min_y + (slices[NINE_SLICE_TOP_LEFT].rect.height / scale_y), - slices[NINE_SLICE_LEFT_CENTER].rect.width / scale_x, - height), - &offscreen); + gsk_ngl_render_job_draw_offscreen_with_color (job, + &GRAPHENE_RECT_INIT (min_x, + min_y + (slices[NINE_SLICE_TOP_LEFT].rect.height / scale_y), + slices[NINE_SLICE_LEFT_CENTER].rect.width / scale_x, + height), + &offscreen, + color); } /* Right side */ @@ -2523,12 +2514,13 @@ gsk_ngl_render_job_visit_blurred_outset_shadow_node (GskNglRenderJob *job, memcpy (&offscreen.area, &slices[NINE_SLICE_RIGHT_CENTER].area, sizeof offscreen.area); float height = (max_y - min_y) - (slices[NINE_SLICE_TOP_RIGHT].rect.height / scale_y + slices[NINE_SLICE_BOTTOM_RIGHT].rect.height / scale_y); - gsk_ngl_render_job_load_vertices_from_offscreen (job, - &GRAPHENE_RECT_INIT (max_x - (slices[NINE_SLICE_RIGHT_CENTER].rect.width / scale_x), - min_y + (slices[NINE_SLICE_TOP_LEFT].rect.height / scale_y), - slices[NINE_SLICE_RIGHT_CENTER].rect.width / scale_x, - height), - &offscreen); + gsk_ngl_render_job_draw_offscreen_with_color (job, + &GRAPHENE_RECT_INIT (max_x - (slices[NINE_SLICE_RIGHT_CENTER].rect.width / scale_x), + min_y + (slices[NINE_SLICE_TOP_LEFT].rect.height / scale_y), + slices[NINE_SLICE_RIGHT_CENTER].rect.width / scale_x, + height), + &offscreen, + color); } /* Bottom side */ @@ -2537,12 +2529,13 @@ gsk_ngl_render_job_visit_blurred_outset_shadow_node (GskNglRenderJob *job, memcpy (&offscreen.area, &slices[NINE_SLICE_BOTTOM_CENTER].area, sizeof offscreen.area); float width = (max_x - min_x) - (slices[NINE_SLICE_BOTTOM_LEFT].rect.width / scale_x + slices[NINE_SLICE_BOTTOM_RIGHT].rect.width / scale_x); - gsk_ngl_render_job_load_vertices_from_offscreen (job, - &GRAPHENE_RECT_INIT (min_x + (slices[NINE_SLICE_BOTTOM_LEFT].rect.width / scale_x), - max_y - (slices[NINE_SLICE_BOTTOM_CENTER].rect.height / scale_y), - width, - slices[NINE_SLICE_BOTTOM_CENTER].rect.height / scale_y), - &offscreen); + gsk_ngl_render_job_draw_offscreen_with_color (job, + &GRAPHENE_RECT_INIT (min_x + (slices[NINE_SLICE_BOTTOM_LEFT].rect.width / scale_x), + max_y - (slices[NINE_SLICE_BOTTOM_CENTER].rect.height / scale_y), + width, + slices[NINE_SLICE_BOTTOM_CENTER].rect.height / scale_y), + &offscreen, + color); } /* Middle */ @@ -2553,11 +2546,12 @@ gsk_ngl_render_job_visit_blurred_outset_shadow_node (GskNglRenderJob *job, slices[NINE_SLICE_RIGHT_CENTER].rect.width / scale_x); float height = (max_y - min_y) - (slices[NINE_SLICE_TOP_CENTER].rect.height / scale_y + slices[NINE_SLICE_BOTTOM_CENTER].rect.height / scale_y); - gsk_ngl_render_job_load_vertices_from_offscreen (job, - &GRAPHENE_RECT_INIT (min_x + (slices[NINE_SLICE_LEFT_CENTER].rect.width / scale_x), - min_y + (slices[NINE_SLICE_TOP_CENTER].rect.height / scale_y), - width, height), - &offscreen); + gsk_ngl_render_job_draw_offscreen_with_color (job, + &GRAPHENE_RECT_INIT (min_x + (slices[NINE_SLICE_LEFT_CENTER].rect.width / scale_x), + min_y + (slices[NINE_SLICE_TOP_CENTER].rect.height / scale_y), + width, height), + &offscreen, + color); } } @@ -2632,7 +2626,7 @@ gsk_ngl_render_job_visit_cross_fade_node (GskNglRenderJob *job, gsk_ngl_program_set_uniform1f (job->current_program, UNIFORM_CROSS_FADE_PROGRESS, 0, progress); - gsk_ngl_render_job_load_vertices_from_offscreen (job, &node->bounds, &offscreen_end); + gsk_ngl_render_job_draw_offscreen (job, &node->bounds, &offscreen_end); gsk_ngl_render_job_end_draw (job); } @@ -2670,7 +2664,7 @@ gsk_ngl_render_job_visit_opacity_node (GskNglRenderJob *job, GL_TEXTURE_2D, GL_TEXTURE0, offscreen.texture_id); - gsk_ngl_render_job_load_vertices_from_offscreen (job, &node->bounds, &offscreen); + gsk_ngl_render_job_draw_offscreen (job, &node->bounds, &offscreen); gsk_ngl_render_job_end_draw (job); } else @@ -2699,7 +2693,6 @@ gsk_ngl_render_job_visit_text_node (GskNglRenderJob *job, GskNglCommandBatch *batch; int x_position = 0; GskNglGlyphKey lookup; - GskNglProgram *program; guint last_texture = 0; GskNglDrawVertex *vertices; guint used = 0; @@ -2708,8 +2701,6 @@ gsk_ngl_render_job_visit_text_node (GskNglRenderJob *job, if (num_glyphs == 0) return; - program = CHOOSE_PROGRAM (job, coloring); - /* If the font has color glyphs, we don't need to recolor anything. * We tell the shader by setting the color to vec4(-1). */ @@ -2721,7 +2712,7 @@ gsk_ngl_render_job_visit_text_node (GskNglRenderJob *job, lookup.font = (PangoFont *)font; lookup.scale = (guint) (text_scale * 1024); - gsk_ngl_render_job_begin_draw (job, program); + gsk_ngl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, coloring)); batch = gsk_ngl_command_queue_get_batch (job->command_queue); vertices = gsk_ngl_command_queue_add_n_vertices (job->command_queue, num_glyphs); @@ -2769,7 +2760,7 @@ gsk_ngl_render_job_visit_text_node (GskNglRenderJob *job, batch->draw.vbo_offset = vbo_offset; } - gsk_ngl_program_set_uniform_texture (program, + gsk_ngl_program_set_uniform_texture (job->current_program, UNIFORM_SHARED_SOURCE, 0, GL_TEXTURE_2D, GL_TEXTURE0, @@ -2787,59 +2778,13 @@ gsk_ngl_render_job_visit_text_node (GskNglRenderJob *job, glyph_x2 = glyph_x + glyph->ink_rect.width; glyph_y2 = glyph_y + glyph->ink_rect.height; - vertices[base+0].position[0] = glyph_x; - vertices[base+0].position[1] = glyph_y; - vertices[base+0].uv[0] = tx; - vertices[base+0].uv[1] = ty; - vertices[base+0].color[0] = c.red; - vertices[base+0].color[1] = c.green; - vertices[base+0].color[2] = c.blue; - vertices[base+0].color[3] = c.alpha; + vertices[base+0] = (GskNglDrawVertex) { { glyph_x, glyph_y }, { tx, ty }, { c.red, c.green, c.blue, c.alpha } }; + vertices[base+1] = (GskNglDrawVertex) { { glyph_x, glyph_y2 }, { tx, ty2 }, { c.red, c.green, c.blue, c.alpha } }; + vertices[base+2] = (GskNglDrawVertex) { { glyph_x2, glyph_y }, { tx2, ty }, { c.red, c.green, c.blue, c.alpha } }; - vertices[base+1].position[0] = glyph_x; - vertices[base+1].position[1] = glyph_y2; - vertices[base+1].uv[0] = tx; - vertices[base+1].uv[1] = ty2; - vertices[base+1].color[0] = c.red; - vertices[base+1].color[1] = c.green; - vertices[base+1].color[2] = c.blue; - vertices[base+1].color[3] = c.alpha; - - vertices[base+2].position[0] = glyph_x2; - vertices[base+2].position[1] = glyph_y; - vertices[base+2].uv[0] = tx2; - vertices[base+2].uv[1] = ty; - vertices[base+2].color[0] = c.red; - vertices[base+2].color[1] = c.green; - vertices[base+2].color[2] = c.blue; - vertices[base+2].color[3] = c.alpha; - - vertices[base+3].position[0] = glyph_x2; - vertices[base+3].position[1] = glyph_y2; - vertices[base+3].uv[0] = tx2; - vertices[base+3].uv[1] = ty2; - vertices[base+3].color[0] = c.red; - vertices[base+3].color[1] = c.green; - vertices[base+3].color[2] = c.blue; - vertices[base+3].color[3] = c.alpha; - - vertices[base+4].position[0] = glyph_x; - vertices[base+4].position[1] = glyph_y2; - vertices[base+4].uv[0] = tx; - vertices[base+4].uv[1] = ty2; - vertices[base+4].color[0] = c.red; - vertices[base+4].color[1] = c.green; - vertices[base+4].color[2] = c.blue; - vertices[base+4].color[3] = c.alpha; - - vertices[base+5].position[0] = glyph_x2; - vertices[base+5].position[1] = glyph_y; - vertices[base+5].uv[0] = tx2; - vertices[base+5].uv[1] = ty; - vertices[base+5].color[0] = c.red; - vertices[base+5].color[1] = c.green; - vertices[base+5].color[2] = c.blue; - vertices[base+5].color[3] = c.alpha; + vertices[base+3] = (GskNglDrawVertex) { { glyph_x2, glyph_y2 }, { tx2, ty2 }, { c.red, c.green, c.blue, c.alpha } }; + vertices[base+4] = (GskNglDrawVertex) { { glyph_x, glyph_y2 }, { tx, ty2 }, { c.red, c.green, c.blue, c.alpha } }; + vertices[base+5] = (GskNglDrawVertex) { { glyph_x2, glyph_y }, { tx2, ty }, { c.red, c.green, c.blue, c.alpha } }; batch->draw.vbo_count += GSK_NGL_N_VERTICES; used++; @@ -2932,13 +2877,12 @@ gsk_ngl_render_job_visit_shadow_node (GskNglRenderJob *job, gsk_ngl_render_job_offset (job, dx, dy); gsk_ngl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, coloring)); - gsk_ngl_render_job_set_color (job, &shadow->color); gsk_ngl_program_set_uniform_texture (job->current_program, UNIFORM_SHARED_SOURCE, 0, GL_TEXTURE_2D, GL_TEXTURE0, offscreen.texture_id); - gsk_ngl_render_job_load_vertices_from_offscreen (job, &bounds, &offscreen); + gsk_ngl_render_job_draw_offscreen_with_color (job, &bounds, &offscreen, &shadow->color); gsk_ngl_render_job_end_draw (job); gsk_ngl_render_job_offset (job, -dx, -dy); } @@ -2992,7 +2936,10 @@ gsk_ngl_render_job_visit_blur_node (GskNglRenderJob *job, GL_TEXTURE_2D, GL_TEXTURE0, offscreen.texture_id); - gsk_ngl_render_job_draw_coords (job, min_x, min_y, max_x, max_y, 0, 1, 1, 0); + gsk_ngl_render_job_draw_coords (job, + min_x, min_y, max_x, max_y, + 0, 1, 1, 0, + &(GdkRGBA) { 0.f, 0.f, 0.f, 0.f } ); gsk_ngl_render_job_end_draw (job); } @@ -3031,7 +2978,7 @@ gsk_ngl_render_job_visit_blend_node (GskNglRenderJob *job, GL_TEXTURE_2D, GL_TEXTURE0, bottom_offscreen.texture_id); - gsk_ngl_render_job_load_vertices_from_offscreen (job, &node->bounds, &bottom_offscreen); + gsk_ngl_render_job_draw_offscreen (job, &node->bounds, &bottom_offscreen); gsk_ngl_render_job_end_draw (job); return; } @@ -3090,7 +3037,7 @@ gsk_ngl_render_job_visit_color_matrix_node (GskNglRenderJob *job, UNIFORM_COLOR_MATRIX_COLOR_OFFSET, 0, 1, offset); - gsk_ngl_render_job_load_vertices_from_offscreen (job, &node->bounds, &offscreen); + gsk_ngl_render_job_draw_offscreen (job, &node->bounds, &offscreen); gsk_ngl_render_job_end_draw (job); } @@ -3101,8 +3048,7 @@ gsk_ngl_render_job_visit_gl_shader_node_fallback (GskNglRenderJob *job, static const GdkRGBA pink = { 255 / 255., 105 / 255., 180 / 255., 1.0 }; gsk_ngl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, color)); - gsk_ngl_render_job_set_color (job, &pink); - gsk_ngl_render_job_draw_rect (job, &node->bounds); + gsk_ngl_render_job_draw_rect_with_color (job, &node->bounds, &pink); gsk_ngl_render_job_end_draw (job); } @@ -3270,7 +3216,7 @@ gsk_ngl_render_job_visit_texture_node (GskNglRenderJob *job, GL_TEXTURE_2D, GL_TEXTURE0, offscreen.texture_id); - gsk_ngl_render_job_load_vertices_from_offscreen (job, &node->bounds, &offscreen); + gsk_ngl_render_job_draw_offscreen (job, &node->bounds, &offscreen); gsk_ngl_render_job_end_draw (job); } else @@ -3309,7 +3255,10 @@ gsk_ngl_render_job_visit_texture_node (GskNglRenderJob *job, GL_TEXTURE0, slice->texture_id); - gsk_ngl_render_job_draw_coords (job, x1, y1, x2, y2, 0, 0, 1, 1); + gsk_ngl_render_job_draw_coords (job, + x1, y1, x2, y2, + 0, 0, 1, 1, + &(GdkRGBA) { 0.f, 0.f, 0.f, 0.f }); } gsk_ngl_render_job_end_draw (job); @@ -3367,7 +3316,7 @@ gsk_ngl_render_job_visit_repeat_node (GskNglRenderJob *job, offscreen.was_offscreen ? offscreen.area.y2 : offscreen.area.y, offscreen.area.x2, offscreen.was_offscreen ? offscreen.area.y : offscreen.area.y2); - gsk_ngl_render_job_load_vertices_from_offscreen (job, &node->bounds, &offscreen); + gsk_ngl_render_job_draw_offscreen (job, &node->bounds, &offscreen); gsk_ngl_render_job_end_draw (job); } @@ -3405,8 +3354,6 @@ gsk_ngl_render_job_visit_node (GskNglRenderJob *job, if (gsk_border_node_get_uniform_color (node) && gsk_rounded_rect_is_rectilinear (gsk_border_node_get_outline (node))) gsk_ngl_render_job_visit_rect_border_node (job, node); - else if (gsk_border_node_get_uniform (node)) - gsk_ngl_render_job_visit_uniform_border_node (job, node); else gsk_ngl_render_job_visit_border_node (job, node); break; @@ -3437,6 +3384,25 @@ gsk_ngl_render_job_visit_node (GskNglRenderJob *job, for (guint i = 0; i < n_children; i++) { const GskRenderNode *child = gsk_container_node_get_child (node, i); + + if (i + 1 < n_children && + job->current_clip->is_fully_contained && + gsk_render_node_get_node_type (child) == GSK_ROUNDED_CLIP_NODE) + { + const GskRenderNode *grandchild = gsk_rounded_clip_node_get_child (child); + const GskRenderNode *child2 = gsk_container_node_get_child (node, i + 1); + if (gsk_render_node_get_node_type (grandchild) == GSK_COLOR_NODE && + gsk_render_node_get_node_type (child2) == GSK_BORDER_NODE && + gsk_border_node_get_uniform_color (child2) && + gsk_rounded_rect_equal (gsk_rounded_clip_node_get_clip (child), + gsk_border_node_get_outline (child2))) + { + gsk_ngl_render_job_visit_css_background (job, child, child2); + i++; /* skip the border node */ + continue; + } + } + gsk_ngl_render_job_visit_node (job, child); } } @@ -3846,7 +3812,6 @@ gsk_ngl_render_job_new (GskNglDriver *driver, job->viewport = *viewport; gsk_ngl_render_job_set_alpha (job, 1.0); - gsk_ngl_render_job_set_color (job, &(GdkRGBA){ 0.f, 0.f, 0.f, 0.f }); gsk_ngl_render_job_set_projection_from_rect (job, viewport, NULL); gsk_ngl_render_job_set_modelview (job, gsk_transform_scale (NULL, scale_factor, scale_factor)); diff --git a/gsk/ngl/gskngltypesprivate.h b/gsk/ngl/gskngltypesprivate.h index dc76fb41f4..a65130c19f 100644 --- a/gsk/ngl/gskngltypesprivate.h +++ b/gsk/ngl/gskngltypesprivate.h @@ -56,6 +56,7 @@ struct _GskNglDrawVertex float position[2]; float uv[2]; float color[4]; + float color2[4]; }; G_END_DECLS diff --git a/gsk/ngl/resources/blend.glsl b/gsk/ngl/resources/blend.glsl index 066c20179d..609f9f29a2 100644 --- a/gsk/ngl/resources/blend.glsl +++ b/gsk/ngl/resources/blend.glsl @@ -310,5 +310,5 @@ void main() { else discard; - gskSetOutputColor(result * u_alpha); + gskSetScaledOutputColor(result, u_alpha); } diff --git a/gsk/ngl/resources/blit.glsl b/gsk/ngl/resources/blit.glsl index c232be2bfd..ced047b9a9 100644 --- a/gsk/ngl/resources/blit.glsl +++ b/gsk/ngl/resources/blit.glsl @@ -13,5 +13,5 @@ void main() { void main() { vec4 diffuse = GskTexture(u_source, vUv); - gskSetOutputColor(diffuse * u_alpha); + gskSetScaledOutputColor(diffuse, u_alpha); } diff --git a/gsk/ngl/resources/border.glsl b/gsk/ngl/resources/border.glsl index a9c04556a4..b8653bad49 100644 --- a/gsk/ngl/resources/border.glsl +++ b/gsk/ngl/resources/border.glsl @@ -11,7 +11,7 @@ _OUT_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_inside_outline; void main() { gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0); - final_color = gsk_premultiply(aColor) * u_alpha; + final_color = gsk_scaled_premultiply(aColor, u_alpha); GskRoundedRect outside = gsk_create_rect(u_outline_rect); GskRoundedRect inside = gsk_rounded_rect_shrink (outside, u_widths); @@ -39,5 +39,5 @@ void main() { gsk_rounded_rect_coverage(gsk_decode_rect(transformed_inside_outline), frag), 0.0, 1.0); - gskSetOutputColor(final_color * alpha); + gskSetScaledOutputColor(final_color, alpha); } diff --git a/gsk/ngl/resources/color.glsl b/gsk/ngl/resources/color.glsl index 670b9979a2..ba98b1b170 100644 --- a/gsk/ngl/resources/color.glsl +++ b/gsk/ngl/resources/color.glsl @@ -6,7 +6,7 @@ _OUT_ vec4 final_color; void main() { gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0); - final_color = gsk_premultiply(aColor) * u_alpha; + final_color = gsk_scaled_premultiply(aColor, u_alpha); } // FRAGMENT_SHADER: diff --git a/gsk/ngl/resources/color_matrix.glsl b/gsk/ngl/resources/color_matrix.glsl index 44dcf9a044..51835f056f 100644 --- a/gsk/ngl/resources/color_matrix.glsl +++ b/gsk/ngl/resources/color_matrix.glsl @@ -23,7 +23,5 @@ void main() { color = u_color_matrix * color + u_color_offset; color = clamp(color, 0.0, 1.0); - color.rgb *= color.a; - - gskSetOutputColor(color * u_alpha); + gskSetOutputColor(gsk_scaled_premultiply(color, u_alpha)); } diff --git a/gsk/ngl/resources/coloring.glsl b/gsk/ngl/resources/coloring.glsl index 5b5d46a732..007c54d562 100644 --- a/gsk/ngl/resources/coloring.glsl +++ b/gsk/ngl/resources/coloring.glsl @@ -12,12 +12,12 @@ void main() { // We use this shader for both plain glyphs (used as mask) // and color glpyhs (used as source). The renderer sets // aColor to vec4(-1) for color glyhs. - if (distance(aColor, vec4(-1)) < 0.001) + if (distance(aColor,vec4(-1)) < 0.1) use_color = 0.0; else use_color = 1.0; - final_color = gsk_premultiply(aColor) * u_alpha; + final_color = gsk_scaled_premultiply(aColor, u_alpha); } // FRAGMENT_SHADER: @@ -29,8 +29,5 @@ _IN_ float use_color; void main() { vec4 diffuse = GskTexture(u_source, vUv); - if (use_color > 0.0) - gskSetOutputColor(final_color * diffuse.a); - else - gskSetOutputColor(diffuse * u_alpha); + gskSetOutputColor(mix(diffuse * u_alpha, final_color * diffuse.a, use_color)); } diff --git a/gsk/ngl/resources/conic_gradient.glsl b/gsk/ngl/resources/conic_gradient.glsl index afb427bb15..3a26cf9563 100644 --- a/gsk/ngl/resources/conic_gradient.glsl +++ b/gsk/ngl/resources/conic_gradient.glsl @@ -18,6 +18,8 @@ void main() { // FRAGMENT_SHADER: // conic_gradient.glsl +#define MAX_COLOR_STOPS 6 + #ifdef GSK_LEGACY uniform int u_num_color_stops; #else @@ -25,7 +27,7 @@ uniform highp int u_num_color_stops; // Why? Because it works like this. #endif uniform vec4 u_geometry; -uniform float u_color_stops[6 * 5]; +uniform float u_color_stops[MAX_COLOR_STOPS * 5]; _NOPERSPECTIVE_ _IN_ vec2 coord; @@ -50,27 +52,31 @@ void main() { // fract() does the modulo here, so now we have progress // into the current conic float offset = fract(angle * u_geometry.z + u_geometry.w); + float curr_offset; + float next_offset; - if (offset < get_offset(0)) { + next_offset = get_offset(0); + if (offset < next_offset) { gskSetOutputColor(gsk_scaled_premultiply(get_color(0), u_alpha)); return; } - int n = u_num_color_stops - 1; - for (int i = 0; i < n; i++) { - float curr_offset = get_offset(i); - float next_offset = get_offset(i + 1); + if (offset >= get_offset(u_num_color_stops - 1)) { + gskSetOutputColor(gsk_scaled_premultiply(get_color(u_num_color_stops - 1), u_alpha)); + return; + } - if (offset >= curr_offset && offset < next_offset) { + for (int i = 0; i < MAX_COLOR_STOPS; i++) { + curr_offset = next_offset; + next_offset = get_offset(i + 1); + + if (offset < next_offset) { float f = (offset - curr_offset) / (next_offset - curr_offset); vec4 curr_color = gsk_premultiply(get_color(i)); vec4 next_color = gsk_premultiply(get_color(i + 1)); vec4 color = mix(curr_color, next_color, f); - - gskSetOutputColor(color * u_alpha); + gskSetScaledOutputColor(color, u_alpha); return; } } - - gskSetOutputColor(gsk_scaled_premultiply(get_color(n), u_alpha)); } diff --git a/gsk/ngl/resources/filled_border.glsl b/gsk/ngl/resources/filled_border.glsl new file mode 100644 index 0000000000..d503dd0500 --- /dev/null +++ b/gsk/ngl/resources/filled_border.glsl @@ -0,0 +1,47 @@ +// VERTEX_SHADER: +// filled_border.glsl + +uniform vec4 u_widths; +uniform vec4[3] u_outline_rect; + +_OUT_ vec4 outer_color; +_OUT_ vec4 inner_color; +_OUT_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_outside_outline; +_OUT_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_inside_outline; + +void main() { + gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0); + + outer_color = gsk_scaled_premultiply(aColor, u_alpha); + inner_color = gsk_scaled_premultiply(aColor2, u_alpha); + + GskRoundedRect outside = gsk_create_rect(u_outline_rect); + GskRoundedRect inside = gsk_rounded_rect_shrink (outside, u_widths); + + gsk_rounded_rect_transform(outside, u_modelview); + gsk_rounded_rect_transform(inside, u_modelview); + + gsk_rounded_rect_encode(outside, transformed_outside_outline); + gsk_rounded_rect_encode(inside, transformed_inside_outline); +} + +// FRAGMENT_SHADER: +// filled_border.glsl + +uniform vec4[3] u_outline_rect; + +_IN_ vec4 outer_color; +_IN_ vec4 inner_color; +_IN_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_outside_outline; +_IN_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_inside_outline; + +void main() { + vec2 frag = gsk_get_frag_coord(); + float outer_coverage = gsk_rounded_rect_coverage(gsk_decode_rect(transformed_outside_outline), frag); + float inner_coverage = gsk_rounded_rect_coverage(gsk_decode_rect(transformed_inside_outline), frag); + + float alpha = clamp(outer_coverage - inner_coverage, 0.0, 1.0); + float alpha2 = clamp(inner_coverage, 0.0, 1.0); + + gskSetOutputColor((outer_color * alpha) + (inner_color * alpha2)); +} diff --git a/gsk/ngl/resources/inset_shadow.glsl b/gsk/ngl/resources/inset_shadow.glsl index 1c3c955035..f052a08580 100644 --- a/gsk/ngl/resources/inset_shadow.glsl +++ b/gsk/ngl/resources/inset_shadow.glsl @@ -12,7 +12,7 @@ _OUT_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_inside_outline; void main() { gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0); - final_color = gsk_premultiply(aColor) * u_alpha; + final_color = gsk_scaled_premultiply(aColor, u_alpha); GskRoundedRect outside = gsk_create_rect(u_outline_rect); GskRoundedRect inside = gsk_rounded_rect_shrink(outside, vec4(u_spread)); @@ -40,5 +40,5 @@ void main() { gsk_rounded_rect_coverage(gsk_decode_rect(transformed_inside_outline), frag), 0.0, 1.0); - gskSetOutputColor(final_color * alpha); + gskSetScaledOutputColor(final_color, alpha); } diff --git a/gsk/ngl/resources/linear_gradient.glsl b/gsk/ngl/resources/linear_gradient.glsl index 1a2f2675e0..c4dfb53722 100644 --- a/gsk/ngl/resources/linear_gradient.glsl +++ b/gsk/ngl/resources/linear_gradient.glsl @@ -42,13 +42,15 @@ void main() { // FRAGMENT_SHADER: // linear_gradient.glsl +#define MAX_COLOR_STOPS 6 + #ifdef GSK_LEGACY uniform int u_num_color_stops; #else uniform highp int u_num_color_stops; // Why? Because it works like this. #endif -uniform float u_color_stops[6 * 5]; +uniform float u_color_stops[MAX_COLOR_STOPS * 5]; uniform bool u_repeat; _NOPERSPECTIVE_ _IN_ vec4 info; @@ -68,31 +70,35 @@ vec4 get_color(int index) { void main() { float offset = dot(info.xy, info.zw); + float curr_offset; + float next_offset; if (u_repeat) { offset = fract(offset); } - if (offset < get_offset(0)) { + next_offset = get_offset(0); + if (offset < next_offset) { gskSetOutputColor(gsk_scaled_premultiply(get_color(0), u_alpha)); return; } - int n = u_num_color_stops - 1; - for (int i = 0; i < n; i++) { - float curr_offset = get_offset(i); - float next_offset = get_offset(i + 1); + if (offset >= get_offset(u_num_color_stops - 1)) { + gskSetOutputColor(gsk_scaled_premultiply(get_color(u_num_color_stops - 1), u_alpha)); + return; + } - if (offset >= curr_offset && offset < next_offset) { + for (int i = 0; i < MAX_COLOR_STOPS; i++) { + curr_offset = next_offset; + next_offset = get_offset(i + 1); + + if (offset < next_offset) { float f = (offset - curr_offset) / (next_offset - curr_offset); vec4 curr_color = gsk_premultiply(get_color(i)); vec4 next_color = gsk_premultiply(get_color(i + 1)); vec4 color = mix(curr_color, next_color, f); - - gskSetOutputColor(color * u_alpha); + gskSetScaledOutputColor(color, u_alpha); return; } } - - gskSetOutputColor(gsk_scaled_premultiply(get_color(n), u_alpha)); } diff --git a/gsk/ngl/resources/outset_shadow.glsl b/gsk/ngl/resources/outset_shadow.glsl index 427aee956c..44b05aa152 100644 --- a/gsk/ngl/resources/outset_shadow.glsl +++ b/gsk/ngl/resources/outset_shadow.glsl @@ -11,7 +11,7 @@ void main() { vUv = vec2(aUv.x, aUv.y); - final_color = gsk_premultiply(aColor) * u_alpha; + final_color = gsk_scaled_premultiply(aColor, u_alpha); GskRoundedRect outline = gsk_create_rect(u_outline_rect); gsk_rounded_rect_transform(outline, u_modelview); @@ -30,7 +30,5 @@ void main() { alpha *= (1.0 - clamp(gsk_rounded_rect_coverage(gsk_decode_rect(transformed_outline), frag), 0.0, 1.0)); - vec4 color = final_color * alpha; - - gskSetOutputColor(color); + gskSetScaledOutputColor(final_color, alpha); } diff --git a/gsk/ngl/resources/preamble.fs.glsl b/gsk/ngl/resources/preamble.fs.glsl index e715d2526d..c1c5a954ee 100644 --- a/gsk/ngl/resources/preamble.fs.glsl +++ b/gsk/ngl/resources/preamble.fs.glsl @@ -123,11 +123,35 @@ void gskSetOutputColor(vec4 color) { #if defined(NO_CLIP) result = color; #elif defined(RECT_CLIP) - result = color * gsk_rect_coverage(gsk_get_bounds(u_clip_rect), + float coverage = gsk_rect_coverage(gsk_get_bounds(u_clip_rect), gsk_get_frag_coord()); + result = color * coverage; #else - result = color * gsk_rounded_rect_coverage(gsk_create_rect(u_clip_rect), + float coverage = gsk_rounded_rect_coverage(gsk_create_rect(u_clip_rect), gsk_get_frag_coord()); + result = color * coverage; +#endif + +#if defined(GSK_GLES) || defined(GSK_LEGACY) + gl_FragColor = result; +#else + outputColor = result; +#endif +} + +void gskSetScaledOutputColor(vec4 color, float alpha) { + vec4 result; + +#if defined(NO_CLIP) + result = color * alpha; +#elif defined(RECT_CLIP) + float coverage = gsk_rect_coverage(gsk_get_bounds(u_clip_rect), + gsk_get_frag_coord()); + result = color * (alpha * coverage); +#else + float coverage = gsk_rounded_rect_coverage(gsk_create_rect(u_clip_rect), + gsk_get_frag_coord()); + result = color * (alpha * coverage); #endif #if defined(GSK_GLES) || defined(GSK_LEGACY) diff --git a/gsk/ngl/resources/preamble.vs.glsl b/gsk/ngl/resources/preamble.vs.glsl index a549ff6ded..758bca89d2 100644 --- a/gsk/ngl/resources/preamble.vs.glsl +++ b/gsk/ngl/resources/preamble.vs.glsl @@ -6,11 +6,13 @@ uniform float u_alpha; attribute vec2 aPosition; attribute vec2 aUv; attribute vec4 aColor; +attribute vec4 aColor2; _OUT_ vec2 vUv; #else _IN_ vec2 aPosition; _IN_ vec2 aUv; _IN_ vec4 aColor; +_IN_ vec4 aColor2; _OUT_ vec2 vUv; #endif diff --git a/gsk/ngl/resources/radial_gradient.glsl b/gsk/ngl/resources/radial_gradient.glsl index e8b57ef635..5990b39a84 100644 --- a/gsk/ngl/resources/radial_gradient.glsl +++ b/gsk/ngl/resources/radial_gradient.glsl @@ -20,6 +20,8 @@ void main() { // FRAGMENT_SHADER: // radial_gradient.glsl +#define MAX_COLOR_STOPS 6 + #ifdef GSK_LEGACY uniform int u_num_color_stops; #else @@ -28,7 +30,7 @@ uniform highp int u_num_color_stops; uniform bool u_repeat; uniform vec2 u_range; -uniform float u_color_stops[6 * 5]; +uniform float u_color_stops[MAX_COLOR_STOPS * 5]; _NOPERSPECTIVE_ _IN_ vec2 coord; @@ -48,31 +50,35 @@ vec4 get_color(int index) { void main() { // Reverse scale float offset = length(coord) * u_range.x + u_range.y; + float curr_offset; + float next_offset; if (u_repeat) { offset = fract(offset); } - if (offset < get_offset(0)) { + next_offset = get_offset(0); + if (offset < next_offset) { gskSetOutputColor(gsk_scaled_premultiply(get_color(0), u_alpha)); return; } - int n = u_num_color_stops - 1; - for (int i = 0; i < n; i++) { - float curr_offset = get_offset(i); - float next_offset = get_offset(i + 1); + if (offset >= get_offset(u_num_color_stops - 1)) { + gskSetOutputColor(gsk_scaled_premultiply(get_color(u_num_color_stops - 1), u_alpha)); + return; + } - if (offset >= curr_offset && offset < next_offset) { + for (int i = 0; i < MAX_COLOR_STOPS; i++) { + curr_offset = next_offset; + next_offset = get_offset(i + 1); + + if (offset < next_offset) { float f = (offset - curr_offset) / (next_offset - curr_offset); vec4 curr_color = gsk_premultiply(get_color(i)); vec4 next_color = gsk_premultiply(get_color(i + 1)); vec4 color = mix(curr_color, next_color, f); - - gskSetOutputColor(color * u_alpha); + gskSetScaledOutputColor(color, u_alpha); return; } } - - gskSetOutputColor(gsk_scaled_premultiply(get_color(n), u_alpha)); } diff --git a/gsk/ngl/resources/repeat.glsl b/gsk/ngl/resources/repeat.glsl index 5d39603396..1b811df2da 100644 --- a/gsk/ngl/resources/repeat.glsl +++ b/gsk/ngl/resources/repeat.glsl @@ -40,5 +40,5 @@ void main() { vec4 diffuse = GskTexture(u_source, tp); - gskSetOutputColor(diffuse * u_alpha); + gskSetScaledOutputColor(diffuse, u_alpha); } diff --git a/gsk/ngl/resources/unblurred_outset_shadow.glsl b/gsk/ngl/resources/unblurred_outset_shadow.glsl index 305cc5f1e2..cd44212c93 100644 --- a/gsk/ngl/resources/unblurred_outset_shadow.glsl +++ b/gsk/ngl/resources/unblurred_outset_shadow.glsl @@ -39,6 +39,6 @@ void main() { gsk_rounded_rect_coverage(gsk_decode_rect(transformed_inside_outline), frag), 0.0, 1.0); - gskSetOutputColor(final_color * alpha); + gskSetScaledOutputColor(final_color, alpha); }