The SDL forums have moved to discourse.libsdl.org.
This is just a read-only archive of the previous forums, to keep old links working.


SDL Forum Index
SDL
Simple Directmedia Layer Forums
How to make SDL 2.0, iOS work together. (Game Center too)
BJ


Joined: 01 May 2012
Posts: 18
Location: Australia
The problem is that SDL uses a pull messaging system, but iOS requires a pull system. Here is how to get the two working together correctly.
(I am using this on a project that is on PC and iOS)

This only change that I made to SDL was as follows
Code:

void
UIKit_PumpEvents(_THIS)
{
    return;
    /*
        When the user presses the 'home' button on the iPod
        the application exits -- immediatly.

        Unlike in Mac OS X, it appears there is no way to cancel the termination.

        This doesn't give the SDL user's application time to respond to an SDL_Quit event.
        So what we do is that in the UIApplicationDelegate class (SDLUIApplicationDelegate),
        when the delegate receives the ApplicationWillTerminate message, we execute
        a longjmp statement to get back here, preventing an immediate exit.
     */
    if (setjmp(*jump_env()) == 0) {
        /* if we're setting the jump, rather than jumping back */
        SInt32 result;
        do {
            result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, TRUE);
        } while (result == kCFRunLoopRunHandledSource);
    }
}


This stops SDL processing all the events ( I added a return at the top of the function ). This fixes SDL crashing some times when other views are laid over the top. The problem of needing the long jump is avoided as this message will be processed when iOS sends the message and not during the next update.

The next thing that needs to be done is to intercept the events as they occur, fortunately this is an easy thing to do. Create a callback function and inform SDL, like so. Always return 0, this will stop SDL from storing the event.
Code:

 int SystemEventCallback(SDL_Event* event)
 {
     MyEventHandler::instance().OnEvent(event);
    return 0;
}

// Add this line to the initialisation code.
SDL_SetEventFilter(EventCallback, NULL);


The event handler looks something like this. (Remember that the events are processed as they occur, so save results when needed)
Code:

void EventHandler::OnEvent(SDL_Event *aEvent)
{
   switch (aEvent->type)
       {
    case SDL_WINDOWEVENT:
        {
            switch (aEvent->window.event)
            {
                case SDL_WINDOWEVENT_FOCUS_LOST:
                    OnLostFocus();
                    break;
                case SDL_WINDOWEVENT_FOCUS_GAINED:
                    OnGainedFocus();
                    break;
            }
            break;
          }
       }
}


Not sure these events work I applied the patch http://forums.libsdl.org/viewtopic.php?t=7733&sid=c9ade150b99a01c8f080cdd465f21b11 to this code so I use the SDL_SYSEVENT_WILL_SUSPEND and SDL_SYSEVENT_WILL_SUSPEND events.

So now we are half done, the other problem is that SDL runs in a tight loop. It is time to change this to an event driven approach. First SDL_uikitopenglview needs to be modified. Create a new objective c class and implement as follows. (Header first)
Code:

#import <UIKit/UIKit.h>
#import "./sdl/src/video/uikit/SDL_uikitopenglview.h"

@interface SDL_uikitopenglview (MYOpenGLView)

- (void)startAnimation;
- (void)stopAnimation;

- (void)doLoop:(id)sender;
@end


Code:

#import "MYOpenGLView.h"
#import <OpenGLES/EAGLDrawable.h>
#import <QuartzCore/QuartzCore.h>
#include "SDL.h"
// a file that will let me use c++ for SDL
#include "SystemCalls.h"

id displayLink;
NSInteger animationFrameInterval = 1;

@implementation SDL_uikitopenglview (MYOpenGLView)

