extract texture generation code to new class

This commit is contained in:
Ted John 2016-06-11 19:13:18 +01:00
parent 8185a88e47
commit 4896d14940
5 changed files with 212 additions and 125 deletions

View File

@ -62,6 +62,7 @@
<ClCompile Include="src\drawing\engines\opengl\OpenGLFramebuffer.cpp" />
<ClCompile Include="src\drawing\engines\opengl\OpenGLShaderProgram.cpp" />
<ClCompile Include="src\drawing\engines\opengl\SwapFramebuffer.cpp" />
<ClCompile Include="src\drawing\engines\opengl\TextureCache.cpp" />
<ClCompile Include="src\drawing\engines\SoftwareDrawingEngine.cpp" />
<ClCompile Include="src\drawing\font.c" />
<ClCompile Include="src\drawing\line.c" />
@ -366,6 +367,7 @@
<ClInclude Include="src\drawing\engines\opengl\OpenGLFramebuffer.h" />
<ClInclude Include="src\drawing\engines\opengl\OpenGLShaderProgram.h" />
<ClInclude Include="src\drawing\engines\opengl\SwapFramebuffer.h" />
<ClInclude Include="src\drawing\engines\opengl\TextureCache.h" />
<ClInclude Include="src\drawing\font.h" />
<ClInclude Include="src\drawing\IDrawingContext.h" />
<ClInclude Include="src\drawing\IDrawingEngine.h" />

View File

@ -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<GLuint> _textures;
std::unordered_map<uint32, GLuint> _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 */

View File

@ -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<GLuint>(numTextures);
for (auto kvp : _imageTextureMap)
{
textures.push_back(kvp.second);
}
glDeleteTextures(textures.size(), textures.data());
}

View File

@ -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 <unordered_map>
#include <SDL_pixels.h>
#include "../../../common.h"
#include "OpenGLAPI.h"
class TextureCache
{
private:
std::unordered_map<uint32, GLuint> _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();
};

View File

@ -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;
}