From 4896d14940d65e97593400e09db8d5ba151d816c Mon Sep 17 00:00:00 2001 From: Ted John Date: Sat, 11 Jun 2016 19:13:18 +0100 Subject: [PATCH] extract texture generation code to new class --- openrct2.vcxproj | 2 + .../engines/opengl/OpenGLDrawingEngine.cpp | 141 ++-------------- src/drawing/engines/opengl/TextureCache.cpp | 151 ++++++++++++++++++ src/drawing/engines/opengl/TextureCache.h | 41 +++++ src/drawing/sprite.c | 2 +- 5 files changed, 212 insertions(+), 125 deletions(-) create mode 100644 src/drawing/engines/opengl/TextureCache.cpp create mode 100644 src/drawing/engines/opengl/TextureCache.h diff --git a/openrct2.vcxproj b/openrct2.vcxproj index e55b959f7f..ec0c401011 100644 --- a/openrct2.vcxproj +++ b/openrct2.vcxproj @@ -62,6 +62,7 @@ + @@ -366,6 +367,7 @@ + diff --git a/src/drawing/engines/opengl/OpenGLDrawingEngine.cpp b/src/drawing/engines/opengl/OpenGLDrawingEngine.cpp index abfcf329c1..eb7d88c0cb 100644 --- a/src/drawing/engines/opengl/OpenGLDrawingEngine.cpp +++ b/src/drawing/engines/opengl/OpenGLDrawingEngine.cpp @@ -38,6 +38,7 @@ IDrawingEngine * DrawingEngineFactory::CreateOpenGL() #include "DrawLineShader.h" #include "FillRectShader.h" #include "SwapFramebuffer.h" +#include "TextureCache.h" #include "../../../core/Console.hpp" #include "../../../core/Exception.hpp" @@ -172,6 +173,9 @@ private: DrawImageMaskedShader * _drawImageMaskedShader = nullptr; DrawLineShader * _drawLineShader = nullptr; FillRectShader * _fillRectShader = nullptr; + + TextureCache * _textureCache = nullptr; + GLuint _vbo; sint32 _offsetX; @@ -181,14 +185,12 @@ private: sint32 _clipRight; sint32 _clipBottom; - std::vector _textures; - std::unordered_map _imageTextureMap; - public: - OpenGLDrawingContext(OpenGLDrawingEngine * engine); + explicit OpenGLDrawingContext(OpenGLDrawingEngine * engine); ~OpenGLDrawingContext() override; IDrawingEngine * GetEngine() override; + TextureCache * GetTextureCache() const { return _textureCache; } void Initialise(); @@ -201,13 +203,6 @@ public: void DrawSpriteSolid(uint32 image, sint32 x, sint32 y, uint8 colour) override; void SetDPI(rct_drawpixelinfo * dpi); - void InvalidateImage(uint32 image); - -private: - GLuint GetOrLoadImageTexture(uint32 image); - GLuint LoadImageTexture(uint32 image); - void * GetImageAsARGB(uint32 image, uint32 tertiaryColour, uint32 * outWidth, uint32 * outHeight); - void FreeTextures(); }; class OpenGLDrawingEngine : public IDrawingEngine @@ -292,6 +287,8 @@ public: colour.b / 255.0f, colour.a / 255.0f }; } + _drawingContext->GetTextureCache() + ->SetPalette(Palette); } void Invalidate(sint32 left, sint32 top, sint32 right, sint32 bottom) override @@ -366,7 +363,8 @@ public: void InvalidateImage(uint32 image) override { - _drawingContext->InvalidateImage(image); + _drawingContext->GetTextureCache() + ->InvalidateImage(image); } rct_drawpixelinfo * GetDPI() @@ -461,6 +459,7 @@ IDrawingEngine * DrawingEngineFactory::CreateOpenGL() OpenGLDrawingContext::OpenGLDrawingContext(OpenGLDrawingEngine * engine) { _engine = engine; + _textureCache = new TextureCache(); } OpenGLDrawingContext::~OpenGLDrawingContext() @@ -469,6 +468,8 @@ OpenGLDrawingContext::~OpenGLDrawingContext() delete _drawImageMaskedShader; delete _drawLineShader; delete _fillRectShader; + + delete _textureCache; } IDrawingEngine * OpenGLDrawingContext::GetEngine() @@ -571,7 +572,7 @@ void OpenGLDrawingContext::DrawSprite(uint32 image, sint32 x, sint32 y, uint32 t } } - GLuint texture = GetOrLoadImageTexture(image); + GLuint texture = _textureCache->GetOrLoadImageTexture(image); sint32 drawOffsetX = g1Element->x_offset; sint32 drawOffsetY = g1Element->y_offset; @@ -614,8 +615,8 @@ void OpenGLDrawingContext::DrawSpriteRawMasked(sint32 x, sint32 y, uint32 maskIm rct_g1_element * g1ElementMask = gfx_get_g1_element(maskImage & 0x7FFFF); rct_g1_element * g1ElementColour = gfx_get_g1_element(colourImage & 0x7FFFF); - GLuint textureMask = GetOrLoadImageTexture(maskImage); - GLuint textureColour = GetOrLoadImageTexture(colourImage); + GLuint textureMask = _textureCache->GetOrLoadImageTexture(maskImage); + GLuint textureColour = _textureCache->GetOrLoadImageTexture(colourImage); sint32 drawOffsetX = g1ElementMask->x_offset; sint32 drawOffsetY = g1ElementMask->y_offset; @@ -656,7 +657,7 @@ void OpenGLDrawingContext::DrawSpriteSolid(uint32 image, sint32 x, sint32 y, uin int g1Id = image & 0x7FFFF; rct_g1_element * g1Element = gfx_get_g1_element(g1Id); - GLuint texture = GetOrLoadImageTexture(image); + GLuint texture = _textureCache->GetOrLoadImageTexture(image); sint32 drawOffsetX = g1Element->x_offset; sint32 drawOffsetY = g1Element->y_offset; @@ -711,112 +712,4 @@ void OpenGLDrawingContext::SetDPI(rct_drawpixelinfo * dpi) _dpi = dpi; } -GLuint OpenGLDrawingContext::GetOrLoadImageTexture(uint32 image) -{ - auto kvp = _imageTextureMap.find(image); - if (kvp != _imageTextureMap.end()) - { - return kvp->second; - } - - GLuint texture = LoadImageTexture(image); - _textures.push_back(texture); - _imageTextureMap[image] = texture; - - // if ((_textures.size() % 100) == 0) - // { - // printf("Textures: %d\n", _textures.size()); - // } - - return texture; -} - -GLuint OpenGLDrawingContext::LoadImageTexture(uint32 image) -{ - GLuint texture; - glGenTextures(1, &texture); - - uint32 width, height; - void * pixels32 = GetImageAsARGB(image, 0, &width, &height); - - glBindTexture(GL_TEXTURE_2D, texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels32); - - delete [] (uint8 *) pixels32; - - return texture; -} - -void * OpenGLDrawingContext::GetImageAsARGB(uint32 image, uint32 tertiaryColour, uint32 * outWidth, uint32 * outHeight) -{ - int g1Id = image & 0x7FFFF; - rct_g1_element * g1Element = gfx_get_g1_element(g1Id); - - uint32 width = (uint32)g1Element->width; - uint32 height = (uint32)g1Element->height; - - size_t numPixels = width * height; - uint8 * pixels8 = new uint8[numPixels]; - Memory::Set(pixels8, 0, numPixels); - - rct_drawpixelinfo dpi; - dpi.bits = pixels8; - dpi.pitch = 0; - dpi.x = 0; - dpi.y = 0; - dpi.width = width; - dpi.height = height; - dpi.zoom_level = 0; - gfx_draw_sprite_software(&dpi, image, -g1Element->x_offset, -g1Element->y_offset, tertiaryColour); - - uint8 * pixels32 = new uint8[width * height * 4]; - uint8 * src = pixels8; - uint8 * dst = pixels32; - for (size_t i = 0; i < numPixels; i++) - { - uint8 paletteIndex = *src++; - if (paletteIndex == 0) - { - // Transparent - *dst++ = 0; - *dst++ = 0; - *dst++ = 0; - *dst++ = 0; - } - else - { - SDL_Color colour = _engine->Palette[paletteIndex]; - *dst++ = colour.r; - *dst++ = colour.g; - *dst++ = colour.b; - *dst++ = colour.a; - } - } - - delete[] pixels8; - - *outWidth = width; - *outHeight = height; - return pixels32; -} - -void OpenGLDrawingContext::InvalidateImage(uint32 image) -{ - auto kvp = _imageTextureMap.find(image); - if (kvp != _imageTextureMap.end()) - { - GLuint texture = kvp->second; - glDeleteTextures(1, &texture); - - _imageTextureMap.erase(kvp); - } -} - -void OpenGLDrawingContext::FreeTextures() -{ - glDeleteTextures(_textures.size(), _textures.data()); -} - #endif /* DISABLE_OPENGL */ diff --git a/src/drawing/engines/opengl/TextureCache.cpp b/src/drawing/engines/opengl/TextureCache.cpp new file mode 100644 index 0000000000..9f94bc916c --- /dev/null +++ b/src/drawing/engines/opengl/TextureCache.cpp @@ -0,0 +1,151 @@ +#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 + +#include "../../../core/Memory.hpp" +#include "TextureCache.h" + +extern "C" +{ + #include "../../drawing.h" +} + +TextureCache::TextureCache() +{ +} + +TextureCache::~TextureCache() +{ + FreeTextures(); +} + +void TextureCache::SetPalette(const SDL_Color * palette) +{ + Memory::CopyArray(_palette, palette, 256); +} + +void TextureCache::InvalidateImage(uint32 image) +{ + auto kvp = _imageTextureMap.find(image); + if (kvp != _imageTextureMap.end()) + { + GLuint texture = kvp->second; + glDeleteTextures(1, &texture); + + _imageTextureMap.erase(kvp); + } +} + +GLuint TextureCache::GetOrLoadImageTexture(uint32 image) +{ + auto kvp = _imageTextureMap.find(image); + if (kvp != _imageTextureMap.end()) + { + return kvp->second; + } + + GLuint texture = LoadImageTexture(image); + _imageTextureMap[image] = texture; + + // if ((_textures.size() % 100) == 0) + // { + // printf("Textures: %d\n", _textures.size()); + // } + + return texture; +} + +GLuint TextureCache::LoadImageTexture(uint32 image) +{ + GLuint texture; + glGenTextures(1, &texture); + + uint32 width, height; + void * pixels32 = GetImageAsARGB(image, 0, &width, &height); + + glBindTexture(GL_TEXTURE_2D, texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels32); + + delete [] (uint8 *) pixels32; + + return texture; +} + +void * TextureCache::GetImageAsARGB(uint32 image, uint32 tertiaryColour, uint32* outWidth, uint32* outHeight) +{ + int g1Id = image & 0x7FFFF; + rct_g1_element * g1Element = gfx_get_g1_element(g1Id); + + uint32 width = (uint32)g1Element->width; + uint32 height = (uint32)g1Element->height; + + size_t numPixels = width * height; + uint8 * pixels8 = new uint8[numPixels]; + Memory::Set(pixels8, 0, numPixels); + + rct_drawpixelinfo dpi; + dpi.bits = pixels8; + dpi.pitch = 0; + dpi.x = 0; + dpi.y = 0; + dpi.width = width; + dpi.height = height; + dpi.zoom_level = 0; + gfx_draw_sprite_software(&dpi, image, -g1Element->x_offset, -g1Element->y_offset, tertiaryColour); + + uint8 * pixels32 = new uint8[width * height * 4]; + uint8 * src = pixels8; + uint8 * dst = pixels32; + for (size_t i = 0; i < numPixels; i++) + { + uint8 paletteIndex = *src++; + if (paletteIndex == 0) + { + // Transparent + *dst++ = 0; + *dst++ = 0; + *dst++ = 0; + *dst++ = 0; + } + else + { + SDL_Color colour = _palette[paletteIndex]; + *dst++ = colour.r; + *dst++ = colour.g; + *dst++ = colour.b; + *dst++ = colour.a; + } + } + + delete[] pixels8; + + *outWidth = width; + *outHeight = height; + return pixels32; +} + +void TextureCache::FreeTextures() +{ + size_t numTextures = _imageTextureMap.size(); + auto textures = std::vector(numTextures); + for (auto kvp : _imageTextureMap) + { + textures.push_back(kvp.second); + } + + glDeleteTextures(textures.size(), textures.data()); +} diff --git a/src/drawing/engines/opengl/TextureCache.h b/src/drawing/engines/opengl/TextureCache.h new file mode 100644 index 0000000000..d0e9f54b8e --- /dev/null +++ b/src/drawing/engines/opengl/TextureCache.h @@ -0,0 +1,41 @@ +#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 +#include +#include "../../../common.h" +#include "OpenGLAPI.h" + +class TextureCache +{ +private: + std::unordered_map _imageTextureMap; + SDL_Color _palette[256]; + +public: + TextureCache(); + ~TextureCache(); + void SetPalette(const SDL_Color * palette); + void InvalidateImage(uint32 image); + GLuint GetOrLoadImageTexture(uint32 image); + +private: + GLuint LoadImageTexture(uint32 image); + void * GetImageAsARGB(uint32 image, uint32 tertiaryColour, uint32 * outWidth, uint32 * outHeight); + void FreeTextures(); +}; diff --git a/src/drawing/sprite.c b/src/drawing/sprite.c index 3fb9dfed32..f04cd9a5cf 100644 --- a/src/drawing/sprite.c +++ b/src/drawing/sprite.c @@ -383,7 +383,7 @@ void FASTCALL gfx_draw_sprite_palette_set_software(rct_drawpixelinfo *dpi, int i .pitch = dpi->pitch, .zoom_level = dpi->zoom_level - 1 }; - gfx_draw_sprite_palette_set(&zoomed_dpi, (image_type << 28) | (image_element - g1_source->zoomed_offset), x >> 1, y >> 1, palette_pointer, unknown_pointer); + gfx_draw_sprite_palette_set_software(&zoomed_dpi, (image_type << 28) | (image_element - g1_source->zoomed_offset), x >> 1, y >> 1, palette_pointer, unknown_pointer); return; }