// make an exact copy of the SDL function
- (id)initWithFrame:(CGRect)frame
      retainBacking:(BOOL)retained
              rBits:(int)rBits
              gBits:(int)gBits
              bBits:(int)bBits
              aBits:(int)aBits
          depthBits:(int)depthBits
        stencilBits:(int)stencilBits
       majorVersion:(int)majorVersion
{
    depthBufferFormat = 0;
   
    if ((self = [super initWithFrame:frame])) {
        const BOOL useStencilBuffer = (stencilBits != 0);
        const BOOL useDepthBuffer = (depthBits != 0);
        NSString *colorFormat = nil;
       
        if (rBits == 8 && gBits == 8 && bBits == 8) {
            /* if user specifically requests rbg888 or some color format higher than 16bpp */
            colorFormat = kEAGLColorFormatRGBA8;
        } else {
            /* default case (faster) */
            colorFormat = kEAGLColorFormatRGB565;
        }
       
        /* Get the layer */
        CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
       
        eaglLayer.opaque = YES;
        eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
                                        [NSNumber numberWithBool: retained], kEAGLDrawablePropertyRetainedBacking, colorFormat, kEAGLDrawablePropertyColorFormat, nil];
       
        if (majorVersion > 1) {
            context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES2];
        } else {
            context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES1];
        }
        if (!context || ![EAGLContext setCurrentContext:context]) {
            [self release];
            SDL_SetError("OpenGL ES %d not supported", majorVersion);
            return nil;
        }
       
        // !!! FIXME: use the screen this is on!
        /* Use the main screen scale (for retina display support) */
        if ([self respondsToSelector:@selector(contentScaleFactor)])
            self.contentScaleFactor = [UIScreen mainScreen].scale;
       
        /* create the buffers */
        glGenFramebuffersOES(1, &viewFramebuffer);
        glGenRenderbuffersOES(1, &viewRenderbuffer);
       
        glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
        glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
        [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer];
        glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);
       
        glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
        glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
       
        if ((useDepthBuffer) || (useStencilBuffer)) {
            if (useStencilBuffer) {
                /* Apparently you need to pack stencil and depth into one buffer. */
                depthBufferFormat = GL_DEPTH24_STENCIL8_OES;
            } else if (useDepthBuffer) {
                /* iOS only has 24-bit depth buffers, even with GL_DEPTH_COMPONENT16_OES */
                depthBufferFormat = GL_DEPTH_COMPONENT24_OES;
            }
           
            glGenRenderbuffersOES(1, &depthRenderbuffer);
            glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
            glRenderbufferStorageOES(GL_RENDERBUFFER_OES, depthBufferFormat, backingWidth, backingHeight);
            if (useDepthBuffer) {
                glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
            }
            if (useStencilBuffer) {
                glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_STENCIL_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
            }
        }
       
        if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) {
            return NO;
        }
        /* end create buffers */
       
        self.autoresizingMask = 0;  // don't allow autoresize, since we need to do some magic in -(void)updateFrame.
       
        [self startAnimation];
    }
    return self;
}

