int X11_GL_GetSwapInterval(_THIS) { if (_this->gl_data->glXSwapIntervalEXT) { Display *display = ((SDL_VideoData *) _this->driverdata)->display; const SDL_WindowData *windowdata = (SDL_WindowData *) SDL_GL_GetCurrentWindow()->driverdata; Window drawable = windowdata->xwindow; unsigned int allow_late_swap_tearing = 0; unsigned int interval = 0; if (_this->gl_data->HAS_GLX_EXT_swap_control_tear) { _this->gl_data->glXQueryDrawable(display, drawable, GLX_LATE_SWAPS_TEAR_EXT, &allow_late_swap_tearing); } _this->gl_data->glXQueryDrawable(display, drawable, GLX_SWAP_INTERVAL_EXT, &interval); if ((allow_late_swap_tearing) && (interval > 0)) { return -((int) interval); } return (int) interval; } else if (_this->gl_data->glXGetSwapIntervalMESA) { return _this->gl_data->glXGetSwapIntervalMESA(); } else { return swapinterval; } }
void bmx_SDL_WarpMouseInWindow(int x, int y) { if( _currentContext ){ SDL_WarpMouseInWindow(_currentContext->window, x, y); } else { SDL_WarpMouseInWindow(SDL_GL_GetCurrentWindow(), x, y); } }
SDL_bool OVL_Init(const char* theme_dir, const char* language) { Uint32 mask = SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER | SDL_INIT_JOYSTICK; if (SDL_WasInit(mask) != mask) { SDL_SetError("SDL not initialized"); \ return SDL_FALSE; } _this = SDL_calloc(1, sizeof(*_this)); if (_this == NULL) { SDL_OutOfMemory(); return SDL_FALSE; } SDL_Window* window = SDL_GL_GetCurrentWindow(); SDL_GLContext context = SDL_GL_GetCurrentContext(); _this->overlay_window = SDL_CreateWindow("Overlay", 0, 0, 1, 1, SDL_WINDOW_HIDDEN); _this->overlay_context = SDL_GL_CreateContext(_this->overlay_window); SDL_GL_MakeCurrent(window, context); return SDL_TRUE; }
void ex1() { SDL_SetWindowTitle( SDL_GL_GetCurrentWindow(), "ex1" ); Uint32 color1, color2; color1 = SDL_MapRGB( backBuffer->format, 200, 40, 40 ); color2 = SDL_MapRGB( backBuffer->format, 40, 40, 200 ); drawGradient( backBuffer, 0, WIN_W-1, WIN_H/2-1, color1, color2 ); }
int WIN_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context) { HDC hdc; if (!_this->gl_data) { return SDL_SetError("OpenGL not initialized"); } /* sanity check that higher level handled this. */ SDL_assert(window || (!window && !context)); /* Some Windows drivers freak out if hdc is NULL, even when context is NULL, against spec. Since hdc is _supposed_ to be ignored if context is NULL, we either use the current GL window, or do nothing if we already have no current context. */ if (!window) { window = SDL_GL_GetCurrentWindow(); if (!window) { SDL_assert(SDL_GL_GetCurrentContext() == NULL); return 0; /* already done. */ } } hdc = ((SDL_WindowData *) window->driverdata)->hdc; if (!_this->gl_data->wglMakeCurrent(hdc, (HGLRC) context)) { return WIN_SetError("wglMakeCurrent()"); } return 0; }
int WIN_GLES_SetupWindow(_THIS, SDL_Window * window) { /* The current context is lost in here; save it and reset it. */ SDL_WindowData *windowdata = (SDL_WindowData *) window->driverdata; SDL_Window *current_win = SDL_GL_GetCurrentWindow(); SDL_GLContext current_ctx = SDL_GL_GetCurrentContext(); if (_this->egl_data == NULL) { if (SDL_EGL_LoadLibrary(_this, NULL, EGL_DEFAULT_DISPLAY) < 0) { SDL_EGL_UnloadLibrary(_this); return -1; } } /* Create the GLES window surface */ windowdata->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType)windowdata->hwnd); if (windowdata->egl_surface == EGL_NO_SURFACE) { return SDL_SetError("Could not create GLES window surface"); } return WIN_GLES_MakeCurrent(_this, current_win, current_ctx); }
/** * Events don't always have valid windows, * but GHOST needs a window _always_. fallback to the GL window. */ static SDL_Window *SDL_GetWindowFromID_fallback(Uint32 id) { SDL_Window *sdl_win = SDL_GetWindowFromID(id); if (sdl_win == NULL) { sdl_win = SDL_GL_GetCurrentWindow(); } return sdl_win; }
glm::mat4 master_renderer::create_projection_matrix() { int w, h; SDL_GL_GetDrawableSize(SDL_GL_GetCurrentWindow(), &w, &h); // This is certainly easier than the Java version... return glm::perspectiveFov(glm::radians(fov), float(w), float(h), near_plane, far_plane); }
static void _PlatformCreateOpenGLContextCore(FPlatformOpenGLContext* OutContext) { check(OutContext); SDL_HWindow PrevWindow = SDL_GL_GetCurrentWindow(); SDL_HGLContext PrevContext = SDL_GL_GetCurrentContext(); OutContext->hGLContext = SDL_GL_CreateContext(OutContext->hWnd); SDL_GL_MakeCurrent(PrevWindow, PrevContext); }
int WIN_GL_SetupWindow(_THIS, SDL_Window * window) { /* The current context is lost in here; save it and reset it. */ SDL_Window *current_win = SDL_GL_GetCurrentWindow(); SDL_GLContext current_ctx = SDL_GL_GetCurrentContext(); const int retval = WIN_GL_SetupWindowInternal(_this, window); WIN_GL_MakeCurrent(_this, current_win, current_ctx); return retval; }
void PlatformGetBackbufferDimensions( uint32& OutWidth, uint32& OutHeight ) { SDL_Window* WindowHandle= SDL_GL_GetCurrentWindow(); check(WindowHandle); SDL_Surface *Surface= SDL_GetWindowSurface(WindowHandle); check(Surface); OutWidth = Surface->w; OutHeight = Surface->h; UE_LOG(LogHTML5OpenGL, Verbose, TEXT("PlatformGetBackbufferDimensions(%d, %d)"), OutWidth, OutHeight); }
void GraphicsWindowSDL2::setSyncToVBlank(bool on) { SDL_Window *oldWin = SDL_GL_GetCurrentWindow(); SDL_GLContext oldCtx = SDL_GL_GetCurrentContext(); SDL_GL_MakeCurrent(mWindow, mContext); SDL_GL_SetSwapInterval(on ? 1 : 0); SDL_GL_MakeCurrent(oldWin, oldCtx); }
GLuint OpenGL::getDefaultFBO() const { #ifdef LOVE_IOS // Hack: iOS uses a custom FBO. SDL_SysWMinfo info = {}; SDL_VERSION(&info.version); SDL_GetWindowWMInfo(SDL_GL_GetCurrentWindow(), &info); return info.info.uikit.framebuffer; #else return 0; #endif }
void ConfigManager::set_mouse_grab(bool v) { log_info("ConfigManager::set_mouse_grab: %1%", v); if (v != get_mouse_grab()) { SDL_SetWindowGrab(SDL_GL_GetCurrentWindow(), static_cast<SDL_bool>(v)); on_mouse_grab_change(v); } m_opts.mouse_grab.set(v); }
void ex3() { SDL_SetWindowTitle( SDL_GL_GetCurrentWindow(), "ex3" ); SDL_Rect sprite1; SDL_Rect sprite2; sprite1.x = WIN_W/2; sprite1.y = WIN_H/2; sprite2.x = sprite1.x + 10; sprite2.y = sprite1.y + 10; SDL_BlitSurface( Background, NULL, backBuffer, NULL ); SDL_BlitSurface( SpriteImage, NULL, backBuffer, &sprite1 ); SDL_BlitSurface( SpriteImage, NULL, backBuffer, &sprite2 ); }
void THMovie::setRenderer(SDL_Renderer *pRenderer) { m_pRenderer = pRenderer; SDL_GLContext prevContext = SDL_GL_GetCurrentContext(); m_pShareWindow = SDL_GL_GetCurrentWindow(); /* We create a new context that we can use on our video thread, that shares * a texture namespace with the main thread's context. */ SDL_GL_SetAttribute(SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 1); m_shareContext = SDL_GL_CreateContext(m_pShareWindow); /* Unfortunately, SDL_GL_CreateContext implicitly makes the new context current, so we revert it. */ SDL_GL_MakeCurrent(m_pShareWindow, prevContext); }
void GraphicsWindowSDL2::init() { if(mValid) return; if(!_traits.valid()) return; WindowData *inheritedWindowData = dynamic_cast<WindowData*>(_traits->inheritedWindowData.get()); mWindow = inheritedWindowData ? inheritedWindowData->mWindow : NULL; mOwnsWindow = (mWindow == 0); if(mOwnsWindow) { OSG_FATAL<<"Error: No SDL window provided."<<std::endl; return; } // SDL will change the current context when it creates a new one, so we // have to get the current one to be able to restore it afterward. SDL_Window *oldWin = SDL_GL_GetCurrentWindow(); SDL_GLContext oldCtx = SDL_GL_GetCurrentContext(); #ifdef OPENGL_ES SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); #endif mContext = SDL_GL_CreateContext(mWindow); if(!mContext) { OSG_FATAL<< "Error: Unable to create OpenGL graphics context: "<<SDL_GetError() <<std::endl; return; } SDL_GL_SetSwapInterval(_traits->vsync ? 1 : 0); SDL_GL_MakeCurrent(oldWin, oldCtx); mValid = true; #if OSG_VERSION_GREATER_OR_EQUAL(3,3,4) getEventQueue()->syncWindowRectangleWithGraphicsContext(); #else getEventQueue()->syncWindowRectangleWithGraphcisContext(); #endif }
int X11_GL_SetSwapInterval(_THIS, int interval) { int status = -1; if ((interval < 0) && (!_this->gl_data->HAS_GLX_EXT_swap_control_tear)) { SDL_SetError("Negative swap interval unsupported in this GL"); } else if (_this->gl_data->glXSwapIntervalEXT) { Display *display = ((SDL_VideoData *) _this->driverdata)->display; const SDL_WindowData *windowdata = (SDL_WindowData *) SDL_GL_GetCurrentWindow()->driverdata; Window drawable = windowdata->xwindow; /* * This is a workaround for a bug in NVIDIA drivers. Bug has been reported * and will be fixed in a future release (probably 319.xx). * * There's a bug where glXSetSwapIntervalEXT ignores updates because * it has the wrong value cached. To work around it, we just run a no-op * update to the current value. */ int currentInterval = X11_GL_GetSwapInterval(_this); _this->gl_data->glXSwapIntervalEXT(display, drawable, currentInterval); _this->gl_data->glXSwapIntervalEXT(display, drawable, interval); status = 0; swapinterval = interval; } else if (_this->gl_data->glXSwapIntervalMESA) { status = _this->gl_data->glXSwapIntervalMESA(interval); if (status != 0) { SDL_SetError("glxSwapIntervalMESA failed"); } else { swapinterval = interval; } } else if (_this->gl_data->glXSwapIntervalSGI) { status = _this->gl_data->glXSwapIntervalSGI(interval); if (status != 0) { SDL_SetError("glxSwapIntervalSGI failed"); } else { swapinterval = interval; } } else { SDL_Unsupported(); } return status; }
void ex2() { SDL_SetWindowTitle( SDL_GL_GetCurrentWindow(), "ex2" ); SDL_Color c; c.r = 40; c.g = 225; c.b = 40; c.a = 255; SDL_Rect rects[10]; for ( int i = 0; i < 10; i++ ) { SDL_Rect r; r.x = rand()%WIN_W; r.y = rand()%WIN_H; r.w = 50; r.h = 100; bool colliding = false; for ( int j = i-1; j >= 0; j-- ) { SDL_Rect r2 = rects[j]; int cx1 = r.x + (r.w/2); int cx2 = r2.x + (r2.w/2); int cy1 = r.y + (r.y/2); int cy2 = r2.y + (r2.y/2); int xDist = abs( cx1 - cx2 ); int yDist = abs( cy1 - cy2 ); int touchDistX = (r.w/2) + (r2.w/2); int touchDistY = (r.h/2) + (r2.h/2); if ( xDist <= touchDistX || yDist <= touchDistY ) { colliding = true; break; } } if ( colliding ) { i--; } else { rects[i] = r; } } SDL_FillRects( backBuffer, rects, 10, SDL_MapRGB( backBuffer->format, c.r, c.g, c.b ) ); }
value lime_window_alert (value message, value title) { #ifdef NME_SDL2 SDL_Window* sdlWindow = SDL_GL_GetCurrentWindow (); if (!sdlWindow) return alloc_null (); #ifdef HX_WINDOWS int count = 0; int speed = 0; bool stopOnForeground = true; SDL_SysWMinfo info; SDL_VERSION (&info.version); SDL_GetWindowWMInfo (sdlWindow, &info); FLASHWINFO fi; fi.cbSize = sizeof (FLASHWINFO); fi.hwnd = info.info.win.window; fi.dwFlags = stopOnForeground ? FLASHW_ALL | FLASHW_TIMERNOFG : FLASHW_ALL | FLASHW_TIMER; fi.uCount = count; fi.dwTimeout = speed; FlashWindowEx (&fi); #endif if (!val_is_null (message)) { SDL_ShowSimpleMessageBox (SDL_MESSAGEBOX_INFORMATION, val_is_null (title) ? "" : val_string (title), val_string (message), sdlWindow); } #endif return alloc_null (); }
int main(int argc, char* argv[]) { MyGame* game = nullptr; // pointer to allow game termination when exceptions are caught try { load(WINDOW_WIDTH, WINDOW_HEIGHT); SDL_Window* window = SDL_GL_GetCurrentWindow(); SDL_GLContext glContext = SDL_GL_GetCurrentContext(); MyGame myGame(window, glContext, WINDOW_WIDTH, WINDOW_HEIGHT); // should MyGame become owner of window and glcontext when passed them? would change ~MyGame() // also, should MyGame::Terminate and Initialize even exist? Initialize could be constructor, terminate destructor game = &myGame; myGame.Initialize(); myGame.Draw(); unsigned int lastUpdate = SDL_GetTicks(); while (myGame.isRunning()) { if (lastUpdate + 66 < SDL_GetTicks()) { myGame.Update(); myGame.Draw(); lastUpdate = SDL_GetTicks(); } } myGame.Terminate(); unload(); } catch (SDLInitError err) { printf("%s, err: %s", err.getMessage().c_str(), SDL_GetError()); std::cin.get(); } catch (InitError err) { printf("Initialization failed, err: %s", err.getMessage().c_str()); std::cin.get(); } catch (GLError err) { char* type = ""; GLchar log[512]; switch (err.getType()) { case GLErrorType::PROGRAM: type = "Program"; glGetProgramInfoLog(err.getHandle(), 512, NULL, log); break; case GLErrorType::PROGRAM_PIPELINE: type = "Program Pipeline"; glGetProgramPipelineInfoLog(err.getHandle(), 512, NULL, log); break; case GLErrorType::SHADER: type = "Shaders"; glGetShaderInfoLog(err.getHandle(), 512, NULL, log); break; } printf("Error with GL %s. \nError Message: %s.\n", type, err.getMessage().c_str()); std::cout << "GL Log: " << log << std::endl; std::cin.get(); } if (game) { game->Terminate(); } unload(); return 0; }
static void PlatformReleaseOpenGL(void* ContextPtr, void* PrevContextPtr) { SDL_GL_MakeCurrent(SDL_GL_GetCurrentWindow(), reinterpret_cast<SDL_HGLContext>(PrevContextPtr)); SDL_GL_DeleteContext(reinterpret_cast<SDL_HGLContext>(ContextPtr)); }
static void PlatformInitOpenGL(void*& ContextPtr, void*& PrevContextPtr, int InMajorVersion, int InMinorVersion) { static bool bInitialized = (SDL_GL_GetCurrentWindow() != NULL) && (SDL_GL_GetCurrentContext() != NULL); if (!bInitialized) { check(InMajorVersion > 3 || (InMajorVersion == 3 && InMinorVersion >= 2)); if (SDL_WasInit(0) == 0) { SDL_Init(SDL_INIT_VIDEO); } else { Uint32 InitializedSubsystemsMask = SDL_WasInit(SDL_INIT_EVERYTHING); if ((InitializedSubsystemsMask & SDL_INIT_VIDEO) == 0) { SDL_InitSubSystem(SDL_INIT_VIDEO); } } if (SDL_GL_LoadLibrary(NULL)) { UE_LOG(LogOpenGLShaderCompiler, Fatal, TEXT("Unable to dynamically load libGL: %s"), ANSI_TO_TCHAR(SDL_GetError())); } if (SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, InMajorVersion)) { UE_LOG(LogOpenGLShaderCompiler, Fatal, TEXT("Failed to set GL major version: %s"), ANSI_TO_TCHAR(SDL_GetError())); } if (SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, InMinorVersion)) { UE_LOG(LogOpenGLShaderCompiler, Fatal, TEXT("Failed to set GL minor version: %s"), ANSI_TO_TCHAR(SDL_GetError())); } if (SDL_GL_SetAttribute( SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG)) { UE_LOG(LogOpenGLShaderCompiler, Fatal, TEXT("Failed to set GL flags: %s"), ANSI_TO_TCHAR(SDL_GetError())); } if (SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE)) { UE_LOG(LogOpenGLShaderCompiler, Fatal, TEXT("Failed to set GL mask/profile: %s"), ANSI_TO_TCHAR(SDL_GetError())); } // Create a dummy context to verify opengl support. FPlatformOpenGLContext DummyContext; _PlatformCreateDummyGLWindow(&DummyContext); _PlatformCreateOpenGLContextCore(&DummyContext); if (DummyContext.hGLContext) { _ContextMakeCurrent(DummyContext.hWnd, DummyContext.hGLContext); } else { UE_LOG(LogOpenGLShaderCompiler, Fatal, TEXT("OpenGL %d.%d not supported by driver"), InMajorVersion, InMinorVersion); return; } PrevContextPtr = NULL; ContextPtr = DummyContext.hGLContext; bInitialized = true; } PrevContextPtr = reinterpret_cast<void*>(SDL_GL_GetCurrentContext()); SDL_HGLContext NewContext = SDL_GL_CreateContext(SDL_GL_GetCurrentWindow()); SDL_GL_MakeCurrent(SDL_GL_GetCurrentWindow(), NewContext); ContextPtr = reinterpret_cast<void*>(NewContext); }
void FHTML5Application::PollGameDeviceState( const float TimeDelta ) { SDL_Event Event; while (SDL_PollEvent(&Event)) { // Tick Input Interface. switch (Event.type) { case SDL_WINDOWEVENT: { SDL_WindowEvent windowEvent = Event.window; // ignore resized client Height/Width #if PLATFORM_HTML5_BROWSER int fs; emscripten_get_canvas_size(&WindowWidth, &WindowHeight, &fs); UE_LOG(LogHTML5Application, Verbose, TEXT("emscripten_get_canvas_size: Width:%d, Height:%d, Fullscreen:%d"), WindowWidth, WindowHeight, fs); #endif #if PLATFORM_HTML5_WIN32 WindowWidth = windowEvent.data1; WindowHeight = windowEvent.data2; #endif switch (windowEvent.event) { case SDL_WINDOWEVENT_SIZE_CHANGED: { UE_LOG(LogHTML5Application, Verbose, TEXT("WindowSizeChanged: Width:%d, Height:%d"), WindowWidth, WindowHeight); MessageHandler->OnSizeChanged(ApplicationWindow,WindowWidth,WindowHeight, false); MessageHandler->OnResizingWindow(ApplicationWindow); FDisplayMetrics DisplayMetrics; FDisplayMetrics::GetDisplayMetrics(DisplayMetrics); BroadcastDisplayMetricsChanged(DisplayMetrics); } break; case SDL_WINDOWEVENT_RESIZED: { UE_LOG(LogHTML5Application, Verbose, TEXT("WindowResized: Width:%d, Height:%d"), WindowWidth, WindowHeight); MessageHandler->OnResizingWindow(ApplicationWindow); FDisplayMetrics DisplayMetrics; FDisplayMetrics::GetDisplayMetrics(DisplayMetrics); BroadcastDisplayMetricsChanged(DisplayMetrics); } break; case SDL_WINDOWEVENT_ENTER: { UE_LOG(LogHTML5Application, Verbose, TEXT("WindowEnter")); MessageHandler->OnCursorSet(); MessageHandler->OnWindowActivationChanged(ApplicationWindow, EWindowActivation::Activate); WarmUpTicks = 0; } break; case SDL_WINDOWEVENT_LEAVE: { UE_LOG(LogHTML5Application, Verbose, TEXT("WindowLeave")); MessageHandler->OnWindowActivationChanged(ApplicationWindow, EWindowActivation::Deactivate); } break; case SDL_WINDOWEVENT_FOCUS_GAINED: { UE_LOG(LogHTML5Application, Verbose, TEXT("WindowFocusGained")); MessageHandler->OnWindowActivationChanged(ApplicationWindow, EWindowActivation::Activate); WarmUpTicks = 0; } break; case SDL_WINDOWEVENT_FOCUS_LOST: { UE_LOG(LogHTML5Application, Verbose, TEXT("WindowFocusLost")); MessageHandler->OnWindowActivationChanged(ApplicationWindow, EWindowActivation::Deactivate); } break; default: break; } } default: { InputInterface->Tick( TimeDelta,Event, ApplicationWindow); } } } InputInterface->SendControllerEvents(); if ( WarmUpTicks >= 0) WarmUpTicks ++; if ( WarmUpTicks == MaxWarmUpTicks ) { // browsers don't allow locking and hiding to work independently. use warmup ticks after the application has settled // on its mouse lock/visibility status. This is necessary even in cases where the game doesn't want to locking because // the lock status oscillates for few ticks before settling down. This causes a Browser UI pop even when we don't intend to lock. // see http://www.w3.org/TR/pointerlock more for information. #if PLATFORM_HTML5_WIN32 SDL_Window* WindowHandle= SDL_GL_GetCurrentWindow(); if (((FHTML5Cursor*)Cursor.Get())->LockStatus && !((FHTML5Cursor*)Cursor.Get())->CursorStatus) { SDL_SetWindowGrab(WindowHandle, SDL_TRUE); SDL_ShowCursor(SDL_DISABLE); SDL_SetRelativeMouseMode(SDL_TRUE); } else { SDL_SetRelativeMouseMode(SDL_FALSE); SDL_ShowCursor(SDL_ENABLE); SDL_SetWindowGrab(WindowHandle, SDL_FALSE); } #endif #if PLATFORM_HTML5_BROWSER if (((FHTML5Cursor*)Cursor.Get())->LockStatus && !((FHTML5Cursor*)Cursor.Get())->CursorStatus) { UE_LOG(LogHTML5Application, Verbose, TEXT("Request pointer lock")); emscripten_request_pointerlock ( "#canvas" , true); } else { UE_LOG(LogHTML5Application, Verbose, TEXT("Exit pointer lock")); emscripten_exit_pointerlock(); } #endif WarmUpTicks = -1; } }
bool ConfigManager::get_mouse_grab() const { return SDL_GetWindowGrab(SDL_GL_GetCurrentWindow()); }
void window::render() { if (graphics::is_debug_supported()) { glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, -1, get_title().c_str()); } auto&& old_window = SDL_GL_GetCurrentWindow(); auto&& old_context = SDL_GL_GetCurrentContext(); // Need to flush here before the context change for macOS OpenGL to // finish rendering the framebuffers (on Intel at least)! glFlush(); SDL_GL_MakeCurrent(handle.get(), get_graphics_context().handle.get()); // Draw each viewport. Layer them on top of each other and use blending // for transparency. Disable depth mask so that transparent views don't // block each other from rendering. // The viewport contains colour already multiplied with the alpha // channel, so instead of doing that again with GL_SRC_ALPHA, it is // drawn with GL_ONE. The destination colour is attenuated normally with // GL_ONE_MINUS_SRC_ALPHA. GLboolean old_blend, old_depth_mask; GLint old_source_rgb, old_source_alpha, old_destination_rgb, old_destination_alpha; glGetBooleanv(GL_BLEND, &old_blend); glGetBooleanv(GL_DEPTH_WRITEMASK, &old_depth_mask); glGetIntegerv(GL_BLEND_SRC_RGB, &old_source_rgb); glGetIntegerv(GL_BLEND_SRC_ALPHA, &old_source_alpha); glGetIntegerv(GL_BLEND_DST_RGB, &old_destination_rgb); glGetIntegerv(GL_BLEND_DST_ALPHA, &old_destination_alpha); glDepthMask(GL_FALSE); glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glViewport(0, 0, get_backbuffer_width(), get_backbuffer_height()); glClearColor(get_background_color().get_r(), get_background_color().get_g(), get_background_color().get_b(), get_background_color().get_a()); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); for (auto&& iterator = graphics::viewport::viewports.rbegin(); iterator != graphics::viewport::viewports.rend(); iterator++) { auto&& viewport = **iterator; if (viewport.get_window() != this) { continue; } viewport.draw(); } glBlendFuncSeparate(old_source_rgb, old_destination_rgb, old_source_alpha, old_destination_alpha); if (not old_blend) { glDisable(GL_BLEND); } if (old_depth_mask) { glDepthMask(GL_TRUE); } SDL_GL_SwapWindow(handle.get()); SDL_GL_MakeCurrent(old_window, old_context); if (graphics::is_debug_supported()) { glPopDebugGroup(); } }