@@ -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
+ trace ! ( "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 )
@@ -224,7 +243,6 @@ impl Device {
224
243
msg_send ! [ render_layer, setMaximumDrawableCount: config. image_count as u64 ] ;
225
244
//TODO: only set it where supported
226
245
msg_send ! [ render_layer, setDisplaySyncEnabled: display_sync] ;
227
- //msg_send![render_layer, setPresentsWithTransaction: true];
228
246
229
247
// Update render layer size
230
248
let view_points_size: CGRect = msg_send ! [ nsview, bounds] ;
@@ -244,32 +262,41 @@ impl Device {
244
262
( view_points_size. size , scale_factor)
245
263
} ;
246
264
247
- let pixel_width = ( view_size. width * scale_factor) as u64 ;
248
- let pixel_height = ( view_size. height * scale_factor) as u64 ;
265
+ let pixel_width = ( view_size. width * scale_factor) as image :: Size ;
266
+ let pixel_height = ( view_size. height * scale_factor) as image :: Size ;
249
267
250
268
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
269
+ . map ( |index| {
270
+ let _ap = AutoreleasePool :: new ( ) ; // for the drawable & texture
271
+ let ( drawable, texture) = unsafe {
272
+ let drawable: & metal:: DrawableRef = msg_send ! [ render_layer, nextDrawable] ;
273
+ assert ! ( !drawable. as_ptr( ) . is_null( ) ) ;
274
+ let texture: & metal:: TextureRef = msg_send ! [ drawable, texture] ;
275
+ ( drawable, texture)
276
+ } ;
277
+ if index == 0 {
278
+ // when resizing, this trick frees up the currently shown frame
279
+ drawable. present ( ) ;
280
+ }
281
+ trace ! ( "\t frame[{}] = {:?}" , index, texture) ;
255
282
Frame {
256
283
inner : Mutex :: new ( FrameInner {
257
- drawable : None ,
284
+ drawable : Some ( drawable . to_owned ( ) ) ,
258
285
available : true ,
259
286
last_frame : 0 ,
260
287
} ) ,
261
- texture,
288
+ texture : texture . to_owned ( ) ,
262
289
}
263
290
} )
264
291
. collect :: < Vec < _ > > ( ) ;
265
292
266
293
let images = frames
267
294
. iter ( )
268
295
. map ( |frame| native:: Image {
269
- raw : frame. texture . clone ( ) , //Note: careful!
296
+ raw : frame. texture . clone ( ) ,
270
297
extent : image:: Extent {
271
- width : pixel_width as _ ,
272
- height : pixel_height as _ ,
298
+ width : pixel_width,
299
+ height : pixel_height,
273
300
depth : 1 ,
274
301
} ,
275
302
num_layers : None ,
@@ -283,8 +310,9 @@ impl Device {
283
310
let swapchain = Swapchain {
284
311
frames : Arc :: new ( frames) ,
285
312
surface : surface. inner . clone ( ) ,
286
- _size_pixels : ( pixel_width, pixel_height) ,
313
+ size_pixels : ( pixel_width, pixel_height) ,
287
314
last_frame : 0 ,
315
+ image_ready_callbacks : Vec :: new ( ) ,
288
316
} ;
289
317
290
318
( swapchain, Backbuffer :: Images ( images) )
@@ -293,14 +321,22 @@ impl Device {
293
321
294
322
impl hal:: Swapchain < Backend > for Swapchain {
295
323
fn acquire_image ( & mut self , sync : hal:: FrameSync < Backend > ) -> Result < hal:: SwapImageIndex , ( ) > {
324
+ self . last_frame += 1 ;
325
+
326
+ //TODO: figure out a proper story of HiDPI
327
+ if false && self . surface . pixel_dimensions ( ) != self . size_pixels {
328
+ return Err ( ( ) )
329
+ }
330
+
296
331
let mut oldest_index = 0 ;
297
332
let mut oldest_frame = self . last_frame ;
298
333
299
- self . last_frame += 1 ;
300
-
301
334
for ( index, frame_arc) in self . frames . iter ( ) . enumerate ( ) {
302
335
let mut frame = frame_arc. inner . lock ( ) . unwrap ( ) ;
303
- if frame. available && frame. drawable . is_some ( ) {
336
+ if !frame. available {
337
+ continue
338
+ }
339
+ if frame. drawable . is_some ( ) {
304
340
frame. available = false ;
305
341
frame. last_frame = self . last_frame ;
306
342
self . signal_sync ( sync) ;
@@ -317,8 +353,10 @@ impl hal::Swapchain<Backend> for Swapchain {
317
353
let ( index, mut frame) = if blocking {
318
354
self . surface . next_frame ( & self . frames )
319
355
} else {
356
+ self . image_ready_callbacks . retain ( |ir| ir. lock ( ) . unwrap ( ) . is_some ( ) ) ;
320
357
match sync {
321
358
hal:: FrameSync :: Semaphore ( semaphore) => {
359
+ self . image_ready_callbacks . push ( Arc :: clone ( & semaphore. image_ready ) ) ;
322
360
let mut sw_image = semaphore. image_ready . lock ( ) . unwrap ( ) ;
323
361
assert ! ( sw_image. is_none( ) ) ;
324
362
* sw_image = Some ( SwapchainImage {
@@ -337,6 +375,7 @@ impl hal::Swapchain<Backend> for Swapchain {
337
375
( oldest_index, frame)
338
376
} ;
339
377
378
+ assert ! ( frame. available) ;
340
379
frame. last_frame = self . last_frame ;
341
380
frame. available = false ;
342
381
0 commit comments