Register FAQ / Rules Forum Spy Search Today's Posts Mark Forums Read
Go Back   MacRumors Forums > Apple Systems and Services > Programming > Mac Programming

Reply
 
Thread Tools Search this Thread Display Modes
Old Feb 5, 2013, 01:19 AM   #1
BehindTimes
macrumors newbie
 
Join Date: Jan 2010
OpenGL flickering on window resizing

This is really bothering me. I have an OpenGL window subclassed from NSOpenGLView and rendering via the display link. If I resize the window via the zoom button, the view flickers like crazy until the resize is complete (typically a white window when I'm filling the screen with black). All other reshapes seem to work as expected except for the zoom button. (FYI, It is double buffered).

If I force a redraw of the frame in the reshape, everything appears smooth, but that kills the performance of trying to resize the window.

I also tried Apple's GLEssentials from the help docs, and saw this problem in there too.

*EDIT*

OK, resizing the window normally also has flickers too.

Last edited by BehindTimes; Feb 5, 2013 at 01:32 AM.
BehindTimes is offline   0 Reply With Quote
Old Feb 5, 2013, 12:20 PM   #2
chrono1081
macrumors 604
 
chrono1081's Avatar
 
Join Date: Jan 2008
Location: Isla Nublar
Quote:
Originally Posted by BehindTimes View Post
This is really bothering me. I have an OpenGL window subclassed from NSOpenGLView and rendering via the display link. If I resize the window via the zoom button, the view flickers like crazy until the resize is complete (typically a white window when I'm filling the screen with black). All other reshapes seem to work as expected except for the zoom button. (FYI, It is double buffered).

If I force a redraw of the frame in the reshape, everything appears smooth, but that kills the performance of trying to resize the window.

I also tried Apple's GLEssentials from the help docs, and saw this problem in there too.

*EDIT*

OK, resizing the window normally also has flickers too.
My OpenGL skills are a bit rusty so this may not be entirely correct but I believe there is a flag somewhere to set when drawing the OpenGL window to enable double buffering which will prevent the flickering.

I hope someone with more knowledge can answer you but this may be what you want to look in to.

EDIT: Oops I noticed you said this happens when resizing. My suggestion may not be of much help.
__________________
Mac Pro (2010): 3.33Ghz Intel Xeon (6 core) - 24 GB RAM - NVidia Quadro k5000
Macbook Air (2010): 2.13 Ghz Intel Core 2 Duo - 4GB RAM
chrono1081 is offline   0 Reply With Quote
Old Feb 5, 2013, 02:14 PM   #3
BehindTimes
Thread Starter
macrumors newbie
 
Join Date: Jan 2010
Quote:
Originally Posted by chrono1081 View Post
My OpenGL skills are a bit rusty so this may not be entirely correct but I believe there is a flag somewhere to set when drawing the OpenGL window to enable double buffering which will prevent the flickering.

I hope someone with more knowledge can answer you but this may be what you want to look in to.

EDIT: Oops I noticed you said this happens when resizing. My suggestion may not be of much help.
Everything was working well when I was just using a timer. It was mainly due to switching to the core video display link as suggested by Apple's guidelines when reshaping the window became an issue. I've tried even replacing NSOpenGLView with NSView and still getting the flickering. It seems that during the reshape method, the callback is not exactly being hit. I wasn't able to capture that in the video, but there were often times when I grabbed the window and resized that I could go several seconds without the buffer being filled.

https://www.youtube.com/watch?v=IK06sbIAGIQ

2 mins displaying the issue, and the last 30 seconds using Apple's own example which demonstrates the same issue.
BehindTimes is offline   0 Reply With Quote
Old Feb 6, 2013, 08:38 PM   #4
Starfox
macrumors regular
 
Join Date: Apr 2011
I'm having the same issue with a double-buffered context. Weird.
Starfox is offline   0 Reply With Quote
Old Feb 7, 2013, 01:37 PM   #5
Sayer
macrumors 6502a
 
Sayer's Avatar
 
Join Date: Jan 2002
Location: Austin, TX
Are you drawing on the main thread? The sample code GLEssentials shows how to do things the *right* way and it was resizing smoothly for me.

No one can see what you are actually doing without you posting some code you are running and seeing the flickering.
__________________
Obama is a true statesman whose experience as a state senator, half-term US Senator & guest lecturer in a Constitutional Law class has fully prepared him to take control of our nuclear arsenal.-Me
Sayer is offline   0 Reply With Quote
Old Feb 7, 2013, 09:35 PM   #6
BehindTimes
Thread Starter
macrumors newbie
 
Join Date: Jan 2010
Quote:
Originally Posted by Sayer View Post
Are you drawing on the main thread? The sample code GLEssentials shows how to do things the *right* way and it was resizing smoothly for me.

No one can see what you are actually doing without you posting some code you are running and seeing the flickering.
No, I am not drawing to the main thread. Rendering on the main thread, everything works fine. It's when rendering on the separate thread things blow up. GLEssentials also has this problem, as I've stated up above. The CVDisplayLinkRef callback is not being hit during a window resize.

But, here's some simple code which is failing (minus functions which have nothing to do with the rendering):

Code:
- (NSOpenGLPixelFormat *) createPixelFormat
{
    NSOpenGLPixelFormatAttribute attr[] =
    {
        //NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
        NSOpenGLPFAAccelerated,
        NSOpenGLPFADoubleBuffer,
        NSOpenGLPFADepthSize, 16,
        0
    };
    
    return [(NSOpenGLPixelFormat *)[NSOpenGLPixelFormat alloc]
            initWithAttributes:attr];
}

- (id)initWithFrame:(NSRect)frame
{
    NSOpenGLPixelFormat *pixelFormat;
    pixelFormat = [self createPixelFormat];
    self = [super initWithFrame:frame pixelFormat:pixelFormat];
    if (self)
    {
        m_bRedraw = false;
    }
    
    return self;
}

- (BOOL) isOpaque
{
    return YES;
}

- (BOOL) isFlipped
{
    return YES;
}

CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* now, const CVTimeStamp* outputTime, CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void* displayLinkContext)
{
    CVReturn result = [(__bridge OpenGLHelper*)displayLinkContext getFrameForTime:outputTime];
    return result;
}

- (CVReturn)getFrameForTime:(const CVTimeStamp*)outputTime
{
    @autoreleasepool
    {
        if ([self lockFocusIfCanDraw])
        {
            NSRect curFrame = [self frame];
            [self drawFrame: curFrame];
            [self unlockFocus];
        }
    }
    return kCVReturnSuccess;
}

- (void) prepareOpenGL
{
    [super prepareOpenGL];
    
    // Synchronize buffer swaps with vertical refresh rate
    GLint swapInt = 1;
    
    [[self openGLContext] makeCurrentContext];
    
    [[self openGLContext] setValues:&swapInt forParameter:NSOpenGLCPSwapInterval];
    
    CGLLockContext([[self openGLContext] CGLContextObj]);

    glEnable( GL_TEXTURE_2D );
    glShadeModel( GL_SMOOTH );
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_LINE_SMOOTH);
    glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 
    CGLUnlockContext([[self openGLContext] CGLContextObj]);
    
    // Create a display link capable of being used with all active displays
    CVDisplayLinkCreateWithActiveCGDisplays(&displayLink);
    
    // Set the renderer output callback function
    CVDisplayLinkSetOutputCallback(displayLink, &MyDisplayLinkCallback, (__bridge void *)(self));
    
    // Set the display link for the current renderer
    CGLContextObj cglContext = [[self openGLContext] CGLContextObj];
    CGLPixelFormatObj cglPixelFormat = [[self pixelFormat] CGLPixelFormatObj];
    CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(displayLink, cglContext, cglPixelFormat);
    
    // Activate the display link
    CVDisplayLinkStart(displayLink);
    
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(applicationWillTerminate:)
                                                 name:NSApplicationWillTerminateNotification
                                               object:nil];
}

