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
2013-04-05 06:13:26 +00:00
# include "OpenGL.h"
# include "Textures.h"
2015-04-30 12:19:58 +00:00
# include "GLSLCombiner.h"
2013-04-05 06:13:26 +00:00
# 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"
2013-04-05 06:13:26 +00:00
2014-09-01 16:19:20 +00:00
using namespace std ;
2015-05-06 12:36:07 +00:00
const GLuint g_noiseTexIndex = 2 ;
const GLuint g_MSTex0Index = g_noiseTexIndex + 1 ;
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 ] ) ;
}
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 ;
}
2014-12-11 07:48:55 +00:00
const struct TextureLoadParameters
2013-04-05 06:13:26 +00:00
{
GetTexelFunc Get16 ;
GLenum glType16 ;
GLint glInternalFormat16 ;
GetTexelFunc Get32 ;
GLenum glType32 ;
GLint glInternalFormat32 ;
u32 autoFormat , lineShift , maxTexels ;
2014-12-11 07:48:55 +00:00
} imageFormat [ 4 ] [ 4 ] [ 5 ] =
{ // G_TT_NONE
2016-03-01 10:48:35 +00:00
{ // Get16 glType16 glInternalFormat16 Get32 glType32 glInternalFormat32 autoFormat
2014-12-11 07:48:55 +00:00
{ // 4-bit
2016-03-01 10:48:35 +00:00
{ GetI4_RGBA4444 , GL_UNSIGNED_SHORT_4_4_4_4 , GL_RGBA4 , GetI4_RGBA8888 , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGBA4 , 4 , 8192 } , // RGBA as I
{ GetNone , GL_UNSIGNED_SHORT_4_4_4_4 , GL_RGBA4 , GetNone , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGBA4 , 4 , 8192 } , // YUV
{ GetI4_RGBA4444 , GL_UNSIGNED_SHORT_4_4_4_4 , GL_RGBA4 , GetI4_RGBA8888 , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGBA4 , 4 , 8192 } , // CI without palette
{ 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
2014-12-11 07:48:55 +00:00
} ,
{ // 8-bit
2016-03-01 10:48:35 +00:00
{ GetI8_RGBA4444 , GL_UNSIGNED_SHORT_4_4_4_4 , GL_RGBA4 , GetI8_RGBA8888 , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGBA , 3 , 4096 } , // RGBA as I
{ GetNone , GL_UNSIGNED_SHORT_4_4_4_4 , GL_RGBA4 , GetNone , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGBA4 , 0 , 4096 } , // YUV
{ GetI8_RGBA4444 , GL_UNSIGNED_SHORT_4_4_4_4 , GL_RGBA4 , GetI8_RGBA8888 , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGBA , 3 , 4096 } , // CI without palette
{ 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
2014-12-11 07:48:55 +00:00
} ,
{ // 16-bit
2016-03-01 10:48:35 +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
{ GetIA88_RGBA4444 , GL_UNSIGNED_SHORT_4_4_4_4 , GL_RGBA4 , GetIA88_RGBA8888 , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGBA , 2 , 2048 } , // CI as IA
{ 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
2014-12-11 07:48:55 +00:00
} ,
{ // 32-bit
2016-03-01 10:48:35 +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
2014-12-11 07:48:55 +00:00
}
2013-04-05 06:13:26 +00:00
} ,
2014-12-11 07:48:55 +00:00
// DUMMY
2016-03-01 10:48:35 +00:00
{ // Get16 glType16 glInternalFormat16 Get32 glType32 glInternalFormat32 autoFormat
2014-12-11 07:48:55 +00:00
{ // 4-bit
2016-03-01 10:48:35 +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
{ GetCI4RGBA_RGBA5551 , GL_UNSIGNED_SHORT_5_5_5_1 , GL_RGB5_A1 , GetCI4RGBA_RGBA8888 , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGB5_A1 , 4 , 4096 } , // IA as CI
{ GetCI4RGBA_RGBA5551 , GL_UNSIGNED_SHORT_5_5_5_1 , GL_RGB5_A1 , GetCI4RGBA_RGBA8888 , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGB5_A1 , 4 , 4096 } , // I as CI
2014-12-11 07:48:55 +00:00
} ,
{ // 8-bit
2016-03-01 10:48:35 +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
{ GetCI8RGBA_RGBA5551 , GL_UNSIGNED_SHORT_5_5_5_1 , GL_RGB5_A1 , GetCI8RGBA_RGBA8888 , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGB5_A1 , 3 , 2048 } , // IA as CI
{ GetCI8RGBA_RGBA5551 , GL_UNSIGNED_SHORT_5_5_5_1 , GL_RGB5_A1 , GetCI8RGBA_RGBA8888 , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGB5_A1 , 3 , 2048 } , // I as CI
2014-12-11 07:48:55 +00:00
} ,
{ // 16-bit
2016-03-01 10:48:35 +00:00
{ GetCI16RGBA_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
{ GetCI16RGBA_RGBA5551 , GL_UNSIGNED_SHORT_5_5_5_1 , GL_RGB5_A1 , GetCI16RGBA_RGBA8888 , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGB5_A1 , 2 , 2048 } , // IA as CI
{ GetNone , GL_UNSIGNED_SHORT_4_4_4_4 , GL_RGBA4 , GetNone , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGBA4 , 0 , 2048 } , // I
2014-12-11 07:48:55 +00:00
} ,
{ // 32-bit
2016-03-01 10:48:35 +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
2014-12-11 07:48:55 +00:00
}
2013-04-05 06:13:26 +00:00
} ,
2014-12-11 07:48:55 +00:00
// G_TT_RGBA16
2016-03-01 10:48:35 +00:00
{ // Get16 glType16 glInternalFormat16 Get32 glType32 glInternalFormat32 autoFormat
2014-12-11 07:48:55 +00:00
{ // 4-bit
2016-03-01 10:48:35 +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
{ GetCI4RGBA_RGBA5551 , GL_UNSIGNED_SHORT_5_5_5_1 , GL_RGB5_A1 , GetCI4RGBA_RGBA8888 , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGB5_A1 , 4 , 4096 } , // IA as CI
{ GetCI4RGBA_RGBA5551 , GL_UNSIGNED_SHORT_5_5_5_1 , GL_RGB5_A1 , GetCI4RGBA_RGBA8888 , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGB5_A1 , 4 , 4096 } , // I as CI
2014-12-11 07:48:55 +00:00
} ,
{ // 8-bit
2016-03-01 10:48:35 +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
{ GetCI8RGBA_RGBA5551 , GL_UNSIGNED_SHORT_5_5_5_1 , GL_RGB5_A1 , GetCI8RGBA_RGBA8888 , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGB5_A1 , 3 , 2048 } , // IA as CI
{ GetCI8RGBA_RGBA5551 , GL_UNSIGNED_SHORT_5_5_5_1 , GL_RGB5_A1 , GetCI8RGBA_RGBA8888 , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGB5_A1 , 3 , 2048 } , // I as CI
2014-12-11 07:48:55 +00:00
} ,
{ // 16-bit
2016-03-01 10:48:35 +00:00
{ GetCI16RGBA_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
{ GetCI16RGBA_RGBA5551 , GL_UNSIGNED_SHORT_5_5_5_1 , GL_RGB5_A1 , GetCI16RGBA_RGBA8888 , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGB5_A1 , 2 , 2048 } , // IA as CI
{ GetNone , GL_UNSIGNED_SHORT_4_4_4_4 , GL_RGBA4 , GetNone , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGBA4 , 0 , 2048 } , // I
2014-12-11 07:48:55 +00:00
} ,
{ // 32-bit
2016-03-01 10:48:35 +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
2014-12-11 07:48:55 +00:00
}
2013-04-05 06:13:26 +00:00
} ,
2014-12-11 07:48:55 +00:00
// G_TT_IA16
2016-03-01 10:48:35 +00:00
{ // Get16 glType16 glInternalFormat16 Get32 glType32 glInternalFormat32 autoFormat
2014-12-11 07:48:55 +00:00
{ // 4-bit
2016-03-01 10:49:43 +00:00
{ GetCI4IA_RGBA4444 , GL_UNSIGNED_SHORT_4_4_4_4 , GL_RGBA4 , GetCI4IA_RGBA8888 , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGBA , 4 , 4096 } , // IA
{ GetNone , GL_UNSIGNED_SHORT_4_4_4_4 , GL_RGBA4 , GetNone , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGBA , 4 , 8192 } , // YUV
{ GetCI4IA_RGBA4444 , GL_UNSIGNED_SHORT_4_4_4_4 , GL_RGBA4 , GetCI4IA_RGBA8888 , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGBA , 4 , 4096 } , // CI
{ GetCI4IA_RGBA4444 , GL_UNSIGNED_SHORT_4_4_4_4 , GL_RGBA4 , GetCI4IA_RGBA8888 , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGBA , 4 , 4096 } , // IA
{ GetCI4IA_RGBA4444 , GL_UNSIGNED_SHORT_4_4_4_4 , GL_RGBA4 , GetCI4IA_RGBA8888 , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGBA , 4 , 4096 } , // I
2014-12-11 07:48:55 +00:00
} ,
{ // 8-bit
2016-03-01 10:49:43 +00:00
{ GetCI8IA_RGBA4444 , GL_UNSIGNED_SHORT_4_4_4_4 , GL_RGBA4 , GetCI8IA_RGBA8888 , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGBA , 3 , 2048 } , // RGBA
{ GetNone , GL_UNSIGNED_SHORT_4_4_4_4 , GL_RGBA4 , GetNone , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGBA , 0 , 4096 } , // YUV
{ GetCI8IA_RGBA4444 , GL_UNSIGNED_SHORT_4_4_4_4 , GL_RGBA4 , GetCI8IA_RGBA8888 , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGBA , 3 , 2048 } , // CI
{ GetCI8IA_RGBA4444 , GL_UNSIGNED_SHORT_4_4_4_4 , GL_RGBA4 , GetCI8IA_RGBA8888 , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGBA , 3 , 2048 } , // IA
{ GetCI8IA_RGBA4444 , GL_UNSIGNED_SHORT_4_4_4_4 , GL_RGBA4 , GetCI8IA_RGBA8888 , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGBA , 3 , 2048 } , // I
2014-12-11 07:48:55 +00:00
} ,
{ // 16-bit
2016-03-01 10:49:43 +00:00
{ GetCI16IA_RGBA4444 , GL_UNSIGNED_SHORT_4_4_4_4 , GL_RGBA4 , GetCI16IA_RGBA8888 , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGBA , 2 , 2048 } , // RGBA
{ GetNone , GL_UNSIGNED_SHORT_4_4_4_4 , GL_RGBA4 , GetNone , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGBA , 2 , 2048 } , // YUV
{ GetNone , GL_UNSIGNED_SHORT_4_4_4_4 , GL_RGBA4 , GetNone , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGBA , 0 , 2048 } , // CI
{ GetCI16IA_RGBA4444 , GL_UNSIGNED_SHORT_4_4_4_4 , GL_RGBA4 , GetCI16IA_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_RGBA , 0 , 2048 } , // I
2014-12-11 07:48:55 +00:00
} ,
{ // 32-bit
2016-03-01 10:49:43 +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_RGBA , 0 , 1024 } , // YUV
{ GetNone , GL_UNSIGNED_SHORT_4_4_4_4 , GL_RGBA4 , GetNone , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGBA , 0 , 1024 } , // CI
{ GetNone , GL_UNSIGNED_SHORT_4_4_4_4 , GL_RGBA4 , GetNone , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGBA , 0 , 1024 } , // IA
{ GetNone , GL_UNSIGNED_SHORT_4_4_4_4 , GL_RGBA4 , GetNone , GL_UNSIGNED_BYTE , GL_RGBA , GL_RGBA , 0 , 1024 } , // I
2014-12-11 07:48:55 +00:00
}
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 ( )
{
2014-09-18 16:16:52 +00:00
m_maxBytes = config . texture . maxBytes ;
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
2015-05-06 12:36:07 +00:00
m_pDummy = addFrameBufferTexture ( ) ; // we don't want to remove dummy texture
_initDummyTexture ( m_pDummy ) ;
2015-03-31 15:24:49 +00:00
2015-05-06 12:36:07 +00:00
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 ;
2015-05-06 12:36:07 +00:00
# ifdef GL_MULTISAMPLING_SUPPORT
2015-09-05 20:05:33 +00:00
if ( config . video . multisampling ! = 0 ) {
m_pMSDummy = addFrameBufferTexture ( ) ; // we don't want to remove dummy texture
_initDummyTexture ( m_pMSDummy ) ;
2015-05-06 12:36:07 +00:00
2015-09-05 20:05:33 +00:00
glBindTexture ( GL_TEXTURE_2D_MULTISAMPLE , m_pMSDummy - > glName ) ;
2015-05-07 14:01:02 +00:00
# if defined(GLES3_1)
2015-09-05 20:05:33 +00:00
glTexStorage2DMultisample ( GL_TEXTURE_2D_MULTISAMPLE , config . video . multisampling ,
GL_RGBA8 , m_pMSDummy - > realWidth , m_pMSDummy - > realHeight , false ) ;
2015-05-07 14:01:02 +00:00
# else
2015-09-05 20:05:33 +00:00
glTexImage2DMultisample ( GL_TEXTURE_2D_MULTISAMPLE , config . video . multisampling ,
GL_RGBA8 , m_pMSDummy - > realWidth , m_pMSDummy - > realHeight , false ) ;
2015-05-07 14:01:02 +00:00
# endif
2015-09-05 20:05:33 +00:00
activateMSDummy ( 0 ) ;
activateMSDummy ( 1 ) ;
} else
2015-05-06 12:36:07 +00:00
# endif
2015-09-05 20:05:33 +00:00
m_pMSDummy = NULL ;
assert ( ! isGLError ( ) ) ;
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 )
2015-10-04 21:41:25 +00:00
glDeleteTextures ( 1 , & cur - > glName ) ;
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 )
2014-09-22 11:40:35 +00:00
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 ;
2015-10-04 21:41:25 +00:00
2015-10-06 11:21:13 +00:00
Textures : : iterator iter = m_textures . end ( ) ;
2014-09-18 16:16:52 +00:00
do {
2014-09-22 11:40:35 +00:00
- - iter ;
2015-10-06 11:21:13 +00:00
CachedTexture & tex = * iter ;
2015-10-04 21:41:25 +00:00
m_cachedBytes - = tex . textureBytes ;
glDeleteTextures ( 1 , & tex . glName ) ;
m_lruTextureLocations . erase ( tex . crc ) ;
2014-09-22 11:40:35 +00:00
} while ( m_cachedBytes > m_maxBytes & & iter ! = m_textures . cbegin ( ) ) ;
2015-10-06 11:21:13 +00:00
m_textures . erase ( iter , m_textures . end ( ) ) ;
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 )
glGetIntegerv ( GL_UNPACK_ALIGNMENT , & m_curUnpackAlignment ) ;
2014-09-18 16:16:52 +00:00
_checkCacheSize ( ) ;
2014-09-22 11:40:35 +00:00
GLuint glName ;
glGenTextures ( 1 , & glName ) ;
2015-10-04 21:41:25 +00:00
m_textures . emplace_front ( glName ) ;
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
{
2015-10-04 21:41:25 +00:00
FBTextures : : const_iterator iter = m_fbTextures . find ( _pTexture - > glName ) ;
assert ( iter ! = m_fbTextures . cend ( ) ) ;
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-11-13 09:51:09 +00:00
struct TileSizes
{
u32 maskWidth , clampWidth , width , realWidth ;
u32 maskHeight , clampHeight , height , realHeight ;
} ;
static
void _calcTileSizes ( u32 _t , TileSizes & _sizes , gDPTile * _pLoadTile )
{
gDPTile * pTile = _t < 2 ? gSP . textureTile [ _t ] : & gDP . tiles [ _t ] ;
2014-12-11 07:48:55 +00:00
const TextureLoadParameters & loadParams = imageFormat [ gDP . otherMode . textureLUT ] [ pTile - > size ] [ pTile - > format ] ;
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
const bool bUseLoadSizes = _pLoadTile ! = NULL & & _pLoadTile - > loadType = = LOADTYPE_TILE & &
( 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 ;
2014-11-12 11:19:53 +00:00
gDPLoadTileInfo & info = gDP . loadInfo [ pTile - > tmem ] ;
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 ;
if ( _sizes . clampWidth > 256 )
pTile - > clamps = 0 ;
if ( _sizes . clampHeight > 256 )
pTile - > clampt = 0 ;
// 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
void _updateCachedTexture ( const GHQTexInfo & _info , CachedTexture * _pTexture )
{
_pTexture - > textureBytes = _info . width * _info . height ;
switch ( _info . format ) {
case GL_RGB :
case GL_RGBA4 :
case GL_RGB5_A1 :
_pTexture - > textureBytes < < = 1 ;
break ;
default :
_pTexture - > textureBytes < < = 2 ;
}
_pTexture - > realWidth = _info . width ;
_pTexture - > realHeight = _info . height ;
2014-12-09 17:37:26 +00:00
/*
2014-11-29 13:29:04 +00:00
_pTexture - > scaleS = 1.0f / ( f32 ) ( _pTexture - > realWidth ) ;
_pTexture - > scaleT = 1.0f / ( f32 ) ( _pTexture - > realHeight ) ;
*/
}
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
u8 * paladdr = NULL ;
u16 * palette = NULL ;
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 ;
2014-11-29 13:29:04 +00:00
if ( txfilter_hirestex ( _pTexture - > crc , ricecrc , palette , & ghqTexInfo ) ) {
2015-08-30 22:44:01 +00:00
glTexImage2D ( GL_TEXTURE_2D , 0 , ghqTexInfo . format ,
ghqTexInfo . width , ghqTexInfo . height , 0 , ghqTexInfo . texture_format ,
ghqTexInfo . pixel_type , ghqTexInfo . data ) ;
2014-11-29 13:29:04 +00:00
assert ( ! isGLError ( ) ) ;
_updateCachedTexture ( ghqTexInfo , _pTexture ) ;
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 ;
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-12-20 15:38:36 +00:00
const TextureLoadParameters & loadParams = imageFormat [ pTexture - > format = = 2 ? G_TT_RGBA16 : G_TT_NONE ] [ pTexture - > size ] [ pTexture - > format ] ;
2015-02-03 07:03:50 +00:00
if ( loadParams . autoFormat = = GL_RGBA ) {
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 ) ;
2014-11-28 05:12:18 +00:00
assert ( pSwapped ! = NULL ) ;
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 ) ;
2014-11-28 05:12:18 +00:00
assert ( pDest ! = NULL ) ;
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-11-29 13:29:04 +00:00
( ( u32 * ) pDest ) [ j + + ] = GetTexel ( ( u64 * ) pSrc , tx , 0 , pTexture - > palette ) ;
2013-04-05 06:13:26 +00:00
else
2014-11-29 13:29:04 +00:00
( ( u16 * ) pDest ) [ j + + ] = GetTexel ( ( u64 * ) pSrc , tx , 0 , pTexture - > palette ) ;
2013-04-05 06:13:26 +00:00
}
}
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 ,
glInternalFormat , ( uint64 ) pTexture - > crc , & ghqTexInfo ) ! = 0 & &
ghqTexInfo . data ! = NULL ) {
if ( ghqTexInfo . width % 2 ! = 0 & &
ghqTexInfo . format ! = GL_RGBA & &
m_curUnpackAlignment > 1 )
2014-11-29 13:29:04 +00:00
glPixelStorei ( GL_UNPACK_ALIGNMENT , 2 ) ;
2015-08-30 22:44:01 +00:00
glTexImage2D ( GL_TEXTURE_2D , 0 , ghqTexInfo . format ,
ghqTexInfo . width , ghqTexInfo . height , 0 ,
ghqTexInfo . texture_format , ghqTexInfo . pixel_type ,
ghqTexInfo . data ) ;
2014-11-29 13:29:04 +00:00
_updateCachedTexture ( ghqTexInfo , pTexture ) ;
bLoaded = true ;
2014-11-19 14:23:10 +00:00
}
}
2014-11-29 13:29:04 +00:00
if ( ! bLoaded ) {
if ( pTexture - > realWidth % 2 ! = 0 & & glInternalFormat ! = GL_RGBA )
glPixelStorei ( GL_UNPACK_ALIGNMENT , 2 ) ;
2015-05-26 08:03:47 +00:00
# ifdef GLES2
2015-08-30 22:44:01 +00:00
glTexImage2D ( GL_TEXTURE_2D , 0 , GL_RGBA , pTexture - > realWidth ,
pTexture - > realHeight , 0 , GL_RGBA , glType , pDest ) ;
2015-05-26 08:03:47 +00:00
# else
2015-08-30 22:44:01 +00:00
glTexImage2D ( GL_TEXTURE_2D , 0 , glInternalFormat , pTexture - > realWidth ,
pTexture - > realHeight , 0 , GL_RGBA , glType , pDest ) ;
2015-05-26 08:03:47 +00:00
# endif
2014-11-29 13:29:04 +00:00
}
2015-05-08 12:33:03 +00:00
if ( m_curUnpackAlignment > 1 )
glPixelStorei ( GL_UNPACK_ALIGNMENT , 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 ;
u8 * addr = ( u8 * ) ( RDRAM + info . texAddress ) ;
int tile_width = _pTexture - > width ;
int tile_height = _pTexture - > height ;
if ( info . loadType = = LOADTYPE_TILE ) {
bpl = info . texWidth < < info . size > > 1 ;
addr + = ( info . ult * bpl ) + ( ( ( info . uls < < info . size ) + 1 ) > > 1 ) ;
}
else {
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 ;
}
}
u8 * paladdr = NULL ;
u16 * palette = NULL ;
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));
}
2015-04-12 12:49:40 +00:00
_ricecrc = txfilter_checksum ( addr , tile_width , tile_height , ( unsigned short ) ( _pTexture - > format < < 8 | _pTexture - > size ) , bpl , paladdr ) ;
2014-12-09 17:37:26 +00:00
GHQTexInfo ghqTexInfo ;
2015-04-12 12:49:40 +00:00
if ( txfilter_hirestex ( _pTexture - > crc , _ricecrc , palette , & ghqTexInfo ) ) {
2015-05-26 08:03:47 +00:00
# ifdef GLES2
glTexImage2D ( GL_TEXTURE_2D , 0 , GL_RGBA , ghqTexInfo . width , ghqTexInfo . height , 0 , GL_RGBA , ghqTexInfo . pixel_type , ghqTexInfo . data ) ;
# else
2014-12-09 17:37:26 +00:00
glTexImage2D ( GL_TEXTURE_2D , 0 , ghqTexInfo . format , ghqTexInfo . width , ghqTexInfo . height , 0 , ghqTexInfo . texture_format , ghqTexInfo . pixel_type , ghqTexInfo . data ) ;
2015-05-26 08:03:47 +00:00
# endif
2014-12-09 17:37:26 +00:00
assert ( ! isGLError ( ) ) ;
_updateCachedTexture ( ghqTexInfo , _pTexture ) ;
return true ;
}
2015-04-12 12:49:40 +00:00
2014-12-09 17:37:26 +00:00
return false ;
}
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 ,
GLuint glInternalFormat ,
GetTexelFunc GetTexel ,
u16 * pLine )
2015-08-30 22:13:00 +00:00
{
u16 mirrorSBit , maskSMask , clampSClamp ;
u16 mirrorTBit , maskTMask , clampTClamp ;
u16 x , y , i , j , tx , ty ;
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 ;
mirrorSBit = ( tmptex . mirrorS ! = 0 | | tmptex . realWidth / tmptex . width = = 2 ) ? 1 < < tmptex . maskS : 0 ;
} 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 ;
mirrorTBit = ( tmptex . mirrorT ! = 0 | | tmptex . realHeight / tmptex . height = = 2 ) ? 1 < < tmptex . maskT : 0 ;
} 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 + + ) {
if ( glInternalFormat = = GL_RGBA ) {
GetYUV_RGBA8888 ( pSrc , pDest + j , x ) ;
} else {
GetYUV_RGBA4444 ( pSrc , ( u16 * ) pDest + j , x ) ;
}
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 ;
}
if ( glInternalFormat = = GL_RGBA ) {
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 ;
GLuint glInternalFormat ;
GLenum glType ;
2014-10-09 09:01:04 +00:00
u32 sizeShift ;
2013-04-05 06:13:26 +00:00
2014-12-11 07:48:55 +00:00
const TextureLoadParameters & loadParams = imageFormat [ gDP . otherMode . textureLUT ] [ _pTexture - > size ] [ _pTexture - > format ] ;
2015-02-03 07:03:50 +00:00
if ( loadParams . autoFormat = = GL_RGBA ) {
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 ) ;
2015-08-30 22:15:16 +00:00
assert ( pDest ! = NULL ) ;
2013-04-05 06:13:26 +00:00
2014-10-09 09:01:04 +00:00
GLint mipLevel = 0 , maxLevel = 0 ;
2015-05-25 15:52:57 +00:00
# ifndef GLES2
2016-03-05 11:51:17 +00:00
if ( config . generalEmulation . enableLOD ! = 0 & & gSP . texture . level > 1 )
maxLevel = _tile = = 0 ? 0 : gSP . texture . level - 1 ;
2015-05-25 15:52:57 +00:00
# endif
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 ) {
2015-08-30 22:13:00 +00:00
_getTextureDestData ( tmptex , pDest , glInternalFormat , GetTexel , & line ) ;
2014-11-20 09:28:31 +00:00
bool bLoaded = false ;
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 ,
tmptex . realWidth , glInternalFormat ,
( unsigned short ) ( _pTexture - > format < < 8 | _pTexture - > size ) ,
ricecrc ) ;
2015-04-12 12:49:40 +00:00
}
2015-08-30 22:44:01 +00:00
else if ( ( config . textureFilter . txEnhancementMode | config . textureFilter . txFilterMode ) ! = 0 & &
maxLevel = = 0 & &
( 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 ,
glInternalFormat , ( uint64 ) _pTexture - > crc ,
& ghqTexInfo ) ! = 0 & & ghqTexInfo . data ! = NULL ) {
2015-05-26 08:03:47 +00:00
# ifdef GLES2
2015-08-30 22:44:01 +00:00
glTexImage2D ( GL_TEXTURE_2D , 0 , GL_RGBA ,
ghqTexInfo . width , ghqTexInfo . height ,
0 , GL_RGBA , ghqTexInfo . pixel_type ,
ghqTexInfo . data ) ;
2015-05-26 08:03:47 +00:00
# else
2015-08-30 22:44:01 +00:00
glTexImage2D ( GL_TEXTURE_2D , 0 , ghqTexInfo . format ,
ghqTexInfo . width , ghqTexInfo . height ,
0 , ghqTexInfo . texture_format , ghqTexInfo . pixel_type ,
ghqTexInfo . data ) ;
2015-05-26 08:03:47 +00:00
# endif
2014-11-20 09:28:31 +00:00
_updateCachedTexture ( ghqTexInfo , _pTexture ) ;
bLoaded = true ;
}
}
if ( ! bLoaded ) {
2015-08-30 22:44:01 +00:00
if ( tmptex . realWidth % 2 ! = 0 & &
glInternalFormat ! = GL_RGBA & &
m_curUnpackAlignment > 1 )
2014-11-20 09:28:31 +00:00
glPixelStorei ( GL_UNPACK_ALIGNMENT , 2 ) ;
2015-05-26 08:03:47 +00:00
# ifdef GLES2
2015-08-30 22:44:01 +00:00
glTexImage2D ( GL_TEXTURE_2D , 0 , GL_RGBA , tmptex . realWidth ,
tmptex . realHeight , 0 , GL_RGBA , glType , pDest ) ;
2015-05-26 08:03:47 +00:00
# else
2015-08-30 22:44:01 +00:00
glTexImage2D ( GL_TEXTURE_2D , mipLevel , glInternalFormat , tmptex . realWidth ,
tmptex . realHeight , 0 , GL_RGBA , glType , pDest ) ;
2015-05-26 08:03:47 +00:00
# endif
2014-11-20 09:28:31 +00:00
}
2014-10-09 09:01:04 +00:00
if ( mipLevel = = maxLevel )
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 ;
_calcTileSizes ( tileMipLevel , sizes , NULL ) ;
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 )
glPixelStorei ( GL_UNPACK_ALIGNMENT , 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 ;
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
{
2014-12-16 10:30:43 +00:00
const u32 line = gSP . textureTile [ t ] - > line ;
const u32 lineBytes = line < < 3 ;
2013-04-05 06:13:26 +00:00
2014-12-16 10:30:43 +00:00
const u64 * src = ( u64 * ) & TMEM [ gSP . textureTile [ t ] - > tmem ] ;
u32 crc = 0xFFFFFFFF ;
2015-03-31 17:49:24 +00:00
crc = CRC_Calculate ( crc , src , _params . height * lineBytes ) ;
2013-04-05 06:13:26 +00:00
2014-12-16 10:30:43 +00:00
if ( gSP . textureTile [ t ] - > size = = G_IM_SIZ_32b ) {
src = ( u64 * ) & TMEM [ gSP . textureTile [ t ] - > tmem + 256 ] ;
2015-03-31 17:49:24 +00:00
crc = CRC_Calculate ( crc , src , _params . height * lineBytes ) ;
2014-12-16 10:30:43 +00:00
}
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 ) ;
}
2016-03-23 15:14:21 +00:00
const u8 tlutMode = gDP . otherMode . textureLUT ;
crc = CRC_Calculate ( crc , & tlutMode , 1 ) ;
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
{
2015-05-06 12:36:07 +00:00
# ifdef GL_MULTISAMPLING_SUPPORT
2015-05-06 13:47:12 +00:00
if ( config . video . multisampling > 0 & & _pTexture - > frameBufferTexture = = CachedTexture : : fbMultiSample ) {
2015-05-06 12:36:07 +00:00
glActiveTexture ( GL_TEXTURE0 + g_MSTex0Index + _t ) ;
// Bind the cached texture
glBindTexture ( GL_TEXTURE_2D_MULTISAMPLE , _pTexture - > glName ) ;
} else
# endif
{
glActiveTexture ( GL_TEXTURE0 + _t ) ;
// Bind the cached texture
glBindTexture ( GL_TEXTURE_2D , _pTexture - > glName ) ;
}
2015-02-27 12:43:12 +00:00
2015-03-27 12:48:37 +00:00
const bool bUseBilinear = ( gDP . otherMode . textureFilter | ( gSP . objRendermode & G_OBJRM_BILERP ) ) ! = 0 ;
2015-05-07 09:40:34 +00:00
const bool bUseLOD = currentCombiner ( ) - > usesLOD ( ) ;
const GLint texLevel = bUseLOD ? _pTexture - > max_level : 0 ;
2015-03-27 12:48:37 +00:00
2015-05-14 14:38:44 +00:00
# ifndef GLES2
2015-05-07 09:40:34 +00:00
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAX_LEVEL , texLevel ) ;
2015-05-14 14:38:44 +00:00
# endif
2015-03-27 12:48:37 +00:00
if ( config . texture . bilinearMode = = BILINEAR_STANDARD ) {
if ( bUseBilinear ) {
2015-05-07 09:40:34 +00:00
if ( texLevel > 0 )
2015-03-27 12:48:37 +00:00
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 {
2015-05-07 09:40:34 +00:00
if ( texLevel > 0 )
2015-03-27 12:48:37 +00:00
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 ) ;
}
} else { // 3 point filter
2015-05-07 09:40:34 +00:00
if ( texLevel > 0 ) { // Apply standard bilinear to mipmap textures
2015-03-27 12:48:37 +00:00
if ( bUseBilinear ) {
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR_MIPMAP_NEAREST ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ;
} else {
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_NEAREST_MIPMAP_NEAREST ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_NEAREST ) ;
}
2015-05-07 09:40:34 +00:00
} else if ( bUseBilinear & & config . generalEmulation . enableLOD ! = 0 & & bUseLOD ) { // Apply standard bilinear to first tile of mipmap texture
2014-10-09 09:01:04 +00:00
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR ) ;
2015-03-27 12:48:37 +00:00
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ;
} else { // Don't use texture filter. Texture will be filtered by 3 point filter shader
2014-10-09 09:01:04 +00:00
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_NEAREST ) ;
2015-03-27 12:48:37 +00:00
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-11-13 05:00:38 +00:00
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_S , _pTexture - > clampS ? GL_CLAMP_TO_EDGE : _pTexture - > mirrorS ? GL_MIRRORED_REPEAT : GL_REPEAT ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_T , _pTexture - > clampT ? GL_CLAMP_TO_EDGE : _pTexture - > mirrorT ? GL_MIRRORED_REPEAT : GL_REPEAT ) ;
2013-04-05 06:13:26 +00:00
2015-02-05 16:05:47 +00:00
if ( video ( ) . getRender ( ) . getRenderState ( ) = = OGLRender : : rsTriangle & & config . texture . maxAnisotropyF > 0.0f )
glTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_MAX_ANISOTROPY_EXT , config . texture . maxAnisotropyF ) ;
2015-10-16 15:42:35 +00:00
_pTexture - > lastDList = video ( ) . getBuffersSwapCount ( ) ;
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
2015-02-27 12:43:12 +00:00
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
}
2015-05-06 12:36:07 +00:00
void TextureCache : : activateMSDummy ( u32 _t )
{
# ifdef GL_MULTISAMPLING_SUPPORT
glActiveTexture ( GL_TEXTURE0 + g_MSTex0Index + _t ) ;
glBindTexture ( GL_TEXTURE_2D_MULTISAMPLE , m_pMSDummy - > glName ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_NEAREST ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_NEAREST ) ;
glBindTexture ( GL_TEXTURE_2D_MULTISAMPLE , 0 ) ;
# endif
}
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 ;
CachedTexture & current = * iter ;
m_textures . splice ( m_textures . begin ( ) , m_textures , iter ) ;
2015-08-29 15:55:34 +00:00
assert ( current . width = = gSP . bgImage . width ) ;
assert ( current . height = = gSP . bgImage . height ) ;
assert ( current . format = = gSP . bgImage . format ) ;
assert ( 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-11-13 05:00:38 +00:00
pCurrent - > mirrorS = 0 ;
pCurrent - > mirrorT = 0 ;
2014-10-22 13:49:48 +00:00
pCurrent - > clampS = 0 ;
pCurrent - > clampT = 0 ;
2014-09-18 16:16:52 +00:00
pCurrent - > line = 0 ;
pCurrent - > tMem = 0 ;
2015-10-16 15:42:35 +00:00
pCurrent - > lastDList = video ( ) . getBuffersSwapCount ( ) ;
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
m_cachedBytes + = pCurrent - > textureBytes ;
current [ 0 ] = pCurrent ;
2013-04-05 06:13:26 +00:00
}
2015-04-12 12:49:40 +00:00
void TextureCache : : _clear ( )
{
current [ 0 ] = current [ 1 ] = NULL ;
for ( Textures : : const_iterator cur = m_textures . cbegin ( ) ; cur ! = m_textures . cend ( ) ; + + cur ) {
2015-10-04 21:41:25 +00:00
m_cachedBytes - = cur - > textureBytes ;
glDeleteTextures ( 1 , & cur - > glName ) ;
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 ) ) ;
}
}
}
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
}
2016-03-05 11:51:17 +00:00
if ( gDP . otherMode . textureLOD = = G_TL_LOD & & gSP . texture . level = = 0 & & _t = = 1 ) {
2014-12-19 14:55:56 +00:00
current [ 1 ] = current [ 0 ] ;
activateTexture ( _t , current [ _t ] ) ;
return ;
}
2015-08-30 22:44:01 +00:00
if ( gSP . texture . tile = = 7 & &
_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 ] ;
2014-11-13 09:51:09 +00:00
TileSizes sizes ;
_calcTileSizes ( _t , sizes , gDP . loadTile ) ;
2013-04-05 06:13:26 +00:00
2014-11-13 09:51:09 +00:00
u32 crc ;
2014-09-03 05:12:48 +00:00
{
TextureParams params ;
2014-11-13 09:51:09 +00:00
params . width = sizes . width ;
params . height = sizes . height ;
params . clampWidth = sizes . clampWidth ;
params . clampHeight = sizes . 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
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 ;
CachedTexture & current = * iter ;
m_textures . splice ( m_textures . begin ( ) , m_textures , iter ) ;
2015-08-29 15:55:34 +00:00
assert ( current . width = = sizes . width ) ;
assert ( current . height = = sizes . height ) ;
assert ( current . clampWidth = = sizes . clampWidth ) ;
assert ( current . clampHeight = = sizes . clampHeight ) ;
assert ( current . maskS = = gSP . textureTile [ _t ] - > masks ) ;
assert ( current . maskT = = gSP . textureTile [ _t ] - > maskt ) ;
assert ( current . mirrorS = = gSP . textureTile [ _t ] - > mirrors ) ;
assert ( current . mirrorT = = gSP . textureTile [ _t ] - > mirrort ) ;
assert ( current . clampS = = gSP . textureTile [ _t ] - > clamps ) ;
assert ( current . clampT = = gSP . textureTile [ _t ] - > clampt ) ;
assert ( current . format = = gSP . textureTile [ _t ] - > format ) ;
assert ( 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-12-19 10:25:44 +00:00
pCurrent - > address = gDP . loadInfo [ gSP . textureTile [ _t ] - > tmem ] . texAddress ;
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-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
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 ;
2015-10-16 15:42:35 +00:00
pCurrent - > lastDList = video ( ) . getBuffersSwapCount ( ) ;
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
m_cachedBytes + = pCurrent - > textureBytes ;
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-03-05 11:51:17 +00:00
if ( gDP . otherMode . textureLOD = = G_TL_LOD & & gSP . texture . level = = 0 )
2015-06-17 16:58:03 +00:00
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 ) ;
}