2014-11-01 08:32:00 +00:00
# include <assert.h>
2013-04-05 06:13:26 +00:00
# include <memory.h>
2014-09-01 16:19:20 +00:00
# include <algorithm>
2013-04-05 06:13:26 +00:00
# include "OpenGL.h"
# include "Textures.h"
# include "GBI.h"
# include "RSP.h"
# include "gDP.h"
# include "gSP.h"
# include "N64.h"
# include "convert.h"
# include "FrameBuffer.h"
2014-04-05 02:57:00 +00:00
# include "Config.h"
2013-04-05 06:13:26 +00:00
2014-09-01 16:19:20 +00:00
using namespace std ;
2013-04-05 06:13:26 +00:00
typedef u32 ( * GetTexelFunc ) ( u64 * src , u16 x , u16 i , u8 palette ) ;
inline u32 GetNone ( u64 * src , u16 x , u16 i , u8 palette )
{
return 0x00000000 ;
}
inline u32 GetCI4IA_RGBA4444 ( u64 * src , u16 x , u16 i , u8 palette )
{
u8 color4B ;
color4B = ( ( u8 * ) src ) [ ( x > > 1 ) ^ ( i < < 1 ) ] ;
if ( x & 1 )
return IA88_RGBA4444 ( * ( u16 * ) & TMEM [ 256 + ( palette < < 4 ) + ( color4B & 0x0F ) ] ) ;
else
return IA88_RGBA4444 ( * ( u16 * ) & TMEM [ 256 + ( palette < < 4 ) + ( color4B > > 4 ) ] ) ;
}
inline u32 GetCI4IA_RGBA8888 ( u64 * src , u16 x , u16 i , u8 palette )
{
u8 color4B ;
color4B = ( ( u8 * ) src ) [ ( x > > 1 ) ^ ( i < < 1 ) ] ;
if ( x & 1 )
return IA88_RGBA8888 ( * ( u16 * ) & TMEM [ 256 + ( palette < < 4 ) + ( color4B & 0x0F ) ] ) ;
else
return IA88_RGBA8888 ( * ( u16 * ) & TMEM [ 256 + ( palette < < 4 ) + ( color4B > > 4 ) ] ) ;
}
inline u32 GetCI4RGBA_RGBA5551 ( u64 * src , u16 x , u16 i , u8 palette )
{
u8 color4B ;
color4B = ( ( u8 * ) src ) [ ( x > > 1 ) ^ ( i < < 1 ) ] ;
if ( x & 1 )
return RGBA5551_RGBA5551 ( * ( u16 * ) & TMEM [ 256 + ( palette < < 4 ) + ( color4B & 0x0F ) ] ) ;
else
return RGBA5551_RGBA5551 ( * ( u16 * ) & TMEM [ 256 + ( palette < < 4 ) + ( color4B > > 4 ) ] ) ;
}
inline u32 GetCI4RGBA_RGBA8888 ( u64 * src , u16 x , u16 i , u8 palette )
{
u8 color4B ;
color4B = ( ( u8 * ) src ) [ ( x > > 1 ) ^ ( i < < 1 ) ] ;
if ( x & 1 )
return RGBA5551_RGBA8888 ( * ( u16 * ) & TMEM [ 256 + ( palette < < 4 ) + ( color4B & 0x0F ) ] ) ;
else
return RGBA5551_RGBA8888 ( * ( u16 * ) & TMEM [ 256 + ( palette < < 4 ) + ( color4B > > 4 ) ] ) ;
}
inline u32 GetIA31_RGBA8888 ( u64 * src , u16 x , u16 i , u8 palette )
{
u8 color4B ;
color4B = ( ( u8 * ) src ) [ ( x > > 1 ) ^ ( i < < 1 ) ] ;
return IA31_RGBA8888 ( ( x & 1 ) ? ( color4B & 0x0F ) : ( color4B > > 4 ) ) ;
}
inline u32 GetIA31_RGBA4444 ( u64 * src , u16 x , u16 i , u8 palette )
{
u8 color4B ;
color4B = ( ( u8 * ) src ) [ ( x > > 1 ) ^ ( i < < 1 ) ] ;
return IA31_RGBA4444 ( ( x & 1 ) ? ( color4B & 0x0F ) : ( color4B > > 4 ) ) ;
}
inline u32 GetI4_RGBA8888 ( u64 * src , u16 x , u16 i , u8 palette )
{
u8 color4B ;
color4B = ( ( u8 * ) src ) [ ( x > > 1 ) ^ ( i < < 1 ) ] ;
return I4_RGBA8888 ( ( x & 1 ) ? ( color4B & 0x0F ) : ( color4B > > 4 ) ) ;
}
inline u32 GetI4_RGBA4444 ( u64 * src , u16 x , u16 i , u8 palette )
{
u8 color4B ;
color4B = ( ( u8 * ) src ) [ ( x > > 1 ) ^ ( i < < 1 ) ] ;
return I4_RGBA4444 ( ( x & 1 ) ? ( color4B & 0x0F ) : ( color4B > > 4 ) ) ;
}
inline u32 GetCI8IA_RGBA4444 ( u64 * src , u16 x , u16 i , u8 palette )
{
return IA88_RGBA4444 ( * ( u16 * ) & TMEM [ 256 + ( ( u8 * ) src ) [ x ^ ( i < < 1 ) ] ] ) ;
}
inline u32 GetCI8IA_RGBA8888 ( u64 * src , u16 x , u16 i , u8 palette )
{
return IA88_RGBA8888 ( * ( u16 * ) & TMEM [ 256 + ( ( u8 * ) src ) [ x ^ ( i < < 1 ) ] ] ) ;
}
inline u32 GetCI8RGBA_RGBA5551 ( u64 * src , u16 x , u16 i , u8 palette )
{
return RGBA5551_RGBA5551 ( * ( u16 * ) & TMEM [ 256 + ( ( u8 * ) src ) [ x ^ ( i < < 1 ) ] ] ) ;
}
inline u32 GetCI8RGBA_RGBA8888 ( u64 * src , u16 x , u16 i , u8 palette )
{
return RGBA5551_RGBA8888 ( * ( u16 * ) & TMEM [ 256 + ( ( u8 * ) src ) [ x ^ ( i < < 1 ) ] ] ) ;
}
inline u32 GetIA44_RGBA8888 ( u64 * src , u16 x , u16 i , u8 palette )
{
return IA44_RGBA8888 ( ( ( u8 * ) src ) [ x ^ ( i < < 1 ) ] ) ;
}
inline u32 GetIA44_RGBA4444 ( u64 * src , u16 x , u16 i , u8 palette )
{
return IA44_RGBA4444 ( ( ( u8 * ) src ) [ x ^ ( i < < 1 ) ] ) ;
}
inline u32 GetI8_RGBA8888 ( u64 * src , u16 x , u16 i , u8 palette )
{
return I8_RGBA8888 ( ( ( u8 * ) src ) [ x ^ ( i < < 1 ) ] ) ;
}
inline u32 GetI8_RGBA4444 ( u64 * src , u16 x , u16 i , u8 palette )
{
return I8_RGBA4444 ( ( ( u8 * ) src ) [ x ^ ( i < < 1 ) ] ) ;
}
inline u32 GetRGBA5551_RGBA8888 ( u64 * src , u16 x , u16 i , u8 palette )
{
2014-10-28 12:02:33 +00:00
u16 tex = ( ( u16 * ) src ) [ x ^ i ] ;
switch ( gDP . otherMode . textureLUT ) {
case G_TT_NONE :
return RGBA5551_RGBA8888 ( tex ) ;
case G_TT_RGBA16 :
return RGBA5551_RGBA8888 ( * ( u16 * ) & TMEM [ 256 + ( tex > > 8 ) ] ) ;
case G_TT_IA16 :
tex = ( * ( u16 * ) & TMEM [ 256 + ( tex > > 8 ) ] ) > > 8 ;
return ( tex < < 24 ) | ( tex < < 16 ) | ( tex < < 8 ) | tex ;
}
return RGBA5551_RGBA8888 ( tex ) ;
2013-04-05 06:13:26 +00:00
}
inline u32 GetRGBA5551_RGBA5551 ( u64 * src , u16 x , u16 i , u8 palette )
{
2014-10-28 12:02:33 +00:00
u16 tex = ( ( u16 * ) src ) [ x ^ i ] ;
switch ( gDP . otherMode . textureLUT ) {
case G_TT_NONE :
return RGBA5551_RGBA5551 ( tex ) ;
case G_TT_RGBA16 :
return RGBA5551_RGBA5551 ( * ( u16 * ) & TMEM [ 256 + ( tex > > 8 ) ] ) ;
case G_TT_IA16 :
tex = ( * ( u16 * ) & TMEM [ 256 + ( tex > > 8 ) ] ) > > 11 ;
return ( 1 < < 15 ) | ( tex < < 10 ) | ( tex < < 5 ) | tex ;
}
return RGBA5551_RGBA5551 ( tex ) ;
2013-04-05 06:13:26 +00:00
}
inline u32 GetIA88_RGBA8888 ( u64 * src , u16 x , u16 i , u8 palette )
{
return IA88_RGBA8888 ( ( ( u16 * ) src ) [ x ^ i ] ) ;
}
inline u32 GetIA88_RGBA4444 ( u64 * src , u16 x , u16 i , u8 palette )
{
return IA88_RGBA4444 ( ( ( u16 * ) src ) [ x ^ i ] ) ;
}
inline u32 GetRGBA8888_RGBA8888 ( u64 * src , u16 x , u16 i , u8 palette )
{
return ( ( u32 * ) src ) [ x ^ i ] ;
}
inline u32 GetRGBA8888_RGBA4444 ( u64 * src , u16 x , u16 i , u8 palette )
{
return RGBA8888_RGBA4444 ( ( ( u32 * ) src ) [ x ^ i ] ) ;
}
2014-10-28 06:12:30 +00:00
u32 YUV_RGBA8888 ( u8 y , u8 u , u8 v )
{
s32 r = ( s32 ) ( y + ( 1.370705f * ( v - 128 ) ) ) ;
s32 g = ( s32 ) ( ( y - ( 0.698001f * ( v - 128 ) ) - ( 0.337633f * ( u - 128 ) ) ) ) ;
s32 b = ( s32 ) ( y + ( 1.732446f * ( u - 128 ) ) ) ;
//clipping the result
if ( r > 255 ) r = 255 ;
if ( g > 255 ) g = 255 ;
if ( b > 255 ) b = 255 ;
if ( r < 0 ) r = 0 ;
if ( g < 0 ) g = 0 ;
if ( b < 0 ) b = 0 ;
return ( 0xff < < 24 ) | ( b < < 16 ) | ( g < < 8 ) | r ;
}
u16 YUV_RGBA4444 ( u8 y , u8 u , u8 v )
{
return RGBA8888_RGBA4444 ( YUV_RGBA8888 ( y , u , v ) ) ;
}
inline void GetYUV_RGBA8888 ( u64 * src , u32 * dst , u16 x )
{
const u32 t = ( ( ( u32 * ) src ) [ x ] ) ;
u8 y1 = ( u8 ) t & 0xFF ;
u8 v = ( u8 ) ( t > > 8 ) & 0xFF ;
u8 y0 = ( u8 ) ( t > > 16 ) & 0xFF ;
u8 u = ( u8 ) ( t > > 24 ) & 0xFF ;
u32 c = YUV_RGBA8888 ( y0 , u , v ) ;
* ( dst + + ) = c ;
c = YUV_RGBA8888 ( y1 , u , v ) ;
* ( dst + + ) = c ;
}
inline void GetYUV_RGBA4444 ( u64 * src , u16 * dst , u16 x )
{
const u32 t = ( ( ( u32 * ) src ) [ x ] ) ;
u8 y1 = ( u8 ) t & 0xFF ;
u8 v = ( u8 ) ( t > > 8 ) & 0xFF ;
u8 y0 = ( u8 ) ( t > > 16 ) & 0xFF ;
u8 u = ( u8 ) ( t > > 24 ) & 0xFF ;
u16 c = YUV_RGBA4444 ( y0 , u , v ) ;
* ( dst + + ) = c ;
c = YUV_RGBA4444 ( y1 , u , v ) ;
* ( dst + + ) = c ;
}
2013-04-05 06:13:26 +00:00
const struct
{
GetTexelFunc Get16 ;
GLenum glType16 ;
GLint glInternalFormat16 ;
GetTexelFunc Get32 ;
GLenum glType32 ;
GLint glInternalFormat32 ;
u32 autoFormat , lineShift , maxTexels ;
} imageFormat [ 4 ] [ 5 ] =
{ // Get16 glType16 glInternalFormat16 Get32 glType32 glInternalFormat32 autoFormat
{ // 4-bit
2014-04-17 06:24:53 +00:00
{ GetCI4RGBA_RGBA5551 , GL_UNSIGNED_SHORT_5_5_5_1 , GL_RGB5_A1 , GetCI4RGBA_RGBA8888 , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGB5_A1 , 4 , 4096 } , // CI (Banjo-Kazooie uses this, doesn't make sense, but it works...)
{ GetNone , GL_UNSIGNED_SHORT_4_4_4_4 , GL_RGBA4 , GetNone , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGBA4 , 4 , 8192 } , // YUV
{ GetCI4RGBA_RGBA5551 , GL_UNSIGNED_SHORT_5_5_5_1 , GL_RGB5_A1 , GetCI4RGBA_RGBA8888 , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGB5_A1 , 4 , 4096 } , // CI
{ GetIA31_RGBA4444 , GL_UNSIGNED_SHORT_4_4_4_4 , GL_RGBA4 , GetIA31_RGBA8888 , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGBA4 , 4 , 8192 } , // IA
{ GetI4_RGBA4444 , GL_UNSIGNED_SHORT_4_4_4_4 , GL_RGBA4 , GetI4_RGBA8888 , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGBA4 , 4 , 8192 } , // I
2013-04-05 06:13:26 +00:00
} ,
{ // 8-bit
2014-04-17 06:24:53 +00:00
{ GetCI8RGBA_RGBA5551 , GL_UNSIGNED_SHORT_5_5_5_1 , GL_RGB5_A1 , GetCI8RGBA_RGBA8888 , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGB5_A1 , 3 , 2048 } , // RGBA
{ GetNone , GL_UNSIGNED_SHORT_4_4_4_4 , GL_RGBA4 , GetNone , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGBA4 , 0 , 4096 } , // YUV
{ GetCI8RGBA_RGBA5551 , GL_UNSIGNED_SHORT_5_5_5_1 , GL_RGB5_A1 , GetCI8RGBA_RGBA8888 , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGB5_A1 , 3 , 2048 } , // CI
{ GetIA44_RGBA4444 , GL_UNSIGNED_SHORT_4_4_4_4 , GL_RGBA4 , GetIA44_RGBA8888 , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGBA4 , 3 , 4096 } , // IA
{ GetI8_RGBA4444 , GL_UNSIGNED_SHORT_4_4_4_4 , GL_RGBA4 , GetI8_RGBA8888 , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGBA , 3 , 4096 } , // I
2013-04-05 06:13:26 +00:00
} ,
{ // 16-bit
2014-04-17 06:24:53 +00:00
{ GetRGBA5551_RGBA5551 , GL_UNSIGNED_SHORT_5_5_5_1 , GL_RGB5_A1 , GetRGBA5551_RGBA8888 , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGB5_A1 , 2 , 2048 } , // RGBA
{ GetNone , GL_UNSIGNED_SHORT_4_4_4_4 , GL_RGBA4 , GetNone , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGBA4 , 2 , 2048 } , // YUV
{ GetNone , GL_UNSIGNED_SHORT_4_4_4_4 , GL_RGBA4 , GetNone , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGBA4 , 0 , 2048 } , // CI
{ GetIA88_RGBA4444 , GL_UNSIGNED_SHORT_4_4_4_4 , GL_RGBA4 , GetIA88_RGBA8888 , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGBA , 2 , 2048 } , // IA
{ GetNone , GL_UNSIGNED_SHORT_4_4_4_4 , GL_RGBA4 , GetNone , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGBA4 , 0 , 2048 } , // I
2013-04-05 06:13:26 +00:00
} ,
{ // 32-bit
2014-04-17 06:24:53 +00:00
{ GetRGBA8888_RGBA4444 , GL_UNSIGNED_SHORT_4_4_4_4 , GL_RGBA4 , GetRGBA8888_RGBA8888 , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGBA , 2 , 1024 } , // RGBA
{ GetNone , GL_UNSIGNED_SHORT_4_4_4_4 , GL_RGBA4 , GetNone , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGBA4 , 0 , 1024 } , // YUV
{ GetNone , GL_UNSIGNED_SHORT_4_4_4_4 , GL_RGBA4 , GetNone , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGBA4 , 0 , 1024 } , // CI
{ GetNone , GL_UNSIGNED_SHORT_4_4_4_4 , GL_RGBA4 , GetNone , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGBA4 , 0 , 1024 } , // IA
{ GetNone , GL_UNSIGNED_SHORT_4_4_4_4 , GL_RGBA4 , GetNone , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGBA4 , 0 , 1024 } , // I
2013-04-05 06:13:26 +00:00
}
} ;
2014-09-18 16:16:52 +00:00
void TextureCache : : init ( )
2013-04-05 06:13:26 +00:00
{
u32 dummyTexture [ 16 ] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } ;
2014-09-18 16:16:52 +00:00
m_bitDepth = config . texture . textureBitDepth ;
m_maxBytes = config . texture . maxBytes ;
m_pDummy = addFrameBufferTexture ( ) ; // we don't want to remove dummy texture
m_pDummy - > address = 0 ;
m_pDummy - > clampS = 1 ;
m_pDummy - > clampT = 1 ;
m_pDummy - > clampWidth = 2 ;
m_pDummy - > clampHeight = 2 ;
m_pDummy - > crc = 0 ;
m_pDummy - > format = 0 ;
m_pDummy - > size = 0 ;
m_pDummy - > frameBufferTexture = FALSE ;
m_pDummy - > width = 2 ;
m_pDummy - > height = 2 ;
m_pDummy - > realWidth = 0 ;
m_pDummy - > realHeight = 0 ;
m_pDummy - > maskS = 0 ;
m_pDummy - > maskT = 0 ;
m_pDummy - > scaleS = 0.5f ;
m_pDummy - > scaleT = 0.5f ;
m_pDummy - > shiftScaleS = 1.0f ;
m_pDummy - > shiftScaleT = 1.0f ;
m_pDummy - > textureBytes = 64 ;
m_pDummy - > tMem = 0 ;
glBindTexture ( GL_TEXTURE_2D , m_pDummy - > glName ) ;
2014-04-17 06:24:53 +00:00
glTexImage2D ( GL_TEXTURE_2D , 0 , GL_RGBA , 2 , 2 , 0 , GL_RGBA , GL_UNSIGNED_BYTE , dummyTexture ) ;
2013-04-05 06:13:26 +00:00
2014-09-18 16:16:52 +00:00
m_cachedBytes = m_pDummy - > textureBytes ;
activateDummy ( 0 ) ;
activateDummy ( 1 ) ;
2014-10-01 09:51:44 +00:00
current [ 0 ] = current [ 1 ] = NULL ;
2013-04-05 06:13:26 +00:00
}
2014-09-18 16:16:52 +00:00
void TextureCache : : destroy ( )
2013-04-05 06:13:26 +00:00
{
2014-09-18 16:16:52 +00:00
current [ 0 ] = current [ 1 ] = NULL ;
2014-09-22 11:40:35 +00:00
for ( Textures : : const_iterator cur = m_textures . cbegin ( ) ; cur ! = m_textures . cend ( ) ; + + cur )
glDeleteTextures ( 1 , & cur - > second . glName ) ;
2014-09-18 16:16:52 +00:00
m_textures . clear ( ) ;
2014-09-22 11:40:35 +00:00
for ( Textures : : const_iterator cur = m_fbTextures . cbegin ( ) ; cur ! = m_fbTextures . cend ( ) ; + + cur )
glDeleteTextures ( 1 , & cur - > second . glName ) ;
2014-09-18 16:16:52 +00:00
m_fbTextures . clear ( ) ;
2014-09-22 11:40:35 +00:00
2014-09-18 16:16:52 +00:00
m_cachedBytes = 0 ;
2013-04-05 06:13:26 +00:00
}
2014-09-18 16:16:52 +00:00
void TextureCache : : _checkCacheSize ( )
2013-04-05 06:13:26 +00:00
{
2014-09-18 16:16:52 +00:00
if ( m_cachedBytes < = m_maxBytes )
return ;
2014-09-22 11:40:35 +00:00
Textures : : const_iterator iter = m_textures . cend ( ) ;
2014-09-18 16:16:52 +00:00
do {
2014-09-22 11:40:35 +00:00
- - iter ;
m_cachedBytes - = iter - > second . textureBytes ;
glDeleteTextures ( 1 , & iter - > second . glName ) ;
} while ( m_cachedBytes > m_maxBytes & & iter ! = m_textures . cbegin ( ) ) ;
m_textures . erase ( iter , m_textures . cend ( ) ) ;
2013-04-05 06:13:26 +00:00
}
2014-09-18 16:16:52 +00:00
CachedTexture * TextureCache : : _addTexture ( u32 _crc32 )
2013-04-05 06:13:26 +00:00
{
2014-09-18 16:16:52 +00:00
_checkCacheSize ( ) ;
2014-09-22 11:40:35 +00:00
GLuint glName ;
glGenTextures ( 1 , & glName ) ;
m_textures . emplace ( _crc32 , glName ) ;
CachedTexture & texture = m_textures . at ( _crc32 ) ;
texture . crc = _crc32 ;
return & texture ;
2013-04-05 06:13:26 +00:00
}
2014-09-18 16:16:52 +00:00
void TextureCache : : removeFrameBufferTexture ( CachedTexture * _pTexture )
2013-04-05 06:13:26 +00:00
{
2014-09-22 11:40:35 +00:00
Textures : : const_iterator iter = m_fbTextures . find ( _pTexture - > glName ) ;
2014-09-18 16:16:52 +00:00
assert ( iter ! = m_fbTextures . end ( ) ) ;
2014-09-22 11:40:35 +00:00
m_cachedBytes - = iter - > second . textureBytes ;
glDeleteTextures ( 1 , & iter - > second . glName ) ;
2014-09-18 16:16:52 +00:00
m_fbTextures . erase ( iter ) ;
2013-04-05 06:13:26 +00:00
}
2014-09-18 16:16:52 +00:00
CachedTexture * TextureCache : : addFrameBufferTexture ( )
2013-04-05 06:13:26 +00:00
{
2014-09-18 16:16:52 +00:00
_checkCacheSize ( ) ;
2014-09-22 11:40:35 +00:00
GLuint glName ;
glGenTextures ( 1 , & glName ) ;
m_fbTextures . emplace ( glName , glName ) ;
return & m_fbTextures . at ( glName ) ;
2013-04-05 06:13:26 +00:00
}
2014-09-18 16:16:52 +00:00
void TextureCache : : _loadBackground ( CachedTexture * pTexture )
2013-04-05 06:13:26 +00:00
{
2014-09-18 16:16:52 +00:00
u32 * pDest ;
2013-04-05 06:13:26 +00:00
2014-09-18 16:16:52 +00:00
u8 * pSwapped , * pSrc ;
2013-04-05 06:13:26 +00:00
u32 numBytes , bpl ;
2013-04-22 04:23:39 +00:00
u32 x , y , j , tx , ty ;
2013-04-05 06:13:26 +00:00
u16 clampSClamp ;
u16 clampTClamp ;
2014-09-18 16:16:52 +00:00
GetTexelFunc GetTexel ;
GLuint glInternalFormat ;
GLenum glType ;
2013-04-05 06:13:26 +00:00
2014-09-18 16:16:52 +00:00
if ( ( ( imageFormat [ pTexture - > size ] [ pTexture - > format ] . autoFormat = = GL_RGBA ) | |
( ( pTexture - > format = = G_IM_FMT_CI ) & & ( gDP . otherMode . textureLUT = = G_TT_IA16 ) ) | | ( m_bitDepth = = 2 ) ) & & ( m_bitDepth ! = 0 ) )
2013-04-05 06:13:26 +00:00
{
2014-09-18 16:16:52 +00:00
pTexture - > textureBytes = ( pTexture - > realWidth * pTexture - > realHeight ) < < 2 ;
if ( ( pTexture - > format = = G_IM_FMT_CI ) & & ( gDP . otherMode . textureLUT = = G_TT_IA16 ) ) {
if ( pTexture - > size = = G_IM_SIZ_4b )
2013-04-05 06:13:26 +00:00
GetTexel = GetCI4IA_RGBA8888 ;
else
GetTexel = GetCI8IA_RGBA8888 ;
2014-04-17 06:24:53 +00:00
glInternalFormat = GL_RGBA ;
2013-04-05 06:13:26 +00:00
glType = GL_UNSIGNED_BYTE ;
2014-09-18 16:16:52 +00:00
} else {
GetTexel = imageFormat [ pTexture - > size ] [ pTexture - > format ] . Get32 ;
glInternalFormat = imageFormat [ pTexture - > size ] [ pTexture - > format ] . glInternalFormat32 ;
glType = imageFormat [ pTexture - > size ] [ pTexture - > format ] . glType32 ;
2013-04-05 06:13:26 +00:00
}
2014-09-18 16:16:52 +00:00
} else {
pTexture - > textureBytes = ( pTexture - > realWidth * pTexture - > realHeight ) < < 1 ;
if ( ( pTexture - > format = = G_IM_FMT_CI ) & & ( gDP . otherMode . textureLUT = = G_TT_IA16 ) ) {
if ( pTexture - > size = = G_IM_SIZ_4b )
2013-04-05 06:13:26 +00:00
GetTexel = GetCI4IA_RGBA4444 ;
else
GetTexel = GetCI8IA_RGBA4444 ;
glInternalFormat = GL_RGBA4 ;
2014-04-17 06:24:53 +00:00
glType = GL_UNSIGNED_SHORT_4_4_4_4 ;
2014-09-18 16:16:52 +00:00
} else {
GetTexel = imageFormat [ pTexture - > size ] [ pTexture - > format ] . Get16 ;
glInternalFormat = imageFormat [ pTexture - > size ] [ pTexture - > format ] . glInternalFormat16 ;
glType = imageFormat [ pTexture - > size ] [ pTexture - > format ] . glType16 ;
2013-04-05 06:13:26 +00:00
}
}
bpl = gSP . bgImage . width < < gSP . bgImage . size > > 1 ;
numBytes = bpl * gSP . bgImage . height ;
2014-09-18 16:16:52 +00:00
pSwapped = ( u8 * ) malloc ( numBytes ) ;
UnswapCopy ( & RDRAM [ gSP . bgImage . address ] , pSwapped , numBytes ) ;
pDest = ( u32 * ) malloc ( pTexture - > textureBytes ) ;
2013-04-05 06:13:26 +00:00
2014-09-18 16:16:52 +00:00
clampSClamp = pTexture - > width - 1 ;
clampTClamp = pTexture - > height - 1 ;
2013-04-05 06:13:26 +00:00
j = 0 ;
2014-09-18 16:16:52 +00:00
for ( y = 0 ; y < pTexture - > realHeight ; y + + ) {
2014-09-01 16:19:20 +00:00
ty = min ( y , ( u32 ) clampTClamp ) ;
2013-04-05 06:13:26 +00:00
2014-09-18 16:16:52 +00:00
pSrc = & pSwapped [ bpl * ty ] ;
2013-04-05 06:13:26 +00:00
2014-09-18 16:16:52 +00:00
for ( x = 0 ; x < pTexture - > realWidth ; x + + ) {
2014-09-01 16:19:20 +00:00
tx = min ( x , ( u32 ) clampSClamp ) ;
2013-04-05 06:13:26 +00:00
2014-04-17 06:24:53 +00:00
if ( glInternalFormat = = GL_RGBA )
2014-09-18 16:16:52 +00:00
( ( u32 * ) pDest ) [ j + + ] = GetTexel ( ( u64 * ) pSrc , tx , 0 , pTexture - > palette ) ;
2013-04-05 06:13:26 +00:00
else
2014-09-18 16:16:52 +00:00
( ( u16 * ) pDest ) [ j + + ] = GetTexel ( ( u64 * ) pSrc , tx , 0 , pTexture - > palette ) ;
2013-04-05 06:13:26 +00:00
}
}
2014-09-18 16:16:52 +00:00
glTexImage2D ( GL_TEXTURE_2D , 0 , glInternalFormat , pTexture - > realWidth , pTexture - > realHeight , 0 , GL_RGBA , glType , pDest ) ;
free ( pDest ) ;
2013-04-05 06:13:26 +00:00
}
2014-10-09 09:01:04 +00:00
void TextureCache : : _load ( u32 _tile , CachedTexture * _pTexture )
2013-04-05 06:13:26 +00:00
{
2014-09-18 16:16:52 +00:00
u32 * pDest ;
2013-04-05 06:13:26 +00:00
2014-09-18 16:16:52 +00:00
u64 * pSrc ;
2013-04-05 06:13:26 +00:00
u16 x , y , i , j , tx , ty , line ;
u16 mirrorSBit , maskSMask , clampSClamp ;
u16 mirrorTBit , maskTMask , clampTClamp ;
2014-09-18 16:16:52 +00:00
GetTexelFunc GetTexel ;
GLuint glInternalFormat ;
GLenum glType ;
2014-10-09 09:01:04 +00:00
u32 sizeShift ;
2013-04-05 06:13:26 +00:00
2014-10-09 09:01:04 +00:00
if ( ( ( imageFormat [ _pTexture - > size ] [ _pTexture - > format ] . autoFormat = = GL_RGBA ) | |
( ( _pTexture - > format = = G_IM_FMT_CI ) & & ( gDP . otherMode . textureLUT = = G_TT_IA16 ) ) | | ( m_bitDepth = = 2 ) ) & & ( m_bitDepth ! = 0 ) )
2013-04-05 06:13:26 +00:00
{
2014-10-09 09:01:04 +00:00
sizeShift = 2 ;
_pTexture - > textureBytes = ( _pTexture - > realWidth * _pTexture - > realHeight ) < < sizeShift ;
if ( ( _pTexture - > format = = G_IM_FMT_CI ) & & ( gDP . otherMode . textureLUT = = G_TT_IA16 ) ) {
if ( _pTexture - > size = = G_IM_SIZ_4b )
2013-04-05 06:13:26 +00:00
GetTexel = GetCI4IA_RGBA8888 ;
else
GetTexel = GetCI8IA_RGBA8888 ;
2014-04-17 06:24:53 +00:00
glInternalFormat = GL_RGBA ;
2013-04-05 06:13:26 +00:00
glType = GL_UNSIGNED_BYTE ;
2014-09-18 16:16:52 +00:00
} else {
2014-10-09 09:01:04 +00:00
GetTexel = imageFormat [ _pTexture - > size ] [ _pTexture - > format ] . Get32 ;
glInternalFormat = imageFormat [ _pTexture - > size ] [ _pTexture - > format ] . glInternalFormat32 ;
glType = imageFormat [ _pTexture - > size ] [ _pTexture - > format ] . glType32 ;
2013-04-05 06:13:26 +00:00
}
2014-09-18 16:16:52 +00:00
} else {
2014-10-09 09:01:04 +00:00
sizeShift = 1 ;
_pTexture - > textureBytes = ( _pTexture - > realWidth * _pTexture - > realHeight ) < < sizeShift ;
if ( ( _pTexture - > format = = G_IM_FMT_CI ) & & ( gDP . otherMode . textureLUT = = G_TT_IA16 ) ) {
if ( _pTexture - > size = = G_IM_SIZ_4b )
2013-04-05 06:13:26 +00:00
GetTexel = GetCI4IA_RGBA4444 ;
else
GetTexel = GetCI8IA_RGBA4444 ;
glInternalFormat = GL_RGBA4 ;
2014-04-17 06:24:53 +00:00
glType = GL_UNSIGNED_SHORT_4_4_4_4 ;
2014-09-18 16:16:52 +00:00
} else {
2014-10-09 09:01:04 +00:00
GetTexel = imageFormat [ _pTexture - > size ] [ _pTexture - > format ] . Get16 ;
glInternalFormat = imageFormat [ _pTexture - > size ] [ _pTexture - > format ] . glInternalFormat16 ;
glType = imageFormat [ _pTexture - > size ] [ _pTexture - > format ] . glType16 ;
2013-04-05 06:13:26 +00:00
}
}
2014-10-09 09:01:04 +00:00
pDest = ( u32 * ) malloc ( _pTexture - > textureBytes ) ;
2013-04-05 06:13:26 +00:00
2014-10-09 09:01:04 +00:00
GLint mipLevel = 0 , maxLevel = 0 ;
if ( gSP . texture . level > 1 )
maxLevel = _tile = = 0 ? 0 : gSP . texture . level - 1 ;
2013-04-05 06:13:26 +00:00
2014-10-09 09:01:04 +00:00
_pTexture - > max_level = maxLevel ;
CachedTexture tmptex ( 0 ) ;
memcpy ( & tmptex , _pTexture , sizeof ( CachedTexture ) ) ;
line = tmptex . line ;
2013-04-05 06:13:26 +00:00
2014-10-09 09:01:04 +00:00
while ( true ) {
if ( tmptex . maskS > 0 ) {
clampSClamp = tmptex . clampS ? tmptex . clampWidth - 1 : ( tmptex . mirrorS ? ( tmptex . width < < 1 ) - 1 : tmptex . width - 1 ) ;
maskSMask = ( 1 < < tmptex . maskS ) - 1 ;
mirrorSBit = tmptex . mirrorS ? 1 < < tmptex . maskS : 0 ;
} else {
clampSClamp = min ( tmptex . clampWidth , tmptex . width ) - 1 ;
maskSMask = 0xFFFF ;
mirrorSBit = 0x0000 ;
}
2013-04-05 06:13:26 +00:00
2014-10-09 09:01:04 +00:00
if ( tmptex . maskT > 0 ) {
clampTClamp = tmptex . clampT ? tmptex . clampHeight - 1 : ( tmptex . mirrorT ? ( tmptex . height < < 1 ) - 1 : tmptex . height - 1 ) ;
maskTMask = ( 1 < < tmptex . maskT ) - 1 ;
mirrorTBit = tmptex . mirrorT ? 1 < < tmptex . maskT : 0 ;
} else {
clampTClamp = min ( tmptex . clampHeight , tmptex . height ) - 1 ;
maskTMask = 0xFFFF ;
mirrorTBit = 0x0000 ;
}
2013-04-05 06:13:26 +00:00
2014-10-09 09:01:04 +00:00
// Hack for Zelda warp texture
if ( ( ( tmptex . tMem < < 3 ) + ( tmptex . width * tmptex . height < < tmptex . size > > 1 ) ) > 4096 )
tmptex . tMem = 0 ;
2013-04-05 06:13:26 +00:00
2014-10-28 05:26:45 +00:00
if ( tmptex . size = = G_IM_SIZ_32b ) {
const u16 * tmem16 = ( u16 * ) TMEM ;
2014-10-28 06:12:30 +00:00
const u32 tbase = tmptex . tMem < < 2 ;
2014-10-28 05:26:45 +00:00
u32 width = ( tmptex . clampWidth ) < < 2 ;
if ( width & 15 ) width + = 16 ;
width & = 0xFFFFFFF0 ;
width > > = 2 ;
u16 gr , ab ;
j = 0 ;
for ( y = 0 ; y < tmptex . realHeight ; + + y ) {
ty = min ( y , clampTClamp ) & maskTMask ;
if ( y & mirrorTBit )
ty ^ = maskTMask ;
u32 tline = tbase + width * ty ;
u32 xorval = ( ty & 1 ) ? 3 : 1 ;
for ( x = 0 ; x < tmptex . realWidth ; + + x ) {
tx = min ( x , clampSClamp ) & maskSMask ;
if ( x & mirrorSBit )
tx ^ = maskSMask ;
u32 taddr = ( ( tline + tx ) ^ xorval ) & 0x3ff ;
gr = swapword ( tmem16 [ taddr ] ) ;
ab = swapword ( tmem16 [ taddr | 0x400 ] ) ;
pDest [ j + + ] = ( ab < < 16 ) | gr ;
}
}
2014-10-28 06:12:30 +00:00
} else if ( tmptex . format = = G_IM_FMT_YUV ) {
j = 0 ;
line < < = 1 ;
for ( y = 0 ; y < tmptex . realHeight ; + + y ) {
pSrc = & TMEM [ tmptex . tMem ] + line * y ;
for ( x = 0 ; x < tmptex . realWidth / 2 ; x + + ) {
if ( glInternalFormat = = GL_RGBA )
GetYUV_RGBA8888 ( pSrc , pDest + j , x ) ;
else
GetYUV_RGBA4444 ( pSrc , ( u16 * ) pDest + j , x ) ;
j + = 2 ;
}
}
2014-10-28 05:26:45 +00:00
} else {
j = 0 ;
for ( y = 0 ; y < tmptex . realHeight ; + + y ) {
ty = min ( y , clampTClamp ) & maskTMask ;
2013-04-05 06:13:26 +00:00
2014-10-28 05:26:45 +00:00
if ( y & mirrorTBit )
ty ^ = maskTMask ;
2013-04-05 06:13:26 +00:00
2014-10-28 05:26:45 +00:00
pSrc = & TMEM [ tmptex . tMem ] + line * ty ;
2013-04-05 06:13:26 +00:00
2014-10-28 05:26:45 +00:00
i = ( ty & 1 ) < < 1 ;
for ( x = 0 ; x < tmptex . realWidth ; + + x ) {
tx = min ( x , clampSClamp ) & maskSMask ;
2013-04-05 06:13:26 +00:00
2014-10-28 05:26:45 +00:00
if ( x & mirrorSBit )
tx ^ = maskSMask ;
2013-04-05 06:13:26 +00:00
2014-10-28 05:26:45 +00:00
if ( glInternalFormat = = GL_RGBA )
pDest [ j + + ] = GetTexel ( pSrc , tx , i , tmptex . palette ) ;
else
( ( u16 * ) pDest ) [ j + + ] = GetTexel ( pSrc , tx , i , tmptex . palette ) ;
}
2014-10-09 09:01:04 +00:00
}
2013-04-05 06:13:26 +00:00
}
2014-10-09 09:01:04 +00:00
glTexImage2D ( GL_TEXTURE_2D , mipLevel , glInternalFormat , tmptex . realWidth , tmptex . realHeight , 0 , GL_RGBA , glType , pDest ) ;
if ( mipLevel = = maxLevel )
break ;
+ + mipLevel ;
if ( line > 1 )
line > > = 1 ;
if ( tmptex . maskS > 0 )
- - tmptex . maskS ;
if ( tmptex . clampWidth > 1 )
tmptex . clampWidth > > = 1 ;
if ( tmptex . width > 1 )
tmptex . width > > = 1 ;
if ( tmptex . realWidth > 1 )
tmptex . realWidth > > = 1 ;
if ( tmptex . maskT > 0 )
- - tmptex . maskT ;
if ( tmptex . clampHeight > 1 )
tmptex . clampHeight > > = 1 ;
if ( tmptex . height > 1 )
tmptex . height > > = 1 ;
if ( tmptex . realHeight > 1 )
tmptex . realHeight > > = 1 ;
tmptex . tMem = gDP . tiles [ gSP . texture . tile + mipLevel + 1 ] . tmem ;
tmptex . palette = gDP . tiles [ gSP . texture . tile + mipLevel + 1 ] . palette ;
_pTexture - > textureBytes + = ( tmptex . realWidth * tmptex . realHeight ) < < sizeShift ;
} ;
2014-09-18 16:16:52 +00:00
free ( pDest ) ;
2013-04-05 06:13:26 +00:00
}
2014-09-03 05:12:48 +00:00
struct TextureParams
{
u16 width ;
u16 height ;
u16 clampWidth ;
u16 clampHeight ;
u8 maskS ;
u8 maskT ;
u8 mirrorS ;
u8 mirrorT ;
u8 clampS ;
u8 clampT ;
u8 format ;
u8 size ;
} ;
2014-09-18 16:16:52 +00:00
static
u32 _calculateCRC ( u32 t , const TextureParams & _params )
2013-04-05 06:13:26 +00:00
{
u32 crc ;
2013-04-22 04:23:39 +00:00
u32 y , bpl , lineBytes , line ;
2013-04-05 06:13:26 +00:00
u64 * src ;
src = ( u64 * ) & TMEM [ gSP . textureTile [ t ] - > tmem ] ;
2014-09-03 05:12:48 +00:00
bpl = _params . width < < gSP . textureTile [ t ] - > size > > 1 ;
2013-04-05 06:13:26 +00:00
lineBytes = gSP . textureTile [ t ] - > line < < 3 ;
line = gSP . textureTile [ t ] - > line ;
2014-09-01 16:21:40 +00:00
if ( gSP . textureTile [ t ] - > size = = G_IM_SIZ_32b )
2013-04-05 06:13:26 +00:00
line < < = 1 ;
crc = 0xFFFFFFFF ;
2014-09-03 05:12:48 +00:00
for ( y = 0 ; y < _params . height ; y + + )
2013-04-05 06:13:26 +00:00
{
crc = CRC_Calculate ( crc , src , bpl ) ;
src + = line ;
}
2014-09-03 05:12:48 +00:00
if ( gDP . otherMode . textureLUT ! = G_TT_NONE | | gSP . textureTile [ t ] - > format = = G_IM_FMT_CI ) {
2013-04-05 06:13:26 +00:00
if ( gSP . textureTile [ t ] - > size = = G_IM_SIZ_4b )
crc = CRC_Calculate ( crc , & gDP . paletteCRC16 [ gSP . textureTile [ t ] - > palette ] , 4 ) ;
else if ( gSP . textureTile [ t ] - > size = = G_IM_SIZ_8b )
crc = CRC_Calculate ( crc , & gDP . paletteCRC256 , 4 ) ;
}
2014-09-03 05:12:48 +00:00
crc = CRC_Calculate ( crc , & _params , sizeof ( _params ) ) ;
2013-04-05 06:13:26 +00:00
return crc ;
}
2014-09-18 16:16:52 +00:00
void TextureCache : : activateTexture ( u32 _t , CachedTexture * _pTexture )
2013-04-05 06:13:26 +00:00
{
2014-09-18 16:16:52 +00:00
glActiveTexture ( GL_TEXTURE0 + _t ) ;
2013-04-05 06:13:26 +00:00
// Bind the cached texture
2014-09-18 16:16:52 +00:00
glBindTexture ( GL_TEXTURE_2D , _pTexture - > glName ) ;
2013-04-05 06:13:26 +00:00
2014-10-09 09:01:04 +00:00
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAX_LEVEL , _pTexture - > max_level ) ;
2013-04-05 06:13:26 +00:00
// Set filter mode. Almost always bilinear, but check anyways
2014-10-24 12:55:31 +00:00
if ( ( gDP . otherMode . textureFilter = = G_TF_BILERP ) | | ( gDP . otherMode . textureFilter = = G_TF_AVERAGE ) | | ( ( gSP . objRendermode & G_OBJRM_BILERP ) ! = 0 ) | | ( config . texture . forceBilinear ) ) {
2014-10-09 09:01:04 +00:00
if ( _pTexture - > max_level > 0 )
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR_MIPMAP_NEAREST ) ;
else
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ;
} else {
if ( _pTexture - > max_level > 0 )
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_NEAREST_MIPMAP_NEAREST ) ;
else
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_NEAREST ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_NEAREST ) ;
2013-04-05 06:13:26 +00:00
}
2014-10-09 09:01:04 +00:00
2013-04-05 06:13:26 +00:00
// Set clamping modes
2014-09-18 16:16:52 +00:00
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_S , _pTexture - > clampS ? GL_CLAMP_TO_EDGE : GL_REPEAT ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_T , _pTexture - > clampT ? GL_CLAMP_TO_EDGE : GL_REPEAT ) ;
2013-04-05 06:13:26 +00:00
2014-09-18 16:16:52 +00:00
_pTexture - > lastDList = RSP . DList ;
2013-04-05 06:13:26 +00:00
2014-09-18 16:16:52 +00:00
current [ _t ] = _pTexture ;
2013-04-05 06:13:26 +00:00
}
2014-09-18 16:16:52 +00:00
void TextureCache : : activateDummy ( u32 _t )
2013-04-05 06:13:26 +00:00
{
2014-09-18 16:16:52 +00:00
glActiveTexture ( GL_TEXTURE0 + _t ) ;
2013-04-05 06:13:26 +00:00
2014-09-18 16:16:52 +00:00
glBindTexture ( GL_TEXTURE_2D , m_pDummy - > glName ) ;
2013-04-05 06:13:26 +00:00
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_NEAREST ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_NEAREST ) ;
}
2014-09-18 16:16:52 +00:00
void TextureCache : : _updateBackground ( )
2013-04-05 06:13:26 +00:00
{
u32 numBytes = gSP . bgImage . width * gSP . bgImage . height < < gSP . bgImage . size > > 1 ;
u32 crc ;
crc = CRC_Calculate ( 0xFFFFFFFF , & RDRAM [ gSP . bgImage . address ] , numBytes ) ;
2014-09-03 05:12:48 +00:00
if ( gDP . otherMode . textureLUT ! = G_TT_NONE | | gSP . bgImage . format = = G_IM_FMT_CI ) {
2013-04-05 06:13:26 +00:00
if ( gSP . bgImage . size = = G_IM_SIZ_4b )
crc = CRC_Calculate ( crc , & gDP . paletteCRC16 [ gSP . bgImage . palette ] , 4 ) ;
else if ( gSP . bgImage . size = = G_IM_SIZ_8b )
crc = CRC_Calculate ( crc , & gDP . paletteCRC256 , 4 ) ;
}
2014-09-03 05:12:48 +00:00
u32 params [ 4 ] = { gSP . bgImage . width , gSP . bgImage . height , gSP . bgImage . format , gSP . bgImage . size } ;
2014-09-18 16:16:52 +00:00
crc = CRC_Calculate ( crc , params , sizeof ( u32 ) * 4 ) ;
2014-09-22 11:40:35 +00:00
Textures : : iterator iter = m_textures . find ( crc ) ;
2014-09-18 16:16:52 +00:00
if ( iter ! = m_textures . end ( ) ) {
2014-09-22 11:40:35 +00:00
CachedTexture & current = iter - > second ;
assert ( ( current . width = = gSP . bgImage . width ) & &
( current . height = = gSP . bgImage . height ) & &
( current . format = = gSP . bgImage . format ) & &
( current . size = = gSP . bgImage . size ) ) ;
2014-09-18 16:16:52 +00:00
2014-09-22 11:40:35 +00:00
activateTexture ( 0 , & current ) ;
2014-09-18 16:16:52 +00:00
m_hits + + ;
return ;
2013-04-05 06:13:26 +00:00
}
2014-09-18 16:16:52 +00:00
m_misses + + ;
2013-04-05 06:13:26 +00:00
2013-11-07 09:01:40 +00:00
glActiveTexture ( GL_TEXTURE0 ) ;
2014-09-18 16:16:52 +00:00
CachedTexture * pCurrent = _addTexture ( crc ) ;
2013-04-05 06:13:26 +00:00
2014-09-18 16:16:52 +00:00
glBindTexture ( GL_TEXTURE_2D , pCurrent - > glName ) ;
2013-04-05 06:13:26 +00:00
2014-09-18 16:16:52 +00:00
pCurrent - > address = gSP . bgImage . address ;
2013-04-05 06:13:26 +00:00
2014-09-18 16:16:52 +00:00
pCurrent - > format = gSP . bgImage . format ;
pCurrent - > size = gSP . bgImage . size ;
2013-04-05 06:13:26 +00:00
2014-09-18 16:16:52 +00:00
pCurrent - > width = gSP . bgImage . width ;
pCurrent - > height = gSP . bgImage . height ;
2013-04-05 06:13:26 +00:00
2014-09-18 16:16:52 +00:00
pCurrent - > clampWidth = gSP . bgImage . width ;
pCurrent - > clampHeight = gSP . bgImage . height ;
pCurrent - > palette = gSP . bgImage . palette ;
pCurrent - > maskS = 0 ;
pCurrent - > maskT = 0 ;
2014-10-22 13:49:48 +00:00
pCurrent - > mirrorS = 1 ;
pCurrent - > mirrorT = 1 ;
pCurrent - > clampS = 0 ;
pCurrent - > clampT = 0 ;
2014-09-18 16:16:52 +00:00
pCurrent - > line = 0 ;
pCurrent - > tMem = 0 ;
pCurrent - > lastDList = RSP . DList ;
pCurrent - > frameBufferTexture = FALSE ;
2013-04-05 06:13:26 +00:00
2014-10-22 13:49:48 +00:00
pCurrent - > realWidth = gSP . bgImage . width ;
pCurrent - > realHeight = gSP . bgImage . height ;
2013-04-05 06:13:26 +00:00
2014-09-18 16:16:52 +00:00
pCurrent - > scaleS = 1.0f / ( f32 ) ( pCurrent - > realWidth ) ;
pCurrent - > scaleT = 1.0f / ( f32 ) ( pCurrent - > realHeight ) ;
2013-04-05 06:13:26 +00:00
2014-09-18 16:16:52 +00:00
pCurrent - > shiftScaleS = 1.0f ;
pCurrent - > shiftScaleT = 1.0f ;
2013-04-05 06:13:26 +00:00
2014-10-22 13:49:48 +00:00
pCurrent - > offsetS = 0.5f ;
pCurrent - > offsetT = 0.5f ;
2014-09-18 16:16:52 +00:00
_loadBackground ( pCurrent ) ;
activateTexture ( 0 , pCurrent ) ;
2013-04-05 06:13:26 +00:00
2014-09-18 16:16:52 +00:00
m_cachedBytes + = pCurrent - > textureBytes ;
current [ 0 ] = pCurrent ;
2013-04-05 06:13:26 +00:00
}
2014-09-18 16:16:52 +00:00
void TextureCache : : update ( u32 _t )
2013-04-05 06:13:26 +00:00
{
2013-04-22 04:23:39 +00:00
u32 crc , maxTexels ;
2013-04-05 06:13:26 +00:00
u32 tileWidth , maskWidth , loadWidth , lineWidth , clampWidth , height ;
u32 tileHeight , maskHeight , loadHeight , lineHeight , clampHeight , width ;
2014-09-18 16:16:52 +00:00
if ( m_bitDepth ! = config . texture . textureBitDepth )
2013-04-05 06:13:26 +00:00
{
2014-09-18 16:16:52 +00:00
destroy ( ) ;
init ( ) ;
2013-04-05 06:13:26 +00:00
}
2014-09-18 16:16:52 +00:00
switch ( gSP . textureTile [ _t ] - > textureMode ) {
2013-06-09 11:55:21 +00:00
case TEXTUREMODE_BGIMAGE :
2014-09-18 16:16:52 +00:00
_updateBackground ( ) ;
2013-04-05 06:13:26 +00:00
return ;
2013-06-09 11:55:21 +00:00
case TEXTUREMODE_FRAMEBUFFER :
2014-09-18 16:16:52 +00:00
FrameBuffer_ActivateBufferTexture ( _t , gSP . textureTile [ _t ] - > frameBuffer ) ;
2013-04-05 06:13:26 +00:00
return ;
2013-06-09 11:55:21 +00:00
case TEXTUREMODE_FRAMEBUFFER_BG :
2014-09-18 16:16:52 +00:00
FrameBuffer_ActivateBufferTextureBG ( _t , gSP . textureTile [ _t ] - > frameBuffer ) ;
2013-06-09 11:55:21 +00:00
return ;
2013-04-05 06:13:26 +00:00
}
2014-09-18 16:16:52 +00:00
maxTexels = imageFormat [ gSP . textureTile [ _t ] - > size ] [ gSP . textureTile [ _t ] - > format ] . maxTexels ;
2013-04-05 06:13:26 +00:00
// Here comes a bunch of code that just calculates the texture size...I wish there was an easier way...
2014-09-18 16:16:52 +00:00
tileWidth = gSP . textureTile [ _t ] - > lrs - gSP . textureTile [ _t ] - > uls + 1 ;
tileHeight = gSP . textureTile [ _t ] - > lrt - gSP . textureTile [ _t ] - > ult + 1 ;
2013-04-05 06:13:26 +00:00
2014-09-18 16:16:52 +00:00
maskWidth = 1 < < gSP . textureTile [ _t ] - > masks ;
maskHeight = 1 < < gSP . textureTile [ _t ] - > maskt ;
2013-04-05 06:13:26 +00:00
loadWidth = gDP . loadTile - > lrs - gDP . loadTile - > uls + 1 ;
loadHeight = gDP . loadTile - > lrt - gDP . loadTile - > ult + 1 ;
2014-09-18 16:16:52 +00:00
lineWidth = gSP . textureTile [ _t ] - > line < < imageFormat [ gSP . textureTile [ _t ] - > size ] [ gSP . textureTile [ _t ] - > format ] . lineShift ;
2013-04-05 06:13:26 +00:00
if ( lineWidth ) // Don't allow division by zero
lineHeight = min ( maxTexels / lineWidth , tileHeight ) ;
else
lineHeight = 0 ;
2014-09-18 16:16:52 +00:00
if ( gSP . textureTile [ _t ] - > textureMode = = TEXTUREMODE_TEXRECT )
2013-04-05 06:13:26 +00:00
{
2014-09-18 16:16:52 +00:00
u16 texRectWidth = gDP . texRect . width - gSP . textureTile [ _t ] - > uls ;
u16 texRectHeight = gDP . texRect . height - gSP . textureTile [ _t ] - > ult ;
2014-11-01 08:32:00 +00:00
const bool bUseLoadSizes = gDP . loadTile - > loadType = = LOADTYPE_TILE & &
2014-11-03 05:18:15 +00:00
( gSP . textureTile [ _t ] - > tmem = = gDP . loadTile - > tmem ) ;
2013-04-05 06:13:26 +00:00
2014-09-18 16:16:52 +00:00
if ( gSP . textureTile [ _t ] - > masks & & ( ( maskWidth * maskHeight ) < = maxTexels ) )
2013-04-05 06:13:26 +00:00
width = maskWidth ;
2014-11-01 08:32:00 +00:00
else if ( bUseLoadSizes ) {
width = loadWidth ;
if ( gSP . textureTile [ _t ] - > size < gDP . loadTile - > size )
width < < = ( gDP . loadTile - > size - gSP . textureTile [ _t ] - > size ) ;
} else if ( ( tileWidth * tileHeight ) < = maxTexels )
2013-04-05 06:13:26 +00:00
width = tileWidth ;
else if ( ( tileWidth * texRectHeight ) < = maxTexels )
width = tileWidth ;
else if ( ( texRectWidth * tileHeight ) < = maxTexels )
width = gDP . texRect . width ;
else if ( ( texRectWidth * texRectHeight ) < = maxTexels )
width = gDP . texRect . width ;
else
width = lineWidth ;
2014-09-18 16:16:52 +00:00
if ( gSP . textureTile [ _t ] - > maskt & & ( ( maskWidth * maskHeight ) < = maxTexels ) )
2013-04-05 06:13:26 +00:00
height = maskHeight ;
2014-11-01 08:32:00 +00:00
else if ( bUseLoadSizes )
height = loadHeight ;
2013-04-05 06:13:26 +00:00
else if ( ( tileWidth * tileHeight ) < = maxTexels )
height = tileHeight ;
else if ( ( tileWidth * texRectHeight ) < = maxTexels )
height = gDP . texRect . height ;
else if ( ( texRectWidth * tileHeight ) < = maxTexels )
height = tileHeight ;
else if ( ( texRectWidth * texRectHeight ) < = maxTexels )
height = gDP . texRect . height ;
else
height = lineHeight ;
// gSP.textureTile[t]->masks = 0;
// gSP.textureTile[t]->maskt = 0;
}
else
{
2014-09-18 16:16:52 +00:00
if ( gSP . textureTile [ _t ] - > masks & & ( ( maskWidth * maskHeight ) < = maxTexels ) )
2013-04-05 06:13:26 +00:00
width = maskWidth ; // Use mask width if set and valid
else if ( ( tileWidth * tileHeight ) < = maxTexels )
width = tileWidth ; // else use tile width if valid
2014-09-18 16:16:52 +00:00
else if ( gSP . textureTile [ _t ] - > loadType = = LOADTYPE_TILE )
2013-04-05 06:13:26 +00:00
width = loadWidth ; // else use load width if load done with LoadTile
else
width = lineWidth ; // else use line-based width
2014-09-18 16:16:52 +00:00
if ( gSP . textureTile [ _t ] - > maskt & & ( ( maskWidth * maskHeight ) < = maxTexels ) )
2013-04-05 06:13:26 +00:00
height = maskHeight ;
else if ( ( tileWidth * tileHeight ) < = maxTexels )
height = tileHeight ;
2014-09-18 16:16:52 +00:00
else if ( gSP . textureTile [ _t ] - > loadType = = LOADTYPE_TILE )
2013-04-05 06:13:26 +00:00
height = loadHeight ;
else
height = lineHeight ;
}
/* if (gDP.loadTile->frameBuffer)
{
FrameBuffer_ActivateBufferTexture ( t , gDP . loadTile - > frameBuffer ) ;
return ;
} */
2014-11-01 08:32:53 +00:00
clampWidth = ( gSP . textureTile [ _t ] - > clamps & & gDP . otherMode . cycleType ! = G_CYC_COPY ) ? tileWidth : width ;
clampHeight = ( gSP . textureTile [ _t ] - > clampt & & gDP . otherMode . cycleType ! = G_CYC_COPY ) ? tileHeight : height ;
2013-04-05 06:13:26 +00:00
if ( clampWidth > 256 )
2014-09-18 16:16:52 +00:00
gSP . textureTile [ _t ] - > clamps = 0 ;
2013-04-05 06:13:26 +00:00
if ( clampHeight > 256 )
2014-09-18 16:16:52 +00:00
gSP . textureTile [ _t ] - > clampt = 0 ;
2013-04-05 06:13:26 +00:00
// Make sure masking is valid
2014-09-01 16:21:40 +00:00
if ( maskWidth > width )
2013-04-05 06:13:26 +00:00
{
2014-09-18 16:16:52 +00:00
gSP . textureTile [ _t ] - > masks = powof ( width ) ;
maskWidth = 1 < < gSP . textureTile [ _t ] - > masks ;
2013-04-05 06:13:26 +00:00
}
if ( maskHeight > height )
{
2014-09-18 16:16:52 +00:00
gSP . textureTile [ _t ] - > maskt = powof ( height ) ;
maskHeight = 1 < < gSP . textureTile [ _t ] - > maskt ;
2013-04-05 06:13:26 +00:00
}
2014-09-03 05:12:48 +00:00
{
TextureParams params ;
params . width = width ;
params . height = height ;
params . clampWidth = clampWidth ;
params . clampHeight = clampHeight ;
2014-09-18 16:16:52 +00:00
params . maskS = gSP . textureTile [ _t ] - > masks ;
params . maskT = gSP . textureTile [ _t ] - > maskt ;
params . mirrorS = gSP . textureTile [ _t ] - > mirrors ;
params . mirrorT = gSP . textureTile [ _t ] - > mirrort ;
params . clampS = gSP . textureTile [ _t ] - > clamps ;
params . clampT = gSP . textureTile [ _t ] - > clampt ;
params . format = gSP . textureTile [ _t ] - > format ;
params . size = gSP . textureTile [ _t ] - > size ;
2013-04-05 06:13:26 +00:00
2014-09-18 16:16:52 +00:00
crc = _calculateCRC ( _t , params ) ;
}
2013-04-05 06:13:26 +00:00
2014-09-18 16:16:52 +00:00
if ( current [ _t ] ! = NULL & & current [ _t ] - > crc = = crc ) {
activateTexture ( _t , current [ _t ] ) ;
return ;
}
2013-04-05 06:13:26 +00:00
2014-09-22 11:40:35 +00:00
Textures : : iterator iter = m_textures . find ( crc ) ;
2014-09-18 16:16:52 +00:00
if ( iter ! = m_textures . end ( ) ) {
2014-09-22 11:40:35 +00:00
CachedTexture & current = iter - > second ;
assert ( ( current . width = = width ) & &
( current . height = = height ) & &
( current . clampWidth = = clampWidth ) & &
( current . clampHeight = = clampHeight ) & &
( current . maskS = = gSP . textureTile [ _t ] - > masks ) & &
( current . maskT = = gSP . textureTile [ _t ] - > maskt ) & &
( current . mirrorS = = gSP . textureTile [ _t ] - > mirrors ) & &
( current . mirrorT = = gSP . textureTile [ _t ] - > mirrort ) & &
( current . clampS = = gSP . textureTile [ _t ] - > clamps ) & &
( current . clampT = = gSP . textureTile [ _t ] - > clampt ) & &
( current . format = = gSP . textureTile [ _t ] - > format ) & &
( current . size = = gSP . textureTile [ _t ] - > size )
2014-09-18 16:16:52 +00:00
) ;
2014-09-22 11:40:35 +00:00
activateTexture ( _t , & current ) ;
2014-09-18 16:16:52 +00:00
m_hits + + ;
return ;
2013-04-05 06:13:26 +00:00
}
2014-09-18 16:16:52 +00:00
m_misses + + ;
2013-04-05 06:13:26 +00:00
2014-09-18 16:16:52 +00:00
glActiveTexture ( GL_TEXTURE0 + _t ) ;
2013-04-05 06:13:26 +00:00
2014-09-18 16:16:52 +00:00
CachedTexture * pCurrent = _addTexture ( crc ) ;
2013-04-05 06:13:26 +00:00
2014-09-18 16:16:52 +00:00
glBindTexture ( GL_TEXTURE_2D , pCurrent - > glName ) ;
2013-04-05 06:13:26 +00:00
2014-09-18 16:16:52 +00:00
pCurrent - > address = gDP . textureImage . address ;
2013-04-05 06:13:26 +00:00
2014-09-18 16:16:52 +00:00
pCurrent - > format = gSP . textureTile [ _t ] - > format ;
pCurrent - > size = gSP . textureTile [ _t ] - > size ;
2013-04-05 06:13:26 +00:00
2014-09-18 16:16:52 +00:00
pCurrent - > width = width ;
pCurrent - > height = height ;
2013-04-05 06:13:26 +00:00
2014-09-18 16:16:52 +00:00
pCurrent - > clampWidth = clampWidth ;
pCurrent - > clampHeight = clampHeight ;
2013-04-05 06:13:26 +00:00
2014-09-18 16:16:52 +00:00
pCurrent - > palette = gSP . textureTile [ _t ] - > palette ;
/* pCurrent->fulS = gSP.textureTile[t]->fulS;
pCurrent - > fulT = gSP . textureTile [ t ] - > fulT ;
pCurrent - > ulS = gSP . textureTile [ t ] - > ulS ;
pCurrent - > ulT = gSP . textureTile [ t ] - > ulT ;
pCurrent - > lrS = gSP . textureTile [ t ] - > lrS ;
pCurrent - > lrT = gSP . textureTile [ t ] - > lrT ; */
pCurrent - > maskS = gSP . textureTile [ _t ] - > masks ;
pCurrent - > maskT = gSP . textureTile [ _t ] - > maskt ;
pCurrent - > mirrorS = gSP . textureTile [ _t ] - > mirrors ;
pCurrent - > mirrorT = gSP . textureTile [ _t ] - > mirrort ;
pCurrent - > clampS = gSP . textureTile [ _t ] - > clamps ;
pCurrent - > clampT = gSP . textureTile [ _t ] - > clampt ;
pCurrent - > line = gSP . textureTile [ _t ] - > line ;
pCurrent - > tMem = gSP . textureTile [ _t ] - > tmem ;
pCurrent - > lastDList = RSP . DList ;
pCurrent - > frameBufferTexture = FALSE ;
2013-04-05 06:13:26 +00:00
2014-09-18 16:16:52 +00:00
/* if (pCurrent->clampS)
pCurrent - > realWidth = pow2 ( clampWidth ) ;
else if ( pCurrent - > mirrorS )
pCurrent - > realWidth = maskWidth < < 1 ;
2013-04-05 06:13:26 +00:00
else
2014-09-18 16:16:52 +00:00
pCurrent - > realWidth = pow2 ( width ) ;
2013-04-05 06:13:26 +00:00
2014-09-18 16:16:52 +00:00
if ( pCurrent - > clampT )
pCurrent - > realHeight = pow2 ( clampHeight ) ;
else if ( pCurrent - > mirrorT )
pCurrent - > realHeight = maskHeight < < 1 ;
2013-04-05 06:13:26 +00:00
else
2014-09-18 16:16:52 +00:00
pCurrent - > realHeight = pow2 ( height ) ; */
2013-04-05 06:13:26 +00:00
2014-09-18 16:16:52 +00:00
if ( pCurrent - > clampS )
pCurrent - > realWidth = pow2 ( clampWidth ) ;
else if ( pCurrent - > mirrorS )
pCurrent - > realWidth = maskWidth < < 1 ;
2013-04-05 06:13:26 +00:00
else
2014-09-18 16:16:52 +00:00
pCurrent - > realWidth = pow2 ( width ) ;
2013-04-05 06:13:26 +00:00
2014-09-18 16:16:52 +00:00
if ( pCurrent - > clampT )
pCurrent - > realHeight = pow2 ( clampHeight ) ;
else if ( pCurrent - > mirrorT )
pCurrent - > realHeight = maskHeight < < 1 ;
2013-04-05 06:13:26 +00:00
else
2014-09-18 16:16:52 +00:00
pCurrent - > realHeight = pow2 ( height ) ;
2013-04-05 06:13:26 +00:00
2014-09-18 16:16:52 +00:00
pCurrent - > scaleS = 1.0f / ( f32 ) ( pCurrent - > realWidth ) ;
pCurrent - > scaleT = 1.0f / ( f32 ) ( pCurrent - > realHeight ) ;
2013-04-05 06:13:26 +00:00
2014-09-18 16:16:52 +00:00
pCurrent - > shiftScaleS = 1.0f ;
pCurrent - > shiftScaleT = 1.0f ;
2013-04-05 06:13:26 +00:00
2014-09-18 16:16:52 +00:00
pCurrent - > offsetS = 0.5f ;
pCurrent - > offsetT = 0.5f ;
2013-04-05 06:13:26 +00:00
2014-09-18 16:16:52 +00:00
if ( gSP . textureTile [ _t ] - > shifts > 10 )
pCurrent - > shiftScaleS = ( f32 ) ( 1 < < ( 16 - gSP . textureTile [ _t ] - > shifts ) ) ;
else if ( gSP . textureTile [ _t ] - > shifts > 0 )
pCurrent - > shiftScaleS / = ( f32 ) ( 1 < < gSP . textureTile [ _t ] - > shifts ) ;
2013-04-05 06:13:26 +00:00
2014-09-18 16:16:52 +00:00
if ( gSP . textureTile [ _t ] - > shiftt > 10 )
pCurrent - > shiftScaleT = ( f32 ) ( 1 < < ( 16 - gSP . textureTile [ _t ] - > shiftt ) ) ;
else if ( gSP . textureTile [ _t ] - > shiftt > 0 )
pCurrent - > shiftScaleT / = ( f32 ) ( 1 < < gSP . textureTile [ _t ] - > shiftt ) ;
2013-04-05 06:13:26 +00:00
2014-10-09 09:01:04 +00:00
_load ( _t , pCurrent ) ;
2014-09-18 16:16:52 +00:00
activateTexture ( _t , pCurrent ) ;
2013-04-05 06:13:26 +00:00
2014-09-18 16:16:52 +00:00
m_cachedBytes + = pCurrent - > textureBytes ;
current [ _t ] = pCurrent ;
2013-04-05 06:13:26 +00:00
}