- (void) SetResizeRedraw: (bool) redraw
{
    m_bRedraw = redraw;
}

- (void) reshape
{
	NSRect rect;
    //[super reshape];
    CGLLockContext([[self openGLContext] CGLContextObj]);
    
	[[self openGLContext] makeCurrentContext];
	[[self openGLContext] update];
	rect = [self bounds];
	glViewport(0, 0, rect.size.width, rect.size.height);
    
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0, rect.size.width, rect.size.height, 0, 0, 100.0f);
    
	CGLUnlockContext([[self openGLContext] CGLContextObj]);
    
    //if (!CVDisplayLinkIsRunning(displayLink))
// Will work if this is uncommented, but kills performance
    /*if(m_bRedraw)
    {
        [self drawFrame:[self frame]];
    }*/
}

- (void)drawRect:(NSRect)dirtyRect
{
    if (!CVDisplayLinkIsRunning(displayLink))
    {
        [self drawFrame:dirtyRect];
    }
}

- (void) drawFrame:(NSRect)dirtyRect
{
    CGLLockContext([[self openGLContext] CGLContextObj]);
    
    [[self openGLContext] makeCurrentContext];
    
    glClearColor(0, 0, 0, 255);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
    CGLFlushDrawable([[self openGLContext] CGLContextObj]);
    CGLUnlockContext([[self openGLContext] CGLContextObj]);
}
BehindTimes is offline   0 Reply With Quote
Old Feb 8, 2013, 03:27 AM   #7
axxxum
macrumors newbie
 
