Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Decompose repeated images and gradients into brush segments in most cases. #2572

Closed
wants to merge 7 commits into from
@@ -7,7 +7,8 @@
void brush_vs(
VertexInfo vi,
int prim_address,
RectWithSize local_rect,
RectWithSize prim_local_rect,
RectWithSize segment_local_rect,
ivec3 user_data,
mat4 transform,
PictureTask pic_task
@@ -18,6 +19,9 @@ void brush_vs(

#define BRUSH_FLAG_PERSPECTIVE_INTERPOLATION 1

#define SEGMENT_SOURCE_AUTO 0
#define SEGMENT_SOURCE_FULL 1

struct BrushInstance {
int picture_address;
int prim_address;
@@ -146,6 +150,7 @@ void main(void) {
vi,
brush.prim_address + VECS_PER_BRUSH_PRIM,
brush_prim.local_rect,
local_segment_rect,
brush.user_data,
scroll_node.transform,
pic_task
@@ -20,7 +20,8 @@ flat varying vec4 vUvClipBounds;
void brush_vs(
VertexInfo vi,
int prim_address,
RectWithSize local_rect,
RectWithSize prim_local_rect,
RectWithSize segment_local_rect,
ivec3 user_data,
mat4 transform,
PictureTask pic_task
@@ -57,11 +57,21 @@ vec2 transform_point_snapped(
void brush_vs(
VertexInfo vi,
int prim_address,
RectWithSize local_rect,
RectWithSize prim_local_rect,
RectWithSize segment_local_rect,
ivec3 user_data,
mat4 transform,
PictureTask pic_task
) {
// We will derive the uv coordinates from the local rect, using either the segment or
// the primitive's local rect depending on whether we want each segment to sample from
// the entire image or parts of it.
RectWithSize local_rect = prim_local_rect;
int segment_source = (user_data.y >> 8) & 0xff;
if (segment_source == SEGMENT_SOURCE_FULL) {
local_rect = segment_local_rect;
}

// If this is in WR_FEATURE_TEXTURE_RECT mode, the rect and size use
// non-normalized texture coordinates.
#ifdef WR_FEATURE_TEXTURE_RECT
@@ -89,8 +99,8 @@ void brush_vs(
vec2 f;

#ifdef WR_FEATURE_ALPHA_PASS
int image_source = user_data.y >> 16;
int raster_space = user_data.y & 0xffff;
int image_source = (user_data.y >> 16) & 0xff;
int raster_space = user_data.y & 0xff;

// Derive the texture coordinates for this image, based on
// whether the source image is a local-space or screen-space
@@ -33,14 +33,20 @@ Gradient fetch_gradient(int address) {
void brush_vs(
VertexInfo vi,
int prim_address,
RectWithSize local_rect,
RectWithSize prim_local_rect,
RectWithSize segment_local_rect,
ivec3 user_data,
mat4 transform,
PictureTask pic_task
) {
vec2 origin = prim_local_rect.p0;
if (user_data.y == SEGMENT_SOURCE_FULL) {
origin = segment_local_rect.p0;
}

Gradient gradient = fetch_gradient(prim_address);

vPos = vi.local_pos - local_rect.p0;
vPos = vi.local_pos - origin;

vec2 start_point = gradient.start_end_point.xy;
vec2 end_point = gradient.start_end_point.zw;
@@ -15,7 +15,8 @@ flat varying int vOp;
void brush_vs(
VertexInfo vi,
int prim_address,
RectWithSize local_rect,
RectWithSize prim_local_rect,
RectWithSize segment_local_rect,
ivec3 user_data,
mat4 transform,
PictureTask pic_task
@@ -34,14 +34,20 @@ RadialGradient fetch_radial_gradient(int address) {
void brush_vs(
VertexInfo vi,
int prim_address,
RectWithSize local_rect,
RectWithSize prim_local_rect,
RectWithSize segment_local_rect,
ivec3 user_data,
mat4 transform,
PictureTask pic_task
) {
vec2 origin = prim_local_rect.p0;
if (user_data.y == SEGMENT_SOURCE_FULL) {
origin = segment_local_rect.p0;
}

RadialGradient gradient = fetch_radial_gradient(prim_address);

vPos = vi.local_pos - local_rect.p0;
vPos = vi.local_pos - origin;

vCenter = gradient.center_start_end_radius.xy;
vStartRadius = gradient.center_start_end_radius.z;
@@ -26,7 +26,8 @@ SolidBrush fetch_solid_primitive(int address) {
void brush_vs(
VertexInfo vi,
int prim_address,
RectWithSize local_rect,
RectWithSize prim_local_rect,
RectWithSize segment_local_rect,
ivec3 user_data,
mat4 transform,
PictureTask pic_task
@@ -73,12 +73,13 @@ void write_uv_rect(
void brush_vs(
VertexInfo vi,
int prim_address,
RectWithSize local_rect,
RectWithSize prim_local_rect,
RectWithSize segment_local_rect,
ivec3 user_data,
mat4 transform,
PictureTask pic_task
) {
vec2 f = (vi.local_pos - local_rect.p0) / local_rect.size;
vec2 f = (vi.local_pos - prim_local_rect.p0) / prim_local_rect.size;

#ifdef WR_FEATURE_ALPHA_PASS
vLocalPos = vi.local_pos;
@@ -19,7 +19,7 @@ use internal_types::{FastHashMap, SavedTargetIndex, SourceTexture};
use picture::{PictureCompositeMode, PicturePrimitive};
use plane_split::{BspSplitter, Polygon, Splitter};
use prim_store::{CachedGradient, ImageSource, PrimitiveIndex, PrimitiveKind, PrimitiveMetadata, PrimitiveStore};
use prim_store::{BrushPrimitive, BrushKind, DeferredResolve, EdgeAaSegmentMask, PictureIndex, PrimitiveRun};
use prim_store::{BrushPrimitive, BrushKind, DeferredResolve, EdgeAaSegmentMask, PictureIndex, PrimitiveRun, SegmentSrc};
use render_task::{RenderTaskAddress, RenderTaskId, RenderTaskKind, RenderTaskTree};
use renderer::{BlendMode, ImageBufferKind};
use renderer::BLOCKS_PER_UV_RECT;
@@ -47,7 +47,7 @@ pub enum TransformBatchKind {
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub enum BrushImageSourceKind {
Color = 0,
//Alpha = 1, // Unused for now, but left here as shaders need to match.
//Alpha = 0x1, // Unused for now, but left here as shaders need to match.
ColorAlphaMask = 2,
}

@@ -938,6 +938,106 @@ impl AlphaBatchBuilder {
);
}
}
BrushKind::Image { request, ref visible_tiles, .. } => {

let segment_src = match brush.segment_desc {
Some(ref desc) => { desc.src }
None => SegmentSrc::Auto,
};

if visible_tiles.is_empty() {
if let Some((batch_kind, textures, user_data)) = get_image_brush_params(
ctx.resource_cache,
gpu_cache,
deferred_resolves,
segment_src,
request
) {
self.add_brush_to_batch(
brush,
prim_metadata,
batch_kind,
specified_blend_mode,
non_segmented_blend_mode,
textures,
clip_chain_rect_index,
clip_task_address,
&task_relative_bounding_rect,
prim_cache_address,
scroll_id,
task_address,
transform_kind,
z,
render_tasks,
user_data,
);
}
} else {
self.batch_list.add_bounding_rect(&task_relative_bounding_rect);

let segments = &brush.segment_desc.as_ref().unwrap().segments;

let mut i = 0;
for (&tile_offset, segment) in visible_tiles.iter().zip(segments.iter()) {
if let Some((batch_kind, textures, user_data)) = get_image_brush_params(
ctx.resource_cache,
gpu_cache,
deferred_resolves,
segment_src,
request.with_tile(tile_offset),
) {

let is_inner = segment.edge_flags.is_empty();
let needs_blending = !prim_metadata.opacity.is_opaque ||
segment.clip_task_id.is_some() ||
(!is_inner && transform_kind == TransformedRectKind::Complex);

let clip_task_address = segment
.clip_task_id
.map_or(OPAQUE_TASK_ADDRESS, |id| render_tasks.get_task_address(id));

let batch_key = BatchKey {
blend_mode: if needs_blending {
non_segmented_blend_mode
} else {
BlendMode::None
},
kind: BatchKind::Brush(batch_kind),
textures,
};

let instance = PrimitiveInstance::from(BrushInstance {
picture_address: task_address,
prim_address: prim_cache_address,
clip_chain_rect_index,
scroll_id,
clip_task_address,
z,
brush_flags: BrushFlags::PERSPECTIVE_INTERPOLATION,
user_data,
segment_index: i as i32,
edge_flags: segment.edge_flags,
});

if needs_blending {
let alpha_batch = self.batch_list.alpha_batch_list.get_suitable_batch(
batch_key,
&task_relative_bounding_rect
);
alpha_batch.push(instance);
} else {
let opaque_batch = self.batch_list.opaque_batch_list.get_suitable_batch(
batch_key,
&task_relative_bounding_rect
);
opaque_batch.push(instance);
}
}

i += 1;
}
}
}
_ => {
if let Some((batch_kind, textures, user_data)) = brush.get_batch_params(
ctx.resource_cache,
@@ -1254,30 +1354,8 @@ impl BrushPrimitive {
cached_gradients: &[CachedGradient],
) -> Option<(BrushBatchKind, BatchTextures, [i32; 3])> {
match self.kind {
BrushKind::Image { request, .. } => {
let cache_item = resolve_image(
request,
resource_cache,
gpu_cache,
deferred_resolves,
);

if cache_item.texture_id == SourceTexture::Invalid {
None
} else {
let textures = BatchTextures::color(cache_item.texture_id);

Some((
BrushBatchKind::Image(get_buffer_kind(cache_item.texture_id)),
textures,
[
cache_item.uv_rect_handle.as_int(gpu_cache),
(BrushImageSourceKind::Color as i32) << 16|
RasterizationSpace::Local as i32,
0,
],
))
}
BrushKind::Image { .. } => {
panic!("bug: get_batch_key is handled at higher level for images");
}
BrushKind::Picture { .. } => {
panic!("bug: get_batch_key is handled at higher level for pictures");
@@ -1297,25 +1375,35 @@ impl BrushPrimitive {
))
}
BrushKind::RadialGradient { gradient_index, .. } => {
let segment_src = match self.segment_desc {
Some(ref desc) => { desc.src }
None => SegmentSrc::Auto,
};

let stops_handle = &cached_gradients[gradient_index.0].handle;
Some((
BrushBatchKind::RadialGradient,
BatchTextures::no_texture(),
[
stops_handle.as_int(gpu_cache),
0,
segment_src as i32,
0,
],
))
}
BrushKind::LinearGradient { gradient_index, .. } => {
let segment_src = match self.segment_desc {
Some(ref desc) => { desc.src }
None => SegmentSrc::Auto,
};

let stops_handle = &cached_gradients[gradient_index.0].handle;
Some((
BrushBatchKind::LinearGradient,
BatchTextures::no_texture(),
[
stops_handle.as_int(gpu_cache),
0,
segment_src as i32,
0,
],
))
@@ -1378,6 +1466,40 @@ impl BrushPrimitive {
}
}


fn get_image_brush_params(
resource_cache: &ResourceCache,
gpu_cache: &mut GpuCache,
deferred_resolves: &mut Vec<DeferredResolve>,
segment_src: SegmentSrc,
request: ImageRequest,
) -> Option<(BrushBatchKind, BatchTextures, [i32; 3])> {

let cache_item = resolve_image(
request,
resource_cache,
gpu_cache,
deferred_resolves,
);

if cache_item.texture_id == SourceTexture::Invalid {
None
} else {
let textures = BatchTextures::color(cache_item.texture_id);
Some((
BrushBatchKind::Image(get_buffer_kind(cache_item.texture_id)),
textures,
[
cache_item.uv_rect_handle.as_int(gpu_cache),
(BrushImageSourceKind::Color as i32) << 16 |
(segment_src as i32) << 8 |
RasterizationSpace::Local as i32,
0,
],
))
}
}

trait AlphaBatchHelpers {
fn get_blend_mode(
&self,
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.