mirror of
https://github.com/Ryujinx/SDL.git
synced 2024-12-25 07:35:38 +00:00
iOS: Fixed some cases where SDL_DestroyWindow or SDL_GL_DeleteContext can cause crashes.
This commit is contained in:
parent
cd1d7c94e9
commit
a86df3b7cf
|
@ -34,6 +34,24 @@
|
||||||
#include "SDL_loadso.h"
|
#include "SDL_loadso.h"
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
|
||||||
|
@interface SDLEAGLContext : EAGLContext
|
||||||
|
|
||||||
|
/* The OpenGL ES context owns a view / drawable. */
|
||||||
|
@property (nonatomic, strong) SDL_uikitopenglview *sdlView;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation SDLEAGLContext
|
||||||
|
|
||||||
|
- (void)dealloc
|
||||||
|
{
|
||||||
|
/* When the context is deallocated, its view should be removed from any
|
||||||
|
* SDL window that it's attached to. */
|
||||||
|
[self.sdlView setSDLWindow:NULL];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
static int UIKit_GL_Initialize(_THIS);
|
static int UIKit_GL_Initialize(_THIS);
|
||||||
|
|
||||||
void *
|
void *
|
||||||
|
@ -117,12 +135,17 @@ SDL_GLContext
|
||||||
UIKit_GL_CreateContext(_THIS, SDL_Window * window)
|
UIKit_GL_CreateContext(_THIS, SDL_Window * window)
|
||||||
{
|
{
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
|
SDLEAGLContext *context = nil;
|
||||||
SDL_uikitopenglview *view;
|
SDL_uikitopenglview *view;
|
||||||
SDL_WindowData *data = (__bridge SDL_WindowData *) window->driverdata;
|
SDL_WindowData *data = (__bridge SDL_WindowData *) window->driverdata;
|
||||||
CGRect frame = UIKit_ComputeViewFrame(window, data.uiwindow.screen);
|
CGRect frame = UIKit_ComputeViewFrame(window, data.uiwindow.screen);
|
||||||
EAGLSharegroup *sharegroup = nil;
|
EAGLSharegroup *sharegroup = nil;
|
||||||
CGFloat scale = 1.0;
|
CGFloat scale = 1.0;
|
||||||
|
|
||||||
|
/* The EAGLRenderingAPI enum values currently map 1:1 to major GLES
|
||||||
|
* versions. */
|
||||||
|
EAGLRenderingAPI api = _this->gl_config.major_version;
|
||||||
|
|
||||||
if (_this->gl_config.share_with_current_context) {
|
if (_this->gl_config.share_with_current_context) {
|
||||||
EAGLContext *context = (__bridge EAGLContext *) SDL_GL_GetCurrentContext();
|
EAGLContext *context = (__bridge EAGLContext *) SDL_GL_GetCurrentContext();
|
||||||
sharegroup = context.sharegroup;
|
sharegroup = context.sharegroup;
|
||||||
|
@ -142,6 +165,12 @@ UIKit_GL_CreateContext(_THIS, SDL_Window * window)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
context = [[SDLEAGLContext alloc] initWithAPI:api sharegroup:sharegroup];
|
||||||
|
if (!context) {
|
||||||
|
SDL_SetError("OpenGL ES %d context could not be created", _this->gl_config.major_version);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* construct our view, passing in SDL's OpenGL configuration data */
|
/* construct our view, passing in SDL's OpenGL configuration data */
|
||||||
view = [[SDL_uikitopenglview alloc] initWithFrame:frame
|
view = [[SDL_uikitopenglview alloc] initWithFrame:frame
|
||||||
scale:scale
|
scale:scale
|
||||||
|
@ -153,13 +182,15 @@ UIKit_GL_CreateContext(_THIS, SDL_Window * window)
|
||||||
depthBits:_this->gl_config.depth_size
|
depthBits:_this->gl_config.depth_size
|
||||||
stencilBits:_this->gl_config.stencil_size
|
stencilBits:_this->gl_config.stencil_size
|
||||||
sRGB:_this->gl_config.framebuffer_srgb_capable
|
sRGB:_this->gl_config.framebuffer_srgb_capable
|
||||||
majorVersion:_this->gl_config.major_version
|
context:context];
|
||||||
shareGroup:sharegroup];
|
|
||||||
if (!view) {
|
if (!view) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDLEAGLContext *context = view.context;
|
/* The context owns the view / drawable. */
|
||||||
|
context.sdlView = view;
|
||||||
|
|
||||||
if (UIKit_GL_MakeCurrent(_this, window, (__bridge SDL_GLContext) context) < 0) {
|
if (UIKit_GL_MakeCurrent(_this, window, (__bridge SDL_GLContext) context) < 0) {
|
||||||
UIKit_GL_DeleteContext(_this, (SDL_GLContext) CFBridgingRetain(context));
|
UIKit_GL_DeleteContext(_this, (SDL_GLContext) CFBridgingRetain(context));
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -175,11 +206,10 @@ void
|
||||||
UIKit_GL_DeleteContext(_THIS, SDL_GLContext context)
|
UIKit_GL_DeleteContext(_THIS, SDL_GLContext context)
|
||||||
{
|
{
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
/* Transfer ownership the +1'd context to ARC. */
|
/* The context was retained in SDL_GL_CreateContext, so we release it
|
||||||
SDLEAGLContext *eaglcontext = (SDLEAGLContext *) CFBridgingRelease(context);
|
* here. The context's view will be detached from its window when the
|
||||||
|
* context is deallocated. */
|
||||||
/* Detach the context's view from its window. */
|
CFRelease(context);
|
||||||
[eaglcontext.sdlView setSDLWindow:NULL];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,14 +26,6 @@
|
||||||
#import "SDL_uikitview.h"
|
#import "SDL_uikitview.h"
|
||||||
#include "SDL_uikitvideo.h"
|
#include "SDL_uikitvideo.h"
|
||||||
|
|
||||||
@class SDL_uikitopenglview;
|
|
||||||
|
|
||||||
@interface SDLEAGLContext : EAGLContext
|
|
||||||
|
|
||||||
@property (nonatomic, weak) SDL_uikitopenglview *sdlView;
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
@interface SDL_uikitopenglview : SDL_uikitview
|
@interface SDL_uikitopenglview : SDL_uikitview
|
||||||
|
|
||||||
- (instancetype)initWithFrame:(CGRect)frame
|
- (instancetype)initWithFrame:(CGRect)frame
|
||||||
|
@ -46,10 +38,9 @@
|
||||||
depthBits:(int)depthBits
|
depthBits:(int)depthBits
|
||||||
stencilBits:(int)stencilBits
|
stencilBits:(int)stencilBits
|
||||||
sRGB:(BOOL)sRGB
|
sRGB:(BOOL)sRGB
|
||||||
majorVersion:(int)majorVersion
|
context:(EAGLContext *)glcontext;
|
||||||
shareGroup:(EAGLSharegroup*)shareGroup;
|
|
||||||
|
|
||||||
@property (nonatomic, readonly, strong) SDLEAGLContext *context;
|
@property (nonatomic, readonly, weak) EAGLContext *context;
|
||||||
|
|
||||||
/* The width and height of the drawable in pixels (as opposed to points.) */
|
/* The width and height of the drawable in pixels (as opposed to points.) */
|
||||||
@property (nonatomic, readonly) int backingWidth;
|
@property (nonatomic, readonly) int backingWidth;
|
||||||
|
@ -59,7 +50,6 @@
|
||||||
@property (nonatomic, readonly) GLuint drawableFramebuffer;
|
@property (nonatomic, readonly) GLuint drawableFramebuffer;
|
||||||
|
|
||||||
- (void)swapBuffers;
|
- (void)swapBuffers;
|
||||||
- (void)setCurrentContext;
|
|
||||||
|
|
||||||
- (void)updateFrame;
|
- (void)updateFrame;
|
||||||
|
|
||||||
|
|
|
@ -27,10 +27,6 @@
|
||||||
#import "SDL_uikitopenglview.h"
|
#import "SDL_uikitopenglview.h"
|
||||||
#include "SDL_uikitwindow.h"
|
#include "SDL_uikitwindow.h"
|
||||||
|
|
||||||
@implementation SDLEAGLContext
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
@implementation SDL_uikitopenglview {
|
@implementation SDL_uikitopenglview {
|
||||||
/* The renderbuffer and framebuffer used to render to this layer. */
|
/* The renderbuffer and framebuffer used to render to this layer. */
|
||||||
GLuint viewRenderbuffer, viewFramebuffer;
|
GLuint viewRenderbuffer, viewFramebuffer;
|
||||||
|
@ -61,26 +57,20 @@
|
||||||
depthBits:(int)depthBits
|
depthBits:(int)depthBits
|
||||||
stencilBits:(int)stencilBits
|
stencilBits:(int)stencilBits
|
||||||
sRGB:(BOOL)sRGB
|
sRGB:(BOOL)sRGB
|
||||||
majorVersion:(int)majorVersion
|
context:(EAGLContext *)glcontext
|
||||||
shareGroup:(EAGLSharegroup*)shareGroup
|
|
||||||
{
|
{
|
||||||
if ((self = [super initWithFrame:frame])) {
|
if ((self = [super initWithFrame:frame])) {
|
||||||
const BOOL useStencilBuffer = (stencilBits != 0);
|
const BOOL useStencilBuffer = (stencilBits != 0);
|
||||||
const BOOL useDepthBuffer = (depthBits != 0);
|
const BOOL useDepthBuffer = (depthBits != 0);
|
||||||
NSString *colorFormat = nil;
|
NSString *colorFormat = nil;
|
||||||
|
|
||||||
/* The EAGLRenderingAPI enum values currently map 1:1 to major GLES
|
context = glcontext;
|
||||||
* versions, and this allows us to handle future OpenGL ES versions. */
|
|
||||||
EAGLRenderingAPI api = majorVersion;
|
|
||||||
|
|
||||||
context = [[SDLEAGLContext alloc] initWithAPI:api sharegroup:shareGroup];
|
|
||||||
if (!context || ![EAGLContext setCurrentContext:context]) {
|
if (!context || ![EAGLContext setCurrentContext:context]) {
|
||||||
SDL_SetError("OpenGL ES %d not supported", majorVersion);
|
SDL_SetError("Could not create OpenGL ES drawable (could not make context current)");
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
context.sdlView = self;
|
|
||||||
|
|
||||||
if (sRGB) {
|
if (sRGB) {
|
||||||
/* sRGB EAGL drawable support was added in iOS 7. */
|
/* sRGB EAGL drawable support was added in iOS 7. */
|
||||||
if (UIKit_IsSystemVersionAtLeast(7.0)) {
|
if (UIKit_IsSystemVersionAtLeast(7.0)) {
|
||||||
|
@ -209,11 +199,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setCurrentContext
|
|
||||||
{
|
|
||||||
[EAGLContext setCurrentContext:context];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)swapBuffers
|
- (void)swapBuffers
|
||||||
{
|
{
|
||||||
/* viewRenderbuffer should always be bound here. Code that binds something
|
/* viewRenderbuffer should always be bound here. Code that binds something
|
||||||
|
@ -264,7 +249,7 @@
|
||||||
|
|
||||||
- (void)dealloc
|
- (void)dealloc
|
||||||
{
|
{
|
||||||
if ([EAGLContext currentContext] == context) {
|
if (context && context == [EAGLContext currentContext]) {
|
||||||
[self destroyFramebuffer];
|
[self destroyFramebuffer];
|
||||||
[EAGLContext setCurrentContext:nil];
|
[EAGLContext setCurrentContext:nil];
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,6 +62,7 @@
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Remove ourself from the old window. */
|
||||||
if (sdlwindow) {
|
if (sdlwindow) {
|
||||||
SDL_uikitview *view = nil;
|
SDL_uikitview *view = nil;
|
||||||
data = (__bridge SDL_WindowData *) sdlwindow->driverdata;
|
data = (__bridge SDL_WindowData *) sdlwindow->driverdata;
|
||||||
|
@ -71,9 +72,7 @@
|
||||||
[self removeFromSuperview];
|
[self removeFromSuperview];
|
||||||
|
|
||||||
/* Restore the next-oldest view in the old window. */
|
/* Restore the next-oldest view in the old window. */
|
||||||
if (data.views.count > 0) {
|
view = data.views.lastObject;
|
||||||
view = data.views[data.views.count - 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
data.viewcontroller.view = view;
|
data.viewcontroller.view = view;
|
||||||
|
|
||||||
|
@ -83,6 +82,7 @@
|
||||||
[data.uiwindow layoutIfNeeded];
|
[data.uiwindow layoutIfNeeded];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Add ourself to the new window. */
|
||||||
if (window) {
|
if (window) {
|
||||||
data = (__bridge SDL_WindowData *) window->driverdata;
|
data = (__bridge SDL_WindowData *) window->driverdata;
|
||||||
|
|
||||||
|
|
|
@ -305,7 +305,17 @@ UIKit_DestroyWindow(_THIS, SDL_Window * window)
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
if (window->driverdata != NULL) {
|
if (window->driverdata != NULL) {
|
||||||
SDL_WindowData *data = (SDL_WindowData *) CFBridgingRelease(window->driverdata);
|
SDL_WindowData *data = (SDL_WindowData *) CFBridgingRelease(window->driverdata);
|
||||||
|
NSArray *views = nil;
|
||||||
|
|
||||||
[data.viewcontroller stopAnimation];
|
[data.viewcontroller stopAnimation];
|
||||||
|
|
||||||
|
/* Detach all views from this window. We use a copy of the array
|
||||||
|
* because setSDLWindow will remove the object from the original
|
||||||
|
* array, which would be undesirable if we were iterating over it. */
|
||||||
|
views = [data.views copy];
|
||||||
|
for (SDL_uikitview *view in views) {
|
||||||
|
[view setSDLWindow:NULL];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
window->driverdata = NULL;
|
window->driverdata = NULL;
|
||||||
|
|
Loading…
Reference in a new issue