1
- use crate :: { text_render:: ContentType , CacheKey , GlyphDetails , GlyphToRender , Params , Resolution } ;
1
+ use crate :: {
2
+ text_render:: ContentType , CacheKey , FontSystem , GlyphDetails , GlyphToRender , GpuCacheStatus ,
3
+ Params , Resolution , SwashCache ,
4
+ } ;
2
5
use etagere:: { size2, Allocation , BucketedAtlasAllocator } ;
3
6
use lru:: LruCache ;
4
7
use std:: { borrow:: Cow , collections:: HashSet , mem:: size_of, num:: NonZeroU64 , sync:: Arc } ;
5
8
use wgpu:: {
6
9
BindGroup , BindGroupDescriptor , BindGroupEntry , BindGroupLayout , BindGroupLayoutEntry ,
7
10
BindingResource , BindingType , BlendState , Buffer , BufferBindingType , BufferDescriptor ,
8
11
BufferUsages , ColorTargetState , ColorWrites , DepthStencilState , Device , Extent3d , FilterMode ,
9
- FragmentState , MultisampleState , PipelineLayout , PipelineLayoutDescriptor , PrimitiveState ,
10
- Queue , RenderPipeline , RenderPipelineDescriptor , Sampler , SamplerBindingType ,
11
- SamplerDescriptor , ShaderModule , ShaderModuleDescriptor , ShaderSource , ShaderStages , Texture ,
12
- TextureDescriptor , TextureDimension , TextureFormat , TextureSampleType , TextureUsages ,
13
- TextureView , TextureViewDescriptor , TextureViewDimension , VertexFormat , VertexState ,
12
+ FragmentState , ImageCopyTexture , ImageDataLayout , MultisampleState , Origin3d , PipelineLayout ,
13
+ PipelineLayoutDescriptor , PrimitiveState , Queue , RenderPipeline , RenderPipelineDescriptor ,
14
+ Sampler , SamplerBindingType , SamplerDescriptor , ShaderModule , ShaderModuleDescriptor ,
15
+ ShaderSource , ShaderStages , Texture , TextureAspect , TextureDescriptor , TextureDimension ,
16
+ TextureFormat , TextureSampleType , TextureUsages , TextureView , TextureViewDescriptor ,
17
+ TextureViewDimension , VertexFormat , VertexState ,
14
18
} ;
15
19
16
20
#[ allow( dead_code) ]
@@ -78,20 +82,19 @@ impl InnerAtlas {
78
82
}
79
83
80
84
// Try to free least recently used allocation
81
- let ( _ , mut value) = self . glyph_cache . peek_lru ( ) ?;
85
+ let ( mut key , mut value) = self . glyph_cache . peek_lru ( ) ?;
82
86
83
87
while value. atlas_id . is_none ( ) {
84
88
let _ = self . glyph_cache . pop_lru ( ) ;
85
89
86
- ( _ , value) = self . glyph_cache . peek_lru ( ) ?;
90
+ ( key , value) = self . glyph_cache . peek_lru ( ) ?;
87
91
}
88
92
89
- let ( key, value) = self . glyph_cache . pop_lru ( ) . unwrap ( ) ;
90
-
91
93
if self . glyphs_in_use . contains ( & key) {
92
94
return None ;
93
95
}
94
96
97
+ let ( _, value) = self . glyph_cache . pop_lru ( ) . unwrap ( ) ;
95
98
self . packer . deallocate ( value. atlas_id . unwrap ( ) ) ;
96
99
}
97
100
}
@@ -110,15 +113,21 @@ impl InnerAtlas {
110
113
self . glyphs_in_use . insert ( glyph) ;
111
114
}
112
115
113
- pub ( crate ) fn grow ( & mut self , device : & wgpu:: Device ) -> bool {
116
+ pub ( crate ) fn grow (
117
+ & mut self ,
118
+ device : & wgpu:: Device ,
119
+ queue : & wgpu:: Queue ,
120
+ font_system : & mut FontSystem ,
121
+ cache : & mut SwashCache ,
122
+ ) -> bool {
114
123
if self . size >= self . max_texture_dimension_2d {
115
124
return false ;
116
125
}
117
126
118
127
// TODO: Better resizing logic (?)
119
128
let new_size = ( self . size + Self :: INITIAL_SIZE ) . min ( self . max_texture_dimension_2d ) ;
120
129
121
- self . packer = BucketedAtlasAllocator :: new ( size2 ( new_size as i32 , new_size as i32 ) ) ;
130
+ self . packer . grow ( size2 ( new_size as i32 , new_size as i32 ) ) ;
122
131
123
132
// Create a texture to use for our atlas
124
133
self . texture = device. create_texture ( & TextureDescriptor {
@@ -136,12 +145,46 @@ impl InnerAtlas {
136
145
view_formats : & [ ] ,
137
146
} ) ;
138
147
148
+ // Re-upload glyphs
149
+ for ( & cache_key, glyph) in & self . glyph_cache {
150
+ let ( x, y) = match glyph. gpu_cache {
151
+ GpuCacheStatus :: InAtlas { x, y, .. } => ( x, y) ,
152
+ GpuCacheStatus :: SkipRasterization => continue ,
153
+ } ;
154
+
155
+ let image = cache. get_image_uncached ( font_system, cache_key) . unwrap ( ) ;
156
+
157
+ let width = image. placement . width as usize ;
158
+ let height = image. placement . height as usize ;
159
+
160
+ queue. write_texture (
161
+ ImageCopyTexture {
162
+ texture : & self . texture ,
163
+ mip_level : 0 ,
164
+ origin : Origin3d {
165
+ x : x as u32 ,
166
+ y : y as u32 ,
167
+ z : 0 ,
168
+ } ,
169
+ aspect : TextureAspect :: All ,
170
+ } ,
171
+ & image. data ,
172
+ ImageDataLayout {
173
+ offset : 0 ,
174
+ bytes_per_row : Some ( width as u32 * self . kind . num_channels ( ) as u32 ) ,
175
+ rows_per_image : None ,
176
+ } ,
177
+ Extent3d {
178
+ width : width as u32 ,
179
+ height : height as u32 ,
180
+ depth_or_array_layers : 1 ,
181
+ } ,
182
+ ) ;
183
+ }
184
+
139
185
self . texture_view = self . texture . create_view ( & TextureViewDescriptor :: default ( ) ) ;
140
186
self . size = new_size;
141
187
142
- self . glyph_cache . clear ( ) ;
143
- self . glyphs_in_use . clear ( ) ;
144
-
145
188
true
146
189
}
147
190
@@ -406,18 +449,24 @@ impl TextAtlas {
406
449
self . color_atlas . trim ( ) ;
407
450
}
408
451
409
- pub fn grow ( & mut self , device : & wgpu:: Device , content_type : ContentType ) -> bool {
452
+ pub ( crate ) fn grow (
453
+ & mut self ,
454
+ device : & wgpu:: Device ,
455
+ queue : & wgpu:: Queue ,
456
+ font_system : & mut FontSystem ,
457
+ cache : & mut SwashCache ,
458
+ content_type : ContentType ,
459
+ ) -> bool {
410
460
let did_grow = match content_type {
411
- ContentType :: Mask => self . mask_atlas . grow ( device) ,
412
- ContentType :: Color => self . color_atlas . grow ( device) ,
461
+ ContentType :: Mask => self . mask_atlas . grow ( device, queue , font_system , cache ) ,
462
+ ContentType :: Color => self . color_atlas . grow ( device, queue , font_system , cache ) ,
413
463
} ;
414
464
415
465
if did_grow {
416
466
self . rebind ( device) ;
417
- true
418
- } else {
419
- false
420
467
}
468
+
469
+ did_grow
421
470
}
422
471
423
472
pub ( crate ) fn glyph ( & self , glyph : & CacheKey ) -> Option < & GlyphDetails > {
0 commit comments