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(|| {
673 ImageResult::UntiledAuto(CachedImageInfo {
674 texture_cache_handle: TextureCacheHandle::invalid(),
675 dirty_rect: ImageDirtyRect::All,
676 manual_eviction: true,
677 })
678 });
679
680 let ImageResult::UntiledAuto(ref mut info) = *image_result else {
681 unreachable!("Expected untiled image for snapshot");
682 };
683
684 let flags = if is_opaque {
685 ImageDescriptorFlags::IS_OPAQUE
686 } else {
687 ImageDescriptorFlags::empty()
688 };
689
690 let descriptor = ImageDescriptor::new(
691 size.width,
692 size.height,
693 self.texture_cache.shared_color_expected_format(),
694 flags,
695 );
696
697 let user_data = [0.0; 4];
700 self.texture_cache.update(
701 &mut info.texture_cache_handle,
702 descriptor,
703 TextureFilter::Linear,
704 None,
705 user_data,
706 DirtyRect::All,
707 gpu_cache,
708 None,
709 render_task.uv_rect_kind(),
710 Eviction::Manual,
711 TargetShader::Default,
712 );
713
714 let (texture_id, uv_rect, _, _, _) =
718 self.texture_cache.get_cache_location(&info.texture_cache_handle);
719
720 render_task.location = RenderTaskLocation::Static {
721 surface: StaticRenderTaskSurface::TextureCache {
722 texture: texture_id,
723 target_kind: RenderTargetKind::Color,
724 },
725 rect: uv_rect.to_i32(),
726 };
727
728 self.resources.image_templates
729 .get_mut(image_key)
730 .unwrap()
731 .adjustment = *adjustment;
732
733 task_id
734 }
735
736 pub fn post_scene_building_update(
737 &mut self,
738 updates: Vec<ResourceUpdate>,
739 profile: &mut TransactionProfile,
740 ) {
741 #[cfg(feature = "capture")]
745 match updates.is_empty() {
746 false => self.capture_dirty = true,
747 _ => {},
748 }
749
750 for update in updates {
751 match update {
752 ResourceUpdate::AddImage(img) => {
753 if let ImageData::Raw(ref bytes) = img.data {
754 self.image_templates_memory += bytes.len();
755 profile.set(profiler::IMAGE_TEMPLATES_MEM, bytes_to_mb(self.image_templates_memory));
756 }
757 self.add_image_template(
758 img.key,
759 img.descriptor,
760 img.data.into(),
761 &img.descriptor.size.into(),
762 img.tiling,
763 );
764 profile.set(profiler::IMAGE_TEMPLATES, self.resources.image_templates.images.len());
765 }
766 ResourceUpdate::UpdateImage(img) => {
767 self.update_image_template(img.key, img.descriptor, img.data.into(), &img.dirty_rect);
768 }
769 ResourceUpdate::AddBlobImage(img) => {
770 self.add_image_template(
771 img.key.as_image(),
772 img.descriptor,
773 CachedImageData::Blob,
774 &img.visible_rect,
775 Some(img.tile_size),
776 );
777 }
778 ResourceUpdate::UpdateBlobImage(img) => {
779 self.update_image_template(
780 img.key.as_image(),
781 img.descriptor,
782 CachedImageData::Blob,
783 &to_image_dirty_rect(
784 &img.dirty_rect
785 ),
786 );
787 self.discard_tiles_outside_visible_area(img.key, &img.visible_rect); self.set_image_visible_rect(img.key.as_image(), &img.visible_rect);
789 }
790 ResourceUpdate::DeleteImage(img) => {
791 self.delete_image_template(img);
792 profile.set(profiler::IMAGE_TEMPLATES, self.resources.image_templates.images.len());
793 profile.set(profiler::IMAGE_TEMPLATES_MEM, bytes_to_mb(self.image_templates_memory));
794 }
795 ResourceUpdate::DeleteBlobImage(img) => {
796 self.delete_image_template(img.as_image());
797 }
798 ResourceUpdate::AddSnapshotImage(img) => {
799 let format = self.texture_cache.shared_color_expected_format();
800 self.add_image_template(
801 img.key.as_image(),
802 ImageDescriptor {
803 format,
804 size: DeviceIntSize::zero(),
806 stride: None,
807 offset: 0,
808 flags: ImageDescriptorFlags::empty(),
809 },
810 CachedImageData::Snapshot,
811 &DeviceIntRect::zero(),
812 None,
813 );
814 }
815 ResourceUpdate::DeleteSnapshotImage(img) => {
816 self.delete_image_template(img.as_image());
817 }
818 ResourceUpdate::DeleteFont(font) => {
819 if let Some(shared_key) = self.resources.fonts.font_keys.delete_key(&font) {
820 self.delete_font_template(shared_key);
821 if let Some(ref mut handler) = &mut self.blob_image_handler {
822 handler.delete_font(shared_key);
823 }
824 profile.set(profiler::FONT_TEMPLATES, self.resources.fonts.templates.len());
825 profile.set(profiler::FONT_TEMPLATES_MEM, bytes_to_mb(self.font_templates_memory));
826 }
827 }
828 ResourceUpdate::DeleteFontInstance(font) => {
829 if let Some(shared_key) = self.resources.fonts.instance_keys.delete_key(&font) {
830 self.delete_font_instance(shared_key);
831 }
832 if let Some(ref mut handler) = &mut self.blob_image_handler {
833 handler.delete_font_instance(font);
834 }
835 }
836 ResourceUpdate::SetBlobImageVisibleArea(key, area) => {
837 self.discard_tiles_outside_visible_area(key, &area);
838 self.set_image_visible_rect(key.as_image(), &area);
839 }
840 ResourceUpdate::AddFont(font) => {
841 let (key, template) = match font {
844 AddFont::Raw(key, bytes, index) => {
845 (key, FontTemplate::Raw(bytes, index))
846 }
847 AddFont::Native(key, native_font_handle) => {
848 (key, FontTemplate::Native(native_font_handle))
849 }
850 };
851 let shared_key = self.resources.fonts.font_keys.map_key(&key);
852 if !self.glyph_rasterizer.has_font(shared_key) {
853 self.add_font_template(shared_key, template);
854 profile.set(profiler::FONT_TEMPLATES, self.resources.fonts.templates.len());
855 profile.set(profiler::FONT_TEMPLATES_MEM, bytes_to_mb(self.font_templates_memory));
856 }
857 }
858 ResourceUpdate::AddFontInstance(..) => {
859 }
861 }
862 }
863 }
864
865 pub fn add_rasterized_blob_images(
866 &mut self,
867 images: Vec<(BlobImageRequest, BlobImageResult)>,
868 profile: &mut TransactionProfile,
869 ) {
870 for (request, result) in images {
871 let data = match result {
872 Ok(data) => data,
873 Err(..) => {
874 warn!("Failed to rasterize a blob image");
875 continue;
876 }
877 };
878
879 profile.add(profiler::RASTERIZED_BLOBS_PX, data.rasterized_rect.area());
880
881 let tiles = self.rasterized_blob_images.entry(request.key).or_insert_with(
884 || { RasterizedBlob::default() }
885 );
886
887 tiles.insert(request.tile, data);
888
889 match self.cached_images.try_get_mut(&request.key.as_image()) {
890 Some(&mut ImageResult::Multi(ref mut entries)) => {
891 let cached_key = CachedImageKey {
892 rendering: ImageRendering::Auto, tile: Some(request.tile),
894 };
895 if let Some(entry) = entries.try_get_mut(&cached_key) {
896 entry.dirty_rect = DirtyRect::All;
897 }
898 }
899 _ => {}
900 }
901 }
902 }
903
904 pub fn add_font_template(&mut self, font_key: FontKey, template: FontTemplate) {
905 if let FontTemplate::Raw(ref data, _) = template {
908 self.resources.weak_fonts.insert(Arc::downgrade(data));
909 self.font_templates_memory += data.len();
910 }
911 self.glyph_rasterizer.add_font(font_key, template.clone());
912 self.resources.fonts.templates.add_font(font_key, template);
913 }
914
915 pub fn delete_font_template(&mut self, font_key: FontKey) {
916 self.glyph_rasterizer.delete_font(font_key);
917 if let Some(FontTemplate::Raw(data, _)) = self.resources.fonts.templates.delete_font(&font_key) {
918 self.font_templates_memory -= data.len();
919 }
920 self.cached_glyphs.delete_fonts(&[font_key]);
921 }
922
923 pub fn delete_font_instance(&mut self, instance_key: FontInstanceKey) {
924 self.resources.fonts.instances.delete_font_instance(instance_key);
925 }
926
927 pub fn get_font_instance(&self, instance_key: FontInstanceKey) -> Option<Arc<BaseFontInstance>> {
928 self.resources.fonts.instances.get_font_instance(instance_key)
929 }
930
931 pub fn get_fonts(&self) -> SharedFontResources {
932 self.resources.fonts.clone()
933 }
934
935 pub fn add_image_template(
936 &mut self,
937 image_key: ImageKey,
938 descriptor: ImageDescriptor,
939 data: CachedImageData,
940 visible_rect: &DeviceIntRect,
941 mut tiling: Option<TileSize>,
942 ) {
943 if let Some(ref mut tile_size) = tiling {
944 *tile_size = (*tile_size).max(16).min(2048);
946 }
947
948 if tiling.is_none() && Self::should_tile(self.tiling_threshold(), &descriptor, &data) {
949 tiling = Some(DEFAULT_TILE_SIZE);
952 }
953
954 let resource = ImageResource {
955 descriptor,
956 data,
957 tiling,
958 visible_rect: *visible_rect,
959 adjustment: AdjustedImageSource::new(),
960 generation: ImageGeneration(0),
961 };
962
963 self.resources.image_templates.insert(image_key, resource);
964 }
965
966 pub fn update_image_template(
967 &mut self,
968 image_key: ImageKey,
969 descriptor: ImageDescriptor,
970 data: CachedImageData,
971 dirty_rect: &ImageDirtyRect,
972 ) {
973 let tiling_threshold = self.tiling_threshold();
974 let image = match self.resources.image_templates.get_mut(image_key) {
975 Some(res) => res,
976 None => panic!("Attempt to update non-existent image"),
977 };
978
979 let mut tiling = image.tiling;
980 if tiling.is_none() && Self::should_tile(tiling_threshold, &descriptor, &data) {
981 tiling = Some(DEFAULT_TILE_SIZE);
982 }
983
984 match self.cached_images.try_get_mut(&image_key) {
987 Some(&mut ImageResult::UntiledAuto(ref mut entry)) => {
988 entry.dirty_rect = entry.dirty_rect.union(dirty_rect);
989 }
990 Some(&mut ImageResult::Multi(ref mut entries)) => {
991 for (key, entry) in entries.iter_mut() {
992 let local_dirty_rect = match (tiling, key.tile) {
994 (Some(tile_size), Some(tile)) => {
995 dirty_rect.map(|mut rect|{
996 let tile_offset = DeviceIntPoint::new(
997 tile.x as i32,
998 tile.y as i32,
999 ) * tile_size as i32;
1000 rect = rect.translate(-tile_offset.to_vector());
1001
1002 let tile_rect = compute_tile_size(
1003 &descriptor.size.into(),
1004 tile_size,
1005 tile,
1006 ).into();
1007
1008 rect.intersection(&tile_rect).unwrap_or_else(DeviceIntRect::zero)
1009 })
1010 }
1011 (None, Some(..)) => DirtyRect::All,
1012 _ => *dirty_rect,
1013 };
1014 entry.dirty_rect = entry.dirty_rect.union(&local_dirty_rect);
1015 }
1016 }
1017 _ => {}
1018 }
1019
1020 if image.descriptor.format != descriptor.format {
1021 trace!("Format change {:?} -> {:?}", image.descriptor.format, descriptor.format);
1023 }
1024 *image = ImageResource {
1025 descriptor,
1026 data,
1027 tiling,
1028 visible_rect: descriptor.size.into(),
1029 adjustment: AdjustedImageSource::new(),
1030 generation: ImageGeneration(image.generation.0 + 1),
1031 };
1032 }
1033
1034 pub fn increment_image_generation(&mut self, key: ImageKey) {
1035 if let Some(image) = self.resources.image_templates.get_mut(key) {
1036 image.generation.0 += 1;
1037 }
1038 }
1039
1040 pub fn delete_image_template(&mut self, image_key: ImageKey) {
1041 let value = self.resources.image_templates.remove(image_key);
1043
1044 if let Some(mut cached) = self.cached_images.remove(&image_key) {
1046 cached.drop_from_cache(&mut self.texture_cache);
1047 }
1048
1049 match value {
1050 Some(image) => if image.data.is_blob() {
1051 if let CachedImageData::Raw(data) = image.data {
1052 self.image_templates_memory -= data.len();
1053 }
1054
1055 let blob_key = BlobImageKey(image_key);
1056 self.deleted_blob_keys.back_mut().unwrap().push(blob_key);
1057 self.rasterized_blob_images.remove(&blob_key);
1058 },
1059 None => {
1060 warn!("Delete the non-exist key");
1061 debug!("key={:?}", image_key);
1062 }
1063 }
1064 }
1065
1066 pub fn get_image_generation(&self, key: ImageKey) -> ImageGeneration {
1068 self.resources
1069 .image_templates
1070 .get(key)
1071 .map_or(ImageGeneration::INVALID, |template| template.generation)
1072 }
1073
1074 pub fn request_image(
1078 &mut self,
1079 request: ImageRequest,
1080 gpu_cache: &mut GpuCache,
1081 ) -> DeviceIntSize {
1082 debug_assert_eq!(self.state, State::AddResources);
1083
1084 let template = match self.resources.image_templates.get(request.key) {
1085 Some(template) => template,
1086 None => {
1087 warn!("ERROR: Trying to render deleted / non-existent key");
1088 debug!("key={:?}", request.key);
1089 return DeviceIntSize::zero();
1090 }
1091 };
1092
1093 let size = match request.tile {
1094 Some(tile) => compute_tile_size(&template.visible_rect, template.tiling.unwrap(), tile),
1095 None => template.descriptor.size,
1096 };
1097
1098 if !template.data.uses_texture_cache() {
1100 return size;
1101 }
1102
1103 let side_size =
1104 template.tiling.map_or(cmp::max(template.descriptor.size.width, template.descriptor.size.height),
1105 |tile_size| tile_size as i32);
1106 if side_size > self.texture_cache.max_texture_size() {
1107 warn!("Dropping image, image:(w:{},h:{}, tile:{}) is too big for hardware!",
1109 template.descriptor.size.width, template.descriptor.size.height, template.tiling.unwrap_or(0));
1110 self.cached_images.insert(request.key, ImageResult::Err(ImageCacheError::OverLimitSize));
1111 return DeviceIntSize::zero();
1112 }
1113
1114 let storage = match self.cached_images.entry(request.key) {
1115 Occupied(e) => {
1116 let entry = e.into_mut();
1121 if !request.is_untiled_auto() {
1122 let untiled_entry = match entry {
1123 &mut ImageResult::UntiledAuto(ref mut entry) => {
1124 Some(mem::replace(entry, CachedImageInfo {
1125 texture_cache_handle: TextureCacheHandle::invalid(),
1126 dirty_rect: DirtyRect::All,
1127 manual_eviction: false,
1128 }))
1129 }
1130 _ => None
1131 };
1132
1133 if let Some(untiled_entry) = untiled_entry {
1134 let mut entries = ResourceClassCache::new();
1135 let untiled_key = CachedImageKey {
1136 rendering: ImageRendering::Auto,
1137 tile: None,
1138 };
1139 entries.insert(untiled_key, untiled_entry);
1140 *entry = ImageResult::Multi(entries);
1141 }
1142 }
1143 entry
1144 }
1145 Vacant(entry) => {
1146 entry.insert(if request.is_untiled_auto() {
1147 ImageResult::UntiledAuto(CachedImageInfo {
1148 texture_cache_handle: TextureCacheHandle::invalid(),
1149 dirty_rect: DirtyRect::All,
1150 manual_eviction: false,
1151 })
1152 } else {
1153 ImageResult::Multi(ResourceClassCache::new())
1154 })
1155 }
1156 };
1157
1158 let entry = match *storage {
1161 ImageResult::UntiledAuto(ref mut entry) => entry,
1162 ImageResult::Multi(ref mut entries) => {
1163 entries.entry(request.into())
1164 .or_insert(CachedImageInfo {
1165 texture_cache_handle: TextureCacheHandle::invalid(),
1166 dirty_rect: DirtyRect::All,
1167 manual_eviction: false,
1168 })
1169 },
1170 ImageResult::Err(_) => panic!("Errors should already have been handled"),
1171 };
1172
1173 let needs_upload = self.texture_cache.request(&entry.texture_cache_handle, gpu_cache);
1174
1175 if !needs_upload && entry.dirty_rect.is_empty() {
1176 return size;
1177 }
1178
1179 if !self.pending_image_requests.insert(request) {
1180 return size;
1181 }
1182
1183 if template.data.is_blob() {
1184 let request: BlobImageRequest = request.into();
1185 let missing = match self.rasterized_blob_images.get(&request.key) {
1186 Some(tiles) => !tiles.contains_key(&request.tile),
1187 _ => true,
1188 };
1189
1190 assert!(!missing);
1191 }
1192
1193 size
1194 }
1195
1196 fn discard_tiles_outside_visible_area(
1197 &mut self,
1198 key: BlobImageKey,
1199 area: &DeviceIntRect
1200 ) {
1201 let tile_size = match self.resources.image_templates.get(key.as_image()) {
1202 Some(template) => template.tiling.unwrap(),
1203 None => {
1204 return;
1206 }
1207 };
1208
1209 let tiles = match self.rasterized_blob_images.get_mut(&key) {
1210 Some(tiles) => tiles,
1211 _ => { return; }
1212 };
1213
1214 let tile_range = compute_tile_range(
1215 &area,
1216 tile_size,
1217 );
1218
1219 tiles.retain(|tile, _| { tile_range.contains(*tile) });
1220
1221 let texture_cache = &mut self.texture_cache;
1222 match self.cached_images.try_get_mut(&key.as_image()) {
1223 Some(&mut ImageResult::Multi(ref mut entries)) => {
1224 entries.retain(|key, entry| {
1225 if key.tile.is_none() || tile_range.contains(key.tile.unwrap()) {
1226 return true;
1227 }
1228 entry.mark_unused(texture_cache);
1229 return false;
1230 });
1231 }
1232 _ => {}
1233 }
1234 }
1235
1236 fn set_image_visible_rect(&mut self, key: ImageKey, rect: &DeviceIntRect) {
1237 if let Some(image) = self.resources.image_templates.get_mut(key) {
1238 image.visible_rect = *rect;
1239 image.descriptor.size = rect.size();
1240 }
1241 }
1242
1243 pub fn request_glyphs(
1244 &mut self,
1245 mut font: FontInstance,
1246 glyph_keys: &[GlyphKey],
1247 gpu_cache: &mut GpuCache,
1248 ) {
1249 debug_assert_eq!(self.state, State::AddResources);
1250
1251 self.glyph_rasterizer.prepare_font(&mut font);
1252 let glyph_key_cache = self.cached_glyphs.insert_glyph_key_cache_for_font(&font);
1253 let texture_cache = &mut self.texture_cache;
1254 self.glyph_rasterizer.request_glyphs(
1255 font,
1256 glyph_keys,
1257 |key| {
1258 if let Some(entry) = glyph_key_cache.try_get(key) {
1259 match entry {
1260 GlyphCacheEntry::Cached(ref glyph) => {
1261 if !texture_cache.request(&glyph.texture_cache_handle, gpu_cache) {
1263 return false;
1264 }
1265 }
1269 GlyphCacheEntry::Blank | GlyphCacheEntry::Pending => return false,
1271 }
1272 };
1273
1274 glyph_key_cache.add_glyph(*key, GlyphCacheEntry::Pending);
1275
1276 true
1277 }
1278 );
1279 }
1280
1281 pub fn pending_updates(&mut self) -> ResourceUpdateList {
1282 ResourceUpdateList {
1283 texture_updates: self.texture_cache.pending_updates(),
1284 native_surface_updates: mem::replace(&mut self.pending_native_surface_updates, Vec::new()),
1285 }
1286 }
1287
1288 pub fn fetch_glyphs<F>(
1289 &self,
1290 mut font: FontInstance,
1291 glyph_keys: &[GlyphKey],
1292 fetch_buffer: &mut Vec<GlyphFetchResult>,
1293 gpu_cache: &mut GpuCache,
1294 mut f: F,
1295 ) where
1296 F: FnMut(TextureSource, GlyphFormat, &[GlyphFetchResult]),
1297 {
1298 debug_assert_eq!(self.state, State::QueryResources);
1299
1300 self.glyph_rasterizer.prepare_font(&mut font);
1301 let glyph_key_cache = self.cached_glyphs.get_glyph_key_cache_for_font(&font);
1302
1303 let mut current_texture_id = TextureSource::Invalid;
1304 let mut current_glyph_format = GlyphFormat::Subpixel;
1305 debug_assert!(fetch_buffer.is_empty());
1306
1307 for (loop_index, key) in glyph_keys.iter().enumerate() {
1308 let (cache_item, glyph_format) = match *glyph_key_cache.get(key) {
1309 GlyphCacheEntry::Cached(ref glyph) => {
1310 (self.texture_cache.get(&glyph.texture_cache_handle), glyph.format)
1311 }
1312 GlyphCacheEntry::Blank | GlyphCacheEntry::Pending => continue,
1313 };
1314 if current_texture_id != cache_item.texture_id ||
1315 current_glyph_format != glyph_format {
1316 if !fetch_buffer.is_empty() {
1317 f(current_texture_id, current_glyph_format, fetch_buffer);
1318 fetch_buffer.clear();
1319 }
1320 current_texture_id = cache_item.texture_id;
1321 current_glyph_format = glyph_format;
1322 }
1323 fetch_buffer.push(GlyphFetchResult {
1324 index_in_text_run: loop_index as i32,
1325 uv_rect_address: gpu_cache.get_address(&cache_item.uv_rect_handle),
1326 offset: DevicePoint::new(cache_item.user_data[0], cache_item.user_data[1]),
1327 size: cache_item.uv_rect.size(),
1328 scale: cache_item.user_data[2],
1329 });
1330 }
1331
1332 if !fetch_buffer.is_empty() {
1333 f(current_texture_id, current_glyph_format, fetch_buffer);
1334 fetch_buffer.clear();
1335 }
1336 }
1337
1338 pub fn map_font_key(&self, key: FontKey) -> FontKey {
1339 self.resources.fonts.font_keys.map_key(&key)
1340 }
1341
1342 pub fn map_font_instance_key(&self, key: FontInstanceKey) -> FontInstanceKey {
1343 self.resources.fonts.instance_keys.map_key(&key)
1344 }
1345
1346 pub fn get_glyph_dimensions(
1347 &mut self,
1348 font: &FontInstance,
1349 glyph_index: GlyphIndex,
1350 ) -> Option<GlyphDimensions> {
1351 match self.cached_glyph_dimensions.entry((font.instance_key, glyph_index)) {
1352 Occupied(entry) => *entry.get(),
1353 Vacant(entry) => *entry.insert(
1354 self.glyph_rasterizer
1355 .get_glyph_dimensions(font, glyph_index),
1356 ),
1357 }
1358 }
1359
1360 pub fn get_glyph_index(&mut self, font_key: FontKey, ch: char) -> Option<u32> {
1361 self.glyph_rasterizer.get_glyph_index(font_key, ch)
1362 }
1363
1364 #[inline]
1365 pub fn get_cached_image(&self, request: ImageRequest) -> Result<CacheItem, ()> {
1366 debug_assert_eq!(self.state, State::QueryResources);
1367 let image_info = self.get_image_info(request)?;
1368
1369 if let Ok(item) = self.get_texture_cache_item(&image_info.texture_cache_handle) {
1370 return Ok(item);
1372 }
1373
1374 if self.resources.image_templates
1375 .get(request.key)
1376 .map_or(false, |img| img.data.is_snapshot()) {
1377 if self.debug_fallback_panic {
1378 panic!("Missing snapshot image");
1379 }
1380 return self.get_texture_cache_item(&self.fallback_handle);
1381 }
1382
1383 panic!("Requested image missing from the texture cache");
1384 }
1385
1386 pub fn get_cached_render_task(
1387 &self,
1388 handle: &RenderTaskCacheEntryHandle,
1389 ) -> &RenderTaskCacheEntry {
1390 self.cached_render_tasks.get_cache_entry(handle)
1391 }
1392
1393 #[inline]
1394 fn get_image_info(&self, request: ImageRequest) -> Result<&CachedImageInfo, ()> {
1395 match *self.cached_images.get(&request.key) {
1398 ImageResult::UntiledAuto(ref image_info) => Ok(image_info),
1399 ImageResult::Multi(ref entries) => Ok(entries.get(&request.into())),
1400 ImageResult::Err(_) => Err(()),
1401 }
1402 }
1403
1404 #[inline]
1405 pub fn get_texture_cache_item(&self, handle: &TextureCacheHandle) -> Result<CacheItem, ()> {
1406 if let Some(item) = self.texture_cache.try_get(handle) {
1407 return Ok(item);
1408 }
1409
1410 Err(())
1411 }
1412
1413 pub fn get_image_properties(&self, image_key: ImageKey) -> Option<ImageProperties> {
1414 let image_template = &self.resources.image_templates.get(image_key);
1415
1416 image_template.map(|image_template| {
1417 let external_image = match image_template.data {
1418 CachedImageData::External(ext_image) => match ext_image.image_type {
1419 ExternalImageType::TextureHandle(_) => Some(ext_image),
1420 ExternalImageType::Buffer => None,
1422 },
1423 CachedImageData::Raw(..)
1425 | CachedImageData::Blob
1426 | CachedImageData::Snapshot
1427 => None,
1428 };
1429
1430 ImageProperties {
1431 descriptor: image_template.descriptor,
1432 external_image,
1433 tiling: image_template.tiling,
1434 visible_rect: image_template.visible_rect,
1435 adjustment: image_template.adjustment,
1436 }
1437 })
1438 }
1439
1440 pub fn begin_frame(&mut self, stamp: FrameStamp, gpu_cache: &mut GpuCache, profile: &mut TransactionProfile) {
1441 profile_scope!("begin_frame");
1442 debug_assert_eq!(self.state, State::Idle);
1443 self.state = State::AddResources;
1444 self.texture_cache.begin_frame(stamp, profile);
1445 self.picture_textures.begin_frame(stamp, &mut self.texture_cache.pending_updates);
1446
1447 self.cached_glyphs.begin_frame(
1448 stamp,
1449 &mut self.texture_cache,
1450 &mut self.glyph_rasterizer,
1451 );
1452 self.cached_render_tasks.begin_frame(&mut self.texture_cache);
1453 self.current_frame_id = stamp.frame_id();
1454
1455 let mut v = self.deleted_blob_keys.pop_front().unwrap_or_else(Vec::new);
1458 v.clear();
1459 self.deleted_blob_keys.push_back(v);
1460
1461 self.texture_cache.run_compaction(gpu_cache);
1462 }
1463
1464 pub fn block_until_all_resources_added(
1465 &mut self,
1466 gpu_cache: &mut GpuCache,
1467 profile: &mut TransactionProfile,
1468 ) {
1469 profile_scope!("block_until_all_resources_added");
1470
1471 debug_assert_eq!(self.state, State::AddResources);
1472 self.state = State::QueryResources;
1473
1474 let cached_glyphs = &mut self.cached_glyphs;
1475 let texture_cache = &mut self.texture_cache;
1476
1477 self.glyph_rasterizer.resolve_glyphs(
1478 |job, can_use_r8_format| {
1479 let GlyphRasterJob { font, key, result } = job;
1480 let glyph_key_cache = cached_glyphs.get_glyph_key_cache_for_font_mut(&*font);
1481 let glyph_info = match result {
1482 Err(_) => GlyphCacheEntry::Blank,
1483 Ok(ref glyph) if glyph.width == 0 || glyph.height == 0 => {
1484 GlyphCacheEntry::Blank
1485 }
1486 Ok(glyph) => {
1487 let mut texture_cache_handle = TextureCacheHandle::invalid();
1488 texture_cache.request(&texture_cache_handle, gpu_cache);
1489 texture_cache.update(
1490 &mut texture_cache_handle,
1491 ImageDescriptor {
1492 size: size2(glyph.width, glyph.height),
1493 stride: None,
1494 format: glyph.format.image_format(can_use_r8_format),
1495 flags: ImageDescriptorFlags::empty(),
1496 offset: 0,
1497 },
1498 TextureFilter::Linear,
1499 Some(CachedImageData::Raw(Arc::new(glyph.bytes))),
1500 [glyph.left, -glyph.top, glyph.scale, 0.0],
1501 DirtyRect::All,
1502 gpu_cache,
1503 Some(glyph_key_cache.eviction_notice()),
1504 UvRectKind::Rect,
1505 Eviction::Auto,
1506 TargetShader::Text,
1507 );
1508 GlyphCacheEntry::Cached(CachedGlyphInfo {
1509 texture_cache_handle,
1510 format: glyph.format,
1511 })
1512 }
1513 };
1514 glyph_key_cache.insert(key, glyph_info);
1515 },
1516 profile,
1517 );
1518
1519 self.update_texture_cache(gpu_cache);
1521 }
1522
1523 fn update_texture_cache(&mut self, gpu_cache: &mut GpuCache) {
1524 profile_scope!("update_texture_cache");
1525
1526 if self.fallback_handle == TextureCacheHandle::invalid() {
1527 let fallback_color = if self.debug_fallback_pink {
1528 vec![255, 0, 255, 255]
1529 } else {
1530 vec![0, 0, 0, 0]
1531 };
1532 self.texture_cache.update(
1533 &mut self.fallback_handle,
1534 ImageDescriptor {
1535 size: size2(1, 1),
1536 stride: None,
1537 format: ImageFormat::BGRA8,
1538 flags: ImageDescriptorFlags::empty(),
1539 offset: 0,
1540 },
1541 TextureFilter::Linear,
1542 Some(CachedImageData::Raw(Arc::new(fallback_color))),
1543 [0.0; 4],
1544 DirtyRect::All,
1545 gpu_cache,
1546 None,
1547 UvRectKind::Rect,
1548 Eviction::Manual,
1549 TargetShader::Default,
1550 );
1551 }
1552
1553 for request in self.pending_image_requests.drain() {
1554 let image_template = self.resources.image_templates.get_mut(request.key).unwrap();
1555 debug_assert!(image_template.data.uses_texture_cache());
1556
1557 let mut updates: SmallVec<[(CachedImageData, Option<DeviceIntRect>); 1]> = SmallVec::new();
1558
1559 match image_template.data {
1560 CachedImageData::Snapshot => {
1561 }
1563 CachedImageData::Raw(..)
1564 | CachedImageData::External(..) => {
1565 updates.push((image_template.data.clone(), None));
1568 }
1569 CachedImageData::Blob => {
1570 let blob_image = self.rasterized_blob_images.get_mut(&BlobImageKey(request.key)).unwrap();
1571 let img = &blob_image[&request.tile.unwrap()];
1572 updates.push((
1573 CachedImageData::Raw(Arc::clone(&img.data)),
1574 Some(img.rasterized_rect)
1575 ));
1576 }
1577 };
1578
1579 for (image_data, blob_rasterized_rect) in updates {
1580 let entry = match *self.cached_images.get_mut(&request.key) {
1581 ImageResult::UntiledAuto(ref mut entry) => entry,
1582 ImageResult::Multi(ref mut entries) => entries.get_mut(&request.into()),
1583 ImageResult::Err(_) => panic!("Update requested for invalid entry")
1584 };
1585
1586 let mut descriptor = image_template.descriptor.clone();
1587 let mut dirty_rect = entry.dirty_rect.replace_with_empty();
1588
1589 if let Some(tile) = request.tile {
1590 let tile_size = image_template.tiling.unwrap();
1591 let clipped_tile_size = compute_tile_size(&image_template.visible_rect, tile_size, tile);
1592 let tiled_on_cpu = image_template.data.is_blob();
1596 if !tiled_on_cpu {
1597 debug_assert_eq!(image_template.visible_rect.min, point2(0, 0));
1600 let bpp = descriptor.format.bytes_per_pixel();
1601 let stride = descriptor.compute_stride();
1602 descriptor.stride = Some(stride);
1603 descriptor.offset +=
1604 tile.y as i32 * tile_size as i32 * stride +
1605 tile.x as i32 * tile_size as i32 * bpp;
1606 }
1607
1608 descriptor.size = clipped_tile_size;
1609 }
1610
1611 if let Some(rect) = blob_rasterized_rect {
1615 dirty_rect = DirtyRect::Partial(rect);
1616 }
1617
1618 let filter = match request.rendering {
1619 ImageRendering::Pixelated => {
1620 TextureFilter::Nearest
1621 }
1622 ImageRendering::Auto | ImageRendering::CrispEdges => {
1623 if descriptor.allow_mipmaps() &&
1631 descriptor.size.width > 512 &&
1632 descriptor.size.height > 512 &&
1633 !self.texture_cache.is_allowed_in_shared_cache(
1634 TextureFilter::Linear,
1635 &descriptor,
1636 ) {
1637 TextureFilter::Trilinear
1638 } else {
1639 TextureFilter::Linear
1640 }
1641 }
1642 };
1643
1644 let eviction = match &image_template.data {
1645 CachedImageData::Blob | CachedImageData::Snapshot => {
1646 entry.manual_eviction = true;
1647 Eviction::Manual
1648 }
1649 _ => {
1650 Eviction::Auto
1651 }
1652 };
1653
1654 self.texture_cache.update(
1656 &mut entry.texture_cache_handle,
1657 descriptor,
1658 filter,
1659 Some(image_data),
1660 [0.0; 4],
1661 dirty_rect,
1662 gpu_cache,
1663 None,
1664 UvRectKind::Rect,
1665 eviction,
1666 TargetShader::Default,
1667 );
1668 }
1669 }
1670 }
1671
1672 pub fn create_compositor_backdrop_surface(
1673 &mut self,
1674 color: ColorF
1675 ) -> NativeSurfaceId {
1676 let id = NativeSurfaceId(NEXT_NATIVE_SURFACE_ID.fetch_add(1, Ordering::Relaxed) as u64);
1677
1678 self.pending_native_surface_updates.push(
1679 NativeSurfaceOperation {
1680 details: NativeSurfaceOperationDetails::CreateBackdropSurface {
1681 id,
1682 color,
1683 },
1684 }
1685 );
1686
1687 id
1688 }
1689
1690 pub fn create_compositor_surface(
1693 &mut self,
1694 virtual_offset: DeviceIntPoint,
1695 tile_size: DeviceIntSize,
1696 is_opaque: bool,
1697 ) -> NativeSurfaceId {
1698 let id = NativeSurfaceId(NEXT_NATIVE_SURFACE_ID.fetch_add(1, Ordering::Relaxed) as u64);
1699
1700 self.pending_native_surface_updates.push(
1701 NativeSurfaceOperation {
1702 details: NativeSurfaceOperationDetails::CreateSurface {
1703 id,
1704 virtual_offset,
1705 tile_size,
1706 is_opaque,
1707 },
1708 }
1709 );
1710
1711 id
1712 }
1713
1714 pub fn create_compositor_external_surface(
1715 &mut self,
1716 is_opaque: bool,
1717 ) -> NativeSurfaceId {
1718 let id = NativeSurfaceId(NEXT_NATIVE_SURFACE_ID.fetch_add(1, Ordering::Relaxed) as u64);
1719
1720 self.pending_native_surface_updates.push(
1721 NativeSurfaceOperation {
1722 details: NativeSurfaceOperationDetails::CreateExternalSurface {
1723 id,
1724 is_opaque,
1725 },
1726 }
1727 );
1728
1729 id
1730 }
1731
1732 pub fn destroy_compositor_surface(
1735 &mut self,
1736 id: NativeSurfaceId,
1737 ) {
1738 self.pending_native_surface_updates.push(
1739 NativeSurfaceOperation {
1740 details: NativeSurfaceOperationDetails::DestroySurface {
1741 id,
1742 }
1743 }
1744 );
1745 }
1746
1747 pub fn create_compositor_tile(
1749 &mut self,
1750 id: NativeTileId,
1751 ) {
1752 self.pending_native_surface_updates.push(
1753 NativeSurfaceOperation {
1754 details: NativeSurfaceOperationDetails::CreateTile {
1755 id,
1756 },
1757 }
1758 );
1759 }
1760
1761 pub fn destroy_compositor_tile(
1763 &mut self,
1764 id: NativeTileId,
1765 ) {
1766 self.pending_native_surface_updates.push(
1767 NativeSurfaceOperation {
1768 details: NativeSurfaceOperationDetails::DestroyTile {
1769 id,
1770 },
1771 }
1772 );
1773 }
1774
1775 pub fn attach_compositor_external_image(
1776 &mut self,
1777 id: NativeSurfaceId,
1778 external_image: ExternalImageId,
1779 ) {
1780 self.pending_native_surface_updates.push(
1781 NativeSurfaceOperation {
1782 details: NativeSurfaceOperationDetails::AttachExternalImage {
1783 id,
1784 external_image,
1785 },
1786 }
1787 );
1788 }
1789
1790
1791 pub fn end_frame(&mut self, profile: &mut TransactionProfile) {
1792 debug_assert_eq!(self.state, State::QueryResources);
1793 profile_scope!("end_frame");
1794 self.state = State::Idle;
1795
1796 self.gc_render_targets(
1809 64 * 1024 * 1024,
1810 32 * 1024 * 1024 * 10,
1811 60,
1812 );
1813
1814 self.texture_cache.end_frame(profile);
1815 self.picture_textures.gc(
1816 &mut self.texture_cache.pending_updates,
1817 );
1818
1819 self.picture_textures.update_profile(profile);
1820 }
1821
1822 pub fn set_debug_flags(&mut self, flags: DebugFlags) {
1823 GLYPH_FLASHING.store(flags.contains(DebugFlags::GLYPH_FLASHING), std::sync::atomic::Ordering::Relaxed);
1824 self.texture_cache.set_debug_flags(flags);
1825 self.picture_textures.set_debug_flags(flags);
1826 self.debug_fallback_panic = flags.contains(DebugFlags::MISSING_SNAPSHOT_PANIC);
1827 let fallback_pink = flags.contains(DebugFlags::MISSING_SNAPSHOT_PINK);
1828
1829 if fallback_pink != self.debug_fallback_pink && self.fallback_handle != TextureCacheHandle::invalid() {
1830 self.texture_cache.evict_handle(&self.fallback_handle);
1831 }
1832 self.debug_fallback_pink = fallback_pink;
1833 }
1834
1835 pub fn clear(&mut self, what: ClearCache) {
1836 if what.contains(ClearCache::IMAGES) {
1837 for (_key, mut cached) in self.cached_images.resources.drain() {
1838 cached.drop_from_cache(&mut self.texture_cache);
1839 }
1840 }
1841 if what.contains(ClearCache::GLYPHS) {
1842 self.cached_glyphs.clear();
1843 }
1844 if what.contains(ClearCache::GLYPH_DIMENSIONS) {
1845 self.cached_glyph_dimensions.clear();
1846 }
1847 if what.contains(ClearCache::RENDER_TASKS) {
1848 self.cached_render_tasks.clear();
1849 }
1850 if what.contains(ClearCache::TEXTURE_CACHE) {
1851 self.texture_cache.clear_all();
1852 self.picture_textures.clear(&mut self.texture_cache.pending_updates);
1853 }
1854 if what.contains(ClearCache::RENDER_TARGETS) {
1855 self.clear_render_target_pool();
1856 }
1857 }
1858
1859 pub fn clear_namespace(&mut self, namespace: IdNamespace) {
1860 self.clear_images(|k| k.0 == namespace);
1861
1862 self.resources.fonts.instances.clear_namespace(namespace);
1864 let deleted_keys = self.resources.fonts.templates.clear_namespace(namespace);
1865 self.glyph_rasterizer.delete_fonts(&deleted_keys);
1866 self.cached_glyphs.clear_namespace(namespace);
1867 if let Some(handler) = &mut self.blob_image_handler {
1868 handler.clear_namespace(namespace);
1869 }
1870
1871 let shared_instance_keys = self.resources.fonts.instance_keys.clear_namespace(namespace);
1873 if !shared_instance_keys.is_empty() {
1874 self.resources.fonts.instances.delete_font_instances(&shared_instance_keys);
1875 self.cached_glyphs.delete_font_instances(&shared_instance_keys, &mut self.glyph_rasterizer);
1876 }
1879
1880 let shared_keys = self.resources.fonts.font_keys.clear_namespace(namespace);
1882 if !shared_keys.is_empty() {
1883 self.glyph_rasterizer.delete_fonts(&shared_keys);
1884 self.resources.fonts.templates.delete_fonts(&shared_keys);
1885 self.cached_glyphs.delete_fonts(&shared_keys);
1886 if let Some(handler) = &mut self.blob_image_handler {
1887 for &key in &shared_keys {
1888 handler.delete_font(key);
1889 }
1890 }
1891 }
1892 }
1893
1894 pub fn report_memory(&self, op: VoidPtrToSizeFn) -> MemoryReport {
1903 let mut report = MemoryReport::default();
1904
1905 let mut seen_fonts = std::collections::HashSet::new();
1906 for (_, font) in self.resources.fonts.templates.lock().iter() {
1909 if let FontTemplate::Raw(ref raw, _) = font {
1910 report.fonts += unsafe { op(raw.as_ptr() as *const c_void) };
1911 seen_fonts.insert(raw.as_ptr());
1912 }
1913 }
1914
1915 for font in self.resources.weak_fonts.iter() {
1916 if !seen_fonts.contains(&font.as_ptr()) {
1917 report.weak_fonts += unsafe { op(font.as_ptr() as *const c_void) };
1918 }
1919 }
1920
1921 for (_, image) in self.resources.image_templates.images.iter() {
1923 report.images += match image.data {
1924 CachedImageData::Raw(ref v) => unsafe { op(v.as_ptr() as *const c_void) },
1925 CachedImageData::Blob
1926 | CachedImageData::External(..)
1927 | CachedImageData::Snapshot => 0,
1928 }
1929 }
1930
1931 report
1947 }
1948
1949 fn clear_images<F: Fn(&ImageKey) -> bool>(&mut self, f: F) {
1951 let keys = self.resources.image_templates.images.keys().filter(|k| f(*k))
1952 .cloned().collect::<SmallVec<[ImageKey; 16]>>();
1953
1954 for key in keys {
1955 self.delete_image_template(key);
1956 }
1957
1958 #[cfg(feature="leak_checks")]
1959 let check_leaks = true;
1960 #[cfg(not(feature="leak_checks"))]
1961 let check_leaks = false;
1962
1963 if check_leaks {
1964 let blob_f = |key: &BlobImageKey| { f(&key.as_image()) };
1965 assert!(!self.resources.image_templates.images.keys().any(&f));
1966 assert!(!self.cached_images.resources.keys().any(&f));
1967 assert!(!self.rasterized_blob_images.keys().any(&blob_f));
1968 }
1969 }
1970
1971 pub fn get_or_create_render_target_from_pool(
1974 &mut self,
1975 size: DeviceIntSize,
1976 format: ImageFormat,
1977 ) -> CacheTextureId {
1978 for target in &mut self.render_target_pool {
1979 if target.size == size &&
1980 target.format == format &&
1981 !target.is_active {
1982 target.is_active = true;
1985 target.last_frame_used = self.current_frame_id;
1986 return target.texture_id;
1987 }
1988 }
1989
1990 let texture_id = self.texture_cache.alloc_render_target(
1993 size,
1994 format,
1995 );
1996
1997 self.render_target_pool.push(RenderTarget {
1998 size,
1999 format,
2000 texture_id,
2001 is_active: true,
2002 last_frame_used: self.current_frame_id,
2003 });
2004
2005 texture_id
2006 }
2007
2008 pub fn return_render_target_to_pool(
2010 &mut self,
2011 id: CacheTextureId,
2012 ) {
2013 let target = self.render_target_pool
2014 .iter_mut()
2015 .find(|t| t.texture_id == id)
2016 .expect("bug: invalid render target id");
2017
2018 assert!(target.is_active);
2019 target.is_active = false;
2020 }
2021
2022 fn clear_render_target_pool(
2024 &mut self,
2025 ) {
2026 for target in self.render_target_pool.drain(..) {
2027 debug_assert!(!target.is_active);
2028 self.texture_cache.free_render_target(target.texture_id);
2029 }
2030 }
2031
2032 fn gc_render_targets(
2035 &mut self,
2036 total_bytes_threshold: usize,
2037 total_bytes_red_line_threshold: usize,
2038 frames_threshold: u64,
2039 ) {
2040 let mut rt_pool_size_in_bytes: usize = self.render_target_pool
2042 .iter()
2043 .map(|t| t.size_in_bytes())
2044 .sum();
2045
2046 if rt_pool_size_in_bytes <= total_bytes_threshold {
2049 return;
2050 }
2051
2052 self.render_target_pool.sort_by_key(|t| t.last_frame_used);
2054
2055 let mut retained_targets = SmallVec::<[RenderTarget; 8]>::new();
2057
2058 for target in self.render_target_pool.drain(..) {
2059 assert!(!target.is_active);
2060
2061 let above_red_line = rt_pool_size_in_bytes > total_bytes_red_line_threshold;
2066 let above_threshold = rt_pool_size_in_bytes > total_bytes_threshold;
2067 let used_recently = target.used_recently(self.current_frame_id, frames_threshold);
2068 let used_this_frame = target.last_frame_used == self.current_frame_id;
2069
2070 if !used_this_frame && (above_red_line || (above_threshold && !used_recently)) {
2071 rt_pool_size_in_bytes -= target.size_in_bytes();
2072 self.texture_cache.free_render_target(target.texture_id);
2073 } else {
2074 retained_targets.push(target);
2075 }
2076 }
2077
2078 self.render_target_pool.extend(retained_targets);
2079 }
2080
2081 #[cfg(test)]
2082 pub fn validate_surfaces(
2083 &self,
2084 expected_surfaces: &[(i32, i32, ImageFormat)],
2085 ) {
2086 assert_eq!(expected_surfaces.len(), self.render_target_pool.len());
2087
2088 for (expected, surface) in expected_surfaces.iter().zip(self.render_target_pool.iter()) {
2089 assert_eq!(DeviceIntSize::new(expected.0, expected.1), surface.size);
2090 assert_eq!(expected.2, surface.format);
2091 }
2092 }
2093}
2094
2095impl Drop for ResourceCache {
2096 fn drop(&mut self) {
2097 self.clear_images(|_| true);
2098 }
2099}
2100
2101#[cfg(any(feature = "capture", feature = "replay"))]
2102#[cfg_attr(feature = "capture", derive(Serialize))]
2103#[cfg_attr(feature = "replay", derive(Deserialize))]
2104struct PlainFontTemplate {
2105 data: String,
2106 index: u32,
2107}
2108
2109#[cfg(any(feature = "capture", feature = "replay"))]
2110#[cfg_attr(feature = "capture", derive(Serialize))]
2111#[cfg_attr(feature = "replay", derive(Deserialize))]
2112struct PlainImageTemplate {
2113 data: String,
2114 descriptor: ImageDescriptor,
2115 tiling: Option<TileSize>,
2116 generation: ImageGeneration,
2117}
2118
2119#[cfg(any(feature = "capture", feature = "replay"))]
2120#[cfg_attr(feature = "capture", derive(Serialize))]
2121#[cfg_attr(feature = "replay", derive(Deserialize))]
2122pub struct PlainResources {
2123 font_templates: FastHashMap<FontKey, PlainFontTemplate>,
2124 font_instances: Vec<BaseFontInstance>,
2125 image_templates: FastHashMap<ImageKey, PlainImageTemplate>,
2126}
2127
2128#[cfg(feature = "capture")]
2129#[derive(Serialize)]
2130pub struct PlainCacheRef<'a> {
2131 current_frame_id: FrameId,
2132 glyphs: &'a GlyphCache,
2133 glyph_dimensions: &'a GlyphDimensionsCache,
2134 images: &'a ImageCache,
2135 render_tasks: &'a RenderTaskCache,
2136 textures: &'a TextureCache,
2137 picture_textures: &'a PictureTextures,
2138}
2139
2140#[cfg(feature = "replay")]
2141#[derive(Deserialize)]
2142pub struct PlainCacheOwn {
2143 current_frame_id: FrameId,
2144 glyphs: GlyphCache,
2145 glyph_dimensions: GlyphDimensionsCache,
2146 images: ImageCache,
2147 render_tasks: RenderTaskCache,
2148 textures: TextureCache,
2149 picture_textures: PictureTextures,
2150}
2151
2152#[cfg(feature = "replay")]
2153const NATIVE_FONT: &'static [u8] = include_bytes!("../res/Proggy.ttf");
2154
2155fn to_image_dirty_rect(blob_dirty_rect: &BlobDirtyRect) -> ImageDirtyRect {
2157 match *blob_dirty_rect {
2158 DirtyRect::Partial(rect) => DirtyRect::Partial(rect.cast_unit()),
2159 DirtyRect::All => DirtyRect::All,
2160 }
2161}
2162
2163impl ResourceCache {
2164 #[cfg(feature = "capture")]
2165 pub fn save_capture(
2166 &mut self, root: &PathBuf
2167 ) -> (PlainResources, Vec<ExternalCaptureImage>) {
2168 use std::fs;
2169 use std::io::Write;
2170
2171 info!("saving resource cache");
2172 let res = &self.resources;
2173 let path_fonts = root.join("fonts");
2174 if !path_fonts.is_dir() {
2175 fs::create_dir(&path_fonts).unwrap();
2176 }
2177 let path_images = root.join("images");
2178 if !path_images.is_dir() {
2179 fs::create_dir(&path_images).unwrap();
2180 }
2181 let path_blobs = root.join("blobs");
2182 if !path_blobs.is_dir() {
2183 fs::create_dir(&path_blobs).unwrap();
2184 }
2185 let path_externals = root.join("externals");
2186 if !path_externals.is_dir() {
2187 fs::create_dir(&path_externals).unwrap();
2188 }
2189
2190 info!("\tfont templates");
2191 let mut font_paths = FastHashMap::default();
2192 for template in res.fonts.templates.lock().values() {
2193 let data: &[u8] = match *template {
2194 FontTemplate::Raw(ref arc, _) => arc,
2195 FontTemplate::Native(_) => continue,
2196 };
2197 let font_id = res.fonts.templates.len() + 1;
2198 let entry = match font_paths.entry(data.as_ptr()) {
2199 Entry::Occupied(_) => continue,
2200 Entry::Vacant(e) => e,
2201 };
2202 let file_name = format!("{}.raw", font_id);
2203 let short_path = format!("fonts/{}", file_name);
2204 fs::File::create(path_fonts.join(file_name))
2205 .expect(&format!("Unable to create {}", short_path))
2206 .write_all(data)
2207 .unwrap();
2208 entry.insert(short_path);
2209 }
2210
2211 info!("\timage templates");
2212 let mut image_paths = FastHashMap::default();
2213 let mut other_paths = FastHashMap::default();
2214 let mut num_blobs = 0;
2215 let mut external_images = Vec::new();
2216 for (&key, template) in res.image_templates.images.iter() {
2217 let desc = &template.descriptor;
2218 match template.data {
2219 CachedImageData::Raw(ref arc) => {
2220 let image_id = image_paths.len() + 1;
2221 let entry = match image_paths.entry(arc.as_ptr()) {
2222 Entry::Occupied(_) => continue,
2223 Entry::Vacant(e) => e,
2224 };
2225
2226 #[cfg(feature = "png")]
2227 CaptureConfig::save_png(
2228 root.join(format!("images/{}.png", image_id)),
2229 desc.size,
2230 desc.format,
2231 desc.stride,
2232 &arc,
2233 );
2234 let file_name = format!("{}.raw", image_id);
2235 let short_path = format!("images/{}", file_name);
2236 fs::File::create(path_images.join(file_name))
2237 .expect(&format!("Unable to create {}", short_path))
2238 .write_all(&*arc)
2239 .unwrap();
2240 entry.insert(short_path);
2241 }
2242 CachedImageData::Blob => {
2243 warn!("Tiled blob images aren't supported yet");
2244 let result = RasterizedBlobImage {
2245 rasterized_rect: desc.size.into(),
2246 data: Arc::new(vec![0; desc.compute_total_size() as usize])
2247 };
2248
2249 assert_eq!(result.rasterized_rect.size(), desc.size);
2250 assert_eq!(result.data.len(), desc.compute_total_size() as usize);
2251
2252 num_blobs += 1;
2253 #[cfg(feature = "png")]
2254 CaptureConfig::save_png(
2255 root.join(format!("blobs/{}.png", num_blobs)),
2256 desc.size,
2257 desc.format,
2258 desc.stride,
2259 &result.data,
2260 );
2261 let file_name = format!("{}.raw", num_blobs);
2262 let short_path = format!("blobs/{}", file_name);
2263 let full_path = path_blobs.clone().join(&file_name);
2264 fs::File::create(full_path)
2265 .expect(&format!("Unable to create {}", short_path))
2266 .write_all(&result.data)
2267 .unwrap();
2268 other_paths.insert(key, short_path);
2269 }
2270 CachedImageData::Snapshot => {
2271 unimplemented!();
2272 }
2273 CachedImageData::External(ref ext) => {
2274 let short_path = format!("externals/{}", external_images.len() + 1);
2275 other_paths.insert(key, short_path.clone());
2276 external_images.push(ExternalCaptureImage {
2277 short_path,
2278 descriptor: desc.clone(),
2279 external: ext.clone(),
2280 });
2281 }
2282 }
2283 }
2284
2285 let mut font_templates = FastHashMap::default();
2286 let mut font_remap = FastHashMap::default();
2287 for key in res.fonts.font_keys.keys() {
2289 let shared_key = res.fonts.font_keys.map_key(&key);
2290 let template = match res.fonts.templates.get_font(&shared_key) {
2291 Some(template) => template,
2292 None => {
2293 debug!("Failed serializing font template {:?}", key);
2294 continue;
2295 }
2296 };
2297 let plain_font = match template {
2298 FontTemplate::Raw(arc, index) => {
2299 PlainFontTemplate {
2300 data: font_paths[&arc.as_ptr()].clone(),
2301 index,
2302 }
2303 }
2304 #[cfg(not(any(target_os = "macos", target_os = "ios")))]
2305 FontTemplate::Native(native) => {
2306 PlainFontTemplate {
2307 data: native.path.to_string_lossy().to_string(),
2308 index: native.index,
2309 }
2310 }
2311 #[cfg(any(target_os = "macos", target_os = "ios"))]
2312 FontTemplate::Native(native) => {
2313 PlainFontTemplate {
2314 data: native.name,
2315 index: 0,
2316 }
2317 }
2318 };
2319 font_templates.insert(key, plain_font);
2320 font_remap.insert(shared_key, key);
2322 }
2323 let mut font_instances = Vec::new();
2324 for instance_key in res.fonts.instance_keys.keys() {
2326 let shared_key = res.fonts.instance_keys.map_key(&instance_key);
2327 let instance = match res.fonts.instances.get_font_instance(shared_key) {
2328 Some(instance) => instance,
2329 None => {
2330 debug!("Failed serializing font instance {:?}", instance_key);
2331 continue;
2332 }
2333 };
2334 font_instances.push(BaseFontInstance {
2337 font_key: font_remap.get(&instance.font_key).cloned().unwrap_or(instance.font_key),
2338 instance_key,
2339 ..(*instance).clone()
2340 });
2341 }
2342 let resources = PlainResources {
2343 font_templates,
2344 font_instances,
2345 image_templates: res.image_templates.images
2346 .iter()
2347 .map(|(key, template)| {
2348 (*key, PlainImageTemplate {
2349 data: match template.data {
2350 CachedImageData::Raw(ref arc) => image_paths[&arc.as_ptr()].clone(),
2351 _ => other_paths[key].clone(),
2352 },
2353 descriptor: template.descriptor.clone(),
2354 tiling: template.tiling,
2355 generation: template.generation,
2356 })
2357 })
2358 .collect(),
2359 };
2360
2361 (resources, external_images)
2362 }
2363
2364 #[cfg(feature = "capture")]
2365 pub fn save_caches(&self, _root: &PathBuf) -> PlainCacheRef {
2366 PlainCacheRef {
2367 current_frame_id: self.current_frame_id,
2368 glyphs: &self.cached_glyphs,
2369 glyph_dimensions: &self.cached_glyph_dimensions,
2370 images: &self.cached_images,
2371 render_tasks: &self.cached_render_tasks,
2372 textures: &self.texture_cache,
2373 picture_textures: &self.picture_textures,
2374 }
2375 }
2376
2377 #[cfg(feature = "replay")]
2378 pub fn load_capture(
2379 &mut self,
2380 resources: PlainResources,
2381 caches: Option<PlainCacheOwn>,
2382 config: &CaptureConfig,
2383 ) -> Vec<PlainExternalImage> {
2384 use std::{fs, path::Path};
2385 use crate::texture_cache::TextureCacheConfig;
2386
2387 info!("loading resource cache");
2388 let mut raw_map = FastHashMap::<String, Arc<Vec<u8>>>::default();
2392
2393 self.clear(ClearCache::all());
2394 self.clear_images(|_| true);
2395
2396 match caches {
2397 Some(cached) => {
2398 self.current_frame_id = cached.current_frame_id;
2399 self.cached_glyphs = cached.glyphs;
2400 self.cached_glyph_dimensions = cached.glyph_dimensions;
2401 self.cached_images = cached.images;
2402 self.cached_render_tasks = cached.render_tasks;
2403 self.texture_cache = cached.textures;
2404 self.picture_textures = cached.picture_textures;
2405 }
2406 None => {
2407 self.current_frame_id = FrameId::INVALID;
2408 self.texture_cache = TextureCache::new(
2409 self.texture_cache.max_texture_size(),
2410 self.texture_cache.tiling_threshold(),
2411 self.texture_cache.color_formats(),
2412 self.texture_cache.swizzle_settings(),
2413 &TextureCacheConfig::DEFAULT,
2414 );
2415 self.picture_textures = PictureTextures::new(
2416 self.picture_textures.default_tile_size(),
2417 self.picture_textures.filter(),
2418 );
2419 }
2420 }
2421
2422 self.glyph_rasterizer.reset();
2423 let res = &mut self.resources;
2424 res.fonts.templates.clear();
2425 res.fonts.instances.clear();
2426 res.image_templates.images.clear();
2427
2428 info!("\tfont templates...");
2429 let root = config.resource_root();
2430 let native_font_replacement = Arc::new(NATIVE_FONT.to_vec());
2431 for (key, plain_template) in resources.font_templates {
2432 let arc = match raw_map.entry(plain_template.data) {
2433 Entry::Occupied(e) => {
2434 e.get().clone()
2435 }
2436 Entry::Vacant(e) => {
2437 let file_path = if Path::new(e.key()).is_absolute() {
2438 PathBuf::from(e.key())
2439 } else {
2440 root.join(e.key())
2441 };
2442 let arc = match fs::read(file_path) {
2443 Ok(buffer) => Arc::new(buffer),
2444 Err(err) => {
2445 error!("Unable to open font template {:?}: {:?}", e.key(), err);
2446 Arc::clone(&native_font_replacement)
2447 }
2448 };
2449 e.insert(arc).clone()
2450 }
2451 };
2452
2453 let template = FontTemplate::Raw(arc, plain_template.index);
2454 if let Some(shared_key) = res.fonts.font_keys.add_key(&key, &template) {
2456 self.glyph_rasterizer.add_font(shared_key, template.clone());
2457 res.fonts.templates.add_font(shared_key, template);
2458 }
2459 }
2460
2461 info!("\tfont instances...");
2462 for instance in resources.font_instances {
2463 let base = BaseFontInstance {
2465 font_key: res.fonts.font_keys.map_key(&instance.font_key),
2466 ..instance
2467 };
2468 if let Some(shared_instance) = res.fonts.instance_keys.add_key(base) {
2469 res.fonts.instances.add_font_instance(shared_instance);
2470 }
2471 }
2472
2473 info!("\timage templates...");
2474 let mut external_images = Vec::new();
2475 for (key, template) in resources.image_templates {
2476 let data = match config.deserialize_for_resource::<PlainExternalImage, _>(&template.data) {
2477 Some(plain) => {
2478 let ext_data = plain.external;
2479 external_images.push(plain);
2480 CachedImageData::External(ext_data)
2481 }
2482 None => {
2483 let arc = match raw_map.entry(template.data) {
2484 Entry::Occupied(e) => {
2485 e.get().clone()
2486 }
2487 Entry::Vacant(e) => {
2488 let buffer = fs::read(root.join(e.key()))
2489 .expect(&format!("Unable to open {}", e.key()));
2490 e.insert(Arc::new(buffer))
2491 .clone()
2492 }
2493 };
2494 CachedImageData::Raw(arc)
2495 }
2496 };
2497
2498 res.image_templates.images.insert(key, ImageResource {
2499 data,
2500 descriptor: template.descriptor,
2501 tiling: template.tiling,
2502 visible_rect: template.descriptor.size.into(),
2503 adjustment: AdjustedImageSource::new(), generation: template.generation,
2505 });
2506 }
2507
2508 external_images
2509 }
2510
2511 #[cfg(feature = "capture")]
2512 pub fn save_capture_sequence(&mut self, config: &mut CaptureConfig) -> Vec<ExternalCaptureImage> {
2513 if self.capture_dirty {
2514 self.capture_dirty = false;
2515 config.prepare_resource();
2516 let (resources, deferred) = self.save_capture(&config.resource_root());
2517 config.serialize_for_resource(&resources, "plain-resources.ron");
2518 deferred
2519 } else {
2520 Vec::new()
2521 }
2522 }
2523}