- (void)startAnimation
{
    // CADisplayLink is API new to iPhone SDK 3.1. Compiling against earlier versions will result in a warning, but can be dismissed
    // if the system version runtime check for CADisplayLink exists in -initWithCoder:.
   
    displayLink = [NSClassFromString(@"CADisplayLink") displayLinkWithTarget:self selector:@selector(doLoop:)];
    [displayLink setFrameInterval:animationFrameInterval];
    [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}

- (void)stopAnimation
{
    [displayLink invalidate];
    displayLink = nil;
}

- (void)doLoop:(id)sender
{
    runApplicationFrame();
}
@end


The initWithFrame function is a copy of the function in SDL with one exception [self startAnimation];. This is the important part as it sets up the way that we do a loop by callback. The start animation function basically sets up the doLoop function to run every x number of frames. Set this animationFrameInterval variable to 1 to run every frame, 2 for every 2nd frame etc. For more details (and other ways to do this) http://www.ananseproductions.com/game-loops-on-ios/.

Call the stopAnimation function when the application is suspended; and call the startAnimation function when the application resumes.

Lastly setup the function to run the application runApplicationFrame();.
Code:

void runApplicationFrame()
{
   // iOS uses a push event system instead of a pull event system
#ifdef WIN32
    SDL_Event Event;
    while (SDL_PollEvent(&Event))
    {
       OnEvent(&Event);
    }
#else
    /* Check for joystick state change */
    SDL_JoystickUpdate();
#endif // WIN32

   // do update stuff here

   // do render stuff here
   SDL_RenderClear(mRenderer);
   SDL_RenderCopy(mRenderer, mPrimaryTexture, NULL, &destRect);
   SDL_RenderPresent(mRenderer);
}


I am assuming that SDL has already been setup, this can all happen as usual. The important one is the SDL_JoystickUpdate (if you are using it) as it was called in the PollEvent function.

Game center and all other iOS windows will now work correctly.

Enjoy
BJ


Joined: 01 May 2012
Posts: 18
Location: Australia
If you need access to the application delegate, window, view or view controller here is how to do it.

Code:

#include "./sdl/src/video/uikit/SDL_uikitappDelegate.h"
#include "./sdl/src/video/uikit/SDL_uikitwindow.h"

SDL_uikitviewcontroller *gViewColtroller = NULL;
UIWindow *gWindow = NULL;
SDL_uikitopenglview *gView = NULL;
SDLUIKitDelegate *gApplicationDelegate = NULL;

void SetUIViewController(SDL_Window *aWindow)
{
    SDL_WindowData *data = (SDL_WindowData *)aWindow->driverdata;
    gViewColtroller = data->viewcontroller;
    gWindow = data->uiwindow;
    gView = data->view;

    gApplicationDelegate = [SDLUIKitDelegate sharedAppDelegate];
}

Just pass in the window, that you have made. Your includes maybe different depending where you have placed the SDL library.
How to make SDL 2.0, iOS work together. (Game Center too)
Brian Barnes
Guest

BJ wrote:

Quote:
The problem is that SDL uses a pull messaging system, but iOS requires a pull system. Here is how to get the two working together correctly.
(I am using this on a project that is on PC and iOS)

This is the 3rd different solution for this.

I want to note a couple problems with it.

1. (I made the same mistake), we don't need to add some new callback to get events in a callback. SDL_EventFilter will actually handle that already, you just need to add the new events.
2. You HAVE to have separate events for will suspend, will resume, did enter background, did enter foreground, low memory, and quit. You can NOT just over ride it as if it's a activate/deactivate, this will NOT follow the guide lines and you WILL have crazy hard to fix crashes.
3. The changes to pump events is unnecessary, just remove the long jump stuff
4. The start/stop animation is a bit different than SDL works anywhere else and is a pretty big mountain to climb. Is that what is causing the game center problem?

There's my patch, there's Piotr's patch, and there's this (which doesn't solve other problems).

I think the solution is use SDL_EventFilter and just add the necessary 6 events. I can work up a patch that does just this, it's a small change from my patch.

Adding these additional calls, through whatever callback mechanism, makes SDL work great for me. Not sure exactly what the game center problem is though, so some of this might be required.

[>] Brian






_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
How to make SDL 2.0, iOS work together. (Game Center too)
Sam Lantinga


Joined: 10 Sep 2009
Posts: 1765
BJ, do you have an example of using Game Center with an SDL app set up this way?

Thanks!

On Thu, May 3, 2012 at 12:27 AM, BJ wrote:
Quote:
The problem is that SDL uses a pull messaging system, but iOS requires a pull system. Here is how to get the two working together correctly.
(I am using this on a project that is on PC and iOS)

This only change that I made to SDL was as follows



Code:


void
UIKit_PumpEvents(_THIS)
{
    return;
    /*
        When the user presses the 'home' button on the iPod
        the application exits -- immediatly.

        Unlike in Mac OS X, it appears there is no way to cancel the termination.

        This doesn't give the SDL user's application time to respond to an SDL_Quit event.
        So what we do is that in the UIApplicationDelegate class (SDLUIApplicationDelegate),
        when the delegate receives the ApplicationWillTerminate message, we execute
        a longjmp statement to get back here, preventing an immediate exit.
     */
    if (setjmp(*jump_env()) == 0) {
        /* if we're setting the jump, rather than jumping back */
        SInt32 result;
        do {
            result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, TRUE);
        } while (result == kCFRunLoopRunHandledSource);
    }
}





This stops SDL processing all the events ( I added a return at the top of the function ). This fixes SDL crashing some times when other views are laid over the top. The problem of needing the long jump is avoided as this message will be processed when iOS sends the message and not during the next update.

The next thing that needs to be done is to intercept the events as they occur, fortunately this is an easy thing to do. Create a callback function and inform SDL, like so. Always return 0, this will stop SDL from storing the event.



Code:


 int SystemEventCallback(SDL_Event* event)
 {
     MyEventHandler::instance().OnEvent(event);
    return 0;
}

// Add this line to the initialisation code.
SDL_SetEventFilter(EventCallback, NULL);





The event handler looks something like this. (Remember that the events are processed as they occur, so save results when needed)



Code:


void EventHandler::OnEvent(SDL_Event *aEvent)
{
   switch (aEvent->type)
       {
    case SDL_WINDOWEVENT:
        {
            switch (aEvent->window.event)
            {
                case SDL_WINDOWEVENT_FOCUS_LOST:
                    OnLostFocus();
                    break;
                case SDL_WINDOWEVENT_FOCUS_GAINED:
                    OnGainedFocus();
                    break;
            }
            break;
          }
       }
}





Not sure these events work I applied the patch http://forums.libsdl.org/viewtopic.php?t=7733&sid=c9ade150b99a01c8f080cdd465f21b11 to this code so I use the SDL_SYSEVENT_WILL_SUSPEND and SDL_SYSEVENT_WILL_SUSPEND events.

So now we are half done, the other problem is that SDL runs in a tight loop. It is time to change this to an event driven approach. First SDL_uikitopenglview needs to be modified. Create a new objective c class and implement as follows. (Header first)



Code:


#import
#import "./sdl/src/video/uikit/SDL_uikitopenglview.h"

@interface SDL_uikitopenglview (MYOpenGLView)

- (void)startAnimation;
- (void)stopAnimation;

- (void)doLoop:(id)sender;
@end








Code:


#import "MYOpenGLView.h"
#import
#import
#include "SDL.h"
// a file that will let me use c++ for SDL
#include "SystemCalls.h"

id displayLink;
NSInteger animationFrameInterval = 1;

@implementation SDL_uikitopenglview (MYOpenGLView)

// make an exact copy of the SDL function
- (id)initWithFrame:(CGRect)frame
      retainBacking:(BOOL)retained
              rBits:(int)rBits
              gBits:(int)gBits
              bBits:(int)bBits
              aBits:(int)aBits
          depthBits:(int)depthBits
        stencilBits:(int)stencilBits
       majorVersion:(int)majorVersion
{
    depthBufferFormat = 0;
   
    if ((self = [super initWithFrame:frame])) {
        const BOOL useStencilBuffer = (stencilBits != 0);
        const BOOL useDepthBuffer = (depthBits != 0);
        NSString *colorFormat = nil;
       
        if (rBits == 8 && gBits == 8 && bBits == Cool {
            /* if user specifically requests rbg888 or some color format higher than 16bpp */
            colorFormat = kEAGLColorFormatRGBA8;
        } else {
            /* default case (faster) */
            colorFormat = kEAGLColorFormatRGB565;
        }
       
        /* Get the layer */
        CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
       
        eaglLayer.opaque = YES;
        eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
                                        [NSNumber numberWithBool: retained], kEAGLDrawablePropertyRetainedBacking, colorFormat, kEAGLDrawablePropertyColorFormat, nil];
       
        if (majorVersion > 1) {
            context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES2];
        } else {
            context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES1];
        }
        if (!context || ![EAGLContext setCurrentContext:context]) {
            [self release];
            SDL_SetError("OpenGL ES %d not supported", majorVersion);
            return nil;
        }
       
        // !!! FIXME: use the screen this is on!
        /* Use the main screen scale (for retina display support) */
        if ([self respondsToSelector:@selector(contentScaleFactor)])
            self.contentScaleFactor = [UIScreen mainScreen].scale;
       
        /* create the buffers */
        glGenFramebuffersOES(1, &viewFramebuffer);
        glGenRenderbuffersOES(1, &viewRenderbuffer);
       
        glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
        glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
        [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer];
        glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);
       
        glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
        glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
       
        if ((useDepthBuffer) || (useStencilBuffer)) {
            if (useStencilBuffer) {
                /* Apparently you need to pack stencil and depth into one buffer. */
                depthBufferFormat = GL_DEPTH24_STENCIL8_OES;
            } else if (useDepthBuffer) {
                /* iOS only has 24-bit depth buffers, even with GL_DEPTH_COMPONENT16_OES */
                depthBufferFormat = GL_DEPTH_COMPONENT24_OES;
            }
           
            glGenRenderbuffersOES(1, &depthRenderbuffer);
            glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
            glRenderbufferStorageOES(GL_RENDERBUFFER_OES, depthBufferFormat, backingWidth, backingHeight);
            if (useDepthBuffer) {
                glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
            }
            if (useStencilBuffer) {
                glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_STENCIL_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
            }
        }
       
        if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) {
            return NO;
        }
        /* end create buffers */
       
        self.autoresizingMask = 0;  // don't allow autoresize, since we need to do some magic in -(void)updateFrame.
       
        [self startAnimation];
    }
    return self;
}

