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>
2015-04-12 12:49:40 +00:00
# include <thread> // std::this_thread::sleep_for
# include <chrono> // std::chrono::seconds
2017-10-02 09:58:55 +00:00
# include "Platform.h"
2013-04-05 06:13:26 +00:00
# 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"
2015-04-12 12:49:40 +00:00
# include "Keys.h"
2014-11-17 14:02:46 +00:00
# include "GLideNHQ/Ext_TxFilter.h"
2016-06-10 11:58:47 +00:00
# include "TextureFilterHandler.h"
2017-10-25 17:20:53 +00:00
# include "DisplayLoadProgress.h"
2016-12-24 17:36:27 +00:00
# include "Graphics/Context.h"
2016-12-27 04:15:29 +00:00
# include "Graphics/Parameters.h"
2017-01-15 07:57:25 +00:00
# include "DisplayWindow.h"
2013-04-05 06:13:26 +00:00
2014-09-01 16:19:20 +00:00
using namespace std ;
2017-01-21 12:48:02 +00:00
using namespace graphics ;
2014-09-01 16:19:20 +00:00
2013-04-05 06:13:26 +00:00
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 ) ] ) ;
}
2014-12-11 07:48:55 +00:00
inline u32 GetCI16IA_RGBA8888 ( u64 * src , u16 x , u16 i , u8 palette )
{
const u16 tex = ( ( u16 * ) src ) [ x ^ i ] ;
const u16 col = ( * ( u16 * ) & TMEM [ 256 + ( tex > > 8 ) ] ) ;
const u16 c = col > > 8 ;
const u16 a = col & 0xFF ;
return ( a < < 24 ) | ( c < < 16 ) | ( c < < 8 ) | c ;
}
inline u32 GetCI16IA_RGBA4444 ( u64 * src , u16 x , u16 i , u8 palette )
{
const u16 tex = ( ( u16 * ) src ) [ x ^ i ] ;
const u16 col = ( * ( u16 * ) & TMEM [ 256 + ( tex > > 8 ) ] ) ;
const u16 c = col > > 12 ;
const u16 a = col & 0x0F ;
return ( a < < 12 ) | ( c < < 8 ) | ( c < < 4 ) | c ;
}
inline u32 GetCI16RGBA_RGBA8888 ( u64 * src , u16 x , u16 i , u8 palette )
{
2015-06-04 18:07:51 +00:00
const u16 tex = ( ( ( u16 * ) src ) [ x ^ i ] ) & 0xFF ;
return RGBA5551_RGBA8888 ( ( ( u16 * ) & TMEM [ 256 ] ) [ tex < < 2 ] ) ;
2014-12-11 07:48:55 +00:00
}
inline u32 GetCI16RGBA_RGBA5551 ( u64 * src , u16 x , u16 i , u8 palette )
{
2015-06-04 18:07:51 +00:00
const u16 tex = ( ( ( u16 * ) src ) [ x ^ i ] ) & 0xFF ;
return RGBA5551_RGBA5551 ( ( ( u16 * ) & TMEM [ 256 ] ) [ tex < < 2 ] ) ;
2014-12-11 07:48:55 +00:00
}
inline u32 GetRGBA5551_RGBA8888 ( u64 * src , u16 x , u16 i , u8 palette )
2013-04-05 06:13:26 +00:00
{
2014-10-28 12:02:33 +00:00
u16 tex = ( ( u16 * ) src ) [ x ^ i ] ;
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 ] ;
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 ] ) ;
}
2017-10-22 13:50:57 +00:00
#if 0
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 ;
}
2017-10-22 13:50:57 +00:00
# else
inline u32 YUV_RGBA8888 ( u8 y , u8 u , u8 v )
2014-10-28 06:12:30 +00:00
{
2017-10-22 13:50:57 +00:00
return ( 0xff < < 24 ) | ( y < < 16 ) | ( v < < 8 ) | u ;
2014-10-28 06:12:30 +00:00
}
2017-10-22 13:50:57 +00:00
# endif
2014-10-28 06:12:30 +00:00
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 ;
}
2017-02-22 05:19:06 +00:00
struct TextureLoadParameters
2013-04-05 06:13:26 +00:00
{
2017-01-28 09:52:09 +00:00
GetTexelFunc Get16 ;
DatatypeParam glType16 ;
InternalColorFormatParam glInternalFormat16 ;
GetTexelFunc Get32 ;
DatatypeParam glType32 ;
InternalColorFormatParam glInternalFormat32 ;
InternalColorFormatParam autoFormat ;
u32 lineShift ;
u32 maxTexels ;
2017-01-28 03:11:45 +00:00
} ;
struct ImageFormat {
ImageFormat ( ) ;
TextureLoadParameters tlp [ 4 ] [ 4 ] [ 5 ] ;
static ImageFormat & get ( ) {
static ImageFormat imageFmt ;
return imageFmt ;
}
} ;
ImageFormat : : ImageFormat ( )
{
2017-02-22 05:19:06 +00:00
TextureLoadParameters imageFormat [ 4 ] [ 4 ] [ 5 ] =
{ // G_TT_NONE
{ // Get16 glType16 glInternalFormat16 Get32 glType32 glInternalFormat32 autoFormat
{ // 4-bit
{ GetI4_RGBA4444 , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetI4_RGBA8888 , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 4 , 8192 } , // RGBA as I
{ GetNone , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 4 , 8192 } , // YUV
{ GetI4_RGBA4444 , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetI4_RGBA8888 , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 4 , 8192 } , // CI without palette
{ GetIA31_RGBA4444 , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetIA31_RGBA8888 , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 4 , 8192 } , // IA
{ GetI4_RGBA4444 , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetI4_RGBA8888 , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 4 , 8192 } , // I
} ,
{ // 8-bit
{ GetI8_RGBA4444 , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetI8_RGBA8888 , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 3 , 4096 } , // RGBA as I
{ GetNone , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 0 , 4096 } , // YUV
{ GetI8_RGBA4444 , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetI8_RGBA8888 , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 3 , 4096 } , // CI without palette
{ GetIA44_RGBA4444 , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetIA44_RGBA8888 , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 3 , 4096 } , // IA
{ GetI8_RGBA4444 , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetI8_RGBA8888 , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 3 , 4096 } , // I
} ,
{ // 16-bit
{ GetRGBA5551_RGBA5551 , datatype : : UNSIGNED_SHORT_5_5_5_1 , internalcolorFormat : : RGB5_A1 , GetRGBA5551_RGBA8888 , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGB5_A1 , 2 , 2048 } , // RGBA
2017-10-22 13:50:57 +00:00
{ GetNone , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 2 , 2048 } , // YUV
2017-02-22 05:19:06 +00:00
{ GetIA88_RGBA4444 , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetIA88_RGBA8888 , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 2 , 2048 } , // CI as IA
{ GetIA88_RGBA4444 , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetIA88_RGBA8888 , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 2 , 2048 } , // IA
{ GetNone , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 0 , 2048 } , // I
} ,
{ // 32-bit
{ GetRGBA8888_RGBA4444 , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetRGBA8888_RGBA8888 , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 2 , 1024 } , // RGBA
{ GetNone , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 0 , 1024 } , // YUV
{ GetNone , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 0 , 1024 } , // CI
{ GetNone , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 0 , 1024 } , // IA
{ GetNone , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 0 , 1024 } , // I
}
2014-12-11 07:48:55 +00:00
} ,
2017-02-22 05:19:06 +00:00
// DUMMY
{ // Get16 glType16 glInternalFormat16 Get32 glType32 glInternalFormat32 autoFormat
{ // 4-bit
{ GetCI4RGBA_RGBA5551 , datatype : : UNSIGNED_SHORT_5_5_5_1 , internalcolorFormat : : RGB5_A1 , GetCI4RGBA_RGBA8888 , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGB5_A1 , 4 , 4096 } , // CI (Banjo-Kazooie uses this, doesn't make sense, but it works...)
{ GetNone , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 4 , 8192 } , // YUV
{ GetCI4RGBA_RGBA5551 , datatype : : UNSIGNED_SHORT_5_5_5_1 , internalcolorFormat : : RGB5_A1 , GetCI4RGBA_RGBA8888 , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGB5_A1 , 4 , 4096 } , // CI
{ GetCI4RGBA_RGBA5551 , datatype : : UNSIGNED_SHORT_5_5_5_1 , internalcolorFormat : : RGB5_A1 , GetCI4RGBA_RGBA8888 , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGB5_A1 , 4 , 4096 } , // IA as CI
{ GetCI4RGBA_RGBA5551 , datatype : : UNSIGNED_SHORT_5_5_5_1 , internalcolorFormat : : RGB5_A1 , GetCI4RGBA_RGBA8888 , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGB5_A1 , 4 , 4096 } , // I as CI
} ,
{ // 8-bit
{ GetCI8RGBA_RGBA5551 , datatype : : UNSIGNED_SHORT_5_5_5_1 , internalcolorFormat : : RGB5_A1 , GetCI8RGBA_RGBA8888 , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGB5_A1 , 3 , 2048 } , // RGBA
{ GetNone , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 0 , 4096 } , // YUV
{ GetCI8RGBA_RGBA5551 , datatype : : UNSIGNED_SHORT_5_5_5_1 , internalcolorFormat : : RGB5_A1 , GetCI8RGBA_RGBA8888 , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGB5_A1 , 3 , 2048 } , // CI
{ GetCI8RGBA_RGBA5551 , datatype : : UNSIGNED_SHORT_5_5_5_1 , internalcolorFormat : : RGB5_A1 , GetCI8RGBA_RGBA8888 , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGB5_A1 , 3 , 2048 } , // IA as CI
{ GetCI8RGBA_RGBA5551 , datatype : : UNSIGNED_SHORT_5_5_5_1 , internalcolorFormat : : RGB5_A1 , GetCI8RGBA_RGBA8888 , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGB5_A1 , 3 , 2048 } , // I as CI
} ,
{ // 16-bit
{ GetCI16RGBA_RGBA5551 , datatype : : UNSIGNED_SHORT_5_5_5_1 , internalcolorFormat : : RGB5_A1 , GetRGBA5551_RGBA8888 , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGB5_A1 , 2 , 2048 } , // RGBA
2017-10-22 13:50:57 +00:00
{ GetNone , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 2 , 2048 } , // YUV
2017-02-22 05:19:06 +00:00
{ GetNone , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 0 , 2048 } , // CI
{ GetCI16RGBA_RGBA5551 , datatype : : UNSIGNED_SHORT_5_5_5_1 , internalcolorFormat : : RGB5_A1 , GetCI16RGBA_RGBA8888 , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGB5_A1 , 2 , 2048 } , // IA as CI
{ GetNone , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 0 , 2048 } , // I
} ,
{ // 32-bit
{ GetRGBA8888_RGBA4444 , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetRGBA8888_RGBA8888 , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 2 , 1024 } , // RGBA
{ GetNone , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 0 , 1024 } , // YUV
{ GetNone , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 0 , 1024 } , // CI
{ GetNone , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 0 , 1024 } , // IA
{ GetNone , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 0 , 1024 } , // I
}
2014-12-11 07:48:55 +00:00
} ,
2017-02-22 05:19:06 +00:00
// G_TT_RGBA16
{ // Get16 glType16 glInternalFormat16 Get32 glType32 glInternalFormat32 autoFormat
{ // 4-bit
{ GetCI4RGBA_RGBA5551 , datatype : : UNSIGNED_SHORT_5_5_5_1 , internalcolorFormat : : RGB5_A1 , GetCI4RGBA_RGBA8888 , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGB5_A1 , 4 , 4096 } , // CI (Banjo-Kazooie uses this, doesn't make sense, but it works...)
{ GetNone , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 4 , 8192 } , // YUV
{ GetCI4RGBA_RGBA5551 , datatype : : UNSIGNED_SHORT_5_5_5_1 , internalcolorFormat : : RGB5_A1 , GetCI4RGBA_RGBA8888 , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGB5_A1 , 4 , 4096 } , // CI
{ GetCI4RGBA_RGBA5551 , datatype : : UNSIGNED_SHORT_5_5_5_1 , internalcolorFormat : : RGB5_A1 , GetCI4RGBA_RGBA8888 , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGB5_A1 , 4 , 4096 } , // IA as CI
{ GetCI4RGBA_RGBA5551 , datatype : : UNSIGNED_SHORT_5_5_5_1 , internalcolorFormat : : RGB5_A1 , GetCI4RGBA_RGBA8888 , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGB5_A1 , 4 , 4096 } , // I as CI
} ,
{ // 8-bit
{ GetCI8RGBA_RGBA5551 , datatype : : UNSIGNED_SHORT_5_5_5_1 , internalcolorFormat : : RGB5_A1 , GetCI8RGBA_RGBA8888 , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGB5_A1 , 3 , 2048 } , // RGBA
{ GetNone , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 0 , 4096 } , // YUV
{ GetCI8RGBA_RGBA5551 , datatype : : UNSIGNED_SHORT_5_5_5_1 , internalcolorFormat : : RGB5_A1 , GetCI8RGBA_RGBA8888 , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGB5_A1 , 3 , 2048 } , // CI
{ GetCI8RGBA_RGBA5551 , datatype : : UNSIGNED_SHORT_5_5_5_1 , internalcolorFormat : : RGB5_A1 , GetCI8RGBA_RGBA8888 , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGB5_A1 , 3 , 2048 } , // IA as CI
{ GetCI8RGBA_RGBA5551 , datatype : : UNSIGNED_SHORT_5_5_5_1 , internalcolorFormat : : RGB5_A1 , GetCI8RGBA_RGBA8888 , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGB5_A1 , 3 , 2048 } , // I as CI
} ,
{ // 16-bit
{ GetCI16RGBA_RGBA5551 , datatype : : UNSIGNED_SHORT_5_5_5_1 , internalcolorFormat : : RGB5_A1 , GetRGBA5551_RGBA8888 , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGB5_A1 , 2 , 2048 } , // RGBA
2017-10-22 13:50:57 +00:00
{ GetNone , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 2 , 2048 } , // YUV
2017-02-22 05:19:06 +00:00
{ GetNone , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 0 , 2048 } , // CI
{ GetCI16RGBA_RGBA5551 , datatype : : UNSIGNED_SHORT_5_5_5_1 , internalcolorFormat : : RGB5_A1 , GetCI16RGBA_RGBA8888 , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGB5_A1 , 2 , 2048 } , // IA as CI
{ GetNone , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 0 , 2048 } , // I
} ,
{ // 32-bit
{ GetRGBA8888_RGBA4444 , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetRGBA8888_RGBA8888 , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 2 , 1024 } , // RGBA
{ GetNone , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 0 , 1024 } , // YUV
{ GetNone , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 0 , 1024 } , // CI
{ GetNone , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 0 , 1024 } , // IA
{ GetNone , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 0 , 1024 } , // I
}
2014-12-11 07:48:55 +00:00
} ,
2017-02-22 05:19:06 +00:00
// G_TT_IA16
{ // Get16 glType16 glInternalFormat16 Get32 glType32 glInternalFormat32 autoFormat
{ // 4-bit
{ GetCI4IA_RGBA4444 , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetCI4IA_RGBA8888 , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 4 , 4096 } , // IA
{ GetNone , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 4 , 8192 } , // YUV
{ GetCI4IA_RGBA4444 , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetCI4IA_RGBA8888 , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 4 , 4096 } , // CI
{ GetCI4IA_RGBA4444 , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetCI4IA_RGBA8888 , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 4 , 4096 } , // IA
{ GetCI4IA_RGBA4444 , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetCI4IA_RGBA8888 , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 4 , 4096 } , // I
} ,
{ // 8-bit
{ GetCI8IA_RGBA4444 , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetCI8IA_RGBA8888 , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 3 , 2048 } , // RGBA
{ GetNone , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 0 , 4096 } , // YUV
{ GetCI8IA_RGBA4444 , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetCI8IA_RGBA8888 , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 3 , 2048 } , // CI
{ GetCI8IA_RGBA4444 , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetCI8IA_RGBA8888 , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 3 , 2048 } , // IA
{ GetCI8IA_RGBA4444 , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetCI8IA_RGBA8888 , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 3 , 2048 } , // I
} ,
{ // 16-bit
{ GetCI16IA_RGBA4444 , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetCI16IA_RGBA8888 , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 2 , 2048 } , // RGBA
{ GetNone , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 2 , 2048 } , // YUV
{ GetNone , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 0 , 2048 } , // CI
{ GetCI16IA_RGBA4444 , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetCI16IA_RGBA8888 , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 2 , 2048 } , // IA
{ GetNone , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 0 , 2048 } , // I
} ,
{ // 32-bit
{ GetRGBA8888_RGBA4444 , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetRGBA8888_RGBA8888 , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 2 , 1024 } , // RGBA
{ GetNone , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 0 , 1024 } , // YUV
{ GetNone , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 0 , 1024 } , // CI
{ GetNone , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 0 , 1024 } , // IA
{ GetNone , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 0 , 1024 } , // I
}
2014-12-11 07:48:55 +00:00
}
2017-02-22 05:19:06 +00:00
} ;
memcpy ( tlp , imageFormat , sizeof ( tlp ) ) ;
}
2013-04-05 06:13:26 +00:00
2014-11-17 14:02:46 +00:00
/** cite from RiceVideo */
inline u32 CalculateDXT ( u32 txl2words )
{
if ( txl2words = = 0 ) return 1 ;
else return ( 2048 + txl2words - 1 ) / txl2words ;
}
u32 sizeBytes [ 4 ] = { 0 , 1 , 2 , 4 } ;
inline u32 Txl2Words ( u32 width , u32 size )
{
if ( size = = 0 )
2014-11-26 13:44:18 +00:00
return max ( 1U , width / 16 ) ;
2014-11-17 14:02:46 +00:00
else
2014-11-26 13:44:18 +00:00
return max ( 1U , width * sizeBytes [ size ] / 8 ) ;
2014-11-17 14:02:46 +00:00
}
inline u32 ReverseDXT ( u32 val , u32 lrs , u32 width , u32 size )
{
if ( val = = 0x800 ) return 1 ;
int low = 2047 / val ;
if ( CalculateDXT ( low ) > val ) low + + ;
int high = 2047 / ( val - 1 ) ;
if ( low = = high ) return low ;
for ( int i = low ; i < = high ; i + + ) {
if ( Txl2Words ( width , size ) = = ( u32 ) i )
return i ;
}
return ( low + high ) / 2 ;
}
/** end RiceVideo cite */
2015-03-31 12:44:41 +00:00
TextureCache & TextureCache : : get ( ) {
static TextureCache cache ;
return cache ;
}
2015-05-06 12:36:07 +00:00
void TextureCache : : _initDummyTexture ( CachedTexture * _pDummy )
2013-04-05 06:13:26 +00:00
{
2015-05-06 12:36:07 +00:00
_pDummy - > address = 0 ;
_pDummy - > clampS = 1 ;
_pDummy - > clampT = 1 ;
_pDummy - > clampWidth = 2 ;
_pDummy - > clampHeight = 2 ;
_pDummy - > crc = 0 ;
_pDummy - > format = 0 ;
_pDummy - > size = 0 ;
2015-05-06 13:47:12 +00:00
_pDummy - > frameBufferTexture = CachedTexture : : fbNone ;
2015-05-06 12:36:07 +00:00
_pDummy - > width = 2 ;
_pDummy - > height = 2 ;
_pDummy - > realWidth = 2 ;
_pDummy - > realHeight = 2 ;
_pDummy - > maskS = 0 ;
_pDummy - > maskT = 0 ;
_pDummy - > scaleS = 0.5f ;
_pDummy - > scaleT = 0.5f ;
_pDummy - > shiftScaleS = 1.0f ;
_pDummy - > shiftScaleT = 1.0f ;
_pDummy - > textureBytes = 2 * 2 * 4 ;
_pDummy - > tMem = 0 ;
}
2013-04-05 06:13:26 +00:00
2015-05-06 12:36:07 +00:00
void TextureCache : : init ( )
{
2015-05-08 12:33:03 +00:00
m_curUnpackAlignment = 0 ;
2014-09-18 16:16:52 +00:00
2015-05-06 12:36:07 +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
2017-01-01 14:59:54 +00:00
m_pDummy = addFrameBufferTexture ( false ) ; // we don't want to remove dummy texture
2015-05-06 12:36:07 +00:00
_initDummyTexture ( m_pDummy ) ;
2015-03-31 15:24:49 +00:00
2017-01-21 12:48:02 +00:00
Context : : InitTextureParams params ;
params . handle = m_pDummy - > name ;
2016-12-29 10:51:38 +00:00
params . mipMapLevel = 0 ;
params . msaaLevel = 0 ;
params . width = m_pDummy - > realWidth ;
params . height = m_pDummy - > realHeight ;
2017-01-28 09:52:09 +00:00
params . format = colorFormat : : RGBA ;
2017-02-14 04:47:10 +00:00
params . internalFormat = gfxContext . convertInternalTextureFormat ( u32 ( internalcolorFormat : : RGBA8 ) ) ;
2017-01-21 12:48:02 +00:00
params . dataType = datatype : : UNSIGNED_BYTE ;
2016-12-29 10:51:38 +00:00
params . data = dummyTexture ;
gfxContext . init2DTexture ( params ) ;
2013-04-05 06:13:26 +00:00
2014-09-18 16:16:52 +00:00
activateDummy ( 0 ) ;
2016-12-27 04:15:29 +00:00
activateDummy ( 1 ) ;
2016-06-10 06:06:06 +00:00
current [ 0 ] = current [ 1 ] = nullptr ;
2015-05-06 12:36:07 +00:00
2016-12-27 04:15:29 +00:00
m_pMSDummy = nullptr ;
2018-04-06 17:17:04 +00:00
if ( config . video . multisampling ! = 0 & & Context : : Multisampling ) {
2017-01-01 14:59:54 +00:00
m_pMSDummy = addFrameBufferTexture ( true ) ; // we don't want to remove dummy texture
2016-12-27 04:15:29 +00:00
_initDummyTexture ( m_pMSDummy ) ;
2018-04-19 13:02:52 +00:00
Context : : InitTextureParams msParams ;
msParams . handle = m_pMSDummy - > name ;
msParams . mipMapLevel = 0 ;
msParams . msaaLevel = config . video . multisampling ;
msParams . width = m_pMSDummy - > realWidth ;
msParams . height = m_pMSDummy - > realHeight ;
msParams . format = colorFormat : : RGBA ;
msParams . internalFormat = gfxContext . convertInternalTextureFormat ( u32 ( internalcolorFormat : : RGBA8 ) ) ;
msParams . dataType = datatype : : UNSIGNED_BYTE ;
gfxContext . init2DTexture ( msParams ) ;
2016-12-27 04:15:29 +00:00
activateMSDummy ( 0 ) ;
activateMSDummy ( 1 ) ;
}
2017-01-22 13:43:05 +00:00
assert ( ! gfxContext . isError ( ) ) ;
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
{
2016-06-10 06:06:06 +00:00
current [ 0 ] = current [ 1 ] = nullptr ;
2014-09-22 11:40:35 +00:00
for ( Textures : : const_iterator cur = m_textures . cbegin ( ) ; cur ! = m_textures . cend ( ) ; + + cur )
2018-05-07 15:43:57 +00:00
gfxContext . deleteTexture ( cur - > name ) ;
2014-09-18 16:16:52 +00:00
m_textures . clear ( ) ;
2015-10-04 21:41:25 +00:00
m_lruTextureLocations . clear ( ) ;
2014-09-22 11:40:35 +00:00
2015-10-04 21:41:25 +00:00
for ( FBTextures : : const_iterator cur = m_fbTextures . cbegin ( ) ; cur ! = m_fbTextures . cend ( ) ; + + cur )
2018-05-07 15:43:57 +00:00
gfxContext . deleteTexture ( cur - > second . name ) ;
2014-09-18 16:16:52 +00:00
m_fbTextures . clear ( ) ;
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
{
2017-11-04 11:43:29 +00:00
if ( m_textures . size ( ) > = m_maxCacheSize ) {
2016-09-15 22:44:55 +00:00
CachedTexture & clsTex = m_textures . back ( ) ;
2018-05-07 15:43:57 +00:00
gfxContext . deleteTexture ( clsTex . name ) ;
2016-09-15 22:44:55 +00:00
m_lruTextureLocations . erase ( clsTex . crc ) ;
m_textures . pop_back ( ) ;
2016-07-02 17:20:41 +00:00
}
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
{
2015-05-08 12:33:03 +00:00
if ( m_curUnpackAlignment = = 0 )
2017-01-22 11:10:52 +00:00
m_curUnpackAlignment = gfxContext . getTextureUnpackAlignment ( ) ;
2014-09-18 16:16:52 +00:00
_checkCacheSize ( ) ;
2017-01-28 09:52:09 +00:00
m_textures . emplace_front ( gfxContext . createTexture ( textureTarget : : TEXTURE_2D ) ) ;
2015-10-04 21:41:25 +00:00
Textures : : iterator new_iter = m_textures . begin ( ) ;
new_iter - > crc = _crc32 ;
m_lruTextureLocations . insert ( std : : pair < u32 , Textures : : iterator > ( _crc32 , new_iter ) ) ;
return & ( * new_iter ) ;
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
{
2017-01-02 14:00:49 +00:00
if ( _pTexture = = nullptr )
return ;
2018-02-22 23:05:59 +00:00
FBTextures : : const_iterator iter = m_fbTextures . find ( u32 ( _pTexture - > name ) ) ;
2015-10-04 21:41:25 +00:00
assert ( iter ! = m_fbTextures . cend ( ) ) ;
2018-05-07 15:43:57 +00:00
gfxContext . deleteTexture ( ObjectHandle ( iter - > second . name ) ) ;
2014-09-18 16:16:52 +00:00
m_fbTextures . erase ( iter ) ;
2013-04-05 06:13:26 +00:00
}
2017-01-01 14:59:54 +00:00
CachedTexture * TextureCache : : addFrameBufferTexture ( bool _multisample )
2013-04-05 06:13:26 +00:00
{
2017-01-21 12:48:02 +00:00
ObjectHandle texName ( gfxContext . createTexture ( _multisample ?
2017-01-28 09:52:09 +00:00
textureTarget : : TEXTURE_2D_MULTISAMPLE : textureTarget : : TEXTURE_2D ) ) ;
2018-02-22 23:05:59 +00:00
m_fbTextures . emplace ( u32 ( texName ) , texName ) ;
return & m_fbTextures . at ( u32 ( texName ) ) ;
2013-04-05 06:13:26 +00:00
}
2014-11-13 09:51:09 +00:00
struct TileSizes
{
u32 maskWidth , clampWidth , width , realWidth ;
u32 maskHeight , clampHeight , height , realHeight ;
2016-07-02 18:09:26 +00:00
u32 bytes ;
2014-11-13 09:51:09 +00:00
} ;
static
void _calcTileSizes ( u32 _t , TileSizes & _sizes , gDPTile * _pLoadTile )
{
gDPTile * pTile = _t < 2 ? gSP . textureTile [ _t ] : & gDP . tiles [ _t ] ;
2017-01-28 03:11:45 +00:00
const TextureLoadParameters & loadParams =
ImageFormat : : get ( ) . tlp [ gDP . otherMode . textureLUT ] [ pTile - > size ] [ pTile - > format ] ;
2014-12-11 07:48:55 +00:00
const u32 maxTexels = loadParams . maxTexels ;
2014-12-20 16:49:03 +00:00
const u32 tileWidth = ( ( pTile - > lrs - pTile - > uls ) & 0x03FF ) + 1 ;
const u32 tileHeight = ( ( pTile - > lrt - pTile - > ult ) & 0x03FF ) + 1 ;
2014-11-13 09:51:09 +00:00
2016-06-10 06:06:06 +00:00
const bool bUseLoadSizes = _pLoadTile ! = nullptr & & _pLoadTile - > loadType = = LOADTYPE_TILE & &
2014-11-13 09:51:09 +00:00
( pTile - > tmem = = _pLoadTile - > tmem ) ;
u32 loadWidth = 0 , loadHeight = 0 ;
if ( bUseLoadSizes ) {
2014-12-20 16:49:03 +00:00
loadWidth = ( ( _pLoadTile - > lrs - _pLoadTile - > uls ) & 0x03FF ) + 1 ;
loadHeight = ( ( _pLoadTile - > lrt - _pLoadTile - > ult ) & 0x03FF ) + 1 ;
2014-11-13 09:51:09 +00:00
}
2014-12-11 07:48:55 +00:00
const u32 lineWidth = pTile - > line < < loadParams . lineShift ;
2014-11-13 09:51:09 +00:00
const u32 lineHeight = lineWidth ! = 0 ? min ( maxTexels / lineWidth , tileHeight ) : 0 ;
u32 maskWidth = 1 < < pTile - > masks ;
u32 maskHeight = 1 < < pTile - > maskt ;
u32 width , height ;
2016-10-15 05:52:34 +00:00
const u32 tMemMask = gDP . otherMode . textureLUT = = G_TT_NONE ? 0x1FF : 0xFF ;
gDPLoadTileInfo & info = gDP . loadInfo [ pTile - > tmem & tMemMask ] ;
2016-07-02 18:09:26 +00:00
_sizes . bytes = info . bytes ;
2014-11-12 11:19:53 +00:00
if ( info . loadType = = LOADTYPE_TILE ) {
2015-03-14 14:07:48 +00:00
if ( pTile - > masks & & ( ( maskWidth * maskHeight ) < = maxTexels ) )
width = maskWidth ; // Use mask width if set and valid
else {
2016-03-05 14:09:11 +00:00
width = info . width ;
2015-03-14 14:07:48 +00:00
if ( info . size > pTile - > size )
width < < = info . size - pTile - > size ;
}
if ( pTile - > maskt & & ( ( maskWidth * maskHeight ) < = maxTexels ) )
height = maskHeight ;
else
height = info . height ;
2014-11-12 11:19:53 +00:00
} else {
if ( pTile - > masks & & ( ( maskWidth * maskHeight ) < = maxTexels ) )
width = maskWidth ; // Use mask width if set and valid
else if ( ( tileWidth * tileHeight ) < = maxTexels )
width = tileWidth ; // else use tile width if valid
else
width = lineWidth ; // else use line-based width
2014-11-13 09:51:09 +00:00
2014-11-12 11:19:53 +00:00
if ( pTile - > maskt & & ( ( maskWidth * maskHeight ) < = maxTexels ) )
height = maskHeight ;
else if ( ( tileWidth * tileHeight ) < = maxTexels )
height = tileHeight ;
else
height = lineHeight ;
}
2015-02-28 09:30:10 +00:00
2014-11-13 09:51:09 +00:00
_sizes . clampWidth = ( pTile - > clamps & & gDP . otherMode . cycleType ! = G_CYC_COPY ) ? tileWidth : width ;
_sizes . clampHeight = ( pTile - > clampt & & gDP . otherMode . cycleType ! = G_CYC_COPY ) ? tileHeight : height ;
// Make sure masking is valid
if ( maskWidth > width ) {
pTile - > masks = powof ( width ) ;
maskWidth = 1 < < pTile - > masks ;
}
if ( maskHeight > height ) {
pTile - > maskt = powof ( height ) ;
maskHeight = 1 < < pTile - > maskt ;
}
_sizes . maskWidth = maskWidth ;
_sizes . maskHeight = maskHeight ;
_sizes . width = width ;
_sizes . height = height ;
2014-11-13 05:00:38 +00:00
if ( pTile - > clamps ! = 0 )
_sizes . realWidth = _sizes . clampWidth ;
2015-02-24 07:33:46 +00:00
else if ( pTile - > masks ! = 0 )
2014-11-13 05:00:38 +00:00
_sizes . realWidth = _sizes . maskWidth ;
2014-11-13 09:51:09 +00:00
else
2014-11-13 05:00:38 +00:00
_sizes . realWidth = _sizes . width ;
2014-11-13 09:51:09 +00:00
2014-11-13 05:00:38 +00:00
if ( pTile - > clampt ! = 0 )
_sizes . realHeight = _sizes . clampHeight ;
2015-02-24 07:33:46 +00:00
else if ( pTile - > maskt ! = 0 )
2014-11-13 05:00:38 +00:00
_sizes . realHeight = _sizes . maskHeight ;
2014-11-13 09:51:09 +00:00
else
2014-11-13 05:00:38 +00:00
_sizes . realHeight = _sizes . height ;
2016-03-05 11:51:17 +00:00
if ( gSP . texture . level > 0 ) {
2014-11-13 05:00:38 +00:00
_sizes . realWidth = pow2 ( _sizes . realWidth ) ;
_sizes . realHeight = pow2 ( _sizes . realHeight ) ;
}
2014-11-13 09:51:09 +00:00
}
2014-11-29 13:29:04 +00:00
inline
2017-11-02 16:39:21 +00:00
void _updateCachedTexture ( const GHQTexInfo & _info , CachedTexture * _pTexture , f32 _scale )
2014-11-29 13:29:04 +00:00
{
_pTexture - > textureBytes = _info . width * _info . height ;
2017-01-22 11:44:42 +00:00
Parameter format ( _info . format ) ;
2017-01-28 09:52:09 +00:00
if ( format = = internalcolorFormat : : RGB8 | |
format = = internalcolorFormat : : RGBA4 | |
format = = internalcolorFormat : : RGB5_A1 ) {
2014-11-29 13:29:04 +00:00
_pTexture - > textureBytes < < = 1 ;
2017-01-22 11:44:42 +00:00
}
else {
2014-11-29 13:29:04 +00:00
_pTexture - > textureBytes < < = 2 ;
}
2017-01-22 11:44:42 +00:00
2017-11-16 11:00:52 +00:00
if ( _pTexture - > realWidth = = _pTexture - > width * 2 )
_pTexture - > clampS = 0 ; // force wrap or mirror s
if ( _pTexture - > realHeight = = _pTexture - > height * 2 )
_pTexture - > clampT = 0 ; // force wrap or mirror t
2014-11-29 13:29:04 +00:00
_pTexture - > realWidth = _info . width ;
_pTexture - > realHeight = _info . height ;
2017-11-02 16:39:21 +00:00
_pTexture - > scaleS = _scale / f32 ( _info . width ) ;
_pTexture - > scaleT = _scale / f32 ( _info . height ) ;
2017-11-16 11:00:52 +00:00
2015-11-19 13:12:31 +00:00
_pTexture - > bHDTexture = true ;
2014-11-29 13:29:04 +00:00
}
2014-12-09 17:37:26 +00:00
bool TextureCache : : _loadHiresBackground ( CachedTexture * _pTexture )
2014-11-29 13:29:04 +00:00
{
if ( ! TFH . isInited ( ) )
return false ;
2014-12-09 17:37:26 +00:00
u8 * addr = ( u8 * ) ( RDRAM + gSP . bgImage . address ) ;
int tile_width = gSP . bgImage . width ;
int tile_height = gSP . bgImage . height ;
int bpl = tile_width < < gSP . bgImage . size > > 1 ;
2014-11-29 13:29:04 +00:00
2016-06-10 06:06:06 +00:00
u8 * paladdr = nullptr ;
u16 * palette = nullptr ;
2014-12-09 17:37:26 +00:00
if ( ( gSP . bgImage . size < G_IM_SIZ_16b ) & & ( gDP . otherMode . textureLUT ! = G_TT_NONE | | gSP . bgImage . format = = G_IM_FMT_CI ) ) {
if ( gSP . bgImage . size = = G_IM_SIZ_8b )
2014-11-29 13:29:04 +00:00
paladdr = ( u8 * ) ( gDP . TexFilterPalette ) ;
else if ( config . textureFilter . txHresAltCRC )
2014-12-09 17:37:26 +00:00
paladdr = ( u8 * ) ( gDP . TexFilterPalette + ( gSP . bgImage . palette < < 5 ) ) ;
2014-11-29 13:29:04 +00:00
else
2014-12-09 17:37:26 +00:00
paladdr = ( u8 * ) ( gDP . TexFilterPalette + ( gSP . bgImage . palette < < 4 ) ) ;
2014-11-29 13:29:04 +00:00
// TODO: fix palette load
// palette = (rdp.pal_8 + (gSP.textureTile[_t]->palette << 4));
}
2015-08-30 22:44:01 +00:00
u64 ricecrc = txfilter_checksum ( addr , tile_width ,
tile_height , ( unsigned short ) ( gSP . bgImage . format < < 8 | gSP . bgImage . size ) ,
bpl , paladdr ) ;
2014-12-09 17:37:26 +00:00
GHQTexInfo ghqTexInfo ;
2017-05-30 03:18:16 +00:00
// TODO: fix problem with zero texture dimensions on GLideNHQ side.
if ( txfilter_hirestex ( _pTexture - > crc , ricecrc , palette , & ghqTexInfo ) & &
ghqTexInfo . width ! = 0 & & ghqTexInfo . height ! = 0 ) {
2017-02-10 09:58:17 +00:00
ghqTexInfo . format = gfxContext . convertInternalTextureFormat ( ghqTexInfo . format ) ;
2017-01-21 12:48:02 +00:00
Context : : InitTextureParams params ;
params . handle = _pTexture - > name ;
2017-01-01 14:59:54 +00:00
params . mipMapLevel = 0 ;
params . msaaLevel = 0 ;
params . width = ghqTexInfo . width ;
params . height = ghqTexInfo . height ;
2017-01-28 09:52:09 +00:00
params . format = ColorFormatParam ( ghqTexInfo . texture_format ) ;
params . internalFormat = InternalColorFormatParam ( ghqTexInfo . format ) ;
params . dataType = DatatypeParam ( ghqTexInfo . pixel_type ) ;
2017-01-01 14:59:54 +00:00
params . data = ghqTexInfo . data ;
gfxContext . init2DTexture ( params ) ;
2017-01-22 13:43:05 +00:00
assert ( ! gfxContext . isError ( ) ) ;
2017-11-02 16:39:21 +00:00
_updateCachedTexture ( ghqTexInfo , _pTexture , f32 ( ghqTexInfo . width ) / f32 ( tile_width ) ) ;
2014-11-29 13:29:04 +00:00
return true ;
}
return false ;
}
2014-11-13 09:51:09 +00:00
void TextureCache : : _loadBackground ( CachedTexture * pTexture )
2013-04-05 06:13:26 +00:00
{
2014-12-09 17:37:26 +00:00
if ( _loadHiresBackground ( pTexture ) )
2014-11-29 13:29:04 +00:00
return ;
2018-04-19 13:02:52 +00:00
u32 * pDest = nullptr ;
u16 * pDest16 = nullptr ;
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 ;
2017-01-28 09:52:09 +00:00
InternalColorFormatParam glInternalFormat ;
DatatypeParam glType ;
2013-04-05 06:13:26 +00:00
2017-01-28 03:11:45 +00:00
const TextureLoadParameters & loadParams =
ImageFormat : : get ( ) . tlp [ pTexture - > format = = 2 ? G_TT_RGBA16 : G_TT_NONE ] [ pTexture - > size ] [ pTexture - > format ] ;
2017-02-05 12:58:33 +00:00
if ( loadParams . autoFormat = = internalcolorFormat : : RGBA8 ) {
2014-09-18 16:16:52 +00:00
pTexture - > textureBytes = ( pTexture - > realWidth * pTexture - > realHeight ) < < 2 ;
2014-12-11 07:48:55 +00:00
GetTexel = loadParams . Get32 ;
glInternalFormat = loadParams . glInternalFormat32 ;
glType = loadParams . glType32 ;
2014-09-18 16:16:52 +00:00
} else {
pTexture - > textureBytes = ( pTexture - > realWidth * pTexture - > realHeight ) < < 1 ;
2014-12-11 07:48:55 +00:00
GetTexel = loadParams . Get16 ;
glInternalFormat = loadParams . glInternalFormat16 ;
glType = loadParams . glType16 ;
2013-04-05 06:13:26 +00:00
}
bpl = gSP . bgImage . width < < gSP . bgImage . size > > 1 ;
numBytes = bpl * gSP . bgImage . height ;
2014-11-29 13:29:04 +00:00
pSwapped = ( u8 * ) malloc ( numBytes ) ;
2017-11-18 15:07:27 +00:00
if ( pSwapped = = nullptr )
return ;
2015-06-17 07:22:21 +00:00
UnswapCopyWrap ( RDRAM , gSP . bgImage . address , pSwapped , 0 , RDRAMSize , numBytes ) ;
2014-11-29 13:29:04 +00:00
pDest = ( u32 * ) malloc ( pTexture - > textureBytes ) ;
2017-11-18 15:07:27 +00:00
if ( pDest = = nullptr ) {
free ( pSwapped ) ;
return ;
}
2018-04-19 13:02:52 +00:00
pDest16 = reinterpret_cast < u16 * > ( pDest ) ;
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
2017-02-05 12:58:33 +00:00
if ( glInternalFormat = = internalcolorFormat : : RGBA8 )
2018-04-19 13:02:52 +00:00
pDest [ j + + ] = GetTexel ( ( u64 * ) pSrc , tx , 0 , pTexture - > palette ) ;
2013-04-05 06:13:26 +00:00
else
2018-04-19 13:02:52 +00:00
pDest16 [ j + + ] = static_cast < u16 > ( GetTexel ( ( u64 * ) pSrc , tx , 0 , pTexture - > palette ) ) ;
2013-04-05 06:13:26 +00:00
}
}
2017-03-31 06:14:15 +00:00
if ( ( config . generalEmulation . hacks & hack_LoadDepthTextures ) ! = 0 & & gDP . colorImage . address = = gDP . depthImageAddress ) {
_loadDepthTexture ( pTexture , ( u16 * ) pDest ) ;
free ( pDest ) ;
free ( pSwapped ) ;
return ;
}
2014-11-29 13:29:04 +00:00
bool bLoaded = false ;
2015-08-30 22:44:01 +00:00
if ( ( config . textureFilter . txEnhancementMode | config . textureFilter . txFilterMode ) ! = 0 & &
config . textureFilter . txFilterIgnoreBG = = 0 & &
TFH . isInited ( ) ) {
2014-11-19 14:23:10 +00:00
GHQTexInfo ghqTexInfo ;
2015-08-30 22:44:01 +00:00
if ( txfilter_filter ( ( u8 * ) pDest , pTexture - > realWidth , pTexture - > realHeight ,
2017-01-22 11:44:42 +00:00
( u16 ) u32 ( glInternalFormat ) , ( uint64 ) pTexture - > crc , & ghqTexInfo ) ! = 0 & &
2016-06-10 06:06:06 +00:00
ghqTexInfo . data ! = nullptr ) {
2017-02-05 13:26:40 +00:00
2015-08-30 22:44:01 +00:00
if ( ghqTexInfo . width % 2 ! = 0 & &
2017-02-05 12:58:33 +00:00
ghqTexInfo . format ! = u32 ( internalcolorFormat : : RGBA8 ) & &
2017-01-22 11:10:52 +00:00
m_curUnpackAlignment > 1 )
gfxContext . setTextureUnpackAlignment ( 2 ) ;
2017-02-05 13:26:40 +00:00
2017-02-10 09:58:17 +00:00
ghqTexInfo . format = gfxContext . convertInternalTextureFormat ( ghqTexInfo . format ) ;
2017-01-21 12:48:02 +00:00
Context : : InitTextureParams params ;
params . handle = pTexture - > name ;
2017-01-01 14:59:54 +00:00
params . mipMapLevel = 0 ;
params . msaaLevel = 0 ;
params . width = ghqTexInfo . width ;
params . height = ghqTexInfo . height ;
2017-01-28 09:52:09 +00:00
params . format = ColorFormatParam ( ghqTexInfo . texture_format ) ;
params . internalFormat = InternalColorFormatParam ( ghqTexInfo . format ) ;
params . dataType = DatatypeParam ( ghqTexInfo . pixel_type ) ;
2017-01-01 14:59:54 +00:00
params . data = ghqTexInfo . data ;
gfxContext . init2DTexture ( params ) ;
2017-11-02 16:39:21 +00:00
_updateCachedTexture ( ghqTexInfo , pTexture , f32 ( ghqTexInfo . width ) / f32 ( pTexture - > realWidth ) ) ;
2014-11-29 13:29:04 +00:00
bLoaded = true ;
2014-11-19 14:23:10 +00:00
}
}
2014-11-29 13:29:04 +00:00
if ( ! bLoaded ) {
2017-02-05 12:58:33 +00:00
if ( pTexture - > realWidth % 2 ! = 0 & & glInternalFormat ! = internalcolorFormat : : RGBA8 )
2017-01-22 13:43:05 +00:00
gfxContext . setTextureUnpackAlignment ( 2 ) ;
2017-01-21 12:48:02 +00:00
Context : : InitTextureParams params ;
params . handle = pTexture - > name ;
2017-01-01 14:59:54 +00:00
params . mipMapLevel = 0 ;
params . msaaLevel = 0 ;
params . width = pTexture - > realWidth ;
params . height = pTexture - > realHeight ;
2017-01-28 09:52:09 +00:00
params . format = colorFormat : : RGBA ;
2017-02-10 09:58:17 +00:00
params . internalFormat = gfxContext . convertInternalTextureFormat ( u32 ( glInternalFormat ) ) ;
2017-01-28 09:52:09 +00:00
params . dataType = glType ;
2017-01-01 14:59:54 +00:00
params . data = pDest ;
gfxContext . init2DTexture ( params ) ;
2014-11-29 13:29:04 +00:00
}
2015-05-08 12:33:03 +00:00
if ( m_curUnpackAlignment > 1 )
2017-01-22 11:10:52 +00:00
gfxContext . setTextureUnpackAlignment ( m_curUnpackAlignment ) ;
2015-10-30 02:37:14 +00:00
free ( pSwapped ) ;
2014-11-29 13:29:04 +00:00
free ( pDest ) ;
}
2015-04-12 12:49:40 +00:00
bool TextureCache : : _loadHiresTexture ( u32 _tile , CachedTexture * _pTexture , u64 & _ricecrc )
2014-12-09 17:37:26 +00:00
{
2014-12-25 10:18:35 +00:00
if ( config . textureFilter . txHiresEnable = = 0 | | ! TFH . isInited ( ) )
2014-12-09 17:37:26 +00:00
return false ;
gDPLoadTileInfo & info = gDP . loadInfo [ _pTexture - > tMem ] ;
int bpl ;
2017-11-02 15:59:18 +00:00
int width , height ;
2014-12-09 17:37:26 +00:00
u8 * addr = ( u8 * ) ( RDRAM + info . texAddress ) ;
if ( info . loadType = = LOADTYPE_TILE ) {
bpl = info . texWidth < < info . size > > 1 ;
addr + = ( info . ult * bpl ) + ( ( ( info . uls < < info . size ) + 1 ) > > 1 ) ;
2017-03-23 15:51:34 +00:00
2017-11-02 15:59:18 +00:00
width = min ( info . width , info . texWidth ) ;
2017-03-23 15:51:34 +00:00
if ( info . size > _pTexture - > size )
2017-11-02 15:59:18 +00:00
width < < = info . size - _pTexture - > size ;
2017-03-23 15:51:34 +00:00
2017-11-02 15:59:18 +00:00
height = info . height ;
if ( ( config . generalEmulation . hacks & hack_MK64 ) ! = 0 & & ( height % 2 ) ! = 0 )
height - - ;
2017-03-23 15:51:34 +00:00
} else {
2017-11-02 15:59:18 +00:00
int tile_width = gDP . tiles [ _tile ] . lrs - gDP . tiles [ _tile ] . uls + 1 ;
int tile_height = gDP . tiles [ _tile ] . lrt - gDP . tiles [ _tile ] . ult + 1 ;
int mask_width = ( gDP . tiles [ _tile ] . masks = = 0 ) ? ( tile_width ) : ( 1 < < gDP . tiles [ _tile ] . masks ) ;
int mask_height = ( gDP . tiles [ _tile ] . maskt = = 0 ) ? ( tile_height ) : ( 1 < < gDP . tiles [ _tile ] . maskt ) ;
if ( ( gDP . tiles [ _tile ] . clamps & & tile_width < = 256 ) )
width = min ( mask_width , tile_width ) ;
else
width = mask_width ;
if ( ( gDP . tiles [ _tile ] . clampt & & tile_height < = 256 ) | | ( mask_height > 256 ) )
height = min ( mask_height , tile_height ) ;
else
height = mask_height ;
2014-12-09 17:37:26 +00:00
if ( gSP . textureTile [ _tile ] - > size = = G_IM_SIZ_32b )
bpl = gSP . textureTile [ _tile ] - > line < < 4 ;
else if ( info . dxt = = 0 )
bpl = gSP . textureTile [ _tile ] - > line < < 3 ;
else {
u32 dxt = info . dxt ;
if ( dxt > 1 )
dxt = ReverseDXT ( dxt , info . width , _pTexture - > width , _pTexture - > size ) ;
bpl = dxt < < 3 ;
}
}
2016-06-10 06:06:06 +00:00
u8 * paladdr = nullptr ;
u16 * palette = nullptr ;
2014-12-09 17:37:26 +00:00
if ( ( _pTexture - > size < G_IM_SIZ_16b ) & & ( gDP . otherMode . textureLUT ! = G_TT_NONE | | _pTexture - > format = = G_IM_FMT_CI ) ) {
if ( _pTexture - > size = = G_IM_SIZ_8b )
paladdr = ( u8 * ) ( gDP . TexFilterPalette ) ;
else if ( config . textureFilter . txHresAltCRC )
paladdr = ( u8 * ) ( gDP . TexFilterPalette + ( _pTexture - > palette < < 5 ) ) ;
else
paladdr = ( u8 * ) ( gDP . TexFilterPalette + ( _pTexture - > palette < < 4 ) ) ;
// TODO: fix palette load
// palette = (rdp.pal_8 + (gSP.textureTile[_t]->palette << 4));
}
2017-11-02 15:59:18 +00:00
_ricecrc = txfilter_checksum ( addr , width , height , ( unsigned short ) ( _pTexture - > format < < 8 | _pTexture - > size ) , bpl , paladdr ) ;
2014-12-09 17:37:26 +00:00
GHQTexInfo ghqTexInfo ;
2017-05-30 03:18:16 +00:00
// TODO: fix problem with zero texture dimensions on GLideNHQ side.
if ( txfilter_hirestex ( _pTexture - > crc , _ricecrc , palette , & ghqTexInfo ) & &
ghqTexInfo . width ! = 0 & & ghqTexInfo . height ! = 0 ) {
2017-02-10 09:58:17 +00:00
ghqTexInfo . format = gfxContext . convertInternalTextureFormat ( ghqTexInfo . format ) ;
2017-01-21 12:48:02 +00:00
Context : : InitTextureParams params ;
params . handle = _pTexture - > name ;
2017-01-01 14:59:54 +00:00
params . mipMapLevel = 0 ;
params . msaaLevel = 0 ;
params . width = ghqTexInfo . width ;
params . height = ghqTexInfo . height ;
2017-01-28 09:52:09 +00:00
params . internalFormat = InternalColorFormatParam ( ghqTexInfo . format ) ;
params . format = ColorFormatParam ( ghqTexInfo . texture_format ) ;
params . dataType = DatatypeParam ( ghqTexInfo . pixel_type ) ;
2017-01-01 14:59:54 +00:00
params . data = ghqTexInfo . data ;
2017-11-05 15:27:13 +00:00
params . textureUnitIndex = textureIndices : : Tex [ _tile ] ;
2017-01-01 14:59:54 +00:00
gfxContext . init2DTexture ( params ) ;
2017-01-22 13:43:05 +00:00
assert ( ! gfxContext . isError ( ) ) ;
2017-11-02 16:39:21 +00:00
_updateCachedTexture ( ghqTexInfo , _pTexture , f32 ( ghqTexInfo . width ) / f32 ( width ) ) ;
2014-12-09 17:37:26 +00:00
return true ;
}
2015-04-12 12:49:40 +00:00
2014-12-09 17:37:26 +00:00
return false ;
}
2016-04-09 15:07:46 +00:00
void TextureCache : : _loadDepthTexture ( CachedTexture * _pTexture , u16 * _pDest )
{
2018-04-06 04:10:43 +00:00
if ( ! config . generalEmulation . enableFragmentDepthWrite )
2017-01-22 13:43:05 +00:00
return ;
2018-04-15 01:25:34 +00:00
u32 size = _pTexture - > realWidth * _pTexture - > realHeight ;
std : : vector < f32 > pDestFloat ( size ) ;
for ( u32 i = 0 ; i < size ; + + i )
2018-05-06 08:28:07 +00:00
pDestFloat [ i ] = _pDest [ i ] / 65535.0f ;
2018-04-15 01:25:34 +00:00
2017-01-21 12:48:02 +00:00
Context : : InitTextureParams params ;
params . handle = _pTexture - > name ;
2017-01-01 14:59:54 +00:00
params . mipMapLevel = 0 ;
params . msaaLevel = 0 ;
params . width = _pTexture - > realWidth ;
params . height = _pTexture - > realHeight ;
2018-04-15 01:25:34 +00:00
params . internalFormat = internalcolorFormat : : R16F ;
2017-01-28 09:52:09 +00:00
params . format = colorFormat : : RED ;
2018-04-15 01:25:34 +00:00
params . dataType = datatype : : FLOAT ;
params . data = pDestFloat . data ( ) ;
2017-01-01 14:59:54 +00:00
gfxContext . init2DTexture ( params ) ;
2016-04-09 15:07:46 +00:00
}
2015-08-30 22:13:00 +00:00
/*
* Worker function for _load
*/
2015-08-30 22:44:01 +00:00
void TextureCache : : _getTextureDestData ( CachedTexture & tmptex ,
u32 * pDest ,
2017-01-22 11:44:42 +00:00
Parameter glInternalFormat ,
2015-08-30 22:44:01 +00:00
GetTexelFunc GetTexel ,
u16 * pLine )
2015-08-30 22:13:00 +00:00
{
u16 mirrorSBit , maskSMask , clampSClamp ;
u16 mirrorTBit , maskTMask , clampTClamp ;
2018-03-11 07:34:42 +00:00
u16 x , y , tx , ty ;
u32 i , j ;
2015-08-30 22:13:00 +00:00
u64 * pSrc ;
if ( tmptex . maskS > 0 ) {
clampSClamp = tmptex . clampS ? tmptex . clampWidth - 1 : ( tmptex . mirrorS ? ( tmptex . width < < 1 ) - 1 : tmptex . width - 1 ) ;
maskSMask = ( 1 < < tmptex . maskS ) - 1 ;
2016-05-03 12:00:08 +00:00
mirrorSBit = tmptex . mirrorS ! = 0 ? 1 < < tmptex . maskS : 0 ;
2015-08-30 22:13:00 +00:00
} else {
2016-03-22 06:00:24 +00:00
clampSClamp = tmptex . clampS ? tmptex . clampWidth - 1 : tmptex . width - 1 ;
2015-08-30 22:13:00 +00:00
maskSMask = 0xFFFF ;
mirrorSBit = 0x0000 ;
}
if ( tmptex . maskT > 0 ) {
clampTClamp = tmptex . clampT ? tmptex . clampHeight - 1 : ( tmptex . mirrorT ? ( tmptex . height < < 1 ) - 1 : tmptex . height - 1 ) ;
maskTMask = ( 1 < < tmptex . maskT ) - 1 ;
2016-05-03 12:00:08 +00:00
mirrorTBit = tmptex . mirrorT ! = 0 ? 1 < < tmptex . maskT : 0 ;
2015-08-30 22:13:00 +00:00
} else {
2016-03-22 06:00:24 +00:00
clampTClamp = tmptex . clampT ? tmptex . clampHeight - 1 : tmptex . height - 1 ;
2015-08-30 22:13:00 +00:00
maskTMask = 0xFFFF ;
mirrorTBit = 0x0000 ;
}
if ( tmptex . size = = G_IM_SIZ_32b ) {
const u16 * tmem16 = ( u16 * ) TMEM ;
const u32 tbase = tmptex . tMem < < 2 ;
int wid_64 = ( tmptex . clampWidth ) < < 2 ;
if ( wid_64 & 15 ) {
wid_64 + = 16 ;
}
wid_64 & = 0xFFFFFFF0 ;
wid_64 > > = 3 ;
int line32 = tmptex . line < < 1 ;
line32 = ( line32 - wid_64 ) < < 3 ;
if ( wid_64 < 1 ) {
wid_64 = 1 ;
}
int width = wid_64 < < 1 ;
line32 = width + ( line32 > > 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 + line32 * 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 ;
}
}
} else if ( tmptex . format = = G_IM_FMT_YUV ) {
j = 0 ;
* pLine < < = 1 ;
for ( y = 0 ; y < tmptex . realHeight ; + + y ) {
pSrc = & TMEM [ tmptex . tMem ] + * pLine * y ;
for ( x = 0 ; x < tmptex . realWidth / 2 ; x + + ) {
2017-10-22 13:50:57 +00:00
GetYUV_RGBA8888 ( pSrc , pDest + j , x ) ;
2015-08-30 22:13:00 +00:00
j + = 2 ;
}
}
} else {
j = 0 ;
2016-02-08 17:15:00 +00:00
const u32 tMemMask = gDP . otherMode . textureLUT = = G_TT_NONE ? 0x1FF : 0xFF ;
2015-08-30 22:13:00 +00:00
for ( y = 0 ; y < tmptex . realHeight ; + + y ) {
ty = min ( y , clampTClamp ) & maskTMask ;
if ( y & mirrorTBit )
ty ^ = maskTMask ;
2016-02-08 17:15:00 +00:00
pSrc = & TMEM [ ( tmptex . tMem + * pLine * ty ) & tMemMask ] ;
2015-08-30 22:13:00 +00:00
i = ( ty & 1 ) < < 1 ;
for ( x = 0 ; x < tmptex . realWidth ; + + x ) {
tx = min ( x , clampSClamp ) & maskSMask ;
if ( x & mirrorSBit ) {
tx ^ = maskSMask ;
}
2017-02-05 12:58:33 +00:00
if ( glInternalFormat = = internalcolorFormat : : RGBA8 ) {
2015-08-30 22:13:00 +00:00
pDest [ j + + ] = GetTexel ( pSrc , tx , i , tmptex . palette ) ;
} else {
( ( u16 * ) pDest ) [ j + + ] = GetTexel ( pSrc , tx , i , tmptex . palette ) ;
}
}
}
}
}
2014-11-29 13:29:04 +00:00
void TextureCache : : _load ( u32 _tile , CachedTexture * _pTexture )
{
2015-04-12 12:49:40 +00:00
u64 ricecrc = 0 ;
if ( _loadHiresTexture ( _tile , _pTexture , ricecrc ) )
2014-11-29 13:29:04 +00:00
return ;
2014-11-19 14:23:10 +00:00
2014-09-18 16:16:52 +00:00
u32 * pDest ;
2013-04-05 06:13:26 +00:00
2015-08-30 22:13:00 +00:00
u16 line ;
2014-09-18 16:16:52 +00:00
GetTexelFunc GetTexel ;
2017-01-28 09:52:09 +00:00
InternalColorFormatParam glInternalFormat ;
DatatypeParam glType ;
2014-10-09 09:01:04 +00:00
u32 sizeShift ;
2013-04-05 06:13:26 +00:00
2017-01-28 03:11:45 +00:00
const TextureLoadParameters & loadParams =
ImageFormat : : get ( ) . tlp [ gDP . otherMode . textureLUT ] [ _pTexture - > size ] [ _pTexture - > format ] ;
2017-02-05 12:58:33 +00:00
if ( loadParams . autoFormat = = internalcolorFormat : : RGBA8 ) {
2014-10-09 09:01:04 +00:00
sizeShift = 2 ;
_pTexture - > textureBytes = ( _pTexture - > realWidth * _pTexture - > realHeight ) < < sizeShift ;
2014-12-11 07:48:55 +00:00
GetTexel = loadParams . Get32 ;
glInternalFormat = loadParams . glInternalFormat32 ;
glType = loadParams . glType32 ;
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 ;
2014-12-11 07:48:55 +00:00
GetTexel = loadParams . Get16 ;
glInternalFormat = loadParams . glInternalFormat16 ;
glType = loadParams . glType16 ;
2013-04-05 06:13:26 +00:00
}
2014-11-29 13:29:04 +00:00
pDest = ( u32 * ) malloc ( _pTexture - > textureBytes ) ;
2016-06-10 06:06:06 +00:00
assert ( pDest ! = nullptr ) ;
2013-04-05 06:13:26 +00:00
2017-01-22 11:10:52 +00:00
s32 mipLevel = 0 ;
2016-11-07 04:34:11 +00:00
_pTexture - > max_level = 0 ;
2013-04-05 06:13:26 +00:00
2017-10-02 09:58:55 +00:00
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 ;
}
}
2014-10-09 09:01:04 +00:00
2017-01-21 12:48:02 +00:00
ObjectHandle name ;
CachedTexture tmptex ( name ) ;
2014-10-09 09:01:04 +00:00
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 ) {
2015-08-30 22:13:00 +00:00
_getTextureDestData ( tmptex , pDest , glInternalFormat , GetTexel , & line ) ;
2014-11-20 09:28:31 +00:00
2016-04-09 15:07:46 +00:00
if ( ( config . generalEmulation . hacks & hack_LoadDepthTextures ) ! = 0 & & gDP . colorImage . address = = gDP . depthImageAddress ) {
_loadDepthTexture ( _pTexture , ( u16 * ) pDest ) ;
free ( pDest ) ;
return ;
}
2015-08-30 22:44:01 +00:00
if ( m_toggleDumpTex & &
config . textureFilter . txHiresEnable ! = 0 & &
config . textureFilter . txDump ! = 0 ) {
txfilter_dmptx ( ( u8 * ) pDest , tmptex . realWidth , tmptex . realHeight ,
2017-01-22 11:44:42 +00:00
tmptex . realWidth , ( u16 ) u32 ( glInternalFormat ) ,
2015-08-30 22:44:01 +00:00
( unsigned short ) ( _pTexture - > format < < 8 | _pTexture - > size ) ,
ricecrc ) ;
2015-04-12 12:49:40 +00:00
}
2016-04-08 06:03:22 +00:00
bool bLoaded = false ;
if ( ( config . textureFilter . txEnhancementMode | config . textureFilter . txFilterMode ) ! = 0 & &
2016-11-07 04:34:11 +00:00
_pTexture - > max_level = = 0 & &
2015-08-30 22:44:01 +00:00
( config . textureFilter . txFilterIgnoreBG = = 0 | | ( RSP . cmd ! = G_TEXRECT & & RSP . cmd ! = G_TEXRECTFLIP ) ) & &
TFH . isInited ( ) )
2014-11-29 13:41:13 +00:00
{
2014-11-20 09:28:31 +00:00
GHQTexInfo ghqTexInfo ;
2015-08-30 22:44:01 +00:00
if ( txfilter_filter ( ( u8 * ) pDest , tmptex . realWidth , tmptex . realHeight ,
2017-01-22 11:44:42 +00:00
( u16 ) u32 ( glInternalFormat ) , ( uint64 ) _pTexture - > crc ,
2016-06-10 06:06:06 +00:00
& ghqTexInfo ) ! = 0 & & ghqTexInfo . data ! = nullptr ) {
2017-02-10 09:58:17 +00:00
ghqTexInfo . format = gfxContext . convertInternalTextureFormat ( ghqTexInfo . format ) ;
2017-01-21 12:48:02 +00:00
Context : : InitTextureParams params ;
params . handle = _pTexture - > name ;
2017-01-26 14:36:54 +00:00
params . textureUnitIndex = textureIndices : : Tex [ _tile ] ;
2017-01-01 14:59:54 +00:00
params . mipMapLevel = 0 ;
params . msaaLevel = 0 ;
params . width = ghqTexInfo . width ;
params . height = ghqTexInfo . height ;
2017-01-28 09:52:09 +00:00
params . internalFormat = InternalColorFormatParam ( ghqTexInfo . format ) ;
params . format = ColorFormatParam ( ghqTexInfo . texture_format ) ;
params . dataType = DatatypeParam ( ghqTexInfo . pixel_type ) ;
2017-01-01 14:59:54 +00:00
params . data = ghqTexInfo . data ;
gfxContext . init2DTexture ( params ) ;
2017-11-02 16:39:21 +00:00
_updateCachedTexture ( ghqTexInfo , _pTexture , f32 ( ghqTexInfo . width ) / f32 ( tmptex . realWidth ) ) ;
2014-11-20 09:28:31 +00:00
bLoaded = true ;
}
}
if ( ! bLoaded ) {
2015-08-30 22:44:01 +00:00
if ( tmptex . realWidth % 2 ! = 0 & &
2017-02-05 12:58:33 +00:00
glInternalFormat ! = internalcolorFormat : : RGBA8 & &
2017-01-22 11:10:52 +00:00
m_curUnpackAlignment > 1 )
gfxContext . setTextureUnpackAlignment ( 2 ) ;
2017-01-21 12:48:02 +00:00
Context : : InitTextureParams params ;
params . handle = _pTexture - > name ;
2017-01-26 14:36:54 +00:00
params . textureUnitIndex = textureIndices : : Tex [ _tile ] ;
2017-01-01 14:59:54 +00:00
params . mipMapLevel = mipLevel ;
params . mipMapLevels = _pTexture - > max_level + 1 ;
params . msaaLevel = 0 ;
params . width = tmptex . realWidth ;
params . height = tmptex . realHeight ;
2017-02-10 09:58:17 +00:00
params . internalFormat = gfxContext . convertInternalTextureFormat ( u32 ( glInternalFormat ) ) ;
2017-01-28 09:52:09 +00:00
params . format = colorFormat : : RGBA ;
2017-01-22 11:44:42 +00:00
params . dataType = glType ;
2017-01-01 14:59:54 +00:00
params . data = pDest ;
gfxContext . init2DTexture ( params ) ;
2014-11-20 09:28:31 +00:00
}
2016-11-07 04:34:11 +00:00
if ( mipLevel = = _pTexture - > max_level )
2014-10-09 09:01:04 +00:00
break ;
+ + mipLevel ;
2014-11-13 09:51:09 +00:00
const u32 tileMipLevel = gSP . texture . tile + mipLevel + 1 ;
gDPTile & mipTile = gDP . tiles [ tileMipLevel ] ;
line = mipTile . line ;
tmptex . tMem = mipTile . tmem ;
tmptex . palette = mipTile . palette ;
tmptex . maskS = mipTile . masks ;
tmptex . maskT = mipTile . maskt ;
TileSizes sizes ;
2016-06-10 06:06:06 +00:00
_calcTileSizes ( tileMipLevel , sizes , nullptr ) ;
2014-11-13 09:51:09 +00:00
tmptex . width = sizes . width ;
tmptex . clampWidth = sizes . clampWidth ;
tmptex . height = sizes . height ;
tmptex . clampHeight = sizes . clampHeight ;
// Insure mip-map levels size consistency.
2014-10-09 09:01:04 +00:00
if ( tmptex . realWidth > 1 )
tmptex . realWidth > > = 1 ;
if ( tmptex . realHeight > 1 )
tmptex . realHeight > > = 1 ;
_pTexture - > textureBytes + = ( tmptex . realWidth * tmptex . realHeight ) < < sizeShift ;
2015-08-30 22:16:40 +00:00
}
2015-05-08 12:33:03 +00:00
if ( m_curUnpackAlignment > 1 )
2017-01-22 11:10:52 +00:00
gfxContext . setTextureUnpackAlignment ( m_curUnpackAlignment ) ;
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 ;
2016-07-11 15:50:37 +00:00
u32 flags ;
2014-09-03 05:12:48 +00:00
} ;
2014-09-18 16:16:52 +00:00
static
2016-07-02 18:09:26 +00:00
u32 _calculateCRC ( u32 _t , const TextureParams & _params , u32 _bytes )
2013-04-05 06:13:26 +00:00
{
2017-12-16 08:14:46 +00:00
const bool rgba32 = gSP . textureTile [ _t ] - > size = = G_IM_SIZ_32b ;
2016-07-13 11:14:29 +00:00
if ( _bytes = = 0 ) {
const u32 lineBytes = gSP . textureTile [ _t ] - > line < < 3 ;
_bytes = _params . height * lineBytes ;
}
2017-12-16 08:14:46 +00:00
if ( rgba32 )
_bytes > > = 1 ;
const u32 tMemMask = ( gDP . otherMode . textureLUT = = G_TT_NONE & & ! rgba32 ) ? 0x1FF : 0xFF ;
2016-10-15 05:52:34 +00:00
const u64 * src = ( u64 * ) & TMEM [ gSP . textureTile [ _t ] - > tmem & tMemMask ] ;
2014-12-16 10:30:43 +00:00
u32 crc = 0xFFFFFFFF ;
2016-07-02 18:09:26 +00:00
crc = CRC_Calculate ( crc , src , _bytes ) ;
2013-04-05 06:13:26 +00:00
2017-12-16 08:14:46 +00:00
if ( rgba32 ) {
2016-07-02 18:09:26 +00:00
src = ( u64 * ) & TMEM [ gSP . textureTile [ _t ] - > tmem + 256 ] ;
crc = CRC_Calculate ( crc , src , _bytes ) ;
2014-12-16 10:30:43 +00:00
}
2016-07-02 18:09:26 +00:00
if ( gDP . otherMode . textureLUT ! = G_TT_NONE | | gSP . textureTile [ _t ] - > format = = G_IM_FMT_CI ) {
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 )
2013-04-05 06:13:26 +00:00
crc = CRC_Calculate ( crc , & gDP . paletteCRC256 , 4 ) ;
}
2014-09-03 05:12:48 +00:00
crc = CRC_Calculate ( crc , & _params , sizeof ( _params ) ) ;
2015-03-31 17:49:24 +00:00
2013-04-05 06:13:26 +00:00
return crc ;
}
2015-02-27 12:43:12 +00:00
void TextureCache : : activateTexture ( u32 _t , CachedTexture * _pTexture )
2013-04-05 06:13:26 +00:00
{
2017-01-01 14:59:54 +00:00
2017-01-21 12:48:02 +00:00
Context : : TexParameters params ;
params . handle = _pTexture - > name ;
2017-01-01 14:59:54 +00:00
if ( config . video . multisampling > 0 & & _pTexture - > frameBufferTexture = = CachedTexture : : fbMultiSample ) {
2017-01-28 09:52:09 +00:00
params . target = textureTarget : : TEXTURE_2D_MULTISAMPLE ;
2017-01-21 12:48:02 +00:00
params . textureUnitIndex = textureIndices : : MSTex [ _t ] ;
2017-01-01 14:59:54 +00:00
} else {
2017-01-28 09:52:09 +00:00
params . target = textureTarget : : TEXTURE_2D ;
2017-01-21 12:48:02 +00:00
params . textureUnitIndex = textureIndices : : Tex [ _t ] ;
2017-01-01 14:59:54 +00:00
2018-09-01 12:43:58 +00:00
const bool bUseBilinear = gDP . otherMode . textureFilter ! = 0 ;
2017-02-18 14:40:41 +00:00
const bool bUseLOD = currentCombiner ( ) - > usesLOD ( ) ;
const s32 texLevel = bUseLOD ? _pTexture - > max_level : 0 ;
params . maxMipmapLevel = Parameter ( texLevel ) ;
2017-01-01 14:59:54 +00:00
2018-01-03 10:09:23 +00:00
if ( bUseLOD ) {
2017-01-01 14:59:54 +00:00
if ( bUseBilinear ) {
2018-01-03 10:09:23 +00:00
// Apply standard bilinear to mipmap textures
if ( texLevel > 0 )
params . minFilter = textureParameters : : FILTER_LINEAR_MIPMAP_NEAREST ;
else
params . minFilter = textureParameters : : FILTER_LINEAR ;
2017-01-21 12:48:02 +00:00
params . magFilter = textureParameters : : FILTER_LINEAR ;
2017-02-18 14:40:41 +00:00
} else {
2018-01-03 10:09:23 +00:00
if ( texLevel > 0 )
params . minFilter = textureParameters : : FILTER_NEAREST_MIPMAP_NEAREST ;
else
params . minFilter = textureParameters : : FILTER_NEAREST ;
2017-01-21 12:48:02 +00:00
params . magFilter = textureParameters : : FILTER_NEAREST ;
2017-01-01 14:59:54 +00:00
}
2017-10-22 13:50:57 +00:00
} else { // Don't use texture filter. Texture will be filtered by filter shader
params . minFilter = textureParameters : : FILTER_NEAREST ;
params . magFilter = textureParameters : : FILTER_NEAREST ;
2017-01-01 14:59:54 +00:00
}
2017-02-18 14:40:41 +00:00
// Set clamping modes
params . wrapS = _pTexture - > clampS ? textureParameters : : WRAP_CLAMP_TO_EDGE :
_pTexture - > mirrorS ? textureParameters : : WRAP_MIRRORED_REPEAT
: textureParameters : : WRAP_REPEAT ;
params . wrapT = _pTexture - > clampT ? textureParameters : : WRAP_CLAMP_TO_EDGE :
_pTexture - > mirrorT ? textureParameters : : WRAP_MIRRORED_REPEAT
: textureParameters : : WRAP_REPEAT ;
2017-01-01 14:59:54 +00:00
2017-02-18 14:40:41 +00:00
if ( dwnd ( ) . getDrawer ( ) . getDrawingState ( ) = = DrawingState : : Triangle & & config . texture . maxAnisotropyF > 0.0f )
params . maxAnisotropy = Parameter ( config . texture . maxAnisotropyF ) ;
}
2017-01-01 14:59:54 +00:00
gfxContext . setTextureParameters ( params ) ;
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
{
2017-01-21 12:48:02 +00:00
Context : : TexParameters params ;
params . handle = m_pDummy - > name ;
2017-01-28 09:52:09 +00:00
params . target = textureTarget : : TEXTURE_2D ;
2017-01-21 12:48:02 +00:00
params . textureUnitIndex = textureIndices : : Tex [ _t ] ;
params . minFilter = textureParameters : : FILTER_NEAREST ;
params . magFilter = textureParameters : : FILTER_NEAREST ;
2017-01-01 14:59:54 +00:00
gfxContext . setTextureParameters ( params ) ;
2013-04-05 06:13:26 +00:00
}
2015-05-06 12:36:07 +00:00
void TextureCache : : activateMSDummy ( u32 _t )
{
2017-01-21 12:48:02 +00:00
Context : : TexParameters params ;
params . handle = m_pMSDummy - > name ;
2017-01-28 09:52:09 +00:00
params . target = textureTarget : : TEXTURE_2D_MULTISAMPLE ;
2017-01-21 12:48:02 +00:00
params . textureUnitIndex = textureIndices : : MSTex [ _t ] ;
2017-01-01 14:59:54 +00:00
gfxContext . setTextureParameters ( params ) ;
2015-05-06 12:36:07 +00:00
}
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 ) ;
2015-10-04 21:41:25 +00:00
Texture_Locations : : iterator locations_iter = m_lruTextureLocations . find ( crc ) ;
if ( locations_iter ! = m_lruTextureLocations . end ( ) ) {
Textures : : iterator iter = locations_iter - > second ;
2017-11-18 15:07:27 +00:00
CachedTexture & currentTex = * iter ;
2015-10-04 21:41:25 +00:00
m_textures . splice ( m_textures . begin ( ) , m_textures , iter ) ;
2017-11-18 15:07:27 +00:00
assert ( currentTex . width = = gSP . bgImage . width ) ;
assert ( currentTex . height = = gSP . bgImage . height ) ;
assert ( currentTex . format = = gSP . bgImage . format ) ;
assert ( currentTex . size = = gSP . bgImage . size ) ;
2018-10-10 17:58:54 +00:00
currentTex . clampS = gSP . bgImage . clampS ;
currentTex . clampT = gSP . bgImage . clampT ;
2014-09-18 16:16:52 +00:00
2017-11-18 15:07:27 +00:00
activateTexture ( 0 , & currentTex ) ;
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
CachedTexture * pCurrent = _addTexture ( crc ) ;
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-11-13 05:00:38 +00:00
pCurrent - > mirrorS = 0 ;
pCurrent - > mirrorT = 0 ;
2018-10-10 17:58:54 +00:00
pCurrent - > clampS = gSP . bgImage . clampS ;
pCurrent - > clampT = gSP . bgImage . clampT ;
2014-09-18 16:16:52 +00:00
pCurrent - > line = 0 ;
pCurrent - > tMem = 0 ;
2015-05-06 13:47:12 +00:00
pCurrent - > frameBufferTexture = CachedTexture : : fbNone ;
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
current [ 0 ] = pCurrent ;
2013-04-05 06:13:26 +00:00
}
2015-04-12 12:49:40 +00:00
void TextureCache : : _clear ( )
{
2016-06-10 06:06:06 +00:00
current [ 0 ] = current [ 1 ] = nullptr ;
2015-04-12 12:49:40 +00:00
2017-01-21 12:48:02 +00:00
for ( auto cur = m_textures . cbegin ( ) ; cur ! = m_textures . cend ( ) ; + + cur ) {
2018-05-07 15:43:57 +00:00
gfxContext . deleteTexture ( cur - > name ) ;
2015-04-12 12:49:40 +00:00
}
m_textures . clear ( ) ;
2015-10-04 21:41:25 +00:00
m_lruTextureLocations . clear ( ) ;
2015-04-12 12:49:40 +00:00
}
2014-09-18 16:16:52 +00:00
void TextureCache : : update ( u32 _t )
2013-04-05 06:13:26 +00:00
{
2015-04-12 12:49:40 +00:00
if ( config . textureFilter . txHiresEnable ! = 0 & & config . textureFilter . txDump ! = 0 ) {
/* Force reload hi-res textures. Useful for texture artists */
if ( isKeyPressed ( G64_VK_R , 0x0001 ) ) {
if ( txfilter_reloadhirestex ( ) ) {
_clear ( ) ;
}
}
/* Turn on texture dump */
else if ( isKeyPressed ( G64_VK_D , 0x0001 ) ) {
m_toggleDumpTex = ! m_toggleDumpTex ;
if ( m_toggleDumpTex ) {
displayLoadProgress ( L " Texture dump - ON \n " ) ;
_clear ( ) ;
std : : this_thread : : sleep_for ( std : : chrono : : seconds ( 1 ) ) ;
}
else {
displayLoadProgress ( L " Texture dump - OFF \n " ) ;
std : : this_thread : : sleep_for ( std : : chrono : : seconds ( 1 ) ) ;
}
}
}
2016-11-29 15:39:59 +00:00
const gDPTile * pTile = gSP . textureTile [ _t ] ;
2016-07-02 18:09:26 +00:00
switch ( pTile - > 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 :
2017-09-29 15:24:30 +00:00
FrameBuffer_ActivateBufferTexture ( _t , pTile - > frameBufferAddress ) ;
2013-04-05 06:13:26 +00:00
return ;
2013-06-09 11:55:21 +00:00
case TEXTUREMODE_FRAMEBUFFER_BG :
2017-09-29 15:24:30 +00:00
FrameBuffer_ActivateBufferTextureBG ( _t , pTile - > frameBufferAddress ) ;
2013-06-09 11:55:21 +00:00
return ;
2013-04-05 06:13:26 +00:00
}
2016-05-10 15:44:03 +00:00
if ( gDP . otherMode . textureLOD = = G_TL_LOD & & gSP . texture . level = = 0 & & ! currentCombiner ( ) - > usesLOD ( ) & & _t = = 1 ) {
current [ 1 ] = current [ 0 ] ;
2017-11-18 15:07:27 +00:00
if ( current [ 1 ] ! = nullptr ) {
activateTexture ( 1 , current [ 1 ] ) ;
return ;
}
2016-05-10 15:44:03 +00:00
}
2015-08-30 22:44:01 +00:00
if ( gSP . texture . tile = = 7 & &
2016-11-29 15:39:59 +00:00
_t = = 0 & &
gSP . textureTile [ 0 ] = = gDP . loadTile & &
gDP . loadTile - > loadType = = LOADTYPE_BLOCK & &
gSP . textureTile [ 0 ] - > tmem = = gSP . textureTile [ 1 ] - > tmem ) {
2014-11-05 07:45:48 +00:00
gSP . textureTile [ 0 ] = gSP . textureTile [ 1 ] ;
2016-11-29 15:39:59 +00:00
pTile = gSP . textureTile [ _t ] ;
}
2014-11-05 07:45:48 +00:00
2017-03-22 13:28:00 +00:00
TileSizes sizes ;
_calcTileSizes ( _t , sizes , gDP . loadTile ) ;
2016-07-02 18:09:26 +00:00
TextureParams params ;
2016-07-12 09:46:07 +00:00
params . flags = pTile - > masks |
( pTile - > maskt < < 4 ) |
( pTile - > mirrors < < 8 ) |
( pTile - > mirrort < < 9 ) |
( pTile - > clamps < < 10 ) |
( pTile - > clampt < < 11 ) |
( pTile - > size < < 12 ) |
( pTile - > format < < 14 ) |
( gDP . otherMode . textureLUT < < 17 ) ;
2016-07-02 18:09:26 +00:00
params . width = sizes . realWidth ;
params . height = sizes . realHeight ;
2013-04-05 06:13:26 +00:00
2016-07-02 18:09:26 +00:00
const u32 crc = _calculateCRC ( _t , params , sizes . bytes ) ;
2013-04-05 06:13:26 +00:00
2016-06-10 06:06:06 +00:00
if ( current [ _t ] ! = nullptr & & current [ _t ] - > crc = = crc ) {
2014-09-18 16:16:52 +00:00
activateTexture ( _t , current [ _t ] ) ;
return ;
}
2013-04-05 06:13:26 +00:00
2015-10-04 21:41:25 +00:00
Texture_Locations : : iterator locations_iter = m_lruTextureLocations . find ( crc ) ;
if ( locations_iter ! = m_lruTextureLocations . end ( ) ) {
Textures : : iterator iter = locations_iter - > second ;
2017-11-18 15:07:27 +00:00
CachedTexture & currentTex = * iter ;
2015-10-04 21:41:25 +00:00
2017-11-18 15:07:27 +00:00
if ( currentTex . width = = sizes . width & & currentTex . height = = sizes . height ) {
2017-03-19 12:18:07 +00:00
m_textures . splice ( m_textures . begin ( ) , m_textures , iter ) ;
2014-09-18 16:16:52 +00:00
2017-11-18 15:07:27 +00:00
assert ( currentTex . format = = pTile - > format ) ;
assert ( currentTex . size = = pTile - > size ) ;
2017-03-19 12:18:07 +00:00
2017-11-18 15:07:27 +00:00
activateTexture ( _t , & currentTex ) ;
2017-03-19 12:18:07 +00:00
m_hits + + ;
return ;
}
2018-05-07 15:43:57 +00:00
gfxContext . deleteTexture ( currentTex . name ) ;
2017-03-19 12:18:07 +00:00
m_lruTextureLocations . erase ( locations_iter ) ;
m_textures . erase ( iter ) ;
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
CachedTexture * pCurrent = _addTexture ( crc ) ;
2013-04-05 06:13:26 +00:00
2016-07-02 18:09:26 +00:00
pCurrent - > address = gDP . loadInfo [ pTile - > tmem ] . texAddress ;
2013-04-05 06:13:26 +00:00
2016-07-02 18:09:26 +00:00
pCurrent - > format = pTile - > format ;
pCurrent - > size = pTile - > size ;
2013-04-05 06:13:26 +00:00
2014-11-13 09:51:09 +00:00
pCurrent - > width = sizes . width ;
pCurrent - > height = sizes . height ;
2013-04-05 06:13:26 +00:00
2014-11-13 09:51:09 +00:00
pCurrent - > clampWidth = sizes . clampWidth ;
pCurrent - > clampHeight = sizes . clampHeight ;
2013-04-05 06:13:26 +00:00
2016-07-02 18:09:26 +00:00
pCurrent - > palette = pTile - > palette ;
2014-09-18 16:16:52 +00:00
/* 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 ; */
2016-07-02 18:09:26 +00:00
pCurrent - > maskS = pTile - > masks ;
pCurrent - > maskT = pTile - > maskt ;
pCurrent - > mirrorS = pTile - > mirrors ;
pCurrent - > mirrorT = pTile - > mirrort ;
pCurrent - > clampS = pTile - > clamps ;
pCurrent - > clampT = pTile - > clampt ;
pCurrent - > line = pTile - > line ;
pCurrent - > tMem = pTile - > tmem ;
2015-05-06 13:47:12 +00:00
pCurrent - > frameBufferTexture = CachedTexture : : fbNone ;
2013-04-05 06:13:26 +00:00
2014-11-13 09:51:09 +00:00
pCurrent - > realWidth = sizes . realWidth ;
pCurrent - > realHeight = sizes . realHeight ;
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 - > offsetS = 0.5f ;
pCurrent - > offsetT = 0.5f ;
2013-04-05 06:13:26 +00:00
2014-12-18 14:14:27 +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
current [ _t ] = pCurrent ;
2013-04-05 06:13:26 +00:00
}
2015-04-29 05:33:11 +00:00
void getTextureShiftScale ( u32 t , const TextureCache & cache , f32 & shiftScaleS , f32 & shiftScaleT )
{
if ( gSP . textureTile [ t ] - > textureMode ! = TEXTUREMODE_NORMAL ) {
shiftScaleS = cache . current [ t ] - > shiftScaleS ;
shiftScaleT = cache . current [ t ] - > shiftScaleT ;
return ;
}
2016-05-10 15:44:03 +00:00
if ( gDP . otherMode . textureLOD = = G_TL_LOD & & gSP . texture . level = = 0 & & ! currentCombiner ( ) - > usesLOD ( ) )
t = 0 ;
2015-04-29 05:33:11 +00:00
if ( gSP . textureTile [ t ] - > shifts > 10 )
shiftScaleS = ( f32 ) ( 1 < < ( 16 - gSP . textureTile [ t ] - > shifts ) ) ;
else if ( gSP . textureTile [ t ] - > shifts > 0 )
shiftScaleS / = ( f32 ) ( 1 < < gSP . textureTile [ t ] - > shifts ) ;
if ( gSP . textureTile [ t ] - > shiftt > 10 )
shiftScaleT = ( f32 ) ( 1 < < ( 16 - gSP . textureTile [ t ] - > shiftt ) ) ;
else if ( gSP . textureTile [ t ] - > shiftt > 0 )
shiftScaleT / = ( f32 ) ( 1 < < gSP . textureTile [ t ] - > shiftt ) ;
}