summaryrefslogtreecommitdiffstats
path: root/gfx/wr/webrender/res/ps_quad.glsl
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/wr/webrender/res/ps_quad.glsl')
-rw-r--r--gfx/wr/webrender/res/ps_quad.glsl287
1 files changed, 287 insertions, 0 deletions
diff --git a/gfx/wr/webrender/res/ps_quad.glsl b/gfx/wr/webrender/res/ps_quad.glsl
new file mode 100644
index 0000000000..e419e9cc49
--- /dev/null
+++ b/gfx/wr/webrender/res/ps_quad.glsl
@@ -0,0 +1,287 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#define WR_FEATURE_TEXTURE_2D
+
+#include shared,rect,transform,render_task,gpu_buffer
+
+flat varying mediump vec4 v_color;
+flat varying mediump vec4 v_uv_sample_bounds;
+flat varying lowp ivec4 v_flags;
+varying highp vec2 v_uv;
+
+#ifdef WR_VERTEX_SHADER
+
+#define EDGE_AA_LEFT 1
+#define EDGE_AA_TOP 2
+#define EDGE_AA_RIGHT 4
+#define EDGE_AA_BOTTOM 8
+
+#define PART_CENTER 0
+#define PART_LEFT 1
+#define PART_TOP 2
+#define PART_RIGHT 3
+#define PART_BOTTOM 4
+
+#define QF_IS_OPAQUE 1
+#define QF_APPLY_DEVICE_CLIP 2
+#define QF_IGNORE_DEVICE_SCALE 4
+
+#define INVALID_SEGMENT_INDEX 0xff
+
+#define AA_PIXEL_RADIUS 2.0
+
+PER_INSTANCE in ivec4 aData;
+
+struct PrimitiveInfo {
+ vec2 local_pos;
+
+ RectWithEndpoint local_prim_rect;
+ RectWithEndpoint local_clip_rect;
+
+ int edge_flags;
+};
+
+struct QuadSegment {
+ RectWithEndpoint rect;
+ vec4 uv_rect;
+};
+
+struct QuadPrimitive {
+ RectWithEndpoint bounds;
+ RectWithEndpoint clip;
+ vec4 color;
+};
+
+QuadSegment fetch_segment(int base, int index) {
+ QuadSegment seg;
+
+ vec4 texels[2] = fetch_from_gpu_buffer_2(base + 3 + index * 2);
+
+ seg.rect = RectWithEndpoint(texels[0].xy, texels[0].zw);
+ seg.uv_rect = texels[1];
+
+ return seg;
+}
+
+QuadPrimitive fetch_primitive(int index) {
+ QuadPrimitive prim;
+
+ vec4 texels[3] = fetch_from_gpu_buffer_3(index);
+
+ prim.bounds = RectWithEndpoint(texels[0].xy, texels[0].zw);
+ prim.clip = RectWithEndpoint(texels[1].xy, texels[1].zw);
+ prim.color = texels[2];
+
+ return prim;
+}
+
+struct QuadInstance {
+ // x
+ int prim_address;
+
+ // y
+ int quad_flags;
+ int edge_flags;
+ int picture_task_address;
+
+ // z
+ int part_index;
+ int z_id;
+
+ // w
+ int segment_index;
+ int transform_id;
+};
+
+QuadInstance decode_instance() {
+ QuadInstance qi = QuadInstance(
+ aData.x,
+
+ (aData.y >> 24) & 0xff,
+ (aData.y >> 16) & 0xff,
+ aData.y & 0xffff,
+
+ (aData.z >> 24) & 0xff,
+ aData.z & 0xffffff,
+
+ (aData.w >> 24) & 0xff,
+ aData.w & 0xffffff
+ );
+
+ return qi;
+}
+
+struct VertexInfo {
+ vec2 local_pos;
+};
+
+VertexInfo write_vertex(vec2 local_pos,
+ float z,
+ Transform transform,
+ vec2 content_origin,
+ RectWithEndpoint task_rect,
+ float device_pixel_scale,
+ int quad_flags) {
+ VertexInfo vi;
+
+ // Transform the current vertex to world space.
+ vec4 world_pos = transform.m * vec4(local_pos, 0.0, 1.0);
+
+ // Convert the world positions to device pixel space.
+ vec2 device_pos = world_pos.xy * device_pixel_scale;
+
+ if ((quad_flags & QF_APPLY_DEVICE_CLIP) != 0) {
+ RectWithEndpoint device_clip_rect = RectWithEndpoint(
+ content_origin,
+ content_origin + task_rect.p1 - task_rect.p0
+ );
+
+ // Clip to task rect
+ device_pos = rect_clamp(device_clip_rect, device_pos);
+
+ vi.local_pos = (transform.inv_m * vec4(device_pos / device_pixel_scale, 0.0, 1.0)).xy;
+ } else {
+ vi.local_pos = local_pos;
+ }
+
+ // Apply offsets for the render task to get correct screen location.
+ vec2 final_offset = -content_origin + task_rect.p0;
+
+ gl_Position = uTransform * vec4(device_pos + final_offset * world_pos.w, z * world_pos.w, world_pos.w);
+
+ return vi;
+}
+
+float edge_aa_offset(int edge, int flags) {
+ return ((flags & edge) != 0) ? AA_PIXEL_RADIUS : 0.0;
+}
+
+PrimitiveInfo ps_quad_main(void) {
+ QuadInstance qi = decode_instance();
+
+ Transform transform = fetch_transform(qi.transform_id);
+ PictureTask task = fetch_picture_task(qi.picture_task_address);
+ QuadPrimitive prim = fetch_primitive(qi.prim_address);
+ float z = float(qi.z_id);
+
+ QuadSegment seg;
+ if (qi.segment_index == INVALID_SEGMENT_INDEX) {
+ seg.rect = prim.bounds;
+ seg.uv_rect = vec4(0.0);
+ } else {
+ seg = fetch_segment(qi.prim_address, qi.segment_index);
+ }
+
+ // The local space rect that we will draw, which is effectively:
+ // - The tile within the primitive we will draw
+ // - Intersected with any local-space clip rect(s)
+ // - Expanded for AA edges where appropriate
+ RectWithEndpoint local_coverage_rect = seg.rect;
+
+ // Apply local clip rect
+ local_coverage_rect.p0 = max(local_coverage_rect.p0, prim.clip.p0);
+ local_coverage_rect.p1 = min(local_coverage_rect.p1, prim.clip.p1);
+ local_coverage_rect.p1 = max(local_coverage_rect.p0, local_coverage_rect.p1);
+
+ switch (qi.part_index) {
+ case PART_LEFT:
+ local_coverage_rect.p1.x = local_coverage_rect.p0.x + AA_PIXEL_RADIUS;
+#ifdef SWGL_ANTIALIAS
+ swgl_antiAlias(EDGE_AA_LEFT);
+#else
+ local_coverage_rect.p0.x -= AA_PIXEL_RADIUS;
+ local_coverage_rect.p0.y -= AA_PIXEL_RADIUS;
+ local_coverage_rect.p1.y += AA_PIXEL_RADIUS;
+#endif
+ break;
+ case PART_TOP:
+ local_coverage_rect.p0.x = local_coverage_rect.p0.x + AA_PIXEL_RADIUS;
+ local_coverage_rect.p1.x = local_coverage_rect.p1.x - AA_PIXEL_RADIUS;
+ local_coverage_rect.p1.y = local_coverage_rect.p0.y + AA_PIXEL_RADIUS;
+#ifdef SWGL_ANTIALIAS
+ swgl_antiAlias(EDGE_AA_TOP);
+#else
+ local_coverage_rect.p0.y -= AA_PIXEL_RADIUS;
+#endif
+ break;
+ case PART_RIGHT:
+ local_coverage_rect.p0.x = local_coverage_rect.p1.x - AA_PIXEL_RADIUS;
+#ifdef SWGL_ANTIALIAS
+ swgl_antiAlias(EDGE_AA_RIGHT);
+#else
+ local_coverage_rect.p1.x += AA_PIXEL_RADIUS;
+ local_coverage_rect.p0.y -= AA_PIXEL_RADIUS;
+ local_coverage_rect.p1.y += AA_PIXEL_RADIUS;
+#endif
+ break;
+ case PART_BOTTOM:
+ local_coverage_rect.p0.x = local_coverage_rect.p0.x + AA_PIXEL_RADIUS;
+ local_coverage_rect.p1.x = local_coverage_rect.p1.x - AA_PIXEL_RADIUS;
+ local_coverage_rect.p0.y = local_coverage_rect.p1.y - AA_PIXEL_RADIUS;
+#ifdef SWGL_ANTIALIAS
+ swgl_antiAlias(EDGE_AA_BOTTOM);
+#else
+ local_coverage_rect.p1.y += AA_PIXEL_RADIUS;
+#endif
+ break;
+ case PART_CENTER:
+ default:
+ local_coverage_rect.p0.x += edge_aa_offset(EDGE_AA_LEFT, qi.edge_flags);
+ local_coverage_rect.p1.x -= edge_aa_offset(EDGE_AA_RIGHT, qi.edge_flags);
+ local_coverage_rect.p0.y += edge_aa_offset(EDGE_AA_TOP, qi.edge_flags);
+ local_coverage_rect.p1.y -= edge_aa_offset(EDGE_AA_BOTTOM, qi.edge_flags);
+ break;
+ }
+
+ vec2 local_pos = mix(local_coverage_rect.p0, local_coverage_rect.p1, aPosition);
+
+ float device_pixel_scale = task.device_pixel_scale;
+ if ((qi.quad_flags & QF_IGNORE_DEVICE_SCALE) != 0) {
+ device_pixel_scale = 1.0f;
+ }
+
+ VertexInfo vi = write_vertex(
+ local_pos,
+ z,
+ transform,
+ task.content_origin,
+ task.task_rect,
+ device_pixel_scale,
+ qi.quad_flags
+ );
+
+ if (seg.uv_rect.xy == seg.uv_rect.zw) {
+ v_color = prim.color;
+ v_flags.y = 0;
+ } else {
+ v_color = vec4(1.0);
+ v_flags.y = 1;
+
+ vec2 f = (vi.local_pos - seg.rect.p0) / (seg.rect.p1 - seg.rect.p0);
+
+ vec2 uv = mix(
+ seg.uv_rect.xy,
+ seg.uv_rect.zw,
+ f
+ );
+
+ vec2 texture_size = vec2(TEX_SIZE(sColor0));
+
+ v_uv = uv / texture_size;
+
+ v_uv_sample_bounds = vec4(
+ seg.uv_rect.xy + vec2(0.5),
+ seg.uv_rect.zw - vec2(0.5)
+ ) / texture_size.xyxy;
+ }
+
+ return PrimitiveInfo(
+ vi.local_pos,
+ prim.bounds,
+ prim.clip,
+ qi.edge_flags
+ );
+}
+#endif