- (void)startAnimation
{
    // CADisplayLink is API new to iPhone SDK 3.1. Compiling against earlier versions will result in a warning, but can be dismissed
    // if the system version runtime check for CADisplayLink exists in -initWithCoder:.
   
    displayLink = [NSClassFromString(@"CADisplayLink") displayLinkWithTarget:self selector:@selector(doLoop:)];
    [displayLink setFrameInterval:animationFrameInterval];
    [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}

- (void)stopAnimation
{
    [displayLink invalidate];
    displayLink = nil;
}

- (void)doLoop:(id)sender
{
    runApplicationFrame();
}
@end





The initWithFrame function is a copy of the function in SDL with one exception [self startAnimation];. This is the important part as it sets up the way that we do a loop by callback. The start animation function basically sets up the doLoop function to run every x number of frames. Set this animationFrameInterval variable to 1 to run every frame, 2 for every 2nd frame etc. For more details (and other ways to do this) http://www.ananseproductions.com/game-loops-on-ios/.

Call the stopAnimation function when the application is suspended; and call the startAnimation function when the application resumes.

Lastly setup the function to run the application runApplicationFrame();.



Code:


void runApplicationFrame()
{
   // iOS uses a push event system instead of a pull event system
#ifdef WIN32
    SDL_Event Event;
    while (SDL_PollEvent(&Event))
    {
       OnEvent(&Event);
    }
#else
    /* Check for joystick state change */
    SDL_JoystickUpdate();
#endif // WIN32

   // do update stuff here

   // do render stuff here
   SDL_RenderClear(mRenderer);
   SDL_RenderCopy(mRenderer, mPrimaryTexture, NULL, &destRect);
   SDL_RenderPresent(mRenderer);
}





I am assuming that SDL has already been setup, this can all happen as usual. The important one is the SDL_JoystickUpdate (if you are using it) as it was called in the PollEvent function.

Game center and all other iOS windows will now work correctly.

Enjoy


_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

How to make SDL 2.0, iOS work together. (Game Center too)
BJ


Joined: 01 May 2012
Posts: 18
Location: Australia
Yes, I do. I can't give you the commercial version; but I did make a little test app before adding it to the commercial one.

Would you like a copy of the xcode project?
How to make SDL 2.0, iOS work together. (Game Center too)
Sam Lantinga


Joined: 10 Sep 2009
Posts: 1765
Yes please.  Thanks!

On Mon, May 28, 2012 at 12:44 AM, Brad Jackson wrote:
Quote:
Yes, I do. I can't give you the commercial version; but I did make a little test app before adding it to the commercial one.

Would you like a copy of the xcode project?



On Sun, May 27, 2012 at 3:47 AM, Sam Lantinga wrote:
Quote:
BJ, do you have an example of using Game Center with an SDL app set up this way?

Thanks!

On Thu, May 3, 2012 at 12:27 AM, BJ wrote:
Quote:
The problem is that SDL uses a pull messaging system, but iOS requires a pull system. Here is how to get the two working together correctly.
(I am using this on a project that is on PC and iOS)

This only change that I made to SDL was as follows



Code:


void
UIKit_PumpEvents(_THIS)
{
    return;
    /*
        When the user presses the 'home' button on the iPod
        the application exits -- immediatly.

        Unlike in Mac OS X, it appears there is no way to cancel the termination.

        This doesn't give the SDL user's application time to respond to an SDL_Quit event.
        So what we do is that in the UIApplicationDelegate class (SDLUIApplicationDelegate),
        when the delegate receives the ApplicationWillTerminate message, we execute
        a longjmp statement to get back here, preventing an immediate exit.
     */
    if (setjmp(*jump_env()) == 0) {
        /* if we're setting the jump, rather than jumping back */
        SInt32 result;
        do {
            result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, TRUE);
        } while (result == kCFRunLoopRunHandledSource);
    }
}





