fixed xfb bumping introduced by my last commit.

implemented loading of native mips, see sms water :).

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5366 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
Rodolfo Osvaldo Bogado 2010-04-14 13:57:16 +00:00
parent 1483715567
commit a25dfc47b4
10 changed files with 123 additions and 33 deletions

View File

@ -55,6 +55,10 @@ inline void AtomicIncrement(volatile u32& target) {
InterlockedIncrement((volatile LONG*)&target);
}
inline void AtomicDecrement(volatile u32& target) {
InterlockedDecrement((volatile LONG*)&target);
}
inline u32 AtomicLoad(volatile u32& src) {
return src; // 32-bit reads are always atomic.
}

View File

@ -21,7 +21,7 @@
namespace D3D
{
LPDIRECT3DTEXTURE9 CreateTexture2D(const u8* buffer, const int width, const int height, const int pitch, D3DFORMAT fmt, bool swap_r_b)
LPDIRECT3DTEXTURE9 CreateTexture2D(const u8* buffer, const int width, const int height, const int pitch, D3DFORMAT fmt, bool swap_r_b, int levels)
{
u32* pBuffer = (u32*)buffer;
LPDIRECT3DTEXTURE9 pTexture;
@ -38,8 +38,8 @@ LPDIRECT3DTEXTURE9 CreateTexture2D(const u8* buffer, const int width, const int
HRESULT hr;
// TODO(ector): Allow mipmaps for non-pow textures on newer cards?
// TODO(ector): Use the game-specified mipmaps?
if (!isPow2)
hr = dev->CreateTexture(width, height, 1, 0, fmt, D3DPOOL_MANAGED, &pTexture, NULL);
if (levels > 0)
hr = dev->CreateTexture(width, height, levels, 0, fmt, D3DPOOL_MANAGED, &pTexture, NULL);
else
hr = dev->CreateTexture(width, height, 0, D3DUSAGE_AUTOGENMIPMAP, fmt, D3DPOOL_MANAGED, &pTexture, NULL);
@ -148,10 +148,9 @@ LPDIRECT3DTEXTURE9 CreateOnlyTexture2D(const int width, const int height, D3DFOR
return pTexture;
}
void ReplaceTexture2D(LPDIRECT3DTEXTURE9 pTexture, const u8* buffer, const int width, const int height, const int pitch, D3DFORMAT fmt, bool swap_r_b)
void ReplaceTexture2D(LPDIRECT3DTEXTURE9 pTexture, const u8* buffer, const int width, const int height, const int pitch, D3DFORMAT fmt, bool swap_r_b, int level)
{
u32* pBuffer = (u32*)buffer;
int level = 0;
D3DLOCKED_RECT Lock;
pTexture->LockRect(level, &Lock, NULL, 0);
u32* pIn = pBuffer;

View File

@ -21,8 +21,8 @@
namespace D3D
{
LPDIRECT3DTEXTURE9 CreateTexture2D(const u8* buffer, const int width, const int height, const int pitch, D3DFORMAT fmt = D3DFMT_A8R8G8B8, bool swap_r_b = false);
void ReplaceTexture2D(LPDIRECT3DTEXTURE9 pTexture, const u8* buffer, const int width, const int height, const int pitch, D3DFORMAT fmt, bool swap_r_b);
LPDIRECT3DTEXTURE9 CreateTexture2D(const u8* buffer, const int width, const int height, const int pitch, D3DFORMAT fmt = D3DFMT_A8R8G8B8, bool swap_r_b = false, int levels = 1);
void ReplaceTexture2D(LPDIRECT3DTEXTURE9 pTexture, const u8* buffer, const int width, const int height, const int pitch, D3DFORMAT fmt, bool swap_r_b, int level = 0);
LPDIRECT3DTEXTURE9 CreateRenderTarget(const int width, const int height);
LPDIRECT3DSURFACE9 CreateDepthStencilSurface(const int width, const int height);
LPDIRECT3DTEXTURE9 CreateOnlyTexture2D(const int width, const int height, D3DFORMAT fmt);

View File

@ -1015,6 +1015,7 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight)
// EFB is copied to XFB. In this way, flickering is reduced in games
// and seems to also give more FPS in ZTP
if (field == FIELD_LOWER) xfbAddr -= fbWidth * 2;
u32 xfbCount = 0;
const XFBSource** xfbSourceList = FBManager.GetXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount);
if (!xfbSourceList || xfbCount == 0)
@ -1389,6 +1390,7 @@ void Renderer::SetSamplerState(int stage, int texindex)
{
const FourTexUnits &tex = bpmem.tex[texindex];
const TexMode0 &tm0 = tex.texMode0[stage];
const TexMode1 &tm1 = tex.texMode1[stage];
D3DTEXTUREFILTERTYPE min, mag, mip;
if (g_ActiveConfig.bForceFiltering)
@ -1399,7 +1401,7 @@ void Renderer::SetSamplerState(int stage, int texindex)
{
min = (tm0.min_filter & 4) ? D3DTEXF_LINEAR : D3DTEXF_POINT;
mag = tm0.mag_filter ? D3DTEXF_LINEAR : D3DTEXF_POINT;
mip = d3dMipFilters[tm0.min_filter & 3];
mip = (tm0.min_filter == 8)?D3DTEXF_NONE:d3dMipFilters[tm0.min_filter & 3];
}
if (texindex)
stage += 4;
@ -1415,11 +1417,9 @@ void Renderer::SetSamplerState(int stage, int texindex)
D3D::SetSamplerState(stage, D3DSAMP_ADDRESSU, d3dClamps[tm0.wrap_s]);
D3D::SetSamplerState(stage, D3DSAMP_ADDRESSV, d3dClamps[tm0.wrap_t]);
//wip
//dev->SetSamplerState(stage,D3DSAMP_MIPMAPLODBIAS,tm0.lod_bias/4.0f);
//char temp[256];
//sprintf(temp,"lod %f",tm0.lod_bias/4.0f);
//g_VideoInitialize.pLog(temp);
//just a test but it seems to work
D3D::SetSamplerState(stage,D3DSAMP_MIPMAPLODBIAS,tm0.lod_bias/2.0f);
D3D::SetSamplerState(stage,D3DSAMP_MAXMIPLEVEL,tm1.min_lod>>4);
}
void Renderer::SetInterlacingMode()

View File

@ -136,7 +136,7 @@ void TextureCache::Cleanup()
}
}
TextureCache::TCacheEntry *TextureCache::Load(int stage, u32 address, int width, int height, int tex_format, int tlutaddr, int tlutfmt)
TextureCache::TCacheEntry *TextureCache::Load(int stage, u32 address, int width, int height, int tex_format, int tlutaddr, int tlutfmt,bool UseNativeMips, int maxlevel)
{
if (address == 0)
return NULL;
@ -144,6 +144,7 @@ TextureCache::TCacheEntry *TextureCache::Load(int stage, u32 address, int width,
u8 *ptr = g_VideoInitialize.pGetMemoryPointer(address);
int bsw = TexDecoder_GetBlockWidthInTexels(tex_format) - 1; //TexelSizeInNibbles(format)*width*height/16;
int bsh = TexDecoder_GetBlockHeightInTexels(tex_format) - 1; //TexelSizeInNibbles(format)*width*height/16;
int bsdepth = TexDecoder_GetTexelSizeInNibbles(tex_format);
int expandedWidth = (width + bsw) & (~bsw);
int expandedHeight = (height + bsh) & (~bsh);
@ -279,12 +280,41 @@ TextureCache::TCacheEntry *TextureCache::Load(int stage, u32 address, int width,
entry.addr = address;
entry.size_in_bytes = TexDecoder_GetTextureSizeInBytes(width, height, tex_format);
entry.isRenderTarget = false;
entry.isNonPow2 = false;//((width & (width - 1)) || (height & (height - 1)));
if (!skip_texture_create) {
entry.texture = D3D::CreateTexture2D((BYTE*)temp, width, height, expandedWidth, d3d_fmt, swap_r_b);
} else {
bool isPow2 = !((width & (width - 1)) || (height & (height - 1)));
entry.isNonPow2 = false;
int TexLevels = (width > height)?width:height;
TexLevels = (isPow2 && UseNativeMips) ? (int)(log((double)TexLevels)/log((double)2)) + 1 : (isPow2?0:1);
if(TexLevels > maxlevel && maxlevel > 0)
TexLevels = maxlevel;
if (!skip_texture_create)
{
entry.texture = D3D::CreateTexture2D((BYTE*)temp, width, height, expandedWidth, d3d_fmt, swap_r_b,TexLevels);
}
else
{
D3D::ReplaceTexture2D(entry.texture, (BYTE*)temp, width, height, expandedWidth, d3d_fmt, swap_r_b);
}
if(TexLevels > 1 && pcfmt != PC_TEX_FMT_NONE)
{
int level = 1;
int mipWidth = (width + 1) >> 1;
int mipHeight = (height + 1) >> 1;
ptr += entry.size_in_bytes;
while((mipHeight || mipWidth) && (level < TexLevels))
{
u32 currentWidth = (mipWidth > 0)? mipWidth : 1;
u32 currentHeight = (mipHeight > 0)? mipHeight : 1;
expandedWidth = (currentWidth + bsw) & (~bsw);
expandedHeight = (currentHeight + bsh) & (~bsh);
TexDecoder_Decode(temp, ptr, expandedWidth, expandedHeight, tex_format, tlutaddr, tlutfmt);
D3D::ReplaceTexture2D(entry.texture, (BYTE*)temp, currentWidth, currentHeight, expandedWidth, d3d_fmt, swap_r_b,level);
u32 size = (max(mipWidth, bsw) * max(mipHeight, bsh) * bsdepth) >> 1;
ptr += size;
mipWidth >>= 1;
mipHeight >>= 1;
level++;
}
}
entry.frameCount = frameCount;
entry.w = width;
entry.h = height;

View File

@ -82,7 +82,7 @@ public:
static void Shutdown();
static void Invalidate(bool shutdown);
static void InvalidateRange(u32 start_address, u32 size);
static TCacheEntry *Load(int stage, u32 address, int width, int height, int format, int tlutaddr, int tlutfmt);
static TCacheEntry *Load(int stage, u32 address, int width, int height, int format, int tlutaddr, int tlutfmt,bool UseNativeMips, int maxlevel);
static void CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle &source_rect);
};

View File

@ -249,7 +249,9 @@ void Flush()
(tex.texImage3[i&3].image_base/* & 0x1FFFFF*/) << 5,
tex.texImage0[i&3].width + 1, tex.texImage0[i&3].height + 1,
tex.texImage0[i&3].format, tex.texTlut[i&3].tmem_offset<<9,
tex.texTlut[i&3].tlut_format);
tex.texTlut[i&3].tlut_format,
(tex.texMode0[i&3].min_filter & 3) && (tex.texMode0[i&3].min_filter != 8),
(tex.texMode1[i&3].max_lod >> 4));
if (tentry) {
PixelShaderManager::SetTexDims(i, tentry->w, tentry->h, 0, 0);

View File

@ -795,7 +795,7 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight)
g_VideoInitialize.pCopiedToXFB(false);
return;
}
if (field == FIELD_LOWER) xfbAddr -= fbWidth * 2;
u32 xfbCount = 0;
const XFBSource** xfbSourceList = g_framebufferManager.GetXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount);
if (!xfbSourceList)

