浏览代码

Restructure OpenGL context sharing

Program, Buffer, Texture... structs no longer store a reference to a
Context. Now it has to be passed explicitly to all methods that mutate
the OpenGL state. This enables caching the state and removing redundant
calls to gl* functions.
Johannes Hofmann 7 年前
父节点
当前提交
38d1cf35e5
共有 6 个文件被更改,包括 83 次插入91 次删除
  1. 9
    11
      src/buffer.rs
  2. 7
    7
      src/main.rs
  3. 20
    21
      src/map_view_gl.rs
  4. 17
    19
      src/program.rs
  5. 12
    18
      src/texture.rs
  6. 18
    15
      src/tile_atlas.rs

+ 9
- 11
src/buffer.rs 查看文件

4
 
4
 
5
 
5
 
6
 #[derive(Clone, Debug)]
6
 #[derive(Clone, Debug)]
7
-pub struct Buffer<'a> {
8
-    cx: &'a Context,
7
+pub struct Buffer {
9
     buffer_obj: u32,
8
     buffer_obj: u32,
10
     num_elements: usize,
9
     num_elements: usize,
11
 }
10
 }
27
     }
26
     }
28
 }
27
 }
29
 
28
 
30
-impl<'a> Buffer<'a> {
31
-    pub fn new(cx: &'a Context, vertex_data: &[f32], num_elements: usize) -> Buffer<'a> {
29
+impl Buffer {
30
+    pub fn new(cx: &mut Context, vertex_data: &[f32], num_elements: usize) -> Buffer {
32
         let mut buffer_obj = 0_u32;
31
         let mut buffer_obj = 0_u32;
33
 
32
 
34
         unsafe {
33
         unsafe {
41
         }
40
         }
42
 
41
 
43
         Buffer {
42
         Buffer {
44
-            cx,
45
             buffer_obj,
43
             buffer_obj,
46
             num_elements,
44
             num_elements,
47
         }
45
         }
48
     }
46
     }
49
 
47
 
50
-    pub fn set_data(&mut self, vertex_data: &[f32], num_elements: usize) {
48
+    pub fn set_data(&mut self, cx: &mut Context, vertex_data: &[f32], num_elements: usize) {
51
         unsafe {
49
         unsafe {
52
-            self.cx.gl.BufferData(context::gl::ARRAY_BUFFER,
50
+            cx.gl.BufferData(context::gl::ARRAY_BUFFER,
53
                                   (vertex_data.len() * mem::size_of::<f32>()) as context::gl::types::GLsizeiptr,
51
                                   (vertex_data.len() * mem::size_of::<f32>()) as context::gl::types::GLsizeiptr,
54
                                   vertex_data.as_ptr() as *const _,
52
                                   vertex_data.as_ptr() as *const _,
55
                                   context::gl::DYNAMIC_DRAW);
53
                                   context::gl::DYNAMIC_DRAW);
57
         self.num_elements = num_elements;
55
         self.num_elements = num_elements;
58
     }
56
     }
59
 
57
 
60
-    pub fn bind(&self) {
58
+    pub fn bind(&self, cx: &mut Context) {
61
         unsafe {
59
         unsafe {
62
-            self.cx.gl.BindBuffer(context::gl::ARRAY_BUFFER, self.buffer_obj);
60
+            cx.gl.BindBuffer(context::gl::ARRAY_BUFFER, self.buffer_obj);
63
         }
61
         }
64
     }
62
     }
65
 
63
 
66
-    pub fn draw(&self, mode: DrawMode) {
64
+    pub fn draw(&self, cx: &mut Context, mode: DrawMode) {
67
         unsafe {
65
         unsafe {
68
-            self.cx.gl.DrawArrays(
66
+            cx.gl.DrawArrays(
69
                 mode.to_gl_enum(),
67
                 mode.to_gl_enum(),
70
                 0,
68
                 0,
71
                 self.num_elements as context::gl::types::GLsizei);
69
                 self.num_elements as context::gl::types::GLsizei);

+ 7
- 7
src/main.rs 查看文件

206
     let window = gl_window.window();
206
     let window = gl_window.window();
207
 
207
 
208
     let _ = unsafe { gl_window.make_current() };
208
     let _ = unsafe { gl_window.make_current() };
209
-    let cx = context::Context::from_gl_window(&gl_window);
209
+    let mut cx = context::Context::from_gl_window(&gl_window);
210
 
210
 
211
     let mut map = {
211
     let mut map = {
212
         let proxy = events_loop.create_proxy();
212
         let proxy = events_loop.create_proxy();
213
 
213
 
214
         map_view_gl::MapViewGl::new(
214
         map_view_gl::MapViewGl::new(
215
-            &cx,
215
+            &mut cx,
216
             window.get_inner_size().unwrap(),
216
             window.get_inner_size().unwrap(),
217
             move || { proxy.wakeup().unwrap(); },
217
             move || { proxy.wakeup().unwrap(); },
218
             config.use_network(),
218
             config.use_network(),
282
 
282
 
283
         if let Action::Resize(w, h) = action {
283
         if let Action::Resize(w, h) = action {
284
             gl_window.resize(w, h);
284
             gl_window.resize(w, h);
285
-            map.set_viewport_size(w, h);
285
+            map.set_viewport_size(&mut cx, w, h);
286
         }
286
         }
287
 
287
 
288
         let redraw = match action {
288
         let redraw = match action {
297
             if !map.viewport_in_map() {
297
             if !map.viewport_in_map() {
298
                 cx.clear_color((0.2, 0.2, 0.2, 1.0));
298
                 cx.clear_color((0.2, 0.2, 0.2, 1.0));
299
             }
299
             }
300
-            let draw_result = map.draw(sources.current());
300
+            let draw_result = map.draw(&mut cx, sources.current());
301
 
301
 
302
             let draw_dur = draw_start.elapsed();
302
             let draw_dur = draw_start.elapsed();
303
 
303
 
304
 
304
 
305
             let _ = gl_window.swap_buffers();
305
             let _ = gl_window.swap_buffers();
306
 
306
 
307
+            last_draw = Instant::now();
308
+
307
             //TODO increase atlas size earlier to avoid excessive copying to the GPU
309
             //TODO increase atlas size earlier to avoid excessive copying to the GPU
308
             //TODO increase max tile cache size?
310
             //TODO increase max tile cache size?
309
             if increase_atlas_size_possible {
311
             if increase_atlas_size_possible {
312
                     Err(x) => x,
314
                     Err(x) => x,
313
                 };
315
                 };
314
                 if draws > 1 {
316
                 if draws > 1 {
315
-                    increase_atlas_size_possible = map.increase_atlas_size().is_ok();
317
+                    increase_atlas_size_possible = map.increase_atlas_size(&mut cx).is_ok();
316
                 }
318
                 }
317
             }
319
             }
318
 
320
 
319
-            last_draw = Instant::now();
320
-
321
             debug!("draw: {} sec (est {} sec)", dur_to_sec(draw_dur), dur_to_sec(est_draw_dur));
321
             debug!("draw: {} sec (est {} sec)", dur_to_sec(draw_dur), dur_to_sec(est_draw_dur));
322
 
322
 
323
             est_draw_dur = if draw_dur > est_draw_dur {
323
             est_draw_dur = if draw_dur > est_draw_dur {

+ 20
- 21
src/map_view_gl.rs 查看文件

14
 const MAX_ZOOM_LEVEL: f64 = 22.0;
14
 const MAX_ZOOM_LEVEL: f64 = 22.0;
15
 
15
 
16
 #[derive(Debug)]
16
 #[derive(Debug)]
17
-pub struct MapViewGl<'a> {
18
-    cx: &'a Context,
19
-    program: Program<'a>,
20
-    buf: Buffer<'a>,
17
+pub struct MapViewGl {
18
+    program: Program,
19
+    buf: Buffer,
21
     viewport_size: (u32, u32),
20
     viewport_size: (u32, u32),
22
     map_view: MapView,
21
     map_view: MapView,
23
     tile_cache: TileCache,
22
     tile_cache: TileCache,
24
-    tile_atlas: TileAtlas<'a>,
23
+    tile_atlas: TileAtlas,
25
 }
24
 }
26
 
25
 
27
-impl<'a> MapViewGl<'a> {
26
+impl MapViewGl {
28
     pub fn new<F>(
27
     pub fn new<F>(
29
-        cx: &Context,
28
+        cx: &mut Context,
30
         initial_size: (u32, u32),
29
         initial_size: (u32, u32),
31
         update_func: F,
30
         update_func: F,
32
         use_network: bool,
31
         use_network: bool,
63
         let buf = Buffer::new(cx, &[], 0);
62
         let buf = Buffer::new(cx, &[], 0);
64
         check_gl_errors!(cx);
63
         check_gl_errors!(cx);
65
 
64
 
66
-        program.add_texture(&tex, CStr::from_bytes_with_nul(b"tex_map\0").unwrap());
65
+        program.add_texture(cx, &tex, CStr::from_bytes_with_nul(b"tex_map\0").unwrap());
67
         check_gl_errors!(cx);
66
         check_gl_errors!(cx);
68
 
67
 
69
-        program.add_attribute(CStr::from_bytes_with_nul(b"position\0").unwrap(), 2, 8, 0);
70
-        program.add_attribute(CStr::from_bytes_with_nul(b"tex_coord\0").unwrap(), 2, 8, 2);
71
-        program.add_attribute(CStr::from_bytes_with_nul(b"tex_minmax\0").unwrap(), 4, 8, 4);
68
+        program.add_attribute(cx, CStr::from_bytes_with_nul(b"position\0").unwrap(), 2, 8, 0);
69
+        program.add_attribute(cx, CStr::from_bytes_with_nul(b"tex_coord\0").unwrap(), 2, 8, 2);
70
+        program.add_attribute(cx, CStr::from_bytes_with_nul(b"tex_minmax\0").unwrap(), 4, 8, 4);
72
         check_gl_errors!(cx);
71
         check_gl_errors!(cx);
73
 
72
 
74
-        program.before_render();
73
+        program.before_render(cx);
75
 
74
 
76
         let mut map_view = MapView::with_filling_zoom(f64::from(initial_size.0), f64::from(initial_size.1), tile_size);
75
         let mut map_view = MapView::with_filling_zoom(f64::from(initial_size.0), f64::from(initial_size.1), tile_size);
77
 
76
 
80
         }
79
         }
81
 
80
 
82
         MapViewGl {
81
         MapViewGl {
83
-            cx,
84
             program,
82
             program,
85
             buf,
83
             buf,
86
             viewport_size: initial_size,
84
             viewport_size: initial_size,
87
             map_view,
85
             map_view,
88
             tile_cache: TileCache::new(move |_tile| update_func(), use_network),
86
             tile_cache: TileCache::new(move |_tile| update_func(), use_network),
89
-            tile_atlas: TileAtlas::new(tex, 256, use_async),
87
+            tile_atlas: TileAtlas::new(cx, tex, 256, use_async),
90
         }
88
         }
91
     }
89
     }
92
 
90
 
93
-    pub fn set_viewport_size(&mut self, width: u32, height: u32) {
91
+    pub fn set_viewport_size(&mut self, cx: &mut Context, width: u32, height: u32) {
94
         self.viewport_size = (width, height);
92
         self.viewport_size = (width, height);
95
         self.map_view.set_size(f64::from(width), f64::from(height));
93
         self.map_view.set_size(f64::from(width), f64::from(height));
96
-        self.cx.set_viewport(0, 0, width, height);
94
+        cx.set_viewport(0, 0, width, height);
97
     }
95
     }
98
 
96
 
99
     pub fn viewport_in_map(&self) -> bool {
97
     pub fn viewport_in_map(&self) -> bool {
100
         self.map_view.viewport_in_map()
98
         self.map_view.viewport_in_map()
101
     }
99
     }
102
 
100
 
103
-    pub fn increase_atlas_size(&mut self) -> Result<(), ()> {
104
-        self.tile_atlas.double_texture_size()
101
+    pub fn increase_atlas_size(&mut self, cx: &mut Context) -> Result<(), ()> {
102
+        self.tile_atlas.double_texture_size(cx)
105
     }
103
     }
106
 
104
 
107
     /// Returns `Err` when tile cache is too small for this view.
105
     /// Returns `Err` when tile cache is too small for this view.
108
     /// Returns the number of OpenGL draw calls, which can be decreased to `1` by increasing the
106
     /// Returns the number of OpenGL draw calls, which can be decreased to `1` by increasing the
109
     /// size of the tile atlas.
107
     /// size of the tile atlas.
110
-    pub fn draw(&mut self, source: &TileSource) -> Result<usize, usize> {
108
+    pub fn draw(&mut self, cx: &mut Context, source: &TileSource) -> Result<usize, usize> {
111
         self.tile_cache.set_view_location(View {
109
         self.tile_cache.set_view_location(View {
112
             source_id: source.id(),
110
             source_id: source.id(),
113
             zoom: self.map_view.tile_zoom(),
111
             zoom: self.map_view.tile_zoom(),
122
         loop {
120
         loop {
123
             let (textured_visible_tiles, remainder_opt, used_tiles) = {
121
             let (textured_visible_tiles, remainder_opt, used_tiles) = {
124
                 self.tile_atlas.textured_visible_tiles(
122
                 self.tile_atlas.textured_visible_tiles(
123
+                    cx,
125
                     remainder,
124
                     remainder,
126
                     max_tiles_to_use,
125
                     max_tiles_to_use,
127
                     source,
126
                     source,
179
                 vertex_data.extend(&minmax);
178
                 vertex_data.extend(&minmax);
180
             }
179
             }
181
 
180
 
182
-            self.buf.set_data(&vertex_data, vertex_data.len() / 4);
183
-            self.buf.draw(DrawMode::Triangles);
181
+            self.buf.set_data(cx, &vertex_data, vertex_data.len() / 4);
182
+            self.buf.draw(cx, DrawMode::Triangles);
184
 
183
 
185
             num_draws += 1;
184
             num_draws += 1;
186
 
185
 

+ 17
- 19
src/program.rs 查看文件

10
 
10
 
11
 
11
 
12
 #[derive(Clone, Debug)]
12
 #[derive(Clone, Debug)]
13
-pub struct Program<'a> {
14
-    cx: &'a ::context::Context,
13
+pub struct Program {
15
     vert_obj: u32,
14
     vert_obj: u32,
16
     frag_obj: u32,
15
     frag_obj: u32,
17
     program_obj: u32,
16
     program_obj: u32,
24
     id: u32,
23
     id: u32,
25
 }
24
 }
26
 
25
 
27
-impl<'a> Program<'a> {
28
-    pub fn from_paths<P: AsRef<Path>>(cx: &'a Context, vert_path: P, frag_path: P) -> Result<Program<'a>, String> {
26
+impl Program {
27
+    pub fn from_paths<P: AsRef<Path>>(cx: &mut Context, vert_path: P, frag_path: P) -> Result<Program, String> {
29
         let vert_src = {
28
         let vert_src = {
30
             let file = File::open(&vert_path)
29
             let file = File::open(&vert_path)
31
                 .map_err(|e| format!("{}", e))?;
30
                 .map_err(|e| format!("{}", e))?;
49
         Self::new(cx, &vert_src, &frag_src)
48
         Self::new(cx, &vert_src, &frag_src)
50
     }
49
     }
51
 
50
 
52
-    pub fn new(cx: &'a Context, vert_src: &[u8], frag_src: &[u8]) -> Result<Program<'a>, String> {
51
+    pub fn new(cx: &mut Context, vert_src: &[u8], frag_src: &[u8]) -> Result<Program, String> {
53
         unsafe {
52
         unsafe {
54
             let vert_obj = {
53
             let vert_obj = {
55
                 let vert_obj = cx.gl.CreateShader(context::gl::VERTEX_SHADER);
54
                 let vert_obj = cx.gl.CreateShader(context::gl::VERTEX_SHADER);
92
             };
91
             };
93
 
92
 
94
             Ok(Program {
93
             Ok(Program {
95
-                cx,
96
                 vert_obj,
94
                 vert_obj,
97
                 frag_obj,
95
                 frag_obj,
98
                 program_obj,
96
                 program_obj,
102
         }
100
         }
103
     }
101
     }
104
 
102
 
105
-    pub fn add_texture(&mut self, texture: &Texture, uniform_name: &CStr) {
103
+    pub fn add_texture(&mut self, cx: &mut Context, texture: &Texture, uniform_name: &CStr) {
106
         //TODO store reference to texture
104
         //TODO store reference to texture
107
         unsafe {
105
         unsafe {
108
-            let tex_loc = self.cx.gl.GetUniformLocation(self.program_obj, uniform_name.as_ptr() as *const _);
109
-            check_gl_errors!(self.cx);
106
+            let tex_loc = cx.gl.GetUniformLocation(self.program_obj, uniform_name.as_ptr() as *const _);
107
+            check_gl_errors!(cx);
110
 
108
 
111
             self.tex_ids.push(texture.id());
109
             self.tex_ids.push(texture.id());
112
             self.tex_locations.push(tex_loc);
110
             self.tex_locations.push(tex_loc);
113
         }
111
         }
114
     }
112
     }
115
 
113
 
116
-    pub fn add_attribute(&mut self, name: &CStr, number_components: u32, stride: usize, offset: usize) {
114
+    pub fn add_attribute(&mut self, cx: &mut Context, name: &CStr, number_components: u32, stride: usize, offset: usize) {
117
         unsafe {
115
         unsafe {
118
-            let attrib_id = self.cx.gl.GetAttribLocation(self.program_obj, name.as_ptr() as *const _);
119
-            self.cx.gl.VertexAttribPointer(
116
+            let attrib_id = cx.gl.GetAttribLocation(self.program_obj, name.as_ptr() as *const _);
117
+            cx.gl.VertexAttribPointer(
120
                 attrib_id as u32,
118
                 attrib_id as u32,
121
                 number_components as i32, // size
119
                 number_components as i32, // size
122
                 context::gl::FLOAT, // type
120
                 context::gl::FLOAT, // type
123
                 0, // normalized
121
                 0, // normalized
124
                 (stride * mem::size_of::<f32>()) as context::gl::types::GLsizei,
122
                 (stride * mem::size_of::<f32>()) as context::gl::types::GLsizei,
125
                 (offset * mem::size_of::<f32>()) as *const () as *const _);
123
                 (offset * mem::size_of::<f32>()) as *const () as *const _);
126
-            self.cx.gl.EnableVertexAttribArray(attrib_id as u32);
124
+            cx.gl.EnableVertexAttribArray(attrib_id as u32);
127
         }
125
         }
128
-        check_gl_errors!(self.cx);
126
+        check_gl_errors!(cx);
129
     }
127
     }
130
 
128
 
131
-    pub fn before_render(&self) {
129
+    pub fn before_render(&self, cx: &mut Context) {
132
         unsafe {
130
         unsafe {
133
-            //self.cx.gl.UseProgram(self.program_obj);
131
+            //cx.gl.UseProgram(self.program_obj);
134
             //TODO check max texture number
132
             //TODO check max texture number
135
             for (i, (tex_id, &tex_loc)) in self.tex_ids.iter().zip(&self.tex_locations).enumerate() {
133
             for (i, (tex_id, &tex_loc)) in self.tex_ids.iter().zip(&self.tex_locations).enumerate() {
136
-                self.cx.gl.ActiveTexture(context::gl::TEXTURE0 + i as u32);
137
-                self.cx.gl.BindTexture(context::gl::TEXTURE_2D, tex_id.id);
138
-                self.cx.gl.Uniform1i(tex_loc, i as i32);
134
+                cx.gl.ActiveTexture(context::gl::TEXTURE0 + i as u32);
135
+                cx.gl.BindTexture(context::gl::TEXTURE_2D, tex_id.id);
136
+                cx.gl.Uniform1i(tex_loc, i as i32);
139
             }
137
             }
140
         }
138
         }
141
     }
139
     }

+ 12
- 18
src/texture.rs 查看文件

5
 use std::os::raw::c_void;
5
 use std::os::raw::c_void;
6
 
6
 
7
 #[derive(Clone, Debug)]
7
 #[derive(Clone, Debug)]
8
-pub struct Texture<'a> {
9
-    cx: &'a Context,
8
+pub struct Texture {
10
     texture_obj: u32,
9
     texture_obj: u32,
11
     width: u32,
10
     width: u32,
12
     height: u32,
11
     height: u32,
18
     pub(crate) id: u32,
17
     pub(crate) id: u32,
19
 }
18
 }
20
 
19
 
21
-impl<'a> Texture<'a> {
22
-    pub fn new(cx: &'a Context, img: &image::DynamicImage) -> Result<Texture<'a>, ()> {
20
+impl Texture {
21
+    pub fn new(cx: &mut Context, img: &image::DynamicImage) -> Result<Texture, ()> {
23
         let format = match *img {
22
         let format = match *img {
24
             image::ImageRgb8(_) => TextureFormat::Rgb8,
23
             image::ImageRgb8(_) => TextureFormat::Rgb8,
25
             image::ImageRgba8(_) => TextureFormat::Rgba8,
24
             image::ImageRgba8(_) => TextureFormat::Rgba8,
29
         Ok(Self::from_bytes(cx, img.width(), img.height(), format, &img.raw_pixels()))
28
         Ok(Self::from_bytes(cx, img.width(), img.height(), format, &img.raw_pixels()))
30
     }
29
     }
31
 
30
 
32
-    pub fn empty(cx: &'a Context, width: u32, height: u32, format: TextureFormat) -> Texture<'a> {
31
+    pub fn empty(cx: &mut Context, width: u32, height: u32, format: TextureFormat) -> Texture {
33
         Self::from_ptr(cx, width, height, format, ::std::ptr::null() as *const _)
32
         Self::from_ptr(cx, width, height, format, ::std::ptr::null() as *const _)
34
     }
33
     }
35
 
34
 
36
-    pub fn from_bytes(cx: &'a Context, width: u32, height: u32, format: TextureFormat, data: &[u8]) -> Texture<'a> {
35
+    pub fn from_bytes(cx: &mut Context, width: u32, height: u32, format: TextureFormat, data: &[u8]) -> Texture {
37
         Self::from_ptr(cx, width, height, format, data.as_ptr() as *const _)
36
         Self::from_ptr(cx, width, height, format, data.as_ptr() as *const _)
38
     }
37
     }
39
 
38
 
40
-    fn from_ptr(cx: &'a Context, width: u32, height: u32, format: TextureFormat, data_ptr: *const c_void) -> Texture<'a> {
39
+    fn from_ptr(cx: &mut Context, width: u32, height: u32, format: TextureFormat, data_ptr: *const c_void) -> Texture {
41
         let mut texture_obj = 0_u32;
40
         let mut texture_obj = 0_u32;
42
         unsafe {
41
         unsafe {
43
             cx.gl.GenTextures(1, &mut texture_obj);
42
             cx.gl.GenTextures(1, &mut texture_obj);
61
         }
60
         }
62
 
61
 
63
         Texture {
62
         Texture {
64
-            cx,
65
             texture_obj,
63
             texture_obj,
66
             width,
64
             width,
67
             height,
65
             height,
69
         }
67
         }
70
     }
68
     }
71
 
69
 
72
-    pub fn sub_image(&mut self, x: i32, y: i32, img: &image::DynamicImage) {
70
+    pub fn sub_image(&mut self, cx: &mut Context, x: i32, y: i32, img: &image::DynamicImage) {
73
         let format = match *img {
71
         let format = match *img {
74
             image::ImageRgb8(_) => TextureFormat::Rgb8,
72
             image::ImageRgb8(_) => TextureFormat::Rgb8,
75
             image::ImageRgba8(_) => TextureFormat::Rgba8,
73
             image::ImageRgba8(_) => TextureFormat::Rgba8,
77
         };
75
         };
78
 
76
 
79
         unsafe {
77
         unsafe {
80
-            self.cx.gl.BindTexture(context::gl::TEXTURE_2D, self.texture_obj);
81
-            self.cx.gl.TexSubImage2D(
78
+            cx.gl.BindTexture(context::gl::TEXTURE_2D, self.texture_obj);
79
+            cx.gl.TexSubImage2D(
82
                 context::gl::TEXTURE_2D,
80
                 context::gl::TEXTURE_2D,
83
                 0, // level
81
                 0, // level
84
                 x, // x offset
82
                 x, // x offset
92
         }
90
         }
93
     }
91
     }
94
 
92
 
95
-    pub fn resize(&mut self, width: u32, height: u32) {
93
+    pub fn resize(&mut self, cx: &mut Context, width: u32, height: u32) {
96
         unsafe {
94
         unsafe {
97
-            self.cx.gl.BindTexture(context::gl::TEXTURE_2D, self.texture_obj);
98
-            self.cx.gl.TexImage2D(
95
+            cx.gl.BindTexture(context::gl::TEXTURE_2D, self.texture_obj);
96
+            cx.gl.TexImage2D(
99
                 context::gl::TEXTURE_2D,
97
                 context::gl::TEXTURE_2D,
100
                 0, // level
98
                 0, // level
101
                 self.format.to_gl_enum() as i32,
99
                 self.format.to_gl_enum() as i32,
124
     pub fn height(&self) -> u32 {
122
     pub fn height(&self) -> u32 {
125
         self.height
123
         self.height
126
     }
124
     }
127
-
128
-    pub fn context(&self) -> &Context {
129
-        self.cx
130
-    }
131
 }
125
 }
132
 
126
 
133
 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
127
 #[derive(Copy, Clone, Debug, Eq, PartialEq)]

+ 18
- 15
src/tile_atlas.rs 查看文件

1
+use context::Context;
1
 use coord::{ScreenRect, SubTileCoord, TileCoord, TextureRect};
2
 use coord::{ScreenRect, SubTileCoord, TileCoord, TextureRect};
2
 use image;
3
 use image;
3
 use linked_hash_map::LinkedHashMap;
4
 use linked_hash_map::LinkedHashMap;
17
 }
18
 }
18
 
19
 
19
 #[derive(Clone, Debug)]
20
 #[derive(Clone, Debug)]
20
-pub struct TileAtlas<'a> {
21
-    texture: Texture<'a>,
21
+pub struct TileAtlas {
22
+    texture: Texture,
22
     tile_size: u32,
23
     tile_size: u32,
23
     slots_lru: LinkedHashMap<CacheSlot, Option<Tile>>, // LRU cache of slots
24
     slots_lru: LinkedHashMap<CacheSlot, Option<Tile>>, // LRU cache of slots
24
     tile_to_slot: HashMap<Tile, CacheSlot>,
25
     tile_to_slot: HashMap<Tile, CacheSlot>,
25
     use_async: bool,
26
     use_async: bool,
26
 }
27
 }
27
 
28
 
28
-impl<'a> TileAtlas<'a> {
29
-    fn init(&mut self) {
29
+impl TileAtlas {
30
+    fn init(&mut self, cx: &mut Context) {
30
         // add tile for default slot
31
         // add tile for default slot
31
         {
32
         {
32
             let img = image::load_from_memory(
33
             let img = image::load_from_memory(
33
                 include_bytes!("../img/no_tile.png"),
34
                 include_bytes!("../img/no_tile.png"),
34
             ).unwrap();
35
             ).unwrap();
35
-            self.texture.sub_image(0, 0, &img);
36
+            self.texture.sub_image(cx, 0, 0, &img);
36
         }
37
         }
37
 
38
 
38
         let slots_x = self.texture.width() / self.tile_size;
39
         let slots_x = self.texture.width() / self.tile_size;
53
         self.tile_to_slot.reserve(num_slots);
54
         self.tile_to_slot.reserve(num_slots);
54
     }
55
     }
55
 
56
 
56
-    pub fn new(tex: Texture<'a>, tile_size: u32, use_async: bool) -> Self {
57
+    pub fn new(cx: &mut Context, tex: Texture, tile_size: u32, use_async: bool) -> Self {
57
         let mut atlas = TileAtlas {
58
         let mut atlas = TileAtlas {
58
             texture: tex,
59
             texture: tex,
59
             tile_size,
60
             tile_size,
62
             use_async,
63
             use_async,
63
         };
64
         };
64
 
65
 
65
-        atlas.init();
66
+        atlas.init(cx);
66
         atlas
67
         atlas
67
     }
68
     }
68
 
69
 
69
-    pub fn double_texture_size(&mut self) -> Result<(), ()> {
70
-        let max_size = self.texture.context().max_texture_size() as u32;
70
+    pub fn double_texture_size(&mut self, cx: &mut Context) -> Result<(), ()> {
71
+        let max_size = cx.max_texture_size() as u32;
71
 
72
 
72
         let new_width = self.texture.width() * 2;
73
         let new_width = self.texture.width() * 2;
73
         let new_height = self.texture.height() * 2;
74
         let new_height = self.texture.height() * 2;
74
 
75
 
75
         if new_width <= max_size && new_height <= max_size {
76
         if new_width <= max_size && new_height <= max_size {
76
-            self.texture.resize(new_width, new_height);
77
+            self.texture.resize(cx, new_width, new_height);
77
 
78
 
78
             // remove old entries, initialize texture
79
             // remove old entries, initialize texture
79
-            self.init();
80
+            self.init(cx);
80
 
81
 
81
             info!("new atlas size {}x{}", new_width, new_height);
82
             info!("new atlas size {}x{}", new_width, new_height);
82
 
83
 
90
         CacheSlot { x: 0, y: 0 }
91
         CacheSlot { x: 0, y: 0 }
91
     }
92
     }
92
 
93
 
93
-    pub fn store(&mut self, tile_coord: TileCoord, source: &TileSource, cache: &mut TileCache, load: bool) -> Option<CacheSlot> {
94
+    pub fn store(&mut self, cx: &mut Context, tile_coord: TileCoord, source: &TileSource, cache: &mut TileCache, load: bool) -> Option<CacheSlot> {
94
         let mut remove_tile = None;
95
         let mut remove_tile = None;
95
         let tile = Tile::new(tile_coord, source.id());
96
         let tile = Tile::new(tile_coord, source.id());
96
 
97
 
113
                     remove_tile = old_tile;
114
                     remove_tile = old_tile;
114
 
115
 
115
                     self.texture.sub_image(
116
                     self.texture.sub_image(
117
+                        cx,
116
                         (slot.x * self.tile_size) as i32,
118
                         (slot.x * self.tile_size) as i32,
117
                         (slot.y * self.tile_size) as i32,
119
                         (slot.y * self.tile_size) as i32,
118
                         img,
120
                         img,
145
     /// the number of used tiles is returned as an `usize`.
147
     /// the number of used tiles is returned as an `usize`.
146
     pub fn textured_visible_tiles<'b>(
148
     pub fn textured_visible_tiles<'b>(
147
         &mut self,
149
         &mut self,
150
+        cx: &mut Context,
148
         visible_tiles: &'b [VisibleTile],
151
         visible_tiles: &'b [VisibleTile],
149
         max_tiles_to_use: usize,
152
         max_tiles_to_use: usize,
150
         source: &TileSource,
153
         source: &TileSource,
166
                 return (tvt, Some(&visible_tiles[i..]), used_slots);
169
                 return (tvt, Some(&visible_tiles[i..]), used_slots);
167
             }
170
             }
168
 
171
 
169
-            if let Some(slot) = self.store(vt.tile, source, cache, true) {
172
+            if let Some(slot) = self.store(cx, vt.tile, source, cache, true) {
170
                 let tex_rect = self.slot_to_texture_rect(slot);
173
                 let tex_rect = self.slot_to_texture_rect(slot);
171
                 used_slots += 1;
174
                 used_slots += 1;
172
                 tvt.push(
175
                 tvt.push(
190
                 // look for cached tiles in lower zoom layers
193
                 // look for cached tiles in lower zoom layers
191
                 for dist in 1..31 {
194
                 for dist in 1..31 {
192
                     if let Some((parent_tile, sub_coord)) = vt.tile.parent(dist) {
195
                     if let Some((parent_tile, sub_coord)) = vt.tile.parent(dist) {
193
-                        if let Some(slot) = self.store(parent_tile, source, cache, false) {
196
+                        if let Some(slot) = self.store(cx, parent_tile, source, cache, false) {
194
                             used_slots += 1;
197
                             used_slots += 1;
195
                             tex_sub_rect = self.subslot_to_texture_rect(slot, sub_coord);
198
                             tex_sub_rect = self.subslot_to_texture_rect(slot, sub_coord);
196
                             tex_rect = self.slot_to_texture_rect(slot);
199
                             tex_rect = self.slot_to_texture_rect(slot);
203
 
206
 
204
                 // look for cached tiles in higher zoom layers
207
                 // look for cached tiles in higher zoom layers
205
                 for &(child_tile, child_sub_coord) in &vt.tile.children() {
208
                 for &(child_tile, child_sub_coord) in &vt.tile.children() {
206
-                    if let Some(slot) = self.store(child_tile, source, cache, false) {
209
+                    if let Some(slot) = self.store(cx, child_tile, source, cache, false) {
207
                         used_slots += 1;
210
                         used_slots += 1;
208
                         let tex_rect = self.slot_to_texture_rect(slot);
211
                         let tex_rect = self.slot_to_texture_rect(slot);
209
 
212