1use api::{BlobImageRequest, ImageDescriptorFlags, ImageFormat, RasterizedBlobImage};
6use api::{DebugFlags, FontInstanceKey, FontKey, FontTemplate, GlyphIndex};
7use api::{ExternalImageData, ExternalImageType, ExternalImageId, BlobImageResult};
8use api::{DirtyRect, GlyphDimensions, IdNamespace, DEFAULT_TILE_SIZE};
9use api::{ColorF, ImageData, ImageDescriptor, ImageKey, ImageRendering, TileSize};
10use api::{BlobImageHandler, BlobImageKey, VoidPtrToSizeFn};
11use api::units::*;
12use euclid::size2;
13use crate::render_target::RenderTargetKind;
14use crate::render_task::{RenderTaskLocation, StaticRenderTaskSurface};
15use crate::{render_api::{ClearCache, AddFont, ResourceUpdate, MemoryReport}, util::WeakTable};
16use crate::prim_store::image::AdjustedImageSource;
17use crate::image_tiling::{compute_tile_size, compute_tile_range};
18#[cfg(feature = "capture")]
19use crate::capture::ExternalCaptureImage;
20#[cfg(feature = "replay")]
21use crate::capture::PlainExternalImage;
22#[cfg(any(feature = "replay", feature = "png", feature="capture"))]
23use crate::capture::CaptureConfig;
24use crate::composite::{NativeSurfaceId, NativeSurfaceOperation, NativeTileId, NativeSurfaceOperationDetails};
25use crate::device::TextureFilter;
26use crate::glyph_cache::{GlyphCache, CachedGlyphInfo};
27use crate::glyph_cache::GlyphCacheEntry;
28use glyph_rasterizer::{GLYPH_FLASHING, FontInstance, GlyphFormat, GlyphKey, GlyphRasterizer, GlyphRasterJob};
29use glyph_rasterizer::{SharedFontResources, BaseFontInstance};
30use crate::gpu_cache::{GpuCache, GpuCacheAddress, GpuCacheHandle};
31use crate::gpu_types::UvRectKind;
32use crate::internal_types::{
33 CacheTextureId, FastHashMap, FastHashSet, TextureSource, ResourceUpdateList,
34 FrameId, FrameStamp,
35};
36use crate::profiler::{self, TransactionProfile, bytes_to_mb};
37use crate::render_task_graph::{RenderTaskId, RenderTaskGraphBuilder};
38use crate::render_task_cache::{RenderTaskCache, RenderTaskCacheKey, RenderTaskParent};
39use crate::render_task_cache::{RenderTaskCacheEntry, RenderTaskCacheEntryHandle};
40use crate::renderer::GpuBufferBuilderF;
41use crate::surface::SurfaceBuilder;
42use euclid::point2;
43use smallvec::SmallVec;
44use std::collections::hash_map::Entry::{self, Occupied, Vacant};
45use std::collections::hash_map::{Iter, IterMut};
46use std::collections::VecDeque;
47use std::{cmp, mem};
48use std::fmt::Debug;
49use std::hash::Hash;
50use std::os::raw::c_void;
51#[cfg(any(feature = "capture", feature = "replay"))]
52use std::path::PathBuf;
53use std::sync::Arc;
54use std::sync::atomic::{AtomicUsize, Ordering};
55use std::u32;
56use crate::texture_cache::{TextureCache, TextureCacheHandle, Eviction, TargetShader};
57use crate::picture_textures::PictureTextures;
58use peek_poke::PeekPoke;
59
60static NEXT_NATIVE_SURFACE_ID: AtomicUsize = AtomicUsize::new(0);
62
63#[cfg_attr(feature = "capture", derive(Serialize))]
64#[cfg_attr(feature = "replay", derive(Deserialize))]
65pub struct GlyphFetchResult {
66 pub index_in_text_run: i32,
67 pub uv_rect_address: GpuCacheAddress,
68 pub offset: DevicePoint,
69 pub size: DeviceIntSize,
70 pub scale: f32,
71}
72
73#[derive(Debug, Clone)]
83#[cfg_attr(feature = "capture", derive(Serialize))]
84#[cfg_attr(feature = "replay", derive(Deserialize))]
85pub struct CacheItem {
86 pub texture_id: TextureSource,
87 pub uv_rect_handle: GpuCacheHandle,
88 pub uv_rect: DeviceIntRect,
89 pub user_data: [f32; 4],
90}
91
92impl CacheItem {
93 pub fn invalid() -> Self {
94 CacheItem {
95 texture_id: TextureSource::Invalid,
96 uv_rect_handle: GpuCacheHandle::new(),
97 uv_rect: DeviceIntRect::zero(),
98 user_data: [0.0; 4],
99 }
100 }
101
102 pub fn is_valid(&self) -> bool {
103 self.texture_id != TextureSource::Invalid
104 }
105}
106
107#[derive(Clone, Debug)]
110pub enum CachedImageData {
111 Raw(Arc<Vec<u8>>),
114 Blob,
119 Snapshot,
124 External(ExternalImageData),
127}
128
129impl From<ImageData> for CachedImageData {
130 fn from(img_data: ImageData) -> Self {
131 match img_data {
132 ImageData::Raw(data) => CachedImageData::Raw(data),
133 ImageData::External(data) => CachedImageData::External(data),
134 }
135 }
136}
137
138impl CachedImageData {
139 #[inline]
141 pub fn is_blob(&self) -> bool {
142 match *self {
143 CachedImageData::Blob => true,
144 _ => false,
145 }
146 }
147
148 #[inline]
149 pub fn is_snapshot(&self) -> bool {
150 match *self {
151 CachedImageData::Snapshot => true,
152 _ => false,
153 }
154 }
155
156 #[inline]
159 pub fn uses_texture_cache(&self) -> bool {
160 match *self {
161 CachedImageData::External(ref ext_data) => match ext_data.image_type {
162 ExternalImageType::TextureHandle(_) => false,
163 ExternalImageType::Buffer => true,
164 },
165 CachedImageData::Blob => true,
166 CachedImageData::Raw(_) => true,
167 CachedImageData::Snapshot => true,
168 }
169 }
170}
171
172#[derive(Debug)]
173#[cfg_attr(feature = "capture", derive(Serialize))]
174#[cfg_attr(feature = "replay", derive(Deserialize))]
175pub struct ImageProperties {
176 pub descriptor: ImageDescriptor,
177 pub external_image: Option<ExternalImageData>,
178 pub tiling: Option<TileSize>,
179 pub visible_rect: DeviceIntRect,
182 pub adjustment: AdjustedImageSource,
183}
184
185#[derive(Debug, Copy, Clone, PartialEq)]
186enum State {
187 Idle,
188 AddResources,
189 QueryResources,
190}
191
192type RasterizedBlob = FastHashMap<TileOffset, RasterizedBlobImage>;
194
195#[cfg_attr(feature = "capture", derive(Serialize))]
196#[cfg_attr(feature = "replay", derive(Deserialize))]
197#[derive(Debug, Copy, Clone, PartialEq, PeekPoke, Default)]
198pub struct ImageGeneration(pub u32);
199
200impl ImageGeneration {
201 pub const INVALID: ImageGeneration = ImageGeneration(u32::MAX);
202}
203
204struct ImageResource {
205 data: CachedImageData,
206 descriptor: ImageDescriptor,
207 tiling: Option<TileSize>,
208 visible_rect: DeviceIntRect,
211 adjustment: AdjustedImageSource,
212 generation: ImageGeneration,
213}
214
215#[derive(Default)]
216struct ImageTemplates {
217 images: FastHashMap<ImageKey, ImageResource>,
218}
219
220impl ImageTemplates {
221 fn insert(&mut self, key: ImageKey, resource: ImageResource) {
222 self.images.insert(key, resource);
223 }
224
225 fn remove(&mut self, key: ImageKey) -> Option<ImageResource> {
226 self.images.remove(&key)
227 }
228
229 fn get(&self, key: ImageKey) -> Option<&ImageResource> {
230 self.images.get(&key)
231 }
232
233 fn get_mut(&mut self, key: ImageKey) -> Option<&mut ImageResource> {
234 self.images.get_mut(&key)
235 }
236}
237
238#[cfg_attr(feature = "capture", derive(Serialize))]
239#[cfg_attr(feature = "replay", derive(Deserialize))]
240struct CachedImageInfo {
241 texture_cache_handle: TextureCacheHandle,
242 dirty_rect: ImageDirtyRect,
243 manual_eviction: bool,
244}
245
246impl CachedImageInfo {
247 fn mark_unused(&mut self, texture_cache: &mut TextureCache) {
248 texture_cache.evict_handle(&self.texture_cache_handle);
249 self.manual_eviction = false;
250 }
251}
252
253#[cfg(debug_assertions)]
254impl Drop for CachedImageInfo {
255 fn drop(&mut self) {
256 debug_assert!(!self.manual_eviction, "Manual eviction requires cleanup");
257 }
258}
259
260#[cfg_attr(feature = "capture", derive(Serialize))]
261#[cfg_attr(feature = "replay", derive(Deserialize))]
262pub struct ResourceClassCache<K: Hash + Eq, V, U: Default> {
263 resources: FastHashMap<K, V>,
264 pub user_data: U,
265}
266
267impl<K, V, U> ResourceClassCache<K, V, U>
268where
269 K: Clone + Hash + Eq + Debug,
270 U: Default,
271{
272 pub fn new() -> Self {
273 ResourceClassCache {
274 resources: FastHashMap::default(),
275 user_data: Default::default(),
276 }
277 }
278
279 pub fn get(&self, key: &K) -> &V {
280 self.resources.get(key)
281 .expect("Didn't find a cached resource with that ID!")
282 }
283
284 pub fn try_get(&self, key: &K) -> Option<&V> {
285 self.resources.get(key)
286 }
287
288 pub fn insert(&mut self, key: K, value: V) {
289 self.resources.insert(key, value);
290 }
291
292 pub fn remove(&mut self, key: &K) -> Option<V> {
293 self.resources.remove(key)
294 }
295
296 pub fn get_mut(&mut self, key: &K) -> &mut V {
297 self.resources.get_mut(key)
298 .expect("Didn't find a cached resource with that ID!")
299 }
300
301 pub fn try_get_mut(&mut self, key: &K) -> Option<&mut V> {
302 self.resources.get_mut(key)
303 }
304
305 pub fn entry(&mut self, key: K) -> Entry<K, V> {
306 self.resources.entry(key)
307 }
308
309 pub fn iter(&self) -> Iter<K, V> {
310 self.resources.iter()
311 }
312
313 pub fn iter_mut(&mut self) -> IterMut<K, V> {
314 self.resources.iter_mut()
315 }
316
317 pub fn is_empty(&mut self) -> bool {
318 self.resources.is_empty()
319 }
320
321 pub fn clear(&mut self) {
322 self.resources.clear();
323 }
324
325 pub fn retain<F>(&mut self, f: F)
326 where
327 F: FnMut(&K, &mut V) -> bool,
328 {
329 self.resources.retain(f);
330 }
331}
332
333#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
334#[cfg_attr(feature = "capture", derive(Serialize))]
335#[cfg_attr(feature = "replay", derive(Deserialize))]
336struct CachedImageKey {
337 pub rendering: ImageRendering,
338 pub tile: Option<TileOffset>,
339}
340
341#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
342#[cfg_attr(feature = "capture", derive(Serialize))]
343#[cfg_attr(feature = "replay", derive(Deserialize))]
344pub struct ImageRequest {
345 pub key: ImageKey,
346 pub rendering: ImageRendering,
347 pub tile: Option<TileOffset>,
348}
349
350impl ImageRequest {
351 pub fn with_tile(&self, offset: TileOffset) -> Self {
352 ImageRequest {
353 key: self.key,
354 rendering: self.rendering,
355 tile: Some(offset),
356 }
357 }
358
359 pub fn is_untiled_auto(&self) -> bool {
360 self.tile.is_none() && self.rendering == ImageRendering::Auto
361 }
362}
363
364impl Into<BlobImageRequest> for ImageRequest {
365 fn into(self) -> BlobImageRequest {
366 BlobImageRequest {
367 key: BlobImageKey(self.key),
368 tile: self.tile.unwrap(),
369 }
370 }
371}
372
373impl Into<CachedImageKey> for ImageRequest {
374 fn into(self) -> CachedImageKey {
375 CachedImageKey {
376 rendering: self.rendering,
377 tile: self.tile,
378 }
379 }
380}
381
382#[derive(Debug)]
383#[cfg_attr(feature = "capture", derive(Clone, Serialize))]
384#[cfg_attr(feature = "replay", derive(Deserialize))]
385pub enum ImageCacheError {
386 OverLimitSize,
387}
388
389#[cfg_attr(feature = "capture", derive(Serialize))]
390#[cfg_attr(feature = "replay", derive(Deserialize))]
391enum ImageResult {
392 UntiledAuto(CachedImageInfo),
393 Multi(ResourceClassCache<CachedImageKey, CachedImageInfo, ()>),
394 Err(ImageCacheError),
395}
396
397impl ImageResult {
398 fn drop_from_cache(&mut self, texture_cache: &mut TextureCache) {
400 match *self {
401 ImageResult::UntiledAuto(ref mut entry) => {
402 entry.mark_unused(texture_cache);
403 },
404 ImageResult::Multi(ref mut entries) => {
405 for entry in entries.resources.values_mut() {
406 entry.mark_unused(texture_cache);
407 }
408 },
409 ImageResult::Err(_) => {},
410 }
411 }
412}
413
414type ImageCache = ResourceClassCache<ImageKey, ImageResult, ()>;
415
416struct Resources {
417 fonts: SharedFontResources,
418 image_templates: ImageTemplates,
419 weak_fonts: WeakTable
423}
424
425pub type GlyphDimensionsCache = FastHashMap<(FontInstanceKey, GlyphIndex), Option<GlyphDimensions>>;
429
430struct RenderTarget {
432 size: DeviceIntSize,
433 format: ImageFormat,
434 texture_id: CacheTextureId,
435 is_active: bool,
437 last_frame_used: FrameId,
438}
439
440impl RenderTarget {
441 fn size_in_bytes(&self) -> usize {
442 let bpp = self.format.bytes_per_pixel() as usize;
443 (self.size.width * self.size.height) as usize * bpp
444 }
445
446 pub fn used_recently(&self, current_frame_id: FrameId, threshold: u64) -> bool {
449 self.last_frame_used + threshold >= current_frame_id
450 }
451}
452
453pub struct ResourceCache {
459 cached_glyphs: GlyphCache,
460 cached_images: ImageCache,
461 cached_render_tasks: RenderTaskCache,
462
463 resources: Resources,
464 state: State,
465 current_frame_id: FrameId,
466
467 #[cfg(feature = "capture")]
468 capture_dirty: bool,
472
473 pub texture_cache: TextureCache,
474 pub picture_textures: PictureTextures,
475
476 cached_glyph_dimensions: GlyphDimensionsCache,
478 glyph_rasterizer: GlyphRasterizer,
479
480 pending_image_requests: FastHashSet<ImageRequest>,
484
485 rasterized_blob_images: FastHashMap<BlobImageKey, RasterizedBlob>,
486
487 deleted_blob_keys: VecDeque<Vec<BlobImageKey>>,
490
491 blob_image_handler: Option<Box<dyn BlobImageHandler>>,
495
496 pending_native_surface_updates: Vec<NativeSurfaceOperation>,
498
499 image_templates_memory: usize,
500 font_templates_memory: usize,
501
502 render_target_pool: Vec<RenderTarget>,
504
505 fallback_handle: TextureCacheHandle,
519 debug_fallback_panic: bool,
520 debug_fallback_pink: bool,
521}
522
523impl ResourceCache {
524 pub fn new(
525 texture_cache: TextureCache,
526 picture_textures: PictureTextures,
527 glyph_rasterizer: GlyphRasterizer,
528 cached_glyphs: GlyphCache,
529 fonts: SharedFontResources,
530 blob_image_handler: Option<Box<dyn BlobImageHandler>>,
531 ) -> Self {
532 ResourceCache {
533 cached_glyphs,
534 cached_images: ResourceClassCache::new(),
535 cached_render_tasks: RenderTaskCache::new(),
536 resources: Resources {
537 fonts,
538 image_templates: ImageTemplates::default(),
539 weak_fonts: WeakTable::new(),
540 },
541 cached_glyph_dimensions: FastHashMap::default(),
542 texture_cache,
543 picture_textures,
544 state: State::Idle,
545 current_frame_id: FrameId::INVALID,
546 pending_image_requests: FastHashSet::default(),
547 glyph_rasterizer,
548 rasterized_blob_images: FastHashMap::default(),
549 deleted_blob_keys: vec![Vec::new(), Vec::new(), Vec::new()].into(),
551 blob_image_handler,
552 pending_native_surface_updates: Vec::new(),
553 #[cfg(feature = "capture")]
554 capture_dirty: true,
555 image_templates_memory: 0,
556 font_templates_memory: 0,
557 render_target_pool: Vec::new(),
558 fallback_handle: TextureCacheHandle::invalid(),
559 debug_fallback_panic: false,
560 debug_fallback_pink: false,
561 }
562 }
563
564 #[cfg(test)]
566 pub fn new_for_testing() -> Self {
567 use rayon::ThreadPoolBuilder;
568
569 let texture_cache = TextureCache::new_for_testing(
570 4096,
571 ImageFormat::RGBA8,
572 );
573 let workers = Arc::new(ThreadPoolBuilder::new().build().unwrap());
574 let glyph_rasterizer = GlyphRasterizer::new(workers, None, true);
575 let cached_glyphs = GlyphCache::new();
576 let fonts = SharedFontResources::new(IdNamespace(0));
577 let picture_textures = PictureTextures::new(
578 crate::picture::TILE_SIZE_DEFAULT,
579 TextureFilter::Nearest,
580 );
581
582 ResourceCache::new(
583 texture_cache,
584 picture_textures,
585 glyph_rasterizer,
586 cached_glyphs,
587 fonts,
588 None,
589 )
590 }
591
592 pub fn max_texture_size(&self) -> i32 {
593 self.texture_cache.max_texture_size()
594 }
595
596 pub fn tiling_threshold(&self) -> i32 {
599 self.texture_cache.tiling_threshold()
600 }
601
602 pub fn enable_multithreading(&mut self, enable: bool) {
603 self.glyph_rasterizer.enable_multithreading(enable);
604 }
605
606 fn should_tile(limit: i32, descriptor: &ImageDescriptor, data: &CachedImageData) -> bool {
607 let size_check = descriptor.size.width > limit || descriptor.size.height > limit;
608 match *data {
609 CachedImageData::Raw(_) | CachedImageData::Blob => size_check,
610 CachedImageData::External(info) => {
611 info.image_type == ExternalImageType::Buffer && size_check
614 }
615 CachedImageData::Snapshot => false,
616 }
617 }
618
619 pub fn request_render_task(
631 &mut self,
632 key: Option<RenderTaskCacheKey>,
633 is_opaque: bool,
634 parent: RenderTaskParent,
635 gpu_cache: &mut GpuCache,
636 gpu_buffer_builder: &mut GpuBufferBuilderF,
637 rg_builder: &mut RenderTaskGraphBuilder,
638 surface_builder: &mut SurfaceBuilder,
639 f: &mut dyn FnMut(&mut RenderTaskGraphBuilder, &mut GpuBufferBuilderF, &mut GpuCache) -> RenderTaskId,
640 ) -> RenderTaskId {
641 self.cached_render_tasks.request_render_task(
642 key.clone(),
643 &mut self.texture_cache,
644 is_opaque,
645 parent,
646 gpu_cache,
647 gpu_buffer_builder,
648 rg_builder,
649 surface_builder,
650 f
651 )
652 }
653
654 pub fn render_as_image(
655 &mut self,
656 image_key: ImageKey,
657 size: DeviceIntSize,
658 rg_builder: &mut RenderTaskGraphBuilder,
659 gpu_buffer_builder: &mut GpuBufferBuilderF,
660 gpu_cache: &mut GpuCache,
661 is_opaque: bool,
662 adjustment: &AdjustedImageSource,
663 f: &mut dyn FnMut(&mut RenderTaskGraphBuilder, &mut GpuBufferBuilderF, &mut GpuCache) -> RenderTaskId,
664 ) -> RenderTaskId {
665
666 let task_id = f(rg_builder, gpu_buffer_builder, gpu_cache);
667
668 let render_task = rg_builder.get_task_mut(task_id);
669
670 let image_result = self.cached_images.entry(image_key).or_insert_with(|| {
688 ImageResult::UntiledAuto(CachedImageInfo {
689 texture_cache_handle: TextureCacheHandle::invalid(),
690 dirty_rect: ImageDirtyRect::All,
691 manual_eviction: true,
692 })
693 });
694
695 let ImageResult::UntiledAuto(ref mut info) = *image_result else {
696 unreachable!("Expected untiled image with auto filter for snapshot");
697 };
698
699 let flags = if is_opaque {
700 ImageDescriptorFlags::IS_OPAQUE
701 } else {
702 ImageDescriptorFlags::empty()
703 };
704
705 let descriptor = ImageDescriptor::new(
706 size.width,
707 size.height,
708 self.texture_cache.shared_color_expected_format(),
709 flags,
710 );
711
712 let force_standalone_texture = true;
719
720 let user_data = [0.0; 4];
723 self.texture_cache.update(
724 &mut info.texture_cache_handle,
725 descriptor,
726 TextureFilter::Linear,
727 None,
728 user_data,
729 DirtyRect::All,
730 gpu_cache,
731 None,
732 render_task.uv_rect_kind(),
733 Eviction::Manual,
734 TargetShader::Default,
735 force_standalone_texture,
736 );
737
738 let (texture_id, uv_rect, _, _, _) =
742 self.texture_cache.get_cache_location(&info.texture_cache_handle);
743
744 render_task.location = RenderTaskLocation::Static {
745 surface: StaticRenderTaskSurface::TextureCache {
746 texture: texture_id,
747 target_kind: RenderTargetKind::Color,
748 },
749 rect: uv_rect.to_i32(),
750 };
751
752 self.resources.image_templates
753 .get_mut(image_key)
754 .unwrap()
755 .adjustment = *adjustment;
756
757 task_id
758 }
759
760 pub fn post_scene_building_update(
761 &mut self,
762 updates: Vec<ResourceUpdate>,
763 profile: &mut TransactionProfile,
764 ) {
765 #[cfg(feature = "capture")]
769 match updates.is_empty() {
770 false => self.capture_dirty = true,
771 _ => {},
772 }
773
774 for update in updates {
775 match update {
776 ResourceUpdate::AddImage(img) => {
777 if let ImageData::Raw(ref bytes) = img.data {
778 self.image_templates_memory += bytes.len();
779 profile.set(profiler::IMAGE_TEMPLATES_MEM, bytes_to_mb(self.image_templates_memory));
780 }
781 self.add_image_template(
782 img.key,
783 img.descriptor,
784 img.data.into(),
785 &img.descriptor.size.into(),
786 img.tiling,
787 );
788 profile.set(profiler::IMAGE_TEMPLATES, self.resources.image_templates.images.len());
789 }
790 ResourceUpdate::UpdateImage(img) => {
791 self.update_image_template(img.key, img.descriptor, img.data.into(), &img.dirty_rect);
792 }
793 ResourceUpdate::AddBlobImage(img) => {
794 self.add_image_template(
795 img.key.as_image(),
796 img.descriptor,
797 CachedImageData::Blob,
798 &img.visible_rect,
799 Some(img.tile_size),
800 );
801 }
802 ResourceUpdate::UpdateBlobImage(img) => {
803 self.update_image_template(
804 img.key.as_image(),
805 img.descriptor,
806 CachedImageData::Blob,
807 &to_image_dirty_rect(
808 &img.dirty_rect
809 ),
810 );
811 self.discard_tiles_outside_visible_area(img.key, &img.visible_rect); self.set_image_visible_rect(img.key.as_image(), &img.visible_rect);
813 }
814 ResourceUpdate::DeleteImage(img) => {
815 self.delete_image_template(img);
816 profile.set(profiler::IMAGE_TEMPLATES, self.resources.image_templates.images.len());
817 profile.set(profiler::IMAGE_TEMPLATES_MEM, bytes_to_mb(self.image_templates_memory));
818 }
819 ResourceUpdate::DeleteBlobImage(img) => {
820 self.delete_image_template(img.as_image());
821 }
822 ResourceUpdate::AddSnapshotImage(img) => {
823 let format = self.texture_cache.shared_color_expected_format();
824 self.add_image_template(
825 img.key.as_image(),
826 ImageDescriptor {
827 format,
828 size: DeviceIntSize::zero(),
830 stride: None,
831 offset: 0,
832 flags: ImageDescriptorFlags::empty(),
833 },
834 CachedImageData::Snapshot,
835 &DeviceIntRect::zero(),
836 None,
837 );
838 }
839 ResourceUpdate::DeleteSnapshotImage(img) => {
840 self.delete_image_template(img.as_image());
841 }
842 ResourceUpdate::DeleteFont(font) => {
843 if let Some(shared_key) = self.resources.fonts.font_keys.delete_key(&font) {
844 self.delete_font_template(shared_key);
845 if let Some(ref mut handler) = &mut self.blob_image_handler {
846 handler.delete_font(shared_key);
847 }
848 profile.set(profiler::FONT_TEMPLATES, self.resources.fonts.templates.len());
849 profile.set(profiler::FONT_TEMPLATES_MEM, bytes_to_mb(self.font_templates_memory));
850 }
851 }
852 ResourceUpdate::DeleteFontInstance(font) => {
853 if let Some(shared_key) = self.resources.fonts.instance_keys.delete_key(&font) {
854 self.delete_font_instance(shared_key);
855 }
856 if let Some(ref mut handler) = &mut self.blob_image_handler {
857 handler.delete_font_instance(font);
858 }
859 }
860 ResourceUpdate::SetBlobImageVisibleArea(key, area) => {
861 self.discard_tiles_outside_visible_area(key, &area);
862 self.set_image_visible_rect(key.as_image(), &area);
863 }
864 ResourceUpdate::AddFont(font) => {
865 let (key, template) = match font {
868 AddFont::Raw(key, bytes, index) => {
869 (key, FontTemplate::Raw(bytes, index))
870 }
871 AddFont::Native(key, native_font_handle) => {
872 (key, FontTemplate::Native(native_font_handle))
873 }
874 };
875 let shared_key = self.resources.fonts.font_keys.map_key(&key);
876 if !self.glyph_rasterizer.has_font(shared_key) {
877 self.add_font_template(shared_key, template);
878 profile.set(profiler::FONT_TEMPLATES, self.resources.fonts.templates.len());
879 profile.set(profiler::FONT_TEMPLATES_MEM, bytes_to_mb(self.font_templates_memory));
880 }
881 }
882 ResourceUpdate::AddFontInstance(..) => {
883 }
885 }
886 }
887 }
888
889 pub fn add_rasterized_blob_images(
890 &mut self,
891 images: Vec<(BlobImageRequest, BlobImageResult)>,
892 profile: &mut TransactionProfile,
893 ) {
894 for (request, result) in images {
895 let data = match result {
896 Ok(data) => data,
897 Err(..) => {
898 warn!("Failed to rasterize a blob image");
899 continue;
900 }
901 };
902
903 profile.add(profiler::RASTERIZED_BLOBS_PX, data.rasterized_rect.area());
904
905 let tiles = self.rasterized_blob_images.entry(request.key).or_insert_with(
908 || { RasterizedBlob::default() }
909 );
910
911 tiles.insert(request.tile, data);
912
913 match self.cached_images.try_get_mut(&request.key.as_image()) {
914 Some(&mut ImageResult::Multi(ref mut entries)) => {
915 let cached_key = CachedImageKey {
916 rendering: ImageRendering::Auto, tile: Some(request.tile),
918 };
919 if let Some(entry) = entries.try_get_mut(&cached_key) {
920 entry.dirty_rect = DirtyRect::All;
921 }
922 }
923 _ => {}
924 }
925 }
926 }
927
928 pub fn add_font_template(&mut self, font_key: FontKey, template: FontTemplate) {
929 if let FontTemplate::Raw(ref data, _) = template {
932 self.resources.weak_fonts.insert(Arc::downgrade(data));
933 self.font_templates_memory += data.len();
934 }
935 self.glyph_rasterizer.add_font(font_key, template.clone());
936 self.resources.fonts.templates.add_font(font_key, template);
937 }
938
939 pub fn delete_font_template(&mut self, font_key: FontKey) {
940 self.glyph_rasterizer.delete_font(font_key);
941 if let Some(FontTemplate::Raw(data, _)) = self.resources.fonts.templates.delete_font(&font_key) {
942 self.font_templates_memory -= data.len();
943 }
944 self.cached_glyphs.delete_fonts(&[font_key]);
945 }
946
947 pub fn delete_font_instance(&mut self, instance_key: FontInstanceKey) {
948 self.resources.fonts.instances.delete_font_instance(instance_key);
949 }
950
951 pub fn get_font_instance(&self, instance_key: FontInstanceKey) -> Option<Arc<BaseFontInstance>> {
952 self.resources.fonts.instances.get_font_instance(instance_key)
953 }
954
955 pub fn get_fonts(&self) -> SharedFontResources {
956 self.resources.fonts.clone()
957 }
958
959 pub fn add_image_template(
960 &mut self,
961 image_key: ImageKey,
962 descriptor: ImageDescriptor,
963 data: CachedImageData,
964 visible_rect: &DeviceIntRect,
965 mut tiling: Option<TileSize>,
966 ) {
967 if let Some(ref mut tile_size) = tiling {
968 *tile_size = (*tile_size).max(16).min(2048);
970 }
971
972 if tiling.is_none() && Self::should_tile(self.tiling_threshold(), &descriptor, &data) {
973 tiling = Some(DEFAULT_TILE_SIZE);
976 }
977
978 let resource = ImageResource {
979 descriptor,
980 data,
981 tiling,
982 visible_rect: *visible_rect,
983 adjustment: AdjustedImageSource::new(),
984 generation: ImageGeneration(0),
985 };
986
987 self.resources.image_templates.insert(image_key, resource);
988 }
989
990 pub fn update_image_template(
991 &mut self,
992 image_key: ImageKey,
993 descriptor: ImageDescriptor,
994 data: CachedImageData,
995 dirty_rect: &ImageDirtyRect,
996 ) {
997 let tiling_threshold = self.tiling_threshold();
998 let image = match self.resources.image_templates.get_mut(image_key) {
999 Some(res) => res,
1000 None => panic!("Attempt to update non-existent image"),
1001 };
1002
1003 let mut tiling = image.tiling;
1004 if tiling.is_none() && Self::should_tile(tiling_threshold, &descriptor, &data) {
1005 tiling = Some(DEFAULT_TILE_SIZE);
1006 }
1007
1008 match self.cached_images.try_get_mut(&image_key) {
1011 Some(&mut ImageResult::UntiledAuto(ref mut entry)) => {
1012 entry.dirty_rect = entry.dirty_rect.union(dirty_rect);
1013 }
1014 Some(&mut ImageResult::Multi(ref mut entries)) => {
1015 for (key, entry) in entries.iter_mut() {
1016 let local_dirty_rect = match (tiling, key.tile) {
1018 (Some(tile_size), Some(tile)) => {
1019 dirty_rect.map(|mut rect|{
1020 let tile_offset = DeviceIntPoint::new(
1021 tile.x as i32,
1022 tile.y as i32,
1023 ) * tile_size as i32;
1024 rect = rect.translate(-tile_offset.to_vector());
1025
1026 let tile_rect = compute_tile_size(
1027 &descriptor.size.into(),
1028 tile_size,
1029 tile,
1030 ).into();
1031
1032 rect.intersection(&tile_rect).unwrap_or_else(DeviceIntRect::zero)
1033 })
1034 }
1035 (None, Some(..)) => DirtyRect::All,
1036 _ => *dirty_rect,
1037 };
1038 entry.dirty_rect = entry.dirty_rect.union(&local_dirty_rect);
1039 }
1040 }
1041 _ => {}
1042 }
1043
1044 if image.descriptor.format != descriptor.format {
1045 trace!("Format change {:?} -> {:?}", image.descriptor.format, descriptor.format);
1047 }
1048 *image = ImageResource {
1049 descriptor,
1050 data,
1051 tiling,
1052 visible_rect: descriptor.size.into(),
1053 adjustment: AdjustedImageSource::new(),
1054 generation: ImageGeneration(image.generation.0 + 1),
1055 };
1056 }
1057
1058 pub fn increment_image_generation(&mut self, key: ImageKey) {
1059 if let Some(image) = self.resources.image_templates.get_mut(key) {
1060 image.generation.0 += 1;
1061 }
1062 }
1063
1064 pub fn delete_image_template(&mut self, image_key: ImageKey) {
1065 let value = self.resources.image_templates.remove(image_key);
1067
1068 if let Some(mut cached) = self.cached_images.remove(&image_key) {
1070 cached.drop_from_cache(&mut self.texture_cache);
1071 }
1072
1073 match value {
1074 Some(image) => if image.data.is_blob() {
1075 if let CachedImageData::Raw(data) = image.data {
1076 self.image_templates_memory -= data.len();
1077 }
1078
1079 let blob_key = BlobImageKey(image_key);
1080 self.deleted_blob_keys.back_mut().unwrap().push(blob_key);
1081 self.rasterized_blob_images.remove(&blob_key);
1082 },
1083 None => {
1084 warn!("Delete the non-exist key");
1085 debug!("key={:?}", image_key);
1086 }
1087 }
1088 }
1089
1090 pub fn get_image_generation(&self, key: ImageKey) -> ImageGeneration {
1092 self.resources
1093 .image_templates
1094 .get(key)
1095 .map_or(ImageGeneration::INVALID, |template| template.generation)
1096 }
1097
1098 pub fn request_image(
1102 &mut self,
1103 mut request: ImageRequest,
1104 gpu_cache: &mut GpuCache,
1105 ) -> DeviceIntSize {
1106 debug_assert_eq!(self.state, State::AddResources);
1107
1108 let template = match self.resources.image_templates.get(request.key) {
1109 Some(template) => template,
1110 None => {
1111 warn!("ERROR: Trying to render deleted / non-existent key");
1112 debug!("key={:?}", request.key);
1113 return DeviceIntSize::zero();
1114 }
1115 };
1116
1117 let size = match request.tile {
1118 Some(tile) => compute_tile_size(&template.visible_rect, template.tiling.unwrap(), tile),
1119 None => template.descriptor.size,
1120 };
1121
1122 if !template.data.uses_texture_cache() {
1124 return size;
1125 }
1126
1127 if template.data.is_snapshot() {
1128 request.rendering = ImageRendering::Auto;
1133 }
1134
1135 let side_size =
1136 template.tiling.map_or(cmp::max(template.descriptor.size.width, template.descriptor.size.height),
1137 |tile_size| tile_size as i32);
1138 if side_size > self.texture_cache.max_texture_size() {
1139 warn!("Dropping image, image:(w:{},h:{}, tile:{}) is too big for hardware!",
1141 template.descriptor.size.width, template.descriptor.size.height, template.tiling.unwrap_or(0));
1142 self.cached_images.insert(request.key, ImageResult::Err(ImageCacheError::OverLimitSize));
1143 return DeviceIntSize::zero();
1144 }
1145
1146 let storage = match self.cached_images.entry(request.key) {
1147 Occupied(e) => {
1148 let entry = e.into_mut();
1153 if !request.is_untiled_auto() {
1154 let untiled_entry = match entry {
1155 &mut ImageResult::UntiledAuto(ref mut entry) => {
1156 Some(mem::replace(entry, CachedImageInfo {
1157 texture_cache_handle: TextureCacheHandle::invalid(),
1158 dirty_rect: DirtyRect::All,
1159 manual_eviction: false,
1160 }))
1161 }
1162 _ => None
1163 };
1164
1165 if let Some(untiled_entry) = untiled_entry {
1166 let mut entries = ResourceClassCache::new();
1167 let untiled_key = CachedImageKey {
1168 rendering: ImageRendering::Auto,
1169 tile: None,
1170 };
1171 entries.insert(untiled_key, untiled_entry);
1172 *entry = ImageResult::Multi(entries);
1173 }
1174 }
1175 entry
1176 }
1177 Vacant(entry) => {
1178 entry.insert(if request.is_untiled_auto() {
1179 ImageResult::UntiledAuto(CachedImageInfo {
1180 texture_cache_handle: TextureCacheHandle::invalid(),
1181 dirty_rect: DirtyRect::All,
1182 manual_eviction: false,
1183 })
1184 } else {
1185 ImageResult::Multi(ResourceClassCache::new())
1186 })
1187 }
1188 };
1189
1190 let entry = match *storage {
1193 ImageResult::UntiledAuto(ref mut entry) => entry,
1194 ImageResult::Multi(ref mut entries) => {
1195 entries.entry(request.into())
1196 .or_insert(CachedImageInfo {
1197 texture_cache_handle: TextureCacheHandle::invalid(),
1198 dirty_rect: DirtyRect::All,
1199 manual_eviction: false,
1200 })
1201 },
1202 ImageResult::Err(_) => panic!("Errors should already have been handled"),
1203 };
1204
1205 let needs_upload = self.texture_cache.request(&entry.texture_cache_handle, gpu_cache);
1206
1207 if !needs_upload && entry.dirty_rect.is_empty() {
1208 return size;
1209 }
1210
1211 if !self.pending_image_requests.insert(request) {
1212 return size;
1213 }
1214
1215 if template.data.is_blob() {
1216 let request: BlobImageRequest = request.into();
1217 let missing = match self.rasterized_blob_images.get(&request.key) {
1218 Some(tiles) => !tiles.contains_key(&request.tile),
1219 _ => true,
1220 };
1221
1222 assert!(!missing);
1223 }
1224
1225 size
1226 }
1227
1228 fn discard_tiles_outside_visible_area(
1229 &mut self,
1230 key: BlobImageKey,
1231 area: &DeviceIntRect
1232 ) {
1233 let tile_size = match self.resources.image_templates.get(key.as_image()) {
1234 Some(template) => template.tiling.unwrap(),
1235 None => {
1236 return;
1238 }
1239 };
1240
1241 let tiles = match self.rasterized_blob_images.get_mut(&key) {
1242 Some(tiles) => tiles,
1243 _ => { return; }
1244 };
1245
1246 let tile_range = compute_tile_range(
1247 &area,
1248 tile_size,
1249 );
1250
1251 tiles.retain(|tile, _| { tile_range.contains(*tile) });
1252
1253 let texture_cache = &mut self.texture_cache;
1254 match self.cached_images.try_get_mut(&key.as_image()) {
1255 Some(&mut ImageResult::Multi(ref mut entries)) => {
1256 entries.retain(|key, entry| {
1257 if key.tile.is_none() || tile_range.contains(key.tile.unwrap()) {
1258 return true;
1259 }
1260 entry.mark_unused(texture_cache);
1261 return false;
1262 });
1263 }
1264 _ => {}
1265 }
1266 }
1267
1268 fn set_image_visible_rect(&mut self, key: ImageKey, rect: &DeviceIntRect) {
1269 if let Some(image) = self.resources.image_templates.get_mut(key) {
1270 image.visible_rect = *rect;
1271 image.descriptor.size = rect.size();
1272 }
1273 }
1274
1275 pub fn request_glyphs(
1276 &mut self,
1277 mut font: FontInstance,
1278 glyph_keys: &[GlyphKey],
1279 gpu_cache: &mut GpuCache,
1280 ) {
1281 debug_assert_eq!(self.state, State::AddResources);
1282
1283 self.glyph_rasterizer.prepare_font(&mut font);
1284 let glyph_key_cache = self.cached_glyphs.insert_glyph_key_cache_for_font(&font);
1285 let texture_cache = &mut self.texture_cache;
1286 self.glyph_rasterizer.request_glyphs(
1287 font,
1288 glyph_keys,
1289 |key| {
1290 if let Some(entry) = glyph_key_cache.try_get(key) {
1291 match entry {
1292 GlyphCacheEntry::Cached(ref glyph) => {
1293 if !texture_cache.request(&glyph.texture_cache_handle, gpu_cache) {
1295 return false;
1296 }
1297 }
1301 GlyphCacheEntry::Blank | GlyphCacheEntry::Pending => return false,
1303 }
1304 };
1305
1306 glyph_key_cache.add_glyph(*key, GlyphCacheEntry::Pending);
1307
1308 true
1309 }
1310 );
1311 }
1312
1313 pub fn pending_updates(&mut self) -> ResourceUpdateList {
1314 ResourceUpdateList {
1315 texture_updates: self.texture_cache.pending_updates(),
1316 native_surface_updates: mem::replace(&mut self.pending_native_surface_updates, Vec::new()),
1317 }
1318 }
1319
1320 pub fn fetch_glyphs<F>(
1321 &self,
1322 mut font: FontInstance,
1323 glyph_keys: &[GlyphKey],
1324 fetch_buffer: &mut Vec<GlyphFetchResult>,
1325 gpu_cache: &mut GpuCache,
1326 mut f: F,
1327 ) where
1328 F: FnMut(TextureSource, GlyphFormat, &[GlyphFetchResult]),
1329 {
1330 debug_assert_eq!(self.state, State::QueryResources);
1331
1332 self.glyph_rasterizer.prepare_font(&mut font);
1333 let glyph_key_cache = self.cached_glyphs.get_glyph_key_cache_for_font(&font);
1334
1335 let mut current_texture_id = TextureSource::Invalid;
1336 let mut current_glyph_format = GlyphFormat::Subpixel;
1337 debug_assert!(fetch_buffer.is_empty());
1338
1339 for (loop_index, key) in glyph_keys.iter().enumerate() {
1340 let (cache_item, glyph_format) = match *glyph_key_cache.get(key) {
1341 GlyphCacheEntry::Cached(ref glyph) => {
1342 (self.texture_cache.get(&glyph.texture_cache_handle), glyph.format)
1343 }
1344 GlyphCacheEntry::Blank | GlyphCacheEntry::Pending => continue,
1345 };
1346 if current_texture_id != cache_item.texture_id ||
1347 current_glyph_format != glyph_format {
1348 if !fetch_buffer.is_empty() {
1349 f(current_texture_id, current_glyph_format, fetch_buffer);
1350 fetch_buffer.clear();
1351 }
1352 current_texture_id = cache_item.texture_id;
1353 current_glyph_format = glyph_format;
1354 }
1355 fetch_buffer.push(GlyphFetchResult {
1356 index_in_text_run: loop_index as i32,
1357 uv_rect_address: gpu_cache.get_address(&cache_item.uv_rect_handle),
1358 offset: DevicePoint::new(cache_item.user_data[0], cache_item.user_data[1]),
1359 size: cache_item.uv_rect.size(),
1360 scale: cache_item.user_data[2],
1361 });
1362 }
1363
1364 if !fetch_buffer.is_empty() {
1365 f(current_texture_id, current_glyph_format, fetch_buffer);
1366 fetch_buffer.clear();
1367 }
1368 }
1369
1370 pub fn map_font_key(&self, key: FontKey) -> FontKey {
1371 self.resources.fonts.font_keys.map_key(&key)
1372 }
1373
1374 pub fn map_font_instance_key(&self, key: FontInstanceKey) -> FontInstanceKey {
1375 self.resources.fonts.instance_keys.map_key(&key)
1376 }
1377
1378 pub fn get_glyph_dimensions(
1379 &mut self,
1380 font: &FontInstance,
1381 glyph_index: GlyphIndex,
1382 ) -> Option<GlyphDimensions> {
1383 match self.cached_glyph_dimensions.entry((font.instance_key, glyph_index)) {
1384 Occupied(entry) => *entry.get(),
1385 Vacant(entry) => *entry.insert(
1386 self.glyph_rasterizer
1387 .get_glyph_dimensions(font, glyph_index),
1388 ),
1389 }
1390 }
1391
1392 pub fn get_glyph_index(&mut self, font_key: FontKey, ch: char) -> Option<u32> {
1393 self.glyph_rasterizer.get_glyph_index(font_key, ch)
1394 }
1395
1396 #[inline]
1397 pub fn get_cached_image(&self, request: ImageRequest) -> Result<CacheItem, ()> {
1398 debug_assert_eq!(self.state, State::QueryResources);
1399 let image_info = self.get_image_info(request)?;
1400
1401 if let Ok(item) = self.get_texture_cache_item(&image_info.texture_cache_handle) {
1402 return Ok(item);
1404 }
1405
1406 if self.resources.image_templates
1407 .get(request.key)
1408 .map_or(false, |img| img.data.is_snapshot()) {
1409 if self.debug_fallback_panic {
1410 panic!("Missing snapshot image");
1411 }
1412 return self.get_texture_cache_item(&self.fallback_handle);
1413 }
1414
1415 panic!("Requested image missing from the texture cache");
1416 }
1417
1418 pub fn get_cached_render_task(
1419 &self,
1420 handle: &RenderTaskCacheEntryHandle,
1421 ) -> &RenderTaskCacheEntry {
1422 self.cached_render_tasks.get_cache_entry(handle)
1423 }
1424
1425 #[inline]
1426 fn get_image_info(&self, request: ImageRequest) -> Result<&CachedImageInfo, ()> {
1427 match *self.cached_images.get(&request.key) {
1430 ImageResult::UntiledAuto(ref image_info) => Ok(image_info),
1431 ImageResult::Multi(ref entries) => Ok(entries.get(&request.into())),
1432 ImageResult::Err(_) => Err(()),
1433 }
1434 }
1435
1436 #[inline]
1437 pub fn get_texture_cache_item(&self, handle: &TextureCacheHandle) -> Result<CacheItem, ()> {
1438 if let Some(item) = self.texture_cache.try_get(handle) {
1439 return Ok(item);
1440 }
1441
1442 Err(())
1443 }
1444
1445 pub fn get_image_properties(&self, image_key: ImageKey) -> Option<ImageProperties> {
1446 let image_template = &self.resources.image_templates.get(image_key);
1447
1448 image_template.map(|image_template| {
1449 let external_image = match image_template.data {
1450 CachedImageData::External(ext_image) => match ext_image.image_type {
1451 ExternalImageType::TextureHandle(_) => Some(ext_image),
1452 ExternalImageType::Buffer => None,
1454 },
1455 CachedImageData::Raw(..)
1457 | CachedImageData::Blob
1458 | CachedImageData::Snapshot
1459 => None,
1460 };
1461
1462 ImageProperties {
1463 descriptor: image_template.descriptor,
1464 external_image,
1465 tiling: image_template.tiling,
1466 visible_rect: image_template.visible_rect,
1467 adjustment: image_template.adjustment,
1468 }
1469 })
1470 }
1471
1472 pub fn begin_frame(&mut self, stamp: FrameStamp, gpu_cache: &mut GpuCache, profile: &mut TransactionProfile) {
1473 profile_scope!("begin_frame");
1474 debug_assert_eq!(self.state, State::Idle);
1475 self.state = State::AddResources;
1476 self.texture_cache.begin_frame(stamp, profile);
1477 self.picture_textures.begin_frame(stamp, &mut self.texture_cache.pending_updates);
1478
1479 self.cached_glyphs.begin_frame(
1480 stamp,
1481 &mut self.texture_cache,
1482 &mut self.glyph_rasterizer,
1483 );
1484 self.cached_render_tasks.begin_frame(&mut self.texture_cache);
1485 self.current_frame_id = stamp.frame_id();
1486
1487 let mut v = self.deleted_blob_keys.pop_front().unwrap_or_else(Vec::new);
1490 v.clear();
1491 self.deleted_blob_keys.push_back(v);
1492
1493 self.texture_cache.run_compaction(gpu_cache);
1494 }
1495
1496 pub fn block_until_all_resources_added(
1497 &mut self,
1498 gpu_cache: &mut GpuCache,
1499 profile: &mut TransactionProfile,
1500 ) {
1501 profile_scope!("block_until_all_resources_added");
1502
1503 debug_assert_eq!(self.state, State::AddResources);
1504 self.state = State::QueryResources;
1505
1506 let cached_glyphs = &mut self.cached_glyphs;
1507 let texture_cache = &mut self.texture_cache;
1508
1509 self.glyph_rasterizer.resolve_glyphs(
1510 |job, can_use_r8_format| {
1511 let GlyphRasterJob { font, key, result } = job;
1512 let glyph_key_cache = cached_glyphs.get_glyph_key_cache_for_font_mut(&*font);
1513 let glyph_info = match result {
1514 Err(_) => GlyphCacheEntry::Blank,
1515 Ok(ref glyph) if glyph.width == 0 || glyph.height == 0 => {
1516 GlyphCacheEntry::Blank
1517 }
1518 Ok(glyph) => {
1519 let mut texture_cache_handle = TextureCacheHandle::invalid();
1520 texture_cache.request(&texture_cache_handle, gpu_cache);
1521 texture_cache.update(
1522 &mut texture_cache_handle,
1523 ImageDescriptor {
1524 size: size2(glyph.width, glyph.height),
1525 stride: None,
1526 format: glyph.format.image_format(can_use_r8_format),
1527 flags: ImageDescriptorFlags::empty(),
1528 offset: 0,
1529 },
1530 TextureFilter::Linear,
1531 Some(CachedImageData::Raw(Arc::new(glyph.bytes))),
1532 [glyph.left, -glyph.top, glyph.scale, 0.0],
1533 DirtyRect::All,
1534 gpu_cache,
1535 Some(glyph_key_cache.eviction_notice()),
1536 UvRectKind::Rect,
1537 Eviction::Auto,
1538 TargetShader::Text,
1539 false,
1540 );
1541 GlyphCacheEntry::Cached(CachedGlyphInfo {
1542 texture_cache_handle,
1543 format: glyph.format,
1544 })
1545 }
1546 };
1547 glyph_key_cache.insert(key, glyph_info);
1548 },
1549 profile,
1550 );
1551
1552 self.update_texture_cache(gpu_cache);
1554 }
1555
1556 fn update_texture_cache(&mut self, gpu_cache: &mut GpuCache) {
1557 profile_scope!("update_texture_cache");
1558
1559 if self.fallback_handle == TextureCacheHandle::invalid() {
1560 let fallback_color = if self.debug_fallback_pink {
1561 vec![255, 0, 255, 255]
1562 } else {
1563 vec![0, 0, 0, 0]
1564 };
1565 self.texture_cache.update(
1566 &mut self.fallback_handle,
1567 ImageDescriptor {
1568 size: size2(1, 1),
1569 stride: None,
1570 format: ImageFormat::BGRA8,
1571 flags: ImageDescriptorFlags::empty(),
1572 offset: 0,
1573 },
1574 TextureFilter::Linear,
1575 Some(CachedImageData::Raw(Arc::new(fallback_color))),
1576 [0.0; 4],
1577 DirtyRect::All,
1578 gpu_cache,
1579 None,
1580 UvRectKind::Rect,
1581 Eviction::Manual,
1582 TargetShader::Default,
1583 false,
1584 );
1585 }
1586
1587 for request in self.pending_image_requests.drain() {
1588 let image_template = self.resources.image_templates.get_mut(request.key).unwrap();
1589 debug_assert!(image_template.data.uses_texture_cache());
1590
1591 let mut updates: SmallVec<[(CachedImageData, Option<DeviceIntRect>); 1]> = SmallVec::new();
1592
1593 match image_template.data {
1594 CachedImageData::Snapshot => {
1595 }
1597 CachedImageData::Raw(..)
1598 | CachedImageData::External(..) => {
1599 updates.push((image_template.data.clone(), None));
1602 }
1603 CachedImageData::Blob => {
1604 let blob_image = self.rasterized_blob_images.get_mut(&BlobImageKey(request.key)).unwrap();
1605 let img = &blob_image[&request.tile.unwrap()];
1606 updates.push((
1607 CachedImageData::Raw(Arc::clone(&img.data)),
1608 Some(img.rasterized_rect)
1609 ));
1610 }
1611 };
1612
1613 for (image_data, blob_rasterized_rect) in updates {
1614 let entry = match *self.cached_images.get_mut(&request.key) {
1615 ImageResult::UntiledAuto(ref mut entry) => entry,
1616 ImageResult::Multi(ref mut entries) => entries.get_mut(&request.into()),
1617 ImageResult::Err(_) => panic!("Update requested for invalid entry")
1618 };
1619
1620 let mut descriptor = image_template.descriptor.clone();
1621 let mut dirty_rect = entry.dirty_rect.replace_with_empty();
1622
1623 if let Some(tile) = request.tile {
1624 let tile_size = image_template.tiling.unwrap();
1625 let clipped_tile_size = compute_tile_size(&image_template.visible_rect, tile_size, tile);
1626 let tiled_on_cpu = image_template.data.is_blob();
1630 if !tiled_on_cpu {
1631 debug_assert_eq!(image_template.visible_rect.min, point2(0, 0));
1634 let bpp = descriptor.format.bytes_per_pixel();
1635 let stride = descriptor.compute_stride();
1636 descriptor.stride = Some(stride);
1637 descriptor.offset +=
1638 tile.y as i32 * tile_size as i32 * stride +
1639 tile.x as i32 * tile_size as i32 * bpp;
1640 }
1641
1642 descriptor.size = clipped_tile_size;
1643 }
1644
1645 if let Some(rect) = blob_rasterized_rect {
1649 dirty_rect = DirtyRect::Partial(rect);
1650 }
1651
1652 let filter = match request.rendering {
1653 ImageRendering::Pixelated => {
1654 TextureFilter::Nearest
1655 }
1656 ImageRendering::Auto | ImageRendering::CrispEdges => {
1657 if descriptor.allow_mipmaps() &&
1665 descriptor.size.width > 512 &&
1666 descriptor.size.height > 512 &&
1667 !self.texture_cache.is_allowed_in_shared_cache(
1668 TextureFilter::Linear,
1669 &descriptor,
1670 ) {
1671 TextureFilter::Trilinear
1672 } else {
1673 TextureFilter::Linear
1674 }
1675 }
1676 };
1677
1678 let eviction = match &image_template.data {
1679 CachedImageData::Blob | CachedImageData::Snapshot => {
1680 entry.manual_eviction = true;
1681 Eviction::Manual
1682 }
1683 _ => {
1684 Eviction::Auto
1685 }
1686 };
1687
1688 self.texture_cache.update(
1690 &mut entry.texture_cache_handle,
1691 descriptor,
1692 filter,
1693 Some(image_data),
1694 [0.0; 4],
1695 dirty_rect,
1696 gpu_cache,
1697 None,
1698 UvRectKind::Rect,
1699 eviction,
1700 TargetShader::Default,
1701 false,
1702 );
1703 }
1704 }
1705 }
1706
1707 pub fn create_compositor_backdrop_surface(
1708 &mut self,
1709 color: ColorF
1710 ) -> NativeSurfaceId {
1711 let id = NativeSurfaceId(NEXT_NATIVE_SURFACE_ID.fetch_add(1, Ordering::Relaxed) as u64);
1712
1713 self.pending_native_surface_updates.push(
1714 NativeSurfaceOperation {
1715 details: NativeSurfaceOperationDetails::CreateBackdropSurface {
1716 id,
1717 color,
1718 },
1719 }
1720 );
1721
1722 id
1723 }
1724
1725 pub fn create_compositor_surface(
1728 &mut self,
1729 virtual_offset: DeviceIntPoint,
1730 tile_size: DeviceIntSize,
1731 is_opaque: bool,
1732 ) -> NativeSurfaceId {
1733 let id = NativeSurfaceId(NEXT_NATIVE_SURFACE_ID.fetch_add(1, Ordering::Relaxed) as u64);
1734
1735 self.pending_native_surface_updates.push(
1736 NativeSurfaceOperation {
1737 details: NativeSurfaceOperationDetails::CreateSurface {
1738 id,
1739 virtual_offset,
1740 tile_size,
1741 is_opaque,
1742 },
1743 }
1744 );
1745
1746 id
1747 }
1748
1749 pub fn create_compositor_external_surface(
1750 &mut self,
1751 is_opaque: bool,
1752 ) -> NativeSurfaceId {
1753 let id = NativeSurfaceId(NEXT_NATIVE_SURFACE_ID.fetch_add(1, Ordering::Relaxed) as u64);
1754
1755 self.pending_native_surface_updates.push(
1756 NativeSurfaceOperation {
1757 details: NativeSurfaceOperationDetails::CreateExternalSurface {
1758 id,
1759 is_opaque,
1760 },
1761 }
1762 );
1763
1764 id
1765 }
1766
1767 pub fn destroy_compositor_surface(
1770 &mut self,
1771 id: NativeSurfaceId,
1772 ) {
1773 self.pending_native_surface_updates.push(
1774 NativeSurfaceOperation {
1775 details: NativeSurfaceOperationDetails::DestroySurface {
1776 id,
1777 }
1778 }
1779 );
1780 }
1781
1782 pub fn create_compositor_tile(
1784 &mut self,
1785 id: NativeTileId,
1786 ) {
1787 self.pending_native_surface_updates.push(
1788 NativeSurfaceOperation {
1789 details: NativeSurfaceOperationDetails::CreateTile {
1790 id,
1791 },
1792 }
1793 );
1794 }
1795
1796 pub fn destroy_compositor_tile(
1798 &mut self,
1799 id: NativeTileId,
1800 ) {
1801 self.pending_native_surface_updates.push(
1802 NativeSurfaceOperation {
1803 details: NativeSurfaceOperationDetails::DestroyTile {
1804 id,
1805 },
1806 }
1807 );
1808 }
1809
1810 pub fn attach_compositor_external_image(
1811 &mut self,
1812 id: NativeSurfaceId,
1813 external_image: ExternalImageId,
1814 ) {
1815 self.pending_native_surface_updates.push(
1816 NativeSurfaceOperation {
1817 details: NativeSurfaceOperationDetails::AttachExternalImage {
1818 id,
1819 external_image,
1820 },
1821 }
1822 );
1823 }
1824
1825
1826 pub fn end_frame(&mut self, profile: &mut TransactionProfile) {
1827 debug_assert_eq!(self.state, State::QueryResources);
1828 profile_scope!("end_frame");
1829 self.state = State::Idle;
1830
1831 self.gc_render_targets(
1844 64 * 1024 * 1024,
1845 32 * 1024 * 1024 * 10,
1846 60,
1847 );
1848
1849 self.texture_cache.end_frame(profile);
1850 self.picture_textures.gc(
1851 &mut self.texture_cache.pending_updates,
1852 );
1853
1854 self.picture_textures.update_profile(profile);
1855 }
1856
1857 pub fn set_debug_flags(&mut self, flags: DebugFlags) {
1858 GLYPH_FLASHING.store(flags.contains(DebugFlags::GLYPH_FLASHING), std::sync::atomic::Ordering::Relaxed);
1859 self.texture_cache.set_debug_flags(flags);
1860 self.picture_textures.set_debug_flags(flags);
1861 self.debug_fallback_panic = flags.contains(DebugFlags::MISSING_SNAPSHOT_PANIC);
1862 let fallback_pink = flags.contains(DebugFlags::MISSING_SNAPSHOT_PINK);
1863
1864 if fallback_pink != self.debug_fallback_pink && self.fallback_handle != TextureCacheHandle::invalid() {
1865 self.texture_cache.evict_handle(&self.fallback_handle);
1866 }
1867 self.debug_fallback_pink = fallback_pink;
1868 }
1869
1870 pub fn clear(&mut self, what: ClearCache) {
1871 if what.contains(ClearCache::IMAGES) {
1872 for (_key, mut cached) in self.cached_images.resources.drain() {
1873 cached.drop_from_cache(&mut self.texture_cache);
1874 }
1875 }
1876 if what.contains(ClearCache::GLYPHS) {
1877 self.cached_glyphs.clear();
1878 }
1879 if what.contains(ClearCache::GLYPH_DIMENSIONS) {
1880 self.cached_glyph_dimensions.clear();
1881 }
1882 if what.contains(ClearCache::RENDER_TASKS) {
1883 self.cached_render_tasks.clear();
1884 }
1885 if what.contains(ClearCache::TEXTURE_CACHE) {
1886 self.texture_cache.clear_all();
1887 self.picture_textures.clear(&mut self.texture_cache.pending_updates);
1888 }
1889 if what.contains(ClearCache::RENDER_TARGETS) {
1890 self.clear_render_target_pool();
1891 }
1892 }
1893
1894 pub fn clear_namespace(&mut self, namespace: IdNamespace) {
1895 self.clear_images(|k| k.0 == namespace);
1896
1897 self.resources.fonts.instances.clear_namespace(namespace);
1899 let deleted_keys = self.resources.fonts.templates.clear_namespace(namespace);
1900 self.glyph_rasterizer.delete_fonts(&deleted_keys);
1901 self.cached_glyphs.clear_namespace(namespace);
1902 if let Some(handler) = &mut self.blob_image_handler {
1903 handler.clear_namespace(namespace);
1904 }
1905
1906 let shared_instance_keys = self.resources.fonts.instance_keys.clear_namespace(namespace);
1908 if !shared_instance_keys.is_empty() {
1909 self.resources.fonts.instances.delete_font_instances(&shared_instance_keys);
1910 self.cached_glyphs.delete_font_instances(&shared_instance_keys, &mut self.glyph_rasterizer);
1911 }
1914
1915 let shared_keys = self.resources.fonts.font_keys.clear_namespace(namespace);
1917 if !shared_keys.is_empty() {
1918 self.glyph_rasterizer.delete_fonts(&shared_keys);
1919 self.resources.fonts.templates.delete_fonts(&shared_keys);
1920 self.cached_glyphs.delete_fonts(&shared_keys);
1921 if let Some(handler) = &mut self.blob_image_handler {
1922 for &key in &shared_keys {
1923 handler.delete_font(key);
1924 }
1925 }
1926 }
1927 }
1928
1929 pub fn report_memory(&self, op: VoidPtrToSizeFn) -> MemoryReport {
1938 let mut report = MemoryReport::default();
1939
1940 let mut seen_fonts = std::collections::HashSet::new();
1941 for (_, font) in self.resources.fonts.templates.lock().iter() {
1944 if let FontTemplate::Raw(ref raw, _) = font {
1945 report.fonts += unsafe { op(raw.as_ptr() as *const c_void) };
1946 seen_fonts.insert(raw.as_ptr());
1947 }
1948 }
1949
1950 for font in self.resources.weak_fonts.iter() {
1951 if !seen_fonts.contains(&font.as_ptr()) {
1952 report.weak_fonts += unsafe { op(font.as_ptr() as *const c_void) };
1953 }
1954 }
1955
1956 for (_, image) in self.resources.image_templates.images.iter() {
1958 report.images += match image.data {
1959 CachedImageData::Raw(ref v) => unsafe { op(v.as_ptr() as *const c_void) },
1960 CachedImageData::Blob
1961 | CachedImageData::External(..)
1962 | CachedImageData::Snapshot => 0,
1963 }
1964 }
1965
1966 report
1982 }
1983
1984 fn clear_images<F: Fn(&ImageKey) -> bool>(&mut self, f: F) {
1986 let keys = self.resources.image_templates.images.keys().filter(|k| f(*k))
1987 .cloned().collect::<SmallVec<[ImageKey; 16]>>();
1988
1989 for key in keys {
1990 self.delete_image_template(key);
1991 }
1992
1993 #[cfg(feature="leak_checks")]
1994 let check_leaks = true;
1995 #[cfg(not(feature="leak_checks"))]
1996 let check_leaks = false;
1997
1998 if check_leaks {
1999 let blob_f = |key: &BlobImageKey| { f(&key.as_image()) };
2000 assert!(!self.resources.image_templates.images.keys().any(&f));
2001 assert!(!self.cached_images.resources.keys().any(&f));
2002 assert!(!self.rasterized_blob_images.keys().any(&blob_f));
2003 }
2004 }
2005
2006 pub fn get_or_create_render_target_from_pool(
2009 &mut self,
2010 size: DeviceIntSize,
2011 format: ImageFormat,
2012 ) -> CacheTextureId {
2013 for target in &mut self.render_target_pool {
2014 if target.size == size &&
2015 target.format == format &&
2016 !target.is_active {
2017 target.is_active = true;
2020 target.last_frame_used = self.current_frame_id;
2021 return target.texture_id;
2022 }
2023 }
2024
2025 let texture_id = self.texture_cache.alloc_render_target(
2028 size,
2029 format,
2030 );
2031
2032 self.render_target_pool.push(RenderTarget {
2033 size,
2034 format,
2035 texture_id,
2036 is_active: true,
2037 last_frame_used: self.current_frame_id,
2038 });
2039
2040 texture_id
2041 }
2042
2043 pub fn return_render_target_to_pool(
2045 &mut self,
2046 id: CacheTextureId,
2047 ) {
2048 let target = self.render_target_pool
2049 .iter_mut()
2050 .find(|t| t.texture_id == id)
2051 .expect("bug: invalid render target id");
2052
2053 assert!(target.is_active);
2054 target.is_active = false;
2055 }
2056
2057 fn clear_render_target_pool(
2059 &mut self,
2060 ) {
2061 for target in self.render_target_pool.drain(..) {
2062 debug_assert!(!target.is_active);
2063 self.texture_cache.free_render_target(target.texture_id);
2064 }
2065 }
2066
2067 fn gc_render_targets(
2070 &mut self,
2071 total_bytes_threshold: usize,
2072 total_bytes_red_line_threshold: usize,
2073 frames_threshold: u64,
2074 ) {
2075 let mut rt_pool_size_in_bytes: usize = self.render_target_pool
2077 .iter()
2078 .map(|t| t.size_in_bytes())
2079 .sum();
2080
2081 if rt_pool_size_in_bytes <= total_bytes_threshold {
2084 return;
2085 }
2086
2087 self.render_target_pool.sort_by_key(|t| t.last_frame_used);
2089
2090 let mut retained_targets = SmallVec::<[RenderTarget; 8]>::new();
2092
2093 for target in self.render_target_pool.drain(..) {
2094 assert!(!target.is_active);
2095
2096 let above_red_line = rt_pool_size_in_bytes > total_bytes_red_line_threshold;
2101 let above_threshold = rt_pool_size_in_bytes > total_bytes_threshold;
2102 let used_recently = target.used_recently(self.current_frame_id, frames_threshold);
2103 let used_this_frame = target.last_frame_used == self.current_frame_id;
2104
2105 if !used_this_frame && (above_red_line || (above_threshold && !used_recently)) {
2106 rt_pool_size_in_bytes -= target.size_in_bytes();
2107 self.texture_cache.free_render_target(target.texture_id);
2108 } else {
2109 retained_targets.push(target);
2110 }
2111 }
2112
2113 self.render_target_pool.extend(retained_targets);
2114 }
2115
2116 #[cfg(test)]
2117 pub fn validate_surfaces(
2118 &self,
2119 expected_surfaces: &[(i32, i32, ImageFormat)],
2120 ) {
2121 assert_eq!(expected_surfaces.len(), self.render_target_pool.len());
2122
2123 for (expected, surface) in expected_surfaces.iter().zip(self.render_target_pool.iter()) {
2124 assert_eq!(DeviceIntSize::new(expected.0, expected.1), surface.size);
2125 assert_eq!(expected.2, surface.format);
2126 }
2127 }
2128}
2129
2130impl Drop for ResourceCache {
2131 fn drop(&mut self) {
2132 self.clear_images(|_| true);
2133 }
2134}
2135
2136#[cfg(any(feature = "capture", feature = "replay"))]
2137#[cfg_attr(feature = "capture", derive(Serialize))]
2138#[cfg_attr(feature = "replay", derive(Deserialize))]
2139struct PlainFontTemplate {
2140 data: String,
2141 index: u32,
2142}
2143
2144#[cfg(any(feature = "capture", feature = "replay"))]
2145#[cfg_attr(feature = "capture", derive(Serialize))]
2146#[cfg_attr(feature = "replay", derive(Deserialize))]
2147struct PlainImageTemplate {
2148 data: String,
2149 descriptor: ImageDescriptor,
2150 tiling: Option<TileSize>,
2151 generation: ImageGeneration,
2152}
2153
2154#[cfg(any(feature = "capture", feature = "replay"))]
2155#[cfg_attr(feature = "capture", derive(Serialize))]
2156#[cfg_attr(feature = "replay", derive(Deserialize))]
2157pub struct PlainResources {
2158 font_templates: FastHashMap<FontKey, PlainFontTemplate>,
2159 font_instances: Vec<BaseFontInstance>,
2160 image_templates: FastHashMap<ImageKey, PlainImageTemplate>,
2161}
2162
2163#[cfg(feature = "capture")]
2164#[derive(Serialize)]
2165pub struct PlainCacheRef<'a> {
2166 current_frame_id: FrameId,
2167 glyphs: &'a GlyphCache,
2168 glyph_dimensions: &'a GlyphDimensionsCache,
2169 images: &'a ImageCache,
2170 render_tasks: &'a RenderTaskCache,
2171 textures: &'a TextureCache,
2172 picture_textures: &'a PictureTextures,
2173}
2174
2175#[cfg(feature = "replay")]
2176#[derive(Deserialize)]
2177pub struct PlainCacheOwn {
2178 current_frame_id: FrameId,
2179 glyphs: GlyphCache,
2180 glyph_dimensions: GlyphDimensionsCache,
2181 images: ImageCache,
2182 render_tasks: RenderTaskCache,
2183 textures: TextureCache,
2184 picture_textures: PictureTextures,
2185}
2186
2187#[cfg(feature = "replay")]
2188const NATIVE_FONT: &'static [u8] = include_bytes!("../res/Proggy.ttf");
2189
2190fn to_image_dirty_rect(blob_dirty_rect: &BlobDirtyRect) -> ImageDirtyRect {
2192 match *blob_dirty_rect {
2193 DirtyRect::Partial(rect) => DirtyRect::Partial(rect.cast_unit()),
2194 DirtyRect::All => DirtyRect::All,
2195 }
2196}
2197
2198impl ResourceCache {
2199 #[cfg(feature = "capture")]
2200 pub fn save_capture(
2201 &mut self, root: &PathBuf
2202 ) -> (PlainResources, Vec<ExternalCaptureImage>) {
2203 use std::fs;
2204 use std::io::Write;
2205
2206 info!("saving resource cache");
2207 let res = &self.resources;
2208 let path_fonts = root.join("fonts");
2209 if !path_fonts.is_dir() {
2210 fs::create_dir(&path_fonts).unwrap();
2211 }
2212 let path_images = root.join("images");
2213 if !path_images.is_dir() {
2214 fs::create_dir(&path_images).unwrap();
2215 }
2216 let path_blobs = root.join("blobs");
2217 if !path_blobs.is_dir() {
2218 fs::create_dir(&path_blobs).unwrap();
2219 }
2220 let path_externals = root.join("externals");
2221 if !path_externals.is_dir() {
2222 fs::create_dir(&path_externals).unwrap();
2223 }
2224
2225 info!("\tfont templates");
2226 let mut font_paths = FastHashMap::default();
2227 for template in res.fonts.templates.lock().values() {
2228 let data: &[u8] = match *template {
2229 FontTemplate::Raw(ref arc, _) => arc,
2230 FontTemplate::Native(_) => continue,
2231 };
2232 let font_id = res.fonts.templates.len() + 1;
2233 let entry = match font_paths.entry(data.as_ptr()) {
2234 Entry::Occupied(_) => continue,
2235 Entry::Vacant(e) => e,
2236 };
2237 let file_name = format!("{}.raw", font_id);
2238 let short_path = format!("fonts/{}", file_name);
2239 fs::File::create(path_fonts.join(file_name))
2240 .expect(&format!("Unable to create {}", short_path))
2241 .write_all(data)
2242 .unwrap();
2243 entry.insert(short_path);
2244 }
2245
2246 info!("\timage templates");
2247 let mut image_paths = FastHashMap::default();
2248 let mut other_paths = FastHashMap::default();
2249 let mut num_blobs = 0;
2250 let mut external_images = Vec::new();
2251 for (&key, template) in res.image_templates.images.iter() {
2252 let desc = &template.descriptor;
2253 match template.data {
2254 CachedImageData::Raw(ref arc) => {
2255 let image_id = image_paths.len() + 1;
2256 let entry = match image_paths.entry(arc.as_ptr()) {
2257 Entry::Occupied(_) => continue,
2258 Entry::Vacant(e) => e,
2259 };
2260
2261 #[cfg(feature = "png")]
2262 CaptureConfig::save_png(
2263 root.join(format!("images/{}.png", image_id)),
2264 desc.size,
2265 desc.format,
2266 desc.stride,
2267 &arc,
2268 );
2269 let file_name = format!("{}.raw", image_id);
2270 let short_path = format!("images/{}", file_name);
2271 fs::File::create(path_images.join(file_name))
2272 .expect(&format!("Unable to create {}", short_path))
2273 .write_all(&*arc)
2274 .unwrap();
2275 entry.insert(short_path);
2276 }
2277 CachedImageData::Blob => {
2278 warn!("Tiled blob images aren't supported yet");
2279 let result = RasterizedBlobImage {
2280 rasterized_rect: desc.size.into(),
2281 data: Arc::new(vec![0; desc.compute_total_size() as usize])
2282 };
2283
2284 assert_eq!(result.rasterized_rect.size(), desc.size);
2285 assert_eq!(result.data.len(), desc.compute_total_size() as usize);
2286
2287 num_blobs += 1;
2288 #[cfg(feature = "png")]
2289 CaptureConfig::save_png(
2290 root.join(format!("blobs/{}.png", num_blobs)),
2291 desc.size,
2292 desc.format,
2293 desc.stride,
2294 &result.data,
2295 );
2296 let file_name = format!("{}.raw", num_blobs);
2297 let short_path = format!("blobs/{}", file_name);
2298 let full_path = path_blobs.clone().join(&file_name);
2299 fs::File::create(full_path)
2300 .expect(&format!("Unable to create {}", short_path))
2301 .write_all(&result.data)
2302 .unwrap();
2303 other_paths.insert(key, short_path);
2304 }
2305 CachedImageData::Snapshot => {
2306 let short_path = format!("snapshots/{}", external_images.len() + 1);
2307 other_paths.insert(key, short_path.clone());
2308 }
2309 CachedImageData::External(ref ext) => {
2310 let short_path = format!("externals/{}", external_images.len() + 1);
2311 other_paths.insert(key, short_path.clone());
2312 external_images.push(ExternalCaptureImage {
2313 short_path,
2314 descriptor: desc.clone(),
2315 external: ext.clone(),
2316 });
2317 }
2318 }
2319 }
2320
2321 let mut font_templates = FastHashMap::default();
2322 let mut font_remap = FastHashMap::default();
2323 for key in res.fonts.font_keys.keys() {
2325 let shared_key = res.fonts.font_keys.map_key(&key);
2326 let template = match res.fonts.templates.get_font(&shared_key) {
2327 Some(template) => template,
2328 None => {
2329 debug!("Failed serializing font template {:?}", key);
2330 continue;
2331 }
2332 };
2333 let plain_font = match template {
2334 FontTemplate::Raw(arc, index) => {
2335 PlainFontTemplate {
2336 data: font_paths[&arc.as_ptr()].clone(),
2337 index,
2338 }
2339 }
2340 #[cfg(not(any(target_os = "macos", target_os = "ios")))]
2341 FontTemplate::Native(native) => {
2342 PlainFontTemplate {
2343 data: native.path.to_string_lossy().to_string(),
2344 index: native.index,
2345 }
2346 }
2347 #[cfg(any(target_os = "macos", target_os = "ios"))]
2348 FontTemplate::Native(native) => {
2349 PlainFontTemplate {
2350 data: native.name,
2351 index: 0,
2352 }
2353 }
2354 };
2355 font_templates.insert(key, plain_font);
2356 font_remap.insert(shared_key, key);
2358 }
2359 let mut font_instances = Vec::new();
2360 for instance_key in res.fonts.instance_keys.keys() {
2362 let shared_key = res.fonts.instance_keys.map_key(&instance_key);
2363 let instance = match res.fonts.instances.get_font_instance(shared_key) {
2364 Some(instance) => instance,
2365 None => {
2366 debug!("Failed serializing font instance {:?}", instance_key);
2367 continue;
2368 }
2369 };
2370 font_instances.push(BaseFontInstance {
2373 font_key: font_remap.get(&instance.font_key).cloned().unwrap_or(instance.font_key),
2374 instance_key,
2375 ..(*instance).clone()
2376 });
2377 }
2378 let resources = PlainResources {
2379 font_templates,
2380 font_instances,
2381 image_templates: res.image_templates.images
2382 .iter()
2383 .map(|(key, template)| {
2384 (*key, PlainImageTemplate {
2385 data: match template.data {
2386 CachedImageData::Raw(ref arc) => image_paths[&arc.as_ptr()].clone(),
2387 _ => other_paths[key].clone(),
2388 },
2389 descriptor: template.descriptor.clone(),
2390 tiling: template.tiling,
2391 generation: template.generation,
2392 })
2393 })
2394 .collect(),
2395 };
2396
2397 (resources, external_images)
2398 }
2399
2400 #[cfg(feature = "capture")]
2401 pub fn save_caches(&self, _root: &PathBuf) -> PlainCacheRef {
2402 PlainCacheRef {
2403 current_frame_id: self.current_frame_id,
2404 glyphs: &self.cached_glyphs,
2405 glyph_dimensions: &self.cached_glyph_dimensions,
2406 images: &self.cached_images,
2407 render_tasks: &self.cached_render_tasks,
2408 textures: &self.texture_cache,
2409 picture_textures: &self.picture_textures,
2410 }
2411 }
2412
2413 #[cfg(feature = "replay")]
2414 pub fn load_capture(
2415 &mut self,
2416 resources: PlainResources,
2417 caches: Option<PlainCacheOwn>,
2418 config: &CaptureConfig,
2419 ) -> Vec<PlainExternalImage> {
2420 use std::{fs, path::Path};
2421 use crate::texture_cache::TextureCacheConfig;
2422
2423 info!("loading resource cache");
2424 let mut raw_map = FastHashMap::<String, Arc<Vec<u8>>>::default();
2428
2429 self.clear(ClearCache::all());
2430 self.clear_images(|_| true);
2431
2432 match caches {
2433 Some(cached) => {
2434 self.current_frame_id = cached.current_frame_id;
2435 self.cached_glyphs = cached.glyphs;
2436 self.cached_glyph_dimensions = cached.glyph_dimensions;
2437 self.cached_images = cached.images;
2438 self.cached_render_tasks = cached.render_tasks;
2439 self.texture_cache = cached.textures;
2440 self.picture_textures = cached.picture_textures;
2441 }
2442 None => {
2443 self.current_frame_id = FrameId::INVALID;
2444 self.texture_cache = TextureCache::new(
2445 self.texture_cache.max_texture_size(),
2446 self.texture_cache.tiling_threshold(),
2447 self.texture_cache.color_formats(),
2448 self.texture_cache.swizzle_settings(),
2449 &TextureCacheConfig::DEFAULT,
2450 );
2451 self.picture_textures = PictureTextures::new(
2452 self.picture_textures.default_tile_size(),
2453 self.picture_textures.filter(),
2454 );
2455 }
2456 }
2457
2458 self.glyph_rasterizer.reset();
2459 let res = &mut self.resources;
2460 res.fonts.templates.clear();
2461 res.fonts.instances.clear();
2462 res.image_templates.images.clear();
2463
2464 info!("\tfont templates...");
2465 let root = config.resource_root();
2466 let native_font_replacement = Arc::new(NATIVE_FONT.to_vec());
2467 for (key, plain_template) in resources.font_templates {
2468 let arc = match raw_map.entry(plain_template.data) {
2469 Entry::Occupied(e) => {
2470 e.get().clone()
2471 }
2472 Entry::Vacant(e) => {
2473 let file_path = if Path::new(e.key()).is_absolute() {
2474 PathBuf::from(e.key())
2475 } else {
2476 root.join(e.key())
2477 };
2478 let arc = match fs::read(file_path) {
2479 Ok(buffer) => Arc::new(buffer),
2480 Err(err) => {
2481 error!("Unable to open font template {:?}: {:?}", e.key(), err);
2482 Arc::clone(&native_font_replacement)
2483 }
2484 };
2485 e.insert(arc).clone()
2486 }
2487 };
2488
2489 let template = FontTemplate::Raw(arc, plain_template.index);
2490 if let Some(shared_key) = res.fonts.font_keys.add_key(&key, &template) {
2492 self.glyph_rasterizer.add_font(shared_key, template.clone());
2493 res.fonts.templates.add_font(shared_key, template);
2494 }
2495 }
2496
2497 info!("\tfont instances...");
2498 for instance in resources.font_instances {
2499 let base = BaseFontInstance {
2501 font_key: res.fonts.font_keys.map_key(&instance.font_key),
2502 ..instance
2503 };
2504 if let Some(shared_instance) = res.fonts.instance_keys.add_key(base) {
2505 res.fonts.instances.add_font_instance(shared_instance);
2506 }
2507 }
2508
2509 info!("\timage templates...");
2510 let mut external_images = Vec::new();
2511 for (key, template) in resources.image_templates {
2512 let data = if template.data.starts_with("snapshots/") {
2513 CachedImageData::Snapshot
2516 } else {
2517 match config.deserialize_for_resource::<PlainExternalImage, _>(&template.data) {
2518 Some(plain) => {
2519 let ext_data = plain.external;
2520 external_images.push(plain);
2521 CachedImageData::External(ext_data)
2522 }
2523 None => {
2524 let arc = match raw_map.entry(template.data) {
2525 Entry::Occupied(e) => e.get().clone(),
2526 Entry::Vacant(e) => {
2527 match fs::read(root.join(e.key())) {
2528 Ok(buffer) => {
2529 e.insert(Arc::new(buffer)).clone()
2530 }
2531 Err(err) => {
2532 log::warn!("Unable to open {}: {err:?}", e.key());
2533 continue;
2534 }
2535 }
2536 }
2537 };
2538 CachedImageData::Raw(arc)
2539 }
2540 }
2541 };
2542
2543 res.image_templates.images.insert(key, ImageResource {
2544 data,
2545 descriptor: template.descriptor,
2546 tiling: template.tiling,
2547 visible_rect: template.descriptor.size.into(),
2548 adjustment: AdjustedImageSource::new(), generation: template.generation,
2550 });
2551 }
2552
2553 external_images
2554 }
2555
2556 #[cfg(feature = "capture")]
2557 pub fn save_capture_sequence(&mut self, config: &mut CaptureConfig) -> Vec<ExternalCaptureImage> {
2558 if self.capture_dirty {
2559 self.capture_dirty = false;
2560 config.prepare_resource();
2561 let (resources, deferred) = self.save_capture(&config.resource_root());
2562 config.serialize_for_resource(&resources, "plain-resources.ron");
2563 deferred
2564 } else {
2565 Vec::new()
2566 }
2567 }
2568}