View File

@ -103,9 +103,10 @@ bool TextureMngr::TCacheEntry::IntersectsMemoryRange(u32 range_address, u32 rang
return true;
}
void TextureMngr::TCacheEntry::SetTextureParameters(TexMode0 &newmode)
void TextureMngr::TCacheEntry::SetTextureParameters(TexMode0 &newmode,TexMode1 &newmode1)
{
mode = newmode;
mode1 = newmode1;
if (isRectangle)
{
// very limited!
@ -130,6 +131,10 @@ void TextureMngr::TCacheEntry::SetTextureParameters(TexMode0 &newmode)
if (g_ActiveConfig.bForceFiltering && newmode.min_filter < 4)
newmode.min_filter += 4; // take equivalent forced linear
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, c_MinLinearFilter[filt]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, newmode1.min_lod >> 4);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, newmode1.max_lod >> 4);
//glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, (newmode.lod_bias/2.0f));
}
else
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
@ -251,9 +256,15 @@ TextureMngr::TCacheEntry* TextureMngr::Load(int texstage, u32 address, int width
return NULL;
TexMode0 &tm0 = bpmem.tex[texstage > 3].texMode0[texstage & 3];
TexMode1 &tm1 = bpmem.tex[texstage > 3].texMode1[texstage & 3];
bool UseNativeMips = (tm0.min_filter & 3) && (tm0.min_filter != 8);
int maxlevel = (tm1.max_lod >> 4);
u8 *ptr = g_VideoInitialize.pGetMemoryPointer(address);
int bsw = TexDecoder_GetBlockWidthInTexels(tex_format) - 1;
int bsh = TexDecoder_GetBlockHeightInTexels(tex_format) - 1;
int bsdepth = TexDecoder_GetTexelSizeInNibbles(tex_format);
int expandedWidth = (width + bsw) & (~bsw);
int expandedHeight = (height + bsh) & (~bsh);
@ -303,8 +314,8 @@ TextureMngr::TCacheEntry* TextureMngr::Load(int texstage, u32 address, int width
// entry.isRectangle ? TextureMngr::EnableTex2D(texstage) : TextureMngr::EnableTexRECT(texstage);
glBindTexture(entry.isRectangle ? GL_TEXTURE_RECTANGLE_ARB : GL_TEXTURE_2D, entry.texture);
GL_REPORT_ERRORD();
if (entry.mode.hex != tm0.hex)
entry.SetTextureParameters(tm0);
if (entry.mode.hex != tm0.hex || entry.mode1.hex != tm1.hex)
entry.SetTextureParameters(tm0,tm1);
//DebugLog("%cC addr: %08x | fmt: %i | e.hash: %08x | w:%04i h:%04i", g_ActiveConfig.bSafeTextureCache ? 'S' : 'U'
// , address, tex_format, entry.hash, width, height);
return &entry;
@ -318,8 +329,8 @@ TextureMngr::TCacheEntry* TextureMngr::Load(int texstage, u32 address, int width
{
glBindTexture(entry.isRectangle ? GL_TEXTURE_RECTANGLE_ARB : GL_TEXTURE_2D, entry.texture);
GL_REPORT_ERRORD();
if (entry.mode.hex != tm0.hex)
entry.SetTextureParameters(tm0);
if (entry.mode.hex != tm0.hex || entry.mode1.hex != tm1.hex)
entry.SetTextureParameters(tm0,tm1);
skip_texture_create = true;
}
else
@ -380,14 +391,20 @@ TextureMngr::TCacheEntry* TextureMngr::Load(int texstage, u32 address, int width
glBindTexture(target, entry.texture);
}
bool isPow2 = !((width & (width - 1)) || (height & (height - 1)));
int TexLevels = (width > height)?width:height;
TexLevels = (isPow2 && UseNativeMips) ? (int)(log((double)TexLevels)/log((double)2)) + 1 : (isPow2?0:1);
if(TexLevels > maxlevel && maxlevel > 0)
TexLevels = maxlevel;
int gl_format;
int gl_iformat;
int gl_type;
entry.bHaveMipMaps = UseNativeMips;
if (dfmt != PC_TEX_FMT_DXT1)
{
if (expandedWidth != width)
glPixelStorei(GL_UNPACK_ROW_LENGTH, expandedWidth);
int gl_format;
int gl_iformat;
int gl_type;
switch (dfmt)
{
default:
@ -429,6 +446,7 @@ TextureMngr::TCacheEntry* TextureMngr::Load(int texstage, u32 address, int width
gl_type = GL_UNSIGNED_SHORT_5_6_5;
break;
}
//generate mipmaps even if we use native mips to suport textures with less levels
bool GenerateMipmaps = !entry.isRectangle && ((tm0.min_filter & 3) == 1 || (tm0.min_filter & 3) == 2);
if (GenerateMipmaps)
{
@ -464,13 +482,49 @@ TextureMngr::TCacheEntry* TextureMngr::Load(int texstage, u32 address, int width
width, height, 0, expandedWidth*expandedHeight/2, temp);
}
}
if(TexLevels > 1 && dfmt != PC_TEX_FMT_NONE)
{
int level = 1;
int mipWidth = (width + 1) >> 1;
int mipHeight = (height + 1) >> 1;
ptr += entry.size_in_bytes;
while((mipHeight || mipWidth))
{
u32 currentWidth = (mipWidth > 0)? mipWidth : 1;
u32 currentHeight = (mipHeight > 0)? mipHeight : 1;
expandedWidth = (currentWidth + bsw) & (~bsw);
expandedHeight = (currentHeight + bsh) & (~bsh);
if(level < TexLevels)
{
TexDecoder_Decode(temp, ptr, expandedWidth, expandedHeight, tex_format, tlutaddr, tlutfmt);
}
//ugly hack but it seems to work
//complete the level not defined in hardware with pixels of the top levels
//this is not a problem as the level are filtered by lod min and max value
if (dfmt != PC_TEX_FMT_DXT1)
{
if (expandedWidth != currentWidth)
glPixelStorei(GL_UNPACK_ROW_LENGTH, expandedWidth);
glTexImage2D(target, level, gl_iformat, currentWidth, currentHeight, 0, gl_format, gl_type, temp);
if (expandedWidth != currentWidth) // reset
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
}
else
{
glCompressedTexImage2D(target, level, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, currentWidth, currentHeight, 0, expandedWidth*expandedHeight/2, temp);
}
u32 size = (max(mipWidth, bsw) * max(mipHeight, bsh) * bsdepth) >> 1;
ptr += size;
mipWidth >>= 1;
mipHeight >>= 1;
level++;
}
}
entry.frameCount = frameCount;
entry.w = width;
entry.h = height;
entry.fmt = FullFormat;
entry.SetTextureParameters(tm0);
entry.SetTextureParameters(tm0,tm1);
if (g_ActiveConfig.bDumpTextures) // dump texture to file
{

View File

@ -38,6 +38,7 @@ public:
u32 paletteHash;
u32 oldpixel; // used for simple cleanup
TexMode0 mode; // current filter and clamp modes that texture is set to
TexMode1 mode1; // current filter and clamp modes that texture is set to
int frameCount;
int w, h, fmt;
@ -49,7 +50,7 @@ public:
bool isRectangle; // if nonpow2, use GL_TEXTURE_2D, else GL_TEXTURE_RECTANGLE_NV
bool bHaveMipMaps;
void SetTextureParameters(TexMode0& newmode);
void SetTextureParameters(TexMode0& newmode,TexMode1 &newmode1);
void Destroy(bool shutdown);
void ConvertFromRenderTarget(u32 taddr, int twidth, int theight, int tformat, int tlutaddr, int tlutfmt);
bool IntersectsMemoryRange(u32 range_address, u32 range_size);