gecko-dev/gfx/webrender/res/brush.glsl

150 строки
4.2 KiB
GLSL

/* 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/. */
#ifdef WR_VERTEX_SHADER
void brush_vs(
VertexInfo vi,
int prim_address,
RectWithSize local_rect,
RectWithSize segment_rect,
ivec4 user_data,
mat4 transform,
PictureTask pic_task,
int brush_flags,
vec4 segment_data
);
#define VECS_PER_SEGMENT 2
#define BRUSH_FLAG_PERSPECTIVE_INTERPOLATION 1
#define BRUSH_FLAG_SEGMENT_RELATIVE 2
#define BRUSH_FLAG_SEGMENT_REPEAT_X 4
#define BRUSH_FLAG_SEGMENT_REPEAT_Y 8
#define BRUSH_FLAG_TEXEL_RECT 16
void main(void) {
// Load the brush instance from vertex attributes.
int prim_header_address = aData.x;
int clip_address = aData.y;
int segment_index = aData.z & 0xffff;
int edge_flags = (aData.z >> 16) & 0xff;
int brush_flags = (aData.z >> 24) & 0xff;
int segment_user_data = aData.w;
PrimitiveHeader ph = fetch_prim_header(prim_header_address);
// Fetch the segment of this brush primitive we are drawing.
int segment_address = ph.specific_prim_address +
VECS_PER_SPECIFIC_BRUSH +
segment_index * VECS_PER_SEGMENT;
vec4[2] segment_data = fetch_from_gpu_cache_2(segment_address);
RectWithSize local_segment_rect = RectWithSize(segment_data[0].xy, segment_data[0].zw);
VertexInfo vi;
// Fetch the dynamic picture that we are drawing on.
PictureTask pic_task = fetch_picture_task(ph.render_task_index);
ClipArea clip_area = fetch_clip_area(clip_address);
Transform transform = fetch_transform(ph.transform_id);
// Write the normal vertex information out.
if (transform.is_axis_aligned) {
vi = write_vertex(
local_segment_rect,
ph.local_clip_rect,
ph.z,
transform,
pic_task,
ph.local_rect
);
// TODO(gw): transform bounds may be referenced by
// the fragment shader when running in
// the alpha pass, even on non-transformed
// items. For now, just ensure it has no
// effect. We can tidy this up as we move
// more items to be brush shaders.
#ifdef WR_FEATURE_ALPHA_PASS
init_transform_vs(vec4(vec2(-1.0e16), vec2(1.0e16)));
#endif
} else {
bvec4 edge_mask = notEqual(edge_flags & ivec4(1, 2, 4, 8), ivec4(0));
vi = write_transform_vertex(
local_segment_rect,
ph.local_rect,
ph.local_clip_rect,
mix(vec4(0.0), vec4(1.0), edge_mask),
ph.z,
transform,
pic_task
);
}
// For brush instances in the alpha pass, always write
// out clip information.
// TODO(gw): It's possible that we might want alpha
// shaders that don't clip in the future,
// but it's reasonable to assume that one
// implies the other, for now.
#ifdef WR_FEATURE_ALPHA_PASS
write_clip(
vi.world_pos,
vi.snap_offset,
clip_area
);
#endif
// Run the specific brush VS code to write interpolators.
brush_vs(
vi,
ph.specific_prim_address,
ph.local_rect,
local_segment_rect,
ivec4(ph.user_data, segment_user_data),
transform.m,
pic_task,
brush_flags,
segment_data[1]
);
}
#endif
#ifdef WR_FRAGMENT_SHADER
struct Fragment {
vec4 color;
#ifdef WR_FEATURE_DUAL_SOURCE_BLENDING
vec4 blend;
#endif
};
Fragment brush_fs();
void main(void) {
#ifdef WR_FEATURE_DEBUG_OVERDRAW
oFragColor = WR_DEBUG_OVERDRAW_COLOR;
#else
// Run the specific brush FS code to output the color.
Fragment frag = brush_fs();
#ifdef WR_FEATURE_ALPHA_PASS
// Apply the clip mask
float clip_alpha = do_clip();
frag.color *= clip_alpha;
#ifdef WR_FEATURE_DUAL_SOURCE_BLENDING
oFragBlend = frag.blend * clip_alpha;
#endif
#endif
// TODO(gw): Handle pre-multiply common code here as required.
oFragColor = frag.color;
#endif
}
#endif