Commit 296e78b6 authored by Sam Lantinga's avatar Sam Lantinga

Fixed bug 1242 - PATCH: Improve support for OpenGL ES under X11

Scott Percival 2011-07-03 06:41:51 PDT

This submission is aimed at making life easier for OpenGL ES capable devices
running a X11 stack (e.g. Maemo, Meego, TrimSlice, other ARM SoC boards not
running Android). SDL's Pandora support already has the neccesary GLES-to-X11
glue code, however it's all ghetto'd off in Makefile.pandora and not very
flexible.

The patch:
- adds an awesome --enable-video-opengles option to configure
- re-modifies the opengles and opengles2 SDL_renderers to use function pointers
- no idea why this was removed?
- for SDL_Renderers, links in libGLESv1_CM, libGLES_CM (for PowerVR fans) or
libGLESv2 at runtime
- links in libEGL.so at runtime - the old code made an assumption that
eglFunctions could be pulled from the active GLES library, PowerVR for one
doesn't let you do that with their libGLESv2
- allows you to pick which of GLES v1 or v2 to load via
SDL_GL_CONTEXT_MAJOR_VERSION

So far I've tested this on a Nokia N900 (OMAP 3430/SGX 530 running Maemo 5) and
a Toshiba AC100 (Tegra 2 running Ubuntu 10.10). I haven't tested it on... well,
everything that isn't those two, such as a Pandora, iOS or Android device. The
Pandora specific code should be kept intact (fingers crossed), and nothing
painfully drastic has been added to the SDL_renderers. The library loading
sequence in SDL_x11opengles has been updated to accomodate both NVIDIA's
propensity to let developers get away with murder and PowerVR's alternative of
punishing every missed step.

The test apps work okay with GLES or GLES2 as the renderer. For some reason
alpha blending doesn't seem to work on the Tegra 2; last week NVIDIA pushed out
a new set of X11 GLES drivers, so I'll try and investigate once I upgrade
those. Also, this patch adds things to configure.in, include/SDL_config.h.in
and test/configure.in. I didn't know what the policy was re. committing
generated spaghetti from autotools, so ./autogen.sh has to be run again. Sorry.

