浏览代码

Draw in multiple steps when texture atlas is too small

Johannes Hofmann 8 年前
父节点
当前提交
489df246d4
共有 3 个文件被更改,包括 76 次插入16 次删除
  1. 44
    11
      src/map_view_gl.rs
  2. 5
    0
      src/tile_cache.rs
  3. 27
    5
      src/tile_cache_gl.rs

+ 44
- 11
src/map_view_gl.rs 查看文件

96
             center: self.map_view.center,
96
             center: self.map_view.center,
97
         });
97
         });
98
 
98
 
99
-        {
100
-            let visible_tiles = self.map_view.visible_tiles(true);
101
-            let textured_visible_tiles = self.tile_cache_gl.textured_visible_tiles(
102
-                &visible_tiles,
103
-                source,
104
-                &mut self.tile_cache,
105
-            );
99
+        self.cx.clear_color((0.2, 0.2, 0.2, 1.0));
100
+
101
+        let visible_tiles = self.map_view.visible_tiles(true);
102
+        let mut remainder = visible_tiles.as_slice();
103
+        let mut num_draws = 0;
104
+        let mut max_tiles_to_use = self.tile_cache.max_tiles();
105
+
106
+        loop {
107
+            let (textured_visible_tiles, remainder_opt, used_tiles) = {
108
+                self.tile_cache_gl.textured_visible_tiles(
109
+                    remainder,
110
+                    max_tiles_to_use,
111
+                    source,
112
+                    &mut self.tile_cache,
113
+                )
114
+            };
115
+
116
+            max_tiles_to_use -= used_tiles;
106
 
117
 
107
             let mut vertex_data: Vec<f32> = Vec::with_capacity(textured_visible_tiles.len() * (6 * 8));
118
             let mut vertex_data: Vec<f32> = Vec::with_capacity(textured_visible_tiles.len() * (6 * 8));
108
             let scale_x = 2.0 / f64::from(self.viewport_size.0);
119
             let scale_x = 2.0 / f64::from(self.viewport_size.0);
109
             let scale_y = -2.0 / f64::from(self.viewport_size.1);
120
             let scale_y = -2.0 / f64::from(self.viewport_size.1);
110
-            for tvt in textured_visible_tiles {
121
+            for tvt in &textured_visible_tiles {
111
                 let minmax = [
122
                 let minmax = [
112
                     tvt.tex_minmax.x1 as f32,
123
                     tvt.tex_minmax.x1 as f32,
113
                     tvt.tex_minmax.y1 as f32,
124
                     tvt.tex_minmax.y1 as f32,
153
             }
164
             }
154
 
165
 
155
             self.buf.set_data(&vertex_data, vertex_data.len() / 4);
166
             self.buf.set_data(&vertex_data, vertex_data.len() / 4);
156
-        }
167
+            self.buf.draw(DrawMode::Triangles);
168
+
169
+            num_draws += 1;
170
+            debug!("draw #{}: tvt.len() = {}, remainder = {:?}, max_tiles = {}",
171
+                num_draws,
172
+                textured_visible_tiles.len(),
173
+                remainder_opt.map(|r| r.len()),
174
+                max_tiles_to_use);
175
+
176
+            if max_tiles_to_use <= 0 {
177
+                warn!("tile cache is too small for this view.");
178
+                break;
179
+            }
157
 
180
 
158
-        self.cx.clear_color((0.9, 0.9, 0.9, 1.0));
159
-        self.buf.draw(DrawMode::Triangles);
181
+            match remainder_opt {
182
+                None => break,
183
+                Some(new_remainder) => {
184
+                    if new_remainder.len() >= remainder.len() {
185
+                        warn!("failed to draw all tiles. number of remaining tiles did not decrease.");
186
+                        break;
187
+                    } else {
188
+                        remainder = new_remainder;
189
+                    }
190
+                },
191
+            }
192
+        }
160
     }
193
     }
161
 
194
 
162
     pub fn step_zoom(&mut self, steps: i32, step_size: f64) {
195
     pub fn step_zoom(&mut self, steps: i32, step_size: f64) {

+ 5
- 0
src/tile_cache.rs 查看文件

28
         }
28
         }
29
     }
29
     }
30
 
30
 
31
+    // Return the maximum number of tiles that this cache can hold at once.
32
+    pub fn max_tiles(&self) -> usize {
33
+        self.max_tiles
34
+    }
35
+
31
     pub fn get_sync(
36
     pub fn get_sync(
32
         &mut self,
37
         &mut self,
33
         tile_coord: TileCoord,
38
         tile_coord: TileCoord,

+ 27
- 5
src/tile_cache_gl.rs 查看文件

95
         slot
95
         slot
96
     }
96
     }
97
 
97
 
