OpenGL ES support for Windows

This commit is contained in:
Gabriel Jacobo 2013-11-22 13:24:53 -03:00
parent 239ba53a4c
commit f21d3e7e2a
32 changed files with 6741 additions and 1210 deletions

View file

@ -25,6 +25,7 @@
#include "SDL_assert.h"
#include "SDL_loadso.h"
#include "SDL_windowsvideo.h"
#include "SDL_windowsopengles.h"
/* WGL implementation of SDL OpenGL support */
@ -323,11 +324,35 @@ HasExtension(const char *extension, const char *extensions)
return SDL_FALSE;
}
static void
WIN_GL_InitExtensions(_THIS, HDC hdc)
void
WIN_GL_InitExtensions(_THIS)
{
const char *(WINAPI * wglGetExtensionsStringARB) (HDC) = 0;
const char *extensions;
HWND hwnd;
HDC hdc;
HGLRC hglrc;
PIXELFORMATDESCRIPTOR pfd;
hwnd =
CreateWindow(SDL_Appname, SDL_Appname, (WS_POPUP | WS_DISABLED), 0, 0,
10, 10, NULL, NULL, SDL_Instance, NULL);
if (!hwnd) {
return;
}
WIN_PumpEvents(_this);
hdc = GetDC(hwnd);
WIN_GL_SetupPixelFormat(_this, &pfd);
SetPixelFormat(hdc, ChoosePixelFormat(hdc, &pfd), &pfd);
hglrc = _this->gl_data->wglCreateContext(hdc);
if (!hglrc) {
return;
}
_this->gl_data->wglMakeCurrent(hdc, hglrc);
wglGetExtensionsStringARB = (const char *(WINAPI *) (HDC))
_this->gl_data->wglGetProcAddress("wglGetExtensionsStringARB");
@ -369,6 +394,18 @@ WIN_GL_InitExtensions(_THIS, HDC hdc)
_this->gl_data->wglSwapIntervalEXT = NULL;
_this->gl_data->wglGetSwapIntervalEXT = NULL;
}
/* Check for WGL_EXT_create_context_es2_profile */
_this->gl_data->HAS_WGL_EXT_create_context_es2_profile = SDL_FALSE;
if (HasExtension("WGL_EXT_create_context_es2_profile", extensions)) {
_this->gl_data->HAS_WGL_EXT_create_context_es2_profile = SDL_TRUE;
}
_this->gl_data->wglMakeCurrent(hdc, NULL);
_this->gl_data->wglDeleteContext(hglrc);
ReleaseDC(hwnd, hdc);
DestroyWindow(hwnd);
WIN_PumpEvents(_this);
}
static int
@ -396,8 +433,6 @@ WIN_GL_ChoosePixelFormatARB(_THIS, int *iAttribs, float *fAttribs)
if (hglrc) {
_this->gl_data->wglMakeCurrent(hdc, hglrc);
WIN_GL_InitExtensions(_this, hdc);
if (_this->gl_data->HAS_WGL_ARB_pixel_format) {
_this->gl_data->wglChoosePixelFormatARB(hdc, iAttribs, fAttribs,
1, &pixel_format,
@ -548,6 +583,27 @@ WIN_GL_CreateContext(_THIS, SDL_Window * window)
HDC hdc = ((SDL_WindowData *) window->driverdata)->hdc;
HGLRC context, share_context;
if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES &&
!_this->gl_data->HAS_WGL_EXT_create_context_es2_profile) {
/* Switch to EGL based functions */
WIN_GL_UnloadLibrary(_this);
_this->GL_LoadLibrary = WIN_GLES_LoadLibrary;
_this->GL_GetProcAddress = WIN_GLES_GetProcAddress;
_this->GL_UnloadLibrary = WIN_GLES_UnloadLibrary;
_this->GL_CreateContext = WIN_GLES_CreateContext;
_this->GL_MakeCurrent = WIN_GLES_MakeCurrent;
_this->GL_SetSwapInterval = WIN_GLES_SetSwapInterval;
_this->GL_GetSwapInterval = WIN_GLES_GetSwapInterval;
_this->GL_SwapWindow = WIN_GLES_SwapWindow;
_this->GL_DeleteContext = WIN_GLES_DeleteContext;
if (WIN_GLES_LoadLibrary(_this, NULL) != 0) {
return NULL;
}
return WIN_GLES_CreateContext(_this, window);
}
if (_this->gl_config.share_with_current_context) {
share_context = (HGLRC)SDL_GL_GetCurrentContext();
} else {
@ -622,8 +678,6 @@ WIN_GL_CreateContext(_THIS, SDL_Window * window)
return NULL;
}
WIN_GL_InitExtensions(_this, hdc);
return context;
}

View file

@ -29,6 +29,7 @@ struct SDL_GLDriverData
{
SDL_bool HAS_WGL_ARB_pixel_format;
SDL_bool HAS_WGL_EXT_swap_control_tear;
SDL_bool HAS_WGL_EXT_create_context_es2_profile;
void *(WINAPI * wglGetProcAddress) (const char *proc);
HGLRC(WINAPI * wglCreateContext) (HDC hdc);
@ -62,6 +63,7 @@ extern int WIN_GL_SetSwapInterval(_THIS, int interval);
extern int WIN_GL_GetSwapInterval(_THIS);
extern void WIN_GL_SwapWindow(_THIS, SDL_Window * window);
extern void WIN_GL_DeleteContext(_THIS, SDL_GLContext context);
extern void WIN_GL_InitExtensions(_THIS);
#ifndef WGL_ARB_pixel_format
#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000

View file

@ -0,0 +1,141 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "SDL_config.h"
#if SDL_VIDEO_DRIVER_WINDOWS && SDL_VIDEO_OPENGL_EGL
#include "SDL_windowsvideo.h"
#include "SDL_windowsopengles.h"
#include "SDL_windowsopengl.h"
#include "SDL_log.h"
/* EGL implementation of SDL OpenGL support */
int
WIN_GLES_LoadLibrary(_THIS, const char *path) {
SDL_VideoData *data = (SDL_VideoData *)_this->driverdata;
/* If the profile requested is not GL ES, switch over to WIN_GL functions */
if (_this->gl_config.profile_mask != SDL_GL_CONTEXT_PROFILE_ES) {
#if SDL_VIDEO_OPENGL_WGL
WIN_GLES_UnloadLibrary(_this);
_this->GL_LoadLibrary = WIN_GL_LoadLibrary;
_this->GL_GetProcAddress = WIN_GL_GetProcAddress;
_this->GL_UnloadLibrary = WIN_GL_UnloadLibrary;
_this->GL_CreateContext = WIN_GL_CreateContext;
_this->GL_MakeCurrent = WIN_GL_MakeCurrent;
_this->GL_SetSwapInterval = WIN_GL_SetSwapInterval;
_this->GL_GetSwapInterval = WIN_GL_GetSwapInterval;
_this->GL_SwapWindow = WIN_GL_SwapWindow;
_this->GL_DeleteContext = WIN_GL_DeleteContext;
return WIN_GL_LoadLibrary(_this, path);
#else
return SDL_SetError("SDL not configured with OpenGL/WGL support");
#endif
}
if (_this->egl_data == NULL) {
return SDL_EGL_LoadLibrary(_this, NULL, EGL_DEFAULT_DISPLAY);
}
return 0;
}
SDL_GLContext
WIN_GLES_CreateContext(_THIS, SDL_Window * window)
{
SDL_GLContext context;
SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
if (_this->gl_config.profile_mask != SDL_GL_CONTEXT_PROFILE_ES) {
/* Switch to WGL based functions */
WIN_GLES_UnloadLibrary(_this);
_this->GL_LoadLibrary = WIN_GL_LoadLibrary;
_this->GL_GetProcAddress = WIN_GL_GetProcAddress;
_this->GL_UnloadLibrary = WIN_GL_UnloadLibrary;
_this->GL_CreateContext = WIN_GL_CreateContext;
_this->GL_MakeCurrent = WIN_GL_MakeCurrent;
_this->GL_SetSwapInterval = WIN_GL_SetSwapInterval;
_this->GL_GetSwapInterval = WIN_GL_GetSwapInterval;
_this->GL_SwapWindow = WIN_GL_SwapWindow;
_this->GL_DeleteContext = WIN_GL_DeleteContext;
if (WIN_GL_LoadLibrary(_this, NULL) != 0) {
return NULL;
}
return WIN_GL_CreateContext(_this, window);
}
context = SDL_EGL_CreateContext(_this, data->egl_surface);
return context;
}
void
WIN_GLES_DeleteContext(_THIS, SDL_GLContext context)
{
SDL_EGL_DeleteContext(_this, context);
WIN_GLES_UnloadLibrary(_this);
}
SDL_EGL_SwapWindow_impl(WIN)
SDL_EGL_MakeCurrent_impl(WIN)
int
WIN_GLES_SetupWindow(_THIS, SDL_Window * window)
{
/* The current context is lost in here; save it and reset it. */
SDL_WindowData *windowdata = (SDL_WindowData *) window->driverdata;
SDL_Window *current_win = SDL_GL_GetCurrentWindow();
SDL_GLContext current_ctx = SDL_GL_GetCurrentContext();
if (_this->egl_data == NULL) {
if (SDL_EGL_LoadLibrary(_this, NULL, EGL_DEFAULT_DISPLAY) < 0) {
return -1;
}
}
/* Create the GLES window surface */
windowdata->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType)windowdata->hwnd);
if (windowdata->egl_surface == EGL_NO_SURFACE) {
return SDL_SetError("Could not create GLES window surface");
}
return WIN_GLES_MakeCurrent(_this, current_win, current_ctx);
}
int
WIN_GLES_SetSwapInterval(_THIS, int interval)
{
/* FIXME: This should call SDL_EGL_SetSwapInterval, but ANGLE has a bug that prevents this
* from working if we do (the window contents freeze and don't swap properly). So, we ignore
* the request for now.
*/
SDL_Log("WARNING: Ignoring SDL_GL_SetSwapInterval call due to ANGLE bug");
return 0;
}
#endif /* SDL_VIDEO_DRIVER_WINDOWS && SDL_VIDEO_OPENGL_EGL */
/* vi: set ts=4 sw=4 expandtab: */

