@@ -44,21 +44,22 @@ impl SurfaceInner {
44
44
let _ap = AutoreleasePool :: new ( ) ;
45
45
let layer_ref = self . render_layer . lock ( ) . unwrap ( ) ;
46
46
47
- let ( drawable, texture_temp) : ( metal:: Drawable , & metal:: TextureRef ) = unsafe {
48
- let drawable: & metal :: DrawableRef = msg_send ! [ * layer_ref, nextDrawable] ;
49
- ( drawable. to_owned ( ) , msg_send ! [ drawable, texture] )
47
+ let ( drawable, texture_temp) : ( & metal:: DrawableRef , & metal:: TextureRef ) = unsafe {
48
+ let drawable = msg_send ! [ * layer_ref, nextDrawable] ;
49
+ ( drawable, msg_send ! [ drawable, texture] )
50
50
} ;
51
51
52
+ //debug!("looking for {:?}", texture_temp);
52
53
let index = frames
53
54
. iter ( )
54
55
. position ( |f| f. texture . as_ptr ( ) == texture_temp. as_ptr ( ) )
55
56
. expect ( "Surface lost?" ) ;
56
57
57
58
let mut frame = frames[ index] . inner . lock ( ) . unwrap ( ) ;
58
59
assert ! ( frame. drawable. is_none( ) ) ;
59
- frame. drawable = Some ( drawable) ;
60
+ frame. drawable = Some ( drawable. to_owned ( ) ) ;
60
61
61
- debug ! ( "Surface next frame is {} " , index) ;
62
+ debug ! ( "next is frame[{}] " , index) ;
62
63
( index, frame)
63
64
}
64
65
}
@@ -82,11 +83,29 @@ struct Frame {
82
83
unsafe impl Send for Frame { }
83
84
unsafe impl Sync for Frame { }
84
85
86
+ impl Drop for Frame {
87
+ fn drop ( & mut self ) {
88
+ info ! ( "dropping Frame" ) ;
89
+ }
90
+ }
91
+
85
92
pub struct Swapchain {
86
93
frames : Arc < Vec < Frame > > ,
87
94
surface : Arc < SurfaceInner > ,
88
- _size_pixels : ( u64 , u64 ) ,
95
+ size_pixels : ( image :: Size , image :: Size ) ,
89
96
last_frame : usize ,
97
+ image_ready_callbacks : Vec < Arc < Mutex < Option < SwapchainImage > > > > ,
98
+ }
99
+
100
+ impl Drop for Swapchain {
101
+ fn drop ( & mut self ) {
102
+ info ! ( "dropping Swapchain" ) ;
103
+ for ir in self . image_ready_callbacks . drain ( ..) {
104
+ if ir. lock ( ) . unwrap ( ) . take ( ) . is_some ( ) {
105
+ debug ! ( "\t with a callback" ) ;
106
+ }
107
+ }
108
+ }
90
109
}
91
110
92
111
impl Swapchain {
@@ -147,7 +166,7 @@ impl SwapchainImage {
147
166
148
167
impl hal:: Surface < Backend > for Surface {
149
168
fn kind ( & self ) -> image:: Kind {
150
- let ( width, height) = self . pixel_dimensions ( ) ;
169
+ let ( width, height) = self . inner . pixel_dimensions ( ) ;
151
170
152
171
image:: Kind :: D2 ( width, height, 1 , 1 )
153
172
}
@@ -157,7 +176,7 @@ impl hal::Surface<Backend> for Surface {
157
176
) -> ( hal:: SurfaceCapabilities , Option < Vec < format:: Format > > , Vec < hal:: PresentMode > ) {
158
177
let caps = hal:: SurfaceCapabilities {
159
178
//Note: this is hardcoded in `CAMetalLayer` documentation
160
- image_count : 2 .. 3 ,
179
+ image_count : 2 .. 4 ,
161
180
current_extent : None ,
162
181
extents : Extent2D { width : 4 , height : 4 } .. Extent2D { width : 4096 , height : 4096 } ,
163
182
max_image_layers : 1 ,
@@ -182,12 +201,12 @@ impl hal::Surface<Backend> for Surface {
182
201
}
183
202
}
184
203
185
- impl Surface {
204
+ impl SurfaceInner {
186
205
fn pixel_dimensions ( & self ) -> ( image:: Size , image:: Size ) {
187
206
unsafe {
188
207
// NSView bounds are measured in DIPs
189
- let bounds: NSRect = msg_send ! [ self . inner . nsview, bounds] ;
190
- let bounds_pixel: NSRect = msg_send ! [ self . inner . nsview, convertRectToBacking: bounds] ;
208
+ let bounds: NSRect = msg_send ! [ self . nsview, bounds] ;
209
+ let bounds_pixel: NSRect = msg_send ! [ self . nsview, convertRectToBacking: bounds] ;
191
210
( bounds_pixel. size . width as _ , bounds_pixel. size . height as _ )
192
211
}
193
212
}
@@ -199,7 +218,7 @@ impl Device {
199
218
surface : & mut Surface ,
200
219
config : SwapchainConfig ,
201
220
) -> ( Swapchain , Backbuffer < Backend > ) {
202
- let _ap = AutoreleasePool :: new ( ) ; // for the drawable
221
+ info ! ( "build_swapchain {:?}" , config ) ;
203
222
204
223
let mtl_format = self . private_caps
205
224
. map_format ( config. color_format )
@@ -244,32 +263,41 @@ impl Device {
244
263
( view_points_size. size , scale_factor)
245
264
} ;
246
265
247
- let pixel_width = ( view_size. width * scale_factor) as u64 ;
248
- let pixel_height = ( view_size. height * scale_factor) as u64 ;
266
+ let pixel_width = ( view_size. width * scale_factor) as image :: Size ;
267
+ let pixel_height = ( view_size. height * scale_factor) as image :: Size ;
249
268
250
269
let frames = ( 0 .. config. image_count )
251
- . map ( |_| unsafe {
252
- let drawable: & metal:: DrawableRef = msg_send ! [ render_layer, nextDrawable] ;
253
- let texture: metal:: Texture = msg_send ! [ drawable, texture] ;
254
- //HACK: not retaining the texture here
270
+ . map ( |index| {
271
+ let _ap = AutoreleasePool :: new ( ) ; // for the drawable & texture
272
+ let ( drawable, texture) = unsafe {
273
+ let drawable: & metal:: DrawableRef = msg_send ! [ render_layer, nextDrawable] ;
274
+ assert ! ( !drawable. as_ptr( ) . is_null( ) ) ;
275
+ let texture: & metal:: TextureRef = msg_send ! [ drawable, texture] ;
276
+ ( drawable, texture)
277
+ } ;
278
+ if index == 0 {
279
+ // when resizing, this trick frees up the currently shown frame
280
+ drawable. present ( ) ;
281
+ }
282
+ //info!("\tframe[{}] = {:?}", index, texture);
255
283
Frame {
256
284
inner : Mutex :: new ( FrameInner {
257
- drawable : None ,
285
+ drawable : Some ( drawable . to_owned ( ) ) ,
258
286
available : true ,
259
287
last_frame : 0 ,
260
288
} ) ,
261
- texture,
289
+ texture : texture . to_owned ( ) ,
262
290
}
263
291
} )
264
292
. collect :: < Vec < _ > > ( ) ;
265
293
266
294
let images = frames
267
295
. iter ( )
268
296
. map ( |frame| native:: Image {
269
- raw : frame. texture . clone ( ) , //Note: careful!
297
+ raw : frame. texture . clone ( ) ,
270
298
extent : image:: Extent {
271
- width : pixel_width as _ ,
272
- height : pixel_height as _ ,
299
+ width : pixel_width,
300
+ height : pixel_height,
273
301
depth : 1 ,
274
302
} ,
275
303
num_layers : None ,
@@ -283,8 +311,9 @@ impl Device {
283
311
let swapchain = Swapchain {
284
312
frames : Arc :: new ( frames) ,
285
313
surface : surface. inner . clone ( ) ,
286
- _size_pixels : ( pixel_width, pixel_height) ,
314
+ size_pixels : ( pixel_width, pixel_height) ,
287
315
last_frame : 0 ,
316
+ image_ready_callbacks : Vec :: new ( ) ,
288
317
} ;
289
318
290
319
( swapchain, Backbuffer :: Images ( images) )
@@ -293,14 +322,22 @@ impl Device {
293
322
294
323
impl hal:: Swapchain < Backend > for Swapchain {
295
324
fn acquire_image ( & mut self , sync : hal:: FrameSync < Backend > ) -> Result < hal:: SwapImageIndex , ( ) > {
325
+ self . last_frame += 1 ;
326
+
327
+ //TODO: figure out a proper story of HiDPI
328
+ if false && self . surface . pixel_dimensions ( ) != self . size_pixels {
329
+ return Err ( ( ) )
330
+ }
331
+
296
332
let mut oldest_index = 0 ;
297
333
let mut oldest_frame = self . last_frame ;
298
334
299
- self . last_frame += 1 ;
300
-
301
335
for ( index, frame_arc) in self . frames . iter ( ) . enumerate ( ) {
302
336
let mut frame = frame_arc. inner . lock ( ) . unwrap ( ) ;
303
- if frame. available && frame. drawable . is_some ( ) {
337
+ if !frame. available {
338
+ continue
339
+ }
340
+ if frame. drawable . is_some ( ) {
304
341
frame. available = false ;
305
342
frame. last_frame = self . last_frame ;
306
343
self . signal_sync ( sync) ;
@@ -317,8 +354,10 @@ impl hal::Swapchain<Backend> for Swapchain {
317
354
let ( index, mut frame) = if blocking {
318
355
self . surface . next_frame ( & self . frames )
319
356
} else {
357
+ self . image_ready_callbacks . retain ( |ir| ir. lock ( ) . unwrap ( ) . is_some ( ) ) ;
320
358
match sync {
321
359
hal:: FrameSync :: Semaphore ( semaphore) => {
360
+ self . image_ready_callbacks . push ( Arc :: clone ( & semaphore. image_ready ) ) ;
322
361
let mut sw_image = semaphore. image_ready . lock ( ) . unwrap ( ) ;
323
362
assert ! ( sw_image. is_none( ) ) ;
324
363
* sw_image = Some ( SwapchainImage {
@@ -337,6 +376,7 @@ impl hal::Swapchain<Backend> for Swapchain {
337
376
( oldest_index, frame)
338
377
} ;
339
378
379
+ assert ! ( frame. available) ;
340
380
frame. last_frame = self . last_frame ;
341
381
frame. available = false ;
342
382
0 commit comments