SDL_gpu  0.11.0
A hardware-accelerated, cross-platform 2D graphics API
SDL_gpu_renderer.c
Go to the documentation of this file.
1 #include "SDL_gpu.h"
2 #include "SDL_platform.h"
3 #include <string.h>
4 
5 #ifndef _MSC_VER
6  #include <strings.h>
7 #else
8  #define __func__ __FUNCTION__
9 #endif
10 
11 #define GPU_MAX_ACTIVE_RENDERERS 20
12 #define GPU_MAX_REGISTERED_RENDERERS 10
13 
16 
18 {
20  GPU_Renderer* (*createFn)(GPU_RendererID request);
21  void (*freeFn)(GPU_Renderer*);
23 
24 static GPU_bool _gpu_renderer_register_is_initialized = GPU_FALSE;
25 
26 static GPU_Renderer* _gpu_renderer_map[GPU_MAX_ACTIVE_RENDERERS];
27 static GPU_RendererRegistration _gpu_renderer_register[GPU_MAX_REGISTERED_RENDERERS];
28 
29 static int _gpu_renderer_order_size = 0;
30 static GPU_RendererID _gpu_renderer_order[GPU_RENDERER_ORDER_MAX];
31 
32 
33 
34 
35 
36 
38 {
39  static GPU_RendererEnum last_enum = GPU_RENDERER_CUSTOM_0;
40  return last_enum++;
41 }
42 
44 {
45  int count;
46  int i;
47 
49 
50  count = 0;
51  for(i = 0; i < GPU_MAX_ACTIVE_RENDERERS; i++)
52  {
53  if(_gpu_renderer_map[i] != NULL)
54  count++;
55  }
56  return count;
57 }
58 
60 {
61  int count;
62  int i;
63 
65 
66  count = 0;
67  for(i = 0; i < GPU_MAX_ACTIVE_RENDERERS; i++)
68  {
69  if(_gpu_renderer_map[i] != NULL)
70  {
71  renderers_array[count] = _gpu_renderer_map[i]->id;
72  count++;
73  }
74  }
75 }
76 
77 
79 {
80  int count;
81  int i;
82 
84 
85  count = 0;
86  for(i = 0; i < GPU_MAX_REGISTERED_RENDERERS; i++)
87  {
88  if(_gpu_renderer_register[i].id.renderer != GPU_RENDERER_UNKNOWN)
89  count++;
90  }
91  return count;
92 }
93 
95 {
96  int count;
97  int i;
98 
100 
101  count = 0;
102  for(i = 0; i < GPU_MAX_REGISTERED_RENDERERS; i++)
103  {
104  if(_gpu_renderer_register[i].id.renderer != GPU_RENDERER_UNKNOWN)
105  {
106  renderers_array[count] = _gpu_renderer_register[i].id;
107  count++;
108  }
109  }
110 }
111 
112 
114 {
115  int i;
116 
118 
119  for(i = 0; i < GPU_MAX_REGISTERED_RENDERERS; i++)
120  {
121  if(_gpu_renderer_register[i].id.renderer == renderer)
122  return _gpu_renderer_register[i].id;
123  }
124 
125  return GPU_MakeRendererID("Unknown", GPU_RENDERER_UNKNOWN, 0, 0);
126 }
127 
139 void GPU_FreeRenderer_GLES_1(GPU_Renderer* renderer);
141 void GPU_FreeRenderer_GLES_2(GPU_Renderer* renderer);
143 void GPU_FreeRenderer_GLES_3(GPU_Renderer* renderer);
144 
145 void GPU_RegisterRenderer(GPU_RendererID id, GPU_Renderer* (*create_renderer)(GPU_RendererID request), void (*free_renderer)(GPU_Renderer* renderer))
146 {
148 
150  return;
151 
152  if(id.renderer == GPU_RENDERER_UNKNOWN)
153  {
154  GPU_PushErrorCode(__func__, GPU_ERROR_USER_ERROR, "Invalid renderer ID");
155  return;
156  }
157  if(create_renderer == NULL)
158  {
159  GPU_PushErrorCode(__func__, GPU_ERROR_USER_ERROR, "NULL renderer create callback");
160  return;
161  }
162  if(free_renderer == NULL)
163  {
164  GPU_PushErrorCode(__func__, GPU_ERROR_USER_ERROR, "NULL renderer free callback");
165  return;
166  }
167 
168  _gpu_renderer_register[i].id = id;
169  _gpu_renderer_register[i].createFn = create_renderer;
170  _gpu_renderer_register[i].freeFn = free_renderer;
171 }
172 
174 {
175  #ifndef SDL_GPU_DISABLE_OPENGL
176  #ifndef SDL_GPU_DISABLE_OPENGL_1_BASE
177  GPU_RegisterRenderer(GPU_MakeRendererID("OpenGL 1 BASE", GPU_RENDERER_OPENGL_1_BASE, 1, 1),
178  &GPU_CreateRenderer_OpenGL_1_BASE,
180  #endif
181 
182  #ifndef SDL_GPU_DISABLE_OPENGL_1
183  GPU_RegisterRenderer(GPU_MakeRendererID("OpenGL 1", GPU_RENDERER_OPENGL_1, 1, 1),
184  &GPU_CreateRenderer_OpenGL_1,
186  #endif
187 
188  #ifndef SDL_GPU_DISABLE_OPENGL_2
189  GPU_RegisterRenderer(GPU_MakeRendererID("OpenGL 2", GPU_RENDERER_OPENGL_2, 2, 0),
190  &GPU_CreateRenderer_OpenGL_2,
192  #endif
193 
194  #ifndef SDL_GPU_DISABLE_OPENGL_3
195  #ifdef __MACOSX__
196  // Depending on OS X version, it might only support core GL 3.3 or 3.2
197  GPU_RegisterRenderer(GPU_MakeRendererID("OpenGL 3", GPU_RENDERER_OPENGL_3, 3, 2),
198  &GPU_CreateRenderer_OpenGL_3,
200  #else
201  GPU_RegisterRenderer(GPU_MakeRendererID("OpenGL 3", GPU_RENDERER_OPENGL_3, 3, 0),
202  &GPU_CreateRenderer_OpenGL_3,
204  #endif
205  #endif
206 
207  #ifndef SDL_GPU_DISABLE_OPENGL_4
208  #ifdef __MACOSX__
209  GPU_RegisterRenderer(GPU_MakeRendererID("OpenGL 4", GPU_RENDERER_OPENGL_4, 4, 1),
210  &GPU_CreateRenderer_OpenGL_4,
212  #else
213  GPU_RegisterRenderer(GPU_MakeRendererID("OpenGL 4", GPU_RENDERER_OPENGL_4, 4, 0),
214  &GPU_CreateRenderer_OpenGL_4,
216  #endif
217  #endif
218  #endif
219 
220  #ifndef SDL_GPU_DISABLE_GLES
221  #ifndef SDL_GPU_DISABLE_GLES_1
222  GPU_RegisterRenderer(GPU_MakeRendererID("OpenGLES 1", GPU_RENDERER_GLES_1, 1, 1),
223  &GPU_CreateRenderer_GLES_1,
225  #endif
226  #ifndef SDL_GPU_DISABLE_GLES_2
227  GPU_RegisterRenderer(GPU_MakeRendererID("OpenGLES 2", GPU_RENDERER_GLES_2, 2, 0),
228  &GPU_CreateRenderer_GLES_2,
230  #endif
231  #ifndef SDL_GPU_DISABLE_GLES_3
232  GPU_RegisterRenderer(GPU_MakeRendererID("OpenGLES 3", GPU_RENDERER_GLES_3, 3, 0),
233  &GPU_CreateRenderer_GLES_3,
235  #endif
236  #endif
237 
238 }
239 
241 {
242  int i;
243 
244  if(_gpu_renderer_register_is_initialized)
245  return;
246 
247  for(i = 0; i < GPU_MAX_REGISTERED_RENDERERS; i++)
248  {
249  _gpu_renderer_register[i].id.name = "Unknown";
250  _gpu_renderer_register[i].id.renderer = GPU_RENDERER_UNKNOWN;
251  _gpu_renderer_register[i].createFn = NULL;
252  _gpu_renderer_register[i].freeFn = NULL;
253  }
254  for(i = 0; i < GPU_MAX_ACTIVE_RENDERERS; i++)
255  {
256  _gpu_renderer_map[i] = NULL;
257  }
258 
259  GPU_GetDefaultRendererOrder(&_gpu_renderer_order_size, _gpu_renderer_order);
260 
261  _gpu_renderer_register_is_initialized = 1;
262 
264 }
265 
267 {
268  int i;
269 
270  for(i = 0; i < GPU_MAX_REGISTERED_RENDERERS; i++)
271  {
272  _gpu_renderer_register[i].id.name = "Unknown";
273  _gpu_renderer_register[i].id.renderer = GPU_RENDERER_UNKNOWN;
274  _gpu_renderer_register[i].createFn = NULL;
275  _gpu_renderer_register[i].freeFn = NULL;
276  }
277  for(i = 0; i < GPU_MAX_ACTIVE_RENDERERS; i++)
278  {
279  _gpu_renderer_map[i] = NULL;
280  }
281 
282  _gpu_renderer_register_is_initialized = 0;
283  _gpu_renderer_order_size = 0;
284 }
285 
286 
287 void GPU_GetRendererOrder(int* order_size, GPU_RendererID* order)
288 {
289  if(order_size != NULL)
290  *order_size = _gpu_renderer_order_size;
291 
292  if(order != NULL && _gpu_renderer_order_size > 0)
293  memcpy(order, _gpu_renderer_order, _gpu_renderer_order_size*sizeof(GPU_RendererID));
294 }
295 
296 void GPU_SetRendererOrder(int order_size, GPU_RendererID* order)
297 {
298  if(order == NULL)
299  {
300  // Restore the default order
301  int count = 0;
302  GPU_RendererID default_order[GPU_RENDERER_ORDER_MAX];
303  GPU_GetDefaultRendererOrder(&count, default_order);
304  GPU_SetRendererOrder(count, default_order); // Call us again with the default order
305  return;
306  }
307 
308  if(order_size <= 0)
309  return;
310 
311  if(order_size > GPU_RENDERER_ORDER_MAX)
312  {
313  GPU_PushErrorCode(__func__, GPU_ERROR_USER_ERROR, "Given order_size (%d) is greater than GPU_RENDERER_ORDER_MAX (%d)", order_size, GPU_RENDERER_ORDER_MAX);
314  order_size = GPU_RENDERER_ORDER_MAX;
315  }
316 
317  memcpy(_gpu_renderer_order, order, order_size*sizeof(GPU_RendererID));
318  _gpu_renderer_order_size = order_size;
319 }
320 
321 
322 
323 void GPU_GetDefaultRendererOrder(int* order_size, GPU_RendererID* order)
324 {
325  int count = 0;
326  GPU_RendererID default_order[GPU_RENDERER_ORDER_MAX];
327 
328  #ifndef SDL_GPU_DISABLE_GLES
329  #ifndef SDL_GPU_DISABLE_GLES3
330  default_order[count++] = GPU_MakeRendererID("OpenGLES 3", GPU_RENDERER_GLES_3, 3, 0);
331  #endif
332  #ifndef SDL_GPU_DISABLE_GLES2
333  default_order[count++] = GPU_MakeRendererID("OpenGLES 2", GPU_RENDERER_GLES_2, 2, 0);
334  #endif
335  #ifndef SDL_GPU_DISABLE_GLES1
336  default_order[count++] = GPU_MakeRendererID("OpenGLES 1", GPU_RENDERER_GLES_1, 1, 1);
337  #endif
338  #endif
339 
340  #ifndef SDL_GPU_DISABLE_OPENGL
341  #ifdef __MACOSX__
342 
343  // My understanding of OS X OpenGL support:
344  // OS X 10.9: GL 2.1, 3.3, 4.1
345  // OS X 10.7: GL 2.1, 3.2
346  // OS X 10.6: GL 1.4, 2.1
347  #ifndef SDL_GPU_DISABLE_OPENGL_4
348  default_order[count++] = GPU_MakeRendererID("OpenGL 4", GPU_RENDERER_OPENGL_4, 4, 1);
349  #endif
350  #ifndef SDL_GPU_DISABLE_OPENGL_3
351  default_order[count++] = GPU_MakeRendererID("OpenGL 3", GPU_RENDERER_OPENGL_3, 3, 2);
352  #endif
353 
354  #else
355 
356  #ifndef SDL_GPU_DISABLE_OPENGL_4
357  default_order[count++] = GPU_MakeRendererID("OpenGL 4", GPU_RENDERER_OPENGL_4, 4, 0);
358  #endif
359  #ifndef SDL_GPU_DISABLE_OPENGL_3
360  default_order[count++] = GPU_MakeRendererID("OpenGL 3", GPU_RENDERER_OPENGL_3, 3, 0);
361  #endif
362 
363  #endif
364 
365  #ifndef SDL_GPU_DISABLE_OPENGL_2
366  default_order[count++] = GPU_MakeRendererID("OpenGL 2", GPU_RENDERER_OPENGL_2, 2, 0);
367  #endif
368  #ifndef SDL_GPU_DISABLE_OPENGL_1
369  default_order[count++] = GPU_MakeRendererID("OpenGL 1", GPU_RENDERER_OPENGL_1, 1, 1);
370  #endif
371 
372  #endif
373 
374  if(order_size != NULL)
375  *order_size = count;
376 
377  if(order != NULL && count > 0)
378  memcpy(order, default_order, count*sizeof(GPU_RendererID));
379 }
380 
381 
383 {
384  GPU_Renderer* result = NULL;
385  int i;
386  for(i = 0; i < GPU_MAX_REGISTERED_RENDERERS; i++)
387  {
388  if(_gpu_renderer_register[i].id.renderer == GPU_RENDERER_UNKNOWN)
389  continue;
390 
391  if(id.renderer == _gpu_renderer_register[i].id.renderer)
392  {
393  if(_gpu_renderer_register[i].createFn != NULL)
394  {
395  // Use the registered name
396  id.name = _gpu_renderer_register[i].id.name;
397  result = _gpu_renderer_register[i].createFn(id);
398  }
399  break;
400  }
401  }
402 
403  if(result == NULL)
404  {
405  GPU_PushErrorCode(__func__, GPU_ERROR_DATA_ERROR, "Renderer was not found in the renderer registry.");
406  }
407  return result;
408 }
409 
410 // Get a renderer from the map.
412 {
413  int i;
415 
416  // Invalid enum?
417  if(id.renderer == GPU_RENDERER_UNKNOWN)
418  return NULL;
419 
420  for(i = 0; i < GPU_MAX_ACTIVE_RENDERERS; i++)
421  {
422  if(_gpu_renderer_map[i] == NULL)
423  continue;
424 
425  if(id.renderer == _gpu_renderer_map[i]->id.renderer)
426  return _gpu_renderer_map[i];
427  }
428 
429  return NULL;
430 }
431 
432 // Create a new renderer based on a registered id and store it in the map.
434 {
435  int i;
436  for(i = 0; i < GPU_MAX_ACTIVE_RENDERERS; i++)
437  {
438  if(_gpu_renderer_map[i] == NULL)
439  {
440  // Create
441  GPU_Renderer* renderer = GPU_CreateRenderer(id);
442  if(renderer == NULL)
443  {
444  GPU_PushErrorCode(__func__, GPU_ERROR_BACKEND_ERROR, "Failed to create new renderer.");
445  return NULL;
446  }
447 
448  // Add
449  _gpu_renderer_map[i] = renderer;
450  // Return
451  return renderer;
452  }
453  }
454 
455  GPU_PushErrorCode(__func__, GPU_ERROR_BACKEND_ERROR, "Couldn't create a new renderer. Too many active renderers for GPU_MAX_ACTIVE_RENDERERS (%d).", GPU_MAX_ACTIVE_RENDERERS);
456  return NULL;
457 }
458 
459 // Free renderer memory according to how the registry instructs
461 {
462  int i;
463  if(renderer == NULL)
464  return;
465 
466  for(i = 0; i < GPU_MAX_REGISTERED_RENDERERS; i++)
467  {
468  if(_gpu_renderer_register[i].id.renderer == GPU_RENDERER_UNKNOWN)
469  continue;
470 
471  if(renderer->id.renderer == _gpu_renderer_register[i].id.renderer)
472  {
473  _gpu_renderer_register[i].freeFn(renderer);
474  return;
475  }
476  }
477 }
478 
479 // Remove a renderer from the active map and free it.
481 {
482  int i;
483  GPU_Renderer* current_renderer;
484 
485  if(renderer == NULL)
486  return;
487 
488  current_renderer = GPU_GetCurrentRenderer();
489  if(current_renderer == renderer)
490  GPU_SetCurrentRenderer(GPU_MakeRendererID("Unknown", GPU_RENDERER_UNKNOWN, 0, 0));
491 
492  for(i = 0; i < GPU_MAX_ACTIVE_RENDERERS; i++)
493  {
494  if(renderer == _gpu_renderer_map[i])
495  {
496  gpu_free_renderer_memory(renderer);
497  _gpu_renderer_map[i] = NULL;
498  return;
499  }
500  }
501 }
void GPU_FreeRenderer(GPU_Renderer *renderer)
void GPU_FreeRenderer_OpenGL_2(GPU_Renderer *renderer)
#define GPU_RENDERER_CUSTOM_0
Definition: SDL_gpu.h:110
GPU_RendererID id
Definition: SDL_gpu.h:656
void GPU_RegisterRenderer(GPU_RendererID id, GPU_Renderer *(*create_renderer)(GPU_RendererID request), void(*free_renderer)(GPU_Renderer *renderer))
GPU_RendererID GPU_GetRendererID(GPU_RendererEnum renderer)
void GPU_FreeRenderer_GLES_1(GPU_Renderer *renderer)
void GPU_GetRendererOrder(int *order_size, GPU_RendererID *order)
GPU_Renderer *(* createFn)(GPU_RendererID request)
GPU_RendererEnum GPU_ReserveNextRendererEnum(void)
void GPU_SetRendererOrder(int order_size, GPU_RendererID *order)
int GPU_GetNumActiveRenderers(void)
void gpu_init_renderer_register(void)
void GPU_FreeRenderer_OpenGL_1_BASE(GPU_Renderer *renderer)
const char * name
Definition: SDL_gpu.h:121
void GPU_GetActiveRendererList(GPU_RendererID *renderers_array)
GPU_Renderer * GPU_CreateRenderer_OpenGL_4(GPU_RendererID request)
GPU_Renderer * GPU_CreateRenderer_OpenGL_1(GPU_RendererID request)
GPU_Renderer * GPU_CreateRenderer_GLES_3(GPU_RendererID request)
void gpu_free_renderer_memory(GPU_Renderer *renderer)
GPU_Renderer * GPU_GetRenderer(GPU_RendererID id)
int GPU_GetNumRegisteredRenderers(void)
#define GPU_MAX_REGISTERED_RENDERERS
GPU_Renderer * GPU_CreateRenderer_OpenGL_1_BASE(GPU_RendererID request)
void GPU_GetDefaultRendererOrder(int *order_size, GPU_RendererID *order)
DECLSPEC GPU_RendererID SDLCALL GPU_MakeRendererID(const char *name, GPU_RendererEnum renderer, int major_version, int minor_version)
Definition: SDL_gpu.c:844
Uint32 GPU_RendererEnum
Definition: SDL_gpu.h:97
GPU_Renderer * GPU_CreateRenderer_OpenGL_3(GPU_RendererID request)
#define GPU_MAX_ACTIVE_RENDERERS
DECLSPEC void SDLCALL GPU_SetCurrentRenderer(GPU_RendererID id)
Definition: SDL_gpu.c:81
void gpu_register_built_in_renderers(void)
void GPU_FreeRenderer_GLES_3(GPU_Renderer *renderer)
void gpu_free_renderer_register(void)
void GPU_FreeRenderer_OpenGL_4(GPU_Renderer *renderer)
#define GPU_FALSE
Definition: SDL_gpu.h:62
GPU_Renderer * GPU_CreateRenderer_OpenGL_2(GPU_RendererID request)
GPU_Renderer * GPU_CreateRenderer_GLES_1(GPU_RendererID request)
void GPU_FreeRenderer_OpenGL_3(GPU_Renderer *renderer)
GPU_RendererEnum renderer
Definition: SDL_gpu.h:122
DECLSPEC void SDLCALL GPU_PushErrorCode(const char *function, GPU_ErrorEnum error, const char *details,...)
Definition: SDL_gpu.c:692
void(* freeFn)(GPU_Renderer *)
void GPU_FreeRenderer_GLES_2(GPU_Renderer *renderer)
GPU_Renderer * GPU_CreateRenderer_GLES_2(GPU_RendererID request)
void GPU_FreeRenderer_OpenGL_1(GPU_Renderer *renderer)
GPU_Renderer * GPU_CreateRenderer(GPU_RendererID id)
#define GPU_RENDERER_ORDER_MAX
Definition: SDL_gpu.h:95
DECLSPEC GPU_Renderer *SDLCALL GPU_GetCurrentRenderer(void)
Definition: SDL_gpu.c:113
void GPU_GetRegisteredRendererList(GPU_RendererID *renderers_array)
#define GPU_bool
Definition: SDL_gpu.h:59
GPU_Renderer * gpu_create_and_add_renderer(GPU_RendererID id)