diff --git a/src/video/opengl.cpp b/src/video/opengl.cpp --- a/src/video/opengl.cpp +++ b/src/video/opengl.cpp @@ -24,6 +24,7 @@ #include "opengl.h" #include "../core/mem_func.hpp" +#include "../core/geometry_func.hpp" #include "../gfx_func.h" #include "../debug.h" @@ -292,8 +293,9 @@ bool OpenGLBackend::Resize(int w, int h, /** * Render video buffer to the screen. + * @param update_rect Rectangle encompassing the dirty region of the video buffer. */ -void OpenGLBackend::Paint() +void OpenGLBackend::Paint(Rect update_rect) { assert(this->vid_buffer != nullptr); @@ -301,8 +303,10 @@ void OpenGLBackend::Paint() /* Update changed rect of the video buffer texture. */ glBindTexture(GL_TEXTURE_2D, this->vid_texture); - glPixelStorei(GL_UNPACK_ROW_LENGTH, _screen.pitch); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, _screen.width, _screen.height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, this->vid_buffer); + if (!IsEmptyRect(update_rect)) { + glPixelStorei(GL_UNPACK_ROW_LENGTH, _screen.pitch); + glTexSubImage2D(GL_TEXTURE_2D, 0, update_rect.left, update_rect.top, update_rect.right - update_rect.left, update_rect.bottom - update_rect.top, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, (uint32 *)this->vid_buffer + update_rect.top * _screen.pitch + update_rect.left); + } /* Blit video buffer to screen. */ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); diff --git a/src/video/opengl.h b/src/video/opengl.h --- a/src/video/opengl.h +++ b/src/video/opengl.h @@ -13,6 +13,7 @@ #define VIDEO_OPENGL_H #include "../core/alloc_type.hpp" +#include "../core/geometry_type.hpp" typedef void (*OGLProc)(); typedef OGLProc (*GetOGLProcAddressProc)(const char *proc); @@ -42,7 +43,7 @@ public: static void Destroy(); bool Resize(int w, int h, bool force = false); - void Paint(); + void Paint(Rect update_rect); /** * Get a pointer to the memory for the video driver to draw to. diff --git a/src/video/win32_v.cpp b/src/video/win32_v.cpp --- a/src/video/win32_v.cpp +++ b/src/video/win32_v.cpp @@ -64,8 +64,6 @@ static std::condition_variable_any *_dra static volatile bool _draw_continue; /** Local copy of the palette for use in the drawing thread. */ static Palette _local_palette; -/** Region of the screen that needs redrawing. */ -static Rect _dirty_rect; bool VideoDriver_Win32Base::ClaimMousePointer() { @@ -886,7 +884,7 @@ void VideoDriver_Win32Base::Stop() void VideoDriver_Win32Base::MakeDirty(int left, int top, int width, int height) { Rect r = {left, top, left + width, top + height}; - _dirty_rect = BoundingRect(_dirty_rect, r); + this->dirty_rect = BoundingRect(this->dirty_rect, r); } void VideoDriver_Win32Base::CheckPaletteAnim() @@ -1243,7 +1241,7 @@ void VideoDriver_Win32GDI::Paint() { PerformanceMeasurer framerate(PFE_VIDEO); - if (IsEmptyRect(_dirty_rect)) return; + if (IsEmptyRect(this->dirty_rect)) return; HDC dc = GetDC(this->main_wnd); HDC dc2 = CreateCompatibleDC(dc); @@ -1279,7 +1277,7 @@ void VideoDriver_Win32GDI::Paint() ReleaseDC(this->main_wnd, dc); - _dirty_rect = {}; + this->dirty_rect = {}; } void VideoDriver_Win32GDI::PaintThread() @@ -1446,6 +1444,8 @@ bool VideoDriver_Win32OpenGL::AllocateBa if (this->gl_rc == nullptr) return false; + this->dirty_rect = {}; + bool res = OpenGLBackend::Get()->Resize(w, h); _wnd.buffer_bits = OpenGLBackend::Get()->GetVideoBuffer(); return res; @@ -1455,6 +1455,8 @@ void VideoDriver_Win32OpenGL::Paint() { PerformanceMeasurer framerate(PFE_VIDEO); + if (IsEmptyRect(this->dirty_rect)) return; + if (_cur_palette.count_dirty != 0) { Blitter *blitter = BlitterFactory::GetCurrentBlitter(); @@ -1473,8 +1475,10 @@ void VideoDriver_Win32OpenGL::Paint() _cur_palette.count_dirty = 0; } - OpenGLBackend::Get()->Paint(); + OpenGLBackend::Get()->Paint(this->dirty_rect); SwapBuffers(this->dc); + + this->dirty_rect = {}; } #endif /* WITH_OPENGL */ diff --git a/src/video/win32_v.h b/src/video/win32_v.h --- a/src/video/win32_v.h +++ b/src/video/win32_v.h @@ -38,6 +38,7 @@ public: protected: HWND main_wnd; ///< Handle to system window. bool fullscreen; ///< Whether to use (true) fullscreen mode. + Rect dirty_rect; ///< Region of the screen that needs redrawing. Dimension GetScreenSize() const override; float GetDPIScale() override;