From 03f8528315fa46c95991a34f3325d7b33ae5538c Mon Sep 17 00:00:00 2001
From: Edward Rudd <urkle@outoforder.cc>
Date: Sat, 02 May 2020 21:48:36 +0000
Subject: [PATCH] Update source to SDL2 2.0.12
---
source/src/render/opengl/SDL_render_gl.c | 1527 +++++++++++++++++++++++++++++++--------------------------
1 files changed, 826 insertions(+), 701 deletions(-)
diff --git a/source/src/render/opengl/SDL_render_gl.c b/source/src/render/opengl/SDL_render_gl.c
index f3e8326..133a20b 100644
--- a/source/src/render/opengl/SDL_render_gl.c
+++ b/source/src/render/opengl/SDL_render_gl.c
@@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
- Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+ Copyright (C) 1997-2020 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
@@ -51,57 +51,6 @@
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 SDL_bool GL_SupportsBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode);
-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
@@ -110,6 +59,25 @@
GLuint FBO;
GL_FBOList *next;
};
+
+typedef struct
+{
+ SDL_bool viewport_dirty;
+ SDL_Rect viewport;
+ SDL_Texture *texture;
+ SDL_Texture *target;
+ int drawablew;
+ int drawableh;
+ SDL_BlendMode blend;
+ GL_Shader shader;
+ SDL_bool cliprect_enabled_dirty;
+ SDL_bool cliprect_enabled;
+ SDL_bool cliprect_dirty;
+ SDL_Rect cliprect;
+ SDL_bool texturing;
+ Uint32 color;
+ Uint32 clear_color;
+} GL_DrawStateCache;
typedef struct
{
@@ -122,14 +90,10 @@
GLDEBUGPROCARB next_error_callback;
GLvoid *next_error_userparam;
+ GLenum textype;
+
SDL_bool GL_ARB_texture_non_power_of_two_supported;
SDL_bool GL_ARB_texture_rectangle_supported;
- struct {
- GL_Shader shader;
- Uint32 color;
- SDL_BlendMode blendMode;
- } current;
-
SDL_bool GL_EXT_framebuffer_object_supported;
GL_FBOList *framebuffers;
@@ -152,12 +116,12 @@
/* Shader support */
GL_ShaderContext *shaders;
+ GL_DrawStateCache drawstate;
} GL_RenderData;
typedef struct
{
GLuint texture;
- GLenum type;
GLfloat texw;
GLfloat texh;
GLenum format;
@@ -214,9 +178,9 @@
data->errors = 0;
data->error_messages = NULL;
}
- } else {
+ } else if (data->glGetError != NULL) {
while (data->glGetError() != GL_NO_ERROR) {
- continue;
+ /* continue; */
}
}
}
@@ -270,67 +234,35 @@
#ifdef __SDL_NOGETPROCADDR__
#define SDL_PROC(ret,func,params) data->func=func;
#else
+ int retval = 0;
#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", #func, SDL_GetError()); \
+ retval = SDL_SetError("Couldn't load GL function %s: %s", #func, SDL_GetError()); \
} \
} while ( 0 );
#endif /* __SDL_NOGETPROCADDR__ */
#include "SDL_glfuncs.h"
#undef SDL_PROC
- return 0;
+ return retval;
}
-
-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_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 = 0xffffffff;
- data->current.blendMode = SDL_BLENDMODE_INVALID;
-
- 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
@@ -382,210 +314,6 @@
}
}
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->SupportsBlendMode = GL_SupportsBlendMode;
- 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 **)(char *)&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
@@ -678,8 +406,15 @@
{
switch (pixel_format) {
case SDL_PIXELFORMAT_ARGB8888:
+ case SDL_PIXELFORMAT_RGB888:
*internalFormat = GL_RGBA8;
*format = GL_BGRA;
+ *type = GL_UNSIGNED_INT_8_8_8_8_REV;
+ break;
+ case SDL_PIXELFORMAT_ABGR8888:
+ case SDL_PIXELFORMAT_BGR888:
+ *internalFormat = GL_RGBA8;
+ *format = GL_RGBA;
*type = GL_UNSIGNED_INT_8_8_8_8_REV;
break;
case SDL_PIXELFORMAT_YV12:
@@ -707,6 +442,7 @@
GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
{
GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
+ const GLenum textype = renderdata->textype;
GL_TextureData *data;
GLint internalFormat;
GLenum format, type;
@@ -714,6 +450,8 @@
GLenum scaleMode;
GL_ActivateRenderer(renderer);
+
+ renderdata->drawstate.texture = NULL; /* we trash this state. */
if (texture->access == SDL_TEXTUREACCESS_TARGET &&
!renderdata->GL_EXT_framebuffer_object_supported) {
@@ -770,19 +508,16 @@
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;
@@ -792,17 +527,17 @@
data->format = format;
data->formattype = type;
scaleMode = (texture->scaleMode == SDL_ScaleModeNearest) ? GL_NEAREST : GL_LINEAR;
- 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);
+ renderdata->glEnable(textype);
+ renderdata->glBindTexture(textype, data->texture);
+ renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, scaleMode);
+ renderdata->glTexParameteri(textype, 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,
+ if (textype != GL_TEXTURE_RECTANGLE_ARB) {
+ renderdata->glTexParameteri(textype, GL_TEXTURE_WRAP_S,
GL_CLAMP_TO_EDGE);
- renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T,
+ renderdata->glTexParameteri(textype, GL_TEXTURE_WRAP_T,
GL_CLAMP_TO_EDGE);
}
#ifdef __MACOSX__
@@ -816,10 +551,10 @@
#define STORAGE_SHARED_APPLE 0x85BF
#endif
if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
- renderdata->glTexParameteri(data->type, GL_TEXTURE_STORAGE_HINT_APPLE,
+ renderdata->glTexParameteri(textype, GL_TEXTURE_STORAGE_HINT_APPLE,
GL_STORAGE_SHARED_APPLE);
} else {
- renderdata->glTexParameteri(data->type, GL_TEXTURE_STORAGE_HINT_APPLE,
+ renderdata->glTexParameteri(textype, GL_TEXTURE_STORAGE_HINT_APPLE,
GL_STORAGE_CACHED_APPLE);
}
if (texture->access == SDL_TEXTUREACCESS_STREAMING
@@ -829,17 +564,17 @@
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,
+ renderdata->glTexImage2D(textype, 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,
+ renderdata->glTexImage2D(textype, 0, internalFormat, texture_w,
texture_h, 0, format, type, NULL);
}
- renderdata->glDisable(data->type);
+ renderdata->glDisable(textype);
if (GL_CheckError("glTexImage2D()", renderer) < 0) {
return -1;
}
@@ -850,33 +585,33 @@
renderdata->glGenTextures(1, &data->utexture);
renderdata->glGenTextures(1, &data->vtexture);
- renderdata->glEnable(data->type);
+ renderdata->glEnable(textype);
- renderdata->glBindTexture(data->type, data->utexture);
- renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER,
+ renderdata->glBindTexture(textype, data->utexture);
+ renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER,
scaleMode);
- renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER,
+ renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER,
scaleMode);
- renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S,
+ renderdata->glTexParameteri(textype, GL_TEXTURE_WRAP_S,
GL_CLAMP_TO_EDGE);
- renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T,
+ renderdata->glTexParameteri(textype, GL_TEXTURE_WRAP_T,
GL_CLAMP_TO_EDGE);
- renderdata->glTexImage2D(data->type, 0, internalFormat, (texture_w+1)/2,
+ renderdata->glTexImage2D(textype, 0, internalFormat, (texture_w+1)/2,
(texture_h+1)/2, 0, format, type, NULL);
- renderdata->glBindTexture(data->type, data->vtexture);
- renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER,
+ renderdata->glBindTexture(textype, data->vtexture);
+ renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER,
scaleMode);
- renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER,
+ renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER,
scaleMode);
- renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S,
+ renderdata->glTexParameteri(textype, GL_TEXTURE_WRAP_S,
GL_CLAMP_TO_EDGE);
- renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T,
+ renderdata->glTexParameteri(textype, GL_TEXTURE_WRAP_T,
GL_CLAMP_TO_EDGE);
- renderdata->glTexImage2D(data->type, 0, internalFormat, (texture_w+1)/2,
+ renderdata->glTexImage2D(textype, 0, internalFormat, (texture_w+1)/2,
(texture_h+1)/2, 0, format, type, NULL);
- renderdata->glDisable(data->type);
+ renderdata->glDisable(textype);
}
if (texture->format == SDL_PIXELFORMAT_NV12 ||
@@ -884,20 +619,20 @@
data->nv12 = SDL_TRUE;
renderdata->glGenTextures(1, &data->utexture);
- renderdata->glEnable(data->type);
+ renderdata->glEnable(textype);
- renderdata->glBindTexture(data->type, data->utexture);
- renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER,
+ renderdata->glBindTexture(textype, data->utexture);
+ renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER,
scaleMode);
- renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER,
+ renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER,
scaleMode);
- renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S,
+ renderdata->glTexParameteri(textype, GL_TEXTURE_WRAP_S,
GL_CLAMP_TO_EDGE);
- renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T,
+ renderdata->glTexParameteri(textype, GL_TEXTURE_WRAP_T,
GL_CLAMP_TO_EDGE);
- renderdata->glTexImage2D(data->type, 0, GL_LUMINANCE_ALPHA, (texture_w+1)/2,
+ renderdata->glTexImage2D(textype, 0, GL_LUMINANCE_ALPHA, (texture_w+1)/2,
(texture_h+1)/2, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL);
- renderdata->glDisable(data->type);
+ renderdata->glDisable(textype);
}
return GL_CheckError("", renderer);
@@ -908,6 +643,7 @@
const SDL_Rect * rect, const void *pixels, int pitch)
{
GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
+ const GLenum textype = renderdata->textype;
GL_TextureData *data = (GL_TextureData *) texture->driverdata;
const int texturebpp = SDL_BYTESPERPIXEL(texture->format);
@@ -915,11 +651,13 @@
GL_ActivateRenderer(renderer);
- renderdata->glEnable(data->type);
- renderdata->glBindTexture(data->type, data->texture);
+ renderdata->drawstate.texture = NULL; /* we trash this state. */
+
+ renderdata->glEnable(textype);
+ renderdata->glBindTexture(textype, 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,
+ renderdata->glTexSubImage2D(textype, 0, rect->x, rect->y, rect->w,
rect->h, data->format, data->formattype,
pixels);
if (data->yuv) {
@@ -928,22 +666,22 @@
/* 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);
+ renderdata->glBindTexture(textype, data->vtexture);
} else {
- renderdata->glBindTexture(data->type, data->utexture);
+ renderdata->glBindTexture(textype, data->utexture);
}
- renderdata->glTexSubImage2D(data->type, 0, rect->x/2, rect->y/2,
+ renderdata->glTexSubImage2D(textype, 0, rect->x/2, rect->y/2,
(rect->w+1)/2, (rect->h+1)/2,
data->format, data->formattype, pixels);
/* Skip to the correct offset into the next texture */
pixels = (const void*)((const Uint8*)pixels + ((rect->h + 1) / 2) * ((pitch + 1) / 2));
if (texture->format == SDL_PIXELFORMAT_YV12) {
- renderdata->glBindTexture(data->type, data->utexture);
+ renderdata->glBindTexture(textype, data->utexture);
} else {
- renderdata->glBindTexture(data->type, data->vtexture);
+ renderdata->glBindTexture(textype, data->vtexture);
}
- renderdata->glTexSubImage2D(data->type, 0, rect->x/2, rect->y/2,
+ renderdata->glTexSubImage2D(textype, 0, rect->x/2, rect->y/2,
(rect->w+1)/2, (rect->h+1)/2,
data->format, data->formattype, pixels);
}
@@ -953,12 +691,12 @@
/* 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,
+ renderdata->glBindTexture(textype, data->utexture);
+ renderdata->glTexSubImage2D(textype, 0, rect->x/2, rect->y/2,
(rect->w + 1)/2, (rect->h + 1)/2,
GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, pixels);
}
- renderdata->glDisable(data->type);
+ renderdata->glDisable(textype);
return GL_CheckError("glTexSubImage2D()", renderer);
}
@@ -971,30 +709,33 @@
const Uint8 *Vplane, int Vpitch)
{
GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
+ const GLenum textype = renderdata->textype;
GL_TextureData *data = (GL_TextureData *) texture->driverdata;
GL_ActivateRenderer(renderer);
- renderdata->glEnable(data->type);
- renderdata->glBindTexture(data->type, data->texture);
+ renderdata->drawstate.texture = NULL; /* we trash this state. */
+
+ renderdata->glEnable(textype);
+ renderdata->glBindTexture(textype, 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,
+ renderdata->glTexSubImage2D(textype, 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,
+ renderdata->glBindTexture(textype, data->utexture);
+ renderdata->glTexSubImage2D(textype, 0, rect->x/2, rect->y/2,
(rect->w + 1)/2, (rect->h + 1)/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,
+ renderdata->glBindTexture(textype, data->vtexture);
+ renderdata->glTexSubImage2D(textype, 0, rect->x/2, rect->y/2,
(rect->w + 1)/2, (rect->h + 1)/2,
data->format, data->formattype, Vplane);
- renderdata->glDisable(data->type);
+ renderdata->glDisable(textype);
return GL_CheckError("glTexSubImage2D()", renderer);
}
@@ -1027,6 +768,43 @@
GL_UpdateTexture(renderer, texture, rect, pixels, data->pitch);
}
+static void
+GL_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture, SDL_ScaleMode scaleMode)
+{
+ GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
+ const GLenum textype = renderdata->textype;
+ GL_TextureData *data = (GL_TextureData *) texture->driverdata;
+ GLenum glScaleMode = (scaleMode == SDL_ScaleModeNearest) ? GL_NEAREST : GL_LINEAR;
+
+ renderdata->glEnable(textype);
+ renderdata->glBindTexture(textype, data->texture);
+ renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, glScaleMode);
+ renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, glScaleMode);
+ renderdata->glDisable(textype);
+
+ if (texture->format == SDL_PIXELFORMAT_YV12 ||
+ texture->format == SDL_PIXELFORMAT_IYUV) {
+ renderdata->glEnable(textype);
+ renderdata->glBindTexture(textype, data->utexture);
+ renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, glScaleMode);
+ renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, glScaleMode);
+
+ renderdata->glBindTexture(textype, data->vtexture);
+ renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, glScaleMode);
+ renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, glScaleMode);
+ renderdata->glDisable(textype);
+ }
+
+ if (texture->format == SDL_PIXELFORMAT_NV12 ||
+ texture->format == SDL_PIXELFORMAT_NV21) {
+ renderdata->glEnable(textype);
+ renderdata->glBindTexture(textype, data->utexture);
+ renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, glScaleMode);
+ renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, glScaleMode);
+ renderdata->glDisable(textype);
+ }
+}
+
static int
GL_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture)
{
@@ -1040,6 +818,8 @@
return SDL_SetError("Render targets not supported by OpenGL");
}
+ data->drawstate.viewport_dirty = SDL_TRUE;
+
if (texture == NULL) {
data->glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
return 0;
@@ -1048,7 +828,7 @@
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);
+ data->glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, data->textype, texturedata->texture, 0);
/* Check FBO status */
status = data->glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
@@ -1057,336 +837,70 @@
return 0;
}
+/* !!! FIXME: all these Queue* calls set up the vertex buffer the way the immediate mode
+ !!! FIXME: renderer wants it, but this might want to operate differently if we move to
+ !!! FIXME: VBOs at some point. */
static int
-GL_UpdateViewport(SDL_Renderer * renderer)
+GL_QueueSetViewport(SDL_Renderer * renderer, SDL_RenderCommand *cmd)
{
- 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);
- }
- }
- data->glMatrixMode(GL_MODELVIEW);
-
- return GL_CheckError("", renderer);
+ return 0; /* nothing to do in this backend. */
}
static int
-GL_UpdateClipRect(SDL_Renderer * renderer)
+GL_QueueDrawPoints(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points, int count)
{
- GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
+ GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, count * 2 * sizeof (GLfloat), 0, &cmd->data.draw.first);
+ int i;
- 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, SDL_BlendMode blendMode)
-{
- if (blendMode != data->current.blendMode) {
- if (blendMode == SDL_BLENDMODE_NONE) {
- data->glDisable(GL_BLEND);
- } else {
- data->glEnable(GL_BLEND);
- data->glBlendFuncSeparate(GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blendMode)),
- GetBlendFunc(SDL_GetBlendModeDstColorFactor(blendMode)),
- GetBlendFunc(SDL_GetBlendModeSrcAlphaFactor(blendMode)),
- GetBlendFunc(SDL_GetBlendModeDstAlphaFactor(blendMode)));
- data->glBlendEquation(GetBlendEquation(SDL_GetBlendModeColorOperation(blendMode)));
- }
- 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);
+ if (!verts) {
+ return -1;
}
- data->glClear(GL_COLOR_BUFFER_BIT);
-
- if (renderer->clipping_enabled) {
- data->glEnable(GL_SCISSOR_TEST);
+ cmd->data.draw.count = count;
+ for (i = 0; i < count; i++) {
+ *(verts++) = 0.5f + points[i].x;
+ *(verts++) = 0.5f + points[i].y;
}
return 0;
}
static int
-GL_RenderDrawPoints(SDL_Renderer * renderer, const SDL_FPoint * points,
- int count)
+GL_QueueFillRects(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FRect * rects, int count)
{
- GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
+ GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, count * 4 * sizeof (GLfloat), 0, &cmd->data.draw.first);
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);
+ if (!verts) {
+ return -1;
}
- 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) {
+ cmd->data.draw.count = count;
+ 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);
+ *(verts++) = rect->x;
+ *(verts++) = rect->y;
+ *(verts++) = rect->x + rect->w;
+ *(verts++) = rect->y + rect->h;
}
- GL_SetBlendMode(data, texture->blendMode);
-
- if (texturedata->yuv || texturedata->nv12) {
- switch (SDL_GetYUVConversionModeForResolution(texture->w, texture->h)) {
- case SDL_YUV_CONVERSION_JPEG:
- if (texturedata->yuv) {
- GL_SetShader(data, SHADER_YUV_JPEG);
- } else if (texture->format == SDL_PIXELFORMAT_NV12) {
- GL_SetShader(data, SHADER_NV12_JPEG);
- } else {
- GL_SetShader(data, SHADER_NV21_JPEG);
- }
- break;
- case SDL_YUV_CONVERSION_BT601:
- if (texturedata->yuv) {
- GL_SetShader(data, SHADER_YUV_BT601);
- } else if (texture->format == SDL_PIXELFORMAT_NV12) {
- GL_SetShader(data, SHADER_NV12_BT601);
- } else {
- GL_SetShader(data, SHADER_NV21_BT601);
- }
- break;
- case SDL_YUV_CONVERSION_BT709:
- if (texturedata->yuv) {
- GL_SetShader(data, SHADER_YUV_BT709);
- } else if (texture->format == SDL_PIXELFORMAT_NV12) {
- GL_SetShader(data, SHADER_NV12_BT709);
- } else {
- GL_SetShader(data, SHADER_NV21_BT709);
- }
- break;
- default:
- return SDL_SetError("Unsupported YUV conversion mode");
- }
- } 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_QueueCopy(SDL_Renderer * renderer, SDL_RenderCommand *cmd, 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;
+ GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, 8 * sizeof (GLfloat), 0, &cmd->data.draw.first);
- GL_ActivateRenderer(renderer);
-
- if (GL_SetupCopy(renderer, texture) < 0) {
+ if (!verts) {
return -1;
}
+
+ cmd->data.draw.count = 1;
minx = dstrect->x;
miny = dstrect->y;
@@ -1402,36 +916,30 @@
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);
+ cmd->data.draw.count = 1;
+ *(verts++) = minx;
+ *(verts++) = miny;
+ *(verts++) = maxx;
+ *(verts++) = maxy;
+ *(verts++) = minu;
+ *(verts++) = maxu;
+ *(verts++) = minv;
+ *(verts++) = maxv;
+ return 0;
}
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_QueueCopyEx(SDL_Renderer * renderer, SDL_RenderCommand *cmd, 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;
+ GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, 11 * sizeof (GLfloat), 0, &cmd->data.draw.first);
- GL_ActivateRenderer(renderer);
-
- if (GL_SetupCopy(renderer, texture) < 0) {
+ if (!verts) {
return -1;
}
@@ -1465,24 +973,390 @@
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);
+ cmd->data.draw.count = 1;
+ *(verts++) = minx;
+ *(verts++) = miny;
+ *(verts++) = maxx;
+ *(verts++) = maxy;
+ *(verts++) = minu;
+ *(verts++) = maxu;
+ *(verts++) = minv;
+ *(verts++) = maxv;
+ *(verts++) = (GLfloat) dstrect->x + centerx;
+ *(verts++) = (GLfloat) dstrect->y + centery;
+ *(verts++) = (GLfloat) angle;
+ return 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();
+static void
+SetDrawState(GL_RenderData *data, const SDL_RenderCommand *cmd, const GL_Shader shader)
+{
+ const SDL_BlendMode blend = cmd->data.draw.blend;
- data->glDisable(texturedata->type);
+ if (data->drawstate.viewport_dirty) {
+ const SDL_bool istarget = data->drawstate.target != NULL;
+ const SDL_Rect *viewport = &data->drawstate.viewport;
+ data->glMatrixMode(GL_PROJECTION);
+ data->glLoadIdentity();
+ data->glViewport(viewport->x,
+ istarget ? viewport->y : (data->drawstate.drawableh - viewport->y - viewport->h),
+ viewport->w, viewport->h);
+ if (viewport->w && viewport->h) {
+ data->glOrtho((GLdouble) 0, (GLdouble) viewport->w,
+ (GLdouble) istarget ? 0 : viewport->h,
+ (GLdouble) istarget ? viewport->h : 0,
+ 0.0, 1.0);
+ }
+ data->glMatrixMode(GL_MODELVIEW);
+ data->drawstate.viewport_dirty = SDL_FALSE;
+ }
+
+ if (data->drawstate.cliprect_enabled_dirty) {
+ if (!data->drawstate.cliprect_enabled) {
+ data->glDisable(GL_SCISSOR_TEST);
+ } else {
+ data->glEnable(GL_SCISSOR_TEST);
+ }
+ data->drawstate.cliprect_enabled_dirty = SDL_FALSE;
+ }
+
+ if (data->drawstate.cliprect_enabled && data->drawstate.cliprect_dirty) {
+ const SDL_Rect *viewport = &data->drawstate.viewport;
+ const SDL_Rect *rect = &data->drawstate.cliprect;
+ data->glScissor(viewport->x + rect->x,
+ data->drawstate.target ? viewport->y + rect->y : data->drawstate.drawableh - viewport->y - rect->y - rect->h,
+ rect->w, rect->h);
+ data->drawstate.cliprect_dirty = SDL_FALSE;
+ }
+
+ if (blend != data->drawstate.blend) {
+ if (blend == SDL_BLENDMODE_NONE) {
+ data->glDisable(GL_BLEND);
+ } else {
+ data->glEnable(GL_BLEND);
+ data->glBlendFuncSeparate(GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blend)),
+ GetBlendFunc(SDL_GetBlendModeDstColorFactor(blend)),
+ GetBlendFunc(SDL_GetBlendModeSrcAlphaFactor(blend)),
+ GetBlendFunc(SDL_GetBlendModeDstAlphaFactor(blend)));
+ data->glBlendEquation(GetBlendEquation(SDL_GetBlendModeColorOperation(blend)));
+ }
+ data->drawstate.blend = blend;
+ }
+
+ if (data->shaders && (shader != data->drawstate.shader)) {
+ GL_SelectShader(data->shaders, shader);
+ data->drawstate.shader = shader;
+ }
+
+ if ((cmd->data.draw.texture != NULL) != data->drawstate.texturing) {
+ if (cmd->data.draw.texture == NULL) {
+ data->glDisable(data->textype);
+ data->drawstate.texturing = SDL_FALSE;
+ } else {
+ data->glEnable(data->textype);
+ data->drawstate.texturing = SDL_TRUE;
+ }
+ }
+}
+
+static void
+SetCopyState(GL_RenderData *data, const SDL_RenderCommand *cmd)
+{
+ SDL_Texture *texture = cmd->data.draw.texture;
+ const GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata;
+ GL_Shader shader;
+
+ if (texture->format == SDL_PIXELFORMAT_ABGR8888 || texture->format == SDL_PIXELFORMAT_ARGB8888) {
+ shader = SHADER_RGBA;
+ } else {
+ shader = SHADER_RGB;
+ }
+
+ if (data->shaders) {
+ if (texturedata->yuv || texturedata->nv12) {
+ switch (SDL_GetYUVConversionModeForResolution(texture->w, texture->h)) {
+ case SDL_YUV_CONVERSION_JPEG:
+ if (texturedata->yuv) {
+ shader = SHADER_YUV_JPEG;
+ } else if (texture->format == SDL_PIXELFORMAT_NV12) {
+ shader = SHADER_NV12_JPEG;
+ } else {
+ shader = SHADER_NV21_JPEG;
+ }
+ break;
+ case SDL_YUV_CONVERSION_BT601:
+ if (texturedata->yuv) {
+ shader = SHADER_YUV_BT601;
+ } else if (texture->format == SDL_PIXELFORMAT_NV12) {
+ shader = SHADER_NV12_BT601;
+ } else {
+ shader = SHADER_NV21_BT601;
+ }
+ break;
+ case SDL_YUV_CONVERSION_BT709:
+ if (texturedata->yuv) {
+ shader = SHADER_YUV_BT709;
+ } else if (texture->format == SDL_PIXELFORMAT_NV12) {
+ shader = SHADER_NV12_BT709;
+ } else {
+ shader = SHADER_NV21_BT709;
+ }
+ break;
+ default:
+ SDL_assert(!"unsupported YUV conversion mode");
+ break;
+ }
+ }
+ }
+
+ SetDrawState(data, cmd, shader);
+
+ if (texture != data->drawstate.texture) {
+ const GLenum textype = data->textype;
+ if (texturedata->yuv) {
+ data->glActiveTextureARB(GL_TEXTURE2_ARB);
+ data->glBindTexture(textype, texturedata->vtexture);
+
+ data->glActiveTextureARB(GL_TEXTURE1_ARB);
+ data->glBindTexture(textype, texturedata->utexture);
+ }
+ if (texturedata->nv12) {
+ data->glActiveTextureARB(GL_TEXTURE1_ARB);
+ data->glBindTexture(textype, texturedata->utexture);
+ }
+ data->glActiveTextureARB(GL_TEXTURE0_ARB);
+ data->glBindTexture(textype, texturedata->texture);
+
+ data->drawstate.texture = texture;
+ }
+}
+
+static int
+GL_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
+{
+ /* !!! FIXME: it'd be nice to use a vertex buffer instead of immediate mode... */
+ GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
+ size_t i;
+
+ if (GL_ActivateRenderer(renderer) < 0) {
+ return -1;
+ }
+
+ data->drawstate.target = renderer->target;
+ if (!data->drawstate.target) {
+ SDL_GL_GetDrawableSize(renderer->window, &data->drawstate.drawablew, &data->drawstate.drawableh);
+ }
+
+
+ while (cmd) {
+ switch (cmd->command) {
+ case SDL_RENDERCMD_SETDRAWCOLOR: {
+ const Uint8 r = cmd->data.color.r;
+ const Uint8 g = cmd->data.color.g;
+ const Uint8 b = cmd->data.color.b;
+ const Uint8 a = cmd->data.color.a;
+ const Uint32 color = ((a << 24) | (r << 16) | (g << 8) | b);
+ if (color != data->drawstate.color) {
+ data->glColor4f((GLfloat) r * inv255f,
+ (GLfloat) g * inv255f,
+ (GLfloat) b * inv255f,
+ (GLfloat) a * inv255f);
+ data->drawstate.color = color;
+ }
+ break;
+ }
+
+ case SDL_RENDERCMD_SETVIEWPORT: {
+ SDL_Rect *viewport = &data->drawstate.viewport;
+ if (SDL_memcmp(viewport, &cmd->data.viewport.rect, sizeof (SDL_Rect)) != 0) {
+ SDL_memcpy(viewport, &cmd->data.viewport.rect, sizeof (SDL_Rect));
+ data->drawstate.viewport_dirty = SDL_TRUE;
+ }
+ break;
+ }
+
+ case SDL_RENDERCMD_SETCLIPRECT: {
+ const SDL_Rect *rect = &cmd->data.cliprect.rect;
+ if (data->drawstate.cliprect_enabled != cmd->data.cliprect.enabled) {
+ data->drawstate.cliprect_enabled = cmd->data.cliprect.enabled;
+ data->drawstate.cliprect_enabled_dirty = SDL_TRUE;
+ }
+ if (SDL_memcmp(&data->drawstate.cliprect, rect, sizeof (SDL_Rect)) != 0) {
+ SDL_memcpy(&data->drawstate.cliprect, rect, sizeof (SDL_Rect));
+ data->drawstate.cliprect_dirty = SDL_TRUE;
+ }
+ break;
+ }
+
+ case SDL_RENDERCMD_CLEAR: {
+ const Uint8 r = cmd->data.color.r;
+ const Uint8 g = cmd->data.color.g;
+ const Uint8 b = cmd->data.color.b;
+ const Uint8 a = cmd->data.color.a;
+ const Uint32 color = ((a << 24) | (r << 16) | (g << 8) | b);
+ if (color != data->drawstate.clear_color) {
+ const GLfloat fr = ((GLfloat) r) * inv255f;
+ const GLfloat fg = ((GLfloat) g) * inv255f;
+ const GLfloat fb = ((GLfloat) b) * inv255f;
+ const GLfloat fa = ((GLfloat) a) * inv255f;
+ data->glClearColor(fr, fg, fb, fa);
+ data->drawstate.clear_color = color;
+ }
+
+ if (data->drawstate.cliprect_enabled || data->drawstate.cliprect_enabled_dirty) {
+ data->glDisable(GL_SCISSOR_TEST);
+ data->drawstate.cliprect_enabled_dirty = data->drawstate.cliprect_enabled;
+ }
+
+ data->glClear(GL_COLOR_BUFFER_BIT);
+
+ break;
+ }
+
+ case SDL_RENDERCMD_DRAW_POINTS: {
+ const size_t count = cmd->data.draw.count;
+ const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
+ SetDrawState(data, cmd, SHADER_SOLID);
+ data->glBegin(GL_POINTS);
+ for (i = 0; i < count; i++, verts += 2) {
+ data->glVertex2f(verts[0], verts[1]);
+ }
+ data->glEnd();
+ break;
+ }
+
+ case SDL_RENDERCMD_DRAW_LINES: {
+ const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
+ const size_t count = cmd->data.draw.count;
+ SetDrawState(data, cmd, SHADER_SOLID);
+ if (count > 2 && (verts[0] == verts[(count-1)*2]) && (verts[1] == verts[(count*2)-1])) {
+ data->glBegin(GL_LINE_LOOP);
+ /* GL_LINE_LOOP takes care of the final segment */
+ for (i = 1; i < count; ++i, verts += 2) {
+ data->glVertex2f(verts[0], verts[1]);
+ }
+ 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, verts += 2) {
+ data->glVertex2f(verts[0], verts[1]);
+ }
+ data->glEnd();
+ verts -= 2 * count;
+
+ /* 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(verts[(count-1)*2], verts[(count*2)-1]);
+ #else
+ /* Linux seems to leave the right-most or bottom-most point open */
+ x1 = verts[0];
+ y1 = verts[1];
+ x2 = verts[(count-1)*2];
+ y2 = verts[(count*2)-1];
+
+ if (x1 > x2) {
+ data->glVertex2f(x1, y1);
+ } else if (x2 > x1) {
+ data->glVertex2f(x2, y2);
+ }
+ if (y1 > y2) {
+ data->glVertex2f(x1, y1);
+ } else if (y2 > y1) {
+ data->glVertex2f(x2, y2);
+ }
+ #endif
+ data->glEnd();
+ }
+ break;
+ }
+
+ case SDL_RENDERCMD_FILL_RECTS: {
+ const size_t count = cmd->data.draw.count;
+ const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
+ SetDrawState(data, cmd, SHADER_SOLID);
+ for (i = 0; i < count; ++i, verts += 4) {
+ data->glRectf(verts[0], verts[1], verts[2], verts[3]);
+ }
+ break;
+ }
+
+ case SDL_RENDERCMD_COPY: {
+ const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
+ const GLfloat minx = verts[0];
+ const GLfloat miny = verts[1];
+ const GLfloat maxx = verts[2];
+ const GLfloat maxy = verts[3];
+ const GLfloat minu = verts[4];
+ const GLfloat maxu = verts[5];
+ const GLfloat minv = verts[6];
+ const GLfloat maxv = verts[7];
+ SetCopyState(data, cmd);
+ 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();
+ break;
+ }
+
+ case SDL_RENDERCMD_COPY_EX: {
+ const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
+ const GLfloat minx = verts[0];
+ const GLfloat miny = verts[1];
+ const GLfloat maxx = verts[2];
+ const GLfloat maxy = verts[3];
+ const GLfloat minu = verts[4];
+ const GLfloat maxu = verts[5];
+ const GLfloat minv = verts[6];
+ const GLfloat maxv = verts[7];
+ const GLfloat translatex = verts[8];
+ const GLfloat translatey = verts[9];
+ const GLdouble angle = verts[10];
+ SetCopyState(data, cmd);
+
+ /* Translate to flip, rotate, translate to position */
+ data->glPushMatrix();
+ data->glTranslatef(translatex, translatey, 0.0f);
+ data->glRotated(angle, 0.0, 0.0, 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();
+ break;
+ }
+
+ case SDL_RENDERCMD_NO_OP:
+ break;
+ }
+
+ cmd = cmd->next;
+ }
return GL_CheckError("", renderer);
}
@@ -1534,10 +1408,11 @@
/* Flip the rows to be top-down if necessary */
if (!renderer->target) {
+ SDL_bool isstack;
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);
+ tmp = SDL_small_alloc(Uint8, length, &isstack);
rows = rect->h / 2;
while (rows--) {
SDL_memcpy(tmp, dst, length);
@@ -1546,7 +1421,7 @@
dst += temp_pitch;
src -= temp_pitch;
}
- SDL_stack_free(tmp);
+ SDL_small_free(tmp, isstack);
}
status = SDL_ConvertPixels(rect->w, rect->h,
@@ -1572,6 +1447,13 @@
GL_TextureData *data = (GL_TextureData *) texture->driverdata;
GL_ActivateRenderer(renderer);
+
+ if (renderdata->drawstate.texture == texture) {
+ renderdata->drawstate.texture = NULL;
+ }
+ if (renderdata->drawstate.target == texture) {
+ renderdata->drawstate.target = NULL;
+ }
if (!data) {
return;
@@ -1631,19 +1513,24 @@
{
GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata;
+ const GLenum textype = data->textype;
+
GL_ActivateRenderer(renderer);
- data->glEnable(texturedata->type);
+ data->glEnable(textype);
if (texturedata->yuv) {
data->glActiveTextureARB(GL_TEXTURE2_ARB);
- data->glBindTexture(texturedata->type, texturedata->vtexture);
+ data->glBindTexture(textype, texturedata->vtexture);
data->glActiveTextureARB(GL_TEXTURE1_ARB);
- data->glBindTexture(texturedata->type, texturedata->utexture);
+ data->glBindTexture(textype, texturedata->utexture);
data->glActiveTextureARB(GL_TEXTURE0_ARB);
}
- data->glBindTexture(texturedata->type, texturedata->texture);
+ data->glBindTexture(textype, texturedata->texture);
+
+ data->drawstate.texturing = SDL_TRUE;
+ data->drawstate.texture = texture;
if(texw) *texw = (float)texturedata->texw;
if(texh) *texh = (float)texturedata->texh;
@@ -1656,23 +1543,261 @@
{
GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata;
+ const GLenum textype = data->textype;
+
GL_ActivateRenderer(renderer);
if (texturedata->yuv) {
data->glActiveTextureARB(GL_TEXTURE2_ARB);
- data->glDisable(texturedata->type);
+ data->glDisable(textype);
data->glActiveTextureARB(GL_TEXTURE1_ARB);
- data->glDisable(texturedata->type);
+ data->glDisable(textype);
data->glActiveTextureARB(GL_TEXTURE0_ARB);
}
- data->glDisable(texturedata->type);
+ data->glDisable(textype);
+
+ data->drawstate.texturing = SDL_FALSE;
+ data->drawstate.texture = NULL;
return 0;
}
+
+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) {
+ SDL_free(renderer);
+ SDL_OutOfMemory();
+ goto error;
+ }
+
+ renderer->GetOutputSize = GL_GetOutputSize;
+ renderer->SupportsBlendMode = GL_SupportsBlendMode;
+ renderer->CreateTexture = GL_CreateTexture;
+ renderer->UpdateTexture = GL_UpdateTexture;
+ renderer->UpdateTextureYUV = GL_UpdateTextureYUV;
+ renderer->LockTexture = GL_LockTexture;
+ renderer->UnlockTexture = GL_UnlockTexture;
+ renderer->SetTextureScaleMode = GL_SetTextureScaleMode;
+ renderer->SetRenderTarget = GL_SetRenderTarget;
+ renderer->QueueSetViewport = GL_QueueSetViewport;
+ renderer->QueueSetDrawColor = GL_QueueSetViewport; /* SetViewport and SetDrawColor are (currently) no-ops. */
+ renderer->QueueDrawPoints = GL_QueueDrawPoints;
+ renderer->QueueDrawLines = GL_QueueDrawPoints; /* lines and points queue vertices the same way. */
+ renderer->QueueFillRects = GL_QueueFillRects;
+ renderer->QueueCopy = GL_QueueCopy;
+ renderer->QueueCopyEx = GL_QueueCopyEx;
+ renderer->RunCommandQueue = GL_RunCommandQueue;
+ 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) {
+ SDL_free(renderer);
+ SDL_free(data);
+ goto error;
+ }
+ if (SDL_GL_MakeCurrent(window, data->context) < 0) {
+ SDL_GL_DeleteContext(data->context);
+ SDL_free(renderer);
+ SDL_free(data);
+ goto error;
+ }
+
+ if (GL_LoadFunctions(data) < 0) {
+ SDL_GL_DeleteContext(data->context);
+ SDL_free(renderer);
+ SDL_free(data);
+ 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 **)(char *)&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);
+ }
+
+ data->textype = GL_TEXTURE_2D;
+ 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;
+ data->textype = GL_TEXTURE_RECTANGLE_ARB;
+ }
+ 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 */
+ data->glMatrixMode(GL_MODELVIEW);
+ data->glLoadIdentity();
+ data->glDisable(GL_DEPTH_TEST);
+ data->glDisable(GL_CULL_FACE);
+ data->glDisable(GL_SCISSOR_TEST);
+ data->glDisable(data->textype);
+ data->glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
+ data->glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+ /* This ended up causing video discrepancies between OpenGL and Direct3D */
+ /* data->glEnable(GL_LINE_SMOOTH); */
+
+ data->drawstate.blend = SDL_BLENDMODE_INVALID;
+ data->drawstate.shader = SHADER_INVALID;
+ data->drawstate.color = 0xFFFFFFFF;
+ data->drawstate.clear_color = 0xFFFFFFFF;
+
+ 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;
+}
+
+
+SDL_RenderDriver GL_RenderDriver = {
+ GL_CreateRenderer,
+ {
+ "opengl",
+ (SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE),
+ 4,
+ {
+ SDL_PIXELFORMAT_ARGB8888,
+ SDL_PIXELFORMAT_ABGR8888,
+ SDL_PIXELFORMAT_RGB888,
+ SDL_PIXELFORMAT_BGR888
+ },
+ 0,
+ 0}
+};
+
+
#endif /* SDL_VIDEO_RENDER_OGL && !SDL_RENDER_DISABLED */
/* vi: set ts=4 sw=4 expandtab: */
--
Gitblit v1.9.3