This stops SDL processing all the events ( I added a return at the top of the function ). This fixes SDL crashing some times when other views are laid over the top. The problem of needing the long jump is avoided as this message will be processed when iOS sends the message and not during the next update.

The next thing that needs to be done is to intercept the events as they occur, fortunately this is an easy thing to do. Create a callback function and inform SDL, like so. Always return 0, this will stop SDL from storing the event.



Code:


 int SystemEventCallback(SDL_Event* event)
 {
     MyEventHandler::instance().OnEvent(event);
    return 0;
}

// Add this line to the initialisation code.
SDL_SetEventFilter(EventCallback, NULL);





The event handler looks something like this. (Remember that the events are processed as they occur, so save results when needed)



Code:


void EventHandler::OnEvent(SDL_Event *aEvent)
{
   switch (aEvent->type)
       {
    case SDL_WINDOWEVENT:
        {
            switch (aEvent->window.event)
            {
                case SDL_WINDOWEVENT_FOCUS_LOST:
                    OnLostFocus();
                    break;
                case SDL_WINDOWEVENT_FOCUS_GAINED:
                    OnGainedFocus();
                    break;
            }
            break;
          }
       }
}





Not sure these events work I applied the patch http://forums.libsdl.org/viewtopic.php?t=7733&sid=c9ade150b99a01c8f080cdd465f21b11 to this code so I use the SDL_SYSEVENT_WILL_SUSPEND and SDL_SYSEVENT_WILL_SUSPEND events.