View file

@ -0,0 +1,51 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "SDL_config.h"
#ifndef _SDL_winopengles_h
#define _SDL_winopengles_h
#if SDL_VIDEO_OPENGL_EGL
#include "../SDL_sysvideo.h"
#include "../SDL_egl_c.h"
/* OpenGLES functions */
#define WIN_GLES_GetAttribute SDL_EGL_GetAttribute
#define WIN_GLES_GetProcAddress SDL_EGL_GetProcAddress
#define WIN_GLES_UnloadLibrary SDL_EGL_UnloadLibrary
#define WIN_GLES_GetSwapInterval SDL_EGL_GetSwapInterval
/* See the WIN_GLES_GetSwapInterval implementation to see why this is commented out */
/*#define WIN_GLES_SetSwapInterval SDL_EGL_SetSwapInterval*/
extern int WIN_GLES_SetSwapInterval(_THIS, int interval);
extern int WIN_GLES_LoadLibrary(_THIS, const char *path);
extern SDL_GLContext WIN_GLES_CreateContext(_THIS, SDL_Window * window);
extern void WIN_GLES_SwapWindow(_THIS, SDL_Window * window);
extern int WIN_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context);
extern void WIN_GLES_DeleteContext(_THIS, SDL_GLContext context);
extern int WIN_GLES_SetupWindow(_THIS, SDL_Window * window);
#endif /* SDL_VIDEO_OPENGL_EGL */
#endif /* _SDL_winopengles_h */
/* vi: set ts=4 sw=4 expandtab: */

