Просмотр исходного кода

Extract code into tile_layer module

Johannes Hofmann 7 лет назад
Родитель
Сommit
13d366fc1d
3 измененных файлов: 221 добавлений и 169 удалений
  1. 1
    0
      src/main.rs
  2. 10
    169
      src/map_view_gl.rs
  3. 210
    0
      src/tile_layer.rs

+ 1
- 0
src/main.rs Просмотреть файл

@@ -30,6 +30,7 @@ pub mod texture;
30 30
 pub mod tile;
31 31
 pub mod tile_atlas;
32 32
 pub mod tile_cache;
33
+pub mod tile_layer;
33 34
 pub mod tile_loader;
34 35
 pub mod tile_source;
35 36
 pub mod url_template;

+ 10
- 169
src/map_view_gl.rs Просмотреть файл

@@ -1,15 +1,9 @@
1
-use ::std::ffi::CStr;
2
-use buffer::{Buffer, DrawMode};
3 1
 use context::Context;
4
-use coord::{MapCoord, ScreenCoord, View};
2
+use coord::{MapCoord, ScreenCoord};
5 3
 use map_view::MapView;
6 4
 use marker_layer::MarkerLayer;
7
-use program::Program;
8
-use texture::{Texture, TextureFormat};
9
-use tile_atlas::TileAtlas;
10
-use tile_cache::TileCache;
5
+use tile_layer::TileLayer;
11 6
 use tile_source::TileSource;
12
-use vertex_attrib::VertexAttribParams;
13 7
 
14 8
 
15 9
 const MIN_ZOOM_LEVEL: f64 = 0.0;
@@ -19,10 +13,7 @@ const MAX_ZOOM_LEVEL: f64 = 22.0;
19 13
 pub struct MapViewGl {
20 14
     map_view: MapView,
21 15
     viewport_size: (u32, u32),
22
-    tile_program: Program,
23
-    tile_buffer: Buffer,
24
-    tile_cache: TileCache,
25
-    tile_atlas: TileAtlas,
16
+    tile_layer: TileLayer,
26 17
     marker_layer: MarkerLayer,
27 18
     last_draw_type: DrawType,
28 19
 }
@@ -52,61 +43,10 @@ impl MapViewGl {
52 43
             map_view.zoom = MIN_ZOOM_LEVEL;
53 44
         }
54 45
 
55
-        let tile_buffer = Buffer::new(cx, &[], 0);
56
-        check_gl_errors!(cx);
57
-        cx.bind_buffer(tile_buffer.id());
58
-
59
-        let mut tile_program = Program::new(
60
-            cx,
61
-            include_bytes!("../shader/map.vert"),
62
-            include_bytes!("../shader/map.frag"),
63
-        ).unwrap();
64
-        check_gl_errors!(cx);
65
-
66
-        let atlas_size = {
67
-            let default_size = 2048;
68
-            let max_size = cx.max_texture_size() as u32;
69
-            if default_size <= max_size {
70
-                default_size
71
-            } else {
72
-                if tile_size * 3 > max_size {
73
-                    error!("maximal tile size ({}) is too small", max_size);
74
-                }
75
-
76
-                max_size
77
-            }
78
-        };
79
-
80
-        let atlas_tex = Texture::empty(cx, atlas_size, atlas_size, TextureFormat::Rgb8);
81
-        check_gl_errors!(cx);
82
-
83
-        tile_program.add_texture(cx, &atlas_tex, CStr::from_bytes_with_nul(b"tex_map\0").unwrap());
84
-        check_gl_errors!(cx);
85
-
86
-        tile_program.add_attribute(
87
-            cx,
88
-            CStr::from_bytes_with_nul(b"position\0").unwrap(),
89
-            &VertexAttribParams::new(2, 8, 0)
90
-        );
91
-        tile_program.add_attribute(
92
-            cx,
93
-            CStr::from_bytes_with_nul(b"tex_coord\0").unwrap(),
94
-            &VertexAttribParams::new(2, 8, 2)
95
-        );
96
-        tile_program.add_attribute(
97
-            cx,
98
-            CStr::from_bytes_with_nul(b"tex_minmax\0").unwrap(),
99
-            &VertexAttribParams::new(4, 8, 4)
100
-        );
101
-        check_gl_errors!(cx);
102
-
103 46
         MapViewGl {
104 47
             map_view,
105 48
             viewport_size: initial_size,
106
-            tile_program,
107
-            tile_buffer,
108
-            tile_cache: TileCache::new(move |_tile| update_func(), use_network),
109
-            tile_atlas: TileAtlas::new(cx, atlas_tex, 256, use_async),
49
+            tile_layer: TileLayer::new(cx, move |_| update_func(), tile_size, use_network, use_async),
110 50
             marker_layer: MarkerLayer::new(cx),
111 51
             last_draw_type: DrawType::Null,
112 52
         }
