1
0
mirror of https://github.com/blawar/GLideN64.git synced 2024-07-04 10:03:36 +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) void TextureCache::_load(u32 _tile, CachedTexture *_pTexture)
{ {
u64 ricecrc = 0; u64 ricecrc = 0;
if (_loadHiresTexture(_tile, _pTexture, ricecrc)) if (_loadHiresTexture(_tile, _pTexture, ricecrc))
return; return;
u16 line; s32 mipLevel = 0;
GetTexelFunc GetTexel; bool force32bitFormat = false;
InternalColorFormatParam glInternalFormat; _pTexture->max_level = 0;
DatatypeParam glType;
u32 sizeShift;
const TextureLoadParameters & loadParams = if (config.generalEmulation.enableLOD != 0 && gSP.texture.level > 1) {
ImageFormat::get().tlp[gDP.otherMode.textureLUT][_pTexture->size][_pTexture->format]; if (_tile == 0) {
if (loadParams.autoFormat == internalcolorFormat::RGBA8) { _pTexture->max_level = 0;
sizeShift = 2; } else {
_pTexture->textureBytes = (_pTexture->width * _pTexture->height) << sizeShift; _pTexture->max_level = static_cast<u8>(gSP.texture.level - 1);
GetTexel = loadParams.Get32; const u16 dim = std::max(_pTexture->width, _pTexture->height);
glInternalFormat = loadParams.glInternalFormat32; while (dim < static_cast<u16>(1 << _pTexture->max_level))
glType = loadParams.glType32; --_pTexture->max_level;
} else {
sizeShift = 1; auto texFormat = gDP.tiles[gSP.texture.tile + 1].format;
_pTexture->textureBytes = (_pTexture->width * _pTexture->height) << sizeShift; auto texSize = gDP.tiles[gSP.texture.tile + 1].size;
GetTexel = loadParams.Get16; u32 tileMipLevel = gSP.texture.tile + 2;
glInternalFormat = loadParams.glInternalFormat16; while (!force32bitFormat && (tileMipLevel < gSP.texture.tile + gSP.texture.level)) {
glType = loadParams.glType16; 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 // RAII holder for texture data
class TexData class TexData
{ {
@ -1127,29 +1158,54 @@ void TextureCache::_load(u32 _tile, CachedTexture *_pTexture)
u32 *pData = NULL; u32 *pData = NULL;
} texData(_pTexture->textureBytes); } texData(_pTexture->textureBytes);
GetTexelFunc GetTexel;
InternalColorFormatParam glInternalFormat;
DatatypeParam glType;
s32 mipLevel = 0; auto getLoadParams = [&](u16 _format, u16 _size)
_pTexture->max_level = 0; {
const TextureLoadParameters & loadParams =
if (config.generalEmulation.enableLOD != 0 && gSP.texture.level > 1) { ImageFormat::get().tlp[gDP.otherMode.textureLUT][_size][_format];
if (_tile == 0) { if (force32bitFormat || loadParams.autoFormat == internalcolorFormat::RGBA8) {
_pTexture->max_level = 0; GetTexel = loadParams.Get32;
} else { glInternalFormat = loadParams.glInternalFormat32;
_pTexture->max_level = static_cast<u8>(gSP.texture.level - 1); glType = loadParams.glType32;
const u16 dim = std::max(_pTexture->width, _pTexture->height);
while (dim < static_cast<u16>(1 << _pTexture->max_level))
--_pTexture->max_level;
} }
} else {
GetTexel = loadParams.Get16;
glInternalFormat = loadParams.glInternalFormat16;
glType = loadParams.glType16;
}
};
ObjectHandle name; CachedTexture tmptex = *_pTexture;
CachedTexture tmptex(name); u16 line = tmptex.line;
memcpy(&tmptex, _pTexture, sizeof(CachedTexture));
line = tmptex.line;
while (true) { 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) { if ((config.generalEmulation.hacks&hack_LoadDepthTextures) != 0 && gDP.colorImage.address == gDP.depthImageAddress) {
_loadDepthTexture(_pTexture, (u16*)texData.get()); _loadDepthTexture(_pTexture, (u16*)texData.get());
@ -1239,6 +1295,8 @@ void TextureCache::_load(u32 _tile, CachedTexture *_pTexture)
tmptex.palette = mipTile.palette; tmptex.palette = mipTile.palette;
tmptex.maskS = mipTile.masks; tmptex.maskS = mipTile.masks;
tmptex.maskT = mipTile.maskt; tmptex.maskT = mipTile.maskt;
tmptex.format = mipTile.format;
tmptex.size = mipTile.size;
TileSizes sizes; TileSizes sizes;
_calcTileSizes(tileMipLevel, sizes, nullptr); _calcTileSizes(tileMipLevel, sizes, nullptr);
tmptex.clampWidth = sizes.clampWidth; tmptex.clampWidth = sizes.clampWidth;
@ -1529,6 +1587,7 @@ void TextureCache::update(u32 _t)
TileSizes sizes; TileSizes sizes;
_calcTileSizes(_t, sizes, gDP.loadTile); _calcTileSizes(_t, sizes, gDP.loadTile);
TextureParams params; TextureParams params;
const u32 texLevel = _t == 0 ? 0U : gSP.texture.level;
params.flags = pTile->masks | params.flags = pTile->masks |
(pTile->maskt << 4) | (pTile->maskt << 4) |
(pTile->mirrors << 8) | (pTile->mirrors << 8) |
@ -1537,7 +1596,8 @@ void TextureCache::update(u32 _t)
(pTile->clampt << 11) | (pTile->clampt << 11) |
(pTile->size << 12) | (pTile->size << 12) |
(pTile->format << 14) | (pTile->format << 14) |
(gDP.otherMode.textureLUT << 17); (gDP.otherMode.textureLUT << 17) |
(texLevel << 19);
params.width = sizes.width; params.width = sizes.width;
params.height = sizes.height; params.height = sizes.height;