Join Date: Feb 2013
Location: Netherlands
From the back of my head since it's been a while I used OpenGL, but in your code I see you explicitly call the frame-update yourself; the proper way however is to let the OpenGL-threading mechanism handle that, i.e. whenever you want the frame updated, put in code '[self setNeedsDisplay:YES];' (self being the instance of the class derived from a View-superclass).

This will indicate to graphics-thread scheduler that your display needs updating (duh!) and whenever the time is ready, it will do so, without flickering.

The ADC-docs I'm sure, contain a more precise and clear formulation of this
axxxum is offline   0 Reply With Quote
Old Feb 8, 2013, 04:14 AM   #8
axxxum
macrumors newbie
 
Join Date: Feb 2013
Location: Netherlands
Quote:
Originally Posted by axxxum View Post
From the back of my head since it's been a while I used OpenGL, but in your code I see you explicitly call the frame-update yourself; the proper way however is to let the OpenGL-threading mechanism handle that, i.e. whenever you want the frame updated, put in code '[self setNeedsDisplay:YES];' (self being the instance of the class derived from a View-superclass).

This will indicate to graphics-thread scheduler that your display needs updating (duh!) and whenever the time is ready, it will do so, without flickering.

The ADC-docs I'm sure, contain a more precise and clear formulation of this
Nevermind, just looked into the GLEssentials sample-code, it's not yer vanilla-OpenGL stuff, as I assumed above.
axxxum is offline   0 Reply With Quote
Old Feb 8, 2013, 05:39 AM   #9
Hem Dutt
macrumors newbie
 
Join Date: Feb 2013
Location: INDIA
Hi,

I tried following code in my reshape function :

Code:
-(void)reshape
{
    NSOpenGLContext *context = [self openGLContext];
    [context makeCurrentContext];
    
    // must lock GL context because display link is threaded
    CGLLockContext([context CGLContextObj]);
    
    
    //glClearColor(0.0, 0.0, 0.0, 0.0);
    glClear(GL_COLOR_BUFFER_BIT);
    
    [context flushBuffer];
    
    CGLUnlockContext([context CGLContextObj]);
}
The code worked and flickering stopped without much overhead.

You must be calling another subroutine in your drawFrame method for your animation (assuming this because I did not found any subroutine for animation in the code) which you have not specified in the forum and the overhead must be because of that subroutine when you are calling drawFrame from within reshape method.

Last edited by 840quadra; Feb 8, 2013 at 11:38 AM. Reason: Please use [Code] tags when sharing code in posts
Hem Dutt is offline   0 Reply With Quote
Old Feb 8, 2013, 07:03 AM   #10
BehindTimes
Thread Starter
macrumors newbie
 
Join Date: Jan 2010
Quote:
Originally Posted by Hem Dutt View Post
Hi,

I tried following code in my reshape function :

-(void)reshape
{
NSOpenGLContext *context = [self openGLContext];
[context makeCurrentContext];

// must lock GL context because display link is threaded
CGLLockContext([context CGLContextObj]);


//glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);

[context flushBuffer];

CGLUnlockContext([context CGLContextObj]);
}

The code worked and flickering stopped without much overhead.

You must be calling another subroutine in your drawFrame method for your animation (assuming this because I did not found any subroutine for animation in the code) which you have not specified in the forum and the overhead must be because of that subroutine when you are calling drawFrame from within reshape method.
It will contain a bit more in the future, but I'm trying to resolve the simple issues first before the program becomes too massive. Embed the OpenGL view in a corner of a window containing a horizontal NSSplitView and a vertical NSSplitView. Try moving the bars now, and you should see slow down. In the video I posted, I just threw together a very simple animation (we're talking 2 textured polygons moving across a plane), and moving the bar dropped the frame rate to under 10 FPS.
BehindTimes is offline   0 Reply With Quote

Reply
MacRumors Forums > Apple Systems and Services > Programming > Mac Programming

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Similar Threads
thread Thread Starter Forum Replies Last Post
Dialog window sidebar resizing fixed in 10.9.3? Raunien OS X Mavericks (10.9) 0 May 15, 2014 05:54 PM
'Drag to edge' window resizing not working ofawx Mac Basics and Help 8 Oct 21, 2013 08:58 AM
window resizing lag rMBP rmbpuser MacBook Pro 1 Dec 22, 2012 03:07 PM
Just upgraded to Lion (10.7) and need help with window resizing Axemantitan Mac Basics and Help 1 Sep 19, 2012 02:53 AM
Window flickers in Safari when resizing window Pegbiter OS X 0 Jun 13, 2012 08:14 AM

Forum Jump

All times are GMT -5. The time now is 03:03 AM.

Mac Rumors | Mac | iPhone | iPhone Game Reviews | iPhone Apps

Mobile Version | Fixed | Fluid | Fluid HD
Copyright 2002-2013, MacRumors.com, LLC