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