The Battle for Wesnoth  1.13.4+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
SDL_gpu_GL_common.inl
Go to the documentation of this file.
1 /* This is an implementation file to be included after certain #defines have been set.
2 See a particular renderer's *.c file for specifics. */
3 
4 
5 // static inline only supported in Visual C++ from version 2015 but can use static __inline instead for older versions
6 #ifndef static_inline
7  #ifdef _MSC_VER
8  #if _MSC_VER < 1900
9  #define static_inline static __inline
10  #else
11  #define static_inline static inline
12  #endif
13  #else
14  #define static_inline static inline
15  #endif
16 #endif
17 
18 // Visual C does not support C99 (which includes a safe snprintf)
19 #ifdef _MSC_VER
20  #define snprintf c99_snprintf
21  // From Valentin Milea: http://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010
22  static_inline int c99_vsnprintf(char* str, size_t size, const char* format, va_list ap)
23  {
24  int count = -1;
25 
26  if (size != 0)
27  count = _vsnprintf_s(str, size, _TRUNCATE, format, ap);
28  if (count == -1)
29  count = _vscprintf(format, ap);
30 
31  return count;
32  }
33 
34  static_inline int c99_snprintf(char* str, size_t size, const char* format, ...)
35  {
36  int count;
37  va_list ap;
38 
39  va_start(ap, format);
40  count = c99_vsnprintf(str, size, format, ap);
41  va_end(ap);
42 
43  return count;
44  }
45 #endif
46 
47 
48 #include "SDL_gpu_GL_matrix.h"
49 #include "SDL_platform.h"
50 
51 #include "stb_image.h"
52 #include "stb_image_write.h"
53 
54 
55 // Forces a flush when vertex limit is reached (roughly 1000 sprites)
56 #define GPU_BLIT_BUFFER_VERTICES_PER_SPRITE 4
57 #define GPU_BLIT_BUFFER_INIT_MAX_NUM_VERTICES (GPU_BLIT_BUFFER_VERTICES_PER_SPRITE*1000)
58 
59 
60 // Near the unsigned short limit (65535)
61 #define GPU_BLIT_BUFFER_ABSOLUTE_MAX_VERTICES 60000
62 // Near the unsigned int limit (4294967295)
63 #define GPU_INDEX_BUFFER_ABSOLUTE_MAX_VERTICES 4000000000u
64 
65 
66 // x, y, s, t, r, g, b, a
67 #define GPU_BLIT_BUFFER_FLOATS_PER_VERTEX 8
68 
69 // bytes per vertex
70 #define GPU_BLIT_BUFFER_STRIDE (sizeof(float)*GPU_BLIT_BUFFER_FLOATS_PER_VERTEX)
71 #define GPU_BLIT_BUFFER_VERTEX_OFFSET 0
72 #define GPU_BLIT_BUFFER_TEX_COORD_OFFSET 2
73 #define GPU_BLIT_BUFFER_COLOR_OFFSET 4
74 
75 
76 #include <math.h>
77 #include <string.h>
78 
79 #ifndef _MSC_VER
80  #include <strings.h>
81 #endif
82 
83 #ifndef M_PI
84 #define M_PI 3.14159265358979323846
85 #endif
86 
87 
88 #ifdef SDL_GPU_USE_SDL2
89  #define GET_ALPHA(sdl_color) ((sdl_color).a)
90 #else
91  #define GET_ALPHA(sdl_color) ((sdl_color).unused)
92 #endif
93 
94 
95 #ifndef GL_VERTEX_SHADER
96  #ifndef SDL_GPU_DISABLE_SHADERS
97  #define SDL_GPU_DISABLE_SHADERS
98  #endif
99 #endif
100 
101 
102 // Internal API for managing window mappings
104 void GPU_RemoveWindowMapping(Uint32 windowID);
106 
107 
108 static SDL_PixelFormat* AllocFormat(GLenum glFormat);
109 static void FreeFormat(SDL_PixelFormat* format);
110 
111 
112 
113 static Uint8 isExtensionSupported(const char* extension_str)
114 {
115 #ifdef SDL_GPU_USE_OPENGL
116  return glewIsExtensionSupported(extension_str);
117 #else
118  // As suggested by Mesa3D.org
119  char* p = (char*)glGetString(GL_EXTENSIONS);
120  char* end;
121  unsigned long extNameLen;
122 
123  extNameLen = strlen(extension_str);
124  end = p + strlen(p);
125 
126  while(p < end)
127  {
128  unsigned long n = strcspn(p, " ");
129  if((extNameLen == n) && (strncmp(extension_str, p, n) == 0))
130  return 1;
131 
132  p += (n + 1);
133  }
134  return 0;
135 #endif
136 }
137 
138 static void init_features(GPU_Renderer* renderer)
139 {
140  // NPOT textures
141 #ifdef SDL_GPU_USE_OPENGL
142  if(isExtensionSupported("GL_ARB_texture_non_power_of_two"))
144  else
146 #elif defined(SDL_GPU_USE_GLES)
147  if(isExtensionSupported("GL_OES_texture_npot") || isExtensionSupported("GL_IMG_texture_npot")
148  || isExtensionSupported("GL_APPLE_texture_2D_limited_npot") || isExtensionSupported("GL_ARB_texture_non_power_of_two"))
150  else
152 #endif
153 
154  // FBO
155 #ifdef SDL_GPU_USE_OPENGL
156  if(isExtensionSupported("GL_EXT_framebuffer_object"))
158  else
160 #elif defined(SDL_GPU_USE_GLES)
161  #if SDL_GPU_GL_TIER < 3
162  if(isExtensionSupported("GL_OES_framebuffer_object"))
164  else
166  #else
168  #endif
169 #endif
170 
171  // Blending
172 #ifdef SDL_GPU_USE_OPENGL
175 
176  if(isExtensionSupported("GL_EXT_blend_equation_separate"))
178  else
180 
181 #elif defined(SDL_GPU_USE_GLES)
182  if(isExtensionSupported("GL_OES_blend_subtract"))
184  else
186 
187  if(isExtensionSupported("GL_OES_blend_func_separate"))
189  else
191 
192  if(isExtensionSupported("GL_OES_blend_equation_separate"))
194  else
196 #endif
197 
198  // Wrap modes
199 #ifdef SDL_GPU_USE_OPENGL
200  #if SDL_GPU_GL_MAJOR_VERSION > 1
202  #else
203  if(isExtensionSupported("GL_ARB_texture_mirrored_repeat"))
205  else
207  #endif
208 #elif defined(SDL_GPU_USE_GLES)
209  #if SDL_GPU_GLES_MAJOR_VERSION > 1
211  #else
212  if(isExtensionSupported("GL_OES_texture_mirrored_repeat"))
214  else
216  #endif
217 #endif
218 
219  // GL texture formats
220  if(isExtensionSupported("GL_EXT_bgr"))
222  if(isExtensionSupported("GL_EXT_bgra"))
224  if(isExtensionSupported("GL_EXT_abgr"))
226 
227  // Disable other texture formats for GLES.
228  // TODO: Add better (static) checking for format support. Some GL versions do not report previously non-core features as extensions.
229  #ifdef SDL_GPU_USE_GLES
230  renderer->enabled_features &= ~GPU_FEATURE_GL_BGR;
233  #endif
234 
235  if(isExtensionSupported("GL_ARB_fragment_shader"))
237  if(isExtensionSupported("GL_ARB_vertex_shader"))
239  if(isExtensionSupported("GL_ARB_geometry_shader4"))
241 }
242 
244 {
247 }
248 
249 
250 static_inline Uint8 isPowerOfTwo(unsigned int x)
251 {
252  return ((x != 0) && !(x & (x - 1)));
253 }
254 
255 static_inline unsigned int getNearestPowerOf2(unsigned int n)
256 {
257  unsigned int x = 1;
258  while(x < n)
259  {
260  x <<= 1;
261  }
262  return x;
263 }
264 
265 static void bindTexture(GPU_Renderer* renderer, GPU_Image* image)
266 {
267  // Bind the texture to which subsequent calls refer
268  if(image != ((GPU_CONTEXT_DATA*)renderer->current_context_target->context->data)->last_image)
269  {
270  GLuint handle = ((GPU_IMAGE_DATA*)image->data)->handle;
271  renderer->FlushBlitBuffer(renderer);
272 
273  glBindTexture( GL_TEXTURE_2D, handle );
274  ((GPU_CONTEXT_DATA*)renderer->current_context_target->context->data)->last_image = image;
275  }
276 }
277 
279 {
280  // Bind the texture to which subsequent calls refer
281  renderer->FlushBlitBuffer(renderer);
282 
283  glBindTexture( GL_TEXTURE_2D, handle );
284  ((GPU_CONTEXT_DATA*)renderer->current_context_target->context->data)->last_image = NULL;
285 }
286 
287 // Returns false if it can't be bound
289 {
291  {
292  // Bind the FBO
293  if(target != ((GPU_CONTEXT_DATA*)renderer->current_context_target->context->data)->last_target)
294  {
295  GLuint handle = 0;
296  if(target != NULL)
297  handle = ((GPU_TARGET_DATA*)target->data)->handle;
298  renderer->FlushBlitBuffer(renderer);
299 
300  extBindFramebuffer(renderer, handle);
301  ((GPU_CONTEXT_DATA*)renderer->current_context_target->context->data)->last_target = target;
302  }
303  return 1;
304  }
305  else
306  {
307  // There's only one possible render target, the default framebuffer.
308  // Note: Could check against the default framebuffer value (((GPU_TARGET_DATA*)target->data)->handle versus result of GL_FRAMEBUFFER_BINDING)...
309  if(target != NULL)
310  {
311  ((GPU_CONTEXT_DATA*)renderer->current_context_target->context->data)->last_target = target;
312  return 1;
313  }
314  return 0;
315  }
316 }
317 
319 {
320  // Bind the FBO
321  renderer->FlushBlitBuffer(renderer);
322 
323  extBindFramebuffer(renderer, handle);
324  ((GPU_CONTEXT_DATA*)renderer->current_context_target->context->data)->last_target = NULL;
325 }
326 
328 {
329  if(image == ((GPU_CONTEXT_DATA*)renderer->current_context_target->context->data)->last_image)
330  {
331  renderer->FlushBlitBuffer(renderer);
332  }
333 }
334 
336 {
337  if(image == ((GPU_CONTEXT_DATA*)renderer->current_context_target->context->data)->last_image)
338  {
339  renderer->FlushBlitBuffer(renderer);
340  ((GPU_CONTEXT_DATA*)renderer->current_context_target->context->data)->last_image = NULL;
341  }
342 }
343 
345 {
346  return (target == ((GPU_CONTEXT_DATA*)renderer->current_context_target->context->data)->last_target
347  || ((GPU_CONTEXT_DATA*)renderer->current_context_target->context->data)->last_target == NULL);
348 }
349 
351 {
352  if(target == ((GPU_CONTEXT_DATA*)renderer->current_context_target->context->data)->last_target
353  || ((GPU_CONTEXT_DATA*)renderer->current_context_target->context->data)->last_target == NULL)
354  {
355  renderer->FlushBlitBuffer(renderer);
356  ((GPU_CONTEXT_DATA*)renderer->current_context_target->context->data)->last_target = NULL;
357  }
358 }
359 
360 static Uint8 growBlitBuffer(GPU_CONTEXT_DATA* cdata, unsigned int minimum_vertices_needed)
361 {
362  unsigned int new_max_num_vertices;
363  float* new_buffer;
364 
365  if(minimum_vertices_needed <= cdata->blit_buffer_max_num_vertices)
366  return 1;
367  if(cdata->blit_buffer_max_num_vertices == GPU_BLIT_BUFFER_ABSOLUTE_MAX_VERTICES)
368  return 0;
369 
370  // Calculate new size (in vertices)
371  new_max_num_vertices = ((unsigned int)cdata->blit_buffer_max_num_vertices) * 2;
372  while(new_max_num_vertices <= minimum_vertices_needed)
373  new_max_num_vertices *= 2;
374 
375  if(new_max_num_vertices > GPU_BLIT_BUFFER_ABSOLUTE_MAX_VERTICES)
376  new_max_num_vertices = GPU_BLIT_BUFFER_ABSOLUTE_MAX_VERTICES;
377 
378  //GPU_LogError("Growing to %d vertices\n", new_max_num_vertices);
379  // Resize the blit buffer
380  new_buffer = (float*)malloc(new_max_num_vertices * GPU_BLIT_BUFFER_STRIDE);
381  memcpy(new_buffer, cdata->blit_buffer, cdata->blit_buffer_num_vertices * GPU_BLIT_BUFFER_STRIDE);
382  free(cdata->blit_buffer);
383  cdata->blit_buffer = new_buffer;
384  cdata->blit_buffer_max_num_vertices = new_max_num_vertices;
385 
386  #ifdef SDL_GPU_USE_GL_TIER3
387  // Resize the VBOs
388  #if !defined(SDL_GPU_NO_VAO)
389  glBindVertexArray(cdata->blit_VAO);
390  #endif
391 
392  glBindBuffer(GL_ARRAY_BUFFER, cdata->blit_VBO[0]);
393  glBufferData(GL_ARRAY_BUFFER, GPU_BLIT_BUFFER_STRIDE * cdata->blit_buffer_max_num_vertices, NULL, GL_STREAM_DRAW);
394  glBindBuffer(GL_ARRAY_BUFFER, cdata->blit_VBO[1]);
395  glBufferData(GL_ARRAY_BUFFER, GPU_BLIT_BUFFER_STRIDE * cdata->blit_buffer_max_num_vertices, NULL, GL_STREAM_DRAW);
396 
397  #if !defined(SDL_GPU_NO_VAO)
399  #endif
400  #endif
401 
402  return 1;
403 }
404 
405 static Uint8 growIndexBuffer(GPU_CONTEXT_DATA* cdata, unsigned int minimum_vertices_needed)
406 {
407  unsigned int new_max_num_vertices;
408  unsigned short* new_indices;
409 
410  if(minimum_vertices_needed <= cdata->index_buffer_max_num_vertices)
411  return 1;
412  if(cdata->index_buffer_max_num_vertices == GPU_INDEX_BUFFER_ABSOLUTE_MAX_VERTICES)
413  return 0;
414 
415  // Calculate new size (in vertices)
416  new_max_num_vertices = cdata->index_buffer_max_num_vertices * 2;
417  while(new_max_num_vertices <= minimum_vertices_needed)
418  new_max_num_vertices *= 2;
419 
420  if(new_max_num_vertices > GPU_INDEX_BUFFER_ABSOLUTE_MAX_VERTICES)
421  new_max_num_vertices = GPU_INDEX_BUFFER_ABSOLUTE_MAX_VERTICES;
422 
423  //GPU_LogError("Growing to %d indices\n", new_max_num_vertices);
424  // Resize the index buffer
425  new_indices = (unsigned short*)malloc(new_max_num_vertices * sizeof(unsigned short));
426  memcpy(new_indices, cdata->index_buffer, cdata->index_buffer_num_vertices * sizeof(unsigned short));
427  free(cdata->index_buffer);
428  cdata->index_buffer = new_indices;
429  cdata->index_buffer_max_num_vertices = new_max_num_vertices;
430 
431  return 1;
432 }
433 
434 
435 // Only for window targets, which have their own contexts.
437 {
438  if(target == NULL || target->context == NULL || renderer->current_context_target == target)
439  return;
440 
441  renderer->FlushBlitBuffer(renderer);
442 
443  #ifdef SDL_GPU_USE_SDL2
444  SDL_GL_MakeCurrent(SDL_GetWindowFromID(target->context->windowID), target->context->context);
445  renderer->current_context_target = target;
446  #endif
447 }
448 
449 static void setClipRect(GPU_Renderer* renderer, GPU_Target* target)
450 {
451  if(target->use_clip_rect)
452  {
453  GPU_Target* context_target = renderer->current_context_target;
455  if(target->context != NULL)
456  {
457  int y = context_target->h - (target->clip_rect.y + target->clip_rect.h);
458  float xFactor = ((float)context_target->context->window_w)/context_target->w;
459  float yFactor = ((float)context_target->context->window_h)/context_target->h;
460  glScissor(target->clip_rect.x * xFactor, y * yFactor, target->clip_rect.w * xFactor, target->clip_rect.h * yFactor);
461  }
462  else
463  glScissor(target->clip_rect.x, target->clip_rect.y, target->clip_rect.w, target->clip_rect.h);
464  }
465 }
466 
467 static void unsetClipRect(GPU_Renderer* renderer, GPU_Target* target)
468 {
469  if(target->use_clip_rect)
471 }
472 
474 {
475  // Set up the camera
476  renderer->SetCamera(renderer, target, &target->camera);
477 
478  setClipRect(renderer, target);
479 }
480 
481 
482 
483 static void changeColor(GPU_Renderer* renderer, SDL_Color color)
484 {
485  #ifdef SDL_GPU_USE_GL_TIER3
486  return;
487  #else
489  if(cdata->last_color.r != color.r
490  || cdata->last_color.g != color.g
491  || cdata->last_color.b != color.b
492  || GET_ALPHA(cdata->last_color) != GET_ALPHA(color))
493  {
494  renderer->FlushBlitBuffer(renderer);
495  cdata->last_color = color;
496  glColor4f(color.r/255.01f, color.g/255.01f, color.b/255.01f, GET_ALPHA(color)/255.01f);
497  }
498  #endif
499 }
500 
501 static void changeBlending(GPU_Renderer* renderer, Uint8 enable)
502 {
504  if(cdata->last_use_blending == enable)
505  return;
506 
507  renderer->FlushBlitBuffer(renderer);
508 
509  if(enable)
511  else
513 
514  cdata->last_use_blending = enable;
515 }
516 
518 {
520  if(cdata->last_blend_mode.source_color == mode.source_color
521  && cdata->last_blend_mode.dest_color == mode.dest_color
522  && cdata->last_blend_mode.source_alpha == mode.source_alpha
523  && cdata->last_blend_mode.dest_alpha == mode.dest_alpha
524  && cdata->last_blend_mode.color_equation == mode.color_equation
525  && cdata->last_blend_mode.alpha_equation == mode.alpha_equation)
526  return;
527 
528  renderer->FlushBlitBuffer(renderer);
529 
530  cdata->last_blend_mode = mode;
531 
532  if(mode.source_color == mode.source_alpha && mode.dest_color == mode.dest_alpha)
533  {
534  glBlendFunc(mode.source_color, mode.dest_color);
535  }
537  {
539  }
540  else
541  {
542  GPU_PushErrorCode("(SDL_gpu internal)", GPU_ERROR_BACKEND_ERROR, "Could not set blend function because GPU_FEATURE_BLEND_FUNC_SEPARATE is not supported.");
543  }
544 
546  {
547  if(mode.color_equation == mode.alpha_equation)
551  else
552  {
553  GPU_PushErrorCode("(SDL_gpu internal)", GPU_ERROR_BACKEND_ERROR, "Could not set blend equation because GPU_FEATURE_BLEND_EQUATIONS_SEPARATE is not supported.");
554  }
555  }
556  else
557  {
558  GPU_PushErrorCode("(SDL_gpu internal)", GPU_ERROR_BACKEND_ERROR, "Could not set blend equation because GPU_FEATURE_BLEND_EQUATIONS is not supported.");
559  }
560 }
561 
562 
563 // If 0 is returned, there is no valid shader.
564 static Uint32 get_proper_program_id(GPU_Renderer* renderer, Uint32 program_object)
565 {
566  GPU_Context* context = renderer->current_context_target->context;
567  if(context->default_textured_shader_program == 0) // No shaders loaded!
568  return 0;
569 
570  if(program_object == 0)
571  return context->default_textured_shader_program;
572 
573  return program_object;
574 }
575 
576 
577 
578 static void applyTexturing(GPU_Renderer* renderer)
579 {
580  GPU_Context* context = renderer->current_context_target->context;
581  if(context->use_texturing != ((GPU_CONTEXT_DATA*)context->data)->last_use_texturing)
582  {
583  ((GPU_CONTEXT_DATA*)context->data)->last_use_texturing = context->use_texturing;
584  if(context->use_texturing)
586  else
588  }
589 }
590 
591 static void changeTexturing(GPU_Renderer* renderer, Uint8 enable)
592 {
593  GPU_Context* context = renderer->current_context_target->context;
594  if(enable != ((GPU_CONTEXT_DATA*)context->data)->last_use_texturing)
595  {
596  renderer->FlushBlitBuffer(renderer);
597 
598  ((GPU_CONTEXT_DATA*)context->data)->last_use_texturing = enable;
599  if(enable)
601  else
603  }
604 }
605 
606 static void enableTexturing(GPU_Renderer* renderer)
607 {
609  {
610  renderer->FlushBlitBuffer(renderer);
612  }
613 }
614 
615 static void disableTexturing(GPU_Renderer* renderer)
616 {
618  {
619  renderer->FlushBlitBuffer(renderer);
621  }
622 }
623 
624 #define MIX_COLOR_COMPONENT_NORMALIZED_RESULT(a, b) ((a)/255.0f * (b)/255.0f)
625 #define MIX_COLOR_COMPONENT(a, b) (((a)/255.0f * (b)/255.0f)*255)
626 #define MIX_COLORS(color1, color2) {MIX_COLOR_COMPONENT(color1.r, color2.r), MIX_COLOR_COMPONENT(color1.g, color2.g), MIX_COLOR_COMPONENT(color1.b, color2.b), MIX_COLOR_COMPONENT(GET_ALPHA(color1), GET_ALPHA(color2))}
627 
629 {
630  GPU_Context* context = renderer->current_context_target->context;
631 
632  enableTexturing(renderer);
633  if(GL_TRIANGLES != ((GPU_CONTEXT_DATA*)context->data)->last_shape)
634  {
635  renderer->FlushBlitBuffer(renderer);
636  ((GPU_CONTEXT_DATA*)context->data)->last_shape = GL_TRIANGLES;
637  }
638 
639  // Blitting
640  if(target->use_color)
641  {
642  SDL_Color color = MIX_COLORS(target->color, image->color);
643  changeColor(renderer, color);
644  }
645  else
646  changeColor(renderer, image->color);
647  changeBlending(renderer, image->use_blending);
648  changeBlendMode(renderer, image->blend_mode);
649 
650  // If we're using the untextured shader, switch it.
652  renderer->ActivateShaderProgram(renderer, context->default_textured_shader_program, NULL);
653 }
654 
655 static void prepareToRenderShapes(GPU_Renderer* renderer, unsigned int shape)
656 {
657  GPU_Context* context = renderer->current_context_target->context;
658 
659  disableTexturing(renderer);
660  if(shape != ((GPU_CONTEXT_DATA*)context->data)->last_shape)
661  {
662  renderer->FlushBlitBuffer(renderer);
663  ((GPU_CONTEXT_DATA*)context->data)->last_shape = shape;
664  }
665 
666  // Shape rendering
667  // Color is set elsewhere for shapes
668  changeBlending(renderer, context->shapes_use_blending);
669  changeBlendMode(renderer, context->shapes_blend_mode);
670 
671  // If we're using the textured shader, switch it.
673  renderer->ActivateShaderProgram(renderer, context->default_untextured_shader_program, NULL);
674 }
675 
676 
677 
679 {
681  GPU_Rect viewport = target->viewport;
682  float y;
683 
684  if(cdata->last_viewport.x == viewport.x && cdata->last_viewport.y == viewport.y && cdata->last_viewport.w == viewport.w && cdata->last_viewport.h == viewport.h)
685  return;
686  cdata->last_viewport = viewport;
687 
688  // Need the real height to flip the y-coord (from OpenGL coord system)
689  y = viewport.y;
690  if(target->image != NULL)
691  y = target->image->h - viewport.h - viewport.y;
692  else if(target->context != NULL)
693  y = target->context->window_h - viewport.h - viewport.y;
694 
695  glViewport(viewport.x, y, viewport.w, viewport.h);
696 }
697 
699 {
701  Uint8 invert = (target->image != NULL);
702  float offsetX, offsetY;
703 
704  cdata->last_camera = target->camera;
705 
706  cdata->last_camera_inverted = invert;
707 
710 
711  if(!invert)
712  GPU_Ortho(target->camera.x, target->w + target->camera.x, target->h + target->camera.y, target->camera.y, -1.0f, 1.0f);
713  else
714  GPU_Ortho(target->camera.x, target->w + target->camera.x, target->camera.y, target->h + target->camera.y, -1.0f, 1.0f); // Special inverted orthographic projection because tex coords are inverted already for render-to-texture
715 
718 
719 
720  offsetX = target->w/2.0f;
721  offsetY = target->h/2.0f;
722  GPU_Translate(offsetX, offsetY, 0);
723  GPU_Rotate(target->camera.angle, 0, 0, 1);
724  GPU_Translate(-offsetX, -offsetY, 0);
725 
726  GPU_Translate(target->camera.x + offsetX, target->camera.y + offsetY, 0);
727  GPU_Scale(target->camera.zoom, target->camera.zoom, 1.0f);
728  GPU_Translate(-target->camera.x - offsetX, -target->camera.y - offsetY, 0);
729 }
730 
732 {
733  return (a.x == b.x && a.y == b.y && a.z == b.z && a.angle == b.angle && a.zoom == b.zoom);
734 }
735 
737 {
738  //GPU_CONTEXT_DATA* cdata = (GPU_CONTEXT_DATA*)GPU_GetContextTarget()->context->data;
739 
740  //if(cdata->last_camera_target != target || !equal_cameras(cdata->last_camera, target->camera))
741  {
742  applyTargetCamera(target);
743  }
744 }
745 
746 #ifdef SDL_GPU_APPLY_TRANSFORMS_TO_GL_STACK
747 static void applyTransforms(void)
748 {
749  float* p = GPU_GetProjection();
750  float* m = GPU_GetModelView();
752  glLoadMatrixf(p);
754  glLoadMatrixf(m);
755 }
756 #endif
757 
758 
759 // Workaround for Intel HD glVertexAttrib() bug.
760 #ifdef SDL_GPU_USE_OPENGL
761 // FIXME: This should probably exist in context storage, as I expect it to be a problem across contexts.
762 static Uint8 apply_Intel_attrib_workaround = 0;
763 static Uint8 vendor_is_Intel = 0;
764 #endif
765 
766 static GPU_Target* Init(GPU_Renderer* renderer, GPU_RendererID renderer_request, Uint16 w, Uint16 h, GPU_WindowFlagEnum SDL_flags)
767 {
768  GPU_InitFlagEnum GPU_flags;
769 #ifdef SDL_GPU_USE_SDL2
770  SDL_Window* window;
771 #else
772  SDL_Surface* screen;
773 #endif
774 
775 #ifdef SDL_GPU_USE_OPENGL
776  const char* vendor_string;
777 #endif
778 
779  if(renderer_request.major_version < 1)
780  {
781  renderer_request.major_version = 1;
782  renderer_request.minor_version = 1;
783  }
784 
785  GPU_flags = GPU_GetPreInitFlags();
786  // Tell SDL what we want.
787  renderer->GPU_init_flags = GPU_flags;
788  if(GPU_flags & GPU_INIT_DISABLE_DOUBLE_BUFFER)
789  SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 0);
790  else
791  SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
792 #ifdef SDL_GPU_USE_SDL2
793  #ifdef SDL_GPU_USE_GLES
794  SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
795  #endif
796  SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, renderer_request.major_version);
797  SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, renderer_request.minor_version);
798 #else
799  if(!(GPU_flags & GPU_INIT_DISABLE_VSYNC))
800  SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1);
801 #endif
802 
803  SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
804 
805  SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
806  SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
807  SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
808  SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
809 
810  renderer->requested_id = renderer_request;
811 
812 #ifdef SDL_GPU_USE_SDL2
813 
814  window = NULL;
815  // Is there a window already set up that we are supposed to use?
816  if(renderer->current_context_target != NULL)
817  window = SDL_GetWindowFromID(renderer->current_context_target->context->windowID);
818  else
819  window = SDL_GetWindowFromID(GPU_GetInitWindow());
820 
821  if(window == NULL)
822  {
823  // Set up window flags
824  SDL_flags |= SDL_WINDOW_OPENGL;
825  if(!(SDL_flags & SDL_WINDOW_HIDDEN))
826  SDL_flags |= SDL_WINDOW_SHOWN;
827 
828  renderer->SDL_init_flags = SDL_flags;
829  window = SDL_CreateWindow("",
830  SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
831  w, h,
832  SDL_flags);
833 
834  if(window == NULL)
835  {
836  GPU_PushErrorCode("GPU_Init", GPU_ERROR_BACKEND_ERROR, "Window creation failed.");
837  return NULL;
838  }
839 
840  GPU_SetInitWindow(SDL_GetWindowID(window));
841  }
842  else
843  renderer->SDL_init_flags = SDL_flags;
844 
845 #else
846  SDL_flags |= SDL_OPENGL;
847  renderer->SDL_init_flags = SDL_flags;
848  screen = SDL_SetVideoMode(w, h, 0, SDL_flags);
849 
850  if(screen == NULL)
851  return NULL;
852 #endif
853 
854  renderer->enabled_features = 0xFFFFFFFF; // Pretend to support them all if using incompatible headers
855 
856 
857  // Create or re-init the current target. This also creates the GL context and initializes enabled_features.
858  #ifdef SDL_GPU_USE_SDL2
859  if(renderer->CreateTargetFromWindow(renderer, SDL_GetWindowID(window), renderer->current_context_target) == NULL)
860  return NULL;
861  #else
862  if(renderer->CreateTargetFromWindow(renderer, 0, renderer->current_context_target) == NULL)
863  return NULL;
864  #endif
865 
866  // If the dimensions of the window don't match what we asked for, then set up a virtual resolution to pretend like they are.
867  if(w != 0 && h != 0 && (w != renderer->current_context_target->w || h != renderer->current_context_target->h))
868  renderer->SetVirtualResolution(renderer, renderer->current_context_target, w, h);
869 
870  // Init glVertexAttrib workaround
871  #ifdef SDL_GPU_USE_OPENGL
872  vendor_string = (const char*)glGetString(GL_VENDOR);
873  if(strstr(vendor_string, "Intel") != NULL)
874  {
875  vendor_is_Intel = 1;
876  apply_Intel_attrib_workaround = 1;
877  }
878  #endif
879 
880  return renderer->current_context_target;
881 }
882 
883 
884 static Uint8 IsFeatureEnabled(GPU_Renderer* renderer, GPU_FeatureEnum feature)
885 {
886  return ((renderer->enabled_features & feature) == feature);
887 }
888 
889 
890 static GPU_Target* CreateTargetFromWindow(GPU_Renderer* renderer, Uint32 windowID, GPU_Target* target)
891 {
892  Uint8 created = 0; // Make a new one or repurpose an existing target?
893  GPU_CONTEXT_DATA* cdata;
894 #ifdef SDL_GPU_USE_SDL2
895  SDL_Window* window;
896 #else
897  SDL_Surface* screen;
898 #endif
899  int framebuffer_handle;
900  SDL_Color white = { 255, 255, 255, 255 };
901 #ifdef SDL_GPU_USE_OPENGL
902  GLenum err;
903 #endif
904  const char* version_string;
905  GPU_FeatureEnum required_features;
906 #ifndef SDL_GPU_DISABLE_SHADERS
907  Uint32 v, f, p;
908 #endif
909 
910  if(target == NULL)
911  {
912  int blit_buffer_storage_size;
913  int index_buffer_storage_size;
914 
915  created = 1;
916  target = (GPU_Target*)malloc(sizeof(GPU_Target));
917  memset(target, 0, sizeof(GPU_Target));
918  target->refcount = 1;
919  target->is_alias = 0;
920  target->data = (GPU_TARGET_DATA*)malloc(sizeof(GPU_TARGET_DATA));
921  memset(target->data, 0, sizeof(GPU_TARGET_DATA));
922  ((GPU_TARGET_DATA*)target->data)->refcount = 1;
923  target->image = NULL;
924  target->context = (GPU_Context*)malloc(sizeof(GPU_Context));
925  memset(target->context, 0, sizeof(GPU_Context));
926  cdata = (GPU_CONTEXT_DATA*)malloc(sizeof(GPU_CONTEXT_DATA));
927  memset(cdata, 0, sizeof(GPU_CONTEXT_DATA));
928  target->context->data = cdata;
929  target->context->context = NULL;
930 
931  cdata->last_image = NULL;
932  cdata->last_target = NULL;
933  // Initialize the blit buffer
934  cdata->blit_buffer_max_num_vertices = GPU_BLIT_BUFFER_INIT_MAX_NUM_VERTICES;
935  cdata->blit_buffer_num_vertices = 0;
937  cdata->blit_buffer = (float*)malloc(blit_buffer_storage_size);
938  cdata->index_buffer_max_num_vertices = GPU_BLIT_BUFFER_INIT_MAX_NUM_VERTICES;
939  cdata->index_buffer_num_vertices = 0;
940  index_buffer_storage_size = GPU_BLIT_BUFFER_INIT_MAX_NUM_VERTICES*sizeof(unsigned short);
941  cdata->index_buffer = (unsigned short*)malloc(index_buffer_storage_size);
942  }
943  else
944  {
946  cdata = (GPU_CONTEXT_DATA*)target->context->data;
947  }
948 
949  #ifdef SDL_GPU_USE_SDL2
950 
951  window = SDL_GetWindowFromID(windowID);
952  if(window == NULL)
953  {
954  if(created)
955  {
956  free(cdata->blit_buffer);
957  free(cdata->index_buffer);
958  free(target->context->data);
959  free(target->context);
960  free(target->data);
961  free(target);
962  }
963  return NULL;
964  }
965 
966  // Store the window info
967  SDL_GetWindowSize(window, &target->context->window_w, &target->context->window_h);
968  target->context->stored_window_w = target->context->window_w;
969  target->context->stored_window_h = target->context->window_h;
970  target->context->windowID = SDL_GetWindowID(window);
971 
972  // Make a new context if needed and make it current
973  if(created || target->context->context == NULL)
974  {
975  target->context->context = SDL_GL_CreateContext(window);
976  renderer->current_context_target = target;
977  GPU_AddWindowMapping(target);
978  }
979  else
980  renderer->MakeCurrent(renderer, target, target->context->windowID);
981 
982  #else
983 
984  screen = SDL_GetVideoSurface();
985  if(screen == NULL)
986  {
987  if(created)
988  {
989  free(cdata->blit_buffer);
990  free(cdata->index_buffer);
991  free(target->context->data);
992  free(target->context);
993  free(target->data);
994  free(target);
995  }
996  return NULL;
997  }
998 
999  target->context->windowID = 1;
1000  target->context->window_w = screen->w;
1001  target->context->window_h = screen->h;
1002  target->context->stored_window_w = target->context->window_w;
1003  target->context->stored_window_h = target->context->window_h;
1004 
1005  renderer->MakeCurrent(renderer, target, target->context->windowID);
1006 
1007  #endif
1008 
1009  framebuffer_handle = 0;
1010  glGetIntegerv(GL_FRAMEBUFFER_BINDING, &framebuffer_handle);
1011  ((GPU_TARGET_DATA*)target->data)->handle = framebuffer_handle;
1012  ((GPU_TARGET_DATA*)target->data)->format = GL_RGBA;
1013 
1014  target->renderer = renderer;
1015  target->w = target->context->window_w;
1016  target->h = target->context->window_h;
1017 
1018  target->use_clip_rect = 0;
1019  target->clip_rect.x = 0;
1020  target->clip_rect.y = 0;
1021  target->clip_rect.w = target->w;
1022  target->clip_rect.h = target->h;
1023  target->use_color = 0;
1024 
1025  target->viewport = GPU_MakeRect(0, 0, target->context->window_w, target->context->window_h);
1026  target->camera = GPU_GetDefaultCamera();
1027 
1028  target->context->line_thickness = 1.0f;
1029  target->context->use_texturing = 1;
1030  target->context->shapes_use_blending = 1;
1032 
1033  cdata->last_color = white;
1034 
1035  cdata->last_use_texturing = 1;
1036  cdata->last_shape = GL_TRIANGLES;
1038 
1039  cdata->last_use_blending = 0;
1040  cdata->last_blend_mode = GPU_GetBlendModeFromPreset(GPU_BLEND_NORMAL);
1041 
1042  cdata->last_viewport = target->viewport;
1043  cdata->last_camera = target->camera; // Redundant due to applyTargetCamera(), below
1044  cdata->last_camera_inverted = 0;
1045 
1046  #ifdef SDL_GPU_USE_OPENGL
1047  err = glewInit();
1048  if (GLEW_OK != err)
1049  {
1050  // Probably don't have the right GL version for this renderer
1051  target->context->failed = 1;
1052  return NULL;
1053  }
1054  #endif
1055 
1056 
1057  // Update our renderer info from the current GL context.
1058  #ifdef SDL_GPU_USE_OPENGL
1059  // OpenGL < 3.0 doesn't have GL_MAJOR_VERSION. Check via version string instead.
1060  version_string = (const char*)glGetString(GL_VERSION);
1061  if(sscanf(version_string, "%d.%d", &renderer->id.major_version, &renderer->id.minor_version) <= 0)
1062  {
1064  #if SDL_GPU_GL_MAJOR_VERSION != 3
1065  renderer->id.minor_version = 1;
1066  #else
1067  renderer->id.minor_version = 0;
1068  #endif
1069 
1070  GPU_PushErrorCode("GPU_CreateTargetFromWindow", GPU_ERROR_BACKEND_ERROR, "Failed to parse OpenGL version string: \"%s\"", version_string);
1071  }
1072  #else
1073  // GLES doesn't have GL_MAJOR_VERSION. Check via version string instead.
1074  version_string = (const char*)glGetString(GL_VERSION);
1075  // OpenGL ES 2.0?
1076  if(sscanf(version_string, "OpenGL ES %d.%d", &renderer->id.major_version, &renderer->id.minor_version) <= 0)
1077  {
1078  // OpenGL ES-CM 1.1? OpenGL ES-CL 1.1?
1079  if(sscanf(version_string, "OpenGL ES-C%*c %d.%d", &renderer->id.major_version, &renderer->id.minor_version) <= 0)
1080  {
1082  #if SDL_GPU_GLES_MAJOR_VERSION == 1
1083  renderer->id.minor_version = 1;
1084  #else
1085  renderer->id.minor_version = 0;
1086  #endif
1087 
1088  GPU_PushErrorCode("GPU_CreateTargetFromWindow", GPU_ERROR_BACKEND_ERROR, "Failed to parse OpenGL version string: \"%s\"", version_string);
1089  }
1090  }
1091  #endif
1092 
1093  // Did the wrong runtime library try to use a later versioned renderer?
1094  if(renderer->id.major_version < renderer->requested_id.major_version)
1095  {
1096  #ifdef SDL_GPU_USE_GLES
1097  GPU_PushErrorCode("GPU_CreateTargetFromWindow", GPU_ERROR_BACKEND_ERROR, "Renderer version (%d) is incompatible with the available OpenGL runtime library version (%d).", renderer->requested_id.major_version, renderer->id.major_version);
1098  #endif
1099  target->context->failed = 1;
1100  return NULL;
1101  }
1102 
1103  init_features(renderer);
1104 
1105  required_features = (renderer->GPU_init_flags & GPU_FEATURE_MASK);
1106  if(!renderer->IsFeatureEnabled(renderer, required_features))
1107  {
1108  GPU_PushErrorCode("GPU_CreateTargetFromWindow", GPU_ERROR_BACKEND_ERROR, "Renderer does not support required features.");
1109  target->context->failed = 1;
1110  return NULL;
1111  }
1112 
1113  #ifdef SDL_GPU_USE_SDL2
1114  // No preference for vsync?
1116  {
1117  // Default to late swap vsync if available
1118  if(SDL_GL_SetSwapInterval(-1) < 0)
1119  SDL_GL_SetSwapInterval(1); // Or go for vsync
1120  }
1121  else if(renderer->GPU_init_flags & GPU_INIT_ENABLE_VSYNC)
1122  SDL_GL_SetSwapInterval(1);
1123  else if(renderer->GPU_init_flags & GPU_INIT_DISABLE_VSYNC)
1124  SDL_GL_SetSwapInterval(0);
1125  #endif
1126 
1127  // Set up GL state
1128 
1129  target->context->projection_matrix.size = 1;
1131 
1132  target->context->modelview_matrix.size = 1;
1134 
1135  target->context->matrix_mode = GPU_MODELVIEW;
1136 
1137  // Modes
1140 
1142  glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
1143 
1144  // Viewport and Framebuffer
1145  glViewport(0.0f, 0.0f, target->viewport.w, target->viewport.h);
1146 
1148  #if SDL_GPU_GL_TIER < 3
1149  glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1150  #endif
1151 
1152  // Set up camera
1153  applyTargetCamera(target);
1154 
1155  renderer->SetLineThickness(renderer, 1.0f);
1156 
1157 
1160  target->context->current_shader_program = 0;
1161 
1162  #ifndef SDL_GPU_DISABLE_SHADERS
1163  // Load default shaders
1164 
1165  // Textured shader
1167 
1168  if(!v)
1169  {
1170  GPU_PushErrorCode("GPU_CreateTargetFromWindow", GPU_ERROR_BACKEND_ERROR, "Failed to load default textured vertex shader.");
1171  target->context->failed = 1;
1172  return NULL;
1173  }
1174 
1176 
1177  if(!f)
1178  {
1179  GPU_PushErrorCode("GPU_CreateTargetFromWindow", GPU_ERROR_BACKEND_ERROR, "Failed to load default textured fragment shader.");
1180  target->context->failed = 1;
1181  return NULL;
1182  }
1183 
1184  p = renderer->LinkShaders(renderer, v, f);
1185 
1186  if(!p)
1187  {
1188  GPU_PushErrorCode("GPU_CreateTargetFromWindow", GPU_ERROR_BACKEND_ERROR, "Failed to link default textured shader program.");
1189  target->context->failed = 1;
1190  return NULL;
1191  }
1192 
1194 
1195  #ifdef SDL_GPU_USE_GL_TIER3
1196  // Get locations of the attributes in the shader
1197  cdata->shader_block[0] = GPU_LoadShaderBlock(p, "gpu_Vertex", "gpu_TexCoord", "gpu_Color", "gpu_ModelViewProjectionMatrix");
1198  #endif
1199 
1200  // Untextured shader
1202 
1203  if(!v)
1204  {
1205  GPU_PushErrorCode("GPU_CreateTargetFromWindow", GPU_ERROR_BACKEND_ERROR, "Failed to load default untextured vertex shader.");
1206  target->context->failed = 1;
1207  return NULL;
1208  }
1209 
1211 
1212  if(!f)
1213  {
1214  GPU_PushErrorCode("GPU_CreateTargetFromWindow", GPU_ERROR_BACKEND_ERROR, "Failed to load default untextured fragment shader.");
1215  target->context->failed = 1;
1216  return NULL;
1217  }
1218 
1219  p = renderer->LinkShaders(renderer, v, f);
1220 
1221  if(!p)
1222  {
1223  GPU_PushErrorCode("GPU_CreateTargetFromWindow", GPU_ERROR_BACKEND_ERROR, "Failed to link default untextured shader program.");
1224  target->context->failed = 1;
1225  return NULL;
1226  }
1227 
1228  glUseProgram(p);
1229 
1231 
1232  #ifdef SDL_GPU_USE_GL_TIER3
1233  // Get locations of the attributes in the shader
1234  cdata->shader_block[1] = GPU_LoadShaderBlock(p, "gpu_Vertex", NULL, "gpu_Color", "gpu_ModelViewProjectionMatrix");
1235  GPU_SetShaderBlock(cdata->shader_block[1]);
1236 
1237  // Create vertex array container and buffer
1238  #if !defined(SDL_GPU_NO_VAO)
1239  glGenVertexArrays(1, &cdata->blit_VAO);
1240  glBindVertexArray(cdata->blit_VAO);
1241  #endif
1242 
1243  glGenBuffers(2, cdata->blit_VBO);
1244  // Create space on the GPU
1245  glBindBuffer(GL_ARRAY_BUFFER, cdata->blit_VBO[0]);
1246  glBufferData(GL_ARRAY_BUFFER, GPU_BLIT_BUFFER_STRIDE * cdata->blit_buffer_max_num_vertices, NULL, GL_STREAM_DRAW);
1247  glBindBuffer(GL_ARRAY_BUFFER, cdata->blit_VBO[1]);
1248  glBufferData(GL_ARRAY_BUFFER, GPU_BLIT_BUFFER_STRIDE * cdata->blit_buffer_max_num_vertices, NULL, GL_STREAM_DRAW);
1249  cdata->blit_VBO_flop = 0;
1250 
1251  glGenBuffers(16, cdata->attribute_VBO);
1252 
1253  // Init 16 attributes to 0 / NULL.
1254  memset(cdata->shader_attributes, 0, 16*sizeof(GPU_AttributeSource));
1255  #endif
1256  #endif
1257 
1258 
1259  return target;
1260 }
1261 
1262 
1264 {
1265  GPU_Target* result;
1266 
1267  if(target == NULL)
1268  return NULL;
1269 
1270  result = (GPU_Target*)malloc(sizeof(GPU_Target));
1271 
1272  // Copy the members
1273  *result = *target;
1274 
1275  // Alias info
1276  if(target->image != NULL)
1277  target->image->refcount++;
1278  ((GPU_TARGET_DATA*)target->data)->refcount++;
1279  result->refcount = 1;
1280  result->is_alias = 1;
1281 
1282  return result;
1283 }
1284 
1285 static void MakeCurrent(GPU_Renderer* renderer, GPU_Target* target, Uint32 windowID)
1286 {
1287 #ifdef SDL_GPU_USE_SDL2
1288  SDL_GLContext c;
1289 #else
1290  SDL_Surface* screen;
1291 #endif
1292 
1293  if(target == NULL)
1294  return;
1295  #ifdef SDL_GPU_USE_SDL2
1296  if(target->image != NULL)
1297  return;
1298 
1299  c = target->context->context;
1300  if(c != NULL)
1301  {
1302  renderer->current_context_target = target;
1303  SDL_GL_MakeCurrent(SDL_GetWindowFromID(windowID), c);
1304  // Reset camera if the target's window was changed
1305  if(target->context->windowID != windowID)
1306  {
1307  SDL_Window* window;
1308 
1309  renderer->FlushBlitBuffer(renderer);
1310 
1311  // Update the window mappings
1312  GPU_RemoveWindowMapping(windowID);
1313  // Don't remove the target's current mapping. That lets other windows refer to it.
1314  target->context->windowID = windowID;
1315  GPU_AddWindowMapping(target);
1316 
1317  // Update target's window size
1318  window = SDL_GetWindowFromID(windowID);
1319  if(window != NULL)
1320  SDL_GetWindowSize(window, &target->context->window_w, &target->context->window_h);
1321 
1322  // Reset the camera for this window
1324  }
1325  }
1326  #else
1327  renderer->current_context_target = target;
1328  // Only one window...
1330  target->context->windowID = 1;
1331  GPU_AddWindowMapping(target);
1332 
1333  // Update target's window size
1334  screen = SDL_GetVideoSurface();
1335  if(screen != NULL)
1336  {
1337  target->context->window_w = screen->w;
1338  target->context->window_h = screen->h;
1339  }
1340  #endif
1341 }
1342 
1343 
1344 static void SetAsCurrent(GPU_Renderer* renderer)
1345 {
1346  if(renderer->current_context_target == NULL)
1347  return;
1348 
1349  renderer->MakeCurrent(renderer, renderer->current_context_target, renderer->current_context_target->context->windowID);
1350 }
1351 
1352 static Uint8 SetWindowResolution(GPU_Renderer* renderer, Uint16 w, Uint16 h)
1353 {
1355 
1356  Uint8 isCurrent = isCurrentTarget(renderer, target);
1357  if(isCurrent)
1358  renderer->FlushBlitBuffer(renderer);
1359 
1360 #ifdef SDL_GPU_USE_SDL2
1361 
1362  SDL_SetWindowSize(SDL_GetWindowFromID(target->context->windowID), w, h);
1363  SDL_GetWindowSize(SDL_GetWindowFromID(target->context->windowID), &target->context->window_w, &target->context->window_h);
1364 
1365 #else
1366  SDL_Surface* surf = SDL_GetVideoSurface();
1367  Uint32 flags = surf->flags;
1368 
1369 
1370  SDL_Surface* screen = SDL_SetVideoMode(w, h, 0, flags);
1371  // There's a bug in SDL. This is a workaround. Let's resize again:
1372  screen = SDL_SetVideoMode(w, h, 0, flags);
1373 
1374  if(screen == NULL)
1375  return 0;
1376 
1377  target->context->window_w = screen->w;
1378  target->context->window_h = screen->h;
1379 
1380  // FIXME: Does the entire GL state need to be reset because the screen was recreated?
1381  // FIXME: This interferes with context state
1383  glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
1384 
1386 #endif
1387 
1388  // Store the resolution for fullscreen_desktop changes
1389  target->context->stored_window_w = target->context->window_w;
1390  target->context->stored_window_h = target->context->window_h;
1391 
1392  // Resets virtual resolution
1393  target->w = target->context->window_w;
1394  target->h = target->context->window_h;
1395 
1396  // Resets viewport
1397  target->viewport = GPU_MakeRect(0, 0, target->w, target->h);
1398  changeViewport(target);
1399 
1400  GPU_UnsetClip(target);
1401 
1402  if(isCurrent)
1403  applyTargetCamera(target);
1404 
1405  return 1;
1406 }
1407 
1408 static void SetVirtualResolution(GPU_Renderer* renderer, GPU_Target* target, Uint16 w, Uint16 h)
1409 {
1410  Uint8 isCurrent;
1411 
1412  if(target == NULL)
1413  return;
1414 
1415  isCurrent = isCurrentTarget(renderer, target);
1416  if(isCurrent)
1417  renderer->FlushBlitBuffer(renderer);
1418 
1419  target->w = w;
1420  target->h = h;
1421 
1422  if(isCurrent)
1423  applyTargetCamera(target);
1424 }
1425 
1427 {
1428  Uint8 isCurrent;
1429 
1430  if(target == NULL)
1431  return;
1432 
1433  isCurrent = isCurrentTarget(renderer, target);
1434  if(isCurrent)
1435  renderer->FlushBlitBuffer(renderer);
1436 
1437  if(target->image != NULL)
1438  {
1439  target->w = target->image->w;
1440  target->h = target->image->h;
1441  }
1442  else if(target->context != NULL)
1443  {
1444  target->w = target->context->window_w;
1445  target->h = target->context->window_h;
1446  }
1447 
1448  if(isCurrent)
1449  applyTargetCamera(target);
1450 }
1451 
1452 static void Quit(GPU_Renderer* renderer)
1453 {
1454  renderer->FreeTarget(renderer, renderer->current_context_target);
1455  renderer->current_context_target = NULL;
1456 }
1457 
1458 
1459 
1460 static Uint8 ToggleFullscreen(GPU_Renderer* renderer, Uint8 use_desktop_resolution)
1461 {
1462 #ifdef SDL_GPU_USE_SDL2
1464  Uint32 old_flags = SDL_GetWindowFlags(SDL_GetWindowFromID(target->context->windowID));
1465  Uint8 is_fullscreen = (old_flags & (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_FULLSCREEN_DESKTOP));
1466 
1467  Uint32 flags = 0;
1468  int w, h;
1469 
1470  if(!is_fullscreen)
1471  {
1472  if(use_desktop_resolution)
1473  flags = SDL_WINDOW_FULLSCREEN_DESKTOP;
1474  else
1475  flags = SDL_WINDOW_FULLSCREEN;
1476  }
1477 
1478  w = target->context->window_w;
1479  h = target->context->window_h;
1480 
1481  if(SDL_SetWindowFullscreen(SDL_GetWindowFromID(target->context->windowID), flags) >= 0)
1482  {
1483  int stored_w, stored_h;
1484  flags = SDL_GetWindowFlags(SDL_GetWindowFromID(target->context->windowID));
1485  is_fullscreen = (flags & (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_FULLSCREEN_DESKTOP));
1486 
1487  // If we just went fullscreen desktop, save the original resolution
1488  if(is_fullscreen && (flags & SDL_WINDOW_FULLSCREEN_DESKTOP))
1489  {
1490  target->context->stored_window_w = w;
1491  target->context->stored_window_h = h;
1492  }
1493 
1494  // Save original dimensions
1495  stored_w = target->context->stored_window_w;
1496  stored_h = target->context->stored_window_h;
1497 
1498  // If we're in windowed mode now and a resolution was stored, restore the original window resolution
1499  if(!is_fullscreen && (stored_w != 0 || stored_h != 0))
1500  {
1501  w = stored_w;
1502  h = stored_h;
1503  }
1504  else
1505  SDL_GetWindowSize(SDL_GetWindowFromID(target->context->windowID), &w, &h);
1506 
1507  renderer->SetWindowResolution(renderer, w, h);
1508 
1509  // SetWindowResolution() resets the stored dimensions.
1510  target->context->stored_window_w = stored_w;
1511  target->context->stored_window_h = stored_h;
1512  }
1513 
1514  return is_fullscreen;
1515 #else
1516  SDL_Surface* surf = SDL_GetVideoSurface();
1517  Uint16 w, h;
1518 
1519  if(SDL_WM_ToggleFullScreen(surf))
1520  return (surf->flags & SDL_FULLSCREEN);
1521 
1522  w = surf->w;
1523  h = surf->h;
1524  surf->flags ^= SDL_FULLSCREEN;
1525  renderer->SetWindowResolution(renderer, w, h);
1526  return (surf->flags & SDL_FULLSCREEN);
1527 #endif
1528 }
1529 
1530 
1532 {
1533  GPU_Camera new_camera;
1534  GPU_Camera old_camera;
1535 
1536  if(target == NULL)
1537  {
1538  GPU_PushErrorCode("GPU_SetCamera", GPU_ERROR_NULL_ARGUMENT, "target");
1539  return GPU_GetDefaultCamera();
1540  }
1541 
1542  if(cam == NULL)
1543  new_camera = GPU_GetDefaultCamera();
1544  else
1545  new_camera = *cam;
1546 
1547  old_camera = target->camera;
1548 
1549  if(!equal_cameras(new_camera, old_camera))
1550  {
1551  if(isCurrentTarget(renderer, target))
1552  renderer->FlushBlitBuffer(renderer);
1553 
1554  target->camera = new_camera;
1555  }
1556 
1557  return old_camera;
1558 }
1559 
1560 
1562 {
1563  GLuint handle, num_layers, bytes_per_pixel;
1564  GLenum gl_format;
1565  GPU_Image* result;
1567  SDL_Color white = { 255, 255, 255, 255 };
1568 
1569  switch(format)
1570  {
1571  case GPU_FORMAT_LUMINANCE:
1572  gl_format = GL_LUMINANCE;
1573  num_layers = 1;
1574  bytes_per_pixel = 1;
1575  break;
1577  gl_format = GL_LUMINANCE_ALPHA;
1578  num_layers = 1;
1579  bytes_per_pixel = 2;
1580  break;
1581  case GPU_FORMAT_RGB:
1582  gl_format = GL_RGB;
1583  num_layers = 1;
1584  bytes_per_pixel = 3;
1585  break;
1586  case GPU_FORMAT_RGBA:
1587  gl_format = GL_RGBA;
1588  num_layers = 1;
1589  bytes_per_pixel = 4;
1590  break;
1591  case GPU_FORMAT_ALPHA:
1592  gl_format = GL_ALPHA;
1593  num_layers = 1;
1594  bytes_per_pixel = 1;
1595  break;
1596  #ifndef SDL_GPU_USE_GLES
1597  case GPU_FORMAT_RG:
1598  gl_format = GL_RG;
1599  num_layers = 1;
1600  bytes_per_pixel = 2;
1601  break;
1602  #endif
1603  case GPU_FORMAT_YCbCr420P:
1604  gl_format = GL_LUMINANCE;
1605  num_layers = 3;
1606  bytes_per_pixel = 1;
1607  break;
1608  case GPU_FORMAT_YCbCr422:
1609  gl_format = GL_LUMINANCE;
1610  num_layers = 3;
1611  bytes_per_pixel = 1;
1612  break;
1613  default:
1614  GPU_PushErrorCode("GPU_CreateUninitializedImage", GPU_ERROR_DATA_ERROR, "Unsupported image format (0x%x)", format);
1615  return NULL;
1616  }
1617 
1618  if(bytes_per_pixel < 1 || bytes_per_pixel > 4)
1619  {
1620  GPU_PushErrorCode("GPU_CreateUninitializedImage", GPU_ERROR_DATA_ERROR, "Unsupported number of bytes per pixel (%d)", bytes_per_pixel);
1621  return NULL;
1622  }
1623 
1624  glGenTextures( 1, &handle );
1625  if(handle == 0)
1626  {
1627  GPU_PushErrorCode("GPU_CreateUninitializedImage", GPU_ERROR_BACKEND_ERROR, "Failed to generate a texture handle.");
1628  return NULL;
1629  }
1630 
1631  flushAndBindTexture( renderer, handle );
1632 
1633  // Set the texture's stretching properties
1638  #if defined(SDL_GPU_USE_GLES) && (SDL_GPU_GLES_TIER == 1)
1640 
1642  #endif
1643 
1644  result = (GPU_Image*)malloc(sizeof(GPU_Image));
1645  result->refcount = 1;
1646  data = (GPU_IMAGE_DATA*)malloc(sizeof(GPU_IMAGE_DATA));
1647  data->refcount = 1;
1648  result->target = NULL;
1649  result->renderer = renderer;
1650  result->format = format;
1651  result->num_layers = num_layers;
1652  result->bytes_per_pixel = bytes_per_pixel;
1653  result->has_mipmaps = 0;
1654 
1655  result->color = white;
1656  result->use_blending = ((format == GPU_FORMAT_LUMINANCE_ALPHA || format == GPU_FORMAT_RGBA)? 1 : 0);
1658  result->filter_mode = GPU_FILTER_LINEAR;
1660  result->wrap_mode_x = GPU_WRAP_NONE;
1661  result->wrap_mode_y = GPU_WRAP_NONE;
1662 
1663  result->data = data;
1664  result->is_alias = 0;
1665  data->handle = handle;
1666  data->format = gl_format;
1667 
1668  result->w = w;
1669  result->h = h;
1670  // POT textures will change this later
1671  result->texture_w = w;
1672  result->texture_h = h;
1673 
1674  return result;
1675 }
1676 
1677 
1678 static GPU_Image* CreateImage(GPU_Renderer* renderer, Uint16 w, Uint16 h, GPU_FormatEnum format)
1679 {
1680  GPU_Image* result;
1681  GLenum internal_format;
1682  static unsigned char* zero_buffer = NULL;
1683  static unsigned int zero_buffer_size = 0;
1684 
1685  if(format < 1)
1686  {
1687  GPU_PushErrorCode("GPU_CreateImage", GPU_ERROR_DATA_ERROR, "Unsupported image format (0x%x)", format);
1688  return NULL;
1689  }
1690 
1691  result = CreateUninitializedImage(renderer, w, h, format);
1692 
1693  if(result == NULL)
1694  {
1695  GPU_PushErrorCode("GPU_CreateImage", GPU_ERROR_BACKEND_ERROR, "Could not create image as requested.");
1696  return NULL;
1697  }
1698 
1699  changeTexturing(renderer, 1);
1700  bindTexture(renderer, result);
1701 
1702  internal_format = ((GPU_IMAGE_DATA*)(result->data))->format;
1703  w = result->w;
1704  h = result->h;
1706  {
1707  if(!isPowerOfTwo(w))
1708  w = getNearestPowerOf2(w);
1709  if(!isPowerOfTwo(h))
1710  h = getNearestPowerOf2(h);
1711  }
1712 
1713  // Initialize texture using a blank buffer
1714  if(zero_buffer_size < w*h*result->bytes_per_pixel)
1715  {
1716  free(zero_buffer);
1717  zero_buffer_size = w*h*result->bytes_per_pixel;
1718  zero_buffer = (unsigned char*)malloc(zero_buffer_size);
1719  memset(zero_buffer, 0, zero_buffer_size);
1720  }
1721 
1723  #ifdef SDL_GPU_USE_OPENGL
1725  #endif
1726 
1727  glTexImage2D(GL_TEXTURE_2D, 0, internal_format, w, h, 0,
1728  internal_format, GL_UNSIGNED_BYTE, zero_buffer);
1729  // Tell SDL_gpu what we got.
1730  result->texture_w = w;
1731  result->texture_h = h;
1732 
1733  // Restore GL defaults
1735  #ifdef SDL_GPU_USE_OPENGL
1737  #endif
1738 
1739  return result;
1740 }
1741 
1742 static GPU_Image* LoadImage(GPU_Renderer* renderer, const char* filename)
1743 {
1744  GPU_Image* result;
1745  SDL_Surface* surface = GPU_LoadSurface(filename);
1746  if(surface == NULL)
1747  {
1748  GPU_PushErrorCode("GPU_LoadImage", GPU_ERROR_DATA_ERROR, "Failed to load image data.");
1749  return NULL;
1750  }
1751 
1752  result = renderer->CopyImageFromSurface(renderer, surface);
1753  SDL_FreeSurface(surface);
1754 
1755  return result;
1756 }
1757 
1758 
1760 {
1761  GPU_Image* result;
1762 
1763  if(image == NULL)
1764  return NULL;
1765 
1766  result = (GPU_Image*)malloc(sizeof(GPU_Image));
1767  // Copy the members
1768  *result = *image;
1769 
1770  // Alias info
1771  ((GPU_IMAGE_DATA*)image->data)->refcount++;
1772  result->refcount = 1;
1773  result->is_alias = 1;
1774 
1775  return result;
1776 }
1777 
1778 
1780 {
1781  if(source == NULL)
1782  return 0;
1783 
1784  if(isCurrentTarget(renderer, source))
1785  renderer->FlushBlitBuffer(renderer);
1786 
1787  if(bindFramebuffer(renderer, source))
1788  {
1789  glReadPixels(0, 0, source->w, source->h, format, GL_UNSIGNED_BYTE, pixels);
1790  return 1;
1791  }
1792  return 0;
1793 }
1794 
1796 {
1797 #ifdef SDL_GPU_USE_GLES
1798  Uint8 created_target;
1799  Uint8 result;
1800 #endif
1801 
1802  if(source == NULL)
1803  return 0;
1804 
1805  // No glGetTexImage() in OpenGLES
1806  #ifdef SDL_GPU_USE_GLES
1807  // Load up the target
1808  created_target = 0;
1809  if(source->target == NULL)
1810  {
1811  renderer->LoadTarget(renderer, source);
1812  created_target = 1;
1813  }
1814  // Get the data
1815  result = readTargetPixels(renderer, source->target, format, pixels);
1816  // Free the target
1817  if(created_target)
1818  renderer->FreeTarget(renderer, source->target);
1819  return result;
1820  #else
1821  // Bind the texture temporarily
1822  glBindTexture(GL_TEXTURE_2D, ((GPU_IMAGE_DATA*)source->data)->handle);
1823  // Get the data
1824  glGetTexImage(GL_TEXTURE_2D, 0, format, GL_UNSIGNED_BYTE, pixels);
1825  // Rebind the last texture
1826  if(((GPU_CONTEXT_DATA*)renderer->current_context_target->context->data)->last_image != NULL)
1827  glBindTexture(GL_TEXTURE_2D, ((GPU_IMAGE_DATA*)(((GPU_CONTEXT_DATA*)renderer->current_context_target->context->data)->last_image)->data)->handle);
1828  return 1;
1829  #endif
1830 }
1831 
1832 static unsigned char* getRawTargetData(GPU_Renderer* renderer, GPU_Target* target)
1833 {
1834  int bytes_per_pixel;
1835  unsigned char* data;
1836  int pitch;
1837  unsigned char* copy;
1838  int y;
1839 
1840  if(isCurrentTarget(renderer, target))
1841  renderer->FlushBlitBuffer(renderer);
1842 
1843  bytes_per_pixel = 4;
1844  if(target->image != NULL)
1845  bytes_per_pixel = target->image->bytes_per_pixel;
1846  data = (unsigned char*)malloc(target->w * target->h * bytes_per_pixel);
1847 
1848  if(!readTargetPixels(renderer, target, ((GPU_TARGET_DATA*)target->data)->format, data))
1849  {
1850  free(data);
1851  return NULL;
1852  }
1853 
1854  // Flip the data vertically (OpenGL framebuffer is read upside down)
1855  pitch = target->w * bytes_per_pixel;
1856  copy = (unsigned char*)malloc(pitch);
1857 
1858  for(y = 0; y < target->h/2; y++)
1859  {
1860  unsigned char* top = &data[target->w * y * bytes_per_pixel];
1861  unsigned char* bottom = &data[target->w * (target->h - y - 1) * bytes_per_pixel];
1862  memcpy(copy, top, pitch);
1863  memcpy(top, bottom, pitch);
1864  memcpy(bottom, copy, pitch);
1865  }
1866  free(copy);
1867 
1868  return data;
1869 }
1870 
1871 static unsigned char* getRawImageData(GPU_Renderer* renderer, GPU_Image* image)
1872 {
1873  unsigned char* data;
1874 
1875  if(image->target != NULL && isCurrentTarget(renderer, image->target))
1876  renderer->FlushBlitBuffer(renderer);
1877 
1878  data = (unsigned char*)malloc(image->w * image->h * image->bytes_per_pixel);
1879 
1880  if(!readImagePixels(renderer, image, ((GPU_IMAGE_DATA*)image->data)->format, data))
1881  {
1882  free(data);
1883  return NULL;
1884  }
1885 
1886  return data;
1887 }
1888 
1889 // From http://stackoverflow.com/questions/5309471/getting-file-extension-in-c
1890 static const char *get_filename_ext(const char *filename)
1891 {
1892  const char *dot = strrchr(filename, '.');
1893  if(!dot || dot == filename)
1894  return "";
1895  return dot + 1;
1896 }
1897 
1898 static Uint8 SaveImage(GPU_Renderer* renderer, GPU_Image* image, const char* filename)
1899 {
1900  const char* extension;
1901  Uint8 result;
1902  unsigned char* data;
1903 
1904  if(image == NULL || filename == NULL ||
1905  image->w < 1 || image->h < 1 || image->bytes_per_pixel < 1 || image->bytes_per_pixel > 4)
1906  {
1907  return 0;
1908  }
1909 
1910  extension = get_filename_ext(filename);
1911 
1912  data = getRawImageData(renderer, image);
1913 
1914  if(data == NULL)
1915  {
1916  GPU_PushErrorCode("GPU_SaveImage", GPU_ERROR_BACKEND_ERROR, "Could not retrieve texture data.");
1917  return 0;
1918  }
1919 
1920  if(SDL_strcasecmp(extension, "png") == 0)
1921  result = stbi_write_png(filename, image->w, image->h, image->bytes_per_pixel, (const unsigned char *const)data, 0);
1922  else if(SDL_strcasecmp(extension, "bmp") == 0)
1923  result = stbi_write_bmp(filename, image->w, image->h, image->bytes_per_pixel, (void*)data);
1924  else if(SDL_strcasecmp(extension, "tga") == 0)
1925  result = stbi_write_tga(filename, image->w, image->h, image->bytes_per_pixel, (void*)data);
1926  else
1927  {
1928  GPU_PushErrorCode("GPU_SaveImage", GPU_ERROR_DATA_ERROR, "Unsupported output file format (%s)", extension);
1929  result = 0;
1930  }
1931 
1932  free(data);
1933  return result;
1934 }
1935 
1936 static SDL_Surface* CopySurfaceFromTarget(GPU_Renderer* renderer, GPU_Target* target)
1937 {
1938  unsigned char* data;
1939  SDL_Surface* result;
1940  SDL_PixelFormat* format;
1941 
1942  if(target == NULL)
1943  {
1944  GPU_PushErrorCode("GPU_CopySurfaceFromTarget", GPU_ERROR_NULL_ARGUMENT, "target");
1945  return NULL;
1946  }
1947  if(target->w < 1 || target->h < 1)
1948  {
1949  GPU_PushErrorCode("GPU_CopySurfaceFromTarget", GPU_ERROR_DATA_ERROR, "Invalid target dimensions (%dx%d)", target->w, target->h);
1950  return NULL;
1951  }
1952 
1953  data = getRawTargetData(renderer, target);
1954 
1955  if(data == NULL)
1956  {
1957  GPU_PushErrorCode("GPU_CopySurfaceFromTarget", GPU_ERROR_BACKEND_ERROR, "Could not retrieve target data.");
1958  return NULL;
1959  }
1960 
1961  format = AllocFormat(((GPU_TARGET_DATA*)target->data)->format);
1962 
1963  result = SDL_CreateRGBSurfaceFrom(data, target->w, target->h, format->BitsPerPixel, target->w*format->BytesPerPixel, format->Rmask, format->Gmask, format->Bmask, format->Amask);
1964 
1965  FreeFormat(format);
1966  return result;
1967 }
1968 
1969 static SDL_Surface* CopySurfaceFromImage(GPU_Renderer* renderer, GPU_Image* image)
1970 {
1971  unsigned char* data;
1972  SDL_Surface* result;
1973  SDL_PixelFormat* format;
1974 
1975  if(image == NULL)
1976  {
1977  GPU_PushErrorCode("GPU_CopySurfaceFromImage", GPU_ERROR_NULL_ARGUMENT, "image");
1978  return NULL;
1979  }
1980  if(image->w < 1 || image->h < 1)
1981  {
1982  GPU_PushErrorCode("GPU_CopySurfaceFromImage", GPU_ERROR_DATA_ERROR, "Invalid image dimensions (%dx%d)", image->w, image->h);
1983  return NULL;
1984  }
1985 
1986  data = getRawImageData(renderer, image);
1987 
1988  if(data == NULL)
1989  {
1990  GPU_PushErrorCode("GPU_CopySurfaceFromImage", GPU_ERROR_BACKEND_ERROR, "Could not retrieve target data.");
1991  return NULL;
1992  }
1993 
1994  format = AllocFormat(((GPU_IMAGE_DATA*)image->data)->format);
1995 
1996  result = SDL_CreateRGBSurfaceFrom(data, image->w, image->h, format->BitsPerPixel, image->w*format->BytesPerPixel, format->Rmask, format->Gmask, format->Bmask, format->Amask);
1997 
1998  FreeFormat(format);
1999  return result;
2000 }
2001 
2002 
2003 
2004 
2005 
2006 
2007 
2008 
2009 
2010 
2011 
2012 
2013 
2014 
2015 
2016 // Returns 0 if a direct conversion (asking OpenGL to do it) is safe. Returns 1 if a copy is needed. Returns -1 on error.
2017 // The surfaceFormatResult is used to specify what direct conversion format the surface pixels are in (source format).
2018 #ifdef SDL_GPU_USE_GLES
2019 // OpenGLES does not do direct conversion. Internal format (glFormat) and original format (surfaceFormatResult) must be the same.
2020 static int compareFormats(GPU_Renderer* renderer, GLenum glFormat, SDL_Surface* surface, GLenum* surfaceFormatResult)
2021 {
2022  SDL_PixelFormat* format = surface->format;
2023  switch(glFormat)
2024  {
2025  // 3-channel formats
2026  case GL_RGB:
2027  if(format->BytesPerPixel != 3)
2028  return 1;
2029 
2030  if(format->Rmask == 0x0000FF && format->Gmask == 0x00FF00 && format->Bmask == 0xFF0000)
2031  {
2032  if(surfaceFormatResult != NULL)
2033  *surfaceFormatResult = GL_RGB;
2034  return 0;
2035  }
2036 #ifdef GL_BGR
2037  if(format->Rmask == 0xFF0000 && format->Gmask == 0x00FF00 && format->Bmask == 0x0000FF)
2038  {
2039  if(renderer->enabled_features & GPU_FEATURE_GL_BGR)
2040  {
2041  if(surfaceFormatResult != NULL)
2042  *surfaceFormatResult = GL_BGR;
2043  return 0;
2044  }
2045  }
2046 #endif
2047  return 1;
2048  // 4-channel formats
2049  case GL_RGBA:
2050  if(format->BytesPerPixel != 4)
2051  return 1;
2052 
2053  if (format->Rmask == 0x000000FF && format->Gmask == 0x0000FF00 && format->Bmask == 0x00FF0000)
2054  {
2055  if(surfaceFormatResult != NULL)
2056  *surfaceFormatResult = GL_RGBA;
2057  return 0;
2058  }
2059 #ifdef GL_BGRA
2060  if (format->Rmask == 0x00FF0000 && format->Gmask == 0x0000FF00 && format->Bmask == 0x000000FF)
2061  {
2062  if(renderer->enabled_features & GPU_FEATURE_GL_BGRA)
2063  {
2064  if(surfaceFormatResult != NULL)
2065  *surfaceFormatResult = GL_BGRA;
2066  return 0;
2067  }
2068  }
2069 #endif
2070 #ifdef GL_ABGR
2071  if (format->Rmask == 0xFF000000 && format->Gmask == 0x00FF0000 && format->Bmask == 0x0000FF00)
2072  {
2073  if(renderer->enabled_features & GPU_FEATURE_GL_ABGR)
2074  {
2075  if(surfaceFormatResult != NULL)
2076  *surfaceFormatResult = GL_ABGR;
2077  return 0;
2078  }
2079  }
2080 #endif
2081  return 1;
2082  default:
2083  GPU_PushErrorCode("GPU_CompareFormats", GPU_ERROR_DATA_ERROR, "Invalid texture format (0x%x)", glFormat);
2084  return -1;
2085  }
2086 }
2087 #else
2088 //GL_RGB/GL_RGBA and Surface format
2089 static int compareFormats(GPU_Renderer* renderer, GLenum glFormat, SDL_Surface* surface, GLenum* surfaceFormatResult)
2090 {
2091  SDL_PixelFormat* format = surface->format;
2092  switch(glFormat)
2093  {
2094  // 3-channel formats
2095  case GL_RGB:
2096  if(format->BytesPerPixel != 3)
2097  return 1;
2098 
2099  // Looks like RGB? Easy!
2100  if(format->Rmask == 0x0000FF && format->Gmask == 0x00FF00 && format->Bmask == 0xFF0000)
2101  {
2102  if(surfaceFormatResult != NULL)
2103  *surfaceFormatResult = GL_RGB;
2104  return 0;
2105  }
2106  // Looks like BGR?
2107  if(format->Rmask == 0xFF0000 && format->Gmask == 0x00FF00 && format->Bmask == 0x0000FF)
2108  {
2109 #ifdef GL_BGR
2110  if(renderer->enabled_features & GPU_FEATURE_GL_BGR)
2111  {
2112  if(surfaceFormatResult != NULL)
2113  *surfaceFormatResult = GL_BGR;
2114  return 0;
2115  }
2116 #endif
2117  }
2118  return 1;
2119 
2120  // 4-channel formats
2121  case GL_RGBA:
2122 
2123  if(format->BytesPerPixel != 4)
2124  return 1;
2125 
2126  // Looks like RGBA? Easy!
2127  if(format->Rmask == 0x000000FF && format->Gmask == 0x0000FF00 && format->Bmask == 0x00FF0000)
2128  {
2129  if(surfaceFormatResult != NULL)
2130  *surfaceFormatResult = GL_RGBA;
2131  return 0;
2132  }
2133  // Looks like ABGR?
2134  if(format->Rmask == 0xFF000000 && format->Gmask == 0x00FF0000 && format->Bmask == 0x0000FF00)
2135  {
2136 #ifdef GL_ABGR
2137  if(renderer->enabled_features & GPU_FEATURE_GL_ABGR)
2138  {
2139  if(surfaceFormatResult != NULL)
2140  *surfaceFormatResult = GL_ABGR;
2141  return 0;
2142  }
2143 #endif
2144  }
2145  // Looks like BGRA?
2146  else if(format->Rmask == 0x00FF0000 && format->Gmask == 0x0000FF00 && format->Bmask == 0x000000FF)
2147  {
2148 #ifdef GL_BGRA
2149  if(renderer->enabled_features & GPU_FEATURE_GL_BGRA)
2150  {
2151  //ARGB, for OpenGL BGRA
2152  if(surfaceFormatResult != NULL)
2153  *surfaceFormatResult = GL_BGRA;
2154  return 0;
2155  }
2156 #endif
2157  }
2158  return 1;
2159  default:
2160  GPU_PushErrorCode("GPU_CompareFormats", GPU_ERROR_DATA_ERROR, "Invalid texture format (0x%x)", glFormat);
2161  return -1;
2162  }
2163 }
2164 #endif
2165 
2166 
2167 // Adapted from SDL_AllocFormat()
2168 static SDL_PixelFormat* AllocFormat(GLenum glFormat)
2169 {
2170  // Yes, I need to do the whole thing myself... :(
2171  int channels;
2172  Uint32 Rmask, Gmask, Bmask, Amask = 0, mask;
2173  SDL_PixelFormat* result;
2174 
2175  switch(glFormat)
2176  {
2177  case GL_RGB:
2178  channels = 3;
2179  Rmask = 0x0000FF;
2180  Gmask = 0x00FF00;
2181  Bmask = 0xFF0000;
2182  break;
2183 #ifdef GL_BGR
2184  case GL_BGR:
2185  channels = 3;
2186  Rmask = 0xFF0000;
2187  Gmask = 0x00FF00;
2188  Bmask = 0x0000FF;
2189  break;
2190 #endif
2191  case GL_RGBA:
2192  channels = 4;
2193  Rmask = 0x000000FF;
2194  Gmask = 0x0000FF00;
2195  Bmask = 0x00FF0000;
2196  Amask = 0xFF000000;
2197  break;
2198 #ifdef GL_BGRA
2199  case GL_BGRA:
2200  channels = 4;
2201  Rmask = 0x00FF0000;
2202  Gmask = 0x0000FF00;
2203  Bmask = 0x000000FF;
2204  Amask = 0xFF000000;
2205  break;
2206 #endif
2207 #ifdef GL_ABGR
2208  case GL_ABGR:
2209  channels = 4;
2210  Rmask = 0xFF000000;
2211  Gmask = 0x00FF0000;
2212  Bmask = 0x0000FF00;
2213  Amask = 0x000000FF;
2214  break;
2215 #endif
2216  default:
2217  return NULL;
2218  }
2219 
2220  //GPU_LogError("AllocFormat(): %d, Masks: %X %X %X %X\n", glFormat, Rmask, Gmask, Bmask, Amask);
2221 
2222  result = (SDL_PixelFormat*)malloc(sizeof(SDL_PixelFormat));
2223  memset(result, 0, sizeof(SDL_PixelFormat));
2224 
2225  result->BitsPerPixel = 8*channels;
2226  result->BytesPerPixel = channels;
2227 
2228  result->Rmask = Rmask;
2229  result->Rshift = 0;
2230  result->Rloss = 8;
2231  if (Rmask) {
2232  for (mask = Rmask; !(mask & 0x01); mask >>= 1)
2233  ++result->Rshift;
2234  for (; (mask & 0x01); mask >>= 1)
2235  --result->Rloss;
2236  }
2237 
2238  result->Gmask = Gmask;
2239  result->Gshift = 0;
2240  result->Gloss = 8;
2241  if (Gmask) {
2242  for (mask = Gmask; !(mask & 0x01); mask >>= 1)
2243  ++result->Gshift;
2244  for (; (mask & 0x01); mask >>= 1)
2245  --result->Gloss;
2246  }
2247 
2248  result->Bmask = Bmask;
2249  result->Bshift = 0;
2250  result->Bloss = 8;
2251  if (Bmask) {
2252  for (mask = Bmask; !(mask & 0x01); mask >>= 1)
2253  ++result->Bshift;
2254  for (; (mask & 0x01); mask >>= 1)
2255  --result->Bloss;
2256  }
2257 
2258  result->Amask = Amask;
2259  result->Ashift = 0;
2260  result->Aloss = 8;
2261  if (Amask) {
2262  for (mask = Amask; !(mask & 0x01); mask >>= 1)
2263  ++result->Ashift;
2264  for (; (mask & 0x01); mask >>= 1)
2265  --result->Aloss;
2266  }
2267 
2268  return result;
2269 }
2270 
2271 static Uint8 hasColorkey(SDL_Surface* surface)
2272 {
2273 #ifdef SDL_GPU_USE_SDL2
2274  return (SDL_GetColorKey(surface, NULL) == 0);
2275 #else
2276  return (surface->flags & SDL_SRCCOLORKEY);
2277 #endif
2278 }
2279 
2280 static void FreeFormat(SDL_PixelFormat* format)
2281 {
2282  free(format);
2283 }
2284 
2285 // Returns NULL on failure. Returns the original surface if no copy is needed. Returns a new surface converted to the right format otherwise.
2286 static SDL_Surface* copySurfaceIfNeeded(GPU_Renderer* renderer, GLenum glFormat, SDL_Surface* surface, GLenum* surfaceFormatResult)
2287 {
2288 #ifdef SDL_GPU_USE_GLES
2289  SDL_Surface* newSurface;
2290  Uint8 *blob;
2291  SDL_Rect rect;
2292  int srcPitch;
2293  int pitch;
2294 #endif
2295 
2296  // If format doesn't match, we need to do a copy
2297  int format_compare = compareFormats(renderer, glFormat, surface, surfaceFormatResult);
2298 
2299  // There's a problem
2300  if(format_compare < 0)
2301  return NULL;
2302 
2303  #ifdef SDL_GPU_USE_GLES
2304  // GLES needs a tightly-packed pixel array
2305  // Based on SDL_UpdateTexture()
2306  newSurface = NULL;
2307  blob = NULL;
2308  rect.x = 0;
2309  rect.y = 0;
2310  rect.w = surface->w;
2311  rect.h = surface->h;
2312  srcPitch = rect.w * surface->format->BytesPerPixel;
2313  pitch = surface->pitch;
2314  if(srcPitch != pitch)
2315  {
2316  Uint8 *src;
2317  Uint8 *pixels = (Uint8*)surface->pixels;
2318  int y;
2319 
2320  /* Bail out if we're supposed to update an empty rectangle */
2321  if(rect.w <= 0 || rect.h <= 0)
2322  return NULL;
2323 
2324  /* Reformat the texture data into a tightly packed array */
2325  src = pixels;
2326  if(pitch != srcPitch)
2327  {
2328  blob = (Uint8*)malloc(srcPitch * rect.h);
2329  if(blob == NULL)
2330  {
2331  // Out of memory
2332  return NULL;
2333  }
2334  src = blob;
2335  for(y = 0; y < rect.h; ++y)
2336  {
2337  memcpy(src, pixels, srcPitch);
2338  src += srcPitch;
2339  pixels += pitch;
2340  }
2341  src = blob;
2342  }
2343 
2344  newSurface = SDL_CreateRGBSurfaceFrom(src, rect.w, rect.h, surface->format->BytesPerPixel, srcPitch, surface->format->Rmask, surface->format->Gmask, surface->format->Bmask, surface->format->Amask);
2345  }
2346 
2347  // Copy it to a different format
2348  if(format_compare > 0)
2349  {
2350  // Convert to the right format
2351  SDL_PixelFormat* dst_fmt = AllocFormat(glFormat);
2352  if(newSurface != NULL)
2353  {
2354  surface = SDL_ConvertSurface(newSurface, dst_fmt, 0);
2355  SDL_FreeSurface(newSurface);
2356  free(blob);
2357  }
2358  else
2359  surface = SDL_ConvertSurface(surface, dst_fmt, 0);
2360  FreeFormat(dst_fmt);
2361  if(surfaceFormatResult != NULL && surface != NULL)
2362  *surfaceFormatResult = glFormat;
2363  }
2364 
2365  #else
2366  // Copy it to a different format
2367  if(format_compare > 0)
2368  {
2369  // Convert to the right format
2370  SDL_PixelFormat* dst_fmt = AllocFormat(glFormat);
2371  surface = SDL_ConvertSurface(surface, dst_fmt, 0);
2372  FreeFormat(dst_fmt);
2373  if(surfaceFormatResult != NULL && surface != NULL)
2374  *surfaceFormatResult = glFormat;
2375  }
2376  #endif
2377 
2378  // No copy needed
2379  return surface;
2380 }
2381 
2383 {
2384  GPU_Image* result = NULL;
2385 
2386  if(image == NULL)
2387  return NULL;
2388 
2389  switch(image->format)
2390  {
2391  case GPU_FORMAT_RGB:
2392  case GPU_FORMAT_RGBA:
2393  // Copy via framebuffer blitting (fast)
2394  {
2395  GPU_Target* target;
2396 
2397  result = renderer->CreateImage(renderer, image->w, image->h, image->format);
2398  if(result == NULL)
2399  {
2400  GPU_PushErrorCode("GPU_CopyImage", GPU_ERROR_BACKEND_ERROR, "Failed to create new image.");
2401  return NULL;
2402  }
2403 
2404  target = GPU_LoadTarget(result);
2405  if(target == NULL)
2406  {
2407  GPU_FreeImage(result);
2408  GPU_PushErrorCode("GPU_CopyImage", GPU_ERROR_BACKEND_ERROR, "Failed to load target.");
2409  return NULL;
2410  }
2411 
2412  // For some reason, I wasn't able to get glCopyTexImage2D() or glCopyTexSubImage2D() working without getting GL_INVALID_ENUM (0x500).
2413  // It seemed to only work for the default framebuffer...
2414 
2415  {
2416  // Clear the color, blending, and filter mode
2417  SDL_Color color = image->color;
2418  Uint8 use_blending = image->use_blending;
2419  GPU_FilterEnum filter_mode = image->filter_mode;
2420  GPU_SetColor(image, NULL);
2421  GPU_SetBlending(image, 0);
2423 
2424  renderer->Blit(renderer, image, NULL, target, image->w / 2, image->h / 2);
2425 
2426  // Restore the saved settings
2427  GPU_SetColor(image, &color);
2428  GPU_SetBlending(image, use_blending);
2429  GPU_SetImageFilter(image, filter_mode);
2430  }
2431 
2432  // Don't free the target yet (a waste of perf), but let it be freed next time...
2433  target->refcount--;
2434  }
2435  break;
2436  case GPU_FORMAT_LUMINANCE:
2438  case GPU_FORMAT_ALPHA:
2439  case GPU_FORMAT_RG:
2440  // Copy via texture download and upload (slow)
2441  {
2442  GLenum internal_format;
2443  int w;
2444  int h;
2445  unsigned char* texture_data = getRawImageData(renderer, image);
2446  if(texture_data == NULL)
2447  {
2448  GPU_PushErrorCode("GPU_CopyImage", GPU_ERROR_BACKEND_ERROR, "Failed to get raw texture data.");
2449  return NULL;
2450  }
2451 
2452  result = CreateUninitializedImage(renderer, image->w, image->h, image->format);
2453  if(result == NULL)
2454  {
2455  free(texture_data);
2456  GPU_PushErrorCode("GPU_CopyImage", GPU_ERROR_BACKEND_ERROR, "Failed to create new image.");
2457  return NULL;
2458  }
2459 
2460  changeTexturing(renderer, 1);
2461  bindTexture(renderer, result);
2462 
2463  internal_format = ((GPU_IMAGE_DATA*)(result->data))->format;
2464  w = result->w;
2465  h = result->h;
2467  {
2468  if(!isPowerOfTwo(w))
2469  w = getNearestPowerOf2(w);
2470  if(!isPowerOfTwo(h))
2471  h = getNearestPowerOf2(h);
2472  }
2473 
2475  #ifdef SDL_GPU_USE_OPENGL
2477  #endif
2478 
2479  glTexImage2D(GL_TEXTURE_2D, 0, internal_format, w, h, 0,
2480  internal_format, GL_UNSIGNED_BYTE, texture_data);
2481  // Tell SDL_gpu what we got.
2482  result->texture_w = w;
2483  result->texture_h = h;
2484 
2485  // Restore GL defaults
2487  #ifdef SDL_GPU_USE_OPENGL
2489  #endif
2490 
2491  free(texture_data);
2492  }
2493  break;
2494  default:
2495  GPU_PushErrorCode("GPU_CopyImage", GPU_ERROR_BACKEND_ERROR, "Could not copy the given image format.");
2496  break;
2497  }
2498 
2499  if(result != NULL)
2500  {
2501  // Copy the image settings
2502  GPU_SetColor(result, &image->color);
2503  GPU_SetBlending(result, image->use_blending);
2504  result->blend_mode = image->blend_mode;
2505  GPU_SetImageFilter(result, image->filter_mode);
2506  GPU_SetSnapMode(result, image->snap_mode);
2507  GPU_SetWrapMode(result, image->wrap_mode_x, image->wrap_mode_y);
2508  if(image->has_mipmaps)
2509  GPU_GenerateMipmaps(result);
2510  }
2511 
2512  return result;
2513 }
2514 
2515 
2516 
2517 
2518 static void UpdateImage(GPU_Renderer* renderer, GPU_Image* image, SDL_Surface* surface, const GPU_Rect* surface_rect)
2519 {
2520  renderer->UpdateSubImage(renderer, image, NULL, surface, surface_rect);
2521 }
2522 
2523 
2524 static void UpdateSubImage(GPU_Renderer* renderer, GPU_Image* image, const GPU_Rect* image_rect, SDL_Surface* surface, const GPU_Rect* surface_rect)
2525 {
2527  GLenum original_format;
2528 
2529  SDL_Surface* newSurface;
2530  GPU_Rect updateRect;
2531  GPU_Rect sourceRect;
2532  int alignment;
2533  Uint8* pixels;
2534 
2535  if(image == NULL || surface == NULL)
2536  return;
2537 
2538  data = (GPU_IMAGE_DATA*)image->data;
2539  original_format = data->format;
2540 
2541  newSurface = copySurfaceIfNeeded(renderer, data->format, surface, &original_format);
2542  if(newSurface == NULL)
2543  {
2544  GPU_PushErrorCode("GPU_UpdateSubImage", GPU_ERROR_BACKEND_ERROR, "Failed to convert surface to proper pixel format.");
2545  return;
2546  }
2547 
2548  if(image_rect != NULL)
2549  {
2550  updateRect = *image_rect;
2551  if(updateRect.x < 0)
2552  {
2553  updateRect.w += updateRect.x;
2554  updateRect.x = 0;
2555  }
2556  if(updateRect.y < 0)
2557  {
2558  updateRect.h += updateRect.y;
2559  updateRect.y = 0;
2560  }
2561  if(updateRect.x + updateRect.w > image->w)
2562  updateRect.w += image->w - (updateRect.x + updateRect.w);
2563  if(updateRect.y + updateRect.h > image->h)
2564  updateRect.h += image->h - (updateRect.y + updateRect.h);
2565 
2566  if(updateRect.w <= 0)
2567  updateRect.w = 0;
2568  if(updateRect.h <= 0)
2569  updateRect.h = 0;
2570  }
2571  else
2572  {
2573  updateRect.x = 0;
2574  updateRect.y = 0;
2575  updateRect.w = image->w;
2576  updateRect.h = image->h;
2577  if(updateRect.w < 0.0f || updateRect.h < 0.0f)
2578  {
2579  GPU_PushErrorCode("GPU_UpdateSubImage", GPU_ERROR_USER_ERROR, "Given negative image rectangle.");
2580  return;
2581  }
2582  }
2583 
2584  if(surface_rect != NULL)
2585  {
2586  sourceRect = *surface_rect;
2587  if(sourceRect.x < 0)
2588  {
2589  sourceRect.w += sourceRect.x;
2590  sourceRect.x = 0;
2591  }
2592  if(sourceRect.y < 0)
2593  {
2594  sourceRect.h += sourceRect.y;
2595  sourceRect.y = 0;
2596  }
2597  if(sourceRect.x + sourceRect.w > newSurface->w)
2598  sourceRect.w += newSurface->w - (sourceRect.x + sourceRect.w);
2599  if(sourceRect.y + sourceRect.h > newSurface->h)
2600  sourceRect.h += newSurface->h - (sourceRect.y + sourceRect.h);
2601 
2602  if(sourceRect.w <= 0)
2603  sourceRect.w = 0;
2604  if(sourceRect.h <= 0)
2605  sourceRect.h = 0;
2606  }
2607  else
2608  {
2609  sourceRect.x = 0;
2610  sourceRect.y = 0;
2611  sourceRect.w = newSurface->w;
2612  sourceRect.h = newSurface->h;
2613  }
2614 
2615 
2616  changeTexturing(renderer, 1);
2617  if(image->target != NULL && isCurrentTarget(renderer, image->target))
2618  renderer->FlushBlitBuffer(renderer);
2619  bindTexture(renderer, image);
2620  alignment = 1;
2621  if(newSurface->format->BytesPerPixel == 4)
2622  alignment = 4;
2623  glPixelStorei(GL_UNPACK_ALIGNMENT, alignment);
2624  #ifdef SDL_GPU_USE_OPENGL
2625  glPixelStorei(GL_UNPACK_ROW_LENGTH, (newSurface->pitch / newSurface->format->BytesPerPixel));
2626  #endif
2627 
2628  // Use the smaller of the image and surface rect dimensions
2629  if(sourceRect.w < updateRect.w)
2630  updateRect.w = sourceRect.w;
2631  if(sourceRect.h < updateRect.h)
2632  updateRect.h = sourceRect.h;
2633 
2634  pixels = (Uint8*)newSurface->pixels;
2635  // Shift the pixels pointer to the proper source position
2636  pixels += (int)(newSurface->pitch * sourceRect.y + (newSurface->format->BytesPerPixel)*sourceRect.x);
2637 
2639  updateRect.x, updateRect.y, updateRect.w, updateRect.h,
2640  original_format, GL_UNSIGNED_BYTE, pixels);
2641 
2642  // Delete temporary surface
2643  if(surface != newSurface)
2644  SDL_FreeSurface(newSurface);
2645 
2646  // Restore GL defaults
2648  #ifdef SDL_GPU_USE_OPENGL
2650  #endif
2651 }
2652 
2653 
2654 static void UpdateImageBytes(GPU_Renderer* renderer, GPU_Image* image, const GPU_Rect* image_rect, const unsigned char* bytes, int bytes_per_row)
2655 {
2657  GLenum original_format;
2658 
2659  GPU_Rect updateRect;
2660  int alignment;
2661 
2662  if(image == NULL || bytes == NULL)
2663  return;
2664 
2665  data = (GPU_IMAGE_DATA*)image->data;
2666  original_format = data->format;
2667 
2668  if(image_rect != NULL)
2669  {
2670  updateRect = *image_rect;
2671  if(updateRect.x < 0)
2672  {
2673  updateRect.w += updateRect.x;
2674  updateRect.x = 0;
2675  }
2676  if(updateRect.y < 0)
2677  {
2678  updateRect.h += updateRect.y;
2679  updateRect.y = 0;
2680  }
2681  if(updateRect.x + updateRect.w > image->w)
2682  updateRect.w += image->w - (updateRect.x + updateRect.w);
2683  if(updateRect.y + updateRect.h > image->h)
2684  updateRect.h += image->h - (updateRect.y + updateRect.h);
2685 
2686  if(updateRect.w <= 0)
2687  updateRect.w = 0;
2688  if(updateRect.h <= 0)
2689  updateRect.h = 0;
2690  }
2691  else
2692  {
2693  updateRect.x = 0;
2694  updateRect.y = 0;
2695  updateRect.w = image->w;
2696  updateRect.h = image->h;
2697  if(updateRect.w < 0.0f || updateRect.h < 0.0f)
2698  {
2699  GPU_PushErrorCode("GPU_UpdateSubImage", GPU_ERROR_USER_ERROR, "Given negative image rectangle.");
2700  return;
2701  }
2702  }
2703 
2704 
2705  changeTexturing(renderer, 1);
2706  if(image->target != NULL && isCurrentTarget(renderer, image->target))
2707  renderer->FlushBlitBuffer(renderer);
2708  bindTexture(renderer, image);
2709  alignment = 1;
2710  glPixelStorei(GL_UNPACK_ALIGNMENT, alignment);
2711  #ifdef SDL_GPU_USE_OPENGL
2712  glPixelStorei(GL_UNPACK_ROW_LENGTH, (bytes_per_row / image->bytes_per_pixel));
2713  #endif
2714 
2716  updateRect.x, updateRect.y, updateRect.w, updateRect.h,
2717  original_format, GL_UNSIGNED_BYTE, bytes);
2718 
2719  // Restore GL defaults
2721  #ifdef SDL_GPU_USE_OPENGL
2723  #endif
2724 }
2725 
2726 
2727 static_inline Uint32 getPixel(SDL_Surface *Surface, int x, int y)
2728 {
2729  Uint8* bits;
2730  Uint32 bpp;
2731 
2732  if(x < 0 || x >= Surface->w)
2733  return 0; // Best I could do for errors
2734 
2735  bpp = Surface->format->BytesPerPixel;
2736  bits = ((Uint8*)Surface->pixels) + y*Surface->pitch + x*bpp;
2737 
2738  switch (bpp)
2739  {
2740  case 1:
2741  return *((Uint8*)Surface->pixels + y * Surface->pitch + x);
2742  break;
2743  case 2:
2744  return *((Uint16*)Surface->pixels + y * Surface->pitch/2 + x);
2745  break;
2746  case 3:
2747  // Endian-correct, but slower
2748  {
2749  Uint8 r, g, b;
2750  r = *((bits)+Surface->format->Rshift/8);
2751  g = *((bits)+Surface->format->Gshift/8);
2752  b = *((bits)+Surface->format->Bshift/8);
2753  return SDL_MapRGB(Surface->format, r, g, b);
2754  }
2755  break;
2756  case 4:
2757  return *((Uint32*)Surface->pixels + y * Surface->pitch/4 + x);
2758  break;
2759  }
2760 
2761  return 0; // FIXME: Handle errors better
2762 }
2763 
2764 static GPU_Image* CopyImageFromSurface(GPU_Renderer* renderer, SDL_Surface* surface)
2765 {
2767  GPU_Image* image;
2768 
2769  if(surface == NULL)
2770  {
2771  GPU_PushErrorCode("GPU_CopyImageFromSurface", GPU_ERROR_NULL_ARGUMENT, "surface");
2772  return NULL;
2773  }
2774 
2775  // See what the best image format is.
2776  if(surface->format->Amask == 0)
2777  {
2778  if(hasColorkey(surface))
2779  format = GPU_FORMAT_RGBA;
2780  else
2781  format = GPU_FORMAT_RGB;
2782  }
2783  else
2784  format = GPU_FORMAT_RGBA;
2785 
2786  image = renderer->CreateImage(renderer, surface->w, surface->h, format);
2787  if(image == NULL)
2788  return NULL;
2789 
2790  renderer->UpdateImage(renderer, image, surface, NULL);
2791 
2792  return image;
2793 }
2794 
2795 
2797 {
2798  SDL_Surface* surface;
2799  GPU_Image* image;
2800 
2801  if(target == NULL)
2802  return NULL;
2803 
2804  surface = renderer->CopySurfaceFromTarget(renderer, target);
2805  image = renderer->CopyImageFromSurface(renderer, surface);
2806  SDL_FreeSurface(surface);
2807 
2808  return image;
2809 }
2810 
2811 
2812 static void FreeImage(GPU_Renderer* renderer, GPU_Image* image)
2813 {
2815 
2816  if(image == NULL)
2817  return;
2818 
2819  if(image->refcount > 1)
2820  {
2821  image->refcount--;
2822  return;
2823  }
2824 
2825  // Delete the attached target first
2826  if(image->target != NULL)
2827  {
2828  GPU_Target* target = image->target;
2829  image->target = NULL;
2830  renderer->FreeTarget(renderer, target);
2831  }
2832 
2833  flushAndClearBlitBufferIfCurrentTexture(renderer, image);
2834 
2835  // Does the renderer data need to be freed too?
2836  data = (GPU_IMAGE_DATA*)image->data;
2837  if(data->refcount > 1)
2838  {
2839  data->refcount--;
2840  }
2841  else
2842  {
2843  glDeleteTextures( 1, &data->handle);
2844  free(data);
2845  }
2846 
2847  free(image);
2848 }
2849 
2850 
2851 
2853 {
2854  GLuint handle;
2855  GLenum status;
2856  GPU_Target* result;
2858 
2859  if(image == NULL)
2860  return NULL;
2861 
2862  if(image->target != NULL)
2863  {
2864  image->target->refcount++;
2865  ((GPU_TARGET_DATA*)image->target->data)->refcount++;
2866  return image->target;
2867  }
2868 
2869  if(!(renderer->enabled_features & GPU_FEATURE_RENDER_TARGETS))
2870  return NULL;
2871 
2872  // Create framebuffer object
2873  glGenFramebuffers(1, &handle);
2874  flushAndBindFramebuffer(renderer, handle);
2875 
2876  // Attach the texture to it
2878 
2880  if(status != GL_FRAMEBUFFER_COMPLETE)
2881  return NULL;
2882 
2883  result = (GPU_Target*)malloc(sizeof(GPU_Target));
2884  memset(result, 0, sizeof(GPU_Target));
2885  result->refcount = 1;
2886  data = (GPU_TARGET_DATA*)malloc(sizeof(GPU_TARGET_DATA));
2887  data->refcount = 1;
2888  result->data = data;
2889  data->handle = handle;
2890  data->format = ((GPU_IMAGE_DATA*)image->data)->format;
2891 
2892  result->renderer = renderer;
2893  result->context = NULL;
2894  result->image = image;
2895  result->w = image->w;
2896  result->h = image->h;
2897 
2898  result->viewport = GPU_MakeRect(0, 0, result->w, result->h);
2899 
2900  result->camera = GPU_GetDefaultCamera();
2901 
2902  result->use_clip_rect = 0;
2903  result->clip_rect.x = 0;
2904  result->clip_rect.y = 0;
2905  result->clip_rect.w = image->w;
2906  result->clip_rect.h = image->h;
2907  result->use_color = 0;
2908 
2909  image->target = result;
2910  return result;
2911 }
2912 
2913 
2914 
2915 static void FreeTarget(GPU_Renderer* renderer, GPU_Target* target)
2916 {
2918 
2919  if(target == NULL)
2920  return;
2921 
2922  if(target->refcount > 1)
2923  {
2924  target->refcount--;
2925  return;
2926  }
2927 
2928  if(target->context != NULL && target->context->failed)
2929  {
2930  GPU_CONTEXT_DATA* cdata = (GPU_CONTEXT_DATA*)target->context->data;
2931 
2932  if(target == renderer->current_context_target)
2933  renderer->current_context_target = NULL;
2934 
2935  free(cdata->blit_buffer);
2936  free(cdata->index_buffer);
2937 
2938  #ifdef SDL_GPU_USE_SDL2
2939  if(target->context->context != 0)
2940  SDL_GL_DeleteContext(target->context->context);
2941  #endif
2942 
2943  // Remove all of the window mappings that refer to this target
2945 
2946  free(target->context->data);
2947  free(target->context);
2948 
2949  // Does the renderer data need to be freed too?
2950  data = ((GPU_TARGET_DATA*)target->data);
2951 
2952  free(data);
2953  free(target);
2954 
2955  return;
2956  }
2957 
2958  if(target == renderer->current_context_target)
2959  {
2960  renderer->FlushBlitBuffer(renderer);
2961  renderer->current_context_target = NULL;
2962  }
2963 
2964  if(!target->is_alias && target->image != NULL)
2965  target->image->target = NULL; // Remove reference to this object
2966 
2967 
2968  // Does the renderer data need to be freed too?
2969  data = ((GPU_TARGET_DATA*)target->data);
2970  if(data->refcount > 1)
2971  {
2972  data->refcount--;
2973  free(target);
2974  return;
2975  }
2976 
2978  {
2979  if(renderer->current_context_target != NULL)
2981  if(data->handle != 0)
2982  glDeleteFramebuffers(1, &data->handle);
2983  }
2984 
2985  if(target->context != NULL)
2986  {
2987  GPU_CONTEXT_DATA* cdata = (GPU_CONTEXT_DATA*)target->context->data;
2988 
2989  free(cdata->blit_buffer);
2990  free(cdata->index_buffer);
2991 
2992  #ifdef SDL_GPU_USE_SDL2
2993  if(target->context->context != 0)
2994  SDL_GL_DeleteContext(target->context->context);
2995  #endif
2996 
2997  #ifdef SDL_GPU_USE_GL_TIER3
2998  glDeleteBuffers(2, cdata->blit_VBO);
2999  glDeleteBuffers(16, cdata->attribute_VBO);
3000  #if !defined(SDL_GPU_NO_VAO)
3001  glDeleteVertexArrays(1, &cdata->blit_VAO);
3002  #endif
3003  #endif
3004 
3005  // Remove all of the window mappings that refer to this target
3007 
3008  free(target->context->data);
3009  free(target->context);
3010  target->context = NULL;
3011  }
3012 
3013  free(data);
3014  free(target);
3015 }
3016 
3017 
3018 
3019 
3020 
3021 #define SET_TEXTURED_VERTEX(x, y, s, t, r, g, b, a) \
3022  blit_buffer[vert_index] = x; \
3023  blit_buffer[vert_index+1] = y; \
3024  blit_buffer[tex_index] = s; \
3025  blit_buffer[tex_index+1] = t; \
3026  blit_buffer[color_index] = r; \
3027  blit_buffer[color_index+1] = g; \
3028  blit_buffer[color_index+2] = b; \
3029  blit_buffer[color_index+3] = a; \
3030  index_buffer[cdata->index_buffer_num_vertices++] = cdata->blit_buffer_num_vertices++; \
3031  vert_index += GPU_BLIT_BUFFER_FLOATS_PER_VERTEX; \
3032  tex_index += GPU_BLIT_BUFFER_FLOATS_PER_VERTEX; \
3033  color_index += GPU_BLIT_BUFFER_FLOATS_PER_VERTEX;
3034 
3035 #define SET_TEXTURED_VERTEX_UNINDEXED(x, y, s, t, r, g, b, a) \
3036  blit_buffer[vert_index] = x; \
3037  blit_buffer[vert_index+1] = y; \
3038  blit_buffer[tex_index] = s; \
3039  blit_buffer[tex_index+1] = t; \
3040  blit_buffer[color_index] = r; \
3041  blit_buffer[color_index+1] = g; \
3042  blit_buffer[color_index+2] = b; \
3043  blit_buffer[color_index+3] = a; \
3044  vert_index += GPU_BLIT_BUFFER_FLOATS_PER_VERTEX; \
3045  tex_index += GPU_BLIT_BUFFER_FLOATS_PER_VERTEX; \
3046  color_index += GPU_BLIT_BUFFER_FLOATS_PER_VERTEX;
3047 
3048 #define SET_UNTEXTURED_VERTEX(x, y, r, g, b, a) \
3049  blit_buffer[vert_index] = x; \
3050  blit_buffer[vert_index+1] = y; \
3051  blit_buffer[color_index] = r; \
3052  blit_buffer[color_index+1] = g; \
3053  blit_buffer[color_index+2] = b; \
3054  blit_buffer[color_index+3] = a; \
3055  index_buffer[cdata->index_buffer_num_vertices++] = cdata->blit_buffer_num_vertices++; \
3056  vert_index += GPU_BLIT_BUFFER_FLOATS_PER_VERTEX; \
3057  color_index += GPU_BLIT_BUFFER_FLOATS_PER_VERTEX;
3058 
3059 #define SET_UNTEXTURED_VERTEX_UNINDEXED(x, y, r, g, b, a) \
3060  blit_buffer[vert_index] = x; \
3061  blit_buffer[vert_index+1] = y; \
3062  blit_buffer[color_index] = r; \
3063  blit_buffer[color_index+1] = g; \
3064  blit_buffer[color_index+2] = b; \
3065  blit_buffer[color_index+3] = a; \
3066  vert_index += GPU_BLIT_BUFFER_FLOATS_PER_VERTEX; \
3067  color_index += GPU_BLIT_BUFFER_FLOATS_PER_VERTEX;
3068 
3069 #define SET_INDEXED_VERTEX(offset) \
3070  index_buffer[cdata->index_buffer_num_vertices++] = blit_buffer_starting_index + (offset);
3071 
3072 
3073 
3074 static void Blit(GPU_Renderer* renderer, GPU_Image* image, GPU_Rect* src_rect, GPU_Target* target, float x, float y)
3075 {
3076  Uint16 tex_w, tex_h;
3077  float w;
3078  float h;
3079  float x1, y1, x2, y2;
3080  float dx1, dy1, dx2, dy2;
3081  GPU_CONTEXT_DATA* cdata;
3082  float* blit_buffer;
3083  unsigned short* index_buffer;
3084  unsigned short blit_buffer_starting_index;
3085  int vert_index;
3086  int tex_index;
3087  int color_index;
3088  float r, g, b, a;
3089 
3090  if(image == NULL)
3091  {
3092  GPU_PushErrorCode("GPU_Blit", GPU_ERROR_NULL_ARGUMENT, "image");
3093  return;
3094  }
3095  if(target == NULL)
3096  {
3097  GPU_PushErrorCode("GPU_Blit", GPU_ERROR_NULL_ARGUMENT, "target");
3098  return;
3099  }
3100  if(renderer != image->renderer || renderer != target->renderer)
3101  {
3102  GPU_PushErrorCode("GPU_Blit", GPU_ERROR_USER_ERROR, "Mismatched renderer");
3103  return;
3104  }
3105 
3106  makeContextCurrent(renderer, target);
3107  if(renderer->current_context_target == NULL)
3108  {
3109  GPU_PushErrorCode("GPU_Blit", GPU_ERROR_USER_ERROR, "NULL context");
3110  return;
3111  }
3112 
3113  prepareToRenderToTarget(renderer, target);
3114  prepareToRenderImage(renderer, target, image);
3115 
3116  // Bind the texture to which subsequent calls refer
3117  bindTexture(renderer, image);
3118 
3119  // Bind the FBO
3120  if(!bindFramebuffer(renderer, target))
3121  {
3122  GPU_PushErrorCode("GPU_Blit", GPU_ERROR_BACKEND_ERROR, "Failed to bind framebuffer.");
3123  return;
3124  }
3125 
3126  tex_w = image->texture_w;
3127  tex_h = image->texture_h;
3128 
3130  {
3131  // Avoid rounding errors in texture sampling by insisting on integral pixel positions
3132  x = floorf(x);
3133  y = floorf(y);
3134  }
3135 
3136  if(src_rect == NULL)
3137  {
3138  // Scale tex coords according to actual texture dims
3139  x1 = 0.0f;
3140  y1 = 0.0f;
3141  x2 = ((float)image->w)/tex_w;
3142  y2 = ((float)image->h)/tex_h;
3143  w = image->w;
3144  h = image->h;
3145  }
3146  else
3147  {
3148  // Scale src_rect tex coords according to actual texture dims
3149  x1 = src_rect->x/(float)tex_w;
3150  y1 = src_rect->y/(float)tex_h;
3151  x2 = (src_rect->x + src_rect->w)/(float)tex_w;
3152  y2 = (src_rect->y + src_rect->h)/(float)tex_h;
3153  w = src_rect->w;
3154  h = src_rect->h;
3155  }
3156 
3157  // Center the image on the given coords
3158  dx1 = x - w/2.0f;
3159  dy1 = y - h/2.0f;
3160  dx2 = x + w/2.0f;
3161  dy2 = y + h/2.0f;
3162 
3164  {
3165  float fractional;
3166  fractional = w/2.0f - floorf(w/2.0f);
3167  dx1 += fractional;
3168  dx2 += fractional;
3169  fractional = h/2.0f - floorf(h/2.0f);
3170  dy1 += fractional;
3171  dy2 += fractional;
3172  }
3173 
3174  cdata = (GPU_CONTEXT_DATA*)renderer->current_context_target->context->data;
3175 
3176  if(cdata->blit_buffer_num_vertices + 4 >= cdata->blit_buffer_max_num_vertices)
3177  {
3178  if(!growBlitBuffer(cdata, cdata->blit_buffer_num_vertices + 4))
3179  renderer->FlushBlitBuffer(renderer);
3180  }
3181  if(cdata->index_buffer_num_vertices + 6 >= cdata->index_buffer_max_num_vertices)
3182  {
3183  if(!growIndexBuffer(cdata, cdata->index_buffer_num_vertices + 6))
3184  renderer->FlushBlitBuffer(renderer);
3185  }
3186 
3187  blit_buffer = cdata->blit_buffer;
3188  index_buffer = cdata->index_buffer;
3189 
3190  blit_buffer_starting_index = cdata->blit_buffer_num_vertices;
3191 
3192  vert_index = GPU_BLIT_BUFFER_VERTEX_OFFSET + cdata->blit_buffer_num_vertices*GPU_BLIT_BUFFER_FLOATS_PER_VERTEX;
3193  tex_index = GPU_BLIT_BUFFER_TEX_COORD_OFFSET + cdata->blit_buffer_num_vertices*GPU_BLIT_BUFFER_FLOATS_PER_VERTEX;
3194  color_index = GPU_BLIT_BUFFER_COLOR_OFFSET + cdata->blit_buffer_num_vertices*GPU_BLIT_BUFFER_FLOATS_PER_VERTEX;
3195  if(target->use_color)
3196  {
3197  r = MIX_COLOR_COMPONENT_NORMALIZED_RESULT(target->color.r, image->color.r);
3198  g = MIX_COLOR_COMPONENT_NORMALIZED_RESULT(target->color.g, image->color.g);
3199  b = MIX_COLOR_COMPONENT_NORMALIZED_RESULT(target->color.b, image->color.b);
3201  }
3202  else
3203  {
3204  r = image->color.r/255.0f;
3205  g = image->color.g/255.0f;
3206  b = image->color.b/255.0f;
3207  a = GET_ALPHA(image->color)/255.0f;
3208  }
3209 
3210  // 4 Quad vertices
3211  SET_TEXTURED_VERTEX_UNINDEXED(dx1, dy1, x1, y1, r, g, b, a);
3212  SET_TEXTURED_VERTEX_UNINDEXED(dx2, dy1, x2, y1, r, g, b, a);
3213  SET_TEXTURED_VERTEX_UNINDEXED(dx2, dy2, x2, y2, r, g, b, a);
3214  SET_TEXTURED_VERTEX_UNINDEXED(dx1, dy2, x1, y2, r, g, b, a);
3215 
3216  // 6 Triangle indices
3217  SET_INDEXED_VERTEX(0);
3218  SET_INDEXED_VERTEX(1);
3219  SET_INDEXED_VERTEX(2);
3220 
3221  SET_INDEXED_VERTEX(0);
3222  SET_INDEXED_VERTEX(2);
3223  SET_INDEXED_VERTEX(3);
3224 
3225  cdata->blit_buffer_num_vertices += GPU_BLIT_BUFFER_VERTICES_PER_SPRITE;
3226 }
3227 
3228 
3229 static void BlitRotate(GPU_Renderer* renderer, GPU_Image* image, GPU_Rect* src_rect, GPU_Target* target, float x, float y, float degrees)
3230 {
3231  float w, h;
3232  if(image == NULL)
3233  {
3234  GPU_PushErrorCode("GPU_BlitRotate", GPU_ERROR_NULL_ARGUMENT, "image");
3235  return;
3236  }
3237  if(target == NULL)
3238  {
3239  GPU_PushErrorCode("GPU_BlitRotate", GPU_ERROR_NULL_ARGUMENT, "target");
3240  return;
3241  }
3242 
3243  w = (src_rect == NULL? image->w : src_rect->w);
3244  h = (src_rect == NULL? image->h : src_rect->h);
3245  renderer->BlitTransformX(renderer, image, src_rect, target, x, y, w/2.0f, h/2.0f, degrees, 1.0f, 1.0f);
3246 }
3247 
3248 static void BlitScale(GPU_Renderer* renderer, GPU_Image* image, GPU_Rect* src_rect, GPU_Target* target, float x, float y, float scaleX, float scaleY)
3249 {
3250  float w, h;
3251  if(image == NULL)
3252  {
3253  GPU_PushErrorCode("GPU_BlitScale", GPU_ERROR_NULL_ARGUMENT, "image");
3254  return;
3255  }
3256  if(target == NULL)
3257  {
3258  GPU_PushErrorCode("GPU_BlitScale", GPU_ERROR_NULL_ARGUMENT, "target");
3259  return;
3260  }
3261 
3262  w = (src_rect == NULL? image->w : src_rect->w);
3263  h = (src_rect == NULL? image->h : src_rect->h);
3264  renderer->BlitTransformX(renderer, image, src_rect, target, x, y, w/2.0f, h/2.0f, 0.0f, scaleX, scaleY);
3265 }
3266 
3267 static void BlitTransform(GPU_Renderer* renderer, GPU_Image* image, GPU_Rect* src_rect, GPU_Target* target, float x, float y, float degrees, float scaleX, float scaleY)
3268 {
3269  float w, h;
3270  if(image == NULL)
3271  {
3272  GPU_PushErrorCode("GPU_BlitTransform", GPU_ERROR_NULL_ARGUMENT, "image");
3273  return;
3274  }
3275  if(target == NULL)
3276  {
3277  GPU_PushErrorCode("GPU_BlitTransform", GPU_ERROR_NULL_ARGUMENT, "target");
3278  return;
3279  }
3280 
3281  w = (src_rect == NULL? image->w : src_rect->w);
3282  h = (src_rect == NULL? image->h : src_rect->h);
3283  renderer->BlitTransformX(renderer, image, src_rect, target, x, y, w/2.0f, h/2.0f, degrees, scaleX, scaleY);
3284 }
3285 
3286 static void BlitTransformX(GPU_Renderer* renderer, GPU_Image* image, GPU_Rect* src_rect, GPU_Target* target, float x, float y, float pivot_x, float pivot_y, float degrees, float scaleX, float scaleY)
3287 {
3288  Uint16 tex_w, tex_h;
3289  float x1, y1, x2, y2;
3290  float dx1, dy1, dx2, dy2, dx3, dy3, dx4, dy4;
3291  float w, h;
3292  GPU_CONTEXT_DATA* cdata;
3293  float* blit_buffer;
3294  unsigned short* index_buffer;
3295  unsigned short blit_buffer_starting_index;
3296  int vert_index;
3297  int tex_index;
3298  int color_index;
3299  float r, g, b, a;
3300 
3301  if(image == NULL)
3302  {
3303  GPU_PushErrorCode("GPU_BlitTransformX", GPU_ERROR_NULL_ARGUMENT, "image");
3304  return;
3305  }
3306  if(target == NULL)
3307  {
3308  GPU_PushErrorCode("GPU_BlitTransformX", GPU_ERROR_NULL_ARGUMENT, "target");
3309  return;
3310  }
3311  if(renderer != image->renderer || renderer != target->renderer)
3312  {
3313  GPU_PushErrorCode("GPU_BlitTransformX", GPU_ERROR_USER_ERROR, "Mismatched renderer");
3314  return;
3315  }
3316 
3317 
3318  makeContextCurrent(renderer, target);
3319 
3320  prepareToRenderToTarget(renderer, target);
3321  prepareToRenderImage(renderer, target, image);
3322 
3323  // Bind the texture to which subsequent calls refer
3324  bindTexture(renderer, image);
3325 
3326  // Bind the FBO
3327  if(!bindFramebuffer(renderer, target))
3328  {
3329  GPU_PushErrorCode("GPU_BlitTransformX", GPU_ERROR_BACKEND_ERROR, "Failed to bind framebuffer.");
3330  return;
3331  }
3332 
3333  tex_w = image->texture_w;
3334  tex_h = image->texture_h;
3335 
3337  {
3338  // Avoid rounding errors in texture sampling by insisting on integral pixel positions
3339  x = floorf(x);
3340  y = floorf(y);
3341  }
3342 
3343  /*
3344  1,1 --- 3,3
3345  | |
3346  | |
3347  4,4 --- 2,2
3348  */
3349  if(src_rect == NULL)
3350  {
3351  // Scale tex coords according to actual texture dims
3352  x1 = 0.0f;
3353  y1 = 0.0f;
3354  x2 = ((float)image->w)/tex_w;
3355  y2 = ((float)image->h)/tex_h;
3356  w = image->w;
3357  h = image->h;
3358  }
3359  else
3360  {
3361  // Scale src_rect tex coords according to actual texture dims
3362  x1 = src_rect->x/(float)tex_w;
3363  y1 = src_rect->y/(float)tex_h;
3364  x2 = (src_rect->x + src_rect->w)/(float)tex_w;
3365  y2 = (src_rect->y + src_rect->h)/(float)tex_h;
3366  w = src_rect->w;
3367  h = src_rect->h;
3368  }
3369 
3370  // Center the image on the given coords (offset later)
3371  dx1 = -w/2.0f;
3372  dy1 = -h/2.0f;
3373  dx2 = w/2.0f;
3374  dy2 = h/2.0f;
3375 
3377  {
3378  // This is a little weird for rotating sprites, but oh well.
3379  float fractional;
3380  fractional = w/2.0f - floorf(w/2.0f);
3381  dx1 += fractional;
3382  dx2 += fractional;
3383  fractional = h/2.0f - floorf(h/2.0f);
3384  dy1 += fractional;
3385  dy2 += fractional;
3386  }
3387 
3388  // Apply transforms
3389 
3390  // Scale
3391  if(scaleX != 1.0f || scaleY != 1.0f)
3392  {
3393  float w = (dx2 - dx1)*scaleX;
3394  float h = (dy2 - dy1)*scaleY;
3395  dx1 = (dx2 + dx1)/2 - w/2;
3396  dx2 = dx1 + w;
3397  dy1 = (dy2 + dy1)/2 - h/2;
3398  dy2 = dy1 + h;
3399  }
3400 
3401  // Shift away from the center (these are relative to the image corner)
3402  pivot_x -= w/2.0f;
3403  pivot_y -= h/2.0f;
3404 
3405  // Translate origin to pivot
3406  dx1 -= pivot_x*scaleX;
3407  dy1 -= pivot_y*scaleY;
3408  dx2 -= pivot_x*scaleX;
3409  dy2 -= pivot_y*scaleY;
3410 
3411  // Get extra vertices for rotation
3412  dx3 = dx2;
3413  dy3 = dy1;
3414  dx4 = dx1;
3415  dy4 = dy2;
3416 
3417  // Rotate about origin (the pivot)
3418  if(degrees != 0.0f)
3419  {
3420  float cosA = cos(degrees*M_PI/180);
3421  float sinA = sin(degrees*M_PI/180);
3422  float tempX = dx1;
3423  dx1 = dx1*cosA - dy1*sinA;
3424  dy1 = tempX*sinA + dy1*cosA;
3425  tempX = dx2;
3426  dx2 = dx2*cosA - dy2*sinA;
3427  dy2 = tempX*sinA + dy2*cosA;
3428  tempX = dx3;
3429  dx3 = dx3*cosA - dy3*sinA;
3430  dy3 = tempX*sinA + dy3*cosA;
3431  tempX = dx4;
3432  dx4 = dx4*cosA - dy4*sinA;
3433  dy4 = tempX*sinA + dy4*cosA;
3434  }
3435 
3436  // Translate to pos
3437  dx1 += x;
3438  dx2 += x;
3439  dx3 += x;
3440  dx4 += x;
3441  dy1 += y;
3442  dy2 += y;
3443  dy3 += y;
3444  dy4 += y;
3445 
3446  cdata = (GPU_CONTEXT_DATA*)renderer->current_context_target->context->data;
3447 
3448  if(cdata->blit_buffer_num_vertices + 4 >= cdata->blit_buffer_max_num_vertices)
3449  {
3450  if(!growBlitBuffer(cdata, cdata->blit_buffer_num_vertices + 4))
3451  renderer->FlushBlitBuffer(renderer);
3452  }
3453  if(cdata->index_buffer_num_vertices + 6 >= cdata->index_buffer_max_num_vertices)
3454  {
3455  if(!growIndexBuffer(cdata, cdata->index_buffer_num_vertices + 6))
3456  renderer->FlushBlitBuffer(renderer);
3457  }
3458 
3459  blit_buffer = cdata->blit_buffer;
3460  index_buffer = cdata->index_buffer;
3461 
3462  blit_buffer_starting_index = cdata->blit_buffer_num_vertices;
3463 
3464  vert_index = GPU_BLIT_BUFFER_VERTEX_OFFSET + cdata->blit_buffer_num_vertices*GPU_BLIT_BUFFER_FLOATS_PER_VERTEX;
3465  tex_index = GPU_BLIT_BUFFER_TEX_COORD_OFFSET + cdata->blit_buffer_num_vertices*GPU_BLIT_BUFFER_FLOATS_PER_VERTEX;
3466  color_index = GPU_BLIT_BUFFER_COLOR_OFFSET + cdata->blit_buffer_num_vertices*GPU_BLIT_BUFFER_FLOATS_PER_VERTEX;
3467 
3468  if(target->use_color)
3469  {
3470  r = MIX_COLOR_COMPONENT_NORMALIZED_RESULT(target->color.r, image->color.r);
3471  g = MIX_COLOR_COMPONENT_NORMALIZED_RESULT(target->color.g, image->color.g);
3472  b = MIX_COLOR_COMPONENT_NORMALIZED_RESULT(target->color.b, image->color.b);
3474  }
3475  else
3476  {
3477  r = image->color.r/255.0f;
3478  g = image->color.g/255.0f;
3479  b = image->color.b/255.0f;
3480  a = GET_ALPHA(image->color)/255.0f;
3481  }
3482 
3483  // 4 Quad vertices
3484  SET_TEXTURED_VERTEX_UNINDEXED(dx1, dy1, x1, y1, r, g, b, a);
3485  SET_TEXTURED_VERTEX_UNINDEXED(dx3, dy3, x2, y1, r, g, b, a);
3486  SET_TEXTURED_VERTEX_UNINDEXED(dx2, dy2, x2, y2, r, g, b, a);
3487  SET_TEXTURED_VERTEX_UNINDEXED(dx4, dy4, x1, y2, r, g, b, a);
3488 
3489  // 6 Triangle indices
3490  SET_INDEXED_VERTEX(0);
3491  SET_INDEXED_VERTEX(1);
3492  SET_INDEXED_VERTEX(2);
3493 
3494  SET_INDEXED_VERTEX(0);
3495  SET_INDEXED_VERTEX(2);
3496  SET_INDEXED_VERTEX(3);
3497 
3498  cdata->blit_buffer_num_vertices += GPU_BLIT_BUFFER_VERTICES_PER_SPRITE;
3499 }
3500 
3501 static void BlitTransformMatrix(GPU_Renderer* renderer, GPU_Image* image, GPU_Rect* src_rect, GPU_Target* target, float x, float y, float* matrix3x3)
3502 {
3503  if(image == NULL)
3504  {
3505  GPU_PushErrorCode("GPU_BlitTransformMatrix", GPU_ERROR_NULL_ARGUMENT, "image");
3506  return;
3507  }
3508  if(target == NULL)
3509  {
3510  GPU_PushErrorCode("GPU_BlitTransformMatrix", GPU_ERROR_NULL_ARGUMENT, "target");
3511  return;
3512  }
3513  if(renderer != image->renderer || renderer != target->renderer)
3514  {
3515  GPU_PushErrorCode("GPU_BlitTransformMatrix", GPU_ERROR_USER_ERROR, "Mismatched renderer");
3516  return;
3517  }
3518 
3519  // TODO: See below.
3520  renderer->FlushBlitBuffer(renderer);
3521 
3522  GPU_PushMatrix();
3523 
3524  // column-major 3x3 to column-major 4x4 (and scooting the 2D translations to the homogeneous column)
3525  // FIXME: Should index 8 replace the homogeneous 1? This looks like it adjusts the z-value...
3526  {
3527  float matrix[16] = {matrix3x3[0], matrix3x3[1], matrix3x3[2], 0,
3528  matrix3x3[3], matrix3x3[4], matrix3x3[5], 0,
3529  0, 0, matrix3x3[8], 0,
3530  matrix3x3[6], matrix3x3[7], 0, 1
3531  };
3532  GPU_Translate(x, y, 0);
3533  GPU_MultMatrix(matrix);
3534  }
3535 
3536  renderer->Blit(renderer, image, src_rect, target, 0, 0);
3537 
3538  // Popping the matrix will revert the transform before it can be used, so we have to flush for now.
3539  // TODO: Do the matrix math myself on the vertex coords.
3540  renderer->FlushBlitBuffer(renderer);
3541 
3542  GPU_PopMatrix();
3543 }
3544 
3545 
3546 
3547 #ifdef SDL_GPU_USE_GL_TIER3
3548 
3549 
3550 static_inline int sizeof_GPU_type(GPU_TypeEnum type)
3551 {
3552  if(type == GPU_TYPE_DOUBLE) return sizeof(double);
3553  if(type == GPU_TYPE_FLOAT) return sizeof(float);
3554  if(type == GPU_TYPE_INT) return sizeof(int);
3555  if(type == GPU_TYPE_UNSIGNED_INT) return sizeof(unsigned int);
3556  if(type == GPU_TYPE_SHORT) return sizeof(short);
3557  if(type == GPU_TYPE_UNSIGNED_SHORT) return sizeof(unsigned short);
3558  if(type == GPU_TYPE_BYTE) return sizeof(char);
3559  if(type == GPU_TYPE_UNSIGNED_BYTE) return sizeof(unsigned char);
3560  return 0;
3561 }
3562 
3563 static void refresh_attribute_data(GPU_CONTEXT_DATA* cdata)
3564 {
3565  int i;
3566  for(i = 0; i < 16; i++)
3567  {
3568  GPU_AttributeSource* a = &cdata->shader_attributes[i];
3569  if(a->attribute.values != NULL && a->attribute.location >= 0 && a->num_values > 0 && a->attribute.format.is_per_sprite)
3570  {
3571  // Expand the values to 4 vertices
3572  int n;
3573  void* storage_ptr = a->per_vertex_storage;
3574  void* values_ptr = (void*)((char*)a->attribute.values + a->attribute.format.offset_bytes);
3575  int value_size_bytes = a->attribute.format.num_elems_per_value * sizeof_GPU_type(a->attribute.format.type);
3576  for(n = 0; n < a->num_values; n+=4)
3577  {
3578  memcpy(storage_ptr, values_ptr, value_size_bytes);
3579  storage_ptr = (void*)((char*)storage_ptr + a->per_vertex_storage_stride_bytes);
3580  memcpy(storage_ptr, values_ptr, value_size_bytes);
3581  storage_ptr = (void*)((char*)storage_ptr + a->per_vertex_storage_stride_bytes);
3582  memcpy(storage_ptr, values_ptr, value_size_bytes);
3583  storage_ptr = (void*)((char*)storage_ptr + a->per_vertex_storage_stride_bytes);
3584  memcpy(storage_ptr, values_ptr, value_size_bytes);
3585  storage_ptr = (void*)((char*)storage_ptr + a->per_vertex_storage_stride_bytes);
3586 
3587  values_ptr = (void*)((char*)values_ptr + a->attribute.format.stride_bytes);
3588  }
3589  }
3590  }
3591 }
3592 
3593 static void upload_attribute_data(GPU_CONTEXT_DATA* cdata, int num_vertices)
3594 {
3595  int i;
3596  for(i = 0; i < 16; i++)
3597  {
3598  GPU_AttributeSource* a = &cdata->shader_attributes[i];
3599  if(a->attribute.values != NULL && a->attribute.location >= 0 && a->num_values > 0)
3600  {
3601  int num_values_used = num_vertices;
3602  int bytes_used;
3603 
3604  if(a->num_values < num_values_used)
3605  num_values_used = a->num_values;
3606 
3607  glBindBuffer(GL_ARRAY_BUFFER, cdata->attribute_VBO[i]);
3608 
3609  bytes_used = a->per_vertex_storage_stride_bytes * num_values_used;
3611 
3614 
3615  a->enabled = 1;
3616  // Move the data along so we use the next values for the next flush
3617  a->num_values -= num_values_used;
3618  if(a->num_values <= 0)
3620  else
3621  a->next_value = (void*)(((char*)a->next_value) + bytes_used);
3622  }
3623  }
3624 }
3625 
3626 static void disable_attribute_data(GPU_CONTEXT_DATA* cdata)
3627 {
3628  int i;
3629  for(i = 0; i < 16; i++)
3630  {
3631  GPU_AttributeSource* a = &cdata->shader_attributes[i];
3632  if(a->enabled)
3633  {
3635  a->enabled = 0;
3636  }
3637  }
3638 }
3639 
3640 #endif
3641 
3643 {
3644  int lowest = cap;
3645 
3646 #ifdef SDL_GPU_USE_GL_TIER3
3647  int i;
3648  for(i = 0; i < 16; i++)
3649  {
3650  GPU_AttributeSource* a = &cdata->shader_attributes[i];
3651  if(a->attribute.values != NULL && a->attribute.location >= 0)
3652  {
3653  if(a->num_values < lowest)
3654  lowest = a->num_values;
3655  }
3656  }
3657 #endif
3658 
3659  return lowest;
3660 }
3661 
3662 
3663 
3664 // Assumes the right format
3665 static void BlitBatch(GPU_Renderer* renderer, GPU_Image* image, GPU_Target* target, unsigned int num_sprites, float* values, GPU_BlitFlagEnum flags)
3666 {
3667  GPU_CONTEXT_DATA* cdata;
3668  unsigned short* index_buffer;
3669  unsigned int i;
3670 
3671  if(image == NULL)
3672  {
3673  GPU_PushErrorCode("GPU_BlitBatch", GPU_ERROR_NULL_ARGUMENT, "image");
3674  return;
3675  }
3676  if(target == NULL)
3677  {
3678  GPU_PushErrorCode("GPU_BlitBatch", GPU_ERROR_NULL_ARGUMENT, "target");
3679  return;
3680  }
3681  if(renderer != image->renderer || renderer != target->renderer)
3682  {
3683  GPU_PushErrorCode("GPU_BlitBatch", GPU_ERROR_USER_ERROR, "Mismatched renderer");
3684  return;
3685  }
3686 
3687  makeContextCurrent(renderer, target);
3688 
3689  // Bind the texture to which subsequent calls refer
3690  bindTexture(renderer, image);
3691 
3692  // Bind the FBO
3693  if(!bindFramebuffer(renderer, target))
3694  {
3695  GPU_PushErrorCode("GPU_BlitBatch", GPU_ERROR_BACKEND_ERROR, "Failed to bind framebuffer.");
3696  return;
3697  }
3698 
3699  prepareToRenderToTarget(renderer, target);
3700  prepareToRenderImage(renderer, target, image);
3701  changeViewport(target);
3702  changeCamera(target);
3703 
3704  changeTexturing(renderer, 1);
3705 
3706  setClipRect(renderer, target);
3707 
3708  #ifdef SDL_GPU_APPLY_TRANSFORMS_TO_GL_STACK
3709  //if(!renderer->IsFeatureEnabled(GPU_FEATURE_VERTEX_SHADER))
3710  applyTransforms();
3711  #endif
3712 
3713 
3714  cdata = (GPU_CONTEXT_DATA*)renderer->current_context_target->context->data;
3715 
3716  renderer->FlushBlitBuffer(renderer);
3717  // Only need to check the blit buffer because of the VBO storage
3718  if(cdata->blit_buffer_num_vertices + num_sprites*4 >= cdata->blit_buffer_max_num_vertices)
3719  {
3720  if(!growBlitBuffer(cdata, cdata->blit_buffer_num_vertices + num_sprites*4))
3721  {
3722  // Can't do all of these sprites! Only do some of them...
3723  num_sprites = (cdata->blit_buffer_max_num_vertices - cdata->blit_buffer_num_vertices)/4;
3724  }
3725  }
3726  if(cdata->index_buffer_num_vertices + num_sprites*6 >= cdata->index_buffer_max_num_vertices)
3727  {
3728  if(!growIndexBuffer(cdata, cdata->index_buffer_num_vertices + num_sprites*6))
3729  {
3730  // Can't do all of these sprites! Only do some of them...
3731  num_sprites = (cdata->index_buffer_max_num_vertices - cdata->index_buffer_num_vertices)/6;
3732  }
3733  }
3734 
3735  index_buffer = cdata->index_buffer;
3736 
3737  #ifdef SDL_GPU_USE_GL_TIER3
3738  refresh_attribute_data(cdata);
3739  #endif
3740 
3741  // Triangle indices
3742  for(i = 0; i < num_sprites; i++)
3743  {
3744  int buffer_num_vertices = i*4;
3745  // First tri
3746  index_buffer[cdata->index_buffer_num_vertices++] = buffer_num_vertices; // 0
3747  index_buffer[cdata->index_buffer_num_vertices++] = buffer_num_vertices+1; // 1
3748  index_buffer[cdata->index_buffer_num_vertices++] = buffer_num_vertices+2; // 2
3749 
3750  // Second tri
3751  index_buffer[cdata->index_buffer_num_vertices++] = buffer_num_vertices; // 0
3752  index_buffer[cdata->index_buffer_num_vertices++] = buffer_num_vertices+2; // 2
3753  index_buffer[cdata->index_buffer_num_vertices++] = buffer_num_vertices+3; // 3
3754  }
3755 
3756 #ifdef SDL_GPU_USE_GL_TIER1
3757  if(values != NULL)
3758  {
3759  float* vertex_pointer = values;
3760  float* texcoord_pointer = values + GPU_BLIT_BUFFER_TEX_COORD_OFFSET;
3761  float* color_pointer = values + GPU_BLIT_BUFFER_COLOR_OFFSET;
3762 
3763  glBegin(GL_QUADS);
3764  for(i = 0; i < num_sprites; i++)
3765  {
3766  glColor4f( *color_pointer, *(color_pointer+1), *(color_pointer+2), *(color_pointer+3) );
3767  glTexCoord2f( *texcoord_pointer, *(texcoord_pointer+1) );
3768  glVertex3f( *vertex_pointer, *(vertex_pointer+1), 0.0f );
3769  color_pointer += GPU_BLIT_BUFFER_FLOATS_PER_VERTEX;
3770  texcoord_pointer += GPU_BLIT_BUFFER_FLOATS_PER_VERTEX;
3771  vertex_pointer += GPU_BLIT_BUFFER_FLOATS_PER_VERTEX;
3772 
3773  glColor4f( *color_pointer, *(color_pointer+1), *(color_pointer+2), *(color_pointer+3) );
3774  glTexCoord2f( *texcoord_pointer, *(texcoord_pointer+1) );
3775  glVertex3f( *vertex_pointer, *(vertex_pointer+1), 0.0f );
3776  color_pointer += GPU_BLIT_BUFFER_FLOATS_PER_VERTEX;
3777  texcoord_pointer += GPU_BLIT_BUFFER_FLOATS_PER_VERTEX;
3778  vertex_pointer += GPU_BLIT_BUFFER_FLOATS_PER_VERTEX;
3779 
3780  glColor4f( *color_pointer, *(color_pointer+1), *(color_pointer+2), *(color_pointer+3) );
3781  glTexCoord2f( *texcoord_pointer, *(texcoord_pointer+1) );
3782  glVertex3f( *vertex_pointer, *(vertex_pointer+1), 0.0f );
3783  color_pointer += GPU_BLIT_BUFFER_FLOATS_PER_VERTEX;
3784  texcoord_pointer += GPU_BLIT_BUFFER_FLOATS_PER_VERTEX;
3785  vertex_pointer += GPU_BLIT_BUFFER_FLOATS_PER_VERTEX;
3786 
3787  glColor4f( *color_pointer, *(color_pointer+1), *(color_pointer+2), *(color_pointer+3) );
3788  glTexCoord2f( *texcoord_pointer, *(texcoord_pointer+1) );
3789  glVertex3f( *vertex_pointer, *(vertex_pointer+1), 0.0f );
3790  color_pointer += GPU_BLIT_BUFFER_FLOATS_PER_VERTEX;
3791  texcoord_pointer += GPU_BLIT_BUFFER_FLOATS_PER_VERTEX;
3792  vertex_pointer += GPU_BLIT_BUFFER_FLOATS_PER_VERTEX;
3793  }
3794  glEnd();
3795  }
3796 #elif defined(SDL_GPU_USE_GL_TIER2)
3797 
3801 
3802  {
3803  int stride = 8*sizeof(float);
3807  }
3808 
3809  glDrawElements(GL_TRIANGLES, cdata->index_buffer_num_vertices, GL_UNSIGNED_SHORT, cdata->index_buffer);
3810 
3814 
3815 #elif defined(SDL_GPU_USE_GL_TIER3)
3816 
3817  // Upload our modelviewprojection matrix
3818  if(cdata->current_shader_block.modelViewProjection_loc >= 0)
3819  {
3820  float mvp[16];
3822  glUniformMatrix4fv(cdata->current_shader_block.modelViewProjection_loc, 1, 0, mvp);
3823  }
3824 
3825  // Update the vertex array object's buffers
3826  #if !defined(SDL_GPU_NO_VAO)
3827  glBindVertexArray(cdata->blit_VAO);
3828  #endif
3829 
3830  if(values != NULL)
3831  {
3832  // Upload blit buffer to a single buffer object
3833  glBindBuffer(GL_ARRAY_BUFFER, cdata->blit_VBO[cdata->blit_VBO_flop]);
3834  cdata->blit_VBO_flop = !cdata->blit_VBO_flop;
3835 
3836  // Copy the whole blit buffer to the GPU
3837  glBufferSubData(GL_ARRAY_BUFFER, 0, GPU_BLIT_BUFFER_STRIDE * (num_sprites*4), values); // Fills GPU buffer with data.
3838 
3839  // Specify the formatting of the blit buffer
3840  if(cdata->current_shader_block.position_loc >= 0)
3841  {
3842  glEnableVertexAttribArray(cdata->current_shader_block.position_loc); // Tell GL to use client-side attribute data
3843  glVertexAttribPointer(cdata->current_shader_block.position_loc, 2, GL_FLOAT, GL_FALSE, GPU_BLIT_BUFFER_STRIDE, 0); // Tell how the data is formatted
3844  }
3845  if(cdata->current_shader_block.texcoord_loc >= 0)
3846  {
3847  glEnableVertexAttribArray(cdata->current_shader_block.texcoord_loc);
3848  glVertexAttribPointer(cdata->current_shader_block.texcoord_loc, 2, GL_FLOAT, GL_FALSE, GPU_BLIT_BUFFER_STRIDE, (void*)(GPU_BLIT_BUFFER_TEX_COORD_OFFSET * sizeof(float)));
3849  }
3850  if(cdata->current_shader_block.color_loc >= 0)
3851  {
3852  glEnableVertexAttribArray(cdata->current_shader_block.color_loc);
3853  glVertexAttribPointer(cdata->current_shader_block.color_loc, 4, GL_FLOAT, GL_FALSE, GPU_BLIT_BUFFER_STRIDE, (void*)(GPU_BLIT_BUFFER_COLOR_OFFSET * sizeof(float)));
3854  }
3855  }
3856 
3857  upload_attribute_data(cdata, num_sprites*4);
3858 
3859  glDrawElements(GL_TRIANGLES, cdata->index_buffer_num_vertices, GL_UNSIGNED_SHORT, cdata->index_buffer);
3860 
3861  // Disable the vertex arrays again
3862  if(cdata->current_shader_block.position_loc >= 0)
3863  glDisableVertexAttribArray(cdata->current_shader_block.position_loc);
3864  if(cdata->current_shader_block.texcoord_loc >= 0)
3865  glDisableVertexAttribArray(cdata->current_shader_block.texcoord_loc);
3866  if(cdata->current_shader_block.color_loc >= 0)
3867  glDisableVertexAttribArray(cdata->current_shader_block.color_loc);
3868 
3869  disable_attribute_data(cdata);
3870 
3871  #if !defined(SDL_GPU_NO_VAO)
3872  glBindVertexArray(0);
3873  #endif
3874 
3875 #endif
3876 
3877  cdata->blit_buffer_num_vertices = 0;
3878  cdata->index_buffer_num_vertices = 0;
3879 
3880  unsetClipRect(renderer, target);
3881 }
3882 
3883 // Assumes the right format
3884 static void TriangleBatch(GPU_Renderer* renderer, GPU_Image* image, GPU_Target* target, unsigned short num_vertices, float* values, unsigned int num_indices, unsigned short* indices, GPU_BlitFlagEnum flags)
3885 {
3886  GPU_CONTEXT_DATA* cdata;
3887  int stride;
3888 
3889  if(num_vertices == 0)
3890  return;
3891 
3892  if(image == NULL)
3893  {
3894  GPU_PushErrorCode("GPU_TriangleBatch", GPU_ERROR_NULL_ARGUMENT, "image");
3895  return;
3896  }
3897  if(target == NULL)
3898  {
3899  GPU_PushErrorCode("GPU_TriangleBatch", GPU_ERROR_NULL_ARGUMENT, "target");
3900  return;
3901  }
3902  if(renderer != image->renderer || renderer != target->renderer)
3903  {
3904  GPU_PushErrorCode("GPU_TriangleBatch", GPU_ERROR_USER_ERROR, "Mismatched renderer");
3905  return;
3906  }
3907 
3908  makeContextCurrent(renderer, target);
3909 
3910  // Bind the texture to which subsequent calls refer
3911  bindTexture(renderer, image);
3912 
3913  // Bind the FBO
3914  if(!bindFramebuffer(renderer, target))
3915  {
3916  GPU_PushErrorCode("GPU_TriangleBatch", GPU_ERROR_BACKEND_ERROR, "Failed to bind framebuffer.");
3917  return;
3918  }
3919 
3920  prepareToRenderToTarget(renderer, target);
3921  prepareToRenderImage(renderer, target, image);
3922  changeViewport(target);
3923  changeCamera(target);
3924 
3925  changeTexturing(renderer, 1);
3926 
3927  setClipRect(renderer, target);
3928 
3929  #ifdef SDL_GPU_APPLY_TRANSFORMS_TO_GL_STACK
3930  //if(!renderer->IsFeatureEnabled(GPU_FEATURE_VERTEX_SHADER))
3931  applyTransforms();
3932  #endif
3933 
3934 
3935  cdata = (GPU_CONTEXT_DATA*)renderer->current_context_target->context->data;
3936 
3937  renderer->FlushBlitBuffer(renderer);
3938 
3939  if(cdata->index_buffer_num_vertices + num_indices >= cdata->index_buffer_max_num_vertices)
3940  {
3941  growBlitBuffer(cdata, cdata->index_buffer_num_vertices + num_indices);
3942  }
3943  if(cdata->blit_buffer_num_vertices + num_vertices >= cdata->blit_buffer_max_num_vertices)
3944  {
3945  growBlitBuffer(cdata, cdata->blit_buffer_num_vertices + num_vertices);
3946  }
3947 
3948  // Only need to check the blit buffer because of the VBO storage
3949  if(cdata->blit_buffer_num_vertices + num_vertices >= cdata->blit_buffer_max_num_vertices)
3950  {
3951  if(!growBlitBuffer(cdata, cdata->blit_buffer_num_vertices + num_vertices))
3952  {
3953  // Can't do all of these sprites! Only do some of them...
3954  num_vertices = (cdata->blit_buffer_max_num_vertices - cdata->blit_buffer_num_vertices);
3955  }
3956  }
3957  if(cdata->index_buffer_num_vertices + num_indices >= cdata->index_buffer_max_num_vertices)
3958  {
3959  if(!growIndexBuffer(cdata, cdata->index_buffer_num_vertices + num_indices))
3960  {
3961  // Can't do all of these sprites! Only do some of them...
3962  num_indices = (cdata->index_buffer_max_num_vertices - cdata->index_buffer_num_vertices);
3963  }
3964  }
3965 
3966  #ifdef SDL_GPU_USE_GL_TIER3
3967  refresh_attribute_data(cdata);
3968  #endif
3969 
3970  stride = GPU_BLIT_BUFFER_STRIDE;
3971  (void)stride;
3972  if(indices == NULL)
3973  num_indices = num_vertices;
3974 
3975 
3976 #ifdef SDL_GPU_USE_GL_TIER1
3977  if(values != NULL)
3978  {
3979  int i;
3980  float* vertex_pointer = values;
3981  float* texcoord_pointer = values + 2;
3982  float* color_pointer = values + 4;
3983 
3984  glBegin(GL_QUADS);
3985  for(i = 0; i < num_vertices; i+=3)
3986  {
3987  glColor4f( *color_pointer, *(color_pointer+1), *(color_pointer+2), *(color_pointer+3) );
3988  glTexCoord2f( *texcoord_pointer, *(texcoord_pointer+1) );
3989  glVertex3f( *vertex_pointer, *(vertex_pointer+1), 0.0f );
3990  color_pointer += GPU_BLIT_BUFFER_FLOATS_PER_VERTEX;
3991  texcoord_pointer += GPU_BLIT_BUFFER_FLOATS_PER_VERTEX;
3992  vertex_pointer += GPU_BLIT_BUFFER_FLOATS_PER_VERTEX;
3993 
3994  glColor4f( *color_pointer, *(color_pointer+1), *(color_pointer+2), *(color_pointer+3) );
3995  glTexCoord2f( *texcoord_pointer, *(texcoord_pointer+1) );
3996  glVertex3f( *vertex_pointer, *(vertex_pointer+1), 0.0f );
3997  color_pointer += GPU_BLIT_BUFFER_FLOATS_PER_VERTEX;
3998  texcoord_pointer += GPU_BLIT_BUFFER_FLOATS_PER_VERTEX;
3999  vertex_pointer += GPU_BLIT_BUFFER_FLOATS_PER_VERTEX;
4000 
4001  glColor4f( *color_pointer, *(color_pointer+1), *(color_pointer+2), *(color_pointer+3) );
4002  glTexCoord2f( *texcoord_pointer, *(texcoord_pointer+1) );
4003  glVertex3f( *vertex_pointer, *(vertex_pointer+1), 0.0f );
4004  color_pointer += GPU_BLIT_BUFFER_FLOATS_PER_VERTEX;
4005  texcoord_pointer += GPU_BLIT_BUFFER_FLOATS_PER_VERTEX;
4006  vertex_pointer += GPU_BLIT_BUFFER_FLOATS_PER_VERTEX;
4007 
4008  glColor4f( *color_pointer, *(color_pointer+1), *(color_pointer+2), *(color_pointer+3) );
4009  glTexCoord2f( *texcoord_pointer, *(texcoord_pointer+1) );
4010  glVertex3f( *vertex_pointer, *(vertex_pointer+1), 0.0f );
4011  color_pointer += GPU_BLIT_BUFFER_FLOATS_PER_VERTEX;
4012  texcoord_pointer += GPU_BLIT_BUFFER_FLOATS_PER_VERTEX;
4013  vertex_pointer += GPU_BLIT_BUFFER_FLOATS_PER_VERTEX;
4014  }
4015  glEnd();
4016  }
4017 #elif defined(SDL_GPU_USE_GL_TIER2)
4018 
4022 
4023  glVertexPointer(2, GL_FLOAT, stride, values);
4024  glTexCoordPointer(2, GL_FLOAT, stride, values + 2);
4025  glColorPointer(4, GL_FLOAT, stride, values + 4);
4026 
4027  if(indices == NULL)
4028  glDrawArrays(GL_TRIANGLES, 0, num_indices);
4029  else
4030  glDrawElements(GL_TRIANGLES, num_indices, GL_UNSIGNED_SHORT, indices);
4031 
4035 
4036 #elif defined(SDL_GPU_USE_GL_TIER3)
4037 
4038  // Upload our modelviewprojection matrix
4039  if(cdata->current_shader_block.modelViewProjection_loc >= 0)
4040  {
4041  float mvp[16];
4043  glUniformMatrix4fv(cdata->current_shader_block.modelViewProjection_loc, 1, 0, mvp);
4044  }
4045 
4046  // Update the vertex array object's buffers
4047  #if !defined(SDL_GPU_NO_VAO)
4048  glBindVertexArray(cdata->blit_VAO);
4049  #endif
4050 
4051  if(values != NULL)
4052  {
4053  // Upload blit buffer to a single buffer object
4054  glBindBuffer(GL_ARRAY_BUFFER, cdata->blit_VBO[cdata->blit_VBO_flop]);
4055  cdata->blit_VBO_flop = !cdata->blit_VBO_flop;
4056 
4057  // Copy the whole blit buffer to the GPU
4058  glBufferSubData(GL_ARRAY_BUFFER, 0, stride * num_vertices, values); // Fills GPU buffer with data.
4059 
4060  // Specify the formatting of the blit buffer
4061  if(cdata->current_shader_block.position_loc >= 0)
4062  {
4063  glEnableVertexAttribArray(cdata->current_shader_block.position_loc); // Tell GL to use client-side attribute data
4064  glVertexAttribPointer(cdata->current_shader_block.position_loc, 2, GL_FLOAT, GL_FALSE, stride, 0); // Tell how the data is formatted
4065  }
4066  if(cdata->current_shader_block.texcoord_loc >= 0)
4067  {
4068  glEnableVertexAttribArray(cdata->current_shader_block.texcoord_loc);
4069  glVertexAttribPointer(cdata->current_shader_block.texcoord_loc, 2, GL_FLOAT, GL_FALSE, stride, (void*)(2 * sizeof(float)));
4070  }
4071  if(cdata->current_shader_block.color_loc >= 0)
4072  {
4073  glEnableVertexAttribArray(cdata->current_shader_block.color_loc);
4074  glVertexAttribPointer(cdata->current_shader_block.color_loc, 4, GL_FLOAT, GL_FALSE, stride, (void*)(4 * sizeof(float)));
4075  }
4076  }
4077 
4078  upload_attribute_data(cdata, num_indices);
4079 
4080  if(indices == NULL)
4081  glDrawArrays(GL_TRIANGLES, 0, num_indices);
4082  else
4083  glDrawElements(GL_TRIANGLES, num_indices, GL_UNSIGNED_SHORT, indices);
4084 
4085  // Disable the vertex arrays again
4086  if(cdata->current_shader_block.position_loc >= 0)
4087  glDisableVertexAttribArray(cdata->current_shader_block.position_loc);
4088  if(cdata->current_shader_block.texcoord_loc >= 0)
4089  glDisableVertexAttribArray(cdata->current_shader_block.texcoord_loc);
4090  if(cdata->current_shader_block.color_loc >= 0)
4091  glDisableVertexAttribArray(cdata->current_shader_block.color_loc);
4092 
4093  disable_attribute_data(cdata);
4094 
4095  #if !defined(SDL_GPU_NO_VAO)
4096  glBindVertexArray(0);
4097  #endif
4098 
4099 #endif
4100 
4101  cdata->blit_buffer_num_vertices = 0;
4102  cdata->index_buffer_num_vertices = 0;
4103 
4104  unsetClipRect(renderer, target);
4105 }
4106 
4108 {
4109  #ifndef __IPHONEOS__
4110  GLint filter;
4111  if(image == NULL)
4112  return;
4113 
4114  if(image->target != NULL && isCurrentTarget(renderer, image->target))
4115  renderer->FlushBlitBuffer(renderer);
4116  bindTexture(renderer, image);
4118  image->has_mipmaps = 1;
4119 
4121  if(filter == GL_LINEAR)
4123  #endif
4124 }
4125 
4126 
4127 
4128 
4129 static GPU_Rect SetClip(GPU_Renderer* renderer, GPU_Target* target, Sint16 x, Sint16 y, Uint16 w, Uint16 h)
4130 {
4131  GPU_Rect r;
4132  if(target == NULL)
4133  {
4134  GPU_Rect r = {0,0,0,0};
4135  return r;
4136  }
4137 
4138  if(isCurrentTarget(renderer, target))
4139  renderer->FlushBlitBuffer(renderer);
4140  target->use_clip_rect = 1;
4141 
4142  r = target->clip_rect;
4143 
4144  target->clip_rect.x = x;
4145  target->clip_rect.y = y;
4146  target->clip_rect.w = w;
4147  target->clip_rect.h = h;
4148 
4149  return r;
4150 }
4151 
4152 static void UnsetClip(GPU_Renderer* renderer, GPU_Target* target)
4153 {
4154  if(target == NULL)
4155  return;
4156 
4157  makeContextCurrent(renderer, target);
4158 
4159  if(isCurrentTarget(renderer, target))
4160  renderer->FlushBlitBuffer(renderer);
4161  // Leave the clip rect values intact so they can still be useful as storage
4162  target->use_clip_rect = 0;
4163 }
4164 
4165 
4166 
4167 
4168 
4169 
4170 static SDL_Color GetPixel(GPU_Renderer* renderer, GPU_Target* target, Sint16 x, Sint16 y)
4171 {
4172  SDL_Color result = {0,0,0,0};
4173  if(target == NULL)
4174  return result;
4175  if(renderer != target->renderer)
4176  return result;
4177  if(x < 0 || y < 0 || x >= target->w || y >= target->h)
4178  return result;
4179 
4180  if(isCurrentTarget(renderer, target))
4181  renderer->FlushBlitBuffer(renderer);
4182  if(bindFramebuffer(renderer, target))
4183  {
4184  unsigned char pixels[4];
4185  glReadPixels(x, y, 1, 1, ((GPU_TARGET_DATA*)target->data)->format, GL_UNSIGNED_BYTE, pixels);
4186 
4187  result.r = pixels[0];
4188  result.g = pixels[1];
4189  result.b = pixels[2];
4190  GET_ALPHA(result) = pixels[3];
4191  }
4192 
4193  return result;
4194 }
4195 
4197 {
4198  GLenum minFilter, magFilter;
4199 
4200  if(image == NULL)
4201  {
4202  GPU_PushErrorCode("GPU_SetImageFilter", GPU_ERROR_NULL_ARGUMENT, "image");
4203  return;
4204  }
4205  if(renderer != image->renderer)
4206  {
4207  GPU_PushErrorCode("GPU_SetImageFilter", GPU_ERROR_USER_ERROR, "Mismatched renderer");
4208  return;
4209  }
4210 
4211  switch(filter)
4212  {
4213  case GPU_FILTER_NEAREST:
4214  minFilter = GL_NEAREST;
4215  magFilter = GL_NEAREST;
4216  break;
4217  case GPU_FILTER_LINEAR:
4218  if(image->has_mipmaps)
4219  minFilter = GL_LINEAR_MIPMAP_NEAREST;
4220  else
4221  minFilter = GL_LINEAR;
4222 
4223  magFilter = GL_LINEAR;
4224  break;
4226  if(image->has_mipmaps)
4227  minFilter = GL_LINEAR_MIPMAP_LINEAR;
4228  else
4229  minFilter = GL_LINEAR;
4230 
4231  magFilter = GL_LINEAR;
4232  break;
4233  default:
4234  GPU_PushErrorCode("GPU_SetImageFilter", GPU_ERROR_USER_ERROR, "Unsupported value for filter (0x%x)", filter);
4235  return;
4236  }
4237 
4238  flushBlitBufferIfCurrentTexture(renderer, image);
4239  bindTexture(renderer, image);
4240 
4241  image->filter_mode = filter;
4242 
4245 }
4246 
4247 static void SetWrapMode(GPU_Renderer* renderer, GPU_Image* image, GPU_WrapEnum wrap_mode_x, GPU_WrapEnum wrap_mode_y)
4248 {
4249  GLenum wrap_x, wrap_y;
4250 
4251  if(image == NULL)
4252  {
4253  GPU_PushErrorCode("GPU_SetWrapMode", GPU_ERROR_NULL_ARGUMENT, "image");
4254  return;
4255  }
4256  if(renderer != image->renderer)
4257  {
4258  GPU_PushErrorCode("GPU_SetWrapMode", GPU_ERROR_USER_ERROR, "Mismatched renderer");
4259  return;
4260  }
4261 
4262  switch(wrap_mode_x)
4263  {
4264  case GPU_WRAP_NONE:
4265  wrap_x = GL_CLAMP_TO_EDGE;
4266  break;
4267  case GPU_WRAP_REPEAT:
4268  wrap_x = GL_REPEAT;
4269  break;
4270  case GPU_WRAP_MIRRORED:
4272  wrap_x = GL_MIRRORED_REPEAT;
4273  else
4274  {
4275  GPU_PushErrorCode("GPU_SetWrapMode", GPU_ERROR_BACKEND_ERROR, "This renderer does not support GPU_WRAP_MIRRORED.");
4276  return;
4277  }
4278  break;
4279  default:
4280  GPU_PushErrorCode("GPU_SetWrapMode", GPU_ERROR_USER_ERROR, "Unsupported value for wrap_mode_x (0x%x)", wrap_mode_x);
4281  return;
4282  }
4283 
4284  switch(wrap_mode_y)
4285  {
4286  case GPU_WRAP_NONE:
4287  wrap_y = GL_CLAMP_TO_EDGE;
4288  break;
4289  case GPU_WRAP_REPEAT:
4290  wrap_y = GL_REPEAT;
4291  break;
4292  case GPU_WRAP_MIRRORED:
4294  wrap_y = GL_MIRRORED_REPEAT;
4295  else
4296  {
4297  GPU_PushErrorCode("GPU_SetWrapMode", GPU_ERROR_BACKEND_ERROR, "This renderer does not support GPU_WRAP_MIRRORED.");
4298  return;
4299  }
4300  break;
4301  default:
4302  GPU_PushErrorCode("GPU_SetWrapMode", GPU_ERROR_USER_ERROR, "Unsupported value for wrap_mode_y (0x%x)", wrap_mode_y);
4303  return;
4304  }
4305 
4306  flushBlitBufferIfCurrentTexture(renderer, image);
4307  bindTexture(renderer, image);
4308 
4309  image->wrap_mode_x = wrap_mode_x;
4310  image->wrap_mode_y = wrap_mode_y;
4311 
4314 }
4315 
4316 
4317 
4318 
4319 
4320 static void Clear(GPU_Renderer* renderer, GPU_Target* target)
4321 {
4322  if(target == NULL)
4323  return;
4324  if(renderer != target->renderer)
4325  return;
4326 
4327  makeContextCurrent(renderer, target);
4328 
4329  if(isCurrentTarget(renderer, target))
4330  renderer->FlushBlitBuffer(renderer);
4331  if(bindFramebuffer(renderer, target))
4332  {
4333  setClipRect(renderer, target);
4334 
4335  glClearColor(0,0,0,0);
4337 
4338  unsetClipRect(renderer, target);
4339  }
4340 }
4341 
4342 
4343 static void ClearRGBA(GPU_Renderer* renderer, GPU_Target* target, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
4344 {
4345  if(target == NULL)
4346  return;
4347  if(renderer != target->renderer)
4348  return;
4349 
4350  makeContextCurrent(renderer, target);
4351 
4352  if(isCurrentTarget(renderer, target))
4353  renderer->FlushBlitBuffer(renderer);
4354  if(bindFramebuffer(renderer, target))
4355  {
4356  setClipRect(renderer, target);
4357 
4358  glClearColor(r/255.0f, g/255.0f, b/255.0f, a/255.0f);
4360 
4361  unsetClipRect(renderer, target);
4362  }
4363 }
4364 
4365 static void DoPartialFlush(GPU_CONTEXT_DATA* cdata, unsigned short num_vertices, float* blit_buffer, unsigned int num_indices, unsigned short* index_buffer)
4366 {
4367 #ifdef SDL_GPU_USE_GL_TIER1
4368 
4369  unsigned short i;
4370  float* vertex_pointer = blit_buffer + GPU_BLIT_BUFFER_VERTEX_OFFSET;
4371  float* texcoord_pointer = blit_buffer + GPU_BLIT_BUFFER_TEX_COORD_OFFSET;
4372 
4373  glBegin(cdata->last_shape);
4374  for(i = 0; i < num_vertices; i++)
4375  {
4376  glTexCoord2f( *texcoord_pointer, *(texcoord_pointer+1) );
4377  glVertex3f( *vertex_pointer, *(vertex_pointer+1), 0.0f );
4378  texcoord_pointer += GPU_BLIT_BUFFER_FLOATS_PER_VERTEX;
4379  vertex_pointer += GPU_BLIT_BUFFER_FLOATS_PER_VERTEX;
4380  }
4381  glEnd();
4382 #elif defined(SDL_GPU_USE_GL_TIER2)
4383 
4386  glVertexPointer(2, GL_FLOAT, GPU_BLIT_BUFFER_STRIDE, blit_buffer + GPU_BLIT_BUFFER_VERTEX_OFFSET);
4387  glTexCoordPointer(2, GL_FLOAT, GPU_BLIT_BUFFER_STRIDE, blit_buffer + GPU_BLIT_BUFFER_TEX_COORD_OFFSET);
4388 
4389  glDrawElements(cdata->last_shape, num_indices, GL_UNSIGNED_SHORT, index_buffer);
4390 
4393 
4394 #elif defined(SDL_GPU_USE_GL_TIER3)
4395 
4396  // Upload our modelviewprojection matrix
4397  if(cdata->current_shader_block.modelViewProjection_loc >= 0)
4398  {
4399  float mvp[16];
4401  glUniformMatrix4fv(cdata->current_shader_block.modelViewProjection_loc, 1, 0, mvp);
4402  }
4403 
4404  // Update the vertex array object's buffers
4405  #if !defined(SDL_GPU_NO_VAO)
4406  glBindVertexArray(cdata->blit_VAO);
4407  #endif
4408 
4409  // Upload blit buffer to a single buffer object
4410  glBindBuffer(GL_ARRAY_BUFFER, cdata->blit_VBO[cdata->blit_VBO_flop]);
4411  cdata->blit_VBO_flop = !cdata->blit_VBO_flop;
4412 
4413  // Copy the whole blit buffer to the GPU
4414  glBufferSubData(GL_ARRAY_BUFFER, 0, GPU_BLIT_BUFFER_STRIDE * num_vertices, blit_buffer); // Fills GPU buffer with data.
4415 
4416  // Specify the formatting of the blit buffer
4417  if(cdata->current_shader_block.position_loc >= 0)
4418  {
4419  glEnableVertexAttribArray(cdata->current_shader_block.position_loc); // Tell GL to use client-side attribute data
4420  glVertexAttribPointer(cdata->current_shader_block.position_loc, 2, GL_FLOAT, GL_FALSE, GPU_BLIT_BUFFER_STRIDE, 0); // Tell how the data is formatted
4421  }
4422  if(cdata->current_shader_block.texcoord_loc >= 0)
4423  {
4424  glEnableVertexAttribArray(cdata->current_shader_block.texcoord_loc);
4425  glVertexAttribPointer(cdata->current_shader_block.texcoord_loc, 2, GL_FLOAT, GL_FALSE, GPU_BLIT_BUFFER_STRIDE, (void*)(GPU_BLIT_BUFFER_TEX_COORD_OFFSET * sizeof(float)));
4426  }
4427  if(cdata->current_shader_block.color_loc >= 0)
4428  {
4429  glEnableVertexAttribArray(cdata->current_shader_block.color_loc);
4430  glVertexAttribPointer(cdata->current_shader_block.color_loc, 4, GL_FLOAT, GL_FALSE, GPU_BLIT_BUFFER_STRIDE, (void*)(GPU_BLIT_BUFFER_COLOR_OFFSET * sizeof(float)));
4431  }
4432 
4433  upload_attribute_data(cdata, num_vertices);
4434 
4435  glDrawElements(cdata->last_shape, num_indices, GL_UNSIGNED_SHORT, index_buffer);
4436 
4437  // Disable the vertex arrays again
4438  if(cdata->current_shader_block.position_loc >= 0)
4439  glDisableVertexAttribArray(cdata->current_shader_block.position_loc);
4440  if(cdata->current_shader_block.texcoord_loc >= 0)
4441  glDisableVertexAttribArray(cdata->current_shader_block.texcoord_loc);
4442  if(cdata->current_shader_block.color_loc >= 0)
4443  glDisableVertexAttribArray(cdata->current_shader_block.color_loc);
4444 
4445  disable_attribute_data(cdata);
4446 
4447  #if !defined(SDL_GPU_NO_VAO)
4448  glBindVertexArray(0);
4449  #endif
4450 
4451 #endif
4452 }
4453 
4454 static void DoUntexturedFlush(GPU_CONTEXT_DATA* cdata, unsigned short num_vertices, float* blit_buffer, unsigned int num_indices, unsigned short* index_buffer)
4455 {
4456 #ifdef SDL_GPU_USE_GL_TIER1
4457 
4458  unsigned short i;
4459  float* vertex_pointer = blit_buffer + GPU_BLIT_BUFFER_VERTEX_OFFSET;
4460  float* color_pointer = blit_buffer + GPU_BLIT_BUFFER_COLOR_OFFSET;
4461 
4462  glBegin(cdata->last_shape);
4463  for(i = 0; i < num_vertices; i++)
4464  {
4465  glColor4f( *color_pointer, *(color_pointer+1), *(color_pointer+2), *(color_pointer+3) );
4466  glVertex3f( *vertex_pointer, *(vertex_pointer+1), 0.0f );
4467  color_pointer += GPU_BLIT_BUFFER_FLOATS_PER_VERTEX;
4468  vertex_pointer += GPU_BLIT_BUFFER_FLOATS_PER_VERTEX;
4469  }
4470  glEnd();
4471 #elif defined(SDL_GPU_USE_GL_TIER2)
4472 
4475 
4476  glVertexPointer(2, GL_FLOAT, GPU_BLIT_BUFFER_STRIDE, blit_buffer + GPU_BLIT_BUFFER_VERTEX_OFFSET);
4477  glColorPointer(4, GL_FLOAT, GPU_BLIT_BUFFER_STRIDE, blit_buffer + GPU_BLIT_BUFFER_COLOR_OFFSET);
4478 
4479  glDrawElements(cdata->last_shape, num_indices, GL_UNSIGNED_SHORT, index_buffer);
4480 
4483 
4484 #elif defined(SDL_GPU_USE_GL_TIER3)
4485 
4486  // Upload our modelviewprojection matrix
4487  if(cdata->current_shader_block.modelViewProjection_loc >= 0)
4488  {
4489  float mvp[16];
4491  glUniformMatrix4fv(cdata->current_shader_block.modelViewProjection_loc, 1, 0, mvp);
4492  }
4493 
4494  // Update the vertex array object's buffers
4495  #if !defined(SDL_GPU_NO_VAO)
4496  glBindVertexArray(cdata->blit_VAO);
4497  #endif
4498 
4499  // Upload blit buffer to a single buffer object
4500  glBindBuffer(GL_ARRAY_BUFFER, cdata->blit_VBO[cdata->blit_VBO_flop]);
4501  cdata->blit_VBO_flop = !cdata->blit_VBO_flop;
4502 
4503  // Copy the whole blit buffer to the GPU
4504  glBufferSubData(GL_ARRAY_BUFFER, 0, GPU_BLIT_BUFFER_STRIDE * num_vertices, blit_buffer); // Fills GPU buffer with data.
4505 
4506  // Specify the formatting of the blit buffer
4507  if(cdata->current_shader_block.position_loc >= 0)
4508  {
4509  glEnableVertexAttribArray(cdata->current_shader_block.position_loc); // Tell GL to use client-side attribute data
4510  glVertexAttribPointer(cdata->current_shader_block.position_loc, 2, GL_FLOAT, GL_FALSE, GPU_BLIT_BUFFER_STRIDE, 0); // Tell how the data is formatted
4511  }
4512  if(cdata->current_shader_block.color_loc >= 0)
4513  {
4514  glEnableVertexAttribArray(cdata->current_shader_block.color_loc);
4515  glVertexAttribPointer(cdata->current_shader_block.color_loc, 4, GL_FLOAT, GL_FALSE, GPU_BLIT_BUFFER_STRIDE, (void*)(GPU_BLIT_BUFFER_COLOR_OFFSET * sizeof(float)));
4516  }
4517 
4518  upload_attribute_data(cdata, num_vertices);
4519 
4520  glDrawElements(cdata->last_shape, num_indices, GL_UNSIGNED_SHORT, index_buffer);
4521 
4522  // Disable the vertex arrays again
4523  if(cdata->current_shader_block.position_loc >= 0)
4524  glDisableVertexAttribArray(cdata->current_shader_block.position_loc);
4525  if(cdata->current_shader_block.color_loc >= 0)
4526  glDisableVertexAttribArray(cdata->current_shader_block.color_loc);
4527 
4528  disable_attribute_data(cdata);
4529 
4530  #if !defined(SDL_GPU_NO_VAO)
4531  glBindVertexArray(0);
4532  #endif
4533 
4534 #endif
4535 }
4536 
4537 #define MAX(a, b) ((a) > (b)? (a) : (b))
4538 
4539 static void FlushBlitBuffer(GPU_Renderer* renderer)
4540 {
4542  if(cdata->blit_buffer_num_vertices > 0 && cdata->last_target != NULL)
4543  {
4544  GPU_Target* dest = cdata->last_target;
4545  int num_vertices;
4546  int num_indices;
4547  float* blit_buffer;
4548  unsigned short* index_buffer;
4549 
4550  changeViewport(dest);
4551  changeCamera(dest);
4552 
4553  applyTexturing(renderer);
4554 
4555  #ifdef SDL_GPU_APPLY_TRANSFORMS_TO_GL_STACK
4556  //if(!renderer->IsFeatureEnabled(GPU_FEATURE_VERTEX_SHADER))
4557  applyTransforms();
4558  #endif
4559 
4560  setClipRect(renderer, dest);
4561 
4562  #ifdef SDL_GPU_USE_GL_TIER3
4563  refresh_attribute_data(cdata);
4564  #endif
4565 
4566  blit_buffer = cdata->blit_buffer;
4567  index_buffer = cdata->index_buffer;
4568 
4569  if(cdata->last_use_texturing)
4570  {
4571  while(cdata->blit_buffer_num_vertices > 0)
4572  {
4573  num_vertices = MAX(cdata->blit_buffer_num_vertices, get_lowest_attribute_num_values(cdata, cdata->blit_buffer_num_vertices));
4574  num_indices = num_vertices * 3 / 2; // 6 indices per sprite / 4 vertices per sprite = 3/2
4575 
4576  DoPartialFlush(cdata, num_vertices, blit_buffer, num_indices, index_buffer);
4577 
4578  cdata->blit_buffer_num_vertices -= num_vertices;
4579  // Move our pointers ahead
4580  blit_buffer += GPU_BLIT_BUFFER_FLOATS_PER_VERTEX*num_vertices;
4581  index_buffer += num_indices;
4582  }
4583  }
4584  else
4585  {
4586  DoUntexturedFlush(cdata, cdata->blit_buffer_num_vertices, blit_buffer, cdata->index_buffer_num_vertices, index_buffer);
4587  }
4588 
4589  cdata->blit_buffer_num_vertices = 0;
4590  cdata->index_buffer_num_vertices = 0;
4591 
4592  unsetClipRect(renderer, dest);
4593  }
4594 }
4595 
4596 static void Flip(GPU_Renderer* renderer, GPU_Target* target)
4597 {
4598  renderer->FlushBlitBuffer(renderer);
4599 
4600  makeContextCurrent(renderer, target);
4601 
4602 #ifdef SDL_GPU_USE_SDL2
4603  SDL_GL_SwapWindow(SDL_GetWindowFromID(renderer->current_context_target->context->windowID));
4604 #else
4605  SDL_GL_SwapBuffers();
4606 #endif
4607 
4608  #ifdef SDL_GPU_USE_OPENGL
4609  if(vendor_is_Intel)
4610  apply_Intel_attrib_workaround = 1;
4611  #endif
4612 }
4613 
4614 
4615 
4616 
4617 // Shader API
4618 
4619 
4620 #include <string.h>
4621 
4622 // On some platforms (e.g. Android), it might not be possible to just create a rwops and get the expected #included files.
4623 // To do it, I might want to add an optional argument that specifies a base directory to prepend to #include file names.
4624 
4625 static Uint32 GetShaderSourceSize(const char* filename);
4626 static Uint32 GetShaderSource(const char* filename, char* result);
4627 
4628 static void read_until_end_of_comment(SDL_RWops* rwops, char multiline)
4629 {
4630  char buffer;
4631  while(SDL_RWread(rwops, &buffer, 1, 1) > 0)
4632  {
4633  if(!multiline)
4634  {
4635  if(buffer == '\n')
4636  break;
4637  }
4638  else
4639  {
4640  if(buffer == '*')
4641  {
4642  // If the stream ends at the next character or it is a '/', then we're done.
4643  if(SDL_RWread(rwops, &buffer, 1, 1) <= 0 || buffer == '/')
4644  break;
4645  }
4646  }
4647  }
4648 }
4649 
4650 static Uint32 GetShaderSourceSize_RW(SDL_RWops* shader_source)
4651 {
4652  Uint32 size;
4653  char last_char;
4654  char buffer[512];
4655  long len;
4656 
4657  if(shader_source == NULL)
4658  return 0;
4659 
4660  size = 0;
4661 
4662  // Read 1 byte at a time until we reach the end
4663  last_char = ' ';
4664  len = 0;
4665  while((len = SDL_RWread(shader_source, &buffer, 1, 1)) > 0)
4666  {
4667  // Follow through an #include directive?
4668  if(buffer[0] == '#')
4669  {
4670  // Get the rest of the line
4671  int line_size = 1;
4672  unsigned long line_len;
4673  char* token;
4674  while((line_len = SDL_RWread(shader_source, buffer+line_size, 1, 1)) > 0)
4675  {
4676  line_size += line_len;
4677  if(buffer[line_size - line_len] == '\n')
4678  break;
4679  }
4680  buffer[line_size] = '\0';
4681 
4682  // Is there "include" after '#'?
4683  token = strtok(buffer, "# \t");
4684 
4685  if(token != NULL && strcmp(token, "include") == 0)
4686  {
4687  // Get filename token
4688  token = strtok(NULL, "\""); // Skip the empty token before the quote
4689  if(token != NULL)
4690  {
4691  // Add the size of the included file and a newline character
4692  size += GetShaderSourceSize(token) + 1;
4693  }
4694  }
4695  else
4696  size += line_size;
4697  last_char = ' ';
4698  continue;
4699  }
4700 
4701  size += len;
4702 
4703  if(last_char == '/')
4704  {
4705  if(buffer[0] == '/')
4706  {
4707  read_until_end_of_comment(shader_source, 0);
4708  size++; // For the end of the comment
4709  }
4710  else if(buffer[0] == '*')
4711  {
4712  read_until_end_of_comment(shader_source, 1);
4713  size += 2; // For the end of the comments
4714  }
4715  last_char = ' ';
4716  }
4717  else
4718  last_char = buffer[0];
4719  }
4720 
4721  // Go back to the beginning of the stream
4722  SDL_RWseek(shader_source, 0, SEEK_SET);
4723  return size;
4724 }
4725 
4726 
4727 static Uint32 GetShaderSource_RW(SDL_RWops* shader_source, char* result)
4728 {
4729  Uint32 size;
4730  char last_char;
4731  char buffer[512];
4732  long len;
4733 
4734  if(shader_source == NULL)
4735  {
4736  result[0] = '\0';
4737  return 0;
4738  }
4739 
4740  size = 0;
4741 
4742  // Read 1 byte at a time until we reach the end
4743  last_char = ' ';
4744  len = 0;
4745  while((len = SDL_RWread(shader_source, &buffer, 1, 1)) > 0)
4746  {
4747  // Follow through an #include directive?
4748  if(buffer[0] == '#')
4749  {
4750  // Get the rest of the line
4751  int line_size = 1;
4752  unsigned long line_len;
4753  char token_buffer[512]; // strtok() is destructive
4754  char* token;
4755  while((line_len = SDL_RWread(shader_source, buffer+line_size, 1, 1)) > 0)
4756  {
4757  line_size += line_len;
4758  if(buffer[line_size - line_len] == '\n')
4759  break;
4760  }
4761 
4762  // Is there "include" after '#'?
4763  memcpy(token_buffer, buffer, line_size+1);
4764  token_buffer[line_size] = '\0';
4765  token = strtok(token_buffer, "# \t");
4766 
4767  if(token != NULL && strcmp(token, "include") == 0)
4768  {
4769  // Get filename token
4770  token = strtok(NULL, "\""); // Skip the empty token before the quote
4771  if(token != NULL)
4772  {
4773  // Add the size of the included file and a newline character
4774  size += GetShaderSource(token, result + size);
4775  result[size] = '\n';
4776  size++;
4777  }
4778  }
4779  else
4780  {
4781  memcpy(result + size, buffer, line_size);
4782  size += line_size;
4783  }
4784  last_char = ' ';
4785  continue;
4786  }
4787 
4788  memcpy(result + size, buffer, len);
4789  size += len;
4790 
4791  if(last_char == '/')
4792  {
4793  if(buffer[0] == '/')
4794  {
4795  read_until_end_of_comment(shader_source, 0);
4796  memcpy(result + size, "\n", 1);
4797  size++;
4798  }
4799  else if(buffer[0] == '*')
4800  {
4801  read_until_end_of_comment(shader_source, 1);
4802  memcpy(result + size, "*/", 2);
4803  size += 2;
4804  }
4805  last_char = ' ';
4806  }
4807  else
4808  last_char = buffer[0];
4809  }
4810  result[size] = '\0';
4811 
4812  // Go back to the beginning of the stream
4813  SDL_RWseek(shader_source, 0, SEEK_SET);
4814  return size;
4815 }
4816 
4817 static Uint32 GetShaderSource(const char* filename, char* result)
4818 {
4819  SDL_RWops* rwops;
4820  Uint32 size;
4821 
4822  if(filename == NULL)
4823  return 0;
4824  rwops = SDL_RWFromFile(filename, "r");
4825 
4826  size = GetShaderSource_RW(rwops, result);
4827 
4828  SDL_RWclose(rwops);
4829  return size;
4830 }
4831 
4832 static Uint32 GetShaderSourceSize(const char* filename)
4833 {
4834  SDL_RWops* rwops;
4835  Uint32 result;
4836 
4837  if(filename == NULL)
4838  return 0;
4839  rwops = SDL_RWFromFile(filename, "r");
4840 
4841  result = GetShaderSourceSize_RW(rwops);
4842 
4843  SDL_RWclose(rwops);
4844  return result;
4845 }
4846 
4847 static char shader_message[256];
4848 
4849 
4850 static Uint32 compile_shader_source(GPU_ShaderEnum shader_type, const char* shader_source)
4851 {
4852  // Create the proper new shader object
4853  GLuint shader_object = 0;
4854 
4855  #ifndef SDL_GPU_DISABLE_SHADERS
4856  GLint compiled;
4857 
4858  switch(shader_type)
4859  {
4860  case GPU_VERTEX_SHADER:
4861  shader_object = glCreateShader(GL_VERTEX_SHADER);
4862  break;
4863  case GPU_FRAGMENT_SHADER:
4864  shader_object = glCreateShader(GL_FRAGMENT_SHADER);
4865  break;
4866  case GPU_GEOMETRY_SHADER:
4867  #ifdef GL_GEOMETRY_SHADER
4868  shader_object = glCreateShader(GL_GEOMETRY_SHADER);
4869  #else
4870  GPU_PushErrorCode("GPU_CompileShader", GPU_ERROR_BACKEND_ERROR, "Hardware does not support GPU_GEOMETRY_SHADER.");
4871  snprintf(shader_message, 256, "Failed to create geometry shader object.\n");
4872  return 0;
4873  #endif
4874  break;
4875  }
4876 
4877  if(shader_object == 0)
4878  {
4879  GPU_PushErrorCode("GPU_CompileShader", GPU_ERROR_BACKEND_ERROR, "Failed to create new shader object");
4880  snprintf(shader_message, 256, "Failed to create new shader object.\n");
4881  return 0;
4882  }
4883 
4884  glShaderSource(shader_object, 1, &shader_source, NULL);
4885 
4886  // Compile the shader source
4887 
4888  glCompileShader(shader_object);
4889 
4890  glGetShaderiv(shader_object, GL_COMPILE_STATUS, &compiled);
4891  if(!compiled)
4892  {
4893  GPU_PushErrorCode("GPU_CompileShader", GPU_ERROR_DATA_ERROR, "Failed to compile shader source");
4894  glGetShaderInfoLog(shader_object, 256, NULL, shader_message);
4895  glDeleteShader(shader_object);
4896  return 0;
4897  }
4898 
4899  #endif
4900 
4901  return shader_object;
4902 }
4903 
4904 
4905 static Uint32 CompileShader_RW(GPU_Renderer* renderer, GPU_ShaderEnum shader_type, SDL_RWops* shader_source)
4906 {
4907  // Read in the shader source code
4908  Uint32 size = GetShaderSourceSize_RW(shader_source);
4909  char* source_string = (char*)malloc(size+1);
4910  int result = GetShaderSource_RW(shader_source, source_string);
4911  Uint32 result2;
4912 
4913  if(!result)
4914  {
4915  GPU_PushErrorCode("GPU_CompileShader", GPU_ERROR_DATA_ERROR, "Failed to read shader source");
4916  snprintf(shader_message, 256, "Failed to read shader source.\n");
4917  free(source_string);
4918  return 0;
4919  }
4920 
4921  result2 = compile_shader_source(shader_type, source_string);
4922  free(source_string);
4923 
4924  return result2;
4925 }
4926 
4927 static Uint32 CompileShader(GPU_Renderer* renderer, GPU_ShaderEnum shader_type, const char* shader_source)
4928 {
4929  Uint32 size = (Uint32)strlen(shader_source);
4930  SDL_RWops* rwops;
4931  if(size == 0)
4932  return 0;
4933  rwops = SDL_RWFromConstMem(shader_source, size);
4934  size = renderer->CompileShader_RW(renderer, shader_type, rwops);
4935  SDL_RWclose(rwops);
4936  return size;
4937 }
4938 
4939 static Uint32 LinkShaderProgram(GPU_Renderer* renderer, Uint32 program_object)
4940 {
4941  #ifndef SDL_GPU_DISABLE_SHADERS
4942  int linked;
4943  glLinkProgram(program_object);
4944 
4945  glGetProgramiv(program_object, GL_LINK_STATUS, &linked);
4946 
4947  if(!linked)
4948  {
4949  GPU_PushErrorCode("GPU_LinkShaderProgram", GPU_ERROR_BACKEND_ERROR, "Failed to link shader program");
4950  glGetProgramInfoLog(program_object, 256, NULL, shader_message);
4951  glDeleteProgram(program_object);
4952  return 0;
4953  }
4954  #endif
4955 
4956  return program_object;
4957 }
4958 
4959 static Uint32 LinkShaders(GPU_Renderer* renderer, Uint32 shader_object1, Uint32 shader_object2)
4960 {
4961  #ifndef SDL_GPU_DISABLE_SHADERS
4962  GLuint p = glCreateProgram();
4963 
4964  glAttachShader(p, shader_object1);
4965  glAttachShader(p, shader_object2);
4966 
4967  return renderer->LinkShaderProgram(renderer, p);
4968  #else
4969  return 0;
4970  #endif
4971 }
4972 
4973 static void FreeShader(GPU_Renderer* renderer, Uint32 shader_object)
4974 {
4975  #ifndef SDL_GPU_DISABLE_SHADERS
4976  glDeleteShader(shader_object);
4977  #endif
4978 }
4979 
4980 static void FreeShaderProgram(GPU_Renderer* renderer, Uint32 program_object)
4981 {
4982  #ifndef SDL_GPU_DISABLE_SHADERS
4983  glDeleteProgram(program_object);
4984  #endif
4985 }
4986 
4987 static void AttachShader(GPU_Renderer* renderer, Uint32 program_object, Uint32 shader_object)
4988 {
4989  #ifndef SDL_GPU_DISABLE_SHADERS
4990  glAttachShader(program_object, shader_object);
4991  #endif
4992 }
4993 
4994 static void DetachShader(GPU_Renderer* renderer, Uint32 program_object, Uint32 shader_object)
4995 {
4996  #ifndef SDL_GPU_DISABLE_SHADERS
4997  glDetachShader(program_object, shader_object);
4998  #endif
4999 }
5000 
5001 static Uint8 IsDefaultShaderProgram(GPU_Renderer* renderer, Uint32 program_object)
5002 {
5003  GPU_Context* context = renderer->current_context_target->context;
5004  return (program_object == context->default_textured_shader_program || program_object == context->default_untextured_shader_program);
5005 }
5006 
5007 static void ActivateShaderProgram(GPU_Renderer* renderer, Uint32 program_object, GPU_ShaderBlock* block)
5008 {
5010  #ifndef SDL_GPU_DISABLE_SHADERS
5011 
5012  if(program_object == 0) // Implies default shader
5013  {
5014  // Already using a default shader?
5017  return;
5018 
5019  program_object = target->context->default_untextured_shader_program;
5020  }
5021 
5022  renderer->FlushBlitBuffer(renderer);
5023  glUseProgram(program_object);
5024 
5025  #ifdef SDL_GPU_USE_GL_TIER3
5026  {
5027  // Set up our shader attribute and uniform locations
5028  GPU_CONTEXT_DATA* cdata = ((GPU_CONTEXT_DATA*)target->context->data);
5029  if(block == NULL)
5030  {
5031  if(program_object == target->context->default_textured_shader_program)
5032  cdata->current_shader_block = cdata->shader_block[0];
5033  else if(program_object == target->context->default_untextured_shader_program)
5034  cdata->current_shader_block = cdata->shader_block[1];
5035  else
5036  {
5038  b.position_loc = -1;
5039  b.texcoord_loc = -1;
5040  b.color_loc = -1;
5041  b.modelViewProjection_loc = -1;
5042  cdata->current_shader_block = b;
5043  }
5044  }
5045  else
5046  cdata->current_shader_block = *block;
5047  }
5048  #endif
5049  #endif
5050 
5051  target->context->current_shader_program = program_object;
5052 }
5053 
5055 {
5056  renderer->ActivateShaderProgram(renderer, 0, NULL);
5057 }
5058 
5059 static const char* GetShaderMessage(GPU_Renderer* renderer)
5060 {
5061  return shader_message;
5062 }
5063 
5064 static int GetAttributeLocation(GPU_Renderer* renderer, Uint32 program_object, const char* attrib_name)
5065 {
5066  #ifndef SDL_GPU_DISABLE_SHADERS
5067  program_object = get_proper_program_id(renderer, program_object);
5068  if(program_object == 0)
5069  return -1;
5070  return glGetAttribLocation(program_object, attrib_name);
5071  #else
5072  return -1;
5073  #endif
5074 }
5075 
5076 static int GetUniformLocation(GPU_Renderer* renderer, Uint32 program_object, const char* uniform_name)
5077 {
5078  #ifndef SDL_GPU_DISABLE_SHADERS
5079  program_object = get_proper_program_id(renderer, program_object);
5080  if(program_object == 0)
5081  return -1;
5082  return glGetUniformLocation(program_object, uniform_name);
5083  #else
5084  return -1;
5085  #endif
5086 }
5087 
5088 static GPU_ShaderBlock LoadShaderBlock(GPU_Renderer* renderer, Uint32 program_object, const char* position_name, const char* texcoord_name, const char* color_name, const char* modelViewMatrix_name)
5089 {
5091  program_object = get_proper_program_id(renderer, program_object);
5092  if(program_object == 0)
5093  {
5094  b.position_loc = -1;
5095  b.texcoord_loc = -1;
5096  b.color_loc = -1;
5097  b.modelViewProjection_loc = -1;
5098  return b;
5099  }
5100 
5101  if(position_name == NULL)
5102  b.position_loc = -1;
5103  else
5104  b.position_loc = renderer->GetAttributeLocation(renderer, program_object, position_name);
5105 
5106  if(texcoord_name == NULL)
5107  b.texcoord_loc = -1;
5108  else
5109  b.texcoord_loc = renderer->GetAttributeLocation(renderer, program_object, texcoord_name);
5110 
5111  if(color_name == NULL)
5112  b.color_loc = -1;
5113  else
5114  b.color_loc = renderer->GetAttributeLocation(renderer, program_object, color_name);
5115 
5116  if(modelViewMatrix_name == NULL)
5117  b.modelViewProjection_loc = -1;
5118  else
5119  b.modelViewProjection_loc = renderer->GetUniformLocation(renderer, program_object, modelViewMatrix_name);
5120 
5121  return b;
5122 }
5123 
5125 {
5126  #ifdef SDL_GPU_USE_GL_TIER3
5127  ((GPU_CONTEXT_DATA*)renderer->current_context_target->context->data)->current_shader_block = block;
5128  #endif
5129 }
5130 
5131 static void SetShaderImage(GPU_Renderer* renderer, GPU_Image* image, int location, int image_unit)
5132 {
5133  // TODO: OpenGL 1 needs to check for ARB_multitexture to use glActiveTexture().
5134  #ifndef SDL_GPU_DISABLE_SHADERS
5135  Uint32 new_texture;
5136  renderer->FlushBlitBuffer(renderer);
5137  if(renderer->current_context_target->context->current_shader_program == 0 || image_unit < 0)
5138  return;
5139 
5140  new_texture = 0;
5141  if(image != NULL)
5142  new_texture = ((GPU_IMAGE_DATA*)image->data)->handle;
5143 
5144  // Set the new image unit
5145  glUniform1i(location, image_unit);
5146  glActiveTexture(GL_TEXTURE0 + image_unit);
5147  glBindTexture(GL_TEXTURE_2D, new_texture);
5148 
5149  if(image_unit != 0)
5151 
5152  #endif
5153 }
5154 
5155 
5156 static void GetUniformiv(GPU_Renderer* renderer, Uint32 program_object, int location, int* values)
5157 {
5158  #ifndef SDL_GPU_DISABLE_SHADERS
5159  program_object = get_proper_program_id(renderer, program_object);
5160  if(program_object != 0)
5161  glGetUniformiv(program_object, location, values);
5162  #endif
5163 }
5164 
5165 static void SetUniformi(GPU_Renderer* renderer, int location, int value)
5166 {
5167  #ifndef SDL_GPU_DISABLE_SHADERS
5168  renderer->FlushBlitBuffer(renderer);
5170  return;
5171  glUniform1i(location, value);
5172  #endif
5173 }
5174 
5175 static void SetUniformiv(GPU_Renderer* renderer, int location, int num_elements_per_value, int num_values, int* values)
5176 {
5177  #ifndef SDL_GPU_DISABLE_SHADERS
5178  renderer->FlushBlitBuffer(renderer);
5180  return;
5181  switch(num_elements_per_value)
5182  {
5183  case 1:
5184  glUniform1iv(location, num_values, values);
5185  break;
5186  case 2:
5187  glUniform2iv(location, num_values, values);
5188  break;
5189  case 3:
5190  glUniform3iv(location, num_values, values);
5191  break;
5192  case 4:
5193  glUniform4iv(location, num_values, values);
5194  break;
5195  }
5196  #endif
5197 }
5198 
5199 
5200 static void GetUniformuiv(GPU_Renderer* renderer, Uint32 program_object, int location, unsigned int* values)
5201 {
5202  #ifndef SDL_GPU_DISABLE_SHADERS
5203  program_object = get_proper_program_id(renderer, program_object);
5204  if(program_object != 0)
5205  #if defined(SDL_GPU_USE_GLES) && SDL_GPU_GLES_MAJOR_VERSION < 3
5206  glGetUniformiv(program_object, location, (int*)values);
5207  #else
5208  glGetUniformuiv(program_object, location, values);
5209  #endif
5210  #endif
5211 }
5212 
5213 static void SetUniformui(GPU_Renderer* renderer, int location, unsigned int value)
5214 {
5215  #ifndef SDL_GPU_DISABLE_SHADERS
5216  renderer->FlushBlitBuffer(renderer);
5218  return;
5219  #if defined(SDL_GPU_USE_GLES) && SDL_GPU_GLES_MAJOR_VERSION < 3
5220  glUniform1i(location, (int)value);
5221  #else
5222  glUniform1ui(location, value);
5223  #endif
5224  #endif
5225 }
5226 
5227 static void SetUniformuiv(GPU_Renderer* renderer, int location, int num_elements_per_value, int num_values, unsigned int* values)
5228 {
5229  #ifndef SDL_GPU_DISABLE_SHADERS
5230  renderer->FlushBlitBuffer(renderer);
5232  return;
5233  #if defined(SDL_GPU_USE_GLES) && SDL_GPU_GLES_MAJOR_VERSION < 3
5234  switch(num_elements_per_value)
5235  {
5236  case 1:
5237  glUniform1iv(location, num_values, (int*)values);
5238  break;
5239  case 2:
5240  glUniform2iv(location, num_values, (int*)values);
5241  break;
5242  case 3:
5243  glUniform3iv(location, num_values, (int*)values);
5244  break;
5245  case 4:
5246  glUniform4iv(location, num_values, (int*)values);
5247  break;
5248  }
5249  #else
5250  switch(num_elements_per_value)
5251  {
5252  case 1:
5253  glUniform1uiv(location, num_values, values);
5254  break;
5255  case 2:
5256  glUniform2uiv(location, num_values, values);
5257  break;
5258  case 3:
5259  glUniform3uiv(location, num_values, values);
5260  break;
5261  case 4:
5262  glUniform4uiv(location, num_values, values);
5263  break;
5264  }
5265  #endif
5266  #endif
5267 }
5268 
5269 
5270 static void GetUniformfv(GPU_Renderer* renderer, Uint32 program_object, int location, float* values)
5271 {
5272  #ifndef SDL_GPU_DISABLE_SHADERS
5273  program_object = get_proper_program_id(renderer, program_object);
5274  if(program_object != 0)
5275  glGetUniformfv(program_object, location, values);
5276  #endif
5277 }
5278 
5279 static void SetUniformf(GPU_Renderer* renderer, int location, float value)
5280 {
5281  #ifndef SDL_GPU_DISABLE_SHADERS
5282  renderer->FlushBlitBuffer(renderer);
5284  return;
5285  glUniform1f(location, value);
5286  #endif
5287 }
5288 
5289 static void SetUniformfv(GPU_Renderer* renderer, int location, int num_elements_per_value, int num_values, float* values)
5290 {
5291  #ifndef SDL_GPU_DISABLE_SHADERS
5292  renderer->FlushBlitBuffer(renderer);
5294  return;
5295  switch(num_elements_per_value)
5296  {
5297  case 1:
5298  glUniform1fv(location, num_values, values);
5299  break;
5300  case 2:
5301  glUniform2fv(location, num_values, values);
5302  break;
5303  case 3:
5304  glUniform3fv(location, num_values, values);
5305  break;
5306  case 4:
5307  glUniform4fv(location, num_values, values);
5308  break;
5309  }
5310  #endif
5311 }
5312 
5313 static void SetUniformMatrixfv(GPU_Renderer* renderer, int location, int num_matrices, int num_rows, int num_columns, Uint8 transpose, float* values)
5314 {
5315  #ifndef SDL_GPU_DISABLE_SHADERS
5316  renderer->FlushBlitBuffer(renderer);
5318  return;
5319  if(num_rows < 2 || num_rows > 4 || num_columns < 2 || num_columns > 4)
5320  {
5321  GPU_PushErrorCode("GPU_SetUniformMatrixfv", GPU_ERROR_DATA_ERROR, "Given invalid dimensions (%dx%d)", num_rows, num_columns);
5322  return;
5323  }
5324  #if defined(SDL_GPU_USE_GLES)
5325  // Hide these symbols so it compiles, but make sure they never get called because GLES only supports square matrices.
5326  #define glUniformMatrix2x3fv glUniformMatrix2fv
5327  #define glUniformMatrix2x4fv glUniformMatrix2fv
5328  #define glUniformMatrix3x2fv glUniformMatrix2fv
5329  #define glUniformMatrix3x4fv glUniformMatrix2fv
5330  #define glUniformMatrix4x2fv glUniformMatrix2fv
5331  #define glUniformMatrix4x3fv glUniformMatrix2fv
5332  if(num_rows != num_columns)
5333  {
5334  GPU_PushErrorCode("GPU_SetUniformMatrixfv", GPU_ERROR_DATA_ERROR, "GLES renderers do not accept non-square matrices (given %dx%d)", num_rows, num_columns);
5335  return;
5336  }
5337  #endif
5338 
5339  switch(num_rows)
5340  {
5341  case 2:
5342  if(num_columns == 2)
5343  glUniformMatrix2fv(location, num_matrices, transpose, values);
5344  else if(num_columns == 3)
5345  glUniformMatrix2x3fv(location, num_matrices, transpose, values);
5346  else if(num_columns == 4)
5347  glUniformMatrix2x4fv(location, num_matrices, transpose, values);
5348  break;
5349  case 3:
5350  if(num_columns == 2)
5351  glUniformMatrix3x2fv(location, num_matrices, transpose, values);
5352  else if(num_columns == 3)
5353  glUniformMatrix3fv(location, num_matrices, transpose, values);
5354  else if(num_columns == 4)
5355  glUniformMatrix3x4fv(location, num_matrices, transpose, values);
5356  break;
5357  case 4:
5358  if(num_columns == 2)
5359  glUniformMatrix4x2fv(location, num_matrices, transpose, values);
5360  else if(num_columns == 3)
5361  glUniformMatrix4x3fv(location, num_matrices, transpose, values);
5362  else if(num_columns == 4)
5363  glUniformMatrix4fv(location, num_matrices, transpose, values);
5364  break;
5365  }
5366  #endif
5367 }
5368 
5369 
5370 static void SetAttributef(GPU_Renderer* renderer, int location, float value)
5371 {
5372  #ifndef SDL_GPU_DISABLE_SHADERS
5373  renderer->FlushBlitBuffer(renderer);
5375  return;
5376 
5377  #ifdef SDL_GPU_USE_OPENGL
5378  if(apply_Intel_attrib_workaround && location == 0)
5379  {
5380  apply_Intel_attrib_workaround = 0;
5382  glEnd();
5383  }
5384  #endif
5385 
5386  glVertexAttrib1f(location, value);
5387 
5388  #endif
5389 }
5390 
5391 static void SetAttributei(GPU_Renderer* renderer, int location, int value)
5392 {
5393  #ifndef SDL_GPU_DISABLE_SHADERS
5394  renderer->FlushBlitBuffer(renderer);
5396  return;
5397 
5398  #ifdef SDL_GPU_USE_OPENGL
5399  if(apply_Intel_attrib_workaround && location == 0)
5400  {
5401  apply_Intel_attrib_workaround = 0;
5403  glEnd();
5404  }
5405  #endif
5406 
5407  glVertexAttribI1i(location, value);
5408 
5409  #endif
5410 }
5411 
5412 static void SetAttributeui(GPU_Renderer* renderer, int location, unsigned int value)
5413 {
5414  #ifndef SDL_GPU_DISABLE_SHADERS
5415  renderer->FlushBlitBuffer(renderer);
5417  return;
5418 
5419  #ifdef SDL_GPU_USE_OPENGL
5420  if(apply_Intel_attrib_workaround && location == 0)
5421  {
5422  apply_Intel_attrib_workaround = 0;
5424  glEnd();
5425  }
5426  #endif
5427 
5428  glVertexAttribI1ui(location, value);
5429 
5430  #endif
5431 }
5432 
5433 
5434 static void SetAttributefv(GPU_Renderer* renderer, int location, int num_elements, float* value)
5435 {
5436  #ifndef SDL_GPU_DISABLE_SHADERS
5437  renderer->FlushBlitBuffer(renderer);
5439  return;
5440 
5441  #ifdef SDL_GPU_USE_OPENGL
5442  if(apply_Intel_attrib_workaround && location == 0)
5443  {
5444  apply_Intel_attrib_workaround = 0;
5446  glEnd();
5447  }
5448  #endif
5449 
5450  switch(num_elements)
5451  {
5452  case 1:
5453  glVertexAttrib1f(location, value[0]);
5454  break;
5455  case 2:
5456  glVertexAttrib2f(location, value[0], value[1]);
5457  break;
5458  case 3:
5459  glVertexAttrib3f(location, value[0], value[1], value[2]);
5460  break;
5461  case 4:
5462  glVertexAttrib4f(location, value[0], value[1], value[2], value[3]);
5463  break;
5464  }
5465 
5466  #endif
5467 }
5468 
5469 static void SetAttributeiv(GPU_Renderer* renderer, int location, int num_elements, int* value)
5470 {
5471  #ifndef SDL_GPU_DISABLE_SHADERS
5472  renderer->FlushBlitBuffer(renderer);
5474  return;
5475 
5476  #ifdef SDL_GPU_USE_OPENGL
5477  if(apply_Intel_attrib_workaround && location == 0)
5478  {
5479  apply_Intel_attrib_workaround = 0;
5481  glEnd();
5482  }
5483  #endif
5484 
5485  switch(num_elements)
5486  {
5487  case 1:
5488  glVertexAttribI1i(location, value[0]);
5489  break;
5490  case 2:
5491  glVertexAttribI2i(location, value[0], value[1]);
5492  break;
5493  case 3:
5494  glVertexAttribI3i(location, value[0], value[1], value[2]);
5495  break;
5496  case 4:
5497  glVertexAttribI4i(location, value[0], value[1], value[2], value[3]);
5498  break;
5499  }
5500 
5501  #endif
5502 }
5503 
5504 static void SetAttributeuiv(GPU_Renderer* renderer, int location, int num_elements, unsigned int* value)
5505 {
5506  #ifndef SDL_GPU_DISABLE_SHADERS
5507  renderer->FlushBlitBuffer(renderer);
5509  return;
5510 
5511  #ifdef SDL_GPU_USE_OPENGL
5512  if(apply_Intel_attrib_workaround && location == 0)
5513  {
5514  apply_Intel_attrib_workaround = 0;
5516  glEnd();
5517  }
5518  #endif
5519 
5520  switch(num_elements)
5521  {
5522  case 1:
5523  glVertexAttribI1ui(location, value[0]);
5524  break;
5525  case 2:
5526  glVertexAttribI2ui(location, value[0], value[1]);
5527  break;
5528  case 3:
5529  glVertexAttribI3ui(location, value[0], value[1], value[2]);
5530  break;
5531  case 4:
5532  glVertexAttribI4ui(location, value[0], value[1], value[2], value[3]);
5533  break;
5534  }
5535 
5536  #endif
5537 }
5538 
5539 static void SetAttributeSource(GPU_Renderer* renderer, int num_values, GPU_Attribute source)
5540 {
5541  #ifdef SDL_GPU_USE_GL_TIER3
5542  GPU_CONTEXT_DATA* cdata;
5544 
5545  if(source.location < 0 || source.location >= 16)
5546  return;
5547  cdata = (GPU_CONTEXT_DATA*)renderer->current_context_target->context->data;
5548  a = &cdata->shader_attributes[source.location];
5549  if(source.format.is_per_sprite)
5550  {
5551  int needed_size;
5552 
5554  a->per_vertex_storage_stride_bytes = source.format.num_elems_per_value * sizeof_GPU_type(source.format.type);
5555  a->num_values = 4 * num_values; // 4 vertices now
5556  needed_size = a->num_values * a->per_vertex_storage_stride_bytes;
5557 
5558  // Make sure we have enough room for converted per-vertex data
5559  if(a->per_vertex_storage_size < needed_size)
5560  {
5561  free(a->per_vertex_storage);
5562  a->per_vertex_storage = malloc(needed_size);
5563  a->per_vertex_storage_size = needed_size;
5564  }
5565  }
5566  else if(a->per_vertex_storage_size > 0)
5567  {
5568  free(a->per_vertex_storage);
5569  a->per_vertex_storage = NULL;
5570  a->per_vertex_storage_size = 0;
5571  }
5572 
5573  a->enabled = 0;
5574  a->attribute = source;
5575 
5576  if(!source.format.is_per_sprite)
5577  {
5578  a->per_vertex_storage = source.values;
5579  a->num_values = num_values;
5582  }
5583 
5585 
5586  #endif
5587 }
5588 
5589 
5590 
5591 #define SET_COMMON_FUNCTIONS(renderer) \
5592  renderer->Init = &Init; \
5593  renderer->IsFeatureEnabled = &IsFeatureEnabled; \
5594  renderer->CreateTargetFromWindow = &CreateTargetFromWindow; \
5595  renderer->CreateAliasTarget = &CreateAliasTarget; \
5596  renderer->MakeCurrent = &MakeCurrent; \
5597  renderer->SetAsCurrent = &SetAsCurrent; \
5598  renderer->SetWindowResolution = &SetWindowResolution; \
5599  renderer->SetVirtualResolution = &SetVirtualResolution; \
5600  renderer->UnsetVirtualResolution = &UnsetVirtualResolution; \
5601  renderer->Quit = &Quit; \
5602  \
5603  renderer->ToggleFullscreen = &ToggleFullscreen; \
5604  renderer->SetCamera = &SetCamera; \
5605  \
5606  renderer->CreateImage = &CreateImage; \
5607  renderer->LoadImage = &LoadImage; \
5608  renderer->CreateAliasImage = &CreateAliasImage; \
5609  renderer->SaveImage = &SaveImage; \
5610  renderer->CopyImage = &CopyImage; \
5611  renderer->UpdateImage = &UpdateImage; \
5612  renderer->UpdateSubImage = &UpdateSubImage; \
5613  renderer->UpdateImageBytes = &UpdateImageBytes; \
5614  renderer->CopyImageFromSurface = &CopyImageFromSurface; \
5615  renderer->CopyImageFromTarget = &CopyImageFromTarget; \
5616  renderer->CopySurfaceFromTarget = &CopySurfaceFromTarget; \
5617  renderer->CopySurfaceFromImage = &CopySurfaceFromImage; \
5618  renderer->FreeImage = &FreeImage; \
5619  \
5620  renderer->LoadTarget = &LoadTarget; \
5621  renderer->FreeTarget = &FreeTarget; \
5622  \
5623  renderer->Blit = &Blit; \
5624  renderer->BlitRotate = &BlitRotate; \
5625  renderer->BlitScale = &BlitScale; \
5626  renderer->BlitTransform = &BlitTransform; \
5627  renderer->BlitTransformX = &BlitTransformX; \
5628  renderer->BlitTransformMatrix = &BlitTransformMatrix; \
5629  renderer->BlitBatch = &BlitBatch; \
5630  renderer->TriangleBatch = &TriangleBatch; \
5631  \
5632  renderer->GenerateMipmaps = &GenerateMipmaps; \
5633  \
5634  renderer->SetClip = &SetClip; \
5635  renderer->UnsetClip = &UnsetClip; \
5636  \
5637  renderer->GetPixel = &GetPixel; \
5638  renderer->SetImageFilter = &SetImageFilter; \
5639  renderer->SetWrapMode = &SetWrapMode; \
5640  \
5641  renderer->Clear = &Clear; \
5642  renderer->ClearRGBA = &ClearRGBA; \
5643  renderer->FlushBlitBuffer = &FlushBlitBuffer; \
5644  renderer->Flip = &Flip; \
5645  \
5646  renderer->CompileShader_RW = &CompileShader_RW; \
5647  renderer->CompileShader = &CompileShader; \
5648  renderer->LinkShaderProgram = &LinkShaderProgram; \
5649  renderer->LinkShaders = &LinkShaders; \
5650  renderer->FreeShader = &FreeShader; \
5651  renderer->FreeShaderProgram = &FreeShaderProgram; \
5652  renderer->AttachShader = &AttachShader; \
5653  renderer->DetachShader = &DetachShader; \
5654  renderer->IsDefaultShaderProgram = &IsDefaultShaderProgram; \
5655  renderer->ActivateShaderProgram = &ActivateShaderProgram; \
5656  renderer->DeactivateShaderProgram = &DeactivateShaderProgram; \
5657  renderer->GetShaderMessage = &GetShaderMessage; \
5658  renderer->GetAttributeLocation = &GetAttributeLocation; \
5659  renderer->GetUniformLocation = &GetUniformLocation; \
5660  renderer->LoadShaderBlock = &LoadShaderBlock; \
5661  renderer->SetShaderBlock = &SetShaderBlock; \
5662  renderer->SetShaderImage = &SetShaderImage; \
5663  renderer->GetUniformiv = &GetUniformiv; \
5664  renderer->SetUniformi = &SetUniformi; \
5665  renderer->SetUniformiv = &SetUniformiv; \
5666  renderer->GetUniformuiv = &GetUniformuiv; \
5667  renderer->SetUniformui = &SetUniformui; \
5668  renderer->SetUniformuiv = &SetUniformuiv; \
5669  renderer->GetUniformfv = &GetUniformfv; \
5670  renderer->SetUniformf = &SetUniformf; \
5671  renderer->SetUniformfv = &SetUniformfv; \
5672  renderer->SetUniformMatrixfv = &SetUniformMatrixfv; \
5673  renderer->SetAttributef = &SetAttributef; \
5674  renderer->SetAttributei = &SetAttributei; \
5675  renderer->SetAttributeui = &SetAttributeui; \
5676  renderer->SetAttributefv = &SetAttributefv; \
5677  renderer->SetAttributeiv = &SetAttributeiv; \
5678  renderer->SetAttributeuiv = &SetAttributeuiv; \
5679  renderer->SetAttributeSource = &SetAttributeSource; \
5680  \
5681  /* Shape rendering */ \
5682  \
5683  renderer->SetLineThickness = &SetLineThickness; \
5684  renderer->SetLineThickness(renderer, 1.0f); \
5685  renderer->GetLineThickness = &GetLineThickness; \
5686  renderer->Pixel = &Pixel; \
5687  renderer->Line = &Line; \
5688  renderer->Arc = &Arc; \
5689  renderer->ArcFilled = &ArcFilled; \
5690  renderer->Circle = &Circle; \
5691  renderer->CircleFilled = &CircleFilled; \
5692  renderer->Sector = &Sector; \
5693  renderer->SectorFilled = &SectorFilled; \
5694  renderer->Tri = &Tri; \
5695  renderer->TriFilled = &TriFilled; \
5696  renderer->Rectangle = &Rectangle; \
5697  renderer->RectangleFilled = &RectangleFilled; \
5698  renderer->RectangleRound = &RectangleRound; \
5699  renderer->RectangleRoundFilled = &RectangleRoundFilled; \
5700  renderer->Polygon = &Polygon; \
5701  renderer->PolygonFilled = &PolygonFilled;
5702 
static void changeCamera(GPU_Target *target)
GLAPI void GLAPIENTRY glDisableClientState(GLenum array)
GLAPI void GLAPIENTRY glDeleteTextures(GLsizei n, const GLuint *textures)
static const GPU_TypeEnum GPU_TYPE_INT
Definition: SDL_gpu.h:377
static Uint8 bindFramebuffer(GPU_Renderer *renderer, GPU_Target *target)
#define glewIsExtensionSupported(x)
Definition: glew.h:15474
float matrix[GPU_MATRIX_STACK_MAX][16]
Definition: SDL_gpu.h:237
GLAPI void GLAPIENTRY glEnableClientState(GLenum array)
void GPU_UnsetClip(GPU_Target *target)
Definition: SDL_gpu.c:1833
#define glGenVertexArrays
Definition: glew.h:5366
GPU_Rect viewport
Definition: SDL_gpu.h:297
static void Clear(GPU_Renderer *renderer, GPU_Target *target)
SDL_Color color
Definition: SDL_gpu.h:295
static void BlitTransformX(GPU_Renderer *renderer, GPU_Image *image, GPU_Rect *src_rect, GPU_Target *target, float x, float y, float pivot_x, float pivot_y, float degrees, float scaleX, float scaleY)
int(* GetAttributeLocation)(GPU_Renderer *renderer, Uint32 program_object, const char *attrib_name)
Definition: SDL_gpu.h:671
static Uint8 SaveImage(GPU_Renderer *renderer, GPU_Image *image, const char *filename)
#define glVertexAttribPointer
Definition: glew.h:1967
GPU_SnapEnum snap_mode
Definition: SDL_gpu.h:189
static GPU_Image * CreateAliasImage(GPU_Renderer *renderer, GPU_Image *image)
float angle
Definition: SDL_gpu.h:207
#define glCreateProgram
Definition: glew.h:1879
static Uint8 isExtensionSupported(const char *extension_str)
static void changeViewport(GPU_Target *target)
static int get_lowest_attribute_num_values(GPU_CONTEXT_DATA *cdata, int cap)
unsigned int GLuint
Definition: glew.h:253
static void SetImageFilter(GPU_Renderer *renderer, GPU_Image *image, GPU_FilterEnum filter)
#define GL_BGR
Definition: glew.h:1198
#define GL_CLAMP_TO_EDGE
Definition: glew.h:1202
GLboolean enable
Definition: glew.h:2589
static void BlitRotate(GPU_Renderer *renderer, GPU_Image *image, GPU_Rect *src_rect, GPU_Target *target, float x, float y, float degrees)
GLint GLint GLsizei GLsizei GLsizei GLint GLenum GLenum const GLvoid * pixels
Definition: glew.h:1222
GLsizei GLboolean transpose
Definition: glew.h:1832
GLAPI void GLAPIENTRY glGetTexImage(GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels)
GLAPI void GLAPIENTRY glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels)
Uint32 texture_w
Definition: SDL_gpu.h:182
void GPU_Translate(float x, float y, float z)
#define glUniform2iv
Definition: glew.h:1917
int bytes_per_pixel
Definition: SDL_gpu.h:181
GPU_Target * target
Definition: SDL_gpu.h:177
Uint32 GPU_BlitFlagEnum
Definition: SDL_gpu.h:360
static void SetWrapMode(GPU_Renderer *renderer, GPU_Image *image, GPU_WrapEnum wrap_mode_x, GPU_WrapEnum wrap_mode_y)
void GPU_SetSnapMode(GPU_Image *image, GPU_SnapEnum mode)
Definition: SDL_gpu.c:2112
#define GPU_DEFAULT_UNTEXTURED_VERTEX_SHADER_SOURCE
GPU_ShaderBlock GPU_LoadShaderBlock(Uint32 program_object, const char *position_name, const char *texcoord_name, const char *color_name, const char *modelViewMatrix_name)
Definition: SDL_gpu.c:2346
#define GL_TEXTURE0
Definition: glew.h:1257
static void SetAttributei(GPU_Renderer *renderer, int location, int value)
#define GL_TEXTURE_WRAP_T
Definition: glew.h:699
#define GL_COLOR_ATTACHMENT0
Definition: glew.h:3410
void GPU_SetShaderBlock(GPU_ShaderBlock block)
Definition: SDL_gpu.c:2361
void GPU_PushMatrix()
#define GL_RGBA
Definition: glew.h:654
static void extBindFramebuffer(GPU_Renderer *renderer, GLuint handle)
#define GPU_DEFAULT_TEXTURED_FRAGMENT_SHADER_SOURCE
static void changeBlendMode(GPU_Renderer *renderer, GPU_BlendMode mode)
GLvoid **typedef void(GLAPIENTRY *PFNGLGETVERTEXATTRIBDVPROC)(GLuint
Definition: glew.h:1806
#define glGenFramebuffers
Definition: glew.h:3478
static const GPU_InitFlagEnum GPU_INIT_DISABLE_DOUBLE_BUFFER
Definition: SDL_gpu.h:349
GPU_Rect GPU_MakeRect(float x, float y, float w, float h)
Definition: SDL_gpu.c:607
GLAPI void GLAPIENTRY glMatrixMode(GLenum mode)
int minor_version
Definition: SDL_gpu.h:57
Uint32 default_untextured_shader_program
Definition: SDL_gpu.h:262
#define glGetUniformiv
Definition: glew.h:1898
static GPU_Rect SetClip(GPU_Renderer *renderer, GPU_Target *target, Sint16 x, Sint16 y, Uint16 w, Uint16 h)
#define GL_EXTENSIONS
Definition: glew.h:673
void GPU_Ortho(float left, float right, float bottom, float top, float near, float far)
#define GPU_BLIT_BUFFER_FLOATS_PER_VERTEX
GLAPI void GLAPIENTRY glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
static SDL_Surface * CopySurfaceFromTarget(GPU_Renderer *renderer, GPU_Target *target)
#define GPU_DEFAULT_UNTEXTURED_FRAGMENT_SHADER_SOURCE
void GPU_MatrixMode(int matrix_mode)
#define glBlendEquation
Definition: glew.h:1537
#define glVertexAttrib2f
Definition: glew.h:1939
void GPU_PopMatrix()
#define GPU_IMAGE_DATA
int modelViewProjection_loc
Definition: SDL_gpu.h:223
GLAPI void GLAPIENTRY glEnable(GLenum cap)
static void SetAttributef(GPU_Renderer *renderer, int location, float value)
static const GPU_TypeEnum GPU_TYPE_DOUBLE
Definition: SDL_gpu.h:380
GPU_Camera GPU_GetDefaultCamera(void)
Definition: SDL_gpu.c:631
void GPU_RemoveWindowMapping(Uint32 windowID)
Definition: SDL_gpu.c:237
#define GL_VERTEX_ARRAY
Definition: glew.h:782
#define glGetShaderiv
Definition: glew.h:1895
static void MakeCurrent(GPU_Renderer *renderer, GPU_Target *target, Uint32 windowID)
static int compareFormats(GPU_Renderer *renderer, GLenum glFormat, SDL_Surface *surface, GLenum *surfaceFormatResult)
static void BlitBatch(GPU_Renderer *renderer, GPU_Image *image, GPU_Target *target, unsigned int num_sprites, float *values, GPU_BlitFlagEnum flags)
#define glCreateShader
Definition: glew.h:1880
static void UpdateImage(GPU_Renderer *renderer, GPU_Image *image, SDL_Surface *surface, const GPU_Rect *surface_rect)
GLsizei stride
Definition: glew.h:1491
#define glEnableVertexAttribArray
Definition: glew.h:1886
#define glUniformMatrix2x4fv
Definition: glew.h:2010
#define GPU_BLIT_BUFFER_VERTEX_OFFSET
GPU_FormatEnum
Definition: SDL_gpu.h:152
#define MAX(a, b)
GLuint GLuint GLsizei GLenum type
Definition: glew.h:1221
#define glUniform4iv
Definition: glew.h:1925
#define GL_GENERATE_MIPMAP
Definition: glew.h:1456
#define GL_MODELVIEW
Definition: glew.h:640
GLAPI void GLAPIENTRY glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels)
Uint32 GPU_WindowFlagEnum
Definition: SDL_gpu.h:339
#define GPU_MODELVIEW
GPU_MatrixStack projection_matrix
Definition: SDL_gpu.h:270
#define glUniformMatrix4x2fv
Definition: glew.h:2013
game_display * screen
Definition: resources.cpp:27
#define glUniformMatrix3x4fv
Definition: glew.h:2012
#define glUniform1i
Definition: glew.h:1912
static void UpdateSubImage(GPU_Renderer *renderer, GPU_Image *image, const GPU_Rect *image_rect, SDL_Surface *surface, const GPU_Rect *surface_rect)
#define GPU_BLIT_BUFFER_STRIDE
int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data)
static Uint8 growIndexBuffer(GPU_CONTEXT_DATA *cdata, unsigned int minimum_vertices_needed)
static GPU_Image * CreateUninitializedImage(GPU_Renderer *renderer, Uint16 w, Uint16 h, GPU_FormatEnum format)
#define glGetAttribLocation
Definition: glew.h:1890
void GPU_SetColor(GPU_Image *image, SDL_Color *color)
Definition: SDL_gpu.c:1844
#define GL_STREAM_DRAW
Definition: glew.h:1633
static void SetUniformfv(GPU_Renderer *renderer, int location, int num_elements_per_value, int num_values, float *values)
GLAPI void GLAPIENTRY glColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
#define glUniform2fv
Definition: glew.h:1915
#define M_PI
static int GetAttributeLocation(GPU_Renderer *renderer, Uint32 program_object, const char *attrib_name)
#define GL_FALSE
Definition: glew.h:287
static Uint32 compile_shader_source(GPU_ShaderEnum shader_type, const char *shader_source)
#define GL_TRIANGLES
Definition: glew.h:303
GPU_WrapEnum wrap_mode_x
Definition: SDL_gpu.h:190
SDL_Rect line_size(const std::string &line, int font_size, int style)
Determine the size of a line of text given a certain font size.
Definition: font.cpp:974
#define glUniformMatrix2x3fv
Definition: glew.h:2009
static void TriangleBatch(GPU_Renderer *renderer, GPU_Image *image, GPU_Target *target, unsigned short num_vertices, float *values, unsigned int num_indices, unsigned short *indices, GPU_BlitFlagEnum flags)
#define glDeleteVertexArrays
Definition: glew.h:5365
GLenum GLsizei GLenum GLenum const GLvoid * image
Definition: glew.h:3783
#define glVertexAttribI3i
Definition: glew.h:2232
GLAPI void GLAPIENTRY glLoadMatrixf(const GLfloat *m)
float y
Definition: SDL_gpu.h:29
SDL_Surface *(* CopySurfaceFromTarget)(GPU_Renderer *renderer, GPU_Target *target)
Definition: SDL_gpu.h:568
#define GL_BGRA
Definition: glew.h:9062
#define SDL_GPU_GL_MAJOR_VERSION
GPU_Target * GPU_GetContextTarget(void)
Definition: SDL_gpu.c:882
static const GPU_FeatureEnum GPU_FEATURE_RENDER_TARGETS
Definition: SDL_gpu.h:315
#define glUniformMatrix2fv
Definition: glew.h:1926
static GPU_Target * CreateAliasTarget(GPU_Renderer *renderer, GPU_Target *target)
static const GPU_FeatureEnum GPU_FEATURE_BLEND_FUNC_SEPARATE
Definition: SDL_gpu.h:317
static void ClearRGBA(GPU_Renderer *renderer, GPU_Target *target, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
#define glUniformMatrix4x3fv
Definition: glew.h:2014
#define SET_TEXTURED_VERTEX_UNINDEXED(x, y, s, t, r, g, b, a)
static void prepareToRenderImage(GPU_Renderer *renderer, GPU_Target *target, GPU_Image *image)
static void SetUniformMatrixfv(GPU_Renderer *renderer, int location, int num_matrices, int num_rows, int num_columns, Uint8 transpose, float *values)
#define glBlendEquationSeparate
Definition: glew.h:1877
void GPU_Scale(float sx, float sy, float sz)
GPU_InitFlagEnum GPU_GetPreInitFlags(void)
Definition: SDL_gpu.c:162
#define GL_UNSIGNED_BYTE
Definition: glew.h:610
void(* MakeCurrent)(GPU_Renderer *renderer, GPU_Target *target, Uint32 windowID)
Definition: SDL_gpu.h:514
#define GL_TEXTURE_COORD_ARRAY
Definition: glew.h:786
void(* ActivateShaderProgram)(GPU_Renderer *renderer, Uint32 program_object, GPU_ShaderBlock *block)
Definition: SDL_gpu.h:662
#define GL_TEXTURE_ENV
Definition: glew.h:683
#define h
#define GL_LINEAR
Definition: glew.h:691
#define GL_ONE_MINUS_SRC_ALPHA
Definition: glew.h:332
GLboolean GLboolean g
Definition: glew.h:7319
int(* GetUniformLocation)(GPU_Renderer *renderer, Uint32 program_object, const char *uniform_name)
Definition: SDL_gpu.h:674
#define glDetachShader
Definition: glew.h:1883
GLint GLint GLint GLint GLint GLint y
Definition: glew.h:1220
static Uint32 GetShaderSourceSize(const char *filename)
GLenum src
Definition: glew.h:2392
static Uint32 LinkShaderProgram(GPU_Renderer *renderer, Uint32 program_object)
static void changeColor(GPU_Renderer *renderer, SDL_Color color)
#define GL_GEOMETRY_SHADER
Definition: glew.h:2322
#define GET_ALPHA(sdl_color)
static void Blit(GPU_Renderer *renderer, GPU_Image *image, GPU_Rect *src_rect, GPU_Target *target, float x, float y)
#define GPU_BLIT_BUFFER_COLOR_OFFSET
GPU_FilterEnum
Definition: SDL_gpu.h:122
static const GPU_FeatureEnum GPU_FEATURE_GL_BGR
Definition: SDL_gpu.h:319
static void applyTargetCamera(GPU_Target *target)
#define glFramebufferTexture2D
Definition: glew.h:3475
static void FreeShader(GPU_Renderer *renderer, Uint32 shader_object)
GLAPI void GLAPIENTRY glTexCoord2f(GLfloat s, GLfloat t)
GPU_Camera camera
Definition: SDL_gpu.h:300
void(* FlushBlitBuffer)(GPU_Renderer *renderer)
Definition: SDL_gpu.h:629
void GPU_Rotate(float degrees, float x, float y, float z)
GLint GLenum GLsizei GLint GLsizei const GLvoid * data
Definition: glew.h:1347
static GPU_Image * CopyImage(GPU_Renderer *renderer, GPU_Image *image)
GLenum mode
Definition: glew.h:2390
#define GPU_FEATURE_MASK
Definition: SDL_gpu.h:336
static const GPU_FeatureEnum GPU_FEATURE_BLEND_EQUATIONS_SEPARATE
Definition: SDL_gpu.h:318
#define GL_MIRRORED_REPEAT
Definition: glew.h:1461
Uint8 use_texturing
Definition: SDL_gpu.h:267
static void UnsetVirtualResolution(GPU_Renderer *renderer, GPU_Target *target)
unsigned int GLenum
Definition: glew.h:251
Uint8(* SetWindowResolution)(GPU_Renderer *renderer, Uint16 w, Uint16 h)
Definition: SDL_gpu.h:520
static void prepareToRenderToTarget(GPU_Renderer *renderer, GPU_Target *target)
Uint16 h
Definition: SDL_gpu.h:291
void GPU_SetBlending(GPU_Image *image, Uint8 enable)
Definition: SDL_gpu.c:1931
#define glVertexAttribI1i
Definition: glew.h:2224
float * GPU_GetProjection(void)
void GPU_PushErrorCode(const char *function, GPU_ErrorEnum error, const char *details,...)
Definition: SDL_gpu.c:503
#define GL_VENDOR
Definition: glew.h:670
SDL_Surface * GPU_LoadSurface(const char *filename)
Definition: SDL_gpu.c:716
#define glBindVertexArray
Definition: glew.h:5364
int per_vertex_storage_size
Definition: SDL_gpu.h:436
static Uint32 CompileShader(GPU_Renderer *renderer, GPU_ShaderEnum shader_type, const char *shader_source)
static Uint8 IsDefaultShaderProgram(GPU_Renderer *renderer, Uint32 program_object)
static SDL_Color GetPixel(GPU_Renderer *renderer, GPU_Target *target, Sint16 x, Sint16 y)
GLboolean GLenum GLenum GLvoid * values
Definition: glew.h:3799
GLAPI void GLAPIENTRY glBlendFunc(GLenum sfactor, GLenum dfactor)
void GPU_GetModelViewProjection(float *result)
#define GPU_BLIT_BUFFER_INIT_MAX_NUM_VERTICES
static const GPU_FeatureEnum GPU_FEATURE_FRAGMENT_SHADER
Definition: SDL_gpu.h:323
#define glUniformMatrix3x2fv
Definition: glew.h:2011
Uint32(* LinkShaders)(GPU_Renderer *renderer, Uint32 shader_object1, Uint32 shader_object2)
Definition: SDL_gpu.h:644
static void SetAsCurrent(GPU_Renderer *renderer)
GPU_Attribute attribute
Definition: SDL_gpu.h:438
static Uint32 GetShaderSource(const char *filename, char *result)
Uint8 is_alias
Definition: SDL_gpu.h:195
void(* Blit)(GPU_Renderer *renderer, GPU_Image *image, GPU_Rect *src_rect, GPU_Target *target, float x, float y)
Definition: SDL_gpu.h:583
#define glUniform4uiv
Definition: glew.h:2223
GLdouble GLdouble GLdouble b
Definition: glew.h:6966
Uint32 texture_h
Definition: SDL_gpu.h:182
#define GPU_DEFAULT_TEXTURED_VERTEX_SHADER_SOURCE
static int GetUniformLocation(GPU_Renderer *renderer, Uint32 program_object, const char *uniform_name)
GPU_FormatEnum format
Definition: SDL_gpu.h:179
GLAPI void GLAPIENTRY glBindTexture(GLenum target, GLuint texture)
#define glUniform3uiv
Definition: glew.h:2221
static const GPU_InitFlagEnum GPU_INIT_DISABLE_VSYNC
Definition: SDL_gpu.h:348
static unsigned char * getRawTargetData(GPU_Renderer *renderer, GPU_Target *target)
#define GL_FRAMEBUFFER_BINDING
Definition: glew.h:3392
static const GPU_FeatureEnum GPU_FEATURE_VERTEX_SHADER
Definition: SDL_gpu.h:322
#define glGetUniformLocation
Definition: glew.h:1896
int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes)
GLAPI void GLAPIENTRY glGetTexParameteriv(GLenum target, GLenum pname, GLint *params)
#define GL_COLOR_BUFFER_BIT
Definition: glew.h:727
static Uint8 readTargetPixels(GPU_Renderer *renderer, GPU_Target *source, GLint format, GLubyte *pixels)
static_inline Uint8 isPowerOfTwo(unsigned int x)
#define glGetShaderInfoLog
Definition: glew.h:1893
static void FreeTarget(GPU_Renderer *renderer, GPU_Target *target)
GPU_BlendEqEnum alpha_equation
Definition: SDL_gpu.h:99
int location
Definition: SDL_gpu.h:423
static const GPU_FeatureEnum GPU_FEATURE_WRAP_REPEAT_MIRRORED
Definition: SDL_gpu.h:326
static Uint8 IsFeatureEnabled(GPU_Renderer *renderer, GPU_FeatureEnum feature)
static const GPU_TypeEnum GPU_TYPE_UNSIGNED_INT
Definition: SDL_gpu.h:378
#define GL_COLOR_ARRAY
Definition: glew.h:784
static void makeContextCurrent(GPU_Renderer *renderer, GPU_Target *target)
#define glUniform1fv
Definition: glew.h:1911
static Uint8 ToggleFullscreen(GPU_Renderer *renderer, Uint8 use_desktop_resolution)
GLuint GLuint end
Definition: glew.h:1221
static void FlushBlitBuffer(GPU_Renderer *renderer)
GLuint64EXT * result
Definition: glew.h:10727
#define glGenerateMipmap
Definition: glew.h:3480
#define GLEW_OK
Definition: glew.h:15440
GPU_TypeEnum type
Definition: SDL_gpu.h:415
Uint32 windowID
Definition: SDL_gpu.h:249
static_inline Uint32 getPixel(SDL_Surface *Surface, int x, int y)
GPU_BlendMode blend_mode
Definition: SDL_gpu.h:187
#define glBufferSubData
Definition: glew.h:1670
static const GPU_FeatureEnum GPU_FEATURE_GEOMETRY_SHADER
Definition: SDL_gpu.h:325
#define glVertexAttrib4f
Definition: glew.h:1959
struct GPU_Renderer * renderer
Definition: SDL_gpu.h:176
void(* BlitTransformX)(GPU_Renderer *renderer, GPU_Image *image, GPU_Rect *src_rect, GPU_Target *target, float x, float y, float pivot_x, float pivot_y, float degrees, float scaleX, float scaleY)
Definition: SDL_gpu.h:595
GPU_Target * current_context_target
Definition: SDL_gpu.h:494
GLAPI void GLAPIENTRY glDrawArrays(GLenum mode, GLint first, GLsizei count)
Uint8 use_clip_rect
Definition: SDL_gpu.h:292
float x
Definition: SDL_gpu.h:206
#define GL_QUADS
Definition: glew.h:306
static void GetUniformiv(GPU_Renderer *renderer, Uint32 program_object, int location, int *values)
#define GPU_BLIT_BUFFER_VERTICES_PER_SPRITE
#define static_inline
static void GetUniformfv(GPU_Renderer *renderer, Uint32 program_object, int location, float *values)
static void SetAttributeuiv(GPU_Renderer *renderer, int location, int num_elements, unsigned int *value)
GPU_BlendEqEnum color_equation
Definition: SDL_gpu.h:98
#define GPU_BLIT_BUFFER_ABSOLUTE_MAX_VERTICES
GLubyte GLubyte GLubyte GLubyte w
Definition: glew.h:1858
const GLdouble * v
Definition: glew.h:1359
GLsizei const GLfloat * value
Definition: glew.h:1817
static GPU_Image * CopyImageFromSurface(GPU_Renderer *renderer, SDL_Surface *surface)
GLenum GLsizei len
Definition: glew.h:5662
static const GPU_TypeEnum GPU_TYPE_UNSIGNED_SHORT
Definition: SDL_gpu.h:376
GPU_BlendMode shapes_blend_mode
Definition: SDL_gpu.h:265
GPU_BlendFuncEnum dest_alpha
Definition: SDL_gpu.h:96
static void DoUntexturedFlush(GPU_CONTEXT_DATA *cdata, unsigned short num_vertices, float *blit_buffer, unsigned int num_indices, unsigned short *index_buffer)
static const GPU_FeatureEnum GPU_FEATURE_BLEND_EQUATIONS
Definition: SDL_gpu.h:316
#define MIX_COLOR_COMPONENT_NORMALIZED_RESULT(a, b)
static Uint32 get_proper_program_id(GPU_Renderer *renderer, Uint32 program_object)
GLboolean GLboolean GLboolean GLboolean a
Definition: glew.h:7319
void GPU_SetInitWindow(Uint32 windowID)
Definition: SDL_gpu.c:145
static void DetachShader(GPU_Renderer *renderer, Uint32 program_object, Uint32 shader_object)
GLAPI void GLAPIENTRY glTexParameteri(GLenum target, GLenum pname, GLint param)
void * context
Definition: SDL_gpu.h:245
static void SetUniformf(GPU_Renderer *renderer, int location, float value)
static void SetVirtualResolution(GPU_Renderer *renderer, GPU_Target *target, Uint16 w, Uint16 h)
void(* SetVirtualResolution)(GPU_Renderer *renderer, GPU_Target *target, Uint16 w, Uint16 h)
Definition: SDL_gpu.h:523
int window_w
Definition: SDL_gpu.h:252
void GPU_AddWindowMapping(GPU_Target *target)
Definition: SDL_gpu.c:191
int position_loc
Definition: SDL_gpu.h:219
#define GL_PROJECTION
Definition: glew.h:641
Uint8 use_color
Definition: SDL_gpu.h:294
#define glUniform3fv
Definition: glew.h:1919
Uint8 failed
Definition: SDL_gpu.h:246
#define glLinkProgram
Definition: glew.h:1905
int per_vertex_storage_offset_bytes
Definition: SDL_gpu.h:435
static void changeTexturing(GPU_Renderer *renderer, Uint8 enable)
void * data
Definition: SDL_gpu.h:290
static const char * GetShaderMessage(GPU_Renderer *renderer)
static GPU_Target * LoadTarget(GPU_Renderer *renderer, GPU_Image *image)
#define glGetProgramiv
Definition: glew.h:1892
GPU_Image * image
Definition: SDL_gpu.h:289
#define GL_RGB
Definition: glew.h:653
GPU_BlendFuncEnum source_color
Definition: SDL_gpu.h:93
GPU_BlendMode GPU_GetBlendModeFromPreset(GPU_BlendPresetEnum preset)
Definition: SDL_gpu.c:1948
#define GPU_INDEX_BUFFER_ABSOLUTE_MAX_VERTICES
GLenum GLint GLuint mask
Definition: glew.h:1813
static void AttachShader(GPU_Renderer *renderer, Uint32 program_object, Uint32 shader_object)
#define glGenBuffers
Definition: glew.h:1674
static void init_features(GPU_Renderer *renderer)
GLAPI void GLAPIENTRY glVertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
int major_version
Definition: SDL_gpu.h:56
struct GPU_Renderer * renderer
Definition: SDL_gpu.h:288
static const GPU_TypeEnum GPU_TYPE_SHORT
Definition: SDL_gpu.h:375
GLAPI void GLAPIENTRY glBegin(GLenum mode)
GLenum glewInit()
Definition: glew.c:11606
int stored_window_w
Definition: SDL_gpu.h:256
static void enableTexturing(GPU_Renderer *renderer)
Uint16 h
Definition: SDL_gpu.h:178
#define GL_BLEND
Definition: glew.h:458
GLfloat GLfloat p
Definition: glew.h:12766
#define GL_COMPILE_STATUS
Definition: glew.h:1761
Uint32 GPU_InitFlagEnum
Definition: SDL_gpu.h:346
typedef int(WINAPI *PFNWGLRELEASEPBUFFERDCARBPROC)(HPBUFFERARB hPbuffer
Uint16 w
Definition: SDL_gpu.h:291
#define GL_REPEAT
Definition: glew.h:701
#define GL_LINK_STATUS
Definition: glew.h:1762
Uint8 shapes_use_blending
Definition: SDL_gpu.h:264
float(* SetLineThickness)(GPU_Renderer *renderer, float thickness)
Definition: SDL_gpu.h:740
surf
Definition: filter.cpp:143
#define GPU_BLIT_BUFFER_TEX_COORD_OFFSET
static Uint8 SetWindowResolution(GPU_Renderer *renderer, Uint16 w, Uint16 h)
static void SetUniformuiv(GPU_Renderer *renderer, int location, int num_elements_per_value, int num_values, unsigned int *values)
GLuint GLuint GLsizei count
Definition: glew.h:1221
static GPU_ShaderBlock LoadShaderBlock(GPU_Renderer *renderer, Uint32 program_object, const char *position_name, const char *texcoord_name, const char *color_name, const char *modelViewMatrix_name)
cl_event GLbitfield flags
Definition: glew.h:3070
int num_layers
Definition: SDL_gpu.h:180
GLuint color
Definition: glew.h:5801
static void Quit(GPU_Renderer *renderer)
static void FreeImage(GPU_Renderer *renderer, GPU_Image *image)
static Uint32 GetShaderSourceSize_RW(SDL_RWops *shader_source)
GPU_RendererID requested_id
Definition: SDL_gpu.h:485
#define GPU_TARGET_DATA
GLAPI void GLAPIENTRY glVertex3f(GLfloat x, GLfloat y, GLfloat z)
#define GL_FRAGMENT_SHADER
Definition: glew.h:1733
static void applyTexturing(GPU_Renderer *renderer)
static void UnsetClip(GPU_Renderer *renderer, GPU_Target *target)
static void BlitTransform(GPU_Renderer *renderer, GPU_Image *image, GPU_Rect *src_rect, GPU_Target *target, float x, float y, float degrees, float scaleX, float scaleY)
static void SetShaderBlock(GPU_Renderer *renderer, GPU_ShaderBlock block)
GLuint buffer
Definition: glew.h:1648
static_inline void flushAndBindTexture(GPU_Renderer *renderer, GLuint handle)
static const GPU_TypeEnum GPU_TYPE_BYTE
Definition: SDL_gpu.h:373
GPU_FilterEnum filter_mode
Definition: SDL_gpu.h:188
static void prepareToRenderShapes(GPU_Renderer *renderer, unsigned int shape)
Encapsulates the map of the game.
Definition: location.hpp:38
Uint8(* IsFeatureEnabled)(GPU_Renderer *renderer, GPU_FeatureEnum feature)
Definition: SDL_gpu.h:504
void GPU_MatrixIdentity(float *result)
static GPU_Image * LoadImage(GPU_Renderer *renderer, const char *filename)
GPU_RendererID id
Definition: SDL_gpu.h:484
static Uint32 GetShaderSource_RW(SDL_RWops *shader_source, char *result)
#define glUniform1f
Definition: glew.h:1910
#define glUniform1iv
Definition: glew.h:1913
#define GL_UNSIGNED_SHORT
Definition: glew.h:612
static_inline Uint8 isCurrentTarget(GPU_Renderer *renderer, GPU_Target *target)
#define GL_TEXTURE_ENV_MODE
Definition: glew.h:681
static void block(LexState *ls)
Definition: lparser.cpp:1081
static_inline void flushAndBindFramebuffer(GPU_Renderer *renderer, GLuint handle)
static void disableTexturing(GPU_Renderer *renderer)
GPU_MatrixStack modelview_matrix
Definition: SDL_gpu.h:271
static_inline void flushBlitBufferIfCurrentTexture(GPU_Renderer *renderer, GPU_Image *image)
static void read_until_end_of_comment(SDL_RWops *rwops, char multiline)
static void SetUniformui(GPU_Renderer *renderer, int location, unsigned int value)
GLAPI void GLAPIENTRY glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices)
#define glGetUniformfv
Definition: glew.h:1897
#define GL_NEAREST
Definition: glew.h:690
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: glew.h:1222
static Uint8 equal_cameras(GPU_Camera a, GPU_Camera b)
logger & err()
Definition: log.cpp:79
#define GL_SRC_ALPHA
Definition: glew.h:331
GLuint GLenum matrix
Definition: glew.h:11418
static const GPU_FeatureEnum GPU_FEATURE_NON_POWER_OF_TWO
Definition: SDL_gpu.h:314
#define glUniformMatrix4fv
Definition: glew.h:1928
void GPU_SetImageFilter(GPU_Image *image, GPU_FilterEnum filter)
Definition: SDL_gpu.c:2094
static void ActivateShaderProgram(GPU_Renderer *renderer, Uint32 program_object, GPU_ShaderBlock *block)
static void setClipRect(GPU_Renderer *renderer, GPU_Target *target)
std::vector< std::string > linked
Definition: build_info.cpp:45
#define GL_FRAMEBUFFER_COMPLETE
Definition: glew.h:3403
static void SetUniformi(GPU_Renderer *renderer, int location, int value)
#define glVertexAttribI2i
Definition: glew.h:2228
#define glAttachShader
Definition: glew.h:1875
GLAPI void GLAPIENTRY glScissor(GLint x, GLint y, GLsizei width, GLsizei height)
GLAPI void GLAPIENTRY glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
#define GL_UNPACK_ROW_LENGTH
Definition: glew.h:507
static void FreeShaderProgram(GPU_Renderer *renderer, Uint32 program_object)
#define GL_TEXTURE_MIN_FILTER
Definition: glew.h:697
GPU_ShaderEnum
Definition: SDL_gpu.h:392
GPU_Target *(* CreateTargetFromWindow)(GPU_Renderer *renderer, Uint32 windowID, GPU_Target *target)
Definition: SDL_gpu.h:508
static void GetUniformuiv(GPU_Renderer *renderer, Uint32 program_object, int location, unsigned int *values)
#define GL_UNPACK_ALIGNMENT
Definition: glew.h:510
GPU_FeatureEnum enabled_features
Definition: SDL_gpu.h:491
GPU_Image *(* CreateImage)(GPU_Renderer *renderer, Uint16 w, Uint16 h, GPU_FormatEnum format)
Definition: SDL_gpu.h:538
void(* UpdateSubImage)(GPU_Renderer *renderer, GPU_Image *image, const GPU_Rect *image_rect, SDL_Surface *surface, const GPU_Rect *surface_rect)
Definition: SDL_gpu.h:556
static SDL_Surface * CopySurfaceFromImage(GPU_Renderer *renderer, GPU_Image *image)
Uint8 has_mipmaps
Definition: SDL_gpu.h:183
GLfloat GLfloat GLfloat GLfloat h
Definition: glew.h:5910
size_t i
Definition: function.cpp:1057
GLboolean invert
Definition: glew.h:1390
#define glUniformMatrix3fv
Definition: glew.h:1927
#define glUniform3iv
Definition: glew.h:1921
#define GL_TEXTURE_MAG_FILTER
Definition: glew.h:696
GLint GLint GLint GLint GLint x
Definition: glew.h:1220
GPU_Target * GPU_LoadTarget(GPU_Image *image)
Definition: SDL_gpu.c:891
GLAPI const GLubyte *GLAPIENTRY glGetString(GLenum name)
#define glUniform4fv
Definition: glew.h:1923
#define glVertexAttribI2ui
Definition: glew.h:2230
static Uint8 readImagePixels(GPU_Renderer *renderer, GPU_Image *source, GLint format, GLubyte *pixels)
#define GPU_PROJECTION
GLAPI void GLAPIENTRY glTexEnvf(GLenum target, GLenum pname, GLfloat param)
GLAPI void GLAPIENTRY glGenTextures(GLsizei n, GLuint *textures)
GLdouble GLdouble GLdouble r
Definition: glew.h:1374
static const char * get_filename_ext(const char *filename)
Uint32(* CompileShader)(GPU_Renderer *renderer, GPU_ShaderEnum shader_type, const char *shader_source)
Definition: SDL_gpu.h:638
void GPU_RemoveWindowMappingByTarget(GPU_Target *target)
Definition: SDL_gpu.c:268
int per_vertex_storage_stride_bytes
Definition: SDL_gpu.h:434
#define GL_SCISSOR_TEST
Definition: glew.h:5891
void GPU_SetWrapMode(GPU_Image *image, GPU_WrapEnum wrap_mode_x, GPU_WrapEnum wrap_mode_y)
Definition: SDL_gpu.c:2120
GPU_Context * context
Definition: SDL_gpu.h:303
GLAPI void GLAPIENTRY glGetIntegerv(GLenum pname, GLint *params)
GLAPI void GLAPIENTRY glClear(GLbitfield mask)
Uint8 is_alias
Definition: SDL_gpu.h:305
#define GL_VERTEX_SHADER
Definition: glew.h:1734
void(* UpdateImage)(GPU_Renderer *renderer, GPU_Image *image, SDL_Surface *surface, const GPU_Rect *surface_rect)
Definition: SDL_gpu.h:553
#define GL_LINEAR_MIPMAP_LINEAR
Definition: glew.h:695
void GPU_MultMatrix(float *A)
#define glBlendFuncSeparate
Definition: glew.h:1538
#define glUniform2uiv
Definition: glew.h:2219
Uint32(* CompileShader_RW)(GPU_Renderer *renderer, GPU_ShaderEnum shader_type, SDL_RWops *shader_source)
Definition: SDL_gpu.h:635
static void GenerateMipmaps(GPU_Renderer *renderer, GPU_Image *image)
GPU_BlendFuncEnum dest_color
Definition: SDL_gpu.h:94
#define glCheckFramebufferStatus
Definition: glew.h:3470
#define glVertexAttrib3f
Definition: glew.h:1945
int refcount
Definition: SDL_gpu.h:194
static void DoPartialFlush(GPU_CONTEXT_DATA *cdata, unsigned short num_vertices, float *blit_buffer, unsigned int num_indices, unsigned short *index_buffer)
GPU_Rect clip_rect
Definition: SDL_gpu.h:293
void * values
Definition: SDL_gpu.h:424
GLAPI void GLAPIENTRY glEnd(void)
#define glVertexAttribI4i
Definition: glew.h:2237
GLsizeiptr size
Definition: glew.h:1649
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
Definition: glew.h:3448
#define GL_ALPHA
Definition: glew.h:652
GPU_InitFlagEnum GPU_init_flags
Definition: SDL_gpu.h:487
GPU_AttributeFormat format
Definition: SDL_gpu.h:425
static const GPU_FeatureEnum GPU_FEATURE_GL_ABGR
Definition: SDL_gpu.h:321
GLclampd n
Definition: glew.h:5903
static void FreeFormat(SDL_PixelFormat *format)
#define MIX_COLORS(color1, color2)
static SDL_Surface * copySurfaceIfNeeded(GPU_Renderer *renderer, GLenum glFormat, SDL_Surface *surface, GLenum *surfaceFormatResult)
#define glDeleteBuffers
Definition: glew.h:1671
float w
Definition: SDL_gpu.h:30
#define glUniform1ui
Definition: glew.h:2216
int matrix_mode
Definition: SDL_gpu.h:269
const GLdouble * m
Definition: glew.h:6968
#define glUniform1uiv
Definition: glew.h:2217
void GPU_GenerateMipmaps(GPU_Image *image)
Definition: SDL_gpu.c:1800
void GPU_FreeImage(GPU_Image *image)
Definition: SDL_gpu.c:873
#define g
Definition: glew.h:12730
static GPU_Image * CreateImage(GPU_Renderer *renderer, Uint16 w, Uint16 h, GPU_FormatEnum format)
float h
Definition: SDL_gpu.h:30
void GPU_LoadIdentity(void)
#define glBindBuffer
Definition: glew.h:1668
static const GPU_FeatureEnum GPU_FEATURE_GL_BGRA
Definition: SDL_gpu.h:320
#define GL_ARRAY_BUFFER
Definition: glew.h:1613
#define GL_FRAMEBUFFER
Definition: glew.h:3428
static const GPU_TypeEnum GPU_TYPE_FLOAT
Definition: SDL_gpu.h:379
static const GPU_TypeEnum GPU_TYPE_UNSIGNED_BYTE
Definition: SDL_gpu.h:374
#define GL_FLOAT
Definition: glew.h:2570
GLenum cap
Definition: glew.h:9255
float * GPU_GetModelView(void)
static void Flip(GPU_Renderer *renderer, GPU_Target *target)
static void DeactivateShaderProgram(GPU_Renderer *renderer)
void * per_vertex_storage
Definition: SDL_gpu.h:437
#define glUseProgram
Definition: glew.h:1929
#define GL_MODULATE
Definition: glew.h:679
int window_h
Definition: SDL_gpu.h:253
int GLint
Definition: glew.h:254
#define glGetProgramInfoLog
Definition: glew.h:1891
#define glDeleteShader
Definition: glew.h:1882
void * data
Definition: SDL_gpu.h:193
#define GL_RG
Definition: glew.h:5127
#define GL_VERSION
Definition: glew.h:672
this module manages the cache of images.
Definition: image.cpp:75
GPU_WindowFlagEnum SDL_init_flags
Definition: SDL_gpu.h:486
GLAPI void GLAPIENTRY glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
#define glVertexAttribI1ui
Definition: glew.h:2226
unsigned int size
Definition: SDL_gpu.h:236
#define GPU_CONTEXT_DATA
#define SET_INDEXED_VERTEX(offset)
static void BlitScale(GPU_Renderer *renderer, GPU_Image *image, GPU_Rect *src_rect, GPU_Target *target, float x, float y, float scaleX, float scaleY)
Uint32 GPU_FeatureEnum
Definition: SDL_gpu.h:313
GLint GLint bottom
Definition: glew.h:5907
GLuint GLuint GLsizei GLenum const GLvoid * indices
Definition: glew.h:1221
SDL_Color color
Definition: SDL_gpu.h:185
Uint16 w
Definition: SDL_gpu.h:178
static void SetUniformiv(GPU_Renderer *renderer, int location, int num_elements_per_value, int num_values, int *values)
#define glDeleteFramebuffers
Definition: glew.h:3471
GPU_WrapEnum
Definition: SDL_gpu.h:143
#define c
Definition: glew.h:12743
#define glVertexAttribI3ui
Definition: glew.h:2234
static Uint32 LinkShaders(GPU_Renderer *renderer, Uint32 shader_object1, Uint32 shader_object2)
Uint32 GPU_TypeEnum
Definition: SDL_gpu.h:371
static char shader_message[256]
float line_thickness
Definition: SDL_gpu.h:266
#define GL_LUMINANCE_ALPHA
Definition: glew.h:656
Uint32 current_shader_program
Definition: SDL_gpu.h:260
#define SDL_FULLSCREEN
Definition: compat.hpp:38
Uint32(* LinkShaderProgram)(GPU_Renderer *renderer, Uint32 program_object)
Definition: SDL_gpu.h:641
#define glDisableVertexAttribArray
Definition: glew.h:1884
static void changeBlending(GPU_Renderer *renderer, Uint8 enable)
GPU_Target *(* LoadTarget)(GPU_Renderer *renderer, GPU_Image *image)
Definition: SDL_gpu.h:577
static GPU_Camera SetCamera(GPU_Renderer *renderer, GPU_Target *target, GPU_Camera *cam)
static void SetShaderImage(GPU_Renderer *renderer, GPU_Image *image, int location, int image_unit)
GPU_WrapEnum wrap_mode_y
Definition: SDL_gpu.h:191
Uint32 GPU_GetInitWindow(void)
Definition: SDL_gpu.c:150
static const GPU_InitFlagEnum GPU_INIT_ENABLE_VSYNC
Definition: SDL_gpu.h:347
float zoom
Definition: SDL_gpu.h:208
static Uint8 hasColorkey(SDL_Surface *surface)
#define mask(n)
Definition: lbitlib.cpp:28
static void SetAttributeiv(GPU_Renderer *renderer, int location, int num_elements, int *value)
void * data
Definition: SDL_gpu.h:273
static unsigned char * getRawImageData(GPU_Renderer *renderer, GPU_Image *image)
#define glBindFramebuffer
Definition: glew.h:3467
GLAPI void GLAPIENTRY glDisable(GLenum cap)
int refcount
Definition: SDL_gpu.h:304
static Uint8 growBlitBuffer(GPU_CONTEXT_DATA *cdata, unsigned int minimum_vertices_needed)
GLAPI void GLAPIENTRY glPixelStorei(GLenum pname, GLint param)
GLAPI void GLAPIENTRY glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
float z
Definition: SDL_gpu.h:206
GPU_Image *(* CopyImageFromSurface)(GPU_Renderer *renderer, SDL_Surface *surface)
Definition: SDL_gpu.h:562
static void BlitTransformMatrix(GPU_Renderer *renderer, GPU_Image *image, GPU_Rect *src_rect, GPU_Target *target, float x, float y, float *matrix3x3)
#define glVertexAttrib1f
Definition: glew.h:1933
#define GL_TEXTURE_WRAP_S
Definition: glew.h:698
int stored_window_h
Definition: SDL_gpu.h:257
#define GL_LINEAR_MIPMAP_NEAREST
Definition: glew.h:693
static void bindTexture(GPU_Renderer *renderer, GPU_Image *image)
int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data)
#define GL_TEXTURE_2D
Definition: glew.h:7985
#define glBufferData
Definition: glew.h:1669
void(* FreeTarget)(GPU_Renderer *renderer, GPU_Target *target)
Definition: SDL_gpu.h:580
static_inline unsigned int getNearestPowerOf2(unsigned int n)
std::vector< std::string > compiled
Definition: build_info.cpp:45
float y
Definition: SDL_gpu.h:206
static GPU_Image * CopyImageFromTarget(GPU_Renderer *renderer, GPU_Target *target)
GPU_Camera(* SetCamera)(GPU_Renderer *renderer, GPU_Target *target, GPU_Camera *cam)
Definition: SDL_gpu.h:535
Uint32 default_textured_shader_program
Definition: SDL_gpu.h:261
GLsizei GLsizei GLchar * source
Definition: glew.h:1800
static void unsetClipRect(GPU_Renderer *renderer, GPU_Target *target)
#define glDeleteProgram
Definition: glew.h:1881
static_inline void flushAndClearBlitBufferIfCurrentTexture(GPU_Renderer *renderer, GPU_Image *image)
unsigned char GLubyte
Definition: glew.h:259
#define GL_LUMINANCE
Definition: glew.h:655
GLAPI void GLAPIENTRY glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels)
#define SDL_GPU_GLES_MAJOR_VERSION
#define GL_TRUE
Definition: glew.h:294
#define glShaderSource
Definition: glew.h:1906
static void SetAttributeui(GPU_Renderer *renderer, int location, unsigned int value)
float x
Definition: SDL_gpu.h:29
Uint8 use_blending
Definition: SDL_gpu.h:186
#define glCompileShader
Definition: glew.h:1878
#define glGetUniformuiv
Definition: glew.h:2209
GLenum target
Definition: glew.h:5190
int texcoord_loc
Definition: SDL_gpu.h:220
static Uint32 CompileShader_RW(GPU_Renderer *renderer, GPU_ShaderEnum shader_type, SDL_RWops *shader_source)
static void SetAttributefv(GPU_Renderer *renderer, int location, int num_elements, float *value)
#define glActiveTexture
Definition: glew.h:1392
GPU_BlendFuncEnum source_alpha
Definition: SDL_gpu.h:95
static_inline void flushAndClearBlitBufferIfCurrentFramebuffer(GPU_Renderer *renderer, GPU_Target *target)
boost::shared_ptr< halo_record > handle
Definition: halo.hpp:34
static SDL_PixelFormat * AllocFormat(GLenum glFormat)
static void UpdateImageBytes(GPU_Renderer *renderer, GPU_Image *image, const GPU_Rect *image_rect, const unsigned char *bytes, int bytes_per_row)
static GPU_Target * CreateTargetFromWindow(GPU_Renderer *renderer, Uint32 windowID, GPU_Target *target)
#define glVertexAttribI4ui
Definition: glew.h:2241
GLclampf f
Definition: glew.h:3024
static void SetAttributeSource(GPU_Renderer *renderer, int num_values, GPU_Attribute source)
static GPU_Target * Init(GPU_Renderer *renderer, GPU_RendererID renderer_request, Uint16 w, Uint16 h, GPU_WindowFlagEnum SDL_flags)