Owner-authorized source migration: 31 helper-only translation units were merged into their callers or existing inline headers; both build manifests updated. Includes the preserved source payload, Lua configuration matching wowdecomp, and exact malloca expansion without diagnostic pragmas. 449 native units compiled locally and 449 staged units compiled by the pinned server toolchain. No previously byte-matched function regressed. Compiler mapping diagnostics remain recorded as needs_cleanup, not accepted or peer-confirmed. Existing independent review records are preserved. README.md is intentionally unchanged.
154 lines
4.5 KiB
C++
154 lines
4.5 KiB
C++
#include "Render/RenderSystemBase.h"
|
|
#include "Render/Textures/Texture.h"
|
|
#include "Render/Textures/TextureCache.h"
|
|
#include "Resource/Bitmap/BitmapResource.h"
|
|
#include "Resource/ResourceMgr.h"
|
|
|
|
#include <cstring>
|
|
#include <windows.h>
|
|
#include <timeapi.h>
|
|
|
|
// INLINED
|
|
bool TextureNameLess::operator()(const char* left, const char* right) const {
|
|
return std::strcmp(left, right) < 0;
|
|
}
|
|
|
|
// OFFSET: 0x004074F5
|
|
// FUNCTION: fn_00152
|
|
TextureCache::TextureCache(ResourceMgr& resources, CRenderSystemBase*& system, TextureSources& sources, const int& reduction, const unsigned& reuseDelay)
|
|
: m_resources(resources), m_system(system), m_sources(sources), m_reduction(reduction), m_reuseDelay(reuseDelay) {
|
|
}
|
|
|
|
// OFFSET: 0x005713C0
|
|
// FUNCTION: fn_02447
|
|
TextureCache::~TextureCache() {
|
|
this->Clear();
|
|
}
|
|
|
|
// OFFSET: 0x00571790
|
|
// FUNCTION: fn_02453
|
|
CTexture* TextureCache::Default() {
|
|
return this->m_system ? this->m_system->BackBufferTexture() : nullptr;
|
|
}
|
|
|
|
// OFFSET: 0x005715E0
|
|
// FUNCTION: fn_02449
|
|
CTexture* TextureCache::Upload(int width, int height, const std::uint32_t* pixels, int format, int option, bool fullSize, bool dynamic, bool renderTarget) {
|
|
const int outputWidth = fullSize ? width : width / this->m_reduction;
|
|
const int outputHeight = fullSize ? height : height / this->m_reduction;
|
|
CTexture* texture = this->m_system ? this->m_system->CreateTexture(outputWidth, outputHeight, format, dynamic, renderTarget) : nullptr;
|
|
|
|
if (texture) {
|
|
texture->Upload(0, 0, width, height, pixels, option, 0);
|
|
texture->unknown_0008 = (texture->unknown_0008 & 0xFF00u) | fullSize;
|
|
}
|
|
|
|
return texture;
|
|
}
|
|
|
|
// OFFSET: 0x00571930
|
|
// FUNCTION: fn_02455
|
|
CTexture* TextureCache::Create(const char* name, int option, bool fullSize, bool dynamic, bool renderTarget) {
|
|
if (std::strstr(name, ".bik")) {
|
|
int width;
|
|
int height;
|
|
|
|
if (this->m_sources.MovieSize(name, width, height)) {
|
|
CTexture* texture = this->m_system ? this->m_system->CreateTexture(width, height, TextureFormat::A8R8G8B8, false, false) : nullptr;
|
|
|
|
if (texture) {
|
|
return texture;
|
|
}
|
|
}
|
|
} else {
|
|
auto* bitmap = static_cast<CBitmapRes*>(this->m_resources.Load(this->m_sources.Resolve(name)));
|
|
|
|
if (bitmap) {
|
|
const auto& image = bitmap->image;
|
|
CTexture* texture = this->Upload(
|
|
image.width, image.height, image.pixels, image.alpha != 0 ? TextureFormat::A4R4G4B4 : TextureFormat::A1R5G5B5, option, fullSize, dynamic, renderTarget
|
|
);
|
|
this->m_resources.Remove(bitmap);
|
|
|
|
return texture;
|
|
}
|
|
}
|
|
|
|
const int extent = 1 / this->m_reduction;
|
|
CTexture* texture = this->m_system ? this->m_system->CreateTexture(extent, extent, TextureFormat::A1R5G5B5, false, false) : nullptr;
|
|
|
|
if (texture) {
|
|
const std::uint32_t transparent = 0;
|
|
texture->Upload(0, 0, 1, 1, &transparent, option, 0);
|
|
texture->unknown_0008 &= 0xFF00u;
|
|
}
|
|
|
|
return texture;
|
|
}
|
|
|
|
// OFFSET: 0x005717A0
|
|
// FUNCTION: fn_02454
|
|
CTexture* TextureCache::Load(const char* name, int option, bool fullSize, bool dynamic, bool renderTarget) {
|
|
const auto found = this->m_textures.find(name);
|
|
|
|
if (found != this->m_textures.end() && found->second) {
|
|
found->second->unknown_0020 = timeGetTime();
|
|
return found->second;
|
|
}
|
|
|
|
CTexture* texture = this->Create(name, option, fullSize, dynamic, renderTarget);
|
|
|
|
if (!texture) {
|
|
return this->Default();
|
|
}
|
|
|
|
strncpy_s(texture->m_name, sizeof(texture->m_name), name, _TRUNCATE);
|
|
texture->unknown_0020 = timeGetTime();
|
|
this->m_textures.emplace(texture->m_name, texture);
|
|
|
|
return texture;
|
|
}
|
|
|
|
// OFFSET: 0x005716F0
|
|
// FUNCTION: fn_02452
|
|
void TextureCache::Remove(CTexture* texture) {
|
|
if (texture->unknown_001C == 0 && texture != this->Default()) {
|
|
const auto found = this->m_textures.find(texture->m_name);
|
|
|
|
if (found != this->m_textures.end()) {
|
|
delete found->second;
|
|
this->m_textures.erase(found);
|
|
}
|
|
}
|
|
}
|
|
|
|
// OFFSET: 0x00571670
|
|
// FUNCTION: fn_02451
|
|
void TextureCache::Clear() {
|
|
for (auto& [name, texture] : this->m_textures) {
|
|
delete texture;
|
|
}
|
|
|
|
this->m_textures.clear();
|
|
}
|
|
|
|
// OFFSET: 0x00571C50
|
|
// FUNCTION: fn_02457
|
|
void TextureCache::ClearUnused() {
|
|
const unsigned threshold = timeGetTime() - this->m_reuseDelay;
|
|
|
|
for (auto entry = this->m_textures.begin(); entry != this->m_textures.end();) {
|
|
CTexture* texture = entry->second;
|
|
|
|
if (texture->unknown_001C != 0 || texture->unknown_0020 >= threshold) {
|
|
++entry;
|
|
} else {
|
|
delete texture;
|
|
entry = this->m_textures.erase(entry);
|
|
}
|
|
}
|
|
|
|
HeapCompact(GetProcessHeap(), 0);
|
|
|
|
this->m_sources.CleanupTextures();
|
|
}
|