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