When to create custom OpenGL view instead of subclass NSOpenGL view

Nibbie
Posts: 4
Joined: 2009.10
Post: #31
Quote:I have tried calling [self setNeedsDisplay:true]; directly from the displaylink callback -> this results in drawRect being called by the main app thread without needing any context locking. I then do all my drawing and rendering from there on the main thread.

Is this a valid approach?
It depends on whether setNeedsDisplay does anything besides set a boolean value and whether that boolean is accessed in only one place in the main thread (in which case the worst problem you're likely to run into is a dropped frame or two). The other thing to consider, is where is all your game update code happening - in the main thread or in the display link thread during a callback? If the latter, then you need to worry about synchronising access between game state during updates and rendering. The last thing you want is for an object you're about to render to be deallocated by the update thread just as you're about to use it (or something similar). Shock Just because you don't have a problem now, doesn't mean one doesn't exist, and random crash bugs like that won't be easy to find and fix. It might be easier just to figure out where the context locking is causing problems.
Quote this message in a reply
Moderator
Posts: 3,577
Joined: 2003.06
Post: #32
imron Wrote:The last thing you want is for an object you're about to render to be deallocated by the update thread just as you're about to use it (or something similar). Shock

One of the ways I had dealt with that previously was to "double-buffer" my states. So then if you're doing tick-interpolation (state-interpolation/sub-update interpolation/or whatever you wanna call it) you have four buffers of state: front/back alphaState/betaState. Then throw in networking, where you take server snapshots, interpolate those, maintain three more states: local client-side prediction (plus archive for checking against the server snapshots) plus erroneous prediction plus correction interpolation, then add those up. THEN throw in whether or not an entity exists between ticks of state on multiple threads. Bonkers.

Just when you think you got this stuff figured out... Rolleyes
Quote this message in a reply
Moderator
Posts: 3,577
Joined: 2003.06
Post: #33
OptimisticMonkey Wrote:I still think that using setNeedsDisplay from the callback might be a good idea.

Out of curiosity, I just tried this. It *sort* of works for me. I get intermittent errors:

CGSUnionRegionWithRect : Invalid region
CGSGetRegionBounds : Invalid region

When it isn't spitting out errors the performance is actually pretty good, at least better than a regular NSTimer on the main thread, but it *still* intermittently drops frames once in a while. So, even if I can figure out how to stop those errors, assuming there isn't something else afoot, at this point it looks like it isn't quite as good as rendering on the display link thread. To me, it appears to be kind of a middle ground in terms of performance between a regular NSTimer and the Display Link.

BTW, I also tried out some tick interpolation with the display link rendering and all I have to say is WOW! It's like I've finally discovered timing nirvana when used in conjunction with display link. Tick interpolation previously didn't give me a big enough improvement over a straight 110 Hz update with a regular NSTimer to be worth the trouble, but now I'm very seriously going to make an attempt at developing a better entity interpolation system. I can play Pong at only 10 ticks per second simulation and it's smooth as a baby's butt. This is really cool stuff to me.
Quote this message in a reply
Member
Posts: 35
Joined: 2009.10
Post: #34
AnotherJake Wrote:You'll be setting your glViewport to the screen size. Switching into full screen can be a new subject all unto itself if you ask me!

Really? I got my fullscreen code from the QTCoreVideo201 sample code on the Mac Reference Library, and they seemed to make it look so easy. Blush

Say, how many of us have taken a look at that sample? As far as I can tell, it's the only sample code from Apple that uses a display link with an OpenGL view (though it's kind of obfuscated with all the QuickTime stuff).
Quote this message in a reply
Moderator
Posts: 3,577
Joined: 2003.06
Post: #35
That sample doesn't really make much sense to me (too much for a glance at least).

