summaryrefslogtreecommitdiff
path: root/Source/Core/VideoCommon/HiresTextures.cpp
diff options
context:
space:
mode:
authordegasus <wickmarkus@web.de>2014-12-22 12:53:03 +0100
committerdegasus <wickmarkus@web.de>2014-12-29 10:24:21 +0100
commit51bfc4c52a49a01683192fafeeb5dd3506e838c9 (patch)
tree32577bc5a1ed493347918bd82144fdcc3b658281 /Source/Core/VideoCommon/HiresTextures.cpp
parenta09d8546364df7528d0d136db5067ede6bb089bc (diff)
VideoCommon: rewrite custom textures
Diffstat (limited to 'Source/Core/VideoCommon/HiresTextures.cpp')
-rw-r--r--Source/Core/VideoCommon/HiresTextures.cpp146
1 files changed, 74 insertions, 72 deletions
diff --git a/Source/Core/VideoCommon/HiresTextures.cpp b/Source/Core/VideoCommon/HiresTextures.cpp
index 2728725b25..dff31975c2 100644
--- a/Source/Core/VideoCommon/HiresTextures.cpp
+++ b/Source/Core/VideoCommon/HiresTextures.cpp
@@ -13,14 +13,14 @@
#include "Common/FileUtil.h"
#include "Common/StringUtil.h"
-#include "VideoCommon/HiresTextures.h"
+#include "Core/ConfigManager.h"
-namespace HiresTextures
-{
+#include "VideoCommon/HiresTextures.h"
+#include "VideoCommon/VideoConfig.h"
-static std::map<std::string, std::string> textureMap;
+std::unordered_map<std::string, std::string> HiresTexture::textureMap;
-void Init(const std::string& gameCode)
+void HiresTexture::Init(const std::string& gameCode)
{
textureMap.clear();
@@ -80,85 +80,87 @@ void Init(const std::string& gameCode)
}
}
-bool HiresTexExists(const std::string& filename)
+HiresTexture* HiresTexture::Search(const u8* texture, size_t texture_size, const u8* tlut, size_t tlut_size, u32 width, u32 height, int format)
{
- return textureMap.find(filename) != textureMap.end();
-}
+ u64 tex_hash = GetHashHiresTexture(texture, (int)texture_size, g_ActiveConfig.iSafeTextureCache_ColorSamples);
+ u64 tlut_hash = 0;
+ u64 hash = tex_hash;
+ if (tlut_size)
+ {
+ tlut_hash = GetHashHiresTexture(tlut, (int)tlut_size, g_ActiveConfig.iSafeTextureCache_ColorSamples);
+ hash ^= tlut_hash;
+ }
-PC_TexFormat GetHiresTex(const std::string& filename, unsigned int* pWidth, unsigned int* pHeight, unsigned int* required_size, int texformat, unsigned int data_size, u8* data)
-{
- if (textureMap.find(filename) == textureMap.end())
- return PC_TEX_FMT_NONE;
+ HiresTexture* ret = nullptr;
+ std::string base_filename = StringFromFormat("%s_%08x_%i", SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str(), (u32)hash, format);
+ for (int level = 0;; level++)
+ {
+ std::string filename = base_filename;
+ if (level)
+ {
+ filename += StringFromFormat("_mip%u", level);
+ }
- int width;
- int height;
- int channels;
+ if (textureMap.find(filename) != textureMap.end())
+ {
+ Level l;
- File::IOFile file;
- file.Open(textureMap[filename], "rb");
- std::vector<u8> buffer(file.GetSize());
- file.ReadBytes(buffer.data(), file.GetSize());
+ File::IOFile file;
+ file.Open(textureMap[filename], "rb");
+ std::vector<u8> buffer(file.GetSize());
+ file.ReadBytes(buffer.data(), file.GetSize());
- u8* temp = SOIL_load_image_from_memory(buffer.data(), (int)buffer.size(), &width, &height, &channels, SOIL_LOAD_RGBA);
+ int channels;
+ l.data = SOIL_load_image_from_memory(buffer.data(), (int)buffer.size(), (int*)&l.width, (int*)&l.height, &channels, SOIL_LOAD_RGBA);
+ l.data_size = (size_t)l.width * l.height * 4;
- if (temp == nullptr)
- {
- ERROR_LOG(VIDEO, "Custom texture %s failed to load", textureMap[filename].c_str());
- return PC_TEX_FMT_NONE;
- }
+ if (l.data == nullptr)
+ {
+ ERROR_LOG(VIDEO, "Custom texture %s failed to load", filename.c_str());
+ break;
+ }
- *pWidth = width;
- *pHeight = height;
+ if (!level)
+ {
+ if (l.width * height != l.height * width)
+ ERROR_LOG(VIDEO, "Invalid custom texture size %dx%d for texture %s. The aspect differs from the native size %dx%d.",
+ l.width, l.height, filename.c_str(), width, height);
+ if (l.width % width || l.height % height)
+ WARN_LOG(VIDEO, "Invalid custom texture size %dx%d for texture %s. Please use an integer upscaling factor based on the native size %dx%d.",
+ l.width, l.height, filename.c_str(), width, height);
+ width = l.width;
+ height = l.height;
+ }
+ else if (width != l.width || height != l.height)
+ {
+ ERROR_LOG(VIDEO, "Invalid custom texture size %dx%d for texture %s. This mipmap layer _must_ be %dx%d.",
+ l.width, l.height, filename.c_str(), width, height);
+ SOIL_free_image_data(l.data);
+ break;
+ }
- //int offset = 0;
- PC_TexFormat returnTex = PC_TEX_FMT_NONE;
+ // calculate the size of the next mipmap
+ width >>= 1;
+ height >>= 1;
- // TODO(neobrain): This function currently has no way to enforce RGBA32
- // output, which however is required on some configurations to function
- // properly. As a lazy workaround, we hence disable the optimized code
- // path for now.
-#if 0
- switch (texformat)
- {
- case GX_TF_I4:
- case GX_TF_I8:
- case GX_TF_IA4:
- case GX_TF_IA8:
- *required_size = width * height * 8;
- if (data_size < *required_size)
- goto cleanup;
-
- for (int i = 0; i < width * height * 4; i += 4)
+ if (!ret)
+ ret = new HiresTexture();
+ ret->m_levels.push_back(l);
+ }
+ else
{
- // Rather than use a luminosity function, just use the most intense color for luminance
- // TODO(neobrain): Isn't this kind of.. stupid?
- data[offset++] = *std::max_element(temp+i, temp+i+3);
- data[offset++] = temp[i+3];
+ break;
}
- returnTex = PC_TEX_FMT_IA8;
- break;
- default:
- *required_size = width * height * 4;
- if (data_size < *required_size)
- goto cleanup;
-
- memcpy(data, temp, width * height * 4);
- returnTex = PC_TEX_FMT_RGBA32;
- break;
}
-#else
- *required_size = width * height * 4;
- if (data_size < *required_size)
- goto cleanup;
-
- memcpy(data, temp, width * height * 4);
- returnTex = PC_TEX_FMT_RGBA32;
-#endif
-
- INFO_LOG(VIDEO, "Loading custom texture from %s", textureMap[filename].c_str());
-cleanup:
- SOIL_free_image_data(temp);
- return returnTex;
+
+ return ret;
}
+HiresTexture::~HiresTexture()
+{
+ for (auto& l : m_levels)
+ {
+ SOIL_free_image_data(l.data);
+ }
}
+