So now we are half done, the other problem is that SDL runs in a tight loop. It is time to change this to an event driven approach. First SDL_uikitopenglview needs to be modified. Create a new objective c class and implement as follows. (Header first)



Code:


#import
#import "./sdl/src/video/uikit/SDL_uikitopenglview.h"

@interface SDL_uikitopenglview (MYOpenGLView)

- (void)startAnimation;
- (void)stopAnimation;

- (void)doLoop:(id)sender;
@end








Code:


#import "MYOpenGLView.h"
#import
#import
#include "SDL.h"
// a file that will let me use c++ for SDL
#include "SystemCalls.h"

id displayLink;
NSInteger animationFrameInterval = 1;

@implementation SDL_uikitopenglview (MYOpenGLView)

// make an exact copy of the SDL function
- (id)initWithFrame:(CGRect)frame
      retainBacking:(BOOL)retained
              rBits:(int)rBits
              gBits:(int)gBits
              bBits:(int)bBits
              aBits:(int)aBits
          depthBits:(int)depthBits
        stencilBits:(int)stencilBits
       majorVersion:(int)majorVersion
{
    depthBufferFormat = 0;
   
    if ((self = [super initWithFrame:frame])) {
        const BOOL useStencilBuffer = (stencilBits != 0);
        const BOOL useDepthBuffer = (depthBits != 0);
        NSString *colorFormat = nil;
       
        if (rBits == 8 && gBits == 8 && bBits == Cool {
            /* if user specifically requests rbg888 or some color format higher than 16bpp */
            colorFormat = kEAGLColorFormatRGBA8;
        } else {
            /* default case (faster) */
            colorFormat = kEAGLColorFormatRGB565;
        }
       
        /* Get the layer */
        CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
       
        eaglLayer.opaque = YES;
        eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
                                        [NSNumber numberWithBool: retained], kEAGLDrawablePropertyRetainedBacking, colorFormat, kEAGLDrawablePropertyColorFormat, nil];
       
        if (majorVersion > 1) {
            context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES2];
        } else {
            context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES1];
        }
        if (!context || ![EAGLContext setCurrentContext:context]) {
            [self release];
            SDL_SetError("OpenGL ES %d not supported", majorVersion);
            return nil;
        }
       
        // !!! FIXME: use the screen this is on!
        /* Use the main screen scale (for retina display support) */
        if ([self respondsToSelector:@selector(contentScaleFactor)])
            self.contentScaleFactor = [UIScreen mainScreen].scale;
       
        /* create the buffers */
        glGenFramebuffersOES(1, &viewFramebuffer);
        glGenRenderbuffersOES(1, &viewRenderbuffer);
       
        glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
        glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
        [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer];
        glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);
       
        glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
        glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
       
        if ((useDepthBuffer) || (useStencilBuffer)) {
            if (useStencilBuffer) {
                /* Apparently you need to pack stencil and depth into one buffer. */
                depthBufferFormat = GL_DEPTH24_STENCIL8_OES;
            } else if (useDepthBuffer) {
                /* iOS only has 24-bit depth buffers, even with GL_DEPTH_COMPONENT16_OES */
                depthBufferFormat = GL_DEPTH_COMPONENT24_OES;
            }
           
            glGenRenderbuffersOES(1, &depthRenderbuffer);
            glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
            glRenderbufferStorageOES(GL_RENDERBUFFER_OES, depthBufferFormat, backingWidth, backingHeight);
            if (useDepthBuffer) {
                glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
            }
            if (useStencilBuffer) {
                glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_STENCIL_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
            }
        }
       
        if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) {
            return NO;
        }
        /* end create buffers */
       
        self.autoresizingMask = 0;  // don't allow autoresize, since we need to do some magic in -(void)updateFrame.
       
        [self startAnimation];
    }
    return self;
}

