1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-23 14:54:30 +01:00
Files
OpenRCT2/src/drawing/engines/opengl/TextureCache.cpp
2016-06-11 19:13:18 +01:00

152 lines
3.9 KiB
C++

#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());
}