@@ -127,117 +67,18 @@ impl MapViewGl {
127 67
     }
128 68
 
129 69
     pub fn increase_atlas_size(&mut self, cx: &mut Context) -> Result<(), ()> {
130
-        self.tile_atlas.double_texture_size(cx)
70
+        self.tile_layer.double_atlas_size(cx)
131 71
     }
132 72
 
133
-    fn draw_tiles(&mut self, cx: &mut Context, source: &TileSource, snap_to_pixel: bool) -> Result<usize, usize> {
73
+    fn draw_tiles(&mut self, cx: &mut Context, source: &TileSource, snap_to_pixel: bool)
74
+        -> Result<usize, usize>
75
+    {
134 76
         if self.last_draw_type != DrawType::Tiles {
135 77
             self.last_draw_type = DrawType::Tiles;
136
-            self.tile_program.enable_vertex_attribs(cx);
137
-            self.tile_program.set_vertex_attribs(cx, &self.tile_buffer);
138
-            cx.set_active_texture_unit(self.tile_atlas.texture().unit());
78
+            self.tile_layer.prepare_draw(cx);
139 79
         }
140 80
 
141
-        self.tile_cache.set_view_location(View {
142
-            source_id: source.id(),
143
-            zoom: self.map_view.tile_zoom(),
144
-            center: self.map_view.center,
145
-        });
146
-
147
-        let visible_tiles = self.map_view.visible_tiles(snap_to_pixel);
148
-        let mut remainder = visible_tiles.as_slice();
149
-        let mut num_draws = 0;
150
-        let mut max_tiles_to_use = self.tile_cache.max_tiles();
151
-
152
-        loop {
153
-            let (textured_visible_tiles, remainder_opt, used_tiles) = {
154
-                self.tile_atlas.textured_visible_tiles(
155
-                    cx,
156
-                    remainder,
157
-                    max_tiles_to_use,
158
-                    source,
159
-                    &mut self.tile_cache,
160
-                )
161
-            };
162
-
163
-            max_tiles_to_use -= used_tiles;
164
-
165
-            let mut vertex_data: Vec<f32> = Vec::with_capacity(textured_visible_tiles.len() * (6 * 8));
166
-            let scale_x = 2.0 / f64::from(self.viewport_size.0);
167
-            let scale_y = -2.0 / f64::from(self.viewport_size.1);
168
-            for tvt in &textured_visible_tiles {
169
-                let minmax = [
170
-                    tvt.tex_minmax.x1 as f32,
171
-                    tvt.tex_minmax.y1 as f32,
172
-                    tvt.tex_minmax.x2 as f32,
173
-                    tvt.tex_minmax.y2 as f32,
174
-                ];
175
-                let p1 = [
176
-                    (tvt.screen_rect.x * scale_x - 1.0) as f32,
177
-                    (tvt.screen_rect.y * scale_y + 1.0) as f32,
178
-                    tvt.tex_rect.x1 as f32,
179
-                    tvt.tex_rect.y1 as f32,
180
-                ];
181
-                let p2 = [
182
-                    (tvt.screen_rect.x * scale_x - 1.0) as f32,
183
-                    ((tvt.screen_rect.y + tvt.screen_rect.height) * scale_y + 1.0) as f32,
184
-                    tvt.tex_rect.x1 as f32,
185
-                    tvt.tex_rect.y2 as f32,
186
-                ];
187
-                let p3 = [
188
-                    ((tvt.screen_rect.x + tvt.screen_rect.width) * scale_x - 1.0) as f32,
189
-                    ((tvt.screen_rect.y + tvt.screen_rect.height) * scale_y + 1.0) as f32,
190
-                    tvt.tex_rect.x2 as f32,
191
-                    tvt.tex_rect.y2 as f32,
192
-                ];
193
-                let p4 = [
194
-                    ((tvt.screen_rect.x + tvt.screen_rect.width) * scale_x - 1.0) as f32,
195
-                    (tvt.screen_rect.y * scale_y + 1.0) as f32,
196
-                    tvt.tex_rect.x2 as f32,
197
-                    tvt.tex_rect.y1 as f32,
198
-                ];
199
-                vertex_data.extend(&p1);
200
-                vertex_data.extend(&minmax);
201
-                vertex_data.extend(&p2);
202
-                vertex_data.extend(&minmax);
203
-                vertex_data.extend(&p3);
204
-                vertex_data.extend(&minmax);
205
-                vertex_data.extend(&p1);
206
-                vertex_data.extend(&minmax);
207
-                vertex_data.extend(&p3);
208
-                vertex_data.extend(&minmax);
209
-                vertex_data.extend(&p4);
210
-                vertex_data.extend(&minmax);
211
-            }
212
-
213
-            self.tile_buffer.set_data(cx, &vertex_data, vertex_data.len() / 4);
214
-            self.tile_buffer.draw(cx, &self.tile_program, DrawMode::Triangles);
215
-
216
-            num_draws += 1;
217
-
218
-            debug!("draw #{}: tvt.len() = {}, remainder = {:?}, max_tiles = {}",
219
-                num_draws,
220
-                textured_visible_tiles.len(),
221
-                remainder_opt.map(|r| r.len()),
222
-                max_tiles_to_use);
223
-
224
-            if max_tiles_to_use == 0 {
225
-                warn!("tile cache is too small for this view.");
226
-                return Err(num_draws);
227
-            }
228
-
229
-            match remainder_opt {
230
-                None => return Ok(num_draws),
231
-                Some(new_remainder) => {
232
-                    if new_remainder.len() >= remainder.len() {
233
-                        warn!("failed to draw all tiles. number of remaining tiles did not decrease.");
234
-                        return Err(num_draws);
235
-                    } else {
236
-                        remainder = new_remainder;
237
-                    }
238
-                },
239
-            }
240
-        }
81
+        self.tile_layer.draw(cx, &self.map_view, source, self.viewport_size, snap_to_pixel)
241 82
     }
242 83
 
243 84
     fn draw_marker(&mut self, cx: &mut Context, snap_to_pixel: bool) {

+ 210
- 0
src/tile_layer.rs Просмотреть файл

@@ -0,0 +1,210 @@
1
+use ::std::ffi::CStr;
2
+use buffer::{Buffer, DrawMode};
3
+use context::Context;
4
+use coord::View;
5
+use map_view::MapView;
6
+use program::Program;
7
+use texture::{Texture, TextureFormat};
8
+use tile::Tile;
9
+use tile_atlas::TileAtlas;
10
+use tile_cache::TileCache;
11
+use tile_source::TileSource;
12
+use vertex_attrib::VertexAttribParams;
13
+
14
+
15
+#[derive(Debug)]
16
+pub struct TileLayer {
17
+    program: Program,
18
+    buffer: Buffer,
19
+    cache: TileCache,
20
+    atlas: TileAtlas,
21
+}
22
+
23
+
24
+impl TileLayer {
25
+    pub fn new<F>(
26
+        cx: &mut Context,
27
+        update_func: F,
28
+        tile_size: u32,
29
+        use_network: bool,
30
+        use_async: bool,
31
+    ) -> TileLayer
32
+        where F: Fn(Tile) + Sync + Send + 'static,
33
+    {
34
+        let buffer = Buffer::new(cx, &[], 0);
35
+        check_gl_errors!(cx);
36
+        cx.bind_buffer(buffer.id());
37
+
38
+        let mut program = Program::new(
39
+            cx,
40
+            include_bytes!("../shader/map.vert"),
41
+            include_bytes!("../shader/map.frag"),
42
+        ).unwrap();
43
+        check_gl_errors!(cx);
44
+
45
+        let atlas_size = {
46
+            let default_size = 2048;
47
+            let max_size = cx.max_texture_size() as u32;
48
+            if default_size <= max_size {
49
+                default_size
50
+            } else {
51
+                if tile_size * 3 > max_size {
52
+                    error!("maximal tile size ({}) is too small", max_size);
53
+                }
54
+
55
+                max_size
56
+            }
57
+        };
58
+
59
+        let atlas_tex = Texture::empty(cx, atlas_size, atlas_size, TextureFormat::Rgb8);
60
+        check_gl_errors!(cx);
61
+
62
+        program.add_texture(cx, &atlas_tex, CStr::from_bytes_with_nul(b"tex_map\0").unwrap());
63
+        check_gl_errors!(cx);
64
+
65
+        program.add_attribute(
66
+            cx,
67
+            CStr::from_bytes_with_nul(b"position\0").unwrap(),
68
+            &VertexAttribParams::new(2, 8, 0)
69
+        );
70
+        program.add_attribute(
71
+            cx,
72
+            CStr::from_bytes_with_nul(b"tex_coord\0").unwrap(),
73
+            &VertexAttribParams::new(2, 8, 2)
74
+        );
75
+        program.add_attribute(
76
+            cx,
77
+            CStr::from_bytes_with_nul(b"tex_minmax\0").unwrap(),
78
+            &VertexAttribParams::new(4, 8, 4)
79
+        );
80
+        check_gl_errors!(cx);
81
+
82
+        TileLayer {
83
+            program,
84
+            buffer,
85
+            cache: TileCache::new(update_func, use_network),
86
+            atlas: TileAtlas::new(cx, atlas_tex, 256, use_async),
87
+        }
88
+    }
89
+
90
+    pub fn double_atlas_size(&mut self, cx: &mut Context) -> Result<(), ()> {
91
+        self.atlas.double_texture_size(cx)
92
+    }
93
+
94
+    // Has to be called once before one or multiple calls to `draw`.
95
+    pub fn prepare_draw(&mut self, cx: &mut Context) {
96
+        self.program.enable_vertex_attribs(cx);
97
+        self.program.set_vertex_attribs(cx, &self.buffer);
98
+        cx.set_active_texture_unit(self.atlas.texture().unit());
99
+    }
100
+
101
+    pub fn draw(
102
+        &mut self,
103
+        cx: &mut Context,
104
+        map_view: &MapView,
105
+        source: &TileSource,
106
+        viewport_size: (u32, u32),
107
+        snap_to_pixel: bool
108
+    ) -> Result<usize, usize> {
109
+        self.cache.set_view_location(View {
110
+            source_id: source.id(),
111
+            zoom: map_view.tile_zoom(),
112
+            center: map_view.center,
113
+        });
114
+
115
+        let visible_tiles = map_view.visible_tiles(snap_to_pixel);
116
+        let mut remainder = visible_tiles.as_slice();
117
+        let mut num_draws = 0;
118
+        let mut max_tiles_to_use = self.cache.max_tiles();
119
+
120
+        loop {
121
+            let (textured_visible_tiles, remainder_opt, used_tiles) = {
122
+                self.atlas.textured_visible_tiles(
123
+                    cx,
124
+                    remainder,
125
+                    max_tiles_to_use,
126
+                    source,
127
+                    &mut self.cache,
128
+                )
129
+            };
130
+
131
+            max_tiles_to_use -= used_tiles;
132
+
133
+            let mut vertex_data: Vec<f32> = Vec::with_capacity(textured_visible_tiles.len() * (6 * 8));
134
+            let scale_x = 2.0 / f64::from(viewport_size.0);
135
+            let scale_y = -2.0 / f64::from(viewport_size.1);
136
+            for tvt in &textured_visible_tiles {
137
+                let minmax = [
138
+                    tvt.tex_minmax.x1 as f32,
139
+                    tvt.tex_minmax.y1 as f32,
140
+                    tvt.tex_minmax.x2 as f32,
141
+                    tvt.tex_minmax.y2 as f32,
142
+                ];
143
+                let p1 = [
144
+                    (tvt.screen_rect.x * scale_x - 1.0) as f32,
145
+                    (tvt.screen_rect.y * scale_y + 1.0) as f32,
146
+                    tvt.tex_rect.x1 as f32,
147
+                    tvt.tex_rect.y1 as f32,
148
+                ];
149
+                let p2 = [
150
+                    (tvt.screen_rect.x * scale_x - 1.0) as f32,
151
+                    ((tvt.screen_rect.y + tvt.screen_rect.height) * scale_y + 1.0) as f32,
152
+                    tvt.tex_rect.x1 as f32,
153
+                    tvt.tex_rect.y2 as f32,
154
+                ];
155
+                let p3 = [
156
+                    ((tvt.screen_rect.x + tvt.screen_rect.width) * scale_x - 1.0) as f32,
157
+                    ((tvt.screen_rect.y + tvt.screen_rect.height) * scale_y + 1.0) as f32,
158
+                    tvt.tex_rect.x2 as f32,
159
+                    tvt.tex_rect.y2 as f32,
160
+                ];
161
+                let p4 = [
162
+                    ((tvt.screen_rect.x + tvt.screen_rect.width) * scale_x - 1.0) as f32,
163
+                    (tvt.screen_rect.y * scale_y + 1.0) as f32,
164
+                    tvt.tex_rect.x2 as f32,
165
+                    tvt.tex_rect.y1 as f32,
166
+                ];
167
+                vertex_data.extend(&p1);
168
+                vertex_data.extend(&minmax);
169
+                vertex_data.extend(&p2);
170
+                vertex_data.extend(&minmax);
171
+                vertex_data.extend(&p3);
172
+                vertex_data.extend(&minmax);
173
+                vertex_data.extend(&p1);
174
+                vertex_data.extend(&minmax);
175
+                vertex_data.extend(&p3);
176
+                vertex_data.extend(&minmax);
177
+                vertex_data.extend(&p4);
178
+                vertex_data.extend(&minmax);
179
+            }
180
+
181
+            self.buffer.set_data(cx, &vertex_data, vertex_data.len() / 4);
182
+            self.buffer.draw(cx, &self.program, DrawMode::Triangles);
183
+
184
+            num_draws += 1;
185
+
186
+            debug!("draw #{}: tvt.len() = {}, remainder = {:?}, max_tiles = {}",
187
+                num_draws,
188
+                textured_visible_tiles.len(),
189
+                remainder_opt.map(|r| r.len()),
190
+                max_tiles_to_use);
191
+
192
+            if max_tiles_to_use == 0 {
193
+                warn!("tile cache is too small for this view.");
194
+                return Err(num_draws);
195
+            }
196
+
197
+            match remainder_opt {
198
+                None => return Ok(num_draws),
199
+                Some(new_remainder) => {
200
+                    if new_remainder.len() >= remainder.len() {
201
+                        warn!("failed to draw all tiles. number of remaining tiles did not decrease.");
202
+                        return Err(num_draws);
203
+                    } else {
204
+                        remainder = new_remainder;
205
+                    }
206
+                },
207
+            }
208
+        }
209
+    }
210
+}