- (void)startAnimation
{
    // CADisplayLink is API new to iPhone SDK 3.1. Compiling against earlier versions will result in a warning, but can be dismissed
    // if the system version runtime check for CADisplayLink exists in -initWithCoder:.
   
    displayLink = [NSClassFromString(@"CADisplayLink") displayLinkWithTarget:self selector:@selector(doLoop:)];
    [displayLink setFrameInterval:animationFrameInterval];
    [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}

- (void)stopAnimation
{
    [displayLink invalidate];
    displayLink = nil;
}

- (void)doLoop:(id)sender
{
    runApplicationFrame();
}
@end





The initWithFrame function is a copy of the function in SDL with one exception [self startAnimation];. This is the important part as it sets up the way that we do a loop by callback. The start animation function basically sets up the doLoop function to run every x number of frames. Set this animationFrameInterval variable to 1 to run every frame, 2 for every 2nd frame etc. For more details (and other ways to do this) http://www.ananseproductions.com/game-loops-on-ios/.

Call the stopAnimation function when the application is suspended; and call the startAnimation function when the application resumes.

Lastly setup the function to run the application runApplicationFrame();.



Code:


void runApplicationFrame()
{
   // iOS uses a push event system instead of a pull event system
#ifdef WIN32
    SDL_Event Event;
    while (SDL_PollEvent(&Event))
    {
       OnEvent(&Event);
    }
#else
    /* Check for joystick state change */
    SDL_JoystickUpdate();
#endif // WIN32

   // do update stuff here

   // do render stuff here
   SDL_RenderClear(mRenderer);
   SDL_RenderCopy(mRenderer, mPrimaryTexture, NULL, &destRect);
   SDL_RenderPresent(mRenderer);
}





I am assuming that SDL has already been setup, this can all happen as usual. The important one is the SDL_JoystickUpdate (if you are using it) as it was called in the PollEvent function.

Game center and all other iOS windows will now work correctly.

Enjoy


_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org










--
-----------------------------
Have you seen Tumblebugs 2 yet?


www.wildfire.com.au


Brad Jackson - Senior Game Programmer
Wildfire Studios Pty. Ltd.
[url=tel:%2B61%20%280%297%203844%201000]+61 (0)7 3844 1000[/url] (office) 
[url=tel:%2B61%20%280%297%203844%208970]+61 (0)7 3844 8970[/url] (fax)
-----------------------------
This email is for the sole use of the addressee/s. It should not be copied, saved or distributed. If received in error, inform the sender and delete it from your mailbox and other storage mechanism. Opinions and advice expressed in this email are those of the sender and may not reflect the views of the company, Wildfire Studios Pty Ltd.


How to make SDL 2.0, iOS work together. (Game Center too)
BJ


Joined: 01 May 2012
Posts: 18
Location: Australia
I have just shared the code from my google docs.

Hope that helps.

https://docs.google.com/open?id=0B0oC0oisumE2NTk0R0N4MEJibEk
Re: How to make SDL 2.0, iOS work together. (Game Center too
BJ


Joined: 01 May 2012
Posts: 18
Location: Australia
The 4th step is essential for Game Center to work, or the messages that the game center windows puts out are lost. iOS expects the applications to take a 'break' between updates to allow other processes to happen.

Brian Barnes wrote:
BJ wrote:

Quote:
The problem is that SDL uses a pull messaging system, but iOS requires a pull system. Here is how to get the two working together correctly.
(I am using this on a project that is on PC and iOS)

This is the 3rd different solution for this.

I want to note a couple problems with it.

1. (I made the same mistake), we don't need to add some new callback to get events in a callback. SDL_EventFilter will actually handle that already, you just need to add the new events.
2. You HAVE to have separate events for will suspend, will resume, did enter background, did enter foreground, low memory, and quit. You can NOT just over ride it as if it's a activate/deactivate, this will NOT follow the guide lines and you WILL have crazy hard to fix crashes.
3. The changes to pump events is unnecessary, just remove the long jump stuff
4. The start/stop animation is a bit different than SDL works anywhere else and is a pretty big mountain to climb. Is that what is causing the game center problem?

There's my patch, there's Piotr's patch, and there's this (which doesn't solve other problems).

I think the solution is use SDL_EventFilter and just add the necessary 6 events. I can work up a patch that does just this, it's a small change from my patch.

Adding these additional calls, through whatever callback mechanism, makes SDL work great for me. Not sure exactly what the game center problem is though, so some of this might be required.

[>] Brian






_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org