slouken@1918
|
1 |
/*
|
slouken@1918
|
2 |
SDL - Simple DirectMedia Layer
|
slouken@3697
|
3 |
Copyright (C) 1997-2010 Sam Lantinga
|
slouken@1918
|
4 |
|
slouken@1918
|
5 |
This library is free software; you can redistribute it and/or
|
slouken@1918
|
6 |
modify it under the terms of the GNU Lesser General Public
|
slouken@1918
|
7 |
License as published by the Free Software Foundation; either
|
slouken@1918
|
8 |
version 2.1 of the License, or (at your option) any later version.
|
slouken@1918
|
9 |
|
slouken@1918
|
10 |
This library is distributed in the hope that it will be useful,
|
slouken@1918
|
11 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
slouken@1918
|
12 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
slouken@1918
|
13 |
Lesser General Public License for more details.
|
slouken@1918
|
14 |
|
slouken@1918
|
15 |
You should have received a copy of the GNU Lesser General Public
|
slouken@1918
|
16 |
License along with this library; if not, write to the Free Software
|
slouken@1918
|
17 |
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
slouken@1918
|
18 |
|
slouken@1918
|
19 |
Sam Lantinga
|
slouken@1918
|
20 |
slouken@libsdl.org
|
slouken@1918
|
21 |
*/
|
slouken@1918
|
22 |
#include "SDL_config.h"
|
slouken@1918
|
23 |
|
slouken@1952
|
24 |
#if SDL_VIDEO_RENDER_OGL
|
slouken@1920
|
25 |
|
slouken@1920
|
26 |
#include "SDL_opengl.h"
|
slouken@5154
|
27 |
#include "../SDL_sysrender.h"
|
slouken@1918
|
28 |
|
slouken@2246
|
29 |
#ifdef __MACOSX__
|
slouken@2246
|
30 |
#include <OpenGL/OpenGL.h>
|
slouken@2246
|
31 |
#endif
|
slouken@2246
|
32 |
|
slouken@2778
|
33 |
|
slouken@1918
|
34 |
/* OpenGL renderer implementation */
|
slouken@1918
|
35 |
|
slouken@2230
|
36 |
/* Details on optimizing the texture path on Mac OS X:
|
slouken@5203
|
37 |
http://developer.apple.com/library/mac/#documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/opengl_texturedata/opengl_texturedata.html
|
slouken@2230
|
38 |
*/
|
slouken@2230
|
39 |
|
slouken@5154
|
40 |
/* Used to re-create the window with OpenGL capability */
|
slouken@5154
|
41 |
extern int SDL_RecreateWindow(SDL_Window * window, Uint32 flags);
|
icculus@2835
|
42 |
|
slouken@1985
|
43 |
static const float inv255f = 1.0f / 255.0f;
|
slouken@1985
|
44 |
|
slouken@1918
|
45 |
static SDL_Renderer *GL_CreateRenderer(SDL_Window * window, Uint32 flags);
|
slouken@5147
|
46 |
static void GL_WindowEvent(SDL_Renderer * renderer,
|
slouken@5147
|
47 |
const SDL_WindowEvent *event);
|
slouken@1918
|
48 |
static int GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
|
slouken@1918
|
49 |
static int GL_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
|
slouken@1918
|
50 |
const SDL_Rect * rect, const void *pixels,
|
slouken@1918
|
51 |
int pitch);
|
slouken@1918
|
52 |
static int GL_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
|
slouken@5156
|
53 |
const SDL_Rect * rect, void **pixels, int *pitch);
|
slouken@1918
|
54 |
static void GL_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
|
slouken@3596
|
55 |
static int GL_RenderClear(SDL_Renderer * renderer);
|
slouken@3596
|
56 |
static int GL_RenderDrawPoints(SDL_Renderer * renderer,
|
slouken@3596
|
57 |
const SDL_Point * points, int count);
|
slouken@3596
|
58 |
static int GL_RenderDrawLines(SDL_Renderer * renderer,
|
slouken@3596
|
59 |
const SDL_Point * points, int count);
|
slouken@3596
|
60 |
static int GL_RenderFillRects(SDL_Renderer * renderer,
|
slouken@3596
|
61 |
const SDL_Rect ** rects, int count);
|
slouken@1918
|
62 |
static int GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
|
slouken@1985
|
63 |
const SDL_Rect * srcrect, const SDL_Rect * dstrect);
|
slouken@3431
|
64 |
static int GL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
|
slouken@3435
|
65 |
Uint32 pixel_format, void * pixels, int pitch);
|
slouken@1918
|
66 |
static void GL_RenderPresent(SDL_Renderer * renderer);
|
slouken@1918
|
67 |
static void GL_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture);
|
slouken@1918
|
68 |
static void GL_DestroyRenderer(SDL_Renderer * renderer);
|
slouken@1918
|
69 |
|
slouken@1918
|
70 |
|
slouken@1918
|
71 |
SDL_RenderDriver GL_RenderDriver = {
|
slouken@1918
|
72 |
GL_CreateRenderer,
|
slouken@1918
|
73 |
{
|
slouken@1918
|
74 |
"opengl",
|
slouken@5203
|
75 |
(SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC),
|
slouken@5156
|
76 |
1,
|
slouken@5156
|
77 |
{SDL_PIXELFORMAT_ARGB8888},
|
slouken@1918
|
78 |
0,
|
slouken@1918
|
79 |
0}
|
slouken@1918
|
80 |
};
|
slouken@1918
|
81 |
|
slouken@1918
|
82 |
typedef struct
|
slouken@1918
|
83 |
{
|
slouken@1918
|
84 |
SDL_GLContext context;
|
slouken@2833
|
85 |
SDL_bool updateSize;
|
slouken@2233
|
86 |
SDL_bool GL_ARB_texture_rectangle_supported;
|
slouken@1927
|
87 |
int blendMode;
|
slouken@1927
|
88 |
|
slouken@1927
|
89 |
/* OpenGL functions */
|
slouken@1927
|
90 |
#define SDL_PROC(ret,func,params) ret (APIENTRY *func) params;
|
slouken@5204
|
91 |
#include "SDL_glfuncs.h"
|
slouken@1927
|
92 |
#undef SDL_PROC
|
slouken@1974
|
93 |
|
slouken@2233
|
94 |
void (*glTextureRangeAPPLE) (GLenum target, GLsizei length,
|
slouken@2233
|
95 |
const GLvoid * pointer);
|
slouken@1918
|
96 |
} GL_RenderData;
|
slouken@1918
|
97 |
|
slouken@1918
|
98 |
typedef struct
|
slouken@1918
|
99 |
{
|
slouken@1918
|
100 |
GLuint texture;
|
slouken@1920
|
101 |
GLenum type;
|
slouken@1918
|
102 |
GLfloat texw;
|
slouken@1918
|
103 |
GLfloat texh;
|
slouken@1920
|
104 |
GLenum format;
|
slouken@1920
|
105 |
GLenum formattype;
|
slouken@1918
|
106 |
void *pixels;
|
slouken@1918
|
107 |
int pitch;
|
slouken@1918
|
108 |
} GL_TextureData;
|
slouken@1918
|
109 |
|
slouken@1918
|
110 |
|
slouken@1924
|
111 |
static void
|
slouken@1924
|
112 |
GL_SetError(const char *prefix, GLenum result)
|
slouken@1924
|
113 |
{
|
slouken@1924
|
114 |
const char *error;
|
slouken@1924
|
115 |
|
slouken@1924
|
116 |
switch (result) {
|
slouken@1924
|
117 |
case GL_NO_ERROR:
|
slouken@1924
|
118 |
error = "GL_NO_ERROR";
|
slouken@1924
|
119 |
break;
|
slouken@1924
|
120 |
case GL_INVALID_ENUM:
|
slouken@1924
|
121 |
error = "GL_INVALID_ENUM";
|
slouken@1924
|
122 |
break;
|
slouken@1924
|
123 |
case GL_INVALID_VALUE:
|
slouken@1924
|
124 |
error = "GL_INVALID_VALUE";
|
slouken@1924
|
125 |
break;
|
slouken@1924
|
126 |
case GL_INVALID_OPERATION:
|
slouken@1924
|
127 |
error = "GL_INVALID_OPERATION";
|
slouken@1924
|
128 |
break;
|
slouken@1924
|
129 |
case GL_STACK_OVERFLOW:
|
slouken@1924
|
130 |
error = "GL_STACK_OVERFLOW";
|
slouken@1924
|
131 |
break;
|
slouken@1924
|
132 |
case GL_STACK_UNDERFLOW:
|
slouken@1924
|
133 |
error = "GL_STACK_UNDERFLOW";
|
slouken@1924
|
134 |
break;
|
slouken@1924
|
135 |
case GL_OUT_OF_MEMORY:
|
slouken@1924
|
136 |
error = "GL_OUT_OF_MEMORY";
|
slouken@1924
|
137 |
break;
|
slouken@1924
|
138 |
case GL_TABLE_TOO_LARGE:
|
slouken@1924
|
139 |
error = "GL_TABLE_TOO_LARGE";
|
slouken@1924
|
140 |
break;
|
slouken@1924
|
141 |
default:
|
slouken@1924
|
142 |
error = "UNKNOWN";
|
slouken@1924
|
143 |
break;
|
slouken@1924
|
144 |
}
|
slouken@1924
|
145 |
SDL_SetError("%s: %s", prefix, error);
|
slouken@1924
|
146 |
}
|
slouken@1924
|
147 |
|
slouken@1927
|
148 |
static int
|
slouken@1927
|
149 |
GL_LoadFunctions(GL_RenderData * data)
|
slouken@1927
|
150 |
{
|
slouken@1927
|
151 |
#ifdef __SDL_NOGETPROCADDR__
|
slouken@1927
|
152 |
#define SDL_PROC(ret,func,params) data->func=func;
|
slouken@1927
|
153 |
#else
|
slouken@1927
|
154 |
#define SDL_PROC(ret,func,params) \
|
slouken@1927
|
155 |
do { \
|
slouken@1927
|
156 |
data->func = SDL_GL_GetProcAddress(#func); \
|
slouken@1927
|
157 |
if ( ! data->func ) { \
|
slouken@1927
|
158 |
SDL_SetError("Couldn't load GL function %s: %s\n", #func, SDL_GetError()); \
|
slouken@1927
|
159 |
return -1; \
|
slouken@1927
|
160 |
} \
|
slouken@1927
|
161 |
} while ( 0 );
|
slouken@1927
|
162 |
#endif /* __SDL_NOGETPROCADDR__ */
|
slouken@1927
|
163 |
|
slouken@5204
|
164 |
#include "SDL_glfuncs.h"
|
slouken@1927
|
165 |
#undef SDL_PROC
|
slouken@1927
|
166 |
return 0;
|
slouken@1927
|
167 |
}
|
slouken@1927
|
168 |
|
slouken@1918
|
169 |
SDL_Renderer *
|
slouken@1918
|
170 |
GL_CreateRenderer(SDL_Window * window, Uint32 flags)
|
slouken@1918
|
171 |
{
|
slouken@1918
|
172 |
SDL_Renderer *renderer;
|
slouken@1918
|
173 |
GL_RenderData *data;
|
slouken@1952
|
174 |
GLint value;
|
slouken@5154
|
175 |
Uint32 window_flags;
|
slouken@1918
|
176 |
|
slouken@5154
|
177 |
window_flags = SDL_GetWindowFlags(window);
|
slouken@5154
|
178 |
if (!(window_flags & SDL_WINDOW_OPENGL)) {
|
slouken@5154
|
179 |
if (SDL_RecreateWindow(window, window_flags | SDL_WINDOW_OPENGL) < 0) {
|
slouken@1924
|
180 |
return NULL;
|
slouken@1924
|
181 |
}
|
slouken@1918
|
182 |
}
|
slouken@1918
|
183 |
|
slouken@1920
|
184 |
renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
|
slouken@1918
|
185 |
if (!renderer) {
|
slouken@1918
|
186 |
SDL_OutOfMemory();
|
slouken@1918
|
187 |
return NULL;
|
slouken@1918
|
188 |
}
|
slouken@1918
|
189 |
|
slouken@1920
|
190 |
data = (GL_RenderData *) SDL_calloc(1, sizeof(*data));
|
slouken@1918
|
191 |
if (!data) {
|
slouken@1918
|
192 |
GL_DestroyRenderer(renderer);
|
slouken@1918
|
193 |
SDL_OutOfMemory();
|
slouken@1918
|
194 |
return NULL;
|
slouken@1918
|
195 |
}
|
slouken@1918
|
196 |
|
slouken@5147
|
197 |
renderer->WindowEvent = GL_WindowEvent;
|
slouken@1918
|
198 |
renderer->CreateTexture = GL_CreateTexture;
|
slouken@1918
|
199 |
renderer->UpdateTexture = GL_UpdateTexture;
|
slouken@1918
|
200 |
renderer->LockTexture = GL_LockTexture;
|
slouken@1918
|
201 |
renderer->UnlockTexture = GL_UnlockTexture;
|
slouken@3596
|
202 |
renderer->RenderClear = GL_RenderClear;
|
slouken@3596
|
203 |
renderer->RenderDrawPoints = GL_RenderDrawPoints;
|
slouken@3596
|
204 |
renderer->RenderDrawLines = GL_RenderDrawLines;
|
slouken@3596
|
205 |
renderer->RenderFillRects = GL_RenderFillRects;
|
slouken@1918
|
206 |
renderer->RenderCopy = GL_RenderCopy;
|
slouken@3431
|
207 |
renderer->RenderReadPixels = GL_RenderReadPixels;
|
slouken@1918
|
208 |
renderer->RenderPresent = GL_RenderPresent;
|
slouken@1918
|
209 |
renderer->DestroyTexture = GL_DestroyTexture;
|
slouken@1918
|
210 |
renderer->DestroyRenderer = GL_DestroyRenderer;
|
slouken@1918
|
211 |
renderer->info = GL_RenderDriver.info;
|
slouken@1918
|
212 |
renderer->driverdata = data;
|
slouken@1918
|
213 |
|
slouken@5142
|
214 |
renderer->info.flags = SDL_RENDERER_ACCELERATED;
|
slouken@1918
|
215 |
|
slouken@3685
|
216 |
data->context = SDL_GL_CreateContext(window);
|
slouken@1918
|
217 |
if (!data->context) {
|
slouken@1918
|
218 |
GL_DestroyRenderer(renderer);
|
slouken@1918
|
219 |
return NULL;
|
slouken@1918
|
220 |
}
|
slouken@3685
|
221 |
if (SDL_GL_MakeCurrent(window, data->context) < 0) {
|
slouken@1918
|
222 |
GL_DestroyRenderer(renderer);
|
slouken@1918
|
223 |
return NULL;
|
slouken@1918
|
224 |
}
|
slouken@5204
|
225 |
|
slouken@5204
|
226 |
if (GL_LoadFunctions(data) < 0) {
|
slouken@5204
|
227 |
GL_DestroyRenderer(renderer);
|
slouken@5204
|
228 |
return NULL;
|
slouken@5204
|
229 |
}
|
slouken@5204
|
230 |
|
slouken@2246
|
231 |
#ifdef __MACOSX__
|
slouken@2246
|
232 |
/* Enable multi-threaded rendering */
|
slouken@2246
|
233 |
/* Disabled until Ryan finishes his VBO/PBO code...
|
bob@2295
|
234 |
CGLEnable(CGLGetCurrentContext(), kCGLCEMPEngine);
|
bob@2295
|
235 |
*/
|
slouken@2246
|
236 |
#endif
|
slouken@2246
|
237 |
|
slouken@1965
|
238 |
if (flags & SDL_RENDERER_PRESENTVSYNC) {
|
slouken@1918
|
239 |
SDL_GL_SetSwapInterval(1);
|
slouken@1918
|
240 |
} else {
|
slouken@1918
|
241 |
SDL_GL_SetSwapInterval(0);
|
slouken@1918
|
242 |
}
|
slouken@1918
|
243 |
if (SDL_GL_GetSwapInterval() > 0) {
|
slouken@1965
|
244 |
renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
|
slouken@1918
|
245 |
}
|
slouken@1918
|
246 |
|
slouken@1952
|
247 |
data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
|
slouken@1952
|
248 |
renderer->info.max_texture_width = value;
|
slouken@1952
|
249 |
data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
|
slouken@1952
|
250 |
renderer->info.max_texture_height = value;
|
slouken@1920
|
251 |
|
slouken@1926
|
252 |
if (SDL_GL_ExtensionSupported("GL_ARB_texture_rectangle")
|
slouken@1926
|
253 |
|| SDL_GL_ExtensionSupported("GL_EXT_texture_rectangle")) {
|
slouken@1926
|
254 |
data->GL_ARB_texture_rectangle_supported = SDL_TRUE;
|
slouken@1926
|
255 |
}
|
slouken@2233
|
256 |
if (SDL_GL_ExtensionSupported("GL_APPLE_texture_range")) {
|
slouken@2233
|
257 |
data->glTextureRangeAPPLE =
|
slouken@2233
|
258 |
(void (*)(GLenum, GLsizei, const GLvoid *))
|
slouken@2233
|
259 |
SDL_GL_GetProcAddress("glTextureRangeAPPLE");
|
slouken@2233
|
260 |
}
|
slouken@1920
|
261 |
|
slouken@1918
|
262 |
/* Set up parameters for rendering */
|
slouken@1927
|
263 |
data->blendMode = -1;
|
slouken@1927
|
264 |
data->glDisable(GL_DEPTH_TEST);
|
slouken@1927
|
265 |
data->glDisable(GL_CULL_FACE);
|
slouken@3262
|
266 |
/* This ended up causing video discrepancies between OpenGL and Direct3D */
|
slouken@3262
|
267 |
/*data->glEnable(GL_LINE_SMOOTH);*/
|
slouken@1926
|
268 |
if (data->GL_ARB_texture_rectangle_supported) {
|
slouken@1927
|
269 |
data->glEnable(GL_TEXTURE_RECTANGLE_ARB);
|
slouken@1926
|
270 |
} else {
|
slouken@1927
|
271 |
data->glEnable(GL_TEXTURE_2D);
|
slouken@1926
|
272 |
}
|
slouken@2833
|
273 |
data->updateSize = SDL_TRUE;
|
slouken@1918
|
274 |
|
slouken@1918
|
275 |
return renderer;
|
slouken@1918
|
276 |
}
|
slouken@1918
|
277 |
|
slouken@5147
|
278 |
static SDL_GLContext SDL_CurrentContext = NULL;
|
slouken@5147
|
279 |
|
slouken@1923
|
280 |
static int
|
slouken@1923
|
281 |
GL_ActivateRenderer(SDL_Renderer * renderer)
|
slouken@1923
|
282 |
{
|
slouken@1923
|
283 |
GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
|
slouken@3685
|
284 |
SDL_Window *window = renderer->window;
|
slouken@1923
|
285 |
|
slouken@5147
|
286 |
if (SDL_CurrentContext != data->context) {
|
slouken@5147
|
287 |
if (SDL_GL_MakeCurrent(window, data->context) < 0) {
|
slouken@5147
|
288 |
return -1;
|
slouken@5147
|
289 |
}
|
slouken@5147
|
290 |
SDL_CurrentContext = data->context;
|
slouken@1970
|
291 |
}
|
slouken@2833
|
292 |
if (data->updateSize) {
|
slouken@5154
|
293 |
int w, h;
|
slouken@5154
|
294 |
|
slouken@5154
|
295 |
SDL_GetWindowSize(window, &w, &h);
|
slouken@2836
|
296 |
data->glMatrixMode(GL_PROJECTION);
|
slouken@2836
|
297 |
data->glLoadIdentity();
|
slouken@2836
|
298 |
data->glMatrixMode(GL_MODELVIEW);
|
slouken@2836
|
299 |
data->glLoadIdentity();
|
slouken@5154
|
300 |
data->glViewport(0, 0, w, h);
|
slouken@5154
|
301 |
data->glOrtho(0.0, (GLdouble) w, (GLdouble) h, 0.0, 0.0, 1.0);
|
slouken@2833
|
302 |
data->updateSize = SDL_FALSE;
|
slouken@2833
|
303 |
}
|
slouken@1970
|
304 |
return 0;
|
slouken@1970
|
305 |
}
|
slouken@1970
|
306 |
|
slouken@5147
|
307 |
static void
|
slouken@5147
|
308 |
GL_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
|
slouken@1970
|
309 |
{
|
slouken@1970
|
310 |
GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
|
slouken@1970
|
311 |
|
slouken@5147
|
312 |
if (event->event == SDL_WINDOWEVENT_RESIZED) {
|
slouken@5147
|
313 |
/* Rebind the context to the window area and update matrices */
|
slouken@5147
|
314 |
SDL_CurrentContext = NULL;
|
slouken@5147
|
315 |
data->updateSize = SDL_TRUE;
|
slouken@5147
|
316 |
}
|
slouken@1923
|
317 |
}
|
slouken@1923
|
318 |
|
slouken@1922
|
319 |
static __inline__ int
|
slouken@1922
|
320 |
power_of_2(int input)
|
slouken@1922
|
321 |
{
|
slouken@1922
|
322 |
int value = 1;
|
slouken@1922
|
323 |
|
slouken@1922
|
324 |
while (value < input) {
|
slouken@1922
|
325 |
value <<= 1;
|
slouken@1922
|
326 |
}
|
slouken@1922
|
327 |
return value;
|
slouken@1922
|
328 |
}
|
slouken@1922
|
329 |
|
slouken@3433
|
330 |
static __inline__ SDL_bool
|
slouken@3433
|
331 |
convert_format(GL_RenderData *renderdata, Uint32 pixel_format,
|
slouken@3433
|
332 |
GLint* internalFormat, GLenum* format, GLenum* type)
|
slouken@3433
|
333 |
{
|
slouken@3433
|
334 |
switch (pixel_format) {
|
slouken@3433
|
335 |
case SDL_PIXELFORMAT_ARGB8888:
|
slouken@5156
|
336 |
*internalFormat = GL_RGBA8;
|
slouken@3433
|
337 |
*format = GL_BGRA;
|
slouken@3433
|
338 |
*type = GL_UNSIGNED_INT_8_8_8_8_REV;
|
slouken@3433
|
339 |
break;
|
slouken@3433
|
340 |
default:
|
slouken@3433
|
341 |
return SDL_FALSE;
|
slouken@3433
|
342 |
}
|
slouken@3433
|
343 |
return SDL_TRUE;
|
slouken@3433
|
344 |
}
|
icculus@2835
|
345 |
|
slouken@1918
|
346 |
static int
|
slouken@1918
|
347 |
GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
|
slouken@1918
|
348 |
{
|
slouken@1918
|
349 |
GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
|
slouken@1918
|
350 |
GL_TextureData *data;
|
slouken@1920
|
351 |
GLint internalFormat;
|
slouken@1920
|
352 |
GLenum format, type;
|
slouken@1922
|
353 |
int texture_w, texture_h;
|
slouken@1924
|
354 |
GLenum result;
|
slouken@1918
|
355 |
|
slouken@5147
|
356 |
GL_ActivateRenderer(renderer);
|
slouken@5147
|
357 |
|
slouken@3433
|
358 |
if (!convert_format(renderdata, texture->format, &internalFormat,
|
slouken@3433
|
359 |
&format, &type)) {
|
slouken@4990
|
360 |
SDL_SetError("Texture format %s not supported by OpenGL",
|
slouken@4990
|
361 |
SDL_GetPixelFormatName(texture->format));
|
slouken@1920
|
362 |
return -1;
|
slouken@1920
|
363 |
}
|
slouken@1920
|
364 |
|
slouken@1920
|
365 |
data = (GL_TextureData *) SDL_calloc(1, sizeof(*data));
|
slouken@1918
|
366 |
if (!data) {
|
slouken@1918
|
367 |
SDL_OutOfMemory();
|
slouken@1918
|
368 |
return -1;
|
slouken@1918
|
369 |
}
|
slouken@1918
|
370 |
|
slouken@2222
|
371 |
if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
|
slouken@5156
|
372 |
data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format);
|
slouken@2222
|
373 |
data->pixels = SDL_malloc(texture->h * data->pitch);
|
slouken@2222
|
374 |
if (!data->pixels) {
|
slouken@2222
|
375 |
SDL_OutOfMemory();
|
slouken@2222
|
376 |
SDL_free(data);
|
slouken@2222
|
377 |
return -1;
|
slouken@2222
|
378 |
}
|
slouken@2222
|
379 |
}
|
slouken@2222
|
380 |
|
slouken@1918
|
381 |
texture->driverdata = data;
|
slouken@1918
|
382 |
|
slouken@1927
|
383 |
renderdata->glGetError();
|
slouken@1927
|
384 |
renderdata->glGenTextures(1, &data->texture);
|
slouken@1926
|
385 |
if (renderdata->GL_ARB_texture_rectangle_supported) {
|
slouken@1926
|
386 |
data->type = GL_TEXTURE_RECTANGLE_ARB;
|
slouken@1926
|
387 |
texture_w = texture->w;
|
slouken@1926
|
388 |
texture_h = texture->h;
|
icculus@2835
|
389 |
data->texw = (GLfloat) texture_w;
|
icculus@2835
|
390 |
data->texh = (GLfloat) texture_h;
|
slouken@1926
|
391 |
} else {
|
slouken@1926
|
392 |
data->type = GL_TEXTURE_2D;
|
slouken@1926
|
393 |
texture_w = power_of_2(texture->w);
|
slouken@1926
|
394 |
texture_h = power_of_2(texture->h);
|
icculus@2835
|
395 |
data->texw = (GLfloat) (texture->w) / texture_w;
|
slouken@1926
|
396 |
data->texh = (GLfloat) texture->h / texture_h;
|
slouken@1926
|
397 |
}
|
icculus@2835
|
398 |
|
slouken@1920
|
399 |
data->format = format;
|
slouken@1920
|
400 |
data->formattype = type;
|
slouken@2884
|
401 |
renderdata->glEnable(data->type);
|
slouken@1927
|
402 |
renderdata->glBindTexture(data->type, data->texture);
|
slouken@2230
|
403 |
renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER,
|
slouken@5138
|
404 |
GL_LINEAR);
|
slouken@2230
|
405 |
renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER,
|
slouken@5138
|
406 |
GL_LINEAR);
|
slouken@2230
|
407 |
renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S,
|
slouken@2230
|
408 |
GL_CLAMP_TO_EDGE);
|
slouken@2230
|
409 |
renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T,
|
slouken@2230
|
410 |
GL_CLAMP_TO_EDGE);
|
slouken@2840
|
411 |
#ifdef __MACOSX__
|
slouken@2230
|
412 |
#ifndef GL_TEXTURE_STORAGE_HINT_APPLE
|
slouken@2230
|
413 |
#define GL_TEXTURE_STORAGE_HINT_APPLE 0x85BC
|
slouken@2230
|
414 |
#endif
|
slouken@2230
|
415 |
#ifndef STORAGE_CACHED_APPLE
|
slouken@2230
|
416 |
#define STORAGE_CACHED_APPLE 0x85BE
|
slouken@2230
|
417 |
#endif
|
slouken@2230
|
418 |
#ifndef STORAGE_SHARED_APPLE
|
slouken@2230
|
419 |
#define STORAGE_SHARED_APPLE 0x85BF
|
slouken@2230
|
420 |
#endif
|
slouken@2230
|
421 |
if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
|
slouken@2230
|
422 |
renderdata->glTexParameteri(data->type, GL_TEXTURE_STORAGE_HINT_APPLE,
|
slouken@2230
|
423 |
GL_STORAGE_SHARED_APPLE);
|
slouken@2230
|
424 |
} else {
|
slouken@2230
|
425 |
renderdata->glTexParameteri(data->type, GL_TEXTURE_STORAGE_HINT_APPLE,
|
slouken@2230
|
426 |
GL_STORAGE_CACHED_APPLE);
|
slouken@2230
|
427 |
}
|
bob@2295
|
428 |
if (texture->access == SDL_TEXTUREACCESS_STREAMING
|
bob@2295
|
429 |
&& texture->format == SDL_PIXELFORMAT_ARGB8888) {
|
slouken@2230
|
430 |
renderdata->glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
|
slouken@2230
|
431 |
renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w,
|
slouken@2230
|
432 |
texture_h, 0, format, type, data->pixels);
|
slouken@5156
|
433 |
}
|
slouken@5156
|
434 |
else
|
slouken@2809
|
435 |
#endif
|
slouken@2230
|
436 |
{
|
slouken@2230
|
437 |
renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w,
|
slouken@2230
|
438 |
texture_h, 0, format, type, NULL);
|
slouken@2230
|
439 |
}
|
slouken@3041
|
440 |
renderdata->glDisable(data->type);
|
slouken@1927
|
441 |
result = renderdata->glGetError();
|
slouken@1924
|
442 |
if (result != GL_NO_ERROR) {
|
slouken@1924
|
443 |
GL_SetError("glTexImage2D()", result);
|
slouken@1924
|
444 |
return -1;
|
slouken@1924
|
445 |
}
|
slouken@1918
|
446 |
return 0;
|
slouken@1918
|
447 |
}
|
slouken@1918
|
448 |
|
slouken@1924
|
449 |
static void
|
slouken@1927
|
450 |
SetupTextureUpdate(GL_RenderData * renderdata, SDL_Texture * texture,
|
slouken@1927
|
451 |
int pitch)
|
slouken@1924
|
452 |
{
|
slouken@1927
|
453 |
renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
slouken@2808
|
454 |
renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH,
|
slouken@5156
|
455 |
(pitch / SDL_BYTESPERPIXEL(texture->format)));
|
slouken@1924
|
456 |
}
|
slouken@1924
|
457 |
|
slouken@1918
|
458 |
static int
|
slouken@1918
|
459 |
GL_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
|
slouken@1918
|
460 |
const SDL_Rect * rect, const void *pixels, int pitch)
|
slouken@1918
|
461 |
{
|
slouken@1927
|
462 |
GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
|
slouken@1918
|
463 |
GL_TextureData *data = (GL_TextureData *) texture->driverdata;
|
slouken@1924
|
464 |
GLenum result;
|
slouken@1918
|
465 |
|
slouken@5147
|
466 |
GL_ActivateRenderer(renderer);
|
slouken@5147
|
467 |
|
slouken@1927
|
468 |
renderdata->glGetError();
|
slouken@1927
|
469 |
SetupTextureUpdate(renderdata, texture, pitch);
|
slouken@2884
|
470 |
renderdata->glEnable(data->type);
|
slouken@1927
|
471 |
renderdata->glBindTexture(data->type, data->texture);
|
slouken@1927
|
472 |
renderdata->glTexSubImage2D(data->type, 0, rect->x, rect->y, rect->w,
|
slouken@1927
|
473 |
rect->h, data->format, data->formattype,
|
slouken@1927
|
474 |
pixels);
|
slouken@3041
|
475 |
renderdata->glDisable(data->type);
|
slouken@1927
|
476 |
result = renderdata->glGetError();
|
slouken@1924
|
477 |
if (result != GL_NO_ERROR) {
|
slouken@1924
|
478 |
GL_SetError("glTexSubImage2D()", result);
|
slouken@1924
|
479 |
return -1;
|
slouken@1924
|
480 |
}
|
slouken@1918
|
481 |
return 0;
|
slouken@1918
|
482 |
}
|
slouken@1918
|
483 |
|
slouken@1918
|
484 |
static int
|
slouken@1918
|
485 |
GL_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
|
slouken@5156
|
486 |
const SDL_Rect * rect, void **pixels, int *pitch)
|
slouken@1918
|
487 |
{
|
slouken@1918
|
488 |
GL_TextureData *data = (GL_TextureData *) texture->driverdata;
|
slouken@1918
|
489 |
|
slouken@1920
|
490 |
*pixels =
|
slouken@1920
|
491 |
(void *) ((Uint8 *) data->pixels + rect->y * data->pitch +
|
slouken@5156
|
492 |
rect->x * SDL_BYTESPERPIXEL(texture->format));
|
slouken@1920
|
493 |
*pitch = data->pitch;
|
slouken@1918
|
494 |
return 0;
|
slouken@1918
|
495 |
}
|
slouken@1918
|
496 |
|
slouken@1918
|
497 |
static void
|
slouken@1918
|
498 |
GL_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
|
slouken@1918
|
499 |
{
|
slouken@5156
|
500 |
GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
|
slouken@5156
|
501 |
GL_TextureData *data = (GL_TextureData *) texture->driverdata;
|
slouken@1918
|
502 |
|
slouken@5156
|
503 |
GL_ActivateRenderer(renderer);
|
slouken@1918
|
504 |
|
slouken@5156
|
505 |
SetupTextureUpdate(renderdata, texture, data->pitch);
|
slouken@5156
|
506 |
renderdata->glEnable(data->type);
|
slouken@5156
|
507 |
renderdata->glBindTexture(data->type, data->texture);
|
slouken@5156
|
508 |
renderdata->glTexSubImage2D(data->type, 0, 0, 0, texture->w, texture->h,
|
slouken@5156
|
509 |
data->format, data->formattype, data->pixels);
|
slouken@5156
|
510 |
renderdata->glDisable(data->type);
|
slouken@1918
|
511 |
}
|
slouken@1918
|
512 |
|
slouken@2936
|
513 |
static void
|
slouken@5140
|
514 |
GL_SetBlendMode(GL_RenderData * data, int blendMode)
|
slouken@2936
|
515 |
{
|
slouken@2936
|
516 |
if (blendMode != data->blendMode) {
|
slouken@2936
|
517 |
switch (blendMode) {
|
slouken@2936
|
518 |
case SDL_BLENDMODE_NONE:
|
slouken@2936
|
519 |
data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
slouken@2936
|
520 |
data->glDisable(GL_BLEND);
|
slouken@2936
|
521 |
break;
|
slouken@2936
|
522 |
case SDL_BLENDMODE_BLEND:
|
slouken@2936
|
523 |
data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
slouken@2936
|
524 |
data->glEnable(GL_BLEND);
|
slouken@2936
|
525 |
data->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
slouken@2936
|
526 |
break;
|
slouken@2936
|
527 |
case SDL_BLENDMODE_ADD:
|
slouken@2936
|
528 |
data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
slouken@2936
|
529 |
data->glEnable(GL_BLEND);
|
slouken@2936
|
530 |
data->glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
slouken@2936
|
531 |
break;
|
slouken@5184
|
532 |
case SDL_BLENDMODE_MOD:
|
slouken@5184
|
533 |
data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
slouken@5184
|
534 |
data->glEnable(GL_BLEND);
|
slouken@5184
|
535 |
data->glBlendFunc(GL_ZERO, GL_SRC_COLOR);
|
slouken@5184
|
536 |
break;
|
slouken@2936
|
537 |
}
|
slouken@2936
|
538 |
data->blendMode = blendMode;
|
slouken@2936
|
539 |
}
|
slouken@2936
|
540 |
}
|
slouken@2936
|
541 |
|
slouken@1918
|
542 |
static int
|
slouken@3596
|
543 |
GL_RenderClear(SDL_Renderer * renderer)
|
slouken@3596
|
544 |
{
|
slouken@3596
|
545 |
GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
|
slouken@3596
|
546 |
|
slouken@5147
|
547 |
GL_ActivateRenderer(renderer);
|
slouken@5147
|
548 |
|
slouken@3596
|
549 |
data->glClearColor((GLfloat) renderer->r * inv255f,
|
slouken@3596
|
550 |
(GLfloat) renderer->g * inv255f,
|
slouken@3596
|
551 |
(GLfloat) renderer->b * inv255f,
|
slouken@3596
|
552 |
(GLfloat) renderer->a * inv255f);
|
slouken@3596
|
553 |
|
slouken@3596
|
554 |
data->glClear(GL_COLOR_BUFFER_BIT);
|
slouken@3596
|
555 |
|
slouken@3596
|
556 |
return 0;
|
slouken@3596
|
557 |
}
|
slouken@3596
|
558 |
|
slouken@3596
|
559 |
static int
|
slouken@3596
|
560 |
GL_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points,
|
slouken@3596
|
561 |
int count)
|
slouken@2884
|
562 |
{
|
slouken@2884
|
563 |
GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
|
slouken@3536
|
564 |
int i;
|
slouken@2884
|
565 |
|
slouken@5147
|
566 |
GL_ActivateRenderer(renderer);
|
slouken@5147
|
567 |
|
slouken@5140
|
568 |
GL_SetBlendMode(data, renderer->blendMode);
|
slouken@2884
|
569 |
|
slouken@2884
|
570 |
data->glColor4f((GLfloat) renderer->r * inv255f,
|
slouken@2884
|
571 |
(GLfloat) renderer->g * inv255f,
|
slouken@2884
|
572 |
(GLfloat) renderer->b * inv255f,
|
slouken@2884
|
573 |
(GLfloat) renderer->a * inv255f);
|
slouken@2884
|
574 |
|
slouken@2901
|
575 |
data->glBegin(GL_POINTS);
|
slouken@3536
|
576 |
for (i = 0; i < count; ++i) {
|
slouken@3536
|
577 |
data->glVertex2f(0.5f + points[i].x, 0.5f + points[i].y);
|
slouken@3536
|
578 |
}
|
slouken@2901
|
579 |
data->glEnd();
|
slouken@2901
|
580 |
|
slouken@2901
|
581 |
return 0;
|
slouken@2901
|
582 |
}
|
slouken@2901
|
583 |
|
slouken@2901
|
584 |
static int
|
slouken@3596
|
585 |
GL_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points,
|
slouken@3596
|
586 |
int count)
|
slouken@2901
|
587 |
{
|
slouken@2901
|
588 |
GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
|
slouken@3536
|
589 |
int i;
|
slouken@2901
|
590 |
|
slouken@5147
|
591 |
GL_ActivateRenderer(renderer);
|
slouken@5147
|
592 |
|
slouken@5140
|
593 |
GL_SetBlendMode(data, renderer->blendMode);
|
slouken@2901
|
594 |
|
slouken@2901
|
595 |
data->glColor4f((GLfloat) renderer->r * inv255f,
|
slouken@2901
|
596 |
(GLfloat) renderer->g * inv255f,
|
slouken@2901
|
597 |
(GLfloat) renderer->b * inv255f,
|
slouken@2901
|
598 |
(GLfloat) renderer->a * inv255f);
|
slouken@2901
|
599 |
|
slouken@3536
|
600 |
if (count > 2 &&
|
slouken@3536
|
601 |
points[0].x == points[count-1].x && points[0].y == points[count-1].y) {
|
slouken@3536
|
602 |
data->glBegin(GL_LINE_LOOP);
|
slouken@3536
|
603 |
/* GL_LINE_LOOP takes care of the final segment */
|
slouken@3536
|
604 |
--count;
|
slouken@3536
|
605 |
for (i = 0; i < count; ++i) {
|
slouken@3536
|
606 |
data->glVertex2f(0.5f + points[i].x, 0.5f + points[i].y);
|
slouken@3536
|
607 |
}
|
slouken@3536
|
608 |
data->glEnd();
|
slouken@3536
|
609 |
} else {
|
slouken@5086
|
610 |
#if defined(__APPLE__) || defined(__WIN32__)
|
aschiffler@4910
|
611 |
#else
|
slouken@4905
|
612 |
int x1, y1, x2, y2;
|
aschiffler@4910
|
613 |
#endif
|
slouken@4905
|
614 |
|
slouken@3536
|
615 |
data->glBegin(GL_LINE_STRIP);
|
slouken@3536
|
616 |
for (i = 0; i < count; ++i) {
|
slouken@3536
|
617 |
data->glVertex2f(0.5f + points[i].x, 0.5f + points[i].y);
|
slouken@3536
|
618 |
}
|
slouken@3536
|
619 |
data->glEnd();
|
slouken@3474
|
620 |
|
slouken@3536
|
621 |
/* The line is half open, so we need one more point to complete it.
|
slouken@3536
|
622 |
* http://www.opengl.org/documentation/specs/version1.1/glspec1.1/node47.html
|
slouken@3536
|
623 |
* If we have to, we can use vertical line and horizontal line textures
|
slouken@3536
|
624 |
* for vertical and horizontal lines, and then create custom textures
|
slouken@3536
|
625 |
* for diagonal lines and software render those. It's terrible, but at
|
slouken@3536
|
626 |
* least it would be pixel perfect.
|
slouken@3536
|
627 |
*/
|
slouken@3536
|
628 |
data->glBegin(GL_POINTS);
|
slouken@5086
|
629 |
#if defined(__APPLE__) || defined(__WIN32__)
|
slouken@3536
|
630 |
/* Mac OS X and Windows seem to always leave the second point open */
|
slouken@3536
|
631 |
data->glVertex2f(0.5f + points[count-1].x, 0.5f + points[count-1].y);
|
slouken@3474
|
632 |
#else
|
slouken@3536
|
633 |
/* Linux seems to leave the right-most or bottom-most point open */
|
slouken@4905
|
634 |
x1 = points[0].x;
|
slouken@4905
|
635 |
y1 = points[0].y;
|
slouken@4905
|
636 |
x2 = points[count-1].x;
|
slouken@4905
|
637 |
y2 = points[count-1].y;
|
slouken@3536
|
638 |
|
slouken@3536
|
639 |
if (x1 > x2) {
|
slouken@3536
|
640 |
data->glVertex2f(0.5f + x1, 0.5f + y1);
|
slouken@3536
|
641 |
} else if (x2 > x1) {
|
slouken@3536
|
642 |
data->glVertex2f(0.5f + x2, 0.5f + y2);
|
slouken@3536
|
643 |
} else if (y1 > y2) {
|
slouken@3536
|
644 |
data->glVertex2f(0.5f + x1, 0.5f + y1);
|
slouken@3536
|
645 |
} else if (y2 > y1) {
|
slouken@3536
|
646 |
data->glVertex2f(0.5f + x2, 0.5f + y2);
|
slouken@3536
|
647 |
}
|
slouken@3536
|
648 |
#endif
|
slouken@3536
|
649 |
data->glEnd();
|
slouken@3474
|
650 |
}
|
slouken@3455
|
651 |
|
slouken@1918
|
652 |
return 0;
|
slouken@1918
|
653 |
}
|
slouken@1918
|
654 |
|
slouken@1918
|
655 |
static int
|
slouken@3596
|
656 |
GL_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count)
|
slouken@2925
|
657 |
{
|
slouken@2925
|
658 |
GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
|
slouken@3536
|
659 |
int i;
|
slouken@2925
|
660 |
|
slouken@5147
|
661 |
GL_ActivateRenderer(renderer);
|
slouken@5147
|
662 |
|
slouken@5140
|
663 |
GL_SetBlendMode(data, renderer->blendMode);
|
slouken@2936
|
664 |
|
slouken@2925
|
665 |
data->glColor4f((GLfloat) renderer->r * inv255f,
|
slouken@2925
|
666 |
(GLfloat) renderer->g * inv255f,
|
slouken@2925
|
667 |
(GLfloat) renderer->b * inv255f,
|
slouken@2925
|
668 |
(GLfloat) renderer->a * inv255f);
|
slouken@2936
|
669 |
|
slouken@3536
|
670 |
for (i = 0; i < count; ++i) {
|
slouken@3536
|
671 |
const SDL_Rect *rect = rects[i];
|
slouken@3536
|
672 |
|
slouken@3536
|
673 |
data->glRecti(rect->x, rect->y, rect->x + rect->w, rect->y + rect->h);
|
slouken@3536
|
674 |
}
|
slouken@2925
|
675 |
|
slouken@2925
|
676 |
return 0;
|
slouken@2925
|
677 |
}
|
slouken@2925
|
678 |
|
slouken@2925
|
679 |
static int
|
slouken@1918
|
680 |
GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
|
slouken@1985
|
681 |
const SDL_Rect * srcrect, const SDL_Rect * dstrect)
|
slouken@1918
|
682 |
{
|
slouken@1918
|
683 |
GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
|
slouken@1918
|
684 |
GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata;
|
slouken@1918
|
685 |
int minx, miny, maxx, maxy;
|
slouken@1918
|
686 |
GLfloat minu, maxu, minv, maxv;
|
slouken@1918
|
687 |
|
slouken@5147
|
688 |
GL_ActivateRenderer(renderer);
|
slouken@5147
|
689 |
|
slouken@1918
|
690 |
minx = dstrect->x;
|
slouken@1918
|
691 |
miny = dstrect->y;
|
slouken@1918
|
692 |
maxx = dstrect->x + dstrect->w;
|
slouken@1918
|
693 |
maxy = dstrect->y + dstrect->h;
|
slouken@1918
|
694 |
|
slouken@1918
|
695 |
minu = (GLfloat) srcrect->x / texture->w;
|
slouken@1920
|
696 |
minu *= texturedata->texw;
|
slouken@1918
|
697 |
maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w;
|
slouken@1920
|
698 |
maxu *= texturedata->texw;
|
slouken@1918
|
699 |
minv = (GLfloat) srcrect->y / texture->h;
|
slouken@1920
|
700 |
minv *= texturedata->texh;
|
slouken@1918
|
701 |
maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h;
|
slouken@1920
|
702 |
maxv *= texturedata->texh;
|
slouken@1918
|
703 |
|
slouken@2884
|
704 |
data->glEnable(texturedata->type);
|
slouken@1927
|
705 |
data->glBindTexture(texturedata->type, texturedata->texture);
|
slouken@1918
|
706 |
|
slouken@1985
|
707 |
if (texture->modMode) {
|
slouken@1985
|
708 |
data->glColor4f((GLfloat) texture->r * inv255f,
|
slouken@1985
|
709 |
(GLfloat) texture->g * inv255f,
|
slouken@1985
|
710 |
(GLfloat) texture->b * inv255f,
|
slouken@1985
|
711 |
(GLfloat) texture->a * inv255f);
|
slouken@1985
|
712 |
} else {
|
slouken@1985
|
713 |
data->glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
slouken@1985
|
714 |
}
|
slouken@1985
|
715 |
|
slouken@5140
|
716 |
GL_SetBlendMode(data, texture->blendMode);
|
slouken@1918
|
717 |
|
slouken@1927
|
718 |
data->glBegin(GL_TRIANGLE_STRIP);
|
slouken@1927
|
719 |
data->glTexCoord2f(minu, minv);
|
slouken@3472
|
720 |
data->glVertex2f((GLfloat) minx, (GLfloat) miny);
|
slouken@1927
|
721 |
data->glTexCoord2f(maxu, minv);
|
slouken@3472
|
722 |
data->glVertex2f((GLfloat) maxx, (GLfloat) miny);
|
slouken@1927
|
723 |
data->glTexCoord2f(minu, maxv);
|
slouken@3472
|
724 |
data->glVertex2f((GLfloat) minx, (GLfloat) maxy);
|
slouken@1927
|
725 |
data->glTexCoord2f(maxu, maxv);
|
slouken@3472
|
726 |
data->glVertex2f((GLfloat) maxx, (GLfloat) maxy);
|
slouken@1927
|
727 |
data->glEnd();
|
slouken@1918
|
728 |
|
slouken@2884
|
729 |
data->glDisable(texturedata->type);
|
slouken@2884
|
730 |
|
slouken@1918
|
731 |
return 0;
|
slouken@1918
|
732 |
}
|
slouken@1918
|
733 |
|
slouken@3431
|
734 |
static int
|
slouken@3431
|
735 |
GL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
|
slouken@3435
|
736 |
Uint32 pixel_format, void * pixels, int pitch)
|
slouken@3431
|
737 |
{
|
slouken@3433
|
738 |
GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
|
slouken@3685
|
739 |
SDL_Window *window = renderer->window;
|
slouken@3433
|
740 |
GLint internalFormat;
|
slouken@3433
|
741 |
GLenum format, type;
|
slouken@3435
|
742 |
Uint8 *src, *dst, *tmp;
|
slouken@5154
|
743 |
int w, h, length, rows;
|
slouken@3433
|
744 |
|
slouken@5147
|
745 |
GL_ActivateRenderer(renderer);
|
slouken@5147
|
746 |
|
slouken@3433
|
747 |
if (!convert_format(data, pixel_format, &internalFormat, &format, &type)) {
|
slouken@3435
|
748 |
/* FIXME: Do a temp copy to a format that is supported */
|
slouken@3433
|
749 |
SDL_SetError("Unsupported pixel format");
|
slouken@3433
|
750 |
return -1;
|
slouken@3433
|
751 |
}
|
slouken@3433
|
752 |
|
slouken@5154
|
753 |
SDL_GetWindowSize(window, &w, &h);
|
slouken@5154
|
754 |
|
slouken@3446
|
755 |
data->glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
slouken@3446
|
756 |
data->glPixelStorei(GL_PACK_ROW_LENGTH,
|
slouken@5156
|
757 |
(pitch / SDL_BYTESPERPIXEL(pixel_format)));
|
slouken@3433
|
758 |
|
slouken@5154
|
759 |
data->glReadPixels(rect->x, (h-rect->y)-rect->h, rect->w, rect->h,
|
slouken@3435
|
760 |
format, type, pixels);
|
slouken@3435
|
761 |
|
slouken@3435
|
762 |
/* Flip the rows to be top-down */
|
slouken@5156
|
763 |
length = rect->w * SDL_BYTESPERPIXEL(pixel_format);
|
slouken@3435
|
764 |
src = (Uint8*)pixels + (rect->h-1)*pitch;
|
slouken@3435
|
765 |
dst = (Uint8*)pixels;
|
slouken@3435
|
766 |
tmp = SDL_stack_alloc(Uint8, length);
|
slouken@3435
|
767 |
rows = rect->h / 2;
|
slouken@3435
|
768 |
while (rows--) {
|
slouken@3435
|
769 |
SDL_memcpy(tmp, dst, length);
|
slouken@3435
|
770 |
SDL_memcpy(dst, src, length);
|
slouken@3435
|
771 |
SDL_memcpy(src, tmp, length);
|
slouken@3447
|
772 |
dst += pitch;
|
slouken@3447
|
773 |
src -= pitch;
|
slouken@3435
|
774 |
}
|
slouken@3435
|
775 |
SDL_stack_free(tmp);
|
slouken@3440
|
776 |
|
slouken@3440
|
777 |
return 0;
|
slouken@3431
|
778 |
}
|
slouken@3431
|
779 |
|
slouken@1918
|
780 |
static void
|
slouken@1918
|
781 |
GL_RenderPresent(SDL_Renderer * renderer)
|
slouken@1918
|
782 |
{
|
slouken@5147
|
783 |
GL_ActivateRenderer(renderer);
|
slouken@5147
|
784 |
|
slouken@1918
|
785 |
SDL_GL_SwapWindow(renderer->window);
|
slouken@1918
|
786 |
}
|
slouken@1918
|
787 |
|
slouken@1918
|
788 |
static void
|
slouken@1918
|
789 |
GL_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
|
slouken@1918
|
790 |
{
|
slouken@1927
|
791 |
GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
|
slouken@1918
|
792 |
GL_TextureData *data = (GL_TextureData *) texture->driverdata;
|
slouken@1918
|
793 |
|
slouken@5147
|
794 |
GL_ActivateRenderer(renderer);
|
slouken@5147
|
795 |
|
slouken@1918
|
796 |
if (!data) {
|
slouken@1918
|
797 |
return;
|
slouken@1918
|
798 |
}
|
slouken@1918
|
799 |
if (data->texture) {
|
slouken@1927
|
800 |
renderdata->glDeleteTextures(1, &data->texture);
|
slouken@1918
|
801 |
}
|
slouken@1920
|
802 |
if (data->pixels) {
|
slouken@1920
|
803 |
SDL_free(data->pixels);
|
slouken@1920
|
804 |
}
|
slouken@1918
|
805 |
SDL_free(data);
|
slouken@1918
|
806 |
texture->driverdata = NULL;
|
slouken@1918
|
807 |
}
|
slouken@1918
|
808 |
|
slouken@1975
|
809 |
static void
|
slouken@1918
|
810 |
GL_DestroyRenderer(SDL_Renderer * renderer)
|
slouken@1918
|
811 |
{
|
slouken@1918
|
812 |
GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
|
slouken@1918
|
813 |
|
slouken@1918
|
814 |
if (data) {
|
slouken@1920
|
815 |
if (data->context) {
|
bob@2328
|
816 |
/* SDL_GL_MakeCurrent(0, NULL); *//* doesn't do anything */
|
slouken@1920
|
817 |
SDL_GL_DeleteContext(data->context);
|
slouken@1918
|
818 |
}
|
slouken@1918
|
819 |
SDL_free(data);
|
slouken@1918
|
820 |
}
|
slouken@1918
|
821 |
SDL_free(renderer);
|
slouken@1918
|
822 |
}
|
slouken@1918
|
823 |
|
slouken@1952
|
824 |
#endif /* SDL_VIDEO_RENDER_OGL */
|
slouken@1918
|
825 |
|
slouken@1918
|
826 |
/* vi: set ts=4 sw=4 expandtab: */
|