1
0
mirror of https://github.com/blawar/GLideN64.git synced 2024-07-02 09:03:37 +00:00

Modifications for mip-mapped textures load.

Treat specail case for Southern Swamp grass texture, Zelda MM, #2315
This commit is contained in:
Sergey Lipskiy 2020-08-28 20:03:24 +07:00
parent 1e915af002
commit 35567da2ad

View File

@ -1077,34 +1077,65 @@ void TextureCache::_getTextureDestData(CachedTexture& tmptex,
}
}
template<typename T>
void doubleTexture(T* pTex, u32 width, u32 height)
{
std::vector<T> vData(width * height);
memcpy(vData.data(), pTex, width * height * sizeof(T));
u32 srcIdx = 0;
u32 dstIdx = 0;
for (u32 y = 0; y < height; ++y) {
const u32 srcIdxCur = srcIdx;
for (u32 x = 0; x < width; ++x) {
pTex[dstIdx++] = vData[srcIdx];
pTex[dstIdx++] = vData[srcIdx++];
}
srcIdx = srcIdxCur;
for (u32 x = 0; x < width; ++x) {
pTex[dstIdx++] = vData[srcIdx];
pTex[dstIdx++] = vData[srcIdx++];
}
}
}
void TextureCache::_load(u32 _tile, CachedTexture *_pTexture)
{
u64 ricecrc = 0;
if (_loadHiresTexture(_tile, _pTexture, ricecrc))
return;
u16 line;
GetTexelFunc GetTexel;
InternalColorFormatParam glInternalFormat;
DatatypeParam glType;
u32 sizeShift;
s32 mipLevel = 0;
bool force32bitFormat = false;
_pTexture->max_level = 0;
const TextureLoadParameters & loadParams =
ImageFormat::get().tlp[gDP.otherMode.textureLUT][_pTexture->size][_pTexture->format];
if (loadParams.autoFormat == internalcolorFormat::RGBA8) {
sizeShift = 2;
_pTexture->textureBytes = (_pTexture->width * _pTexture->height) << sizeShift;
GetTexel = loadParams.Get32;
glInternalFormat = loadParams.glInternalFormat32;
glType = loadParams.glType32;
} else {
sizeShift = 1;
_pTexture->textureBytes = (_pTexture->width * _pTexture->height) << sizeShift;
GetTexel = loadParams.Get16;
glInternalFormat = loadParams.glInternalFormat16;
glType = loadParams.glType16;
if (config.generalEmulation.enableLOD != 0 && gSP.texture.level > 1) {
if (_tile == 0) {
_pTexture->max_level = 0;
} else {
_pTexture->max_level = static_cast<u8>(gSP.texture.level - 1);
const u16 dim = std::max(_pTexture->width, _pTexture->height);
while (dim < static_cast<u16>(1 << _pTexture->max_level))
--_pTexture->max_level;
auto texFormat = gDP.tiles[gSP.texture.tile + 1].format;
auto texSize = gDP.tiles[gSP.texture.tile + 1].size;
u32 tileMipLevel = gSP.texture.tile + 2;
while (!force32bitFormat && (tileMipLevel < gSP.texture.tile + gSP.texture.level)) {
gDPTile const& mipTile = gDP.tiles[tileMipLevel++];
force32bitFormat = texFormat != mipTile.format || texSize != mipTile.size;
}
}
}
u32 sizeShift = 1;
{
const TextureLoadParameters & loadParams =
ImageFormat::get().tlp[gDP.otherMode.textureLUT][_pTexture->size][_pTexture->format];
if (force32bitFormat || loadParams.autoFormat == internalcolorFormat::RGBA8)
sizeShift = 2;
}
_pTexture->textureBytes = (_pTexture->width * _pTexture->height) << sizeShift;
// RAII holder for texture data
class TexData
{
@ -1127,29 +1158,54 @@ void TextureCache::_load(u32 _tile, CachedTexture *_pTexture)
u32 *pData = NULL;
} texData(_pTexture->textureBytes);
GetTexelFunc GetTexel;
InternalColorFormatParam glInternalFormat;
DatatypeParam glType;
s32 mipLevel = 0;
_pTexture->max_level = 0;
if (config.generalEmulation.enableLOD != 0 && gSP.texture.level > 1) {
if (_tile == 0) {
_pTexture->max_level = 0;
} else {
_pTexture->max_level = static_cast<u8>(gSP.texture.level - 1);
const u16 dim = std::max(_pTexture->width, _pTexture->height);
while (dim < static_cast<u16>(1 << _pTexture->max_level))
--_pTexture->max_level;
auto getLoadParams = [&](u16 _format, u16 _size)
{
const TextureLoadParameters & loadParams =
ImageFormat::get().tlp[gDP.otherMode.textureLUT][_size][_format];
if (force32bitFormat || loadParams.autoFormat == internalcolorFormat::RGBA8) {
GetTexel = loadParams.Get32;
glInternalFormat = loadParams.glInternalFormat32;
glType = loadParams.glType32;
}
}
else {
GetTexel = loadParams.Get16;
glInternalFormat = loadParams.glInternalFormat16;
glType = loadParams.glType16;
}
};
ObjectHandle name;
CachedTexture tmptex(name);
memcpy(&tmptex, _pTexture, sizeof(CachedTexture));
line = tmptex.line;
CachedTexture tmptex = *_pTexture;
u16 line = tmptex.line;
while (true) {
_getTextureDestData(tmptex, texData.get(), glInternalFormat, GetTexel, &line);
getLoadParams(tmptex.format, tmptex.size);
{
const u32 tileMipLevel = gSP.texture.tile + mipLevel + 1;
gDPTile & mipTile = gDP.tiles[tileMipLevel];
if (tmptex.max_level > 1 &&
tmptex.width == (mipTile.lrs - mipTile.uls + 1) * 2 &&
tmptex.height == (mipTile.lrt - mipTile.ult + 1) * 2)
{
// Special case for Southern Swamp grass texture, Zelda MM. See #2315
const u16 texWidth = tmptex.width;
const u16 texHeight = tmptex.height;
tmptex.width = mipTile.lrs - mipTile.uls + 1;
tmptex.height = mipTile.lrt - mipTile.ult + 1;
_getTextureDestData(tmptex, texData.get(), glInternalFormat, GetTexel, &line);
if (sizeShift == 2)
doubleTexture<u32>(texData.get(), tmptex.width, tmptex.height);
else
doubleTexture<u16>((u16*)texData.get(), tmptex.width, tmptex.height);
tmptex.width = texWidth;
tmptex.height = texHeight;
} else {
_getTextureDestData(tmptex, texData.get(), glInternalFormat, GetTexel, &line);
}
}
if ((config.generalEmulation.hacks&hack_LoadDepthTextures) != 0 && gDP.colorImage.address == gDP.depthImageAddress) {
_loadDepthTexture(_pTexture, (u16*)texData.get());
@ -1239,6 +1295,8 @@ void TextureCache::_load(u32 _tile, CachedTexture *_pTexture)
tmptex.palette = mipTile.palette;
tmptex.maskS = mipTile.masks;
tmptex.maskT = mipTile.maskt;
tmptex.format = mipTile.format;
tmptex.size = mipTile.size;
TileSizes sizes;
_calcTileSizes(tileMipLevel, sizes, nullptr);
tmptex.clampWidth = sizes.clampWidth;
@ -1529,6 +1587,7 @@ void TextureCache::update(u32 _t)
TileSizes sizes;
_calcTileSizes(_t, sizes, gDP.loadTile);
TextureParams params;
const u32 texLevel = _t == 0 ? 0U : gSP.texture.level;
params.flags = pTile->masks |
(pTile->maskt << 4) |
(pTile->mirrors << 8) |
@ -1537,7 +1596,8 @@ void TextureCache::update(u32 _t)
(pTile->clampt << 11) |
(pTile->size << 12) |
(pTile->format << 14) |
(gDP.otherMode.textureLUT << 17);
(gDP.otherMode.textureLUT << 17) |
(texLevel << 19);
params.width = sizes.width;
params.height = sizes.height;