this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

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