From 424ffa0559eae0e4d2a92c5bce81328c9bbdc83f Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sun, 6 Feb 2011 10:22:25 -0800 Subject: [PATCH] Prefer the OpenGL ES 2.0 context when it's available, make it possible to create an OpenGL 2.0 context on iPhoneOS --- src/render/SDL_render.c | 6 +-- src/render/SDL_sysrender.h | 6 +-- src/render/opengles/SDL_render_gles.c | 3 ++ src/render/opengles2/SDL_render_gles2.c | 66 ++++++++++++++----------- src/video/SDL_video.c | 32 ++++++++---- src/video/uikit/SDL_uikitopengles.m | 3 +- src/video/uikit/SDL_uikitopenglview.h | 45 ++++++++--------- src/video/uikit/SDL_uikitopenglview.m | 8 ++- 8 files changed, 98 insertions(+), 71 deletions(-) diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c index c71c2a11b..c6396e6b7 100644 --- a/src/render/SDL_render.c +++ b/src/render/SDL_render.c @@ -50,12 +50,12 @@ static const SDL_RenderDriver *render_drivers[] = { #if SDL_VIDEO_RENDER_OGL &GL_RenderDriver, #endif -#if SDL_VIDEO_RENDER_OGL_ES - &GLES_RenderDriver, -#endif #if SDL_VIDEO_RENDER_OGL_ES2 &GLES2_RenderDriver, #endif +#if SDL_VIDEO_RENDER_OGL_ES + &GLES_RenderDriver, +#endif #if SDL_VIDEO_RENDER_DIRECTFB &DirectFB_RenderDriver, #endif diff --git a/src/render/SDL_sysrender.h b/src/render/SDL_sysrender.h index 2c835bec9..f456f8848 100644 --- a/src/render/SDL_sysrender.h +++ b/src/render/SDL_sysrender.h @@ -124,12 +124,12 @@ extern SDL_RenderDriver D3D_RenderDriver; #if SDL_VIDEO_RENDER_OGL extern SDL_RenderDriver GL_RenderDriver; #endif -#if SDL_VIDEO_RENDER_OGL_ES -extern SDL_RenderDriver GLES_RenderDriver; -#endif #if SDL_VIDEO_RENDER_OGL_ES2 extern SDL_RenderDriver GLES2_RenderDriver; #endif +#if SDL_VIDEO_RENDER_OGL_ES +extern SDL_RenderDriver GLES_RenderDriver; +#endif #if SDL_VIDEO_RENDER_DIRECTFB extern SDL_RenderDriver DirectFB_RenderDriver; #endif diff --git a/src/render/opengles/SDL_render_gles.c b/src/render/opengles/SDL_render_gles.c index b8bf9a580..680875964 100644 --- a/src/render/opengles/SDL_render_gles.c +++ b/src/render/opengles/SDL_render_gles.c @@ -184,6 +184,9 @@ GLES_CreateRenderer(SDL_Window * window, Uint32 flags) renderer->info.flags = SDL_RENDERER_ACCELERATED; + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); + data->context = SDL_GL_CreateContext(window); if (!data->context) { GLES_DestroyRenderer(renderer); diff --git a/src/render/opengles2/SDL_render_gles2.c b/src/render/opengles2/SDL_render_gles2.c index 7687a531d..3a1a1de99 100644 --- a/src/render/opengles2/SDL_render_gles2.c +++ b/src/render/opengles2/SDL_render_gles2.c @@ -185,24 +185,29 @@ GLES2_DestroyRenderer(SDL_Renderer *renderer) GLES2_ProgramCacheEntry *entry; GLES2_ProgramCacheEntry *next; - GLES2_ActivateRenderer(renderer); - /* Deallocate everything */ - entry = rdata->program_cache.head; - while (entry) - { - glDeleteShader(entry->vertex_shader->id); - glDeleteShader(entry->fragment_shader->id); - SDL_free(entry->vertex_shader); - SDL_free(entry->fragment_shader); - glDeleteProgram(entry->id); - next = entry->next; - SDL_free(entry); - entry = next; + if (rdata) { + GLES2_ActivateRenderer(renderer); + + entry = rdata->program_cache.head; + while (entry) { + glDeleteShader(entry->vertex_shader->id); + glDeleteShader(entry->fragment_shader->id); + SDL_free(entry->vertex_shader); + SDL_free(entry->fragment_shader); + glDeleteProgram(entry->id); + next = entry->next; + SDL_free(entry); + entry = next; + } + if (rdata->context) { + SDL_GL_DeleteContext(rdata->context); + } + if (rdata->shader_formats) { + SDL_free(rdata->shader_formats); + } + SDL_free(rdata); } - SDL_GL_DeleteContext(rdata->context); - SDL_free(rdata->shader_formats); - SDL_free(renderer->driverdata); SDL_free(renderer); } @@ -1081,12 +1086,15 @@ GLES2_CreateRenderer(SDL_Window *window, Uint32 flags) /* Create the renderer struct */ renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(SDL_Renderer)); + if (!renderer) { + SDL_OutOfMemory(); + return NULL; + } + rdata = (GLES2_DriverContext *)SDL_calloc(1, sizeof(GLES2_DriverContext)); - if (!renderer) - { + if (!rdata) { + GLES2_DestroyRenderer(renderer); SDL_OutOfMemory(); - SDL_free(renderer); - SDL_free(rdata); return NULL; } renderer->info = GLES2_RenderDriver.info; @@ -1095,17 +1103,18 @@ GLES2_CreateRenderer(SDL_Window *window, Uint32 flags) renderer->info.flags = SDL_RENDERER_ACCELERATED; - /* Create the GL context */ + /* Create an OpenGL ES 2.0 context */ + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); + rdata->context = SDL_GL_CreateContext(window); if (!rdata->context) { - SDL_free(renderer); - SDL_free(rdata); + GLES2_DestroyRenderer(renderer); return NULL; } if (SDL_GL_MakeCurrent(window, rdata->context) < 0) { - SDL_free(renderer); - SDL_free(rdata); + GLES2_DestroyRenderer(renderer); return NULL; } @@ -1132,9 +1141,8 @@ GLES2_CreateRenderer(SDL_Window *window, Uint32 flags) rdata->shader_formats = (GLenum *)SDL_calloc(nFormats, sizeof(GLenum)); if (!rdata->shader_formats) { + GLES2_DestroyRenderer(renderer); SDL_OutOfMemory(); - SDL_free(renderer); - SDL_free(rdata); return NULL; } rdata->shader_format_count = nFormats; @@ -1144,10 +1152,8 @@ GLES2_CreateRenderer(SDL_Window *window, Uint32 flags) glGetIntegerv(GL_SHADER_BINARY_FORMATS, (GLint *)rdata->shader_formats); if (glGetError() != GL_NO_ERROR) { + GLES2_DestroyRenderer(renderer); SDL_SetError("Failed to query supported shader formats"); - SDL_free(renderer); - SDL_free(rdata->shader_formats); - SDL_free(rdata); return NULL; } if (hasCompiler) diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index c2ab5a885..147c82a30 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -30,13 +30,17 @@ #include "SDL_pixels_c.h" #include "../events/SDL_events_c.h" +#if SDL_VIDEO_OPENGL +#include "SDL_opengl.h" +#endif /* SDL_VIDEO_OPENGL */ + #if SDL_VIDEO_OPENGL_ES #include "SDL_opengles.h" #endif /* SDL_VIDEO_OPENGL_ES */ -#if SDL_VIDEO_OPENGL -#include "SDL_opengl.h" -#endif /* SDL_VIDEO_OPENGL */ +#if SDL_VIDEO_OPENGL_ES2 +#include "SDL_opengles2.h" +#endif /* SDL_VIDEO_OPENGL_ES2 */ #include "SDL_syswm.h" @@ -481,8 +485,16 @@ SDL_VideoInit(const char *driver_name) _this->gl_config.multisamplesamples = 0; _this->gl_config.retained_backing = 1; _this->gl_config.accelerated = -1; /* accelerated or not, both are fine */ +#if SDL_VIDEO_OPENGL _this->gl_config.major_version = 2; _this->gl_config.minor_version = 1; +#elif SDL_VIDEO_OPENGL_ES2 + _this->gl_config.major_version = 2; + _this->gl_config.minor_version = 0; +#elif SDL_VIDEO_OPENGL_ES + _this->gl_config.major_version = 1; + _this->gl_config.minor_version = 1; +#endif /* Initialize the video subsystem */ if (_this->VideoInit(_this) < 0) { @@ -1897,7 +1909,7 @@ SDL_GL_UnloadLibrary(void) SDL_bool SDL_GL_ExtensionSupported(const char *extension) { -#if SDL_VIDEO_OPENGL || SDL_VIDEO_OPENGL_ES +#if SDL_VIDEO_OPENGL || SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2 const GLubyte *(APIENTRY * glGetStringFunc) (GLenum); const char *extensions; const char *start; @@ -1951,7 +1963,7 @@ SDL_GL_ExtensionSupported(const char *extension) int SDL_GL_SetAttribute(SDL_GLattr attr, int value) { -#if SDL_VIDEO_OPENGL || SDL_VIDEO_OPENGL_ES +#if SDL_VIDEO_OPENGL || SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2 int retval; if (!_this) { @@ -2032,7 +2044,7 @@ SDL_GL_SetAttribute(SDL_GLattr attr, int value) int SDL_GL_GetAttribute(SDL_GLattr attr, int *value) { -#if SDL_VIDEO_OPENGL || SDL_VIDEO_OPENGL_ES +#if SDL_VIDEO_OPENGL || SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2 void (APIENTRY * glGetIntegervFunc) (GLenum pname, GLint * params); GLenum(APIENTRY * glGetErrorFunc) (void); GLenum attrib = 0; @@ -2068,7 +2080,7 @@ SDL_GL_GetAttribute(SDL_GLattr attr, int *value) attrib = GL_ALPHA_BITS; break; case SDL_GL_DOUBLEBUFFER: -#ifndef SDL_VIDEO_OPENGL_ES +#if SDL_VIDEO_OPENGL attrib = GL_DOUBLEBUFFER; break; #else @@ -2084,7 +2096,7 @@ SDL_GL_GetAttribute(SDL_GLattr attr, int *value) case SDL_GL_STENCIL_SIZE: attrib = GL_STENCIL_BITS; break; -#ifndef SDL_VIDEO_OPENGL_ES +#if SDL_VIDEO_OPENGL case SDL_GL_ACCUM_RED_SIZE: attrib = GL_ACCUM_RED_BITS; break; @@ -2111,14 +2123,14 @@ SDL_GL_GetAttribute(SDL_GLattr attr, int *value) return 0; #endif case SDL_GL_MULTISAMPLEBUFFERS: -#ifndef SDL_VIDEO_OPENGL_ES +#if SDL_VIDEO_OPENGL attrib = GL_SAMPLE_BUFFERS_ARB; #else attrib = GL_SAMPLE_BUFFERS; #endif break; case SDL_GL_MULTISAMPLESAMPLES: -#ifndef SDL_VIDEO_OPENGL_ES +#if SDL_VIDEO_OPENGL attrib = GL_SAMPLES_ARB; #else attrib = GL_SAMPLES; diff --git a/src/video/uikit/SDL_uikitopengles.m b/src/video/uikit/SDL_uikitopengles.m index a29fe9a4c..257b3efa4 100644 --- a/src/video/uikit/SDL_uikitopengles.m +++ b/src/video/uikit/SDL_uikitopengles.m @@ -113,7 +113,8 @@ SDL_GLContext UIKit_GL_CreateContext(_THIS, SDL_Window * window) gBits: _this->gl_config.green_size \ bBits: _this->gl_config.blue_size \ aBits: _this->gl_config.alpha_size \ - depthBits: _this->gl_config.depth_size]; + depthBits: _this->gl_config.depth_size \ + majorVersion: _this->gl_config.major_version]; data->view = view; diff --git a/src/video/uikit/SDL_uikitopenglview.h b/src/video/uikit/SDL_uikitopenglview.h index 660ad2eea..730dee428 100644 --- a/src/video/uikit/SDL_uikitopenglview.h +++ b/src/video/uikit/SDL_uikitopenglview.h @@ -26,26 +26,26 @@ #import #import "SDL_uikitview.h" /* - This class wraps the CAEAGLLayer from CoreAnimation into a convenient UIView subclass. - The view content is basically an EAGL surface you render your OpenGL scene into. - Note that setting the view non-opaque will only work if the EAGL surface has an alpha channel. + This class wraps the CAEAGLLayer from CoreAnimation into a convenient UIView subclass. + The view content is basically an EAGL surface you render your OpenGL scene into. + Note that setting the view non-opaque will only work if the EAGL surface has an alpha channel. */ /* *INDENT-OFF* */ @interface SDL_uikitopenglview : SDL_uikitview { - + @private - /* The pixel dimensions of the backbuffer */ - GLint backingWidth; - GLint backingHeight; - - EAGLContext *context; - - /* OpenGL names for the renderbuffer and framebuffers used to render to this view */ - GLuint viewRenderbuffer, viewFramebuffer; - - /* OpenGL name for the depth buffer that is attached to viewFramebuffer, if it exists (0 if it does not exist) */ - GLuint depthRenderbuffer; - + /* The pixel dimensions of the backbuffer */ + GLint backingWidth; + GLint backingHeight; + + EAGLContext *context; + + /* OpenGL names for the renderbuffer and framebuffers used to render to this view */ + GLuint viewRenderbuffer, viewFramebuffer; + + /* OpenGL name for the depth buffer that is attached to viewFramebuffer, if it exists (0 if it does not exist) */ + GLuint depthRenderbuffer; + } @property (nonatomic, retain, readonly) EAGLContext *context; @@ -54,12 +54,13 @@ - (void)setCurrentContext; - (id)initWithFrame:(CGRect)frame - retainBacking:(BOOL)retained \ - rBits:(int)rBits \ - gBits:(int)gBits \ - bBits:(int)bBits \ - aBits:(int)aBits \ - depthBits:(int)depthBits; + retainBacking:(BOOL)retained \ + rBits:(int)rBits \ + gBits:(int)gBits \ + bBits:(int)bBits \ + aBits:(int)aBits \ + depthBits:(int)depthBits \ + majorVersion:(int)majorVersion; @end /* *INDENT-ON* */ diff --git a/src/video/uikit/SDL_uikitopenglview.m b/src/video/uikit/SDL_uikitopenglview.m index 6e590533c..d89b8b194 100644 --- a/src/video/uikit/SDL_uikitopenglview.m +++ b/src/video/uikit/SDL_uikitopenglview.m @@ -47,6 +47,7 @@ - (id)initWithFrame:(CGRect)frame \ bBits:(int)bBits \ aBits:(int)aBits \ depthBits:(int)depthBits \ + majorVersion:(int)majorVersion \ { NSString *colorFormat=nil; GLuint depthBufferFormat; @@ -86,8 +87,11 @@ - (id)initWithFrame:(CGRect)frame \ eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool: retained], kEAGLDrawablePropertyRetainedBacking, colorFormat, kEAGLDrawablePropertyColorFormat, nil]; - context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES1]; - + if (majorVersion > 1) { + context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES2]; + } else { + context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES1]; + } if (!context || ![EAGLContext setCurrentContext:context]) { [self release]; return nil;