diff --git a/examples/core/core_basic_multiple-windows.c b/examples/core/core_basic_multiple-windows.c new file mode 100644 index 000000000000..4d051e7067de --- /dev/null +++ b/examples/core/core_basic_multiple-windows.c @@ -0,0 +1,72 @@ +/******************************************************************************************* +* +* raylib [core] example - Basic window +* +* Welcome to raylib! +* +* To test examples in Notepad++, provided with default raylib installer package, +* just press F6 and run [raylib_compile_execute] script, it will compile and execute. +* Note that compiled executable is placed in the same folder as .c file +* +* You can find all basic examples on [C:\raylib\raylib\examples] directory and +* raylib official webpage: [www.raylib.com] +* +* Enjoy using raylib. :) +* +* This example has been created using raylib 1.0 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2013-2020 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [core] example - window 1"); + InitWindow(screenWidth, screenHeight, "raylib [core] example - window 2"); + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + // TODO: Update your variables here + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(0); + + ClearBackground(RAYWHITE); + + DrawText("Congrats! You created your FIST window!", 190, 200, 20, LIGHTGRAY); + + EndDrawing(); + + BeginDrawing(1); + + ClearBackground(RAYWHITE); + + DrawText("Congrats! You created your SECOND window!", 190, 200, 20, LIGHTGRAY); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} \ No newline at end of file diff --git a/src/core.c b/src/core.c index 54e422c49a8d..8ff5bcfb3ef0 100644 --- a/src/core.c +++ b/src/core.c @@ -367,7 +367,9 @@ typedef struct CoreData { char **dropFilesPath; // Store dropped files paths as strings int dropFilesCount; // Count dropped files strings - } Window; + } Window[MAX_CONTEXTS]; + unsigned int currentWindow; + unsigned int numWindows; #if defined(PLATFORM_ANDROID) struct { bool appEnabled; // Flag to detect if app is active ** = true @@ -620,8 +622,9 @@ void InitWindow(int width, int height, const char *title) #endif TRACELOG(LOG_INFO, "Initializing raylib %s", RAYLIB_VERSION); - - CORE.Window.title = title; + + CORE.currentWindow = CORE.numWindows; + CORE.Window[CORE.currentWindow].title = title; // Initialize required global values different than 0 CORE.Input.Keyboard.exitKey = KEY_ESCAPE; @@ -634,10 +637,10 @@ void InitWindow(int width, int height, const char *title) #endif #if defined(PLATFORM_ANDROID) - CORE.Window.screen.width = width; - CORE.Window.screen.height = height; - CORE.Window.currentFbo.width = width; - CORE.Window.currentFbo.height = height; + CORE.Window[CORE.currentWindow].screen.width = width; + CORE.Window[CORE.currentWindow].screen.height = height; + CORE.Window[CORE.currentWindow].currentFbo.width = width; + CORE.Window[CORE.currentWindow].currentFbo.height = height; // Input data is android app pointer CORE.Android.internalDataPath = CORE.Android.app->activity->internalDataPath; @@ -679,7 +682,7 @@ void InitWindow(int width, int height, const char *title) int pollEvents = 0; // Wait for window to be initialized (display and context) - while (!CORE.Window.ready) + while (!CORE.Window[CORE.currentWindow].ready) { // Process events loop while ((pollResult = ALooper_pollAll(0, NULL, &pollEvents, (void**)&CORE.Android.source)) >= 0) @@ -688,27 +691,29 @@ void InitWindow(int width, int height, const char *title) if (CORE.Android.source != NULL) CORE.Android.source->process(CORE.Android.app, CORE.Android.source); // NOTE: Never close window, native activity is controlled by the system! - //if (CORE.Android.app->destroyRequested != 0) CORE.Window.shouldClose = true; + //if (CORE.Android.app->destroyRequested != 0) CORE.Window[CORE.currentWindow].shouldClose = true; } } #else // Init graphics device (display device and OpenGL context) // NOTE: returns true if window and graphic device has been initialized successfully - CORE.Window.ready = InitGraphicsDevice(width, height); - - if (!CORE.Window.ready) return; - else CORE.Window.focused = true; - + CORE.Window[CORE.numWindows].ready = InitGraphicsDevice(width, height); + CORE.numWindows++; + if (!CORE.Window[CORE.currentWindow].ready) return; + else CORE.Window[CORE.currentWindow].focused = true; // Init hi-res timer InitTimer(); #if defined(SUPPORT_DEFAULT_FONT) - // Load default font - // NOTE: External functions (defined in module: text) - LoadFontDefault(); - Rectangle rec = GetFontDefault().recs[95]; - // NOTE: We setup a 1px padding on char rectangle to avoid pixel bleeding on MSAA filtering - SetShapesTexture(GetFontDefault().texture, (Rectangle){ rec.x + 1, rec.y + 1, rec.width - 2, rec.height - 2 }); + if (CORE.currentWindow == 0) //load fonts only the first time + { + // Load default font + // NOTE: External functions (defined in module: text) + LoadFontDefault(); + Rectangle rec = GetFontDefault().recs[95]; + // NOTE: We setup a 1px padding on char rectangle to avoid pixel bleeding on MSAA filtering + SetShapesTexture(GetFontDefault().texture, (Rectangle) { rec.x + 1, rec.y + 1, rec.width - 2, rec.height - 2 }); + } #endif #if defined(PLATFORM_DESKTOP) && defined(SUPPORT_HIGH_DPI) // Set default font texture filter for HighDPI (blurry) @@ -748,9 +753,10 @@ void InitWindow(int width, int height, const char *title) emscripten_set_gamepaddisconnected_callback(NULL, 1, EmscriptenGamepadCallback); #endif - CORE.Input.Mouse.position.x = (float)CORE.Window.screen.width/2.0f; - CORE.Input.Mouse.position.y = (float)CORE.Window.screen.height/2.0f; + CORE.Input.Mouse.position.x = (float)CORE.Window[CORE.currentWindow].screen.width/2.0f; + CORE.Input.Mouse.position.y = (float)CORE.Window[CORE.currentWindow].screen.height/2.0f; #endif // PLATFORM_ANDROID + glfwMakeContextCurrent(CORE.Window[0].handle); //switch to the main context, } // Close window and unload OpenGL context @@ -771,7 +777,7 @@ void CloseWindow(void) rlglClose(); // De-init rlgl #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) - glfwDestroyWindow(CORE.Window.handle); + glfwDestroyWindow(CORE.Window[CORE.currentWindow].handle); glfwTerminate(); #endif @@ -781,33 +787,33 @@ void CloseWindow(void) #if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) || defined(PLATFORM_UWP) // Close surface, context and display - if (CORE.Window.device != EGL_NO_DISPLAY) + if (CORE.Window[CORE.currentWindow].device != EGL_NO_DISPLAY) { - eglMakeCurrent(CORE.Window.device, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + eglMakeCurrent(CORE.Window[CORE.currentWindow].device, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - if (CORE.Window.surface != EGL_NO_SURFACE) + if (CORE.Window[CORE.currentWindow].surface != EGL_NO_SURFACE) { - eglDestroySurface(CORE.Window.device, CORE.Window.surface); - CORE.Window.surface = EGL_NO_SURFACE; + eglDestroySurface(CORE.Window[CORE.currentWindow].device, CORE.Window[CORE.currentWindow].surface); + CORE.Window[CORE.currentWindow].surface = EGL_NO_SURFACE; } - if (CORE.Window.context != EGL_NO_CONTEXT) + if (CORE.Window[CORE.currentWindow].context != EGL_NO_CONTEXT) { - eglDestroyContext(CORE.Window.device, CORE.Window.context); - CORE.Window.context = EGL_NO_CONTEXT; + eglDestroyContext(CORE.Window[CORE.currentWindow].device, CORE.Window[CORE.currentWindow].context); + CORE.Window[CORE.currentWindow].context = EGL_NO_CONTEXT; } - eglTerminate(CORE.Window.device); - CORE.Window.device = EGL_NO_DISPLAY; + eglTerminate(CORE.Window[CORE.currentWindow].device); + CORE.Window[CORE.currentWindow].device = EGL_NO_DISPLAY; } #endif #if defined(PLATFORM_RPI) // Wait for mouse and gamepad threads to finish before closing // NOTE: Those threads should already have finished at this point - // because they are controlled by CORE.Window.shouldClose variable + // because they are controlled by CORE.Window[CORE.currentWindow].shouldClose variable - CORE.Window.shouldClose = true; // Added to force threads to exit when the close window is called + CORE.Window[CORE.currentWindow].shouldClose = true; // Added to force threads to exit when the close window is called for (int i = 0; i < sizeof(CORE.Input.eventWorker)/sizeof(InputEventWorker); ++i) { @@ -826,7 +832,7 @@ void CloseWindow(void) // Check if window has been initialized successfully bool IsWindowReady(void) { - return CORE.Window.ready; + return CORE.Window[CORE.currentWindow].ready; } // Check if KEY_ESCAPE pressed or Close icon pressed @@ -843,20 +849,20 @@ bool WindowShouldClose(void) #endif #if defined(PLATFORM_DESKTOP) - if (CORE.Window.ready) + if (CORE.Window[CORE.currentWindow].ready) { // While window minimized, stop loop execution - while (!CORE.Window.alwaysRun && CORE.Window.minimized) glfwWaitEvents(); + while (!CORE.Window[CORE.currentWindow].alwaysRun && CORE.Window[CORE.currentWindow].minimized) glfwWaitEvents(); - CORE.Window.shouldClose = glfwWindowShouldClose(CORE.Window.handle); + CORE.Window[CORE.currentWindow].shouldClose = glfwWindowShouldClose(CORE.Window[CORE.currentWindow].handle); - return CORE.Window.shouldClose; + return CORE.Window[CORE.currentWindow].shouldClose; } else return true; #endif #if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) || defined(PLATFORM_UWP) - if (CORE.Window.ready) return CORE.Window.shouldClose; + if (CORE.Window[CORE.currentWindow].ready) return CORE.Window[CORE.currentWindow].shouldClose; else return true; #endif } @@ -865,7 +871,7 @@ bool WindowShouldClose(void) bool IsWindowMinimized(void) { #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) || defined(PLATFORM_UWP) - return CORE.Window.minimized; + return CORE.Window[CORE.currentWindow].minimized; #else return false; #endif @@ -875,7 +881,7 @@ bool IsWindowMinimized(void) bool IsWindowFocused(void) { #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) || defined(PLATFORM_UWP) - return CORE.Window.focused; + return CORE.Window[CORE.currentWindow].focused; #else return false; #endif @@ -885,7 +891,7 @@ bool IsWindowFocused(void) bool IsWindowResized(void) { #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) || defined(PLATFORM_UWP) - return CORE.Window.resized; + return CORE.Window[CORE.currentWindow].resized; #else return false; #endif @@ -895,7 +901,7 @@ bool IsWindowResized(void) bool IsWindowHidden(void) { #if defined(PLATFORM_DESKTOP) - return (glfwGetWindowAttrib(CORE.Window.handle, GLFW_VISIBLE) == GLFW_FALSE); + return (glfwGetWindowAttrib(CORE.Window[CORE.currentWindow].handle, GLFW_VISIBLE) == GLFW_FALSE); #endif return false; } @@ -903,7 +909,7 @@ bool IsWindowHidden(void) // Check if window is currently fullscreen bool IsWindowFullscreen(void) { - return CORE.Window.fullscreen; + return CORE.Window[CORE.currentWindow].fullscreen; } // Toggle fullscreen mode (only PLATFORM_DESKTOP) @@ -911,27 +917,27 @@ void ToggleFullscreen(void) { #if defined(PLATFORM_DESKTOP) // NOTE: glfwSetWindowMonitor() doesn't work properly (bugs) - if (!CORE.Window.fullscreen) + if (!CORE.Window[CORE.currentWindow].fullscreen) { // Store previous window position (in case we exit fullscreen) - glfwGetWindowPos(CORE.Window.handle, &CORE.Window.position.x, &CORE.Window.position.y); + glfwGetWindowPos(CORE.Window[CORE.currentWindow].handle, &CORE.Window[CORE.currentWindow].position.x, &CORE.Window[CORE.currentWindow].position.y); GLFWmonitor *monitor = glfwGetPrimaryMonitor(); if (!monitor) { TRACELOG(LOG_WARNING, "GLFW: Failed to get monitor"); - glfwSetWindowMonitor(CORE.Window.handle, glfwGetPrimaryMonitor(), 0, 0, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE); + glfwSetWindowMonitor(CORE.Window[CORE.currentWindow].handle, glfwGetPrimaryMonitor(), 0, 0, CORE.Window[CORE.currentWindow].screen.width, CORE.Window[CORE.currentWindow].screen.height, GLFW_DONT_CARE); return; } const GLFWvidmode *mode = glfwGetVideoMode(monitor); - glfwSetWindowMonitor(CORE.Window.handle, glfwGetPrimaryMonitor(), 0, 0, CORE.Window.screen.width, CORE.Window.screen.height, mode->refreshRate); + glfwSetWindowMonitor(CORE.Window[CORE.currentWindow].handle, glfwGetPrimaryMonitor(), 0, 0, CORE.Window[CORE.currentWindow].screen.width, CORE.Window[CORE.currentWindow].screen.height, mode->refreshRate); // Try to enable GPU V-Sync, so frames are limited to screen refresh rate (60Hz -> 60 FPS) // NOTE: V-Sync can be enabled by graphic driver configuration - if (CORE.Window.flags & FLAG_VSYNC_HINT) glfwSwapInterval(1); + if (CORE.Window[CORE.currentWindow].flags & FLAG_VSYNC_HINT) glfwSwapInterval(1); } - else glfwSetWindowMonitor(CORE.Window.handle, NULL, CORE.Window.position.x, CORE.Window.position.y, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE); + else glfwSetWindowMonitor(CORE.Window[CORE.currentWindow].handle, NULL, CORE.Window[CORE.currentWindow].position.x, CORE.Window[CORE.currentWindow].position.y, CORE.Window[CORE.currentWindow].screen.width, CORE.Window[CORE.currentWindow].screen.height, GLFW_DONT_CARE); #endif #if defined(PLATFORM_WEB) /* @@ -944,7 +950,7 @@ void ToggleFullscreen(void) //EM_ASM(Module.requestFullscreen(false, false);); /* - if (!CORE.Window.fullscreen) + if (!CORE.Window[CORE.currentWindow].fullscreen) { //https://github.com/emscripten-core/emscripten/issues/5124 EmscriptenFullscreenStrategy strategy = { @@ -971,7 +977,7 @@ void ToggleFullscreen(void) TRACELOG(LOG_WARNING, "SYSTEM: Failed to toggle to windowed mode"); #endif - CORE.Window.fullscreen = !CORE.Window.fullscreen; // Toggle fullscreen flag + CORE.Window[CORE.currentWindow].fullscreen = !CORE.Window[CORE.currentWindow].fullscreen; // Toggle fullscreen flag } // Set icon for window (only PLATFORM_DESKTOP) @@ -989,7 +995,7 @@ void SetWindowIcon(Image image) // NOTE 1: We only support one image icon // NOTE 2: The specified image data is copied before this function returns - glfwSetWindowIcon(CORE.Window.handle, 1, icon); + glfwSetWindowIcon(CORE.Window[CORE.currentWindow].handle, 1, icon); } else TRACELOG(LOG_WARNING, "GLFW: Window icon image must be in R8G8B8A8 pixel format"); #endif @@ -998,9 +1004,9 @@ void SetWindowIcon(Image image) // Set title for window (only PLATFORM_DESKTOP) void SetWindowTitle(const char *title) { - CORE.Window.title = title; + CORE.Window[CORE.currentWindow].title = title; #if defined(PLATFORM_DESKTOP) - glfwSetWindowTitle(CORE.Window.handle, title); + glfwSetWindowTitle(CORE.Window[CORE.currentWindow].handle, title); #endif } @@ -1008,7 +1014,7 @@ void SetWindowTitle(const char *title) void SetWindowPosition(int x, int y) { #if defined(PLATFORM_DESKTOP) - glfwSetWindowPos(CORE.Window.handle, x, y); + glfwSetWindowPos(CORE.Window[CORE.currentWindow].handle, x, y); #endif } @@ -1024,7 +1030,7 @@ void SetWindowMonitor(int monitor) TRACELOG(LOG_INFO, "GLFW: Selected fullscreen monitor: [%i] %s", monitor, glfwGetMonitorName(monitors[monitor])); const GLFWvidmode *mode = glfwGetVideoMode(monitors[monitor]); - glfwSetWindowMonitor(CORE.Window.handle, monitors[monitor], 0, 0, mode->width, mode->height, mode->refreshRate); + glfwSetWindowMonitor(CORE.Window[CORE.currentWindow].handle, monitors[monitor], 0, 0, mode->width, mode->height, mode->refreshRate); } else TRACELOG(LOG_WARNING, "GLFW: Failed to find selected monitor"); #endif @@ -1035,7 +1041,7 @@ void SetWindowMinSize(int width, int height) { #if defined(PLATFORM_DESKTOP) const GLFWvidmode *mode = glfwGetVideoMode(glfwGetPrimaryMonitor()); - glfwSetWindowSizeLimits(CORE.Window.handle, width, height, mode->width, mode->height); + glfwSetWindowSizeLimits(CORE.Window[CORE.currentWindow].handle, width, height, mode->width, mode->height); #endif } @@ -1044,7 +1050,7 @@ void SetWindowMinSize(int width, int height) void SetWindowSize(int width, int height) { #if defined(PLATFORM_DESKTOP) - glfwSetWindowSize(CORE.Window.handle, width, height); + glfwSetWindowSize(CORE.Window[CORE.currentWindow].handle, width, height); #endif #if defined(PLATFORM_WEB) emscripten_set_canvas_size(width, height); // DEPRECATED! @@ -1060,7 +1066,7 @@ void SetWindowSize(int width, int height) void UnhideWindow(void) { #if defined(PLATFORM_DESKTOP) - glfwShowWindow(CORE.Window.handle); + glfwShowWindow(CORE.Window[CORE.currentWindow].handle); #endif } @@ -1068,20 +1074,20 @@ void UnhideWindow(void) void HideWindow(void) { #if defined(PLATFORM_DESKTOP) - glfwHideWindow(CORE.Window.handle); + glfwHideWindow(CORE.Window[CORE.currentWindow].handle); #endif } // Get current screen width int GetScreenWidth(void) { - return CORE.Window.screen.width; + return CORE.Window[CORE.currentWindow].screen.width; } // Get current screen height int GetScreenHeight(void) { - return CORE.Window.screen.height; + return CORE.Window[CORE.currentWindow].screen.height; } // Get native window handle @@ -1089,7 +1095,7 @@ void *GetWindowHandle(void) { #if defined(PLATFORM_DESKTOP) && defined(_WIN32) // NOTE: Returned handle is: void *HWND (windows.h) - return glfwGetWin32Window(CORE.Window.handle); + return glfwGetWin32Window(CORE.Window[CORE.currentWindow].handle); #elif defined(__linux__) // NOTE: Returned handle is: unsigned long Window (X.h) // typedef unsigned long XID; @@ -1208,7 +1214,7 @@ Vector2 GetWindowPosition(void) int x = 0; int y = 0; #if defined(PLATFORM_DESKTOP) - glfwGetWindowPos(CORE.Window.handle, &x, &y); + glfwGetWindowPos(CORE.Window[CORE.currentWindow].handle, &x, &y); #endif return (Vector2){ (float)x, (float)y }; } @@ -1249,7 +1255,7 @@ const char *GetMonitorName(int monitor) const char *GetClipboardText(void) { #if defined(PLATFORM_DESKTOP) - return glfwGetClipboardString(CORE.Window.handle); + return glfwGetClipboardString(CORE.Window[CORE.currentWindow].handle); #else return NULL; #endif @@ -1259,7 +1265,7 @@ const char *GetClipboardText(void) void SetClipboardText(const char *text) { #if defined(PLATFORM_DESKTOP) - glfwSetClipboardString(CORE.Window.handle, text); + glfwSetClipboardString(CORE.Window[CORE.currentWindow].handle, text); #endif } @@ -1267,7 +1273,7 @@ void SetClipboardText(const char *text) void ShowCursor(void) { #if defined(PLATFORM_DESKTOP) - glfwSetInputMode(CORE.Window.handle, GLFW_CURSOR, GLFW_CURSOR_NORMAL); + glfwSetInputMode(CORE.Window[CORE.currentWindow].handle, GLFW_CURSOR, GLFW_CURSOR_NORMAL); #endif #if defined(PLATFORM_UWP) UWPGetMouseShowFunc()(); @@ -1279,7 +1285,7 @@ void ShowCursor(void) void HideCursor(void) { #if defined(PLATFORM_DESKTOP) - glfwSetInputMode(CORE.Window.handle, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); + glfwSetInputMode(CORE.Window[CORE.currentWindow].handle, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); #endif #if defined(PLATFORM_UWP) UWPGetMouseHideFunc()(); @@ -1297,7 +1303,7 @@ bool IsCursorHidden(void) void EnableCursor(void) { #if defined(PLATFORM_DESKTOP) - glfwSetInputMode(CORE.Window.handle, GLFW_CURSOR, GLFW_CURSOR_NORMAL); + glfwSetInputMode(CORE.Window[CORE.currentWindow].handle, GLFW_CURSOR, GLFW_CURSOR_NORMAL); #endif #if defined(PLATFORM_UWP) UWPGetMouseUnlockFunc()(); @@ -1309,7 +1315,7 @@ void EnableCursor(void) void DisableCursor(void) { #if defined(PLATFORM_DESKTOP) - glfwSetInputMode(CORE.Window.handle, GLFW_CURSOR, GLFW_CURSOR_DISABLED); + glfwSetInputMode(CORE.Window[CORE.currentWindow].handle, GLFW_CURSOR, GLFW_CURSOR_DISABLED); #endif #if defined(PLATFORM_UWP) UWPGetMouseLockFunc()(); @@ -1331,14 +1337,18 @@ void ClearBackground(Color color) } // Setup canvas (framebuffer) to start drawing -void BeginDrawing(void) +void BeginDrawing(unsigned int contextID) { + CORE.currentWindow = contextID; + rlSetContext(contextID); + glfwMakeContextCurrent(CORE.Window[CORE.currentWindow].handle); + CORE.Time.current = GetTime(); // Number of elapsed seconds since InitTimer() CORE.Time.update = CORE.Time.current - CORE.Time.previous; CORE.Time.previous = CORE.Time.current; rlLoadIdentity(); // Reset current matrix (modelview) - rlMultMatrixf(MatrixToFloat(CORE.Window.screenScale)); // Apply screen scaling + rlMultMatrixf(MatrixToFloat(CORE.Window[CORE.currentWindow].screenScale)); // Apply screen scaling //rlTranslatef(0.375, 0.375, 0); // HACK to have 2D pixel-perfect drawing on OpenGL 1.1 // NOTE: Not required with OpenGL 3.3+ @@ -1367,16 +1377,16 @@ void EndDrawing(void) { // Get image data for the current frame (from backbuffer) // NOTE: This process is very slow... :( - unsigned char *screenData = rlReadScreenPixels(CORE.Window.screen.width, CORE.Window.screen.height); - GifWriteFrame(screenData, CORE.Window.screen.width, CORE.Window.screen.height, 10, 8, false); + unsigned char *screenData = rlReadScreenPixels(CORE.Window[CORE.currentWindow].screen.width, CORE.Window[CORE.currentWindow].screen.height); + GifWriteFrame(screenData, CORE.Window[CORE.currentWindow].screen.width, CORE.Window[CORE.currentWindow].screen.height, 10, 8, false); RL_FREE(screenData); // Free image data } if (((gifFramesCounter/15)%2) == 1) { - DrawCircle(30, CORE.Window.screen.height - 20, 10, RED); - DrawText("RECORDING", 50, CORE.Window.screen.height - 25, 10, MAROON); + DrawCircle(30, CORE.Window[CORE.currentWindow].screen.height - 20, 10, RED); + DrawText("RECORDING", 50, CORE.Window[CORE.currentWindow].screen.height - 25, 10, MAROON); } rlglDraw(); // Draw RECORDING message @@ -1417,7 +1427,7 @@ void BeginMode2D(Camera2D camera) rlMultMatrixf(MatrixToFloat(GetCameraMatrix2D(camera))); // Apply screen scaling if required - rlMultMatrixf(MatrixToFloat(CORE.Window.screenScale)); + rlMultMatrixf(MatrixToFloat(CORE.Window[CORE.currentWindow].screenScale)); } // Ends 2D mode with custom camera @@ -1426,7 +1436,7 @@ void EndMode2D(void) rlglDraw(); // Draw Buffers (Only OpenGL 3+ and ES2) rlLoadIdentity(); // Reset current matrix (modelview) - rlMultMatrixf(MatrixToFloat(CORE.Window.screenScale)); // Apply screen scaling if required + rlMultMatrixf(MatrixToFloat(CORE.Window[CORE.currentWindow].screenScale)); // Apply screen scaling if required } // Initializes 3D mode with custom camera (3D) @@ -1438,7 +1448,7 @@ void BeginMode3D(Camera3D camera) rlPushMatrix(); // Save previous matrix, which contains the settings for the 2d ortho projection rlLoadIdentity(); // Reset current matrix (projection) - float aspect = (float)CORE.Window.currentFbo.width/(float)CORE.Window.currentFbo.height; + float aspect = (float)CORE.Window[CORE.currentWindow].currentFbo.width/(float)CORE.Window[CORE.currentWindow].currentFbo.height; if (camera.type == CAMERA_PERSPECTIVE) { @@ -1480,7 +1490,7 @@ void EndMode3D(void) rlMatrixMode(RL_MODELVIEW); // Switch back to modelview matrix rlLoadIdentity(); // Reset current matrix (modelview) - rlMultMatrixf(MatrixToFloat(CORE.Window.screenScale)); // Apply screen scaling if required + rlMultMatrixf(MatrixToFloat(CORE.Window[CORE.currentWindow].screenScale)); // Apply screen scaling if required rlDisableDepthTest(); // Disable DEPTH_TEST for 2D } @@ -1509,8 +1519,8 @@ void BeginTextureMode(RenderTexture2D target) // Setup current width/height for proper aspect ratio // calculation when using BeginMode3D() - CORE.Window.currentFbo.width = target.texture.width; - CORE.Window.currentFbo.height = target.texture.height; + CORE.Window[CORE.currentWindow].currentFbo.width = target.texture.width; + CORE.Window[CORE.currentWindow].currentFbo.height = target.texture.height; } // Ends drawing to render texture @@ -1521,11 +1531,11 @@ void EndTextureMode(void) rlDisableRenderTexture(); // Disable render target // Set viewport to default framebuffer size - SetupViewport(CORE.Window.render.width, CORE.Window.render.height); + SetupViewport(CORE.Window[CORE.currentWindow].render.width, CORE.Window[CORE.currentWindow].render.height); // Reset current screen size - CORE.Window.currentFbo.width = GetScreenWidth(); - CORE.Window.currentFbo.height = GetScreenHeight(); + CORE.Window[CORE.currentWindow].currentFbo.width = GetScreenWidth(); + CORE.Window[CORE.currentWindow].currentFbo.height = GetScreenHeight(); } // Begin scissor mode (define screen area for following drawing) @@ -1535,7 +1545,7 @@ void BeginScissorMode(int x, int y, int width, int height) rlglDraw(); // Force drawing elements rlEnableScissorTest(); - rlScissor(x, CORE.Window.currentFbo.height - (y + height), width, height); + rlScissor(x, CORE.Window[CORE.currentWindow].currentFbo.height - (y + height), width, height); } // End scissor mode @@ -1571,7 +1581,7 @@ Ray GetMouseRay(Vector2 mouse, Camera camera) } else if (camera.type == CAMERA_ORTHOGRAPHIC) { - float aspect = (float)CORE.Window.screen.width/(float)CORE.Window.screen.height; + float aspect = (float)CORE.Window[CORE.currentWindow].screen.width/(float)CORE.Window[CORE.currentWindow].screen.height; double top = camera.fovy/2.0; double right = top*aspect; @@ -1655,7 +1665,7 @@ Vector2 GetWorldToScreenEx(Vector3 position, Camera camera, int width, int heigh } else if (camera.type == CAMERA_ORTHOGRAPHIC) { - float aspect = (float)CORE.Window.screen.width/(float)CORE.Window.screen.height; + float aspect = (float)CORE.Window[CORE.currentWindow].screen.width/(float)CORE.Window[CORE.currentWindow].screen.height; double top = camera.fovy/2.0; double right = top*aspect; @@ -1769,10 +1779,10 @@ double GetTime(void) // Setup window configuration flags (view FLAGS) void SetConfigFlags(unsigned int flags) { - CORE.Window.flags = flags; + CORE.Window[CORE.currentWindow].flags = flags; - if (CORE.Window.flags & FLAG_FULLSCREEN_MODE) CORE.Window.fullscreen = true; - if (CORE.Window.flags & FLAG_WINDOW_ALWAYS_RUN) CORE.Window.alwaysRun = true; + if (CORE.Window[CORE.currentWindow].flags & FLAG_FULLSCREEN_MODE) CORE.Window[CORE.currentWindow].fullscreen = true; + if (CORE.Window[CORE.currentWindow].flags & FLAG_WINDOW_ALWAYS_RUN) CORE.Window[CORE.currentWindow].alwaysRun = true; } // NOTE TRACELOG() function is located in [utils.h] @@ -1782,8 +1792,8 @@ void SetConfigFlags(unsigned int flags) // have their own internal file-systems, to dowload image to user file-system some additional mechanism is required void TakeScreenshot(const char *fileName) { - unsigned char *imgData = rlReadScreenPixels(CORE.Window.render.width, CORE.Window.render.height); - Image image = { imgData, CORE.Window.render.width, CORE.Window.render.height, 1, UNCOMPRESSED_R8G8B8A8 }; + unsigned char *imgData = rlReadScreenPixels(CORE.Window[CORE.currentWindow].render.width, CORE.Window[CORE.currentWindow].render.height); + Image image = { imgData, CORE.Window[CORE.currentWindow].render.width, CORE.Window[CORE.currentWindow].render.height, 1, UNCOMPRESSED_R8G8B8A8 }; char path[512] = { 0 }; #if defined(PLATFORM_ANDROID) @@ -2071,27 +2081,27 @@ bool ChangeDirectory(const char *dir) // Check if a file has been dropped into window bool IsFileDropped(void) { - if (CORE.Window.dropFilesCount > 0) return true; + if (CORE.Window[CORE.currentWindow].dropFilesCount > 0) return true; else return false; } // Get dropped files names char **GetDroppedFiles(int *count) { - *count = CORE.Window.dropFilesCount; - return CORE.Window.dropFilesPath; + *count = CORE.Window[CORE.currentWindow].dropFilesCount; + return CORE.Window[CORE.currentWindow].dropFilesPath; } // Clear dropped files paths buffer void ClearDroppedFiles(void) { - if (CORE.Window.dropFilesCount > 0) + if (CORE.Window[CORE.currentWindow].dropFilesCount > 0) { - for (int i = 0; i < CORE.Window.dropFilesCount; i++) RL_FREE(CORE.Window.dropFilesPath[i]); + for (int i = 0; i < CORE.Window[CORE.currentWindow].dropFilesCount; i++) RL_FREE(CORE.Window[CORE.currentWindow].dropFilesPath[i]); - RL_FREE(CORE.Window.dropFilesPath); + RL_FREE(CORE.Window[CORE.currentWindow].dropFilesPath); - CORE.Window.dropFilesCount = 0; + CORE.Window[CORE.currentWindow].dropFilesCount = 0; } } @@ -2566,7 +2576,7 @@ void SetMousePosition(int x, int y) CORE.Input.Mouse.position = (Vector2){ (float)x, (float)y }; #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) // NOTE: emscripten not implemented - glfwSetCursorPos(CORE.Window.handle, CORE.Input.Mouse.position.x, CORE.Input.Mouse.position.y); + glfwSetCursorPos(CORE.Window[CORE.currentWindow].handle, CORE.Input.Mouse.position.x, CORE.Input.Mouse.position.y); #endif #if defined(PLATFORM_UWP) UWPGetMouseSetPosFunc()(x, y); @@ -2630,15 +2640,15 @@ Vector2 GetTouchPosition(int index) else TRACELOG(LOG_WARNING, "INPUT: Required touch point out of range (Max touch points: %i)", MAX_TOUCH_POINTS); #if defined(PLATFORM_ANDROID) - if ((CORE.Window.screen.width > CORE.Window.display.width) || (CORE.Window.screen.height > CORE.Window.display.height)) + if ((CORE.Window[CORE.currentWindow].screen.width > CORE.Window[CORE.currentWindow].display.width) || (CORE.Window[CORE.currentWindow].screen.height > CORE.Window[CORE.currentWindow].display.height)) { - position.x = position.x*((float)CORE.Window.screen.width/(float)(CORE.Window.display.width - CORE.Window.renderOffset.x)) - CORE.Window.renderOffset.x/2; - position.y = position.y*((float)CORE.Window.screen.height/(float)(CORE.Window.display.height - CORE.Window.renderOffset.y)) - CORE.Window.renderOffset.y/2; + position.x = position.x*((float)CORE.Window[CORE.currentWindow].screen.width/(float)(CORE.Window[CORE.currentWindow].display.width - CORE.Window[CORE.currentWindow].renderOffset.x)) - CORE.Window[CORE.currentWindow].renderOffset.x/2; + position.y = position.y*((float)CORE.Window[CORE.currentWindow].screen.height/(float)(CORE.Window[CORE.currentWindow].display.height - CORE.Window[CORE.currentWindow].renderOffset.y)) - CORE.Window[CORE.currentWindow].renderOffset.y/2; } else { - position.x = position.x*((float)CORE.Window.render.width/(float)CORE.Window.display.width) - CORE.Window.renderOffset.x/2; - position.y = position.y*((float)CORE.Window.render.height/(float)CORE.Window.display.height) - CORE.Window.renderOffset.y/2; + position.x = position.x*((float)CORE.Window[CORE.currentWindow].render.width/(float)CORE.Window[CORE.currentWindow].display.width) - CORE.Window[CORE.currentWindow].renderOffset.x/2; + position.y = position.y*((float)CORE.Window[CORE.currentWindow].render.height/(float)CORE.Window[CORE.currentWindow].display.height) - CORE.Window[CORE.currentWindow].renderOffset.y/2; } #endif @@ -2662,12 +2672,12 @@ Vector2 GetTouchPosition(int index) // NOTE: returns false in case graphic device could not be created static bool InitGraphicsDevice(int width, int height) { - CORE.Window.screen.width = width; // User desired width - CORE.Window.screen.height = height; // User desired height + //CORE.Window[CORE.currentWindow].screen.width = width; // User desired width + //CORE.Window[CORE.currentWindow].screen.height = height; // User desired height - CORE.Window.screenScale = MatrixIdentity(); // No draw scaling required by default + // CORE.Window[CORE.currentWindow].screenScale = MatrixIdentity(); // No draw scaling required by default - // NOTE: Framebuffer (render area - CORE.Window.render.width, CORE.Window.render.height) could include black bars... + // NOTE: Framebuffer (render area - CORE.Window[CORE.currentWindow].render.width, CORE.Window[CORE.currentWindow].render.height) could include black bars... // ...in top-down or left-right to match display aspect ratio (no weird scalings) #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) @@ -2676,11 +2686,13 @@ static bool InitGraphicsDevice(int width, int height) #if defined(__APPLE__) glfwInitHint(GLFW_COCOA_CHDIR_RESOURCES, GLFW_FALSE); #endif - - if (!glfwInit()) + if (CORE.numWindows == 0) //if it's the first context { - TRACELOG(LOG_WARNING, "GLFW: Failed to initialize GLFW"); - return false; + if (!glfwInit()) + { + TRACELOG(LOG_WARNING, "GLFW: Failed to initialize GLFW"); + return false; + } } // NOTE: Getting video modes is not implemented in emscripten GLFW3 version @@ -2694,17 +2706,20 @@ static bool InitGraphicsDevice(int width, int height) } const GLFWvidmode *mode = glfwGetVideoMode(monitor); - CORE.Window.display.width = mode->width; - CORE.Window.display.height = mode->height; + CORE.Window[CORE.currentWindow].screenScale = MatrixIdentity(); // No draw scaling required by default + CORE.Window[CORE.currentWindow].screen.width = width; // User desired width + CORE.Window[CORE.currentWindow].screen.height = height; // User desired height + CORE.Window[CORE.currentWindow].display.width = mode->width; + CORE.Window[CORE.currentWindow].display.height = mode->height; // Screen size security check - if (CORE.Window.screen.width <= 0) CORE.Window.screen.width = CORE.Window.display.width; - if (CORE.Window.screen.height <= 0) CORE.Window.screen.height = CORE.Window.display.height; + if (CORE.Window[CORE.currentWindow].screen.width <= 0) CORE.Window[CORE.currentWindow].screen.width = CORE.Window[CORE.currentWindow].display.width; + if (CORE.Window[CORE.currentWindow].screen.height <= 0) CORE.Window[CORE.currentWindow].screen.height = CORE.Window[CORE.currentWindow].display.height; #endif // PLATFORM_DESKTOP #if defined(PLATFORM_WEB) - CORE.Window.display.width = CORE.Window.screen.width; - CORE.Window.display.height = CORE.Window.screen.height; + CORE.Window[CORE.currentWindow].display.width = CORE.Window[CORE.currentWindow].screen.width; + CORE.Window[CORE.currentWindow].display.height = CORE.Window[CORE.currentWindow].screen.height; #endif // PLATFORM_WEB glfwDefaultWindowHints(); // Set default windows hints: @@ -2724,21 +2739,21 @@ static bool InitGraphicsDevice(int width, int height) #endif // Check some Window creation flags - if (CORE.Window.flags & FLAG_WINDOW_HIDDEN) glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); // Visible window + if (CORE.Window[CORE.currentWindow].flags & FLAG_WINDOW_HIDDEN) glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); // Visible window else glfwWindowHint(GLFW_VISIBLE, GLFW_TRUE); // Window initially hidden - if (CORE.Window.flags & FLAG_WINDOW_RESIZABLE) glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); // Resizable window + if (CORE.Window[CORE.currentWindow].flags & FLAG_WINDOW_RESIZABLE) glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); // Resizable window else glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); // Avoid window being resizable - if (CORE.Window.flags & FLAG_WINDOW_UNDECORATED) glfwWindowHint(GLFW_DECORATED, GLFW_FALSE); // Border and buttons on Window + if (CORE.Window[CORE.currentWindow].flags & FLAG_WINDOW_UNDECORATED) glfwWindowHint(GLFW_DECORATED, GLFW_FALSE); // Border and buttons on Window else glfwWindowHint(GLFW_DECORATED, GLFW_TRUE); // Decorated window // FLAG_WINDOW_TRANSPARENT not supported on HTML5 and not included in any released GLFW version yet #if defined(GLFW_TRANSPARENT_FRAMEBUFFER) - if (CORE.Window.flags & FLAG_WINDOW_TRANSPARENT) glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE); // Transparent framebuffer + if (CORE.Window[CORE.currentWindow].flags & FLAG_WINDOW_TRANSPARENT) glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE); // Transparent framebuffer else glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_FALSE); // Opaque framebuffer #endif - if (CORE.Window.flags & FLAG_MSAA_4X_HINT) glfwWindowHint(GLFW_SAMPLES, 4); // Tries to enable multisampling x4 (MSAA), default is 0 + if (CORE.Window[CORE.currentWindow].flags & FLAG_MSAA_4X_HINT) glfwWindowHint(GLFW_SAMPLES, 4); // Tries to enable multisampling x4 (MSAA), default is 0 // NOTE: When asking for an OpenGL context version, most drivers provide highest supported version // with forward compatibility to older OpenGL versions. @@ -2761,7 +2776,7 @@ static bool InitGraphicsDevice(int width, int height) #else glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_FALSE); // Fordward Compatibility Hint: Only 3.3 and above! #endif - //glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE); // Request OpenGL DEBUG context + //glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE); // Request OpenGL DEBUG context } else if (rlGetVersion() == OPENGL_ES_20) // Request OpenGL ES 2.0 context { @@ -2775,28 +2790,28 @@ static bool InitGraphicsDevice(int width, int height) #endif } - if (CORE.Window.fullscreen) + if (CORE.Window[CORE.currentWindow].fullscreen) { // remember center for switchinging from fullscreen to window - CORE.Window.position.x = CORE.Window.display.width/2 - CORE.Window.screen.width/2; - CORE.Window.position.y = CORE.Window.display.height/2 - CORE.Window.screen.height/2; + CORE.Window[CORE.currentWindow].position.x = CORE.Window[CORE.currentWindow].display.width / 2 - CORE.Window[CORE.currentWindow].screen.width / 2; + CORE.Window[CORE.currentWindow].position.y = CORE.Window[CORE.currentWindow].display.height / 2 - CORE.Window[CORE.currentWindow].screen.height / 2; - if (CORE.Window.position.x < 0) CORE.Window.position.x = 0; - if (CORE.Window.position.y < 0) CORE.Window.position.y = 0; + if (CORE.Window[CORE.currentWindow].position.x < 0) CORE.Window[CORE.currentWindow].position.x = 0; + if (CORE.Window[CORE.currentWindow].position.y < 0) CORE.Window[CORE.currentWindow].position.y = 0; - // Obtain recommended CORE.Window.display.width/CORE.Window.display.height from a valid videomode for the monitor + // Obtain recommended CORE.Window[CORE.currentWindow].display.width/CORE.Window[CORE.currentWindow].display.height from a valid videomode for the monitor int count = 0; - const GLFWvidmode *modes = glfwGetVideoModes(glfwGetPrimaryMonitor(), &count); + const GLFWvidmode* modes = glfwGetVideoModes(glfwGetPrimaryMonitor(), &count); - // Get closest video mode to desired CORE.Window.screen.width/CORE.Window.screen.height + // Get closest video mode to desired CORE.Window[CORE.currentWindow].screen.width/CORE.Window[CORE.currentWindow].screen.height for (int i = 0; i < count; i++) { - if ((unsigned int)modes[i].width >= CORE.Window.screen.width) + if ((unsigned int)modes[i].width >= CORE.Window[CORE.currentWindow].screen.width) { - if ((unsigned int)modes[i].height >= CORE.Window.screen.height) + if ((unsigned int)modes[i].height >= CORE.Window[CORE.currentWindow].screen.height) { - CORE.Window.display.width = modes[i].width; - CORE.Window.display.height = modes[i].height; + CORE.Window[CORE.currentWindow].display.width = modes[i].width; + CORE.Window[CORE.currentWindow].display.height = modes[i].height; break; } } @@ -2804,12 +2819,12 @@ static bool InitGraphicsDevice(int width, int height) #if defined(PLATFORM_DESKTOP) // If we are windowed fullscreen, ensures that window does not minimize when focus is lost - if ((CORE.Window.screen.height == CORE.Window.display.height) && (CORE.Window.screen.width == CORE.Window.display.width)) + if ((CORE.Window[CORE.currentWindow].screen.height == CORE.Window[CORE.currentWindow].display.height) && (CORE.Window[CORE.currentWindow].screen.width == CORE.Window[CORE.currentWindow].display.width)) { glfwWindowHint(GLFW_AUTO_ICONIFY, 0); } #endif - TRACELOG(LOG_WARNING, "SYSTEM: Closest fullscreen videomode: %i x %i", CORE.Window.display.width, CORE.Window.display.height); + TRACELOG(LOG_WARNING, "SYSTEM: Closest fullscreen videomode: %i x %i", CORE.Window[CORE.currentWindow].display.width, CORE.Window[CORE.currentWindow].display.height); // NOTE: ISSUE: Closest videomode could not match monitor aspect-ratio, for example, // for a desired screen size of 800x450 (16:9), closest supported videomode is 800x600 (4:3), @@ -2818,39 +2833,41 @@ static bool InitGraphicsDevice(int width, int height) // Try to setup the most appropiate fullscreen framebuffer for the requested screenWidth/screenHeight // It considers device display resolution mode and setups a framebuffer with black bars if required (render size/offset) - // Modified global variables: CORE.Window.screen.width/CORE.Window.screen.height - CORE.Window.render.width/CORE.Window.render.height - CORE.Window.renderOffset.x/CORE.Window.renderOffset.y - CORE.Window.screenScale + // Modified global variables: CORE.Window[CORE.currentWindow].screen.width/CORE.Window[CORE.currentWindow].screen.height - CORE.Window[CORE.currentWindow].render.width/CORE.Window[CORE.currentWindow].render.height - CORE.Window[CORE.currentWindow].renderOffset.x/CORE.Window[CORE.currentWindow].renderOffset.y - CORE.Window[CORE.currentWindow].screenScale // TODO: It is a quite cumbersome solution to display size vs requested size, it should be reviewed or removed... // HighDPI monitors are properly considered in a following similar function: SetupViewport() - SetupFramebuffer(CORE.Window.display.width, CORE.Window.display.height); + SetupFramebuffer(CORE.Window[CORE.currentWindow].display.width, CORE.Window[CORE.currentWindow].display.height); - CORE.Window.handle = glfwCreateWindow(CORE.Window.display.width, CORE.Window.display.height, CORE.Window.title, glfwGetPrimaryMonitor(), NULL); + CORE.Window[CORE.currentWindow].handle = glfwCreateWindow(CORE.Window[CORE.currentWindow].display.width, CORE.Window[CORE.currentWindow].display.height, CORE.Window[CORE.currentWindow].title, glfwGetPrimaryMonitor(), CORE.currentWindow == 0 ? NULL : CORE.Window[0].handle); + //CORE.Window[CORE.currentWindow].handle = glfwCreateWindow(CORE.Window[CORE.currentWindow].display.width, CORE.Window[CORE.currentWindow].display.height, CORE.Window[CORE.currentWindow].title, glfwGetPrimaryMonitor(), NULL); // NOTE: Full-screen change, not working properly... - //glfwSetWindowMonitor(CORE.Window.handle, glfwGetPrimaryMonitor(), 0, 0, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE); + //glfwSetWindowMonitor(CORE.Window[CORE.currentWindow].handle, glfwGetPrimaryMonitor(), 0, 0, CORE.Window[CORE.currentWindow].screen.width, CORE.Window[CORE.currentWindow].screen.height, GLFW_DONT_CARE); } else { // No-fullscreen window creation - CORE.Window.handle = glfwCreateWindow(CORE.Window.screen.width, CORE.Window.screen.height, CORE.Window.title, NULL, NULL); + CORE.Window[CORE.currentWindow].handle = glfwCreateWindow(CORE.Window[CORE.currentWindow].screen.width, CORE.Window[CORE.currentWindow].screen.height, CORE.Window[CORE.currentWindow].title, NULL, CORE.currentWindow == 0 ? NULL : CORE.Window[0].handle); + //CORE.Window[CORE.currentWindow].handle = glfwCreateWindow(CORE.Window[CORE.currentWindow].screen.width, CORE.Window[CORE.currentWindow].screen.height, CORE.Window[CORE.currentWindow].title, NULL, NULL); - if (CORE.Window.handle) + if (CORE.Window[CORE.currentWindow].handle) { #if defined(PLATFORM_DESKTOP) // Center window on screen - int windowPosX = CORE.Window.display.width/2 - CORE.Window.screen.width/2; - int windowPosY = CORE.Window.display.height/2 - CORE.Window.screen.height/2; + int windowPosX = CORE.Window[CORE.currentWindow].display.width / 2 - CORE.Window[CORE.currentWindow].screen.width / 2; + int windowPosY = CORE.Window[CORE.currentWindow].display.height / 2 - CORE.Window[CORE.currentWindow].screen.height / 2; if (windowPosX < 0) windowPosX = 0; if (windowPosY < 0) windowPosY = 0; - glfwSetWindowPos(CORE.Window.handle, windowPosX, windowPosY); + glfwSetWindowPos(CORE.Window[CORE.currentWindow].handle, windowPosX, windowPosY); #endif - CORE.Window.render.width = CORE.Window.screen.width; - CORE.Window.render.height = CORE.Window.screen.height; + CORE.Window[CORE.currentWindow].render.width = CORE.Window[CORE.currentWindow].screen.width; + CORE.Window[CORE.currentWindow].render.height = CORE.Window[CORE.currentWindow].screen.height; } } - if (!CORE.Window.handle) + if (!CORE.Window[CORE.currentWindow].handle) { glfwTerminate(); TRACELOG(LOG_WARNING, "GLFW: Failed to initialize Window"); @@ -2860,25 +2877,25 @@ static bool InitGraphicsDevice(int width, int height) { TRACELOG(LOG_INFO, "DISPLAY: Device initialized successfully"); #if defined(PLATFORM_DESKTOP) - TRACELOG(LOG_INFO, " > Display size: %i x %i", CORE.Window.display.width, CORE.Window.display.height); + TRACELOG(LOG_INFO, " > Display size: %i x %i", CORE.Window[CORE.currentWindow].display.width, CORE.Window[CORE.currentWindow].display.height); #endif - TRACELOG(LOG_INFO, " > Render size: %i x %i", CORE.Window.render.width, CORE.Window.render.height); - TRACELOG(LOG_INFO, " > Screen size: %i x %i", CORE.Window.screen.width, CORE.Window.screen.height); - TRACELOG(LOG_INFO, " > Viewport offsets: %i, %i", CORE.Window.renderOffset.x, CORE.Window.renderOffset.y); + TRACELOG(LOG_INFO, " > Render size: %i x %i", CORE.Window[CORE.currentWindow].render.width, CORE.Window[CORE.currentWindow].render.height); + TRACELOG(LOG_INFO, " > Screen size: %i x %i", CORE.Window[CORE.currentWindow].screen.width, CORE.Window[CORE.currentWindow].screen.height); + TRACELOG(LOG_INFO, " > Viewport offsets: %i, %i", CORE.Window[CORE.currentWindow].renderOffset.x, CORE.Window[CORE.currentWindow].renderOffset.y); } - glfwSetWindowSizeCallback(CORE.Window.handle, WindowSizeCallback); // NOTE: Resizing not allowed by default! - glfwSetCursorEnterCallback(CORE.Window.handle, CursorEnterCallback); - glfwSetKeyCallback(CORE.Window.handle, KeyCallback); - glfwSetMouseButtonCallback(CORE.Window.handle, MouseButtonCallback); - glfwSetCursorPosCallback(CORE.Window.handle, MouseCursorPosCallback); // Track mouse position changes - glfwSetCharCallback(CORE.Window.handle, CharCallback); - glfwSetScrollCallback(CORE.Window.handle, ScrollCallback); - glfwSetWindowIconifyCallback(CORE.Window.handle, WindowIconifyCallback); - glfwSetWindowFocusCallback(CORE.Window.handle, WindowFocusCallback); - glfwSetDropCallback(CORE.Window.handle, WindowDropCallback); - - glfwMakeContextCurrent(CORE.Window.handle); + glfwSetWindowSizeCallback(CORE.Window[CORE.currentWindow].handle, WindowSizeCallback); // NOTE: Resizing not allowed by default! + glfwSetCursorEnterCallback(CORE.Window[CORE.currentWindow].handle, CursorEnterCallback); + glfwSetKeyCallback(CORE.Window[CORE.currentWindow].handle, KeyCallback); + glfwSetMouseButtonCallback(CORE.Window[CORE.currentWindow].handle, MouseButtonCallback); + glfwSetCursorPosCallback(CORE.Window[CORE.currentWindow].handle, MouseCursorPosCallback); // Track mouse position changes + glfwSetCharCallback(CORE.Window[CORE.currentWindow].handle, CharCallback); + glfwSetScrollCallback(CORE.Window[CORE.currentWindow].handle, ScrollCallback); + glfwSetWindowIconifyCallback(CORE.Window[CORE.currentWindow].handle, WindowIconifyCallback); + glfwSetWindowFocusCallback(CORE.Window[CORE.currentWindow].handle, WindowFocusCallback); + glfwSetDropCallback(CORE.Window[CORE.currentWindow].handle, WindowDropCallback); + + glfwMakeContextCurrent(CORE.Window[CORE.currentWindow].handle); #if !defined(PLATFORM_WEB) glfwSwapInterval(0); // No V-Sync by default @@ -2892,7 +2909,7 @@ static bool InitGraphicsDevice(int width, int height) // Try to enable GPU V-Sync, so frames are limited to screen refresh rate (60Hz -> 60 FPS) // NOTE: V-Sync can be enabled by graphic driver configuration - if (CORE.Window.flags & FLAG_VSYNC_HINT) + if (CORE.Window[CORE.currentWindow].flags & FLAG_VSYNC_HINT) { // WARNING: It seems to hits a critical render path in Intel HD Graphics glfwSwapInterval(1); @@ -2901,7 +2918,7 @@ static bool InitGraphicsDevice(int width, int height) #endif // PLATFORM_DESKTOP || PLATFORM_WEB #if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) || defined(PLATFORM_UWP) - CORE.Window.fullscreen = true; + CORE.Window[CORE.currentWindow].fullscreen = true; #if defined(PLATFORM_RPI) bcm_host_init(); @@ -2916,7 +2933,7 @@ static bool InitGraphicsDevice(int width, int height) EGLint samples = 0; EGLint sampleBuffer = 0; - if (CORE.Window.flags & FLAG_MSAA_4X_HINT) + if (CORE.Window[CORE.currentWindow].flags & FLAG_MSAA_4X_HINT) { samples = 4; sampleBuffer = 1; @@ -3013,34 +3030,34 @@ static bool InitGraphicsDevice(int width, int height) // // This tries to initialize EGL to D3D11 Feature Level 10_0+. See above comment for details. - CORE.Window.device = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, defaultDisplayAttributes); - if (CORE.Window.device == EGL_NO_DISPLAY) + CORE.Window[CORE.currentWindow].device = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, defaultDisplayAttributes); + if (CORE.Window[CORE.currentWindow].device == EGL_NO_DISPLAY) { TRACELOG(LOG_WARNING, "DISPLAY: Failed to initialize EGL device"); return false; } - if (eglInitialize(CORE.Window.device, NULL, NULL) == EGL_FALSE) + if (eglInitialize(CORE.Window[CORE.currentWindow].device, NULL, NULL) == EGL_FALSE) { // This tries to initialize EGL to D3D11 Feature Level 9_3, if 10_0+ is unavailable (e.g. on some mobile devices). - CORE.Window.device = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, fl9_3DisplayAttributes); - if (CORE.Window.device == EGL_NO_DISPLAY) + CORE.Window[CORE.currentWindow].device = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, fl9_3DisplayAttributes); + if (CORE.Window[CORE.currentWindow].device == EGL_NO_DISPLAY) { TRACELOG(LOG_WARNING, "DISPLAY: Failed to initialize EGL device"); return false; } - if (eglInitialize(CORE.Window.device, NULL, NULL) == EGL_FALSE) + if (eglInitialize(CORE.Window[CORE.currentWindow].device, NULL, NULL) == EGL_FALSE) { // This initializes EGL to D3D11 Feature Level 11_0 on WARP, if 9_3+ is unavailable on the default GPU. - CORE.Window.device = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, warpDisplayAttributes); - if (CORE.Window.device == EGL_NO_DISPLAY) + CORE.Window[CORE.currentWindow].device = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, warpDisplayAttributes); + if (CORE.Window[CORE.currentWindow].device == EGL_NO_DISPLAY) { TRACELOG(LOG_WARNING, "DISPLAY: Failed to initialize EGL device"); return false; } - if (eglInitialize(CORE.Window.device, NULL, NULL) == EGL_FALSE) + if (eglInitialize(CORE.Window[CORE.currentWindow].device, NULL, NULL) == EGL_FALSE) { // If all of the calls to eglInitialize returned EGL_FALSE then an error has occurred. TRACELOG(LOG_WARNING, "DISPLAY: Failed to initialize EGL device"); @@ -3050,7 +3067,7 @@ static bool InitGraphicsDevice(int width, int height) } EGLint numConfigs = 0; - if ((eglChooseConfig(CORE.Window.device, framebufferAttribs, &CORE.Window.config, 1, &numConfigs) == EGL_FALSE) || (numConfigs == 0)) + if ((eglChooseConfig(CORE.Window[CORE.currentWindow].device, framebufferAttribs, &CORE.Window[CORE.currentWindow].config, 1, &numConfigs) == EGL_FALSE) || (numConfigs == 0)) { TRACELOG(LOG_WARNING, "DISPLAY: Failed to choose first EGL configuration"); return false; @@ -3086,31 +3103,27 @@ static bool InitGraphicsDevice(int width, int height) //https://stackoverflow.com/questions/46550182/how-to-create-eglsurface-using-c-winrt-and-angle - //CORE.Window.surface = eglCreateWindowSurface(CORE.Window.device, CORE.Window.config, reinterpret_cast(surfaceCreationProperties), surfaceAttributes); - CORE.Window.surface = eglCreateWindowSurface(CORE.Window.device, CORE.Window.config, (EGLNativeWindowType) UWPGetCoreWindowPtr(), surfaceAttributes); - if (CORE.Window.surface == EGL_NO_SURFACE) + //CORE.Window[CORE.currentWindow].surface = eglCreateWindowSurface(CORE.Window[CORE.currentWindow].device, CORE.Window[CORE.currentWindow].config, reinterpret_cast(surfaceCreationProperties), surfaceAttributes); + CORE.Window[CORE.currentWindow].surface = eglCreateWindowSurface(CORE.Window[CORE.currentWindow].device, CORE.Window[CORE.currentWindow].config, (EGLNativeWindowType) UWPGetCoreWindowPtr(), surfaceAttributes); + if (CORE.Window[CORE.currentWindow].surface == EGL_NO_SURFACE) { TRACELOG(LOG_WARNING, "DISPLAY: Failed to create EGL fullscreen surface"); return false; } - CORE.Window.context = eglCreateContext(CORE.Window.device, CORE.Window.config, EGL_NO_CONTEXT, contextAttribs); - if (CORE.Window.context == EGL_NO_CONTEXT) + CORE.Window[CORE.currentWindow].context = eglCreateContext(CORE.Window[CORE.currentWindow].device, CORE.Window[CORE.currentWindow].config, EGL_NO_CONTEXT, contextAttribs); + if (CORE.Window[CORE.currentWindow].context == EGL_NO_CONTEXT) { TRACELOG(LOG_WARNING, "DISPLAY: Failed to create EGL context"); return false; } // Get EGL device window size - eglQuerySurface(CORE.Window.device, CORE.Window.surface, EGL_WIDTH, &CORE.Window.screen.width); - eglQuerySurface(CORE.Window.device, CORE.Window.surface, EGL_HEIGHT, &CORE.Window.screen.height); + eglQuerySurface(CORE.Window[CORE.currentWindow].device, CORE.Window[CORE.currentWindow].surface, EGL_WIDTH, &CORE.Window[CORE.currentWindow].screen.width); + eglQuerySurface(CORE.Window[CORE.currentWindow].device, CORE.Window[CORE.currentWindow].surface, EGL_HEIGHT, &CORE.Window[CORE.currentWindow].screen.height); // Get display size - UWPGetDisplaySizeFunc()(&CORE.Window.display.width, &CORE.Window.display.height); - - // Use the width and height of the surface for render - CORE.Window.render.width = CORE.Window.screen.width; - CORE.Window.render.height = CORE.Window.screen.height; + UWPGetDisplaySizeFunc()(&CORE.Window[CORE.currentWindow].display.width, &CORE.Window[CORE.currentWindow].display.height); #endif // PLATFORM_UWP @@ -3118,15 +3131,15 @@ static bool InitGraphicsDevice(int width, int height) EGLint numConfigs = 0; // Get an EGL device connection - CORE.Window.device = eglGetDisplay(EGL_DEFAULT_DISPLAY); - if (CORE.Window.device == EGL_NO_DISPLAY) + CORE.Window[CORE.currentWindow].device = eglGetDisplay(EGL_DEFAULT_DISPLAY); + if (CORE.Window[CORE.currentWindow].device == EGL_NO_DISPLAY) { TRACELOG(LOG_WARNING, "DISPLAY: Failed to initialize EGL device"); return false; } // Initialize the EGL device connection - if (eglInitialize(CORE.Window.device, NULL, NULL) == EGL_FALSE) + if (eglInitialize(CORE.Window[CORE.currentWindow].device, NULL, NULL) == EGL_FALSE) { // If all of the calls to eglInitialize returned EGL_FALSE then an error has occurred. TRACELOG(LOG_WARNING, "DISPLAY: Failed to initialize EGL device"); @@ -3134,14 +3147,14 @@ static bool InitGraphicsDevice(int width, int height) } // Get an appropriate EGL framebuffer configuration - eglChooseConfig(CORE.Window.device, framebufferAttribs, &CORE.Window.config, 1, &numConfigs); + eglChooseConfig(CORE.Window[CORE.currentWindow].device, framebufferAttribs, &CORE.Window[CORE.currentWindow].config, 1, &numConfigs); // Set rendering API eglBindAPI(EGL_OPENGL_ES_API); // Create an EGL rendering context - CORE.Window.context = eglCreateContext(CORE.Window.device, CORE.Window.config, EGL_NO_CONTEXT, contextAttribs); - if (CORE.Window.context == EGL_NO_CONTEXT) + CORE.Window[CORE.currentWindow].context = eglCreateContext(CORE.Window[CORE.currentWindow].device, CORE.Window[CORE.currentWindow].config, EGL_NO_CONTEXT, contextAttribs); + if (CORE.Window[CORE.currentWindow].context == EGL_NO_CONTEXT) { TRACELOG(LOG_WARNING, "DISPLAY: Failed to create EGL context"); return false; @@ -3155,44 +3168,38 @@ static bool InitGraphicsDevice(int width, int height) // EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is guaranteed to be accepted by ANativeWindow_setBuffersGeometry() // As soon as we picked a EGLConfig, we can safely reconfigure the ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID - eglGetConfigAttrib(CORE.Window.device, CORE.Window.config, EGL_NATIVE_VISUAL_ID, &displayFormat); + eglGetConfigAttrib(CORE.Window[CORE.currentWindow].device, CORE.Window[CORE.currentWindow].config, EGL_NATIVE_VISUAL_ID, &displayFormat); // At this point we need to manage render size vs screen size - // NOTE: This function use and modify global module variables: - // -> CORE.Window.screen.width/CORE.Window.screen.height - // -> CORE.Window.render.width/CORE.Window.render.height - // -> CORE.Window.screenScale - SetupFramebuffer(CORE.Window.display.width, CORE.Window.display.height); + // NOTE: This function use and modify global module variables: CORE.Window[CORE.currentWindow].screen.width/CORE.Window[CORE.currentWindow].screen.height and CORE.Window[CORE.currentWindow].render.width/CORE.Window[CORE.currentWindow].render.height and CORE.Window[CORE.currentWindow].screenScale + SetupFramebuffer(CORE.Window[CORE.currentWindow].display.width, CORE.Window[CORE.currentWindow].display.height); - ANativeWindow_setBuffersGeometry(CORE.Android.app->window, CORE.Window.render.width, CORE.Window.render.height, displayFormat); + ANativeWindow_setBuffersGeometry(CORE.Android.app->window, CORE.Window[CORE.currentWindow].render.width, CORE.Window[CORE.currentWindow].render.height, displayFormat); //ANativeWindow_setBuffersGeometry(CORE.Android.app->window, 0, 0, displayFormat); // Force use of native display size - CORE.Window.surface = eglCreateWindowSurface(CORE.Window.device, CORE.Window.config, CORE.Android.app->window, NULL); + CORE.Window[CORE.currentWindow].surface = eglCreateWindowSurface(CORE.Window[CORE.currentWindow].device, CORE.Window[CORE.currentWindow].config, CORE.Android.app->window, NULL); #endif // PLATFORM_ANDROID #if defined(PLATFORM_RPI) - graphics_get_display_size(0, &CORE.Window.display.width, &CORE.Window.display.height); + graphics_get_display_size(0, &CORE.Window[CORE.currentWindow].display.width, &CORE.Window[CORE.currentWindow].display.height); // Screen size security check - if (CORE.Window.screen.width <= 0) CORE.Window.screen.width = CORE.Window.display.width; - if (CORE.Window.screen.height <= 0) CORE.Window.screen.height = CORE.Window.display.height; + if (CORE.Window[CORE.currentWindow].screen.width <= 0) CORE.Window[CORE.currentWindow].screen.width = CORE.Window[CORE.currentWindow].display.width; + if (CORE.Window[CORE.currentWindow].screen.height <= 0) CORE.Window[CORE.currentWindow].screen.height = CORE.Window[CORE.currentWindow].display.height; // At this point we need to manage render size vs screen size - // NOTE: This function use and modify global module variables: - // -> CORE.Window.screen.width/CORE.Window.screen.height - // -> CORE.Window.render.width/CORE.Window.render.height - // -> CORE.Window.screenScale - SetupFramebuffer(CORE.Window.display.width, CORE.Window.display.height); + // NOTE: This function use and modify global module variables: CORE.Window[CORE.currentWindow].screen.width/CORE.Window[CORE.currentWindow].screen.height and CORE.Window[CORE.currentWindow].render.width/CORE.Window[CORE.currentWindow].render.height and CORE.Window[CORE.currentWindow].screenScale + SetupFramebuffer(CORE.Window[CORE.currentWindow].display.width, CORE.Window[CORE.currentWindow].display.height); dstRect.x = 0; dstRect.y = 0; - dstRect.width = CORE.Window.display.width; - dstRect.height = CORE.Window.display.height; + dstRect.width = CORE.Window[CORE.currentWindow].display.width; + dstRect.height = CORE.Window[CORE.currentWindow].display.height; srcRect.x = 0; srcRect.y = 0; - srcRect.width = CORE.Window.render.width << 16; - srcRect.height = CORE.Window.render.height << 16; + srcRect.width = CORE.Window[CORE.currentWindow].render.width << 16; + srcRect.height = CORE.Window[CORE.currentWindow].render.height << 16; // NOTE: RPI dispmanx windowing system takes care of srcRec scaling to dstRec by hardware (no cost) // Take care that renderWidth/renderHeight fit on displayWidth/displayHeight aspect ratio @@ -3209,19 +3216,19 @@ static bool InitGraphicsDevice(int width, int height) dispmanElement = vc_dispmanx_element_add(dispmanUpdate, dispmanDisplay, 0/*layer*/, &dstRect, 0/*src*/, &srcRect, DISPMANX_PROTECTION_NONE, &alpha, 0/*clamp*/, DISPMANX_NO_ROTATE); - CORE.Window.handle.element = dispmanElement; - CORE.Window.handle.width = CORE.Window.render.width; - CORE.Window.handle.height = CORE.Window.render.height; + CORE.Window[CORE.currentWindow].handle.element = dispmanElement; + CORE.Window[CORE.currentWindow].handle.width = CORE.Window[CORE.currentWindow].render.width; + CORE.Window[CORE.currentWindow].handle.height = CORE.Window[CORE.currentWindow].render.height; vc_dispmanx_update_submit_sync(dispmanUpdate); - CORE.Window.surface = eglCreateWindowSurface(CORE.Window.device, CORE.Window.config, &CORE.Window.handle, NULL); + CORE.Window[CORE.currentWindow].surface = eglCreateWindowSurface(CORE.Window[CORE.currentWindow].device, CORE.Window[CORE.currentWindow].config, &CORE.Window[CORE.currentWindow].handle, NULL); //--------------------------------------------------------------------------------- #endif // PLATFORM_RPI // There must be at least one frame displayed before the buffers are swapped - //eglSwapInterval(CORE.Window.device, 1); + //eglSwapInterval(CORE.Window[CORE.currentWindow].device, 1); - if (eglMakeCurrent(CORE.Window.device, CORE.Window.surface, CORE.Window.surface, CORE.Window.context) == EGL_FALSE) + if (eglMakeCurrent(CORE.Window[CORE.currentWindow].device, CORE.Window[CORE.currentWindow].surface, CORE.Window[CORE.currentWindow].surface, CORE.Window[CORE.currentWindow].context) == EGL_FALSE) { TRACELOG(LOG_WARNING, "DISPLAY: Failed to attach EGL rendering context to EGL surface"); return false; @@ -3229,40 +3236,42 @@ static bool InitGraphicsDevice(int width, int height) else { TRACELOG(LOG_INFO, "DISPLAY: Device initialized successfully"); - TRACELOG(LOG_INFO, " > Display size: %i x %i", CORE.Window.display.width, CORE.Window.display.height); - TRACELOG(LOG_INFO, " > Render size: %i x %i", CORE.Window.render.width, CORE.Window.render.height); - TRACELOG(LOG_INFO, " > Screen size: %i x %i", CORE.Window.screen.width, CORE.Window.screen.height); - TRACELOG(LOG_INFO, " > Viewport offsets: %i, %i", CORE.Window.renderOffset.x, CORE.Window.renderOffset.y); + TRACELOG(LOG_INFO, " > Display size: %i x %i", CORE.Window[CORE.currentWindow].display.width, CORE.Window[CORE.currentWindow].display.height); + TRACELOG(LOG_INFO, " > Render size: %i x %i", CORE.Window[CORE.currentWindow].render.width, CORE.Window[CORE.currentWindow].render.height); + TRACELOG(LOG_INFO, " > Screen size: %i x %i", CORE.Window[CORE.currentWindow].screen.width, CORE.Window[CORE.currentWindow].screen.height); + TRACELOG(LOG_INFO, " > Viewport offsets: %i, %i", CORE.Window[CORE.currentWindow].renderOffset.x, CORE.Window[CORE.currentWindow].renderOffset.y); } -#endif // PLATFORM_ANDROID || PLATFORM_RPI || defined(PLATFORM_UWP) - +#endif // PLATFORM_ANDROID || PLATFORM_RPI + rlSetContext(CORE.currentWindow); // Initialize OpenGL context (states and resources) - // NOTE: CORE.Window.screen.width and CORE.Window.screen.height not used, just stored as globals in rlgl - rlglInit(CORE.Window.screen.width, CORE.Window.screen.height); + // NOTE: CORE.Window[CORE.currentWindow].screen.width and CORE.Window[CORE.currentWindow].screen.height not used, just stored as globals in rlgl + rlglInit(CORE.Window[CORE.currentWindow].screen.width, CORE.Window[CORE.currentWindow].screen.height); - int fbWidth = CORE.Window.render.width; - int fbHeight = CORE.Window.render.height; + int fbWidth = CORE.Window[CORE.currentWindow].render.width; + int fbHeight = CORE.Window[CORE.currentWindow].render.height; #if defined(PLATFORM_DESKTOP) && defined(SUPPORT_HIGH_DPI) - glfwGetFramebufferSize(CORE.Window.handle, &fbWidth, &fbHeight); + glfwGetFramebufferSize(CORE.Window[CORE.currentWindow].handle, &fbWidth, &fbHeight); // Screen scaling matrix is required in case desired screen area is different than display area - CORE.Window.screenScale = MatrixScale((float)fbWidth/CORE.Window.screen.width, (float)fbHeight/CORE.Window.screen.height, 1.0f); + CORE.Window[CORE.currentWindow].screenScale = MatrixScale((float)fbWidth/CORE.Window[CORE.currentWindow].screen.width, (float)fbHeight/CORE.Window[CORE.currentWindow].screen.height, 1.0f); #if !defined(__APPLE__) - SetMouseScale((float)CORE.Window.screen.width/fbWidth, (float)CORE.Window.screen.height/fbHeight); + SetMouseScale((float)CORE.Window[CORE.currentWindow].screen.width/fbWidth, (float)CORE.Window[CORE.currentWindow].screen.height/fbHeight); #endif #endif // PLATFORM_DESKTOP && SUPPORT_HIGH_DPI // Setup default viewport SetupViewport(fbWidth, fbHeight); - CORE.Window.currentFbo.width = CORE.Window.screen.width; - CORE.Window.currentFbo.height = CORE.Window.screen.height; - + //for (CORE.currentWindow = 0; CORE.currentWindow < 2; CORE.currentWindow++) + { + CORE.Window[CORE.currentWindow].currentFbo.width = CORE.Window[CORE.currentWindow].screen.width; + CORE.Window[CORE.currentWindow].currentFbo.height = CORE.Window[CORE.currentWindow].screen.height; + } ClearBackground(RAYWHITE); // Default background color for raylib games :P #if defined(PLATFORM_ANDROID) || defined(PLATFORM_UWP) - CORE.Window.ready = true; + CORE.Window[CORE.currentWindow].ready = true; #endif return true; } @@ -3270,94 +3279,94 @@ static bool InitGraphicsDevice(int width, int height) // Set viewport for a provided width and height static void SetupViewport(int width, int height) { - CORE.Window.render.width = width; - CORE.Window.render.height = height; + CORE.Window[CORE.currentWindow].render.width = width; + CORE.Window[CORE.currentWindow].render.height = height; // Set viewport width and height // NOTE: We consider render size and offset in case black bars are required and // render area does not match full display area (this situation is only applicable on fullscreen mode) - rlViewport(CORE.Window.renderOffset.x/2, CORE.Window.renderOffset.y/2, CORE.Window.render.width - CORE.Window.renderOffset.x, CORE.Window.render.height - CORE.Window.renderOffset.y); + rlViewport(CORE.Window[CORE.currentWindow].renderOffset.x/2, CORE.Window[CORE.currentWindow].renderOffset.y/2, CORE.Window[CORE.currentWindow].render.width - CORE.Window[CORE.currentWindow].renderOffset.x, CORE.Window[CORE.currentWindow].render.height - CORE.Window[CORE.currentWindow].renderOffset.y); rlMatrixMode(RL_PROJECTION); // Switch to projection matrix rlLoadIdentity(); // Reset current matrix (projection) // Set orthographic projection to current framebuffer size // NOTE: Configured top-left corner as (0, 0) - rlOrtho(0, CORE.Window.render.width, CORE.Window.render.height, 0, 0.0f, 1.0f); + rlOrtho(0, CORE.Window[CORE.currentWindow].render.width, CORE.Window[CORE.currentWindow].render.height, 0, 0.0f, 1.0f); rlMatrixMode(RL_MODELVIEW); // Switch back to modelview matrix rlLoadIdentity(); // Reset current matrix (modelview) } // Compute framebuffer size relative to screen size and display size -// NOTE: Global variables CORE.Window.render.width/CORE.Window.render.height and CORE.Window.renderOffset.x/CORE.Window.renderOffset.y can be modified +// NOTE: Global variables CORE.Window[CORE.currentWindow].render.width/CORE.Window[CORE.currentWindow].render.height and CORE.Window[CORE.currentWindow].renderOffset.x/CORE.Window[CORE.currentWindow].renderOffset.y can be modified static void SetupFramebuffer(int width, int height) { - // Calculate CORE.Window.render.width and CORE.Window.render.height, we have the display size (input params) and the desired screen size (global var) - if ((CORE.Window.screen.width > CORE.Window.display.width) || (CORE.Window.screen.height > CORE.Window.display.height)) + // Calculate CORE.Window[CORE.currentWindow].render.width and CORE.Window[CORE.currentWindow].render.height, we have the display size (input params) and the desired screen size (global var) + if ((CORE.Window[CORE.currentWindow].screen.width > CORE.Window[CORE.currentWindow].display.width) || (CORE.Window[CORE.currentWindow].screen.height > CORE.Window[CORE.currentWindow].display.height)) { - TRACELOG(LOG_WARNING, "DISPLAY: Downscaling required: Screen size (%ix%i) is bigger than display size (%ix%i)", CORE.Window.screen.width, CORE.Window.screen.height, CORE.Window.display.width, CORE.Window.display.height); + TRACELOG(LOG_WARNING, "DISPLAY: Downscaling required: Screen size (%ix%i) is bigger than display size (%ix%i)", CORE.Window[CORE.currentWindow].screen.width, CORE.Window[CORE.currentWindow].screen.height, CORE.Window[CORE.currentWindow].display.width, CORE.Window[CORE.currentWindow].display.height); // Downscaling to fit display with border-bars - float widthRatio = (float)CORE.Window.display.width/(float)CORE.Window.screen.width; - float heightRatio = (float)CORE.Window.display.height/(float)CORE.Window.screen.height; + float widthRatio = (float)CORE.Window[CORE.currentWindow].display.width/(float)CORE.Window[CORE.currentWindow].screen.width; + float heightRatio = (float)CORE.Window[CORE.currentWindow].display.height/(float)CORE.Window[CORE.currentWindow].screen.height; if (widthRatio <= heightRatio) { - CORE.Window.render.width = CORE.Window.display.width; - CORE.Window.render.height = (int)round((float)CORE.Window.screen.height*widthRatio); - CORE.Window.renderOffset.x = 0; - CORE.Window.renderOffset.y = (CORE.Window.display.height - CORE.Window.render.height); + CORE.Window[CORE.currentWindow].render.width = CORE.Window[CORE.currentWindow].display.width; + CORE.Window[CORE.currentWindow].render.height = (int)round((float)CORE.Window[CORE.currentWindow].screen.height*widthRatio); + CORE.Window[CORE.currentWindow].renderOffset.x = 0; + CORE.Window[CORE.currentWindow].renderOffset.y = (CORE.Window[CORE.currentWindow].display.height - CORE.Window[CORE.currentWindow].render.height); } else { - CORE.Window.render.width = (int)round((float)CORE.Window.screen.width*heightRatio); - CORE.Window.render.height = CORE.Window.display.height; - CORE.Window.renderOffset.x = (CORE.Window.display.width - CORE.Window.render.width); - CORE.Window.renderOffset.y = 0; + CORE.Window[CORE.currentWindow].render.width = (int)round((float)CORE.Window[CORE.currentWindow].screen.width*heightRatio); + CORE.Window[CORE.currentWindow].render.height = CORE.Window[CORE.currentWindow].display.height; + CORE.Window[CORE.currentWindow].renderOffset.x = (CORE.Window[CORE.currentWindow].display.width - CORE.Window[CORE.currentWindow].render.width); + CORE.Window[CORE.currentWindow].renderOffset.y = 0; } // Screen scaling required - float scaleRatio = (float)CORE.Window.render.width/(float)CORE.Window.screen.width; - CORE.Window.screenScale = MatrixScale(scaleRatio, scaleRatio, 1.0f); + float scaleRatio = (float)CORE.Window[CORE.currentWindow].render.width/(float)CORE.Window[CORE.currentWindow].screen.width; + CORE.Window[CORE.currentWindow].screenScale = MatrixScale(scaleRatio, scaleRatio, 1.0f); // NOTE: We render to full display resolution! // We just need to calculate above parameters for downscale matrix and offsets - CORE.Window.render.width = CORE.Window.display.width; - CORE.Window.render.height = CORE.Window.display.height; + CORE.Window[CORE.currentWindow].render.width = CORE.Window[CORE.currentWindow].display.width; + CORE.Window[CORE.currentWindow].render.height = CORE.Window[CORE.currentWindow].display.height; - TRACELOG(LOG_WARNING, "DISPLAY: Downscale matrix generated, content will be rendered at (%ix%i)", CORE.Window.render.width, CORE.Window.render.height); + TRACELOG(LOG_WARNING, "DISPLAY: Downscale matrix generated, content will be rendered at (%ix%i)", CORE.Window[CORE.currentWindow].render.width, CORE.Window[CORE.currentWindow].render.height); } - else if ((CORE.Window.screen.width < CORE.Window.display.width) || (CORE.Window.screen.height < CORE.Window.display.height)) + else if ((CORE.Window[CORE.currentWindow].screen.width < CORE.Window[CORE.currentWindow].display.width) || (CORE.Window[CORE.currentWindow].screen.height < CORE.Window[CORE.currentWindow].display.height)) { // Required screen size is smaller than display size - TRACELOG(LOG_INFO, "DISPLAY: Upscaling required: Screen size (%ix%i) smaller than display size (%ix%i)", CORE.Window.screen.width, CORE.Window.screen.height, CORE.Window.display.width, CORE.Window.display.height); + TRACELOG(LOG_INFO, "DISPLAY: Upscaling required: Screen size (%ix%i) smaller than display size (%ix%i)", CORE.Window[CORE.currentWindow].screen.width, CORE.Window[CORE.currentWindow].screen.height, CORE.Window[CORE.currentWindow].display.width, CORE.Window[CORE.currentWindow].display.height); // Upscaling to fit display with border-bars - float displayRatio = (float)CORE.Window.display.width/(float)CORE.Window.display.height; - float screenRatio = (float)CORE.Window.screen.width/(float)CORE.Window.screen.height; + float displayRatio = (float)CORE.Window[CORE.currentWindow].display.width/(float)CORE.Window[CORE.currentWindow].display.height; + float screenRatio = (float)CORE.Window[CORE.currentWindow].screen.width/(float)CORE.Window[CORE.currentWindow].screen.height; if (displayRatio <= screenRatio) { - CORE.Window.render.width = CORE.Window.screen.width; - CORE.Window.render.height = (int)round((float)CORE.Window.screen.width/displayRatio); - CORE.Window.renderOffset.x = 0; - CORE.Window.renderOffset.y = (CORE.Window.render.height - CORE.Window.screen.height); + CORE.Window[CORE.currentWindow].render.width = CORE.Window[CORE.currentWindow].screen.width; + CORE.Window[CORE.currentWindow].render.height = (int)round((float)CORE.Window[CORE.currentWindow].screen.width/displayRatio); + CORE.Window[CORE.currentWindow].renderOffset.x = 0; + CORE.Window[CORE.currentWindow].renderOffset.y = (CORE.Window[CORE.currentWindow].render.height - CORE.Window[CORE.currentWindow].screen.height); } else { - CORE.Window.render.width = (int)round((float)CORE.Window.screen.height*displayRatio); - CORE.Window.render.height = CORE.Window.screen.height; - CORE.Window.renderOffset.x = (CORE.Window.render.width - CORE.Window.screen.width); - CORE.Window.renderOffset.y = 0; + CORE.Window[CORE.currentWindow].render.width = (int)round((float)CORE.Window[CORE.currentWindow].screen.height*displayRatio); + CORE.Window[CORE.currentWindow].render.height = CORE.Window[CORE.currentWindow].screen.height; + CORE.Window[CORE.currentWindow].renderOffset.x = (CORE.Window[CORE.currentWindow].render.width - CORE.Window[CORE.currentWindow].screen.width); + CORE.Window[CORE.currentWindow].renderOffset.y = 0; } } else { - CORE.Window.render.width = CORE.Window.screen.width; - CORE.Window.render.height = CORE.Window.screen.height; - CORE.Window.renderOffset.x = 0; - CORE.Window.renderOffset.y = 0; + CORE.Window[CORE.currentWindow].render.width = CORE.Window[CORE.currentWindow].screen.width; + CORE.Window[CORE.currentWindow].render.height = CORE.Window[CORE.currentWindow].screen.height; + CORE.Window[CORE.currentWindow].renderOffset.x = 0; + CORE.Window[CORE.currentWindow].renderOffset.y = 0; } } @@ -3618,7 +3627,7 @@ static void PollInputEvents(void) } } - CORE.Window.resized = false; + CORE.Window[CORE.currentWindow].resized = false; #if defined(SUPPORT_EVENTS_WAITING) glfwWaitEvents(); @@ -3689,7 +3698,7 @@ static void PollInputEvents(void) // NOTE: Never close window, native activity is controlled by the system! if (CORE.Android.app->destroyRequested != 0) { - //CORE.Window.shouldClose = true; + //CORE.Window[CORE.currentWindow].shouldClose = true; //ANativeActivity_finish(CORE.Android.app->activity); } } @@ -3709,11 +3718,11 @@ static void PollInputEvents(void) static void SwapBuffers(void) { #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) - glfwSwapBuffers(CORE.Window.handle); + glfwSwapBuffers(CORE.Window[CORE.currentWindow].handle); #endif #if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) || defined(PLATFORM_UWP) - eglSwapBuffers(CORE.Window.device, CORE.Window.surface); + eglSwapBuffers(CORE.Window[CORE.currentWindow].device, CORE.Window[CORE.currentWindow].surface); #endif } @@ -3735,7 +3744,7 @@ static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, i { if (key == CORE.Input.Keyboard.exitKey && action == GLFW_PRESS) { - glfwSetWindowShouldClose(CORE.Window.handle, GLFW_TRUE); + glfwSetWindowShouldClose(CORE.Window[CORE.currentWindow].handle, GLFW_TRUE); // NOTE: Before closing window, while loop must be left! } @@ -3772,7 +3781,7 @@ static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, i // NOTE: delay represents the time between frames in the gif, if we capture a gif frame every // 10 game frames and each frame trakes 16.6ms (60fps), delay between gif frames should be ~16.6*10. - GifBegin(path, CORE.Window.screen.width, CORE.Window.screen.height, (int)(GetFrameTime()*10.0f), 8, false); + GifBegin(path, CORE.Window[CORE.currentWindow].screen.width, CORE.Window[CORE.currentWindow].screen.height, (int)(GetFrameTime()*10.0f), 8, false); screenshotCounter++; TRACELOG(LOG_INFO, "SYSTEM: Start animated GIF recording: %s", TextFormat("screenrec%03i.gif", screenshotCounter)); @@ -3822,7 +3831,7 @@ static void MouseButtonCallback(GLFWwindow *window, int button, int action, int // Register touch points position, only one point registered gestureEvent.position[0] = GetMousePosition(); - // Normalize gestureEvent.position[0] for CORE.Window.screen.width and CORE.Window.screen.height + // Normalize gestureEvent.position[0] for CORE.Window[CORE.currentWindow].screen.width and CORE.Window[CORE.currentWindow].screen.height gestureEvent.position[0].x /= (float)GetScreenWidth(); gestureEvent.position[0].y /= (float)GetScreenHeight(); @@ -3853,7 +3862,7 @@ static void MouseCursorPosCallback(GLFWwindow *window, double x, double y) // Register touch points position, only one point registered gestureEvent.position[0] = CORE.Input.Touch.position[0]; - // Normalize gestureEvent.position[0] for CORE.Window.screen.width and CORE.Window.screen.height + // Normalize gestureEvent.position[0] for CORE.Window[CORE.currentWindow].screen.width and CORE.Window[CORE.currentWindow].screen.height gestureEvent.position[0].x /= (float)GetScreenWidth(); gestureEvent.position[0].y /= (float)GetScreenHeight(); @@ -3893,28 +3902,28 @@ static void WindowSizeCallback(GLFWwindow *window, int width, int height) SetupViewport(width, height); // Reset viewport and projection matrix for new size // Set current screen size - CORE.Window.screen.width = width; - CORE.Window.screen.height = height; - CORE.Window.currentFbo.width = width; - CORE.Window.currentFbo.height = height; + CORE.Window[CORE.currentWindow].screen.width = width; + CORE.Window[CORE.currentWindow].screen.height = height; + CORE.Window[CORE.currentWindow].currentFbo.width = width; + CORE.Window[CORE.currentWindow].currentFbo.height = height; // NOTE: Postprocessing texture is not scaled to new size - CORE.Window.resized = true; + CORE.Window[CORE.currentWindow].resized = true; } // GLFW3 WindowIconify Callback, runs when window is minimized/restored static void WindowIconifyCallback(GLFWwindow *window, int iconified) { - if (iconified) CORE.Window.minimized = true; // The window was iconified - else CORE.Window.minimized = false; // The window was restored + if (iconified) CORE.Window[CORE.currentWindow].minimized = true; // The window was iconified + else CORE.Window[CORE.currentWindow].minimized = false; // The window was restored } // GLFW3 WindowFocus Callback, runs when window get/lose focus static void WindowFocusCallback(GLFWwindow *window, int focused) { - if (focused) CORE.Window.focused = true; // The window was focused - else CORE.Window.focused = false; // The window lost focus + if (focused) CORE.Window[CORE.currentWindow].focused = true; // The window was focused + else CORE.Window[CORE.currentWindow].focused = false; // The window lost focus } // GLFW3 Window Drop Callback, runs when drop files into window @@ -3924,15 +3933,15 @@ static void WindowDropCallback(GLFWwindow *window, int count, const char **paths { ClearDroppedFiles(); - CORE.Window.dropFilesPath = (char **)RL_MALLOC(sizeof(char *)*count); + CORE.Window[CORE.currentWindow].dropFilesPath = (char **)RL_MALLOC(sizeof(char *)*count); for (int i = 0; i < count; i++) { - CORE.Window.dropFilesPath[i] = (char *)RL_MALLOC(sizeof(char)*MAX_FILEPATH_LENGTH); - strcpy(CORE.Window.dropFilesPath[i], paths[i]); + CORE.Window[CORE.currentWindow].dropFilesPath[i] = (char *)RL_MALLOC(sizeof(char)*MAX_FILEPATH_LENGTH); + strcpy(CORE.Window[CORE.currentWindow].dropFilesPath[i], paths[i]); } - CORE.Window.dropFilesCount = count; + CORE.Window[CORE.currentWindow].dropFilesCount = count; } #endif @@ -3955,22 +3964,22 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd) { // Reset screen scaling to full display size EGLint displayFormat; - eglGetConfigAttrib(CORE.Window.device, CORE.Window.config, EGL_NATIVE_VISUAL_ID, &displayFormat); - ANativeWindow_setBuffersGeometry(app->window, CORE.Window.render.width, CORE.Window.render.height, displayFormat); + eglGetConfigAttrib(CORE.Window[CORE.currentWindow].device, CORE.Window[CORE.currentWindow].config, EGL_NATIVE_VISUAL_ID, &displayFormat); + ANativeWindow_setBuffersGeometry(app->window, CORE.Window[CORE.currentWindow].render.width, CORE.Window[CORE.currentWindow].render.height, displayFormat); // Recreate display surface and re-attach OpenGL context - CORE.Window.surface = eglCreateWindowSurface(CORE.Window.device, CORE.Window.config, app->window, NULL); - eglMakeCurrent(CORE.Window.device, CORE.Window.surface, CORE.Window.surface, CORE.Window.context); + CORE.Window[CORE.currentWindow].surface = eglCreateWindowSurface(CORE.Window[CORE.currentWindow].device, CORE.Window[CORE.currentWindow].config, app->window, NULL); + eglMakeCurrent(CORE.Window[CORE.currentWindow].device, CORE.Window[CORE.currentWindow].surface, CORE.Window[CORE.currentWindow].surface, CORE.Window[CORE.currentWindow].context); CORE.Android.contextRebindRequired = false; } else { - CORE.Window.display.width = ANativeWindow_getWidth(CORE.Android.app->window); - CORE.Window.display.height = ANativeWindow_getHeight(CORE.Android.app->window); + CORE.Window[CORE.currentWindow].display.width = ANativeWindow_getWidth(CORE.Android.app->window); + CORE.Window[CORE.currentWindow].display.height = ANativeWindow_getHeight(CORE.Android.app->window); // Init graphics device (display device and OpenGL context) - InitGraphicsDevice(CORE.Window.screen.width, CORE.Window.screen.height); + InitGraphicsDevice(CORE.Window[CORE.currentWindow].screen.width, CORE.Window[CORE.currentWindow].screen.height); // Init hi-res timer InitTimer(); @@ -4017,8 +4026,8 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd) // Dettach OpenGL context and destroy display surface // NOTE 1: Detaching context before destroying display surface avoids losing our resources (textures, shaders, VBOs...) // NOTE 2: In some cases (too many context loaded), OS could unload context automatically... :( - eglMakeCurrent(CORE.Window.device, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - eglDestroySurface(CORE.Window.device, CORE.Window.surface); + eglMakeCurrent(CORE.Window[CORE.currentWindow].device, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + eglDestroySurface(CORE.Window[CORE.currentWindow].device, CORE.Window[CORE.currentWindow].surface); CORE.Android.contextRebindRequired = true; } break; @@ -4186,12 +4195,12 @@ static EM_BOOL EmscriptenFullscreenChangeCallback(int eventType, const Emscripte /* if (event->isFullscreen) { - CORE.Window.fullscreen = true; + CORE.Window[CORE.currentWindow].fullscreen = true; TRACELOG(LOG_INFO, "WEB: Canvas scaled to fullscreen. ElementSize: (%ix%i), ScreenSize(%ix%i)", event->elementWidth, event->elementHeight, event->screenWidth, event->screenHeight); } else { - CORE.Window.fullscreen = false; + CORE.Window[CORE.currentWindow].fullscreen = false; TRACELOG(LOG_INFO, "WEB: Canvas scaled to windowed. ElementSize: (%ix%i), ScreenSize(%ix%i)", event->elementWidth, event->elementHeight, event->screenWidth, event->screenHeight); } @@ -4208,8 +4217,8 @@ static EM_BOOL EmscriptenKeyboardCallback(int eventType, const EmscriptenKeyboar // WARNING: Not executed when pressing Esc to exit fullscreen, it seems document has priority over #canvas emscripten_exit_pointerlock(); - CORE.Window.fullscreen = false; - TRACELOG(LOG_INFO, "CORE.Window.fullscreen = %s", CORE.Window.fullscreen? "true" : "false"); + CORE.Window[CORE.currentWindow].fullscreen = false; + TRACELOG(LOG_INFO, "CORE.Window[CORE.currentWindow].fullscreen = %s", CORE.Window[CORE.currentWindow].fullscreen? "true" : "false"); } return 0; @@ -4272,7 +4281,7 @@ static EM_BOOL EmscriptenTouchCallback(int eventType, const EmscriptenTouchEvent //EMSCRIPTEN_RESULT res = emscripten_get_canvas_element_size("#canvas", &canvasWidth, &canvasHeight); emscripten_get_element_css_size("#canvas", &canvasWidth, &canvasHeight); - // Normalize gestureEvent.position[x] for CORE.Window.screen.width and CORE.Window.screen.height + // Normalize gestureEvent.position[x] for CORE.Window[CORE.currentWindow].screen.width and CORE.Window[CORE.currentWindow].screen.height gestureEvent.position[0].x *= ((float)GetScreenWidth()/(float)canvasWidth); gestureEvent.position[0].y *= ((float)GetScreenHeight()/(float)canvasHeight); gestureEvent.position[1].x *= ((float)GetScreenWidth()/(float)canvasWidth); @@ -4485,7 +4494,7 @@ static void ProcessKeyboard(void) } // Check exit key (same functionality as GLFW3 KeyCallback()) - if (CORE.Input.Keyboard.currentKeyState[CORE.Input.Keyboard.exitKey] == 1) CORE.Window.shouldClose = true; + if (CORE.Input.Keyboard.currentKeyState[CORE.Input.Keyboard.exitKey] == 1) CORE.Window[CORE.currentWindow].shouldClose = true; #if defined(SUPPORT_SCREEN_CAPTURE) // Check screen capture key (raylib key: KEY_F12) @@ -4774,7 +4783,7 @@ static void *EventThread(void *arg) bool gestureUpdate = false; int keycode; - while (!CORE.Window.shouldClose) + while (!CORE.Window[CORE.currentWindow].shouldClose) { // Try to read data from the device and only continue if successful if (read(worker->fd, &event, sizeof(event)) == (int)sizeof(event)) @@ -4813,7 +4822,7 @@ static void *EventThread(void *arg) // Basic movement if (event.code == ABS_X) { - CORE.Input.Mouse.position.x = (event.value - worker->absRange.x)*CORE.Window.screen.width/worker->absRange.width; // Scale acording to absRange + CORE.Input.Mouse.position.x = (event.value - worker->absRange.x)*CORE.Window[CORE.currentWindow].screen.width/worker->absRange.width; // Scale acording to absRange #if defined(SUPPORT_GESTURES_SYSTEM) touchAction = TOUCH_MOVE; @@ -4823,7 +4832,7 @@ static void *EventThread(void *arg) if (event.code == ABS_Y) { - CORE.Input.Mouse.position.y = (event.value - worker->absRange.y)*CORE.Window.screen.height/worker->absRange.height; // Scale acording to absRange + CORE.Input.Mouse.position.y = (event.value - worker->absRange.y)*CORE.Window[CORE.currentWindow].screen.height/worker->absRange.height; // Scale acording to absRange #if defined(SUPPORT_GESTURES_SYSTEM) touchAction = TOUCH_MOVE; @@ -4836,12 +4845,12 @@ static void *EventThread(void *arg) if (event.code == ABS_MT_POSITION_X) { - if (worker->touchSlot < MAX_TOUCH_POINTS) CORE.Input.Touch.position[worker->touchSlot].x = (event.value - worker->absRange.x)*CORE.Window.screen.width/worker->absRange.width; // Scale acording to absRange + if (worker->touchSlot < MAX_TOUCH_POINTS) CORE.Input.Touch.position[worker->touchSlot].x = (event.value - worker->absRange.x)*CORE.Window[CORE.currentWindow].screen.width/worker->absRange.width; // Scale acording to absRange } if (event.code == ABS_MT_POSITION_Y) { - if (worker->touchSlot < MAX_TOUCH_POINTS) CORE.Input.Touch.position[worker->touchSlot].y = (event.value - worker->absRange.y)*CORE.Window.screen.height/worker->absRange.height; // Scale acording to absRange + if (worker->touchSlot < MAX_TOUCH_POINTS) CORE.Input.Touch.position[worker->touchSlot].y = (event.value - worker->absRange.y)*CORE.Window[CORE.currentWindow].screen.height/worker->absRange.height; // Scale acording to absRange } if (event.code == ABS_MT_TRACKING_ID) @@ -4900,7 +4909,7 @@ static void *EventThread(void *arg) } #endif - if (CORE.Input.Keyboard.currentKeyState[CORE.Input.Keyboard.exitKey] == 1) CORE.Window.shouldClose = true; + if (CORE.Input.Keyboard.currentKeyState[CORE.Input.Keyboard.exitKey] == 1) CORE.Window[CORE.currentWindow].shouldClose = true; TRACELOGD("RPI: KEY_%s ScanCode: %4i KeyCode: %4i", event.value == 0 ? "UP":"DOWN", event.code, keycode); } @@ -4909,10 +4918,10 @@ static void *EventThread(void *arg) // Screen confinement if (CORE.Input.Mouse.position.x < 0) CORE.Input.Mouse.position.x = 0; - if (CORE.Input.Mouse.position.x > CORE.Window.screen.width/CORE.Input.Mouse.scale.x) CORE.Input.Mouse.position.x = CORE.Window.screen.width/CORE.Input.Mouse.scale.x; + if (CORE.Input.Mouse.position.x > CORE.Window[CORE.currentWindow].screen.width/CORE.Input.Mouse.scale.x) CORE.Input.Mouse.position.x = CORE.Window[CORE.currentWindow].screen.width/CORE.Input.Mouse.scale.x; if (CORE.Input.Mouse.position.y < 0) CORE.Input.Mouse.position.y = 0; - if (CORE.Input.Mouse.position.y > CORE.Window.screen.height/CORE.Input.Mouse.scale.y) CORE.Input.Mouse.position.y = CORE.Window.screen.height/CORE.Input.Mouse.scale.y; + if (CORE.Input.Mouse.position.y > CORE.Window[CORE.currentWindow].screen.height/CORE.Input.Mouse.scale.y) CORE.Input.Mouse.position.y = CORE.Window[CORE.currentWindow].screen.height/CORE.Input.Mouse.scale.y; // Gesture update if (gestureUpdate) @@ -4997,7 +5006,7 @@ static void *GamepadThread(void *arg) // Read gamepad event struct js_event gamepadEvent; - while (!CORE.Window.shouldClose) + while (!CORE.Window[CORE.currentWindow].shouldClose) { for (int i = 0; i < MAX_GAMEPADS; i++) { @@ -5097,7 +5106,7 @@ void UWPKeyDownEvent(int key, bool down, bool controlKey) if (key == CORE.Input.Keyboard.exitKey && down) { // Time to close the window. - CORE.Window.shouldClose = true; + CORE.Window[CORE.currentWindow].shouldClose = true; } else if (key == KEY_F12 && down) { @@ -5127,7 +5136,7 @@ void UWPKeyDownEvent(int key, bool down, bool controlKey) // NOTE: delay represents the time between frames in the gif, if we capture a gif frame every // 10 game frames and each frame trakes 16.6ms (60fps), delay between gif frames should be ~16.6*10. - GifBegin(path, CORE.Window.screen.width, CORE.Window.screen.height, (int)(GetFrameTime() * 10.0f), 8, false); + GifBegin(path, CORE.Window[CORE.currentWindow].screen.width, CORE.Window[CORE.currentWindow].screen.height, (int)(GetFrameTime() * 10.0f), 8, false); screenshotCounter++; TRACELOG(LOG_INFO, "SYSTEM: Start animated GIF recording: %s", TextFormat("screenrec%03i.gif", screenshotCounter)); @@ -5181,7 +5190,7 @@ void UWPMouseButtonEvent(int button, bool down) // Register touch points position, only one point registered gestureEvent.position[0] = GetMousePosition(); - // Normalize gestureEvent.position[0] for CORE.Window.screen.width and CORE.Window.screen.height + // Normalize gestureEvent.position[0] for CORE.Window[CORE.currentWindow].screen.width and CORE.Window[CORE.currentWindow].screen.height gestureEvent.position[0].x /= (float)GetScreenWidth(); gestureEvent.position[0].y /= (float)GetScreenHeight(); @@ -5211,7 +5220,7 @@ void UWPMousePosEvent(double x, double y) // Register touch points position, only one point registered gestureEvent.position[0] = CORE.Input.Mouse.position; - // Normalize gestureEvent.position[0] for CORE.Window.screen.width and CORE.Window.screen.height + // Normalize gestureEvent.position[0] for CORE.Window[CORE.currentWindow].screen.width and CORE.Window[CORE.currentWindow].screen.height gestureEvent.position[0].x /= (float)GetScreenWidth(); gestureEvent.position[0].y /= (float)GetScreenHeight(); @@ -5225,14 +5234,14 @@ void UWPResizeEvent(int width, int height) SetupViewport(width, height); // Reset viewport and projection matrix for new size // Set current screen size - CORE.Window.screen.width = width; - CORE.Window.screen.height = height; - CORE.Window.currentFbo.width = width; - CORE.Window.currentFbo.height = height; + CORE.Window[CORE.currentWindow].screen.width = width; + CORE.Window[CORE.currentWindow].screen.height = height; + CORE.Window[CORE.currentWindow].currentFbo.width = width; + CORE.Window[CORE.currentWindow].currentFbo.height = height; // NOTE: Postprocessing texture is not scaled to new size - CORE.Window.resized = true; + CORE.Window[CORE.currentWindow].resized = true; } void UWPActivateGamepadEvent(int gamepad, bool active) @@ -5276,7 +5285,7 @@ void UWPGestureMove(int pointer, float x, float y) gestureEvent.position[0].x = x; gestureEvent.position[0].y = y; - // Normalize gestureEvent.position[0] for CORE.Window.screen.width and CORE.Window.screen.height + // Normalize gestureEvent.position[0] for CORE.Window[CORE.currentWindow].screen.width and CORE.Window[CORE.currentWindow].screen.height gestureEvent.position[0].x /= (float)GetScreenWidth(); gestureEvent.position[0].y /= (float)GetScreenHeight(); @@ -5301,7 +5310,7 @@ void UWPGestureTouch(int pointer, float x, float y, bool touch) gestureEvent.position[0].x = x; gestureEvent.position[0].y = y; - // Normalize gestureEvent.position[0] for CORE.Window.screen.width and CORE.Window.screen.height + // Normalize gestureEvent.position[0] for CORE.Window[CORE.currentWindow].screen.width and CORE.Window[CORE.currentWindow].screen.height gestureEvent.position[0].x /= (float)GetScreenWidth(); gestureEvent.position[0].y /= (float)GetScreenHeight(); diff --git a/src/raylib.h b/src/raylib.h index c9338e077cc4..aab4c875b3ef 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -158,7 +158,7 @@ #define ShowWindow UnhideWindow #define LoadText LoadFileText //#define Fade(c, a) ColorAlpha(c, a) - +#define MAX_CONTEXTS 2 //---------------------------------------------------------------------------------- // Structures Definition //---------------------------------------------------------------------------------- @@ -909,7 +909,7 @@ RLAPI bool IsCursorOnScreen(void); // Check if cu // Drawing-related functions RLAPI void ClearBackground(Color color); // Set background color (framebuffer clear color) -RLAPI void BeginDrawing(void); // Setup canvas (framebuffer) to start drawing +RLAPI void BeginDrawing(unsigned int contextID); // Setup canvas (framebuffer) to start drawing RLAPI void EndDrawing(void); // End canvas drawing and swap buffers (double buffering) RLAPI void BeginMode2D(Camera2D camera); // Initialize 2D mode with custom camera (2D) RLAPI void EndMode2D(void); // Ends 2D mode with custom camera diff --git a/src/rlgl.h b/src/rlgl.h index 9d6c85c75d15..bb876f744078 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -888,7 +888,9 @@ typedef struct rlglData { // Global Variables Definition //---------------------------------------------------------------------------------- #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) -static rlglData RLGL = { 0 }; +static rlglData RLGL[MAX_CONTEXTS]; +unsigned int currentContext = 0; +unsigned int numContexts = 0; #endif // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2 #if defined(GRAPHICS_API_OPENGL_ES2) @@ -969,52 +971,57 @@ void rlMultMatrixf(float *matf) { glMultMatrixf(matf); } #elif defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) +void rlSetContext(unsigned int c) +{ + currentContext = c; +} + // Choose the current matrix to be transformed void rlMatrixMode(int mode) { - if (mode == RL_PROJECTION) RLGL.State.currentMatrix = &RLGL.State.projection; - else if (mode == RL_MODELVIEW) RLGL.State.currentMatrix = &RLGL.State.modelview; + if (mode == RL_PROJECTION) RLGL[currentContext].State.currentMatrix = &RLGL[currentContext].State.projection; + else if (mode == RL_MODELVIEW) RLGL[currentContext].State.currentMatrix = &RLGL[currentContext].State.modelview; //else if (mode == RL_TEXTURE) // Not supported - RLGL.State.currentMatrixMode = mode; + RLGL[currentContext].State.currentMatrixMode = mode; } -// Push the current matrix into RLGL.State.stack +// Push the current matrix into RLGL[currentContext].State.stack void rlPushMatrix(void) { - if (RLGL.State.stackCounter >= MAX_MATRIX_STACK_SIZE) TRACELOG(LOG_ERROR, "RLGL: Matrix stack overflow (MAX_MATRIX_STACK_SIZE)"); + if (RLGL[currentContext].State.stackCounter >= MAX_MATRIX_STACK_SIZE) TRACELOG(LOG_ERROR, "RLGL: Matrix stack overflow (MAX_MATRIX_STACK_SIZE)"); - if (RLGL.State.currentMatrixMode == RL_MODELVIEW) + if (RLGL[currentContext].State.currentMatrixMode == RL_MODELVIEW) { - RLGL.State.transformRequired = true; - RLGL.State.currentMatrix = &RLGL.State.transform; + RLGL[currentContext].State.transformRequired = true; + RLGL[currentContext].State.currentMatrix = &RLGL[currentContext].State.transform; } - RLGL.State.stack[RLGL.State.stackCounter] = *RLGL.State.currentMatrix; - RLGL.State.stackCounter++; + RLGL[currentContext].State.stack[RLGL[currentContext].State.stackCounter] = *RLGL[currentContext].State.currentMatrix; + RLGL[currentContext].State.stackCounter++; } -// Pop lattest inserted matrix from RLGL.State.stack +// Pop lattest inserted matrix from RLGL[currentContext].State.stack void rlPopMatrix(void) { - if (RLGL.State.stackCounter > 0) + if (RLGL[currentContext].State.stackCounter > 0) { - Matrix mat = RLGL.State.stack[RLGL.State.stackCounter - 1]; - *RLGL.State.currentMatrix = mat; - RLGL.State.stackCounter--; + Matrix mat = RLGL[currentContext].State.stack[RLGL[currentContext].State.stackCounter - 1]; + *RLGL[currentContext].State.currentMatrix = mat; + RLGL[currentContext].State.stackCounter--; } - if ((RLGL.State.stackCounter == 0) && (RLGL.State.currentMatrixMode == RL_MODELVIEW)) + if ((RLGL[currentContext].State.stackCounter == 0) && (RLGL[currentContext].State.currentMatrixMode == RL_MODELVIEW)) { - RLGL.State.currentMatrix = &RLGL.State.modelview; - RLGL.State.transformRequired = false; + RLGL[currentContext].State.currentMatrix = &RLGL[currentContext].State.modelview; + RLGL[currentContext].State.transformRequired = false; } } // Reset current matrix to identity matrix void rlLoadIdentity(void) { - *RLGL.State.currentMatrix = MatrixIdentity(); + *RLGL[currentContext].State.currentMatrix = MatrixIdentity(); } // Multiply the current matrix by a translation matrix @@ -1023,7 +1030,7 @@ void rlTranslatef(float x, float y, float z) Matrix matTranslation = MatrixTranslate(x, y, z); // NOTE: We transpose matrix with multiplication order - *RLGL.State.currentMatrix = MatrixMultiply(matTranslation, *RLGL.State.currentMatrix); + *RLGL[currentContext].State.currentMatrix = MatrixMultiply(matTranslation, *RLGL[currentContext].State.currentMatrix); } // Multiply the current matrix by a rotation matrix @@ -1035,7 +1042,7 @@ void rlRotatef(float angleDeg, float x, float y, float z) matRotation = MatrixRotate(Vector3Normalize(axis), angleDeg*DEG2RAD); // NOTE: We transpose matrix with multiplication order - *RLGL.State.currentMatrix = MatrixMultiply(matRotation, *RLGL.State.currentMatrix); + *RLGL[currentContext].State.currentMatrix = MatrixMultiply(matRotation, *RLGL[currentContext].State.currentMatrix); } // Multiply the current matrix by a scaling matrix @@ -1044,7 +1051,7 @@ void rlScalef(float x, float y, float z) Matrix matScale = MatrixScale(x, y, z); // NOTE: We transpose matrix with multiplication order - *RLGL.State.currentMatrix = MatrixMultiply(matScale, *RLGL.State.currentMatrix); + *RLGL[currentContext].State.currentMatrix = MatrixMultiply(matScale, *RLGL[currentContext].State.currentMatrix); } // Multiply the current matrix by another matrix @@ -1056,7 +1063,7 @@ void rlMultMatrixf(float *matf) matf[2], matf[6], matf[10], matf[14], matf[3], matf[7], matf[11], matf[15] }; - *RLGL.State.currentMatrix = MatrixMultiply(*RLGL.State.currentMatrix, mat); + *RLGL[currentContext].State.currentMatrix = MatrixMultiply(*RLGL[currentContext].State.currentMatrix, mat); } // Multiply the current matrix by a perspective matrix generated by parameters @@ -1064,7 +1071,7 @@ void rlFrustum(double left, double right, double bottom, double top, double znea { Matrix matPerps = MatrixFrustum(left, right, bottom, top, znear, zfar); - *RLGL.State.currentMatrix = MatrixMultiply(*RLGL.State.currentMatrix, matPerps); + *RLGL[currentContext].State.currentMatrix = MatrixMultiply(*RLGL[currentContext].State.currentMatrix, matPerps); } // Multiply the current matrix by an orthographic matrix generated by parameters @@ -1072,13 +1079,13 @@ void rlOrtho(double left, double right, double bottom, double top, double znear, { Matrix matOrtho = MatrixOrtho(left, right, bottom, top, znear, zfar); - *RLGL.State.currentMatrix = MatrixMultiply(*RLGL.State.currentMatrix, matOrtho); + *RLGL[currentContext].State.currentMatrix = MatrixMultiply(*RLGL[currentContext].State.currentMatrix, matOrtho); } #endif // Set the viewport area (transformation from normalized device coordinates to window coordinates) -// NOTE: Updates global variables: RLGL.State.framebufferWidth, RLGL.State.framebufferHeight +// NOTE: Updates global variables: RLGL[currentContext].State.framebufferWidth, RLGL[currentContext].State.framebufferHeight void rlViewport(int x, int y, int width, int height) { glViewport(x, y, width, height); @@ -1119,36 +1126,36 @@ void rlBegin(int mode) { // Draw mode can be RL_LINES, RL_TRIANGLES and RL_QUADS // NOTE: In all three cases, vertex are accumulated over default internal vertex buffer - if (RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].mode != mode) + if (RLGL[currentContext].currentBatch->draws[RLGL[currentContext].currentBatch->drawsCounter - 1].mode != mode) { - if (RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount > 0) + if (RLGL[currentContext].currentBatch->draws[RLGL[currentContext].currentBatch->drawsCounter - 1].vertexCount > 0) { - // Make sure current RLGL.currentBatch->draws[i].vertexCount is aligned a multiple of 4, + // Make sure current RLGL[currentContext].currentBatch->draws[i].vertexCount is aligned a multiple of 4, // that way, following QUADS drawing will keep aligned with index processing // It implies adding some extra alignment vertex at the end of the draw, // those vertex are not processed but they are considered as an additional offset // for the next set of vertex to be drawn - if (RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].mode == RL_LINES) RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment = ((RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount < 4)? RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount : RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount%4); - else if (RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].mode == RL_TRIANGLES) RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment = ((RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount < 4)? 1 : (4 - (RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount%4))); + if (RLGL[currentContext].currentBatch->draws[RLGL[currentContext].currentBatch->drawsCounter - 1].mode == RL_LINES) RLGL[currentContext].currentBatch->draws[RLGL[currentContext].currentBatch->drawsCounter - 1].vertexAlignment = ((RLGL[currentContext].currentBatch->draws[RLGL[currentContext].currentBatch->drawsCounter - 1].vertexCount < 4)? RLGL[currentContext].currentBatch->draws[RLGL[currentContext].currentBatch->drawsCounter - 1].vertexCount : RLGL[currentContext].currentBatch->draws[RLGL[currentContext].currentBatch->drawsCounter - 1].vertexCount%4); + else if (RLGL[currentContext].currentBatch->draws[RLGL[currentContext].currentBatch->drawsCounter - 1].mode == RL_TRIANGLES) RLGL[currentContext].currentBatch->draws[RLGL[currentContext].currentBatch->drawsCounter - 1].vertexAlignment = ((RLGL[currentContext].currentBatch->draws[RLGL[currentContext].currentBatch->drawsCounter - 1].vertexCount < 4)? 1 : (4 - (RLGL[currentContext].currentBatch->draws[RLGL[currentContext].currentBatch->drawsCounter - 1].vertexCount%4))); - else RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment = 0; + else RLGL[currentContext].currentBatch->draws[RLGL[currentContext].currentBatch->drawsCounter - 1].vertexAlignment = 0; - if (rlCheckBufferLimit(RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment)) rlglDraw(); + if (rlCheckBufferLimit(RLGL[currentContext].currentBatch->draws[RLGL[currentContext].currentBatch->drawsCounter - 1].vertexAlignment)) rlglDraw(); else { - RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter += RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment; - RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter += RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment; - RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].tcCounter += RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment; + RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].vCounter += RLGL[currentContext].currentBatch->draws[RLGL[currentContext].currentBatch->drawsCounter - 1].vertexAlignment; + RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].cCounter += RLGL[currentContext].currentBatch->draws[RLGL[currentContext].currentBatch->drawsCounter - 1].vertexAlignment; + RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].tcCounter += RLGL[currentContext].currentBatch->draws[RLGL[currentContext].currentBatch->drawsCounter - 1].vertexAlignment; - RLGL.currentBatch->drawsCounter++; + RLGL[currentContext].currentBatch->drawsCounter++; } } - if (RLGL.currentBatch->drawsCounter >= DEFAULT_BATCH_DRAWCALLS) rlglDraw(); + if (RLGL[currentContext].currentBatch->drawsCounter >= DEFAULT_BATCH_DRAWCALLS) rlglDraw(); - RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].mode = mode; - RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount = 0; - RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].textureId = RLGL.State.defaultTextureId; + RLGL[currentContext].currentBatch->draws[RLGL[currentContext].currentBatch->drawsCounter - 1].mode = mode; + RLGL[currentContext].currentBatch->draws[RLGL[currentContext].currentBatch->drawsCounter - 1].vertexCount = 0; + RLGL[currentContext].currentBatch->draws[RLGL[currentContext].currentBatch->drawsCounter - 1].textureId = RLGL[currentContext].State.defaultTextureId; } } @@ -1159,30 +1166,30 @@ void rlEnd(void) // NOTE: In OpenGL 1.1, one glColor call can be made for all the subsequent glVertex calls // Make sure colors count match vertex count - if (RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter != RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter) + if (RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].vCounter != RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].cCounter) { - int addColors = RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter - RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter; + int addColors = RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].vCounter - RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].cCounter; for (int i = 0; i < addColors; i++) { - RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter] = RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter - 4]; - RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter + 1] = RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter - 3]; - RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter + 2] = RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter - 2]; - RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter + 3] = RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter - 1]; - RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter++; + RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].colors[4*RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].cCounter] = RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].colors[4*RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].cCounter - 4]; + RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].colors[4*RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].cCounter + 1] = RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].colors[4*RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].cCounter - 3]; + RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].colors[4*RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].cCounter + 2] = RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].colors[4*RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].cCounter - 2]; + RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].colors[4*RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].cCounter + 3] = RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].colors[4*RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].cCounter - 1]; + RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].cCounter++; } } // Make sure texcoords count match vertex count - if (RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter != RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].tcCounter) + if (RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].vCounter != RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].tcCounter) { - int addTexCoords = RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter - RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].tcCounter; + int addTexCoords = RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].vCounter - RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].tcCounter; for (int i = 0; i < addTexCoords; i++) { - RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].texcoords[2*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].tcCounter] = 0.0f; - RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].texcoords[2*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].tcCounter + 1] = 0.0f; - RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].tcCounter++; + RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].texcoords[2*RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].tcCounter] = 0.0f; + RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].texcoords[2*RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].tcCounter + 1] = 0.0f; + RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].tcCounter++; } } @@ -1191,16 +1198,16 @@ void rlEnd(void) // NOTE: Depth increment is dependant on rlOrtho(): z-near and z-far values, // as well as depth buffer bit-depth (16bit or 24bit or 32bit) // Correct increment formula would be: depthInc = (zfar - znear)/pow(2, bits) - RLGL.currentBatch->currentDepth += (1.0f/20000.0f); + RLGL[currentContext].currentBatch->currentDepth += (1.0f/20000.0f); // Verify internal buffers limits // NOTE: This check is combined with usage of rlCheckBufferLimit() - if ((RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter) >= (RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].elementsCount*4 - 4)) + if ((RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].vCounter) >= (RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].elementsCount*4 - 4)) { // WARNING: If we are between rlPushMatrix() and rlPopMatrix() and we need to force a rlglDraw(), - // we need to call rlPopMatrix() before to recover *RLGL.State.currentMatrix (RLGL.State.modelview) for the next forced draw call! - // If we have multiple matrix pushed, it will require "RLGL.State.stackCounter" pops before launching the draw - for (int i = RLGL.State.stackCounter; i >= 0; i--) rlPopMatrix(); + // we need to call rlPopMatrix() before to recover *RLGL[currentContext].State.currentMatrix (RLGL[currentContext].State.modelview) for the next forced draw call! + // If we have multiple matrix pushed, it will require "RLGL[currentContext].State.stackCounter" pops before launching the draw + for (int i = RLGL[currentContext].State.stackCounter; i >= 0; i--) rlPopMatrix(); rlglDraw(); } } @@ -1212,17 +1219,17 @@ void rlVertex3f(float x, float y, float z) Vector3 vec = { x, y, z }; // Transform provided vector if required - if (RLGL.State.transformRequired) vec = Vector3Transform(vec, RLGL.State.transform); + if (RLGL[currentContext].State.transformRequired) vec = Vector3Transform(vec, RLGL[currentContext].State.transform); // Verify that current vertex buffer elements limit has not been reached - if (RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter < (RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].elementsCount*4)) + if (RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].vCounter < (RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].elementsCount*4)) { - RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vertices[3*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter] = vec.x; - RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vertices[3*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter + 1] = vec.y; - RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vertices[3*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter + 2] = vec.z; - RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter++; + RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].vertices[3*RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].vCounter] = vec.x; + RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].vertices[3*RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].vCounter + 1] = vec.y; + RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].vertices[3*RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].vCounter + 2] = vec.z; + RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].vCounter++; - RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount++; + RLGL[currentContext].currentBatch->draws[RLGL[currentContext].currentBatch->drawsCounter - 1].vertexCount++; } else TRACELOG(LOG_ERROR, "RLGL: Batch elements overflow"); } @@ -1230,22 +1237,22 @@ void rlVertex3f(float x, float y, float z) // Define one vertex (position) void rlVertex2f(float x, float y) { - rlVertex3f(x, y, RLGL.currentBatch->currentDepth); + rlVertex3f(x, y, RLGL[currentContext].currentBatch->currentDepth); } // Define one vertex (position) void rlVertex2i(int x, int y) { - rlVertex3f((float)x, (float)y, RLGL.currentBatch->currentDepth); + rlVertex3f((float)x, (float)y, RLGL[currentContext].currentBatch->currentDepth); } // Define one vertex (texture coordinate) // NOTE: Texture coordinates are limited to QUADS only void rlTexCoord2f(float x, float y) { - RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].texcoords[2*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].tcCounter] = x; - RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].texcoords[2*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].tcCounter + 1] = y; - RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].tcCounter++; + RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].texcoords[2*RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].tcCounter] = x; + RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].texcoords[2*RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].tcCounter + 1] = y; + RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].tcCounter++; } // Define one vertex (normal) @@ -1258,11 +1265,11 @@ void rlNormal3f(float x, float y, float z) // Define one vertex (color) void rlColor4ub(byte x, byte y, byte z, byte w) { - RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter] = x; - RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter + 1] = y; - RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter + 2] = z; - RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter + 3] = w; - RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter++; + RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].colors[4*RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].cCounter] = x; + RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].colors[4*RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].cCounter + 1] = y; + RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].colors[4*RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].cCounter + 2] = z; + RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].colors[4*RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].cCounter + 3] = w; + RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].cCounter++; } // Define one vertex (color) @@ -1292,35 +1299,35 @@ void rlEnableTexture(unsigned int id) #endif #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - if (RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].textureId != id) + if (RLGL[currentContext].currentBatch->draws[RLGL[currentContext].currentBatch->drawsCounter - 1].textureId != id) { - if (RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount > 0) + if (RLGL[currentContext].currentBatch->draws[RLGL[currentContext].currentBatch->drawsCounter - 1].vertexCount > 0) { - // Make sure current RLGL.currentBatch->draws[i].vertexCount is aligned a multiple of 4, + // Make sure current RLGL[currentContext].currentBatch->draws[i].vertexCount is aligned a multiple of 4, // that way, following QUADS drawing will keep aligned with index processing // It implies adding some extra alignment vertex at the end of the draw, // those vertex are not processed but they are considered as an additional offset // for the next set of vertex to be drawn - if (RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].mode == RL_LINES) RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment = ((RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount < 4)? RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount : RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount%4); - else if (RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].mode == RL_TRIANGLES) RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment = ((RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount < 4)? 1 : (4 - (RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount%4))); + if (RLGL[currentContext].currentBatch->draws[RLGL[currentContext].currentBatch->drawsCounter - 1].mode == RL_LINES) RLGL[currentContext].currentBatch->draws[RLGL[currentContext].currentBatch->drawsCounter - 1].vertexAlignment = ((RLGL[currentContext].currentBatch->draws[RLGL[currentContext].currentBatch->drawsCounter - 1].vertexCount < 4)? RLGL[currentContext].currentBatch->draws[RLGL[currentContext].currentBatch->drawsCounter - 1].vertexCount : RLGL[currentContext].currentBatch->draws[RLGL[currentContext].currentBatch->drawsCounter - 1].vertexCount%4); + else if (RLGL[currentContext].currentBatch->draws[RLGL[currentContext].currentBatch->drawsCounter - 1].mode == RL_TRIANGLES) RLGL[currentContext].currentBatch->draws[RLGL[currentContext].currentBatch->drawsCounter - 1].vertexAlignment = ((RLGL[currentContext].currentBatch->draws[RLGL[currentContext].currentBatch->drawsCounter - 1].vertexCount < 4)? 1 : (4 - (RLGL[currentContext].currentBatch->draws[RLGL[currentContext].currentBatch->drawsCounter - 1].vertexCount%4))); - else RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment = 0; + else RLGL[currentContext].currentBatch->draws[RLGL[currentContext].currentBatch->drawsCounter - 1].vertexAlignment = 0; - if (rlCheckBufferLimit(RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment)) rlglDraw(); + if (rlCheckBufferLimit(RLGL[currentContext].currentBatch->draws[RLGL[currentContext].currentBatch->drawsCounter - 1].vertexAlignment)) rlglDraw(); else { - RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter += RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment; - RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter += RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment; - RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].tcCounter += RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment; + RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].vCounter += RLGL[currentContext].currentBatch->draws[RLGL[currentContext].currentBatch->drawsCounter - 1].vertexAlignment; + RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].cCounter += RLGL[currentContext].currentBatch->draws[RLGL[currentContext].currentBatch->drawsCounter - 1].vertexAlignment; + RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].tcCounter += RLGL[currentContext].currentBatch->draws[RLGL[currentContext].currentBatch->drawsCounter - 1].vertexAlignment; - RLGL.currentBatch->drawsCounter++; + RLGL[currentContext].currentBatch->drawsCounter++; } } - if (RLGL.currentBatch->drawsCounter >= DEFAULT_BATCH_DRAWCALLS) rlglDraw(); + if (RLGL[currentContext].currentBatch->drawsCounter >= DEFAULT_BATCH_DRAWCALLS) rlglDraw(); - RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].textureId = id; - RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount = 0; + RLGL[currentContext].currentBatch->draws[RLGL[currentContext].currentBatch->drawsCounter - 1].textureId = id; + RLGL[currentContext].currentBatch->draws[RLGL[currentContext].currentBatch->drawsCounter - 1].vertexCount = 0; } #endif } @@ -1334,7 +1341,7 @@ void rlDisableTexture(void) #else // NOTE: If quads batch limit is reached, // we force a draw call and next batch starts - if (RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter >= (RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].elementsCount*4)) rlglDraw(); + if (RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].vCounter >= (RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].elementsCount*4)) rlglDraw(); #endif } @@ -1351,7 +1358,7 @@ void rlTextureParameters(unsigned int id, int param, int value) if (value == RL_WRAP_MIRROR_CLAMP) { #if !defined(GRAPHICS_API_OPENGL_11) - if (RLGL.ExtSupported.texMirrorClamp) glTexParameteri(GL_TEXTURE_2D, param, value); + if (RLGL[currentContext].ExtSupported.texMirrorClamp) glTexParameteri(GL_TEXTURE_2D, param, value); else TRACELOG(LOG_WARNING, "GL: Clamp mirror wrap mode not supported (GL_MIRROR_CLAMP_EXT)"); #endif } @@ -1363,10 +1370,10 @@ void rlTextureParameters(unsigned int id, int param, int value) case RL_TEXTURE_ANISOTROPIC_FILTER: { #if !defined(GRAPHICS_API_OPENGL_11) - if (value <= RLGL.ExtSupported.maxAnisotropicLevel) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)value); - else if (RLGL.ExtSupported.maxAnisotropicLevel > 0.0f) + if (value <= RLGL[currentContext].ExtSupported.maxAnisotropicLevel) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)value); + else if (RLGL[currentContext].ExtSupported.maxAnisotropicLevel > 0.0f) { - TRACELOG(LOG_WARNING, "GL: Maximum anisotropic filter level supported is %iX", id, RLGL.ExtSupported.maxAnisotropicLevel); + TRACELOG(LOG_WARNING, "GL: Maximum anisotropic filter level supported is %iX", id, RLGL[currentContext].ExtSupported.maxAnisotropicLevel); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)value); } else TRACELOG(LOG_WARNING, "GL: Anisotropic filtering not supported"); @@ -1474,7 +1481,7 @@ void rlDeleteShader(unsigned int id) void rlDeleteVertexArrays(unsigned int id) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - if (RLGL.ExtSupported.vao) + if (RLGL[currentContext].ExtSupported.vao) { if (id != 0) glDeleteVertexArrays(1, &id); TRACELOG(LOG_INFO, "VAO: [ID %i] Unloaded vertex data from VRAM (GPU)", id); @@ -1489,7 +1496,7 @@ void rlDeleteBuffers(unsigned int id) if (id != 0) { glDeleteBuffers(1, &id); - if (!RLGL.ExtSupported.vao) TRACELOG(LOG_INFO, "VBO: [ID %i] Unloaded vertex data from VRAM (GPU)", id); + if (!RLGL[currentContext].ExtSupported.vao) TRACELOG(LOG_INFO, "VBO: [ID %i] Unloaded vertex data from VRAM (GPU)", id); } #endif } @@ -1529,6 +1536,10 @@ void rlUpdateBuffer(int bufferId, void *data, int dataSize) // Initialize rlgl: OpenGL extensions, default buffers/shaders/textures, OpenGL states void rlglInit(int width, int height) { + currentContext = numContexts; + if (numContexts == 0) //initialize the struct for the first time + memset(RLGL, 0, sizeof(rlglData) * MAX_CONTEXTS); + numContexts++; // Check OpenGL information and capabilities //------------------------------------------------------------------------------ // Print current OpenGL and GLSL version @@ -1568,12 +1579,12 @@ void rlglInit(int width, int height) #if defined(GRAPHICS_API_OPENGL_33) && !defined(GRAPHICS_API_OPENGL_21) // NOTE: On OpenGL 3.3 VAO and NPOT are supported by default - RLGL.ExtSupported.vao = true; + RLGL[currentContext].ExtSupported.vao = true; // Multiple texture extensions supported by default - RLGL.ExtSupported.texNPOT = true; - RLGL.ExtSupported.texFloat32 = true; - RLGL.ExtSupported.texDepth = true; + RLGL[currentContext].ExtSupported.texNPOT = true; + RLGL[currentContext].ExtSupported.texFloat32 = true; + RLGL[currentContext].ExtSupported.texDepth = true; // We get a list of available extensions and we check for some of them (compressed textures) // NOTE: We don't need to check again supported extensions but we do (GLAD already dealt with that) @@ -1633,53 +1644,53 @@ void rlglInit(int width, int height) glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSOESPROC)eglGetProcAddress("glDeleteVertexArraysOES"); //glIsVertexArray = (PFNGLISVERTEXARRAYOESPROC)eglGetProcAddress("glIsVertexArrayOES"); // NOTE: Fails in WebGL, omitted - if ((glGenVertexArrays != NULL) && (glBindVertexArray != NULL) && (glDeleteVertexArrays != NULL)) RLGL.ExtSupported.vao = true; + if ((glGenVertexArrays != NULL) && (glBindVertexArray != NULL) && (glDeleteVertexArrays != NULL)) RLGL[currentContext].ExtSupported.vao = true; } // Check NPOT textures support // NOTE: Only check on OpenGL ES, OpenGL 3.3 has NPOT textures full support as core feature - if (strcmp(extList[i], (const char *)"GL_OES_texture_npot") == 0) RLGL.ExtSupported.texNPOT = true; + if (strcmp(extList[i], (const char*)"GL_OES_texture_npot") == 0) RLGL[currentContext].ExtSupported.texNPOT = true; // Check texture float support - if (strcmp(extList[i], (const char *)"GL_OES_texture_float") == 0) RLGL.ExtSupported.texFloat32 = true; + if (strcmp(extList[i], (const char*)"GL_OES_texture_float") == 0) RLGL[currentContext].ExtSupported.texFloat32 = true; // Check depth texture support - if ((strcmp(extList[i], (const char *)"GL_OES_depth_texture") == 0) || - (strcmp(extList[i], (const char *)"GL_WEBGL_depth_texture") == 0)) RLGL.ExtSupported.texDepth = true; + if ((strcmp(extList[i], (const char*)"GL_OES_depth_texture") == 0) || + (strcmp(extList[i], (const char*)"GL_WEBGL_depth_texture") == 0)) RLGL[currentContext].ExtSupported.texDepth = true; - if (strcmp(extList[i], (const char *)"GL_OES_depth24") == 0) RLGL.ExtSupported.maxDepthBits = 24; - if (strcmp(extList[i], (const char *)"GL_OES_depth32") == 0) RLGL.ExtSupported.maxDepthBits = 32; + if (strcmp(extList[i], (const char*)"GL_OES_depth24") == 0) RLGL[currentContext].ExtSupported.maxDepthBits = 24; + if (strcmp(extList[i], (const char*)"GL_OES_depth32") == 0) RLGL[currentContext].ExtSupported.maxDepthBits = 32; #endif // DDS texture compression support - if ((strcmp(extList[i], (const char *)"GL_EXT_texture_compression_s3tc") == 0) || - (strcmp(extList[i], (const char *)"GL_WEBGL_compressed_texture_s3tc") == 0) || - (strcmp(extList[i], (const char *)"GL_WEBKIT_WEBGL_compressed_texture_s3tc") == 0)) RLGL.ExtSupported.texCompDXT = true; + if ((strcmp(extList[i], (const char*)"GL_EXT_texture_compression_s3tc") == 0) || + (strcmp(extList[i], (const char*)"GL_WEBGL_compressed_texture_s3tc") == 0) || + (strcmp(extList[i], (const char*)"GL_WEBKIT_WEBGL_compressed_texture_s3tc") == 0)) RLGL[currentContext].ExtSupported.texCompDXT = true; // ETC1 texture compression support - if ((strcmp(extList[i], (const char *)"GL_OES_compressed_ETC1_RGB8_texture") == 0) || - (strcmp(extList[i], (const char *)"GL_WEBGL_compressed_texture_etc1") == 0)) RLGL.ExtSupported.texCompETC1 = true; + if ((strcmp(extList[i], (const char*)"GL_OES_compressed_ETC1_RGB8_texture") == 0) || + (strcmp(extList[i], (const char*)"GL_WEBGL_compressed_texture_etc1") == 0)) RLGL[currentContext].ExtSupported.texCompETC1 = true; // ETC2/EAC texture compression support - if (strcmp(extList[i], (const char *)"GL_ARB_ES3_compatibility") == 0) RLGL.ExtSupported.texCompETC2 = true; + if (strcmp(extList[i], (const char*)"GL_ARB_ES3_compatibility") == 0) RLGL[currentContext].ExtSupported.texCompETC2 = true; // PVR texture compression support - if (strcmp(extList[i], (const char *)"GL_IMG_texture_compression_pvrtc") == 0) RLGL.ExtSupported.texCompPVRT = true; + if (strcmp(extList[i], (const char*)"GL_IMG_texture_compression_pvrtc") == 0) RLGL[currentContext].ExtSupported.texCompPVRT = true; // ASTC texture compression support - if (strcmp(extList[i], (const char *)"GL_KHR_texture_compression_astc_hdr") == 0) RLGL.ExtSupported.texCompASTC = true; + if (strcmp(extList[i], (const char*)"GL_KHR_texture_compression_astc_hdr") == 0) RLGL[currentContext].ExtSupported.texCompASTC = true; // Anisotropic texture filter support - if (strcmp(extList[i], (const char *)"GL_EXT_texture_filter_anisotropic") == 0) + if (strcmp(extList[i], (const char*)"GL_EXT_texture_filter_anisotropic") == 0) { - RLGL.ExtSupported.texAnisoFilter = true; - glGetFloatv(0x84FF, &RLGL.ExtSupported.maxAnisotropicLevel); // GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT + RLGL[currentContext].ExtSupported.texAnisoFilter = true; + glGetFloatv(0x84FF, &RLGL[currentContext].ExtSupported.maxAnisotropicLevel); // GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT } // Clamp mirror wrap mode supported - if (strcmp(extList[i], (const char *)"GL_EXT_texture_mirror_clamp") == 0) RLGL.ExtSupported.texMirrorClamp = true; + if (strcmp(extList[i], (const char*)"GL_EXT_texture_mirror_clamp") == 0) RLGL[currentContext].ExtSupported.texMirrorClamp = true; // Debug marker support - if (strcmp(extList[i], (const char *)"GL_EXT_debug_marker") == 0) RLGL.ExtSupported.debugMarker = true; + if (strcmp(extList[i], (const char*)"GL_EXT_debug_marker") == 0) RLGL[currentContext].ExtSupported.debugMarker = true; } // Free extensions pointers @@ -1690,49 +1701,48 @@ void rlglInit(int width, int height) #endif #if defined(GRAPHICS_API_OPENGL_ES2) - if (RLGL.ExtSupported.vao) TRACELOG(LOG_INFO, "GL: VAO extension detected, VAO functions initialized successfully"); + if (RLGL[currentContext].ExtSupported.vao) TRACELOG(LOG_INFO, "GL: VAO extension detected, VAO functions initialized successfully"); else TRACELOG(LOG_WARNING, "GL: VAO extension not found, VAO usage not supported"); - if (RLGL.ExtSupported.texNPOT) TRACELOG(LOG_INFO, "GL: NPOT textures extension detected, full NPOT textures supported"); + if (RLGL[currentContext].ExtSupported.texNPOT) TRACELOG(LOG_INFO, "GL: NPOT textures extension detected, full NPOT textures supported"); else TRACELOG(LOG_WARNING, "GL: NPOT textures extension not found, limited NPOT support (no-mipmaps, no-repeat)"); #endif - if (RLGL.ExtSupported.texCompDXT) TRACELOG(LOG_INFO, "GL: DXT compressed textures supported"); - if (RLGL.ExtSupported.texCompETC1) TRACELOG(LOG_INFO, "GL: ETC1 compressed textures supported"); - if (RLGL.ExtSupported.texCompETC2) TRACELOG(LOG_INFO, "GL: ETC2/EAC compressed textures supported"); - if (RLGL.ExtSupported.texCompPVRT) TRACELOG(LOG_INFO, "GL: PVRT compressed textures supported"); - if (RLGL.ExtSupported.texCompASTC) TRACELOG(LOG_INFO, "GL: ASTC compressed textures supported"); + if (RLGL[currentContext].ExtSupported.texCompDXT) TRACELOG(LOG_INFO, "GL: DXT compressed textures supported"); + if (RLGL[currentContext].ExtSupported.texCompETC1) TRACELOG(LOG_INFO, "GL: ETC1 compressed textures supported"); + if (RLGL[currentContext].ExtSupported.texCompETC2) TRACELOG(LOG_INFO, "GL: ETC2/EAC compressed textures supported"); + if (RLGL[currentContext].ExtSupported.texCompPVRT) TRACELOG(LOG_INFO, "GL: PVRT compressed textures supported"); + if (RLGL[currentContext].ExtSupported.texCompASTC) TRACELOG(LOG_INFO, "GL: ASTC compressed textures supported"); - if (RLGL.ExtSupported.texAnisoFilter) TRACELOG(LOG_INFO, "GL: Anisotropic textures filtering supported (max: %.0fX)", RLGL.ExtSupported.maxAnisotropicLevel); - if (RLGL.ExtSupported.texMirrorClamp) TRACELOG(LOG_INFO, "GL: Mirror clamp wrap texture mode supported"); + if (RLGL[currentContext].ExtSupported.texAnisoFilter) TRACELOG(LOG_INFO, "GL: Anisotropic textures filtering supported (max: %.0fX)", RLGL[currentContext].ExtSupported.maxAnisotropicLevel); + if (RLGL[currentContext].ExtSupported.texMirrorClamp) TRACELOG(LOG_INFO, "GL: Mirror clamp wrap texture mode supported"); - if (RLGL.ExtSupported.debugMarker) TRACELOG(LOG_INFO, "GL: Debug Marker supported"); + if (RLGL[currentContext].ExtSupported.debugMarker) TRACELOG(LOG_INFO, "GL: Debug Marker supported"); // Initialize buffers, default shaders and default textures //---------------------------------------------------------- // Init default white texture unsigned char pixels[4] = { 255, 255, 255, 255 }; // 1 pixel RGBA (4 bytes) - RLGL.State.defaultTextureId = rlLoadTexture(pixels, 1, 1, UNCOMPRESSED_R8G8B8A8, 1); + RLGL[currentContext].State.defaultTextureId = rlLoadTexture(pixels, 1, 1, UNCOMPRESSED_R8G8B8A8, 1); - if (RLGL.State.defaultTextureId != 0) TRACELOG(LOG_INFO, "TEXTURE: [ID %i] Default texture loaded successfully", RLGL.State.defaultTextureId); + if (RLGL[currentContext].State.defaultTextureId != 0) TRACELOG(LOG_INFO, "TEXTURE: [ID %i] Default texture loaded successfully", RLGL[currentContext].State.defaultTextureId); else TRACELOG(LOG_WARNING, "TEXTURE: Failed to load default texture"); // Init default Shader (customized for GL 3.3 and ES2) - RLGL.State.defaultShader = LoadShaderDefault(); - RLGL.State.currentShader = RLGL.State.defaultShader; - + RLGL[currentContext].State.defaultShader = LoadShaderDefault(); + RLGL[currentContext].State.currentShader = RLGL[currentContext].State.defaultShader; // Init default vertex arrays buffers - RLGL.defaultBatch = LoadRenderBatch(DEFAULT_BATCH_BUFFERS, DEFAULT_BATCH_BUFFER_ELEMENTS); - RLGL.currentBatch = &RLGL.defaultBatch; + RLGL[currentContext].defaultBatch = LoadRenderBatch(DEFAULT_BATCH_BUFFERS, DEFAULT_BATCH_BUFFER_ELEMENTS); + RLGL[currentContext].currentBatch = &RLGL[currentContext].defaultBatch; // Init stack matrices (emulating OpenGL 1.1) - for (int i = 0; i < MAX_MATRIX_STACK_SIZE; i++) RLGL.State.stack[i] = MatrixIdentity(); + for (int i = 0; i < MAX_MATRIX_STACK_SIZE; i++) RLGL[currentContext].State.stack[i] = MatrixIdentity(); // Init internal matrices - RLGL.State.transform = MatrixIdentity(); - RLGL.State.projection = MatrixIdentity(); - RLGL.State.modelview = MatrixIdentity(); - RLGL.State.currentMatrix = &RLGL.State.modelview; + RLGL[currentContext].State.transform = MatrixIdentity(); + RLGL[currentContext].State.projection = MatrixIdentity(); + RLGL[currentContext].State.modelview = MatrixIdentity(); + RLGL[currentContext].State.currentMatrix = &RLGL[currentContext].State.modelview; #endif // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2 @@ -1764,28 +1774,29 @@ void rlglInit(int width, int height) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear color and depth buffers (depth buffer required for 3D) #if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21) - // Store screen size into global variables - RLGL.State.framebufferWidth = width; - RLGL.State.framebufferHeight = height; +// Store screen size into global variables + RLGL[currentContext].State.framebufferWidth = width; + RLGL[currentContext].State.framebufferHeight = height; - // Init texture and rectangle used on basic shapes drawing - RLGL.State.shapesTexture = GetTextureDefault(); - RLGL.State.shapesTextureRec = (Rectangle){ 0.0f, 0.0f, 1.0f, 1.0f }; + // Init texture and rectangle used on basic shapes drawing + RLGL[currentContext].State.shapesTexture = GetTextureDefault(); + RLGL[currentContext].State.shapesTextureRec = (Rectangle){ 0.0f, 0.0f, 1.0f, 1.0f }; #endif - TRACELOG(LOG_INFO, "RLGL: Default state initialized successfully"); + TRACELOG(LOG_INFO, "RLGL: Default state initialized successfully"); + } // Vertex Buffer Object deinitialization (memory free) void rlglClose(void) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - UnloadRenderBatch(RLGL.defaultBatch); + UnloadRenderBatch(RLGL[currentContext].defaultBatch); UnloadShaderDefault(); // Unload default shader - glDeleteTextures(1, &RLGL.State.defaultTextureId); // Unload default texture + glDeleteTextures(1, &RLGL[currentContext].State.defaultTextureId); // Unload default texture - TRACELOG(LOG_INFO, "TEXTURE: [ID %i] Unloaded default texture data from VRAM (GPU)", RLGL.State.defaultTextureId); + TRACELOG(LOG_INFO, "TEXTURE: [ID %i] Unloaded default texture data from VRAM (GPU)", RLGL[currentContext].State.defaultTextureId); #endif } @@ -1793,7 +1804,7 @@ void rlglClose(void) void rlglDraw(void) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - DrawRenderBatch(RLGL.currentBatch); // NOTE: Stereo rendering is checked inside + DrawRenderBatch(RLGL[currentContext].currentBatch); // NOTE: Stereo rendering is checked inside #endif } @@ -1820,7 +1831,7 @@ bool rlCheckBufferLimit(int vCount) { bool overflow = false; #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - if ((RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter + vCount) >= (RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].elementsCount*4)) overflow = true; + if ((RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].vCounter + vCount) >= (RLGL[currentContext].currentBatch->vertexBuffer[RLGL[currentContext].currentBatch->currentBuffer].elementsCount*4)) overflow = true; #endif return overflow; } @@ -1829,7 +1840,7 @@ bool rlCheckBufferLimit(int vCount) void rlSetDebugMarker(const char *text) { #if defined(GRAPHICS_API_OPENGL_33) - if (RLGL.ExtSupported.debugMarker) glInsertEventMarkerEXT(0, text); + if (RLGL[currentContext].ExtSupported.debugMarker) glInsertEventMarkerEXT(0, text); #endif } @@ -1894,32 +1905,32 @@ unsigned int rlLoadTexture(void *data, int width, int height, int format, int mi return id; } #else - if ((!RLGL.ExtSupported.texCompDXT) && ((format == COMPRESSED_DXT1_RGB) || (format == COMPRESSED_DXT1_RGBA) || + if ((!RLGL[currentContext].ExtSupported.texCompDXT) && ((format == COMPRESSED_DXT1_RGB) || (format == COMPRESSED_DXT1_RGBA) || (format == COMPRESSED_DXT3_RGBA) || (format == COMPRESSED_DXT5_RGBA))) { TRACELOG(LOG_WARNING, "GL: DXT compressed texture format not supported"); return id; } #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - if ((!RLGL.ExtSupported.texCompETC1) && (format == COMPRESSED_ETC1_RGB)) + if ((!RLGL[currentContext].ExtSupported.texCompETC1) && (format == COMPRESSED_ETC1_RGB)) { TRACELOG(LOG_WARNING, "GL: ETC1 compressed texture format not supported"); return id; } - if ((!RLGL.ExtSupported.texCompETC2) && ((format == COMPRESSED_ETC2_RGB) || (format == COMPRESSED_ETC2_EAC_RGBA))) + if ((!RLGL[currentContext].ExtSupported.texCompETC2) && ((format == COMPRESSED_ETC2_RGB) || (format == COMPRESSED_ETC2_EAC_RGBA))) { TRACELOG(LOG_WARNING, "GL: ETC2 compressed texture format not supported"); return id; } - if ((!RLGL.ExtSupported.texCompPVRT) && ((format == COMPRESSED_PVRT_RGB) || (format == COMPRESSED_PVRT_RGBA))) + if ((!RLGL[currentContext].ExtSupported.texCompPVRT) && ((format == COMPRESSED_PVRT_RGB) || (format == COMPRESSED_PVRT_RGBA))) { TRACELOG(LOG_WARNING, "GL: PVRT compressed texture format not supported"); return id; } - if ((!RLGL.ExtSupported.texCompASTC) && ((format == COMPRESSED_ASTC_4x4_RGBA) || (format == COMPRESSED_ASTC_8x8_RGBA))) + if ((!RLGL[currentContext].ExtSupported.texCompASTC) && ((format == COMPRESSED_ASTC_4x4_RGBA) || (format == COMPRESSED_ASTC_8x8_RGBA))) { TRACELOG(LOG_WARNING, "GL: ASTC compressed texture format not supported"); return id; @@ -1989,7 +2000,7 @@ unsigned int rlLoadTexture(void *data, int width, int height, int format, int mi // NOTE: glTexParameteri does NOT affect texture uploading, just the way it's used #if defined(GRAPHICS_API_OPENGL_ES2) // NOTE: OpenGL ES 2.0 with no GL_OES_texture_npot support (i.e. WebGL) has limited NPOT support, so CLAMP_TO_EDGE must be used - if (RLGL.ExtSupported.texNPOT) + if (RLGL[currentContext].ExtSupported.texNPOT) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // Set texture to repeat on x-axis glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // Set texture to repeat on y-axis @@ -2047,7 +2058,7 @@ unsigned int rlLoadTextureDepth(int width, int height, int bits, bool useRenderB #if defined(GRAPHICS_API_OPENGL_33) glInternalFormat = GL_DEPTH_COMPONENT24; #elif defined(GRAPHICS_API_OPENGL_ES2) - if (RLGL.ExtSupported.maxDepthBits >= 24) glInternalFormat = GL_DEPTH_COMPONENT24_OES; + if (RLGL[currentContext].ExtSupported.maxDepthBits >= 24) glInternalFormat = GL_DEPTH_COMPONENT24_OES; #endif } @@ -2056,11 +2067,11 @@ unsigned int rlLoadTextureDepth(int width, int height, int bits, bool useRenderB #if defined(GRAPHICS_API_OPENGL_33) glInternalFormat = GL_DEPTH_COMPONENT32; #elif defined(GRAPHICS_API_OPENGL_ES2) - if (RLGL.ExtSupported.maxDepthBits == 32) glInternalFormat = GL_DEPTH_COMPONENT32_OES; + if (RLGL[currentContext].ExtSupported.maxDepthBits == 32) glInternalFormat = GL_DEPTH_COMPONENT32_OES; #endif } - if (!useRenderBuffer && RLGL.ExtSupported.texDepth) + if (!useRenderBuffer && RLGL[currentContext].ExtSupported.texDepth) { glGenTextures(1, &id); glBindTexture(GL_TEXTURE_2D, id); @@ -2181,9 +2192,9 @@ void rlGetGlTextureFormats(int format, unsigned int *glInternalFormat, unsigned case UNCOMPRESSED_R4G4B4A4: *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_SHORT_4_4_4_4; break; case UNCOMPRESSED_R8G8B8A8: *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_BYTE; break; #if !defined(GRAPHICS_API_OPENGL_11) - case UNCOMPRESSED_R32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_LUMINANCE; *glFormat = GL_LUMINANCE; *glType = GL_FLOAT; break; // NOTE: Requires extension OES_texture_float - case UNCOMPRESSED_R32G32B32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_FLOAT; break; // NOTE: Requires extension OES_texture_float - case UNCOMPRESSED_R32G32B32A32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_FLOAT; break; // NOTE: Requires extension OES_texture_float + case UNCOMPRESSED_R32: if (RLGL[currentContext].ExtSupported.texFloat32) *glInternalFormat = GL_LUMINANCE; *glFormat = GL_LUMINANCE; *glType = GL_FLOAT; break; // NOTE: Requires extension OES_texture_float + case UNCOMPRESSED_R32G32B32: if (RLGL[currentContext].ExtSupported.texFloat32) *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_FLOAT; break; // NOTE: Requires extension OES_texture_float + case UNCOMPRESSED_R32G32B32A32: if (RLGL[currentContext].ExtSupported.texFloat32) *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_FLOAT; break; // NOTE: Requires extension OES_texture_float #endif #elif defined(GRAPHICS_API_OPENGL_33) case UNCOMPRESSED_GRAYSCALE: *glInternalFormat = GL_R8; *glFormat = GL_RED; *glType = GL_UNSIGNED_BYTE; break; @@ -2193,22 +2204,22 @@ void rlGetGlTextureFormats(int format, unsigned int *glInternalFormat, unsigned case UNCOMPRESSED_R5G5B5A1: *glInternalFormat = GL_RGB5_A1; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_SHORT_5_5_5_1; break; case UNCOMPRESSED_R4G4B4A4: *glInternalFormat = GL_RGBA4; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_SHORT_4_4_4_4; break; case UNCOMPRESSED_R8G8B8A8: *glInternalFormat = GL_RGBA8; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_BYTE; break; - case UNCOMPRESSED_R32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_R32F; *glFormat = GL_RED; *glType = GL_FLOAT; break; - case UNCOMPRESSED_R32G32B32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGB32F; *glFormat = GL_RGB; *glType = GL_FLOAT; break; - case UNCOMPRESSED_R32G32B32A32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGBA32F; *glFormat = GL_RGBA; *glType = GL_FLOAT; break; + case UNCOMPRESSED_R32: if (RLGL[currentContext].ExtSupported.texFloat32) *glInternalFormat = GL_R32F; *glFormat = GL_RED; *glType = GL_FLOAT; break; + case UNCOMPRESSED_R32G32B32: if (RLGL[currentContext].ExtSupported.texFloat32) *glInternalFormat = GL_RGB32F; *glFormat = GL_RGB; *glType = GL_FLOAT; break; + case UNCOMPRESSED_R32G32B32A32: if (RLGL[currentContext].ExtSupported.texFloat32) *glInternalFormat = GL_RGBA32F; *glFormat = GL_RGBA; *glType = GL_FLOAT; break; #endif #if !defined(GRAPHICS_API_OPENGL_11) - case COMPRESSED_DXT1_RGB: if (RLGL.ExtSupported.texCompDXT) *glInternalFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; break; - case COMPRESSED_DXT1_RGBA: if (RLGL.ExtSupported.texCompDXT) *glInternalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; break; - case COMPRESSED_DXT3_RGBA: if (RLGL.ExtSupported.texCompDXT) *glInternalFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; break; - case COMPRESSED_DXT5_RGBA: if (RLGL.ExtSupported.texCompDXT) *glInternalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; break; - case COMPRESSED_ETC1_RGB: if (RLGL.ExtSupported.texCompETC1) *glInternalFormat = GL_ETC1_RGB8_OES; break; // NOTE: Requires OpenGL ES 2.0 or OpenGL 4.3 - case COMPRESSED_ETC2_RGB: if (RLGL.ExtSupported.texCompETC2) *glInternalFormat = GL_COMPRESSED_RGB8_ETC2; break; // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3 - case COMPRESSED_ETC2_EAC_RGBA: if (RLGL.ExtSupported.texCompETC2) *glInternalFormat = GL_COMPRESSED_RGBA8_ETC2_EAC; break; // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3 - case COMPRESSED_PVRT_RGB: if (RLGL.ExtSupported.texCompPVRT) *glInternalFormat = GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG; break; // NOTE: Requires PowerVR GPU - case COMPRESSED_PVRT_RGBA: if (RLGL.ExtSupported.texCompPVRT) *glInternalFormat = GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG; break; // NOTE: Requires PowerVR GPU - case COMPRESSED_ASTC_4x4_RGBA: if (RLGL.ExtSupported.texCompASTC) *glInternalFormat = GL_COMPRESSED_RGBA_ASTC_4x4_KHR; break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3 - case COMPRESSED_ASTC_8x8_RGBA: if (RLGL.ExtSupported.texCompASTC) *glInternalFormat = GL_COMPRESSED_RGBA_ASTC_8x8_KHR; break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3 + case COMPRESSED_DXT1_RGB: if (RLGL[currentContext].ExtSupported.texCompDXT) *glInternalFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; break; + case COMPRESSED_DXT1_RGBA: if (RLGL[currentContext].ExtSupported.texCompDXT) *glInternalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; break; + case COMPRESSED_DXT3_RGBA: if (RLGL[currentContext].ExtSupported.texCompDXT) *glInternalFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; break; + case COMPRESSED_DXT5_RGBA: if (RLGL[currentContext].ExtSupported.texCompDXT) *glInternalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; break; + case COMPRESSED_ETC1_RGB: if (RLGL[currentContext].ExtSupported.texCompETC1) *glInternalFormat = GL_ETC1_RGB8_OES; break; // NOTE: Requires OpenGL ES 2.0 or OpenGL 4.3 + case COMPRESSED_ETC2_RGB: if (RLGL[currentContext].ExtSupported.texCompETC2) *glInternalFormat = GL_COMPRESSED_RGB8_ETC2; break; // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3 + case COMPRESSED_ETC2_EAC_RGBA: if (RLGL[currentContext].ExtSupported.texCompETC2) *glInternalFormat = GL_COMPRESSED_RGBA8_ETC2_EAC; break; // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3 + case COMPRESSED_PVRT_RGB: if (RLGL[currentContext].ExtSupported.texCompPVRT) *glInternalFormat = GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG; break; // NOTE: Requires PowerVR GPU + case COMPRESSED_PVRT_RGBA: if (RLGL[currentContext].ExtSupported.texCompPVRT) *glInternalFormat = GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG; break; // NOTE: Requires PowerVR GPU + case COMPRESSED_ASTC_4x4_RGBA: if (RLGL[currentContext].ExtSupported.texCompASTC) *glInternalFormat = GL_COMPRESSED_RGBA_ASTC_4x4_KHR; break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3 + case COMPRESSED_ASTC_8x8_RGBA: if (RLGL[currentContext].ExtSupported.texCompASTC) *glInternalFormat = GL_COMPRESSED_RGBA_ASTC_8x8_KHR; break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3 #endif default: TRACELOG(LOG_WARNING, "TEXTURE: Current format not supported (%i)", format); break; } @@ -2226,8 +2237,8 @@ RenderTexture2D rlLoadRenderTexture(int width, int height, int format, int depth { RenderTexture2D target = { 0 }; -#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)) && defined(SUPPORT_RENDER_TEXTURES_HINT) - if (useDepthTexture && RLGL.ExtSupported.texDepth) target.depthTexture = true; +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + if (useDepthTexture && RLGL[currentContext].ExtSupported.texDepth) target.depthTexture = true; // Create the framebuffer object glGenFramebuffers(1, &target.id); @@ -2279,7 +2290,7 @@ RenderTexture2D rlLoadRenderTexture(int width, int height, int format, int depth // NOTE: Attach type: 0-Color, 1-Depth renderbuffer, 2-Depth texture void rlRenderTextureAttach(RenderTexture2D target, unsigned int id, int attachType) { -#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)) && defined(SUPPORT_RENDER_TEXTURES_HINT) +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) glBindFramebuffer(GL_FRAMEBUFFER, target.id); if (attachType == 0) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, id, 0); @@ -2298,7 +2309,7 @@ bool rlRenderTextureComplete(RenderTexture target) { bool result = false; -#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)) && defined(SUPPORT_RENDER_TEXTURES_HINT) +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) glBindFramebuffer(GL_FRAMEBUFFER, target.id); GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); @@ -2375,7 +2386,7 @@ void rlGenerateMipmaps(Texture2D *texture) else TRACELOG(LOG_WARNING, "TEXTURE: [ID %i] Failed to generate mipmaps for provided texture format", texture->id); } #elif defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - if ((texIsPOT) || (RLGL.ExtSupported.texNPOT)) + if ((texIsPOT) || (RLGL[currentContext].ExtSupported.texNPOT)) { //glHint(GL_GENERATE_MIPMAP_HINT, GL_DONT_CARE); // Hint for mipmaps generation algorythm: GL_FASTEST, GL_NICEST, GL_DONT_CARE glGenerateMipmap(GL_TEXTURE_2D); // Generate mipmaps automatically @@ -2418,7 +2429,7 @@ void rlLoadMesh(Mesh *mesh, bool dynamic) int drawHint = GL_STATIC_DRAW; if (dynamic) drawHint = GL_DYNAMIC_DRAW; - if (RLGL.ExtSupported.vao) + if (RLGL[currentContext].ExtSupported.vao) { // Initialize Quads VAO (Buffer A) glGenVertexArrays(1, &mesh->vaoId); @@ -2512,7 +2523,7 @@ void rlLoadMesh(Mesh *mesh, bool dynamic) glBufferData(GL_ELEMENT_ARRAY_BUFFER, mesh->triangleCount*3*sizeof(unsigned short), mesh->indices, drawHint); } - if (RLGL.ExtSupported.vao) + if (RLGL[currentContext].ExtSupported.vao) { if (mesh->vaoId > 0) TRACELOG(LOG_INFO, "VAO: [ID %i] Mesh uploaded successfully to VRAM (GPU)", mesh->vaoId); else TRACELOG(LOG_WARNING, "VAO: Failed to load mesh to VRAM (GPU)"); @@ -2533,7 +2544,7 @@ unsigned int rlLoadAttribBuffer(unsigned int vaoId, int shaderLoc, void *buffer, int drawHint = GL_STATIC_DRAW; if (dynamic) drawHint = GL_DYNAMIC_DRAW; - if (RLGL.ExtSupported.vao) glBindVertexArray(vaoId); + if (RLGL[currentContext].ExtSupported.vao) glBindVertexArray(vaoId); glGenBuffers(1, &id); glBindBuffer(GL_ARRAY_BUFFER, id); @@ -2541,7 +2552,7 @@ unsigned int rlLoadAttribBuffer(unsigned int vaoId, int shaderLoc, void *buffer, glVertexAttribPointer(shaderLoc, 2, GL_FLOAT, 0, 0, 0); glEnableVertexAttribArray(shaderLoc); - if (RLGL.ExtSupported.vao) glBindVertexArray(0); + if (RLGL[currentContext].ExtSupported.vao) glBindVertexArray(0); #endif return id; @@ -2560,7 +2571,7 @@ void rlUpdateMeshAt(Mesh mesh, int buffer, int count, int index) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) // Activate mesh VAO - if (RLGL.ExtSupported.vao) glBindVertexArray(mesh.vaoId); + if (RLGL[currentContext].ExtSupported.vao) glBindVertexArray(mesh.vaoId); switch (buffer) { @@ -2627,7 +2638,7 @@ void rlUpdateMeshAt(Mesh mesh, int buffer, int count, int index) } // Unbind the current VAO - if (RLGL.ExtSupported.vao) glBindVertexArray(0); + if (RLGL[currentContext].ExtSupported.vao) glBindVertexArray(0); // Another option would be using buffer mapping... //mesh.vertices = glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE); @@ -2694,21 +2705,21 @@ void rlDrawMesh(Mesh mesh, Material material, Matrix transform) (float)material.maps[MAP_SPECULAR].color.b/255.0f, (float)material.maps[MAP_SPECULAR].color.a/255.0f); - if (material.shader.locs[LOC_MATRIX_VIEW] != -1) SetShaderValueMatrix(material.shader, material.shader.locs[LOC_MATRIX_VIEW], RLGL.State.modelview); - if (material.shader.locs[LOC_MATRIX_PROJECTION] != -1) SetShaderValueMatrix(material.shader, material.shader.locs[LOC_MATRIX_PROJECTION], RLGL.State.projection); + if (material.shader.locs[LOC_MATRIX_VIEW] != -1) SetShaderValueMatrix(material.shader, material.shader.locs[LOC_MATRIX_VIEW], RLGL[currentContext].State.modelview); + if (material.shader.locs[LOC_MATRIX_PROJECTION] != -1) SetShaderValueMatrix(material.shader, material.shader.locs[LOC_MATRIX_PROJECTION], RLGL[currentContext].State.projection); // At this point the modelview matrix just contains the view matrix (camera) // That's because BeginMode3D() sets it an no model-drawing function modifies it, all use rlPushMatrix() and rlPopMatrix() - Matrix matView = RLGL.State.modelview; // View matrix (camera) - Matrix matProjection = RLGL.State.projection; // Projection matrix (perspective) + Matrix matView = RLGL[currentContext].State.modelview; // View matrix (camera) + Matrix matProjection = RLGL[currentContext].State.projection; // Projection matrix (perspective) - // TODO: Consider possible transform matrices in the RLGL.State.stack + // TODO: Consider possible transform matrices in the RLGL[currentContext].State.stack // Is this the right order? or should we start with the first stored matrix instead of the last one? //Matrix matStackTransform = MatrixIdentity(); - //for (int i = RLGL.State.stackCounter; i > 0; i--) matStackTransform = MatrixMultiply(RLGL.State.stack[i], matStackTransform); + //for (int i = RLGL[currentContext].State.stackCounter; i > 0; i--) matStackTransform = MatrixMultiply(RLGL[currentContext].State.stack[i], matStackTransform); // Transform to camera-space coordinates - Matrix matModelView = MatrixMultiply(transform, MatrixMultiply(RLGL.State.transform, matView)); + Matrix matModelView = MatrixMultiply(transform, MatrixMultiply(RLGL[currentContext].State.transform, matView)); //----------------------------------------------------- // Bind active texture maps (if available) @@ -2725,7 +2736,7 @@ void rlDrawMesh(Mesh mesh, Material material, Matrix transform) } // Bind vertex array objects (or VBOs) - if (RLGL.ExtSupported.vao) glBindVertexArray(mesh.vaoId); + if (RLGL[currentContext].ExtSupported.vao) glBindVertexArray(mesh.vaoId); else { // Bind mesh VBO data: vertex position (shader-location = 0) @@ -2785,18 +2796,18 @@ void rlDrawMesh(Mesh mesh, Material material, Matrix transform) int eyesCount = 1; #if defined(SUPPORT_VR_SIMULATOR) - if (RLGL.Vr.stereoRender) eyesCount = 2; + if (RLGL[currentContext].Vr.stereoRender) eyesCount = 2; #endif for (int eye = 0; eye < eyesCount; eye++) { - if (eyesCount == 1) RLGL.State.modelview = matModelView; + if (eyesCount == 1) RLGL[currentContext].State.modelview = matModelView; #if defined(SUPPORT_VR_SIMULATOR) else SetStereoView(eye, matProjection, matModelView); #endif // Calculate model-view-projection matrix (MVP) - Matrix matMVP = MatrixMultiply(RLGL.State.modelview, RLGL.State.projection); // Transform to screen-space coordinates + Matrix matMVP = MatrixMultiply(RLGL[currentContext].State.modelview, RLGL[currentContext].State.projection); // Transform to screen-space coordinates // Send combined model-view-projection matrix to shader glUniformMatrix4fv(material.shader.locs[LOC_MATRIX_MVP], 1, false, MatrixToFloat(matMVP)); @@ -2815,7 +2826,7 @@ void rlDrawMesh(Mesh mesh, Material material, Matrix transform) } // Unind vertex array objects (or VBOs) - if (RLGL.ExtSupported.vao) glBindVertexArray(0); + if (RLGL[currentContext].ExtSupported.vao) glBindVertexArray(0); else { glBindBuffer(GL_ARRAY_BUFFER, 0); @@ -2825,10 +2836,10 @@ void rlDrawMesh(Mesh mesh, Material material, Matrix transform) // Unbind shader program glUseProgram(0); - // Restore RLGL.State.projection/RLGL.State.modelview matrices + // Restore RLGL[currentContext].State.projection/RLGL[currentContext].State.modelview matrices // NOTE: In stereo rendering matrices are being modified to fit every eye - RLGL.State.projection = matProjection; - RLGL.State.modelview = matView; + RLGL[currentContext].State.projection = matProjection; + RLGL[currentContext].State.modelview = matView; #endif } @@ -2966,7 +2977,7 @@ Texture2D GetTextureDefault(void) { Texture2D texture = { 0 }; #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - texture.id = RLGL.State.defaultTextureId; + texture.id = RLGL[currentContext].State.defaultTextureId; texture.width = 1; texture.height = 1; texture.mipmaps = 1; @@ -2982,7 +2993,7 @@ Texture2D GetShapesTexture(void) Texture2D texture = { 0 }; return texture; #else - return RLGL.State.shapesTexture; + return RLGL[currentContext].State.shapesTexture; #endif } @@ -2993,7 +3004,7 @@ Rectangle GetShapesTextureRec(void) Rectangle rec = { 0 }; return rec; #else - return RLGL.State.shapesTextureRec; + return RLGL[currentContext].State.shapesTextureRec; #endif } @@ -3001,8 +3012,8 @@ Rectangle GetShapesTextureRec(void) void SetShapesTexture(Texture2D texture, Rectangle source) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - RLGL.State.shapesTexture = texture; - RLGL.State.shapesTextureRec = source; + RLGL[currentContext].State.shapesTexture = texture; + RLGL[currentContext].State.shapesTextureRec = source; #endif } @@ -3010,7 +3021,7 @@ void SetShapesTexture(Texture2D texture, Rectangle source) Shader GetShaderDefault(void) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - return RLGL.State.defaultShader; + return RLGL[currentContext].State.defaultShader; #else Shader shader = { 0 }; return shader; @@ -3050,24 +3061,24 @@ Shader LoadShaderCode(const char *vsCode, const char *fsCode) for (int i = 0; i < MAX_SHADER_LOCATIONS; i++) shader.locs[i] = -1; #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - unsigned int vertexShaderId = RLGL.State.defaultVShaderId; - unsigned int fragmentShaderId = RLGL.State.defaultFShaderId; + unsigned int vertexShaderId = RLGL[currentContext].State.defaultVShaderId; + unsigned int fragmentShaderId = RLGL[currentContext].State.defaultFShaderId; if (vsCode != NULL) vertexShaderId = CompileShader(vsCode, GL_VERTEX_SHADER); if (fsCode != NULL) fragmentShaderId = CompileShader(fsCode, GL_FRAGMENT_SHADER); - if ((vertexShaderId == RLGL.State.defaultVShaderId) && (fragmentShaderId == RLGL.State.defaultFShaderId)) shader = RLGL.State.defaultShader; + if ((vertexShaderId == RLGL[currentContext].State.defaultVShaderId) && (fragmentShaderId == RLGL[currentContext].State.defaultFShaderId)) shader = RLGL[currentContext].State.defaultShader; else { shader.id = LoadShaderProgram(vertexShaderId, fragmentShaderId); - if (vertexShaderId != RLGL.State.defaultVShaderId) glDeleteShader(vertexShaderId); - if (fragmentShaderId != RLGL.State.defaultFShaderId) glDeleteShader(fragmentShaderId); + if (vertexShaderId != RLGL[currentContext].State.defaultVShaderId) glDeleteShader(vertexShaderId); + if (fragmentShaderId != RLGL[currentContext].State.defaultFShaderId) glDeleteShader(fragmentShaderId); if (shader.id == 0) { TRACELOG(LOG_WARNING, "SHADER: Failed to load custom shader code"); - shader = RLGL.State.defaultShader; + shader = RLGL[currentContext].State.defaultShader; } // After shader loading, we TRY to set default location names @@ -3115,10 +3126,10 @@ void UnloadShader(Shader shader) void BeginShaderMode(Shader shader) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - if (RLGL.State.currentShader.id != shader.id) + if (RLGL[currentContext].State.currentShader.id != shader.id) { rlglDraw(); - RLGL.State.currentShader = shader; + RLGL[currentContext].State.currentShader = shader; } #endif } @@ -3127,7 +3138,7 @@ void BeginShaderMode(Shader shader) void EndShaderMode(void) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - BeginShaderMode(RLGL.State.defaultShader); + BeginShaderMode(RLGL[currentContext].State.defaultShader); #endif } @@ -3203,7 +3214,7 @@ void SetShaderValueTexture(Shader shader, int uniformLoc, Texture2D texture) void SetMatrixProjection(Matrix projection) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - RLGL.State.projection = projection; + RLGL[currentContext].State.projection = projection; #endif } @@ -3219,7 +3230,7 @@ Matrix GetMatrixProjection(void) { m.m12 = mat[12]; m.m13 = mat[13]; m.m14 = mat[14]; m.m15 = mat[15]; return m; #else - return RLGL.State.projection; + return RLGL[currentContext].State.projection; #endif # } @@ -3228,7 +3239,7 @@ Matrix GetMatrixProjection(void) { void SetMatrixModelview(Matrix view) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - RLGL.State.modelview = view; + RLGL[currentContext].State.modelview = view; #endif } @@ -3244,7 +3255,7 @@ Matrix GetMatrixModelview(void) matrix.m8 = mat[8]; matrix.m9 = mat[9]; matrix.m10 = mat[10]; matrix.m11 = mat[11]; matrix.m12 = mat[12]; matrix.m13 = mat[13]; matrix.m14 = mat[14]; matrix.m15 = mat[15]; #else - matrix = RLGL.State.modelview; + matrix = RLGL[currentContext].State.modelview; #endif return matrix; } @@ -3286,7 +3297,7 @@ Texture2D GenTextureCubemap(Shader shader, Texture2D map, int size) #if defined(GRAPHICS_API_OPENGL_33) glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB32F, size, size, 0, GL_RGB, GL_FLOAT, NULL); #elif defined(GRAPHICS_API_OPENGL_ES2) - if (RLGL.ExtSupported.texFloat32) glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, size, size, 0, GL_RGB, GL_FLOAT, NULL); + if (RLGL[currentContext].ExtSupported.texFloat32) glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, size, size, 0, GL_RGB, GL_FLOAT, NULL); #endif } @@ -3331,7 +3342,7 @@ Texture2D GenTextureCubemap(Shader shader, Texture2D map, int size) glBindFramebuffer(GL_FRAMEBUFFER, 0); // Reset viewport dimensions to default - glViewport(0, 0, RLGL.State.framebufferWidth, RLGL.State.framebufferHeight); + glViewport(0, 0, RLGL[currentContext].State.framebufferWidth, RLGL[currentContext].State.framebufferHeight); //glEnable(GL_CULL_FACE); // NOTE: Texture2D is a GL_TEXTURE_CUBE_MAP, not a GL_TEXTURE_2D! @@ -3409,7 +3420,7 @@ Texture2D GenTextureIrradiance(Shader shader, Texture2D cubemap, int size) glBindFramebuffer(GL_FRAMEBUFFER, 0); // Reset viewport dimensions to default - glViewport(0, 0, RLGL.State.framebufferWidth, RLGL.State.framebufferHeight); + glViewport(0, 0, RLGL[currentContext].State.framebufferWidth, RLGL[currentContext].State.framebufferHeight); irradiance.width = size; irradiance.height = size; @@ -3504,7 +3515,7 @@ Texture2D GenTexturePrefilter(Shader shader, Texture2D cubemap, int size) glBindFramebuffer(GL_FRAMEBUFFER, 0); // Reset viewport dimensions to default - glViewport(0, 0, RLGL.State.framebufferWidth, RLGL.State.framebufferHeight); + glViewport(0, 0, RLGL[currentContext].State.framebufferWidth, RLGL[currentContext].State.framebufferHeight); prefilter.width = size; prefilter.height = size; @@ -3527,7 +3538,7 @@ Texture2D GenTextureBRDF(Shader shader, int size) #if defined(GRAPHICS_API_OPENGL_33) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, size, size, 0, GL_RGB, GL_FLOAT, NULL); #elif defined(GRAPHICS_API_OPENGL_ES2) - if (RLGL.ExtSupported.texFloat32) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, size, size, 0, GL_RGB, GL_FLOAT, NULL); + if (RLGL[currentContext].ExtSupported.texFloat32) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, size, size, 0, GL_RGB, GL_FLOAT, NULL); #endif glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); @@ -3561,7 +3572,7 @@ Texture2D GenTextureBRDF(Shader shader, int size) glDeleteFramebuffers(1, &fbo); // Reset viewport dimensions to default - glViewport(0, 0, RLGL.State.framebufferWidth, RLGL.State.framebufferHeight); + glViewport(0, 0, RLGL[currentContext].State.framebufferWidth, RLGL[currentContext].State.framebufferHeight); brdf.width = size; brdf.height = size; @@ -3602,15 +3613,15 @@ void EndBlendMode(void) #if defined(SUPPORT_VR_SIMULATOR) // Init VR simulator for selected device parameters -// NOTE: It modifies the global variable: RLGL.Vr.stereoFbo +// NOTE: It modifies the global variable: RLGL[currentContext].Vr.stereoFbo void InitVrSimulator(void) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) // Initialize framebuffer and textures for stereo rendering // NOTE: Screen size should match HMD aspect ratio - RLGL.Vr.stereoFbo = rlLoadRenderTexture(RLGL.State.framebufferWidth, RLGL.State.framebufferHeight, UNCOMPRESSED_R8G8B8A8, 24, false); + RLGL[currentContext].Vr.stereoFbo = rlLoadRenderTexture(RLGL[currentContext].State.framebufferWidth, RLGL[currentContext].State.framebufferHeight, UNCOMPRESSED_R8G8B8A8, 24, false); - RLGL.Vr.simulatorReady = true; + RLGL[currentContext].Vr.simulatorReady = true; #else TRACELOG(LOG_WARNING, "RLGL: VR Simulator not supported on OpenGL 1.1"); #endif @@ -3627,7 +3638,7 @@ void UpdateVrTracking(Camera *camera) void CloseVrSimulator(void) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - if (RLGL.Vr.simulatorReady) rlDeleteRenderTextures(RLGL.Vr.stereoFbo); // Unload stereo framebuffer and texture + if (RLGL[currentContext].Vr.simulatorReady) rlDeleteRenderTextures(RLGL[currentContext].Vr.stereoFbo); // Unload stereo framebuffer and texture #endif } @@ -3635,11 +3646,11 @@ void CloseVrSimulator(void) void SetVrConfiguration(VrDeviceInfo hmd, Shader distortion) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - // Reset RLGL.Vr.config for a new values assignment - memset(&RLGL.Vr.config, 0, sizeof(RLGL.Vr.config)); + // Reset RLGL[currentContext].Vr.config for a new values assignment + memset(&RLGL[currentContext].Vr.config, 0, sizeof(RLGL[currentContext].Vr.config)); // Assign distortion shader - RLGL.Vr.config.distortionShader = distortion; + RLGL[currentContext].Vr.config.distortionShader = distortion; // Compute aspect ratio float aspect = ((float)hmd.hResolution*0.5f)/(float)hmd.vResolution; @@ -3681,37 +3692,37 @@ void SetVrConfiguration(VrDeviceInfo hmd, Shader distortion) // Compute camera projection matrices float projOffset = 4.0f*lensShift; // Scaled to projection space coordinates [-1..1] Matrix proj = MatrixPerspective(fovy, aspect, RL_CULL_DISTANCE_NEAR, RL_CULL_DISTANCE_FAR); - RLGL.Vr.config.eyesProjection[0] = MatrixMultiply(proj, MatrixTranslate(projOffset, 0.0f, 0.0f)); - RLGL.Vr.config.eyesProjection[1] = MatrixMultiply(proj, MatrixTranslate(-projOffset, 0.0f, 0.0f)); + RLGL[currentContext].Vr.config.eyesProjection[0] = MatrixMultiply(proj, MatrixTranslate(projOffset, 0.0f, 0.0f)); + RLGL[currentContext].Vr.config.eyesProjection[1] = MatrixMultiply(proj, MatrixTranslate(-projOffset, 0.0f, 0.0f)); // Compute camera transformation matrices // NOTE: Camera movement might seem more natural if we model the head. // Our axis of rotation is the base of our head, so we might want to add // some y (base of head to eye level) and -z (center of head to eye protrusion) to the camera positions. - RLGL.Vr.config.eyesViewOffset[0] = MatrixTranslate(-hmd.interpupillaryDistance*0.5f, 0.075f, 0.045f); - RLGL.Vr.config.eyesViewOffset[1] = MatrixTranslate(hmd.interpupillaryDistance*0.5f, 0.075f, 0.045f); + RLGL[currentContext].Vr.config.eyesViewOffset[0] = MatrixTranslate(-hmd.interpupillaryDistance*0.5f, 0.075f, 0.045f); + RLGL[currentContext].Vr.config.eyesViewOffset[1] = MatrixTranslate(hmd.interpupillaryDistance*0.5f, 0.075f, 0.045f); // Compute eyes Viewports - RLGL.Vr.config.eyeViewportRight[2] = hmd.hResolution/2; - RLGL.Vr.config.eyeViewportRight[3] = hmd.vResolution; + RLGL[currentContext].Vr.config.eyeViewportRight[2] = hmd.hResolution/2; + RLGL[currentContext].Vr.config.eyeViewportRight[3] = hmd.vResolution; - RLGL.Vr.config.eyeViewportLeft[0] = hmd.hResolution/2; - RLGL.Vr.config.eyeViewportLeft[1] = 0; - RLGL.Vr.config.eyeViewportLeft[2] = hmd.hResolution/2; - RLGL.Vr.config.eyeViewportLeft[3] = hmd.vResolution; + RLGL[currentContext].Vr.config.eyeViewportLeft[0] = hmd.hResolution/2; + RLGL[currentContext].Vr.config.eyeViewportLeft[1] = 0; + RLGL[currentContext].Vr.config.eyeViewportLeft[2] = hmd.hResolution/2; + RLGL[currentContext].Vr.config.eyeViewportLeft[3] = hmd.vResolution; - if (RLGL.Vr.config.distortionShader.id > 0) + if (RLGL[currentContext].Vr.config.distortionShader.id > 0) { // Update distortion shader with lens and distortion-scale parameters - SetShaderValue(RLGL.Vr.config.distortionShader, GetShaderLocation(RLGL.Vr.config.distortionShader, "leftLensCenter"), leftLensCenter, UNIFORM_VEC2); - SetShaderValue(RLGL.Vr.config.distortionShader, GetShaderLocation(RLGL.Vr.config.distortionShader, "rightLensCenter"), rightLensCenter, UNIFORM_VEC2); - SetShaderValue(RLGL.Vr.config.distortionShader, GetShaderLocation(RLGL.Vr.config.distortionShader, "leftScreenCenter"), leftScreenCenter, UNIFORM_VEC2); - SetShaderValue(RLGL.Vr.config.distortionShader, GetShaderLocation(RLGL.Vr.config.distortionShader, "rightScreenCenter"), rightScreenCenter, UNIFORM_VEC2); - - SetShaderValue(RLGL.Vr.config.distortionShader, GetShaderLocation(RLGL.Vr.config.distortionShader, "scale"), scale, UNIFORM_VEC2); - SetShaderValue(RLGL.Vr.config.distortionShader, GetShaderLocation(RLGL.Vr.config.distortionShader, "scaleIn"), scaleIn, UNIFORM_VEC2); - SetShaderValue(RLGL.Vr.config.distortionShader, GetShaderLocation(RLGL.Vr.config.distortionShader, "hmdWarpParam"), hmd.lensDistortionValues, UNIFORM_VEC4); - SetShaderValue(RLGL.Vr.config.distortionShader, GetShaderLocation(RLGL.Vr.config.distortionShader, "chromaAbParam"), hmd.chromaAbCorrection, UNIFORM_VEC4); + SetShaderValue(RLGL[currentContext].Vr.config.distortionShader, GetShaderLocation(RLGL[currentContext].Vr.config.distortionShader, "leftLensCenter"), leftLensCenter, UNIFORM_VEC2); + SetShaderValue(RLGL[currentContext].Vr.config.distortionShader, GetShaderLocation(RLGL[currentContext].Vr.config.distortionShader, "rightLensCenter"), rightLensCenter, UNIFORM_VEC2); + SetShaderValue(RLGL[currentContext].Vr.config.distortionShader, GetShaderLocation(RLGL[currentContext].Vr.config.distortionShader, "leftScreenCenter"), leftScreenCenter, UNIFORM_VEC2); + SetShaderValue(RLGL[currentContext].Vr.config.distortionShader, GetShaderLocation(RLGL[currentContext].Vr.config.distortionShader, "rightScreenCenter"), rightScreenCenter, UNIFORM_VEC2); + + SetShaderValue(RLGL[currentContext].Vr.config.distortionShader, GetShaderLocation(RLGL[currentContext].Vr.config.distortionShader, "scale"), scale, UNIFORM_VEC2); + SetShaderValue(RLGL[currentContext].Vr.config.distortionShader, GetShaderLocation(RLGL[currentContext].Vr.config.distortionShader, "scaleIn"), scaleIn, UNIFORM_VEC2); + SetShaderValue(RLGL[currentContext].Vr.config.distortionShader, GetShaderLocation(RLGL[currentContext].Vr.config.distortionShader, "hmdWarpParam"), hmd.lensDistortionValues, UNIFORM_VEC4); + SetShaderValue(RLGL[currentContext].Vr.config.distortionShader, GetShaderLocation(RLGL[currentContext].Vr.config.distortionShader, "chromaAbParam"), hmd.chromaAbCorrection, UNIFORM_VEC4); } #endif } @@ -3720,7 +3731,7 @@ void SetVrConfiguration(VrDeviceInfo hmd, Shader distortion) bool IsVrSimulatorReady(void) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - return RLGL.Vr.simulatorReady; + return RLGL[currentContext].Vr.simulatorReady; #else return false; #endif @@ -3730,18 +3741,18 @@ bool IsVrSimulatorReady(void) void ToggleVrMode(void) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - RLGL.Vr.simulatorReady = !RLGL.Vr.simulatorReady; + RLGL[currentContext].Vr.simulatorReady = !RLGL[currentContext].Vr.simulatorReady; - if (!RLGL.Vr.simulatorReady) + if (!RLGL[currentContext].Vr.simulatorReady) { - RLGL.Vr.stereoRender = false; + RLGL[currentContext].Vr.stereoRender = false; // Reset viewport and default projection-modelview matrices - rlViewport(0, 0, RLGL.State.framebufferWidth, RLGL.State.framebufferHeight); - RLGL.State.projection = MatrixOrtho(0.0, RLGL.State.framebufferWidth, RLGL.State.framebufferHeight, 0.0, 0.0, 1.0); - RLGL.State.modelview = MatrixIdentity(); + rlViewport(0, 0, RLGL[currentContext].State.framebufferWidth, RLGL[currentContext].State.framebufferHeight); + RLGL[currentContext].State.projection = MatrixOrtho(0.0, RLGL[currentContext].State.framebufferWidth, RLGL[currentContext].State.framebufferHeight, 0.0, 0.0, 1.0); + RLGL[currentContext].State.modelview = MatrixIdentity(); } - else RLGL.Vr.stereoRender = true; + else RLGL[currentContext].Vr.stereoRender = true; #endif } @@ -3749,15 +3760,15 @@ void ToggleVrMode(void) void BeginVrDrawing(void) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - if (RLGL.Vr.simulatorReady) + if (RLGL[currentContext].Vr.simulatorReady) { - rlEnableRenderTexture(RLGL.Vr.stereoFbo.id); // Setup framebuffer for stereo rendering + rlEnableRenderTexture(RLGL[currentContext].Vr.stereoFbo.id); // Setup framebuffer for stereo rendering //glEnable(GL_FRAMEBUFFER_SRGB); // Enable SRGB framebuffer (only if required) //glViewport(0, 0, buffer.width, buffer.height); // Useful if rendering to separate framebuffers (every eye) rlClearScreenBuffers(); // Clear current framebuffer - RLGL.Vr.stereoRender = true; + RLGL[currentContext].Vr.stereoRender = true; } #endif } @@ -3766,29 +3777,29 @@ void BeginVrDrawing(void) void EndVrDrawing(void) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - if (RLGL.Vr.simulatorReady) + if (RLGL[currentContext].Vr.simulatorReady) { - RLGL.Vr.stereoRender = false; // Disable stereo render + RLGL[currentContext].Vr.stereoRender = false; // Disable stereo render rlDisableRenderTexture(); // Unbind current framebuffer rlClearScreenBuffers(); // Clear current framebuffer // Set viewport to default framebuffer size (screen size) - rlViewport(0, 0, RLGL.State.framebufferWidth, RLGL.State.framebufferHeight); + rlViewport(0, 0, RLGL[currentContext].State.framebufferWidth, RLGL[currentContext].State.framebufferHeight); // Let rlgl reconfigure internal matrices rlMatrixMode(RL_PROJECTION); // Enable internal projection matrix rlLoadIdentity(); // Reset internal projection matrix - rlOrtho(0.0, RLGL.State.framebufferWidth, RLGL.State.framebufferHeight, 0.0, 0.0, 1.0); // Recalculate internal RLGL.State.projection matrix + rlOrtho(0.0, RLGL[currentContext].State.framebufferWidth, RLGL[currentContext].State.framebufferHeight, 0.0, 0.0, 1.0); // Recalculate internal RLGL[currentContext].State.projection matrix rlMatrixMode(RL_MODELVIEW); // Enable internal modelview matrix rlLoadIdentity(); // Reset internal modelview matrix - // Draw RenderTexture (RLGL.Vr.stereoFbo) using distortion shader if available - if (RLGL.Vr.config.distortionShader.id > 0) RLGL.State.currentShader = RLGL.Vr.config.distortionShader; - else RLGL.State.currentShader = GetShaderDefault(); + // Draw RenderTexture (RLGL[currentContext].Vr.stereoFbo) using distortion shader if available + if (RLGL[currentContext].Vr.config.distortionShader.id > 0) RLGL[currentContext].State.currentShader = RLGL[currentContext].Vr.config.distortionShader; + else RLGL[currentContext].State.currentShader = GetShaderDefault(); - rlEnableTexture(RLGL.Vr.stereoFbo.texture.id); + rlEnableTexture(RLGL[currentContext].Vr.stereoFbo.texture.id); rlPushMatrix(); rlBegin(RL_QUADS); @@ -3801,30 +3812,30 @@ void EndVrDrawing(void) // Bottom-right corner for texture and quad rlTexCoord2f(0.0f, 0.0f); - rlVertex2f(0.0f, (float)RLGL.Vr.stereoFbo.texture.height); + rlVertex2f(0.0f, (float)RLGL[currentContext].Vr.stereoFbo.texture.height); // Top-right corner for texture and quad rlTexCoord2f(1.0f, 0.0f); - rlVertex2f((float)RLGL.Vr.stereoFbo.texture.width, (float)RLGL.Vr.stereoFbo.texture.height); + rlVertex2f((float)RLGL[currentContext].Vr.stereoFbo.texture.width, (float)RLGL[currentContext].Vr.stereoFbo.texture.height); // Top-left corner for texture and quad rlTexCoord2f(1.0f, 1.0f); - rlVertex2f((float)RLGL.Vr.stereoFbo.texture.width, 0.0f); + rlVertex2f((float)RLGL[currentContext].Vr.stereoFbo.texture.width, 0.0f); rlEnd(); rlPopMatrix(); rlDisableTexture(); // Update and draw render texture fbo with distortion to backbuffer - DrawRenderBatch(RLGL.currentBatch); + DrawRenderBatch(RLGL[currentContext].currentBatch); - // Restore RLGL.State.defaultShader - RLGL.State.currentShader = RLGL.State.defaultShader; + // Restore RLGL[currentContext].State.defaultShader + RLGL[currentContext].State.currentShader = RLGL[currentContext].State.defaultShader; // Reset viewport and default projection-modelview matrices - rlViewport(0, 0, RLGL.State.framebufferWidth, RLGL.State.framebufferHeight); - RLGL.State.projection = MatrixOrtho(0.0, RLGL.State.framebufferWidth, RLGL.State.framebufferHeight, 0.0, 0.0, 1.0); - RLGL.State.modelview = MatrixIdentity(); + rlViewport(0, 0, RLGL[currentContext].State.framebufferWidth, RLGL[currentContext].State.framebufferHeight); + RLGL[currentContext].State.projection = MatrixOrtho(0.0, RLGL[currentContext].State.framebufferWidth, RLGL[currentContext].State.framebufferHeight, 0.0, 0.0, 1.0); + RLGL[currentContext].State.modelview = MatrixIdentity(); rlDisableDepthTest(); } @@ -4001,10 +4012,10 @@ static Shader LoadShaderDefault(void) "} \n"; // NOTE: Compiled vertex/fragment shaders are kept for re-use - RLGL.State.defaultVShaderId = CompileShader(defaultVShaderStr, GL_VERTEX_SHADER); // Compile default vertex shader - RLGL.State.defaultFShaderId = CompileShader(defaultFShaderStr, GL_FRAGMENT_SHADER); // Compile default fragment shader + RLGL[currentContext].State.defaultVShaderId = CompileShader(defaultVShaderStr, GL_VERTEX_SHADER); // Compile default vertex shader + RLGL[currentContext].State.defaultFShaderId = CompileShader(defaultFShaderStr, GL_FRAGMENT_SHADER); // Compile default fragment shader - shader.id = LoadShaderProgram(RLGL.State.defaultVShaderId, RLGL.State.defaultFShaderId); + shader.id = LoadShaderProgram(RLGL[currentContext].State.defaultVShaderId, RLGL[currentContext].State.defaultFShaderId); if (shader.id > 0) { @@ -4066,14 +4077,13 @@ static void UnloadShaderDefault(void) { glUseProgram(0); - glDetachShader(RLGL.State.defaultShader.id, RLGL.State.defaultVShaderId); - glDetachShader(RLGL.State.defaultShader.id, RLGL.State.defaultFShaderId); - glDeleteShader(RLGL.State.defaultVShaderId); - glDeleteShader(RLGL.State.defaultFShaderId); - - glDeleteProgram(RLGL.State.defaultShader.id); + glDetachShader(RLGL[currentContext].State.defaultShader.id, RLGL[currentContext].State.defaultVShaderId); + glDetachShader(RLGL[currentContext].State.defaultShader.id, RLGL[currentContext].State.defaultFShaderId); + glDeleteShader(RLGL[currentContext].State.defaultVShaderId); + glDeleteShader(RLGL[currentContext].State.defaultFShaderId); - RL_FREE(RLGL.State.defaultShader.locs); + glDeleteProgram(RLGL[currentContext].State.defaultShader.id); + RL_FREE(RLGL[currentContext].State.defaultShader.locs); } // Load render batch @@ -4129,7 +4139,7 @@ static RenderBatch LoadRenderBatch(int numBuffers, int bufferElements) //-------------------------------------------------------------------------------------------- for (int i = 0; i < numBuffers; i++) { - if (RLGL.ExtSupported.vao) + if (RLGL[currentContext].ExtSupported.vao) { // Initialize Quads VAO glGenVertexArrays(1, &batch.vertexBuffer[i].vaoId); @@ -4141,22 +4151,22 @@ static RenderBatch LoadRenderBatch(int numBuffers, int bufferElements) glGenBuffers(1, &batch.vertexBuffer[i].vboId[0]); glBindBuffer(GL_ARRAY_BUFFER, batch.vertexBuffer[i].vboId[0]); glBufferData(GL_ARRAY_BUFFER, bufferElements*3*4*sizeof(float), batch.vertexBuffer[i].vertices, GL_DYNAMIC_DRAW); - glEnableVertexAttribArray(RLGL.State.currentShader.locs[LOC_VERTEX_POSITION]); - glVertexAttribPointer(RLGL.State.currentShader.locs[LOC_VERTEX_POSITION], 3, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(RLGL[currentContext].State.currentShader.locs[LOC_VERTEX_POSITION]); + glVertexAttribPointer(RLGL[currentContext].State.currentShader.locs[LOC_VERTEX_POSITION], 3, GL_FLOAT, 0, 0, 0); // Vertex texcoord buffer (shader-location = 1) glGenBuffers(1, &batch.vertexBuffer[i].vboId[1]); glBindBuffer(GL_ARRAY_BUFFER, batch.vertexBuffer[i].vboId[1]); glBufferData(GL_ARRAY_BUFFER, bufferElements*2*4*sizeof(float), batch.vertexBuffer[i].texcoords, GL_DYNAMIC_DRAW); - glEnableVertexAttribArray(RLGL.State.currentShader.locs[LOC_VERTEX_TEXCOORD01]); - glVertexAttribPointer(RLGL.State.currentShader.locs[LOC_VERTEX_TEXCOORD01], 2, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(RLGL[currentContext].State.currentShader.locs[LOC_VERTEX_TEXCOORD01]); + glVertexAttribPointer(RLGL[currentContext].State.currentShader.locs[LOC_VERTEX_TEXCOORD01], 2, GL_FLOAT, 0, 0, 0); // Vertex color buffer (shader-location = 3) glGenBuffers(1, &batch.vertexBuffer[i].vboId[2]); glBindBuffer(GL_ARRAY_BUFFER, batch.vertexBuffer[i].vboId[2]); glBufferData(GL_ARRAY_BUFFER, bufferElements*4*4*sizeof(unsigned char), batch.vertexBuffer[i].colors, GL_DYNAMIC_DRAW); - glEnableVertexAttribArray(RLGL.State.currentShader.locs[LOC_VERTEX_COLOR]); - glVertexAttribPointer(RLGL.State.currentShader.locs[LOC_VERTEX_COLOR], 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); + glEnableVertexAttribArray(RLGL[currentContext].State.currentShader.locs[LOC_VERTEX_COLOR]); + glVertexAttribPointer(RLGL[currentContext].State.currentShader.locs[LOC_VERTEX_COLOR], 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); // Fill index buffer glGenBuffers(1, &batch.vertexBuffer[i].vboId[3]); @@ -4171,7 +4181,7 @@ static RenderBatch LoadRenderBatch(int numBuffers, int bufferElements) TRACELOG(LOG_INFO, "RLGL: Render batch vertex buffers loaded successfully"); // Unbind the current VAO - if (RLGL.ExtSupported.vao) glBindVertexArray(0); + if (RLGL[currentContext].ExtSupported.vao) glBindVertexArray(0); //-------------------------------------------------------------------------------------------- // Init draw calls tracking system @@ -4185,9 +4195,9 @@ static RenderBatch LoadRenderBatch(int numBuffers, int bufferElements) batch.draws[i].vertexAlignment = 0; //batch.draws[i].vaoId = 0; //batch.draws[i].shaderId = 0; - batch.draws[i].textureId = RLGL.State.defaultTextureId; - //batch.draws[i].RLGL.State.projection = MatrixIdentity(); - //batch.draws[i].RLGL.State.modelview = MatrixIdentity(); + batch.draws[i].textureId = RLGL[currentContext].State.defaultTextureId; + //batch.draws[i].RLGL[currentContext].State.projection = MatrixIdentity(); + //batch.draws[i].RLGL[currentContext].State.modelview = MatrixIdentity(); } batch.buffersCount = numBuffers; // Record buffer count @@ -4209,7 +4219,7 @@ static void DrawRenderBatch(RenderBatch *batch) if (batch->vertexBuffer[batch->currentBuffer].vCounter > 0) { // Activate elements VAO - if (RLGL.ExtSupported.vao) glBindVertexArray(batch->vertexBuffer[batch->currentBuffer].vaoId); + if (RLGL[currentContext].ExtSupported.vao) glBindVertexArray(batch->vertexBuffer[batch->currentBuffer].vaoId); // Vertex positions buffer glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[0]); @@ -4242,18 +4252,18 @@ static void DrawRenderBatch(RenderBatch *batch) // glUnmapBuffer(GL_ARRAY_BUFFER); // Unbind the current VAO - if (RLGL.ExtSupported.vao) glBindVertexArray(0); + if (RLGL[currentContext].ExtSupported.vao) glBindVertexArray(0); } //------------------------------------------------------------------------------------------------------------ // Draw batch vertex buffers (considering VR stereo if required) //------------------------------------------------------------------------------------------------------------ - Matrix matProjection = RLGL.State.projection; - Matrix matModelView = RLGL.State.modelview; + Matrix matProjection = RLGL[currentContext].State.projection; + Matrix matModelView = RLGL[currentContext].State.modelview; int eyesCount = 1; #if defined(SUPPORT_VR_SIMULATOR) - if (RLGL.Vr.stereoRender) eyesCount = 2; + if (RLGL[currentContext].Vr.stereoRender) eyesCount = 2; #endif for (int eye = 0; eye < eyesCount; eye++) @@ -4266,40 +4276,40 @@ static void DrawRenderBatch(RenderBatch *batch) if (batch->vertexBuffer[batch->currentBuffer].vCounter > 0) { // Set current shader and upload current MVP matrix - glUseProgram(RLGL.State.currentShader.id); + glUseProgram(RLGL[currentContext].State.currentShader.id); // Create modelview-projection matrix - Matrix matMVP = MatrixMultiply(RLGL.State.modelview, RLGL.State.projection); + Matrix matMVP = MatrixMultiply(RLGL[currentContext].State.modelview, RLGL[currentContext].State.projection); - glUniformMatrix4fv(RLGL.State.currentShader.locs[LOC_MATRIX_MVP], 1, false, MatrixToFloat(matMVP)); - glUniform4f(RLGL.State.currentShader.locs[LOC_COLOR_DIFFUSE], 1.0f, 1.0f, 1.0f, 1.0f); - glUniform1i(RLGL.State.currentShader.locs[LOC_MAP_DIFFUSE], 0); // Provided value refers to the texture unit (active) + glUniformMatrix4fv(RLGL[currentContext].State.currentShader.locs[LOC_MATRIX_MVP], 1, false, MatrixToFloat(matMVP)); + glUniform4f(RLGL[currentContext].State.currentShader.locs[LOC_COLOR_DIFFUSE], 1.0f, 1.0f, 1.0f, 1.0f); + glUniform1i(RLGL[currentContext].State.currentShader.locs[LOC_MAP_DIFFUSE], 0); // Provided value refers to the texture unit (active) // TODO: Support additional texture units on custom shader - //if (RLGL.State.currentShader->locs[LOC_MAP_SPECULAR] > 0) glUniform1i(RLGL.State.currentShader.locs[LOC_MAP_SPECULAR], 1); - //if (RLGL.State.currentShader->locs[LOC_MAP_NORMAL] > 0) glUniform1i(RLGL.State.currentShader.locs[LOC_MAP_NORMAL], 2); + //if (RLGL[currentContext].State.currentShader->locs[LOC_MAP_SPECULAR] > 0) glUniform1i(RLGL[currentContext].State.currentShader.locs[LOC_MAP_SPECULAR], 1); + //if (RLGL[currentContext].State.currentShader->locs[LOC_MAP_NORMAL] > 0) glUniform1i(RLGL[currentContext].State.currentShader.locs[LOC_MAP_NORMAL], 2); // NOTE: Right now additional map textures not considered for default buffers drawing int vertexOffset = 0; - if (RLGL.ExtSupported.vao) glBindVertexArray(batch->vertexBuffer[batch->currentBuffer].vaoId); + if (RLGL[currentContext].ExtSupported.vao) glBindVertexArray(batch->vertexBuffer[batch->currentBuffer].vaoId); else { // Bind vertex attrib: position (shader-location = 0) glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[0]); - glVertexAttribPointer(RLGL.State.currentShader.locs[LOC_VERTEX_POSITION], 3, GL_FLOAT, 0, 0, 0); - glEnableVertexAttribArray(RLGL.State.currentShader.locs[LOC_VERTEX_POSITION]); + glVertexAttribPointer(RLGL[currentContext].State.currentShader.locs[LOC_VERTEX_POSITION], 3, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(RLGL[currentContext].State.currentShader.locs[LOC_VERTEX_POSITION]); // Bind vertex attrib: texcoord (shader-location = 1) glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[1]); - glVertexAttribPointer(RLGL.State.currentShader.locs[LOC_VERTEX_TEXCOORD01], 2, GL_FLOAT, 0, 0, 0); - glEnableVertexAttribArray(RLGL.State.currentShader.locs[LOC_VERTEX_TEXCOORD01]); + glVertexAttribPointer(RLGL[currentContext].State.currentShader.locs[LOC_VERTEX_TEXCOORD01], 2, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(RLGL[currentContext].State.currentShader.locs[LOC_VERTEX_TEXCOORD01]); // Bind vertex attrib: color (shader-location = 3) glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[2]); - glVertexAttribPointer(RLGL.State.currentShader.locs[LOC_VERTEX_COLOR], 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); - glEnableVertexAttribArray(RLGL.State.currentShader.locs[LOC_VERTEX_COLOR]); + glVertexAttribPointer(RLGL[currentContext].State.currentShader.locs[LOC_VERTEX_COLOR], 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); + glEnableVertexAttribArray(RLGL[currentContext].State.currentShader.locs[LOC_VERTEX_COLOR]); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[3]); } @@ -4311,8 +4321,8 @@ static void DrawRenderBatch(RenderBatch *batch) glBindTexture(GL_TEXTURE_2D, batch->draws[i].textureId); // TODO: Find some way to bind additional textures --> Use global texture IDs? Register them on draw[i]? - //if (RLGL.State.currentShader->locs[LOC_MAP_SPECULAR] > 0) { glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, textureUnit1_id); } - //if (RLGL.State.currentShader->locs[LOC_MAP_SPECULAR] > 0) { glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, textureUnit2_id); } + //if (RLGL[currentContext].State.currentShader->locs[LOC_MAP_SPECULAR] > 0) { glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, textureUnit1_id); } + //if (RLGL[currentContext].State.currentShader->locs[LOC_MAP_SPECULAR] > 0) { glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, textureUnit2_id); } if ((batch->draws[i].mode == RL_LINES) || (batch->draws[i].mode == RL_TRIANGLES)) glDrawArrays(batch->draws[i].mode, vertexOffset, batch->draws[i].vertexCount); else @@ -4330,7 +4340,7 @@ static void DrawRenderBatch(RenderBatch *batch) vertexOffset += (batch->draws[i].vertexCount + batch->draws[i].vertexAlignment); } - if (!RLGL.ExtSupported.vao) + if (!RLGL[currentContext].ExtSupported.vao) { glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); @@ -4339,7 +4349,7 @@ static void DrawRenderBatch(RenderBatch *batch) glBindTexture(GL_TEXTURE_2D, 0); // Unbind textures } - if (RLGL.ExtSupported.vao) glBindVertexArray(0); // Unbind VAO + if (RLGL[currentContext].ExtSupported.vao) glBindVertexArray(0); // Unbind VAO glUseProgram(0); // Unbind shader program } @@ -4356,15 +4366,15 @@ static void DrawRenderBatch(RenderBatch *batch) batch->currentDepth = -1.0f; // Restore projection/modelview matrices - RLGL.State.projection = matProjection; - RLGL.State.modelview = matModelView; + RLGL[currentContext].State.projection = matProjection; + RLGL[currentContext].State.modelview = matModelView; - // Reset RLGL.currentBatch->draws array + // Reset RLGL[currentContext].currentBatch->draws array for (int i = 0; i < DEFAULT_BATCH_DRAWCALLS; i++) { batch->draws[i].mode = RL_QUADS; batch->draws[i].vertexCount = 0; - batch->draws[i].textureId = RLGL.State.defaultTextureId; + batch->draws[i].textureId = RLGL[currentContext].State.defaultTextureId; } batch->drawsCounter = 1; @@ -4379,7 +4389,7 @@ static void DrawRenderBatch(RenderBatch *batch) static void UnloadRenderBatch(RenderBatch batch) { // Unbind everything - if (RLGL.ExtSupported.vao) glBindVertexArray(0); + if (RLGL[currentContext].ExtSupported.vao) glBindVertexArray(0); glDisableVertexAttribArray(0); glDisableVertexAttribArray(1); glDisableVertexAttribArray(2); @@ -4397,7 +4407,7 @@ static void UnloadRenderBatch(RenderBatch batch) glDeleteBuffers(1, &batch.vertexBuffer[i].vboId[3]); // Delete VAOs from GPU (VRAM) - if (RLGL.ExtSupported.vao) glDeleteVertexArrays(1, &batch.vertexBuffer[i].vaoId); + if (RLGL[currentContext].ExtSupported.vao) glDeleteVertexArrays(1, &batch.vertexBuffer[i].vaoId); // Free vertex arrays memory from CPU (RAM) RL_FREE(batch.vertexBuffer[i].vertices); @@ -4414,15 +4424,15 @@ static void UnloadRenderBatch(RenderBatch batch) // Set the active render batch for rlgl static void SetRenderBatchActive(RenderBatch *batch) { - DrawRenderBatch(RLGL.currentBatch); - RLGL.currentBatch = batch; + DrawRenderBatch(RLGL[currentContext].currentBatch); + RLGL[currentContext].currentBatch = batch; } // Set default render batch for rlgl static void SetRenderBatchDefault(void) { - DrawRenderBatch(RLGL.currentBatch); - RLGL.currentBatch = &RLGL.defaultBatch; + DrawRenderBatch(RLGL[currentContext].currentBatch); + RLGL[currentContext].currentBatch = &RLGL[currentContext].defaultBatch; } // Renders a 1x1 XY quad in NDC @@ -4544,13 +4554,13 @@ static void SetStereoView(int eye, Matrix matProjection, Matrix matModelView) Matrix eyeModelView = matModelView; // Setup viewport and projection/modelview matrices using tracking data - rlViewport(eye*RLGL.State.framebufferWidth/2, 0, RLGL.State.framebufferWidth/2, RLGL.State.framebufferHeight); + rlViewport(eye*RLGL[currentContext].State.framebufferWidth/2, 0, RLGL[currentContext].State.framebufferWidth/2, RLGL[currentContext].State.framebufferHeight); // Apply view offset to modelview matrix - eyeModelView = MatrixMultiply(matModelView, RLGL.Vr.config.eyesViewOffset[eye]); + eyeModelView = MatrixMultiply(matModelView, RLGL[currentContext].Vr.config.eyesViewOffset[eye]); // Set current eye projection matrix - eyeProjection = RLGL.Vr.config.eyesProjection[eye]; + eyeProjection = RLGL[currentContext].Vr.config.eyesProjection[eye]; SetMatrixModelview(eyeModelView); SetMatrixProjection(eyeProjection);