Full screen involves potentially a few things which may trip you up. Here are some off the top of my head:
- getting display properties is a super-duper pain in the rear
- you gotta make sure you "capture" the display(s)
- wanna fade in/out to avoid flashes?
- good luck debugging!
- have to make a separate context for full screen, and remember to share it (not a big deal though)
- input will likely need to be handled differently. I have to override sendEvent to get what I want for some stuff
- mouse input can be inconsistent with some mouses, and can be particularly whacky with Wacom tablets (they're a little strange in windowed too, but it gets worse in full screen)
- don't forget you get no access to Cocoa UI widgets when in full screen, which means no Cocoa dialogs for saving, notifying, etc.
- events might still fall through to the menu (don't know if this is fixed in Snow Leopard), so gotta hide the menu
- wanna implement cmd-h? how about cmd-q? how about any other menu equivalents?

and on and on... Oh yes, there are *lots* of issues to deal with when going full screen on Mac. Wink You'd think it'd be easier, but it ain't.
Quote this message in a reply
Member
Posts: 35
Joined: 2009.10
Post: #36
AnotherJake Wrote:That sample doesn't really make much sense to me (too much for a glance at least).

Full screen involves potentially a few things which may trip you up. Here are some off the top of my head:
- getting display properties is a super-duper pain in the rear
- you gotta make sure you "capture" the display(s)
- wanna fade in/out to avoid flashes?
- good luck debugging!
- have to make a separate context for full screen, and remember to share it (not a big deal though)
- input will likely need to be handled differently. I have to override sendEvent to get what I want for some stuff
- mouse input can be inconsistent with some mouses, and can be particularly whacky with Wacom tablets (they're a little strange in windowed too, but it gets worse in full screen)
- don't forget you get no access to Cocoa UI widgets when in full screen, which means no Cocoa dialogs for saving, notifying, etc.
- events might still fall through to the menu (don't know if this is fixed in Snow Leopard), so gotta hide the menu
- wanna implement cmd-h? how about cmd-q? how about any other menu equivalents?

and on and on... Oh yes, there are *lots* of issues to deal with when going full screen on Mac. Wink You'd think it'd be easier, but it ain't.

The sample code did fullscreen in only two lines but they left that stuff out. Mad

Moving on...I was just thinking about how we're dealing with the OpenGL context. For one thing, I see you're sending makeCurrentContext to the view's context in both reshape and drawFrame. Are you calling makeCurrentContext because the view's context is not guaranteed to still be the current context for some reason?

Also, since we need to protect the view's context, and judging by this message on the Apple mailing lists, we may need to override the view's update and clearGLContext methods to put locks in them as well. So far I'm thinking along the lines of:

Code:
- (void)update
{
    [lock lock];
    [super update];
    [lock unlock];
}

- (void)clearGLContext
{
    [lock lock];
    [super update];
    [lock unlock];
}

Here I'm using an NSRecursiveLock instead of using CGLLockContext and CGLUnlockContext like before.
Quote this message in a reply
Moderator
Posts: 3,577
Joined: 2003.06
Post: #37
Coyote Wrote:Moving on...I was just thinking about how we're dealing with the OpenGL context. For one thing, I see you're sending makeCurrentContext to the view's context in both reshape and drawFrame. Are you calling makeCurrentContext because the view's context is not guaranteed to still be the current context for some reason?
I don't know. I've been doing it for so many years like that I don't remember what the reasoning was behind it. Perhaps it was recommended by Apple, or perhaps it was because I was experiencing crashes/funky behavior and those calls fixed it. I know that OpenGL contexts are not thread safe, so I know that they gotta be locked when threading, but in terms of placement in specific NSView methods, I don't have any specific knowledge there -- I figure if it works it works; if it doesn't then need to examine something else.

Coyote Wrote:Also, since we need to protect the view's context, and judging by this message on the Apple mailing lists, we may need to override the view's update and clearGLContext methods to put locks in them as well. So far I'm thinking along the lines of:

...
I don't know anything about that. It's possible that since that message was from 2004 the behavior may have already been addressed by new versions of OS X. Like I said, this is just the way I've been doing it for years. As far as I know, it's stable. Beyond that, any other necessary context or other locking on behalf of the system I am unaware of. Since I'm only drawing with OpenGL, that's the only context I take responsibility for locking. The other window stuff I assume to be handled properly by the OS, on the main thread. I think reshape and drawRect are the only ones I ever worry about in terms of OpenGL drawing.
Quote this message in a reply
Member
Posts: 35
Joined: 2009.10
Post: #38
Well, in that case, I'm just going to call [[self openGLContext] makeCurrentContext] whenever I need to touch some OpenGL stuff. Right now that's only in my reshape and [/i]drawRect[/i] methods ([/i]drawRect[/i] is called by drawFrameForTime from the Core Video thread). I'm also not going to bother with overriding update or clearGLContext until I get a mysterious crash.

Right now I've been able to get a white rotating box over a black screen. Now I have to finalize my keyboard input code and set up window focus events so that the game will pause when I minimize the window, switch to another application, etc.
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  OpenGL view first frame flickers garbage mk12 8 6,834 Sep 4, 2010 06:06 PM
Last Post: mk12
  View Controllers MacSteve85 2 2,471 Jan 27, 2010 07:22 PM
Last Post: MacSteve85
  multiple nsopengl subviews problem NelsonMandella 0 2,246 Nov 9, 2009 09:44 PM
Last Post: NelsonMandella
  GL view bounds question/quirk rezwits 3 3,442 Jul 12, 2009 08:45 AM
Last Post: rezwits
  How do I place all of my UI elements to be subviews of another view/window? xenocide 2 2,803 Feb 1, 2009 08:32 PM
Last Post: xenocide