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

184 строки
5.7 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(
int prim_address,
vec2 local_pos,
RectWithSize local_rect,
ivec2 user_data,
PictureTask pic_task
);
#define VECS_PER_BRUSH_PRIM 2
#define VECS_PER_SEGMENT 2
struct BrushInstance {
int picture_address;
int prim_address;
int clip_chain_rect_index;
int scroll_node_id;
int clip_address;
int z;
int segment_index;
ivec2 user_data;
};
BrushInstance load_brush() {
BrushInstance bi;
bi.picture_address = aData0.x;
bi.prim_address = aData0.y;
bi.clip_chain_rect_index = aData0.z / 65536;
bi.scroll_node_id = aData0.z % 65536;
bi.clip_address = aData0.w;
bi.z = aData1.x;
bi.segment_index = aData1.y;
bi.user_data = aData1.zw;
return bi;
}
struct BrushPrimitive {
RectWithSize local_rect;
RectWithSize local_clip_rect;
};
BrushPrimitive fetch_brush_primitive(int address, int clip_chain_rect_index) {
vec4 data[2] = fetch_from_resource_cache_2(address);
RectWithSize clip_chain_rect = fetch_clip_chain_rect(clip_chain_rect_index);
RectWithSize brush_clip_rect = RectWithSize(data[1].xy, data[1].zw);
RectWithSize clip_rect = intersect_rects(clip_chain_rect, brush_clip_rect);
BrushPrimitive prim = BrushPrimitive(RectWithSize(data[0].xy, data[0].zw), clip_rect);
return prim;
}
void main(void) {
// Load the brush instance from vertex attributes.
BrushInstance brush = load_brush();
// Load the geometry for this brush. For now, this is simply the
// local rect of the primitive. In the future, this will support
// loading segment rects, and other rect formats (glyphs).
BrushPrimitive brush_prim =
fetch_brush_primitive(brush.prim_address, brush.clip_chain_rect_index);
// Fetch the segment of this brush primitive we are drawing.
int segment_address = brush.prim_address +
VECS_PER_BRUSH_PRIM +
VECS_PER_SPECIFIC_BRUSH +
brush.segment_index * VECS_PER_SEGMENT;
vec4[2] segment_data = fetch_from_resource_cache_2(segment_address);
RectWithSize local_segment_rect = RectWithSize(segment_data[0].xy, segment_data[0].zw);
vec2 device_pos, local_pos;
// Fetch the dynamic picture that we are drawing on.
PictureTask pic_task = fetch_picture_task(brush.picture_address);
ClipArea clip_area = fetch_clip_area(brush.clip_address);
if (pic_task.pic_kind_and_raster_mode > 0.0) {
local_pos = local_segment_rect.p0 + aPosition.xy * local_segment_rect.size;
// Right now - pictures only support local positions. In the future, this
// will be expanded to support transform picture types (the common kind).
device_pos = pic_task.common_data.task_rect.p0 +
uDevicePixelRatio * (local_pos - pic_task.content_origin);
#ifdef WR_FEATURE_ALPHA_PASS
write_clip(
vec2(0.0),
clip_area
);
#endif
// Write the final position transformed by the orthographic device-pixel projection.
gl_Position = uTransform * vec4(device_pos, 0.0, 1.0);
} else {
VertexInfo vi;
ClipScrollNode scroll_node = fetch_clip_scroll_node(brush.scroll_node_id);
// Write the normal vertex information out.
if (scroll_node.is_axis_aligned) {
vi = write_vertex(
local_segment_rect,
brush_prim.local_clip_rect,
float(brush.z),
scroll_node,
pic_task,
brush_prim.local_rect
);
// TODO(gw): vLocalBounds 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
vLocalBounds = vec4(vec2(-1000000.0), vec2(1000000.0));
#endif
} else {
bvec4 edge_mask = notEqual(int(segment_data[1].x) & ivec4(1, 2, 4, 8), ivec4(0));
vi = write_transform_vertex(
local_segment_rect,
brush_prim.local_rect,
brush_prim.local_clip_rect,
mix(vec4(0.0), vec4(1.0), edge_mask),
float(brush.z),
scroll_node,
pic_task
);
}
local_pos = vi.local_pos;
// 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.screen_pos,
clip_area
);
#endif
}
// Run the specific brush VS code to write interpolators.
brush_vs(
brush.prim_address + VECS_PER_BRUSH_PRIM,
local_pos,
brush_prim.local_rect,
brush.user_data,
pic_task
);
}
#endif
#ifdef WR_FRAGMENT_SHADER
vec4 brush_fs();
void main(void) {
// Run the specific brush FS code to output the color.
vec4 color = brush_fs();
#ifdef WR_FEATURE_ALPHA_PASS
// Apply the clip mask
color *= do_clip();
#endif
// TODO(gw): Handle pre-multiply common code here as required.
oFragColor = color;
}
#endif