diff --git a/openrct2.vcxproj b/openrct2.vcxproj index 91b965c2ce..f8caad1f7a 100644 --- a/openrct2.vcxproj +++ b/openrct2.vcxproj @@ -383,6 +383,7 @@ + diff --git a/src/drawing/engines/opengl/DrawCommands.h b/src/drawing/engines/opengl/DrawCommands.h new file mode 100644 index 0000000000..87a3853780 --- /dev/null +++ b/src/drawing/engines/opengl/DrawCommands.h @@ -0,0 +1,50 @@ +#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers +/***************************************************************************** +* OpenRCT2, an open source clone of Roller Coaster Tycoon 2. +* +* OpenRCT2 is the work of many authors, a full list can be found in contributors.md +* For more information, visit https://github.com/OpenRCT2/OpenRCT2 +* +* OpenRCT2 is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* A full copy of the GNU General Public License can be found in licence.txt +*****************************************************************************/ +#pragma endregion + +#pragma once + +#include "../../../common.h" +#include "OpenGLAPI.h" +#include "GLSLTypes.h" + +struct DrawRectCommand { + uint32 flags; + GLuint sourceFramebuffer; + vec4f colours[2]; + sint32 clip[4]; + sint32 bounds[4]; +}; + +struct DrawLineCommand { + vec4f colour; + sint32 clip[4]; + sint32 pos[4]; +}; + +struct DrawImageCommand { + uint32 flags; + vec4f colour; + sint32 clip[4]; + GLuint texColour; + sint32 bounds[4]; +}; + +struct DrawImageMaskedCommand { + sint32 clip[4]; + GLuint texMask; + GLuint texColour; + sint32 bounds[4]; +}; \ No newline at end of file diff --git a/src/drawing/engines/opengl/FillRectShader.cpp b/src/drawing/engines/opengl/FillRectShader.cpp index 0baf1065c1..3bf5bb363c 100644 --- a/src/drawing/engines/opengl/FillRectShader.cpp +++ b/src/drawing/engines/opengl/FillRectShader.cpp @@ -87,6 +87,7 @@ void FillRectShader::SetColour(int index, vec4f colour) void FillRectShader::SetSourceFramebuffer(GLuint texture) { + _sourceFramebuffer = texture; OpenGLAPI::SetTexture2D(0, texture); } @@ -98,4 +99,8 @@ void FillRectShader::Draw(sint32 left, sint32 top, sint32 right, sint32 bottom) glDrawArrays(GL_TRIANGLES, 0, 6); } +GLuint FillRectShader::GetSourceFramebuffer() const { + return _sourceFramebuffer; +} + #endif /* DISABLE_OPENGL */ diff --git a/src/drawing/engines/opengl/FillRectShader.h b/src/drawing/engines/opengl/FillRectShader.h index d96c33c705..80af878fc6 100644 --- a/src/drawing/engines/opengl/FillRectShader.h +++ b/src/drawing/engines/opengl/FillRectShader.h @@ -36,6 +36,8 @@ private: GLuint _vbo; GLuint _vao; + GLuint _sourceFramebuffer = 0; + public: FillRectShader(); ~FillRectShader() override; @@ -49,6 +51,8 @@ public: void Draw(sint32 left, sint32 top, sint32 right, sint32 bottom); + GLuint GetSourceFramebuffer() const; + private: void GetLocations(); }; diff --git a/src/drawing/engines/opengl/OpenGLDrawingEngine.cpp b/src/drawing/engines/opengl/OpenGLDrawingEngine.cpp index f0b0df073a..84f66ccfd6 100644 --- a/src/drawing/engines/opengl/OpenGLDrawingEngine.cpp +++ b/src/drawing/engines/opengl/OpenGLDrawingEngine.cpp @@ -39,6 +39,7 @@ IDrawingEngine * DrawingEngineFactory::CreateOpenGL() #include "FillRectShader.h" #include "SwapFramebuffer.h" #include "TextureCache.h" +#include "DrawCommands.h" #include "../../../core/Console.hpp" #include "../../../core/Exception.hpp" @@ -191,6 +192,13 @@ private: sint32 _clipRight; sint32 _clipBottom; + struct { + std::vector rectangles; + std::vector lines; + std::vector images; + std::vector maskedImages; + } _commandBuffers; + public: explicit OpenGLDrawingContext(OpenGLDrawingEngine * engine); ~OpenGLDrawingContext() override; @@ -210,6 +218,13 @@ public: void DrawSpriteSolid(uint32 image, sint32 x, sint32 y, uint8 colour) override; void DrawGlyph(uint32 image, sint32 x, sint32 y, uint8 * palette) override; + void FlushCommandBuffers(); + + void FlushRectangles(); + void FlushLines(); + void FlushImages(); + void FlushMaskedImages(); + void SetDPI(rct_drawpixelinfo * dpi); }; @@ -325,11 +340,14 @@ public: gfx_draw_pickedup_peep(&_bitsDPI); + _drawingContext->FlushCommandBuffers(); _swapFramebuffer->SwapCopy(); rct2_draw(&_bitsDPI); } + _drawingContext->FlushCommandBuffers(); + // Scale up to window _screenFramebuffer->Bind(); _copyFramebufferShader->Use(); @@ -512,6 +530,8 @@ void OpenGLDrawingContext::Initialise() void OpenGLDrawingContext::Resize(sint32 width, sint32 height) { + FlushCommandBuffers(); + _drawImageShader->Use(); _drawImageShader->SetScreenSize(width, height); _drawImageMaskedShader->Use(); @@ -524,6 +544,8 @@ void OpenGLDrawingContext::Resize(sint32 width, sint32 height) void OpenGLDrawingContext::ResetPalette() { + FlushCommandBuffers(); + _textureCache->SetPalette(_engine->Palette); _drawImageShader->Use(); _drawImageShader->SetPalette(_engine->GLPalette); @@ -543,6 +565,9 @@ void OpenGLDrawingContext::FillRect(uint32 colour, sint32 left, sint32 top, sint right += _offsetX; bottom += _offsetY; + DrawRectCommand command = {}; + command.sourceFramebuffer = _fillRectShader->GetSourceFramebuffer(); + vec4f paletteColour[2]; paletteColour[0] = _engine->GLPalette[(colour >> 0) & 0xFF]; paletteColour[1] = paletteColour[0]; @@ -550,8 +575,7 @@ void OpenGLDrawingContext::FillRect(uint32 colour, sint32 left, sint32 top, sint { paletteColour[1].a = 0; - _fillRectShader->Use(); - _fillRectShader->SetFlags(0); + command.flags = 0; } else if (colour & 0x2000000) { @@ -568,20 +592,29 @@ void OpenGLDrawingContext::FillRect(uint32 colour, sint32 left, sint32 top, sint paletteColour[1] = paletteColour[0]; GLuint srcTexture = _engine->SwapCopyReturningSourceTexture(); - _fillRectShader->Use(); - _fillRectShader->SetFlags(1); - _fillRectShader->SetSourceFramebuffer(srcTexture); + command.flags = 1; + command.sourceFramebuffer = srcTexture; } else { - _fillRectShader->Use(); - _fillRectShader->SetFlags(0); + command.flags = 0; } - _fillRectShader->SetColour(0, paletteColour[0]); - _fillRectShader->SetColour(1, paletteColour[1]); - _fillRectShader->SetClip(_clipLeft, _clipTop, _clipRight, _clipBottom); - _fillRectShader->Draw(left, top, right + 1, bottom + 1); + command.colours[0] = paletteColour[0]; + command.colours[1] = paletteColour[1]; + + command.clip[0] = _clipLeft; + command.clip[1] = _clipTop; + command.clip[2] = _clipRight; + command.clip[3] = _clipBottom; + + command.bounds[0] = left; + command.bounds[1] = top; + command.bounds[2] = right + 1; + command.bounds[3] = bottom + 1; + + _commandBuffers.rectangles.push_back(command); + FlushCommandBuffers(); } void OpenGLDrawingContext::DrawLine(uint32 colour, sint32 x1, sint32 y1, sint32 x2, sint32 y2) @@ -592,11 +625,22 @@ void OpenGLDrawingContext::DrawLine(uint32 colour, sint32 x1, sint32 y1, sint32 y2 += _offsetY; vec4f paletteColour = _engine->GLPalette[colour & 0xFF]; + + DrawLineCommand command = {}; + command.colour = paletteColour; - _drawLineShader->Use(); - _drawLineShader->SetClip(_clipLeft, _clipTop, _clipRight, _clipBottom); - _drawLineShader->SetColour(paletteColour); - _drawLineShader->Draw(x1, y1, x2, y2); + command.clip[0] = _clipLeft; + command.clip[1] = _clipTop; + command.clip[2] = _clipRight; + command.clip[3] = _clipBottom; + + command.pos[0] = x1; + command.pos[1] = y1; + command.pos[2] = x2; + command.pos[3] = y2; + + _commandBuffers.lines.push_back(command); + FlushCommandBuffers(); } void OpenGLDrawingContext::DrawSprite(uint32 image, sint32 x, sint32 y, uint32 tertiaryColour) @@ -664,10 +708,24 @@ void OpenGLDrawingContext::DrawSprite(uint32 image, sint32 x, sint32 y, uint32 t right += _clipLeft; bottom += _clipTop; - _drawImageShader->Use(); - _drawImageShader->SetClip(_clipLeft, _clipTop, _clipRight, _clipBottom); - _drawImageShader->SetTexture(texture); - _drawImageShader->Draw(left, top, right, bottom); + DrawImageCommand command = {}; + + command.flags = 0; + + command.clip[0] = _clipLeft; + command.clip[1] = _clipTop; + command.clip[2] = _clipRight; + command.clip[3] = _clipBottom; + + command.texColour = texture; + + command.bounds[0] = left; + command.bounds[1] = top; + command.bounds[2] = right; + command.bounds[3] = bottom; + + _commandBuffers.images.push_back(command); + FlushCommandBuffers(); } void OpenGLDrawingContext::DrawSpriteRawMasked(sint32 x, sint32 y, uint32 maskImage, uint32 colourImage) @@ -714,11 +772,23 @@ void OpenGLDrawingContext::DrawSpriteRawMasked(sint32 x, sint32 y, uint32 maskIm right += _clipLeft; bottom += _clipTop; - _drawImageMaskedShader->Use(); - _drawImageMaskedShader->SetClip(_clipLeft, _clipTop, _clipRight, _clipBottom); - _drawImageMaskedShader->SetTextureMask(textureMask); - _drawImageMaskedShader->SetTextureColour(textureColour); - _drawImageMaskedShader->Draw(left, top, right, bottom); + DrawImageMaskedCommand command = {}; + + command.clip[0] = _clipLeft; + command.clip[1] = _clipTop; + command.clip[2] = _clipRight; + command.clip[3] = _clipBottom; + + command.texMask = textureMask; + command.texColour = textureColour; + + command.bounds[0] = left; + command.bounds[1] = top; + command.bounds[2] = right; + command.bounds[3] = bottom; + + _commandBuffers.maskedImages.push_back(command); + FlushCommandBuffers(); } void OpenGLDrawingContext::DrawSpriteSolid(uint32 image, sint32 x, sint32 y, uint8 colour) @@ -754,13 +824,25 @@ void OpenGLDrawingContext::DrawSpriteSolid(uint32 image, sint32 x, sint32 y, uin right += _offsetX; bottom += _offsetY; - _drawImageShader->Use(); - _drawImageShader->SetClip(_clipLeft, _clipTop, _clipRight, _clipBottom); - _drawImageShader->SetTexture(texture); - _drawImageShader->SetFlags(1); - _drawImageShader->SetColour(paletteColour); - _drawImageShader->Draw(left, top, right, bottom); - _drawImageShader->SetFlags(0); + DrawImageCommand command = {}; + + command.flags = 1; + command.colour = paletteColour; + + command.clip[0] = _clipLeft; + command.clip[1] = _clipTop; + command.clip[2] = _clipRight; + command.clip[3] = _clipBottom; + + command.texColour = texture; + + command.bounds[0] = left; + command.bounds[1] = top; + command.bounds[2] = right; + command.bounds[3] = bottom; + + _commandBuffers.images.push_back(command); + FlushCommandBuffers(); } void OpenGLDrawingContext::DrawGlyph(uint32 image, sint32 x, sint32 y, uint8 * palette) @@ -794,11 +876,81 @@ void OpenGLDrawingContext::DrawGlyph(uint32 image, sint32 x, sint32 y, uint8 * p right += _offsetX; bottom += _offsetY; - _drawImageShader->Use(); - _drawImageShader->SetClip(_clipLeft, _clipTop, _clipRight, _clipBottom); - _drawImageShader->SetTexture(texture); - _drawImageShader->Draw(left, top, right, bottom); - _drawImageShader->SetFlags(0); + DrawImageCommand command = {}; + + command.flags = 0; + + command.clip[0] = _clipLeft; + command.clip[1] = _clipTop; + command.clip[2] = _clipRight; + command.clip[3] = _clipBottom; + + command.texColour = texture; + + command.bounds[0] = left; + command.bounds[1] = top; + command.bounds[2] = right; + command.bounds[3] = bottom; + + _commandBuffers.images.push_back(command); + FlushCommandBuffers(); +} + +void OpenGLDrawingContext::FlushCommandBuffers() { + FlushRectangles(); + FlushLines(); + FlushImages(); + FlushMaskedImages(); +} + +void OpenGLDrawingContext::FlushRectangles() { + for (const auto& command : _commandBuffers.rectangles) { + _fillRectShader->Use(); + _fillRectShader->SetFlags(command.flags); + _fillRectShader->SetSourceFramebuffer(command.sourceFramebuffer); + _fillRectShader->SetColour(0, command.colours[0]); + _fillRectShader->SetColour(1, command.colours[1]); + _fillRectShader->SetClip(command.clip[0], command.clip[1], command.clip[2], command.clip[3]); + _fillRectShader->Draw(command.bounds[0], command.bounds[1], command.bounds[2], command.bounds[3]); + } + + _commandBuffers.rectangles.clear(); +} + +void OpenGLDrawingContext::FlushLines() { + for (const auto& command : _commandBuffers.lines) { + _drawLineShader->Use(); + _drawLineShader->SetColour(command.colour); + _drawLineShader->SetClip(command.clip[0], command.clip[1], command.clip[2], command.clip[3]); + _drawLineShader->Draw(command.pos[0], command.pos[1], command.pos[2], command.pos[3]); + } + + _commandBuffers.lines.clear(); +} + +void OpenGLDrawingContext::FlushImages() { + for (const auto& command : _commandBuffers.images) { + _drawImageShader->Use(); + _drawImageShader->SetClip(_clipLeft, _clipTop, _clipRight, _clipBottom); + _drawImageShader->SetTexture(command.texColour); + _drawImageShader->SetFlags(command.flags); + _drawImageShader->SetColour(command.colour); + _drawImageShader->Draw(command.bounds[0], command.bounds[1], command.bounds[2], command.bounds[3]); + } + + _commandBuffers.images.clear(); +} + +void OpenGLDrawingContext::FlushMaskedImages() { + for (const auto& command : _commandBuffers.maskedImages) { + _drawImageMaskedShader->Use(); + _drawImageMaskedShader->SetClip(command.clip[0], command.clip[1], command.clip[2], command.clip[3]); + _drawImageMaskedShader->SetTextureMask(command.texMask); + _drawImageMaskedShader->SetTextureColour(command.texColour); + _drawImageMaskedShader->Draw(command.bounds[0], command.bounds[1], command.bounds[2], command.bounds[3]); + } + + _commandBuffers.maskedImages.clear(); } void OpenGLDrawingContext::SetDPI(rct_drawpixelinfo * dpi)