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)