зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1509495 - Update webrender to commit af2b372624db589115511b4705849a33e6acd35d (WR PR #3277). r=kats
https://github.com/servo/webrender/pull/3277 Differential Revision: https://phabricator.services.mozilla.com/D12809 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
79fce9d9bb
Коммит
aada6c49ca
|
@ -1 +1 @@
|
|||
523be3a9461de2716828cd2271aabaffc5e4caa0
|
||||
af2b372624db589115511b4705849a33e6acd35d
|
||||
|
|
|
@ -17,7 +17,8 @@ use rayon::prelude::*;
|
|||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use webrender::api::{self, DisplayListBuilder, DocumentId, PipelineId, RenderApi, Transaction};
|
||||
use webrender::api::{ColorF, DeviceIntRect, DeviceIntPoint};
|
||||
use webrender::api::ColorF;
|
||||
use webrender::euclid::size2;
|
||||
|
||||
// This example shows how to implement a very basic BlobImageHandler that can only render
|
||||
// a checkerboard pattern.
|
||||
|
@ -28,8 +29,8 @@ type ImageRenderingCommands = api::ColorU;
|
|||
// Serialize/deserialize the blob.
|
||||
// For real usecases you should probably use serde rather than doing it by hand.
|
||||
|
||||
fn serialize_blob(color: api::ColorU) -> Vec<u8> {
|
||||
vec![color.r, color.g, color.b, color.a]
|
||||
fn serialize_blob(color: api::ColorU) -> Arc<Vec<u8>> {
|
||||
Arc::new(vec![color.r, color.g, color.b, color.a])
|
||||
}
|
||||
|
||||
fn deserialize_blob(blob: &[u8]) -> Result<ImageRenderingCommands, ()> {
|
||||
|
@ -50,9 +51,13 @@ fn render_blob(
|
|||
) -> api::BlobImageResult {
|
||||
let color = *commands;
|
||||
|
||||
// Note: This implementation ignores the dirty rect which isn't incorrect
|
||||
// but is a missed optimization.
|
||||
|
||||
// Allocate storage for the result. Right now the resource cache expects the
|
||||
// tiles to have have no stride or offset.
|
||||
let mut texels = Vec::with_capacity((descriptor.size.width * descriptor.size.height * 4) as usize);
|
||||
let bpp = 4;
|
||||
let mut texels = Vec::with_capacity((descriptor.rect.size.area() * bpp) as usize);
|
||||
|
||||
// Generate a per-tile pattern to see it in the demo. For a real use case it would not
|
||||
// make sense for the rendered content to depend on its tile.
|
||||
|
@ -61,12 +66,15 @@ fn render_blob(
|
|||
None => true,
|
||||
};
|
||||
|
||||
for y in 0 .. descriptor.size.height {
|
||||
for x in 0 .. descriptor.size.width {
|
||||
let [w, h] = descriptor.rect.size.to_array();
|
||||
let offset = descriptor.rect.origin;
|
||||
|
||||
for y in 0..h {
|
||||
for x in 0..w {
|
||||
// Apply the tile's offset. This is important: all drawing commands should be
|
||||
// translated by this offset to give correct results with tiled blob images.
|
||||
let x2 = x + descriptor.offset.x as i32;
|
||||
let y2 = y + descriptor.offset.y as i32;
|
||||
let x2 = x + offset.x;
|
||||
let y2 = y + offset.y;
|
||||
|
||||
// Render a simple checkerboard pattern
|
||||
let checker = if (x2 % 20 >= 10) != (y2 % 20 >= 10) {
|
||||
|
@ -98,10 +106,7 @@ fn render_blob(
|
|||
|
||||
Ok(api::RasterizedBlobImage {
|
||||
data: Arc::new(texels),
|
||||
rasterized_rect: DeviceIntRect {
|
||||
origin: DeviceIntPoint::origin(),
|
||||
size: descriptor.size,
|
||||
},
|
||||
rasterized_rect: size2(w, h).into(),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -117,7 +122,7 @@ struct CheckerboardRenderer {
|
|||
// case the command list is a simple 32 bits value and would be cheap to clone before sending
|
||||
// to the workers. But in a more realistic scenario the commands would typically be bigger
|
||||
// and more expensive to clone, so let's pretend it is also the case here.
|
||||
image_cmds: HashMap<api::ImageKey, Arc<ImageRenderingCommands>>,
|
||||
image_cmds: HashMap<api::BlobImageKey, Arc<ImageRenderingCommands>>,
|
||||
}
|
||||
|
||||
impl CheckerboardRenderer {
|
||||
|
@ -130,19 +135,19 @@ impl CheckerboardRenderer {
|
|||
}
|
||||
|
||||
impl api::BlobImageHandler for CheckerboardRenderer {
|
||||
fn add(&mut self, key: api::ImageKey, cmds: Arc<api::BlobImageData>, _: Option<api::TileSize>) {
|
||||
fn add(&mut self, key: api::BlobImageKey, cmds: Arc<api::BlobImageData>, _: Option<api::TileSize>) {
|
||||
self.image_cmds
|
||||
.insert(key, Arc::new(deserialize_blob(&cmds[..]).unwrap()));
|
||||
}
|
||||
|
||||
fn update(&mut self, key: api::ImageKey, cmds: Arc<api::BlobImageData>, _dirty_rect: Option<api::DeviceIntRect>) {
|
||||
fn update(&mut self, key: api::BlobImageKey, cmds: Arc<api::BlobImageData>, _dirty_rect: &api::BlobDirtyRect) {
|
||||
// Here, updating is just replacing the current version of the commands with
|
||||
// the new one (no incremental updates).
|
||||
self.image_cmds
|
||||
.insert(key, Arc::new(deserialize_blob(&cmds[..]).unwrap()));
|
||||
}
|
||||
|
||||
fn delete(&mut self, key: api::ImageKey) {
|
||||
fn delete(&mut self, key: api::BlobImageKey) {
|
||||
self.image_cmds.remove(&key);
|
||||
}
|
||||
|
||||
|
@ -165,7 +170,7 @@ impl api::BlobImageHandler for CheckerboardRenderer {
|
|||
|
||||
struct Rasterizer {
|
||||
workers: Arc<ThreadPool>,
|
||||
image_cmds: HashMap<api::ImageKey, Arc<ImageRenderingCommands>>,
|
||||
image_cmds: HashMap<api::BlobImageKey, Arc<ImageRenderingCommands>>,
|
||||
}
|
||||
|
||||
impl api::AsyncBlobImageRasterizer for Rasterizer {
|
||||
|
@ -198,19 +203,19 @@ impl Example for App {
|
|||
_pipeline_id: PipelineId,
|
||||
_document_id: DocumentId,
|
||||
) {
|
||||
let blob_img1 = api.generate_image_key();
|
||||
txn.add_image(
|
||||
let blob_img1 = api.generate_blob_image_key();
|
||||
txn.add_blob_image(
|
||||
blob_img1,
|
||||
api::ImageDescriptor::new(500, 500, api::ImageFormat::BGRA8, true, false),
|
||||
api::ImageData::new_blob_image(serialize_blob(api::ColorU::new(50, 50, 150, 255))),
|
||||
serialize_blob(api::ColorU::new(50, 50, 150, 255)),
|
||||
Some(128),
|
||||
);
|
||||
|
||||
let blob_img2 = api.generate_image_key();
|
||||
txn.add_image(
|
||||
let blob_img2 = api.generate_blob_image_key();
|
||||
txn.add_blob_image(
|
||||
blob_img2,
|
||||
api::ImageDescriptor::new(200, 200, api::ImageFormat::BGRA8, true, false),
|
||||
api::ImageData::new_blob_image(serialize_blob(api::ColorU::new(50, 150, 50, 255))),
|
||||
serialize_blob(api::ColorU::new(50, 150, 50, 255)),
|
||||
None,
|
||||
);
|
||||
|
||||
|
@ -232,7 +237,7 @@ impl Example for App {
|
|||
api::LayoutSize::new(0.0, 0.0),
|
||||
api::ImageRendering::Auto,
|
||||
api::AlphaType::PremultipliedAlpha,
|
||||
blob_img1,
|
||||
blob_img1.as_image(),
|
||||
ColorF::WHITE,
|
||||
);
|
||||
|
||||
|
@ -243,7 +248,7 @@ impl Example for App {
|
|||
api::LayoutSize::new(0.0, 0.0),
|
||||
api::ImageRendering::Auto,
|
||||
api::AlphaType::PremultipliedAlpha,
|
||||
blob_img2,
|
||||
blob_img2.as_image(),
|
||||
ColorF::WHITE,
|
||||
);
|
||||
|
||||
|
|
|
@ -105,7 +105,7 @@ impl Example for App {
|
|||
self.image_key,
|
||||
ImageDescriptor::new(64, 64, ImageFormat::BGRA8, true, false),
|
||||
ImageData::new(image_data),
|
||||
None,
|
||||
&DirtyRect::All,
|
||||
);
|
||||
let mut txn = Transaction::new();
|
||||
txn.generate_frame();
|
||||
|
|
|
@ -243,7 +243,7 @@ impl Example for App {
|
|||
image_key,
|
||||
ImageDescriptor::new(size, size, ImageFormat::BGRA8, true, false),
|
||||
ImageData::new(self.image_generator.take()),
|
||||
None,
|
||||
&DirtyRect::All,
|
||||
);
|
||||
},
|
||||
winit::VirtualKeyCode::E => {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
//! Module only available when pathfinder is deactivated when webrender is
|
||||
//! compiled regularly (i.e. any configuration without feature = "pathfinder")
|
||||
|
||||
use api::{ImageData, ImageDescriptor, ImageFormat};
|
||||
use api::{ImageDescriptor, ImageFormat, DirtyRect};
|
||||
use device::TextureFilter;
|
||||
use euclid::size2;
|
||||
use gpu_types::UvRectKind;
|
||||
|
@ -15,6 +15,7 @@ use platform::font::FontContext;
|
|||
use glyph_rasterizer::{FontInstance, FontContexts, GlyphKey};
|
||||
use glyph_rasterizer::{GlyphRasterizer, GlyphRasterJob, GlyphRasterJobs, GlyphRasterResult};
|
||||
use glyph_cache::{GlyphCache, CachedGlyphInfo, GlyphCacheEntry};
|
||||
use resource_cache::CachedImageData;
|
||||
use texture_cache::{TextureCache, TextureCacheHandle, Eviction};
|
||||
use gpu_cache::GpuCache;
|
||||
use render_task::{RenderTaskTree, RenderTaskCache};
|
||||
|
@ -182,9 +183,9 @@ impl GlyphRasterizer {
|
|||
offset: 0,
|
||||
},
|
||||
TextureFilter::Linear,
|
||||
Some(ImageData::Raw(Arc::new(glyph.bytes))),
|
||||
Some(CachedImageData::Raw(Arc::new(glyph.bytes))),
|
||||
[glyph.left, -glyph.top, glyph.scale],
|
||||
None,
|
||||
DirtyRect::All,
|
||||
gpu_cache,
|
||||
Some(glyph_key_cache.eviction_notice()),
|
||||
UvRectKind::Rect,
|
||||
|
|
|
@ -205,4 +205,3 @@ pub use renderer::MAX_VERTEX_TEXTURE_WIDTH;
|
|||
pub use shade::{Shaders, WrShaders};
|
||||
pub use webrender_api as api;
|
||||
pub use webrender_api::euclid;
|
||||
pub use resource_cache::intersect_for_tile;
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
use api::{DeviceRect, FilterOp, MixBlendMode, PipelineId, PremultipliedColorF, PictureRect, PicturePoint};
|
||||
use api::{DeviceIntRect, DevicePoint, LayoutRect, PictureToRasterTransform, LayoutPixel, PropertyBinding, PropertyBindingId};
|
||||
use api::{DevicePixelScale, RasterRect, RasterSpace, PictureSize, DeviceIntPoint, ColorF, ImageKey};
|
||||
use api::{DevicePixelScale, RasterRect, RasterSpace, PictureSize, DeviceIntPoint, ColorF, ImageKey, DirtyRect};
|
||||
use api::{PicturePixel, RasterPixel, WorldPixel, WorldRect, ImageFormat, ImageDescriptor};
|
||||
use box_shadow::{BLUR_SAMPLE_SCALE};
|
||||
use clip::{ClipNodeCollector, ClipStore, ClipChainId, ClipChainNode};
|
||||
|
@ -1843,7 +1843,7 @@ impl PicturePrimitive {
|
|||
TextureFilter::Linear,
|
||||
None,
|
||||
[0.0; 3],
|
||||
None,
|
||||
DirtyRect::All,
|
||||
frame_state.gpu_cache,
|
||||
None,
|
||||
UvRectKind::Rect,
|
||||
|
|
|
@ -15,7 +15,7 @@ use api::{DevicePixelScale, DeviceIntPoint, DeviceIntRect, DeviceIntSize};
|
|||
use api::{DocumentId, DocumentLayer, ExternalScrollId, FrameMsg, HitTestFlags, HitTestResult};
|
||||
use api::{IdNamespace, LayoutPoint, PipelineId, RenderNotifier, SceneMsg, ScrollClamping};
|
||||
use api::{MemoryReport, VoidPtrToSizeFn};
|
||||
use api::{ScrollLocation, ScrollNodeState, TransactionMsg, ResourceUpdate, ImageKey};
|
||||
use api::{ScrollLocation, ScrollNodeState, TransactionMsg, ResourceUpdate, BlobImageKey};
|
||||
use api::{NotificationRequest, Checkpoint};
|
||||
use api::channel::{MsgReceiver, Payload};
|
||||
#[cfg(feature = "capture")]
|
||||
|
@ -1393,19 +1393,15 @@ impl RenderBackend {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_blob_image_updates(updates: &[ResourceUpdate]) -> Vec<ImageKey> {
|
||||
fn get_blob_image_updates(updates: &[ResourceUpdate]) -> Vec<BlobImageKey> {
|
||||
let mut requests = Vec::new();
|
||||
for update in updates {
|
||||
match *update {
|
||||
ResourceUpdate::AddImage(ref img) => {
|
||||
if img.data.is_blob() {
|
||||
requests.push(img.key);
|
||||
}
|
||||
ResourceUpdate::AddBlobImage(ref img) => {
|
||||
requests.push(img.key);
|
||||
}
|
||||
ResourceUpdate::UpdateImage(ref img) => {
|
||||
if img.data.is_blob() {
|
||||
requests.push(img.key);
|
||||
}
|
||||
ResourceUpdate::UpdateBlobImage(ref img) => {
|
||||
requests.push(img.key);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
use api::{DeviceIntPoint, DeviceIntRect, DeviceIntSize, DeviceSize, DeviceIntSideOffsets};
|
||||
use api::{DevicePixelScale, ImageDescriptor, ImageFormat};
|
||||
use api::{LineStyle, LineOrientation, LayoutSize, ColorF};
|
||||
use api::{LineStyle, LineOrientation, LayoutSize, ColorF, DirtyRect};
|
||||
#[cfg(feature = "pathfinder")]
|
||||
use api::FontRenderMode;
|
||||
use border::{BorderCornerCacheKey, BorderEdgeCacheKey};
|
||||
|
@ -1255,7 +1255,7 @@ impl RenderTaskCache {
|
|||
TextureFilter::Linear,
|
||||
None,
|
||||
entry.user_data.unwrap_or([0.0; 3]),
|
||||
None,
|
||||
DirtyRect::All,
|
||||
gpu_cache,
|
||||
None,
|
||||
render_task.uv_rect_kind(),
|
||||
|
|
|
@ -4,14 +4,14 @@
|
|||
|
||||
use api::{AddFont, BlobImageResources, AsyncBlobImageRasterizer, ResourceUpdate};
|
||||
use api::{BlobImageDescriptor, BlobImageHandler, BlobImageRequest, RasterizedBlobImage};
|
||||
use api::{ClearCache, ColorF, DevicePoint, DeviceIntPoint, DeviceIntRect, DeviceIntSize};
|
||||
use api::{ClearCache, ColorF, DeviceIntPoint, DeviceIntRect, DeviceIntSize};
|
||||
use api::{DebugFlags, FontInstanceKey, FontKey, FontTemplate, GlyphIndex};
|
||||
use api::{ExternalImageData, ExternalImageType, BlobImageResult, BlobImageParams};
|
||||
use api::{FontInstanceData, FontInstanceOptions, FontInstancePlatformOptions, FontVariation};
|
||||
use api::{GlyphDimensions, IdNamespace};
|
||||
use api::{ImageData, ImageDescriptor, ImageKey, ImageRendering};
|
||||
use api::{MemoryReport, VoidPtrToSizeFn};
|
||||
use api::{TileOffset, TileSize, TileRange, BlobImageData};
|
||||
use api::{ImageData, ImageDescriptor, ImageKey, ImageRendering, ImageDirtyRect, DirtyRect};
|
||||
use api::{BlobImageKey, BlobDirtyRect, MemoryReport, VoidPtrToSizeFn};
|
||||
use api::{TileOffset, TileSize, TileRange, BlobImageData, LayoutIntRect, LayoutIntSize};
|
||||
use app_units::Au;
|
||||
#[cfg(feature = "capture")]
|
||||
use capture::ExternalCaptureImage;
|
||||
|
@ -86,6 +86,57 @@ impl CacheItem {
|
|||
}
|
||||
}
|
||||
|
||||
/// Represents the backing store of an image in the cache.
|
||||
/// This storage can take several forms.
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum CachedImageData {
|
||||
/// A simple series of bytes, provided by the embedding and owned by WebRender.
|
||||
/// The format is stored out-of-band, currently in ImageDescriptor.
|
||||
Raw(Arc<Vec<u8>>),
|
||||
/// An series of commands that can be rasterized into an image via an
|
||||
/// embedding-provided callback.
|
||||
///
|
||||
/// The commands are stored elsewhere and this variant is used as a placeholder.
|
||||
Blob,
|
||||
/// An image owned by the embedding, and referenced by WebRender. This may
|
||||
/// take the form of a texture or a heap-allocated buffer.
|
||||
External(ExternalImageData),
|
||||
}
|
||||
|
||||
impl From<ImageData> for CachedImageData {
|
||||
fn from(img_data: ImageData) -> Self {
|
||||
match img_data {
|
||||
ImageData::Raw(data) => CachedImageData::Raw(data),
|
||||
ImageData::External(data) => CachedImageData::External(data),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CachedImageData {
|
||||
/// Returns true if this represents a blob.
|
||||
#[inline]
|
||||
pub fn is_blob(&self) -> bool {
|
||||
match *self {
|
||||
CachedImageData::Blob => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if this variant of CachedImageData should go through the texture
|
||||
/// cache.
|
||||
#[inline]
|
||||
pub fn uses_texture_cache(&self) -> bool {
|
||||
match *self {
|
||||
CachedImageData::External(ref ext_data) => match ext_data.image_type {
|
||||
ExternalImageType::TextureHandle(_) => false,
|
||||
ExternalImageType::Buffer => true,
|
||||
},
|
||||
CachedImageData::Blob => true,
|
||||
CachedImageData::Raw(_) => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
|
@ -113,12 +164,12 @@ enum RasterizedBlob {
|
|||
struct BlobImageTemplate {
|
||||
descriptor: ImageDescriptor,
|
||||
tiling: Option<TileSize>,
|
||||
dirty_rect: Option<DeviceIntRect>,
|
||||
dirty_rect: BlobDirtyRect,
|
||||
viewport_tiles: Option<TileRange>,
|
||||
}
|
||||
|
||||
struct ImageResource {
|
||||
data: ImageData,
|
||||
data: CachedImageData,
|
||||
descriptor: ImageDescriptor,
|
||||
tiling: Option<TileSize>,
|
||||
viewport_tiles: Option<TileRange>,
|
||||
|
@ -157,7 +208,7 @@ impl ImageTemplates {
|
|||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
struct CachedImageInfo {
|
||||
texture_cache_handle: TextureCacheHandle,
|
||||
dirty_rect: Option<DeviceIntRect>,
|
||||
dirty_rect: ImageDirtyRect,
|
||||
manual_eviction: bool,
|
||||
}
|
||||
|
||||
|
@ -175,46 +226,6 @@ pub struct ResourceClassCache<K: Hash + Eq, V, U: Default> {
|
|||
pub user_data: U,
|
||||
}
|
||||
|
||||
pub fn intersect_for_tile(
|
||||
dirty: DeviceIntRect,
|
||||
clipped_tile_size: DeviceIntSize,
|
||||
tile_size: TileSize,
|
||||
tile_offset: TileOffset,
|
||||
|
||||
) -> Option<DeviceIntRect> {
|
||||
dirty.intersection(&DeviceIntRect::new(
|
||||
DeviceIntPoint::new(
|
||||
tile_offset.x as i32 * tile_size as i32,
|
||||
tile_offset.y as i32 * tile_size as i32
|
||||
),
|
||||
clipped_tile_size,
|
||||
)).map(|mut r| {
|
||||
// we can't translate by a negative size so do it manually
|
||||
r.origin.x -= tile_offset.x as i32 * tile_size as i32;
|
||||
r.origin.y -= tile_offset.y as i32 * tile_size as i32;
|
||||
r
|
||||
})
|
||||
}
|
||||
|
||||
fn merge_dirty_rect(
|
||||
prev_dirty_rect: &Option<DeviceIntRect>,
|
||||
dirty_rect: &Option<DeviceIntRect>,
|
||||
descriptor: &ImageDescriptor,
|
||||
) -> Option<DeviceIntRect> {
|
||||
// It is important to never assume an empty dirty rect implies a full reupload here,
|
||||
// although we are able to do so elsewhere. We store the descriptor's full rect instead
|
||||
// There are update sequences which could cause us to forget the correct dirty regions
|
||||
// regions if we cleared the dirty rect when we received None, e.g.:
|
||||
// 1) Update with no dirty rect. We want to reupload everything.
|
||||
// 2) Update with dirty rect B. We still want to reupload everything, not just B.
|
||||
// 3) Perform the upload some time later.
|
||||
match (dirty_rect, prev_dirty_rect) {
|
||||
(&Some(ref rect), &Some(ref prev_rect)) => Some(rect.union(&prev_rect)),
|
||||
(&Some(ref rect), &None) => Some(*rect),
|
||||
(&None, _) => Some(descriptor.full_rect()),
|
||||
}
|
||||
}
|
||||
|
||||
impl<K, V, U> ResourceClassCache<K, V, U>
|
||||
where
|
||||
K: Clone + Hash + Eq + Debug,
|
||||
|
@ -307,7 +318,7 @@ impl ImageRequest {
|
|||
impl Into<BlobImageRequest> for ImageRequest {
|
||||
fn into(self) -> BlobImageRequest {
|
||||
BlobImageRequest {
|
||||
key: self.key,
|
||||
key: BlobImageKey(self.key),
|
||||
tile: self.tile,
|
||||
}
|
||||
}
|
||||
|
@ -387,11 +398,6 @@ impl BlobImageResources for Resources {
|
|||
None => None,
|
||||
}
|
||||
}
|
||||
fn get_image(&self, key: ImageKey) -> Option<(&ImageData, &ImageDescriptor)> {
|
||||
self.image_templates
|
||||
.get(key)
|
||||
.map(|resource| (&resource.data, &resource.descriptor))
|
||||
}
|
||||
}
|
||||
|
||||
pub type GlyphDimensionsCache = FastHashMap<(FontInstance, GlyphIndex), Option<GlyphDimensions>>;
|
||||
|
@ -422,8 +428,8 @@ pub struct ResourceCache {
|
|||
pending_image_requests: FastHashSet<ImageRequest>,
|
||||
|
||||
blob_image_handler: Option<Box<BlobImageHandler>>,
|
||||
rasterized_blob_images: FastHashMap<ImageKey, RasterizedBlob>,
|
||||
blob_image_templates: FastHashMap<ImageKey, BlobImageTemplate>,
|
||||
rasterized_blob_images: FastHashMap<BlobImageKey, RasterizedBlob>,
|
||||
blob_image_templates: FastHashMap<BlobImageKey, BlobImageTemplate>,
|
||||
|
||||
// If while building a frame we encounter blobs that we didn't already
|
||||
// rasterize, add them to this list and rasterize them synchronously.
|
||||
|
@ -461,11 +467,11 @@ impl ResourceCache {
|
|||
self.texture_cache.max_texture_size()
|
||||
}
|
||||
|
||||
fn should_tile(limit: i32, descriptor: &ImageDescriptor, data: &ImageData) -> bool {
|
||||
fn should_tile(limit: i32, descriptor: &ImageDescriptor, data: &CachedImageData) -> bool {
|
||||
let size_check = descriptor.size.width > limit || descriptor.size.height > limit;
|
||||
match *data {
|
||||
ImageData::Raw(_) | ImageData::Blob(_) => size_check,
|
||||
ImageData::External(info) => {
|
||||
CachedImageData::Raw(_) | CachedImageData::Blob => size_check,
|
||||
CachedImageData::External(info) => {
|
||||
// External handles already represent existing textures so it does
|
||||
// not make sense to tile them into smaller ones.
|
||||
info.image_type == ExternalImageType::Buffer && size_check
|
||||
|
@ -513,10 +519,28 @@ impl ResourceCache {
|
|||
if let ImageData::Raw(ref bytes) = img.data {
|
||||
profile_counters.image_templates.inc(bytes.len());
|
||||
}
|
||||
self.add_image_template(img.key, img.descriptor, img.data, img.tiling);
|
||||
self.add_image_template(img.key, img.descriptor, img.data.into(), img.tiling);
|
||||
}
|
||||
ResourceUpdate::UpdateImage(img) => {
|
||||
self.update_image_template(img.key, img.descriptor, img.data, img.dirty_rect);
|
||||
self.update_image_template(img.key, img.descriptor, img.data.into(), &img.dirty_rect);
|
||||
}
|
||||
ResourceUpdate::AddBlobImage(img) => {
|
||||
self.add_image_template(
|
||||
img.key.as_image(),
|
||||
img.descriptor,
|
||||
CachedImageData::Blob,
|
||||
img.tiling,
|
||||
);
|
||||
}
|
||||
ResourceUpdate::UpdateBlobImage(img) => {
|
||||
self.update_image_template(
|
||||
img.key.as_image(),
|
||||
img.descriptor,
|
||||
CachedImageData::Blob,
|
||||
&to_image_dirty_rect(
|
||||
&img.dirty_rect
|
||||
),
|
||||
);
|
||||
}
|
||||
ResourceUpdate::DeleteImage(img) => {
|
||||
self.delete_image_template(img);
|
||||
|
@ -527,7 +551,7 @@ impl ResourceCache {
|
|||
ResourceUpdate::DeleteFontInstance(font) => {
|
||||
self.delete_font_instance(font);
|
||||
}
|
||||
ResourceUpdate::SetImageVisibleArea(key, area) => {
|
||||
ResourceUpdate::SetBlobImageVisibleArea(key, area) => {
|
||||
self.discard_tiles_outside_visible_area(key, &area);
|
||||
}
|
||||
ResourceUpdate::AddFont(_) |
|
||||
|
@ -545,27 +569,23 @@ impl ResourceCache {
|
|||
) {
|
||||
for update in updates.iter() {
|
||||
match *update {
|
||||
ResourceUpdate::AddImage(ref img) => {
|
||||
if let ImageData::Blob(ref blob_data) = img.data {
|
||||
self.add_blob_image(
|
||||
img.key,
|
||||
&img.descriptor,
|
||||
img.tiling,
|
||||
Arc::clone(blob_data),
|
||||
);
|
||||
}
|
||||
ResourceUpdate::AddBlobImage(ref img) => {
|
||||
self.add_blob_image(
|
||||
img.key,
|
||||
&img.descriptor,
|
||||
img.tiling,
|
||||
Arc::clone(&img.data),
|
||||
);
|
||||
}
|
||||
ResourceUpdate::UpdateImage(ref img) => {
|
||||
if let ImageData::Blob(ref blob_data) = img.data {
|
||||
self.update_blob_image(
|
||||
img.key,
|
||||
&img.descriptor,
|
||||
&img.dirty_rect,
|
||||
Arc::clone(blob_data)
|
||||
);
|
||||
}
|
||||
ResourceUpdate::UpdateBlobImage(ref img) => {
|
||||
self.update_blob_image(
|
||||
img.key,
|
||||
&img.descriptor,
|
||||
&img.dirty_rect,
|
||||
Arc::clone(&img.data),
|
||||
);
|
||||
}
|
||||
ResourceUpdate::SetImageVisibleArea(ref key, ref area) => {
|
||||
ResourceUpdate::SetBlobImageVisibleArea(ref key, ref area) => {
|
||||
if let Some(template) = self.blob_image_templates.get_mut(&key) {
|
||||
if let Some(tile_size) = template.tiling {
|
||||
template.viewport_tiles = Some(compute_tile_range(
|
||||
|
@ -730,7 +750,7 @@ impl ResourceCache {
|
|||
&mut self,
|
||||
image_key: ImageKey,
|
||||
descriptor: ImageDescriptor,
|
||||
data: ImageData,
|
||||
data: CachedImageData,
|
||||
mut tiling: Option<TileSize>,
|
||||
) {
|
||||
if tiling.is_none() && Self::should_tile(self.max_texture_size(), &descriptor, &data) {
|
||||
|
@ -753,8 +773,8 @@ impl ResourceCache {
|
|||
&mut self,
|
||||
image_key: ImageKey,
|
||||
descriptor: ImageDescriptor,
|
||||
data: ImageData,
|
||||
dirty_rect: Option<DeviceIntRect>,
|
||||
data: CachedImageData,
|
||||
dirty_rect: &ImageDirtyRect,
|
||||
) {
|
||||
let max_texture_size = self.max_texture_size();
|
||||
let image = match self.resources.image_templates.get_mut(image_key) {
|
||||
|
@ -771,24 +791,27 @@ impl ResourceCache {
|
|||
// updated independently.
|
||||
match self.cached_images.try_get_mut(&image_key) {
|
||||
Some(&mut ImageResult::UntiledAuto(ref mut entry)) => {
|
||||
entry.dirty_rect = merge_dirty_rect(&entry.dirty_rect, &dirty_rect, &descriptor);
|
||||
entry.dirty_rect = entry.dirty_rect.union(dirty_rect);
|
||||
}
|
||||
Some(&mut ImageResult::Multi(ref mut entries)) => {
|
||||
let tile_size = tiling.unwrap();
|
||||
for (key, entry) in entries.iter_mut() {
|
||||
let merged_rect = merge_dirty_rect(&entry.dirty_rect, &dirty_rect, &descriptor);
|
||||
// We want the dirty rect relative to the tile and not the whole image.
|
||||
let local_dirty_rect = match key.tile {
|
||||
Some(tile) => {
|
||||
dirty_rect.map(|mut rect|{
|
||||
let tile_offset = DeviceIntPoint::new(
|
||||
tile.x as i32,
|
||||
tile.y as i32,
|
||||
) * tile_size as i32;
|
||||
rect.origin -= tile_offset.to_vector();
|
||||
|
||||
entry.dirty_rect = match (key.tile, merged_rect) {
|
||||
(Some(tile), Some(rect)) => {
|
||||
let tile_size = image.tiling.unwrap();
|
||||
let clipped_tile_size = compute_tile_size(&descriptor, tile_size, tile);
|
||||
|
||||
rect.intersection(&DeviceIntRect::new(
|
||||
DeviceIntPoint::new(tile.x as i32, tile.y as i32) * tile_size as i32,
|
||||
clipped_tile_size,
|
||||
))
|
||||
rect
|
||||
})
|
||||
}
|
||||
_ => merged_rect,
|
||||
None => *dirty_rect,
|
||||
};
|
||||
entry.dirty_rect = entry.dirty_rect.union(&local_dirty_rect);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
|
@ -805,7 +828,7 @@ impl ResourceCache {
|
|||
// Happens before scene building.
|
||||
pub fn add_blob_image(
|
||||
&mut self,
|
||||
key: ImageKey,
|
||||
key: BlobImageKey,
|
||||
descriptor: &ImageDescriptor,
|
||||
mut tiling: Option<TileSize>,
|
||||
data: Arc<BlobImageData>,
|
||||
|
@ -820,12 +843,7 @@ impl ResourceCache {
|
|||
BlobImageTemplate {
|
||||
descriptor: *descriptor,
|
||||
tiling,
|
||||
dirty_rect: Some(
|
||||
DeviceIntRect::new(
|
||||
DeviceIntPoint::zero(),
|
||||
descriptor.size,
|
||||
)
|
||||
),
|
||||
dirty_rect: DirtyRect::All,
|
||||
viewport_tiles: None,
|
||||
},
|
||||
);
|
||||
|
@ -834,12 +852,12 @@ impl ResourceCache {
|
|||
// Happens before scene building.
|
||||
pub fn update_blob_image(
|
||||
&mut self,
|
||||
key: ImageKey,
|
||||
key: BlobImageKey,
|
||||
descriptor: &ImageDescriptor,
|
||||
dirty_rect: &Option<DeviceIntRect>,
|
||||
dirty_rect: &BlobDirtyRect,
|
||||
data: Arc<BlobImageData>,
|
||||
) {
|
||||
self.blob_image_handler.as_mut().unwrap().update(key, data, *dirty_rect);
|
||||
self.blob_image_handler.as_mut().unwrap().update(key, data, dirty_rect);
|
||||
|
||||
let max_texture_size = self.max_texture_size();
|
||||
|
||||
|
@ -852,11 +870,7 @@ impl ResourceCache {
|
|||
*image = BlobImageTemplate {
|
||||
descriptor: *descriptor,
|
||||
tiling,
|
||||
dirty_rect: match (*dirty_rect, image.dirty_rect) {
|
||||
(Some(rect), Some(prev_rect)) => Some(rect.union(&prev_rect)),
|
||||
(Some(rect), None) => Some(rect),
|
||||
(None, _) => None,
|
||||
},
|
||||
dirty_rect: dirty_rect.union(&image.dirty_rect),
|
||||
viewport_tiles: image.viewport_tiles,
|
||||
};
|
||||
}
|
||||
|
@ -872,9 +886,10 @@ impl ResourceCache {
|
|||
|
||||
match value {
|
||||
Some(image) => if image.data.is_blob() {
|
||||
self.blob_image_handler.as_mut().unwrap().delete(image_key);
|
||||
self.blob_image_templates.remove(&image_key);
|
||||
self.rasterized_blob_images.remove(&image_key);
|
||||
let blob_key = BlobImageKey(image_key);
|
||||
self.blob_image_handler.as_mut().unwrap().delete(blob_key);
|
||||
self.blob_image_templates.remove(&blob_key);
|
||||
self.rasterized_blob_images.remove(&blob_key);
|
||||
},
|
||||
None => {
|
||||
warn!("Delete the non-exist key");
|
||||
|
@ -890,11 +905,11 @@ impl ResourceCache {
|
|||
) -> bool {
|
||||
match self.cached_images.try_get(&image_key) {
|
||||
Some(ImageResult::UntiledAuto(ref info)) => {
|
||||
info.dirty_rect.is_some()
|
||||
!info.dirty_rect.is_empty()
|
||||
}
|
||||
Some(ImageResult::Multi(ref entries)) => {
|
||||
for (_, entry) in &entries.resources {
|
||||
if entry.dirty_rect.is_some() {
|
||||
if !entry.dirty_rect.is_empty() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -953,7 +968,7 @@ impl ResourceCache {
|
|||
&mut ImageResult::UntiledAuto(ref mut entry) => {
|
||||
Some(mem::replace(entry, CachedImageInfo {
|
||||
texture_cache_handle: TextureCacheHandle::invalid(),
|
||||
dirty_rect: None,
|
||||
dirty_rect: DirtyRect::All,
|
||||
manual_eviction: false,
|
||||
}))
|
||||
}
|
||||
|
@ -976,7 +991,7 @@ impl ResourceCache {
|
|||
entry.insert(if request.is_untiled_auto() {
|
||||
ImageResult::UntiledAuto(CachedImageInfo {
|
||||
texture_cache_handle: TextureCacheHandle::invalid(),
|
||||
dirty_rect: Some(template.descriptor.full_rect()),
|
||||
dirty_rect: DirtyRect::All,
|
||||
manual_eviction: false,
|
||||
})
|
||||
} else {
|
||||
|
@ -993,7 +1008,7 @@ impl ResourceCache {
|
|||
entries.entry(request.into())
|
||||
.or_insert(CachedImageInfo {
|
||||
texture_cache_handle: TextureCacheHandle::invalid(),
|
||||
dirty_rect: Some(template.descriptor.full_rect()),
|
||||
dirty_rect: DirtyRect::All,
|
||||
manual_eviction: false,
|
||||
})
|
||||
},
|
||||
|
@ -1002,7 +1017,7 @@ impl ResourceCache {
|
|||
|
||||
let needs_upload = self.texture_cache.request(&entry.texture_cache_handle, gpu_cache);
|
||||
|
||||
if !needs_upload && entry.dirty_rect.is_none() {
|
||||
if !needs_upload && entry.dirty_rect.is_empty() {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -1021,38 +1036,31 @@ impl ResourceCache {
|
|||
// For some reason the blob image is missing. We'll fall back to
|
||||
// rasterizing it on the render backend thread.
|
||||
if missing {
|
||||
let descriptor = match template.tiling {
|
||||
Some(tile_size) => {
|
||||
let tile = request.tile.unwrap();
|
||||
BlobImageDescriptor {
|
||||
offset: DevicePoint::new(
|
||||
tile.x as f32 * tile_size as f32,
|
||||
tile.y as f32 * tile_size as f32,
|
||||
),
|
||||
size: compute_tile_size(
|
||||
&template.descriptor,
|
||||
tile_size,
|
||||
tile,
|
||||
),
|
||||
format: template.descriptor.format,
|
||||
let descriptor = BlobImageDescriptor {
|
||||
rect: match template.tiling {
|
||||
Some(tile_size) => {
|
||||
let tile = request.tile.unwrap();
|
||||
LayoutIntRect {
|
||||
origin: point2(tile.x, tile.y) * tile_size as i32,
|
||||
size: blob_size(compute_tile_size(
|
||||
&template.descriptor,
|
||||
tile_size,
|
||||
tile,
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {
|
||||
BlobImageDescriptor {
|
||||
offset: DevicePoint::origin(),
|
||||
size: template.descriptor.size,
|
||||
format: template.descriptor.format,
|
||||
}
|
||||
}
|
||||
None => blob_size(template.descriptor.size).into(),
|
||||
},
|
||||
format: template.descriptor.format,
|
||||
};
|
||||
|
||||
assert!(descriptor.size.width != 0 && descriptor.size.height != 0);
|
||||
assert!(!descriptor.rect.is_empty());
|
||||
|
||||
self.missing_blob_images.push(
|
||||
BlobImageParams {
|
||||
request,
|
||||
descriptor,
|
||||
dirty_rect: None,
|
||||
dirty_rect: DirtyRect::All,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -1061,7 +1069,7 @@ impl ResourceCache {
|
|||
|
||||
pub fn create_blob_scene_builder_requests(
|
||||
&mut self,
|
||||
keys: &[ImageKey]
|
||||
keys: &[BlobImageKey]
|
||||
) -> (Option<Box<AsyncBlobImageRasterizer>>, Vec<BlobImageParams>) {
|
||||
if self.blob_image_handler.is_none() {
|
||||
return (None, Vec::new());
|
||||
|
@ -1085,8 +1093,9 @@ impl ResourceCache {
|
|||
)
|
||||
});
|
||||
|
||||
let image_dirty_rect = to_image_dirty_rect(&template.dirty_rect);
|
||||
// Don't request tiles that weren't invalidated.
|
||||
if let Some(dirty_rect) = template.dirty_rect {
|
||||
if let DirtyRect::Partial(dirty_rect) = image_dirty_rect {
|
||||
let dirty_rect = DeviceIntRect {
|
||||
origin: point2(
|
||||
dirty_rect.origin.x,
|
||||
|
@ -1122,15 +1131,14 @@ impl ResourceCache {
|
|||
|
||||
for_each_tile_in_range(&tiles, |tile| {
|
||||
let descriptor = BlobImageDescriptor {
|
||||
offset: DevicePoint::new(
|
||||
tile.x as f32 * tile_size as f32,
|
||||
tile.y as f32 * tile_size as f32,
|
||||
),
|
||||
size: compute_tile_size(
|
||||
&template.descriptor,
|
||||
tile_size,
|
||||
tile,
|
||||
),
|
||||
rect: LayoutIntRect {
|
||||
origin: point2(tile.x, tile.y) * tile_size as i32,
|
||||
size: blob_size(compute_tile_size(
|
||||
&template.descriptor,
|
||||
tile_size,
|
||||
tile,
|
||||
)),
|
||||
},
|
||||
format: template.descriptor.format,
|
||||
};
|
||||
|
||||
|
@ -1144,12 +1152,12 @@ impl ResourceCache {
|
|||
tile: Some(tile),
|
||||
},
|
||||
descriptor,
|
||||
dirty_rect: None,
|
||||
dirty_rect: DirtyRect::All,
|
||||
}
|
||||
);
|
||||
});
|
||||
} else {
|
||||
let mut needs_upload = match self.cached_images.try_get(&key) {
|
||||
let mut needs_upload = match self.cached_images.try_get(&key.as_image()) {
|
||||
Some(&ImageResult::UntiledAuto(ref entry)) => {
|
||||
self.texture_cache.needs_upload(&entry.texture_cache_handle)
|
||||
}
|
||||
|
@ -1166,7 +1174,7 @@ impl ResourceCache {
|
|||
//
|
||||
// We do the latter here but it's not ideal and might want to revisit and do
|
||||
// the former instead.
|
||||
match self.rasterized_blob_images.get(&key) {
|
||||
match self.rasterized_blob_images.get(key) {
|
||||
Some(RasterizedBlob::NonTiled(ref queue)) => {
|
||||
if queue.len() > 2 {
|
||||
needs_upload = true;
|
||||
|
@ -1177,7 +1185,7 @@ impl ResourceCache {
|
|||
|
||||
let dirty_rect = if needs_upload {
|
||||
// The texture cache entry has been evicted, treat it as all dirty.
|
||||
None
|
||||
DirtyRect::All
|
||||
} else {
|
||||
template.dirty_rect
|
||||
};
|
||||
|
@ -1189,15 +1197,14 @@ impl ResourceCache {
|
|||
tile: None,
|
||||
},
|
||||
descriptor: BlobImageDescriptor {
|
||||
offset: DevicePoint::zero(),
|
||||
size: template.descriptor.size,
|
||||
rect: blob_size(template.descriptor.size).into(),
|
||||
format: template.descriptor.format,
|
||||
},
|
||||
dirty_rect,
|
||||
}
|
||||
);
|
||||
}
|
||||
template.dirty_rect = None;
|
||||
template.dirty_rect = DirtyRect::empty();
|
||||
}
|
||||
let handler = self.blob_image_handler.as_mut().unwrap();
|
||||
handler.prepare_resources(&self.resources, &blob_request_params);
|
||||
|
@ -1206,7 +1213,7 @@ impl ResourceCache {
|
|||
|
||||
fn discard_tiles_outside_visible_area(
|
||||
&mut self,
|
||||
key: ImageKey,
|
||||
key: BlobImageKey,
|
||||
area: &DeviceIntRect
|
||||
) {
|
||||
let template = match self.blob_image_templates.get(&key) {
|
||||
|
@ -1234,7 +1241,7 @@ impl ResourceCache {
|
|||
tiles.retain(|tile, _| { tile_range.contains(tile) });
|
||||
|
||||
let texture_cache = &mut self.texture_cache;
|
||||
match self.cached_images.try_get_mut(&key) {
|
||||
match self.cached_images.try_get_mut(&key.as_image()) {
|
||||
Some(&mut ImageResult::Multi(ref mut entries)) => {
|
||||
entries.retain(|key, entry| {
|
||||
if key.tile.is_none() || tile_range.contains(&key.tile.unwrap()) {
|
||||
|
@ -1426,13 +1433,13 @@ impl ResourceCache {
|
|||
|
||||
image_template.map(|image_template| {
|
||||
let external_image = match image_template.data {
|
||||
ImageData::External(ext_image) => match ext_image.image_type {
|
||||
CachedImageData::External(ext_image) => match ext_image.image_type {
|
||||
ExternalImageType::TextureHandle(_) => Some(ext_image),
|
||||
// external buffer uses resource_cache.
|
||||
ExternalImageType::Buffer => None,
|
||||
},
|
||||
// raw and blob image are all using resource_cache.
|
||||
ImageData::Raw(..) | ImageData::Blob(..) => None,
|
||||
CachedImageData::Raw(..) | CachedImageData::Blob => None,
|
||||
};
|
||||
|
||||
ImageProperties {
|
||||
|
@ -1511,29 +1518,29 @@ impl ResourceCache {
|
|||
let image_template = self.resources.image_templates.get_mut(request.key).unwrap();
|
||||
debug_assert!(image_template.data.uses_texture_cache());
|
||||
|
||||
let mut updates: SmallVec<[(ImageData, Option<DeviceIntRect>); 1]> = SmallVec::new();
|
||||
let mut updates: SmallVec<[(CachedImageData, Option<DeviceIntRect>); 1]> = SmallVec::new();
|
||||
|
||||
match image_template.data {
|
||||
ImageData::Raw(..) | ImageData::External(..) => {
|
||||
CachedImageData::Raw(..) | CachedImageData::External(..) => {
|
||||
// Safe to clone here since the Raw image data is an
|
||||
// Arc, and the external image data is small.
|
||||
updates.push((image_template.data.clone(), None));
|
||||
}
|
||||
ImageData::Blob(..) => {
|
||||
CachedImageData::Blob => {
|
||||
|
||||
let blob_image = self.rasterized_blob_images.get_mut(&request.key).unwrap();
|
||||
let blob_image = self.rasterized_blob_images.get_mut(&BlobImageKey(request.key)).unwrap();
|
||||
match (blob_image, request.tile) {
|
||||
(RasterizedBlob::Tiled(ref tiles), Some(tile)) => {
|
||||
let img = &tiles[&tile];
|
||||
updates.push((
|
||||
ImageData::Raw(Arc::clone(&img.data)),
|
||||
CachedImageData::Raw(Arc::clone(&img.data)),
|
||||
Some(img.rasterized_rect)
|
||||
));
|
||||
}
|
||||
(RasterizedBlob::NonTiled(ref mut queue), None) => {
|
||||
for img in queue.drain(..) {
|
||||
updates.push((
|
||||
ImageData::Raw(img.data),
|
||||
CachedImageData::Raw(img.data),
|
||||
Some(img.rasterized_rect)
|
||||
));
|
||||
}
|
||||
|
@ -1554,23 +1561,12 @@ impl ResourceCache {
|
|||
};
|
||||
|
||||
let mut descriptor = image_template.descriptor.clone();
|
||||
let mut local_dirty_rect;
|
||||
let mut dirty_rect = entry.dirty_rect.replace_with_empty();
|
||||
|
||||
if let Some(tile) = request.tile {
|
||||
let tile_size = image_template.tiling.unwrap();
|
||||
let clipped_tile_size = compute_tile_size(&descriptor, tile_size, tile);
|
||||
|
||||
local_dirty_rect = if let Some(rect) = entry.dirty_rect.take() {
|
||||
// We should either have a dirty rect, or we are re-uploading where the dirty
|
||||
// rect is ignored anyway.
|
||||
let intersection = intersect_for_tile(rect, clipped_tile_size, tile_size, tile);
|
||||
debug_assert!(intersection.is_some() ||
|
||||
self.texture_cache.needs_upload(&entry.texture_cache_handle));
|
||||
intersection
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// The tiled image could be stored on the CPU as one large image or be
|
||||
// already broken up into tiles. This affects the way we compute the stride
|
||||
// and offset.
|
||||
|
@ -1585,15 +1581,13 @@ impl ResourceCache {
|
|||
}
|
||||
|
||||
descriptor.size = clipped_tile_size;
|
||||
} else {
|
||||
local_dirty_rect = entry.dirty_rect.take();
|
||||
}
|
||||
|
||||
// If we are uploading the dirty region of a blob image we might have several
|
||||
// rects to upload so we use each of these rasterized rects rather than the
|
||||
// overall dirty rect of the image.
|
||||
if blob_rasterized_rect.is_some() {
|
||||
local_dirty_rect = blob_rasterized_rect;
|
||||
if let Some(rect) = blob_rasterized_rect {
|
||||
dirty_rect = DirtyRect::Partial(rect);
|
||||
}
|
||||
|
||||
let filter = match request.rendering {
|
||||
|
@ -1636,7 +1630,7 @@ impl ResourceCache {
|
|||
filter,
|
||||
Some(image_data),
|
||||
[0.0; 3],
|
||||
local_dirty_rect,
|
||||
dirty_rect,
|
||||
gpu_cache,
|
||||
None,
|
||||
UvRectKind::Rect,
|
||||
|
@ -1714,9 +1708,8 @@ impl ResourceCache {
|
|||
// Measure images.
|
||||
for (_, image) in self.resources.image_templates.images.iter() {
|
||||
report.images += match image.data {
|
||||
ImageData::Raw(ref v) => unsafe { op(v.as_ptr() as *const c_void) },
|
||||
ImageData::Blob(ref v) => unsafe { op(v.as_ptr() as *const c_void) },
|
||||
ImageData::External(..) => 0,
|
||||
CachedImageData::Raw(ref v) => unsafe { op(v.as_ptr() as *const c_void) },
|
||||
CachedImageData::Blob | CachedImageData::External(..) => 0,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1747,11 +1740,11 @@ impl ResourceCache {
|
|||
self.delete_image_template(key);
|
||||
}
|
||||
|
||||
let blob_f = |key: &BlobImageKey| { f(&key.as_image()) };
|
||||
debug_assert!(!self.resources.image_templates.images.keys().any(&f));
|
||||
debug_assert!(!self.cached_images.resources.keys().any(&f));
|
||||
debug_assert!(!self.blob_image_templates.keys().any(&f));
|
||||
debug_assert!(!self.rasterized_blob_images.keys().any(&f));
|
||||
|
||||
debug_assert!(!self.blob_image_templates.keys().any(&blob_f));
|
||||
debug_assert!(!self.rasterized_blob_images.keys().any(&blob_f));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1855,6 +1848,19 @@ pub struct PlainCacheOwn {
|
|||
#[cfg(feature = "replay")]
|
||||
const NATIVE_FONT: &'static [u8] = include_bytes!("../res/Proggy.ttf");
|
||||
|
||||
// This currently only casts the unit but will soon apply an offset
|
||||
fn to_image_dirty_rect(blob_dirty_rect: &BlobDirtyRect) -> ImageDirtyRect {
|
||||
match *blob_dirty_rect {
|
||||
DirtyRect::Partial(rect) => DirtyRect::Partial(
|
||||
DeviceIntRect {
|
||||
origin: DeviceIntPoint::new(rect.origin.x, rect.origin.y),
|
||||
size: DeviceIntSize::new(rect.size.width, rect.size.height),
|
||||
}
|
||||
),
|
||||
DirtyRect::All => DirtyRect::All,
|
||||
}
|
||||
}
|
||||
|
||||
impl ResourceCache {
|
||||
#[cfg(feature = "capture")]
|
||||
pub fn save_capture(
|
||||
|
@ -1913,7 +1919,7 @@ impl ResourceCache {
|
|||
for (&key, template) in res.image_templates.images.iter() {
|
||||
let desc = &template.descriptor;
|
||||
match template.data {
|
||||
ImageData::Raw(ref arc) => {
|
||||
CachedImageData::Raw(ref arc) => {
|
||||
let image_id = image_paths.len() + 1;
|
||||
let entry = match image_paths.entry(arc.as_ptr()) {
|
||||
Entry::Occupied(_) => continue,
|
||||
|
@ -1935,22 +1941,21 @@ impl ResourceCache {
|
|||
.unwrap();
|
||||
entry.insert(short_path);
|
||||
}
|
||||
ImageData::Blob(_) => {
|
||||
CachedImageData::Blob => {
|
||||
assert_eq!(template.tiling, None);
|
||||
let blob_request_params = &[
|
||||
BlobImageParams {
|
||||
request: BlobImageRequest {
|
||||
key,
|
||||
key: BlobImageKey(key),
|
||||
//TODO: support tiled blob images
|
||||
// https://github.com/servo/webrender/issues/2236
|
||||
tile: None,
|
||||
},
|
||||
descriptor: BlobImageDescriptor {
|
||||
size: desc.size,
|
||||
offset: DevicePoint::zero(),
|
||||
rect: blob_size(desc.size).into(),
|
||||
format: desc.format,
|
||||
},
|
||||
dirty_rect: None,
|
||||
dirty_rect: DirtyRect::All,
|
||||
}
|
||||
];
|
||||
|
||||
|
@ -1980,7 +1985,7 @@ impl ResourceCache {
|
|||
.unwrap();
|
||||
other_paths.insert(key, short_path);
|
||||
}
|
||||
ImageData::External(ref ext) => {
|
||||
CachedImageData::External(ref ext) => {
|
||||
let short_path = format!("externals/{}", external_images.len() + 1);
|
||||
other_paths.insert(key, short_path.clone());
|
||||
external_images.push(ExternalCaptureImage {
|
||||
|
@ -2015,7 +2020,7 @@ impl ResourceCache {
|
|||
.map(|(key, template)| {
|
||||
(*key, PlainImageTemplate {
|
||||
data: match template.data {
|
||||
ImageData::Raw(ref arc) => image_paths[&arc.as_ptr()].clone(),
|
||||
CachedImageData::Raw(ref arc) => image_paths[&arc.as_ptr()].clone(),
|
||||
_ => other_paths[key].clone(),
|
||||
},
|
||||
descriptor: template.descriptor.clone(),
|
||||
|
@ -2121,7 +2126,7 @@ impl ResourceCache {
|
|||
Some(plain) => {
|
||||
let ext_data = plain.external;
|
||||
external_images.push(plain);
|
||||
ImageData::External(ext_data)
|
||||
CachedImageData::External(ext_data)
|
||||
}
|
||||
None => {
|
||||
let arc = match raw_map.entry(template.data) {
|
||||
|
@ -2138,7 +2143,7 @@ impl ResourceCache {
|
|||
.clone()
|
||||
}
|
||||
};
|
||||
ImageData::Raw(arc)
|
||||
CachedImageData::Raw(arc)
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -2153,3 +2158,12 @@ impl ResourceCache {
|
|||
external_images
|
||||
}
|
||||
}
|
||||
|
||||
/// For now the blob's coordinate space have the same pixel sizes as the
|
||||
/// rendered texture's device space (only a translation is applied).
|
||||
/// So going from one to the other is only a matter of casting away the unit
|
||||
/// for sizes.
|
||||
#[inline]
|
||||
fn blob_size(device_size: DeviceIntSize) -> LayoutIntSize {
|
||||
size2(device_size.width, device_size.height)
|
||||
}
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
* 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::{DebugFlags, DeviceIntPoint, DeviceIntRect, DeviceIntSize};
|
||||
use api::{ExternalImageType, ImageData, ImageFormat};
|
||||
use api::{DebugFlags, DeviceIntPoint, DeviceIntRect, DeviceIntSize, DirtyRect, ImageDirtyRect};
|
||||
use api::{ExternalImageType, ImageFormat};
|
||||
use api::ImageDescriptor;
|
||||
use device::{TextureFilter, total_gpu_bytes_allocated};
|
||||
use freelist::{FreeList, FreeListHandle, UpsertResult, WeakFreeListHandle};
|
||||
|
@ -13,7 +13,7 @@ use internal_types::{CacheTextureId, LayerIndex, TextureUpdateList, TextureUpdat
|
|||
use internal_types::{TextureSource, TextureCacheAllocInfo, TextureCacheUpdate};
|
||||
use profiler::{ResourceProfileCounter, TextureCacheProfileCounters};
|
||||
use render_backend::{FrameId, FrameStamp};
|
||||
use resource_cache::CacheItem;
|
||||
use resource_cache::{CacheItem, CachedImageData};
|
||||
use std::cell::Cell;
|
||||
use std::cmp;
|
||||
use std::mem;
|
||||
|
@ -673,9 +673,9 @@ impl TextureCache {
|
|||
handle: &mut TextureCacheHandle,
|
||||
descriptor: ImageDescriptor,
|
||||
filter: TextureFilter,
|
||||
data: Option<ImageData>,
|
||||
data: Option<CachedImageData>,
|
||||
user_data: [f32; 3],
|
||||
mut dirty_rect: Option<DeviceIntRect>,
|
||||
mut dirty_rect: ImageDirtyRect,
|
||||
gpu_cache: &mut GpuCache,
|
||||
eviction_notice: Option<&EvictionNotice>,
|
||||
uv_rect_kind: UvRectKind,
|
||||
|
@ -702,7 +702,7 @@ impl TextureCache {
|
|||
self.allocate(¶ms, handle);
|
||||
|
||||
// If we reallocated, we need to upload the whole item again.
|
||||
dirty_rect = None;
|
||||
dirty_rect = DirtyRect::All;
|
||||
}
|
||||
|
||||
let entry = self.entries.get_opt_mut(handle)
|
||||
|
@ -742,7 +742,7 @@ impl TextureCache {
|
|||
entry.size,
|
||||
entry.texture_id,
|
||||
layer_index as i32,
|
||||
dirty_rect,
|
||||
&dirty_rect,
|
||||
);
|
||||
self.pending_updates.push_update(op);
|
||||
}
|
||||
|
@ -1385,19 +1385,19 @@ impl TextureCacheUpdate {
|
|||
// rendering thread in order to do an upload to the right
|
||||
// location in the texture cache.
|
||||
fn new_update(
|
||||
data: ImageData,
|
||||
data: CachedImageData,
|
||||
descriptor: &ImageDescriptor,
|
||||
origin: DeviceIntPoint,
|
||||
size: DeviceIntSize,
|
||||
texture_id: CacheTextureId,
|
||||
layer_index: i32,
|
||||
dirty_rect: Option<DeviceIntRect>,
|
||||
dirty_rect: &ImageDirtyRect,
|
||||
) -> TextureCacheUpdate {
|
||||
let source = match data {
|
||||
ImageData::Blob(..) => {
|
||||
CachedImageData::Blob => {
|
||||
panic!("The vector image should have been rasterized.");
|
||||
}
|
||||
ImageData::External(ext_image) => match ext_image.image_type {
|
||||
CachedImageData::External(ext_image) => match ext_image.image_type {
|
||||
ExternalImageType::TextureHandle(_) => {
|
||||
panic!("External texture handle should not go through texture_cache.");
|
||||
}
|
||||
|
@ -1406,7 +1406,7 @@ impl TextureCacheUpdate {
|
|||
channel_index: ext_image.channel_index,
|
||||
},
|
||||
},
|
||||
ImageData::Raw(bytes) => {
|
||||
CachedImageData::Raw(bytes) => {
|
||||
let finish = descriptor.offset +
|
||||
descriptor.size.width * descriptor.format.bytes_per_pixel() +
|
||||
(descriptor.size.height - 1) * descriptor.compute_stride();
|
||||
|
@ -1416,8 +1416,8 @@ impl TextureCacheUpdate {
|
|||
}
|
||||
};
|
||||
|
||||
let update_op = match dirty_rect {
|
||||
Some(dirty) => {
|
||||
let update_op = match *dirty_rect {
|
||||
DirtyRect::Partial(dirty) => {
|
||||
// the dirty rectangle doesn't have to be within the area but has to intersect it, at least
|
||||
let stride = descriptor.compute_stride();
|
||||
let offset = descriptor.offset + dirty.origin.y * stride + dirty.origin.x * descriptor.format.bytes_per_pixel();
|
||||
|
@ -1437,7 +1437,7 @@ impl TextureCacheUpdate {
|
|||
layer_index,
|
||||
}
|
||||
}
|
||||
None => {
|
||||
DirtyRect::All => {
|
||||
TextureCacheUpdate {
|
||||
id: texture_id,
|
||||
rect: DeviceIntRect::new(origin, size),
|
||||
|
|
|
@ -11,11 +11,13 @@ use std::fmt;
|
|||
use std::marker::PhantomData;
|
||||
use std::os::raw::c_void;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
use std::u32;
|
||||
use {BuiltDisplayList, BuiltDisplayListDescriptor, ColorF, DeviceIntPoint, DeviceIntRect};
|
||||
use {DeviceIntSize, ExternalScrollId, FontInstanceKey, FontInstanceOptions};
|
||||
use {FontInstancePlatformOptions, FontKey, FontVariation, GlyphDimensions, GlyphIndex, ImageData};
|
||||
use {ImageDescriptor, ImageKey, ItemTag, LayoutPoint, LayoutSize, LayoutTransform, LayoutVector2D};
|
||||
use {ImageDescriptor, ItemTag, LayoutPoint, LayoutSize, LayoutTransform, LayoutVector2D};
|
||||
use {BlobDirtyRect, ImageDirtyRect, ImageKey, BlobImageKey, BlobImageData};
|
||||
use {NativeFontHandle, WorldPoint};
|
||||
|
||||
pub type TileSize = u16;
|
||||
|
@ -26,8 +28,10 @@ pub type DocumentLayer = i8;
|
|||
pub enum ResourceUpdate {
|
||||
AddImage(AddImage),
|
||||
UpdateImage(UpdateImage),
|
||||
AddBlobImage(AddBlobImage),
|
||||
UpdateBlobImage(UpdateBlobImage),
|
||||
DeleteImage(ImageKey),
|
||||
SetImageVisibleArea(ImageKey, DeviceIntRect),
|
||||
SetBlobImageVisibleArea(BlobImageKey, DeviceIntRect),
|
||||
AddFont(AddFont),
|
||||
DeleteFont(FontKey),
|
||||
AddFontInstance(AddFontInstance),
|
||||
|
@ -321,13 +325,13 @@ impl Transaction {
|
|||
key: ImageKey,
|
||||
descriptor: ImageDescriptor,
|
||||
data: ImageData,
|
||||
dirty_rect: Option<DeviceIntRect>,
|
||||
dirty_rect: &ImageDirtyRect,
|
||||
) {
|
||||
self.resource_updates.push(ResourceUpdate::UpdateImage(UpdateImage {
|
||||
key,
|
||||
descriptor,
|
||||
data,
|
||||
dirty_rect,
|
||||
dirty_rect: *dirty_rect,
|
||||
}));
|
||||
}
|
||||
|
||||
|
@ -335,8 +339,46 @@ impl Transaction {
|
|||
self.resource_updates.push(ResourceUpdate::DeleteImage(key));
|
||||
}
|
||||
|
||||
pub fn set_image_visible_area(&mut self, key: ImageKey, area: DeviceIntRect) {
|
||||
self.resource_updates.push(ResourceUpdate::SetImageVisibleArea(key, area))
|
||||
pub fn add_blob_image(
|
||||
&mut self,
|
||||
key: BlobImageKey,
|
||||
descriptor: ImageDescriptor,
|
||||
data: Arc<BlobImageData>,
|
||||
tiling: Option<TileSize>,
|
||||
) {
|
||||
self.resource_updates.push(
|
||||
ResourceUpdate::AddBlobImage(AddBlobImage {
|
||||
key,
|
||||
descriptor,
|
||||
data,
|
||||
tiling,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
pub fn update_blob_image(
|
||||
&mut self,
|
||||
key: BlobImageKey,
|
||||
descriptor: ImageDescriptor,
|
||||
data: Arc<BlobImageData>,
|
||||
dirty_rect: &BlobDirtyRect,
|
||||
) {
|
||||
self.resource_updates.push(
|
||||
ResourceUpdate::UpdateBlobImage(UpdateBlobImage {
|
||||
key,
|
||||
descriptor,
|
||||
data,
|
||||
dirty_rect: *dirty_rect,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
pub fn delete_blob_image(&mut self, key: BlobImageKey) {
|
||||
self.resource_updates.push(ResourceUpdate::DeleteImage(key.as_image()));
|
||||
}
|
||||
|
||||
pub fn set_blob_image_visible_area(&mut self, key: BlobImageKey, area: DeviceIntRect) {
|
||||
self.resource_updates.push(ResourceUpdate::SetBlobImageVisibleArea(key, area))
|
||||
}
|
||||
|
||||
pub fn add_raw_font(&mut self, key: FontKey, bytes: Vec<u8>, index: u32) {
|
||||
|
@ -464,7 +506,25 @@ pub struct UpdateImage {
|
|||
pub key: ImageKey,
|
||||
pub descriptor: ImageDescriptor,
|
||||
pub data: ImageData,
|
||||
pub dirty_rect: Option<DeviceIntRect>,
|
||||
pub dirty_rect: ImageDirtyRect,
|
||||
}
|
||||
|
||||
#[derive(Clone, Deserialize, Serialize)]
|
||||
pub struct AddBlobImage {
|
||||
pub key: BlobImageKey,
|
||||
pub descriptor: ImageDescriptor,
|
||||
//#[serde(with = "serde_image_data_raw")]
|
||||
pub data: Arc<BlobImageData>,
|
||||
pub tiling: Option<TileSize>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Deserialize, Serialize)]
|
||||
pub struct UpdateBlobImage {
|
||||
pub key: BlobImageKey,
|
||||
pub descriptor: ImageDescriptor,
|
||||
//#[serde(with = "serde_image_data_raw")]
|
||||
pub data: Arc<BlobImageData>,
|
||||
pub dirty_rect: BlobDirtyRect,
|
||||
}
|
||||
|
||||
#[derive(Clone, Deserialize, Serialize)]
|
||||
|
@ -1011,6 +1071,11 @@ impl RenderApi {
|
|||
ImageKey::new(self.namespace_id, new_id)
|
||||
}
|
||||
|
||||
/// Creates a `BlobImageKey`.
|
||||
pub fn generate_blob_image_key(&self) -> BlobImageKey {
|
||||
BlobImageKey(self.generate_image_key())
|
||||
}
|
||||
|
||||
/// Add/remove/update resources such as images and fonts.
|
||||
pub fn update_resources(&self, resources: Vec<ResourceUpdate>) {
|
||||
if resources.is_empty() {
|
||||
|
|
|
@ -8,9 +8,10 @@ extern crate serde_bytes;
|
|||
|
||||
use font::{FontInstanceKey, FontInstanceData, FontKey, FontTemplate};
|
||||
use std::sync::Arc;
|
||||
use {DevicePoint, DeviceIntPoint, DeviceIntRect, DeviceIntSize};
|
||||
use {IdNamespace, TileOffset, TileSize};
|
||||
use euclid::size2;
|
||||
use {DeviceIntPoint, DeviceIntRect, DeviceIntSize, LayoutIntRect};
|
||||
use {BlobDirtyRect, IdNamespace, TileOffset, TileSize};
|
||||
use euclid::{size2, TypedRect, num::Zero};
|
||||
use std::ops::{Add, Sub};
|
||||
|
||||
/// An opaque identifier describing an image registered with WebRender.
|
||||
/// This is used as a handle to reference images, and is used as the
|
||||
|
@ -29,6 +30,20 @@ impl ImageKey {
|
|||
}
|
||||
}
|
||||
|
||||
/// An opaque identifier describing a blob image registered with WebRender.
|
||||
/// This is used as a handle to reference blob images, and can be used as an
|
||||
/// image in display items.
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
pub struct BlobImageKey(pub ImageKey);
|
||||
|
||||
impl BlobImageKey {
|
||||
/// Interpret this blob image as an image for a display item.
|
||||
pub fn as_image(&self) -> ImageKey {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
/// An arbitrary identifier for an external image provided by the
|
||||
/// application. It must be a unique identifier for each external
|
||||
/// image.
|
||||
|
@ -228,9 +243,6 @@ pub enum ImageData {
|
|||
/// A simple series of bytes, provided by the embedding and owned by WebRender.
|
||||
/// The format is stored out-of-band, currently in ImageDescriptor.
|
||||
Raw(#[serde(with = "serde_image_data_raw")] Arc<Vec<u8>>),
|
||||
/// An series of commands that can be rasterized into an image via an
|
||||
/// embedding-provided callback.
|
||||
Blob(#[serde(with = "serde_image_data_raw")] Arc<BlobImageData>),
|
||||
/// An image owned by the embedding, and referenced by WebRender. This may
|
||||
/// take the form of a texture or a heap-allocated buffer.
|
||||
External(ExternalImageData),
|
||||
|
@ -261,34 +273,6 @@ impl ImageData {
|
|||
pub fn new_shared(bytes: Arc<Vec<u8>>) -> Self {
|
||||
ImageData::Raw(bytes)
|
||||
}
|
||||
|
||||
/// Mints a new Blob ImageData.
|
||||
pub fn new_blob_image(commands: BlobImageData) -> Self {
|
||||
ImageData::Blob(Arc::new(commands))
|
||||
}
|
||||
|
||||
/// Returns true if this ImageData represents a blob.
|
||||
#[inline]
|
||||
pub fn is_blob(&self) -> bool {
|
||||
match *self {
|
||||
ImageData::Blob(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if this variant of ImageData should go through the texture
|
||||
/// cache.
|
||||
#[inline]
|
||||
pub fn uses_texture_cache(&self) -> bool {
|
||||
match *self {
|
||||
ImageData::External(ref ext_data) => match ext_data.image_type {
|
||||
ExternalImageType::TextureHandle(_) => false,
|
||||
ExternalImageType::Buffer => true,
|
||||
},
|
||||
ImageData::Blob(_) => true,
|
||||
ImageData::Raw(_) => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The resources exposed by the resource cache available for use by the blob rasterizer.
|
||||
|
@ -297,8 +281,6 @@ pub trait BlobImageResources {
|
|||
fn get_font_data(&self, key: FontKey) -> &FontTemplate;
|
||||
/// Returns the `FontInstanceData` for the given key, if found.
|
||||
fn get_font_instance_data(&self, key: FontInstanceKey) -> Option<FontInstanceData>;
|
||||
/// Returns the image metadata and backing store for the given key, if found.
|
||||
fn get_image(&self, key: ImageKey) -> Option<(&ImageData, &ImageDescriptor)>;
|
||||
}
|
||||
|
||||
/// A handler on the render backend that can create rasterizer objects which will
|
||||
|
@ -319,13 +301,13 @@ pub trait BlobImageHandler: Send {
|
|||
);
|
||||
|
||||
/// Register a blob image.
|
||||
fn add(&mut self, key: ImageKey, data: Arc<BlobImageData>, tiling: Option<TileSize>);
|
||||
fn add(&mut self, key: BlobImageKey, data: Arc<BlobImageData>, tiling: Option<TileSize>);
|
||||
|
||||
/// Update an already registered blob image.
|
||||
fn update(&mut self, key: ImageKey, data: Arc<BlobImageData>, dirty_rect: Option<DeviceIntRect>);
|
||||
fn update(&mut self, key: BlobImageKey, data: Arc<BlobImageData>, dirty_rect: &BlobDirtyRect);
|
||||
|
||||
/// Delete an already registered blob image.
|
||||
fn delete(&mut self, key: ImageKey);
|
||||
fn delete(&mut self, key: BlobImageKey);
|
||||
|
||||
/// A hook to let the handler clean up any state related to a font which the resource
|
||||
/// cache is about to delete.
|
||||
|
@ -365,7 +347,100 @@ pub struct BlobImageParams {
|
|||
/// the entire image when only a portion is updated.
|
||||
///
|
||||
/// If set to None the entire image is rasterized.
|
||||
pub dirty_rect: Option<DeviceIntRect>,
|
||||
pub dirty_rect: BlobDirtyRect,
|
||||
}
|
||||
|
||||
/// The possible states of a Dirty rect.
|
||||
///
|
||||
/// This exists because people kept getting confused with `Option<Rect>`.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub enum DirtyRect<T: Copy, U> {
|
||||
/// Everything is Dirty, equivalent to Partial(image_bounds)
|
||||
All,
|
||||
/// Some specific amount is dirty
|
||||
Partial(TypedRect<T, U>)
|
||||
}
|
||||
|
||||
impl<T, U> DirtyRect<T, U>
|
||||
where
|
||||
T: Copy + Clone
|
||||
+ PartialOrd + PartialEq
|
||||
+ Add<T, Output = T>
|
||||
+ Sub<T, Output = T>
|
||||
+ Zero
|
||||
{
|
||||
/// Creates an empty DirtyRect (indicating nothing is invalid)
|
||||
pub fn empty() -> Self {
|
||||
DirtyRect::Partial(TypedRect::zero())
|
||||
}
|
||||
|
||||
/// Returns whether the dirty rect is empty
|
||||
pub fn is_empty(&self) -> bool {
|
||||
match self {
|
||||
DirtyRect::All => false,
|
||||
DirtyRect::Partial(rect) => rect.is_empty(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Replaces self with the empty rect and returns the old value.
|
||||
pub fn replace_with_empty(&mut self) -> Self {
|
||||
::std::mem::replace(self, DirtyRect::empty())
|
||||
}
|
||||
|
||||
/// Maps over the contents of Partial.
|
||||
pub fn map<F>(self, func: F) -> Self
|
||||
where F: FnOnce(TypedRect<T, U>) -> TypedRect<T, U>,
|
||||
{
|
||||
use DirtyRect::*;
|
||||
|
||||
match self {
|
||||
All => All,
|
||||
Partial(rect) => Partial(func(rect)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Unions the dirty rects.
|
||||
pub fn union(&self, other: &Self) -> Self {
|
||||
use DirtyRect::*;
|
||||
|
||||
match (*self, *other) {
|
||||
(All, _) | (_, All) => All,
|
||||
(Partial(rect1), Partial(rect2)) => Partial(rect1.union(&rect2)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Intersects the dirty rects.
|
||||
pub fn intersection(&self, other: &Self) -> Self {
|
||||
use DirtyRect::*;
|
||||
|
||||
match (*self, *other) {
|
||||
(All, rect) | (rect, All) => rect,
|
||||
(Partial(rect1), Partial(rect2)) => Partial(rect1.intersection(&rect2)
|
||||
.unwrap_or(TypedRect::zero()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts the dirty rect into a subrect of the given one via intersection.
|
||||
pub fn to_subrect_of(&self, rect: &TypedRect<T, U>) -> TypedRect<T, U> {
|
||||
use DirtyRect::*;
|
||||
|
||||
match *self {
|
||||
All => *rect,
|
||||
Partial(dirty_rect) => dirty_rect.intersection(rect)
|
||||
.unwrap_or(TypedRect::zero()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, U> Copy for DirtyRect<T, U> {}
|
||||
impl<T: Copy, U> Clone for DirtyRect<T, U> {
|
||||
fn clone(&self) -> Self { *self }
|
||||
}
|
||||
|
||||
impl<T: Copy, U> From<TypedRect<T, U>> for DirtyRect<T, U> {
|
||||
fn from(rect: TypedRect<T, U>) -> Self {
|
||||
DirtyRect::Partial(rect)
|
||||
}
|
||||
}
|
||||
|
||||
/// Backing store for blob image command streams.
|
||||
|
@ -378,11 +453,9 @@ pub type BlobImageResult = Result<RasterizedBlobImage, BlobImageError>;
|
|||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct BlobImageDescriptor {
|
||||
/// Size in device pixels of the blob's output image.
|
||||
pub size: DeviceIntSize,
|
||||
/// When tiling, offset point in device pixels of this tile in the full
|
||||
/// image. Generally (0, 0) outside of tiling.
|
||||
pub offset: DevicePoint,
|
||||
/// Surface of the image or tile to render in the same coordinate space as
|
||||
/// the drawing commands.
|
||||
pub rect: LayoutIntRect,
|
||||
/// Format for the data in the backing store.
|
||||
pub format: ImageFormat,
|
||||
}
|
||||
|
@ -390,7 +463,8 @@ pub struct BlobImageDescriptor {
|
|||
/// Representation of a rasterized blob image. This is obtained by passing
|
||||
/// `BlobImageData` to the embedding via the rasterization callback.
|
||||
pub struct RasterizedBlobImage {
|
||||
/// The bounding rectangle for this blob image.
|
||||
/// The rectangle that was rasterized in device pixels, relative to the
|
||||
/// image or tile.
|
||||
pub rasterized_rect: DeviceIntRect,
|
||||
/// Backing store. The format is stored out of band in `BlobImageDescriptor`.
|
||||
pub data: Arc<Vec<u8>>,
|
||||
|
@ -412,7 +486,7 @@ pub enum BlobImageError {
|
|||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
pub struct BlobImageRequest {
|
||||
/// Unique handle to the image.
|
||||
pub key: ImageKey,
|
||||
pub key: BlobImageKey,
|
||||
/// Tiling offset in number of tiles, if applicable.
|
||||
///
|
||||
/// `None` if the image will not be tiled.
|
||||
|
|
|
@ -13,12 +13,13 @@
|
|||
//! in the context of coordinate systems.
|
||||
|
||||
use app_units::Au;
|
||||
use euclid::{Length, TypedRect, TypedScale, TypedSize2D, TypedTransform3D};
|
||||
use euclid::{Length, TypedRect, TypedScale, TypedSize2D, TypedTransform3D, TypedTranslation2D};
|
||||
use euclid::{TypedPoint2D, TypedPoint3D, TypedVector2D, TypedVector3D, TypedSideOffsets2D};
|
||||
use DirtyRect;
|
||||
|
||||
/// Geometry in the coordinate system of the render target (screen or intermediate
|
||||
/// surface) in physical pixels.
|
||||
#[derive(Hash, Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
|
||||
#[derive(Hash, Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
|
||||
pub struct DevicePixel;
|
||||
|
||||
pub type DeviceIntRect = TypedRect<i32, DevicePixel>;
|
||||
|
@ -75,6 +76,10 @@ pub type LayoutVector3D = TypedVector3D<f32, LayoutPixel>;
|
|||
pub type LayoutSize = TypedSize2D<f32, LayoutPixel>;
|
||||
pub type LayoutSideOffsets = TypedSideOffsets2D<f32, LayoutPixel>;
|
||||
|
||||
pub type LayoutIntRect = TypedRect<i32, LayoutPixel>;
|
||||
pub type LayoutIntPoint = TypedPoint2D<i32, LayoutPixel>;
|
||||
pub type LayoutIntSize = TypedSize2D<i32, LayoutPixel>;
|
||||
|
||||
/// Geometry in the document's coordinate space (logical pixels).
|
||||
#[derive(Hash, Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
|
||||
pub struct WorldPixel;
|
||||
|
@ -119,6 +124,11 @@ pub type LayoutRectAu = TypedRect<Au, LayoutPixel>;
|
|||
pub type LayoutSizeAu = TypedSize2D<Au, LayoutPixel>;
|
||||
pub type LayoutVector2DAu = TypedVector2D<Au, LayoutPixel>;
|
||||
|
||||
pub type ImageDirtyRect = DirtyRect<i32, DevicePixel>;
|
||||
pub type BlobDirtyRect = DirtyRect<i32, LayoutPixel>;
|
||||
|
||||
pub type BlobToDeviceTranslation = TypedTranslation2D<i32, LayoutPixel, DevicePixel>;
|
||||
|
||||
/// Stores two coordinates in texel space. The coordinates
|
||||
/// are stored in texel coordinates because the texture atlas
|
||||
/// may grow. Storing them as texel coords and normalizing
|
||||
|
|
|
@ -8,13 +8,11 @@ use std::collections::HashMap;
|
|||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
use webrender::api::*;
|
||||
use webrender::intersect_for_tile;
|
||||
use euclid::size2;
|
||||
|
||||
// Serialize/deserialize the blob.
|
||||
|
||||
pub fn serialize_blob(color: ColorU) -> Vec<u8> {
|
||||
vec![color.r, color.g, color.b, color.a]
|
||||
pub fn serialize_blob(color: ColorU) -> Arc<Vec<u8>> {
|
||||
Arc::new(vec![color.r, color.g, color.b, color.a])
|
||||
}
|
||||
|
||||
fn deserialize_blob(blob: &[u8]) -> Result<ColorU, ()> {
|
||||
|
@ -38,12 +36,11 @@ fn render_blob(
|
|||
color: ColorU,
|
||||
descriptor: &BlobImageDescriptor,
|
||||
tile: Option<(TileSize, TileOffset)>,
|
||||
dirty_rect: Option<DeviceIntRect>,
|
||||
dirty_rect: &BlobDirtyRect,
|
||||
) -> BlobImageResult {
|
||||
// Allocate storage for the result. Right now the resource cache expects the
|
||||
// tiles to have have no stride or offset.
|
||||
let buf_size = descriptor.size.width *
|
||||
descriptor.size.height *
|
||||
let buf_size = descriptor.rect.size.area() *
|
||||
descriptor.format.bytes_per_pixel();
|
||||
let mut texels = vec![0u8; (buf_size) as usize];
|
||||
|
||||
|
@ -54,23 +51,19 @@ fn render_blob(
|
|||
None => true,
|
||||
};
|
||||
|
||||
let mut dirty_rect = dirty_rect.unwrap_or(DeviceIntRect::new(
|
||||
descriptor.offset.to_i32(),
|
||||
descriptor.size,
|
||||
));
|
||||
let dirty_rect = dirty_rect.to_subrect_of(&descriptor.rect);
|
||||
|
||||
if let Some((tile_size, tile)) = tile {
|
||||
dirty_rect = intersect_for_tile(dirty_rect, size2(tile_size as i32, tile_size as i32),
|
||||
tile_size, tile)
|
||||
.expect("empty rects should be culled by webrender");
|
||||
}
|
||||
// We want the dirty rect local to the tile rather than the whole image.
|
||||
let tx: BlobToDeviceTranslation = (-descriptor.rect.origin.to_vector()).into();
|
||||
|
||||
for y in dirty_rect.min_y() .. dirty_rect.max_y() {
|
||||
for x in dirty_rect.min_x() .. dirty_rect.max_x() {
|
||||
let rasterized_rect = tx.transform_rect(&dirty_rect);
|
||||
|
||||
for y in rasterized_rect.min_y() .. rasterized_rect.max_y() {
|
||||
for x in rasterized_rect.min_x() .. rasterized_rect.max_x() {
|
||||
// Apply the tile's offset. This is important: all drawing commands should be
|
||||
// translated by this offset to give correct results with tiled blob images.
|
||||
let x2 = x + descriptor.offset.x as i32;
|
||||
let y2 = y + descriptor.offset.y as i32;
|
||||
let x2 = x + descriptor.rect.origin.x;
|
||||
let y2 = y + descriptor.rect.origin.y;
|
||||
|
||||
// Render a simple checkerboard pattern
|
||||
let checker = if (x2 % 20 >= 10) != (y2 % 20 >= 10) {
|
||||
|
@ -84,13 +77,14 @@ fn render_blob(
|
|||
match descriptor.format {
|
||||
ImageFormat::BGRA8 => {
|
||||
let a = color.a * checker + tc;
|
||||
texels[((y * descriptor.size.width + x) * 4 + 0) as usize] = premul(color.b * checker + tc, a);
|
||||
texels[((y * descriptor.size.width + x) * 4 + 1) as usize] = premul(color.g * checker + tc, a);
|
||||
texels[((y * descriptor.size.width + x) * 4 + 2) as usize] = premul(color.r * checker + tc, a);
|
||||
texels[((y * descriptor.size.width + x) * 4 + 3) as usize] = a;
|
||||
let pixel_offset = ((y * descriptor.rect.size.width + x) * 4) as usize;
|
||||
texels[pixel_offset + 0] = premul(color.b * checker + tc, a);
|
||||
texels[pixel_offset + 1] = premul(color.g * checker + tc, a);
|
||||
texels[pixel_offset + 2] = premul(color.r * checker + tc, a);
|
||||
texels[pixel_offset + 3] = a;
|
||||
}
|
||||
ImageFormat::R8 => {
|
||||
texels[(y * descriptor.size.width + x) as usize] = color.a * checker + tc;
|
||||
texels[(y * descriptor.rect.size.width + x) as usize] = color.a * checker + tc;
|
||||
}
|
||||
_ => {
|
||||
return Err(BlobImageError::Other(
|
||||
|
@ -103,7 +97,7 @@ fn render_blob(
|
|||
|
||||
Ok(RasterizedBlobImage {
|
||||
data: Arc::new(texels),
|
||||
rasterized_rect: dirty_rect,
|
||||
rasterized_rect,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -120,7 +114,7 @@ impl BlobCallbacks {
|
|||
}
|
||||
|
||||
pub struct CheckerboardRenderer {
|
||||
image_cmds: HashMap<ImageKey, (ColorU, Option<TileSize>)>,
|
||||
image_cmds: HashMap<BlobImageKey, (ColorU, Option<TileSize>)>,
|
||||
callbacks: Arc<Mutex<BlobCallbacks>>,
|
||||
}
|
||||
|
||||
|
@ -134,18 +128,18 @@ impl CheckerboardRenderer {
|
|||
}
|
||||
|
||||
impl BlobImageHandler for CheckerboardRenderer {
|
||||
fn add(&mut self, key: ImageKey, cmds: Arc<BlobImageData>, tile_size: Option<TileSize>) {
|
||||
fn add(&mut self, key: BlobImageKey, cmds: Arc<BlobImageData>, tile_size: Option<TileSize>) {
|
||||
self.image_cmds
|
||||
.insert(key, (deserialize_blob(&cmds[..]).unwrap(), tile_size));
|
||||
}
|
||||
|
||||
fn update(&mut self, key: ImageKey, cmds: Arc<BlobImageData>, _dirty_rect: Option<DeviceIntRect>) {
|
||||
fn update(&mut self, key: BlobImageKey, cmds: Arc<BlobImageData>, _dirty_rect: &BlobDirtyRect) {
|
||||
// Here, updating is just replacing the current version of the commands with
|
||||
// the new one (no incremental updates).
|
||||
self.image_cmds.get_mut(&key).unwrap().0 = deserialize_blob(&cmds[..]).unwrap();
|
||||
}
|
||||
|
||||
fn delete(&mut self, key: ImageKey) {
|
||||
fn delete(&mut self, key: BlobImageKey) {
|
||||
self.image_cmds.remove(&key);
|
||||
}
|
||||
|
||||
|
@ -175,11 +169,11 @@ struct Command {
|
|||
color: ColorU,
|
||||
descriptor: BlobImageDescriptor,
|
||||
tile: Option<(TileSize, TileOffset)>,
|
||||
dirty_rect: Option<DeviceIntRect>
|
||||
dirty_rect: BlobDirtyRect,
|
||||
}
|
||||
|
||||
struct Rasterizer {
|
||||
image_cmds: HashMap<ImageKey, (ColorU, Option<TileSize>)>,
|
||||
image_cmds: HashMap<BlobImageKey, (ColorU, Option<TileSize>)>,
|
||||
}
|
||||
|
||||
impl AsyncBlobImageRasterizer for Rasterizer {
|
||||
|
@ -205,7 +199,7 @@ impl AsyncBlobImageRasterizer for Rasterizer {
|
|||
).collect();
|
||||
|
||||
requests.iter().map(|cmd| {
|
||||
(cmd.request, render_blob(cmd.color, &cmd.descriptor, cmd.tile, cmd.dirty_rect))
|
||||
(cmd.request, render_blob(cmd.color, &cmd.descriptor, cmd.tile, &cmd.dirty_rect))
|
||||
}).collect()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -120,7 +120,7 @@ impl JsonFrameWriter {
|
|||
);
|
||||
let bytes = match img.data {
|
||||
ImageData::Raw(ref v) => (**v).clone(),
|
||||
ImageData::External(_) | ImageData::Blob(_) => {
|
||||
ImageData::External(_) => {
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
@ -154,6 +154,10 @@ impl JsonFrameWriter {
|
|||
}
|
||||
}
|
||||
}
|
||||
ResourceUpdate::AddBlobImage(..)
|
||||
| ResourceUpdate::UpdateBlobImage(..) => {
|
||||
println!("Blob images not supported (ignoring command).");
|
||||
}
|
||||
ResourceUpdate::DeleteImage(img) => {
|
||||
self.images.remove(&img);
|
||||
}
|
||||
|
@ -177,7 +181,7 @@ impl JsonFrameWriter {
|
|||
);
|
||||
}
|
||||
ResourceUpdate::DeleteFontInstance(_) => {}
|
||||
ResourceUpdate::SetImageVisibleArea(..) => {}
|
||||
ResourceUpdate::SetBlobImageVisibleArea(..) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -94,11 +94,11 @@ impl<'a> RawtestHarness<'a> {
|
|||
let layout_size = LayoutSize::new(800., 800.);
|
||||
let mut txn = Transaction::new();
|
||||
|
||||
let blob_img = self.wrench.api.generate_image_key();
|
||||
txn.add_image(
|
||||
let blob_img = self.wrench.api.generate_blob_image_key();
|
||||
txn.add_blob_image(
|
||||
blob_img,
|
||||
ImageDescriptor::new(151, 56, ImageFormat::BGRA8, true, false),
|
||||
ImageData::new_blob_image(blob::serialize_blob(ColorU::new(50, 50, 150, 255))),
|
||||
blob::serialize_blob(ColorU::new(50, 50, 150, 255)),
|
||||
Some(128),
|
||||
);
|
||||
|
||||
|
@ -113,7 +113,7 @@ impl<'a> RawtestHarness<'a> {
|
|||
size(151.0, 56.0),
|
||||
ImageRendering::Auto,
|
||||
AlphaType::PremultipliedAlpha,
|
||||
blob_img,
|
||||
blob_img.as_image(),
|
||||
ColorF::WHITE,
|
||||
);
|
||||
|
||||
|
@ -127,7 +127,7 @@ impl<'a> RawtestHarness<'a> {
|
|||
// Leaving a tiled blob image in the resource cache
|
||||
// confuses the `test_capture`. TODO: remove this
|
||||
txn = Transaction::new();
|
||||
txn.delete_image(blob_img);
|
||||
txn.delete_blob_image(blob_img);
|
||||
self.wrench.api.update_resources(txn.resource_updates);
|
||||
}
|
||||
|
||||
|
@ -149,11 +149,11 @@ impl<'a> RawtestHarness<'a> {
|
|||
let layout_size = LayoutSize::new(800., 800.);
|
||||
let mut txn = Transaction::new();
|
||||
|
||||
let blob_img = self.wrench.api.generate_image_key();
|
||||
txn.add_image(
|
||||
let blob_img = self.wrench.api.generate_blob_image_key();
|
||||
txn.add_blob_image(
|
||||
blob_img,
|
||||
ImageDescriptor::new(1510, 111256, ImageFormat::BGRA8, false, false),
|
||||
ImageData::new_blob_image(blob::serialize_blob(ColorU::new(50, 50, 150, 255))),
|
||||
blob::serialize_blob(ColorU::new(50, 50, 150, 255)),
|
||||
Some(31),
|
||||
);
|
||||
|
||||
|
@ -180,10 +180,10 @@ impl<'a> RawtestHarness<'a> {
|
|||
image_size,
|
||||
ImageRendering::Auto,
|
||||
AlphaType::PremultipliedAlpha,
|
||||
blob_img,
|
||||
blob_img.as_image(),
|
||||
ColorF::WHITE,
|
||||
);
|
||||
txn.set_image_visible_area(
|
||||
txn.set_blob_image_visible_area(
|
||||
blob_img,
|
||||
DeviceIntRect {
|
||||
origin: point2(0, 111256 / 30),
|
||||
|
@ -235,7 +235,7 @@ impl<'a> RawtestHarness<'a> {
|
|||
// Leaving a tiled blob image in the resource cache
|
||||
// confuses the `test_capture`. TODO: remove this
|
||||
txn = Transaction::new();
|
||||
txn.delete_image(blob_img);
|
||||
txn.delete_blob_image(blob_img);
|
||||
self.wrench.api.update_resources(txn.resource_updates);
|
||||
|
||||
*self.wrench.callbacks.lock().unwrap() = blob::BlobCallbacks::new();
|
||||
|
@ -265,8 +265,8 @@ impl<'a> RawtestHarness<'a> {
|
|||
let mut builder = DisplayListBuilder::new(self.wrench.root_pipeline_id, layout_size);
|
||||
let mut txn = Transaction::new();
|
||||
|
||||
let blob_img1 = self.wrench.api.generate_image_key();
|
||||
txn.add_image(
|
||||
let blob_img1 = self.wrench.api.generate_blob_image_key();
|
||||
txn.add_blob_image(
|
||||
blob_img1,
|
||||
ImageDescriptor::new(
|
||||
image_size.width as i32,
|
||||
|
@ -275,7 +275,7 @@ impl<'a> RawtestHarness<'a> {
|
|||
false,
|
||||
false
|
||||
),
|
||||
ImageData::new_blob_image(blob::serialize_blob(ColorU::new(50, 50, 150, 255))),
|
||||
blob::serialize_blob(ColorU::new(50, 50, 150, 255)),
|
||||
Some(100),
|
||||
);
|
||||
|
||||
|
@ -285,7 +285,7 @@ impl<'a> RawtestHarness<'a> {
|
|||
image_size,
|
||||
ImageRendering::Auto,
|
||||
AlphaType::PremultipliedAlpha,
|
||||
blob_img1,
|
||||
blob_img1.as_image(),
|
||||
ColorF::WHITE,
|
||||
);
|
||||
|
||||
|
@ -295,8 +295,8 @@ impl<'a> RawtestHarness<'a> {
|
|||
let mut builder = DisplayListBuilder::new(self.wrench.root_pipeline_id, layout_size);
|
||||
let mut txn = Transaction::new();
|
||||
|
||||
let blob_img2 = self.wrench.api.generate_image_key();
|
||||
txn.add_image(
|
||||
let blob_img2 = self.wrench.api.generate_blob_image_key();
|
||||
txn.add_blob_image(
|
||||
blob_img2,
|
||||
ImageDescriptor::new(
|
||||
image_size.width as i32,
|
||||
|
@ -305,12 +305,12 @@ impl<'a> RawtestHarness<'a> {
|
|||
false,
|
||||
false
|
||||
),
|
||||
ImageData::new_blob_image(blob::serialize_blob(ColorU::new(50, 50, 150, 255))),
|
||||
blob::serialize_blob(ColorU::new(50, 50, 150, 255)),
|
||||
Some(100),
|
||||
);
|
||||
// Set a visible rectangle that is too small.
|
||||
// This will force sync rasterization of the missing tiles during frame building.
|
||||
txn.set_image_visible_area(blob_img2, DeviceIntRect {
|
||||
txn.set_blob_image_visible_area(blob_img2, DeviceIntRect {
|
||||
origin: point2(200, 200),
|
||||
size: size2(80, 80),
|
||||
});
|
||||
|
@ -321,7 +321,7 @@ impl<'a> RawtestHarness<'a> {
|
|||
image_size,
|
||||
ImageRendering::Auto,
|
||||
AlphaType::PremultipliedAlpha,
|
||||
blob_img2,
|
||||
blob_img2.as_image(),
|
||||
ColorF::WHITE,
|
||||
);
|
||||
|
||||
|
@ -331,8 +331,8 @@ impl<'a> RawtestHarness<'a> {
|
|||
assert!(pixels1 == pixels2);
|
||||
|
||||
txn = Transaction::new();
|
||||
txn.delete_image(blob_img1);
|
||||
txn.delete_image(blob_img2);
|
||||
txn.delete_blob_image(blob_img1);
|
||||
txn.delete_blob_image(blob_img2);
|
||||
self.wrench.api.update_resources(txn.resource_updates);
|
||||
}
|
||||
|
||||
|
@ -354,11 +354,11 @@ impl<'a> RawtestHarness<'a> {
|
|||
let mut txn = Transaction::new();
|
||||
let layout_size = LayoutSize::new(800., 800.);
|
||||
|
||||
let blob_img = self.wrench.api.generate_image_key();
|
||||
txn.add_image(
|
||||
let blob_img = self.wrench.api.generate_blob_image_key();
|
||||
txn.add_blob_image(
|
||||
blob_img,
|
||||
ImageDescriptor::new(1510, 1510, ImageFormat::BGRA8, false, false),
|
||||
ImageData::new_blob_image(blob::serialize_blob(ColorU::new(50, 50, 150, 255))),
|
||||
blob::serialize_blob(ColorU::new(50, 50, 150, 255)),
|
||||
None,
|
||||
);
|
||||
|
||||
|
@ -375,7 +375,7 @@ impl<'a> RawtestHarness<'a> {
|
|||
image_size,
|
||||
ImageRendering::Auto,
|
||||
AlphaType::PremultipliedAlpha,
|
||||
blob_img,
|
||||
blob_img.as_image(),
|
||||
ColorF::WHITE,
|
||||
);
|
||||
|
||||
|
@ -400,7 +400,7 @@ impl<'a> RawtestHarness<'a> {
|
|||
image_size,
|
||||
ImageRendering::Auto,
|
||||
AlphaType::PremultipliedAlpha,
|
||||
blob_img,
|
||||
blob_img.as_image(),
|
||||
ColorF::WHITE,
|
||||
);
|
||||
|
||||
|
@ -410,11 +410,11 @@ impl<'a> RawtestHarness<'a> {
|
|||
|
||||
let mut txn = Transaction::new();
|
||||
|
||||
txn.update_image(
|
||||
txn.update_blob_image(
|
||||
blob_img,
|
||||
ImageDescriptor::new(1510, 1510, ImageFormat::BGRA8, false, false),
|
||||
ImageData::new_blob_image(blob::serialize_blob(ColorU::new(50, 50, 150, 255))),
|
||||
Some(rect(10, 10, 100, 100)),
|
||||
blob::serialize_blob(ColorU::new(50, 50, 150, 255)),
|
||||
&rect(10, 10, 100, 100).into(),
|
||||
);
|
||||
|
||||
let mut builder = DisplayListBuilder::new(self.wrench.root_pipeline_id, layout_size);
|
||||
|
@ -430,7 +430,7 @@ impl<'a> RawtestHarness<'a> {
|
|||
image_size,
|
||||
ImageRendering::Auto,
|
||||
AlphaType::PremultipliedAlpha,
|
||||
blob_img,
|
||||
blob_img.as_image(),
|
||||
ColorF::WHITE,
|
||||
);
|
||||
|
||||
|
@ -445,7 +445,7 @@ impl<'a> RawtestHarness<'a> {
|
|||
// Leaving a tiled blob image in the resource cache
|
||||
// confuses the `test_capture`. TODO: remove this
|
||||
txn = Transaction::new();
|
||||
txn.delete_image(blob_img);
|
||||
txn.delete_blob_image(blob_img);
|
||||
self.wrench.api.update_resources(txn.resource_updates);
|
||||
}
|
||||
|
||||
|
@ -465,11 +465,11 @@ impl<'a> RawtestHarness<'a> {
|
|||
{
|
||||
let api = &self.wrench.api;
|
||||
|
||||
blob_img = api.generate_image_key();
|
||||
txn.add_image(
|
||||
blob_img = api.generate_blob_image_key();
|
||||
txn.add_blob_image(
|
||||
blob_img,
|
||||
ImageDescriptor::new(500, 500, ImageFormat::BGRA8, false, false),
|
||||
ImageData::new_blob_image(blob::serialize_blob(ColorU::new(50, 50, 150, 255))),
|
||||
blob::serialize_blob(ColorU::new(50, 50, 150, 255)),
|
||||
None,
|
||||
);
|
||||
}
|
||||
|
@ -491,7 +491,7 @@ impl<'a> RawtestHarness<'a> {
|
|||
size(0.0, 0.0),
|
||||
ImageRendering::Auto,
|
||||
AlphaType::PremultipliedAlpha,
|
||||
blob_img,
|
||||
blob_img.as_image(),
|
||||
ColorF::WHITE,
|
||||
);
|
||||
|
||||
|
@ -514,7 +514,7 @@ impl<'a> RawtestHarness<'a> {
|
|||
size(0.0, 0.0),
|
||||
ImageRendering::Auto,
|
||||
AlphaType::PremultipliedAlpha,
|
||||
blob_img,
|
||||
blob_img.as_image(),
|
||||
ColorF::WHITE,
|
||||
);
|
||||
|
||||
|
@ -553,18 +553,18 @@ impl<'a> RawtestHarness<'a> {
|
|||
let (blob_img, blob_img2) = {
|
||||
let api = &self.wrench.api;
|
||||
|
||||
blob_img = api.generate_image_key();
|
||||
txn.add_image(
|
||||
blob_img = api.generate_blob_image_key();
|
||||
txn.add_blob_image(
|
||||
blob_img,
|
||||
ImageDescriptor::new(500, 500, ImageFormat::BGRA8, false, false),
|
||||
ImageData::new_blob_image(blob::serialize_blob(ColorU::new(50, 50, 150, 255))),
|
||||
blob::serialize_blob(ColorU::new(50, 50, 150, 255)),
|
||||
None,
|
||||
);
|
||||
blob_img2 = api.generate_image_key();
|
||||
txn.add_image(
|
||||
blob_img2 = api.generate_blob_image_key();
|
||||
txn.add_blob_image(
|
||||
blob_img2,
|
||||
ImageDescriptor::new(500, 500, ImageFormat::BGRA8, false, false),
|
||||
ImageData::new_blob_image(blob::serialize_blob(ColorU::new(80, 50, 150, 255))),
|
||||
blob::serialize_blob(ColorU::new(80, 50, 150, 255)),
|
||||
None,
|
||||
);
|
||||
(blob_img, blob_img2)
|
||||
|
@ -599,7 +599,7 @@ impl<'a> RawtestHarness<'a> {
|
|||
size(0.0, 0.0),
|
||||
ImageRendering::Auto,
|
||||
AlphaType::PremultipliedAlpha,
|
||||
blob_img,
|
||||
blob_img.as_image(),
|
||||
ColorF::WHITE,
|
||||
);
|
||||
builder.push_image(
|
||||
|
@ -608,7 +608,7 @@ impl<'a> RawtestHarness<'a> {
|
|||
size(0.0, 0.0),
|
||||
ImageRendering::Auto,
|
||||
AlphaType::PremultipliedAlpha,
|
||||
blob_img2,
|
||||
blob_img2.as_image(),
|
||||
ColorF::WHITE,
|
||||
);
|
||||
};
|
||||
|
@ -623,17 +623,17 @@ impl<'a> RawtestHarness<'a> {
|
|||
|
||||
// update and redraw both images
|
||||
let mut txn = Transaction::new();
|
||||
txn.update_image(
|
||||
txn.update_blob_image(
|
||||
blob_img,
|
||||
ImageDescriptor::new(500, 500, ImageFormat::BGRA8, false, false),
|
||||
ImageData::new_blob_image(blob::serialize_blob(ColorU::new(50, 50, 150, 255))),
|
||||
Some(rect(100, 100, 100, 100)),
|
||||
blob::serialize_blob(ColorU::new(50, 50, 150, 255)),
|
||||
&rect(100, 100, 100, 100).into(),
|
||||
);
|
||||
txn.update_image(
|
||||
txn.update_blob_image(
|
||||
blob_img2,
|
||||
ImageDescriptor::new(500, 500, ImageFormat::BGRA8, false, false),
|
||||
ImageData::new_blob_image(blob::serialize_blob(ColorU::new(59, 50, 150, 255))),
|
||||
Some(rect(100, 100, 100, 100)),
|
||||
blob::serialize_blob(ColorU::new(59, 50, 150, 255)),
|
||||
&rect(100, 100, 100, 100).into(),
|
||||
);
|
||||
|
||||
let mut builder = DisplayListBuilder::new(self.wrench.root_pipeline_id, layout_size);
|
||||
|
@ -644,11 +644,11 @@ impl<'a> RawtestHarness<'a> {
|
|||
|
||||
// only update the first image
|
||||
let mut txn = Transaction::new();
|
||||
txn.update_image(
|
||||
txn.update_blob_image(
|
||||
blob_img,
|
||||
ImageDescriptor::new(500, 500, ImageFormat::BGRA8, false, false),
|
||||
ImageData::new_blob_image(blob::serialize_blob(ColorU::new(50, 150, 150, 255))),
|
||||
Some(rect(200, 200, 100, 100)),
|
||||
blob::serialize_blob(ColorU::new(50, 150, 150, 255)),
|
||||
&rect(200, 200, 100, 100).into(),
|
||||
);
|
||||
|
||||
let mut builder = DisplayListBuilder::new(self.wrench.root_pipeline_id, layout_size);
|
||||
|
@ -679,11 +679,11 @@ impl<'a> RawtestHarness<'a> {
|
|||
let mut txn = Transaction::new();
|
||||
|
||||
let blob_img = {
|
||||
let img = self.wrench.api.generate_image_key();
|
||||
txn.add_image(
|
||||
let img = self.wrench.api.generate_blob_image_key();
|
||||
txn.add_blob_image(
|
||||
img,
|
||||
ImageDescriptor::new(500, 500, ImageFormat::BGRA8, false, false),
|
||||
ImageData::new_blob_image(blob::serialize_blob(ColorU::new(50, 50, 150, 255))),
|
||||
blob::serialize_blob(ColorU::new(50, 50, 150, 255)),
|
||||
None,
|
||||
);
|
||||
img
|
||||
|
@ -699,7 +699,7 @@ impl<'a> RawtestHarness<'a> {
|
|||
size(0.0, 0.0),
|
||||
ImageRendering::Auto,
|
||||
AlphaType::PremultipliedAlpha,
|
||||
blob_img,
|
||||
blob_img.as_image(),
|
||||
ColorF::WHITE,
|
||||
);
|
||||
|
||||
|
@ -710,11 +710,11 @@ impl<'a> RawtestHarness<'a> {
|
|||
|
||||
// draw the blob image a second time after updating it with the same color
|
||||
let mut txn = Transaction::new();
|
||||
txn.update_image(
|
||||
txn.update_blob_image(
|
||||
blob_img,
|
||||
ImageDescriptor::new(500, 500, ImageFormat::BGRA8, false, false),
|
||||
ImageData::new_blob_image(blob::serialize_blob(ColorU::new(50, 50, 150, 255))),
|
||||
Some(rect(100, 100, 100, 100)),
|
||||
blob::serialize_blob(ColorU::new(50, 50, 150, 255)),
|
||||
&rect(100, 100, 100, 100).into(),
|
||||
);
|
||||
|
||||
// make a new display list that refers to the first image
|
||||
|
@ -726,7 +726,7 @@ impl<'a> RawtestHarness<'a> {
|
|||
size(0.0, 0.0),
|
||||
ImageRendering::Auto,
|
||||
AlphaType::PremultipliedAlpha,
|
||||
blob_img,
|
||||
blob_img.as_image(),
|
||||
ColorF::WHITE,
|
||||
);
|
||||
|
||||
|
@ -735,11 +735,11 @@ impl<'a> RawtestHarness<'a> {
|
|||
|
||||
// draw the blob image a third time after updating it with a different color
|
||||
let mut txn = Transaction::new();
|
||||
txn.update_image(
|
||||
txn.update_blob_image(
|
||||
blob_img,
|
||||
ImageDescriptor::new(500, 500, ImageFormat::BGRA8, false, false),
|
||||
ImageData::new_blob_image(blob::serialize_blob(ColorU::new(50, 150, 150, 255))),
|
||||
Some(rect(200, 200, 100, 100)),
|
||||
blob::serialize_blob(ColorU::new(50, 150, 150, 255)),
|
||||
&rect(200, 200, 100, 100).into(),
|
||||
);
|
||||
|
||||
// make a new display list that refers to the first image
|
||||
|
@ -751,7 +751,7 @@ impl<'a> RawtestHarness<'a> {
|
|||
size(0.0, 0.0),
|
||||
ImageRendering::Auto,
|
||||
AlphaType::PremultipliedAlpha,
|
||||
blob_img,
|
||||
blob_img.as_image(),
|
||||
ColorF::WHITE,
|
||||
);
|
||||
|
||||
|
|
|
@ -93,7 +93,7 @@ impl RonFrameWriter {
|
|||
ResourceUpdate::AddImage(ref img) => {
|
||||
let bytes = match img.data {
|
||||
ImageData::Raw(ref v) => (**v).clone(),
|
||||
ImageData::External(_) | ImageData::Blob(_) => {
|
||||
ImageData::External(_) => {
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
@ -118,7 +118,6 @@ impl RonFrameWriter {
|
|||
data.path = None;
|
||||
data.bytes = Some((**bytes).clone());
|
||||
} else {
|
||||
// Other existing image types only make sense within the gecko integration.
|
||||
println!(
|
||||
"Wrench only supports updating buffer images ({}).",
|
||||
"ignoring update commands"
|
||||
|
@ -126,6 +125,10 @@ impl RonFrameWriter {
|
|||
}
|
||||
}
|
||||
}
|
||||
ResourceUpdate::AddBlobImage(..)
|
||||
| ResourceUpdate::UpdateBlobImage(..) => {
|
||||
println!("Blob images not supported (ignoring command).");
|
||||
}
|
||||
ResourceUpdate::DeleteImage(img) => {
|
||||
self.images.remove(&img);
|
||||
}
|
||||
|
@ -141,7 +144,7 @@ impl RonFrameWriter {
|
|||
ResourceUpdate::DeleteFont(_) => {}
|
||||
ResourceUpdate::AddFontInstance(_) => {}
|
||||
ResourceUpdate::DeleteFontInstance(_) => {}
|
||||
ResourceUpdate::SetImageVisibleArea(..) => {}
|
||||
ResourceUpdate::SetBlobImageVisibleArea(..) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -550,7 +550,7 @@ impl YamlFrameWriter {
|
|||
);
|
||||
let bytes = match img.data {
|
||||
ImageData::Raw(ref v) => (**v).clone(),
|
||||
ImageData::External(_) | ImageData::Blob(_) => {
|
||||
ImageData::External(_) => {
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
@ -586,6 +586,10 @@ impl YamlFrameWriter {
|
|||
}
|
||||
}
|
||||
}
|
||||
ResourceUpdate::AddBlobImage(..)
|
||||
| ResourceUpdate::UpdateBlobImage(..) => {
|
||||
println!("Blob images not supported (ignoring command).");
|
||||
}
|
||||
ResourceUpdate::DeleteImage(img) => {
|
||||
self.images.remove(&img);
|
||||
}
|
||||
|
@ -609,7 +613,7 @@ impl YamlFrameWriter {
|
|||
);
|
||||
}
|
||||
ResourceUpdate::DeleteFontInstance(_) => {}
|
||||
ResourceUpdate::SetImageVisibleArea(..) => {}
|
||||
ResourceUpdate::SetBlobImageVisibleArea(..) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче