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"
2018-11-01 12:22:04 +00:00
# include "RDP.h"
2013-04-05 06:13:26 +00:00
# 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"
2021-10-24 10:11:42 +00:00
# include "GLideNHQ/TxFilterExport.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
2022-01-16 17:27:17 +00:00
# ifdef NATIVE
# define RDRAM ((u8*)0)
# endif
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
2022-02-12 08:22:09 +00:00
u32 GetNone ( u16 offset , u16 x , u16 i , u8 palette )
2013-04-05 06:13:26 +00:00
{
return 0x00000000 ;
}
2022-02-12 08:22:09 +00:00
inline u8 Get4BitPaletteColor ( u16 offset , u16 x , u16 i )
{
u8 * tmem8 = reinterpret_cast < u8 * > ( TMEM ) ;
return tmem8 [ ( ( offset < < 3 ) + ( ( x > > 1 ) ^ ( i < < 1 ) ) ) & 0xFFF ] ;
}
u32 GetCI4_RGBA8888 ( u16 offset , u16 x , u16 i , u8 palette )
{
const u8 color4B = Get4BitPaletteColor ( offset , x , i ) ;
return CI4_RGBA8888 ( ( x & 1 ) ? ( palette < < 4 ) | ( color4B & 0x0F ) : ( palette < < 4 ) | ( color4B > > 4 ) ) ;
}
u32 GetCI4_RGBA4444 ( u16 offset , u16 x , u16 i , u8 palette )
{
const u8 color4B = Get4BitPaletteColor ( offset , x , i ) ;
return CI4_RGBA4444 ( ( x & 1 ) ? ( palette < < 4 ) | ( color4B & 0x0F ) : ( palette < < 4 ) | ( color4B > > 4 ) ) ;
}
u32 GetCI4IA_RGBA4444 ( u16 offset , u16 x , u16 i , u8 palette )
{
const u8 color4B = Get4BitPaletteColor ( offset , x , i ) ;
if ( x & 1 )
return IA88_RGBA4444 ( * ( u16 * ) & TMEM [ ( 0x100 + ( palette < < 4 ) + ( color4B & 0x0F ) ) & 0x1FF ] ) ;
else
return IA88_RGBA4444 ( * ( u16 * ) & TMEM [ ( 0x100 + ( palette < < 4 ) + ( color4B > > 4 ) ) & 0x1FF ] ) ;
}
u32 GetCI4IA_RGBA8888 ( u16 offset , u16 x , u16 i , u8 palette )
{
const u8 color4B = Get4BitPaletteColor ( offset , x , i ) ;
if ( x & 1 )
return IA88_RGBA8888 ( * ( u16 * ) & TMEM [ ( 0x100 + ( palette < < 4 ) + ( color4B & 0x0F ) ) & 0x1FF ] ) ;
else
return IA88_RGBA8888 ( * ( u16 * ) & TMEM [ ( 0x100 + ( palette < < 4 ) + ( color4B > > 4 ) ) & 0x1FF ] ) ;
}
u32 GetCI4RGBA_RGBA5551 ( u16 offset , u16 x , u16 i , u8 palette )
{
const u8 color4B = Get4BitPaletteColor ( offset , x , i ) ;
if ( x & 1 )
return RGBA5551_RGBA5551 ( * ( u16 * ) & TMEM [ ( 0x100 + ( palette < < 4 ) + ( color4B & 0x0F ) ) & 0x1FF ] ) ;
else
return RGBA5551_RGBA5551 ( * ( u16 * ) & TMEM [ ( 0x100 + ( palette < < 4 ) + ( color4B > > 4 ) ) & 0x1FF ] ) ;
}
u32 GetCI4RGBA_RGBA8888 ( u16 offset , u16 x , u16 i , u8 palette )
{
const u8 color4B = Get4BitPaletteColor ( offset , x , i ) ;
if ( x & 1 )
return RGBA5551_RGBA8888 ( * ( u16 * ) & TMEM [ ( 0x100 + ( palette < < 4 ) + ( color4B & 0x0F ) ) & 0x1FF ] ) ;
else
return RGBA5551_RGBA8888 ( * ( u16 * ) & TMEM [ ( 0x100 + ( palette < < 4 ) + ( color4B > > 4 ) ) & 0x1FF ] ) ;
}
u32 GetIA31_RGBA8888 ( u16 offset , u16 x , u16 i , u8 palette )
{
const u8 color4B = Get4BitPaletteColor ( offset , x , i ) ;
return IA31_RGBA8888 ( ( x & 1 ) ? ( color4B & 0x0F ) : ( color4B > > 4 ) ) ;
}
u32 GetIA31_RGBA4444 ( u16 offset , u16 x , u16 i , u8 palette )
{
const u8 color4B = Get4BitPaletteColor ( offset , x , i ) ;
return IA31_RGBA4444 ( ( x & 1 ) ? ( color4B & 0x0F ) : ( color4B > > 4 ) ) ;
}
u32 GetI4_RGBA8888 ( u16 offset , u16 x , u16 i , u8 palette )
{
const u8 color4B = Get4BitPaletteColor ( offset , x , i ) ;
return I4_RGBA8888 ( ( x & 1 ) ? ( color4B & 0x0F ) : ( color4B > > 4 ) ) ;
}
u32 GetI4_RGBA4444 ( u16 offset , u16 x , u16 i , u8 palette )
{
const u8 color4B = Get4BitPaletteColor ( offset , x , i ) ;
return I4_RGBA4444 ( ( x & 1 ) ? ( color4B & 0x0F ) : ( color4B > > 4 ) ) ;
}
inline u8 Get8BitPaletteColor ( u16 offset , u16 x , u16 i )
{
u8 * tmem8 = reinterpret_cast < u8 * > ( TMEM ) ;
return tmem8 [ ( ( offset < < 3 ) + ( x ^ ( i < < 1 ) ) ) & 0xFFF ] ;
}
u32 GetCI8IA_RGBA4444 ( u16 offset , u16 x , u16 i , u8 palette )
{
const u8 color = Get8BitPaletteColor ( offset , x , i ) ;
return IA88_RGBA4444 ( * ( u16 * ) & TMEM [ ( 0x100 + color ) & 0x1FF ] ) ;
}
u32 GetCI8IA_RGBA8888 ( u16 offset , u16 x , u16 i , u8 palette )
{
const u8 color = Get8BitPaletteColor ( offset , x , i ) ;
return IA88_RGBA8888 ( * ( u16 * ) & TMEM [ ( 0x100 + color ) & 0x1FF ] ) ;
}
u32 GetCI8RGBA_RGBA5551 ( u16 offset , u16 x , u16 i , u8 palette )
{
const u8 color = Get8BitPaletteColor ( offset , x , i ) ;
return RGBA5551_RGBA5551 ( * ( u16 * ) & TMEM [ ( 0x100 + color ) & 0x1FF ] ) ;
}
u32 GetCI8RGBA_RGBA8888 ( u16 offset , u16 x , u16 i , u8 palette )
{
const u8 color = Get8BitPaletteColor ( offset , x , i ) ;
return RGBA5551_RGBA8888 ( * ( u16 * ) & TMEM [ ( 0x100 + color ) & 0x1FF ] ) ;
}
u32 GetIA44_RGBA8888 ( u16 offset , u16 x , u16 i , u8 palette )
{
const u8 color = Get8BitPaletteColor ( offset , x , i ) ;
return IA44_RGBA8888 ( color ) ;
}
u32 GetIA44_RGBA4444 ( u16 offset , u16 x , u16 i , u8 palette )
{
const u8 color = Get8BitPaletteColor ( offset , x , i ) ;
return IA44_RGBA4444 ( color ) ;
}
u32 GetI8_RGBA8888 ( u16 offset , u16 x , u16 i , u8 palette )
{
const u8 color = Get8BitPaletteColor ( offset , x , i ) ;
return I8_RGBA8888 ( color ) ;
}
u32 GetI8_RGBA4444 ( u16 offset , u16 x , u16 i , u8 palette )
{
const u8 color = Get8BitPaletteColor ( offset , x , i ) ;
return I8_RGBA4444 ( color ) ;
}
inline u16 Get16BitColor ( u16 offset , u16 x , u16 i )
{
u16 * tmem16 = reinterpret_cast < u16 * > ( TMEM ) ;
return tmem16 [ ( ( offset < < 2 ) + ( x ^ i ) ) & 0x7FF ] ;
}
u32 GetI16_RGBA8888 ( u16 offset , u16 x , u16 i , u8 palette )
{
const u16 tex = Get16BitColor ( offset , x , i ) ;
u32 r = tex > > 8 ;
u32 g = tex & 0xFF ;
u32 b = r ;
u32 a = g ;
return ( a < < 24 ) | ( b < < 16 ) | ( g < < 8 ) | r ;
}
u32 GetI16_RGBA4444 ( u16 offset , u16 x , u16 i , u8 palette )
{
const u16 tex = Get16BitColor ( offset , x , i ) ;
u16 r = tex > > 12 ;
u16 g = tex & 0x0F ;
u16 b = r ;
u16 a = g ;
return ( a < < 12 ) | ( b < < 8 ) | ( g < < 4 ) | r ;
}
u32 GetCI16IA_RGBA8888 ( u16 offset , u16 x , u16 i , u8 palette )
{
const u16 tex = Get16BitColor ( offset , x , i ) ;
const u16 col = ( * ( u16 * ) & TMEM [ 0x100 + ( tex & 0xFF ) ] ) ;
const u16 c = col > > 8 ;
const u16 a = col & 0xFF ;
return ( a < < 24 ) | ( c < < 16 ) | ( c < < 8 ) | c ;
}
u32 GetCI16IA_RGBA4444 ( u16 offset , u16 x , u16 i , u8 palette )
{
const u16 tex = Get16BitColor ( offset , x , i ) ;
const u16 col = ( * ( u16 * ) & TMEM [ 0x100 + ( tex & 0xFF ) ] ) ;
const u16 c = col > > 12 ;
const u16 a = col & 0x0F ;
return ( a < < 12 ) | ( c < < 8 ) | ( c < < 4 ) | c ;
}
u32 GetCI16RGBA_RGBA8888 ( u16 offset , u16 x , u16 i , u8 palette )
{
const u16 tex = Get16BitColor ( offset , x , i ) & 0xFF ;
return RGBA5551_RGBA8888 ( ( ( u16 * ) & TMEM [ 0x100 ] ) [ tex < < 2 ] ) ;
}
u32 GetCI16RGBA_RGBA5551 ( u16 offset , u16 x , u16 i , u8 palette )
{
const u16 tex = Get16BitColor ( offset , x , i ) & 0xFF ;
return RGBA5551_RGBA5551 ( ( ( u16 * ) & TMEM [ 0x100 ] ) [ tex < < 2 ] ) ;
}
u32 GetRGBA5551_RGBA8888 ( u16 offset , u16 x , u16 i , u8 palette )
{
const u16 tex = Get16BitColor ( offset , x , i ) ;
return RGBA5551_RGBA8888 ( tex ) ;
}
u32 GetRGBA5551_RGBA5551 ( u16 offset , u16 x , u16 i , u8 palette )
{
const u16 tex = Get16BitColor ( offset , x , i ) ;
return RGBA5551_RGBA5551 ( tex ) ;
}
u32 GetIA88_RGBA8888 ( u16 offset , u16 x , u16 i , u8 palette )
{
const u16 tex = Get16BitColor ( offset , x , i ) ;
return IA88_RGBA8888 ( tex ) ;
}
u32 GetIA88_RGBA4444 ( u16 offset , u16 x , u16 i , u8 palette )
{
const u16 tex = Get16BitColor ( offset , x , i ) ;
return IA88_RGBA4444 ( tex ) ;
}
inline u32 Get32BitColor ( u16 offset , u16 x , u16 i )
{
u32 * tmem32 = reinterpret_cast < u32 * > ( TMEM ) ;
2022-03-29 21:42:02 +00:00
return tmem32 [ ( ( offset < < 1 ) + ( x ^ i ) ) & LOAD_BLOCK32_MASK ] ;
2022-02-12 08:22:09 +00:00
}
u32 GetRGBA8888_RGBA8888 ( u16 offset , u16 x , u16 i , u8 palette )
{
return Get32BitColor ( offset , x , i ) ;
}
u32 GetRGBA8888_RGBA4444 ( u16 offset , u16 x , u16 i , u8 palette )
{
const u32 tex = Get32BitColor ( offset , x , i ) ;
return RGBA8888_RGBA4444 ( tex ) ;
}
inline u32 YUV_RGBA8888 ( u8 y , u8 u , u8 v )
{
return ( 0xff < < 24 ) | ( y < < 16 ) | ( v < < 8 ) | u ;
}
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 ;
}
u32 GetNoneBG ( u64 * src , u16 x , u16 i , u8 palette )
{
return 0x00000000 ;
}
u32 GetCI4_RGBA8888_BG ( u64 * src , u16 x , u16 i , u8 palette )
2013-04-05 06:13:26 +00:00
{
2019-03-06 11:36:40 +00:00
u8 color4B = ( ( u8 * ) src ) [ ( x > > 1 ) ^ ( i < < 1 ) ] ;
2013-04-05 06:13:26 +00:00
2019-03-23 05:37:38 +00:00
return CI4_RGBA8888 ( ( x & 1 ) ? ( palette < < 4 ) | ( color4B & 0x0F ) : ( palette < < 4 ) | ( color4B > > 4 ) ) ;
2019-03-06 11:36:40 +00:00
}
2022-02-12 08:22:09 +00:00
u32 GetCI4_RGBA4444_BG ( u64 * src , u16 x , u16 i , u8 palette )
2019-03-06 11:36:40 +00:00
{
u8 color4B = ( ( u8 * ) src ) [ ( x > > 1 ) ^ ( i < < 1 ) ] ;
2019-03-23 05:37:38 +00:00
return CI4_RGBA4444 ( ( x & 1 ) ? ( palette < < 4 ) | ( color4B & 0x0F ) : ( palette < < 4 ) | ( color4B > > 4 ) ) ;
2019-03-06 11:36:40 +00:00
}
2022-02-12 08:22:09 +00:00
u32 GetCI4IA_RGBA4444_BG ( u64 * src , u16 x , u16 i , u8 palette )
2019-03-06 11:36:40 +00:00
{
2022-02-12 08:22:09 +00:00
u8 color4B = ( ( u8 * ) src ) [ ( x > > 1 ) ^ ( i < < 1 ) ] ;
2013-04-05 06:13:26 +00:00
if ( x & 1 )
2022-02-12 08:22:09 +00:00
return IA88_RGBA4444 ( * ( u16 * ) & TMEM [ 256 + ( palette < < 4 ) + ( color4B & 0x0F ) ] ) ;
2013-04-05 06:13:26 +00:00
else
2022-02-12 08:22:09 +00:00
return IA88_RGBA4444 ( * ( u16 * ) & TMEM [ 256 + ( palette < < 4 ) + ( color4B > > 4 ) ] ) ;
2013-04-05 06:13:26 +00:00
}
2022-02-12 08:22:09 +00:00
u32 GetCI4IA_RGBA8888_BG ( u64 * src , u16 x , u16 i , u8 palette )
2013-04-05 06:13:26 +00:00
{
2022-02-12 08:22:09 +00:00
u8 color4B = ( ( u8 * ) src ) [ ( x > > 1 ) ^ ( i < < 1 ) ] ;
2013-04-05 06:13:26 +00:00
if ( x & 1 )
2022-02-12 08:22:09 +00:00
return IA88_RGBA8888 ( * ( u16 * ) & TMEM [ 256 + ( palette < < 4 ) + ( color4B & 0x0F ) ] ) ;
2013-04-05 06:13:26 +00:00
else
2022-02-12 08:22:09 +00:00
return IA88_RGBA8888 ( * ( u16 * ) & TMEM [ 256 + ( palette < < 4 ) + ( color4B > > 4 ) ] ) ;
2013-04-05 06:13:26 +00:00
}
2022-02-12 08:22:09 +00:00
u32 GetCI4RGBA_RGBA5551_BG ( u64 * src , u16 x , u16 i , u8 palette )
2013-04-05 06:13:26 +00:00
{
2022-02-12 08:22:09 +00:00
u8 color4B = ( ( u8 * ) src ) [ ( x > > 1 ) ^ ( i < < 1 ) ] ;
2013-04-05 06:13:26 +00:00
if ( x & 1 )
2022-02-12 08:22:09 +00:00
return RGBA5551_RGBA5551 ( * ( u16 * ) & TMEM [ 256 + ( palette < < 4 ) + ( color4B & 0x0F ) ] ) ;
2013-04-05 06:13:26 +00:00
else
2022-02-12 08:22:09 +00:00
return RGBA5551_RGBA5551 ( * ( u16 * ) & TMEM [ 256 + ( palette < < 4 ) + ( color4B > > 4 ) ] ) ;
2013-04-05 06:13:26 +00:00
}
2022-02-12 08:22:09 +00:00
u32 GetCI4RGBA_RGBA8888_BG ( u64 * src , u16 x , u16 i , u8 palette )
2013-04-05 06:13:26 +00:00
{
2022-02-12 08:22:09 +00:00
u8 color4B = ( ( u8 * ) src ) [ ( x > > 1 ) ^ ( i < < 1 ) ] ;
2013-04-05 06:13:26 +00:00
if ( x & 1 )
2022-02-12 08:22:09 +00:00
return RGBA5551_RGBA8888 ( * ( u16 * ) & TMEM [ 256 + ( palette < < 4 ) + ( color4B & 0x0F ) ] ) ;
2013-04-05 06:13:26 +00:00
else
2022-02-12 08:22:09 +00:00
return RGBA5551_RGBA8888 ( * ( u16 * ) & TMEM [ 256 + ( palette < < 4 ) + ( color4B > > 4 ) ] ) ;
2013-04-05 06:13:26 +00:00
}
2022-02-12 08:22:09 +00:00
u32 GetIA31_RGBA8888_BG ( u64 * src , u16 x , u16 i , u8 palette )
2013-04-05 06:13:26 +00:00
{
2022-02-12 08:22:09 +00:00
u8 color4B = ( ( u8 * ) src ) [ ( x > > 1 ) ^ ( i < < 1 ) ] ;
2013-04-05 06:13:26 +00:00
2022-02-12 08:22:09 +00:00
return IA31_RGBA8888 ( ( x & 1 ) ? ( color4B & 0x0F ) : ( color4B > > 4 ) ) ;
2013-04-05 06:13:26 +00:00
}
2022-02-12 08:22:09 +00:00
u32 GetIA31_RGBA4444_BG ( u64 * src , u16 x , u16 i , u8 palette )
2013-04-05 06:13:26 +00:00
{
2022-02-12 08:22:09 +00:00
u8 color4B = ( ( u8 * ) src ) [ ( x > > 1 ) ^ ( i < < 1 ) ] ;
2013-04-05 06:13:26 +00:00
2022-02-12 08:22:09 +00:00
return IA31_RGBA4444 ( ( x & 1 ) ? ( color4B & 0x0F ) : ( color4B > > 4 ) ) ;
2013-04-05 06:13:26 +00:00
}
2022-02-12 08:22:09 +00:00
u32 GetI4_RGBA8888_BG ( u64 * src , u16 x , u16 i , u8 palette )
2013-04-05 06:13:26 +00:00
{
2022-02-12 08:22:09 +00:00
u8 color4B = ( ( u8 * ) src ) [ ( x > > 1 ) ^ ( i < < 1 ) ] ;
2013-04-05 06:13:26 +00:00
2022-02-12 08:22:09 +00:00
return I4_RGBA8888 ( ( x & 1 ) ? ( color4B & 0x0F ) : ( color4B > > 4 ) ) ;
2013-04-05 06:13:26 +00:00
}
2022-02-12 08:22:09 +00:00
u32 GetI4_RGBA4444_BG ( u64 * src , u16 x , u16 i , u8 palette )
2013-04-05 06:13:26 +00:00
{
2022-02-12 08:22:09 +00:00
u8 color4B = ( ( u8 * ) src ) [ ( x > > 1 ) ^ ( i < < 1 ) ] ;
2013-04-05 06:13:26 +00:00
2022-02-12 08:22:09 +00:00
return I4_RGBA4444 ( ( x & 1 ) ? ( color4B & 0x0F ) : ( color4B > > 4 ) ) ;
2013-04-05 06:13:26 +00:00
}
2022-02-12 08:22:09 +00:00
u32 GetCI8IA_RGBA4444_BG ( u64 * src , u16 x , u16 i , u8 palette )
2013-04-05 06:13:26 +00:00
{
2022-02-12 08:22:09 +00:00
return IA88_RGBA4444 ( * ( u16 * ) & TMEM [ 256 + ( ( u8 * ) src ) [ x ^ ( i < < 1 ) ] ] ) ;
2013-04-05 06:13:26 +00:00
}
2022-02-12 08:22:09 +00:00
u32 GetCI8IA_RGBA8888_BG ( u64 * src , u16 x , u16 i , u8 palette )
2013-04-05 06:13:26 +00:00
{
2022-02-12 08:22:09 +00:00
return IA88_RGBA8888 ( * ( u16 * ) & TMEM [ 256 + ( ( u8 * ) src ) [ x ^ ( i < < 1 ) ] ] ) ;
2013-04-05 06:13:26 +00:00
}
2022-02-12 08:22:09 +00:00
u32 GetCI8RGBA_RGBA5551_BG ( u64 * src , u16 x , u16 i , u8 palette )
2013-04-05 06:13:26 +00:00
{
2022-02-12 08:22:09 +00:00
return RGBA5551_RGBA5551 ( * ( u16 * ) & TMEM [ 256 + ( ( u8 * ) src ) [ x ^ ( i < < 1 ) ] ] ) ;
2013-04-05 06:13:26 +00:00
}
2022-02-12 08:22:09 +00:00
u32 GetCI8RGBA_RGBA8888_BG ( u64 * src , u16 x , u16 i , u8 palette )
2013-04-05 06:13:26 +00:00
{
2022-02-12 08:22:09 +00:00
return RGBA5551_RGBA8888 ( * ( u16 * ) & TMEM [ 256 + ( ( u8 * ) src ) [ x ^ ( i < < 1 ) ] ] ) ;
2013-04-05 06:13:26 +00:00
}
2022-02-12 08:22:09 +00:00
u32 GetIA44_RGBA8888_BG ( u64 * src , u16 x , u16 i , u8 palette )
2013-04-05 06:13:26 +00:00
{
2022-02-12 08:22:09 +00:00
return IA44_RGBA8888 ( ( ( u8 * ) src ) [ x ^ ( i < < 1 ) ] ) ;
2013-04-05 06:13:26 +00:00
}
2022-02-12 08:22:09 +00:00
u32 GetIA44_RGBA4444_BG ( u64 * src , u16 x , u16 i , u8 palette )
2013-04-05 06:13:26 +00:00
{
2022-02-12 08:22:09 +00:00
return IA44_RGBA4444 ( ( ( u8 * ) src ) [ x ^ ( i < < 1 ) ] ) ;
2013-04-05 06:13:26 +00:00
}
2022-02-12 08:22:09 +00:00
u32 GetI8_RGBA8888_BG ( u64 * src , u16 x , u16 i , u8 palette )
2013-04-05 06:13:26 +00:00
{
2022-02-12 08:22:09 +00:00
return I8_RGBA8888 ( ( ( u8 * ) src ) [ x ^ ( i < < 1 ) ] ) ;
2013-04-05 06:13:26 +00:00
}
2022-02-12 08:22:09 +00:00
u32 GetI8_RGBA4444_BG ( u64 * src , u16 x , u16 i , u8 palette )
2013-04-05 06:13:26 +00:00
{
2022-02-12 08:22:09 +00:00
return I8_RGBA4444 ( ( ( u8 * ) src ) [ x ^ ( i < < 1 ) ] ) ;
2013-04-05 06:13:26 +00:00
}
2022-02-12 08:22:09 +00:00
u32 GetI16_RGBA8888_BG ( u64 * src , u16 x , u16 i , u8 palette )
2021-10-30 17:04:33 +00:00
{
const u16 tex = ( ( u16 * ) src ) [ x ^ i ] ;
u32 r = tex > > 8 ;
u32 g = tex & 0xFF ;
u32 b = r ;
u32 a = g ;
return ( a < < 24 ) | ( b < < 16 ) | ( g < < 8 ) | r ;
}
2022-02-12 08:22:09 +00:00
u32 GetI16_RGBA4444_BG ( u64 * src , u16 x , u16 i , u8 palette )
2021-10-30 17:04:33 +00:00
{
const u16 tex = ( ( u16 * ) src ) [ x ^ i ] ;
u16 r = tex > > 12 ;
u16 g = tex & 0x0F ;
u16 b = r ;
u16 a = g ;
return ( a < < 12 ) | ( b < < 8 ) | ( g < < 4 ) | r ;
}
2022-02-12 08:22:09 +00:00
u32 GetCI16IA_RGBA8888_BG ( u64 * src , u16 x , u16 i , u8 palette )
2014-12-11 07:48:55 +00:00
{
const u16 tex = ( ( u16 * ) src ) [ x ^ i ] ;
2020-05-10 13:14:53 +00:00
const u16 col = ( * ( u16 * ) & TMEM [ 256 + ( tex & 0xFF ) ] ) ;
2014-12-11 07:48:55 +00:00
const u16 c = col > > 8 ;
const u16 a = col & 0xFF ;
return ( a < < 24 ) | ( c < < 16 ) | ( c < < 8 ) | c ;
}
2022-02-12 08:22:09 +00:00
u32 GetCI16IA_RGBA4444_BG ( u64 * src , u16 x , u16 i , u8 palette )
2014-12-11 07:48:55 +00:00
{
const u16 tex = ( ( u16 * ) src ) [ x ^ i ] ;
2020-05-10 13:14:53 +00:00
const u16 col = ( * ( u16 * ) & TMEM [ 256 + ( tex & 0xFF ) ] ) ;
2014-12-11 07:48:55 +00:00
const u16 c = col > > 12 ;
const u16 a = col & 0x0F ;
return ( a < < 12 ) | ( c < < 8 ) | ( c < < 4 ) | c ;
}
2022-02-12 08:22:09 +00:00
u32 GetCI16RGBA_RGBA8888_BG ( u64 * src , u16 x , u16 i , u8 palette )
2014-12-11 07:48:55 +00:00
{
2022-02-12 08:22:09 +00:00
const u16 tex = ( ( ( u16 * ) src ) [ x ^ i ] ) & 0xFF ;
2015-06-04 18:07:51 +00:00
return RGBA5551_RGBA8888 ( ( ( u16 * ) & TMEM [ 256 ] ) [ tex < < 2 ] ) ;
2014-12-11 07:48:55 +00:00
}
2022-02-12 08:22:09 +00:00
u32 GetCI16RGBA_RGBA5551_BG ( u64 * src , u16 x , u16 i , u8 palette )
2014-12-11 07:48:55 +00:00
{
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
}
2022-02-12 08:22:09 +00:00
u32 GetRGBA5551_RGBA8888_BG ( 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
}
2022-02-12 08:22:09 +00:00
u32 GetRGBA5551_RGBA5551_BG ( 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_RGBA5551 ( tex ) ;
2013-04-05 06:13:26 +00:00
}
2022-02-12 08:22:09 +00:00
u32 GetIA88_RGBA8888_BG ( u64 * src , u16 x , u16 i , u8 palette )
2013-04-05 06:13:26 +00:00
{
return IA88_RGBA8888 ( ( ( u16 * ) src ) [ x ^ i ] ) ;
}
2022-02-12 08:22:09 +00:00
u32 GetIA88_RGBA4444_BG ( u64 * src , u16 x , u16 i , u8 palette )
2013-04-05 06:13:26 +00:00
{
return IA88_RGBA4444 ( ( ( u16 * ) src ) [ x ^ i ] ) ;
}
2022-02-12 08:22:09 +00:00
u32 GetRGBA8888_RGBA8888_BG ( u64 * src , u16 x , u16 i , u8 palette )
2013-04-05 06:13:26 +00:00
{
return ( ( u32 * ) src ) [ x ^ i ] ;
}
2022-02-12 08:22:09 +00:00
u32 GetRGBA8888_RGBA4444_BG ( u64 * src , u16 x , u16 i , u8 palette )
2013-04-05 06:13:26 +00:00
{
return RGBA8888_RGBA4444 ( ( ( u32 * ) src ) [ x ^ i ] ) ;
}
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 ;
2022-02-12 08:22:09 +00:00
GetTexelFuncBG Get16BG ;
2017-01-28 09:52:09 +00:00
DatatypeParam glType16 ;
InternalColorFormatParam glInternalFormat16 ;
GetTexelFunc Get32 ;
2022-02-12 08:22:09 +00:00
GetTexelFuncBG Get32BG ;
2017-01-28 09:52:09 +00:00
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
2022-02-12 08:22:09 +00:00
{ GetI4_RGBA4444 , GetI4_RGBA4444_BG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetI4_RGBA8888 , GetI4_RGBA8888_BG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 4 , 8192 } , // RGBA as I
{ GetNone , GetNoneBG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , GetNoneBG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 4 , 8192 } , // YUV
{ GetCI4_RGBA4444 , GetCI4_RGBA4444_BG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetCI4_RGBA8888 , GetCI4_RGBA8888_BG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 4 , 8192 } , // CI without palette
{ GetIA31_RGBA4444 , GetIA31_RGBA4444_BG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetIA31_RGBA8888 , GetIA31_RGBA8888_BG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 4 , 8192 } , // IA
{ GetI4_RGBA4444 , GetI4_RGBA4444_BG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetI4_RGBA8888 , GetI4_RGBA8888_BG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 4 , 8192 } , // I
2017-02-22 05:19:06 +00:00
} ,
{ // 8-bit
2022-02-12 08:22:09 +00:00
{ GetI8_RGBA4444 , GetI8_RGBA4444_BG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetI8_RGBA8888 , GetI8_RGBA8888_BG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 3 , 4096 } , // RGBA as I
{ GetNone , GetNoneBG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , GetNoneBG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 0 , 4096 } , // YUV
{ GetI8_RGBA4444 , GetI8_RGBA4444_BG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetI8_RGBA8888 , GetI8_RGBA8888_BG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 3 , 4096 } , // CI without palette
{ GetIA44_RGBA4444 , GetIA44_RGBA4444_BG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetIA44_RGBA8888 , GetIA44_RGBA8888_BG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 3 , 4096 } , // IA
{ GetI8_RGBA4444 , GetI8_RGBA4444_BG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetI8_RGBA8888 , GetI8_RGBA8888_BG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 3 , 4096 } , // I
2017-02-22 05:19:06 +00:00
} ,
{ // 16-bit
2022-02-12 08:22:09 +00:00
{ GetRGBA5551_RGBA5551 , GetRGBA5551_RGBA5551_BG , datatype : : UNSIGNED_SHORT_5_5_5_1 , internalcolorFormat : : RGB5_A1 , GetRGBA5551_RGBA8888 , GetRGBA5551_RGBA8888_BG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGB5_A1 , 2 , 2048 } , // RGBA
{ GetNone , GetNoneBG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , GetNoneBG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 2 , 2048 } , // YUV
{ GetIA88_RGBA4444 , GetIA88_RGBA4444_BG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetIA88_RGBA8888 , GetIA88_RGBA8888_BG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 2 , 2048 } , // CI as IA
{ GetIA88_RGBA4444 , GetIA88_RGBA4444_BG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetIA88_RGBA8888 , GetIA88_RGBA8888_BG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 2 , 2048 } , // IA
{ GetI16_RGBA4444 , GetI16_RGBA4444_BG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetI16_RGBA8888 , GetI16_RGBA8888_BG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 0 , 2048 } , // I
2017-02-22 05:19:06 +00:00
} ,
{ // 32-bit
2022-02-12 08:22:09 +00:00
{ GetRGBA8888_RGBA4444 , GetRGBA8888_RGBA4444_BG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetRGBA8888_RGBA8888 , GetRGBA8888_RGBA8888_BG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 2 , 1024 } , // RGBA
{ GetNone , GetNoneBG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , GetNoneBG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 0 , 1024 } , // YUV
{ GetNone , GetNoneBG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , GetNoneBG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 0 , 1024 } , // CI
{ GetNone , GetNoneBG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , GetNoneBG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 0 , 1024 } , // IA
{ GetNone , GetNoneBG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , GetNoneBG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 0 , 1024 } , // I
2017-02-22 05:19:06 +00:00
}
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
2022-02-12 08:22:09 +00:00
{ GetCI4RGBA_RGBA5551 , GetCI4RGBA_RGBA5551_BG , datatype : : UNSIGNED_SHORT_5_5_5_1 , internalcolorFormat : : RGB5_A1 , GetCI4RGBA_RGBA8888 , GetCI4RGBA_RGBA8888_BG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGB5_A1 , 4 , 4096 } , // CI (Banjo-Kazooie uses this, doesn't make sense, but it works...)
{ GetNone , GetNoneBG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , GetNoneBG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 4 , 8192 } , // YUV
{ GetCI4RGBA_RGBA5551 , GetCI4RGBA_RGBA5551_BG , datatype : : UNSIGNED_SHORT_5_5_5_1 , internalcolorFormat : : RGB5_A1 , GetCI4RGBA_RGBA8888 , GetCI4RGBA_RGBA8888_BG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGB5_A1 , 4 , 4096 } , // CI
{ GetCI4RGBA_RGBA5551 , GetCI4RGBA_RGBA5551_BG , datatype : : UNSIGNED_SHORT_5_5_5_1 , internalcolorFormat : : RGB5_A1 , GetCI4RGBA_RGBA8888 , GetCI4RGBA_RGBA8888_BG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGB5_A1 , 4 , 4096 } , // IA as CI
{ GetCI4RGBA_RGBA5551 , GetCI4RGBA_RGBA5551_BG , datatype : : UNSIGNED_SHORT_5_5_5_1 , internalcolorFormat : : RGB5_A1 , GetCI4RGBA_RGBA8888 , GetCI4RGBA_RGBA8888_BG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGB5_A1 , 4 , 4096 } , // I as CI
2017-02-22 05:19:06 +00:00
} ,
{ // 8-bit
2022-02-12 08:22:09 +00:00
{ GetCI8RGBA_RGBA5551 , GetCI8RGBA_RGBA5551_BG , datatype : : UNSIGNED_SHORT_5_5_5_1 , internalcolorFormat : : RGB5_A1 , GetCI8RGBA_RGBA8888 , GetCI8RGBA_RGBA8888_BG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGB5_A1 , 3 , 2048 } , // RGBA
{ GetNone , GetNoneBG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , GetNoneBG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 0 , 4096 } , // YUV
{ GetCI8RGBA_RGBA5551 , GetCI8RGBA_RGBA5551_BG , datatype : : UNSIGNED_SHORT_5_5_5_1 , internalcolorFormat : : RGB5_A1 , GetCI8RGBA_RGBA8888 , GetCI8RGBA_RGBA8888_BG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGB5_A1 , 3 , 2048 } , // CI
{ GetCI8RGBA_RGBA5551 , GetCI8RGBA_RGBA5551_BG , datatype : : UNSIGNED_SHORT_5_5_5_1 , internalcolorFormat : : RGB5_A1 , GetCI8RGBA_RGBA8888 , GetCI8RGBA_RGBA8888_BG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGB5_A1 , 3 , 2048 } , // IA as CI
{ GetCI8RGBA_RGBA5551 , GetCI8RGBA_RGBA5551_BG , datatype : : UNSIGNED_SHORT_5_5_5_1 , internalcolorFormat : : RGB5_A1 , GetCI8RGBA_RGBA8888 , GetCI8RGBA_RGBA8888_BG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGB5_A1 , 3 , 2048 } , // I as CI
2017-02-22 05:19:06 +00:00
} ,
{ // 16-bit
2022-02-12 08:22:09 +00:00
{ GetCI16RGBA_RGBA5551 , GetCI16RGBA_RGBA5551_BG , datatype : : UNSIGNED_SHORT_5_5_5_1 , internalcolorFormat : : RGB5_A1 , GetRGBA5551_RGBA8888 , GetRGBA5551_RGBA8888_BG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGB5_A1 , 2 , 2048 } , // RGBA
{ GetNone , GetNoneBG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , GetNoneBG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 2 , 2048 } , // YUV
{ GetNone , GetNoneBG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , GetNoneBG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 0 , 2048 } , // CI
{ GetCI16RGBA_RGBA5551 , GetCI16RGBA_RGBA5551_BG , datatype : : UNSIGNED_SHORT_5_5_5_1 , internalcolorFormat : : RGB5_A1 , GetCI16RGBA_RGBA8888 , GetCI16RGBA_RGBA8888_BG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGB5_A1 , 2 , 2048 } , // IA as CI
{ GetNone , GetNoneBG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , GetNoneBG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 0 , 2048 } , // I
2017-02-22 05:19:06 +00:00
} ,
{ // 32-bit
2022-02-12 08:22:09 +00:00
{ GetRGBA8888_RGBA4444 , GetRGBA8888_RGBA4444_BG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetRGBA8888_RGBA8888 , GetRGBA8888_RGBA8888_BG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 2 , 1024 } , // RGBA
{ GetNone , GetNoneBG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , GetNoneBG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 0 , 1024 } , // YUV
{ GetNone , GetNoneBG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , GetNoneBG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 0 , 1024 } , // CI
{ GetNone , GetNoneBG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , GetNoneBG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 0 , 1024 } , // IA
{ GetNone , GetNoneBG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , GetNoneBG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 0 , 1024 } , // I
2017-02-22 05:19:06 +00:00
}
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
2022-02-12 08:22:09 +00:00
{ GetCI4RGBA_RGBA5551 , GetCI4RGBA_RGBA5551_BG , datatype : : UNSIGNED_SHORT_5_5_5_1 , internalcolorFormat : : RGB5_A1 , GetCI4RGBA_RGBA8888 , GetCI4RGBA_RGBA8888_BG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGB5_A1 , 4 , 4096 } , // CI (Banjo-Kazooie uses this, doesn't make sense, but it works...)
{ GetNone , GetNoneBG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , GetNoneBG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 4 , 8192 } , // YUV
{ GetCI4RGBA_RGBA5551 , GetCI4RGBA_RGBA5551_BG , datatype : : UNSIGNED_SHORT_5_5_5_1 , internalcolorFormat : : RGB5_A1 , GetCI4RGBA_RGBA8888 , GetCI4RGBA_RGBA8888_BG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGB5_A1 , 4 , 4096 } , // CI
{ GetCI4RGBA_RGBA5551 , GetCI4RGBA_RGBA5551_BG , datatype : : UNSIGNED_SHORT_5_5_5_1 , internalcolorFormat : : RGB5_A1 , GetCI4RGBA_RGBA8888 , GetCI4RGBA_RGBA8888_BG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGB5_A1 , 4 , 4096 } , // IA as CI
{ GetCI4RGBA_RGBA5551 , GetCI4RGBA_RGBA5551_BG , datatype : : UNSIGNED_SHORT_5_5_5_1 , internalcolorFormat : : RGB5_A1 , GetCI4RGBA_RGBA8888 , GetCI4RGBA_RGBA8888_BG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGB5_A1 , 4 , 4096 } , // I as CI
2017-02-22 05:19:06 +00:00
} ,
{ // 8-bit
2022-02-12 08:22:09 +00:00
{ GetCI8RGBA_RGBA5551 , GetCI8RGBA_RGBA5551_BG , datatype : : UNSIGNED_SHORT_5_5_5_1 , internalcolorFormat : : RGB5_A1 , GetCI8RGBA_RGBA8888 , GetCI8RGBA_RGBA8888_BG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGB5_A1 , 3 , 2048 } , // RGBA
{ GetNone , GetNoneBG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , GetNoneBG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 0 , 4096 } , // YUV
{ GetCI8RGBA_RGBA5551 , GetCI8RGBA_RGBA5551_BG , datatype : : UNSIGNED_SHORT_5_5_5_1 , internalcolorFormat : : RGB5_A1 , GetCI8RGBA_RGBA8888 , GetCI8RGBA_RGBA8888_BG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGB5_A1 , 3 , 2048 } , // CI
{ GetCI8RGBA_RGBA5551 , GetCI8RGBA_RGBA5551_BG , datatype : : UNSIGNED_SHORT_5_5_5_1 , internalcolorFormat : : RGB5_A1 , GetCI8RGBA_RGBA8888 , GetCI8RGBA_RGBA8888_BG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGB5_A1 , 3 , 2048 } , // IA as CI
{ GetCI8RGBA_RGBA5551 , GetCI8RGBA_RGBA5551_BG , datatype : : UNSIGNED_SHORT_5_5_5_1 , internalcolorFormat : : RGB5_A1 , GetCI8RGBA_RGBA8888 , GetCI8RGBA_RGBA8888_BG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGB5_A1 , 3 , 2048 } , // I as CI
2017-02-22 05:19:06 +00:00
} ,
{ // 16-bit
2022-02-12 08:22:09 +00:00
{ GetCI16RGBA_RGBA5551 , GetCI16RGBA_RGBA5551_BG , datatype : : UNSIGNED_SHORT_5_5_5_1 , internalcolorFormat : : RGB5_A1 , GetRGBA5551_RGBA8888 , GetRGBA5551_RGBA8888_BG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGB5_A1 , 2 , 2048 } , // RGBA
{ GetNone , GetNoneBG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , GetNoneBG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 2 , 2048 } , // YUV
{ GetNone , GetNoneBG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , GetNoneBG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 0 , 2048 } , // CI
{ GetCI16RGBA_RGBA5551 , GetCI16RGBA_RGBA5551_BG , datatype : : UNSIGNED_SHORT_5_5_5_1 , internalcolorFormat : : RGB5_A1 , GetCI16RGBA_RGBA8888 , GetCI16RGBA_RGBA8888_BG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGB5_A1 , 2 , 2048 } , // IA as CI
{ GetNone , GetNoneBG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , GetNoneBG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 0 , 2048 } , // I
2017-02-22 05:19:06 +00:00
} ,
{ // 32-bit
2022-02-12 08:22:09 +00:00
{ GetRGBA8888_RGBA4444 , GetRGBA8888_RGBA4444_BG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetRGBA8888_RGBA8888 , GetRGBA8888_RGBA8888_BG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 2 , 1024 } , // RGBA
{ GetNone , GetNoneBG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , GetNoneBG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 0 , 1024 } , // YUV
{ GetNone , GetNoneBG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , GetNoneBG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 0 , 1024 } , // CI
{ GetNone , GetNoneBG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , GetNoneBG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 0 , 1024 } , // IA
{ GetNone , GetNoneBG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , GetNoneBG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA4 , 0 , 1024 } , // I
2017-02-22 05:19:06 +00:00
}
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
2022-02-12 08:22:09 +00:00
{ GetCI4IA_RGBA4444 , GetCI4IA_RGBA4444_BG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetCI4IA_RGBA8888 , GetCI4IA_RGBA8888_BG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 4 , 4096 } , // IA
{ GetNone , GetNoneBG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , GetNoneBG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 4 , 8192 } , // YUV
{ GetCI4IA_RGBA4444 , GetCI4IA_RGBA4444_BG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetCI4IA_RGBA8888 , GetCI4IA_RGBA8888_BG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 4 , 4096 } , // CI
{ GetCI4IA_RGBA4444 , GetCI4IA_RGBA4444_BG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetCI4IA_RGBA8888 , GetCI4IA_RGBA8888_BG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 4 , 4096 } , // IA
{ GetCI4IA_RGBA4444 , GetCI4IA_RGBA4444_BG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetCI4IA_RGBA8888 , GetCI4IA_RGBA8888_BG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 4 , 4096 } , // I
2017-02-22 05:19:06 +00:00
} ,
{ // 8-bit
2022-02-12 08:22:09 +00:00
{ GetCI8IA_RGBA4444 , GetCI8IA_RGBA4444_BG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetCI8IA_RGBA8888 , GetCI8IA_RGBA8888_BG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 3 , 2048 } , // RGBA
{ GetNone , GetNoneBG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , GetNoneBG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 0 , 4096 } , // YUV
{ GetCI8IA_RGBA4444 , GetCI8IA_RGBA4444_BG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetCI8IA_RGBA8888 , GetCI8IA_RGBA8888_BG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 3 , 2048 } , // CI
{ GetCI8IA_RGBA4444 , GetCI8IA_RGBA4444_BG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetCI8IA_RGBA8888 , GetCI8IA_RGBA8888_BG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 3 , 2048 } , // IA
{ GetCI8IA_RGBA4444 , GetCI8IA_RGBA4444_BG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetCI8IA_RGBA8888 , GetCI8IA_RGBA8888_BG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 3 , 2048 } , // I
2017-02-22 05:19:06 +00:00
} ,
{ // 16-bit
2022-02-12 08:22:09 +00:00
{ GetCI16IA_RGBA4444 , GetCI16IA_RGBA4444_BG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetCI16IA_RGBA8888 , GetCI16IA_RGBA8888_BG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 2 , 2048 } , // RGBA
{ GetNone , GetNoneBG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , GetNoneBG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 2 , 2048 } , // YUV
{ GetNone , GetNoneBG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , GetNoneBG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 0 , 2048 } , // CI
{ GetCI16IA_RGBA4444 , GetCI16IA_RGBA4444_BG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetCI16IA_RGBA8888 , GetCI16IA_RGBA8888_BG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 2 , 2048 } , // IA
{ GetNone , GetNoneBG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , GetNoneBG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 0 , 2048 } , // I
2017-02-22 05:19:06 +00:00
} ,
{ // 32-bit
2022-02-12 08:22:09 +00:00
{ GetRGBA8888_RGBA4444 , GetRGBA8888_RGBA4444_BG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetRGBA8888_RGBA8888 , GetRGBA8888_RGBA8888_BG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 2 , 1024 } , // RGBA
{ GetNone , GetNoneBG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , GetNoneBG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 0 , 1024 } , // YUV
{ GetNone , GetNoneBG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , GetNoneBG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 0 , 1024 } , // CI
{ GetNone , GetNoneBG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , GetNoneBG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 0 , 1024 } , // IA
{ GetNone , GetNoneBG , datatype : : UNSIGNED_SHORT_4_4_4_4 , internalcolorFormat : : RGBA4 , GetNone , GetNoneBG , datatype : : UNSIGNED_BYTE , internalcolorFormat : : RGBA8 , internalcolorFormat : : RGBA8 , 0 , 1024 } , // I
2017-02-22 05:19:06 +00:00
}
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 - > maskS = 0 ;
_pDummy - > maskT = 0 ;
_pDummy - > scaleS = 0.5f ;
_pDummy - > scaleT = 0.5f ;
2020-04-18 16:20:17 +00:00
_pDummy - > hdRatioS = 1.0f ;
_pDummy - > hdRatioT = 1.0f ;
2015-05-06 12:36:07 +00:00
_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
2019-11-29 22:09:09 +00:00
m_pDummy = addFrameBufferTexture ( textureTarget : : TEXTURE_2D ) ; // 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 ;
2019-05-08 14:04:24 +00:00
params . width = m_pDummy - > width ;
params . height = m_pDummy - > height ;
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 ) {
2019-11-29 22:09:09 +00:00
m_pMSDummy = addFrameBufferTexture ( textureTarget : : TEXTURE_2D_MULTISAMPLE ) ; // 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 ;
2019-05-08 14:04:24 +00:00
msParams . width = m_pMSDummy - > width ;
msParams . height = m_pMSDummy - > height ;
2018-04-19 13:02:52 +00:00
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 ( ) ;
2021-10-26 12:51:49 +00:00
2021-10-30 07:57:36 +00:00
m_hdTexCacheSize = 0 ;
2013-04-05 06:13:26 +00:00
}
2021-10-30 07:57:36 +00:00
void TextureCache : : _checkHdTexLimit ( )
2013-04-05 06:13:26 +00:00
{
2021-10-30 07:57:36 +00:00
const u64 maxCacheSize = config . textureFilter . txHiresVramLimit * 1024u * 1024u ;
2021-10-26 12:51:49 +00:00
// we don't need to do anything,
// when the limit has been disabled
2021-10-30 07:57:36 +00:00
if ( maxCacheSize = = 0u )
2021-10-26 12:51:49 +00:00
return ;
2021-10-30 07:57:36 +00:00
// keep removing hd textures until we're below the max size
for ( auto iter = m_textures . rbegin ( ) ; iter ! = m_textures . rend ( ) & & m_hdTexCacheSize > = maxCacheSize ; )
2021-10-26 12:51:49 +00:00
{
2021-10-30 07:57:36 +00:00
if ( ! iter - > bHDTexture ) {
+ + iter ;
} else {
assert ( m_hdTexCacheSize > = iter - > textureBytes ) ;
m_hdTexCacheSize - = iter - > textureBytes ;
gfxContext . deleteTexture ( iter - > name ) ;
m_lruTextureLocations . erase ( iter - > crc ) ;
iter = decltype ( iter ) ( m_textures . erase ( std : : next ( iter ) . base ( ) ) ) ;
}
}
}
void TextureCache : : _checkCacheSize ( )
{
if ( m_textures . size ( ) > = m_maxCacheSize ) {
2016-09-15 22:44:55 +00:00
CachedTexture & clsTex = m_textures . back ( ) ;
2021-10-30 07:57:36 +00:00
if ( clsTex . bHDTexture )
m_hdTexCacheSize - = clsTex . textureBytes ;
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
}
2020-03-30 02:21:06 +00:00
CachedTexture * TextureCache : : _addTexture ( u64 _crc64 )
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 ( ) ;
2020-03-30 02:21:06 +00:00
new_iter - > crc = _crc64 ;
m_lruTextureLocations . insert ( std : : pair < u64 , Textures : : iterator > ( _crc64 , new_iter ) ) ;
2015-10-04 21:41:25 +00:00
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 ( ) ) ;
2021-04-28 11:10:58 +00:00
if ( iter ! = m_fbTextures . cend ( ) ) {
gfxContext . deleteTexture ( ObjectHandle ( iter - > second . name ) ) ;
m_fbTextures . erase ( iter ) ;
}
2013-04-05 06:13:26 +00:00
}
2019-11-29 22:09:09 +00:00
CachedTexture * TextureCache : : addFrameBufferTexture ( graphics : : Parameter _target )
2013-04-05 06:13:26 +00:00
{
2019-11-29 22:09:09 +00:00
ObjectHandle texName ( gfxContext . createTexture ( _target ) ) ;
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
{
2019-05-08 14:04:24 +00:00
u32 clampWidth = 0U ;
u32 width = 0U ;
u32 clampHeight = 0U ;
u32 height = 0U ;
u32 bytes = 0U ;
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 ] ;
2018-09-20 02:46:13 +00:00
pTile - > masks = pTile - > originalMaskS ;
pTile - > maskt = pTile - > originalMaskT ;
2014-11-13 09:51:09 +00:00
2022-03-29 21:42:02 +00:00
u32 tileWidth = ( ( pTile - > lrs - pTile - > uls ) & LOAD_BLOCK32_MASK ) + 1 ;
u32 tileHeight = ( ( pTile - > lrt - pTile - > ult ) & LOAD_BLOCK32_MASK ) + 1 ;
2019-05-08 14:04:24 +00:00
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 ] ;
2018-10-17 12:29:00 +00:00
if ( pTile - > tmem = = gDP . loadTile - > tmem ) {
if ( gDP . loadTile - > loadWidth ! = 0 & & gDP . loadTile - > masks = = 0 )
info . width = gDP . loadTile - > loadWidth ;
if ( gDP . loadTile - > loadHeight ! = 0 & & gDP . loadTile - > maskt = = 0 ) {
info . height = gDP . loadTile - > loadHeight ;
info . bytes = info . height * ( gDP . loadTile - > line < < 3 ) ;
2019-03-05 09:06:26 +00:00
if ( gDP . loadTile - > size = = G_IM_SIZ_32b )
// 32 bit texture loaded into lower and upper half of TMEM, thus actual bytes doubled.
info . bytes * = 2 ;
2018-10-17 12:29:00 +00:00
}
}
2021-12-18 16:46:47 +00:00
gDP . loadTile - > loadWidth = gDP . loadTile - > loadHeight = 0 ;
2016-07-02 18:09:26 +00:00
_sizes . bytes = info . bytes ;
2019-05-08 14:04:24 +00:00
2019-10-11 18:03:14 +00:00
if ( tileWidth = = 1 & & tileHeight = = 1 & &
gDP . otherMode . cycleType = = G_CYC_COPY & &
_pLoadTile ! = nullptr ) {
const u32 ulx = _SHIFTR ( RDP . w1 , 14 , 10 ) ;
const u32 uly = _SHIFTR ( RDP . w1 , 2 , 10 ) ;
const u32 lrx = _SHIFTR ( RDP . w0 , 14 , 10 ) ;
const u32 lry = _SHIFTR ( RDP . w0 , 2 , 10 ) ;
tileWidth = lrx - ulx + 1 ;
tileHeight = lry - uly + 1 ;
}
2019-05-08 14:04:24 +00:00
u32 width = 0 , height = 0 ;
2014-11-12 11:19:53 +00:00
if ( info . loadType = = LOADTYPE_TILE ) {
2019-05-08 14:04:24 +00:00
width = min ( info . width , info . texWidth ) ;
2019-10-12 16:57:10 +00:00
if ( width = = 0 )
width = tileWidth ;
2019-05-08 14:04:24 +00:00
if ( info . size > pTile - > size )
width < < = info . size - pTile - > size ;
2014-11-13 09:51:09 +00:00
2019-05-08 14:04:24 +00:00
height = info . height ;
2019-10-12 16:57:10 +00:00
if ( height = = 0 )
height = tileHeight ;
2019-05-08 14:04:24 +00:00
if ( ( config . generalEmulation . hacks & hack_MK64 ) ! = 0 & & ( height % 2 ) ! = 0 )
height - - ;
} else {
2019-10-12 16:57:10 +00:00
const TextureLoadParameters & loadParams =
ImageFormat : : get ( ) . tlp [ gDP . otherMode . textureLUT ] [ pTile - > size ] [ pTile - > format ] ;
2019-05-08 14:04:24 +00:00
int tile_width = pTile - > lrs - pTile - > uls + 1 ;
int tile_height = pTile - > lrt - pTile - > ult + 1 ;
2015-02-28 09:30:10 +00:00
2019-05-08 14:04:24 +00:00
int mask_width = ( pTile - > masks = = 0 ) ? ( tile_width ) : ( 1 < < pTile - > masks ) ;
int mask_height = ( pTile - > maskt = = 0 ) ? ( tile_height ) : ( 1 < < pTile - > maskt ) ;
2014-11-13 09:51:09 +00:00
2020-01-02 11:30:50 +00:00
if ( pTile - > clamps )
2019-05-08 14:04:24 +00:00
width = min ( mask_width , tile_width ) ;
2019-10-12 16:57:10 +00:00
else if ( ( u32 ) ( mask_width * mask_height ) < = loadParams . maxTexels )
2019-05-08 14:04:24 +00:00
width = mask_width ;
2019-10-12 16:57:10 +00:00
else
width = tileWidth ;
2014-11-13 09:51:09 +00:00
2020-01-02 11:30:50 +00:00
if ( pTile - > clampt )
2019-05-08 14:04:24 +00:00
height = min ( mask_height , tile_height ) ;
2019-10-12 16:57:10 +00:00
else if ( ( u32 ) ( mask_width * mask_height ) < = loadParams . maxTexels )
2019-05-08 14:04:24 +00:00
height = mask_height ;
2019-10-12 16:57:10 +00:00
else
height = tileHeight ;
2014-11-13 09:51:09 +00:00
}
2019-05-08 14:04:24 +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 ;
2019-08-21 05:16:26 +00:00
2019-10-28 09:20:09 +00:00
_sizes . width = ( info . loadType = = LOADTYPE_TILE & &
pTile - > clamps ! = 0 & &
pTile - > masks = = 0 ) ?
_sizes . clampWidth :
width ;
_sizes . height = ( info . loadType = = LOADTYPE_TILE & &
pTile - > clampt ! = 0 & &
pTile - > maskt = = 0 ) ?
_sizes . clampHeight :
height ;
2014-11-13 09:51:09 +00:00
}
2021-10-30 07:57:36 +00:00
void TextureCache : : _updateCachedTexture ( const GHQTexInfo & _info , CachedTexture * _pTexture , u16 widthOrg , u16 heightOrg )
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 ;
2019-05-08 14:04:24 +00:00
} else {
2014-11-29 13:29:04 +00:00
_pTexture - > textureBytes < < = 2 ;
}
2017-01-22 11:44:42 +00:00
2019-05-08 14:04:24 +00:00
_pTexture - > scaleS = 1.0f / ( _pTexture - > maskS ? f32 ( pow2 ( widthOrg ) ) : f32 ( widthOrg ) ) ;
_pTexture - > scaleT = 1.0f / ( _pTexture - > maskT ? f32 ( pow2 ( heightOrg ) ) : f32 ( heightOrg ) ) ;
2020-06-14 06:39:42 +00:00
2020-07-15 16:51:49 +00:00
_pTexture - > hdRatioS = ( f32 ) ( _info . width ) / ( f32 ) ( _pTexture - > width ) ;
_pTexture - > hdRatioT = ( f32 ) ( _info . height ) / ( f32 ) ( _pTexture - > height ) ;
2017-11-16 11:00:52 +00:00
2015-11-19 13:12:31 +00:00
_pTexture - > bHDTexture = true ;
2021-10-30 07:57:36 +00:00
m_hdTexCacheSize + = _pTexture - > textureBytes ;
_checkHdTexLimit ( ) ;
2014-11-29 13:29:04 +00:00
}
2019-02-19 05:49:05 +00:00
bool TextureCache : : _loadHiresBackground ( CachedTexture * _pTexture , u64 & _ricecrc )
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));
}
2019-02-19 05:49:05 +00:00
_ricecrc = txfilter_checksum ( addr , tile_width ,
2022-01-22 09:27:42 +00:00
tile_height , 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.
2022-01-22 09:27:42 +00:00
if ( txfilter_hirestex ( _pTexture - > crc , _ricecrc , palette , N64FormatSize ( _pTexture - > format , _pTexture - > size ) , & ghqTexInfo ) & &
2017-05-30 03:18:16 +00:00
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 ( ) ) ;
2019-05-08 14:04:24 +00:00
_updateCachedTexture ( ghqTexInfo , _pTexture , tile_width , tile_height ) ;
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
{
2019-02-19 05:49:05 +00:00
u64 ricecrc = 0 ;
if ( _loadHiresBackground ( pTexture , ricecrc ) )
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 ;
2022-02-12 08:22:09 +00:00
GetTexelFuncBG 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 ) {
2019-05-08 14:04:24 +00:00
pTexture - > textureBytes = ( pTexture - > width * pTexture - > height ) < < 2 ;
2022-02-12 08:22:09 +00:00
GetTexel = loadParams . Get32BG ;
2014-12-11 07:48:55 +00:00
glInternalFormat = loadParams . glInternalFormat32 ;
glType = loadParams . glType32 ;
2014-09-18 16:16:52 +00:00
} else {
2019-05-08 14:04:24 +00:00
pTexture - > textureBytes = ( pTexture - > width * pTexture - > height ) < < 1 ;
2022-02-12 08:22:09 +00:00
GetTexel = loadParams . Get16BG ;
2014-12-11 07:48:55 +00:00
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 ;
2019-05-08 14:04:24 +00:00
for ( y = 0 ; y < pTexture - > height ; 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
2019-05-08 14:04:24 +00:00
for ( x = 0 ; x < pTexture - > width ; 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 ;
}
2019-02-19 05:49:05 +00:00
if ( m_toggleDumpTex & &
config . textureFilter . txHiresEnable ! = 0 & &
2021-07-28 12:38:42 +00:00
config . hotkeys . enabledKeys [ Config : : HotKey : : hkTexDump ] ! = 0 ) {
2019-05-08 14:04:24 +00:00
txfilter_dmptx ( ( u8 * ) pDest , pTexture - > width , pTexture - > height ,
pTexture - > width , ( u16 ) u32 ( glInternalFormat ) ,
2022-01-22 09:27:42 +00:00
N64FormatSize ( pTexture - > format , pTexture - > size ) ,
2019-02-19 05:49:05 +00:00
ricecrc ) ;
}
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 ;
2019-05-08 14:04:24 +00:00
if ( txfilter_filter ( ( u8 * ) pDest , pTexture - > width , pTexture - > height ,
2022-01-22 09:27:42 +00:00
( u16 ) u32 ( glInternalFormat ) , pTexture - > crc , N64FormatSize ( pTexture - > format , pTexture - > size ) , & 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 ) ;
2019-05-08 14:04:24 +00:00
_updateCachedTexture ( ghqTexInfo , pTexture , pTexture - > width , pTexture - > height ) ;
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 ) {
2019-05-08 14:04:24 +00:00
if ( pTexture - > width % 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 ;
2019-05-08 14:04:24 +00:00
params . width = pTexture - > width ;
params . height = pTexture - > height ;
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 ] ;
2019-10-26 11:57:28 +00:00
// Temporal workaround for crash problem with mip-mapped textures. See #1711 for details.
// TODO: make proper fix.
if ( info . texAddress = = 0 )
return false ;
2014-12-09 17:37:26 +00:00
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 {
2019-05-09 03:59:17 +00:00
const gDPTile * pTile = gSP . textureTile [ _tile ] ;
int tile_width = pTile - > lrs - pTile - > uls + 1 ;
int tile_height = pTile - > lrt - pTile - > ult + 1 ;
2017-11-02 15:59:18 +00:00
2019-05-09 03:59:17 +00:00
int mask_width = ( pTile - > masks = = 0 ) ? ( tile_width ) : ( 1 < < pTile - > masks ) ;
int mask_height = ( pTile - > maskt = = 0 ) ? ( tile_height ) : ( 1 < < pTile - > maskt ) ;
2017-11-02 15:59:18 +00:00
2019-05-09 03:59:17 +00:00
if ( ( pTile - > clamps & & tile_width < = 256 ) )
2017-11-02 15:59:18 +00:00
width = min ( mask_width , tile_width ) ;
else
width = mask_width ;
2019-05-09 03:59:17 +00:00
if ( ( pTile - > clampt & & tile_height < = 256 ) | | ( mask_height > 256 ) )
2017-11-02 15:59:18 +00:00
height = min ( mask_height , tile_height ) ;
else
height = mask_height ;
2019-05-09 03:59:17 +00:00
if ( pTile - > size = = G_IM_SIZ_32b )
bpl = pTile - > line < < 4 ;
2014-12-09 17:37:26 +00:00
else if ( info . dxt = = 0 )
2019-05-09 03:59:17 +00:00
bpl = pTile - > line < < 3 ;
2014-12-09 17:37:26 +00:00
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));
}
2022-01-22 09:27:42 +00:00
_ricecrc = txfilter_checksum ( addr , width , height , _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.
2022-01-22 09:27:42 +00:00
if ( txfilter_hirestex ( _pTexture - > crc , _ricecrc , palette , N64FormatSize ( _pTexture - > format , _pTexture - > size ) , & ghqTexInfo ) & &
2017-05-30 03:18:16 +00:00
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 ( ) ) ;
2019-05-08 14:04:24 +00:00
_updateCachedTexture ( ghqTexInfo , _pTexture , width , height ) ;
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 ;
2019-05-08 14:04:24 +00:00
u32 size = _pTexture - > width * _pTexture - > height ;
2018-04-15 01:25:34 +00:00
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 ;
2019-05-08 14:04:24 +00:00
params . width = _pTexture - > width ;
params . height = _pTexture - > height ;
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
{
2019-05-08 14:04:24 +00:00
u16 maskSMask , clampSClamp ;
u16 maskTMask , clampTClamp ;
2018-03-11 07:34:42 +00:00
u16 x , y , tx , ty ;
u32 i , j ;
2019-05-08 14:04:24 +00:00
2015-08-30 22:13:00 +00:00
if ( tmptex . maskS > 0 ) {
clampSClamp = tmptex . clampS ? tmptex . clampWidth - 1 : ( tmptex . mirrorS ? ( tmptex . width < < 1 ) - 1 : tmptex . width - 1 ) ;
maskSMask = ( 1 < < tmptex . maskS ) - 1 ;
} 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 ;
}
if ( tmptex . maskT > 0 ) {
clampTClamp = tmptex . clampT ? tmptex . clampHeight - 1 : ( tmptex . mirrorT ? ( tmptex . height < < 1 ) - 1 : tmptex . height - 1 ) ;
maskTMask = ( 1 < < tmptex . maskT ) - 1 ;
} 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 ;
}
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 ;
2019-05-08 14:04:24 +00:00
for ( y = 0 ; y < tmptex . height ; + + y ) {
2015-08-30 22:13:00 +00:00
ty = min ( y , clampTClamp ) & maskTMask ;
u32 tline = tbase + line32 * ty ;
u32 xorval = ( ty & 1 ) ? 3 : 1 ;
2019-05-08 14:04:24 +00:00
for ( x = 0 ; x < tmptex . width ; + + x ) {
2015-08-30 22:13:00 +00:00
tx = min ( x , clampSClamp ) & maskSMask ;
2022-03-29 21:42:02 +00:00
u32 taddr = ( ( tline + tx ) ^ xorval ) & LOAD_BLOCK32_MASK ;
2022-01-16 17:27:17 +00:00
# ifdef NATIVE
gr = tmem16 [ taddr ] ;
2022-03-29 21:42:02 +00:00
ab = tmem16 [ taddr | LOAD_BLOCK32_MAX ] ;
2022-01-16 17:27:17 +00:00
# else
2015-08-30 22:13:00 +00:00
gr = swapword ( tmem16 [ taddr ] ) ;
2022-03-29 21:42:02 +00:00
ab = swapword ( tmem16 [ taddr | LOAD_BLOCK32_MAX ] ) ;
2022-01-16 17:27:17 +00:00
# endif
2015-08-30 22:13:00 +00:00
pDest [ j + + ] = ( ab < < 16 ) | gr ;
}
}
} else if ( tmptex . format = = G_IM_FMT_YUV ) {
j = 0 ;
* pLine < < = 1 ;
2019-05-08 14:04:24 +00:00
for ( y = 0 ; y < tmptex . height ; + + y ) {
2022-02-12 08:22:09 +00:00
u64 * pSrc = & TMEM [ tmptex . tMem ] + * pLine * y ;
2019-05-08 14:04:24 +00:00
for ( x = 0 ; x < tmptex . width / 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 ;
2019-05-08 14:04:24 +00:00
for ( y = 0 ; y < tmptex . height ; + + y ) {
2015-08-30 22:13:00 +00:00
ty = min ( y , clampTClamp ) & maskTMask ;
2022-02-12 08:22:09 +00:00
u16 tmemOffset = ( tmptex . tMem + * pLine * ty ) & tMemMask ;
2015-08-30 22:13:00 +00:00
i = ( ty & 1 ) < < 1 ;
2019-05-08 14:04:24 +00:00
for ( x = 0 ; x < tmptex . width ; + + x ) {
2015-08-30 22:13:00 +00:00
tx = min ( x , clampSClamp ) & maskSMask ;
2022-02-12 08:22:09 +00:00
if ( glInternalFormat = = internalcolorFormat : : RGBA8 )
pDest [ j + + ] = GetTexel ( tmemOffset , tx , i , tmptex . palette ) ;
else
( ( u16 * ) pDest ) [ j + + ] = GetTexel ( tmemOffset , tx , i , tmptex . palette ) ;
2015-08-30 22:13:00 +00:00
}
}
}
}
2020-08-28 13:03:24 +00:00
template < typename T >
void doubleTexture ( T * pTex , u32 width , u32 height )
{
std : : vector < T > vData ( width * height ) ;
memcpy ( vData . data ( ) , pTex , width * height * sizeof ( T ) ) ;
u32 srcIdx = 0 ;
u32 dstIdx = 0 ;
for ( u32 y = 0 ; y < height ; + + y ) {
const u32 srcIdxCur = srcIdx ;
for ( u32 x = 0 ; x < width ; + + x ) {
pTex [ dstIdx + + ] = vData [ srcIdx ] ;
pTex [ dstIdx + + ] = vData [ srcIdx + + ] ;
}
srcIdx = srcIdxCur ;
for ( u32 x = 0 ; x < width ; + + x ) {
pTex [ dstIdx + + ] = vData [ srcIdx ] ;
pTex [ dstIdx + + ] = vData [ srcIdx + + ] ;
}
}
}
2021-10-11 23:22:23 +00:00
void TextureCache : : _loadFast ( u32 _tile , CachedTexture * _pTexture )
{
u64 ricecrc = 0 ;
if ( _loadHiresTexture ( _tile , _pTexture , ricecrc ) )
return ;
s32 mipLevel = 0 ;
bool force32bitFormat = false ;
_pTexture - > max_level = 0 ;
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 ;
auto texFormat = gDP . tiles [ gSP . texture . tile + 1 ] . format ;
auto texSize = gDP . tiles [ gSP . texture . tile + 1 ] . size ;
u32 tileMipLevel = gSP . texture . tile + 2 ;
while ( ! force32bitFormat & & ( tileMipLevel < gSP . texture . tile + gSP . texture . level ) ) {
gDPTile const & mipTile = gDP . tiles [ tileMipLevel + + ] ;
force32bitFormat = texFormat ! = mipTile . format | | texSize ! = mipTile . size ;
}
}
}
u32 sizeShift = 1 ;
{
const TextureLoadParameters & loadParams =
ImageFormat : : get ( ) . tlp [ gDP . otherMode . textureLUT ] [ _pTexture - > size ] [ _pTexture - > format ] ;
if ( force32bitFormat | | loadParams . autoFormat = = internalcolorFormat : : RGBA8 )
sizeShift = 2 ;
}
_pTexture - > textureBytes = ( _pTexture - > width * _pTexture - > height ) < < sizeShift ;
unsigned int totalTexSize = std : : max ( static_cast < u32 > ( _pTexture - > textureBytes / sizeof ( u32 ) + 8 ) , MIPMAP_TILE_WIDTH )
* ( _pTexture - > max_level + 1 ) ;
if ( m_tempTextureHolder . size ( ) < totalTexSize ) {
m_tempTextureHolder . resize ( totalTexSize ) ;
}
GetTexelFunc GetTexel ;
InternalColorFormatParam glInternalFormat ;
DatatypeParam glType ;
auto getLoadParams = [ & ] ( u16 _format , u16 _size )
{
const TextureLoadParameters & loadParams =
ImageFormat : : get ( ) . tlp [ gDP . otherMode . textureLUT ] [ _size ] [ _format ] ;
if ( force32bitFormat | | loadParams . autoFormat = = internalcolorFormat : : RGBA8 ) {
GetTexel = loadParams . Get32 ;
glInternalFormat = loadParams . glInternalFormat32 ;
glType = loadParams . glType32 ;
}
else {
GetTexel = loadParams . Get16 ;
glInternalFormat = loadParams . glInternalFormat16 ;
glType = loadParams . glType16 ;
}
} ;
CachedTexture tmptex = * _pTexture ;
u16 line = tmptex . line ;
while ( true ) {
getLoadParams ( tmptex . format , tmptex . size ) ;
{
const u32 tileMipLevel = gSP . texture . tile + mipLevel + 1 ;
gDPTile & mipTile = gDP . tiles [ tileMipLevel ] ;
if ( tmptex . max_level > 1 & &
tmptex . width = = ( mipTile . lrs - mipTile . uls + 1 ) * 2 & &
tmptex . height = = ( mipTile . lrt - mipTile . ult + 1 ) * 2 )
{
// Special case for Southern Swamp grass texture, Zelda MM. See #2315
const u16 texWidth = tmptex . width ;
const u16 texHeight = tmptex . height ;
tmptex . width = mipTile . lrs - mipTile . uls + 1 ;
tmptex . height = mipTile . lrt - mipTile . ult + 1 ;
_getTextureDestData ( tmptex , m_tempTextureHolder . data ( ) , glInternalFormat , GetTexel , & line ) ;
if ( sizeShift = = 2 )
doubleTexture < u32 > ( m_tempTextureHolder . data ( ) , tmptex . width , tmptex . height ) ;
else
doubleTexture < u16 > ( ( u16 * ) m_tempTextureHolder . data ( ) , tmptex . width , tmptex . height ) ;
tmptex . width = texWidth ;
tmptex . height = texHeight ;
} else {
_getTextureDestData ( tmptex , m_tempTextureHolder . data ( ) , glInternalFormat , GetTexel , & line ) ;
}
}
if ( ( config . generalEmulation . hacks & hack_LoadDepthTextures ) ! = 0 & & gDP . colorImage . address = = gDP . depthImageAddress ) {
_loadDepthTexture ( _pTexture , ( u16 * ) m_tempTextureHolder . data ( ) ) ;
return ;
}
if ( m_toggleDumpTex & &
config . textureFilter . txHiresEnable ! = 0 & &
config . hotkeys . enabledKeys [ Config : : HotKey : : hkTexDump ] ! = 0 ) {
txfilter_dmptx ( ( u8 * ) m_tempTextureHolder . data ( ) , tmptex . width , tmptex . height ,
tmptex . width , ( u16 ) u32 ( glInternalFormat ) ,
2022-01-22 09:27:42 +00:00
N64FormatSize ( _pTexture - > format , _pTexture - > size ) ,
2021-10-11 23:22:23 +00:00
ricecrc ) ;
}
bool bLoaded = false ;
bool needEnhance = ( config . textureFilter . txEnhancementMode | config . textureFilter . txFilterMode ) ! = 0 & &
_pTexture - > max_level = = 0 & &
TFH . isInited ( ) ;
if ( needEnhance ) {
if ( config . textureFilter . txFilterIgnoreBG ! = 0 ) {
switch ( GBI . getMicrocodeType ( ) ) {
case S2DEX_1_07 :
case S2DEX_1_03 :
case S2DEX_1_05 :
needEnhance = RSP . cmd ! = 0x01 & & RSP . cmd ! = 0x02 ;
break ;
case S2DEX2 :
needEnhance = RSP . cmd ! = 0x09 & & RSP . cmd ! = 0x0A ;
break ;
}
}
}
if ( needEnhance ) {
GHQTexInfo ghqTexInfo ;
if ( txfilter_filter ( ( u8 * ) m_tempTextureHolder . data ( ) , tmptex . width , tmptex . height ,
( u16 ) u32 ( glInternalFormat ) , ( uint64 ) _pTexture - > crc ,
2022-01-22 09:27:42 +00:00
N64FormatSize ( _pTexture - > format , _pTexture - > size ) ,
2021-10-11 23:22:23 +00:00
& ghqTexInfo ) ! = 0 & & ghqTexInfo . data ! = nullptr ) {
if ( ghqTexInfo . width % 2 ! = 0 & &
ghqTexInfo . format ! = u32 ( internalcolorFormat : : RGBA8 ) & &
m_curUnpackAlignment > 1 )
gfxContext . setTextureUnpackAlignment ( 2 ) ;
ghqTexInfo . format = gfxContext . convertInternalTextureFormat ( ghqTexInfo . format ) ;
Context : : InitTextureParams params ;
params . handle = _pTexture - > name ;
params . textureUnitIndex = textureIndices : : Tex [ _tile ] ;
params . mipMapLevel = 0 ;
params . msaaLevel = 0 ;
params . width = ghqTexInfo . width ;
params . height = ghqTexInfo . height ;
params . internalFormat = InternalColorFormatParam ( ghqTexInfo . format ) ;
params . format = ColorFormatParam ( ghqTexInfo . texture_format ) ;
params . dataType = DatatypeParam ( ghqTexInfo . pixel_type ) ;
params . data = ghqTexInfo . data ;
gfxContext . init2DTexture ( params ) ;
_updateCachedTexture ( ghqTexInfo , _pTexture , tmptex . width , tmptex . height ) ;
bLoaded = true ;
}
}
if ( ! bLoaded ) {
if ( tmptex . width % 2 ! = 0 & &
glInternalFormat ! = internalcolorFormat : : RGBA8 & &
m_curUnpackAlignment > 1 )
gfxContext . setTextureUnpackAlignment ( 2 ) ;
Context : : InitTextureParams params ;
params . handle = _pTexture - > name ;
params . textureUnitIndex = textureIndices : : Tex [ _tile ] ;
params . mipMapLevel = mipLevel ;
params . mipMapLevels = _pTexture - > max_level + 1 ;
params . msaaLevel = 0 ;
params . width = tmptex . width ;
params . height = tmptex . height ;
params . internalFormat = gfxContext . convertInternalTextureFormat ( u32 ( glInternalFormat ) ) ;
params . format = colorFormat : : RGBA ;
params . dataType = glType ;
params . data = m_tempTextureHolder . data ( ) ;
gfxContext . init2DTexture ( params ) ;
}
if ( mipLevel = = _pTexture - > max_level )
break ;
+ + mipLevel ;
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 ;
tmptex . format = mipTile . format ;
tmptex . size = mipTile . size ;
TileSizes sizes ;
_calcTileSizes ( tileMipLevel , sizes , nullptr ) ;
tmptex . clampWidth = sizes . clampWidth ;
tmptex . clampHeight = sizes . clampHeight ;
// Insure mip-map levels size consistency.
if ( tmptex . width > 1 )
tmptex . width > > = 1 ;
if ( tmptex . height > 1 )
tmptex . height > > = 1 ;
_pTexture - > textureBytes + = ( tmptex . width * tmptex . height ) < < sizeShift ;
}
if ( m_curUnpackAlignment > 1 )
gfxContext . setTextureUnpackAlignment ( m_curUnpackAlignment ) ;
}
void TextureCache : : _loadAccurate ( u32 _tile , CachedTexture * _pTexture )
2014-11-29 13:29:04 +00:00
{
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
2020-08-28 13:03:24 +00:00
bool force32bitFormat = false ;
_pTexture - > max_level = 0 ;
2013-04-05 06:13:26 +00:00
2022-02-13 13:58:03 +00:00
if ( currentCombiner ( ) - > usesLOD ( ) & & gSP . texture . level > 1 & & _tile > 0 ) {
2021-08-21 17:00:51 +00:00
_pTexture - > max_level = gDP . otherMode . textureDetail = = G_TD_DETAIL ?
static_cast < u8 > ( gSP . texture . level ) :
static_cast < u8 > ( gSP . texture . level - 1 ) ;
force32bitFormat = _pTexture - > max_level > 0 ;
2020-08-28 13:03:24 +00:00
}
u32 sizeShift = 1 ;
{
const TextureLoadParameters & loadParams =
2017-01-28 03:11:45 +00:00
ImageFormat : : get ( ) . tlp [ gDP . otherMode . textureLUT ] [ _pTexture - > size ] [ _pTexture - > format ] ;
2020-08-28 13:03:24 +00:00
if ( force32bitFormat | | loadParams . autoFormat = = internalcolorFormat : : RGBA8 )
sizeShift = 2 ;
2013-04-05 06:13:26 +00:00
}
2020-08-28 13:03:24 +00:00
_pTexture - > textureBytes = ( _pTexture - > width * _pTexture - > height ) < < sizeShift ;
2013-04-05 06:13:26 +00:00
2021-10-11 23:22:23 +00:00
unsigned int totalTexSize = std : : max ( static_cast < u32 > ( _pTexture - > textureBytes / sizeof ( u32 ) + 8 ) , MIPMAP_TILE_WIDTH )
* ( _pTexture - > max_level + 1 ) ;
if ( m_tempTextureHolder . size ( ) < totalTexSize ) {
m_tempTextureHolder . resize ( totalTexSize ) ;
}
2020-08-28 04:36:59 +00:00
2020-08-28 13:03:24 +00:00
GetTexelFunc GetTexel ;
InternalColorFormatParam glInternalFormat ;
DatatypeParam glType ;
2013-04-05 06:13:26 +00:00
2020-08-28 13:03:24 +00:00
auto getLoadParams = [ & ] ( u16 _format , u16 _size )
{
const TextureLoadParameters & loadParams =
ImageFormat : : get ( ) . tlp [ gDP . otherMode . textureLUT ] [ _size ] [ _format ] ;
if ( force32bitFormat | | loadParams . autoFormat = = internalcolorFormat : : RGBA8 ) {
GetTexel = loadParams . Get32 ;
glInternalFormat = loadParams . glInternalFormat32 ;
glType = loadParams . glType32 ;
2017-10-02 09:58:55 +00:00
}
2020-08-28 13:03:24 +00:00
else {
GetTexel = loadParams . Get16 ;
glInternalFormat = loadParams . glInternalFormat16 ;
glType = loadParams . glType16 ;
}
} ;
2014-10-09 09:01:04 +00:00
2020-08-28 13:03:24 +00:00
CachedTexture tmptex = * _pTexture ;
u16 line = tmptex . line ;
2013-04-05 06:13:26 +00:00
2021-08-21 17:00:51 +00:00
if ( _pTexture - > max_level > 0 )
{
u32 mipLevel = 0 ;
u32 texDataOffset = 8 ; // number of gDP.tiles
// Load all tiles into one 1D texture atlas.
while ( true )
2020-08-28 13:03:24 +00:00
{
2021-11-06 09:43:14 +00:00
u32 mipRatioS = gDP . tiles [ gSP . texture . tile + mipLevel + 1 ] . shifts + 5u ;
if ( mipRatioS > = 16u ) mipRatioS - = 16u ;
u32 mipRatioT = gDP . tiles [ gSP . texture . tile + mipLevel + 1 ] . shiftt + 5u ;
if ( mipRatioT > = 16 ) mipRatioT - = 16u ;
const u32 tileSizePacked = texDataOffset | ( tmptex . width < < 16 ) | ( mipRatioT < < 24 ) | ( mipRatioS < < 28 ) ;
2021-10-11 23:22:23 +00:00
m_tempTextureHolder [ mipLevel ] = tileSizePacked ;
2021-08-21 17:00:51 +00:00
getLoadParams ( tmptex . format , tmptex . size ) ;
2021-10-11 23:22:23 +00:00
_getTextureDestData ( tmptex , & m_tempTextureHolder [ texDataOffset ] , glInternalFormat , GetTexel , & line ) ;
2021-08-21 17:00:51 +00:00
if ( m_toggleDumpTex & &
config . textureFilter . txHiresEnable ! = 0 & &
config . hotkeys . enabledKeys [ Config : : HotKey : : hkTexDump ] ! = 0 ) {
2021-10-11 23:22:23 +00:00
txfilter_dmptx ( ( u8 * ) ( m_tempTextureHolder . data ( ) + texDataOffset ) , tmptex . width , tmptex . height ,
2021-08-21 17:00:51 +00:00
tmptex . width , ( u16 ) u32 ( glInternalFormat ) ,
2022-01-22 09:27:42 +00:00
N64FormatSize ( _pTexture - > format , _pTexture - > size ) ,
2021-08-21 17:00:51 +00:00
ricecrc ) ;
}
texDataOffset + = tmptex . width * tmptex . height ;
if ( mipLevel = = _pTexture - > max_level )
break ;
+ + mipLevel ;
2020-08-28 13:03:24 +00:00
const u32 tileMipLevel = gSP . texture . tile + mipLevel + 1 ;
gDPTile & mipTile = gDP . tiles [ tileMipLevel ] ;
2021-08-21 17:00:51 +00:00
gDPTile & prevMipTile = gDP . tiles [ tileMipLevel - 1 ] ;
line = mipTile . line ;
tmptex . tMem = mipTile . tmem ;
tmptex . palette = mipTile . palette ;
tmptex . maskS = mipTile . masks ;
tmptex . maskT = mipTile . maskt ;
tmptex . format = mipTile . format ;
tmptex . size = mipTile . size ;
TileSizes sizes ;
_calcTileSizes ( tileMipLevel , sizes , nullptr ) ;
2021-12-18 16:46:47 +00:00
tmptex . width = std : : min ( tmptex . width , static_cast < u16 > ( sizes . width ) ) ;
tmptex . height = std : : min ( tmptex . height , static_cast < u16 > ( sizes . height ) ) ;
2021-08-21 17:00:51 +00:00
tmptex . clampWidth = sizes . clampWidth ;
tmptex . clampHeight = sizes . clampHeight ;
_pTexture - > textureBytes + = ( tmptex . width * tmptex . height ) < < sizeShift ;
2020-08-28 13:03:24 +00:00
}
2014-11-20 09:28:31 +00:00
2021-08-21 17:00:51 +00:00
Context : : InitTextureParams params ;
params . handle = _pTexture - > name ;
params . textureUnitIndex = textureIndices : : Tex [ _tile ] ;
params . mipMapLevel = 0 ;
params . mipMapLevels = 1 ;
params . msaaLevel = 0 ;
2021-08-25 16:12:27 +00:00
params . width = std : : min ( texDataOffset , MIPMAP_TILE_WIDTH ) ;
params . height = ( texDataOffset / MIPMAP_TILE_WIDTH ) + ( ( texDataOffset % MIPMAP_TILE_WIDTH ) ? 1 : 0 ) ;
2021-08-21 17:00:51 +00:00
params . internalFormat = gfxContext . convertInternalTextureFormat ( u32 ( glInternalFormat ) ) ;
params . format = colorFormat : : RGBA ;
params . dataType = glType ;
2021-10-11 23:22:23 +00:00
params . data = m_tempTextureHolder . data ( ) ;
2021-08-21 17:00:51 +00:00
gfxContext . init2DTexture ( params ) ;
2021-08-28 06:12:48 +00:00
_pTexture - > mipmapAtlasWidth = params . width ;
_pTexture - > mipmapAtlasHeight = params . height ;
2021-08-21 17:00:51 +00:00
}
else
{
getLoadParams ( tmptex . format , tmptex . size ) ;
2021-10-11 23:22:23 +00:00
_getTextureDestData ( tmptex , m_tempTextureHolder . data ( ) , glInternalFormat , GetTexel , & line ) ;
2021-08-21 17:00:51 +00:00
2016-04-09 15:07:46 +00:00
if ( ( config . generalEmulation . hacks & hack_LoadDepthTextures ) ! = 0 & & gDP . colorImage . address = = gDP . depthImageAddress ) {
2021-10-11 23:22:23 +00:00
_loadDepthTexture ( _pTexture , ( u16 * ) m_tempTextureHolder . data ( ) ) ;
2016-04-09 15:07:46 +00:00
return ;
}
2015-08-30 22:44:01 +00:00
if ( m_toggleDumpTex & &
2020-11-16 04:28:21 +00:00
config . textureFilter . txHiresEnable ! = 0 & &
2021-07-28 12:38:42 +00:00
config . hotkeys . enabledKeys [ Config : : HotKey : : hkTexDump ] ! = 0 ) {
2021-10-11 23:22:23 +00:00
txfilter_dmptx ( ( u8 * ) m_tempTextureHolder . data ( ) , tmptex . width , tmptex . height ,
2019-05-08 14:04:24 +00:00
tmptex . width , ( u16 ) u32 ( glInternalFormat ) ,
2022-01-22 09:27:42 +00:00
N64FormatSize ( _pTexture - > format , _pTexture - > size ) ,
2015-08-30 22:44:01 +00:00
ricecrc ) ;
2015-04-12 12:49:40 +00:00
}
2016-04-08 06:03:22 +00:00
bool bLoaded = false ;
2019-02-24 12:47:28 +00:00
bool needEnhance = ( config . textureFilter . txEnhancementMode | config . textureFilter . txFilterMode ) ! = 0 & &
_pTexture - > max_level = = 0 & &
TFH . isInited ( ) ;
if ( needEnhance ) {
if ( config . textureFilter . txFilterIgnoreBG ! = 0 ) {
switch ( GBI . getMicrocodeType ( ) ) {
case S2DEX_1_07 :
case S2DEX_1_03 :
case S2DEX_1_05 :
needEnhance = RSP . cmd ! = 0x01 & & RSP . cmd ! = 0x02 ;
break ;
case S2DEX2 :
needEnhance = RSP . cmd ! = 0x09 & & RSP . cmd ! = 0x0A ;
break ;
}
}
}
if ( needEnhance ) {
2014-11-20 09:28:31 +00:00
GHQTexInfo ghqTexInfo ;
2021-10-11 23:22:23 +00:00
if ( txfilter_filter ( ( u8 * ) m_tempTextureHolder . data ( ) , tmptex . width , tmptex . height ,
2017-01-22 11:44:42 +00:00
( u16 ) u32 ( glInternalFormat ) , ( uint64 ) _pTexture - > crc ,
2022-01-22 09:27:42 +00:00
N64FormatSize ( _pTexture - > format , _pTexture - > size ) ,
2016-06-10 06:06:06 +00:00
& ghqTexInfo ) ! = 0 & & ghqTexInfo . data ! = nullptr ) {
2019-02-15 10:44:45 +00:00
if ( ghqTexInfo . width % 2 ! = 0 & &
ghqTexInfo . format ! = u32 ( internalcolorFormat : : RGBA8 ) & &
m_curUnpackAlignment > 1 )
gfxContext . setTextureUnpackAlignment ( 2 ) ;
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 ) ;
2019-05-08 14:04:24 +00:00
_updateCachedTexture ( ghqTexInfo , _pTexture , tmptex . width , tmptex . height ) ;
2014-11-20 09:28:31 +00:00
bLoaded = true ;
}
}
if ( ! bLoaded ) {
2019-05-08 14:04:24 +00:00
if ( tmptex . width % 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 ] ;
2021-08-21 17:00:51 +00:00
params . mipMapLevel = 0 ;
params . mipMapLevels = 1 ;
2017-01-01 14:59:54 +00:00
params . msaaLevel = 0 ;
2019-05-08 14:04:24 +00:00
params . width = tmptex . width ;
params . height = tmptex . height ;
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 ;
2021-10-11 23:22:23 +00:00
params . data = m_tempTextureHolder . data ( ) ;
2017-01-01 14:59:54 +00:00
gfxContext . init2DTexture ( params ) ;
2014-11-20 09:28:31 +00:00
}
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 ) ;
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
2020-03-30 02:21:06 +00:00
u64 _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 ;
2020-11-10 08:41:35 +00:00
const u32 tMem = gSP . textureTile [ _t ] - > tmem & tMemMask ;
const u64 * src = ( u64 * ) & TMEM [ tMem ] ;
2020-06-14 15:59:20 +00:00
const u32 maxBytes = ( tMemMask + 1 ) < < 3 ;
2020-11-10 08:41:35 +00:00
const u32 tileTmemInBytes = tMem < < 3 ;
2020-06-14 15:59:20 +00:00
if ( ! rgba32 & & ( tileTmemInBytes + _bytes > maxBytes ) )
_bytes = maxBytes - tileTmemInBytes ;
2020-03-30 02:21:06 +00:00
u64 crc = UINT64_MAX ;
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 ) {
2020-06-14 15:59:20 +00:00
src = ( u64 * ) & TMEM [ ( gSP . textureTile [ _t ] - > tmem + 256 ) & 0x1FF ] ;
2016-07-02 18:09:26 +00:00
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 )
2020-04-04 14:13:00 +00:00
crc = CRC_Calculate ( crc , & gDP . paletteCRC16 [ gSP . textureTile [ _t ] - > palette ] , sizeof ( u64 ) ) ;
2016-07-02 18:09:26 +00:00
else if ( gSP . textureTile [ _t ] - > size = = G_IM_SIZ_8b )
2020-04-04 14:13:00 +00:00
crc = CRC_Calculate ( crc , & gDP . paletteCRC256 , sizeof ( u64 ) ) ;
2013-04-05 06:13:26 +00:00
}
2014-09-03 05:12:48 +00:00
2019-02-25 08:38:52 +00:00
if ( config . generalEmulation . enableLOD ! = 0 & & gSP . texture . level > 1 & & _t > 0 )
crc = CRC_Calculate ( crc , & gSP . texture . level , 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 ] ;
2021-12-06 16:03:43 +00:00
params . minFilter = textureParameters : : FILTER_NEAREST ;
params . magFilter = textureParameters : : FILTER_NEAREST ;
params . maxMipmapLevel = Parameter ( 0 ) ;
if ( config . generalEmulation . enableInaccurateTextureCoordinates ! = 0 ) {
const bool bUseBilinear = gDP . otherMode . textureFilter ! = G_TF_POINT & & config . texture . bilinearMode ! = BILINEAR_3POINT ;
const bool bUseLOD = currentCombiner ( ) - > usesLOD ( ) ;
const s32 texLevel = bUseLOD ? _pTexture - > max_level : 0 ;
params . maxMipmapLevel = Parameter ( texLevel ) ;
if ( bUseLOD ) {
if ( bUseBilinear ) {
// Apply standard bilinear to mipmap textures
if ( texLevel > 0 )
params . minFilter = textureParameters : : FILTER_LINEAR_MIPMAP_NEAREST ;
else
params . minFilter = textureParameters : : FILTER_LINEAR ;
params . magFilter = textureParameters : : FILTER_LINEAR ;
} else {
if ( texLevel > 0 )
params . minFilter = textureParameters : : FILTER_NEAREST_MIPMAP_NEAREST ;
else
params . minFilter = textureParameters : : FILTER_NEAREST ;
params . magFilter = textureParameters : : FILTER_NEAREST ;
}
2017-01-01 14:59:54 +00:00
}
2021-12-06 16:03:43 +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
2021-07-22 05:05:13 +00:00
if ( config . texture . anisotropy ! = 0 ) {
2020-05-04 12:17:23 +00:00
switch ( dwnd ( ) . getDrawer ( ) . getDrawingState ( ) ) {
case DrawingState : : Triangle :
case DrawingState : : ScreenSpaceTriangle :
2021-07-22 05:05:13 +00:00
params . maxAnisotropy = Parameter ( static_cast < f32 > ( config . texture . anisotropy ) ) ;
2020-05-04 12:17:23 +00:00
break ;
2020-11-15 16:03:08 +00:00
default :
break ;
2020-05-04 12:17:23 +00:00
}
}
2017-02-18 14:40:41 +00:00
}
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 ;
2020-03-30 02:21:06 +00:00
u64 crc ;
2013-04-05 06:13:26 +00:00
2020-03-30 02:21:06 +00:00
crc = CRC_Calculate ( UINT64_MAX , & RDRAM [ gSP . bgImage . address ] , numBytes ) ;
2013-04-05 06:13:26 +00:00
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 )
2020-04-04 14:13:00 +00:00
crc = CRC_Calculate ( crc , & gDP . paletteCRC16 [ gSP . bgImage . palette ] , sizeof ( u64 ) ) ;
2013-04-05 06:13:26 +00:00
else if ( gSP . bgImage . size = = G_IM_SIZ_8b )
2020-04-04 14:13:00 +00:00
crc = CRC_Calculate ( crc , & gDP . paletteCRC256 , sizeof ( u64 ) ) ;
2013-04-05 06:13:26 +00:00
}
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
2019-05-08 14:04:24 +00:00
pCurrent - > scaleS = 1.0f / ( f32 ) ( pCurrent - > width ) ;
pCurrent - > scaleT = 1.0f / ( f32 ) ( pCurrent - > height ) ;
2013-04-05 06:13:26 +00:00
2020-04-18 16:20:17 +00:00
pCurrent - > hdRatioS = 1.0f ;
pCurrent - > hdRatioT = 1.0f ;
2014-09-18 16:16:52 +00:00
pCurrent - > shiftScaleS = 1.0f ;
pCurrent - > shiftScaleT = 1.0f ;
2013-04-05 06:13:26 +00:00
2019-10-07 10:25:22 +00:00
pCurrent - > offsetS = 0.0f ;
pCurrent - > offsetT = 0.0f ;
2014-10-22 13:49:48 +00:00
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
}
2020-11-16 04:28:21 +00:00
void TextureCache : : clear ( )
2015-04-12 12:49:40 +00:00
{
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 ( ) ;
2021-10-30 07:57:36 +00:00
m_hdTexCacheSize = 0u ;
2015-04-12 12:49:40 +00:00
}
2020-11-16 04:28:21 +00:00
void TextureCache : : toggleDumpTex ( )
2013-04-05 06:13:26 +00:00
{
2020-11-16 04:28:21 +00:00
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 ) ) ;
2015-04-12 12:49:40 +00:00
}
2020-11-16 04:28:21 +00:00
}
2015-04-12 12:49:40 +00:00
2020-11-16 04:28:21 +00:00
void TextureCache : : update ( u32 _t )
{
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
}
2021-10-11 23:22:23 +00:00
if ( _t = = 1 & & needReplaceTex1ByTex0 ( ) ) {
current [ 1 ] = current [ 0 ] ;
if ( current [ 1 ] ! = nullptr ) {
activateTexture ( 1 , current [ 1 ] ) ;
return ;
}
}
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 ;
2020-08-28 13:03:24 +00:00
const u32 texLevel = _t = = 0 ? 0U : gSP . texture . level ;
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 ) |
2020-08-28 13:03:24 +00:00
( gDP . otherMode . textureLUT < < 17 ) |
( texLevel < < 19 ) ;
2019-05-08 14:04:24 +00:00
params . width = sizes . width ;
params . height = sizes . height ;
2013-04-05 06:13:26 +00:00
2020-03-30 02:21:06 +00:00
const u64 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 ;
}
2021-10-30 07:57:36 +00:00
if ( currentTex . bHDTexture )
m_hdTexCacheSize - = currentTex . textureBytes ;
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
2019-05-08 14:04:24 +00:00
pCurrent - > scaleS = 1.0f / ( pCurrent - > maskS ? f32 ( pow2 ( pCurrent - > width ) ) : f32 ( pCurrent - > width ) ) ;
pCurrent - > scaleT = 1.0f / ( pCurrent - > maskT ? f32 ( pow2 ( pCurrent - > height ) ) : f32 ( pCurrent - > height ) ) ;
2013-04-05 06:13:26 +00:00
2020-04-18 16:20:17 +00:00
pCurrent - > hdRatioS = 1.0f ;
pCurrent - > hdRatioT = 1.0f ;
2019-10-07 10:25:22 +00:00
pCurrent - > offsetS = 0.0f ;
pCurrent - > offsetT = 0.0f ;
2013-04-05 06:13:26 +00:00
2021-10-11 23:22:23 +00:00
if ( config . generalEmulation . enableInaccurateTextureCoordinates ) {
_loadFast ( _t , pCurrent ) ;
} else {
_loadAccurate ( _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 )
{
2021-11-06 09:57:36 +00:00
gDPTile & tile = * gSP . textureTile [ t ] ;
if ( tile . textureMode ! = TEXTUREMODE_NORMAL ) {
2015-04-29 05:33:11 +00:00
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 ;
2021-11-06 09:57:36 +00:00
shiftScaleS = calcShiftScaleS ( tile ) ;
shiftScaleT = calcShiftScaleT ( tile ) ;
2021-10-11 23:22:23 +00:00
}
bool needReplaceTex1ByTex0 ( )
{
return config . generalEmulation . enableInaccurateTextureCoordinates & &
gSP . texture . level = = 0 & & gDP . otherMode . textureLOD = = G_TL_LOD & & gDP . otherMode . textureDetail = = G_TD_CLAMP ;
}