| /* |
| Simple DirectMedia Layer |
| Copyright (C) 1997-2016 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_internal.h" |
| |
| #if SDL_VIDEO_DRIVER_PSP |
| |
| #include <stdlib.h> |
| #include <string.h> |
| |
| #include "SDL_error.h" |
| #include "SDL_pspvideo.h" |
| #include "SDL_pspgl_c.h" |
| |
| /*****************************************************************************/ |
| /* SDL OpenGL/OpenGL ES functions */ |
| /*****************************************************************************/ |
| #define EGLCHK(stmt) \ |
| do { \ |
| EGLint err; \ |
| \ |
| stmt; \ |
| err = eglGetError(); \ |
| if (err != EGL_SUCCESS) { \ |
| SDL_SetError("EGL error %d", err); \ |
| return 0; \ |
| } \ |
| } while (0) |
| |
| int |
| PSP_GL_LoadLibrary(_THIS, const char *path) |
| { |
| if (!_this->gl_config.driver_loaded) { |
| _this->gl_config.driver_loaded = 1; |
| } |
| |
| return 0; |
| } |
| |
| /* pspgl doesn't provide this call, so stub it out since SDL requires it. |
| #define GLSTUB(func,params) void func params {} |
| |
| GLSTUB(glOrtho,(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, |
| GLdouble zNear, GLdouble zFar)) |
| */ |
| void * |
| PSP_GL_GetProcAddress(_THIS, const char *proc) |
| { |
| return eglGetProcAddress(proc); |
| } |
| |
| void |
| PSP_GL_UnloadLibrary(_THIS) |
| { |
| eglTerminate(_this->gl_data->display); |
| } |
| |
| static EGLint width = 480; |
| static EGLint height = 272; |
| |
| SDL_GLContext |
| PSP_GL_CreateContext(_THIS, SDL_Window * window) |
| { |
| |
| SDL_WindowData *wdata = (SDL_WindowData *) window->driverdata; |
| |
| EGLint attribs[32]; |
| EGLDisplay display; |
| EGLContext context; |
| EGLSurface surface; |
| EGLConfig config; |
| EGLint num_configs; |
| int i; |
| |
| |
| /* EGL init taken from glutCreateWindow() in PSPGL's glut.c. */ |
| EGLCHK(display = eglGetDisplay(0)); |
| EGLCHK(eglInitialize(display, NULL, NULL)); |
| wdata->uses_gles = SDL_TRUE; |
| window->flags |= SDL_WINDOW_FULLSCREEN; |
| |
| /* Setup the config based on SDL's current values. */ |
| i = 0; |
| attribs[i++] = EGL_RED_SIZE; |
| attribs[i++] = _this->gl_config.red_size; |
| attribs[i++] = EGL_GREEN_SIZE; |
| attribs[i++] = _this->gl_config.green_size; |
| attribs[i++] = EGL_BLUE_SIZE; |
| attribs[i++] = _this->gl_config.blue_size; |
| attribs[i++] = EGL_DEPTH_SIZE; |
| attribs[i++] = _this->gl_config.depth_size; |
| |
| if (_this->gl_config.alpha_size) |
| { |
| attribs[i++] = EGL_ALPHA_SIZE; |
| attribs[i++] = _this->gl_config.alpha_size; |
| } |
| if (_this->gl_config.stencil_size) |
| { |
| attribs[i++] = EGL_STENCIL_SIZE; |
| attribs[i++] = _this->gl_config.stencil_size; |
| } |
| |
| attribs[i++] = EGL_NONE; |
| |
| EGLCHK(eglChooseConfig(display, attribs, &config, 1, &num_configs)); |
| |
| if (num_configs == 0) |
| { |
| SDL_SetError("No valid EGL configs for requested mode"); |
| return 0; |
| } |
| |
| EGLCHK(eglGetConfigAttrib(display, config, EGL_WIDTH, &width)); |
| EGLCHK(eglGetConfigAttrib(display, config, EGL_HEIGHT, &height)); |
| |
| EGLCHK(context = eglCreateContext(display, config, NULL, NULL)); |
| EGLCHK(surface = eglCreateWindowSurface(display, config, 0, NULL)); |
| EGLCHK(eglMakeCurrent(display, surface, surface, context)); |
| |
| _this->gl_data->display = display; |
| _this->gl_data->context = context; |
| _this->gl_data->surface = surface; |
| |
| |
| return context; |
| } |
| |
| int |
| PSP_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context) |
| { |
| if (!eglMakeCurrent(_this->gl_data->display, _this->gl_data->surface, |
| _this->gl_data->surface, _this->gl_data->context)) |
| { |
| return SDL_SetError("Unable to make EGL context current"); |
| } |
| return 0; |
| } |
| |
| int |
| PSP_GL_SetSwapInterval(_THIS, int interval) |
| { |
| EGLBoolean status; |
| status = eglSwapInterval(_this->gl_data->display, interval); |
| if (status == EGL_TRUE) { |
| /* Return success to upper level */ |
| _this->gl_data->swapinterval = interval; |
| return 0; |
| } |
| /* Failed to set swap interval */ |
| return SDL_SetError("Unable to set the EGL swap interval"); |
| } |
| |
| int |
| PSP_GL_GetSwapInterval(_THIS) |
| { |
| return _this->gl_data->swapinterval; |
| } |
| |
| void |
| PSP_GL_SwapWindow(_THIS, SDL_Window * window) |
| { |
| eglSwapBuffers(_this->gl_data->display, _this->gl_data->surface); |
| } |
| |
| void |
| PSP_GL_DeleteContext(_THIS, SDL_GLContext context) |
| { |
| SDL_VideoData *phdata = (SDL_VideoData *) _this->driverdata; |
| EGLBoolean status; |
| |
| if (phdata->egl_initialized != SDL_TRUE) { |
| SDL_SetError("PSP: GLES initialization failed, no OpenGL ES support"); |
| return; |
| } |
| |
| /* Check if OpenGL ES connection has been initialized */ |
| if (_this->gl_data->display != EGL_NO_DISPLAY) { |
| if (context != EGL_NO_CONTEXT) { |
| status = eglDestroyContext(_this->gl_data->display, context); |
| if (status != EGL_TRUE) { |
| /* Error during OpenGL ES context destroying */ |
| SDL_SetError("PSP: OpenGL ES context destroy error"); |
| return; |
| } |
| } |
| } |
| |
| return; |
| } |
| |
| #endif /* SDL_VIDEO_DRIVER_PSP */ |
| |
| /* vi: set ts=4 sw=4 expandtab: */ |