View file

@ -44,6 +44,7 @@
#include "SDL_windowsmodes.h"
#include "SDL_windowsmouse.h"
#include "SDL_windowsopengl.h"
#include "SDL_windowsopengles.h"
#include "SDL_windowswindow.h"
#include "SDL_events.h"
#include "SDL_loadso.h"

View file

@ -273,6 +273,32 @@ WIN_CreateWindow(_THIS, SDL_Window * window)
DestroyWindow(hwnd);
return -1;
}
#if SDL_VIDEO_OPENGL_WGL
/* We need to initialize the extensions before deciding how to create ES profiles */
if (window->flags & SDL_WINDOW_OPENGL) {
WIN_GL_InitExtensions(_this);
}
#endif
#if SDL_VIDEO_OPENGL_ES2
if ((window->flags & SDL_WINDOW_OPENGL) &&
_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES
#if SDL_VIDEO_OPENGL_WGL
&& (!_this->gl_data || !_this->gl_data->HAS_WGL_EXT_create_context_es2_profile)
#endif
) {
#if SDL_VIDEO_OPENGL_EGL
if (WIN_GLES_SetupWindow(_this, window) < 0) {
WIN_DestroyWindow(_this, window);
return -1;
}
#else
return SDL_SetError("Could not create GLES window surface (no EGL support available)");
#endif /* SDL_VIDEO_OPENGL_EGL */
} else
#endif /* SDL_VIDEO_OPENGL_ES2 */
#if SDL_VIDEO_OPENGL_WGL
if (window->flags & SDL_WINDOW_OPENGL) {
if (WIN_GL_SetupWindow(_this, window) < 0) {
@ -281,6 +307,7 @@ WIN_CreateWindow(_THIS, SDL_Window * window)
}
}
#endif
return 0;
}

View file

@ -23,6 +23,10 @@
#ifndef _SDL_windowswindow_h
#define _SDL_windowswindow_h
#if SDL_VIDEO_OPENGL_EGL
#include "../SDL_egl_c.h"
#endif
typedef struct
{
SDL_Window *window;
@ -35,6 +39,9 @@ typedef struct
WPARAM mouse_button_flags;
BOOL expected_resize;
struct SDL_VideoData *videodata;
#if SDL_VIDEO_OPENGL_EGL
EGLSurface egl_surface;
#endif
} SDL_WindowData;
extern int WIN_CreateWindow(_THIS, SDL_Window * window);