98
-    pub fn textured_visible_tiles(
98
+    /// Finds textures from the cache for a given slice of visible tiles. The texture atlas may not
99
+    /// be big enough to hold all textures at once; a possible remainder of untextured visible tiles is
100
+    /// returned as an `Option`.
101
+    /// The function guarantees that no more than `max_tiles_to_use` tiles are used for texturing;
102
+    /// the number of used tiles is returned as an `usize`.
103
+    pub fn textured_visible_tiles<'b>(
99
         &mut self,
104
         &mut self,
100
-        visible_tiles: &[VisibleTile],
105
+        visible_tiles: &'b [VisibleTile],
106
+        max_tiles_to_use: usize,
101
         source: &TileSource,
107
         source: &TileSource,
102
         cache: &mut TileCache,
108
         cache: &mut TileCache,
103
-        ) -> Vec<TexturedVisibleTile>
109
+        ) -> (Vec<TexturedVisibleTile>, Option<&'b [VisibleTile]>, usize)
104
     {
110
     {
105
         let mut tvt = Vec::with_capacity(visible_tiles.len());
111
         let mut tvt = Vec::with_capacity(visible_tiles.len());
106
 
112
 
107
         let inset_x = 0.5 / f64::from(self.texture.width());
113
         let inset_x = 0.5 / f64::from(self.texture.width());
108
         let inset_y = 0.5 / f64::from(self.texture.height());
114
         let inset_y = 0.5 / f64::from(self.texture.height());
109
 
115
 
110
-        for vt in visible_tiles {
116
+        let num_usable_slots = self.slots_lru.len();
117
+        // The number of actually used slots may be lower, because slots can be used multiple times
118
+        // in the same view (especially the default slot).
119
+        let mut used_slots = 0_usize;
120
+
121
+        for (i, vt) in visible_tiles.iter().enumerate() {
122
+            if used_slots >= num_usable_slots || used_slots >= max_tiles_to_use {
123
+                return (tvt, Some(&visible_tiles[i..]), used_slots);
124
+            }
125
+
111
             if let Some(slot) = self.store(vt.tile, source, cache, true) {
126
             if let Some(slot) = self.store(vt.tile, source, cache, true) {
112
                 let tex_rect = self.slot_to_texture_rect(slot);
127
                 let tex_rect = self.slot_to_texture_rect(slot);
128
+                used_slots += 1;
113
                 tvt.push(
129
                 tvt.push(
114
                     TexturedVisibleTile {
130
                     TexturedVisibleTile {
115
                         screen_rect: vt.rect,
131
                         screen_rect: vt.rect,
120
             } else {
136
             } else {
121
                 // exact tile not found
137
                 // exact tile not found
122
 
138
 
139
+                if used_slots + 5 > num_usable_slots || used_slots + 5 > max_tiles_to_use {
140
+                    return (tvt, Some(&visible_tiles[i..]), used_slots);
141
+                }
142
+
123
                 // default tile
143
                 // default tile
124
                 let mut tex_sub_rect = self.slot_to_texture_rect(Self::default_slot());
144
                 let mut tex_sub_rect = self.slot_to_texture_rect(Self::default_slot());
125
                 let mut tex_rect = tex_sub_rect;
145
                 let mut tex_rect = tex_sub_rect;
128
                 for dist in 1..31 {
148
                 for dist in 1..31 {
129
                     if let Some((parent_tile, sub_coord)) = vt.tile.parent(dist) {
149
                     if let Some((parent_tile, sub_coord)) = vt.tile.parent(dist) {
130
                         if let Some(slot) = self.store(parent_tile, source, cache, false) {
150
                         if let Some(slot) = self.store(parent_tile, source, cache, false) {
151
+                            used_slots += 1;
131
                             tex_sub_rect = self.subslot_to_texture_rect(slot, sub_coord);
152
                             tex_sub_rect = self.subslot_to_texture_rect(slot, sub_coord);
132
                             tex_rect = self.slot_to_texture_rect(slot);
153
                             tex_rect = self.slot_to_texture_rect(slot);
133
                             break;
154
                             break;
140
                 // look for cached tiles in higher zoom layers
161
                 // look for cached tiles in higher zoom layers
141
                 for &(child_tile, child_sub_coord) in &vt.tile.children() {
162
                 for &(child_tile, child_sub_coord) in &vt.tile.children() {
142
                     if let Some(slot) = self.store(child_tile, source, cache, false) {
163
                     if let Some(slot) = self.store(child_tile, source, cache, false) {
164
+                        used_slots += 1;
143
                         let tex_rect = self.slot_to_texture_rect(slot);
165
                         let tex_rect = self.slot_to_texture_rect(slot);
144
 
166
 
145
                         tvt.push(
167
                         tvt.push(
162
             };
184
             };
163
         }
185
         }
164
 
186
 
165
-        tvt
187
+        (tvt, None, used_slots)
166
     }
188
     }
167
 
189
 
168
     fn slot_to_texture_rect(&self, slot: CacheSlot) -> TextureRect {
190
     fn slot_to_texture_rect(&self, slot: CacheSlot) -> TextureRect {