[gtk/wip/baedert/for-master: 735/748] gl renderer: Transform rounded rect on the GPU
- From: Timm Bäder <baedert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/baedert/for-master: 735/748] gl renderer: Transform rounded rect on the GPU
- Date: Fri, 24 Jan 2020 05:21:05 +0000 (UTC)
commit c8fa1f19dbb490bc30a6dcb670a655720577e6e3
Author: Timm Bäder <mail baedert org>
Date: Sun Jan 19 17:11:57 2020 +0100
gl renderer: Transform rounded rect on the GPU
Change the RoundedRect struct we use in our shaders so we can transform
it using (affine) matrices.
gsk/gl/gskglrenderer.c | 47 ++++++---------
gsk/resources/glsl/border.glsl | 3 +
gsk/resources/glsl/inset_shadow.glsl | 16 +++--
gsk/resources/glsl/outset_shadow.glsl | 1 +
gsk/resources/glsl/preamble.fs.glsl | 80 +++++++++++++++----------
gsk/resources/glsl/unblurred_outset_shadow.glsl | 16 +++--
6 files changed, 94 insertions(+), 69 deletions(-)
---
diff --git a/gsk/gl/gskglrenderer.c b/gsk/gl/gskglrenderer.c
index ddead714c7..1dd08f88e7 100644
--- a/gsk/gl/gskglrenderer.c
+++ b/gsk/gl/gskglrenderer.c
@@ -535,17 +535,16 @@ transform_rect (GskGLRenderer *self,
RenderOpBuilder *builder,
const GskRoundedRect *rect)
{
- const float scale = ops_get_scale (builder);
GskRoundedRect r;
- int i;
- ops_transform_bounds_modelview (builder, &rect->bounds, &r.bounds);
+ r.bounds.origin.x = builder->dx + rect->bounds.origin.x;
+ r.bounds.origin.y = builder->dy + rect->bounds.origin.y;
+ r.bounds.size = rect->bounds.size;
- for (i = 0; i < 4; i ++)
- {
- r.corner[i].width = rect->corner[i].width * scale;
- r.corner[i].height = rect->corner[i].height * scale;
- }
+ r.corner[0] = rect->corner[0];
+ r.corner[1] = rect->corner[1];
+ r.corner[2] = rect->corner[2];
+ r.corner[3] = rect->corner[3];
return r;
}
@@ -745,24 +744,22 @@ render_border_node (GskGLRenderer *self,
GskRenderNode *node,
RenderOpBuilder *builder)
{
- const float scale = ops_get_scale (builder);
const float min_x = builder->dx + node->bounds.origin.x;
const float min_y = builder->dy + node->bounds.origin.y;
const float max_x = min_x + node->bounds.size.width;
const float max_y = min_y + node->bounds.size.height;
const GdkRGBA *colors = gsk_border_node_peek_colors (node);
const GskRoundedRect *rounded_outline = gsk_border_node_peek_outline (node);
- const float *og_widths = gsk_border_node_peek_widths (node);
- float widths[4];
+ const float *widths = gsk_border_node_peek_widths (node);
int i;
struct {
float w;
float h;
} sizes[4];
- if (og_widths[0] == og_widths[1] &&
- og_widths[0] == og_widths[2] &&
- og_widths[0] == og_widths[3] &&
+ if (widths[0] == widths[1] &&
+ widths[0] == widths[2] &&
+ widths[0] == widths[3] &&
gdk_rgba_equal (&colors[0], &colors[1]) &&
gdk_rgba_equal (&colors[0], &colors[2]) &&
gdk_rgba_equal (&colors[0], &colors[3]))
@@ -773,7 +770,7 @@ render_border_node (GskGLRenderer *self,
op = ops_begin (builder, OP_CHANGE_INSET_SHADOW);
op->color = &colors[0];
op->outline = transform_rect (self, builder, rounded_outline);
- op->spread = og_widths[0] * scale;
+ op->spread = widths[0];
op->offset[0] = 0;
op->offset[1] = 0;
@@ -781,9 +778,6 @@ render_border_node (GskGLRenderer *self,
return;
}
- for (i = 0; i < 4; i ++)
- widths[i] = og_widths[i];
-
/* Top left */
if (widths[3] > 0)
sizes[0].w = MAX (widths[3], rounded_outline->corner[0].width);
@@ -829,9 +823,6 @@ render_border_node (GskGLRenderer *self,
else
sizes[3].h = 0;
- for (i = 0; i < 4; i ++)
- widths[i] *= scale;
-
{
const GskQuadVertex side_data[4][6] = {
/* Top */
@@ -1481,7 +1472,6 @@ render_unblurred_inset_shadow_node (GskGLRenderer *self,
GskRenderNode *node,
RenderOpBuilder *builder)
{
- const float scale = ops_get_scale (builder);
const float blur_radius = gsk_inset_shadow_node_get_blur_radius (node);
const float dx = gsk_inset_shadow_node_get_dx (node);
const float dy = gsk_inset_shadow_node_get_dy (node);
@@ -1494,9 +1484,9 @@ render_unblurred_inset_shadow_node (GskGLRenderer *self,
op = ops_begin (builder, OP_CHANGE_INSET_SHADOW);
op->color = gsk_inset_shadow_node_peek_color (node);
op->outline = transform_rect (self, builder, gsk_inset_shadow_node_peek_outline (node));
- op->spread = spread * scale;
- op->offset[0] = dx * scale;
- op->offset[1] = dy * scale;
+ op->spread = spread;
+ op->offset[0] = dx;
+ op->offset[1] = dy;
load_vertex_data (ops_draw (builder, NULL), node, builder);
}
@@ -1647,7 +1637,6 @@ render_unblurred_outset_shadow_node (GskGLRenderer *self,
GskRenderNode *node,
RenderOpBuilder *builder)
{
- const float scale = ops_get_scale (builder);
const GskRoundedRect *outline = gsk_outset_shadow_node_peek_outline (node);
const float spread = gsk_outset_shadow_node_get_spread (node);
const float dx = gsk_outset_shadow_node_get_dx (node);
@@ -1658,9 +1647,9 @@ render_unblurred_outset_shadow_node (GskGLRenderer *self,
op = ops_begin (builder, OP_CHANGE_UNBLURRED_OUTSET_SHADOW);
op->color = gsk_outset_shadow_node_peek_color (node);
op->outline = transform_rect (self, builder, outline);
- op->spread = spread * scale;
- op->offset[0] = dx * scale;
- op->offset[1] = dy * scale;
+ op->spread = spread;
+ op->offset[0] = dx;
+ op->offset[1] = dy;
load_vertex_data (ops_draw (builder, NULL), node, builder);
}
diff --git a/gsk/resources/glsl/border.glsl b/gsk/resources/glsl/border.glsl
index a47fe7e393..505c850217 100644
--- a/gsk/resources/glsl/border.glsl
+++ b/gsk/resources/glsl/border.glsl
@@ -25,6 +25,9 @@ void main() {
RoundedRect outside = create_rect(u_outline_rect);
RoundedRect inside = rounded_rect_shrink (outside, u_widths);
+ rounded_rect_transform(outside, u_modelview);
+ rounded_rect_transform(inside, u_modelview);
+
float alpha = clamp (rounded_rect_coverage (outside, f.xy) -
rounded_rect_coverage (inside, f.xy),
0.0, 1.0);
diff --git a/gsk/resources/glsl/inset_shadow.glsl b/gsk/resources/glsl/inset_shadow.glsl
index 425b140391..087798abaf 100644
--- a/gsk/resources/glsl/inset_shadow.glsl
+++ b/gsk/resources/glsl/inset_shadow.glsl
@@ -20,15 +20,21 @@ _IN_ vec4 final_color;
void main() {
vec4 f = gl_FragCoord;
- vec4 color;
f.x += u_viewport.x;
f.y = (u_viewport.y + u_viewport.w) - f.y;
RoundedRect outside = create_rect(u_outline_rect);
RoundedRect inside = rounded_rect_shrink(outside, vec4(u_spread));
- color = final_color * clamp (rounded_rect_coverage (outside, f.xy) -
- rounded_rect_coverage (inside, f.xy - u_offset),
- 0.0, 1.0);
- setOutputColor(color);
+
+ rounded_rect_offset(inside, u_offset);
+
+ rounded_rect_transform(outside, u_modelview);
+ rounded_rect_transform(inside, u_modelview);
+
+ float alpha = clamp (rounded_rect_coverage (outside, f.xy) -
+ rounded_rect_coverage (inside, f.xy),
+ 0.0, 1.0);
+
+ setOutputColor(final_color * alpha);
}
diff --git a/gsk/resources/glsl/outset_shadow.glsl b/gsk/resources/glsl/outset_shadow.glsl
index f0c5b3fede..ada444d612 100644
--- a/gsk/resources/glsl/outset_shadow.glsl
+++ b/gsk/resources/glsl/outset_shadow.glsl
@@ -26,6 +26,7 @@ void main() {
f.y = (u_viewport.y + u_viewport.w) - f.y;
RoundedRect outline = create_rect(u_outline_rect);
+ rounded_rect_transform(outline, u_modelview);
float alpha = Texture(u_source, vUv).a;
alpha *= (1.0 - clamp(rounded_rect_coverage(outline, f.xy), 0.0, 1.0));
diff --git a/gsk/resources/glsl/preamble.fs.glsl b/gsk/resources/glsl/preamble.fs.glsl
index 00a8c2135e..056a4a27b7 100644
--- a/gsk/resources/glsl/preamble.fs.glsl
+++ b/gsk/resources/glsl/preamble.fs.glsl
@@ -6,7 +6,6 @@ precision highp float;
precision highp float;
#endif
-
uniform sampler2D u_source;
uniform mat4 u_projection;
uniform mat4 u_modelview;
@@ -33,18 +32,24 @@ _IN_ vec2 vUv;
struct RoundedRect
{
vec4 bounds;
- vec4 corner_widths;
- vec4 corner_heights;
+ // Look, arrays can't be in structs if you want to return the struct
+ // from a function in gles or whatever. Just kill me.
+ vec4 corner_points1; // xy = top left, zw = top right
+ vec4 corner_points2; // xy = bottom right, zw = bottom left
};
// Transform from a GskRoundedRect to a RoundedRect as we need it.
RoundedRect
-create_rect(vec4 data[3])
+create_rect(vec4[3] data)
{
vec4 bounds = vec4(data[0].xy, data[0].xy + data[0].zw);
- vec4 widths = vec4(data[1].x, data[1].z, data[2].x, data[2].z);
- vec4 heights = vec4(data[1].y, data[1].w, data[2].y, data[2].w);
- return RoundedRect(bounds, widths, heights);
+
+ vec4 corner_points1 = vec4(bounds.xy + data[1].xy,
+ bounds.zy + vec2(data[1].zw * vec2(-1, 1)));
+ vec4 corner_points2 = vec4(bounds.zw + (data[2].xy * vec2(-1, -1)),
+ bounds.xw + vec2(data[2].zw * vec2(1, -1)));
+
+ return RoundedRect(bounds, corner_points1, corner_points2);
}
float
@@ -73,15 +78,15 @@ rounded_rect_coverage (RoundedRect r, vec2 p)
p.x >= r.bounds.z || p.y >= r.bounds.w)
return 0.0;
- vec2 rad_tl = vec2(r.corner_widths.x, r.corner_heights.x);
- vec2 rad_tr = vec2(r.corner_widths.y, r.corner_heights.y);
- vec2 rad_br = vec2(r.corner_widths.z, r.corner_heights.z);
- vec2 rad_bl = vec2(r.corner_widths.w, r.corner_heights.w);
+ vec2 rad_tl = r.corner_points1.xy - r.bounds.xy;
+ vec2 rad_tr = r.corner_points1.zw - r.bounds.zy;
+ vec2 rad_br = r.corner_points2.xy - r.bounds.zw;
+ vec2 rad_bl = r.corner_points2.zw - r.bounds.xw;
- vec2 ref_tl = r.bounds.xy + vec2( r.corner_widths.x, r.corner_heights.x);
- vec2 ref_tr = r.bounds.zy + vec2(-r.corner_widths.y, r.corner_heights.y);
- vec2 ref_br = r.bounds.zw + vec2(-r.corner_widths.z, -r.corner_heights.z);
- vec2 ref_bl = r.bounds.xw + vec2( r.corner_widths.w, -r.corner_heights.w);
+ vec2 ref_tl = r.corner_points1.xy;
+ vec2 ref_tr = r.corner_points1.zw;
+ vec2 ref_br = r.corner_points2.xy;
+ vec2 ref_bl = r.corner_points2.zw;
float d_tl = ellipsis_coverage(p, ref_tl, rad_tl);
float d_tr = ellipsis_coverage(p, ref_tr, rad_tr);
@@ -103,26 +108,38 @@ RoundedRect
rounded_rect_shrink (RoundedRect r, vec4 amount)
{
vec4 new_bounds = r.bounds + vec4(1.0,1.0,-1.0,-1.0) * amount.wxyz;
- vec4 new_widths = vec4(0);
- vec4 new_heights = vec4(0);
+ vec4 new_corner_points1 = r.corner_points1;
+ vec4 new_corner_points2 = r.corner_points2;
- // Left top
- if (r.corner_widths.x > 0.0) new_widths.x = r.corner_widths.x - amount.w;
- if (r.corner_heights.x > 0.0) new_heights.x = r.corner_heights.x - amount.x;
+ if (r.corner_points1.xy == r.bounds.xy) new_corner_points1.xy = new_bounds.xy;
+ if (r.corner_points1.zw == r.bounds.zy) new_corner_points1.zw = new_bounds.zy;
+ if (r.corner_points2.xy == r.bounds.zw) new_corner_points2.xy = new_bounds.zw;
+ if (r.corner_points2.zw == r.bounds.xw) new_corner_points2.zw = new_bounds.xw;
- // Top right
- if (r.corner_widths.y > 0.0) new_widths.y = r.corner_widths.y - amount.y;
- if (r.corner_heights.y > 0.0) new_heights.y = r.corner_heights.y - amount.x;
+ return RoundedRect (new_bounds, new_corner_points1, new_corner_points2);
+}
- // Bottom right
- if (r.corner_widths.z > 0.0) new_widths.z = r.corner_widths.z - amount.y;
- if (r.corner_heights.z > 0.0) new_heights.z = r.corner_heights.z - amount.z;
+void
+rounded_rect_offset(inout RoundedRect r, vec2 offset)
+{
+ r.bounds.xy += offset;
+ r.bounds.zw += offset;
+ r.corner_points1.xy += offset;
+ r.corner_points1.zw += offset;
+ r.corner_points2.xy += offset;
+ r.corner_points2.zw += offset;
+}
+
+void rounded_rect_transform(inout RoundedRect r, mat4 mat)
+{
+ r.bounds.xy = (mat * vec4(r.bounds.xy, 0.0, 1.0)).xy;
+ r.bounds.zw = (mat * vec4(r.bounds.zw, 0.0, 1.0)).xy;
- // Bottom left
- if (r.corner_widths.w > 0.0) new_widths.w = r.corner_widths.w - amount.w;
- if (r.corner_heights.w > 0.0) new_heights.w = r.corner_heights.w - amount.z;
+ r.corner_points1.xy = (mat * vec4(r.corner_points1.xy, 0.0, 1.0)).xy;
+ r.corner_points1.zw = (mat * vec4(r.corner_points1.zw, 0.0, 1.0)).xy;
- return RoundedRect (new_bounds, new_widths, new_heights);
+ r.corner_points2.xy = (mat * vec4(r.corner_points2.xy, 0.0, 1.0)).xy;
+ r.corner_points2.zw = (mat * vec4(r.corner_points2.zw, 0.0, 1.0)).xy;
}
vec4 Texture(sampler2D sampler, vec2 texCoords) {
@@ -141,6 +158,9 @@ void setOutputColor(vec4 color) {
f.x += u_viewport.x;
f.y = (u_viewport.y + u_viewport.w) - f.y;
+
+ // We do *NOT* transform the clip rect here since we already
+ // need to do that on the CPU.
#if GSK_GLES
gl_FragColor = color * rounded_rect_coverage(create_rect(u_clip_rect), f.xy);
#elif GSK_LEGACY
diff --git a/gsk/resources/glsl/unblurred_outset_shadow.glsl b/gsk/resources/glsl/unblurred_outset_shadow.glsl
index f48288d05c..c5190d392e 100644
--- a/gsk/resources/glsl/unblurred_outset_shadow.glsl
+++ b/gsk/resources/glsl/unblurred_outset_shadow.glsl
@@ -20,15 +20,21 @@ _IN_ vec4 final_color;
void main() {
vec4 f = gl_FragCoord;
- vec4 color;
f.x += u_viewport.x;
f.y = (u_viewport.y + u_viewport.w) - f.y;
RoundedRect inside = create_rect(u_outline_rect);
RoundedRect outside = rounded_rect_shrink(inside, vec4(- u_spread));
- color = final_color * clamp (rounded_rect_coverage (outside, f.xy - u_offset) -
- rounded_rect_coverage (inside, f.xy),
- 0.0, 1.0);
- setOutputColor(color);
+
+ rounded_rect_offset(outside, u_offset);
+
+ rounded_rect_transform(outside, u_modelview);
+ rounded_rect_transform(inside, u_modelview);
+
+ float alpha = clamp (rounded_rect_coverage (outside, f.xy) -
+ rounded_rect_coverage (inside, f.xy),
+ 0.0, 1.0);
+
+ setOutputColor(final_color * alpha);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]