1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2025-12-11 10:02:27 +01:00

Improve performance of panning the viewport with OpenGL renderer (#24413)

* Improve performance of panning the viewport with OpenGL renderer

* Use a shader to perform the copy rect operation

* Clear the frame buffer after its initialized

* Handle Y flip in shader, be explicit about FBO draw state

* Target 330 core, remove the y flip handling

* Explicitly use GL_RGB8 and not GL_RGB

* Add more error handling, clear depth when depth is created

* Lets try this

* Make sure blend and depth are disabled

* Bind the source fbo for reading

* Try this alternative approach

* Set read and draw buffer before glBlitFramebuffer

* Apple is forcing my hand

* Update changelog.txt
This commit is contained in:
Matt
2025-05-21 18:35:05 +03:00
committed by GitHub
parent 1cf3f50176
commit 01b577fa58
19 changed files with 383 additions and 85 deletions

View File

@@ -1,4 +1,4 @@
#version 150
#version 330 core
uniform vec4 uPalette[256];
uniform usampler2D uTexture;

View File

@@ -1,4 +1,4 @@
#version 150
#version 330 core
in vec4 vPosition;
in vec2 vTextureCoordinate;

View File

@@ -1,4 +1,4 @@
#version 150
#version 330 core
// clang-format off
uniform usampler2D uOpaqueTex;

View File

@@ -1,4 +1,4 @@
#version 150
#version 330 core
in vec4 vPosition;
in vec2 vTextureCoordinate;

View File

@@ -0,0 +1,11 @@
#version 330 core
in vec2 fTextureCoordinate;
out vec4 fragColor;
uniform sampler2D uTexture;
void main()
{
fragColor = texture(uTexture, fTextureCoordinate);
}

View File

@@ -0,0 +1,17 @@
#version 330 core
in vec2 vPosition;
in vec2 vTextureCoordinate;
out vec2 fTextureCoordinate;
uniform vec4 uSourceRect;
uniform vec2 uTextureSize;
void main()
{
gl_Position = vec4(vPosition, 0.0, 1.0);
vec2 srcPos = vec2(uSourceRect.xy);
vec2 srcSize = vec2(uSourceRect.zw);
fTextureCoordinate = (srcPos + vTextureCoordinate * srcSize) / uTextureSize;
}

View File

@@ -1,4 +1,4 @@
#version 150
#version 330 core
flat in uint fColour;

View File

@@ -1,4 +1,4 @@
#version 150
#version 330 core
// Allows for about 8 million draws per frame
const float DEPTH_INCREMENT = 1.0 / float(1u << 22u);

View File

@@ -1,4 +1,4 @@
#version 150
#version 330 core
// clang-format off
const int MASK_REMAP_COUNT = 3;

View File

@@ -1,4 +1,4 @@
#version 150
#version 330 core
// Allows for about 8 million draws per frame
const float DEPTH_INCREMENT = 1.0 / float(1u << 22u);

View File

@@ -5,6 +5,7 @@
- Improved: [#24364] Improve the fallback vehicle sprites for Zero G Rolls, and allow small ones to be built without cheats if the fallbacks are available.
- Improved: [#24368] Clicking the in-game update notication now leads to a more user-friendly download page.
- Improved: [#24409] Steam installs of RCT Classic are now detected automatically.
- Improved: [#24413] Better performance when moving the viewport on Windows and Linux platforms.
- Improved: [#24417] Improve the fallback vehicle sprites for Dive Loops.
- Change: [#24342] g2.dat is now split into g2.dat and fonts.dat.
- Change: [#24362] The Windows installer now prevents installing to the same folder as RollerCoaster Tycoon 2 or Classic.

View File

@@ -0,0 +1,96 @@
/*****************************************************************************
* Copyright (c) 2014-2025 OpenRCT2 developers
*
* For a complete list of all authors, please refer to contributors.md
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
*
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#ifndef DISABLE_OPENGL
#include "CopyRectShader.h"
using namespace OpenRCT2::Ui;
namespace
{
struct VDStruct
{
GLfloat position[2];
GLfloat texturecoordinate[2];
};
} // namespace
constexpr VDStruct kVertexData[4] = {
{ -1.0f, -1.0f, 0.0f, 0.0f },
{ 1.0f, -1.0f, 1.0f, 0.0f },
{ -1.0f, 1.0f, 0.0f, 1.0f },
{ 1.0f, 1.0f, 1.0f, 1.0f },
};
CopyRectShader::CopyRectShader()
: OpenGLShaderProgram("copyrect")
{
GetLocations();
glCall(glGenBuffers, 1, &_vbo);
glCall(glGenVertexArrays, 1, &_vao);
glCall(glBindBuffer, GL_ARRAY_BUFFER, _vbo);
glCall(glBufferData, GL_ARRAY_BUFFER, sizeof(kVertexData), kVertexData, GL_STATIC_DRAW);
glCall(glBindVertexArray, _vao);
glCall(
glVertexAttribPointer, vPosition, 2, GL_FLOAT, GL_FALSE, glSizeOf<VDStruct>(),
reinterpret_cast<void*>(offsetof(VDStruct, position)));
glCall(
glVertexAttribPointer, vTextureCoordinate, 2, GL_FLOAT, GL_FALSE, glSizeOf<VDStruct>(),
reinterpret_cast<void*>(offsetof(VDStruct, texturecoordinate)));
glCall(glEnableVertexAttribArray, vPosition);
glCall(glEnableVertexAttribArray, vTextureCoordinate);
Use();
glCall(glUniform1i, uTexture, 0); // Bind texture to unit 0
}
CopyRectShader::~CopyRectShader()
{
glCall(glDeleteBuffers, 1, &_vbo);
glCall(glDeleteVertexArrays, 1, &_vao);
}
void CopyRectShader::GetLocations()
{
uTexture = GetUniformLocation("uTexture");
uSourceRect = GetUniformLocation("uSourceRect");
uTextureSize = GetUniformLocation("uTextureSize");
vPosition = GetAttributeLocation("vPosition");
vTextureCoordinate = GetAttributeLocation("vTextureCoordinate");
}
void CopyRectShader::SetTexture(GLuint texture)
{
OpenGLAPI::SetTexture(0, GL_TEXTURE_2D, texture);
}
void CopyRectShader::SetSourceRect(int32_t x, int32_t y, int32_t width, int32_t height)
{
glUniform4f(
uSourceRect, static_cast<GLfloat>(x), static_cast<GLfloat>(y), static_cast<GLfloat>(width),
static_cast<GLfloat>(height));
}
void CopyRectShader::SetTextureSize(int32_t width, int32_t height)
{
glUniform2f(uTextureSize, static_cast<GLfloat>(width), static_cast<GLfloat>(height));
}
void CopyRectShader::Draw()
{
glCall(glBindVertexArray, _vao);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
#endif /* DISABLE_OPENGL */

View File

@@ -0,0 +1,43 @@
/*****************************************************************************
* Copyright (c) 2014-2025 OpenRCT2 developers
*
* For a complete list of all authors, please refer to contributors.md
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
*
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#pragma once
#include "GLSLTypes.h"
#include "OpenGLShaderProgram.h"
namespace OpenRCT2::Ui
{
class CopyRectShader final : public OpenGLShaderProgram
{
private:
GLint uTexture{ -1 };
GLint uSourceRect{ -1 };
GLint uTextureSize{ -1 };
GLint vPosition{ -1 };
GLint vTextureCoordinate{ -1 };
GLuint _vbo{};
GLuint _vao{};
public:
CopyRectShader();
~CopyRectShader() override;
static void SetTexture(GLuint texture);
void SetSourceRect(int32_t x, int32_t y, int32_t width, int32_t height);
void SetTextureSize(int32_t width, int32_t height);
void Draw();
private:
void GetLocations();
};
} // namespace OpenRCT2::Ui

View File

@@ -44,6 +44,13 @@
#define glGetIntegerv __static__glGetIntegerv
#define glGetTexImage __static__glGetTexImage
#define glTexSubImage2D __static__glTexSubImage2D
#define glDrawBuffers __static__glDrawBuffers
#define glCheckFramebufferStatus __static__glCheckFramebufferStatus
#define glClearDepth __static__glClearDepth
#define glReadBuffer __static__glReadBuffer
#define glDrawBuffer __static__glDrawBuffer
// END [Do not define 1.1 function signatures]
#endif
@@ -81,6 +88,11 @@
#undef glGetIntegerv
#undef glGetTexImage
#undef glTexSubImage2D
#undef glDrawBuffers
#undef glCheckFramebufferStatus
#undef glClearDepth
#undef glReadBuffer
#undef glDrawBuffer
// 1.1 function signatures
using PFNGLBEGINPROC = void(APIENTRYP)(GLenum mode);
@@ -116,6 +128,11 @@ using PFNGLGETTEXIMAGEPROC = void(APIENTRYP)(GLenum target, GLint level, GLenum
using PFNGLTEXSUBIMAGE2D = void(APIENTRYP)(
GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type,
const GLvoid* pixels);
using PFNGLDRAWBUFFERSPROC = void(APIENTRYP)(GLsizei n, const GLenum* bufs);
using PFNGLCHECKFRAMEBUFFERSTATUSPROC = GLenum(APIENTRYP)(GLenum target);
using PFNGLCLEARDEPTHPROC = void(APIENTRYP)(GLdouble depth);
using PFNGLREADBUFFERPROC = void(APIENTRYP)(GLenum mode);
using PFNGLDRAWBUFFERPROC = void(APIENTRYP)(GLenum mode);
#define OPENGL_PROC(TYPE, PROC) extern TYPE PROC;
#include "OpenGLAPIProc.h"

View File

@@ -91,6 +91,7 @@ OPENGL_PROC(PFNGLUNIFORM2FPROC, glUniform2f)
OPENGL_PROC(PFNGLUNIFORM4FPROC, glUniform4f)
OPENGL_PROC(PFNGLUNIFORM4IPROC, glUniform4i)
OPENGL_PROC(PFNGLUNIFORM4FVPROC, glUniform4fv)
OPENGL_PROC(PFNGLUNIFORM2FVPROC, glUniform2fv)
OPENGL_PROC(PFNGLUSEPROGRAMPROC, glUseProgram)
OPENGL_PROC(PFNGLVERTEXATTRIBIPOINTERPROC, glVertexAttribIPointer)
OPENGL_PROC(PFNGLVERTEXATTRIBPOINTERPROC, glVertexAttribPointer)
@@ -103,3 +104,8 @@ extern "C" void glVertexAttribDivisor(GLuint index, GLuint divisor);
#endif
OPENGL_PROC(PFNGLBLENDFUNCSEPARATEPROC, glBlendFuncSeparate)
OPENGL_PROC(PFNGLTEXSUBIMAGE2D, glTexSubImage2D)
OPENGL_PROC(PFNGLDRAWBUFFERSPROC, glDrawBuffers)
OPENGL_PROC(PFNGLCHECKFRAMEBUFFERSTATUSPROC, glCheckFramebufferStatus)
OPENGL_PROC(PFNGLCLEARDEPTHPROC, glClearDepth)
OPENGL_PROC(PFNGLREADBUFFERPROC, glReadBuffer)
OPENGL_PROC(PFNGLDRAWBUFFERPROC, glDrawBuffer)

View File

@@ -11,6 +11,7 @@
#include "../DrawingEngineFactory.hpp"
#include "ApplyPaletteShader.h"
#include "CopyRectShader.h"
#include "DrawCommands.h"
#include "DrawLineShader.h"
#include "DrawRectShader.h"
@@ -208,9 +209,12 @@ private:
std::unique_ptr<OpenGLDrawingContext> _drawingContext;
std::unique_ptr<ApplyPaletteShader> _applyPaletteShader;
std::unique_ptr<CopyRectShader> _copyRectShader;
std::unique_ptr<OpenGLFramebuffer> _screenFramebuffer;
std::unique_ptr<OpenGLFramebuffer> _scaleFramebuffer;
std::unique_ptr<OpenGLFramebuffer> _smoothScaleFramebuffer;
std::unique_ptr<OpenGLFramebuffer> _tempFramebuffer;
OpenGLWeatherDrawer _weatherDrawer;
InvalidationGrid _invalidationGrid;
@@ -236,9 +240,9 @@ public:
void Initialise() override
{
OpenGLVersion requiredVersion = kOpenGLMinimumRequiredVersion;
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, requiredVersion.Major);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, requiredVersion.Minor);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
_context = SDL_GL_CreateContext(_window);
if (_context == nullptr)
@@ -257,6 +261,7 @@ public:
_drawingContext->Initialise();
_applyPaletteShader = std::make_unique<ApplyPaletteShader>();
_copyRectShader = std::make_unique<CopyRectShader>();
}
void Resize(uint32_t width, uint32_t height) override
@@ -266,6 +271,7 @@ public:
ConfigureDirtyGrid();
_drawingContext->Resize(width, height);
_tempFramebuffer = std::make_unique<OpenGLFramebuffer>(width, height);
_drawingContext->StartNewDraw();
_drawingContext->Clear(_mainRT, PaletteIndex::pi10);
@@ -414,24 +420,70 @@ public:
_drawingContext->FlushCommandBuffers();
OpenGLFramebuffer& framebuffer = _drawingContext->GetFinalFramebuffer();
framebuffer.Bind();
framebuffer.GetPixels(_mainRT);
auto& framebuffer = _drawingContext->GetFinalFramebuffer();
const int32_t texWidth = static_cast<int32_t>(framebuffer.GetWidth());
const int32_t texHeight = static_cast<int32_t>(framebuffer.GetHeight());
// Originally 0x00683359
// Adjust for move off screen
// NOTE: when zooming, there can be x, y, dx, dy combinations that go off the
// screen; hence the checks. This code should ultimately not be called when
// zooming because this function is specific to updating the screen on move
int32_t lmargin = std::min(x - dx, 0);
int32_t rmargin = std::min(static_cast<int32_t>(_width) - (x - dx + width), 0);
int32_t rmargin = std::min(texWidth - (x - dx + width), 0);
int32_t tmargin = std::min(y - dy, 0);
int32_t bmargin = std::min(static_cast<int32_t>(_height) - (y - dy + height), 0);
int32_t bmargin = std::min(texHeight - (y - dy + height), 0);
x -= lmargin;
y -= tmargin;
width += lmargin + rmargin;
height += tmargin + bmargin;
if (width <= 0 || height <= 0)
return;
#ifndef __MACOSX__
auto& tempBuffer = *_tempFramebuffer;
const auto flipYAxis = [texHeight](int32_t yPos, int32_t h) {
// Convert to OpenGL bottom-left origin coords.
return texHeight - yPos - h;
};
int32_t srcX = x - dx;
int32_t srcY = flipYAxis(y - dy, height);
int32_t destX = x;
int32_t destY = flipYAxis(y, height);
glCall(glDisable, GL_BLEND);
glCall(glDisable, GL_DEPTH_TEST);
// First pass: Copy from main to temp
GLuint mainTexture = framebuffer.GetTexture();
tempBuffer.BindDraw();
framebuffer.BindRead();
glCall(glViewport, 0, 0, width, height);
_copyRectShader->Use();
_copyRectShader->SetTexture(mainTexture);
_copyRectShader->SetSourceRect(srcX, srcY, width, height);
_copyRectShader->SetTextureSize(texWidth, texHeight);
_copyRectShader->Draw();
// Second pass: Copy from temp to main
GLuint tempTexture = tempBuffer.GetTexture();
framebuffer.BindDraw();
tempBuffer.BindRead();
glCall(glViewport, destX, destY, width, height);
_copyRectShader->Use();
_copyRectShader->SetTexture(tempTexture);
_copyRectShader->SetSourceRect(0, 0, width, height);
_copyRectShader->SetTextureSize(texWidth, texHeight);
_copyRectShader->Draw();
#else
// Slow but functional path for MacOS, OpenGL is deprecated on MacOS
// and there seems to be issues that aren't present on other platforms.
framebuffer.GetPixels(_mainRT);
int32_t stride = _mainRT.LineStride();
uint8_t* to = _mainRT.bits + y * stride + x;
uint8_t* from = _mainRT.bits + (y - dy) * stride + x - dx;
@@ -453,6 +505,8 @@ public:
}
framebuffer.SetPixels(_mainRT);
#endif
}
IDrawingContext* GetDrawingContext() override

View File

@@ -33,20 +33,22 @@ OpenGLFramebuffer::OpenGLFramebuffer(int32_t width, int32_t height, bool depth,
_width = width;
_height = height;
glGenTextures(1, &_texture);
glBindTexture(GL_TEXTURE_2D, _texture);
glCall(glGenTextures, 1, &_texture);
glCall(glBindTexture, GL_TEXTURE_2D, _texture);
if (integer)
{
int internalFormat = word ? GL_R16UI : GL_R8UI;
int type = word ? GL_UNSIGNED_SHORT : GL_UNSIGNED_BYTE;
glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, GL_RED_INTEGER, type, nullptr);
glCall(glTexImage2D, GL_TEXTURE_2D, 0, internalFormat, width, height, 0, GL_RED_INTEGER, type, nullptr);
}
else
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
glCall(glTexImage2D, GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glCall(glTexParameteri, GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glCall(glTexParameteri, GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glCall(glTexParameteri, GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glCall(glTexParameteri, GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
if (depth)
{
@@ -57,36 +59,125 @@ OpenGLFramebuffer::OpenGLFramebuffer(int32_t width, int32_t height, bool depth,
_depth = 0;
}
glGenFramebuffers(1, &_id);
glBindFramebuffer(GL_FRAMEBUFFER, _id);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _texture, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, _depth, 0);
glCall(glGenFramebuffers, 1, &_id);
glCall(glBindFramebuffer, GL_FRAMEBUFFER, _id);
glCall(glFramebufferTexture2D, GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _texture, 0);
if (depth)
{
glCall(glFramebufferTexture2D, GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, _depth, 0);
}
// Verify completeness
const GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE)
{
const char* errorMsg = "Unknown error";
switch (status)
{
case GL_FRAMEBUFFER_UNDEFINED:
errorMsg = "Undefined";
break;
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
errorMsg = "Incomplete attachment";
break;
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
errorMsg = "Missing attachment";
break;
case GL_FRAMEBUFFER_UNSUPPORTED:
errorMsg = "Unsupported combination";
break;
}
LOG_ERROR("Framebuffer incomplete: (%u) %s", status, errorMsg);
}
const GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT0 };
glCall(glDrawBuffers, 1, drawBuffers);
// Clear the framebuffer.
glCall(glClearColor, 0, 0, 0, 0);
if (depth)
{
glCall(glClearDepth, 1.0f);
glCall(glClear, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
else
{
glCall(glClear, GL_COLOR_BUFFER_BIT);
}
glCall(glBindFramebuffer, GL_FRAMEBUFFER, 0);
}
OpenGLFramebuffer::~OpenGLFramebuffer()
{
if (_id != kBackBufferID)
{
glDeleteTextures(1, &_texture);
glDeleteTextures(1, &_depth);
glDeleteFramebuffers(1, &_id);
glCall(glDeleteTextures, 1, &_texture);
glCall(glDeleteTextures, 1, &_depth);
glCall(glDeleteFramebuffers, 1, &_id);
}
}
void OpenGLFramebuffer::Bind() const
{
glBindFramebuffer(GL_FRAMEBUFFER, _id);
glViewport(0, 0, static_cast<GLsizei>(_width), static_cast<GLsizei>(_height));
glCall(glBindFramebuffer, GL_FRAMEBUFFER, _id);
glCall(glViewport, 0, 0, static_cast<GLsizei>(_width), static_cast<GLsizei>(_height));
}
void OpenGLFramebuffer::BindDraw() const
{
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _id);
glCall(glBindFramebuffer, GL_DRAW_FRAMEBUFFER, _id);
}
void OpenGLFramebuffer::BindRead() const
{
glBindFramebuffer(GL_READ_FRAMEBUFFER, _id);
glCall(glBindFramebuffer, GL_READ_FRAMEBUFFER, _id);
}
void OpenGLFramebuffer::SwapColourBuffer(OpenGLFramebuffer& other)
{
std::swap(_texture, other._texture);
glCall(glBindFramebuffer, GL_FRAMEBUFFER, _id);
glCall(glFramebufferTexture2D, GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _texture, 0);
glCall(glBindFramebuffer, GL_FRAMEBUFFER, other._id);
glCall(glFramebufferTexture2D, GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, other._texture, 0);
}
GLuint OpenGLFramebuffer::SwapDepthTexture(GLuint depth)
{
std::swap(_depth, depth);
glCall(glBindFramebuffer, GL_FRAMEBUFFER, _id);
glCall(glFramebufferTexture2D, GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, _depth, 0);
return depth;
}
void OpenGLFramebuffer::Copy(OpenGLFramebuffer& src, GLenum filter)
{
BindDraw();
src.BindRead();
glCall(glBlitFramebuffer, 0, 0, src.GetWidth(), src.GetHeight(), 0, 0, _width, _height, GL_COLOR_BUFFER_BIT, filter);
Bind();
}
GLuint OpenGLFramebuffer::CreateDepthTexture(int32_t width, int32_t height)
{
GLuint depth;
glCall(glGenTextures, 1, &depth);
glCall(glBindTexture, GL_TEXTURE_2D, depth);
glCall(
glTexImage2D, GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);
glCall(glTexParameteri, GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glCall(glTexParameteri, GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glCall(glTexParameteri, GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
glCall(glTexParameteri, GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glCall(glTexParameteri, GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
return depth;
}
void OpenGLFramebuffer::GetPixels(RenderTarget& rt) const
@@ -94,9 +185,9 @@ void OpenGLFramebuffer::GetPixels(RenderTarget& rt) const
assert(rt.width == _width && rt.height == _height);
auto pixels = std::make_unique<uint8_t[]>(_width * _height);
glBindTexture(GL_TEXTURE_2D, _texture);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, pixels.get());
glCall(glBindTexture, GL_TEXTURE_2D, _texture);
glCall(glPixelStorei, GL_PACK_ALIGNMENT, 1);
glCall(glGetTexImage, GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, pixels.get());
// Flip pixels vertically on copy
uint8_t* src = pixels.get() + ((_height - 1) * _width);
@@ -109,47 +200,6 @@ void OpenGLFramebuffer::GetPixels(RenderTarget& rt) const
}
}
void OpenGLFramebuffer::SwapColourBuffer(OpenGLFramebuffer& other)
{
std::swap(_texture, other._texture);
glBindFramebuffer(GL_FRAMEBUFFER, _id);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _texture, 0);
glBindFramebuffer(GL_FRAMEBUFFER, other._id);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, other._texture, 0);
}
GLuint OpenGLFramebuffer::SwapDepthTexture(GLuint depth)
{
std::swap(_depth, depth);
glBindFramebuffer(GL_FRAMEBUFFER, _id);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, _depth, 0);
return depth;
}
void OpenGLFramebuffer::Copy(OpenGLFramebuffer& src, GLenum filter)
{
BindDraw();
src.BindRead();
glBlitFramebuffer(0, 0, src.GetWidth(), src.GetHeight(), 0, 0, _width, _height, GL_COLOR_BUFFER_BIT, filter);
Bind();
}
GLuint OpenGLFramebuffer::CreateDepthTexture(int32_t width, int32_t height)
{
GLuint depth;
glGenTextures(1, &depth);
glBindTexture(GL_TEXTURE_2D, depth);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
return depth;
}
void OpenGLFramebuffer::SetPixels(const RenderTarget& rt)
{
assert(rt.width == _width && rt.height == _height);
@@ -165,12 +215,9 @@ void OpenGLFramebuffer::SetPixels(const RenderTarget& rt)
dst -= _width;
}
glBindTexture(GL_TEXTURE_2D, _texture);
CheckGLError();
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
CheckGLError();
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, _width, _height, GL_RED_INTEGER, GL_UNSIGNED_BYTE, pixels.get());
CheckGLError();
glCall(glBindTexture, GL_TEXTURE_2D, _texture);
glCall(glPixelStorei, GL_UNPACK_ALIGNMENT, 1);
glCall(glTexSubImage2D, GL_TEXTURE_2D, 0, 0, 0, _width, _height, GL_RED_INTEGER, GL_UNSIGNED_BYTE, pixels.get());
}
#endif /* DISABLE_OPENGL */

View File

@@ -42,6 +42,10 @@ namespace OpenRCT2::Ui
{
return _height;
}
GLuint GetFBO() const
{
return _id;
}
GLuint GetTexture() const
{
return _texture;

View File

@@ -52,6 +52,7 @@
<ClInclude Include="drawing\engines\DrawingEngineFactory.hpp" />
<ClInclude Include="drawing\engines\opengl\ApplyPaletteShader.h" />
<ClInclude Include="drawing\engines\opengl\ApplyTransparencyShader.h" />
<ClInclude Include="drawing\engines\opengl\CopyRectShader.h" />
<ClInclude Include="drawing\engines\opengl\DrawCommands.h" />
<ClInclude Include="drawing\engines\opengl\DrawLineShader.h" />
<ClInclude Include="drawing\engines\opengl\DrawRectShader.h" />
@@ -119,6 +120,7 @@
<ClCompile Include="drawing\engines\HardwareDisplayDrawingEngine.cpp" />
<ClCompile Include="drawing\engines\opengl\ApplyPaletteShader.cpp" />
<ClCompile Include="drawing\engines\opengl\ApplyTransparencyShader.cpp" />
<ClCompile Include="drawing\engines\opengl\CopyRectShader.cpp" />
<ClCompile Include="drawing\engines\opengl\DrawLineShader.cpp" />
<ClCompile Include="drawing\engines\opengl\DrawRectShader.cpp" />
<ClCompile Include="drawing\engines\opengl\OpenGLAPI.cpp" />