I think that's about everything, let me know if there's anything I've
overlooked.
parent 02fe2020
This diff is collapsed.
......@@ -1474,6 +1474,57 @@ CheckOpenGLX11()
fi
}
dnl Check to see if OpenGL ES support is desired
AC_ARG_ENABLE(video-opengles,
AC_HELP_STRING([--enable-video-opengles], [include OpenGL ES support [[default=yes]]]),
, enable_video_opengles=yes)
dnl Find OpenGL ES
CheckOpenGLESX11()
{
if test x$enable_video = xyes -a x$enable_video_opengles = xyes; then
AC_MSG_CHECKING(for OpenGL ES (EGL) support)
video_opengles=no
AC_TRY_COMPILE([
#include <EGL/egl.h>
],[
],[
video_opengles=yes
])
AC_MSG_RESULT($video_opengles)
if test x$video_opengles = xyes; then
AC_MSG_CHECKING(for OpenGL ES v1 headers)
video_opengles_v1=no
AC_TRY_COMPILE([
#include <GLES/gl.h>
#include <GLES/glext.h>
],[
],[
video_opengles_v1=yes
])
AC_MSG_RESULT($video_opengles_v1)
if test x$video_opengles_v1 = xyes; then
AC_DEFINE(SDL_VIDEO_OPENGL_ES, 1, [ ])
AC_DEFINE(SDL_VIDEO_RENDER_OGL_ES, 1, [ ])
fi
AC_MSG_CHECKING(for OpenGL ES v2 headers)
video_opengles_v2=no
AC_TRY_COMPILE([
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
],[
],[
video_opengles_v2=yes
])
AC_MSG_RESULT($video_opengles_v2)
if test x$video_opengles_v2 = xyes; then
AC_DEFINE(SDL_VIDEO_OPENGL_ES2, 1, [ ])
AC_DEFINE(SDL_VIDEO_RENDER_OGL_ES2, 1, [ ])
fi
fi
fi
}
dnl Check for Windows OpenGL
CheckWINDOWSGL()
{
......@@ -2043,6 +2094,7 @@ case "$host" in
CheckDirectFB
CheckFusionSound
CheckOpenGLX11
CheckOpenGLESX11
CheckInputEvents
CheckTslib
CheckUSBHID
......
......@@ -271,6 +271,7 @@
#undef SDL_VIDEO_RENDER_D3D
#undef SDL_VIDEO_RENDER_OGL
#undef SDL_VIDEO_RENDER_OGL_ES
#undef SDL_VIDEO_RENDER_OGL_ES2
#undef SDL_VIDEO_RENDER_DIRECTFB
/* Enable OpenGL support */
......
SDL_PROC(void, glBindTexture, (GLenum, GLuint))
SDL_PROC(void, glBlendFunc, (GLenum, GLenum))
SDL_PROC(void, glClear, (GLbitfield))
SDL_PROC(void, glClearColor, (GLclampf, GLclampf, GLclampf, GLclampf))
SDL_PROC(void, glColor4f, (GLfloat, GLfloat, GLfloat, GLfloat))
SDL_PROC(void, glDeleteTextures, (GLsizei, const GLuint *))
SDL_PROC(void, glDisable, (GLenum))
SDL_PROC(void, glDisableClientState, (GLenum array))
SDL_PROC(void, glDrawArrays, (GLenum, GLint, GLsizei))
SDL_PROC(void, glDrawTexiOES, (GLint, GLint, GLint, GLint, GLint))
SDL_PROC(void, glEnable, (GLenum))
SDL_PROC(void, glEnableClientState, (GLenum))
SDL_PROC(void, glGenTextures, (GLsizei, GLuint *))
SDL_PROC(GLenum, glGetError, (void))
SDL_PROC(void, glGetIntegerv, (GLenum, GLint *))
SDL_PROC(void, glLoadIdentity, (void))
SDL_PROC(void, glMatrixMode, (GLenum))
SDL_PROC(void, glOrthof, (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat))
SDL_PROC(void, glPixelStorei, (GLenum, GLint))
SDL_PROC(void, glReadPixels, (GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLvoid*))
SDL_PROC(void, glTexCoordPointer, (GLint, GLenum, GLsizei, const GLvoid *))
SDL_PROC(void, glTexEnvf, (GLenum, GLenum, GLfloat))
SDL_PROC(void, glTexImage2D, (GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *))
SDL_PROC(void, glTexParameteri, (GLenum, GLenum, GLint))
SDL_PROC(void, glTexParameteriv, (GLenum, GLenum, const GLint *))
SDL_PROC(void, glTexSubImage2D, (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *))
SDL_PROC(void, glVertexPointer, (GLint, GLenum, GLsizei, const GLvoid *))
SDL_PROC(void, glViewport, (GLint, GLint, GLsizei, GLsizei))
/* vi: set ts=4 sw=4 expandtab: */
This diff is collapsed.
SDL_PROC(void, glActiveTexture, (GLenum))
SDL_PROC(void, glAttachShader, (GLuint, GLuint))
SDL_PROC(void, glBindAttribLocation, (GLuint, GLuint, const char *))
SDL_PROC(void, glBindTexture, (GLenum, GLuint))
SDL_PROC(void, glBlendFunc, (GLenum, GLenum))
SDL_PROC(void, glClear, (GLbitfield))
SDL_PROC(void, glClearColor, (GLclampf, GLclampf, GLclampf, GLclampf))
SDL_PROC(void, glCompileShader, (GLuint))
SDL_PROC(GLuint, glCreateProgram, (void))
SDL_PROC(GLuint, glCreateShader, (GLenum))
SDL_PROC(void, glDeleteProgram, (GLuint))
SDL_PROC(void, glDeleteShader, (GLuint))
SDL_PROC(void, glDeleteTextures, (GLsizei, const GLuint *))
SDL_PROC(void, glDisable, (GLenum))
SDL_PROC(void, glDisableVertexAttribArray, (GLuint))
SDL_PROC(void, glDrawArrays, (GLenum, GLint, GLsizei))
SDL_PROC(void, glEnable, (GLenum))
SDL_PROC(void, glEnableVertexAttribArray, (GLuint))
SDL_PROC(void, glFinish, (void))
SDL_PROC(void, glGenTextures, (GLsizei, GLuint *))
SDL_PROC(void, glGetBooleanv, (GLenum, GLboolean *))
SDL_PROC(const GLubyte *, glGetString, (GLenum))
SDL_PROC(GLenum, glGetError, (void))
SDL_PROC(void, glGetIntegerv, (GLenum, GLint *))
SDL_PROC(void, glGetProgramiv, (GLuint, GLenum, GLint *))
SDL_PROC(void, glGetShaderInfoLog, (GLuint, GLsizei, GLsizei *, char *))
SDL_PROC(void, glGetShaderiv, (GLuint, GLenum, GLint *))
SDL_PROC(GLint, glGetUniformLocation, (GLuint, const char *))
SDL_PROC(void, glLinkProgram, (GLuint))
SDL_PROC(void, glPixelStorei, (GLenum, GLint))
SDL_PROC(void, glReadPixels, (GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLvoid*))
SDL_PROC(void, glShaderBinary, (GLsizei, const GLuint *, GLenum, const void *, GLsizei))
SDL_PROC(void, glShaderSource, (GLuint, GLsizei, const char **, const GLint *))
SDL_PROC(void, glTexImage2D, (GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, const void *))
SDL_PROC(void, glTexParameteri, (GLenum, GLenum, GLint))
SDL_PROC(void, glTexSubImage2D, (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *))
SDL_PROC(void, glUniform1i, (GLint, GLint))
SDL_PROC(void, glUniform4f, (GLint, GLfloat, GLfloat, GLfloat, GLfloat))
SDL_PROC(void, glUniformMatrix4fv, (GLint, GLsizei, GLboolean, const GLfloat *))
SDL_PROC(void, glUseProgram, (GLuint))
SDL_PROC(void, glVertexAttribPointer, (GLuint, GLint, GLenum, GLboolean, GLsizei, const void *))
SDL_PROC(void, glViewport, (GLint, GLint, GLsizei, GLsizei))
This diff is collapsed.
......@@ -286,7 +286,7 @@ struct SDL_VideoDevice
void *driverdata;
struct SDL_GLDriverData *gl_data;
#if SDL_VIDEO_DRIVER_PANDORA
#if SDL_VIDEO_OPENGL_ES
struct SDL_PrivateGLESData *gles_data;
#endif
......
......@@ -189,6 +189,9 @@ ShouldUseTextureFramebuffer()
}
return hasAcceleratedOpenGL;
}
#elif SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
/* Let's be optimistic about this! */
return SDL_TRUE;
#else
return SDL_FALSE;
#endif
......@@ -1138,7 +1141,7 @@ SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags)
}
/* Some platforms have OpenGL enabled by default */
#if (SDL_VIDEO_OPENGL && __MACOSX__) || SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
#if (SDL_VIDEO_OPENGL && __MACOSX__) || __IPHONEOS__ || __ANDROID__
flags |= SDL_WINDOW_OPENGL;
#endif
if (flags & SDL_WINDOW_OPENGL) {
......
......@@ -25,7 +25,10 @@
#include "SDL_x11video.h"
#include "SDL_x11opengles.h"
#define DEFAULT_OPENGL "/usr/lib/libGLES_CM.so"
#define DEFAULT_EGL "/usr/lib/libEGL.so"
#define DEFAULT_OGL_ES2 "/usr/lib/libGLESv2.so"
#define DEFAULT_OGL_ES_PVR "/usr/lib/libGLES_CM.so"
#define DEFAULT_OGL_ES "/usr/lib/libGLESv1_CM.so"
#define LOAD_FUNC(NAME) \
*((void**)&_this->gles_data->NAME) = dlsym(handle, #NAME); \
......@@ -44,13 +47,15 @@ X11_GLES_GetProcAddress(_THIS, const char *proc)
void *handle;
void *retval;
handle = _this->gl_config.dll_handle;
handle = _this->gles_data->egl_dll_handle;
if (_this->gles_data->eglGetProcAddress) {
retval = _this->gles_data->eglGetProcAddress(proc);
if (retval) {
return retval;
}
}
handle = _this->gl_config.dll_handle;
#if defined(__OpenBSD__) && !defined(__ELF__)
#undef dlsym(x,y);
#endif
......@@ -70,6 +75,7 @@ X11_GLES_UnloadLibrary(_THIS)
_this->gles_data->eglTerminate(_this->gles_data->egl_display);
dlclose(_this->gl_config.dll_handle);
dlclose(_this->gles_data->egl_dll_handle);
_this->gles_data->eglGetProcAddress = NULL;
_this->gles_data->eglChooseConfig = NULL;
......@@ -111,7 +117,7 @@ X11_GLES_LoadLibrary(_THIS, const char *path)
dlclose(handle);
path = getenv("SDL_VIDEO_GL_DRIVER");
if (path == NULL) {
path = DEFAULT_OPENGL;
path = DEFAULT_EGL;
}
handle = dlopen(path, dlopen_flags);
}
......@@ -153,6 +159,29 @@ X11_GLES_LoadLibrary(_THIS, const char *path)
return -1;
}
_this->gles_data->egl_dll_handle = handle;
path = getenv("SDL_VIDEO_GL_DRIVER");
handle = dlopen(path, dlopen_flags);
if ((path == NULL) | (handle == NULL)) {
if (_this->gl_config.major_version > 1) {
path = DEFAULT_OGL_ES2;
handle = dlopen(path, dlopen_flags);
} else {
path = DEFAULT_OGL_ES;
handle = dlopen(path, dlopen_flags);
if (handle == NULL) {
path = DEFAULT_OGL_ES_PVR;
handle = dlopen(path, dlopen_flags);
}
}
}
if (handle == NULL) {
SDL_SetError("Could not initialize OpenGL ES library");
return -1;
}
_this->gl_config.dll_handle = handle;
_this->gl_config.driver_loaded = 1;
......@@ -218,6 +247,13 @@ X11_GLES_GetVisual(_THIS, Display * display, int screen)
attribs[i++] = _this->gl_config.multisamplesamples;
}
attribs[i++] = EGL_RENDERABLE_TYPE;
if (_this->gl_config.major_version == 2) {
attribs[i++] = EGL_OPENGL_ES2_BIT;
} else {
attribs[i++] = EGL_OPENGL_ES_BIT;
}
attribs[i++] = EGL_NONE;
if (_this->gles_data->eglChooseConfig(_this->gles_data->egl_display,
......@@ -260,17 +296,25 @@ X11_GLES_GetVisual(_THIS, Display * display, int screen)
SDL_GLContext
X11_GLES_CreateContext(_THIS, SDL_Window * window)
{
int retval;
EGLint context_attrib_list[] = {
EGL_CONTEXT_CLIENT_VERSION,
1,
EGL_NONE
};
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
Display *display = data->videodata->display;
XSync(display, False);
if (_this->gl_config.major_version) {
context_attrib_list[1] = _this->gl_config.major_version;
}
_this->gles_data->egl_context =
_this->gles_data->eglCreateContext(_this->gles_data->egl_display,
_this->gles_data->egl_config,
EGL_NO_CONTEXT, NULL);
EGL_NO_CONTEXT, context_attrib_list);
XSync(display, False);
if (_this->gles_data->egl_context == EGL_NO_CONTEXT) {
......@@ -280,12 +324,12 @@ X11_GLES_CreateContext(_THIS, SDL_Window * window)
_this->gles_data->egl_active = 1;
if (_this->gles_data->egl_active)
retval = 1;
else
retval = 0;
if (X11_GLES_MakeCurrent(_this, window, context) < 0) {
X11_GLES_DeleteContext(_this, context);
return NULL;
}
return (retval);
return (SDL_GLContext)(1);
}
int
......
......@@ -32,6 +32,7 @@ typedef struct SDL_PrivateGLESData
{
int egl_active; /* to stop switching drivers while we have a valid context */
XVisualInfo *egl_visualinfo;
void *egl_dll_handle;
EGLDisplay egl_display;
EGLContext egl_context; /* Current GLES context */
EGLSurface egl_surface;
......
......@@ -34,7 +34,7 @@
#include "SDL_x11shape.h"
#include "SDL_x11touch.h"
#if SDL_VIDEO_DRIVER_PANDORA
#if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
#include "SDL_x11opengles.h"
#endif
......@@ -110,7 +110,7 @@ X11_DeleteDevice(SDL_VideoDevice * device)
}
SDL_free(data->windowlist);
SDL_free(device->driverdata);
#if SDL_VIDEO_DRIVER_PANDORA
#if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
SDL_free(device->gles_data);
#endif
SDL_free(device);
......@@ -143,7 +143,7 @@ X11_CreateDevice(int devindex)
}
device->driverdata = data;
#if SDL_VIDEO_DRIVER_PANDORA
#if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
device->gles_data = (struct SDL_PrivateGLESData *) SDL_calloc(1, sizeof(SDL_PrivateGLESData));
if (!device->gles_data) {
SDL_OutOfMemory();
......@@ -226,7 +226,7 @@ X11_CreateDevice(int devindex)
device->GL_SwapWindow = X11_GL_SwapWindow;
device->GL_DeleteContext = X11_GL_DeleteContext;
#endif
#if SDL_VIDEO_DRIVER_PANDORA
#if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
device->GL_LoadLibrary = X11_GLES_LoadLibrary;
device->GL_GetProcAddress = X11_GLES_GetProcAddress;
device->GL_UnloadLibrary = X11_GLES_UnloadLibrary;
......
......@@ -31,7 +31,7 @@
#include "SDL_x11mouse.h"
#include "SDL_x11shape.h"
#ifdef SDL_VIDEO_DRIVER_PANDORA
#if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
#include "SDL_x11opengles.h"
#endif
......@@ -289,7 +289,7 @@ X11_CreateWindow(_THIS, SDL_Window * window)
XFree(vinfo);
} else
#endif
#ifdef SDL_VIDEO_DRIVER_PANDORA
#if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
if (window->flags & SDL_WINDOW_OPENGL) {
XVisualInfo *vinfo;
......@@ -401,17 +401,19 @@ X11_CreateWindow(_THIS, SDL_Window * window)
SDL_SetError("Couldn't create window");
return -1;
}
#if SDL_VIDEO_DRIVER_PANDORA
/* Create the GLES window surface */
_this->gles_data->egl_surface =
_this->gles_data->eglCreateWindowSurface(_this->gles_data->
#if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
if (window->flags & SDL_WINDOW_OPENGL) {
/* Create the GLES window surface */
_this->gles_data->egl_surface =
_this->gles_data->eglCreateWindowSurface(_this->gles_data->
egl_display,
_this->gles_data->egl_config,
(NativeWindowType) w, NULL);
if (_this->gles_data->egl_surface == EGL_NO_SURFACE) {
SDL_SetError("Could not create GLES window surface");
return -1;
if (_this->gles_data->egl_surface == EGL_NO_SURFACE) {
SDL_SetError("Could not create GLES window surface");
return -1;
}
}
#endif
......
......@@ -3764,12 +3764,10 @@ cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
#if defined (__QNXNTO__)
#include <GLES/gl.h>
#elif defined (__IPHONEOS__)
#if defined (__IPHONEOS__)
#include <OpenGLES/ES1/gl.h>
#else
#error "No OpenGL ES support"
#include <GLES/gl.h>
#endif /* __QNXNTO__ */
int
......@@ -3812,11 +3810,12 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
{ echo "$as_me:$LINENO: result: $have_opengles" >&5
echo "${ECHO_T}$have_opengles" >&6; }
if test x$have_opengl = xyes; then
CFLAGS="$CFLAGS -DHAVE_OPENGL"
GLLIB="$XPATH $SYS_GL_LIBS"
elif test x$have_opengles = xyes; then
GLLIB=""
if test x$have_opengles = xyes; then
CFLAGS="$CFLAGS -DHAVE_OPENGLES"
GLLIB="$XPATH -lGLESv1_CM"
elif test x$have_opengl = xyes; then
CFLAGS="$CFLAGS -DHAVE_OPENGL"
GLLIB="$XPATH $SYS_GL_LIBS"
else
GLLIB=""
......
......@@ -103,12 +103,10 @@ dnl Check for OpenGL ES
AC_MSG_CHECKING(for OpenGL ES support)
have_opengles=no
AC_TRY_COMPILE([
#if defined (__QNXNTO__)
#include <GLES/gl.h>
#elif defined (__IPHONEOS__)
#if defined (__IPHONEOS__)
#include <OpenGLES/ES1/gl.h>
#else
#error "No OpenGL ES support"
#include <GLES/gl.h>
#endif /* __QNXNTO__ */
],[
],[
......@@ -116,11 +114,12 @@ have_opengles=yes
])
AC_MSG_RESULT($have_opengles)
if test x$have_opengl = xyes; then
CFLAGS="$CFLAGS -DHAVE_OPENGL"
GLLIB="$XPATH $SYS_GL_LIBS"
elif test x$have_opengles = xyes; then
GLLIB=""
if test x$have_opengles = xyes; then
CFLAGS="$CFLAGS -DHAVE_OPENGLES"
GLLIB="$XPATH -lGLESv1_CM"
elif test x$have_opengl = xyes; then
CFLAGS="$CFLAGS -DHAVE_OPENGL"
GLLIB="$XPATH $SYS_GL_LIBS"
else
GLLIB=""
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment