зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1921980 - Adjust the image primitive to compensate for the difference in the picture's rasterized area. r=gw
Differential Revision: https://phabricator.services.mozilla.com/D227256
This commit is contained in:
Родитель
c0c13f6ff1
Коммит
be82e29897
|
@ -2569,9 +2569,13 @@ impl BatchBuilder {
|
|||
(gpu_cache.get_address(&segment_instance.gpu_cache_handle), segments)
|
||||
};
|
||||
|
||||
let local_rect = image_instance.adjustment.map_local_rect(&prim_rect);
|
||||
let local_clip_rect = image_instance.tight_local_clip_rect
|
||||
.intersection_unchecked(&local_rect);
|
||||
|
||||
let prim_header = PrimitiveHeader {
|
||||
local_rect: prim_rect,
|
||||
local_clip_rect: prim_info.clip_chain.local_clip_rect,
|
||||
local_rect,
|
||||
local_clip_rect,
|
||||
specific_prim_address: prim_cache_address,
|
||||
transform_id,
|
||||
};
|
||||
|
|
|
@ -99,6 +99,7 @@ use api::{PropertyBinding, PropertyBindingId, FilterPrimitive, FilterOpGraphPict
|
|||
use api::{DebugFlags, ImageKey, ColorF, ColorU, PrimitiveFlags, SnapshotInfo};
|
||||
use api::{ImageRendering, ColorDepth, YuvRangedColorSpace, YuvFormat, AlphaType};
|
||||
use api::units::*;
|
||||
use crate::prim_store::image::AdjustedImageSource;
|
||||
use crate::{command_buffer::PrimitiveCommand, render_task_graph::RenderTaskGraphBuilder, renderer::GpuBufferBuilderF};
|
||||
use crate::box_shadow::BLUR_SAMPLE_SCALE;
|
||||
use crate::clip::{ClipStore, ClipChainInstance, ClipLeafId, ClipNodeId, ClipTreeBuilder};
|
||||
|
@ -8334,6 +8335,10 @@ fn request_render_task(
|
|||
|
||||
let task_id = match snapshot {
|
||||
Some(info) => {
|
||||
let adjustment = AdjustedImageSource::from_rects(
|
||||
&info.area,
|
||||
&surface_rects.clipped_local.cast_unit()
|
||||
);
|
||||
let task_id = frame_state.resource_cache.render_as_image(
|
||||
info.key.as_image(),
|
||||
surface_rects.task_size,
|
||||
|
@ -8341,6 +8346,7 @@ fn request_render_task(
|
|||
&mut frame_state.frame_gpu_data.f32,
|
||||
frame_state.gpu_cache,
|
||||
is_opaque,
|
||||
&adjustment,
|
||||
f
|
||||
);
|
||||
|
||||
|
|
|
@ -718,7 +718,7 @@ fn prepare_interned_prim_for_render(
|
|||
&mut scratch.segments,
|
||||
&mut scratch.segment_instances,
|
||||
|request| {
|
||||
image_data.write_prim_gpu_blocks(request);
|
||||
image_data.write_prim_gpu_blocks(&image_instance.adjustment, request);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ use api::{
|
|||
RasterSpace, Shadow, YuvColorSpace, ColorRange, YuvFormat,
|
||||
};
|
||||
use api::units::*;
|
||||
use euclid::point2;
|
||||
use crate::composite::CompositorSurfaceKind;
|
||||
use crate::scene_building::{CreateShadow, IsVisible};
|
||||
use crate::frame_builder::{FrameBuildingContext, FrameBuildingState};
|
||||
|
@ -72,6 +73,7 @@ pub struct ImageInstance {
|
|||
pub visible_tiles: Vec<VisibleImageTile>,
|
||||
pub src_color: Option<RenderTaskId>,
|
||||
pub normalized_uvs: bool,
|
||||
pub adjustment: AdjustedImageSource,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
|
@ -169,9 +171,25 @@ impl ImageData {
|
|||
tile: None,
|
||||
};
|
||||
|
||||
// Tighten the clip rect because decomposing the repeated image can
|
||||
// produce primitives that are partially covering the original image
|
||||
// rect and we want to clip these extra parts out.
|
||||
// We also rely on having a tight clip rect in some cases other than
|
||||
// tiled/repeated images, for example when rendering a snapshot image
|
||||
// where the snapshot area is tighter than the rasterized area.
|
||||
let tight_clip_rect = visibility
|
||||
.clip_chain
|
||||
.local_clip_rect
|
||||
.intersection(&common.prim_rect).unwrap();
|
||||
image_instance.tight_local_clip_rect = tight_clip_rect;
|
||||
|
||||
image_instance.adjustment = AdjustedImageSource::new();
|
||||
|
||||
match image_properties {
|
||||
// Non-tiled (most common) path.
|
||||
Some(ImageProperties { tiling: None, ref descriptor, ref external_image, .. }) => {
|
||||
Some(ImageProperties { tiling: None, ref descriptor, ref external_image, adjustment, .. }) => {
|
||||
image_instance.adjustment = adjustment;
|
||||
|
||||
let mut size = frame_state.resource_cache.request_image(
|
||||
request,
|
||||
frame_state.gpu_cache,
|
||||
|
@ -298,15 +316,6 @@ impl ImageData {
|
|||
// thing.
|
||||
let active_rect = visible_rect;
|
||||
|
||||
// Tighten the clip rect because decomposing the repeated image can
|
||||
// produce primitives that are partially covering the original image
|
||||
// rect and we want to clip these extra parts out.
|
||||
let tight_clip_rect = visibility
|
||||
.clip_chain
|
||||
.local_clip_rect
|
||||
.intersection(&common.prim_rect).unwrap();
|
||||
image_instance.tight_local_clip_rect = tight_clip_rect;
|
||||
|
||||
let visible_rect = compute_conservative_visible_rect(
|
||||
&visibility.clip_chain,
|
||||
frame_state.current_dirty_region().combined,
|
||||
|
@ -374,19 +383,20 @@ impl ImageData {
|
|||
}
|
||||
|
||||
if let Some(mut request) = frame_state.gpu_cache.request(&mut common.gpu_cache_handle) {
|
||||
self.write_prim_gpu_blocks(&mut request);
|
||||
self.write_prim_gpu_blocks(&image_instance.adjustment, &mut request);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_prim_gpu_blocks(&self, request: &mut GpuDataRequest) {
|
||||
pub fn write_prim_gpu_blocks(&self, adjustment: &AdjustedImageSource, request: &mut GpuDataRequest) {
|
||||
let stretch_size = adjustment.map_stretch_size(self.stretch_size);
|
||||
// Images are drawn as a white color, modulated by the total
|
||||
// opacity coming from any collapsed property bindings.
|
||||
// Size has to match `VECS_PER_SPECIFIC_BRUSH` from `brush_image.glsl` exactly.
|
||||
request.push(self.color.premultiplied());
|
||||
request.push(PremultipliedColorF::WHITE);
|
||||
request.push([
|
||||
self.stretch_size.width + self.tile_spacing.width,
|
||||
self.stretch_size.height + self.tile_spacing.height,
|
||||
stretch_size.width + self.tile_spacing.width,
|
||||
stretch_size.height + self.tile_spacing.height,
|
||||
0.0,
|
||||
0.0,
|
||||
]);
|
||||
|
@ -449,6 +459,7 @@ impl InternablePrimitive for Image {
|
|||
visible_tiles: Vec::new(),
|
||||
src_color: None,
|
||||
normalized_uvs: false,
|
||||
adjustment: AdjustedImageSource::new(),
|
||||
});
|
||||
|
||||
PrimitiveInstanceKind::Image {
|
||||
|
@ -483,6 +494,95 @@ impl IsVisible for Image {
|
|||
}
|
||||
}
|
||||
|
||||
/// Represents an adjustment to apply to an image primitive.
|
||||
/// This can be used to compensate for a difference between the bounds of
|
||||
/// the images expected by the primitive and the bounds that were actually
|
||||
/// drawn in the texture cache.
|
||||
///
|
||||
/// This happens when rendering snapshot images: A picture is marked so that
|
||||
/// a specific reference area in layout space can be rendered as an image.
|
||||
/// However, the bounds of the rasterized area of the picture typically differ
|
||||
/// from that reference area.
|
||||
///
|
||||
/// The adjustment is stored as 4 floats (x0, y0, x1, y1) that represent a
|
||||
/// transformation of the primitve's local rect such that:
|
||||
///
|
||||
/// ```
|
||||
/// adjusted_rect.min = prim_rect.min + prim_rect.size() * (x0, y0);
|
||||
/// adjusted_rect.max = prim_rect.max + prim_rect.size() * (x1, y1);
|
||||
/// ```
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
pub struct AdjustedImageSource {
|
||||
x0: f32,
|
||||
y0: f32,
|
||||
x1: f32,
|
||||
y1: f32,
|
||||
}
|
||||
|
||||
impl AdjustedImageSource {
|
||||
/// The "identity" adjustment.
|
||||
pub fn new() -> Self {
|
||||
AdjustedImageSource {
|
||||
x0: 0.0,
|
||||
y0: 0.0,
|
||||
x1: 0.0,
|
||||
y1: 0.0,
|
||||
}
|
||||
}
|
||||
|
||||
/// An adjustment to render an image item defined in function of the `reference`
|
||||
/// rect whereas the `actual` rect was cached instead.
|
||||
pub fn from_rects(reference: &LayoutRect, actual: &LayoutRect) -> Self {
|
||||
let ref_size = reference.size();
|
||||
let min_offset = reference.min.to_vector();
|
||||
let max_offset = reference.max.to_vector();
|
||||
AdjustedImageSource {
|
||||
x0: (actual.min.x - min_offset.x) / ref_size.width,
|
||||
y0: (actual.min.y - min_offset.y) / ref_size.height,
|
||||
x1: (actual.max.x - max_offset.x) / ref_size.width,
|
||||
y1: (actual.max.y - max_offset.y) / ref_size.height,
|
||||
}
|
||||
}
|
||||
|
||||
/// Adjust the primitive's local rect.
|
||||
pub fn map_local_rect(&self, rect: &LayoutRect) -> LayoutRect {
|
||||
let w = rect.width();
|
||||
let h = rect.height();
|
||||
LayoutRect {
|
||||
min: point2(
|
||||
rect.min.x + w * self.x0,
|
||||
rect.min.y + h * self.y0,
|
||||
),
|
||||
max: point2(
|
||||
rect.max.x + w * self.x1,
|
||||
rect.max.y + h * self.y1,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
/// The stretch size has to be adjusted as well because it is defined
|
||||
/// using the snapshot area as reference but will stretch the rasterized
|
||||
/// area instead.
|
||||
///
|
||||
/// It has to be scaled by a factor of (adjusted.size() / prim_rect.size()).
|
||||
/// We derive the formula in function of the adjustment factors:
|
||||
///
|
||||
/// ```
|
||||
/// factor = (adjusted.max - adjusted.min) / (w, h)
|
||||
/// = (rect.max + (w, h) * (x1, y1) - (rect.min + (w, h) * (x0, y0))) / (w, h)
|
||||
/// = ((w, h) + (w, h) * (x1, y1) - (w, h) * (x0, y0)) / (w, h)
|
||||
/// = (1.0, 1.0) + (x1, y1) - (x0, y0)
|
||||
/// ```
|
||||
pub fn map_stretch_size(&self, size: LayoutSize) -> LayoutSize {
|
||||
LayoutSize::new(
|
||||
size.width * (1.0 + self.x1 - self.x0),
|
||||
size.height * (1.0 + self.y1 - self.y0),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
|
|
|
@ -13,6 +13,7 @@ use euclid::size2;
|
|||
use crate::render_target::RenderTargetKind;
|
||||
use crate::render_task::{RenderTaskLocation, StaticRenderTaskSurface};
|
||||
use crate::{render_api::{ClearCache, AddFont, ResourceUpdate, MemoryReport}, util::WeakTable};
|
||||
use crate::prim_store::image::AdjustedImageSource;
|
||||
use crate::image_tiling::{compute_tile_size, compute_tile_range};
|
||||
#[cfg(feature = "capture")]
|
||||
use crate::capture::ExternalCaptureImage;
|
||||
|
@ -178,6 +179,7 @@ pub struct ImageProperties {
|
|||
// Potentially a subset of the image's total rectangle. This rectangle is what
|
||||
// we map to the (layout space) display item bounds.
|
||||
pub visible_rect: DeviceIntRect,
|
||||
pub adjustment: AdjustedImageSource,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
|
@ -206,6 +208,7 @@ struct ImageResource {
|
|||
/// This is used to express images that are virtually very large
|
||||
/// but with only a visible sub-set that is valid at a given time.
|
||||
visible_rect: DeviceIntRect,
|
||||
adjustment: AdjustedImageSource,
|
||||
generation: ImageGeneration,
|
||||
}
|
||||
|
||||
|
@ -636,6 +639,7 @@ impl ResourceCache {
|
|||
gpu_buffer_builder: &mut GpuBufferBuilderF,
|
||||
gpu_cache: &mut GpuCache,
|
||||
is_opaque: bool,
|
||||
adjustment: &AdjustedImageSource,
|
||||
f: &mut dyn FnMut(&mut RenderTaskGraphBuilder, &mut GpuBufferBuilderF, &mut GpuCache) -> RenderTaskId,
|
||||
) -> RenderTaskId {
|
||||
|
||||
|
@ -698,6 +702,11 @@ impl ResourceCache {
|
|||
})
|
||||
);
|
||||
|
||||
self.resources.image_templates
|
||||
.get_mut(image_key)
|
||||
.unwrap()
|
||||
.adjustment = *adjustment;
|
||||
|
||||
task_id
|
||||
}
|
||||
|
||||
|
@ -924,6 +933,7 @@ impl ResourceCache {
|
|||
data,
|
||||
tiling,
|
||||
visible_rect: *visible_rect,
|
||||
adjustment: AdjustedImageSource::new(),
|
||||
generation: ImageGeneration(0),
|
||||
};
|
||||
|
||||
|
@ -993,6 +1003,7 @@ impl ResourceCache {
|
|||
data,
|
||||
tiling,
|
||||
visible_rect: descriptor.size.into(),
|
||||
adjustment: AdjustedImageSource::new(),
|
||||
generation: ImageGeneration(image.generation.0 + 1),
|
||||
};
|
||||
}
|
||||
|
@ -1373,6 +1384,7 @@ impl ResourceCache {
|
|||
external_image,
|
||||
tiling: image_template.tiling,
|
||||
visible_rect: image_template.visible_rect,
|
||||
adjustment: image_template.adjustment,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -2405,6 +2417,7 @@ impl ResourceCache {
|
|||
descriptor: template.descriptor,
|
||||
tiling: template.tiling,
|
||||
visible_rect: template.descriptor.size.into(),
|
||||
adjustment: AdjustedImageSource::new(), // TODO(nical)
|
||||
generation: template.generation,
|
||||
});
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче