зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1457241 - Update webrender to commit 4b65822a2f7e1fed246a492f9fe193ede2f37d74. r=jrmuizel
MozReview-Commit-ID: EIE8tuyH8Ai --HG-- extra : rebase_source : 8886acf54a54822ee1de326a6ad082edd069dea1
This commit is contained in:
Родитель
2eb85c90dd
Коммит
4e2f121981
|
@ -40,24 +40,6 @@ ImageBrushData fetch_image_data(int address) {
|
|||
return data;
|
||||
}
|
||||
|
||||
struct ImageBrushExtraData {
|
||||
RectWithSize rendered_task_rect;
|
||||
vec2 offset;
|
||||
};
|
||||
|
||||
ImageBrushExtraData fetch_image_extra_data(int address) {
|
||||
vec4[2] raw_data = fetch_from_resource_cache_2(address);
|
||||
RectWithSize rendered_task_rect = RectWithSize(
|
||||
raw_data[0].xy,
|
||||
raw_data[0].zw
|
||||
);
|
||||
ImageBrushExtraData data = ImageBrushExtraData(
|
||||
rendered_task_rect,
|
||||
raw_data[1].xy
|
||||
);
|
||||
return data;
|
||||
}
|
||||
|
||||
#ifdef WR_FEATURE_ALPHA_PASS
|
||||
vec2 transform_point_snapped(
|
||||
vec2 local_pos,
|
||||
|
@ -105,7 +87,7 @@ void brush_vs(
|
|||
max_uv - vec2(0.5)
|
||||
) / texture_size.xyxy;
|
||||
|
||||
vec2 f;
|
||||
vec2 f = (vi.local_pos - local_rect.p0) / local_rect.size;
|
||||
|
||||
#ifdef WR_FEATURE_ALPHA_PASS
|
||||
int color_mode = user_data.y >> 16;
|
||||
|
@ -121,41 +103,18 @@ void brush_vs(
|
|||
// image.
|
||||
switch (raster_space) {
|
||||
case RASTER_SCREEN: {
|
||||
ImageBrushExtraData extra_data = fetch_image_extra_data(user_data.z);
|
||||
|
||||
vec2 snapped_device_pos;
|
||||
|
||||
// For drop-shadows, we need to apply a local offset
|
||||
// in order to generate the correct screen-space UV.
|
||||
// For other effects, we can use the 1:1 mapping of
|
||||
// the vertex device position for the UV generation.
|
||||
switch (color_mode) {
|
||||
case COLOR_MODE_ALPHA: {
|
||||
vec2 local_pos = vi.local_pos - extra_data.offset;
|
||||
snapped_device_pos = transform_point_snapped(
|
||||
local_pos,
|
||||
local_rect,
|
||||
transform
|
||||
);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
snapped_device_pos = vi.snapped_device_pos;
|
||||
break;
|
||||
}
|
||||
|
||||
f = (snapped_device_pos - extra_data.rendered_task_rect.p0) / extra_data.rendered_task_rect.size;
|
||||
|
||||
// Since the screen space UVs specify an arbitrary quad, do
|
||||
// a bilinear interpolation to get the correct UV for this
|
||||
// local position.
|
||||
ImageResourceExtra extra_data = fetch_image_resource_extra(user_data.x);
|
||||
vec2 x = mix(extra_data.st_tl, extra_data.st_tr, f.x);
|
||||
vec2 y = mix(extra_data.st_bl, extra_data.st_br, f.x);
|
||||
f = mix(x, y, f.y);
|
||||
break;
|
||||
}
|
||||
case RASTER_LOCAL:
|
||||
default: {
|
||||
f = (vi.local_pos - local_rect.p0) / local_rect.size;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
f = (vi.local_pos - local_rect.p0) / local_rect.size;
|
||||
#endif
|
||||
|
||||
// Offset and scale vUv here to avoid doing it in the fragment shader.
|
||||
|
|
|
@ -58,8 +58,6 @@ void brush_vs(
|
|||
vRepeatedSize = local_rect.size / tile_repeat.xy;
|
||||
vRepeatedSize.y *= ratio_xy;
|
||||
|
||||
vPos;
|
||||
|
||||
vGradientAddress = user_data.x;
|
||||
|
||||
// Whether to repeat the gradient instead of clamping.
|
||||
|
|
|
@ -15,6 +15,7 @@ flat varying vec4 vPoint_Tangent0;
|
|||
flat varying vec4 vPoint_Tangent1;
|
||||
flat varying vec3 vDotParams;
|
||||
flat varying vec2 vAlphaMask;
|
||||
flat varying vec4 vTaskRect;
|
||||
|
||||
#ifdef WR_VERTEX_SHADER
|
||||
// Matches BorderCorner enum in border.rs
|
||||
|
@ -145,9 +146,13 @@ void main(void) {
|
|||
vec2 device_pos = world_pos.xy * uDevicePixelRatio;
|
||||
|
||||
// Position vertex within the render task area.
|
||||
vec2 final_pos = device_pos -
|
||||
area.screen_origin +
|
||||
area.common_data.task_rect.p0;
|
||||
vec2 task_rect_origin = area.common_data.task_rect.p0;
|
||||
vec2 final_pos = device_pos - area.screen_origin + task_rect_origin;
|
||||
|
||||
// We pass the task rectangle to the fragment shader so that we can do one last clip
|
||||
// in order to ensure that we don't draw outside the task rectangle.
|
||||
vTaskRect.xy = task_rect_origin;
|
||||
vTaskRect.zw = task_rect_origin + area.common_data.task_rect.size;
|
||||
|
||||
// Calculate the local space position for this vertex.
|
||||
vec4 node_pos = get_node_pos(world_pos.xy, scroll_node);
|
||||
|
@ -190,6 +195,9 @@ void main(void) {
|
|||
// Completely mask out clip if zero'ing out the rect.
|
||||
d = d * vAlphaMask.y;
|
||||
|
||||
// Make sure that we don't draw outside the task rectangle.
|
||||
d = d * point_inside_rect(gl_FragCoord.xy, vTaskRect.xy, vTaskRect.zw);
|
||||
|
||||
oFragColor = vec4(d, 0.0, 0.0, 1.0);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
uniform HIGHP_SAMPLER_FLOAT sampler2D sResourceCache;
|
||||
|
||||
#define VECS_PER_IMAGE_RESOURCE 2
|
||||
|
||||
// TODO(gw): This is here temporarily while we have
|
||||
// both GPU store and cache. When the GPU
|
||||
// store code is removed, we can change the
|
||||
|
@ -113,4 +115,23 @@ ImageResource fetch_image_resource_direct(ivec2 address) {
|
|||
return ImageResource(uv_rect, data[1].x, data[1].yzw);
|
||||
}
|
||||
|
||||
// Fetch optional extra data for a texture cache resource. This can contain
|
||||
// a polygon defining a UV rect within the texture cache resource.
|
||||
struct ImageResourceExtra {
|
||||
vec2 st_tl;
|
||||
vec2 st_tr;
|
||||
vec2 st_bl;
|
||||
vec2 st_br;
|
||||
};
|
||||
|
||||
ImageResourceExtra fetch_image_resource_extra(int address) {
|
||||
vec4 data[2] = fetch_from_resource_cache_2(address + VECS_PER_IMAGE_RESOURCE);
|
||||
return ImageResourceExtra(
|
||||
data[0].xy,
|
||||
data[0].zw,
|
||||
data[1].xy,
|
||||
data[1].zw
|
||||
);
|
||||
}
|
||||
|
||||
#endif //WR_VERTEX_SHADER
|
||||
|
|
|
@ -18,7 +18,6 @@ use gpu_types::{PrimitiveInstance, RasterizationSpace, SimplePrimitiveInstance,
|
|||
use gpu_types::ZBufferIdGenerator;
|
||||
use internal_types::{FastHashMap, SavedTargetIndex, SourceTexture};
|
||||
use picture::{PictureCompositeMode, PicturePrimitive, PictureSurface};
|
||||
use picture::{IMAGE_BRUSH_BLOCKS, IMAGE_BRUSH_EXTRA_BLOCKS};
|
||||
use plane_split::{BspSplitter, Polygon, Splitter};
|
||||
use prim_store::{CachedGradient, ImageSource, PrimitiveIndex, PrimitiveKind, PrimitiveMetadata, PrimitiveStore};
|
||||
use prim_store::{BrushPrimitive, BrushKind, DeferredResolve, EdgeAaSegmentMask, PictureIndex, PrimitiveRun};
|
||||
|
@ -700,7 +699,7 @@ impl AlphaBatchBuilder {
|
|||
uv_rect_address.as_int(),
|
||||
(ShaderColorMode::ColorBitmap as i32) << 16 |
|
||||
RasterizationSpace::Screen as i32,
|
||||
picture.extra_gpu_data_handle.as_int(gpu_cache),
|
||||
0,
|
||||
],
|
||||
};
|
||||
batch.push(PrimitiveInstance::from(instance));
|
||||
|
@ -750,11 +749,7 @@ impl AlphaBatchBuilder {
|
|||
.as_int();
|
||||
|
||||
// Get the GPU cache address of the extra data handle.
|
||||
let extra_data_address = gpu_cache.get_address(&picture.extra_gpu_data_handle);
|
||||
let shadow_prim_address = extra_data_address
|
||||
.offset(IMAGE_BRUSH_EXTRA_BLOCKS);
|
||||
let shadow_data_address = extra_data_address
|
||||
.offset(IMAGE_BRUSH_EXTRA_BLOCKS + IMAGE_BRUSH_BLOCKS);
|
||||
let shadow_prim_address = gpu_cache.get_address(&picture.extra_gpu_data_handle);
|
||||
|
||||
let shadow_instance = BrushInstance {
|
||||
picture_address: task_address,
|
||||
|
@ -770,7 +765,7 @@ impl AlphaBatchBuilder {
|
|||
shadow_uv_rect_address,
|
||||
(ShaderColorMode::Alpha as i32) << 16 |
|
||||
RasterizationSpace::Screen as i32,
|
||||
shadow_data_address.as_int(),
|
||||
0,
|
||||
],
|
||||
};
|
||||
|
||||
|
@ -780,7 +775,7 @@ impl AlphaBatchBuilder {
|
|||
content_uv_rect_address,
|
||||
(ShaderColorMode::ColorBitmap as i32) << 16 |
|
||||
RasterizationSpace::Screen as i32,
|
||||
extra_data_address.as_int(),
|
||||
0,
|
||||
],
|
||||
..shadow_instance
|
||||
};
|
||||
|
@ -953,7 +948,7 @@ impl AlphaBatchBuilder {
|
|||
uv_rect_address,
|
||||
(ShaderColorMode::ColorBitmap as i32) << 16 |
|
||||
RasterizationSpace::Screen as i32,
|
||||
picture.extra_gpu_data_handle.as_int(gpu_cache),
|
||||
0,
|
||||
],
|
||||
};
|
||||
batch.push(PrimitiveInstance::from(instance));
|
||||
|
|
|
@ -101,6 +101,9 @@ pub struct ClipScrollNode {
|
|||
/// World transform for content transformed by this node.
|
||||
pub world_content_transform: LayoutToWorldFastTransform,
|
||||
|
||||
/// The current transform kind of world_content_transform.
|
||||
pub transform_kind: TransformedRectKind,
|
||||
|
||||
/// Pipeline that this layer belongs to
|
||||
pub pipeline_id: PipelineId,
|
||||
|
||||
|
@ -142,6 +145,7 @@ impl ClipScrollNode {
|
|||
local_viewport_rect: *rect,
|
||||
world_viewport_transform: LayoutToWorldFastTransform::identity(),
|
||||
world_content_transform: LayoutToWorldFastTransform::identity(),
|
||||
transform_kind: TransformedRectKind::AxisAligned,
|
||||
parent: parent_index,
|
||||
children: Vec::new(),
|
||||
pipeline_id,
|
||||
|
@ -285,15 +289,10 @@ impl ClipScrollNode {
|
|||
}
|
||||
};
|
||||
|
||||
let transform_kind = if self.world_content_transform.preserves_2d_axis_alignment() {
|
||||
TransformedRectKind::AxisAligned
|
||||
} else {
|
||||
TransformedRectKind::Complex
|
||||
};
|
||||
let data = ClipScrollNodeData {
|
||||
transform: self.world_content_transform.into(),
|
||||
inv_transform,
|
||||
transform_kind: transform_kind as u32 as f32,
|
||||
transform_kind: self.transform_kind as u32 as f32,
|
||||
padding: [0.0; 3],
|
||||
};
|
||||
|
||||
|
@ -321,6 +320,12 @@ impl ClipScrollNode {
|
|||
|
||||
self.update_transform(state, next_coordinate_system_id, scene_properties);
|
||||
|
||||
self.transform_kind = if self.world_content_transform.preserves_2d_axis_alignment() {
|
||||
TransformedRectKind::AxisAligned
|
||||
} else {
|
||||
TransformedRectKind::Complex
|
||||
};
|
||||
|
||||
// If this node is a reference frame, we check if it has a non-invertible matrix.
|
||||
// For non-reference-frames we assume that they will produce only additional
|
||||
// translations which should be invertible.
|
||||
|
|
|
@ -1843,6 +1843,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
stops_count: usize,
|
||||
extend_mode: ExtendMode,
|
||||
gradient_index: CachedGradientIndex,
|
||||
stretch_size: LayoutSize,
|
||||
) {
|
||||
// Try to ensure that if the gradient is specified in reverse, then so long as the stops
|
||||
// are also supplied in reverse that the rendered result will be equivalent. To do this,
|
||||
|
@ -1871,6 +1872,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
start_point: sp,
|
||||
end_point: ep,
|
||||
gradient_index,
|
||||
stretch_size,
|
||||
},
|
||||
None,
|
||||
);
|
||||
|
@ -1889,43 +1891,49 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
stops: ItemRange<GradientStop>,
|
||||
stops_count: usize,
|
||||
extend_mode: ExtendMode,
|
||||
tile_size: LayoutSize,
|
||||
stretch_size: LayoutSize,
|
||||
tile_spacing: LayoutSize,
|
||||
) {
|
||||
let gradient_index = CachedGradientIndex(self.cached_gradients.len());
|
||||
self.cached_gradients.push(CachedGradient::new());
|
||||
|
||||
let prim_infos = info.decompose(
|
||||
tile_size,
|
||||
tile_spacing,
|
||||
64 * 64,
|
||||
);
|
||||
|
||||
if prim_infos.is_empty() {
|
||||
self.add_gradient_impl(
|
||||
clip_and_scroll,
|
||||
info,
|
||||
start_point,
|
||||
end_point,
|
||||
stops,
|
||||
stops_count,
|
||||
extend_mode,
|
||||
gradient_index,
|
||||
if tile_spacing != LayoutSize::zero() {
|
||||
let prim_infos = info.decompose(
|
||||
stretch_size,
|
||||
tile_spacing,
|
||||
64 * 64,
|
||||
);
|
||||
} else {
|
||||
for prim_info in prim_infos {
|
||||
self.add_gradient_impl(
|
||||
clip_and_scroll,
|
||||
&prim_info,
|
||||
start_point,
|
||||
end_point,
|
||||
stops,
|
||||
stops_count,
|
||||
extend_mode,
|
||||
gradient_index,
|
||||
);
|
||||
|
||||
if !prim_infos.is_empty() {
|
||||
for prim_info in prim_infos {
|
||||
self.add_gradient_impl(
|
||||
clip_and_scroll,
|
||||
&prim_info,
|
||||
start_point,
|
||||
end_point,
|
||||
stops,
|
||||
stops_count,
|
||||
extend_mode,
|
||||
gradient_index,
|
||||
prim_info.rect.size,
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
self.add_gradient_impl(
|
||||
clip_and_scroll,
|
||||
info,
|
||||
start_point,
|
||||
end_point,
|
||||
stops,
|
||||
stops_count,
|
||||
extend_mode,
|
||||
gradient_index,
|
||||
stretch_size,
|
||||
);
|
||||
}
|
||||
|
||||
fn add_radial_gradient_impl(
|
||||
|
@ -1939,6 +1947,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
stops: ItemRange<GradientStop>,
|
||||
extend_mode: ExtendMode,
|
||||
gradient_index: CachedGradientIndex,
|
||||
stretch_size: LayoutSize,
|
||||
) {
|
||||
let prim = BrushPrimitive::new(
|
||||
BrushKind::RadialGradient {
|
||||
|
@ -1949,6 +1958,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
end_radius,
|
||||
ratio_xy,
|
||||
gradient_index,
|
||||
stretch_size,
|
||||
},
|
||||
None,
|
||||
);
|
||||
|
@ -1971,45 +1981,51 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
ratio_xy: f32,
|
||||
stops: ItemRange<GradientStop>,
|
||||
extend_mode: ExtendMode,
|
||||
tile_size: LayoutSize,
|
||||
stretch_size: LayoutSize,
|
||||
tile_spacing: LayoutSize,
|
||||
) {
|
||||
let gradient_index = CachedGradientIndex(self.cached_gradients.len());
|
||||
self.cached_gradients.push(CachedGradient::new());
|
||||
|
||||
let prim_infos = info.decompose(
|
||||
tile_size,
|
||||
tile_spacing,
|
||||
64 * 64,
|
||||
);
|
||||
|
||||
if prim_infos.is_empty() {
|
||||
self.add_radial_gradient_impl(
|
||||
clip_and_scroll,
|
||||
info,
|
||||
center,
|
||||
start_radius,
|
||||
end_radius,
|
||||
ratio_xy,
|
||||
stops,
|
||||
extend_mode,
|
||||
gradient_index,
|
||||
if tile_spacing != LayoutSize::zero() {
|
||||
let prim_infos = info.decompose(
|
||||
stretch_size,
|
||||
tile_spacing,
|
||||
64 * 64,
|
||||
);
|
||||
} else {
|
||||
for prim_info in prim_infos {
|
||||
self.add_radial_gradient_impl(
|
||||
clip_and_scroll,
|
||||
&prim_info,
|
||||
center,
|
||||
start_radius,
|
||||
end_radius,
|
||||
ratio_xy,
|
||||
stops,
|
||||
extend_mode,
|
||||
gradient_index,
|
||||
);
|
||||
|
||||
if !prim_infos.is_empty() {
|
||||
for prim_info in prim_infos {
|
||||
self.add_radial_gradient_impl(
|
||||
clip_and_scroll,
|
||||
&prim_info,
|
||||
center,
|
||||
start_radius,
|
||||
end_radius,
|
||||
ratio_xy,
|
||||
stops,
|
||||
extend_mode,
|
||||
gradient_index,
|
||||
stretch_size,
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
self.add_radial_gradient_impl(
|
||||
clip_and_scroll,
|
||||
info,
|
||||
center,
|
||||
start_radius,
|
||||
end_radius,
|
||||
ratio_xy,
|
||||
stops,
|
||||
extend_mode,
|
||||
gradient_index,
|
||||
stretch_size,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn add_text(
|
||||
|
@ -2137,7 +2153,6 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
// See if conditions are met to run through the new
|
||||
// image brush shader, which supports segments.
|
||||
if tile_spacing == LayoutSize::zero() &&
|
||||
stretch_size == info.rect.size &&
|
||||
tile_offset.is_none() {
|
||||
let prim = BrushPrimitive::new(
|
||||
BrushKind::Image {
|
||||
|
|
|
@ -10,7 +10,7 @@ use clip_scroll_node::{ClipScrollNode};
|
|||
use clip_scroll_tree::{ClipScrollNodeIndex, ClipScrollTree};
|
||||
use display_list_flattener::{DisplayListFlattener};
|
||||
use gpu_cache::GpuCache;
|
||||
use gpu_types::{ClipChainRectIndex, ClipScrollNodeData};
|
||||
use gpu_types::{ClipChainRectIndex, ClipScrollNodeData, UvRectKind};
|
||||
use hit_test::{HitTester, HitTestingRun};
|
||||
use internal_types::{FastHashMap};
|
||||
use picture::PictureSurface;
|
||||
|
@ -233,6 +233,7 @@ impl FrameBuilder {
|
|||
PrimitiveIndex(0),
|
||||
DeviceIntPoint::zero(),
|
||||
pic_state.tasks,
|
||||
UvRectKind::Rect,
|
||||
);
|
||||
|
||||
let render_task_id = frame_state.render_tasks.add(root_render_task);
|
||||
|
|
|
@ -21,6 +21,7 @@ use device::TextureFilter;
|
|||
use euclid::{TypedPoint2D, TypedSize2D, TypedVector2D};
|
||||
use glyph_cache::{CachedGlyphInfo, GlyphCache, GlyphCacheEntry};
|
||||
use gpu_cache::GpuCache;
|
||||
use gpu_types::UvRectKind;
|
||||
use internal_types::ResourceCacheError;
|
||||
#[cfg(feature = "pathfinder")]
|
||||
use pathfinder_font_renderer;
|
||||
|
@ -800,6 +801,7 @@ impl GlyphRasterizer {
|
|||
None,
|
||||
gpu_cache,
|
||||
Some(glyph_key_cache.eviction_notice()),
|
||||
UvRectKind::Rect,
|
||||
);
|
||||
GlyphCacheEntry::Cached(CachedGlyphInfo {
|
||||
texture_cache_handle,
|
||||
|
|
|
@ -151,13 +151,6 @@ impl GpuCacheAddress {
|
|||
v: u16::MAX,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn offset(&self, offset: usize) -> Self {
|
||||
GpuCacheAddress {
|
||||
u: self.u + offset as u16,
|
||||
v: self.v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<usize> for GpuCacheAddress {
|
||||
|
|
|
@ -277,15 +277,38 @@ impl ClipScrollNodeData {
|
|||
#[repr(C)]
|
||||
pub struct ClipChainRectIndex(pub usize);
|
||||
|
||||
// Texture cache resources can be either a simple rect, or define
|
||||
// a polygon within a rect by specifying a UV coordinate for each
|
||||
// corner. This is useful for rendering screen-space rasterized
|
||||
// off-screen surfaces.
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
pub enum UvRectKind {
|
||||
// The 2d bounds of the texture cache entry define the
|
||||
// valid UV space for this texture cache entry.
|
||||
Rect,
|
||||
// The four vertices below define a quad within
|
||||
// the texture cache entry rect. The shader can
|
||||
// use a bilerp() to correctly interpolate a
|
||||
// UV coord in the vertex shader.
|
||||
Quad {
|
||||
top_left: DevicePoint,
|
||||
top_right: DevicePoint,
|
||||
bottom_left: DevicePoint,
|
||||
bottom_right: DevicePoint,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
#[repr(C)]
|
||||
pub struct ImageSource {
|
||||
pub p0: DevicePoint,
|
||||
pub p1: DevicePoint,
|
||||
pub texture_layer: f32,
|
||||
pub user_data: [f32; 3],
|
||||
pub uv_rect_kind: UvRectKind,
|
||||
}
|
||||
|
||||
impl ImageSource {
|
||||
|
@ -302,5 +325,22 @@ impl ImageSource {
|
|||
self.user_data[1],
|
||||
self.user_data[2],
|
||||
]);
|
||||
|
||||
// If this is a polygon uv kind, then upload the four vertices.
|
||||
if let UvRectKind::Quad { top_left, top_right, bottom_left, bottom_right } = self.uv_rect_kind {
|
||||
request.push([
|
||||
top_left.x,
|
||||
top_left.y,
|
||||
top_right.x,
|
||||
top_right.y,
|
||||
]);
|
||||
|
||||
request.push([
|
||||
bottom_left.x,
|
||||
bottom_left.y,
|
||||
bottom_right.x,
|
||||
bottom_right.y,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,13 +2,15 @@
|
|||
* 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/. */
|
||||
|
||||
use api::{FilterOp, MixBlendMode, PipelineId, PremultipliedColorF};
|
||||
use api::{DeviceIntRect, DeviceIntSize, LayoutRect};
|
||||
use api::{PictureIntPoint, PictureIntRect, PictureIntSize};
|
||||
use api::{DeviceRect, FilterOp, MixBlendMode, PipelineId, PremultipliedColorF};
|
||||
use api::{DeviceIntRect, DeviceIntSize, DevicePoint, LayoutPoint, LayoutRect};
|
||||
use api::{DevicePixelScale, PictureIntPoint, PictureIntRect, PictureIntSize};
|
||||
use box_shadow::{BLUR_SAMPLE_SCALE};
|
||||
use clip_scroll_node::ClipScrollNode;
|
||||
use clip_scroll_tree::ClipScrollNodeIndex;
|
||||
use frame_builder::{FrameBuildingContext, FrameBuildingState, PictureState};
|
||||
use frame_builder::{FrameBuildingContext, FrameBuildingState, PictureState, PrimitiveRunContext};
|
||||
use gpu_cache::{GpuCacheHandle};
|
||||
use gpu_types::UvRectKind;
|
||||
use prim_store::{PrimitiveIndex, PrimitiveRun, PrimitiveRunLocalRect};
|
||||
use prim_store::{PrimitiveMetadata, ScrollNodeAndClipChain};
|
||||
use render_task::{ClearMode, RenderTask, RenderTaskCacheEntryHandle};
|
||||
|
@ -16,6 +18,7 @@ use render_task::{RenderTaskCacheKey, RenderTaskCacheKeyKind, RenderTaskId, Rend
|
|||
use scene::{FilterOpHelpers, SceneProperties};
|
||||
use std::mem;
|
||||
use tiling::RenderTargetKind;
|
||||
use util::TransformedRectKind;
|
||||
|
||||
/*
|
||||
A picture represents a dynamically rendered image. It consists of:
|
||||
|
@ -27,9 +30,6 @@ use tiling::RenderTargetKind;
|
|||
this picture (e.g. in screen space or local space).
|
||||
*/
|
||||
|
||||
pub const IMAGE_BRUSH_EXTRA_BLOCKS: usize = 2;
|
||||
pub const IMAGE_BRUSH_BLOCKS: usize = 6;
|
||||
|
||||
/// Specifies how this Picture should be composited
|
||||
/// onto the target it belongs to.
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
|
@ -127,10 +127,6 @@ pub struct PicturePrimitive {
|
|||
// in this picture.
|
||||
pub apply_local_clip_rect: bool,
|
||||
|
||||
// The current screen-space rect of the rendered
|
||||
// portion of this picture.
|
||||
task_rect: DeviceIntRect,
|
||||
|
||||
// If a mix-blend-mode, contains the render task for
|
||||
// the readback of the framebuffer that we use to sample
|
||||
// from in the mix-blend-mode shader.
|
||||
|
@ -199,7 +195,6 @@ impl PicturePrimitive {
|
|||
extra_gpu_data_handle: GpuCacheHandle::new(),
|
||||
apply_local_clip_rect,
|
||||
pipeline_id,
|
||||
task_rect: DeviceIntRect::zero(),
|
||||
id,
|
||||
}
|
||||
}
|
||||
|
@ -281,11 +276,12 @@ impl PicturePrimitive {
|
|||
&mut self,
|
||||
prim_index: PrimitiveIndex,
|
||||
prim_metadata: &mut PrimitiveMetadata,
|
||||
prim_run_context: &PrimitiveRunContext,
|
||||
mut pic_state_for_children: PictureState,
|
||||
pic_state: &mut PictureState,
|
||||
frame_context: &FrameBuildingContext,
|
||||
frame_state: &mut FrameBuildingState,
|
||||
) -> Option<DeviceIntRect> {
|
||||
) {
|
||||
let prim_screen_rect = prim_metadata
|
||||
.screen_rect
|
||||
.as_ref()
|
||||
|
@ -293,10 +289,9 @@ impl PicturePrimitive {
|
|||
if self.can_draw_directly_to_parent_surface() {
|
||||
pic_state.tasks.extend(pic_state_for_children.tasks);
|
||||
self.surface = None;
|
||||
return None;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// TODO(gw): Almost all of the Picture types below use extra_gpu_cache_data
|
||||
// to store the same type of data. The exception is the filter
|
||||
// with a ColorMatrix, which stores the color matrix here. It's
|
||||
|
@ -322,6 +317,13 @@ impl PicturePrimitive {
|
|||
.intersection(&prim_screen_rect.unclipped)
|
||||
.unwrap();
|
||||
|
||||
let uv_rect_kind = calculate_uv_rect_kind(
|
||||
&prim_metadata.local_rect,
|
||||
&prim_run_context.scroll_node,
|
||||
&device_rect,
|
||||
frame_context.device_pixel_scale,
|
||||
);
|
||||
|
||||
// If we are drawing a blur that has primitives or clips that contain
|
||||
// a complex coordinate system, don't bother caching them (for now).
|
||||
// It's likely that they are animating and caching may not help here
|
||||
|
@ -334,6 +336,7 @@ impl PicturePrimitive {
|
|||
prim_index,
|
||||
device_rect.origin,
|
||||
pic_state_for_children.tasks,
|
||||
uv_rect_kind,
|
||||
);
|
||||
|
||||
let picture_task_id = frame_state.render_tasks.add(picture_task);
|
||||
|
@ -388,6 +391,7 @@ impl PicturePrimitive {
|
|||
prim_index,
|
||||
device_rect.origin,
|
||||
child_tasks,
|
||||
uv_rect_kind,
|
||||
);
|
||||
|
||||
let picture_task_id = render_tasks.add(picture_task);
|
||||
|
@ -412,10 +416,8 @@ impl PicturePrimitive {
|
|||
};
|
||||
|
||||
self.surface = Some(surface);
|
||||
|
||||
Some(device_rect)
|
||||
}
|
||||
Some(PictureCompositeMode::Filter(FilterOp::DropShadow(_, blur_radius, _))) => {
|
||||
Some(PictureCompositeMode::Filter(FilterOp::DropShadow(offset, blur_radius, color))) => {
|
||||
let blur_std_deviation = blur_radius * frame_context.device_pixel_scale.0;
|
||||
let blur_range = (blur_std_deviation * BLUR_SAMPLE_SCALE).ceil() as i32;
|
||||
|
||||
|
@ -433,11 +435,19 @@ impl PicturePrimitive {
|
|||
.intersection(&prim_screen_rect.unclipped)
|
||||
.unwrap();
|
||||
|
||||
let uv_rect_kind = calculate_uv_rect_kind(
|
||||
&prim_metadata.local_rect,
|
||||
&prim_run_context.scroll_node,
|
||||
&device_rect,
|
||||
frame_context.device_pixel_scale,
|
||||
);
|
||||
|
||||
let mut picture_task = RenderTask::new_picture(
|
||||
RenderTaskLocation::Dynamic(None, Some(device_rect.size)),
|
||||
prim_index,
|
||||
device_rect.origin,
|
||||
pic_state_for_children.tasks,
|
||||
uv_rect_kind,
|
||||
);
|
||||
picture_task.mark_for_saving();
|
||||
|
||||
|
@ -457,112 +467,7 @@ impl PicturePrimitive {
|
|||
pic_state.tasks.push(render_task_id);
|
||||
self.surface = Some(PictureSurface::RenderTask(render_task_id));
|
||||
|
||||
Some(device_rect)
|
||||
}
|
||||
Some(PictureCompositeMode::MixBlend(..)) => {
|
||||
let picture_task = RenderTask::new_picture(
|
||||
RenderTaskLocation::Dynamic(None, Some(prim_screen_rect.clipped.size)),
|
||||
prim_index,
|
||||
prim_screen_rect.clipped.origin,
|
||||
pic_state_for_children.tasks,
|
||||
);
|
||||
|
||||
let readback_task_id = frame_state.render_tasks.add(
|
||||
RenderTask::new_readback(prim_screen_rect.clipped)
|
||||
);
|
||||
|
||||
self.secondary_render_task_id = Some(readback_task_id);
|
||||
pic_state.tasks.push(readback_task_id);
|
||||
|
||||
let render_task_id = frame_state.render_tasks.add(picture_task);
|
||||
pic_state.tasks.push(render_task_id);
|
||||
self.surface = Some(PictureSurface::RenderTask(render_task_id));
|
||||
|
||||
Some(prim_screen_rect.clipped)
|
||||
}
|
||||
Some(PictureCompositeMode::Filter(filter)) => {
|
||||
let device_rect = match filter {
|
||||
FilterOp::ColorMatrix(m) => {
|
||||
if let Some(mut request) = frame_state.gpu_cache.request(&mut self.extra_gpu_data_handle) {
|
||||
for i in 0..5 {
|
||||
request.push([m[i*4], m[i*4+1], m[i*4+2], m[i*4+3]]);
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
_ => Some(prim_screen_rect.clipped),
|
||||
};
|
||||
|
||||
let picture_task = RenderTask::new_picture(
|
||||
RenderTaskLocation::Dynamic(None, Some(prim_screen_rect.clipped.size)),
|
||||
prim_index,
|
||||
prim_screen_rect.clipped.origin,
|
||||
pic_state_for_children.tasks,
|
||||
);
|
||||
|
||||
let render_task_id = frame_state.render_tasks.add(picture_task);
|
||||
pic_state.tasks.push(render_task_id);
|
||||
self.surface = Some(PictureSurface::RenderTask(render_task_id));
|
||||
|
||||
device_rect
|
||||
}
|
||||
Some(PictureCompositeMode::Blit) | None => {
|
||||
let picture_task = RenderTask::new_picture(
|
||||
RenderTaskLocation::Dynamic(None, Some(prim_screen_rect.clipped.size)),
|
||||
prim_index,
|
||||
prim_screen_rect.clipped.origin,
|
||||
pic_state_for_children.tasks,
|
||||
);
|
||||
|
||||
let render_task_id = frame_state.render_tasks.add(picture_task);
|
||||
pic_state.tasks.push(render_task_id);
|
||||
self.surface = Some(PictureSurface::RenderTask(render_task_id));
|
||||
|
||||
Some(prim_screen_rect.clipped)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn prepare_for_render(
|
||||
&mut self,
|
||||
prim_index: PrimitiveIndex,
|
||||
prim_metadata: &mut PrimitiveMetadata,
|
||||
pic_state_for_children: PictureState,
|
||||
pic_state: &mut PictureState,
|
||||
frame_context: &FrameBuildingContext,
|
||||
frame_state: &mut FrameBuildingState,
|
||||
) {
|
||||
let device_rect = self.prepare_for_render_inner(
|
||||
prim_index,
|
||||
prim_metadata,
|
||||
pic_state_for_children,
|
||||
pic_state,
|
||||
frame_context,
|
||||
frame_state,
|
||||
);
|
||||
|
||||
// If this picture type uses the common / general GPU data
|
||||
// format, then write it now.
|
||||
if let Some(device_rect) = device_rect {
|
||||
// If scrolling or property animation has resulted in the task
|
||||
// rect being different than last time, invalidate the GPU
|
||||
// cache entry for this picture to ensure that the correct
|
||||
// task rect is provided to the image shader.
|
||||
if self.task_rect != device_rect {
|
||||
frame_state.gpu_cache.invalidate(&self.extra_gpu_data_handle);
|
||||
self.task_rect = device_rect;
|
||||
}
|
||||
|
||||
if let Some(mut request) = frame_state.gpu_cache.request(&mut self.extra_gpu_data_handle) {
|
||||
// [GLSL ImageBrushExtraData: task_rect, offset]
|
||||
request.push(self.task_rect.to_f32());
|
||||
request.push([0.0; 4]);
|
||||
|
||||
// TODO(gw): It would make the shaders a bit simpler if the offset
|
||||
// was provided as part of the brush::picture instance,
|
||||
// rather than in the Picture data itself.
|
||||
if let Some(PictureCompositeMode::Filter(FilterOp::DropShadow(offset, _, color))) = self.composite_mode {
|
||||
if let Some(mut request) = frame_state.gpu_cache.request(&mut self.extra_gpu_data_handle) {
|
||||
// TODO(gw): This is very hacky code below! It stores an extra
|
||||
// brush primitive below for the special case of a
|
||||
// drop-shadow where we need a different local
|
||||
|
@ -570,9 +475,6 @@ impl PicturePrimitive {
|
|||
// we could consider abstracting the code in prim_store.rs
|
||||
// that writes a brush primitive header.
|
||||
|
||||
// NOTE: If any of the layout below changes, the IMAGE_BRUSH_EXTRA_BLOCKS and
|
||||
// IMAGE_BRUSH_BLOCKS fields above *must* be updated.
|
||||
|
||||
// Basic brush primitive header is (see end of prepare_prim_for_render_inner in prim_store.rs)
|
||||
// local_rect
|
||||
// clip_rect
|
||||
|
@ -592,12 +494,175 @@ impl PicturePrimitive {
|
|||
// segment rect / repetitions
|
||||
request.push(shadow_rect);
|
||||
request.push([1.0, 1.0, 0.0, 0.0]);
|
||||
|
||||
// Now write another GLSL ImageBrush struct, for the shadow to reference.
|
||||
request.push(self.task_rect.to_f32());
|
||||
request.push([offset.x, offset.y, 0.0, 0.0]);
|
||||
}
|
||||
}
|
||||
Some(PictureCompositeMode::MixBlend(..)) => {
|
||||
let uv_rect_kind = calculate_uv_rect_kind(
|
||||
&prim_metadata.local_rect,
|
||||
&prim_run_context.scroll_node,
|
||||
&prim_screen_rect.clipped,
|
||||
frame_context.device_pixel_scale,
|
||||
);
|
||||
|
||||
let picture_task = RenderTask::new_picture(
|
||||
RenderTaskLocation::Dynamic(None, Some(prim_screen_rect.clipped.size)),
|
||||
prim_index,
|
||||
prim_screen_rect.clipped.origin,
|
||||
pic_state_for_children.tasks,
|
||||
uv_rect_kind,
|
||||
);
|
||||
|
||||
let readback_task_id = frame_state.render_tasks.add(
|
||||
RenderTask::new_readback(prim_screen_rect.clipped)
|
||||
);
|
||||
|
||||
self.secondary_render_task_id = Some(readback_task_id);
|
||||
pic_state.tasks.push(readback_task_id);
|
||||
|
||||
let render_task_id = frame_state.render_tasks.add(picture_task);
|
||||
pic_state.tasks.push(render_task_id);
|
||||
self.surface = Some(PictureSurface::RenderTask(render_task_id));
|
||||
}
|
||||
Some(PictureCompositeMode::Filter(filter)) => {
|
||||
if let FilterOp::ColorMatrix(m) = filter {
|
||||
if let Some(mut request) = frame_state.gpu_cache.request(&mut self.extra_gpu_data_handle) {
|
||||
for i in 0..5 {
|
||||
request.push([m[i*4], m[i*4+1], m[i*4+2], m[i*4+3]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let uv_rect_kind = calculate_uv_rect_kind(
|
||||
&prim_metadata.local_rect,
|
||||
&prim_run_context.scroll_node,
|
||||
&prim_screen_rect.clipped,
|
||||
frame_context.device_pixel_scale,
|
||||
);
|
||||
|
||||
let picture_task = RenderTask::new_picture(
|
||||
RenderTaskLocation::Dynamic(None, Some(prim_screen_rect.clipped.size)),
|
||||
prim_index,
|
||||
prim_screen_rect.clipped.origin,
|
||||
pic_state_for_children.tasks,
|
||||
uv_rect_kind,
|
||||
);
|
||||
|
||||
let render_task_id = frame_state.render_tasks.add(picture_task);
|
||||
pic_state.tasks.push(render_task_id);
|
||||
self.surface = Some(PictureSurface::RenderTask(render_task_id));
|
||||
}
|
||||
Some(PictureCompositeMode::Blit) | None => {
|
||||
let uv_rect_kind = calculate_uv_rect_kind(
|
||||
&prim_metadata.local_rect,
|
||||
&prim_run_context.scroll_node,
|
||||
&prim_screen_rect.clipped,
|
||||
frame_context.device_pixel_scale,
|
||||
);
|
||||
|
||||
let picture_task = RenderTask::new_picture(
|
||||
RenderTaskLocation::Dynamic(None, Some(prim_screen_rect.clipped.size)),
|
||||
prim_index,
|
||||
prim_screen_rect.clipped.origin,
|
||||
pic_state_for_children.tasks,
|
||||
uv_rect_kind,
|
||||
);
|
||||
|
||||
let render_task_id = frame_state.render_tasks.add(picture_task);
|
||||
pic_state.tasks.push(render_task_id);
|
||||
self.surface = Some(PictureSurface::RenderTask(render_task_id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn prepare_for_render(
|
||||
&mut self,
|
||||
prim_index: PrimitiveIndex,
|
||||
prim_metadata: &mut PrimitiveMetadata,
|
||||
prim_run_context: &PrimitiveRunContext,
|
||||
pic_state_for_children: PictureState,
|
||||
pic_state: &mut PictureState,
|
||||
frame_context: &FrameBuildingContext,
|
||||
frame_state: &mut FrameBuildingState,
|
||||
) {
|
||||
self.prepare_for_render_inner(
|
||||
prim_index,
|
||||
prim_metadata,
|
||||
prim_run_context,
|
||||
pic_state_for_children,
|
||||
pic_state,
|
||||
frame_context,
|
||||
frame_state,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate a single screen-space UV for a picture.
|
||||
fn calculate_screen_uv(
|
||||
local_pos: &LayoutPoint,
|
||||
clip_scroll_node: &ClipScrollNode,
|
||||
rendered_rect: &DeviceRect,
|
||||
device_pixel_scale: DevicePixelScale,
|
||||
) -> DevicePoint {
|
||||
let world_pos = clip_scroll_node
|
||||
.world_content_transform
|
||||
.transform_point2d(local_pos);
|
||||
|
||||
let mut device_pos = world_pos * device_pixel_scale;
|
||||
|
||||
// Apply snapping for axis-aligned scroll nodes, as per prim_shared.glsl.
|
||||
if clip_scroll_node.transform_kind == TransformedRectKind::AxisAligned {
|
||||
device_pos.x = (device_pos.x + 0.5).floor();
|
||||
device_pos.y = (device_pos.y + 0.5).floor();
|
||||
}
|
||||
|
||||
DevicePoint::new(
|
||||
(device_pos.x - rendered_rect.origin.x) / rendered_rect.size.width,
|
||||
(device_pos.y - rendered_rect.origin.y) / rendered_rect.size.height,
|
||||
)
|
||||
}
|
||||
|
||||
// Calculate a UV rect within an image based on the screen space
|
||||
// vertex positions of a picture.
|
||||
fn calculate_uv_rect_kind(
|
||||
local_rect: &LayoutRect,
|
||||
clip_scroll_node: &ClipScrollNode,
|
||||
rendered_rect: &DeviceIntRect,
|
||||
device_pixel_scale: DevicePixelScale,
|
||||
) -> UvRectKind {
|
||||
let rendered_rect = rendered_rect.to_f32();
|
||||
|
||||
let top_left = calculate_screen_uv(
|
||||
&local_rect.origin,
|
||||
clip_scroll_node,
|
||||
&rendered_rect,
|
||||
device_pixel_scale,
|
||||
);
|
||||
|
||||
let top_right = calculate_screen_uv(
|
||||
&local_rect.top_right(),
|
||||
clip_scroll_node,
|
||||
&rendered_rect,
|
||||
device_pixel_scale,
|
||||
);
|
||||
|
||||
let bottom_left = calculate_screen_uv(
|
||||
&local_rect.bottom_left(),
|
||||
clip_scroll_node,
|
||||
&rendered_rect,
|
||||
device_pixel_scale,
|
||||
);
|
||||
|
||||
let bottom_right = calculate_screen_uv(
|
||||
&local_rect.bottom_right(),
|
||||
clip_scroll_node,
|
||||
&rendered_rect,
|
||||
device_pixel_scale,
|
||||
);
|
||||
|
||||
UvRectKind::Quad {
|
||||
top_left,
|
||||
top_right,
|
||||
bottom_left,
|
||||
bottom_right,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -131,7 +131,10 @@ impl FontContext {
|
|||
}
|
||||
|
||||
let system_fc = dwrote::FontCollection::system();
|
||||
let font = system_fc.get_font_from_descriptor(&font_handle).unwrap();
|
||||
let font = match system_fc.get_font_from_descriptor(&font_handle) {
|
||||
Some(font) => font,
|
||||
None => { panic!("missing descriptor {:?}", font_handle) }
|
||||
};
|
||||
let face = font.create_font_face();
|
||||
self.fonts.insert(*font_key, face);
|
||||
}
|
||||
|
|
|
@ -276,6 +276,7 @@ pub enum BrushKind {
|
|||
start_radius: f32,
|
||||
end_radius: f32,
|
||||
ratio_xy: f32,
|
||||
stretch_size: LayoutSize,
|
||||
},
|
||||
LinearGradient {
|
||||
gradient_index: CachedGradientIndex,
|
||||
|
@ -285,6 +286,7 @@ pub enum BrushKind {
|
|||
reverse_stops: bool,
|
||||
start_point: LayoutPoint,
|
||||
end_point: LayoutPoint,
|
||||
stretch_size: LayoutSize,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1641,6 +1643,7 @@ impl PrimitiveStore {
|
|||
pic.prepare_for_render(
|
||||
prim_index,
|
||||
metadata,
|
||||
prim_run_context,
|
||||
pic_state_for_children,
|
||||
pic_state,
|
||||
frame_context,
|
||||
|
@ -1684,15 +1687,32 @@ impl PrimitiveStore {
|
|||
PrimitiveKind::Brush => {
|
||||
let brush = &self.cpu_brushes[metadata.cpu_prim_index.0];
|
||||
brush.write_gpu_blocks(&mut request);
|
||||
|
||||
let repeat = match brush.kind {
|
||||
BrushKind::Image { stretch_size, .. } |
|
||||
BrushKind::LinearGradient { stretch_size, .. } |
|
||||
BrushKind::RadialGradient { stretch_size, .. } => {
|
||||
[
|
||||
metadata.local_rect.size.width / stretch_size.width,
|
||||
metadata.local_rect.size.height / stretch_size.height,
|
||||
0.0,
|
||||
0.0,
|
||||
]
|
||||
}
|
||||
_ => {
|
||||
[1.0, 1.0, 0.0, 0.0]
|
||||
}
|
||||
};
|
||||
|
||||
match brush.segment_desc {
|
||||
Some(ref segment_desc) => {
|
||||
for segment in &segment_desc.segments {
|
||||
// has to match VECS_PER_SEGMENT
|
||||
request.write_segment(segment.local_rect);
|
||||
request.write_segment(segment.local_rect, repeat);
|
||||
}
|
||||
}
|
||||
None => {
|
||||
request.write_segment(metadata.local_rect);
|
||||
request.write_segment(metadata.local_rect, repeat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2462,13 +2482,9 @@ impl<'a> GpuDataRequest<'a> {
|
|||
fn write_segment(
|
||||
&mut self,
|
||||
local_rect: LayoutRect,
|
||||
extra_params: [f32; 4],
|
||||
) {
|
||||
self.push(local_rect);
|
||||
self.push([
|
||||
1.0,
|
||||
1.0,
|
||||
0.0,
|
||||
0.0
|
||||
]);
|
||||
self.push(extra_params);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -732,6 +732,9 @@ impl RenderBackend {
|
|||
);
|
||||
}
|
||||
},
|
||||
SceneBuilderResult::FlushComplete(tx) => {
|
||||
tx.send(()).ok();
|
||||
}
|
||||
SceneBuilderResult::Stopped => {
|
||||
panic!("We haven't sent a Stop yet, how did we get a Stopped back?");
|
||||
}
|
||||
|
@ -754,6 +757,13 @@ impl RenderBackend {
|
|||
// inflight messages, otherwise the scene builder might panic.
|
||||
while let Ok(msg) = self.scene_rx.recv() {
|
||||
match msg {
|
||||
SceneBuilderResult::FlushComplete(tx) => {
|
||||
// If somebody's blocked waiting for a flush, how did they
|
||||
// trigger the RB thread to shut down? This shouldn't happen
|
||||
// but handle it gracefully anyway.
|
||||
debug_assert!(false);
|
||||
tx.send(()).ok();
|
||||
}
|
||||
SceneBuilderResult::Stopped => break,
|
||||
_ => continue,
|
||||
}
|
||||
|
@ -778,6 +788,9 @@ impl RenderBackend {
|
|||
ApiMsg::WakeSceneBuilder => {
|
||||
self.scene_tx.send(SceneBuilderRequest::WakeUp).unwrap();
|
||||
}
|
||||
ApiMsg::FlushSceneBuilder(tx) => {
|
||||
self.scene_tx.send(SceneBuilderRequest::Flush(tx)).unwrap();
|
||||
}
|
||||
ApiMsg::UpdateResources(updates) => {
|
||||
self.resource_cache
|
||||
.update_resources(updates, &mut profile_counters.resources);
|
||||
|
|
|
@ -14,7 +14,7 @@ use euclid::{TypedPoint2D, TypedVector2D};
|
|||
use freelist::{FreeList, FreeListHandle, WeakFreeListHandle};
|
||||
use glyph_rasterizer::GpuGlyphCacheKey;
|
||||
use gpu_cache::{GpuCache, GpuCacheAddress, GpuCacheHandle};
|
||||
use gpu_types::{ImageSource, RasterizationSpace};
|
||||
use gpu_types::{ImageSource, RasterizationSpace, UvRectKind};
|
||||
use internal_types::{FastHashMap, SavedTargetIndex, SourceTexture};
|
||||
#[cfg(feature = "pathfinder")]
|
||||
use pathfinder_partitioner::mesh::Mesh;
|
||||
|
@ -196,6 +196,7 @@ pub struct PictureTask {
|
|||
pub prim_index: PrimitiveIndex,
|
||||
pub content_origin: DeviceIntPoint,
|
||||
pub uv_rect_handle: GpuCacheHandle,
|
||||
uv_rect_kind: UvRectKind,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -205,6 +206,7 @@ pub struct BlurTask {
|
|||
pub blur_std_deviation: f32,
|
||||
pub target_kind: RenderTargetKind,
|
||||
pub uv_rect_handle: GpuCacheHandle,
|
||||
uv_rect_kind: UvRectKind,
|
||||
}
|
||||
|
||||
impl BlurTask {
|
||||
|
@ -306,6 +308,7 @@ impl RenderTask {
|
|||
prim_index: PrimitiveIndex,
|
||||
content_origin: DeviceIntPoint,
|
||||
children: Vec<RenderTaskId>,
|
||||
uv_rect_kind: UvRectKind,
|
||||
) -> Self {
|
||||
RenderTask {
|
||||
children,
|
||||
|
@ -314,6 +317,7 @@ impl RenderTask {
|
|||
prim_index,
|
||||
content_origin,
|
||||
uv_rect_handle: GpuCacheHandle::new(),
|
||||
uv_rect_kind,
|
||||
}),
|
||||
clear_mode: ClearMode::Transparent,
|
||||
saved_index: None,
|
||||
|
@ -488,7 +492,10 @@ impl RenderTask {
|
|||
) -> Self {
|
||||
// Adjust large std deviation value.
|
||||
let mut adjusted_blur_std_deviation = blur_std_deviation;
|
||||
let blur_target_size = render_tasks[src_task_id].get_dynamic_size();
|
||||
let (blur_target_size, uv_rect_kind) = {
|
||||
let src_task = &render_tasks[src_task_id];
|
||||
(src_task.get_dynamic_size(), src_task.uv_rect_kind())
|
||||
};
|
||||
let mut adjusted_blur_target_size = blur_target_size;
|
||||
let mut downscaling_src_task_id = src_task_id;
|
||||
let mut scale_factor = 1.0;
|
||||
|
@ -515,6 +522,7 @@ impl RenderTask {
|
|||
blur_std_deviation: adjusted_blur_std_deviation,
|
||||
target_kind,
|
||||
uv_rect_handle: GpuCacheHandle::new(),
|
||||
uv_rect_kind,
|
||||
}),
|
||||
clear_mode,
|
||||
saved_index: None,
|
||||
|
@ -529,6 +537,7 @@ impl RenderTask {
|
|||
blur_std_deviation: adjusted_blur_std_deviation,
|
||||
target_kind,
|
||||
uv_rect_handle: GpuCacheHandle::new(),
|
||||
uv_rect_kind,
|
||||
}),
|
||||
clear_mode,
|
||||
saved_index: None,
|
||||
|
@ -575,6 +584,31 @@ impl RenderTask {
|
|||
}
|
||||
}
|
||||
|
||||
fn uv_rect_kind(&self) -> UvRectKind {
|
||||
match self.kind {
|
||||
RenderTaskKind::CacheMask(..) |
|
||||
RenderTaskKind::Glyph(_) |
|
||||
RenderTaskKind::Readback(..) |
|
||||
RenderTaskKind::Scaling(..) => {
|
||||
unreachable!("bug: unexpected render task");
|
||||
}
|
||||
|
||||
RenderTaskKind::Picture(ref task) => {
|
||||
task.uv_rect_kind
|
||||
}
|
||||
|
||||
RenderTaskKind::VerticalBlur(ref task) |
|
||||
RenderTaskKind::HorizontalBlur(ref task) => {
|
||||
task.uv_rect_kind
|
||||
}
|
||||
|
||||
RenderTaskKind::ClipRegion(..) |
|
||||
RenderTaskKind::Blit(..) => {
|
||||
UvRectKind::Rect
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Write (up to) 8 floats of data specific to the type
|
||||
// of render task that is provided to the GPU shaders
|
||||
// via a vertex texture.
|
||||
|
@ -778,13 +812,13 @@ impl RenderTask {
|
|||
) {
|
||||
let (target_rect, target_index) = self.get_target_rect();
|
||||
|
||||
let cache_handle = match self.kind {
|
||||
let (cache_handle, uv_rect_kind) = match self.kind {
|
||||
RenderTaskKind::HorizontalBlur(ref mut info) |
|
||||
RenderTaskKind::VerticalBlur(ref mut info) => {
|
||||
&mut info.uv_rect_handle
|
||||
(&mut info.uv_rect_handle, info.uv_rect_kind)
|
||||
}
|
||||
RenderTaskKind::Picture(ref mut info) => {
|
||||
&mut info.uv_rect_handle
|
||||
(&mut info.uv_rect_handle, info.uv_rect_kind)
|
||||
}
|
||||
RenderTaskKind::Readback(..) |
|
||||
RenderTaskKind::Scaling(..) |
|
||||
|
@ -797,11 +831,15 @@ impl RenderTask {
|
|||
};
|
||||
|
||||
if let Some(mut request) = gpu_cache.request(cache_handle) {
|
||||
let p0 = target_rect.origin.to_f32();
|
||||
let p1 = target_rect.bottom_right().to_f32();
|
||||
|
||||
let image_source = ImageSource {
|
||||
p0: target_rect.origin.to_f32(),
|
||||
p1: target_rect.bottom_right().to_f32(),
|
||||
p0,
|
||||
p1,
|
||||
texture_layer: target_index.0 as f32,
|
||||
user_data: [0.0; 3],
|
||||
uv_rect_kind,
|
||||
};
|
||||
image_source.write_gpu_blocks(&mut request);
|
||||
}
|
||||
|
@ -1012,6 +1050,7 @@ impl RenderTaskCache {
|
|||
None,
|
||||
gpu_cache,
|
||||
None,
|
||||
render_task.uv_rect_kind(),
|
||||
);
|
||||
|
||||
// Get the allocation details in the texture cache, and store
|
||||
|
|
|
@ -24,6 +24,7 @@ use glyph_cache::GlyphCache;
|
|||
use glyph_cache::GlyphCacheEntry;
|
||||
use glyph_rasterizer::{FontInstance, GlyphFormat, GlyphRasterizer, GlyphRequest};
|
||||
use gpu_cache::{GpuCache, GpuCacheAddress, GpuCacheHandle};
|
||||
use gpu_types::UvRectKind;
|
||||
use internal_types::{FastHashMap, FastHashSet, SourceTexture, TextureUpdateList};
|
||||
use profiler::{ResourceProfileCounters, TextureCacheProfileCounters};
|
||||
use render_backend::FrameId;
|
||||
|
@ -1057,6 +1058,7 @@ impl ResourceCache {
|
|||
dirty_rect,
|
||||
gpu_cache,
|
||||
None,
|
||||
UvRectKind::Rect,
|
||||
);
|
||||
image_template.dirty_rect = None;
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ pub enum SceneBuilderRequest {
|
|||
current_epochs: FastHashMap<PipelineId, Epoch>,
|
||||
},
|
||||
WakeUp,
|
||||
Flush(MsgSender<()>),
|
||||
Stop
|
||||
}
|
||||
|
||||
|
@ -38,6 +39,7 @@ pub enum SceneBuilderResult {
|
|||
render: bool,
|
||||
result_tx: Sender<SceneSwapResult>,
|
||||
},
|
||||
FlushComplete(MsgSender<()>),
|
||||
Stopped,
|
||||
}
|
||||
|
||||
|
@ -125,6 +127,10 @@ impl SceneBuilder {
|
|||
fn process_message(&mut self, msg: SceneBuilderRequest) -> bool {
|
||||
match msg {
|
||||
SceneBuilderRequest::WakeUp => {}
|
||||
SceneBuilderRequest::Flush(tx) => {
|
||||
self.tx.send(SceneBuilderResult::FlushComplete(tx)).unwrap();
|
||||
let _ = self.api_tx.send(ApiMsg::WakeUp);
|
||||
}
|
||||
SceneBuilderRequest::Transaction {
|
||||
document_id,
|
||||
scene,
|
||||
|
|
|
@ -8,7 +8,7 @@ use api::ImageDescriptor;
|
|||
use device::TextureFilter;
|
||||
use freelist::{FreeList, FreeListHandle, UpsertResult, WeakFreeListHandle};
|
||||
use gpu_cache::{GpuCache, GpuCacheHandle};
|
||||
use gpu_types::ImageSource;
|
||||
use gpu_types::{ImageSource, UvRectKind};
|
||||
use internal_types::{CacheTextureId, FastHashMap, TextureUpdateList, TextureUpdateSource};
|
||||
use internal_types::{RenderTargetInfo, SourceTexture, TextureUpdate, TextureUpdateOp};
|
||||
use profiler::{ResourceProfileCounter, TextureCacheProfileCounters};
|
||||
|
@ -110,6 +110,8 @@ struct CacheEntry {
|
|||
texture_id: CacheTextureId,
|
||||
// Optional notice when the entry is evicted from the cache.
|
||||
eviction_notice: Option<EvictionNotice>,
|
||||
// The type of UV rect this entry specifies.
|
||||
uv_rect_kind: UvRectKind,
|
||||
}
|
||||
|
||||
impl CacheEntry {
|
||||
|
@ -121,6 +123,7 @@ impl CacheEntry {
|
|||
filter: TextureFilter,
|
||||
user_data: [f32; 3],
|
||||
last_access: FrameId,
|
||||
uv_rect_kind: UvRectKind,
|
||||
) -> Self {
|
||||
CacheEntry {
|
||||
size,
|
||||
|
@ -132,6 +135,7 @@ impl CacheEntry {
|
|||
filter,
|
||||
uv_rect_handle: GpuCacheHandle::new(),
|
||||
eviction_notice: None,
|
||||
uv_rect_kind,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -154,6 +158,7 @@ impl CacheEntry {
|
|||
p1: (origin + self.size).to_f32(),
|
||||
texture_layer: layer_index,
|
||||
user_data: self.user_data,
|
||||
uv_rect_kind: self.uv_rect_kind,
|
||||
};
|
||||
image_source.write_gpu_blocks(&mut request);
|
||||
}
|
||||
|
@ -394,6 +399,7 @@ impl TextureCache {
|
|||
mut dirty_rect: Option<DeviceUintRect>,
|
||||
gpu_cache: &mut GpuCache,
|
||||
eviction_notice: Option<&EvictionNotice>,
|
||||
uv_rect_kind: UvRectKind,
|
||||
) {
|
||||
// Determine if we need to allocate texture cache memory
|
||||
// for this item. We need to reallocate if any of the following
|
||||
|
@ -422,7 +428,13 @@ impl TextureCache {
|
|||
};
|
||||
|
||||
if realloc {
|
||||
self.allocate(handle, descriptor, filter, user_data);
|
||||
self.allocate(
|
||||
handle,
|
||||
descriptor,
|
||||
filter,
|
||||
user_data,
|
||||
uv_rect_kind,
|
||||
);
|
||||
|
||||
// If we reallocated, we need to upload the whole item again.
|
||||
dirty_rect = None;
|
||||
|
@ -639,7 +651,7 @@ impl TextureCache {
|
|||
// - We have freed an item that will definitely allow us to
|
||||
// fit the currently requested allocation.
|
||||
let needed_slab_size =
|
||||
SlabSize::new(required_alloc.width, required_alloc.height).get_size();
|
||||
SlabSize::new(required_alloc.width, required_alloc.height);
|
||||
let mut found_matching_slab = false;
|
||||
let mut freed_complete_page = false;
|
||||
let mut evicted_items = 0;
|
||||
|
@ -698,6 +710,7 @@ impl TextureCache {
|
|||
descriptor: &ImageDescriptor,
|
||||
filter: TextureFilter,
|
||||
user_data: [f32; 3],
|
||||
uv_rect_kind: UvRectKind,
|
||||
) -> Option<CacheEntry> {
|
||||
// Work out which cache it goes in, based on format.
|
||||
let texture_array = match (descriptor.format, filter) {
|
||||
|
@ -745,6 +758,7 @@ impl TextureCache {
|
|||
descriptor.height,
|
||||
user_data,
|
||||
self.frame_id,
|
||||
uv_rect_kind,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -765,11 +779,12 @@ impl TextureCache {
|
|||
allowed_in_shared_cache = false;
|
||||
}
|
||||
|
||||
// Anything larger than 512 goes in a standalone texture.
|
||||
// Anything larger than TEXTURE_REGION_DIMENSIONS goes in a standalone texture.
|
||||
// TODO(gw): If we find pages that suffer from batch breaks in this
|
||||
// case, add support for storing these in a standalone
|
||||
// texture array.
|
||||
if descriptor.width > 512 || descriptor.height > 512 {
|
||||
if descriptor.width > TEXTURE_REGION_DIMENSIONS ||
|
||||
descriptor.height > TEXTURE_REGION_DIMENSIONS {
|
||||
allowed_in_shared_cache = false;
|
||||
}
|
||||
|
||||
|
@ -785,6 +800,7 @@ impl TextureCache {
|
|||
descriptor: ImageDescriptor,
|
||||
filter: TextureFilter,
|
||||
user_data: [f32; 3],
|
||||
uv_rect_kind: UvRectKind,
|
||||
) {
|
||||
assert!(descriptor.width > 0 && descriptor.height > 0);
|
||||
|
||||
|
@ -803,7 +819,8 @@ impl TextureCache {
|
|||
new_cache_entry = self.allocate_from_shared_cache(
|
||||
&descriptor,
|
||||
filter,
|
||||
user_data
|
||||
user_data,
|
||||
uv_rect_kind,
|
||||
);
|
||||
|
||||
// If we failed to allocate in the shared cache, run an
|
||||
|
@ -814,7 +831,8 @@ impl TextureCache {
|
|||
new_cache_entry = self.allocate_from_shared_cache(
|
||||
&descriptor,
|
||||
filter,
|
||||
user_data
|
||||
user_data,
|
||||
uv_rect_kind,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -847,6 +865,7 @@ impl TextureCache {
|
|||
filter,
|
||||
user_data,
|
||||
frame_id,
|
||||
uv_rect_kind,
|
||||
));
|
||||
|
||||
allocated_in_shared_cache = false;
|
||||
|
@ -900,43 +919,48 @@ impl TextureCache {
|
|||
}
|
||||
}
|
||||
|
||||
// A list of the block sizes that a region can be initialized with.
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
enum SlabSize {
|
||||
Size16x16,
|
||||
Size32x32,
|
||||
Size64x64,
|
||||
Size128x128,
|
||||
Size256x256,
|
||||
Size512x512,
|
||||
struct SlabSize {
|
||||
width: u32,
|
||||
height: u32,
|
||||
}
|
||||
|
||||
impl SlabSize {
|
||||
fn new(width: u32, height: u32) -> SlabSize {
|
||||
// TODO(gw): Consider supporting non-square
|
||||
// allocator sizes here.
|
||||
let max_dim = cmp::max(width, height);
|
||||
let x_size = quantize_dimension(width);
|
||||
let y_size = quantize_dimension(height);
|
||||
|
||||
match max_dim {
|
||||
0 => unreachable!(),
|
||||
1...16 => SlabSize::Size16x16,
|
||||
17...32 => SlabSize::Size32x32,
|
||||
33...64 => SlabSize::Size64x64,
|
||||
65...128 => SlabSize::Size128x128,
|
||||
129...256 => SlabSize::Size256x256,
|
||||
257...512 => SlabSize::Size512x512,
|
||||
_ => panic!("Invalid dimensions for cache!"),
|
||||
assert!(x_size > 0 && x_size <= TEXTURE_REGION_DIMENSIONS);
|
||||
assert!(y_size > 0 && y_size <= TEXTURE_REGION_DIMENSIONS);
|
||||
|
||||
let (width, height) = match (x_size, y_size) {
|
||||
// Special cased rectangular slab pages.
|
||||
(512, 256) => (512, 256),
|
||||
(512, 128) => (512, 128),
|
||||
(512, 64) => (512, 64),
|
||||
(256, 512) => (256, 512),
|
||||
(128, 512) => (128, 512),
|
||||
( 64, 512) => ( 64, 512),
|
||||
|
||||
// If none of those fit, use a square slab size.
|
||||
(x_size, y_size) => {
|
||||
let square_size = cmp::max(x_size, y_size);
|
||||
(square_size, square_size)
|
||||
}
|
||||
};
|
||||
|
||||
SlabSize {
|
||||
width,
|
||||
height,
|
||||
}
|
||||
}
|
||||
|
||||
fn get_size(&self) -> u32 {
|
||||
match *self {
|
||||
SlabSize::Size16x16 => 16,
|
||||
SlabSize::Size32x32 => 32,
|
||||
SlabSize::Size64x64 => 64,
|
||||
SlabSize::Size128x128 => 128,
|
||||
SlabSize::Size256x256 => 256,
|
||||
SlabSize::Size512x512 => 512,
|
||||
fn invalid() -> SlabSize {
|
||||
SlabSize {
|
||||
width: 0,
|
||||
height: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -960,9 +984,8 @@ impl TextureLocation {
|
|||
struct TextureRegion {
|
||||
layer_index: i32,
|
||||
region_size: u32,
|
||||
slab_size: u32,
|
||||
slab_size: SlabSize,
|
||||
free_slots: Vec<TextureLocation>,
|
||||
slots_per_axis: u32,
|
||||
total_slot_count: usize,
|
||||
origin: DeviceUintPoint,
|
||||
}
|
||||
|
@ -972,9 +995,8 @@ impl TextureRegion {
|
|||
TextureRegion {
|
||||
layer_index,
|
||||
region_size,
|
||||
slab_size: 0,
|
||||
slab_size: SlabSize::invalid(),
|
||||
free_slots: Vec::new(),
|
||||
slots_per_axis: 0,
|
||||
total_slot_count: 0,
|
||||
origin,
|
||||
}
|
||||
|
@ -982,15 +1004,16 @@ impl TextureRegion {
|
|||
|
||||
// Initialize a region to be an allocator for a specific slab size.
|
||||
fn init(&mut self, slab_size: SlabSize) {
|
||||
debug_assert!(self.slab_size == 0);
|
||||
debug_assert!(self.slab_size == SlabSize::invalid());
|
||||
debug_assert!(self.free_slots.is_empty());
|
||||
|
||||
self.slab_size = slab_size.get_size();
|
||||
self.slots_per_axis = self.region_size / self.slab_size;
|
||||
self.slab_size = slab_size;
|
||||
let slots_per_x_axis = self.region_size / self.slab_size.width;
|
||||
let slots_per_y_axis = self.region_size / self.slab_size.height;
|
||||
|
||||
// Add each block to a freelist.
|
||||
for y in 0 .. self.slots_per_axis {
|
||||
for x in 0 .. self.slots_per_axis {
|
||||
for y in 0 .. slots_per_y_axis {
|
||||
for x in 0 .. slots_per_x_axis {
|
||||
self.free_slots.push(TextureLocation::new(x, y));
|
||||
}
|
||||
}
|
||||
|
@ -1001,30 +1024,31 @@ impl TextureRegion {
|
|||
// Deinit a region, allowing it to become a region with
|
||||
// a different allocator size.
|
||||
fn deinit(&mut self) {
|
||||
self.slab_size = 0;
|
||||
self.slab_size = SlabSize::invalid();
|
||||
self.free_slots.clear();
|
||||
self.slots_per_axis = 0;
|
||||
self.total_slot_count = 0;
|
||||
}
|
||||
|
||||
fn is_empty(&self) -> bool {
|
||||
self.slab_size == 0
|
||||
self.slab_size == SlabSize::invalid()
|
||||
}
|
||||
|
||||
// Attempt to allocate a fixed size block from this region.
|
||||
fn alloc(&mut self) -> Option<DeviceUintPoint> {
|
||||
debug_assert!(self.slab_size != SlabSize::invalid());
|
||||
|
||||
self.free_slots.pop().map(|location| {
|
||||
DeviceUintPoint::new(
|
||||
self.origin.x + self.slab_size * location.0 as u32,
|
||||
self.origin.y + self.slab_size * location.1 as u32,
|
||||
self.origin.x + self.slab_size.width * location.0 as u32,
|
||||
self.origin.y + self.slab_size.height * location.1 as u32,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
// Free a block in this region.
|
||||
fn free(&mut self, point: DeviceUintPoint) {
|
||||
let x = (point.x - self.origin.x) / self.slab_size;
|
||||
let y = (point.y - self.origin.y) / self.slab_size;
|
||||
let x = (point.x - self.origin.x) / self.slab_size.width;
|
||||
let y = (point.y - self.origin.y) / self.slab_size.height;
|
||||
self.free_slots.push(TextureLocation::new(x, y));
|
||||
|
||||
// If this region is completely unused, deinit it
|
||||
|
@ -1089,6 +1113,7 @@ impl TextureArray {
|
|||
height: u32,
|
||||
user_data: [f32; 3],
|
||||
frame_id: FrameId,
|
||||
uv_rect_kind: UvRectKind,
|
||||
) -> Option<CacheEntry> {
|
||||
// Lazily allocate the regions if not already created.
|
||||
// This means that very rarely used image formats can be
|
||||
|
@ -1118,7 +1143,6 @@ impl TextureArray {
|
|||
// Quantize the size of the allocation to select a region to
|
||||
// allocate from.
|
||||
let slab_size = SlabSize::new(width, height);
|
||||
let slab_size_dim = slab_size.get_size();
|
||||
|
||||
// TODO(gw): For simplicity, the initial implementation just
|
||||
// has a single vec<> of regions. We could easily
|
||||
|
@ -1134,9 +1158,9 @@ impl TextureArray {
|
|||
// Run through the existing regions of this size, and see if
|
||||
// we can find a free block in any of them.
|
||||
for (i, region) in self.regions.iter_mut().enumerate() {
|
||||
if region.slab_size == 0 {
|
||||
if region.is_empty() {
|
||||
empty_region_index = Some(i);
|
||||
} else if region.slab_size == slab_size_dim {
|
||||
} else if region.slab_size == slab_size {
|
||||
if let Some(location) = region.alloc() {
|
||||
entry_kind = Some(EntryKind::Cache {
|
||||
layer_index: region.layer_index as u16,
|
||||
|
@ -1174,6 +1198,7 @@ impl TextureArray {
|
|||
filter: self.filter,
|
||||
texture_id: self.texture_id.unwrap(),
|
||||
eviction_notice: None,
|
||||
uv_rect_kind,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -1244,3 +1269,16 @@ impl TextureUpdate {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn quantize_dimension(size: u32) -> u32 {
|
||||
match size {
|
||||
0 => unreachable!(),
|
||||
1...16 => 16,
|
||||
17...32 => 32,
|
||||
33...64 => 64,
|
||||
65...128 => 128,
|
||||
129...256 => 256,
|
||||
257...512 => 512,
|
||||
_ => panic!("Invalid dimensions for cache!"),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -633,6 +633,7 @@ pub enum ApiMsg {
|
|||
/// through another channel.
|
||||
WakeUp,
|
||||
WakeSceneBuilder,
|
||||
FlushSceneBuilder(MsgSender<()>),
|
||||
ShutDown,
|
||||
}
|
||||
|
||||
|
@ -653,6 +654,7 @@ impl fmt::Debug for ApiMsg {
|
|||
ApiMsg::ShutDown => "ApiMsg::ShutDown",
|
||||
ApiMsg::WakeUp => "ApiMsg::WakeUp",
|
||||
ApiMsg::WakeSceneBuilder => "ApiMsg::WakeSceneBuilder",
|
||||
ApiMsg::FlushSceneBuilder(..) => "ApiMsg::FlushSceneBuilder",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -965,6 +967,15 @@ impl RenderApi {
|
|||
self.send_message(ApiMsg::WakeSceneBuilder);
|
||||
}
|
||||
|
||||
/// Block until a round-trip to the scene builder thread has completed. This
|
||||
/// ensures that any transactions (including ones deferred to the scene
|
||||
/// builder thread) have been processed.
|
||||
pub fn flush_scene_builder(&self) {
|
||||
let (tx, rx) = channel::msg_channel().unwrap();
|
||||
self.send_message(ApiMsg::FlushSceneBuilder(tx));
|
||||
rx.recv().unwrap(); // block until done
|
||||
}
|
||||
|
||||
/// Save a capture of the current frame state for debugging.
|
||||
pub fn save_capture(&self, path: PathBuf, bits: CaptureBits) {
|
||||
let msg = ApiMsg::DebugCommand(DebugCommand::SaveCapture(path, bits));
|
||||
|
|
|
@ -1 +1 @@
|
|||
751236199b39bb8dac78522713133ca18c603fb3
|
||||
4b65822a2f7e1fed246a492f9fe193ede2f37d74
|
||||
|
|
Загрузка…
Ссылка в новой задаче