@@ -311,6 +311,7 @@ -(id) initWithFrame:(NSRect)frameRect
311311 currentScreenTex = 0 ;
312312
313313 statusbar_updated = NO ;
314+ isResizing = NO ;
314315
315316 [self registerForDraggedTypes: [NSArray arrayWithObjects: NSFilenamesPboardType , nil ]];
316317
@@ -571,31 +572,48 @@ -(void) drawRect:(NSRect)aRect
571572-(void ) doReshape
572573{
573574 [view_lock lock ];
575+
576+ /* Set resize flag to block rendering during reshape */
577+ isResizing = YES ;
578+
579+ /* Stop display link during reshape to prevent drawing with invalid context */
580+ [self displayLinkStop ];
581+
574582 NSRect rect;
575583
576- [[self openGLContext ] makeCurrentContext ];
584+ NSOpenGLContext *context = [self openGLContext ];
585+ if (context) {
586+ [context makeCurrentContext ];
577587
578- rect = [self bounds ];
588+ rect = [self bounds ];
579589
580- glViewport ( 0 , 0 , (int ) rect.size .width , (int ) rect.size .height );
590+ glViewport ( 0 , 0 , (int ) rect.size .width , (int ) rect.size .height );
581591
582- glMatrixMode ( GL_PROJECTION );
583- glLoadIdentity ();
592+ glMatrixMode ( GL_PROJECTION );
593+ glLoadIdentity ();
584594
585- glMatrixMode ( GL_MODELVIEW );
586- glLoadIdentity ();
587-
588- [[self openGLContext ] update ];
595+ glMatrixMode ( GL_MODELVIEW );
596+ glLoadIdentity ();
597+
598+ [context update ];
599+ }
589600
590601 statusbar_updated = YES ;
602+
603+ /* Clear resize flag and restart display link after reshape completes */
604+ isResizing = NO ;
605+ [self displayLinkStart ];
606+
591607 [view_lock unlock ];
592608}
593609
594610/* scrolled, moved or resized */
595611-(void ) reshape
596612{
597613 [super reshape ];
598- [self performSelectorOnMainThread: @selector (doReshape ) withObject: self waitUntilDone: NO ];
614+ /* Wait for reshape to complete to prevent queuing multiple reshape operations
615+ during slow drag resize, which can cause race conditions */
616+ [self performSelectorOnMainThread: @selector (doReshape ) withObject: self waitUntilDone: YES ];
599617}
600618
601619-(void ) destroyTexture
@@ -1333,6 +1351,15 @@ -(CVReturn) displayFrame:(const CVTimeStamp *)timeStamp
13331351 int i;
13341352 PIG_dirtytable *workdirty = NULL ;
13351353
1354+ /* Skip rendering if window is being resized to prevent crashes */
1355+ [view_lock lock ];
1356+ BOOL resizing = isResizing;
1357+ [view_lock unlock ];
1358+
1359+ if (resizing) {
1360+ return kCVReturnSuccess ;
1361+ }
1362+
13361363 // Is it possible that while waiting for a lock the emulator is stopped?
13371364 // or already holds the lock? If so give up on updating the frame rather
13381365 // than deadlock on getting the lock - may mean that we miss some screen
@@ -1341,6 +1368,12 @@ -(CVReturn) displayFrame:(const CVTimeStamp *)timeStamp
13411368 return kCVReturnSuccess ;
13421369 }
13431370
1371+ /* Check if buffered_screen.dirty is initialized - it might be NULL during initialization or cleanup */
1372+ if ( !buffered_screen.dirty ) {
1373+ [buffered_screen_lock unlock ];
1374+ return kCVReturnSuccess ;
1375+ }
1376+
13441377 if ( buffered_screen.dirty ->count == 0 && !statusbar_updated ) {
13451378 [buffered_screen_lock unlock ];
13461379 return kCVReturnSuccess ;
@@ -1354,6 +1387,20 @@ -(CVReturn) displayFrame:(const CVTimeStamp *)timeStamp
13541387 // occur, also cover the screen texture swap
13551388 [view_lock lock ];
13561389
1390+ // Double-check resize flag after acquiring lock - resize might have started
1391+ if (isResizing) {
1392+ [view_lock unlock ];
1393+ [buffered_screen_lock unlock ];
1394+ return kCVReturnSuccess ;
1395+ }
1396+
1397+ // Check if textures are initialized - they may be destroyed during window resize
1398+ if (!screenTexInitialised) {
1399+ [view_lock unlock ];
1400+ [buffered_screen_lock unlock ];
1401+ return kCVReturnSuccess ;
1402+ }
1403+
13571404 if (screenTex[currentScreenTex].dirty )
13581405 pig_dirty_copy ( &workdirty, screenTex[currentScreenTex].dirty );
13591406
0 commit comments