NSOpenGLView and resizable NSWindow problem

  • I'm trying to programmatically create a NSOpenGLView inside a NSWindow
    and I'm having trouble getting the NSOpenGLView to correct resize.  This
    is a simplified version of what I'm doing ...



    NSRect myrect.... // 100, 100, 400, 500

    unsigned int mask = titledwindow | resizable | closeable |
    miniaturizable;



    NSWindow *win = [NSWindow alloc] initWithContentRect:myrect styleMask:
    mask backing: NSBackingStoreBuffered defer:NO];

    MyGLView *view = [MyGLView] alloc] init;

    [win setContentView: view];



    [view setAutoresizingMask: (NSViewWidthSizable | NSViewHeightSizable)];



    My GL drawing is very simple - basic GL setup including the viewport
    plus a glClearColor and glFlush call.  The viewport is using the view's
    bounds (or frame) to set itself.  On the first drawRect, everything
    draws fine - a solid color is displayed in the entire window.  But if I
    resize the window larger, the GL content is limited to the original size
    of the window.  I can see the view's frame and bound value match the
    frame and bounds of the window itself but the GL rendering just appears
    clipped to the original size.



    My openGL view class does nothing besides override drawRect.    Do I
    need to override anything else to correctly resize the openglview?  I
    tried resizeWithOldSuperviewSize and can see resize calls happening but
    my own experimental implementation of this does not help.



    Thanks for any help.



    Werner Sharp
  • On Tue, 31 Oct 2006 11:21:48 -0800
    "Werner Sharp" <wsharp...> wrote:

    WS> I'm trying to programmatically create a NSOpenGLView inside a NSWindow
    WS> and I'm having trouble getting the NSOpenGLView to correct resize.  This

    I had the same problem (plus others) with NSOpenGLView. Eventually, I
    ditched it and subclassed NSView with the following code:

    //--------------------------------------------------------------------
    - (id)initWithFrame: (NSRect)frameRect
    {
        static NSOpenGLPixelFormatAttribute attrs[] =
    {
            NSOpenGLPFANoRecovery,
      NSOpenGLPFAWindow,
            NSOpenGLPFAColorSize,        (NSOpenGLPixelFormatAttribute)24,
            NSOpenGLPFADepthSize,        (NSOpenGLPixelFormatAttribute)16,
            NSOpenGLPFADoubleBuffer,
            NSOpenGLPFAAccelerated,
      NSOpenGLPFASampleBuffers, (NSOpenGLPixelFormatAttribute)1,
      NSOpenGLPFASamples,  (NSOpenGLPixelFormatAttribute)4,
            (NSOpenGLPixelFormatAttribute)0
        };

        self = [super initWithFrame: frameRect];

        if( self ) {
      NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];

      pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes: attrs];
      glContext  = [[NSOpenGLContext alloc] initWithFormat: pixelFormat shareContext: nil];

      [nc addObserver: self
                 selector: @selector( reshape )
                     name: NSViewFrameDidChangeNotification
                    object: self];

      ready  = NO;
        }

        return( self );
    }
    //--------------------------------------------------------------------
    - (void)dealloc
    {
    [[NSNotificationCenter defaultCenter] removeObserver: self];

    [glContext release];
    [pixelFormat release];
    [super dealloc];
    }
    //--------------------------------------------------------------------
    - (BOOL)isOpaque
    {
    return( YES );
    }
    //--------------------------------------------------------------------
    - (BOOL)isFlipped
    {
    return( YES );
    }
    //--------------------------------------------------------------------
    - (void)reshape
    {
    NSSize size = [self frame].size;
    BOOL setCtx = [NSOpenGLContext currentContext] != glContext;

    [glContext update];

    if( setCtx )
      [glContext makeCurrentContext];

    glViewport( 0, 0, (GLint) size.width, (GLint) size.height );

    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();

    gluPerspective( 40.0, size.width / size.height, 1.0f, 1000.0f );

    if( setCtx )
      [NSOpenGLContext clearCurrentContext];
    }
    //--------------------------------------------------------------------
    - (void)drawRect: (NSRect) rect
    {
    [glContext setView: self];
    [glContext makeCurrentContext];

    if( !ready ) {

      // here I call a method to create some glLists, etc...
      [self reshape];

      ready = YES;
    }

    // render the scene

    [glContext flushBuffer];

    [NSOpenGLContext clearCurrentContext];
    }
    //---------------------------------------------------------------------------

    So far this solution seems to work well. It also proved a lot easier
    than getting NSOpenGLView to work as it should ;-)

    Any improvement is welcome.

    --
    Simone Tellini
    http://tellini.info
  • Thanks for the quick reply.

    I compared the differences and isolated it down to one tiny bit.  If I
    add this...

    - (void) reshape
    {
    [[self openGLContext] update];
    }

    ...then my subclass of NSOpenGLView works correctly.

    I get white flickering in both versions when I drag the window under the
    dock sometimes.  I'm not sure why that is.

    -Werner

    -----Original Message-----
    From: cocoa-dev-bounces+wsharp=<adobe.com...>
    [mailto:cocoa-dev-bounces+wsharp=<adobe.com...>] On Behalf Of
    Simone Tellini
    Sent: Tuesday, October 31, 2006 11:51 AM
    To: <cocoa-dev...>
    Subject: Re: NSOpenGLView and resizable NSWindow problem

    On Tue, 31 Oct 2006 11:21:48 -0800
    "Werner Sharp" <wsharp...> wrote:

    WS> I'm trying to programmatically create a NSOpenGLView inside a
    NSWindow
    WS> and I'm having trouble getting the NSOpenGLView to correct resize.
    This

    I had the same problem (plus others) with NSOpenGLView. Eventually, I
    ditched it and subclassed NSView with the following code:

    //--------------------------------------------------------------------
    - (id)initWithFrame: (NSRect)frameRect
    {
        static NSOpenGLPixelFormatAttribute attrs[] =
    {
            NSOpenGLPFANoRecovery,
      NSOpenGLPFAWindow,
            NSOpenGLPFAColorSize,
    (NSOpenGLPixelFormatAttribute)24,
            NSOpenGLPFADepthSize,
    (NSOpenGLPixelFormatAttribute)16,
            NSOpenGLPFADoubleBuffer,
            NSOpenGLPFAAccelerated,
      NSOpenGLPFASampleBuffers,
    (NSOpenGLPixelFormatAttribute)1,
      NSOpenGLPFASamples,
    (NSOpenGLPixelFormatAttribute)4,
            (NSOpenGLPixelFormatAttribute)0
        };

        self = [super initWithFrame: frameRect];

        if( self ) {
      NSNotificationCenter *nc = [NSNotificationCenter
    defaultCenter];

      pixelFormat = [[NSOpenGLPixelFormat alloc]
    initWithAttributes: attrs];
      glContext  = [[NSOpenGLContext alloc] initWithFormat:
    pixelFormat shareContext: nil];

      [nc addObserver: self
                 selector: @selector( reshape )
                     name:
    NSViewFrameDidChangeNotification
                    object: self];

      ready  = NO;
        }

        return( self );
    }
    //--------------------------------------------------------------------
    - (void)dealloc
    {
    [[NSNotificationCenter defaultCenter] removeObserver: self];

    [glContext release];
    [pixelFormat release];
    [super dealloc];
    }
    //--------------------------------------------------------------------
    - (BOOL)isOpaque
    {
    return( YES );
    }
    //--------------------------------------------------------------------
    - (BOOL)isFlipped
    {
    return( YES );
    }
    //--------------------------------------------------------------------
    - (void)reshape
    {
    NSSize size = [self frame].size;
    BOOL setCtx = [NSOpenGLContext currentContext] != glContext;

    [glContext update];

    if( setCtx )
      [glContext makeCurrentContext];

    glViewport( 0, 0, (GLint) size.width, (GLint) size.height );

    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();

    gluPerspective( 40.0, size.width / size.height, 1.0f, 1000.0f );

    if( setCtx )
      [NSOpenGLContext clearCurrentContext];
    }
    //--------------------------------------------------------------------
    - (void)drawRect: (NSRect) rect
    {
    [glContext setView: self];
    [glContext makeCurrentContext];

    if( !ready ) {

      // here I call a method to create some glLists, etc...
      [self reshape];

      ready = YES;
    }

    // render the scene

    [glContext flushBuffer];

    [NSOpenGLContext clearCurrentContext];
    }
    //----------------------------------------------------------------------
    -----

    So far this solution seems to work well. It also proved a lot easier
    than getting NSOpenGLView to work as it should ;-)

    Any improvement is welcome.

    --
    Simone Tellini
    http://tellini.info

    _______________________________________________
    Do not post admin requests to the list. They will be ignored.
    Cocoa-dev mailing list      (<Cocoa-dev...>)
    Help/Unsubscribe/Update your Subscription:
    http://lists.apple.com/mailman/options/cocoa-dev/<wsharp...>

    This email sent to <wsharp...>
  • Hi,
    Am 31.10.2006 um 22:12 schrieb Werner Sharp:

    > Thanks for the quick reply.
    >
    > I compared the differences and isolated it down to one tiny bit.  If I
    > add this...
    >
    > - (void) reshape
    > {
    > [[self openGLContext] update];
    > }
    >
    > ...then my subclass of NSOpenGLView works correctly.
    >
    > I get white flickering in both versions when I drag the window
    > under the
    > dock sometimes.  I'm not sure why that is.
    >
    > -Werner
    <snip>
    >
    > On Tue, 31 Oct 2006 11:21:48 -0800
    > "Werner Sharp" <wsharp...> wrote:
    <snip>
    > - (void)reshape
    > {
    <snip>
    > }
    > //--------------------------------------------------------------------
    > - (void)drawRect: (NSRect) rect
    > {
    <snip>
    >
    > if( !ready ) {
    >
    > // here I call a method to create some glLists, etc...
    > [self reshape];
    >
    > ready = YES;
    > }
    <snip>
    > }
    > //--------------------------------------------------------------------
    > --
    <snip>
    > Simone Tellini

    according to NSOpenGLView's documentation - based on my experience
    it's correct - reshape and update are called automatically by Cocoa.
    It shouldn't be necessary to call reshape from inside drawRect and
    update from inside reshape. But if someone does, then reshape will be
    called twice and update three times.

    No insult intended, but, I think, there may be something basically
    wrong in the composition of the application.

    What do others think?

    BTW, wouldn't it be better to take this problem to the Mac-OpenGL
    mailing list?!

    Cheers
    Klaus
previous month october 2006 next month
MTWTFSS
            1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31          
Go to today