this repo has no description
at Multitexture 2296 lines 71 kB view raw
1#include "SDL_gpu.h" 2#include "SDL_gpu_RendererImpl.h" 3#include "SDL_platform.h" 4#include "stb_image.h" 5#include "stb_image_write.h" 6#include <stdlib.h> 7#include <string.h> 8 9#ifdef __ANDROID__ 10#include <android/log.h> 11#endif 12 13#ifdef _MSC_VER 14 #define __func__ __FUNCTION__ 15 #pragma warning(push) 16 // Visual Studio wants to complain about while(0) 17 #pragma warning(disable: 4127) 18#endif 19 20#include "stb_image.h" 21 22#ifdef SDL_GPU_USE_SDL2 23 #define GET_ALPHA(sdl_color) ((sdl_color).a) 24#else 25 #define GET_ALPHA(sdl_color) ((sdl_color).unused) 26#endif 27 28#define CHECK_RENDERER (_gpu_current_renderer != NULL) 29#define MAKE_CURRENT_IF_NONE(target) do{ if(_gpu_current_renderer->current_context_target == NULL && target != NULL && target->context != NULL) GPU_MakeCurrent(target, target->context->windowID); } while(0) 30#define CHECK_CONTEXT (_gpu_current_renderer->current_context_target != NULL) 31#define RETURN_ERROR(code, details) do{ GPU_PushErrorCode(__func__, code, "%s", details); return; } while(0) 32 33int gpu_strcasecmp(const char* s1, const char* s2); 34 35void gpu_init_renderer_register(void); 36void gpu_free_renderer_register(void); 37GPU_Renderer* gpu_create_and_add_renderer(GPU_RendererID id); 38 39int gpu_default_print(GPU_LogLevelEnum log_level, const char* format, va_list args); 40 41/*! A mapping of windowID to a GPU_Target to facilitate GPU_GetWindowTarget(). */ 42typedef struct GPU_WindowMapping 43{ 44 Uint32 windowID; 45 GPU_Target* target; 46} GPU_WindowMapping; 47 48static GPU_Renderer* _gpu_current_renderer = NULL; 49 50static GPU_DebugLevelEnum _gpu_debug_level = GPU_DEBUG_LEVEL_0; 51 52#define GPU_DEFAULT_MAX_NUM_ERRORS 20 53#define GPU_ERROR_FUNCTION_STRING_MAX 128 54#define GPU_ERROR_DETAILS_STRING_MAX 512 55static GPU_ErrorObject* _gpu_error_code_queue = NULL; 56static unsigned int _gpu_num_error_codes = 0; 57static unsigned int _gpu_error_code_queue_size = GPU_DEFAULT_MAX_NUM_ERRORS; 58static GPU_ErrorObject _gpu_error_code_result; 59 60#define GPU_INITIAL_WINDOW_MAPPINGS_SIZE 10 61static GPU_WindowMapping* _gpu_window_mappings = NULL; 62static int _gpu_window_mappings_size = 0; 63static int _gpu_num_window_mappings = 0; 64 65static Uint32 _gpu_init_windowID = 0; 66 67static GPU_InitFlagEnum _gpu_preinit_flags = GPU_DEFAULT_INIT_FLAGS; 68static GPU_InitFlagEnum _gpu_required_features = 0; 69 70static Uint8 _gpu_initialized_SDL_core = 0; 71static Uint8 _gpu_initialized_SDL = 0; 72 73static int (*_gpu_print)(GPU_LogLevelEnum log_level, const char* format, va_list args) = &gpu_default_print; 74 75 76SDL_version GPU_GetLinkedVersion(void) 77{ 78 return GPU_GetCompiledVersion(); 79} 80 81void GPU_SetCurrentRenderer(GPU_RendererID id) 82{ 83 _gpu_current_renderer = GPU_GetRenderer(id); 84 85 if(_gpu_current_renderer != NULL) 86 _gpu_current_renderer->impl->SetAsCurrent(_gpu_current_renderer); 87} 88 89void GPU_ResetRendererState(void) 90{ 91 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 92 return; 93 94 _gpu_current_renderer->impl->ResetRendererState(_gpu_current_renderer); 95} 96 97void GPU_SetCoordinateMode(Uint8 use_math_coords) 98{ 99 if(_gpu_current_renderer == NULL) 100 return; 101 102 _gpu_current_renderer->coordinate_mode = use_math_coords; 103} 104 105Uint8 GPU_GetCoordinateMode(void) 106{ 107 if(_gpu_current_renderer == NULL) 108 return 0; 109 110 return _gpu_current_renderer->coordinate_mode; 111} 112 113GPU_Renderer* GPU_GetCurrentRenderer(void) 114{ 115 return _gpu_current_renderer; 116} 117 118Uint32 GPU_GetCurrentShaderProgram(void) 119{ 120 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 121 return 0; 122 123 return _gpu_current_renderer->current_context_target->context->current_shader_program; 124} 125 126 127int gpu_default_print(GPU_LogLevelEnum log_level, const char* format, va_list args) 128{ 129 switch(log_level) 130 { 131#ifdef __ANDROID__ 132 case GPU_LOG_INFO: 133 return __android_log_vprint((GPU_GetDebugLevel() >= GPU_DEBUG_LEVEL_3? ANDROID_LOG_ERROR : ANDROID_LOG_INFO), "APPLICATION", format, args); 134 case GPU_LOG_WARNING: 135 return __android_log_vprint((GPU_GetDebugLevel() >= GPU_DEBUG_LEVEL_2? ANDROID_LOG_ERROR : ANDROID_LOG_WARN), "APPLICATION", format, args); 136 case GPU_LOG_ERROR: 137 return __android_log_vprint(ANDROID_LOG_ERROR, "APPLICATION", format, args); 138#else 139 case GPU_LOG_INFO: 140 return vfprintf((GPU_GetDebugLevel() >= GPU_DEBUG_LEVEL_3? stderr : stdout), format, args); 141 case GPU_LOG_WARNING: 142 return vfprintf((GPU_GetDebugLevel() >= GPU_DEBUG_LEVEL_2? stderr : stdout), format, args); 143 case GPU_LOG_ERROR: 144 return vfprintf(stderr, format, args); 145#endif 146 default: 147 return 0; 148 } 149} 150 151void GPU_SetLogCallback(int (*callback)(GPU_LogLevelEnum log_level, const char* format, va_list args)) 152{ 153 if(callback == NULL) 154 _gpu_print = &gpu_default_print; 155 else 156 _gpu_print = callback; 157} 158 159void GPU_LogInfo(const char* format, ...) 160{ 161 va_list args; 162 va_start(args, format); 163 _gpu_print(GPU_LOG_INFO, format, args); 164 va_end(args); 165} 166 167void GPU_LogWarning(const char* format, ...) 168{ 169 va_list args; 170 va_start(args, format); 171 _gpu_print(GPU_LOG_WARNING, format, args); 172 va_end(args); 173} 174 175void GPU_LogError(const char* format, ...) 176{ 177 va_list args; 178 va_start(args, format); 179 _gpu_print(GPU_LOG_ERROR, format, args); 180 va_end(args); 181} 182 183 184static Uint8 gpu_init_SDL(void) 185{ 186 if(!_gpu_initialized_SDL) 187 { 188 if(!_gpu_initialized_SDL_core && !SDL_WasInit(SDL_INIT_EVERYTHING)) 189 { 190 // Nothing has been set up, so init SDL and the video subsystem. 191 if(SDL_Init(SDL_INIT_VIDEO) < 0) 192 { 193 GPU_PushErrorCode("GPU_Init", GPU_ERROR_BACKEND_ERROR, "Failed to initialize SDL video subsystem"); 194 return 0; 195 } 196 _gpu_initialized_SDL_core = 1; 197 } 198 199 // SDL is definitely ready now, but we're going to init the video subsystem to be sure that SDL_gpu keeps it available until GPU_Quit(). 200 if(SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) 201 { 202 GPU_PushErrorCode("GPU_Init", GPU_ERROR_BACKEND_ERROR, "Failed to initialize SDL video subsystem"); 203 return 0; 204 } 205 _gpu_initialized_SDL = 1; 206 } 207 return 1; 208} 209 210void GPU_SetInitWindow(Uint32 windowID) 211{ 212 _gpu_init_windowID = windowID; 213} 214 215Uint32 GPU_GetInitWindow(void) 216{ 217 return _gpu_init_windowID; 218} 219 220void GPU_SetPreInitFlags(GPU_InitFlagEnum GPU_flags) 221{ 222 _gpu_preinit_flags = GPU_flags; 223} 224 225GPU_InitFlagEnum GPU_GetPreInitFlags(void) 226{ 227 return _gpu_preinit_flags; 228} 229 230void GPU_SetRequiredFeatures(GPU_FeatureEnum features) 231{ 232 _gpu_required_features = features; 233} 234 235GPU_FeatureEnum GPU_GetRequiredFeatures(void) 236{ 237 return _gpu_required_features; 238} 239 240static void gpu_init_error_queue(void) 241{ 242 if(_gpu_error_code_queue == NULL) 243 { 244 unsigned int i; 245 _gpu_error_code_queue = (GPU_ErrorObject*)SDL_malloc(sizeof(GPU_ErrorObject)*_gpu_error_code_queue_size); 246 247 for(i = 0; i < _gpu_error_code_queue_size; i++) 248 { 249 _gpu_error_code_queue[i].function = (char*)SDL_malloc(GPU_ERROR_FUNCTION_STRING_MAX+1); 250 _gpu_error_code_queue[i].error = GPU_ERROR_NONE; 251 _gpu_error_code_queue[i].details = (char*)SDL_malloc(GPU_ERROR_DETAILS_STRING_MAX+1); 252 } 253 _gpu_num_error_codes = 0; 254 255 _gpu_error_code_result.function = (char*)SDL_malloc(GPU_ERROR_FUNCTION_STRING_MAX+1); 256 _gpu_error_code_result.error = GPU_ERROR_NONE; 257 _gpu_error_code_result.details = (char*)SDL_malloc(GPU_ERROR_DETAILS_STRING_MAX+1); 258 } 259} 260 261static void gpu_init_window_mappings(void) 262{ 263 if(_gpu_window_mappings == NULL) 264 { 265 _gpu_window_mappings_size = GPU_INITIAL_WINDOW_MAPPINGS_SIZE; 266 _gpu_window_mappings = (GPU_WindowMapping*)SDL_malloc(_gpu_window_mappings_size * sizeof(GPU_WindowMapping)); 267 _gpu_num_window_mappings = 0; 268 } 269} 270 271void GPU_AddWindowMapping(GPU_Target* target) 272{ 273 Uint32 windowID; 274 int i; 275 276 if(_gpu_window_mappings == NULL) 277 gpu_init_window_mappings(); 278 279 if(target == NULL || target->context == NULL) 280 return; 281 282 windowID = target->context->windowID; 283 if(windowID == 0) // Invalid window ID 284 return; 285 286 // Check for duplicates 287 for(i = 0; i < _gpu_num_window_mappings; i++) 288 { 289 if(_gpu_window_mappings[i].windowID == windowID) 290 { 291 if(_gpu_window_mappings[i].target != target) 292 GPU_PushErrorCode(__func__, GPU_ERROR_DATA_ERROR, "WindowID %u already has a mapping.", windowID); 293 return; 294 } 295 // Don't check the target because it's okay for a single target to be used with multiple windows 296 } 297 298 // Check if list is big enough to hold another 299 if(_gpu_num_window_mappings >= _gpu_window_mappings_size) 300 { 301 GPU_WindowMapping* new_array; 302 _gpu_window_mappings_size *= 2; 303 new_array = (GPU_WindowMapping*)SDL_malloc(_gpu_window_mappings_size * sizeof(GPU_WindowMapping)); 304 memcpy(new_array, _gpu_window_mappings, _gpu_num_window_mappings * sizeof(GPU_WindowMapping)); 305 SDL_free(_gpu_window_mappings); 306 _gpu_window_mappings = new_array; 307 } 308 309 // Add to end of list 310 { 311 GPU_WindowMapping m; 312 m.windowID = windowID; 313 m.target = target; 314 _gpu_window_mappings[_gpu_num_window_mappings] = m; 315 } 316 _gpu_num_window_mappings++; 317} 318 319void GPU_RemoveWindowMapping(Uint32 windowID) 320{ 321 int i; 322 323 if(_gpu_window_mappings == NULL) 324 gpu_init_window_mappings(); 325 326 if(windowID == 0) // Invalid window ID 327 return; 328 329 // Find the occurrence 330 for(i = 0; i < _gpu_num_window_mappings; i++) 331 { 332 if(_gpu_window_mappings[i].windowID == windowID) 333 { 334 int num_to_move; 335 336 // Unset the target's window 337 _gpu_window_mappings[i].target->context->windowID = 0; 338 339 // Move the remaining entries to replace the removed one 340 _gpu_num_window_mappings--; 341 num_to_move = _gpu_num_window_mappings - i; 342 if(num_to_move > 0) 343 memmove(&_gpu_window_mappings[i], &_gpu_window_mappings[i+1], num_to_move * sizeof(GPU_WindowMapping)); 344 return; 345 } 346 } 347 348} 349 350void GPU_RemoveWindowMappingByTarget(GPU_Target* target) 351{ 352 Uint32 windowID; 353 int i; 354 355 if(_gpu_window_mappings == NULL) 356 gpu_init_window_mappings(); 357 358 if(target == NULL || target->context == NULL) 359 return; 360 361 windowID = target->context->windowID; 362 if(windowID == 0) // Invalid window ID 363 return; 364 365 // Unset the target's window 366 target->context->windowID = 0; 367 368 // Find the occurrences 369 for(i = 0; i < _gpu_num_window_mappings; ) 370 { 371 if(_gpu_window_mappings[i].target == target) 372 { 373 // Move the remaining entries to replace the removed one 374 int num_to_move; 375 _gpu_num_window_mappings--; 376 num_to_move = _gpu_num_window_mappings - i; 377 if(num_to_move > 0) 378 memmove(&_gpu_window_mappings[i], &_gpu_window_mappings[i+1], num_to_move * sizeof(GPU_WindowMapping)); 379 return; 380 } 381 else 382 i++; 383 } 384 385} 386 387GPU_Target* GPU_GetWindowTarget(Uint32 windowID) 388{ 389 int i; 390 391 if(_gpu_window_mappings == NULL) 392 gpu_init_window_mappings(); 393 394 if(windowID == 0) // Invalid window ID 395 return NULL; 396 397 // Find the occurrence 398 for(i = 0; i < _gpu_num_window_mappings; i++) 399 { 400 if(_gpu_window_mappings[i].windowID == windowID) 401 return _gpu_window_mappings[i].target; 402 } 403 404 return NULL; 405} 406 407GPU_Target* GPU_Init(Uint16 w, Uint16 h, GPU_WindowFlagEnum SDL_flags) 408{ 409 int renderer_order_size; 410 int i; 411 GPU_RendererID renderer_order[GPU_RENDERER_ORDER_MAX]; 412 413 gpu_init_error_queue(); 414 415 gpu_init_renderer_register(); 416 417 if(!gpu_init_SDL()) 418 return NULL; 419 420 renderer_order_size = 0; 421 GPU_GetRendererOrder(&renderer_order_size, renderer_order); 422 423 // Init the renderers in order 424 for(i = 0; i < renderer_order_size; i++) 425 { 426 GPU_Target* screen = GPU_InitRendererByID(renderer_order[i], w, h, SDL_flags); 427 if(screen != NULL) 428 return screen; 429 } 430 431 GPU_PushErrorCode("GPU_Init", GPU_ERROR_BACKEND_ERROR, "No renderer out of %d was able to initialize properly", renderer_order_size); 432 return NULL; 433} 434 435GPU_Target* GPU_InitRenderer(GPU_RendererEnum renderer_enum, Uint16 w, Uint16 h, GPU_WindowFlagEnum SDL_flags) 436{ 437 // Search registry for this renderer and use that id 438 return GPU_InitRendererByID(GPU_GetRendererID(renderer_enum), w, h, SDL_flags); 439} 440 441GPU_Target* GPU_InitRendererByID(GPU_RendererID renderer_request, Uint16 w, Uint16 h, GPU_WindowFlagEnum SDL_flags) 442{ 443 GPU_Renderer* renderer; 444 GPU_Target* screen; 445 446 gpu_init_error_queue(); 447 gpu_init_renderer_register(); 448 449 if(!gpu_init_SDL()) 450 return NULL; 451 452 renderer = gpu_create_and_add_renderer(renderer_request); 453 if(renderer == NULL) 454 return NULL; 455 456 GPU_SetCurrentRenderer(renderer->id); 457 458 screen = renderer->impl->Init(renderer, renderer_request, w, h, SDL_flags); 459 if(screen == NULL) 460 { 461 GPU_PushErrorCode("GPU_InitRendererByID", GPU_ERROR_BACKEND_ERROR, "Renderer %s failed to initialize properly", renderer->id.name); 462 // Init failed, destroy the renderer... 463 // Erase the window mappings 464 _gpu_num_window_mappings = 0; 465 GPU_CloseCurrentRenderer(); 466 } 467 else 468 GPU_SetInitWindow(0); 469 return screen; 470} 471 472Uint8 GPU_IsFeatureEnabled(GPU_FeatureEnum feature) 473{ 474 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 475 return 0; 476 477 return ((_gpu_current_renderer->enabled_features & feature) == feature); 478} 479 480GPU_Target* GPU_CreateTargetFromWindow(Uint32 windowID) 481{ 482 if(_gpu_current_renderer == NULL) 483 return NULL; 484 485 return _gpu_current_renderer->impl->CreateTargetFromWindow(_gpu_current_renderer, windowID, NULL); 486} 487 488GPU_Target* GPU_CreateAliasTarget(GPU_Target* target) 489{ 490 if(!CHECK_RENDERER) 491 return NULL; 492 MAKE_CURRENT_IF_NONE(target); 493 if(!CHECK_CONTEXT) 494 return NULL; 495 496 return _gpu_current_renderer->impl->CreateAliasTarget(_gpu_current_renderer, target); 497} 498 499void GPU_MakeCurrent(GPU_Target* target, Uint32 windowID) 500{ 501 if(_gpu_current_renderer == NULL) 502 return; 503 504 _gpu_current_renderer->impl->MakeCurrent(_gpu_current_renderer, target, windowID); 505} 506 507Uint8 GPU_SetFullscreen(Uint8 enable_fullscreen, Uint8 use_desktop_resolution) 508{ 509 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 510 return 0; 511 512 return _gpu_current_renderer->impl->SetFullscreen(_gpu_current_renderer, enable_fullscreen, use_desktop_resolution); 513} 514 515Uint8 GPU_GetFullscreen(void) 516{ 517#ifdef SDL_GPU_USE_SDL2 518 GPU_Target* target = GPU_GetContextTarget(); 519 if(target == NULL) 520 return 0; 521 return (Uint8)(SDL_GetWindowFlags(SDL_GetWindowFromID(target->context->windowID)) 522 & (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_FULLSCREEN_DESKTOP)); 523#else 524 SDL_Surface* surf = SDL_GetVideoSurface(); 525 if(surf == NULL) 526 return 0; 527 return (surf->flags & SDL_FULLSCREEN); 528#endif 529} 530 531Uint8 GPU_SetWindowResolution(Uint16 w, Uint16 h) 532{ 533 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL || w == 0 || h == 0) 534 return 0; 535 536 return _gpu_current_renderer->impl->SetWindowResolution(_gpu_current_renderer, w, h); 537} 538 539 540void GPU_GetVirtualResolution(GPU_Target* target, Uint16* w, Uint16* h) 541{ 542 // No checking here for NULL w or h... Should we? 543 if (target == NULL) 544 { 545 *w = 0; 546 *h = 0; 547 } 548 else { 549 *w = target->w; 550 *h = target->h; 551 } 552} 553 554void GPU_SetVirtualResolution(GPU_Target* target, Uint16 w, Uint16 h) 555{ 556 if(!CHECK_RENDERER) 557 RETURN_ERROR(GPU_ERROR_USER_ERROR, "NULL renderer"); 558 MAKE_CURRENT_IF_NONE(target); 559 if(!CHECK_CONTEXT) 560 RETURN_ERROR(GPU_ERROR_USER_ERROR, "NULL context"); 561 if(w == 0 || h == 0) 562 return; 563 564 _gpu_current_renderer->impl->SetVirtualResolution(_gpu_current_renderer, target, w, h); 565} 566 567void GPU_UnsetVirtualResolution(GPU_Target* target) 568{ 569 if(!CHECK_RENDERER) 570 RETURN_ERROR(GPU_ERROR_USER_ERROR, "NULL renderer"); 571 MAKE_CURRENT_IF_NONE(target); 572 if(!CHECK_CONTEXT) 573 RETURN_ERROR(GPU_ERROR_USER_ERROR, "NULL context"); 574 575 _gpu_current_renderer->impl->UnsetVirtualResolution(_gpu_current_renderer, target); 576} 577 578void GPU_SetImageVirtualResolution(GPU_Image* image, Uint16 w, Uint16 h) 579{ 580 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL || w == 0 || h == 0) 581 return; 582 583 if(image == NULL) 584 return; 585 586 image->w = w; 587 image->h = h; 588 image->using_virtual_resolution = 1; 589} 590 591void GPU_UnsetImageVirtualResolution(GPU_Image* image) 592{ 593 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 594 return; 595 596 if(image == NULL) 597 return; 598 599 image->w = image->base_w; 600 image->h = image->base_h; 601 image->using_virtual_resolution = 0; 602} 603 604void gpu_free_error_queue(void) 605{ 606 unsigned int i; 607 // Free the error queue 608 for(i = 0; i < _gpu_error_code_queue_size; i++) 609 { 610 SDL_free(_gpu_error_code_queue[i].function); 611 _gpu_error_code_queue[i].function = NULL; 612 SDL_free(_gpu_error_code_queue[i].details); 613 _gpu_error_code_queue[i].details = NULL; 614 } 615 SDL_free(_gpu_error_code_queue); 616 _gpu_error_code_queue = NULL; 617 _gpu_num_error_codes = 0; 618 619 SDL_free(_gpu_error_code_result.function); 620 _gpu_error_code_result.function = NULL; 621 SDL_free(_gpu_error_code_result.details); 622 _gpu_error_code_result.details = NULL; 623} 624 625// Deletes all existing errors 626void GPU_SetErrorQueueMax(unsigned int max) 627{ 628 gpu_free_error_queue(); 629 630 // Reallocate with new size 631 _gpu_error_code_queue_size = max; 632 gpu_init_error_queue(); 633} 634 635void GPU_CloseCurrentRenderer(void) 636{ 637 if(_gpu_current_renderer == NULL) 638 return; 639 640 _gpu_current_renderer->impl->Quit(_gpu_current_renderer); 641 GPU_FreeRenderer(_gpu_current_renderer); 642} 643 644void GPU_Quit(void) 645{ 646 if(_gpu_num_error_codes > 0 && GPU_GetDebugLevel() >= GPU_DEBUG_LEVEL_1) 647 GPU_LogError("GPU_Quit: %d uncleared error%s.\n", _gpu_num_error_codes, (_gpu_num_error_codes > 1? "s" : "")); 648 649 gpu_free_error_queue(); 650 651 if(_gpu_current_renderer == NULL) 652 return; 653 654 _gpu_current_renderer->impl->Quit(_gpu_current_renderer); 655 GPU_FreeRenderer(_gpu_current_renderer); 656 // FIXME: Free all renderers 657 _gpu_current_renderer = NULL; 658 659 _gpu_init_windowID = 0; 660 661 // Free window mappings 662 SDL_free(_gpu_window_mappings); 663 _gpu_window_mappings = NULL; 664 _gpu_window_mappings_size = 0; 665 _gpu_num_window_mappings = 0; 666 667 gpu_free_renderer_register(); 668 669 if(_gpu_initialized_SDL) 670 { 671 SDL_QuitSubSystem(SDL_INIT_VIDEO); 672 _gpu_initialized_SDL = 0; 673 674 if(_gpu_initialized_SDL_core) 675 { 676 SDL_Quit(); 677 _gpu_initialized_SDL_core = 0; 678 } 679 } 680} 681 682void GPU_SetDebugLevel(GPU_DebugLevelEnum level) 683{ 684 if(level > GPU_DEBUG_LEVEL_MAX) 685 level = GPU_DEBUG_LEVEL_MAX; 686 _gpu_debug_level = level; 687} 688 689GPU_DebugLevelEnum GPU_GetDebugLevel(void) 690{ 691 return _gpu_debug_level; 692} 693 694void GPU_PushErrorCode(const char* function, GPU_ErrorEnum error, const char* details, ...) 695{ 696 gpu_init_error_queue(); 697 698 if(GPU_GetDebugLevel() >= GPU_DEBUG_LEVEL_1) 699 { 700 // Print the message 701 if(details != NULL) 702 { 703 char buf[GPU_ERROR_DETAILS_STRING_MAX]; 704 va_list lst; 705 va_start(lst, details); 706 vsnprintf(buf, GPU_ERROR_DETAILS_STRING_MAX, details, lst); 707 va_end(lst); 708 709 GPU_LogError("%s: %s - %s\n", (function == NULL? "NULL" : function), GPU_GetErrorString(error), buf); 710 } 711 else 712 GPU_LogError("%s: %s\n", (function == NULL? "NULL" : function), GPU_GetErrorString(error)); 713 } 714 715 if(_gpu_num_error_codes < _gpu_error_code_queue_size) 716 { 717 if(function == NULL) 718 _gpu_error_code_queue[_gpu_num_error_codes].function[0] = '\0'; 719 else 720 { 721 strncpy(_gpu_error_code_queue[_gpu_num_error_codes].function, function, GPU_ERROR_FUNCTION_STRING_MAX); 722 _gpu_error_code_queue[_gpu_num_error_codes].function[GPU_ERROR_FUNCTION_STRING_MAX] = '\0'; 723 } 724 _gpu_error_code_queue[_gpu_num_error_codes].error = error; 725 if(details == NULL) 726 _gpu_error_code_queue[_gpu_num_error_codes].details[0] = '\0'; 727 else 728 { 729 va_list lst; 730 va_start(lst, details); 731 vsnprintf(_gpu_error_code_queue[_gpu_num_error_codes].details, GPU_ERROR_DETAILS_STRING_MAX, details, lst); 732 va_end(lst); 733 } 734 _gpu_num_error_codes++; 735 } 736} 737 738GPU_ErrorObject GPU_PopErrorCode(void) 739{ 740 unsigned int i; 741 GPU_ErrorObject result = {NULL, GPU_ERROR_NONE, NULL}; 742 743 gpu_init_error_queue(); 744 745 if(_gpu_num_error_codes <= 0) 746 return result; 747 748 // Pop the oldest 749 strcpy(_gpu_error_code_result.function, _gpu_error_code_queue[0].function); 750 _gpu_error_code_result.error = _gpu_error_code_queue[0].error; 751 strcpy(_gpu_error_code_result.details, _gpu_error_code_queue[0].details); 752 753 // We'll be returning that one 754 result = _gpu_error_code_result; 755 756 // Move the rest down 757 _gpu_num_error_codes--; 758 for(i = 0; i < _gpu_num_error_codes; i++) 759 { 760 strcpy(_gpu_error_code_queue[i].function, _gpu_error_code_queue[i+1].function); 761 _gpu_error_code_queue[i].error = _gpu_error_code_queue[i+1].error; 762 strcpy(_gpu_error_code_queue[i].details, _gpu_error_code_queue[i+1].details); 763 } 764 return result; 765} 766 767const char* GPU_GetErrorString(GPU_ErrorEnum error) 768{ 769 switch(error) 770 { 771 case GPU_ERROR_NONE: 772 return "NO ERROR"; 773 case GPU_ERROR_BACKEND_ERROR: 774 return "BACKEND ERROR"; 775 case GPU_ERROR_DATA_ERROR: 776 return "DATA ERROR"; 777 case GPU_ERROR_USER_ERROR: 778 return "USER ERROR"; 779 case GPU_ERROR_UNSUPPORTED_FUNCTION: 780 return "UNSUPPORTED FUNCTION"; 781 case GPU_ERROR_NULL_ARGUMENT: 782 return "NULL ARGUMENT"; 783 case GPU_ERROR_FILE_NOT_FOUND: 784 return "FILE NOT FOUND"; 785 } 786 return "UNKNOWN ERROR"; 787} 788 789 790void GPU_GetVirtualCoords(GPU_Target* target, float* x, float* y, float displayX, float displayY) 791{ 792 if(target == NULL) 793 return; 794 795 if(target->context != NULL) 796 { 797 if(x != NULL) 798 *x = (displayX*target->w)/target->context->window_w; 799 if(y != NULL) 800 *y = (displayY*target->h)/target->context->window_h; 801 } 802 else if(target->image != NULL) 803 { 804 if(x != NULL) 805 *x = (displayX*target->w)/target->image->w; 806 if(y != NULL) 807 *y = (displayY*target->h)/target->image->h; 808 } 809 else 810 { 811 if(x != NULL) 812 *x = displayX; 813 if(y != NULL) 814 *y = displayY; 815 } 816} 817 818GPU_Rect GPU_MakeRect(float x, float y, float w, float h) 819{ 820 GPU_Rect r; 821 r.x = x; 822 r.y = y; 823 r.w = w; 824 r.h = h; 825 826 return r; 827} 828 829SDL_Color GPU_MakeColor(Uint8 r, Uint8 g, Uint8 b, Uint8 a) 830{ 831 SDL_Color c; 832 c.r = r; 833 c.g = g; 834 c.b = b; 835 GET_ALPHA(c) = a; 836 837 return c; 838} 839 840GPU_RendererID GPU_MakeRendererID(const char* name, GPU_RendererEnum renderer, int major_version, int minor_version) 841{ 842 GPU_RendererID r; 843 r.name = name; 844 r.renderer = renderer; 845 r.major_version = major_version; 846 r.minor_version = minor_version; 847 848 return r; 849} 850 851void GPU_SetViewport(GPU_Target* target, GPU_Rect viewport) 852{ 853 if(target != NULL) 854 target->viewport = viewport; 855} 856 857void GPU_UnsetViewport(GPU_Target* target) 858{ 859 if(target != NULL) 860 target->viewport = GPU_MakeRect(0, 0, target->w, target->h); 861} 862 863GPU_Camera GPU_GetDefaultCamera(void) 864{ 865 GPU_Camera cam = {0.0f, 0.0f, -10.0f, 0.0f, 1.0f}; 866 return cam; 867} 868 869GPU_Camera GPU_GetCamera(GPU_Target* target) 870{ 871 if(target == NULL) 872 return GPU_GetDefaultCamera(); 873 return target->camera; 874} 875 876GPU_Camera GPU_SetCamera(GPU_Target* target, GPU_Camera* cam) 877{ 878 if(_gpu_current_renderer == NULL) 879 return GPU_GetDefaultCamera(); 880 MAKE_CURRENT_IF_NONE(target); 881 if(_gpu_current_renderer->current_context_target == NULL) 882 return GPU_GetDefaultCamera(); 883 884 return _gpu_current_renderer->impl->SetCamera(_gpu_current_renderer, target, cam); 885} 886 887GPU_Image* GPU_CreateImage(Uint16 w, Uint16 h, GPU_FormatEnum format) 888{ 889 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 890 return NULL; 891 892 return _gpu_current_renderer->impl->CreateImage(_gpu_current_renderer, w, h, format); 893} 894 895GPU_Image* GPU_CreateImageUsingTexture(Uint32 handle, Uint8 take_ownership) 896{ 897 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 898 return NULL; 899 900 return _gpu_current_renderer->impl->CreateImageUsingTexture(_gpu_current_renderer, handle, take_ownership); 901} 902 903GPU_Image* GPU_LoadImage(const char* filename) 904{ 905 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 906 return NULL; 907 908 return _gpu_current_renderer->impl->LoadImage(_gpu_current_renderer, filename); 909} 910 911GPU_Image* GPU_CreateAliasImage(GPU_Image* image) 912{ 913 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 914 return NULL; 915 916 return _gpu_current_renderer->impl->CreateAliasImage(_gpu_current_renderer, image); 917} 918 919Uint8 GPU_SaveImage(GPU_Image* image, const char* filename, GPU_FileFormatEnum format) 920{ 921 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 922 return 0; 923 924 return _gpu_current_renderer->impl->SaveImage(_gpu_current_renderer, image, filename, format); 925} 926 927GPU_Image* GPU_CopyImage(GPU_Image* image) 928{ 929 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 930 return NULL; 931 932 return _gpu_current_renderer->impl->CopyImage(_gpu_current_renderer, image); 933} 934 935void GPU_UpdateImage(GPU_Image* image, const GPU_Rect* image_rect, SDL_Surface* surface, const GPU_Rect* surface_rect) 936{ 937 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 938 return; 939 940 _gpu_current_renderer->impl->UpdateImage(_gpu_current_renderer, image, image_rect, surface, surface_rect); 941} 942 943void GPU_UpdateImageBytes(GPU_Image* image, const GPU_Rect* image_rect, const unsigned char* bytes, int bytes_per_row) 944{ 945 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 946 return; 947 948 _gpu_current_renderer->impl->UpdateImageBytes(_gpu_current_renderer, image, image_rect, bytes, bytes_per_row); 949} 950 951Uint8 GPU_ReplaceImage(GPU_Image* image, SDL_Surface* surface, const GPU_Rect* surface_rect) 952{ 953 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 954 return 0; 955 956 return _gpu_current_renderer->impl->ReplaceImage(_gpu_current_renderer, image, surface, surface_rect); 957} 958 959static SDL_Surface* gpu_copy_raw_surface_data(unsigned char* data, int width, int height, int channels) 960{ 961 int i; 962 Uint32 Rmask, Gmask, Bmask, Amask = 0; 963 SDL_Surface* result; 964 965 if(data == NULL) 966 { 967 GPU_PushErrorCode(__func__, GPU_ERROR_DATA_ERROR, "Got NULL data"); 968 return NULL; 969 } 970 971 switch(channels) 972 { 973 case 1: 974 Rmask = Gmask = Bmask = 0; // Use default RGB masks for 8-bit 975 break; 976 case 2: 977 Rmask = Gmask = Bmask = 0; // Use default RGB masks for 16-bit 978 break; 979 case 3: 980 // These are reversed from what SDL_image uses... That is bad. :( Needs testing. 981#if SDL_BYTEORDER == SDL_BIG_ENDIAN 982 Rmask = 0xff0000; 983 Gmask = 0x00ff00; 984 Bmask = 0x0000ff; 985#else 986 Rmask = 0x0000ff; 987 Gmask = 0x00ff00; 988 Bmask = 0xff0000; 989#endif 990 break; 991 case 4: 992 Rmask = 0x000000ff; 993 Gmask = 0x0000ff00; 994 Bmask = 0x00ff0000; 995 Amask = 0xff000000; 996 break; 997 default: 998 Rmask = Gmask = Bmask = 0; 999 GPU_PushErrorCode(__func__, GPU_ERROR_DATA_ERROR, "Invalid number of channels: %d", channels); 1000 return NULL; 1001 break; 1002 } 1003 1004 result = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, channels*8, Rmask, Gmask, Bmask, Amask); 1005 if(result == NULL) 1006 { 1007 GPU_PushErrorCode(__func__, GPU_ERROR_DATA_ERROR, "Failed to create new %dx%d surface", width, height); 1008 return NULL; 1009 } 1010 1011 // Copy row-by-row in case the pitch doesn't match 1012 for(i = 0; i < height; ++i) 1013 { 1014 memcpy((Uint8*)result->pixels + i*result->pitch, data + channels*width*i, channels*width); 1015 } 1016 1017 if(result != NULL && result->format->palette != NULL) 1018 { 1019 // SDL_CreateRGBSurface has no idea what palette to use, so it uses a blank one. 1020 // We'll at least create a grayscale one, but it's not ideal... 1021 // Better would be to get the palette from stbi, but stbi doesn't do that! 1022 SDL_Color colors[256]; 1023 int i; 1024 1025 for(i = 0; i < 256; i++) 1026 { 1027 colors[i].r = colors[i].g = colors[i].b = (Uint8)i; 1028 } 1029 1030 /* Set palette */ 1031#ifdef SDL_GPU_USE_SDL2 1032 SDL_SetPaletteColors(result->format->palette, colors, 0, 256); 1033#else 1034 SDL_SetPalette(result, SDL_LOGPAL, colors, 0, 256); 1035#endif 1036 } 1037 1038 return result; 1039} 1040 1041SDL_Surface* GPU_LoadSurface_RW(SDL_RWops* rwops, Uint8 free_rwops) 1042{ 1043 int width, height, channels; 1044 unsigned char* data; 1045 SDL_Surface* result; 1046 1047 int data_bytes; 1048 unsigned char* c_data; 1049 1050 if(rwops == NULL) 1051 { 1052 GPU_PushErrorCode(__func__, GPU_ERROR_NULL_ARGUMENT, "rwops"); 1053 return NULL; 1054 } 1055 1056 // Get count of bytes 1057 SDL_RWseek(rwops, 0, SEEK_SET); 1058 data_bytes = SDL_RWseek(rwops, 0, SEEK_END); 1059 SDL_RWseek(rwops, 0, SEEK_SET); 1060 1061 // Read in the rwops data 1062 c_data = (unsigned char*)SDL_malloc(data_bytes); 1063 SDL_RWread(rwops, c_data, 1, data_bytes); 1064 1065 // Load image 1066 data = stbi_load_from_memory(c_data, data_bytes, &width, &height, &channels, 0); 1067 1068 // Clean up temp data 1069 SDL_free(c_data); 1070 if(free_rwops) 1071 SDL_RWclose(rwops); 1072 1073 if(data == NULL) 1074 { 1075 GPU_PushErrorCode(__func__, GPU_ERROR_DATA_ERROR, "Failed to load from rwops: %s", stbi_failure_reason()); 1076 return NULL; 1077 } 1078 1079 // Copy into a surface 1080 result = gpu_copy_raw_surface_data(data, width, height, channels); 1081 1082 stbi_image_free(data); 1083 1084 return result; 1085} 1086 1087SDL_Surface* GPU_LoadSurface(const char* filename) 1088{ 1089 int width, height, channels; 1090 unsigned char* data; 1091 SDL_Surface* result; 1092 1093 if(filename == NULL) 1094 { 1095 GPU_PushErrorCode("GPU_LoadSurface", GPU_ERROR_NULL_ARGUMENT, "filename"); 1096 return NULL; 1097 } 1098 1099#ifdef __ANDROID__ 1100 // Must use SDL_RWops to access the assets directory automatically 1101 if(strlen(filename) > 0 && filename[0] != '/') 1102 return GPU_LoadSurface_RW(SDL_RWFromFile(filename, "r"), 1); 1103#endif 1104 1105 data = stbi_load(filename, &width, &height, &channels, 0); 1106 1107 if(data == NULL) 1108 { 1109 GPU_PushErrorCode(__func__, GPU_ERROR_DATA_ERROR, "Failed to load \"%s\": %s", filename, stbi_failure_reason()); 1110 return NULL; 1111 } 1112 1113 result = gpu_copy_raw_surface_data(data, width, height, channels); 1114 1115 stbi_image_free(data); 1116 1117 return result; 1118} 1119 1120// From http://stackoverflow.com/questions/5309471/getting-file-extension-in-c 1121static const char *get_filename_ext(const char *filename) 1122{ 1123 const char *dot = strrchr(filename, '.'); 1124 if(!dot || dot == filename) 1125 return ""; 1126 return dot + 1; 1127} 1128 1129Uint8 GPU_SaveSurface(SDL_Surface* surface, const char* filename, GPU_FileFormatEnum format) 1130{ 1131 Uint8 result; 1132 unsigned char* data; 1133 1134 if(surface == NULL || filename == NULL || 1135 surface->w < 1 || surface->h < 1) 1136 { 1137 return 0; 1138 } 1139 1140 1141 data = surface->pixels; 1142 1143 if(format == GPU_FILE_AUTO) 1144 { 1145 const char* extension = get_filename_ext(filename); 1146 if(gpu_strcasecmp(extension, "png") == 0) 1147 format = GPU_FILE_PNG; 1148 else if(gpu_strcasecmp(extension, "bmp") == 0) 1149 format = GPU_FILE_BMP; 1150 else if(gpu_strcasecmp(extension, "tga") == 0) 1151 format = GPU_FILE_TGA; 1152 else 1153 { 1154 GPU_PushErrorCode(__func__, GPU_ERROR_DATA_ERROR, "Could not detect output file format from file name"); 1155 return 0; 1156 } 1157 } 1158 1159 switch(format) 1160 { 1161 case GPU_FILE_PNG: 1162 result = (stbi_write_png(filename, surface->w, surface->h, surface->format->BytesPerPixel, (const unsigned char *const)data, 0) > 0); 1163 break; 1164 case GPU_FILE_BMP: 1165 result = (stbi_write_bmp(filename, surface->w, surface->h, surface->format->BytesPerPixel, (void*)data) > 0); 1166 break; 1167 case GPU_FILE_TGA: 1168 result = (stbi_write_tga(filename, surface->w, surface->h, surface->format->BytesPerPixel, (void*)data) > 0); 1169 break; 1170 default: 1171 GPU_PushErrorCode(__func__, GPU_ERROR_DATA_ERROR, "Unsupported output file format"); 1172 result = 0; 1173 break; 1174 } 1175 1176 return result; 1177} 1178 1179GPU_Image* GPU_CopyImageFromSurface(SDL_Surface* surface) 1180{ 1181 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 1182 return NULL; 1183 1184 return _gpu_current_renderer->impl->CopyImageFromSurface(_gpu_current_renderer, surface); 1185} 1186 1187GPU_Image* GPU_CopyImageFromTarget(GPU_Target* target) 1188{ 1189 if(_gpu_current_renderer == NULL) 1190 return NULL; 1191 MAKE_CURRENT_IF_NONE(target); 1192 if(_gpu_current_renderer->current_context_target == NULL) 1193 return NULL; 1194 1195 return _gpu_current_renderer->impl->CopyImageFromTarget(_gpu_current_renderer, target); 1196} 1197 1198SDL_Surface* GPU_CopySurfaceFromTarget(GPU_Target* target) 1199{ 1200 if(_gpu_current_renderer == NULL) 1201 return NULL; 1202 MAKE_CURRENT_IF_NONE(target); 1203 if(_gpu_current_renderer->current_context_target == NULL) 1204 return NULL; 1205 1206 return _gpu_current_renderer->impl->CopySurfaceFromTarget(_gpu_current_renderer, target); 1207} 1208 1209SDL_Surface* GPU_CopySurfaceFromImage(GPU_Image* image) 1210{ 1211 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 1212 return NULL; 1213 1214 return _gpu_current_renderer->impl->CopySurfaceFromImage(_gpu_current_renderer, image); 1215} 1216 1217void GPU_FreeImage(GPU_Image* image) 1218{ 1219 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 1220 return; 1221 1222 _gpu_current_renderer->impl->FreeImage(_gpu_current_renderer, image); 1223} 1224 1225 1226GPU_Target* GPU_GetContextTarget(void) 1227{ 1228 if(_gpu_current_renderer == NULL) 1229 return NULL; 1230 1231 return _gpu_current_renderer->current_context_target; 1232} 1233 1234 1235GPU_Target* GPU_LoadTarget(GPU_Image* image) 1236{ 1237 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 1238 return NULL; 1239 1240 return _gpu_current_renderer->impl->LoadTarget(_gpu_current_renderer, image); 1241} 1242 1243 1244 1245void GPU_FreeTarget(GPU_Target* target) 1246{ 1247 if(_gpu_current_renderer == NULL) 1248 return; 1249 1250 _gpu_current_renderer->impl->FreeTarget(_gpu_current_renderer, target); 1251} 1252 1253 1254 1255void GPU_Blit(GPU_Image* image, GPU_Rect* src_rect, GPU_Target* target, float x, float y) 1256{ 1257 if(!CHECK_RENDERER) 1258 RETURN_ERROR(GPU_ERROR_USER_ERROR, "NULL renderer"); 1259 MAKE_CURRENT_IF_NONE(target); 1260 if(!CHECK_CONTEXT) 1261 RETURN_ERROR(GPU_ERROR_USER_ERROR, "NULL context"); 1262 1263 if(image == NULL) 1264 RETURN_ERROR(GPU_ERROR_NULL_ARGUMENT, "image"); 1265 if(target == NULL) 1266 RETURN_ERROR(GPU_ERROR_NULL_ARGUMENT, "target"); 1267 1268 _gpu_current_renderer->impl->Blit(_gpu_current_renderer, image, src_rect, target, x, y); 1269} 1270 1271 1272void GPU_BlitRotate(GPU_Image* image, GPU_Rect* src_rect, GPU_Target* target, float x, float y, float angle) 1273{ 1274 if(!CHECK_RENDERER) 1275 RETURN_ERROR(GPU_ERROR_USER_ERROR, "NULL renderer"); 1276 MAKE_CURRENT_IF_NONE(target); 1277 if(!CHECK_CONTEXT) 1278 RETURN_ERROR(GPU_ERROR_USER_ERROR, "NULL context"); 1279 1280 if(image == NULL) 1281 RETURN_ERROR(GPU_ERROR_NULL_ARGUMENT, "image"); 1282 if(target == NULL) 1283 RETURN_ERROR(GPU_ERROR_NULL_ARGUMENT, "target"); 1284 1285 _gpu_current_renderer->impl->BlitRotate(_gpu_current_renderer, image, src_rect, target, x, y, angle); 1286} 1287 1288void GPU_BlitScale(GPU_Image* image, GPU_Rect* src_rect, GPU_Target* target, float x, float y, float scaleX, float scaleY) 1289{ 1290 if(!CHECK_RENDERER) 1291 RETURN_ERROR(GPU_ERROR_USER_ERROR, "NULL renderer"); 1292 MAKE_CURRENT_IF_NONE(target); 1293 if(!CHECK_CONTEXT) 1294 RETURN_ERROR(GPU_ERROR_USER_ERROR, "NULL context"); 1295 1296 if(image == NULL) 1297 RETURN_ERROR(GPU_ERROR_NULL_ARGUMENT, "image"); 1298 if(target == NULL) 1299 RETURN_ERROR(GPU_ERROR_NULL_ARGUMENT, "target"); 1300 1301 _gpu_current_renderer->impl->BlitScale(_gpu_current_renderer, image, src_rect, target, x, y, scaleX, scaleY); 1302} 1303 1304void GPU_BlitTransform(GPU_Image* image, GPU_Rect* src_rect, GPU_Target* target, float x, float y, float angle, float scaleX, float scaleY) 1305{ 1306 if(!CHECK_RENDERER) 1307 RETURN_ERROR(GPU_ERROR_USER_ERROR, "NULL renderer"); 1308 MAKE_CURRENT_IF_NONE(target); 1309 if(!CHECK_CONTEXT) 1310 RETURN_ERROR(GPU_ERROR_USER_ERROR, "NULL context"); 1311 1312 if(image == NULL) 1313 RETURN_ERROR(GPU_ERROR_NULL_ARGUMENT, "image"); 1314 if(target == NULL) 1315 RETURN_ERROR(GPU_ERROR_NULL_ARGUMENT, "target"); 1316 1317 _gpu_current_renderer->impl->BlitTransform(_gpu_current_renderer, image, src_rect, target, x, y, angle, scaleX, scaleY); 1318} 1319 1320void GPU_BlitTransformX(GPU_Image* image, GPU_Rect* src_rect, GPU_Target* target, float x, float y, float pivot_x, float pivot_y, float angle, float scaleX, float scaleY) 1321{ 1322 if(!CHECK_RENDERER) 1323 RETURN_ERROR(GPU_ERROR_USER_ERROR, "NULL renderer"); 1324 MAKE_CURRENT_IF_NONE(target); 1325 if(!CHECK_CONTEXT) 1326 RETURN_ERROR(GPU_ERROR_USER_ERROR, "NULL context"); 1327 1328 if(image == NULL) 1329 RETURN_ERROR(GPU_ERROR_NULL_ARGUMENT, "image"); 1330 if(target == NULL) 1331 RETURN_ERROR(GPU_ERROR_NULL_ARGUMENT, "target"); 1332 1333 _gpu_current_renderer->impl->BlitTransformX(_gpu_current_renderer, image, src_rect, target, x, y, pivot_x, pivot_y, angle, scaleX, scaleY); 1334} 1335 1336void GPU_TriangleBatch(GPU_Image* image, GPU_Target* target, unsigned short num_vertices, float* values, unsigned int num_indices, unsigned short* indices, GPU_BatchFlagEnum flags) 1337{ 1338 if(!CHECK_RENDERER) 1339 RETURN_ERROR(GPU_ERROR_USER_ERROR, "NULL renderer"); 1340 MAKE_CURRENT_IF_NONE(target); 1341 if(!CHECK_CONTEXT) 1342 RETURN_ERROR(GPU_ERROR_USER_ERROR, "NULL context"); 1343 1344 if(target == NULL) 1345 RETURN_ERROR(GPU_ERROR_NULL_ARGUMENT, "target"); 1346 1347 if(num_vertices == 0) 1348 return; 1349 1350 1351 _gpu_current_renderer->impl->TriangleBatch(_gpu_current_renderer, image, target, num_vertices, values, num_indices, indices, flags); 1352} 1353 1354 1355 1356 1357void GPU_GenerateMipmaps(GPU_Image* image) 1358{ 1359 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 1360 return; 1361 1362 _gpu_current_renderer->impl->GenerateMipmaps(_gpu_current_renderer, image); 1363} 1364 1365 1366 1367 1368GPU_Rect GPU_SetClipRect(GPU_Target* target, GPU_Rect rect) 1369{ 1370 if(target == NULL || _gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 1371 { 1372 GPU_Rect r = {0,0,0,0}; 1373 return r; 1374 } 1375 1376 return _gpu_current_renderer->impl->SetClip(_gpu_current_renderer, target, (Sint16)rect.x, (Sint16)rect.y, (Uint16)rect.w, (Uint16)rect.h); 1377} 1378 1379GPU_Rect GPU_SetClip(GPU_Target* target, Sint16 x, Sint16 y, Uint16 w, Uint16 h) 1380{ 1381 if(target == NULL || _gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 1382 { 1383 GPU_Rect r = {0,0,0,0}; 1384 return r; 1385 } 1386 1387 return _gpu_current_renderer->impl->SetClip(_gpu_current_renderer, target, x, y, w, h); 1388} 1389 1390void GPU_UnsetClip(GPU_Target* target) 1391{ 1392 if(target == NULL || _gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 1393 return; 1394 1395 _gpu_current_renderer->impl->UnsetClip(_gpu_current_renderer, target); 1396} 1397 1398 1399 1400SDL_Color GPU_GetColor(GPU_Image* image) 1401{ 1402 return image->color; 1403} 1404 1405 1406 1407void GPU_SetColor(GPU_Image* image, SDL_Color color) 1408{ 1409 if(image == NULL) 1410 return; 1411 1412 image->color = color; 1413} 1414 1415void GPU_SetRGB(GPU_Image* image, Uint8 r, Uint8 g, Uint8 b) 1416{ 1417 SDL_Color c; 1418 c.r = r; 1419 c.g = g; 1420 c.b = b; 1421 GET_ALPHA(c) = 255; 1422 1423 if(image == NULL) 1424 return; 1425 1426 image->color = c; 1427} 1428 1429void GPU_SetRGBA(GPU_Image* image, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 1430{ 1431 SDL_Color c; 1432 c.r = r; 1433 c.g = g; 1434 c.b = b; 1435 GET_ALPHA(c) = a; 1436 1437 if(image == NULL) 1438 return; 1439 1440 image->color = c; 1441} 1442 1443void GPU_UnsetColor(GPU_Image* image) 1444{ 1445 SDL_Color c = {255, 255, 255, 255}; 1446 if(image == NULL) 1447 return; 1448 1449 image->color = c; 1450} 1451 1452void GPU_SetTargetColor(GPU_Target* target, SDL_Color color) 1453{ 1454 if(target == NULL) 1455 return; 1456 1457 target->use_color = 1; 1458 target->color = color; 1459} 1460 1461void GPU_SetTargetRGB(GPU_Target* target, Uint8 r, Uint8 g, Uint8 b) 1462{ 1463 SDL_Color c; 1464 c.r = r; 1465 c.g = g; 1466 c.b = b; 1467 GET_ALPHA(c) = 255; 1468 1469 if(target == NULL) 1470 return; 1471 1472 target->use_color = !(r == 255 && g == 255 && b == 255); 1473 target->color = c; 1474} 1475 1476void GPU_SetTargetRGBA(GPU_Target* target, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 1477{ 1478 SDL_Color c; 1479 c.r = r; 1480 c.g = g; 1481 c.b = b; 1482 GET_ALPHA(c) = a; 1483 1484 if(target == NULL) 1485 return; 1486 1487 target->use_color = !(r == 255 && g == 255 && b == 255 && a == 255); 1488 target->color = c; 1489} 1490 1491void GPU_UnsetTargetColor(GPU_Target* target) 1492{ 1493 SDL_Color c = {255, 255, 255, 255}; 1494 if(target == NULL) 1495 return; 1496 1497 target->use_color = 0; 1498 target->color = c; 1499} 1500 1501Uint8 GPU_GetBlending(GPU_Image* image) 1502{ 1503 if(image == NULL) 1504 return 0; 1505 1506 return image->use_blending; 1507} 1508 1509 1510void GPU_SetBlending(GPU_Image* image, Uint8 enable) 1511{ 1512 if(image == NULL) 1513 return; 1514 1515 image->use_blending = enable; 1516} 1517 1518void GPU_SetShapeBlending(Uint8 enable) 1519{ 1520 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 1521 return; 1522 1523 _gpu_current_renderer->current_context_target->context->shapes_use_blending = enable; 1524} 1525 1526 1527GPU_BlendMode GPU_GetBlendModeFromPreset(GPU_BlendPresetEnum preset) 1528{ 1529 switch(preset) 1530 { 1531 case GPU_BLEND_NORMAL: 1532 { 1533 GPU_BlendMode b = {GPU_FUNC_SRC_ALPHA, GPU_FUNC_ONE_MINUS_SRC_ALPHA, GPU_FUNC_SRC_ALPHA, GPU_FUNC_ONE_MINUS_SRC_ALPHA, GPU_EQ_ADD, GPU_EQ_ADD}; 1534 return b; 1535 } 1536 break; 1537 case GPU_BLEND_PREMULTIPLIED_ALPHA: 1538 { 1539 GPU_BlendMode b = {GPU_FUNC_ONE, GPU_FUNC_ONE_MINUS_SRC_ALPHA, GPU_FUNC_ONE, GPU_FUNC_ONE_MINUS_SRC_ALPHA, GPU_EQ_ADD, GPU_EQ_ADD}; 1540 return b; 1541 } 1542 break; 1543 case GPU_BLEND_MULTIPLY: 1544 { 1545 GPU_BlendMode b = {GPU_FUNC_DST_COLOR, GPU_FUNC_ZERO, GPU_FUNC_SRC_ALPHA, GPU_FUNC_ONE_MINUS_SRC_ALPHA, GPU_EQ_ADD, GPU_EQ_ADD}; 1546 return b; 1547 } 1548 break; 1549 case GPU_BLEND_ADD: 1550 { 1551 GPU_BlendMode b = {GPU_FUNC_SRC_ALPHA, GPU_FUNC_ONE, GPU_FUNC_SRC_ALPHA, GPU_FUNC_ONE, GPU_EQ_ADD, GPU_EQ_ADD}; 1552 return b; 1553 } 1554 break; 1555 case GPU_BLEND_SUBTRACT: 1556 // FIXME: Use src alpha for source components? 1557 { 1558 GPU_BlendMode b = {GPU_FUNC_ONE, GPU_FUNC_ONE, GPU_FUNC_ONE, GPU_FUNC_ONE, GPU_EQ_SUBTRACT, GPU_EQ_SUBTRACT}; 1559 return b; 1560 } 1561 break; 1562 case GPU_BLEND_MOD_ALPHA: 1563 // Don't disturb the colors, but multiply the dest alpha by the src alpha 1564 { 1565 GPU_BlendMode b = {GPU_FUNC_ZERO, GPU_FUNC_ONE, GPU_FUNC_ZERO, GPU_FUNC_SRC_ALPHA, GPU_EQ_ADD, GPU_EQ_ADD}; 1566 return b; 1567 } 1568 break; 1569 case GPU_BLEND_SET_ALPHA: 1570 // Don't disturb the colors, but set the alpha to the src alpha 1571 { 1572 GPU_BlendMode b = {GPU_FUNC_ZERO, GPU_FUNC_ONE, GPU_FUNC_ONE, GPU_FUNC_ZERO, GPU_EQ_ADD, GPU_EQ_ADD}; 1573 return b; 1574 } 1575 break; 1576 case GPU_BLEND_SET: 1577 { 1578 GPU_BlendMode b = {GPU_FUNC_ONE, GPU_FUNC_ZERO, GPU_FUNC_ONE, GPU_FUNC_ZERO, GPU_EQ_ADD, GPU_EQ_ADD}; 1579 return b; 1580 } 1581 break; 1582 case GPU_BLEND_NORMAL_KEEP_ALPHA: 1583 { 1584 GPU_BlendMode b = {GPU_FUNC_SRC_ALPHA, GPU_FUNC_ONE_MINUS_SRC_ALPHA, GPU_FUNC_ZERO, GPU_FUNC_ONE, GPU_EQ_ADD, GPU_EQ_ADD}; 1585 return b; 1586 } 1587 break; 1588 case GPU_BLEND_NORMAL_ADD_ALPHA: 1589 { 1590 GPU_BlendMode b = {GPU_FUNC_SRC_ALPHA, GPU_FUNC_ONE_MINUS_SRC_ALPHA, GPU_FUNC_ONE, GPU_FUNC_ONE, GPU_EQ_ADD, GPU_EQ_ADD}; 1591 return b; 1592 } 1593 break; 1594 default: 1595 GPU_PushErrorCode(__func__, GPU_ERROR_USER_ERROR, "Blend preset not supported: %d", preset); 1596 { 1597 GPU_BlendMode b = {GPU_FUNC_SRC_ALPHA, GPU_FUNC_ONE_MINUS_SRC_ALPHA, GPU_FUNC_SRC_ALPHA, GPU_FUNC_ONE_MINUS_SRC_ALPHA, GPU_EQ_ADD, GPU_EQ_ADD}; 1598 return b; 1599 } 1600 break; 1601 } 1602} 1603 1604 1605void GPU_SetBlendFunction(GPU_Image* image, GPU_BlendFuncEnum source_color, GPU_BlendFuncEnum dest_color, GPU_BlendFuncEnum source_alpha, GPU_BlendFuncEnum dest_alpha) 1606{ 1607 if(image == NULL) 1608 return; 1609 1610 image->blend_mode.source_color = source_color; 1611 image->blend_mode.dest_color = dest_color; 1612 image->blend_mode.source_alpha = source_alpha; 1613 image->blend_mode.dest_alpha = dest_alpha; 1614} 1615 1616void GPU_SetBlendEquation(GPU_Image* image, GPU_BlendEqEnum color_equation, GPU_BlendEqEnum alpha_equation) 1617{ 1618 if(image == NULL) 1619 return; 1620 1621 image->blend_mode.color_equation = color_equation; 1622 image->blend_mode.alpha_equation = alpha_equation; 1623} 1624 1625void GPU_SetBlendMode(GPU_Image* image, GPU_BlendPresetEnum preset) 1626{ 1627 GPU_BlendMode b; 1628 if(image == NULL) 1629 return; 1630 1631 b = GPU_GetBlendModeFromPreset(preset); 1632 GPU_SetBlendFunction(image, b.source_color, b.dest_color, b.source_alpha, b.dest_alpha); 1633 GPU_SetBlendEquation(image, b.color_equation, b.alpha_equation); 1634} 1635 1636void GPU_SetShapeBlendFunction(GPU_BlendFuncEnum source_color, GPU_BlendFuncEnum dest_color, GPU_BlendFuncEnum source_alpha, GPU_BlendFuncEnum dest_alpha) 1637{ 1638 GPU_Context* context; 1639 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 1640 return; 1641 1642 context = _gpu_current_renderer->current_context_target->context; 1643 1644 context->shapes_blend_mode.source_color = source_color; 1645 context->shapes_blend_mode.dest_color = dest_color; 1646 context->shapes_blend_mode.source_alpha = source_alpha; 1647 context->shapes_blend_mode.dest_alpha = dest_alpha; 1648} 1649 1650void GPU_SetShapeBlendEquation(GPU_BlendEqEnum color_equation, GPU_BlendEqEnum alpha_equation) 1651{ 1652 GPU_Context* context; 1653 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 1654 return; 1655 1656 context = _gpu_current_renderer->current_context_target->context; 1657 1658 context->shapes_blend_mode.color_equation = color_equation; 1659 context->shapes_blend_mode.alpha_equation = alpha_equation; 1660} 1661 1662void GPU_SetShapeBlendMode(GPU_BlendPresetEnum preset) 1663{ 1664 GPU_BlendMode b; 1665 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 1666 return; 1667 1668 b = GPU_GetBlendModeFromPreset(preset); 1669 GPU_SetShapeBlendFunction(b.source_color, b.dest_color, b.source_alpha, b.dest_alpha); 1670 GPU_SetShapeBlendEquation(b.color_equation, b.alpha_equation); 1671} 1672 1673void GPU_SetImageFilter(GPU_Image* image, GPU_FilterEnum filter) 1674{ 1675 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 1676 return; 1677 if(image == NULL) 1678 return; 1679 1680 _gpu_current_renderer->impl->SetImageFilter(_gpu_current_renderer, image, filter); 1681} 1682 1683GPU_SnapEnum GPU_GetSnapMode(GPU_Image* image) 1684{ 1685 if(image == NULL) 1686 return 0; 1687 1688 return image->snap_mode; 1689} 1690 1691void GPU_SetSnapMode(GPU_Image* image, GPU_SnapEnum mode) 1692{ 1693 if(image == NULL) 1694 return; 1695 1696 image->snap_mode = mode; 1697} 1698 1699void GPU_SetWrapMode(GPU_Image* image, GPU_WrapEnum wrap_mode_x, GPU_WrapEnum wrap_mode_y) 1700{ 1701 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 1702 return; 1703 if(image == NULL) 1704 return; 1705 1706 _gpu_current_renderer->impl->SetWrapMode(_gpu_current_renderer, image, wrap_mode_x, wrap_mode_y); 1707} 1708 1709 1710SDL_Color GPU_GetPixel(GPU_Target* target, Sint16 x, Sint16 y) 1711{ 1712 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 1713 { 1714 SDL_Color c = {0,0,0,0}; 1715 return c; 1716 } 1717 1718 return _gpu_current_renderer->impl->GetPixel(_gpu_current_renderer, target, x, y); 1719} 1720 1721 1722 1723 1724 1725 1726 1727void GPU_Clear(GPU_Target* target) 1728{ 1729 if(!CHECK_RENDERER) 1730 RETURN_ERROR(GPU_ERROR_USER_ERROR, "NULL renderer"); 1731 MAKE_CURRENT_IF_NONE(target); 1732 if(!CHECK_CONTEXT) 1733 RETURN_ERROR(GPU_ERROR_USER_ERROR, "NULL context"); 1734 1735 _gpu_current_renderer->impl->ClearRGBA(_gpu_current_renderer, target, 0, 0, 0, 0); 1736} 1737 1738void GPU_ClearColor(GPU_Target* target, SDL_Color color) 1739{ 1740 if(!CHECK_RENDERER) 1741 RETURN_ERROR(GPU_ERROR_USER_ERROR, "NULL renderer"); 1742 MAKE_CURRENT_IF_NONE(target); 1743 if(!CHECK_CONTEXT) 1744 RETURN_ERROR(GPU_ERROR_USER_ERROR, "NULL context"); 1745 1746 _gpu_current_renderer->impl->ClearRGBA(_gpu_current_renderer, target, color.r, color.g, color.b, GET_ALPHA(color)); 1747} 1748 1749void GPU_ClearRGB(GPU_Target* target, Uint8 r, Uint8 g, Uint8 b) 1750{ 1751 if(!CHECK_RENDERER) 1752 RETURN_ERROR(GPU_ERROR_USER_ERROR, "NULL renderer"); 1753 MAKE_CURRENT_IF_NONE(target); 1754 if(!CHECK_CONTEXT) 1755 RETURN_ERROR(GPU_ERROR_USER_ERROR, "NULL context"); 1756 1757 _gpu_current_renderer->impl->ClearRGBA(_gpu_current_renderer, target, r, g, b, 255); 1758} 1759 1760void GPU_ClearRGBA(GPU_Target* target, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 1761{ 1762 if(!CHECK_RENDERER) 1763 RETURN_ERROR(GPU_ERROR_USER_ERROR, "NULL renderer"); 1764 MAKE_CURRENT_IF_NONE(target); 1765 if(!CHECK_CONTEXT) 1766 RETURN_ERROR(GPU_ERROR_USER_ERROR, "NULL context"); 1767 1768 _gpu_current_renderer->impl->ClearRGBA(_gpu_current_renderer, target, r, g, b, a); 1769} 1770 1771void GPU_FlushBlitBuffer(void) 1772{ 1773 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 1774 return; 1775 1776 _gpu_current_renderer->impl->FlushBlitBuffer(_gpu_current_renderer); 1777} 1778 1779void GPU_Flip(GPU_Target* target) 1780{ 1781 if(!CHECK_RENDERER) 1782 RETURN_ERROR(GPU_ERROR_USER_ERROR, "NULL renderer"); 1783 MAKE_CURRENT_IF_NONE(target); 1784 if(!CHECK_CONTEXT) 1785 RETURN_ERROR(GPU_ERROR_USER_ERROR, "NULL context"); 1786 1787 _gpu_current_renderer->impl->Flip(_gpu_current_renderer, target); 1788} 1789 1790 1791 1792 1793 1794// Shader API 1795 1796 1797Uint32 GPU_CompileShader_RW(GPU_ShaderEnum shader_type, SDL_RWops* shader_source, Uint8 free_rwops) 1798{ 1799 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 1800 { 1801 if(free_rwops) 1802 SDL_RWclose(shader_source); 1803 return 0; 1804 } 1805 1806 return _gpu_current_renderer->impl->CompileShader_RW(_gpu_current_renderer, shader_type, shader_source, free_rwops); 1807} 1808 1809Uint32 GPU_LoadShader(GPU_ShaderEnum shader_type, const char* filename) 1810{ 1811 SDL_RWops* rwops; 1812 1813 if(filename == NULL) 1814 { 1815 GPU_PushErrorCode(__func__, GPU_ERROR_NULL_ARGUMENT, "filename"); 1816 return 0; 1817 } 1818 1819 rwops = SDL_RWFromFile(filename, "r"); 1820 if(rwops == NULL) 1821 { 1822 GPU_PushErrorCode(__func__, GPU_ERROR_FILE_NOT_FOUND, "%s", filename); 1823 return 0; 1824 } 1825 1826 return GPU_CompileShader_RW(shader_type, rwops, 1); 1827} 1828 1829Uint32 GPU_CompileShader(GPU_ShaderEnum shader_type, const char* shader_source) 1830{ 1831 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 1832 return 0; 1833 1834 return _gpu_current_renderer->impl->CompileShader(_gpu_current_renderer, shader_type, shader_source); 1835} 1836 1837Uint8 GPU_LinkShaderProgram(Uint32 program_object) 1838{ 1839 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 1840 return 0; 1841 1842 return _gpu_current_renderer->impl->LinkShaderProgram(_gpu_current_renderer, program_object); 1843} 1844 1845Uint32 GPU_CreateShaderProgram(void) 1846{ 1847 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 1848 return 0; 1849 1850 return _gpu_current_renderer->impl->CreateShaderProgram(_gpu_current_renderer); 1851} 1852 1853Uint32 GPU_LinkShaders(Uint32 shader_object1, Uint32 shader_object2) 1854{ 1855 Uint32 p; 1856 1857 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 1858 return 0; 1859 1860 if((_gpu_current_renderer->enabled_features & GPU_FEATURE_BASIC_SHADERS) != GPU_FEATURE_BASIC_SHADERS) 1861 return 0; 1862 1863 p = _gpu_current_renderer->impl->CreateShaderProgram(_gpu_current_renderer); 1864 1865 _gpu_current_renderer->impl->AttachShader(_gpu_current_renderer, p, shader_object1); 1866 _gpu_current_renderer->impl->AttachShader(_gpu_current_renderer, p, shader_object2); 1867 1868 if(_gpu_current_renderer->impl->LinkShaderProgram(_gpu_current_renderer, p)) 1869 return p; 1870 1871 _gpu_current_renderer->impl->FreeShaderProgram(_gpu_current_renderer, p); 1872 return 0; 1873} 1874 1875void GPU_FreeShader(Uint32 shader_object) 1876{ 1877 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 1878 return; 1879 1880 _gpu_current_renderer->impl->FreeShader(_gpu_current_renderer, shader_object); 1881} 1882 1883void GPU_FreeShaderProgram(Uint32 program_object) 1884{ 1885 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 1886 return; 1887 1888 _gpu_current_renderer->impl->FreeShaderProgram(_gpu_current_renderer, program_object); 1889} 1890 1891void GPU_AttachShader(Uint32 program_object, Uint32 shader_object) 1892{ 1893 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 1894 return; 1895 1896 _gpu_current_renderer->impl->AttachShader(_gpu_current_renderer, program_object, shader_object); 1897} 1898 1899void GPU_DetachShader(Uint32 program_object, Uint32 shader_object) 1900{ 1901 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 1902 return; 1903 1904 _gpu_current_renderer->impl->DetachShader(_gpu_current_renderer, program_object, shader_object); 1905} 1906 1907Uint8 GPU_IsDefaultShaderProgram(Uint32 program_object) 1908{ 1909 GPU_Context* context; 1910 1911 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 1912 return 0; 1913 1914 context = _gpu_current_renderer->current_context_target->context; 1915 return (program_object == context->default_textured_shader_program || program_object == context->default_untextured_shader_program); 1916} 1917 1918void GPU_ActivateShaderProgram(Uint32 program_object, GPU_ShaderBlock* block) 1919{ 1920 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 1921 return; 1922 1923 _gpu_current_renderer->impl->ActivateShaderProgram(_gpu_current_renderer, program_object, block); 1924} 1925 1926void GPU_DeactivateShaderProgram(void) 1927{ 1928 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 1929 return; 1930 1931 _gpu_current_renderer->impl->DeactivateShaderProgram(_gpu_current_renderer); 1932} 1933 1934const char* GPU_GetShaderMessage(void) 1935{ 1936 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 1937 return NULL; 1938 1939 return _gpu_current_renderer->impl->GetShaderMessage(_gpu_current_renderer); 1940} 1941 1942int GPU_GetAttributeLocation(Uint32 program_object, const char* attrib_name) 1943{ 1944 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 1945 return 0; 1946 1947 return _gpu_current_renderer->impl->GetAttributeLocation(_gpu_current_renderer, program_object, attrib_name); 1948} 1949 1950GPU_AttributeFormat GPU_MakeAttributeFormat(int num_elems_per_vertex, GPU_TypeEnum type, Uint8 normalize, int stride_bytes, int offset_bytes) 1951{ 1952 GPU_AttributeFormat f; 1953 f.is_per_sprite = 0; 1954 f.num_elems_per_value = num_elems_per_vertex; 1955 f.type = type; 1956 f.normalize = normalize; 1957 f.stride_bytes = stride_bytes; 1958 f.offset_bytes = offset_bytes; 1959 return f; 1960} 1961 1962GPU_Attribute GPU_MakeAttribute(int location, void* values, GPU_AttributeFormat format) 1963{ 1964 GPU_Attribute a; 1965 a.location = location; 1966 a.values = values; 1967 a.format = format; 1968 return a; 1969} 1970 1971int GPU_GetUniformLocation(Uint32 program_object, const char* uniform_name) 1972{ 1973 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 1974 return 0; 1975 1976 return _gpu_current_renderer->impl->GetUniformLocation(_gpu_current_renderer, program_object, uniform_name); 1977} 1978 1979GPU_ShaderBlock GPU_LoadShaderBlock(Uint32 program_object, const char* position_name, const char* texcoord_name, const char* color_name, const char* modelViewMatrix_name) 1980{ 1981 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 1982 { 1983 GPU_ShaderBlock b; 1984 b.position_loc = -1; 1985 b.texcoord_loc = -1; 1986 b.color_loc = -1; 1987 b.modelViewProjection_loc = -1; 1988 return b; 1989 } 1990 1991 return _gpu_current_renderer->impl->LoadShaderBlock(_gpu_current_renderer, program_object, position_name, texcoord_name, color_name, modelViewMatrix_name); 1992} 1993 1994void GPU_SetShaderBlock(GPU_ShaderBlock block) 1995{ 1996 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 1997 return; 1998 1999 _gpu_current_renderer->impl->SetShaderBlock(_gpu_current_renderer, block); 2000} 2001 2002void GPU_SetShaderImage(GPU_Image* image, int location, int image_unit) 2003{ 2004 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 2005 return; 2006 2007 _gpu_current_renderer->impl->SetShaderImage(_gpu_current_renderer, image, location, image_unit); 2008} 2009 2010GPU_MultitextureBlock GPU_LoadMultitextureBlock(int count, char** image_names, char** texcoord_names) 2011{ 2012 GPU_MultitextureBlock result; 2013 result.image_names = (char**)SDL_malloc(count * sizeof(char*)); 2014 result.texcoord_names = (char**)SDL_malloc(count * sizeof(char*)); 2015 for (int i = 0; i < count; ++i) 2016 { 2017 result.image_names[i] = (char*)SDL_malloc(strlen(image_names[i]) + 1); 2018 result.texcoord_names[i] = (char*)SDL_malloc(strlen(texcoord_names[i]) + 1); 2019 strcpy(result.image_names[i], image_names[i]); 2020 strcpy(result.texcoord_names[i], texcoord_names[i]); 2021 } 2022 result.num_textures = count; 2023 return result; 2024} 2025 2026void GPU_FreeMultitextureBlock(GPU_MultitextureBlock* value) 2027{ 2028 int count = value->num_textures; 2029 for (int i = 0; i < count; ++i) 2030 { 2031 SDL_free(value->image_names[i]); 2032 SDL_free(value->texcoord_names[i]); 2033 } 2034 SDL_free(value->image_names); 2035 SDL_free(value->texcoord_names); 2036} 2037 2038void GPU_SetMultitextureBlock(GPU_MultitextureBlock* value) 2039{ 2040 _gpu_current_renderer->multitexture_block = value; 2041} 2042 2043void GPU_MultitextureBlit(GPU_Image** images, GPU_Rect* rects, GPU_Target* target, float x, float y) 2044{ 2045 if (!CHECK_RENDERER) 2046 RETURN_ERROR(GPU_ERROR_USER_ERROR, "NULL renderer"); 2047 MAKE_CURRENT_IF_NONE(target); 2048 if (!CHECK_CONTEXT) 2049 RETURN_ERROR(GPU_ERROR_USER_ERROR, "NULL context"); 2050 2051 if (images == NULL) 2052 RETURN_ERROR(GPU_ERROR_NULL_ARGUMENT, "images"); 2053 if (rects == NULL) 2054 RETURN_ERROR(GPU_ERROR_NULL_ARGUMENT, "rects"); 2055 if (target == NULL) 2056 RETURN_ERROR(GPU_ERROR_NULL_ARGUMENT, "target"); 2057 2058 _gpu_current_renderer->impl->MultitextureBlit(_gpu_current_renderer, images, rects, target, x, y); 2059} 2060 2061void GPU_BlitBatch(GPU_Image* image, GPU_Target* target, Uint32 num_sprites, 2062 float* values, GPU_BatchFlagEnum flags) 2063{} 2064 2065void GPU_BlitBatchSeparate(GPU_Image* image, GPU_Target* target, Uint32 num_sprites, 2066 float* positions, float* src_rects, float* colors, GPU_BatchFlagEnum flags) 2067{ 2068} 2069 2070void GPU_GetUniformiv(Uint32 program_object, int location, int* values) 2071{ 2072 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 2073 return; 2074 2075 _gpu_current_renderer->impl->GetUniformiv(_gpu_current_renderer, program_object, location, values); 2076} 2077 2078void GPU_SetUniformi(int location, int value) 2079{ 2080 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 2081 return; 2082 2083 _gpu_current_renderer->impl->SetUniformi(_gpu_current_renderer, location, value); 2084} 2085 2086void GPU_SetUniformiv(int location, int num_elements_per_value, int num_values, int* values) 2087{ 2088 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 2089 return; 2090 2091 _gpu_current_renderer->impl->SetUniformiv(_gpu_current_renderer, location, num_elements_per_value, num_values, values); 2092} 2093 2094 2095void GPU_GetUniformuiv(Uint32 program_object, int location, unsigned int* values) 2096{ 2097 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 2098 return; 2099 2100 _gpu_current_renderer->impl->GetUniformuiv(_gpu_current_renderer, program_object, location, values); 2101} 2102 2103void GPU_SetUniformui(int location, unsigned int value) 2104{ 2105 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 2106 return; 2107 2108 _gpu_current_renderer->impl->SetUniformui(_gpu_current_renderer, location, value); 2109} 2110 2111void GPU_SetUniformuiv(int location, int num_elements_per_value, int num_values, unsigned int* values) 2112{ 2113 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 2114 return; 2115 2116 _gpu_current_renderer->impl->SetUniformuiv(_gpu_current_renderer, location, num_elements_per_value, num_values, values); 2117} 2118 2119 2120void GPU_GetUniformfv(Uint32 program_object, int location, float* values) 2121{ 2122 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 2123 return; 2124 2125 _gpu_current_renderer->impl->GetUniformfv(_gpu_current_renderer, program_object, location, values); 2126} 2127 2128void GPU_SetUniformf(int location, float value) 2129{ 2130 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 2131 return; 2132 2133 _gpu_current_renderer->impl->SetUniformf(_gpu_current_renderer, location, value); 2134} 2135 2136void GPU_SetUniformfv(int location, int num_elements_per_value, int num_values, float* values) 2137{ 2138 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 2139 return; 2140 2141 _gpu_current_renderer->impl->SetUniformfv(_gpu_current_renderer, location, num_elements_per_value, num_values, values); 2142} 2143 2144// Same as GPU_GetUniformfv() 2145void GPU_GetUniformMatrixfv(Uint32 program_object, int location, float* values) 2146{ 2147 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 2148 return; 2149 2150 _gpu_current_renderer->impl->GetUniformfv(_gpu_current_renderer, program_object, location, values); 2151} 2152 2153void GPU_SetUniformMatrixfv(int location, int num_matrices, int num_rows, int num_columns, Uint8 transpose, float* values) 2154{ 2155 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 2156 return; 2157 2158 _gpu_current_renderer->impl->SetUniformMatrixfv(_gpu_current_renderer, location, num_matrices, num_rows, num_columns, transpose, values); 2159} 2160 2161 2162void GPU_SetAttributef(int location, float value) 2163{ 2164 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 2165 return; 2166 2167 _gpu_current_renderer->impl->SetAttributef(_gpu_current_renderer, location, value); 2168} 2169 2170void GPU_SetAttributei(int location, int value) 2171{ 2172 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 2173 return; 2174 2175 _gpu_current_renderer->impl->SetAttributei(_gpu_current_renderer, location, value); 2176} 2177 2178void GPU_SetAttributeui(int location, unsigned int value) 2179{ 2180 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 2181 return; 2182 2183 _gpu_current_renderer->impl->SetAttributeui(_gpu_current_renderer, location, value); 2184} 2185 2186void GPU_SetAttributefv(int location, int num_elements, float* value) 2187{ 2188 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 2189 return; 2190 2191 _gpu_current_renderer->impl->SetAttributefv(_gpu_current_renderer, location, num_elements, value); 2192} 2193 2194void GPU_SetAttributeiv(int location, int num_elements, int* value) 2195{ 2196 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 2197 return; 2198 2199 _gpu_current_renderer->impl->SetAttributeiv(_gpu_current_renderer, location, num_elements, value); 2200} 2201 2202void GPU_SetAttributeuiv(int location, int num_elements, unsigned int* value) 2203{ 2204 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 2205 return; 2206 2207 _gpu_current_renderer->impl->SetAttributeuiv(_gpu_current_renderer, location, num_elements, value); 2208} 2209 2210void GPU_SetAttributeSource(int num_values, GPU_Attribute source) 2211{ 2212 if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 2213 return; 2214 2215 _gpu_current_renderer->impl->SetAttributeSource(_gpu_current_renderer, num_values, source); 2216} 2217 2218 2219 2220 2221// gpu_strcasecmp() 2222// A portable strcasecmp() from UC Berkeley 2223/* 2224 * Copyright (c) 1987 Regents of the University of California. 2225 * All rights reserved. 2226 * 2227 * Redistribution and use in source and binary forms are permitted 2228 * provided that this notice is preserved and that due credit is given 2229 * to the University of California at Berkeley. The name of the University 2230 * may not be used to endorse or promote products derived from this 2231 * software without specific written prior permission. This software 2232 * is provided ``as is'' without express or implied warranty. 2233 */ 2234 2235/* 2236 * This array is designed for mapping upper and lower case letter 2237 * together for a case independent comparison. The mappings are 2238 * based upon ascii character sequences. 2239 */ 2240static const unsigned char caseless_charmap[] = 2241{ 2242 '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', 2243 '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', 2244 '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', 2245 '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', 2246 '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', 2247 '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057', 2248 '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', 2249 '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077', 2250 '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147', 2251 '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', 2252 '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', 2253 '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137', 2254 '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147', 2255 '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', 2256 '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', 2257 '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177', 2258 '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207', 2259 '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217', 2260 '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', 2261 '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237', 2262 '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247', 2263 '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257', 2264 '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267', 2265 '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277', 2266 '\300', '\341', '\342', '\343', '\344', '\345', '\346', '\347', 2267 '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', 2268 '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', 2269 '\370', '\371', '\372', '\333', '\334', '\335', '\336', '\337', 2270 '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', 2271 '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', 2272 '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', 2273 '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377', 2274}; 2275 2276int gpu_strcasecmp(const char* s1, const char* s2) 2277{ 2278 unsigned char u1, u2; 2279 2280 for (;;) 2281 { 2282 u1 = (unsigned char) *s1++; 2283 u2 = (unsigned char) *s2++; 2284 if (caseless_charmap[u1] != caseless_charmap[u2]) 2285 return caseless_charmap[u1] - caseless_charmap[u2]; 2286 if (u1 == '\0') 2287 return 0; 2288 } 2289 return 0; 2290} 2291 2292 2293#ifdef _MSC_VER 2294 #pragma warning(pop) 2295#endif 2296