diff options
Diffstat (limited to '3rdparty/SDL2/src/render/opengl/SDL_render_gl.c')
-rw-r--r-- | 3rdparty/SDL2/src/render/opengl/SDL_render_gl.c | 1597 |
1 files changed, 0 insertions, 1597 deletions
diff --git a/3rdparty/SDL2/src/render/opengl/SDL_render_gl.c b/3rdparty/SDL2/src/render/opengl/SDL_render_gl.c deleted file mode 100644 index 1ca2cb5c4c0..00000000000 --- a/3rdparty/SDL2/src/render/opengl/SDL_render_gl.c +++ /dev/null @@ -1,1597 +0,0 @@ -/* - 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_RENDER_OGL && !SDL_RENDER_DISABLED - -#include "SDL_hints.h" -#include "SDL_log.h" -#include "SDL_assert.h" -#include "SDL_opengl.h" -#include "../SDL_sysrender.h" -#include "SDL_shaders_gl.h" - -#ifdef __MACOSX__ -#include <OpenGL/OpenGL.h> -#endif - -/* To prevent unnecessary window recreation, - * these should match the defaults selected in SDL_GL_ResetAttributes - */ - -#define RENDERER_CONTEXT_MAJOR 2 -#define RENDERER_CONTEXT_MINOR 1 - -/* OpenGL renderer implementation */ - -/* Details on optimizing the texture path on Mac OS X: - http://developer.apple.com/library/mac/#documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/opengl_texturedata/opengl_texturedata.html -*/ - -/* Used to re-create the window with OpenGL capability */ -extern int SDL_RecreateWindow(SDL_Window * window, Uint32 flags); - -static const float inv255f = 1.0f / 255.0f; - -static SDL_Renderer *GL_CreateRenderer(SDL_Window * window, Uint32 flags); -static void GL_WindowEvent(SDL_Renderer * renderer, - const SDL_WindowEvent *event); -static int GL_GetOutputSize(SDL_Renderer * renderer, int *w, int *h); -static int GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture); -static int GL_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, - const SDL_Rect * rect, const void *pixels, - int pitch); -static int GL_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture, - const SDL_Rect * rect, - const Uint8 *Yplane, int Ypitch, - const Uint8 *Uplane, int Upitch, - const Uint8 *Vplane, int Vpitch); -static int GL_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture, - const SDL_Rect * rect, void **pixels, int *pitch); -static void GL_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture); -static int GL_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture); -static int GL_UpdateViewport(SDL_Renderer * renderer); -static int GL_UpdateClipRect(SDL_Renderer * renderer); -static int GL_RenderClear(SDL_Renderer * renderer); -static int GL_RenderDrawPoints(SDL_Renderer * renderer, - const SDL_FPoint * points, int count); -static int GL_RenderDrawLines(SDL_Renderer * renderer, - const SDL_FPoint * points, int count); -static int GL_RenderFillRects(SDL_Renderer * renderer, - const SDL_FRect * rects, int count); -static int GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, - const SDL_Rect * srcrect, const SDL_FRect * dstrect); -static int GL_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture, - const SDL_Rect * srcrect, const SDL_FRect * dstrect, - const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip); -static int GL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect, - Uint32 pixel_format, void * pixels, int pitch); -static void GL_RenderPresent(SDL_Renderer * renderer); -static void GL_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture); -static void GL_DestroyRenderer(SDL_Renderer * renderer); -static int GL_BindTexture (SDL_Renderer * renderer, SDL_Texture *texture, float *texw, float *texh); -static int GL_UnbindTexture (SDL_Renderer * renderer, SDL_Texture *texture); - -SDL_RenderDriver GL_RenderDriver = { - GL_CreateRenderer, - { - "opengl", - (SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE), - 1, - {SDL_PIXELFORMAT_ARGB8888}, - 0, - 0} -}; - -typedef struct GL_FBOList GL_FBOList; - -struct GL_FBOList -{ - Uint32 w, h; - GLuint FBO; - GL_FBOList *next; -}; - -typedef struct -{ - SDL_GLContext context; - - SDL_bool debug_enabled; - SDL_bool GL_ARB_debug_output_supported; - int errors; - char **error_messages; - GLDEBUGPROCARB next_error_callback; - GLvoid *next_error_userparam; - - SDL_bool GL_ARB_texture_non_power_of_two_supported; - SDL_bool GL_ARB_texture_rectangle_supported; - struct { - GL_Shader shader; - Uint32 color; - int blendMode; - } current; - - SDL_bool GL_EXT_framebuffer_object_supported; - GL_FBOList *framebuffers; - - /* OpenGL functions */ -#define SDL_PROC(ret,func,params) ret (APIENTRY *func) params; -#include "SDL_glfuncs.h" -#undef SDL_PROC - - /* Multitexture support */ - SDL_bool GL_ARB_multitexture_supported; - PFNGLACTIVETEXTUREARBPROC glActiveTextureARB; - GLint num_texture_units; - - PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT; - PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT; - PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT; - PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT; - PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT; - - /* Shader support */ - GL_ShaderContext *shaders; - -} GL_RenderData; - -typedef struct -{ - GLuint texture; - GLenum type; - GLfloat texw; - GLfloat texh; - GLenum format; - GLenum formattype; - void *pixels; - int pitch; - SDL_Rect locked_rect; - - /* YUV texture support */ - SDL_bool yuv; - SDL_bool nv12; - GLuint utexture; - GLuint vtexture; - - GL_FBOList *fbo; -} GL_TextureData; - -SDL_FORCE_INLINE const char* -GL_TranslateError (GLenum error) -{ -#define GL_ERROR_TRANSLATE(e) case e: return #e; - switch (error) { - GL_ERROR_TRANSLATE(GL_INVALID_ENUM) - GL_ERROR_TRANSLATE(GL_INVALID_VALUE) - GL_ERROR_TRANSLATE(GL_INVALID_OPERATION) - GL_ERROR_TRANSLATE(GL_OUT_OF_MEMORY) - GL_ERROR_TRANSLATE(GL_NO_ERROR) - GL_ERROR_TRANSLATE(GL_STACK_OVERFLOW) - GL_ERROR_TRANSLATE(GL_STACK_UNDERFLOW) - GL_ERROR_TRANSLATE(GL_TABLE_TOO_LARGE) - default: - return "UNKNOWN"; -} -#undef GL_ERROR_TRANSLATE -} - -SDL_FORCE_INLINE void -GL_ClearErrors(SDL_Renderer *renderer) -{ - GL_RenderData *data = (GL_RenderData *) renderer->driverdata; - - if (!data->debug_enabled) - { - return; - } - if (data->GL_ARB_debug_output_supported) { - if (data->errors) { - int i; - for (i = 0; i < data->errors; ++i) { - SDL_free(data->error_messages[i]); - } - SDL_free(data->error_messages); - - data->errors = 0; - data->error_messages = NULL; - } - } else { - while (data->glGetError() != GL_NO_ERROR) { - continue; - } - } -} - -SDL_FORCE_INLINE int -GL_CheckAllErrors (const char *prefix, SDL_Renderer *renderer, const char *file, int line, const char *function) -{ - GL_RenderData *data = (GL_RenderData *) renderer->driverdata; - int ret = 0; - - if (!data->debug_enabled) - { - return 0; - } - if (data->GL_ARB_debug_output_supported) { - if (data->errors) { - int i; - for (i = 0; i < data->errors; ++i) { - SDL_SetError("%s: %s (%d): %s %s", prefix, file, line, function, data->error_messages[i]); - ret = -1; - } - GL_ClearErrors(renderer); - } - } else { - /* check gl errors (can return multiple errors) */ - for (;;) { - GLenum error = data->glGetError(); - if (error != GL_NO_ERROR) { - if (prefix == NULL || prefix[0] == '\0') { - prefix = "generic"; - } - SDL_SetError("%s: %s (%d): %s %s (0x%X)", prefix, file, line, function, GL_TranslateError(error), error); - ret = -1; - } else { - break; - } - } - } - return ret; -} - -#if 0 -#define GL_CheckError(prefix, renderer) -#elif defined(_MSC_VER) -#define GL_CheckError(prefix, renderer) GL_CheckAllErrors(prefix, renderer, __FILE__, __LINE__, __FUNCTION__) -#else -#define GL_CheckError(prefix, renderer) GL_CheckAllErrors(prefix, renderer, __FILE__, __LINE__, __PRETTY_FUNCTION__) -#endif - -static int -GL_LoadFunctions(GL_RenderData * data) -{ -#ifdef __SDL_NOGETPROCADDR__ -#define SDL_PROC(ret,func,params) data->func=func; -#else -#define SDL_PROC(ret,func,params) \ - do { \ - data->func = SDL_GL_GetProcAddress(#func); \ - if ( ! data->func ) { \ - return SDL_SetError("Couldn't load GL function %s: %s\n", #func, SDL_GetError()); \ - } \ - } while ( 0 ); -#endif /* __SDL_NOGETPROCADDR__ */ - -#include "SDL_glfuncs.h" -#undef SDL_PROC - return 0; -} - -static SDL_GLContext SDL_CurrentContext = NULL; - -static int -GL_ActivateRenderer(SDL_Renderer * renderer) -{ - GL_RenderData *data = (GL_RenderData *) renderer->driverdata; - - if (SDL_CurrentContext != data->context || - SDL_GL_GetCurrentContext() != data->context) { - if (SDL_GL_MakeCurrent(renderer->window, data->context) < 0) { - return -1; - } - SDL_CurrentContext = data->context; - - GL_UpdateViewport(renderer); - } - - GL_ClearErrors(renderer); - - return 0; -} - -/* This is called if we need to invalidate all of the SDL OpenGL state */ -static void -GL_ResetState(SDL_Renderer *renderer) -{ - GL_RenderData *data = (GL_RenderData *) renderer->driverdata; - - if (SDL_GL_GetCurrentContext() == data->context) { - GL_UpdateViewport(renderer); - } else { - GL_ActivateRenderer(renderer); - } - - data->current.shader = SHADER_NONE; - data->current.color = 0; - data->current.blendMode = -1; - - data->glDisable(GL_DEPTH_TEST); - data->glDisable(GL_CULL_FACE); - /* This ended up causing video discrepancies between OpenGL and Direct3D */ - /* data->glEnable(GL_LINE_SMOOTH); */ - - data->glMatrixMode(GL_MODELVIEW); - data->glLoadIdentity(); - - GL_CheckError("", renderer); -} - -static void APIENTRY -GL_HandleDebugMessage(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const char *message, const void *userParam) -{ - SDL_Renderer *renderer = (SDL_Renderer *) userParam; - GL_RenderData *data = (GL_RenderData *) renderer->driverdata; - - if (type == GL_DEBUG_TYPE_ERROR_ARB) { - /* Record this error */ - int errors = data->errors + 1; - char **error_messages = SDL_realloc(data->error_messages, errors * sizeof(*data->error_messages)); - if (error_messages) { - data->errors = errors; - data->error_messages = error_messages; - data->error_messages[data->errors-1] = SDL_strdup(message); - } - } - - /* If there's another error callback, pass it along, otherwise log it */ - if (data->next_error_callback) { - data->next_error_callback(source, type, id, severity, length, message, data->next_error_userparam); - } else { - if (type == GL_DEBUG_TYPE_ERROR_ARB) { - SDL_LogError(SDL_LOG_CATEGORY_RENDER, "%s", message); - } else { - SDL_LogDebug(SDL_LOG_CATEGORY_RENDER, "%s", message); - } - } -} - -static GL_FBOList * -GL_GetFBO(GL_RenderData *data, Uint32 w, Uint32 h) -{ - GL_FBOList *result = data->framebuffers; - - while (result && ((result->w != w) || (result->h != h))) { - result = result->next; - } - - if (!result) { - result = SDL_malloc(sizeof(GL_FBOList)); - if (result) { - result->w = w; - result->h = h; - data->glGenFramebuffersEXT(1, &result->FBO); - result->next = data->framebuffers; - data->framebuffers = result; - } - } - return result; -} - -SDL_Renderer * -GL_CreateRenderer(SDL_Window * window, Uint32 flags) -{ - SDL_Renderer *renderer; - GL_RenderData *data; - GLint value; - Uint32 window_flags; - int profile_mask = 0, major = 0, minor = 0; - SDL_bool changed_window = SDL_FALSE; - - SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &profile_mask); - SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &major); - SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &minor); - - window_flags = SDL_GetWindowFlags(window); - if (!(window_flags & SDL_WINDOW_OPENGL) || - profile_mask == SDL_GL_CONTEXT_PROFILE_ES || major != RENDERER_CONTEXT_MAJOR || minor != RENDERER_CONTEXT_MINOR) { - - changed_window = SDL_TRUE; - SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, 0); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, RENDERER_CONTEXT_MAJOR); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, RENDERER_CONTEXT_MINOR); - - if (SDL_RecreateWindow(window, window_flags | SDL_WINDOW_OPENGL) < 0) { - goto error; - } - } - - renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer)); - if (!renderer) { - SDL_OutOfMemory(); - goto error; - } - - data = (GL_RenderData *) SDL_calloc(1, sizeof(*data)); - if (!data) { - GL_DestroyRenderer(renderer); - SDL_OutOfMemory(); - goto error; - } - - renderer->WindowEvent = GL_WindowEvent; - renderer->GetOutputSize = GL_GetOutputSize; - renderer->CreateTexture = GL_CreateTexture; - renderer->UpdateTexture = GL_UpdateTexture; - renderer->UpdateTextureYUV = GL_UpdateTextureYUV; - renderer->LockTexture = GL_LockTexture; - renderer->UnlockTexture = GL_UnlockTexture; - renderer->SetRenderTarget = GL_SetRenderTarget; - renderer->UpdateViewport = GL_UpdateViewport; - renderer->UpdateClipRect = GL_UpdateClipRect; - renderer->RenderClear = GL_RenderClear; - renderer->RenderDrawPoints = GL_RenderDrawPoints; - renderer->RenderDrawLines = GL_RenderDrawLines; - renderer->RenderFillRects = GL_RenderFillRects; - renderer->RenderCopy = GL_RenderCopy; - renderer->RenderCopyEx = GL_RenderCopyEx; - renderer->RenderReadPixels = GL_RenderReadPixels; - renderer->RenderPresent = GL_RenderPresent; - renderer->DestroyTexture = GL_DestroyTexture; - renderer->DestroyRenderer = GL_DestroyRenderer; - renderer->GL_BindTexture = GL_BindTexture; - renderer->GL_UnbindTexture = GL_UnbindTexture; - renderer->info = GL_RenderDriver.info; - renderer->info.flags = SDL_RENDERER_ACCELERATED; - renderer->driverdata = data; - renderer->window = window; - - data->context = SDL_GL_CreateContext(window); - if (!data->context) { - GL_DestroyRenderer(renderer); - goto error; - } - if (SDL_GL_MakeCurrent(window, data->context) < 0) { - GL_DestroyRenderer(renderer); - goto error; - } - - if (GL_LoadFunctions(data) < 0) { - GL_DestroyRenderer(renderer); - goto error; - } - -#ifdef __MACOSX__ - /* Enable multi-threaded rendering */ - /* Disabled until Ryan finishes his VBO/PBO code... - CGLEnable(CGLGetCurrentContext(), kCGLCEMPEngine); - */ -#endif - - if (flags & SDL_RENDERER_PRESENTVSYNC) { - SDL_GL_SetSwapInterval(1); - } else { - SDL_GL_SetSwapInterval(0); - } - if (SDL_GL_GetSwapInterval() > 0) { - renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; - } - - /* Check for debug output support */ - if (SDL_GL_GetAttribute(SDL_GL_CONTEXT_FLAGS, &value) == 0 && - (value & SDL_GL_CONTEXT_DEBUG_FLAG)) { - data->debug_enabled = SDL_TRUE; - } - if (data->debug_enabled && SDL_GL_ExtensionSupported("GL_ARB_debug_output")) { - PFNGLDEBUGMESSAGECALLBACKARBPROC glDebugMessageCallbackARBFunc = (PFNGLDEBUGMESSAGECALLBACKARBPROC) SDL_GL_GetProcAddress("glDebugMessageCallbackARB"); - - data->GL_ARB_debug_output_supported = SDL_TRUE; - data->glGetPointerv(GL_DEBUG_CALLBACK_FUNCTION_ARB, (GLvoid **)&data->next_error_callback); - data->glGetPointerv(GL_DEBUG_CALLBACK_USER_PARAM_ARB, &data->next_error_userparam); - glDebugMessageCallbackARBFunc(GL_HandleDebugMessage, renderer); - - /* Make sure our callback is called when errors actually happen */ - data->glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB); - } - - if (SDL_GL_ExtensionSupported("GL_ARB_texture_non_power_of_two")) { - data->GL_ARB_texture_non_power_of_two_supported = SDL_TRUE; - } else if (SDL_GL_ExtensionSupported("GL_ARB_texture_rectangle") || - SDL_GL_ExtensionSupported("GL_EXT_texture_rectangle")) { - data->GL_ARB_texture_rectangle_supported = SDL_TRUE; - } - if (data->GL_ARB_texture_rectangle_supported) { - data->glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB, &value); - renderer->info.max_texture_width = value; - renderer->info.max_texture_height = value; - } else { - data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value); - renderer->info.max_texture_width = value; - renderer->info.max_texture_height = value; - } - - /* Check for multitexture support */ - if (SDL_GL_ExtensionSupported("GL_ARB_multitexture")) { - data->glActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC) SDL_GL_GetProcAddress("glActiveTextureARB"); - if (data->glActiveTextureARB) { - data->GL_ARB_multitexture_supported = SDL_TRUE; - data->glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &data->num_texture_units); - } - } - - /* Check for shader support */ - if (SDL_GetHintBoolean(SDL_HINT_RENDER_OPENGL_SHADERS, SDL_TRUE)) { - data->shaders = GL_CreateShaderContext(); - } - SDL_LogInfo(SDL_LOG_CATEGORY_RENDER, "OpenGL shaders: %s", - data->shaders ? "ENABLED" : "DISABLED"); - - /* We support YV12 textures using 3 textures and a shader */ - if (data->shaders && data->num_texture_units >= 3) { - renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_YV12; - renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_IYUV; - renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_NV12; - renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_NV21; - } - -#ifdef __MACOSX__ - renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_UYVY; -#endif - - if (SDL_GL_ExtensionSupported("GL_EXT_framebuffer_object")) { - data->GL_EXT_framebuffer_object_supported = SDL_TRUE; - data->glGenFramebuffersEXT = (PFNGLGENFRAMEBUFFERSEXTPROC) - SDL_GL_GetProcAddress("glGenFramebuffersEXT"); - data->glDeleteFramebuffersEXT = (PFNGLDELETEFRAMEBUFFERSEXTPROC) - SDL_GL_GetProcAddress("glDeleteFramebuffersEXT"); - data->glFramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) - SDL_GL_GetProcAddress("glFramebufferTexture2DEXT"); - data->glBindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC) - SDL_GL_GetProcAddress("glBindFramebufferEXT"); - data->glCheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) - SDL_GL_GetProcAddress("glCheckFramebufferStatusEXT"); - renderer->info.flags |= SDL_RENDERER_TARGETTEXTURE; - } - data->framebuffers = NULL; - - /* Set up parameters for rendering */ - GL_ResetState(renderer); - - return renderer; - -error: - if (changed_window) { - /* Uh oh, better try to put it back... */ - SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, profile_mask); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, major); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, minor); - SDL_RecreateWindow(window, window_flags); - } - return NULL; -} - -static void -GL_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event) -{ - if (event->event == SDL_WINDOWEVENT_SIZE_CHANGED || - event->event == SDL_WINDOWEVENT_SHOWN || - event->event == SDL_WINDOWEVENT_HIDDEN) { - /* Rebind the context to the window area and update matrices */ - SDL_CurrentContext = NULL; - } -} - -static int -GL_GetOutputSize(SDL_Renderer * renderer, int *w, int *h) -{ - SDL_GL_GetDrawableSize(renderer->window, w, h); - return 0; -} - -SDL_FORCE_INLINE int -power_of_2(int input) -{ - int value = 1; - - while (value < input) { - value <<= 1; - } - return value; -} - -SDL_FORCE_INLINE SDL_bool -convert_format(GL_RenderData *renderdata, Uint32 pixel_format, - GLint* internalFormat, GLenum* format, GLenum* type) -{ - switch (pixel_format) { - case SDL_PIXELFORMAT_ARGB8888: - *internalFormat = GL_RGBA8; - *format = GL_BGRA; - *type = GL_UNSIGNED_INT_8_8_8_8_REV; - break; - case SDL_PIXELFORMAT_YV12: - case SDL_PIXELFORMAT_IYUV: - case SDL_PIXELFORMAT_NV12: - case SDL_PIXELFORMAT_NV21: - *internalFormat = GL_LUMINANCE; - *format = GL_LUMINANCE; - *type = GL_UNSIGNED_BYTE; - break; -#ifdef __MACOSX__ - case SDL_PIXELFORMAT_UYVY: - *internalFormat = GL_RGB8; - *format = GL_YCBCR_422_APPLE; - *type = GL_UNSIGNED_SHORT_8_8_APPLE; - break; -#endif - default: - return SDL_FALSE; - } - return SDL_TRUE; -} - -static GLenum -GetScaleQuality(void) -{ - const char *hint = SDL_GetHint(SDL_HINT_RENDER_SCALE_QUALITY); - - if (!hint || *hint == '0' || SDL_strcasecmp(hint, "nearest") == 0) { - return GL_NEAREST; - } else { - return GL_LINEAR; - } -} - -static int -GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) -{ - GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata; - GL_TextureData *data; - GLint internalFormat; - GLenum format, type; - int texture_w, texture_h; - GLenum scaleMode; - - GL_ActivateRenderer(renderer); - - if (texture->access == SDL_TEXTUREACCESS_TARGET && - !renderdata->GL_EXT_framebuffer_object_supported) { - return SDL_SetError("Render targets not supported by OpenGL"); - } - - if (!convert_format(renderdata, texture->format, &internalFormat, - &format, &type)) { - return SDL_SetError("Texture format %s not supported by OpenGL", - SDL_GetPixelFormatName(texture->format)); - } - - data = (GL_TextureData *) SDL_calloc(1, sizeof(*data)); - if (!data) { - return SDL_OutOfMemory(); - } - - if (texture->access == SDL_TEXTUREACCESS_STREAMING) { - size_t size; - data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format); - size = texture->h * data->pitch; - if (texture->format == SDL_PIXELFORMAT_YV12 || - texture->format == SDL_PIXELFORMAT_IYUV) { - /* Need to add size for the U and V planes */ - size += (2 * (texture->h * data->pitch) / 4); - } - if (texture->format == SDL_PIXELFORMAT_NV12 || - texture->format == SDL_PIXELFORMAT_NV21) { - /* Need to add size for the U/V plane */ - size += ((texture->h * data->pitch) / 2); - } - data->pixels = SDL_calloc(1, size); - if (!data->pixels) { - SDL_free(data); - return SDL_OutOfMemory(); - } - } - - if (texture->access == SDL_TEXTUREACCESS_TARGET) { - data->fbo = GL_GetFBO(renderdata, texture->w, texture->h); - } else { - data->fbo = NULL; - } - - GL_CheckError("", renderer); - renderdata->glGenTextures(1, &data->texture); - if (GL_CheckError("glGenTextures()", renderer) < 0) { - if (data->pixels) { - SDL_free(data->pixels); - } - SDL_free(data); - return -1; - } - texture->driverdata = data; - - if (renderdata->GL_ARB_texture_non_power_of_two_supported) { - data->type = GL_TEXTURE_2D; - texture_w = texture->w; - texture_h = texture->h; - data->texw = 1.0f; - data->texh = 1.0f; - } else if (renderdata->GL_ARB_texture_rectangle_supported) { - data->type = GL_TEXTURE_RECTANGLE_ARB; - texture_w = texture->w; - texture_h = texture->h; - data->texw = (GLfloat) texture_w; - data->texh = (GLfloat) texture_h; - } else { - data->type = GL_TEXTURE_2D; - texture_w = power_of_2(texture->w); - texture_h = power_of_2(texture->h); - data->texw = (GLfloat) (texture->w) / texture_w; - data->texh = (GLfloat) texture->h / texture_h; - } - - data->format = format; - data->formattype = type; - scaleMode = GetScaleQuality(); - renderdata->glEnable(data->type); - renderdata->glBindTexture(data->type, data->texture); - renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER, scaleMode); - renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER, scaleMode); - /* According to the spec, CLAMP_TO_EDGE is the default for TEXTURE_RECTANGLE - and setting it causes an INVALID_ENUM error in the latest NVidia drivers. - */ - if (data->type != GL_TEXTURE_RECTANGLE_ARB) { - renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S, - GL_CLAMP_TO_EDGE); - renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T, - GL_CLAMP_TO_EDGE); - } -#ifdef __MACOSX__ -#ifndef GL_TEXTURE_STORAGE_HINT_APPLE -#define GL_TEXTURE_STORAGE_HINT_APPLE 0x85BC -#endif -#ifndef STORAGE_CACHED_APPLE -#define STORAGE_CACHED_APPLE 0x85BE -#endif -#ifndef STORAGE_SHARED_APPLE -#define STORAGE_SHARED_APPLE 0x85BF -#endif - if (texture->access == SDL_TEXTUREACCESS_STREAMING) { - renderdata->glTexParameteri(data->type, GL_TEXTURE_STORAGE_HINT_APPLE, - GL_STORAGE_SHARED_APPLE); - } else { - renderdata->glTexParameteri(data->type, GL_TEXTURE_STORAGE_HINT_APPLE, - GL_STORAGE_CACHED_APPLE); - } - if (texture->access == SDL_TEXTUREACCESS_STREAMING - && texture->format == SDL_PIXELFORMAT_ARGB8888 - && (texture->w % 8) == 0) { - renderdata->glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE); - renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, - (data->pitch / SDL_BYTESPERPIXEL(texture->format))); - renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w, - texture_h, 0, format, type, data->pixels); - renderdata->glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE); - } - else -#endif - { - renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w, - texture_h, 0, format, type, NULL); - } - renderdata->glDisable(data->type); - if (GL_CheckError("glTexImage2D()", renderer) < 0) { - return -1; - } - - if (texture->format == SDL_PIXELFORMAT_YV12 || - texture->format == SDL_PIXELFORMAT_IYUV) { - data->yuv = SDL_TRUE; - - renderdata->glGenTextures(1, &data->utexture); - renderdata->glGenTextures(1, &data->vtexture); - renderdata->glEnable(data->type); - - renderdata->glBindTexture(data->type, data->utexture); - renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER, - scaleMode); - renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER, - scaleMode); - renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S, - GL_CLAMP_TO_EDGE); - renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T, - GL_CLAMP_TO_EDGE); - renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w/2, - texture_h/2, 0, format, type, NULL); - - renderdata->glBindTexture(data->type, data->vtexture); - renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER, - scaleMode); - renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER, - scaleMode); - renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S, - GL_CLAMP_TO_EDGE); - renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T, - GL_CLAMP_TO_EDGE); - renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w/2, - texture_h/2, 0, format, type, NULL); - - renderdata->glDisable(data->type); - } - - if (texture->format == SDL_PIXELFORMAT_NV12 || - texture->format == SDL_PIXELFORMAT_NV21) { - data->nv12 = SDL_TRUE; - - renderdata->glGenTextures(1, &data->utexture); - renderdata->glEnable(data->type); - - renderdata->glBindTexture(data->type, data->utexture); - renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER, - scaleMode); - renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER, - scaleMode); - renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S, - GL_CLAMP_TO_EDGE); - renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T, - GL_CLAMP_TO_EDGE); - renderdata->glTexImage2D(data->type, 0, GL_LUMINANCE_ALPHA, texture_w/2, - texture_h/2, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL); - renderdata->glDisable(data->type); - } - - return GL_CheckError("", renderer); -} - -static int -GL_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, - const SDL_Rect * rect, const void *pixels, int pitch) -{ - GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata; - GL_TextureData *data = (GL_TextureData *) texture->driverdata; - const int texturebpp = SDL_BYTESPERPIXEL(texture->format); - - SDL_assert(texturebpp != 0); /* otherwise, division by zero later. */ - - GL_ActivateRenderer(renderer); - - renderdata->glEnable(data->type); - renderdata->glBindTexture(data->type, data->texture); - renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, (pitch / texturebpp)); - renderdata->glTexSubImage2D(data->type, 0, rect->x, rect->y, rect->w, - rect->h, data->format, data->formattype, - pixels); - if (data->yuv) { - renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, (pitch / 2)); - - /* Skip to the correct offset into the next texture */ - pixels = (const void*)((const Uint8*)pixels + rect->h * pitch); - if (texture->format == SDL_PIXELFORMAT_YV12) { - renderdata->glBindTexture(data->type, data->vtexture); - } else { - renderdata->glBindTexture(data->type, data->utexture); - } - renderdata->glTexSubImage2D(data->type, 0, rect->x/2, rect->y/2, - rect->w/2, rect->h/2, - data->format, data->formattype, pixels); - - /* Skip to the correct offset into the next texture */ - pixels = (const void*)((const Uint8*)pixels + (rect->h * pitch)/4); - if (texture->format == SDL_PIXELFORMAT_YV12) { - renderdata->glBindTexture(data->type, data->utexture); - } else { - renderdata->glBindTexture(data->type, data->vtexture); - } - renderdata->glTexSubImage2D(data->type, 0, rect->x/2, rect->y/2, - rect->w/2, rect->h/2, - data->format, data->formattype, pixels); - } - - if (data->nv12) { - renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, (pitch / 2)); - - /* Skip to the correct offset into the next texture */ - pixels = (const void*)((const Uint8*)pixels + rect->h * pitch); - renderdata->glBindTexture(data->type, data->utexture); - renderdata->glTexSubImage2D(data->type, 0, rect->x/2, rect->y/2, - rect->w/2, rect->h/2, - GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, pixels); - } - renderdata->glDisable(data->type); - - return GL_CheckError("glTexSubImage2D()", renderer); -} - -static int -GL_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture, - const SDL_Rect * rect, - const Uint8 *Yplane, int Ypitch, - const Uint8 *Uplane, int Upitch, - const Uint8 *Vplane, int Vpitch) -{ - GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata; - GL_TextureData *data = (GL_TextureData *) texture->driverdata; - - GL_ActivateRenderer(renderer); - - renderdata->glEnable(data->type); - renderdata->glBindTexture(data->type, data->texture); - renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, Ypitch); - renderdata->glTexSubImage2D(data->type, 0, rect->x, rect->y, rect->w, - rect->h, data->format, data->formattype, - Yplane); - - renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, Upitch); - renderdata->glBindTexture(data->type, data->utexture); - renderdata->glTexSubImage2D(data->type, 0, rect->x/2, rect->y/2, - rect->w/2, rect->h/2, - data->format, data->formattype, Uplane); - - renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, Vpitch); - renderdata->glBindTexture(data->type, data->vtexture); - renderdata->glTexSubImage2D(data->type, 0, rect->x/2, rect->y/2, - rect->w/2, rect->h/2, - data->format, data->formattype, Vplane); - renderdata->glDisable(data->type); - - return GL_CheckError("glTexSubImage2D()", renderer); -} - -static int -GL_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture, - const SDL_Rect * rect, void **pixels, int *pitch) -{ - GL_TextureData *data = (GL_TextureData *) texture->driverdata; - - data->locked_rect = *rect; - *pixels = - (void *) ((Uint8 *) data->pixels + rect->y * data->pitch + - rect->x * SDL_BYTESPERPIXEL(texture->format)); - *pitch = data->pitch; - return 0; -} - -static void -GL_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture) -{ - GL_TextureData *data = (GL_TextureData *) texture->driverdata; - const SDL_Rect *rect; - void *pixels; - - rect = &data->locked_rect; - pixels = - (void *) ((Uint8 *) data->pixels + rect->y * data->pitch + - rect->x * SDL_BYTESPERPIXEL(texture->format)); - GL_UpdateTexture(renderer, texture, rect, pixels, data->pitch); -} - -static int -GL_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture) -{ - GL_RenderData *data = (GL_RenderData *) renderer->driverdata; - GL_TextureData *texturedata; - GLenum status; - - GL_ActivateRenderer(renderer); - - if (!data->GL_EXT_framebuffer_object_supported) { - return SDL_SetError("Render targets not supported by OpenGL"); - } - - if (texture == NULL) { - data->glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - return 0; - } - - texturedata = (GL_TextureData *) texture->driverdata; - data->glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, texturedata->fbo->FBO); - /* TODO: check if texture pixel format allows this operation */ - data->glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, texturedata->type, texturedata->texture, 0); - /* Check FBO status */ - status = data->glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); - if (status != GL_FRAMEBUFFER_COMPLETE_EXT) { - return SDL_SetError("glFramebufferTexture2DEXT() failed"); - } - return 0; -} - -static int -GL_UpdateViewport(SDL_Renderer * renderer) -{ - GL_RenderData *data = (GL_RenderData *) renderer->driverdata; - - if (SDL_CurrentContext != data->context) { - /* We'll update the viewport after we rebind the context */ - return 0; - } - - if (renderer->target) { - data->glViewport(renderer->viewport.x, renderer->viewport.y, - renderer->viewport.w, renderer->viewport.h); - } else { - int w, h; - - SDL_GL_GetDrawableSize(renderer->window, &w, &h); - data->glViewport(renderer->viewport.x, (h - renderer->viewport.y - renderer->viewport.h), - renderer->viewport.w, renderer->viewport.h); - } - - data->glMatrixMode(GL_PROJECTION); - data->glLoadIdentity(); - if (renderer->viewport.w && renderer->viewport.h) { - if (renderer->target) { - data->glOrtho((GLdouble) 0, - (GLdouble) renderer->viewport.w, - (GLdouble) 0, - (GLdouble) renderer->viewport.h, - 0.0, 1.0); - } else { - data->glOrtho((GLdouble) 0, - (GLdouble) renderer->viewport.w, - (GLdouble) renderer->viewport.h, - (GLdouble) 0, - 0.0, 1.0); - } - } - return GL_CheckError("", renderer); -} - -static int -GL_UpdateClipRect(SDL_Renderer * renderer) -{ - GL_RenderData *data = (GL_RenderData *) renderer->driverdata; - - if (renderer->clipping_enabled) { - const SDL_Rect *rect = &renderer->clip_rect; - data->glEnable(GL_SCISSOR_TEST); - if (renderer->target) { - data->glScissor(renderer->viewport.x + rect->x, renderer->viewport.y + rect->y, rect->w, rect->h); - } else { - int w, h; - - SDL_GL_GetDrawableSize(renderer->window, &w, &h); - data->glScissor(renderer->viewport.x + rect->x, h - renderer->viewport.y - rect->y - rect->h, rect->w, rect->h); - } - } else { - data->glDisable(GL_SCISSOR_TEST); - } - return 0; -} - -static void -GL_SetShader(GL_RenderData * data, GL_Shader shader) -{ - if (data->shaders && shader != data->current.shader) { - GL_SelectShader(data->shaders, shader); - data->current.shader = shader; - } -} - -static void -GL_SetColor(GL_RenderData * data, Uint8 r, Uint8 g, Uint8 b, Uint8 a) -{ - Uint32 color = ((a << 24) | (r << 16) | (g << 8) | b); - - if (color != data->current.color) { - data->glColor4f((GLfloat) r * inv255f, - (GLfloat) g * inv255f, - (GLfloat) b * inv255f, - (GLfloat) a * inv255f); - data->current.color = color; - } -} - -static void -GL_SetBlendMode(GL_RenderData * data, int blendMode) -{ - if (blendMode != data->current.blendMode) { - switch (blendMode) { - case SDL_BLENDMODE_NONE: - data->glDisable(GL_BLEND); - break; - case SDL_BLENDMODE_BLEND: - data->glEnable(GL_BLEND); - data->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - break; - case SDL_BLENDMODE_ADD: - data->glEnable(GL_BLEND); - data->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ZERO, GL_ONE); - break; - case SDL_BLENDMODE_MOD: - data->glEnable(GL_BLEND); - data->glBlendFuncSeparate(GL_ZERO, GL_SRC_COLOR, GL_ZERO, GL_ONE); - break; - } - data->current.blendMode = blendMode; - } -} - -static void -GL_SetDrawingState(SDL_Renderer * renderer) -{ - GL_RenderData *data = (GL_RenderData *) renderer->driverdata; - - GL_ActivateRenderer(renderer); - - GL_SetColor(data, renderer->r, - renderer->g, - renderer->b, - renderer->a); - - GL_SetBlendMode(data, renderer->blendMode); - - GL_SetShader(data, SHADER_SOLID); -} - -static int -GL_RenderClear(SDL_Renderer * renderer) -{ - GL_RenderData *data = (GL_RenderData *) renderer->driverdata; - - GL_ActivateRenderer(renderer); - - data->glClearColor((GLfloat) renderer->r * inv255f, - (GLfloat) renderer->g * inv255f, - (GLfloat) renderer->b * inv255f, - (GLfloat) renderer->a * inv255f); - - if (renderer->clipping_enabled) { - data->glDisable(GL_SCISSOR_TEST); - } - - data->glClear(GL_COLOR_BUFFER_BIT); - - if (renderer->clipping_enabled) { - data->glEnable(GL_SCISSOR_TEST); - } - - return 0; -} - -static int -GL_RenderDrawPoints(SDL_Renderer * renderer, const SDL_FPoint * points, - int count) -{ - GL_RenderData *data = (GL_RenderData *) renderer->driverdata; - int i; - - GL_SetDrawingState(renderer); - - data->glBegin(GL_POINTS); - for (i = 0; i < count; ++i) { - data->glVertex2f(0.5f + points[i].x, 0.5f + points[i].y); - } - data->glEnd(); - - return 0; -} - -static int -GL_RenderDrawLines(SDL_Renderer * renderer, const SDL_FPoint * points, - int count) -{ - GL_RenderData *data = (GL_RenderData *) renderer->driverdata; - int i; - - GL_SetDrawingState(renderer); - - if (count > 2 && - points[0].x == points[count-1].x && points[0].y == points[count-1].y) { - data->glBegin(GL_LINE_LOOP); - /* GL_LINE_LOOP takes care of the final segment */ - --count; - for (i = 0; i < count; ++i) { - data->glVertex2f(0.5f + points[i].x, 0.5f + points[i].y); - } - data->glEnd(); - } else { -#if defined(__MACOSX__) || defined(__WIN32__) -#else - int x1, y1, x2, y2; -#endif - - data->glBegin(GL_LINE_STRIP); - for (i = 0; i < count; ++i) { - data->glVertex2f(0.5f + points[i].x, 0.5f + points[i].y); - } - data->glEnd(); - - /* The line is half open, so we need one more point to complete it. - * http://www.opengl.org/documentation/specs/version1.1/glspec1.1/node47.html - * If we have to, we can use vertical line and horizontal line textures - * for vertical and horizontal lines, and then create custom textures - * for diagonal lines and software render those. It's terrible, but at - * least it would be pixel perfect. - */ - data->glBegin(GL_POINTS); -#if defined(__MACOSX__) || defined(__WIN32__) - /* Mac OS X and Windows seem to always leave the last point open */ - data->glVertex2f(0.5f + points[count-1].x, 0.5f + points[count-1].y); -#else - /* Linux seems to leave the right-most or bottom-most point open */ - x1 = points[0].x; - y1 = points[0].y; - x2 = points[count-1].x; - y2 = points[count-1].y; - - if (x1 > x2) { - data->glVertex2f(0.5f + x1, 0.5f + y1); - } else if (x2 > x1) { - data->glVertex2f(0.5f + x2, 0.5f + y2); - } - if (y1 > y2) { - data->glVertex2f(0.5f + x1, 0.5f + y1); - } else if (y2 > y1) { - data->glVertex2f(0.5f + x2, 0.5f + y2); - } -#endif - data->glEnd(); - } - return GL_CheckError("", renderer); -} - -static int -GL_RenderFillRects(SDL_Renderer * renderer, const SDL_FRect * rects, int count) -{ - GL_RenderData *data = (GL_RenderData *) renderer->driverdata; - int i; - - GL_SetDrawingState(renderer); - - for (i = 0; i < count; ++i) { - const SDL_FRect *rect = &rects[i]; - - data->glRectf(rect->x, rect->y, rect->x + rect->w, rect->y + rect->h); - } - return GL_CheckError("", renderer); -} - -static int -GL_SetupCopy(SDL_Renderer * renderer, SDL_Texture * texture) -{ - GL_RenderData *data = (GL_RenderData *) renderer->driverdata; - GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata; - - data->glEnable(texturedata->type); - if (texturedata->yuv) { - data->glActiveTextureARB(GL_TEXTURE2_ARB); - data->glBindTexture(texturedata->type, texturedata->vtexture); - - data->glActiveTextureARB(GL_TEXTURE1_ARB); - data->glBindTexture(texturedata->type, texturedata->utexture); - - data->glActiveTextureARB(GL_TEXTURE0_ARB); - } - if (texturedata->nv12) { - data->glActiveTextureARB(GL_TEXTURE1_ARB); - data->glBindTexture(texturedata->type, texturedata->utexture); - - data->glActiveTextureARB(GL_TEXTURE0_ARB); - } - data->glBindTexture(texturedata->type, texturedata->texture); - - if (texture->modMode) { - GL_SetColor(data, texture->r, texture->g, texture->b, texture->a); - } else { - GL_SetColor(data, 255, 255, 255, 255); - } - - GL_SetBlendMode(data, texture->blendMode); - - if (texturedata->yuv) { - GL_SetShader(data, SHADER_YUV); - } else if (texturedata->nv12) { - if (texture->format == SDL_PIXELFORMAT_NV12) { - GL_SetShader(data, SHADER_NV12); - } else { - GL_SetShader(data, SHADER_NV21); - } - } else { - GL_SetShader(data, SHADER_RGB); - } - return 0; -} - -static int -GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, - const SDL_Rect * srcrect, const SDL_FRect * dstrect) -{ - GL_RenderData *data = (GL_RenderData *) renderer->driverdata; - GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata; - GLfloat minx, miny, maxx, maxy; - GLfloat minu, maxu, minv, maxv; - - GL_ActivateRenderer(renderer); - - if (GL_SetupCopy(renderer, texture) < 0) { - return -1; - } - - minx = dstrect->x; - miny = dstrect->y; - maxx = dstrect->x + dstrect->w; - maxy = dstrect->y + dstrect->h; - - minu = (GLfloat) srcrect->x / texture->w; - minu *= texturedata->texw; - maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w; - maxu *= texturedata->texw; - minv = (GLfloat) srcrect->y / texture->h; - minv *= texturedata->texh; - maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h; - maxv *= texturedata->texh; - - data->glBegin(GL_TRIANGLE_STRIP); - data->glTexCoord2f(minu, minv); - data->glVertex2f(minx, miny); - data->glTexCoord2f(maxu, minv); - data->glVertex2f(maxx, miny); - data->glTexCoord2f(minu, maxv); - data->glVertex2f(minx, maxy); - data->glTexCoord2f(maxu, maxv); - data->glVertex2f(maxx, maxy); - data->glEnd(); - - data->glDisable(texturedata->type); - - return GL_CheckError("", renderer); -} - -static int -GL_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture, - const SDL_Rect * srcrect, const SDL_FRect * dstrect, - const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip) -{ - GL_RenderData *data = (GL_RenderData *) renderer->driverdata; - GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata; - GLfloat minx, miny, maxx, maxy; - GLfloat centerx, centery; - GLfloat minu, maxu, minv, maxv; - - GL_ActivateRenderer(renderer); - - if (GL_SetupCopy(renderer, texture) < 0) { - return -1; - } - - centerx = center->x; - centery = center->y; - - if (flip & SDL_FLIP_HORIZONTAL) { - minx = dstrect->w - centerx; - maxx = -centerx; - } - else { - minx = -centerx; - maxx = dstrect->w - centerx; - } - - if (flip & SDL_FLIP_VERTICAL) { - miny = dstrect->h - centery; - maxy = -centery; - } - else { - miny = -centery; - maxy = dstrect->h - centery; - } - - minu = (GLfloat) srcrect->x / texture->w; - minu *= texturedata->texw; - maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w; - maxu *= texturedata->texw; - minv = (GLfloat) srcrect->y / texture->h; - minv *= texturedata->texh; - maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h; - maxv *= texturedata->texh; - - /* Translate to flip, rotate, translate to position */ - data->glPushMatrix(); - data->glTranslatef((GLfloat)dstrect->x + centerx, (GLfloat)dstrect->y + centery, (GLfloat)0.0); - data->glRotated(angle, (GLdouble)0.0, (GLdouble)0.0, (GLdouble)1.0); - - data->glBegin(GL_TRIANGLE_STRIP); - data->glTexCoord2f(minu, minv); - data->glVertex2f(minx, miny); - data->glTexCoord2f(maxu, minv); - data->glVertex2f(maxx, miny); - data->glTexCoord2f(minu, maxv); - data->glVertex2f(minx, maxy); - data->glTexCoord2f(maxu, maxv); - data->glVertex2f(maxx, maxy); - data->glEnd(); - data->glPopMatrix(); - - data->glDisable(texturedata->type); - - return GL_CheckError("", renderer); -} - -static int -GL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect, - Uint32 pixel_format, void * pixels, int pitch) -{ - GL_RenderData *data = (GL_RenderData *) renderer->driverdata; - Uint32 temp_format = renderer->target ? renderer->target->format : SDL_PIXELFORMAT_ARGB8888; - void *temp_pixels; - int temp_pitch; - GLint internalFormat; - GLenum format, type; - Uint8 *src, *dst, *tmp; - int w, h, length, rows; - int status; - - GL_ActivateRenderer(renderer); - - temp_pitch = rect->w * SDL_BYTESPERPIXEL(temp_format); - temp_pixels = SDL_malloc(rect->h * temp_pitch); - if (!temp_pixels) { - return SDL_OutOfMemory(); - } - - if (!convert_format(data, temp_format, &internalFormat, &format, &type)) { - SDL_free(temp_pixels); - return SDL_SetError("Texture format %s not supported by OpenGL", - SDL_GetPixelFormatName(temp_format)); - } - - SDL_GetRendererOutputSize(renderer, &w, &h); - - data->glPixelStorei(GL_PACK_ALIGNMENT, 1); - data->glPixelStorei(GL_PACK_ROW_LENGTH, - (temp_pitch / SDL_BYTESPERPIXEL(temp_format))); - - data->glReadPixels(rect->x, renderer->target ? rect->y : (h-rect->y)-rect->h, - rect->w, rect->h, format, type, temp_pixels); - - if (GL_CheckError("glReadPixels()", renderer) < 0) { - SDL_free(temp_pixels); - return -1; - } - - /* Flip the rows to be top-down if necessary */ - if (!renderer->target) { - length = rect->w * SDL_BYTESPERPIXEL(temp_format); - src = (Uint8*)temp_pixels + (rect->h-1)*temp_pitch; - dst = (Uint8*)temp_pixels; - tmp = SDL_stack_alloc(Uint8, length); - rows = rect->h / 2; - while (rows--) { - SDL_memcpy(tmp, dst, length); - SDL_memcpy(dst, src, length); - SDL_memcpy(src, tmp, length); - dst += temp_pitch; - src -= temp_pitch; - } - SDL_stack_free(tmp); - } - - status = SDL_ConvertPixels(rect->w, rect->h, - temp_format, temp_pixels, temp_pitch, - pixel_format, pixels, pitch); - SDL_free(temp_pixels); - - return status; -} - -static void -GL_RenderPresent(SDL_Renderer * renderer) -{ - GL_ActivateRenderer(renderer); - - SDL_GL_SwapWindow(renderer->window); -} - -static void -GL_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture) -{ - GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata; - GL_TextureData *data = (GL_TextureData *) texture->driverdata; - - GL_ActivateRenderer(renderer); - - if (!data) { - return; - } - if (data->texture) { - renderdata->glDeleteTextures(1, &data->texture); - } - if (data->yuv) { - renderdata->glDeleteTextures(1, &data->utexture); - renderdata->glDeleteTextures(1, &data->vtexture); - } - SDL_free(data->pixels); - SDL_free(data); - texture->driverdata = NULL; -} - -static void -GL_DestroyRenderer(SDL_Renderer * renderer) -{ - GL_RenderData *data = (GL_RenderData *) renderer->driverdata; - - if (data) { - GL_ClearErrors(renderer); - if (data->GL_ARB_debug_output_supported) { - PFNGLDEBUGMESSAGECALLBACKARBPROC glDebugMessageCallbackARBFunc = (PFNGLDEBUGMESSAGECALLBACKARBPROC) SDL_GL_GetProcAddress("glDebugMessageCallbackARB"); - - /* Uh oh, we don't have a safe way of removing ourselves from the callback chain, if it changed after we set our callback. */ - /* For now, just always replace the callback with the original one */ - glDebugMessageCallbackARBFunc(data->next_error_callback, data->next_error_userparam); - } - if (data->shaders) { - GL_DestroyShaderContext(data->shaders); - } - if (data->context) { - while (data->framebuffers) { - GL_FBOList *nextnode = data->framebuffers->next; - /* delete the framebuffer object */ - data->glDeleteFramebuffersEXT(1, &data->framebuffers->FBO); - GL_CheckError("", renderer); - SDL_free(data->framebuffers); - data->framebuffers = nextnode; - } - SDL_GL_DeleteContext(data->context); - } - SDL_free(data); - } - SDL_free(renderer); -} - -static int -GL_BindTexture (SDL_Renderer * renderer, SDL_Texture *texture, float *texw, float *texh) -{ - GL_RenderData *data = (GL_RenderData *) renderer->driverdata; - GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata; - GL_ActivateRenderer(renderer); - - data->glEnable(texturedata->type); - if (texturedata->yuv) { - data->glActiveTextureARB(GL_TEXTURE2_ARB); - data->glBindTexture(texturedata->type, texturedata->vtexture); - - data->glActiveTextureARB(GL_TEXTURE1_ARB); - data->glBindTexture(texturedata->type, texturedata->utexture); - - data->glActiveTextureARB(GL_TEXTURE0_ARB); - } - data->glBindTexture(texturedata->type, texturedata->texture); - - if(texw) *texw = (float)texturedata->texw; - if(texh) *texh = (float)texturedata->texh; - - return 0; -} - -static int -GL_UnbindTexture (SDL_Renderer * renderer, SDL_Texture *texture) -{ - GL_RenderData *data = (GL_RenderData *) renderer->driverdata; - GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata; - GL_ActivateRenderer(renderer); - - if (texturedata->yuv) { - data->glActiveTextureARB(GL_TEXTURE2_ARB); - data->glDisable(texturedata->type); - - data->glActiveTextureARB(GL_TEXTURE1_ARB); - data->glDisable(texturedata->type); - - data->glActiveTextureARB(GL_TEXTURE0_ARB); - } - - data->glDisable(texturedata->type); - - return 0; -} - -#endif /* SDL_VIDEO_RENDER_OGL && !SDL_RENDER_DISABLED */ - -/* vi: set ts=4 sw=4 expandtab: */ |