this repo has no description
at master 505 lines 15 kB view raw
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}