2010-03-19 00:31:15 +00:00
/* ZZ Open GL graphics plugin
2010-07-10 08:20:50 +00:00
* Copyright ( c ) 2009 - 2010 zeydlitz @ gmail . com , arcum42 @ gmail . com
* Based on Zerofrog ' s ZeroGS KOSMOS ( c ) 2005 - 2008
2010-03-19 00:31:15 +00:00
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
2010-07-04 22:49:00 +00:00
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA
2010-03-19 00:31:15 +00:00
*/
2010-06-19 05:41:06 +00:00
// Realization of Flush -- drawing function of GS
2010-03-19 00:31:15 +00:00
# include <stdlib.h>
2012-04-19 21:22:08 +00:00
# include <math.h>
2010-03-19 00:31:15 +00:00
# include "GS.h"
# include "Mem.h"
# include "targets.h"
2010-08-17 13:38:57 +00:00
# include "ZZoglFlushHack.h"
2010-09-15 16:54:19 +00:00
# include "ZZoglShaders.h"
2010-12-20 19:57:50 +00:00
# include "ZZClut.h"
2012-04-19 21:22:08 +00:00
# include "ZZoglFlush.h"
2010-03-19 00:31:15 +00:00
//------------------ Defines
2012-04-19 21:22:08 +00:00
# ifdef ZEROGS_DEVBUILD
bool g_bUpdateEffect = false ;
bool g_bSaveTex = false ; // saves the current texture
bool g_bSaveResolved = false ;
2010-04-25 09:02:36 +00:00
# endif // !defined(ZEROGS_DEVBUILD)
2010-03-19 00:31:15 +00:00
2012-04-19 21:22:08 +00:00
bool g_bSaveTrans = false ;
bool s_bWriteDepth = false ;
bool s_bDestAlphaTest = false ;
2010-03-19 00:31:15 +00:00
2012-04-19 21:22:08 +00:00
bool g_bUpdateStencil = true ;
bool bCanRenderStencil = true ;
2010-03-19 00:31:15 +00:00
// local alpha blending settings
2012-04-19 21:22:08 +00:00
GLenum s_rgbeq , s_alphaeq ; // set by zgsBlendEquationSeparateEXT // ZZ
2010-03-19 00:31:15 +00:00
2012-04-19 21:22:08 +00:00
// Note: blendalpha[2] & blendinvalpha[2] are never used !!! The index 2 is changed to 0
// Note: blendalpha[3] & blendinvalpha[3] are special case for dest blending on 24bits. FIXME: I was expected GL_ONE & GL_ZERO ! -- greg
static const u32 blendalpha [ 4 ] = { GL_SRC_ALPHA , GL_DST_ALPHA , GL_CONSTANT_COLOR_EXT , GL_SRC_ALPHA } ; // ZZ
static const u32 blendinvalpha [ 4 ] = { GL_ONE_MINUS_SRC_ALPHA , GL_ONE_MINUS_DST_ALPHA , GL_ONE_MINUS_CONSTANT_COLOR_EXT , GL_ONE_MINUS_SRC_ALPHA } ; //ZZ
2010-03-19 00:31:15 +00:00
static const u32 g_dwAlphaCmp [ ] = { GL_NEVER , GL_ALWAYS , GL_LESS , GL_LEQUAL , GL_EQUAL , GL_GEQUAL , GL_GREATER , GL_NOTEQUAL } ; // ZZ
// used for afail case
static const u32 g_dwReverseAlphaCmp [ ] = { GL_ALWAYS , GL_NEVER , GL_GEQUAL , GL_GREATER , GL_NOTEQUAL , GL_LESS , GL_LEQUAL , GL_EQUAL } ;
static const u32 g_dwZCmp [ ] = { GL_NEVER , GL_ALWAYS , GL_GEQUAL , GL_GREATER } ;
/////////////////////
// graphics resources
# define s_bForceTexFlush 1 // ZZ
2010-07-04 03:53:01 +00:00
static u32 s_ptexCurSet [ 2 ] = { 0 } ;
2010-03-19 00:31:15 +00:00
static u32 s_ptexNextSet [ 2 ] = { 0 } ; // ZZ
int s_ClutResolve = 0 ; // ZZ
int g_nDepthUsed = 0 ; // ffx2 pal movies
int s_nWriteDepthCount = 0 ; // ZZ
int s_nWriteDestAlphaTest = 0 ; // ZZ
2012-04-19 21:22:08 +00:00
int s_nWireframeCount = 0 ;
2010-03-19 00:31:15 +00:00
////////////////////
// State parameters
2010-09-19 08:01:48 +00:00
static float4 vAlphaBlendColor ; // used for GPU_COLOR
2010-07-04 03:53:01 +00:00
static bool bNeedBlendFactorInAlpha ; // set if the output source alpha is different from the real source alpha (only when blend factor > 0x80)
2010-03-19 00:31:15 +00:00
static u32 s_dwColorWrite = 0xf ; // the color write mask of the current target
2012-04-19 21:22:08 +00:00
// g_flag_vars g_vars;
2010-03-19 00:31:15 +00:00
2010-07-04 03:53:01 +00:00
//static alphaInfo s_alphaInfo; // ZZ
2010-04-25 00:31:27 +00:00
2012-04-19 21:22:08 +00:00
int g_PrevBitwiseTexX = - 1 , g_PrevBitwiseTexY = - 1 ; // textures stored in SAMP_BITWISEANDX and SAMP_BITWISEANDY // ZZ
2010-05-01 20:33:53 +00:00
float fiTexWidth [ 2 ] , fiTexHeight [ 2 ] ; // current tex width and height
2012-04-19 21:22:08 +00:00
Point AA = { 0 , 0 } ; // if AA.y is set, then AA.x has to be set.
2010-03-19 00:31:15 +00:00
2012-04-19 21:22:08 +00:00
VB vb [ 2 ] ;
2010-05-01 20:33:53 +00:00
int icurctx = - 1 ;
2010-03-19 00:31:15 +00:00
2012-04-19 21:22:08 +00:00
void Draw ( const VB & curvb )
{
2012-05-15 06:45:26 +00:00
# ifdef GLSL4_API
ZZshSetupShader ( ) ;
# endif
2012-04-19 21:22:08 +00:00
glDrawArrays ( primtype [ curvb . curprim . prim ] , 0 , curvb . nCount ) ;
}
2010-03-19 00:31:15 +00:00
2010-05-01 20:33:53 +00:00
inline float AlphaReferedValue ( int aref )
{
2012-04-19 21:22:08 +00:00
// return (b2XAlphaTest) ? min(1.0f, (float)aref / 127.5f) : (float)aref / 255.0f ;
return min ( 1.0f , ( float ) aref / 127.5f ) ;
2010-03-19 00:31:15 +00:00
}
2010-05-01 20:33:53 +00:00
inline void SetAlphaTest ( const pixTest & curtest )
{
2010-03-19 00:31:15 +00:00
// if s_dwColorWrite is nontrivial, than we should not off alphatest.
// This fix GOW and Okami.
2010-05-01 20:33:53 +00:00
if ( ! curtest . ate & & USEALPHATESTING & & ( s_dwColorWrite ! = 2 & & s_dwColorWrite ! = 14 ) )
{
2010-03-19 00:31:15 +00:00
glDisable ( GL_ALPHA_TEST ) ;
}
2010-05-01 20:33:53 +00:00
else
{
2010-03-19 00:31:15 +00:00
glEnable ( GL_ALPHA_TEST ) ;
glAlphaFunc ( g_dwAlphaCmp [ curtest . atst ] , AlphaReferedValue ( curtest . aref ) ) ;
}
}
2010-09-15 16:54:19 +00:00
// Return, if tcc, aem or psm mode told us, than Alpha test should be used
// if tcc == 0 than no alpha used, aem used for alpha expanding and I am not sure
// that it's correct, psm -- color mode,
inline bool IsAlphaTestExpansion ( tex0Info tex0 )
{
return ( tex0 . tcc & & gs . texa . aem & & PSMT_ALPHAEXP ( PIXEL_STORAGE_FORMAT ( tex0 ) ) ) ;
}
2010-03-19 00:31:15 +00:00
// Switch wireframe rendering off for first flush, so it's draw few solid primitives
2010-05-01 20:33:53 +00:00
inline void SwitchWireframeOff ( )
{
2010-06-19 06:23:40 +00:00
if ( conf . wireframe ( ) )
2010-05-01 20:33:53 +00:00
{
if ( s_nWireframeCount > 0 )
{
2010-03-19 00:31:15 +00:00
glPolygonMode ( GL_FRONT_AND_BACK , GL_FILL ) ;
}
}
}
// Switch wireframe rendering on, look at previous function
2010-05-01 20:33:53 +00:00
inline void SwitchWireframeOn ( )
{
2010-06-19 06:23:40 +00:00
if ( conf . wireframe ( ) )
2010-05-01 20:33:53 +00:00
{
if ( s_nWireframeCount > 0 )
{
2010-03-19 00:31:15 +00:00
glPolygonMode ( GL_FRONT_AND_BACK , GL_LINE ) ;
- - s_nWireframeCount ;
}
}
}
2010-10-17 08:47:31 +00:00
extern u32 ptexBilinearBlocks ;
2010-03-19 00:31:15 +00:00
int GetTexFilter ( const tex1Info & tex1 )
{
// always force
2010-05-01 20:33:53 +00:00
if ( conf . bilinear = = 2 ) return 1 ;
2010-03-19 00:31:15 +00:00
int texfilter = 0 ;
2010-05-01 20:33:53 +00:00
if ( conf . bilinear & & ptexBilinearBlocks ! = 0 )
{
if ( tex1 . mmin < = 1 )
texfilter = tex1 . mmin | tex1 . mmag ;
2010-03-19 00:31:15 +00:00
else
2010-05-01 20:33:53 +00:00
texfilter = tex1 . mmag ? ( ( tex1 . mmin + 2 ) & 5 ) : tex1 . mmin ;
2010-03-19 00:31:15 +00:00
texfilter = texfilter = = 1 | | texfilter = = 4 | | texfilter = = 5 ;
}
2010-05-01 20:33:53 +00:00
2010-03-19 00:31:15 +00:00
return texfilter ;
}
2010-10-16 11:54:46 +00:00
void ReloadEffects ( )
2010-03-19 00:31:15 +00:00
{
2010-04-25 09:02:36 +00:00
# ifdef ZEROGS_DEVBUILD
2010-05-01 20:33:53 +00:00
2013-06-28 17:32:37 +00:00
for ( u32 i = 0 ; i < ArraySize ( ppsTexture ) ; + + i )
2010-05-01 20:33:53 +00:00
{
2010-03-19 00:31:15 +00:00
SAFE_RELEASE_PROG ( ppsTexture [ i ] . prog ) ;
}
2010-05-01 20:33:53 +00:00
2010-03-19 00:31:15 +00:00
memset ( ppsTexture , 0 , sizeof ( ppsTexture ) ) ;
2010-05-01 20:33:53 +00:00
2010-09-19 08:01:48 +00:00
ZZshLoadExtraEffects ( ) ;
2010-03-19 00:31:15 +00:00
# endif
}
long BufferNumber = 0 ;
2010-04-25 09:02:36 +00:00
// This is a debug function. It prints all buffer info and save current texture into the file, then prints the file name.
2010-05-01 20:33:53 +00:00
inline void VisualBufferMessage ( int context )
{
2010-04-25 08:33:05 +00:00
# if defined(WRITE_PRIM_LOGS) && defined(_DEBUG)
2010-03-19 00:31:15 +00:00
BufferNumber + + ;
2010-10-16 11:54:46 +00:00
VB & curvb = vb [ context ] ;
2010-03-19 00:31:15 +00:00
static const char * patst [ 8 ] = { " NEVER " , " ALWAYS " , " LESS " , " LEQUAL " , " EQUAL " , " GEQUAL " , " GREATER " , " NOTEQUAL " } ;
static const char * pztst [ 4 ] = { " NEVER " , " ALWAYS " , " GEQUAL " , " GREATER " } ;
static const char * pafail [ 4 ] = { " KEEP " , " FB_ONLY " , " ZB_ONLY " , " RGB_ONLY " } ;
2010-06-21 12:03:14 +00:00
ZZLog : : Debug_Log ( " **Drawing ctx %d, num %d, fbp: 0x%x, zbp: 0x%x, fpsm: %d, zpsm: %d, fbw: %d " , context , vb [ context ] . nCount , curvb . prndr - > fbp , curvb . zbuf . zbp , curvb . prndr - > psm , curvb . zbuf . psm , curvb . prndr - > fbw ) ;
ZZLog : : Debug_Log ( " prim: prim=%x iip=%x tme=%x fge=%x abe=%x aa1=%x fst=%x ctxt=%x fix=%x " ,
2010-05-01 20:33:53 +00:00
curvb . curprim . prim , curvb . curprim . iip , curvb . curprim . tme , curvb . curprim . fge , curvb . curprim . abe , curvb . curprim . aa1 , curvb . curprim . fst , curvb . curprim . ctxt , curvb . curprim . fix ) ;
2010-06-21 12:03:14 +00:00
ZZLog : : Debug_Log ( " test: ate:%d, atst: %s, aref: %d, afail: %s, date: %d, datm: %d, zte: %d, ztst: %s, fba: %d " ,
2010-05-01 20:33:53 +00:00
curvb . test . ate , patst [ curvb . test . atst ] , curvb . test . aref , pafail [ curvb . test . afail ] , curvb . test . date , curvb . test . datm , curvb . test . zte , pztst [ curvb . test . ztst ] , curvb . fba . fba ) ;
2010-06-21 12:03:14 +00:00
ZZLog : : Debug_Log ( " alpha: A%d B%d C%d D%d FIX:%d pabe: %d; aem: %d, ta0: %d, ta1: %d \n " , curvb . alpha . a , curvb . alpha . b , curvb . alpha . c , curvb . alpha . d , curvb . alpha . fix , gs . pabe , gs . texa . aem , gs . texa . ta [ 0 ] , gs . texa . ta [ 1 ] ) ;
ZZLog : : Debug_Log ( " tex0: tbp0=0x%x, tbw=%d, psm=0x%x, tw=%d, th=%d, tcc=%d, tfx=%d, cbp=0x%x, cpsm=0x%x, csm=%d, csa=%d, cld=%d " ,
2010-05-01 20:33:53 +00:00
curvb . tex0 . tbp0 , curvb . tex0 . tbw , curvb . tex0 . psm , curvb . tex0 . tw ,
curvb . tex0 . th , curvb . tex0 . tcc , curvb . tex0 . tfx , curvb . tex0 . cbp ,
curvb . tex0 . cpsm , curvb . tex0 . csm , curvb . tex0 . csa , curvb . tex0 . cld ) ;
2010-03-19 00:31:15 +00:00
char * Name ;
2010-05-01 20:33:53 +00:00
Name = NamedSaveTex ( & curvb . tex0 , 1 ) ;
ZZLog : : Error_Log ( " TGA name '%s'. " , Name ) ;
free ( Name ) ;
2010-07-04 03:53:01 +00:00
ZZLog : : Debug_Log ( " buffer %ld. \n " , BufferNumber ) ;
2010-03-19 00:31:15 +00:00
# endif
}
2010-05-01 20:33:53 +00:00
inline void SaveRendererTarget ( VB & curvb )
{
2010-03-19 00:31:15 +00:00
# ifdef _DEBUG
2010-05-01 20:33:53 +00:00
2010-10-17 08:47:31 +00:00
// Needs a # after rndr to work...
2010-07-04 03:53:01 +00:00
// char str[255];
2010-10-17 08:47:31 +00:00
// sprintf(str, "rndr.tga");
2010-07-04 03:53:01 +00:00
// SaveRenderTarget(str, curvb.prndr->fbw, curvb.prndr->fbh, 0);
2010-05-01 20:33:53 +00:00
2010-03-19 00:31:15 +00:00
# endif
}
// Stop effects in Developers mode
2010-05-01 20:33:53 +00:00
inline void FlushUpdateEffect ( )
{
2010-04-25 09:02:36 +00:00
# if defined(DEVBUILD)
2010-05-01 20:33:53 +00:00
if ( g_bUpdateEffect )
{
2010-03-19 00:31:15 +00:00
ReloadEffects ( ) ;
g_bUpdateEffect = 0 ;
}
2010-05-01 20:33:53 +00:00
2010-03-19 00:31:15 +00:00
# endif
}
2012-04-19 21:22:08 +00:00
// Check, maybe we could skip flush
2010-05-01 20:33:53 +00:00
inline bool IsFlushNoNeed ( VB & curvb , const pixTest & curtest )
{
2010-08-22 10:48:23 +00:00
if ( curvb . nCount = = 0 | | ( curtest . zte & & curtest . ztst = = 0 ) | | IsBadFrame ( curvb ) )
2010-05-01 20:33:53 +00:00
{
2010-03-19 00:31:15 +00:00
curvb . nCount = 0 ;
return true ;
}
2010-05-01 20:33:53 +00:00
2010-03-19 00:31:15 +00:00
return false ;
}
2010-04-25 00:31:27 +00:00
// Transfer targets, that are located in current texture.
2010-05-01 20:33:53 +00:00
inline void FlushTransferRangesHelper ( VB & curvb )
{
if ( s_RangeMngr . ranges . size ( ) > 0 )
{
2010-03-19 00:31:15 +00:00
// don't want infinite loop, so set nCount to 0.
u32 prevcount = curvb . nCount ;
curvb . nCount = 0 ;
FlushTransferRanges ( curvb . curprim . tme ? & curvb . tex0 : NULL ) ;
curvb . nCount + = prevcount ;
}
}
2010-07-10 06:04:32 +00:00
// If set bit for texture checking, do it. Maybe it's all.
2010-05-01 20:33:53 +00:00
inline bool FushTexDataHelper ( VB & curvb )
{
if ( curvb . bNeedFrameCheck | | curvb . bNeedZCheck )
{
2010-03-19 00:31:15 +00:00
curvb . CheckFrame ( curvb . curprim . tme ? curvb . tex0 . tbp0 : 0 ) ;
}
2010-05-01 20:33:53 +00:00
if ( curvb . bNeedTexCheck ) // Zeydlitz want to try this
{
2010-03-19 00:31:15 +00:00
curvb . FlushTexData ( ) ;
2010-05-01 20:33:53 +00:00
if ( curvb . nCount = = 0 ) return true ;
2010-03-19 00:31:15 +00:00
}
2010-05-01 20:33:53 +00:00
2010-03-19 00:31:15 +00:00
return false ;
}
// Null target mean that we do something really bad.
2010-05-01 20:33:53 +00:00
inline bool FlushCheckForNULLTarget ( VB & curvb , int context )
{
if ( ( curvb . prndr = = NULL ) | | ( curvb . pdepth = = NULL ) )
{
2010-03-19 00:31:15 +00:00
ERROR_LOG_SPAMA ( " Current render target NULL (ctx: %d) " , context ) ;
curvb . nCount = 0 ;
return true ;
}
2010-05-01 20:33:53 +00:00
2010-03-19 00:31:15 +00:00
return false ;
}
// O.k. A set of resolutions, we do before real flush. We do RangeManager, FrameCheck and
2010-04-25 00:31:27 +00:00
// ZCheck before this.
2010-05-01 20:33:53 +00:00
inline bool FlushInitialTest ( VB & curvb , const pixTest & curtest , int context )
{
2010-03-19 00:31:15 +00:00
GL_REPORT_ERRORD ( ) ;
2010-05-01 20:33:53 +00:00
assert ( context > = 0 & & context < = 1 ) ;
2010-03-19 00:31:15 +00:00
FlushUpdateEffect ( ) ;
2010-05-01 20:33:53 +00:00
if ( IsFlushNoNeed ( curvb , curtest ) ) return true ;
2010-03-19 00:31:15 +00:00
FlushTransferRangesHelper ( curvb ) ;
2010-05-01 20:33:53 +00:00
if ( FushTexDataHelper ( curvb ) ) return true ;
2010-03-19 00:31:15 +00:00
GL_REPORT_ERRORD ( ) ;
2010-05-01 20:33:53 +00:00
if ( FlushCheckForNULLTarget ( curvb , context ) ) return true ;
2010-03-19 00:31:15 +00:00
return false ;
}
2010-12-12 00:33:10 +00:00
inline void TargetLog ( int & tbw , int & tbp0 , int & tpsm , VB & curvb , bool miss )
2010-12-02 11:12:42 +00:00
{
# ifdef _DEBUG
if ( tbp0 = = 0x3600 & & tbw = = 0x100 )
{
2010-12-12 00:33:10 +00:00
if ( miss )
2010-12-02 11:12:42 +00:00
{
ZZLog : : Debug_Log ( " Miss %x 0x%x %d " , tbw , tbp0 , tpsm ) ;
typedef map < u32 , CRenderTarget * > MAPTARGETS ;
for ( MAPTARGETS : : iterator itnew = s_RTs . mapTargets . begin ( ) ; itnew ! = s_RTs . mapTargets . end ( ) ; + + itnew )
{
ZZLog : : Debug_Log ( " \t Render %x 0x%x %x " , itnew - > second - > fbw , itnew - > second - > fbp , itnew - > second - > psm ) ;
}
for ( MAPTARGETS : : iterator itnew = s_DepthRTs . mapTargets . begin ( ) ; itnew ! = s_DepthRTs . mapTargets . end ( ) ; + + itnew )
{
ZZLog : : Debug_Log ( " \t Depth %x 0x%x %x " , itnew - > second - > fbw , itnew - > second - > fbp , itnew - > second - > psm ) ;
}
ZZLog : : Debug_Log ( " \t Curvb 0x%x 0x%x 0x%x %x " , curvb . frame . fbp , curvb . prndr - > end , curvb . prndr - > fbp , curvb . prndr - > fbw ) ;
}
else
ZZLog : : Debug_Log ( " Hit %x 0x%x %x " , tbw , tbp0 , tpsm ) ;
}
# endif
}
2010-03-19 00:31:15 +00:00
// Try to different approach if texture target was not found
2010-05-01 20:33:53 +00:00
inline CRenderTarget * FlushReGetTarget ( int & tbw , int & tbp0 , int & tpsm , VB & curvb )
{
2010-03-19 00:31:15 +00:00
// This was incorrect code
CRenderTarget * ptextarg = NULL ;
2010-12-02 11:12:42 +00:00
if ( PSMT_ISZTEX ( tpsm ) )
{
// try depth
ptextarg = s_DepthRTs . GetTarg ( tbp0 , tbw ) ;
}
// I wonder if either of these hacks are useful, or if I can just remove them?
if ( ( conf . settings ( ) . reget ) & & ( tpsm = = PSMT8 ) )
2010-05-01 20:33:53 +00:00
{
2010-03-19 00:31:15 +00:00
// check for targets with half the width. Break Valkyrie Chronicles
2010-10-23 08:15:39 +00:00
ptextarg = s_RTs . GetTarg ( tbp0 , tbw / 2 ) ;
2010-05-01 20:33:53 +00:00
if ( ptextarg = = NULL )
{
2010-03-19 00:31:15 +00:00
tbp0 & = ~ 0x7ff ;
2010-10-23 08:15:39 +00:00
ptextarg = s_RTs . GetTarg ( tbp0 , tbw / 2 ) ; // mgs3 hack
2010-03-19 00:31:15 +00:00
2010-05-01 20:33:53 +00:00
if ( ptextarg = = NULL )
{
2010-03-19 00:31:15 +00:00
// check the next level (mgs3)
tbp0 & = ~ 0xfff ;
2010-10-23 08:15:39 +00:00
ptextarg = s_RTs . GetTarg ( tbp0 , tbw / 2 ) ; // mgs3 hack
2010-03-19 00:31:15 +00:00
}
2010-05-01 20:33:53 +00:00
if ( ptextarg ! = NULL & & ptextarg - > start > tbp0 * 256 )
{
2010-03-19 00:31:15 +00:00
// target beyond range, so ignore
ptextarg = NULL ;
}
}
}
2010-12-02 11:12:42 +00:00
if ( ( conf . settings ( ) . texture_targs ) & & ( ptextarg = = NULL ) )
2010-05-01 20:33:53 +00:00
{
2010-03-19 00:31:15 +00:00
// check if any part of the texture intersects the current target
2010-05-01 20:33:53 +00:00
if ( ! PSMT_ISCLUT ( tpsm ) & & ( curvb . tex0 . tbp0 > = curvb . frame . fbp ) & & ( ( curvb . tex0 . tbp0 ) < curvb . prndr - > end ) )
{
2010-03-19 00:31:15 +00:00
ptextarg = curvb . prndr ;
}
}
2010-12-02 11:12:42 +00:00
2010-12-12 00:33:10 +00:00
TargetLog ( tbw , tbp0 , tpsm , curvb , ( ptextarg = = NULL ) ) ;
2010-03-19 00:31:15 +00:00
return ptextarg ;
}
2010-12-02 11:12:42 +00:00
// Find target to draw a texture.
2010-05-01 20:33:53 +00:00
inline CRenderTarget * FlushGetTarget ( VB & curvb )
{
2010-03-19 00:31:15 +00:00
int tbw , tbp0 , tpsm ;
CRenderTarget * ptextarg = NULL ;
2010-12-02 11:12:42 +00:00
if ( ! curvb . curprim . tme ) return ptextarg ; // Which would be NULL, currently.
2010-05-01 20:33:53 +00:00
if ( curvb . bNeedTexCheck )
{
2010-10-16 11:10:48 +00:00
ZZLog : : Error_Log ( " How it is possible? " ) ;
2010-03-19 00:31:15 +00:00
// not yet initied, but still need to get correct target! (xeno3 ingame)
tbp0 = ZZOglGet_tbp0_TexBits ( curvb . uNextTex0Data [ 0 ] ) ;
tbw = ZZOglGet_tbw_TexBitsMult ( curvb . uNextTex0Data [ 0 ] ) ;
tpsm = ZZOglGet_psm_TexBitsFix ( curvb . uNextTex0Data [ 0 ] ) ;
}
2010-05-01 20:33:53 +00:00
else
{
2010-03-19 00:31:15 +00:00
tbw = curvb . tex0 . tbw ;
tbp0 = curvb . tex0 . tbp0 ;
tpsm = curvb . tex0 . psm ;
}
2010-10-23 08:15:39 +00:00
ptextarg = s_RTs . GetTarg ( tbp0 , tbw ) ;
2010-05-01 20:33:53 +00:00
2010-12-02 11:12:42 +00:00
if ( ptextarg = = NULL ) ptextarg = FlushReGetTarget ( tbw , tbp0 , tpsm , curvb ) ;
2010-04-25 00:31:27 +00:00
2010-05-01 20:33:53 +00:00
if ( ( ptextarg ! = NULL ) & & ! ( ptextarg - > status & CRenderTarget : : TS_NeedUpdate ) )
{
if ( PSMT_BITMODE ( tpsm ) = = 4 ) // handle 8h cluts
{
2010-03-19 00:31:15 +00:00
// don't support clut targets, read from mem
// 4hl - kh2 check - from dx version -- arcum42
2010-05-01 20:33:53 +00:00
if ( tpsm = = PSMT4 & & s_ClutResolve < = 1 )
{
// xenosaga requires 2 resolves
2010-03-19 00:31:15 +00:00
u32 prevcount = curvb . nCount ;
curvb . nCount = 0 ;
ptextarg - > Resolve ( ) ;
s_ClutResolve + + ;
curvb . nCount + = prevcount ;
}
2010-05-01 20:33:53 +00:00
2010-03-19 00:31:15 +00:00
ptextarg = NULL ;
}
2010-05-01 20:33:53 +00:00
else
{
if ( ptextarg = = curvb . prndr )
{
2010-03-19 00:31:15 +00:00
// need feedback
curvb . prndr - > CreateFeedback ( ) ;
if ( s_bWriteDepth & & ( curvb . pdepth ! = NULL ) )
curvb . pdepth - > SetRenderTarget ( 1 ) ;
else
ResetRenderTarget ( 1 ) ;
}
}
}
2010-05-01 20:33:53 +00:00
else
{
2010-12-02 11:12:42 +00:00
// If a texture needs updating, clear it.
2010-05-01 20:33:53 +00:00
ptextarg = NULL ;
}
2010-04-25 00:31:27 +00:00
2010-03-19 00:31:15 +00:00
return ptextarg ;
}
// Set target for current context
2010-05-01 20:33:53 +00:00
inline void FlushSetContextTarget ( VB & curvb , int context )
{
if ( ! curvb . bVarsSetTarg )
{
2010-03-19 00:31:15 +00:00
SetContextTarget ( context ) ;
2010-05-01 20:33:53 +00:00
}
else
{
assert ( curvb . pdepth ! = NULL ) ;
2010-04-25 00:31:27 +00:00
2010-05-01 20:33:53 +00:00
if ( curvb . pdepth - > status & CRenderTarget : : TS_Virtual )
{
if ( ! curvb . zbuf . zmsk )
{
2014-06-13 20:38:04 +00:00
# ifdef NDEBUG
s_DepthRTs . Promote ( GetFrameKey ( curvb . pdepth ) ) ;
# else
2010-03-19 00:31:15 +00:00
CRenderTarget * ptemp = s_DepthRTs . Promote ( GetFrameKey ( curvb . pdepth ) ) ;
2010-05-01 20:33:53 +00:00
assert ( ptemp = = curvb . pdepth ) ;
2014-06-13 20:38:04 +00:00
# endif
2010-03-19 00:31:15 +00:00
}
else
2010-05-01 20:33:53 +00:00
{
2010-03-19 00:31:15 +00:00
curvb . pdepth - > status & = ~ CRenderTarget : : TS_NeedUpdate ;
2010-05-01 20:33:53 +00:00
}
2010-03-19 00:31:15 +00:00
}
2010-05-01 20:33:53 +00:00
if ( ( curvb . pdepth - > status & CRenderTarget : : TS_NeedUpdate ) | | ( curvb . prndr - > status & CRenderTarget : : TS_NeedUpdate ) )
2010-03-19 00:31:15 +00:00
SetContextTarget ( context ) ;
}
2010-05-01 20:33:53 +00:00
assert ( ! ( curvb . prndr - > status & CRenderTarget : : TS_NeedUpdate ) ) ;
2010-03-19 00:31:15 +00:00
curvb . prndr - > status = 0 ;
2010-04-25 00:31:27 +00:00
2010-05-01 20:33:53 +00:00
if ( curvb . pdepth ! = NULL )
{
2010-07-07 10:14:42 +00:00
# ifdef _DEBUG
// Reduce an assert to a warning.
if ( curvb . pdepth - > status & CRenderTarget : : TS_NeedUpdate )
{
2010-07-07 10:41:17 +00:00
ZZLog : : Debug_Log ( " In FlushSetContextTarget, pdepth has TS_NeedUpdate set. " ) ;
2010-07-07 10:14:42 +00:00
}
# endif
2010-05-01 20:33:53 +00:00
if ( ! curvb . zbuf . zmsk )
{
assert ( ! ( curvb . pdepth - > status & CRenderTarget : : TS_Virtual ) ) ;
2010-03-19 00:31:15 +00:00
curvb . pdepth - > status = 0 ;
}
}
}
2010-05-01 20:33:53 +00:00
inline void FlushSetStream ( VB & curvb )
{
2012-04-19 21:22:08 +00:00
// setup current buffer
2010-03-19 00:31:15 +00:00
glBindBuffer ( GL_ARRAY_BUFFER , g_vboBuffers [ g_nCurVBOIndex ] ) ;
glBufferData ( GL_ARRAY_BUFFER , curvb . nCount * sizeof ( VertexGPU ) , curvb . pBufferData , GL_STREAM_DRAW ) ;
2012-04-19 21:22:08 +00:00
g_nCurVBOIndex = ( g_nCurVBOIndex + 1 ) % ArraySize ( g_vboBuffers ) ;
2010-03-19 00:31:15 +00:00
// void* pdata = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
2014-08-27 03:45:23 +00:00
// memcpy(pdata, curvb.pBufferData, curvb.nCount * sizeof(VertexGPU));
2010-03-19 00:31:15 +00:00
// glUnmapBuffer(GL_ARRAY_BUFFER);
SET_STREAM ( ) ;
2010-06-15 11:20:52 +00:00
GL_REPORT_ERRORD ( ) ;
2010-03-19 00:31:15 +00:00
}
2010-05-01 20:33:53 +00:00
// Set color mask. Really, it's not as good as PS2 one.
inline void FlushSetColorMask ( VB & curvb )
{
s_dwColorWrite = ( PSMT_BITMODE ( curvb . prndr - > psm ) = = 1 ) ? ( COLORMASK_BLUE | COLORMASK_GREEN | COLORMASK_RED ) : 0xf ;
2010-03-19 00:31:15 +00:00
int maskR = ZZOglGet_fbmRed_FrameBits ( curvb . frame . fbm ) ;
int maskG = ZZOglGet_fbmGreen_FrameBits ( curvb . frame . fbm ) ;
int maskB = ZZOglGet_fbmBlue_FrameBits ( curvb . frame . fbm ) ;
int maskA = ZZOglGet_fbmAlpha_FrameBits ( curvb . frame . fbm ) ;
2010-05-01 20:33:53 +00:00
if ( maskR = = 0xff ) s_dwColorWrite & = ~ COLORMASK_RED ;
if ( maskG = = 0xff ) s_dwColorWrite & = ~ COLORMASK_GREEN ;
if ( maskB = = 0xff ) s_dwColorWrite & = ~ COLORMASK_BLUE ;
2012-04-19 21:22:08 +00:00
if ( ( maskA = = 0xff ) | | ( curvb . curprim . abe & & ( curvb . test . atst = = ATST_LESS & & curvb . test . aref = = 128 ) ) )
2010-03-19 00:31:15 +00:00
s_dwColorWrite & = ~ COLORMASK_ALPHA ;
GL_COLORMASK ( s_dwColorWrite ) ;
}
// Set Scissors for scissor test.
2010-05-01 20:33:53 +00:00
inline void FlushSetScissorRect ( VB & curvb )
{
2010-03-19 00:31:15 +00:00
Rect & scissor = curvb . prndr - > scissorrect ;
glScissor ( scissor . x , scissor . y , scissor . w , scissor . h ) ;
}
// Prior really doing something check context
2010-05-01 20:33:53 +00:00
inline void FlushDoContextJob ( VB & curvb , int context )
{
2010-03-19 00:31:15 +00:00
SaveRendererTarget ( curvb ) ;
FlushSetContextTarget ( curvb , context ) ;
icurctx = context ;
2010-04-25 00:31:27 +00:00
2010-03-19 00:31:15 +00:00
FlushSetStream ( curvb ) ;
FlushSetColorMask ( curvb ) ;
FlushSetScissorRect ( curvb ) ;
}
// Set 1 is Alpha test is EQUAL and alpha should be proceed with care.
2010-05-01 20:33:53 +00:00
inline int FlushGetExactcolor ( const pixTest curtest )
{
2010-03-19 00:31:15 +00:00
if ( ! ( g_nPixelShaderVer & SHADER_REDUCED ) )
// ffx2 breaks when ==7
2012-04-19 21:22:08 +00:00
return ( ( curtest . ate & & curtest . aref < = 128 ) & & ( curtest . atst = = ATST_EQUAL ) ) ; // || curtest.atst == ATST_NOTEQUAL);
2010-04-25 00:31:27 +00:00
2010-03-19 00:31:15 +00:00
return 0 ;
}
// fill the buffer by decoding the clut
2010-05-01 20:33:53 +00:00
inline void FlushDecodeClut ( VB & curvb , GLuint & ptexclut )
{
2010-03-19 00:31:15 +00:00
glGenTextures ( 1 , & ptexclut ) ;
glBindTexture ( GL_TEXTURE_2D , ptexclut ) ;
2010-05-01 20:33:53 +00:00
if ( ptexclut ! = 0 )
{
2010-12-20 19:57:50 +00:00
int clutsize ;
2010-03-19 00:31:15 +00:00
int entries = PSMT_IS8CLUT ( curvb . tex0 . psm ) ? 256 : 16 ;
2010-04-25 00:31:27 +00:00
2011-01-25 19:29:08 +00:00
if ( curvb . tex0 . csm & & curvb . tex0 . csa ) ZZLog : : Debug_Log ( " ERROR, csm1. " ) ;
2010-03-19 00:31:15 +00:00
2010-12-20 19:57:50 +00:00
if ( PSMT_IS32BIT ( curvb . tex0 . cpsm ) ) {
2011-01-25 19:29:08 +00:00
__aligned16 u32 data [ 256 ] ;
2010-03-19 00:31:15 +00:00
clutsize = min ( entries , 256 - curvb . tex0 . csa * 16 ) * 4 ;
2011-01-25 19:29:08 +00:00
ClutBuffer_to_Array < u32 > ( ( u32 * ) data , curvb . tex0 . csa , clutsize ) ;
Texture2D ( 4 , 256 , 1 , GL_RGBA , GL_UNSIGNED_BYTE , data ) ;
2010-12-20 19:57:50 +00:00
} else {
2011-01-25 19:29:08 +00:00
__aligned16 u16 data [ 256 ] ;
2010-03-19 00:31:15 +00:00
clutsize = min ( entries , 512 - curvb . tex0 . csa * 16 ) * 2 ;
2011-01-25 19:29:08 +00:00
ClutBuffer_to_Array < u16 > ( ( u16 * ) data , curvb . tex0 . csa , clutsize ) ;
Texture2D ( 4 , 256 , 1 , GL_RGBA , GL_UNSIGNED_SHORT_5_5_5_1 , data ) ;
2010-12-20 19:57:50 +00:00
}
2010-03-19 00:31:15 +00:00
s_vecTempTextures . push_back ( ptexclut ) ;
2010-04-25 00:31:27 +00:00
2010-05-01 20:33:53 +00:00
if ( g_bSaveTex ) SaveTexture ( " clut.tga " , GL_TEXTURE_2D , ptexclut , 256 , 1 ) ;
2010-03-19 00:31:15 +00:00
2010-06-19 12:59:51 +00:00
setTex2DWrap ( GL_REPEAT ) ;
setTex2DFilters ( GL_LINEAR ) ;
2010-03-19 00:31:15 +00:00
}
}
2010-05-01 20:33:53 +00:00
inline int FlushGetShaderType ( VB & curvb , CRenderTarget * ptextarg , GLuint & ptexclut )
{
2010-06-19 08:46:40 +00:00
if ( PSMT_ISCLUT ( curvb . tex0 . psm ) & & ! ( conf . settings ( ) . no_target_clut ) )
2010-05-01 20:33:53 +00:00
{
2010-03-19 00:31:15 +00:00
FlushDecodeClut ( curvb , ptexclut ) ;
2010-05-01 20:33:53 +00:00
if ( ! ( g_nPixelShaderVer & SHADER_REDUCED ) & & PSMT_ISHALF ( ptextarg - > psm ) )
{
2010-03-19 00:31:15 +00:00
return 4 ;
}
2010-05-01 20:33:53 +00:00
else
{
2010-04-25 00:31:27 +00:00
// Valkyrie
2010-03-19 00:31:15 +00:00
return 2 ;
}
2010-04-25 00:31:27 +00:00
}
2010-03-19 00:31:15 +00:00
2010-05-01 20:33:53 +00:00
if ( PSMT_ISHALF_STORAGE ( curvb . tex0 ) ! = PSMT_ISHALF ( ptextarg - > psm ) & & ( ! ( g_nPixelShaderVer & SHADER_REDUCED ) | | ! curvb . curprim . fge ) )
{
if ( PSMT_ISHALF_STORAGE ( curvb . tex0 ) )
{
2010-03-19 00:31:15 +00:00
// converting from 32->16
// Radiata Chronicles
return 3 ;
}
2010-05-01 20:33:53 +00:00
else
{
2010-03-19 00:31:15 +00:00
// converting from 16->32
// Star Ward: Force
return 0 ;
}
}
2010-05-01 20:33:53 +00:00
2010-03-19 00:31:15 +00:00
return 1 ;
}
2010-07-04 03:53:01 +00:00
//Set page offsets depends on shader type.
2013-07-03 18:42:05 +00:00
inline void FlushSetPageOffset ( FRAGMENTSHADER * pfragment , int shadertype , CRenderTarget * ptextarg )
2010-05-01 20:33:53 +00:00
{
2010-03-19 00:31:15 +00:00
SetShaderCaller ( " FlushSetPageOffset " ) ;
2010-09-19 08:01:48 +00:00
float4 vpageoffset ;
2010-03-19 00:31:15 +00:00
vpageoffset . w = 0 ;
2010-05-01 20:33:53 +00:00
switch ( shadertype )
{
case 3 :
vpageoffset . x = - 0.1f / 256.0f ;
vpageoffset . y = - 0.001f / 256.0f ;
vpageoffset . z = - 0.1f / ( ptextarg - > fbh ) ;
vpageoffset . w = 0.0f ;
break ;
case 4 :
vpageoffset . x = 2 ;
vpageoffset . y = 1 ;
vpageoffset . z = 0 ;
vpageoffset . w = 0.0001f ;
break ;
2010-03-19 00:31:15 +00:00
}
2010-05-01 20:33:53 +00:00
2010-03-19 00:31:15 +00:00
// zoe2
2010-05-01 20:33:53 +00:00
if ( PSMT_ISZTEX ( ptextarg - > psm ) ) vpageoffset . w = - 1.0f ;
2010-03-19 00:31:15 +00:00
2012-05-07 19:51:58 +00:00
ZZshSetParameter4fv ( pfragment - > prog , pfragment - > fPageOffset , vpageoffset , " g_fPageOffset " ) ;
2010-03-19 00:31:15 +00:00
}
2012-04-19 21:22:08 +00:00
//Setting texture offsets depends on shader type.
2013-07-03 18:42:05 +00:00
inline void FlushSetTexOffset ( FRAGMENTSHADER * pfragment , int shadertype , VB & curvb , CRenderTarget * ptextarg )
2010-05-01 20:33:53 +00:00
{
2010-03-19 00:31:15 +00:00
SetShaderCaller ( " FlushSetTexOffset " ) ;
2010-09-19 08:01:48 +00:00
float4 v ;
2010-05-01 20:33:53 +00:00
if ( shadertype = = 3 )
{
2010-09-19 08:01:48 +00:00
float4 v ;
2010-03-19 00:31:15 +00:00
v . x = 16.0f / ( float ) curvb . tex0 . tw ;
v . y = 16.0f / ( float ) curvb . tex0 . th ;
v . z = 0.5f * v . x ;
v . w = 0.5f * v . y ;
2012-05-07 19:51:58 +00:00
ZZshSetParameter4fv ( pfragment - > prog , pfragment - > fTexOffset , v , " g_fTexOffset " ) ;
2010-03-19 00:31:15 +00:00
}
2010-05-01 20:33:53 +00:00
else if ( shadertype = = 4 )
{
2010-09-19 08:01:48 +00:00
float4 v ;
2010-03-19 00:31:15 +00:00
v . x = 16.0f / ( float ) ptextarg - > fbw ;
v . y = 16.0f / ( float ) ptextarg - > fbh ;
v . z = - 1 ;
v . w = 8.0f / ( float ) ptextarg - > fbh ;
2012-05-07 19:51:58 +00:00
ZZshSetParameter4fv ( pfragment - > prog , pfragment - > fTexOffset , v , " g_fTexOffset " ) ;
2010-03-19 00:31:15 +00:00
}
}
// Set dimension (Real!) of texture. z and w
2013-07-03 18:42:05 +00:00
inline void FlushTextureDims ( FRAGMENTSHADER * pfragment , int shadertype , VB & curvb , CRenderTarget * ptextarg )
2010-05-01 20:33:53 +00:00
{
2010-03-19 00:31:15 +00:00
SetShaderCaller ( " FlushTextureDims " ) ;
2010-09-19 08:01:48 +00:00
float4 vTexDims ;
2010-03-19 00:31:15 +00:00
vTexDims . x = ( float ) RW ( curvb . tex0 . tw ) ;
vTexDims . y = ( float ) RH ( curvb . tex0 . th ) ;
// look at the offset of tbp0 from fbp
2010-05-01 20:33:53 +00:00
if ( curvb . tex0 . tbp0 < = ptextarg - > fbp )
{
2010-03-19 00:31:15 +00:00
vTexDims . z = 0 ; //-0.5f/(float)ptextarg->fbw;
vTexDims . w = 0 ; //0.2f/(float)ptextarg->fbh;
}
2010-05-01 20:33:53 +00:00
else
{
2010-03-19 06:38:44 +00:00
//u32 tbp0 = curvb.tex0.tbp0 >> 5; // align to a page
2010-03-19 00:31:15 +00:00
int blockheight = PSMT_ISHALF ( ptextarg - > psm ) ? 64 : 32 ;
int ycoord = ( ( curvb . tex0 . tbp0 - ptextarg - > fbp ) / ( 32 * ( ptextarg - > fbw > > 6 ) ) ) * blockheight ;
int xcoord = ( ( ( curvb . tex0 . tbp0 - ptextarg - > fbp ) % ( 32 * ( ptextarg - > fbw > > 6 ) ) ) ) * 2 ;
vTexDims . z = ( float ) xcoord ;
vTexDims . w = ( float ) ycoord ;
}
2010-04-25 00:31:27 +00:00
if ( shadertype = = 4 )
2010-03-19 00:31:15 +00:00
vTexDims . z + = 8.0f ;
2012-05-07 19:51:58 +00:00
ZZshSetParameter4fv ( pfragment - > prog , pfragment - > fTexDims , vTexDims , " g_fTexDims " ) ;
2010-03-19 00:31:15 +00:00
}
// Apply TEX1 mmag and mmin -- filter for expanding/reducing texture
// We ignore all settings, only NEAREST (0) is used
2010-05-01 20:33:53 +00:00
inline void FlushApplyResizeFilter ( VB & curvb , u32 & dwFilterOpts , CRenderTarget * ptextarg , int context )
{
2010-03-19 00:31:15 +00:00
u32 ptexset = ( ptextarg = = curvb . prndr ) ? ptextarg - > ptexFeedback : ptextarg - > ptex ;
s_ptexCurSet [ context ] = ptexset ;
if ( ( ! curvb . tex1 . mmag ) | | ( ! curvb . tex1 . mmin ) )
glBindTexture ( GL_TEXTURE_RECTANGLE_NV , ptexset ) ;
2010-05-01 20:33:53 +00:00
if ( ! curvb . tex1 . mmag )
{
2010-03-19 00:31:15 +00:00
glTexParameteri ( GL_TEXTURE_RECTANGLE_NV , GL_TEXTURE_MAG_FILTER , GL_NEAREST ) ;
dwFilterOpts | = 1 ;
}
2010-04-25 00:31:27 +00:00
2010-05-01 20:33:53 +00:00
if ( ! curvb . tex1 . mmin )
{
2010-03-19 00:31:15 +00:00
glTexParameteri ( GL_TEXTURE_RECTANGLE_NV , GL_TEXTURE_MIN_FILTER , GL_NEAREST ) ;
dwFilterOpts | = 2 ;
}
}
2010-07-04 03:53:01 +00:00
// Usage existing targets depends on several tricks, 32-16 conversion and CLUTing, so we need to handle it.
inline FRAGMENTSHADER * FlushUseExistRenderTarget ( VB & curvb , CRenderTarget * ptextarg , u32 & dwFilterOpts , int exactcolor , int context )
2010-05-01 20:33:53 +00:00
{
2010-03-19 00:31:15 +00:00
if ( ptextarg - > IsDepth ( ) )
SetWriteDepth ( ) ;
GLuint ptexclut = 0 ;
2010-05-01 20:33:53 +00:00
2010-09-15 16:54:19 +00:00
//int psm = PIXEL_STORAGE_FORMAT(curvb.tex0);
2010-03-19 00:31:15 +00:00
int shadertype = FlushGetShaderType ( curvb , ptextarg , ptexclut ) ;
2010-09-19 08:01:48 +00:00
FRAGMENTSHADER * pfragment = ZZshLoadShadeEffect ( shadertype , 0 , curvb . curprim . fge ,
2010-09-15 16:54:19 +00:00
IsAlphaTestExpansion ( curvb . tex0 ) , exactcolor , curvb . clamp , context , NULL ) ;
2010-03-19 00:31:15 +00:00
2013-07-03 18:42:05 +00:00
FlushSetPageOffset ( pfragment , shadertype , ptextarg ) ;
2010-05-01 20:33:53 +00:00
2013-07-03 18:42:05 +00:00
FlushSetTexOffset ( pfragment , shadertype , curvb , ptextarg ) ;
2010-05-01 20:33:53 +00:00
2013-07-03 18:42:05 +00:00
FlushTextureDims ( pfragment , shadertype , curvb , ptextarg ) ;
2010-03-19 00:31:15 +00:00
2010-05-01 20:33:53 +00:00
if ( pfragment - > sCLUT ! = NULL & & ptexclut ! = 0 )
2012-05-07 19:51:58 +00:00
ZZshGLSetTextureParameter ( pfragment - > prog , pfragment - > sCLUT , ptexclut , " CLUT " ) ;
2010-03-19 00:31:15 +00:00
FlushApplyResizeFilter ( curvb , dwFilterOpts , ptextarg , context ) ;
2010-04-25 00:31:27 +00:00
2010-05-01 20:33:53 +00:00
if ( g_bSaveTex )
2010-03-19 00:31:15 +00:00
SaveTexture ( " tex.tga " , GL_TEXTURE_RECTANGLE_NV ,
2010-05-01 20:33:53 +00:00
ptextarg = = curvb . prndr ? ptextarg - > ptexFeedback : ptextarg - > ptex , RW ( ptextarg - > fbw ) , RH ( ptextarg - > fbh ) ) ;
2010-03-19 00:31:15 +00:00
return pfragment ;
}
// Usage most major shader.
2010-05-01 20:33:53 +00:00
inline FRAGMENTSHADER * FlushMadeNewTarget ( VB & curvb , int exactcolor , int context )
{
2010-03-19 00:31:15 +00:00
// save the texture
2010-05-01 20:33:53 +00:00
if ( g_bSaveTex )
{
2010-12-20 19:57:50 +00:00
// FIXME: I suspect one of g_bSaveTex test variable is wrong
2010-05-01 20:33:53 +00:00
if ( g_bSaveTex = = 1 )
{
2010-03-19 00:31:15 +00:00
SaveTex ( & curvb . tex0 , 1 ) ;
2010-05-01 20:33:53 +00:00
/*CMemoryTarget* pmemtarg = */
g_MemTargs . GetMemoryTarget ( curvb . tex0 , 0 ) ;
}
else
{
SaveTex ( & curvb . tex0 , 0 ) ;
2010-03-19 00:31:15 +00:00
}
}
2010-09-19 08:01:48 +00:00
FRAGMENTSHADER * pfragment = ZZshLoadShadeEffect ( 0 , GetTexFilter ( curvb . tex1 ) , curvb . curprim . fge ,
2010-09-15 16:54:19 +00:00
IsAlphaTestExpansion ( curvb . tex0 ) , exactcolor , curvb . clamp , context , NULL ) ;
2010-03-19 00:31:15 +00:00
if ( pfragment = = NULL )
2010-04-25 08:33:05 +00:00
ZZLog : : Error_Log ( " Could not find memory target shader. " ) ;
2010-03-19 00:31:15 +00:00
return pfragment ;
}
// We made an shader, so now need to put all common variables.
2010-05-01 20:33:53 +00:00
inline void FlushSetTexture ( VB & curvb , FRAGMENTSHADER * pfragment , CRenderTarget * ptextarg , int context )
{
2010-03-19 00:31:15 +00:00
SetTexVariables ( context , pfragment ) ;
2010-04-25 00:31:27 +00:00
SetTexInt ( context , pfragment , ptextarg = = NULL ) ;
2010-09-15 16:54:19 +00:00
// have to enable the texture parameters(curtest.atst)
if ( curvb . ptexClamp [ 0 ] ! = 0 )
2012-05-07 19:51:58 +00:00
ZZshGLSetTextureParameter ( pfragment - > prog , pfragment - > sBitwiseANDX , curvb . ptexClamp [ 0 ] , " Clamp 0 " ) ;
2010-09-15 16:54:19 +00:00
if ( curvb . ptexClamp [ 1 ] ! = 0 )
2012-05-07 19:51:58 +00:00
ZZshGLSetTextureParameter ( pfragment - > prog , pfragment - > sBitwiseANDY , curvb . ptexClamp [ 1 ] , " Clamp 1 " ) ;
2010-09-15 16:54:19 +00:00
2012-05-15 06:45:26 +00:00
// FIXME condition is a bit strange for GLSL
# ifdef GLSL4_API
if ( s_ptexCurSet [ context ] ! = 0 )
ZZshGLSetTextureParameter ( pfragment - > prog , pfragment - > sMemory , s_ptexCurSet [ context ] , " Clamp memory " ) ;
# else
2010-09-15 16:54:19 +00:00
if ( pfragment - > sMemory ! = NULL & & s_ptexCurSet [ context ] ! = 0 )
2012-05-07 19:51:58 +00:00
ZZshGLSetTextureParameter ( pfragment - > prog , pfragment - > sMemory , s_ptexCurSet [ context ] , " Clamp memory " ) ;
2012-05-15 06:45:26 +00:00
# endif
2010-03-19 00:31:15 +00:00
}
2010-09-15 16:54:19 +00:00
// Reset program and texture variables;
2012-04-19 21:22:08 +00:00
inline void FlushBindProgram ( FRAGMENTSHADER * pfragment , int context )
2010-05-01 20:33:53 +00:00
{
2010-03-19 00:31:15 +00:00
vb [ context ] . bTexConstsSync = 0 ;
vb [ context ] . bVarsTexSync = 0 ;
2010-09-15 16:54:19 +00:00
ZZshSetPixelShader ( pfragment - > prog ) ;
2010-03-19 00:31:15 +00:00
}
2010-05-01 20:33:53 +00:00
inline FRAGMENTSHADER * FlushRendererStage ( VB & curvb , u32 & dwFilterOpts , CRenderTarget * ptextarg , int exactcolor , int context )
{
2010-03-19 00:31:15 +00:00
FRAGMENTSHADER * pfragment = NULL ;
// set the correct pixel shaders
2010-05-01 20:33:53 +00:00
if ( curvb . curprim . tme )
{
2010-04-25 00:31:27 +00:00
if ( ptextarg ! = NULL )
2010-07-04 03:53:01 +00:00
pfragment = FlushUseExistRenderTarget ( curvb , ptextarg , dwFilterOpts , exactcolor , context ) ;
2010-04-25 00:31:27 +00:00
else
2010-03-19 00:31:15 +00:00
pfragment = FlushMadeNewTarget ( curvb , exactcolor , context ) ;
2010-04-25 00:31:27 +00:00
2010-05-01 20:33:53 +00:00
if ( pfragment = = NULL )
{
2010-04-25 08:33:05 +00:00
ZZLog : : Error_Log ( " Shader is not found. " ) ;
2010-03-19 00:31:15 +00:00
// return NULL;
}
2010-05-01 20:33:53 +00:00
2010-04-25 00:31:27 +00:00
FlushSetTexture ( curvb , pfragment , ptextarg , context ) ;
2010-03-19 00:31:15 +00:00
}
2010-05-01 20:33:53 +00:00
else
{
2010-03-19 00:31:15 +00:00
pfragment = & ppsRegular [ curvb . curprim . fge + 2 * s_bWriteDepth ] ;
}
2010-04-25 00:31:27 +00:00
GL_REPORT_ERRORD ( ) ;
2010-03-19 00:31:15 +00:00
// set the shaders
2010-09-15 16:54:19 +00:00
SetShaderCaller ( " FlushRendererStage " ) ;
ZZshSetVertexShader ( pvs [ 2 * ( ( curvb . curprim . _val > > 1 ) & 3 ) + 8 * s_bWriteDepth + context ] ) ;
2012-04-19 21:22:08 +00:00
FlushBindProgram ( pfragment , context ) ;
2010-03-19 00:31:15 +00:00
GL_REPORT_ERRORD ( ) ;
return pfragment ;
}
2010-05-01 20:33:53 +00:00
inline bool AlphaCanRenderStencil ( VB & curvb )
{
2010-04-25 00:31:27 +00:00
return g_bUpdateStencil & & ( PSMT_BITMODE ( curvb . prndr - > psm ) ! = 1 ) & &
2010-06-19 08:46:40 +00:00
! ZZOglGet_fbmHighByte ( curvb . frame . fbm ) & & ! ( conf . settings ( ) . no_stencil ) ;
2010-03-19 00:31:15 +00:00
}
2012-04-19 21:22:08 +00:00
inline void AlphaSetStencil ( )
2010-05-01 20:33:53 +00:00
{
2012-04-19 21:22:08 +00:00
if ( s_bDestAlphaTest & & bCanRenderStencil )
2010-05-01 20:33:53 +00:00
{
2010-03-19 00:31:15 +00:00
glEnable ( GL_STENCIL_TEST ) ;
GL_STENCILFUNC ( GL_ALWAYS , 0 , 0 ) ;
glStencilOp ( GL_KEEP , GL_KEEP , GL_KEEP ) ;
}
else glDisable ( GL_STENCIL_TEST ) ;
}
2010-10-23 04:14:19 +00:00
//inline u32 FtoDW(float f) { return (*((u32*)&f)); }
2010-05-01 20:33:53 +00:00
inline void AlphaSetDepthTest ( VB & curvb , const pixTest curtest , FRAGMENTSHADER * pfragment )
{
2010-03-19 00:31:15 +00:00
glDepthMask ( ! curvb . zbuf . zmsk & & curtest . zte ) ;
2010-05-01 20:33:53 +00:00
// && curtest.zte && (curtest.ztst > 1) );
2010-03-19 00:31:15 +00:00
2010-05-01 20:33:53 +00:00
if ( curtest . zte )
{
2010-03-19 00:31:15 +00:00
if ( curtest . ztst > 1 ) g_nDepthUsed = 2 ;
2012-04-19 21:22:08 +00:00
#if 0
2010-05-01 20:33:53 +00:00
if ( ( curtest . ztst = = 2 ) ^ ( g_nDepthBias ! = 0 ) )
{
2010-03-19 00:31:15 +00:00
g_nDepthBias = ( curtest . ztst = = 2 ) ;
//SETRS(D3DRS_DEPTHBIAS, g_nDepthBias?FtoDW(0.0003f):FtoDW(0.000015f));
}
2012-04-19 21:22:08 +00:00
# endif
2010-05-01 20:33:53 +00:00
2010-03-19 00:31:15 +00:00
glDepthFunc ( g_dwZCmp [ curtest . ztst ] ) ;
}
2010-05-01 20:33:53 +00:00
2010-03-19 00:31:15 +00:00
GL_ZTEST ( curtest . zte ) ;
2010-05-01 20:33:53 +00:00
if ( s_bWriteDepth )
{
if ( ! curvb . zbuf . zmsk )
2010-03-19 00:31:15 +00:00
curvb . pdepth - > SetRenderTarget ( 1 ) ;
else
ResetRenderTarget ( 1 ) ;
}
}
2010-05-01 20:33:53 +00:00
inline u32 AlphaSetupBlendTest ( VB & curvb )
{
2010-03-19 00:31:15 +00:00
if ( curvb . curprim . abe )
SetAlphaVariables ( curvb . alpha ) ;
else
glDisable ( GL_BLEND ) ;
u32 oldabe = curvb . curprim . abe ;
2010-05-01 20:33:53 +00:00
if ( gs . pabe )
{
2010-04-25 08:33:05 +00:00
//ZZLog::Error_Log("PABE!");
2010-03-19 00:31:15 +00:00
curvb . curprim . abe = 1 ;
glEnable ( GL_BLEND ) ;
}
2010-05-01 20:33:53 +00:00
2010-03-19 00:31:15 +00:00
return oldabe ;
}
2012-04-19 21:22:08 +00:00
inline void AlphaRenderFBA ( VB & curvb , FRAGMENTSHADER * pfragment )
2010-05-01 20:33:53 +00:00
{
2010-03-19 00:31:15 +00:00
// needs to be before RenderAlphaTest
2010-05-01 20:33:53 +00:00
if ( ( gs . pabe ) | | ( curvb . fba . fba & & ! ZZOglGet_fbmHighByte ( curvb . frame . fbm ) ) | | ( s_bDestAlphaTest & & bCanRenderStencil ) )
{
2012-05-07 19:51:58 +00:00
RenderFBA ( curvb , pfragment ) ;
2010-03-19 00:31:15 +00:00
}
2010-04-25 00:31:27 +00:00
2010-03-19 00:31:15 +00:00
}
2010-05-01 20:33:53 +00:00
inline u32 AlphaRenderAlpha ( VB & curvb , const pixTest curtest , FRAGMENTSHADER * pfragment , int exactcolor )
{
2010-03-19 00:31:15 +00:00
SetShaderCaller ( " AlphaRenderAlpha " ) ;
u32 dwUsingSpecialTesting = 0 ;
2010-05-01 20:33:53 +00:00
if ( curvb . curprim . abe )
{
2012-04-19 21:22:08 +00:00
if ( ( bNeedBlendFactorInAlpha | | ( ( curtest . ate & & curtest . atst > ATST_ALWAYS ) & & ( curtest . aref > 0x80 ) ) ) )
2010-05-01 20:33:53 +00:00
{
2010-03-19 00:31:15 +00:00
// need special stencil processing for the alpha
2012-05-07 19:51:58 +00:00
RenderAlphaTest ( curvb , pfragment ) ;
2010-03-19 00:31:15 +00:00
dwUsingSpecialTesting = 1 ;
}
// harvest fishing
2010-09-19 08:01:48 +00:00
float4 v = vAlphaBlendColor ;
2010-05-01 20:33:53 +00:00
if ( exactcolor )
{
2010-04-25 00:31:27 +00:00
v . y * = 255 ;
v . w * = 255 ;
2010-03-19 00:31:15 +00:00
}
2010-05-01 20:33:53 +00:00
2012-05-07 19:51:58 +00:00
ZZshSetParameter4fv ( pfragment - > prog , pfragment - > sOneColor , v , " g_fOneColor " ) ;
2010-03-19 00:31:15 +00:00
}
2010-05-01 20:33:53 +00:00
else
{
2010-03-19 00:31:15 +00:00
// not using blending so set to defaults
2010-09-19 08:01:48 +00:00
float4 v = exactcolor ? float4 ( 1 , 510 * 255.0f / 256.0f , 0 , 0 ) : float4 ( 1 , 2 * 255.0f / 256.0f , 0 , 0 ) ;
2012-05-07 19:51:58 +00:00
ZZshSetParameter4fv ( pfragment - > prog , pfragment - > sOneColor , v , " g_fOneColor " ) ;
2010-03-19 00:31:15 +00:00
}
2010-05-01 20:33:53 +00:00
2010-03-19 00:31:15 +00:00
return dwUsingSpecialTesting ;
}
2012-04-19 21:22:08 +00:00
inline void AlphaRenderStencil ( VB & curvb , u32 dwUsingSpecialTesting )
2010-05-01 20:33:53 +00:00
{
if ( s_bDestAlphaTest & & bCanRenderStencil )
{
2010-03-19 00:31:15 +00:00
// if not 24bit and can write to high alpha bit
RenderStencil ( curvb , dwUsingSpecialTesting ) ;
}
2010-05-01 20:33:53 +00:00
else
{
2010-03-19 00:31:15 +00:00
s_stencilref = STENCIL_SPECIAL ;
s_stencilmask = STENCIL_SPECIAL ;
// setup the stencil to only accept the test pixels
2010-05-01 20:33:53 +00:00
if ( dwUsingSpecialTesting )
{
2010-03-19 00:31:15 +00:00
glEnable ( GL_STENCIL_TEST ) ;
glStencilMask ( STENCIL_PIXELWRITE ) ;
2010-05-01 20:33:53 +00:00
GL_STENCILFUNC ( GL_EQUAL , STENCIL_SPECIAL | STENCIL_PIXELWRITE , STENCIL_SPECIAL ) ;
2010-03-19 00:31:15 +00:00
glStencilOp ( GL_KEEP , GL_KEEP , GL_REPLACE ) ;
}
}
2012-04-19 21:22:08 +00:00
// #ifdef _DEBUG
// if (bDestAlphaColor == 1)
// {
// ZZLog::Debug_Log("Dest alpha blending! Manipulate alpha here.");
// }
//
// #endif
2010-03-19 00:31:15 +00:00
2010-05-01 20:33:53 +00:00
if ( bCanRenderStencil & & gs . pabe )
{
2010-03-19 00:31:15 +00:00
// only render the pixels with alpha values >= 0x80
2010-05-01 20:33:53 +00:00
GL_STENCILFUNC ( GL_EQUAL , s_stencilref | STENCIL_FBA , s_stencilmask | STENCIL_FBA ) ;
2010-03-19 00:31:15 +00:00
}
GL_REPORT_ERRORD ( ) ;
}
2010-05-01 20:33:53 +00:00
inline void AlphaTest ( VB & curvb )
{
2010-10-16 11:10:48 +00:00
// ZZLog::Debug_Log("%d %d %d %d %d", curvb.test.date, curvb.test.datm, gs.texa.aem, curvb.test.ate, curvb.test.atst );
2010-03-19 00:31:15 +00:00
// return;
2010-05-01 20:33:53 +00:00
// Zeydlitz changed this with a reason! It's an "Alpha more than 1 hack."
2012-04-19 21:22:08 +00:00
if ( curvb . test . ate = = 1 & & curvb . test . atst = = ATST_ALWAYS & & curvb . test . date = = 1 )
2010-05-01 20:33:53 +00:00
{
2010-03-19 00:31:15 +00:00
if ( curvb . test . datm = = 1 )
2010-05-01 20:33:53 +00:00
{
2010-04-25 00:31:27 +00:00
glAlphaFunc ( GL_GREATER , 1.0f ) ;
2010-05-01 20:33:53 +00:00
}
else
{
2010-04-25 00:31:27 +00:00
glAlphaFunc ( GL_LESS , 1.0f ) ;
2010-10-16 11:10:48 +00:00
ZZLog : : Debug_Log ( " %d %d %d " , curvb . test . date , curvb . test . datm , gs . texa . aem ) ;
2010-03-19 00:31:15 +00:00
}
}
2012-04-19 21:22:08 +00:00
if ( ! curvb . test . ate | | curvb . test . atst > ATST_NEVER )
2010-05-01 20:33:53 +00:00
{
2010-06-19 05:41:06 +00:00
Draw ( curvb ) ;
2010-03-19 00:31:15 +00:00
}
GL_REPORT_ERRORD ( ) ;
}
2010-05-01 20:33:53 +00:00
inline void AlphaPabe ( VB & curvb , FRAGMENTSHADER * pfragment , int exactcolor )
{
if ( gs . pabe )
{
2010-03-19 00:31:15 +00:00
SetShaderCaller ( " AlphaPabe " ) ;
// only render the pixels with alpha values < 0x80
glDisable ( GL_BLEND ) ;
GL_STENCILFUNC_SET ( ) ;
2010-09-19 08:01:48 +00:00
float4 v ;
2010-05-01 20:33:53 +00:00
v . x = 1 ;
v . y = 2 ;
v . z = 0 ;
v . w = 0 ;
if ( exactcolor ) v . y * = 255 ;
2012-05-07 19:51:58 +00:00
ZZshSetParameter4fv ( pfragment - > prog , pfragment - > sOneColor , v , " g_fOneColor " ) ;
2010-03-19 00:31:15 +00:00
2010-06-19 05:41:06 +00:00
Draw ( curvb ) ;
2010-03-19 00:31:15 +00:00
// reset
2010-05-01 20:33:53 +00:00
if ( ! s_stencilmask ) s_stencilfunc = GL_ALWAYS ;
2010-03-19 00:31:15 +00:00
GL_STENCILFUNC_SET ( ) ;
}
GL_REPORT_ERRORD ( ) ;
}
2010-05-01 20:33:53 +00:00
// Alpha Failure does not work properly on this cases. True means that no failure job should be done.
// First three cases are trivial manual.
inline bool AlphaFailureIgnore ( const pixTest curtest )
{
2012-04-19 21:22:08 +00:00
if ( ( ! curtest . ate ) | | ( curtest . atst = = ATST_ALWAYS ) | | ( curtest . afail = = AFAIL_KEEP ) ) return true ;
2010-05-01 20:33:53 +00:00
2010-06-19 08:46:40 +00:00
if ( conf . settings ( ) . no_alpha_fail & & ( ( s_dwColorWrite < 8 ) | | ( s_dwColorWrite = = 15 & & curtest . atst = = 5 & & ( curtest . aref = = 64 ) ) ) )
2010-03-19 00:31:15 +00:00
return true ;
// old and seemingly incorrect code.
2012-04-19 21:22:08 +00:00
// if ((s_dwColorWrite < 8 && s_dwColorWrite !=8) && curtest.afail == AFAIL_FB_ONLY)
2010-03-19 00:31:15 +00:00
// return true;
2012-04-19 21:22:08 +00:00
// if ((s_dwColorWrite == 0xf) && curtest.atst == ATST_GEQUAL && curtest.afail == AFAIL_FB_ONLY && !(conf.settings() & GAME_REGETHACK))
2010-03-19 00:31:15 +00:00
// return true;
return false ;
}
// more work on alpha failure case
2012-04-19 21:22:08 +00:00
inline void AlphaFailureTestJob ( VB & curvb , const pixTest curtest , FRAGMENTSHADER * pfragment , int exactcolor , int oldabe )
2010-05-01 20:33:53 +00:00
{
2012-04-19 21:22:08 +00:00
// Note, case when ate == 1, atst == ATST_NEVER and afail > AFAIL_KEEP in documentation wrote as failure case. But it seems that
2010-05-01 20:33:53 +00:00
// either doc's are incorrect or this case has some issues.
if ( AlphaFailureIgnore ( curtest ) ) return ;
2010-03-19 00:31:15 +00:00
2010-04-25 00:31:27 +00:00
# ifdef NOALFAFAIL
2010-04-25 08:33:05 +00:00
ZZLog : : Error_Log ( " Alpha job here %d %d %d %d %d %d " , s_dwColorWrite , curtest . atst , curtest . afail , curtest . aref , gs . pabe , s_bWriteDepth ) ;
2010-05-01 20:33:53 +00:00
2010-03-19 00:31:15 +00:00
// return;
2010-04-25 00:31:27 +00:00
# endif
2010-03-19 00:31:15 +00:00
SetShaderCaller ( " AlphaFailureTestJob " ) ;
// need to reverse the test and disable some targets
glAlphaFunc ( g_dwReverseAlphaCmp [ curtest . atst ] , AlphaReferedValue ( curtest . aref ) ) ;
2010-05-01 20:33:53 +00:00
if ( curtest . afail & 1 ) // front buffer update only
{
2012-04-19 21:22:08 +00:00
if ( curtest . afail = = AFAIL_RGB_ONLY ) glColorMask ( 1 , 1 , 1 , 0 ) ; // disable alpha
2010-03-19 00:31:15 +00:00
glDepthMask ( 0 ) ;
2010-05-01 20:33:53 +00:00
if ( s_bWriteDepth ) ResetRenderTarget ( 1 ) ;
2010-03-19 00:31:15 +00:00
}
2010-05-01 20:33:53 +00:00
else
{
2010-03-19 00:31:15 +00:00
// zbuffer update only
2010-05-01 20:33:53 +00:00
glColorMask ( 0 , 0 , 0 , 0 ) ;
2010-03-19 00:31:15 +00:00
}
2010-05-01 20:33:53 +00:00
if ( gs . pabe & & bCanRenderStencil )
{
2010-03-19 00:31:15 +00:00
// only render the pixels with alpha values >= 0x80
2010-09-19 08:01:48 +00:00
float4 v = vAlphaBlendColor ;
2010-05-01 20:33:53 +00:00
if ( exactcolor ) { v . y * = 255 ; v . w * = 255 ; }
2012-05-07 19:51:58 +00:00
ZZshSetParameter4fv ( pfragment - > prog , pfragment - > sOneColor , v , " g_fOneColor " ) ;
2010-05-01 20:33:53 +00:00
2010-03-19 00:31:15 +00:00
glEnable ( GL_BLEND ) ;
2010-05-01 20:33:53 +00:00
GL_STENCILFUNC ( GL_EQUAL , s_stencilref | STENCIL_FBA , s_stencilmask | STENCIL_FBA ) ;
2010-03-19 00:31:15 +00:00
}
2010-06-19 05:41:06 +00:00
Draw ( curvb ) ;
2010-05-01 20:33:53 +00:00
2010-03-19 00:31:15 +00:00
GL_REPORT_ERRORD ( ) ;
2010-05-01 20:33:53 +00:00
if ( gs . pabe )
{
2010-03-19 00:31:15 +00:00
// only render the pixels with alpha values < 0x80
glDisable ( GL_BLEND ) ;
GL_STENCILFUNC_SET ( ) ;
2010-09-19 08:01:48 +00:00
float4 v ;
2010-05-01 20:33:53 +00:00
v . x = 1 ;
v . y = 2 ;
v . z = 0 ;
v . w = 0 ;
2010-03-19 00:31:15 +00:00
if ( exactcolor ) v . y * = 255 ;
2010-05-01 20:33:53 +00:00
2012-05-07 19:51:58 +00:00
ZZshSetParameter4fv ( pfragment - > prog , pfragment - > sOneColor , v , " g_fOneColor " ) ;
2010-03-19 00:31:15 +00:00
2010-06-19 05:41:06 +00:00
Draw ( curvb ) ;
2010-03-19 00:31:15 +00:00
// reset
2010-05-01 20:33:53 +00:00
if ( oldabe ) glEnable ( GL_BLEND ) ;
if ( ! s_stencilmask ) s_stencilfunc = GL_ALWAYS ;
2010-03-19 00:31:15 +00:00
GL_STENCILFUNC_SET ( ) ;
}
// restore
2010-05-01 20:33:53 +00:00
if ( ( curtest . afail & 1 ) & & ! curvb . zbuf . zmsk )
{
2010-03-19 00:31:15 +00:00
glDepthMask ( 1 ) ;
2010-05-01 20:33:53 +00:00
if ( s_bWriteDepth )
{
assert ( curvb . pdepth ! = NULL ) ;
curvb . pdepth - > SetRenderTarget ( 1 ) ;
2010-03-19 00:31:15 +00:00
}
}
GL_COLORMASK ( s_dwColorWrite ) ;
2010-05-01 20:33:53 +00:00
2010-03-19 00:31:15 +00:00
// not needed anymore since rest of ops concentrate on image processing
GL_REPORT_ERRORD ( ) ;
}
2010-05-01 20:33:53 +00:00
inline void AlphaSpecialTesting ( VB & curvb , FRAGMENTSHADER * pfragment , u32 dwUsingSpecialTesting , int exactcolor )
{
if ( dwUsingSpecialTesting )
{
2010-03-19 00:31:15 +00:00
SetShaderCaller ( " AlphaSpecialTesting " ) ;
// render the real alpha
glDisable ( GL_ALPHA_TEST ) ;
2010-05-01 20:33:53 +00:00
glColorMask ( 0 , 0 , 0 , 1 ) ;
2010-03-19 00:31:15 +00:00
2010-05-01 20:33:53 +00:00
if ( s_bWriteDepth )
{
2010-03-19 00:31:15 +00:00
ResetRenderTarget ( 1 ) ;
}
glDepthMask ( 0 ) ;
2010-05-01 20:33:53 +00:00
glStencilFunc ( GL_EQUAL , STENCIL_SPECIAL | STENCIL_PIXELWRITE , STENCIL_SPECIAL | STENCIL_PIXELWRITE ) ;
2010-03-19 00:31:15 +00:00
glStencilOp ( GL_KEEP , GL_KEEP , GL_KEEP ) ;
2010-09-19 08:01:48 +00:00
float4 v = float4 ( 0 , exactcolor ? 510.0f : 2.0f , 0 , 0 ) ;
2012-05-07 19:51:58 +00:00
ZZshSetParameter4fv ( pfragment - > prog , pfragment - > sOneColor , v , " g_fOneColor " ) ;
2010-06-19 05:41:06 +00:00
Draw ( curvb ) ;
2010-03-19 00:31:15 +00:00
// don't need to restore
}
GL_REPORT_ERRORD ( ) ;
}
2012-04-19 21:22:08 +00:00
inline void AlphaDestinationTest ( VB & curvb , FRAGMENTSHADER * pfragment )
2010-05-01 20:33:53 +00:00
{
2012-04-19 21:22:08 +00:00
if ( s_dwColorWrite & COLORMASK_ALPHA )
2010-05-01 20:33:53 +00:00
{
2012-04-19 21:22:08 +00:00
if ( curvb . fba . fba )
2010-05-01 20:33:53 +00:00
{
2012-05-07 19:51:58 +00:00
ProcessFBA ( curvb , pfragment ) ;
2012-04-19 21:22:08 +00:00
}
else if ( s_bDestAlphaTest & & bCanRenderStencil )
{
// finally make sure all entries are 1 when the dest alpha >= 0x80 (if fba is 1, this is already the case)
ProcessStencil ( curvb ) ;
2010-03-19 00:31:15 +00:00
}
}
2012-04-19 21:22:08 +00:00
// if (bDestAlphaColor == 1)
// {
// // need to reset the dest colors to their original counter parts
// //ZZLog::Warn_Log("Need to reset dest alpha color");
// }
2010-03-19 00:31:15 +00:00
}
2010-05-01 20:33:53 +00:00
inline void AlphaSaveTarget ( VB & curvb )
{
2010-03-19 00:31:15 +00:00
# ifdef _DEBUG
return ; // Do nothing
2010-04-25 00:31:27 +00:00
2010-04-30 04:40:31 +00:00
//#ifdef _WIN32
// CreateDirectory("frames", NULL);
//#else
// char* strdir="";
// sprintf(strdir, "mkdir %s", "frames");
// system(strdir);
//#endif
// char str[255];
2010-10-17 08:47:31 +00:00
// Needs a # after frame to work properly.
// sprintf(str, "frames/frame.tga");
2010-09-15 16:54:19 +00:00
2012-04-19 21:22:08 +00:00
// //FB::Unbind(); // switch to the backbuffer
2010-09-15 16:54:19 +00:00
// //glFlush();
// //SaveTexture("tex.jpg", GL_TEXTURE_RECTANGLE_NV, curvb.prndr->ptex, RW(curvb.prndr->fbw), RH(curvb.prndr->fbh));
// SaveRenderTarget(str, RW(curvb.prndr->fbw), RH(curvb.prndr->fbh), 0);
2010-03-19 00:31:15 +00:00
# endif
}
2010-05-01 20:33:53 +00:00
inline void FlushUndoFiter ( u32 dwFilterOpts )
{
if ( dwFilterOpts )
{
2010-03-19 00:31:15 +00:00
// undo filter changes (binding didn't change)
2010-05-01 20:33:53 +00:00
if ( dwFilterOpts & 1 ) glTexParameteri ( GL_TEXTURE_RECTANGLE_NV , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ;
if ( dwFilterOpts & 2 ) glTexParameteri ( GL_TEXTURE_RECTANGLE_NV , GL_TEXTURE_MIN_FILTER , GL_LINEAR ) ;
2010-03-19 00:31:15 +00:00
}
}
2010-05-01 20:33:53 +00:00
// This is the most important function! It draws all collected info onscreen.
2010-10-16 11:54:46 +00:00
void Flush ( int context )
2010-03-19 00:31:15 +00:00
{
FUNCLOG
VB & curvb = vb [ context ] ;
const pixTest curtest = curvb . test ;
2012-06-01 08:21:31 +00:00
# ifdef GLSL4_API
g_cs . set_context ( context ) ;
# endif
2010-03-19 00:31:15 +00:00
2010-05-01 20:33:53 +00:00
if ( FlushInitialTest ( curvb , curtest , context ) ) return ;
2010-03-19 00:31:15 +00:00
VisualBufferMessage ( context ) ;
2010-04-25 00:31:27 +00:00
2010-03-19 00:31:15 +00:00
GL_REPORT_ERRORD ( ) ;
2010-05-01 20:33:53 +00:00
2010-03-19 00:31:15 +00:00
CRenderTarget * ptextarg = FlushGetTarget ( curvb ) ;
2010-04-25 00:31:27 +00:00
2010-03-19 00:31:15 +00:00
SwitchWireframeOff ( ) ;
FlushDoContextJob ( curvb , context ) ;
2010-07-04 03:53:01 +00:00
u32 dwUsingSpecialTesting = 0 , dwFilterOpts = 0 ;
2010-03-19 00:31:15 +00:00
int exactcolor = FlushGetExactcolor ( curtest ) ;
2010-05-01 20:33:53 +00:00
2010-03-19 00:31:15 +00:00
FRAGMENTSHADER * pfragment = FlushRendererStage ( curvb , dwFilterOpts , ptextarg , exactcolor , context ) ;
2012-04-19 21:22:08 +00:00
bCanRenderStencil = AlphaCanRenderStencil ( curvb ) ;
2010-05-01 20:33:53 +00:00
if ( curtest . date | | gs . pabe ) SetDestAlphaTest ( ) ;
2010-03-19 00:31:15 +00:00
2012-04-19 21:22:08 +00:00
AlphaSetStencil ( ) ;
2010-03-19 00:31:15 +00:00
AlphaSetDepthTest ( curvb , curtest , pfragment ) ; // Error!
SetAlphaTest ( curtest ) ;
2010-05-01 20:33:53 +00:00
2010-03-19 00:31:15 +00:00
u32 oldabe = AlphaSetupBlendTest ( curvb ) ; // Unavoidable
// needs to be before RenderAlphaTest
2012-04-19 21:22:08 +00:00
AlphaRenderFBA ( curvb , pfragment ) ;
2010-05-01 20:33:53 +00:00
2010-03-19 00:31:15 +00:00
dwUsingSpecialTesting = AlphaRenderAlpha ( curvb , curtest , pfragment , exactcolor ) ; // Unavoidable
2012-04-19 21:22:08 +00:00
AlphaRenderStencil ( curvb , dwUsingSpecialTesting ) ;
2010-03-19 00:31:15 +00:00
AlphaTest ( curvb ) ; // Unavoidable
AlphaPabe ( curvb , pfragment , exactcolor ) ;
2012-04-19 21:22:08 +00:00
AlphaFailureTestJob ( curvb , curtest , pfragment , exactcolor , oldabe ) ;
2010-03-19 00:31:15 +00:00
AlphaSpecialTesting ( curvb , pfragment , dwUsingSpecialTesting , exactcolor ) ;
2012-04-19 21:22:08 +00:00
AlphaDestinationTest ( curvb , pfragment ) ;
2010-03-19 00:31:15 +00:00
AlphaSaveTarget ( curvb ) ;
2010-05-01 20:33:53 +00:00
2010-03-19 00:31:15 +00:00
GL_REPORT_ERRORD ( ) ;
2010-04-25 00:31:27 +00:00
2010-03-19 00:31:15 +00:00
FlushUndoFiter ( dwFilterOpts ) ;
2010-05-01 20:33:53 +00:00
ppf + = curvb . nCount + 0x100000 ;
2010-03-19 00:31:15 +00:00
curvb . nCount = 0 ;
curvb . curprim . abe = oldabe ;
2010-05-01 20:33:53 +00:00
2010-03-19 00:31:15 +00:00
SwitchWireframeOn ( ) ;
2010-05-01 20:33:53 +00:00
2010-03-19 00:31:15 +00:00
GL_REPORT_ERRORD ( ) ;
}
2010-10-16 11:54:46 +00:00
void FlushBoth ( )
2010-06-19 05:41:06 +00:00
{
Flush ( 0 ) ;
Flush ( 1 ) ;
}
2012-04-19 21:22:08 +00:00
// Often called for several reasons
// Call flush if renderer or depth target is equal to ptr
void FlushIfNecesary ( void * ptr )
{
if ( vb [ 0 ] . prndr = = ptr | | vb [ 0 ] . pdepth = = ptr ) Flush ( 0 ) ;
if ( vb [ 1 ] . prndr = = ptr | | vb [ 1 ] . pdepth = = ptr ) Flush ( 1 ) ;
}
2012-05-07 19:51:58 +00:00
inline void RenderFBA ( const VB & curvb , FRAGMENTSHADER * pfragment )
2010-03-19 00:31:15 +00:00
{
// add fba to all pixels
GL_STENCILFUNC ( GL_ALWAYS , STENCIL_FBA , 0xff ) ;
glStencilMask ( STENCIL_CLEAR ) ;
glStencilOp ( GL_ZERO , GL_KEEP , GL_REPLACE ) ;
glDisable ( GL_DEPTH_TEST ) ;
glDepthMask ( 0 ) ;
2010-05-01 20:33:53 +00:00
glColorMask ( 0 , 0 , 0 , 0 ) ;
2010-03-19 00:31:15 +00:00
2010-05-01 20:33:53 +00:00
if ( s_bWriteDepth ) ResetRenderTarget ( 1 ) ;
2010-03-19 00:31:15 +00:00
SetShaderCaller ( " RenderFBA " ) ;
2010-05-01 20:33:53 +00:00
2010-03-19 00:31:15 +00:00
glEnable ( GL_ALPHA_TEST ) ;
2010-05-01 20:33:53 +00:00
2010-03-19 00:31:15 +00:00
glAlphaFunc ( GL_GEQUAL , 1 ) ;
2010-09-19 08:01:48 +00:00
float4 v ( 1 , 2 , 0 , 0 ) ;
2010-05-01 20:33:53 +00:00
2012-05-07 19:51:58 +00:00
ZZshSetParameter4fv ( pfragment - > prog , pfragment - > sOneColor , v , " g_fOneColor " ) ;
2010-03-19 00:31:15 +00:00
2010-06-19 05:41:06 +00:00
Draw ( curvb ) ;
2010-03-19 00:31:15 +00:00
SetAlphaTest ( curvb . test ) ;
// reset (not necessary)
GL_COLORMASK ( s_dwColorWrite ) ;
2010-05-01 20:33:53 +00:00
2010-03-19 00:31:15 +00:00
glStencilOp ( GL_KEEP , GL_KEEP , GL_REPLACE ) ;
2010-05-01 20:33:53 +00:00
if ( ! curvb . zbuf . zmsk )
2010-03-19 00:31:15 +00:00
{
glDepthMask ( 1 ) ;
2010-04-25 00:31:27 +00:00
2010-05-01 20:33:53 +00:00
assert ( curvb . pdepth ! = NULL ) ;
if ( s_bWriteDepth ) curvb . pdepth - > SetRenderTarget ( 1 ) ;
2010-03-19 00:31:15 +00:00
}
2010-05-01 20:33:53 +00:00
2010-03-19 00:31:15 +00:00
GL_ZTEST ( curvb . test . zte ) ;
}
2012-05-07 19:51:58 +00:00
__forceinline void RenderAlphaTest ( const VB & curvb , FRAGMENTSHADER * pfragment )
2010-03-19 00:31:15 +00:00
{
2010-05-01 20:33:53 +00:00
if ( ! g_bUpdateStencil ) return ;
2010-03-19 00:31:15 +00:00
2012-04-19 21:22:08 +00:00
if ( ( curvb . test . ate ) & & ( curvb . test . afail = = AFAIL_FB_ONLY ) ) glDisable ( GL_ALPHA_TEST ) ;
2010-03-19 00:31:15 +00:00
glDepthMask ( 0 ) ;
2010-05-01 20:33:53 +00:00
glColorMask ( 0 , 0 , 0 , 0 ) ;
if ( s_bWriteDepth ) ResetRenderTarget ( 1 ) ;
2010-03-19 00:31:15 +00:00
SetShaderCaller ( " RenderAlphaTest " ) ;
2010-09-19 08:01:48 +00:00
float4 v ( 1 , 2 , 0 , 0 ) ;
2010-05-01 20:33:53 +00:00
2012-05-07 19:51:58 +00:00
ZZshSetParameter4fv ( pfragment - > prog , pfragment - > sOneColor , v , " g_fOneColor " ) ;
2010-03-19 00:31:15 +00:00
// or a 1 to the stencil buffer wherever alpha passes
glStencilOp ( GL_KEEP , GL_KEEP , GL_REPLACE ) ;
2010-05-01 20:33:53 +00:00
2010-03-19 00:31:15 +00:00
s_stencilfunc = GL_ALWAYS ;
glEnable ( GL_STENCIL_TEST ) ;
2010-04-25 00:31:27 +00:00
2010-05-01 20:33:53 +00:00
if ( ! s_bDestAlphaTest )
2010-03-19 00:31:15 +00:00
{
// clear everything
s_stencilref = 0 ;
glStencilMask ( STENCIL_CLEAR ) ;
glDisable ( GL_ALPHA_TEST ) ;
GL_STENCILFUNC_SET ( ) ;
2010-06-19 05:41:06 +00:00
Draw ( curvb ) ;
2010-03-19 00:31:15 +00:00
2012-04-19 21:22:08 +00:00
if ( curvb . test . ate & & curvb . test . afail ! = AFAIL_FB_ONLY & & USEALPHATESTING ) glEnable ( GL_ALPHA_TEST ) ;
2010-03-19 00:31:15 +00:00
}
2012-04-19 21:22:08 +00:00
if ( curvb . test . ate & & curvb . test . atst > ATST_ALWAYS & & curvb . test . aref > 0x80 )
2010-03-19 00:31:15 +00:00
{
2010-09-19 08:01:48 +00:00
v = float4 ( 1 , 1 , 0 , 0 ) ;
2012-05-07 19:51:58 +00:00
ZZshSetParameter4fv ( pfragment - > prog , pfragment - > sOneColor , v , " g_fOneColor " ) ;
2010-03-19 00:31:15 +00:00
glAlphaFunc ( g_dwAlphaCmp [ curvb . test . atst ] , AlphaReferedValue ( curvb . test . aref ) ) ;
}
s_stencilref = STENCIL_SPECIAL ;
2010-05-01 20:33:53 +00:00
2010-03-19 00:31:15 +00:00
glStencilMask ( STENCIL_SPECIAL ) ;
GL_STENCILFUNC_SET ( ) ;
glDisable ( GL_DEPTH_TEST ) ;
2010-04-25 00:31:27 +00:00
2010-06-19 05:41:06 +00:00
Draw ( curvb ) ;
2010-03-19 00:31:15 +00:00
2010-05-01 20:33:53 +00:00
if ( curvb . test . zte ) glEnable ( GL_DEPTH_TEST ) ;
2010-03-19 00:31:15 +00:00
GL_ALPHATEST ( 0 ) ;
2010-05-01 20:33:53 +00:00
2010-03-19 00:31:15 +00:00
GL_COLORMASK ( s_dwColorWrite ) ;
2010-05-01 20:33:53 +00:00
if ( ! curvb . zbuf . zmsk )
2010-03-19 00:31:15 +00:00
{
glDepthMask ( 1 ) ;
// set rt next level
2010-05-01 20:33:53 +00:00
2010-03-19 00:31:15 +00:00
if ( s_bWriteDepth ) curvb . pdepth - > SetRenderTarget ( 1 ) ;
}
}
2010-10-16 11:54:46 +00:00
inline void RenderStencil ( const VB & curvb , u32 dwUsingSpecialTesting )
2010-03-19 00:31:15 +00:00
{
2010-04-25 00:31:27 +00:00
//NOTE: This stencil hack for dest alpha testing ONLY works when
2010-03-19 00:31:15 +00:00
// the geometry in one DrawPrimitive call does not overlap
// mark the stencil buffer for the new data's bits (mark 4 if alpha is >= 0xff)
// mark 4 if a pixel was written (so that the stencil buf can be changed with new values)
glStencilMask ( STENCIL_PIXELWRITE ) ;
glStencilOp ( GL_KEEP , GL_KEEP , GL_REPLACE ) ;
2010-05-01 20:33:53 +00:00
s_stencilmask = ( curvb . test . date ? STENCIL_ALPHABIT : 0 ) | ( dwUsingSpecialTesting ? STENCIL_SPECIAL : 0 ) ;
2010-03-19 00:31:15 +00:00
s_stencilfunc = s_stencilmask ? GL_EQUAL : GL_ALWAYS ;
2010-04-25 00:31:27 +00:00
2010-05-01 20:33:53 +00:00
s_stencilref = curvb . test . date * curvb . test . datm | STENCIL_PIXELWRITE | ( dwUsingSpecialTesting ? STENCIL_SPECIAL : 0 ) ;
2010-03-19 00:31:15 +00:00
GL_STENCILFUNC_SET ( ) ;
}
2010-10-16 11:54:46 +00:00
inline void ProcessStencil ( const VB & curvb )
2010-03-19 00:31:15 +00:00
{
2010-05-01 20:33:53 +00:00
assert ( ! curvb . fba . fba ) ;
2010-03-19 00:31:15 +00:00
// set new alpha bit
glStencilMask ( STENCIL_ALPHABIT ) ;
2010-05-01 20:33:53 +00:00
GL_STENCILFUNC ( GL_EQUAL , STENCIL_PIXELWRITE , STENCIL_PIXELWRITE | STENCIL_FBA ) ;
2010-03-19 00:31:15 +00:00
glStencilOp ( GL_KEEP , GL_KEEP , GL_REPLACE ) ;
glDisable ( GL_DEPTH_TEST ) ;
glDepthMask ( 0 ) ;
2010-05-01 20:33:53 +00:00
glColorMask ( 0 , 0 , 0 , 0 ) ;
2010-03-19 00:31:15 +00:00
if ( s_bWriteDepth ) ResetRenderTarget ( 1 ) ;
GL_ALPHATEST ( 0 ) ;
2010-05-01 20:33:53 +00:00
2010-03-19 00:31:15 +00:00
SetShaderCaller ( " ProcessStencil " ) ;
2010-09-15 16:54:19 +00:00
ZZshSetPixelShader ( ppsOne . prog ) ;
2010-06-19 05:41:06 +00:00
Draw ( curvb ) ;
2010-03-19 00:31:15 +00:00
// process when alpha >= 0xff
2010-05-01 20:33:53 +00:00
GL_STENCILFUNC ( GL_EQUAL , STENCIL_PIXELWRITE | STENCIL_FBA | STENCIL_ALPHABIT , STENCIL_PIXELWRITE | STENCIL_FBA ) ;
2010-06-19 05:41:06 +00:00
Draw ( curvb ) ;
2010-03-19 00:31:15 +00:00
// clear STENCIL_PIXELWRITE bit
glStencilMask ( STENCIL_CLEAR ) ;
2010-05-01 20:33:53 +00:00
GL_STENCILFUNC ( GL_ALWAYS , 0 , STENCIL_PIXELWRITE | STENCIL_FBA ) ;
2010-06-19 05:41:06 +00:00
Draw ( curvb ) ;
2010-03-19 00:31:15 +00:00
// restore state
GL_COLORMASK ( s_dwColorWrite ) ;
2010-05-01 20:33:53 +00:00
if ( curvb . test . ate & & USEALPHATESTING ) glEnable ( GL_ALPHA_TEST ) ;
2010-03-19 00:31:15 +00:00
2010-05-01 20:33:53 +00:00
if ( ! curvb . zbuf . zmsk )
{
2010-03-19 00:31:15 +00:00
glDepthMask ( 1 ) ;
2010-05-01 20:33:53 +00:00
if ( s_bWriteDepth )
{
assert ( curvb . pdepth ! = NULL ) ;
2010-03-19 00:31:15 +00:00
curvb . pdepth - > SetRenderTarget ( 1 ) ;
}
}
GL_ZTEST ( curvb . test . zte ) ;
2010-05-01 20:33:53 +00:00
2010-03-19 00:31:15 +00:00
glStencilOp ( GL_KEEP , GL_KEEP , GL_KEEP ) ;
}
2012-05-07 19:51:58 +00:00
__forceinline void ProcessFBA ( const VB & curvb , FRAGMENTSHADER * pfragment )
2010-03-19 00:31:15 +00:00
{
2010-05-01 20:33:53 +00:00
if ( ( curvb . frame . fbm & 0x80000000 ) ) return ;
2010-03-19 00:31:15 +00:00
// add fba to all pixels that were written and alpha was less than 0xff
glStencilMask ( STENCIL_ALPHABIT ) ;
glStencilOp ( GL_KEEP , GL_KEEP , GL_REPLACE ) ;
2010-05-01 20:33:53 +00:00
GL_STENCILFUNC ( GL_EQUAL , STENCIL_FBA | STENCIL_PIXELWRITE | STENCIL_ALPHABIT , STENCIL_PIXELWRITE | STENCIL_FBA ) ;
2010-03-19 00:31:15 +00:00
glDisable ( GL_DEPTH_TEST ) ;
2010-05-01 20:33:53 +00:00
2010-03-19 00:31:15 +00:00
glDepthMask ( 0 ) ;
2010-05-01 20:33:53 +00:00
glColorMask ( 0 , 0 , 0 , 1 ) ;
if ( s_bWriteDepth ) ResetRenderTarget ( 1 ) ;
2010-04-25 00:31:27 +00:00
2010-03-19 00:31:15 +00:00
SetShaderCaller ( " ProcessFBA " ) ;
// processes the pixels with ALPHA < 0x80*2
glEnable ( GL_ALPHA_TEST ) ;
glAlphaFunc ( GL_LEQUAL , 1 ) ;
// add 1 to dest
GL_BLEND_ALPHA ( GL_ONE , GL_ONE ) ;
GL_BLENDEQ_ALPHA ( GL_FUNC_ADD ) ;
2012-05-07 19:51:58 +00:00
// FIXME: Seem dangerous
// float f = 1;
// ZZshSetParameter4fv(pfragment->prog, pfragment->sOneColor, &f, "g_fOneColor");
float4 v = float4 ( 1 , 1 , 0 , 0 ) ;
ZZshSetParameter4fv ( pfragment - > prog , pfragment - > sOneColor , v , " g_fOneColor " ) ;
2010-09-15 16:54:19 +00:00
ZZshSetPixelShader ( ppsOne . prog ) ;
2010-06-19 05:41:06 +00:00
Draw ( curvb ) ;
2010-03-19 00:31:15 +00:00
glDisable ( GL_ALPHA_TEST ) ;
// reset bits
glStencilMask ( STENCIL_CLEAR ) ;
2010-05-01 20:33:53 +00:00
GL_STENCILFUNC ( GL_GREATER , 0 , STENCIL_PIXELWRITE | STENCIL_FBA ) ;
2010-03-19 00:31:15 +00:00
glStencilOp ( GL_KEEP , GL_KEEP , GL_ZERO ) ;
2010-06-19 05:41:06 +00:00
Draw ( curvb ) ;
2010-03-19 00:31:15 +00:00
2012-04-19 21:22:08 +00:00
if ( ( curvb . test . atst ! = ATST_NEVER ) & & USEALPHATESTING )
2010-05-01 20:33:53 +00:00
{
2010-03-19 00:31:15 +00:00
glEnable ( GL_ALPHA_TEST ) ;
glAlphaFunc ( g_dwAlphaCmp [ curvb . test . atst ] , AlphaReferedValue ( curvb . test . aref ) ) ;
}
// restore (SetAlphaVariables)
GL_BLEND_ALPHA ( GL_ONE , GL_ZERO ) ;
2010-05-01 20:33:53 +00:00
if ( vAlphaBlendColor . y < 0 ) GL_BLENDEQ_ALPHA ( GL_FUNC_REVERSE_SUBTRACT ) ;
2010-03-19 00:31:15 +00:00
// reset (not necessary)
GL_COLORMASK ( s_dwColorWrite ) ;
2010-05-01 20:33:53 +00:00
if ( ! curvb . zbuf . zmsk )
{
2010-03-19 00:31:15 +00:00
glDepthMask ( 1 ) ;
if ( s_bWriteDepth ) curvb . pdepth - > SetRenderTarget ( 1 ) ;
}
2010-05-01 20:33:53 +00:00
2010-03-19 00:31:15 +00:00
GL_ZTEST ( curvb . test . zte ) ;
}
2010-10-16 11:54:46 +00:00
void SetContextTarget ( int context )
2010-03-19 00:31:15 +00:00
{
FUNCLOG
VB & curvb = vb [ context ] ;
GL_REPORT_ERRORD ( ) ;
2010-05-01 20:33:53 +00:00
if ( curvb . prndr = = NULL )
2010-03-19 00:31:15 +00:00
curvb . prndr = s_RTs . GetTarg ( curvb . frame , 0 , get_maxheight ( curvb . gsfb . fbp , curvb . gsfb . fbw , curvb . gsfb . psm ) ) ;
// make sure targets are valid
2010-05-01 20:33:53 +00:00
if ( curvb . pdepth = = NULL )
{
2010-03-19 00:31:15 +00:00
frameInfo f ;
f . fbp = curvb . zbuf . zbp ;
f . fbw = curvb . frame . fbw ;
f . fbh = curvb . prndr - > fbh ;
f . psm = curvb . zbuf . psm ;
f . fbm = 0 ;
2010-05-01 20:33:53 +00:00
curvb . pdepth = ( CDepthTarget * ) s_DepthRTs . GetTarg ( f , CRenderTargetMngr : : TO_DepthBuffer | CRenderTargetMngr : : TO_StrictHeight |
( curvb . zbuf . zmsk ? CRenderTargetMngr : : TO_Virtual : 0 ) , get_maxheight ( curvb . zbuf . zbp , curvb . gsfb . fbw , 0 ) ) ;
2010-03-19 00:31:15 +00:00
}
2010-05-01 20:33:53 +00:00
assert ( curvb . prndr ! = NULL & & curvb . pdepth ! = NULL ) ;
2010-06-15 11:20:52 +00:00
if ( curvb . pdepth - > fbh ! = curvb . prndr - > fbh ) ZZLog : : Debug_Log ( " (curvb.pdepth->fbh(0x%x) != curvb.prndr->fbh(0x%x)) " , curvb . pdepth - > fbh , curvb . prndr - > fbh ) ;
//assert(curvb.pdepth->fbh == curvb.prndr->fbh);
2010-03-19 00:31:15 +00:00
2010-05-01 20:33:53 +00:00
if ( curvb . pdepth - > status & CRenderTarget : : TS_Virtual )
{
2010-04-25 00:31:27 +00:00
2010-05-01 20:33:53 +00:00
if ( ! curvb . zbuf . zmsk )
{
2014-06-13 20:38:04 +00:00
# ifdef NDEBUG
s_DepthRTs . Promote ( curvb . pdepth - > fbp | ( curvb . pdepth - > fbw < < 16 ) ) ;
# else
2010-05-01 20:33:53 +00:00
CRenderTarget * ptemp = s_DepthRTs . Promote ( curvb . pdepth - > fbp | ( curvb . pdepth - > fbw < < 16 ) ) ;
assert ( ptemp = = curvb . pdepth ) ;
2014-06-13 20:38:04 +00:00
# endif
2010-03-19 00:31:15 +00:00
}
else
2010-05-01 20:33:53 +00:00
{
2010-03-19 00:31:15 +00:00
curvb . pdepth - > status & = ~ CRenderTarget : : TS_NeedUpdate ;
2010-05-01 20:33:53 +00:00
}
2010-03-19 00:31:15 +00:00
}
2013-07-03 18:42:05 +00:00
//bool bSetTarg = 1;
2010-03-19 00:31:15 +00:00
2010-05-01 20:33:53 +00:00
if ( curvb . pdepth - > status & CRenderTarget : : TS_NeedUpdate )
{
assert ( ! ( curvb . pdepth - > status & CRenderTarget : : TS_Virtual ) ) ;
2010-03-19 00:31:15 +00:00
// don't update if virtual
curvb . pdepth - > Update ( context , curvb . prndr ) ;
2013-07-03 18:42:05 +00:00
//bSetTarg = 0;
2010-03-19 00:31:15 +00:00
}
2010-04-25 00:31:27 +00:00
2010-03-19 00:31:15 +00:00
GL_REPORT_ERRORD ( ) ;
2010-05-01 20:33:53 +00:00
if ( curvb . prndr - > status & CRenderTarget : : TS_NeedUpdate )
{
/* if(bSetTarg) {
2010-10-16 11:10:48 +00:00
* ZZLog : : Debug_Log ( " Here " ) ;
2010-05-01 20:33:53 +00:00
* if ( s_bWriteDepth ) {
* curvb . pdepth - > SetRenderTarget ( 1 ) ;
* curvb . pdepth - > SetDepthStencilSurface ( ) ;
* }
* else
* curvb . pdepth - > SetDepthStencilSurface ( ) ;
* } */
2010-03-19 00:31:15 +00:00
curvb . prndr - > Update ( context , curvb . pdepth ) ;
}
2010-05-01 20:33:53 +00:00
else
{
2010-03-19 00:31:15 +00:00
//if( (vb[0].prndr != vb[1].prndr && vb[!context].bVarsSetTarg) || !vb[context].bVarsSetTarg )
curvb . prndr - > SetRenderTarget ( 0 ) ;
2010-04-25 00:31:27 +00:00
//if( bSetTarg && ((vb[0].pdepth != vb[1].pdepth && vb[!context].bVarsSetTarg) || !vb[context].bVarsSetTarg) )
2010-03-19 00:31:15 +00:00
curvb . pdepth - > SetDepthStencilSurface ( ) ;
2010-04-25 00:31:27 +00:00
2010-10-16 11:54:46 +00:00
if ( conf . mrtdepth & & IsWriteDepth ( ) ) curvb . pdepth - > SetRenderTarget ( 1 ) ;
2010-03-19 00:31:15 +00:00
if ( s_ptexCurSet [ 0 ] = = curvb . prndr - > ptex ) s_ptexCurSet [ 0 ] = 0 ;
if ( s_ptexCurSet [ 1 ] = = curvb . prndr - > ptex ) s_ptexCurSet [ 1 ] = 0 ;
curvb . prndr - > SetViewport ( ) ;
}
curvb . prndr - > SetTarget ( curvb . frame . fbp , curvb . scissor , context ) ;
2010-05-01 20:33:53 +00:00
if ( ( curvb . zbuf . zbp - curvb . pdepth - > fbp ) ! = ( curvb . frame . fbp - curvb . prndr - > fbp ) & & curvb . test . zte )
2010-04-25 08:33:05 +00:00
ZZLog : : Warn_Log ( " Frame and zbuf not aligned. " ) ;
2010-03-19 00:31:15 +00:00
2010-05-01 23:34:44 +00:00
curvb . bVarsSetTarg = true ;
2010-03-19 00:31:15 +00:00
2010-05-01 23:34:44 +00:00
if ( vb [ ! context ] . prndr ! = curvb . prndr ) vb [ ! context ] . bVarsSetTarg = false ;
2010-05-01 20:33:53 +00:00
2010-07-07 10:14:42 +00:00
# ifdef _DEBUG
// These conditions happen often enough that we'll just warn about it rather then abort in Debug mode.
if ( curvb . prndr - > status & CRenderTarget : : TS_NeedUpdate )
{
ZZLog : : Debug_Log ( " In SetContextTarget, prndr is ending with TS_NeedUpdate set. " ) ;
}
if ( curvb . pdepth ! = NULL & & ( curvb . pdepth - > status & CRenderTarget : : TS_NeedUpdate ) )
{
ZZLog : : Debug_Log ( " In SetContextTarget, pdepth is ending with TS_NeedUpdate set. " ) ;
}
# endif
2010-05-01 20:33:53 +00:00
2010-03-19 00:31:15 +00:00
GL_REPORT_ERRORD ( ) ;
}
2010-10-16 11:54:46 +00:00
void SetTexInt ( int context , FRAGMENTSHADER * pfragment , int settexint )
2010-05-01 20:33:53 +00:00
{
2010-03-19 00:31:15 +00:00
FUNCLOG
2010-05-01 20:33:53 +00:00
if ( settexint )
{
2010-03-19 00:31:15 +00:00
tex0Info & tex0 = vb [ context ] . tex0 ;
2010-04-25 00:31:27 +00:00
2010-12-01 14:17:12 +00:00
if ( vb [ context ] . bVarsTexSync ) {
SetTexVariablesInt ( context , GetTexFilter ( vb [ context ] . tex1 ) , tex0 , true , pfragment , s_bForceTexFlush ) ;
} else {
SetTexVariablesInt ( context , GetTexFilter ( vb [ context ] . tex1 ) , tex0 , false , pfragment , s_bForceTexFlush ) ;
INC_TEXVARS ( ) ;
}
vb [ context ] . bVarsTexSync = true ;
2010-03-19 00:31:15 +00:00
}
2010-05-01 20:33:53 +00:00
else
{
2010-05-01 23:34:44 +00:00
vb [ context ] . bVarsTexSync = false ;
2010-03-19 00:31:15 +00:00
}
}
// clamp relies on texture width
2010-09-19 08:01:48 +00:00
void SetTexClamping ( int context , FRAGMENTSHADER * pfragment )
2010-05-01 20:33:53 +00:00
{
2010-03-19 00:31:15 +00:00
FUNCLOG
SetShaderCaller ( " SetTexClamping " ) ;
2010-10-16 11:54:46 +00:00
clampInfo * pclamp = & vb [ context ] . clamp ;
2010-09-19 08:01:48 +00:00
float4 v , v2 ;
2010-03-19 00:31:15 +00:00
v . x = v . y = 0 ;
2010-10-16 11:54:46 +00:00
u32 * ptex = vb [ context ] . ptexClamp ;
2010-03-19 00:31:15 +00:00
ptex [ 0 ] = ptex [ 1 ] = 0 ;
2010-10-16 11:54:46 +00:00
float fw = vb [ context ] . tex0 . tw ;
float fh = vb [ context ] . tex0 . th ;
2010-03-19 00:31:15 +00:00
2010-05-01 20:33:53 +00:00
switch ( pclamp - > wms )
{
2012-04-19 21:22:08 +00:00
case CLAMP_REPEAT :
2010-05-01 20:33:53 +00:00
v2 . x = - 1e10 ;
v2 . z = 1e10 ;
2010-03-19 00:31:15 +00:00
break ;
2010-05-01 20:33:53 +00:00
2012-04-19 21:22:08 +00:00
case CLAMP_CLAMP : // pclamp
2010-03-19 00:31:15 +00:00
// suikoden5 movie text
2010-05-01 20:33:53 +00:00
v2 . x = 0 ;
v2 . z = 1 - 0.5f / fw ;
2010-03-19 00:31:15 +00:00
break ;
2010-05-01 20:33:53 +00:00
2012-04-19 21:22:08 +00:00
case CLAMP_REGION_CLAMP : // reg pclamp
2010-05-01 20:33:53 +00:00
v2 . x = ( pclamp - > minu + 0.5f ) / fw ;
v2 . z = ( pclamp - > maxu - 0.5f ) / fw ;
2010-03-19 00:31:15 +00:00
break ;
2012-04-19 21:22:08 +00:00
case CLAMP_REGION_REPEAT : // region rep x
2010-03-19 00:31:15 +00:00
v . x = 0.9999f ;
2010-08-18 10:52:57 +00:00
v . z = ( float ) fw ;
2010-03-19 00:31:15 +00:00
v2 . x = ( float ) GPU_TEXMASKWIDTH / fw ;
v2 . z = pclamp - > maxu / fw ;
int correctMinu = pclamp - > minu & ( ~ pclamp - > maxu ) ; // (A && B) || C == (A && (B && !C)) + C
2010-05-01 20:33:53 +00:00
if ( correctMinu ! = g_PrevBitwiseTexX )
{
2010-03-19 00:31:15 +00:00
g_PrevBitwiseTexX = correctMinu ;
2010-10-16 11:54:46 +00:00
ptex [ 0 ] = s_BitwiseTextures . GetTex ( correctMinu , 0 ) ;
2010-05-01 20:33:53 +00:00
}
2010-03-19 00:31:15 +00:00
break ;
}
2010-05-01 20:33:53 +00:00
switch ( pclamp - > wmt )
{
2012-04-19 21:22:08 +00:00
case CLAMP_REPEAT :
2010-05-01 20:33:53 +00:00
v2 . y = - 1e10 ;
v2 . w = 1e10 ;
2010-03-19 00:31:15 +00:00
break ;
2010-05-01 20:33:53 +00:00
2012-04-19 21:22:08 +00:00
case CLAMP_CLAMP : // pclamp
2010-03-19 00:31:15 +00:00
// suikoden5 movie text
2010-05-01 20:33:53 +00:00
v2 . y = 0 ;
v2 . w = 1 - 0.5f / fh ;
2010-03-19 00:31:15 +00:00
break ;
2010-05-01 20:33:53 +00:00
2012-04-19 21:22:08 +00:00
case CLAMP_REGION_CLAMP : // reg pclamp
2010-05-01 20:33:53 +00:00
v2 . y = ( pclamp - > minv + 0.5f ) / fh ;
v2 . w = ( pclamp - > maxv - 0.5f ) / fh ;
2010-03-19 00:31:15 +00:00
break ;
2012-04-19 21:22:08 +00:00
case CLAMP_REGION_REPEAT : // region rep y
2010-03-19 00:31:15 +00:00
v . y = 0.9999f ;
2010-08-18 10:52:57 +00:00
v . w = ( float ) fh ;
2010-03-19 00:31:15 +00:00
v2 . y = ( float ) GPU_TEXMASKWIDTH / fh ;
v2 . w = pclamp - > maxv / fh ;
int correctMinv = pclamp - > minv & ( ~ pclamp - > maxv ) ; // (A && B) || C == (A && (B && !C)) + C
2010-05-01 20:33:53 +00:00
if ( correctMinv ! = g_PrevBitwiseTexY )
{
2010-03-19 00:31:15 +00:00
g_PrevBitwiseTexY = correctMinv ;
2010-10-16 11:54:46 +00:00
ptex [ 1 ] = s_BitwiseTextures . GetTex ( correctMinv , ptex [ 0 ] ) ;
2010-03-19 00:31:15 +00:00
}
break ;
2010-05-01 20:33:53 +00:00
}
2010-03-19 00:31:15 +00:00
2010-05-01 20:33:53 +00:00
if ( pfragment - > fTexWrapMode ! = 0 )
2012-05-07 19:51:58 +00:00
ZZshSetParameter4fv ( pfragment - > prog , pfragment - > fTexWrapMode , v , " g_fTexWrapMode " ) ;
2010-05-01 20:33:53 +00:00
if ( pfragment - > fClampExts ! = 0 )
2012-05-07 19:51:58 +00:00
ZZshSetParameter4fv ( pfragment - > prog , pfragment - > fClampExts , v2 , " g_fClampExts " ) ;
2010-03-19 00:31:15 +00:00
}
2010-05-01 20:33:53 +00:00
int CheckTexArray [ 4 ] [ 2 ] [ 2 ] [ 2 ] = { { { { 0 , } } } } ;
2010-10-16 11:54:46 +00:00
void SetTexVariables ( int context , FRAGMENTSHADER * pfragment )
2010-05-01 20:33:53 +00:00
{
2010-03-19 00:31:15 +00:00
FUNCLOG
2010-05-01 20:33:53 +00:00
2010-03-19 00:31:15 +00:00
if ( ! vb [ context ] . curprim . tme ) return ;
2010-05-01 20:33:53 +00:00
assert ( ! vb [ context ] . bNeedTexCheck ) ;
2010-03-19 00:31:15 +00:00
2010-09-19 08:01:48 +00:00
float4 v , v2 ;
2010-05-01 20:33:53 +00:00
2010-03-19 00:31:15 +00:00
tex0Info & tex0 = vb [ context ] . tex0 ;
2010-04-25 00:31:27 +00:00
2010-03-19 06:38:44 +00:00
//float fw = (float)tex0.tw;
//float fh = (float)tex0.th;
2010-03-19 00:31:15 +00:00
2010-05-01 20:33:53 +00:00
if ( ! vb [ context ] . bTexConstsSync )
{
2010-03-19 00:31:15 +00:00
SetShaderCaller ( " SetTexVariables " ) ;
// alpha and texture highlighting
2012-04-19 21:22:08 +00:00
float4 valpha , valpha2 ;
2010-03-19 00:31:15 +00:00
// if clut, use the frame format
2010-09-15 16:54:19 +00:00
int psm = PIXEL_STORAGE_FORMAT ( tex0 ) ;
2010-03-19 00:31:15 +00:00
2010-09-15 16:54:19 +00:00
// ZZLog::Error_Log( "A %d psm, is-clut %d. cpsm %d | %d %d", psm, PSMT_ISCLUT(psm), tex0.cpsm, tex0.tfx, tex0.tcc );
2010-03-19 00:31:15 +00:00
2012-04-19 21:22:08 +00:00
/* tcc -- Texture Color Component 0=RGB, 1=RGBA + use Alpha from TEXA reg when not in PSM
2010-05-01 20:33:53 +00:00
* tfx - - Texture Function ( 0 = modulate , 1 = decal , 2 = hilight , 3 = hilight2 )
*
* valpha2 = 0 0 2 1 0 0 2 1
* 1 0 0 0 1 1 0 0
* 0 0 2 0 0 1 2 0
* 0 0 2 0 0 1 2 0
*
* 0 1 , ! nNeed 1 , psm = 2 , 10 1 , psm = 1
* valpha = 0 0 0 1 0 2 0 0 2 ta0 2 ta1 - 2 ta0 0 0 2 ta0 0 0 0
* 0 0 0 1 0 1 0 0 ta0 ta1 - ta0 0 0 ta0 0 0 0
* 0 0 1 1 0 1 1 1 1 1 ta0 0 1 1
* 0 0 1 1 0 1 1 0 1 0 ta0 0 1 0
*/
2012-04-19 21:22:08 +00:00
valpha2 . x = ( tex0 . tfx = = TFX_DECAL ) ;
valpha2 . y = ( tex0 . tcc = = 1 ) & & ( tex0 . tfx ! = TFX_MODULATE ) ;
valpha2 . z = ( tex0 . tfx ! = TFX_DECAL ) * 2 ;
valpha2 . w = ( tex0 . tfx = = TFX_MODULATE ) ;
2010-05-01 20:33:53 +00:00
2012-04-19 21:22:08 +00:00
if ( tex0 . tcc & & PSMT_ALPHAEXP ( psm ) )
2010-05-01 20:33:53 +00:00
{
2012-04-19 21:22:08 +00:00
valpha . x = ( gs . texa . ta [ 0 ] / 255.0f ) * ( 1 + ( tex0 . tfx = = TFX_MODULATE ) ) ;
if ( psm = = PSMCT24 )
{
valpha . y = 0 ;
}
else
{
valpha . y = ( ( gs . texa . ta [ 1 ] - gs . texa . ta [ 0 ] ) / 255.0f ) * ( 1 + ( tex0 . tfx = = TFX_MODULATE ) ) ;
}
2010-05-01 20:33:53 +00:00
}
else
{
2012-04-19 21:22:08 +00:00
valpha . x = 0 ;
valpha . y = ( ! ! tex0 . tcc ) * ( 1 + ( tex0 . tfx = = TFX_MODULATE ) ) ;
2010-03-19 00:31:15 +00:00
}
2012-04-19 21:22:08 +00:00
valpha . z = ( tex0 . tfx = = TFX_HIGHLIGHT2 ) ;
valpha . w = ( tex0 . tcc = = 0 ) | | ( tex0 . tcc = = 1 & & tex0 . tfx = = TFX_HIGHLIGHT ) ;
2010-03-19 00:31:15 +00:00
2012-05-07 19:51:58 +00:00
ZZshSetParameter4fv ( pfragment - > prog , pfragment - > fTexAlpha , valpha , " g_fTexAlpha " ) ;
ZZshSetParameter4fv ( pfragment - > prog , pfragment - > fTexAlpha2 , valpha2 , " g_fTexAlpha2 " ) ;
2010-05-01 20:33:53 +00:00
2010-09-15 16:54:19 +00:00
if ( IsAlphaTestExpansion ( tex0 ) )
2012-04-19 21:22:08 +00:00
{
float4 vblack ;
vblack . x = vblack . y = vblack . z = vblack . w = 10 ;
if ( tex0 . tcc & & gs . texa . aem & & psm = = PSMCT24 ) vblack . w = 0 ;
2012-05-07 19:51:58 +00:00
ZZshSetParameter4fv ( pfragment - > prog , pfragment - > fTestBlack , vblack , " g_fTestBlack " ) ;
2012-04-19 21:22:08 +00:00
}
2010-03-19 00:31:15 +00:00
SetTexClamping ( context , pfragment ) ;
2010-05-01 20:33:53 +00:00
2010-05-01 23:34:44 +00:00
vb [ context ] . bTexConstsSync = true ;
2010-04-25 00:31:27 +00:00
}
2010-03-19 00:31:15 +00:00
2010-05-01 20:33:53 +00:00
if ( s_bTexFlush )
{
if ( PSMT_ISCLUT ( tex0 . psm ) )
2010-03-19 00:31:15 +00:00
texClutWrite ( context ) ;
else
2010-05-01 23:34:44 +00:00
s_bTexFlush = false ;
2010-03-19 00:31:15 +00:00
}
}
2010-10-16 11:54:46 +00:00
void SetTexVariablesInt ( int context , int bilinear , const tex0Info & tex0 , bool CheckVB , FRAGMENTSHADER * pfragment , int force )
2010-05-01 20:33:53 +00:00
{
2010-03-19 00:31:15 +00:00
FUNCLOG
2010-09-19 08:01:48 +00:00
float4 v ;
2010-09-15 16:54:19 +00:00
CMemoryTarget * pmemtarg = g_MemTargs . GetMemoryTarget ( tex0 , 1 ) ;
2010-04-25 00:31:27 +00:00
2010-09-15 16:54:19 +00:00
assert ( pmemtarg ! = NULL & & pfragment ! = NULL & & pmemtarg - > ptex ! = NULL ) ;
2010-05-01 20:33:53 +00:00
if ( pmemtarg = = NULL | | pfragment = = NULL | | pmemtarg - > ptex = = NULL )
2010-03-19 00:31:15 +00:00
{
2010-09-15 16:54:19 +00:00
ZZLog : : Error_Log ( " SetTexVariablesInt error. " ) ;
2010-03-19 00:31:15 +00:00
return ;
2010-04-25 00:31:27 +00:00
}
2010-09-15 16:54:19 +00:00
if ( CheckVB & & vb [ context ] . pmemtarg = = pmemtarg ) return ;
2010-03-19 00:31:15 +00:00
SetShaderCaller ( " SetTexVariablesInt " ) ;
float fw = ( float ) tex0 . tw ;
float fh = ( float ) tex0 . th ;
bool bUseBilinear = bilinear > 1 | | ( bilinear & & conf . bilinear ) ;
2010-05-01 20:33:53 +00:00
if ( bUseBilinear )
{
2010-03-19 00:31:15 +00:00
v . x = ( float ) fw ;
v . y = ( float ) fh ;
v . z = 1.0f / ( float ) fw ;
v . w = 1.0f / ( float ) fh ;
2010-05-01 20:33:53 +00:00
2012-04-19 21:22:08 +00:00
ZZshSetParameter4fvWithRetry ( & pfragment - > fRealTexDims , pfragment - > prog , v , " g_fRealTexDims " ) ;
2010-03-19 00:31:15 +00:00
}
2010-05-01 20:33:53 +00:00
if ( m_Blocks [ tex0 . psm ] . bpp = = 0 )
{
2010-04-25 08:33:05 +00:00
ZZLog : : Error_Log ( " Undefined tex psm 0x%x! " , tex0 . psm ) ;
2010-03-19 00:31:15 +00:00
return ;
}
const BLOCK & b = m_Blocks [ tex0 . psm ] ;
float fbw = ( float ) tex0 . tbw ;
2010-09-19 08:01:48 +00:00
float4 vTexDims ;
2010-05-01 20:33:53 +00:00
2010-03-19 00:31:15 +00:00
vTexDims . x = b . vTexDims . x * ( fw ) ;
vTexDims . y = b . vTexDims . y * ( fh ) ;
vTexDims . z = ( float ) BLOCK_TEXWIDTH * ( 0.002f / 64.0f + 0.01f / 128.0f ) ;
vTexDims . w = ( float ) BLOCK_TEXHEIGHT * 0.1f / 512.0f ;
2010-05-01 20:33:53 +00:00
if ( bUseBilinear )
{
vTexDims . x * = 1 / 128.0f ;
vTexDims . y * = 1 / 512.0f ;
vTexDims . z * = 1 / 128.0f ;
vTexDims . w * = 1 / 512.0f ;
2010-03-19 00:31:15 +00:00
}
2010-05-01 20:33:53 +00:00
float g_fitexwidth = g_fiGPU_TEXWIDTH / ( float ) pmemtarg - > widthmult ;
2010-03-19 06:38:44 +00:00
//float g_texwidth = GPU_TEXWIDTH*(float)pmemtarg->widthmult;
2010-03-19 00:31:15 +00:00
2010-05-01 20:33:53 +00:00
float fpage = tex0 . tbp0 * ( 64.0f * g_fitexwidth ) ; // + 0.05f * g_fitexwidth;
2010-03-19 00:31:15 +00:00
float fpageint = floorf ( fpage ) ;
2010-03-19 06:38:44 +00:00
//int starttbp = (int)fpage;
2010-04-25 00:31:27 +00:00
2010-03-19 00:31:15 +00:00
// 2048 is number of words to span one page
//float fblockstride = (2048.0f /(float)(g_texwidth*BLOCK_TEXWIDTH)) * b.vTexDims.x * fbw;
2010-05-01 20:33:53 +00:00
float fblockstride = ( 2048.0f / ( float ) ( GPU_TEXWIDTH * ( float ) pmemtarg - > widthmult * BLOCK_TEXWIDTH ) ) * b . vTexDims . x * fbw ;
2010-03-19 00:31:15 +00:00
2010-05-01 20:33:53 +00:00
assert ( fblockstride > = 1.0f ) ;
2010-03-19 00:31:15 +00:00
v . x = ( float ) ( 2048 * g_fitexwidth ) ;
v . y = fblockstride ;
2010-05-01 20:33:53 +00:00
v . z = g_fBlockMult / ( float ) pmemtarg - > widthmult ;
v . w = fpage - fpageint ;
2010-03-19 00:31:15 +00:00
2010-05-01 20:33:53 +00:00
if ( g_fBlockMult > 1 )
{
2010-03-19 00:31:15 +00:00
// make sure to divide by mult (since the G16R16 texture loses info)
2010-05-01 20:33:53 +00:00
v . z * = b . bpp * ( 1 / 32.0f ) ;
2010-03-19 00:31:15 +00:00
}
2012-05-07 19:51:58 +00:00
ZZshSetParameter4fv ( pfragment - > prog , pfragment - > fTexDims , vTexDims , " g_fTexDims " ) ;
2010-05-01 20:33:53 +00:00
2010-09-19 08:01:48 +00:00
// ZZshSetParameter4fv(pfragment->fTexBlock, b.vTexBlock, "g_fTexBlock"); // I change it, and it's working. Seems casting from float4 to float[4] is ok.
2012-05-07 19:51:58 +00:00
ZZshSetParameter4fv ( pfragment - > prog , pfragment - > fTexBlock , & b . vTexBlock . x , " g_fTexBlock " ) ;
ZZshSetParameter4fv ( pfragment - > prog , pfragment - > fTexOffset , v , " g_fTexOffset " ) ;
2010-03-19 00:31:15 +00:00
// get hardware texture dims
2010-09-20 10:09:46 +00:00
//int texheight = pmemtarg->texH;
int texwidth = pmemtarg - > texW ;
2010-03-19 00:31:15 +00:00
v . y = 1.0f ;
2010-05-01 20:33:53 +00:00
v . x = ( fpageint - ( float ) pmemtarg - > realy / ( float ) pmemtarg - > widthmult + 0.5f ) ; //*v.y;
2010-03-19 00:31:15 +00:00
v . z = ( float ) texwidth ;
2010-05-01 20:33:53 +00:00
/* if( !(g_nPixelShaderVer & SHADER_ACCURATE) || bUseBilinear ) {
if ( tex0 . psm = = PSMT4 )
v . w = 0.0f ;
else
v . w = 0.25f ;
}
2010-03-19 00:31:15 +00:00
else
2010-05-01 20:33:53 +00:00
v . w = 0.5f ; */
2010-03-19 00:31:15 +00:00
v . w = 0.5f ;
2012-05-07 19:51:58 +00:00
ZZshSetParameter4fv ( pfragment - > prog , pfragment - > fPageOffset , v , " g_fPageOffset " ) ;
2010-03-19 00:31:15 +00:00
2010-05-01 20:33:53 +00:00
if ( force )
2010-03-19 00:31:15 +00:00
s_ptexCurSet [ context ] = pmemtarg - > ptex - > tex ;
2010-04-25 00:31:27 +00:00
else
2010-03-19 00:31:15 +00:00
s_ptexNextSet [ context ] = pmemtarg - > ptex - > tex ;
2010-04-25 00:31:27 +00:00
vb [ context ] . pmemtarg = pmemtarg ;
2010-05-01 20:33:53 +00:00
2010-05-01 23:34:44 +00:00
vb [ context ] . bVarsTexSync = false ;
2010-03-19 00:31:15 +00:00
}
2012-04-19 21:22:08 +00:00
#if 0
2010-03-19 00:31:15 +00:00
# define SET_ALPHA_COLOR_FACTOR(sign) \
{ \
switch ( a . c ) \
{ \
case 0 : \
vAlphaBlendColor . y = ( sign ) ? 2.0f * 255.0f / 256.0f : - 2.0f * 255.0f / 256.0f ; \
2012-04-19 21:22:08 +00:00
s_srcalpha = GL_ONE ; \
2010-03-19 00:31:15 +00:00
s_alphaeq = ( sign ) ? GL_FUNC_ADD : GL_FUNC_REVERSE_SUBTRACT ; \
break ; \
\
case 1 : \
/* if in 24 bit mode, dest alpha should be one */ \
switch ( PSMT_BITMODE ( vb [ icurctx ] . prndr - > psm ) ) \
{ \
case 0 : \
bDestAlphaColor = ( a . d ! = 2 ) & & ( ( a . a = = a . d ) | | ( a . b = = a . d ) ) ; \
break ; \
\
case 1 : \
/* dest alpha should be one */ \
bDestAlphaColor = 2 ; \
break ; \
/* default: 16bit surface, so returned alpha is ok */ \
} \
break ; \
2012-04-19 21:22:08 +00:00
\
2010-03-19 00:31:15 +00:00
case 2 : \
2010-07-04 03:53:01 +00:00
bNeedBlendFactorInAlpha = true ; /* should disable alpha channel writing */ \
2010-03-19 00:31:15 +00:00
vAlphaBlendColor . y = 0 ; \
vAlphaBlendColor . w = ( sign ) ? ( float ) a . fix * ( 2.0f / 255.0f ) : ( float ) a . fix * ( - 2.0f / 255.0f ) ; \
usec = 0 ; /* change so that alpha comes from source*/ \
break ; \
} \
2012-04-19 21:22:08 +00:00
}
2010-05-01 20:33:53 +00:00
2013-07-03 18:42:05 +00:00
#if 0
if ( a . fix < = 0x80 ) { \
dwTemp = ( a . fix * 2 ) > 255 ? 255 : ( a . fix * 2 ) ; \
dwTemp = dwTemp | ( dwTemp < < 8 ) | ( dwTemp < < 16 ) | 0x80000000 ; \
ZZLog : : Debug_Log ( " bfactor: %8.8x " , dwTemp ) ; \
glBlendColorEXT ( dwTemp ) ; \
} \
else { \
# endif
2010-03-19 00:31:15 +00:00
2010-10-17 09:07:16 +00:00
//void ResetAlphaVariables() {
// FUNCLOG
//}
2010-03-19 00:31:15 +00:00
2010-10-16 11:54:46 +00:00
inline void NeedFactor ( int w )
2010-05-01 20:33:53 +00:00
{
if ( bDestAlphaColor = = 2 )
{
2010-07-04 03:53:01 +00:00
bNeedBlendFactorInAlpha = ( w + 1 ) ? true : false ;
2010-03-19 00:31:15 +00:00
vAlphaBlendColor . y = 0 ;
vAlphaBlendColor . w = ( float ) w ;
}
}
2012-04-19 21:22:08 +00:00
# endif
template < bool SIGN , bool NEED_FACTOR >
__forceinline int Set_Alpha_Color_Factor ( const alphaInfo & a )
{
2012-04-29 18:50:07 +00:00
int usec = 0 ;
2012-04-19 21:22:08 +00:00
switch ( a . c )
{
case 0 :
usec = 0 ;
/* Note: there are already default value when sign is 1. So only change them
* when sign is 0
*/
if ( ! SIGN ) {
vAlphaBlendColor . y = - 2.0f * 255.0f / 256.0f ;
s_alphaeq = GL_FUNC_REVERSE_SUBTRACT ;
}
break ;
case 1 :
usec = 1 ;
/* if in 24 bit mode, dest alpha should be one */
if ( PSMT_BITMODE ( vb [ icurctx ] . prndr - > psm ) = = 1 ) {
/* dest alpha should be one */
ZZLog : : Debug_Log ( " Alpha on a 24 bits framebuffer, good place to check the value of blend " ) ;
// FIMXE: the array constains GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA
// It will love a test with GL_ONE and GL_ZERO
usec = 4 ;
// need a factor correction
if ( NEED_FACTOR ) {
bNeedBlendFactorInAlpha = ( SIGN ) ? true : false ;
vAlphaBlendColor . y = 0 ;
vAlphaBlendColor . w = ( SIGN ) ? 1.0 : - 1.0 ;
}
}
break ;
case 2 :
usec = 0 ; /* change so that alpha comes from source*/
bNeedBlendFactorInAlpha = true ; /* should disable alpha channel writing */
vAlphaBlendColor . y = 0 ;
vAlphaBlendColor . w = ( SIGN ) ? ( float ) a . fix * ( 2.0f / 255.0f ) : ( float ) a . fix * ( - 2.0f / 255.0f ) ;
break ;
default :
assert ( 0 ) ;
}
return usec ;
}
2010-03-19 00:31:15 +00:00
2010-03-19 06:38:44 +00:00
//static int CheckArray[48][2] = {{0,}};
2010-03-19 00:31:15 +00:00
2010-10-16 11:54:46 +00:00
void SetAlphaVariables ( const alphaInfo & a )
2010-03-19 00:31:15 +00:00
{
FUNCLOG
bool alphaenable = true ;
// TODO: negative color when not clamping turns to positive???
2012-04-19 21:22:08 +00:00
// g_vars._bAlphaState = 0; // set all to zero
2010-07-04 03:53:01 +00:00
bNeedBlendFactorInAlpha = false ;
2012-04-19 21:22:08 +00:00
// b2XAlphaTest = 1;
2010-03-19 06:38:44 +00:00
//u32 dwTemp = 0xffffffff;
2012-04-19 21:22:08 +00:00
// bDestAlphaColor = 0;
2010-03-19 00:31:15 +00:00
// default
s_srcalpha = GL_ONE ;
s_dstalpha = GL_ZERO ;
s_alphaeq = GL_FUNC_ADD ;
2012-04-19 21:22:08 +00:00
s_rgbeq = GL_FUNC_ADD ;
2010-03-19 00:31:15 +00:00
2010-07-04 03:53:01 +00:00
// s_alphaInfo = a;
2010-09-19 08:01:48 +00:00
vAlphaBlendColor = float4 ( 1 , 2 * 255.0f / 256.0f , 0 , 0 ) ;
2012-04-19 21:22:08 +00:00
// u32 usec = a.c;
u32 usec ;
const bool POS_A = true ;
const bool NEG_A = false ;
const bool NEED_FACTOR = true ;
2010-03-19 00:31:15 +00:00
2010-05-01 20:33:53 +00:00
/*
* Alpha table
* a + b + d
* S D
* 0 a - a 1 | 0 0 0
* 1 0 0 0 | a - a 1
* 2 0 0 0 | 0 0 0
*
* d = 0 Cs
* a b 0 Cs 1 Cd 2 0
* | |
* 0 000 : a + - a + 1 | 0 + 0 + 0 = 1 | 010 : a + 0 + 1 | 0 + - a + 0 = 1 - ( - a ) ( + ) ( - a ) | 020 : a + 0 + 1 | 0 + 0 + 0 = 1 - ( - a ) ( + ) 0
* 1 100 : 0 + - a + 1 | a + 0 + 0 = 1 - a ( + ) a | 110 : 0 + 0 + 1 | a + - a + 0 = 1 | 120 : 0 + 0 + 1 | a + 0 + 0 = 1 ( + ) a
* 2 200 : 0 + - a + 1 | 0 + 0 + 0 = 1 - a ( + ) 0 | 210 : 0 + 0 + 1 | 0 + - a + 0 = 1 ( - ) a | 220 : 0 + 0 + 1 | 0 + 0 + 0 = 1
*
* d = 1 Cd
* 0 | 1 | 2
* 0 001 : a + - a + 0 | 0 + 0 + 1 = 0 ( + ) 1 | 011 : a + 0 + 0 | 0 + - a + 1 = a ( + ) 1 - a | 021 : a + 0 + 0 | 0 + 0 + 1 = a ( + ) 1
* 1 101 : 0 + - a + 0 | a + 0 + 1 = ( - a ) ( + ) 1 - ( - a ) | 111 : 0 + 0 + 0 | a + - a + 1 = 0 ( + ) 1 | 121 : 0 + 0 + 0 | a + 0 + 1 = 0 ( + ) 1 - ( - a )
* 2 201 : 0 + - a + 0 | 0 + 0 + 1 = a ( R - ) 1 | 211 : 0 + 0 + 0 | 0 + - a + 1 = 0 ( + ) 1 - a | 221 : 0 + 0 + 0 | 0 + 0 + 1 = 0 ( + ) 1
*
* d = 2 0
* 0 | 1 | 2
* 0 002 : a + - a + 0 | 0 + 0 + 0 = 0 | 012 : a + 0 + 0 | 0 + - a + 0 = a ( - ) a | 022 : a + 0 + 0 | 0 + 0 + 0 = a ( + ) 0
* 1 102 : 0 + - a + 0 | a + 0 + 0 = a ( R - ) a | 112 : 0 + 0 + 0 | a + - a + 0 = 0 | 122 : 0 + 0 + 0 | a + 0 + 0 = 0 ( + ) a
* 2 202 : 0 + - a + 0 | 0 + 0 + 0 = a ( R - ) 0 | 212 : 0 + 0 + 0 | 0 + - a + 0 = 0 ( - ) a | 222 : 0 + 0 + 0 | 0 + 0 + 0 = 0
*
2012-04-19 21:22:08 +00:00
* Formulae is : ( a - b ) * ( c / 128 ) + d
2010-05-01 20:33:53 +00:00
* 0 1 2
* a Cs Cd 0
* b Cs Cd 0
* c As Ad ALPHA . FIX
* d Cs Cd 0
*
* We want to emulate Cs * F1 ( alpha ) + Cd * F2 ( alpha ) by OpenGl blending : ( Cs * Ss ( + , - , R - ) Cd * Sd )
* SET_ALPHA_COLOR_FACTOR ( sign ) set Set A ( as As > > 7 , Ad > > 7 or FIX > > 7 ) with sign .
* So we could use 1 + a as one_minus_alpha and - a as alpha .
*
*/
int code = ( a . a * 16 ) + ( a . b * 4 ) + a . d ;
2010-03-19 00:31:15 +00:00
2012-04-19 21:22:08 +00:00
// #define one_minus_alpha (bDestAlphaColor == 2) ? GL_ONE_MINUS_SRC_ALPHA : blendinvalpha[usec]
// #define alpha (bDestAlphaColor == 2) ? GL_SRC_ALPHA : blendalpha[usec]
// #define one (bDestAlphaColor == 2) ? GL_ONE : blendalpha[usec]
// #define zero (bDestAlphaColor == 2) ? GL_ZERO : blendinvalpha[usec]
# define one_minus_alpha blendinvalpha[usec]
# define alpha blendalpha[usec]
2010-03-19 00:31:15 +00:00
2010-04-25 00:31:27 +00:00
switch ( code )
2010-05-01 20:33:53 +00:00
{
2010-03-19 00:31:15 +00:00
case 0 : // 000 // Cs -- nothing changed
2012-04-19 21:22:08 +00:00
case 20 : // 110 = 16+4=20 // Cs
case 40 : // 220 = 32+8=40 // Cs
2010-05-01 20:33:53 +00:00
{
alphaenable = false ;
break ;
}
2012-04-19 21:22:08 +00:00
case 2 : //002 // 0 -- should be zero
2010-03-19 00:31:15 +00:00
case 22 : //112 // 0
2010-05-01 20:33:53 +00:00
case 42 : //222 = 32+8+2 =42 // 0
{
s_rgbeq = GL_FUNC_ADD ;
s_srcrgb = GL_ZERO ;
s_dstrgb = GL_ZERO ;
break ;
}
2010-04-25 00:31:27 +00:00
case 1 : //001 // Cd -- Should be destination alpha
2010-03-19 00:31:15 +00:00
case 21 : //111, // Cd -- 0*Source + 1*Desrinarion
2010-05-01 20:33:53 +00:00
case 41 : //221 = 32+8+1=41 // Cd --
{
s_rgbeq = GL_FUNC_ADD ;
s_srcrgb = GL_ZERO ;
s_dstrgb = GL_ONE ;
break ;
}
case 4 : // 010 // (Cs-Cd)*A+Cs = Cs * (A + 1) - Cd * A
{
2012-04-19 21:22:08 +00:00
// bAlphaClamping = 3;
// SET_ALPHA_COLOR_FACTOR(0); // a = -A
usec = Set_Alpha_Color_Factor < NEG_A , NEED_FACTOR > ( a ) ;
2010-05-01 20:33:53 +00:00
s_rgbeq = GL_FUNC_ADD ; // Cs*(1-a)+Cd*a
s_srcrgb = one_minus_alpha ;
s_dstrgb = alpha ;
2012-04-19 21:22:08 +00:00
// NeedFactor(-1);
2010-05-01 20:33:53 +00:00
break ;
}
case 5 : // 011 // (Cs-Cd)*A+Cs = Cs * A + Cd * (1-A)
{
2012-04-19 21:22:08 +00:00
// bAlphaClamping = 3; // all testing
// SET_ALPHA_COLOR_FACTOR(1);
usec = Set_Alpha_Color_Factor < POS_A , NEED_FACTOR > ( a ) ;
2010-03-19 00:31:15 +00:00
s_rgbeq = GL_FUNC_ADD ;
s_srcrgb = alpha ;
s_dstrgb = one_minus_alpha ;
2010-04-25 00:31:27 +00:00
2012-04-19 21:22:08 +00:00
// NeedFactor(1);
2010-03-19 00:31:15 +00:00
break ;
2010-05-01 20:33:53 +00:00
}
2012-04-19 21:22:08 +00:00
case 6 : //012 // (Cs-Cd)*A = Cs*A - Cd*A
2010-05-01 20:33:53 +00:00
{
2012-04-19 21:22:08 +00:00
// bAlphaClamping = 3;
// SET_ALPHA_COLOR_FACTOR(1);
usec = Set_Alpha_Color_Factor < POS_A , ! NEED_FACTOR > ( a ) ;
2010-03-19 00:31:15 +00:00
2010-05-01 20:33:53 +00:00
s_rgbeq = GL_FUNC_SUBTRACT ;
2010-03-19 00:31:15 +00:00
s_srcrgb = alpha ;
s_dstrgb = alpha ;
break ;
2010-05-01 20:33:53 +00:00
}
case 8 : //020 // Cs*A+Cs = Cs * (1+A)
{
2012-04-19 21:22:08 +00:00
// bAlphaClamping = 2; // max testing
// SET_ALPHA_COLOR_FACTOR(0); // Zeydlitz change this! a = -A
usec = Set_Alpha_Color_Factor < NEG_A , ! NEED_FACTOR > ( a ) ;
2010-05-01 20:33:53 +00:00
s_rgbeq = GL_FUNC_ADD ;
2010-03-19 00:31:15 +00:00
s_srcrgb = one_minus_alpha ; // Cs*(1-a).
s_dstrgb = GL_ZERO ;
// NeedFactor(1);
break ;
2010-05-01 20:33:53 +00:00
}
2010-03-19 00:31:15 +00:00
2010-05-01 20:33:53 +00:00
case 9 : //021 // Cs*A+Cd
{
2012-04-19 21:22:08 +00:00
// bAlphaClamping = 2; // max testing
// SET_ALPHA_COLOR_FACTOR(1);
usec = Set_Alpha_Color_Factor < POS_A , ! NEED_FACTOR > ( a ) ;
2010-05-01 20:33:53 +00:00
s_rgbeq = GL_FUNC_ADD ;
2012-04-19 21:22:08 +00:00
s_srcrgb = alpha ; // ZZ change it too.
2010-03-19 00:31:15 +00:00
s_dstrgb = GL_ONE ;
break ;
2010-05-01 20:33:53 +00:00
}
2010-03-19 00:31:15 +00:00
2010-05-01 20:33:53 +00:00
case 10 : //022 // Cs*A
{
2012-04-19 21:22:08 +00:00
// bAlphaClamping = 2; // max testing
// SET_ALPHA_COLOR_FACTOR(1);
usec = Set_Alpha_Color_Factor < POS_A , ! NEED_FACTOR > ( a ) ;
2010-05-01 20:33:53 +00:00
s_rgbeq = GL_FUNC_ADD ;
s_srcrgb = alpha ;
s_dstrgb = GL_ZERO ;
break ;
2010-03-19 00:31:15 +00:00
}
2012-04-19 21:22:08 +00:00
case 16 : //100 // (Cd-Cs)*A + Cs = Cd*A + Cs*(1-A)
2010-03-19 00:31:15 +00:00
{
2012-04-19 21:22:08 +00:00
// bAlphaClamping = 3;
// SET_ALPHA_COLOR_FACTOR(1);
usec = Set_Alpha_Color_Factor < POS_A , NEED_FACTOR > ( a ) ;
2010-05-01 20:33:53 +00:00
s_rgbeq = GL_FUNC_ADD ;
s_srcrgb = one_minus_alpha ;
s_dstrgb = alpha ;
2012-04-19 21:22:08 +00:00
// NeedFactor(1);
2010-05-01 20:33:53 +00:00
break ;
2010-03-19 00:31:15 +00:00
}
2010-05-01 20:33:53 +00:00
2012-04-19 21:22:08 +00:00
case 17 : //101 // (Cd-Cs)*A + Cd = Cd*(A+1) - A*Cs
2010-03-19 00:31:15 +00:00
{
2012-04-19 21:22:08 +00:00
// bAlphaClamping = 3; // all testing
// SET_ALPHA_COLOR_FACTOR(0);
usec = Set_Alpha_Color_Factor < NEG_A , NEED_FACTOR > ( a ) ;
2010-05-01 20:33:53 +00:00
s_rgbeq = GL_FUNC_ADD ;
s_srcrgb = alpha ;
s_dstrgb = one_minus_alpha ;
2012-04-19 21:22:08 +00:00
// NeedFactor(-1);
2010-05-01 20:33:53 +00:00
break ;
2010-03-19 00:31:15 +00:00
}
2010-05-01 20:33:53 +00:00
2012-04-19 21:22:08 +00:00
case 18 : //102 // (Cd-Cs)*A = Cd*A - Cs*A
2010-03-19 00:31:15 +00:00
{
2012-04-19 21:22:08 +00:00
// bAlphaClamping = 3;
// SET_ALPHA_COLOR_FACTOR(1);
usec = Set_Alpha_Color_Factor < POS_A , ! NEED_FACTOR > ( a ) ;
2010-03-19 00:31:15 +00:00
2010-05-01 20:33:53 +00:00
s_rgbeq = GL_FUNC_REVERSE_SUBTRACT ;
s_srcrgb = alpha ;
s_dstrgb = alpha ;
2010-03-19 00:31:15 +00:00
2010-05-01 20:33:53 +00:00
break ;
}
2012-04-19 21:22:08 +00:00
case 24 : //120 = 16+8 // Cd*A + Cs
2010-05-01 20:33:53 +00:00
{
2012-04-19 21:22:08 +00:00
// bAlphaClamping = 2; // max testing
// SET_ALPHA_COLOR_FACTOR(1);
usec = Set_Alpha_Color_Factor < POS_A , ! NEED_FACTOR > ( a ) ;
2010-05-01 20:33:53 +00:00
s_rgbeq = GL_FUNC_ADD ;
s_srcrgb = GL_ONE ;
s_dstrgb = alpha ;
break ;
2010-03-19 00:31:15 +00:00
}
2010-05-01 20:33:53 +00:00
case 25 : //121 // Cd*(1+A)
{
2012-04-19 21:22:08 +00:00
// bAlphaClamping = 2; // max testing
// SET_ALPHA_COLOR_FACTOR(0);
usec = Set_Alpha_Color_Factor < NEG_A , ! NEED_FACTOR > ( a ) ;
2010-04-25 00:31:27 +00:00
2010-05-01 20:33:53 +00:00
s_rgbeq = GL_FUNC_ADD ;
s_srcrgb = GL_ZERO ;
s_dstrgb = one_minus_alpha ;
2010-04-25 00:31:27 +00:00
2010-05-01 20:33:53 +00:00
// NeedFactor(-1);
break ;
}
2010-03-19 00:31:15 +00:00
2012-04-19 21:22:08 +00:00
case 26 : //122 // Cd*A
2010-05-01 20:33:53 +00:00
{
2012-04-19 21:22:08 +00:00
// bAlphaClamping = 2;
// SET_ALPHA_COLOR_FACTOR(1);
usec = Set_Alpha_Color_Factor < POS_A , ! NEED_FACTOR > ( a ) ;
2010-03-19 00:31:15 +00:00
2010-05-01 20:33:53 +00:00
s_rgbeq = GL_FUNC_ADD ;
s_srcrgb = GL_ZERO ;
s_dstrgb = alpha ;
break ;
}
2010-03-19 00:31:15 +00:00
2012-04-19 21:22:08 +00:00
case 32 : // 200 = 32 // -Cs*A + Cs = Cs*(1-A)
2010-03-19 00:31:15 +00:00
{
2012-04-19 21:22:08 +00:00
// bAlphaClamping = 1; // min testing
// SET_ALPHA_COLOR_FACTOR(1);
usec = Set_Alpha_Color_Factor < POS_A , ! NEED_FACTOR > ( a ) ;
2010-05-01 20:33:53 +00:00
s_rgbeq = GL_FUNC_ADD ;
s_srcrgb = one_minus_alpha ;
s_dstrgb = GL_ZERO ;
break ;
2010-03-19 00:31:15 +00:00
}
2010-05-01 20:33:53 +00:00
case 33 : //201 // -Cs*A + Cd
2010-03-19 00:31:15 +00:00
{
2012-04-19 21:22:08 +00:00
// bAlphaClamping = 1; // min testing
// SET_ALPHA_COLOR_FACTOR(1);
usec = Set_Alpha_Color_Factor < POS_A , ! NEED_FACTOR > ( a ) ;
2010-05-01 20:33:53 +00:00
s_rgbeq = GL_FUNC_REVERSE_SUBTRACT ;
s_srcrgb = alpha ;
s_dstrgb = GL_ONE ;
break ;
}
2012-04-19 21:22:08 +00:00
case 34 : //202 // -Cs*A
case 38 : //212 // -Cd*A
2010-05-01 20:33:53 +00:00
{
2012-04-19 21:22:08 +00:00
// bAlphaClamping = 1; // min testing -- negative values
2010-05-01 20:33:53 +00:00
s_rgbeq = GL_FUNC_ADD ;
s_srcrgb = GL_ZERO ;
s_dstrgb = GL_ZERO ;
break ;
}
2012-04-19 21:22:08 +00:00
case 36 : //210 // -Cd*A + Cs
2010-05-01 20:33:53 +00:00
{
2012-04-19 21:22:08 +00:00
// bAlphaClamping = 1; // min testing
// SET_ALPHA_COLOR_FACTOR(1);
usec = Set_Alpha_Color_Factor < POS_A , ! NEED_FACTOR > ( a ) ;
2010-05-01 20:33:53 +00:00
s_rgbeq = GL_FUNC_SUBTRACT ;
s_srcrgb = GL_ONE ;
s_dstrgb = alpha ;
break ;
2010-03-19 00:31:15 +00:00
}
2012-04-19 21:22:08 +00:00
case 37 : //211 // -Cd*A+Cd = Cd * (1-A)
2010-05-01 20:33:53 +00:00
{
2012-04-19 21:22:08 +00:00
// bAlphaClamping = 1; // min testing
// SET_ALPHA_COLOR_FACTOR(1);
usec = Set_Alpha_Color_Factor < POS_A , ! NEED_FACTOR > ( a ) ;
2010-05-01 20:33:53 +00:00
s_rgbeq = GL_FUNC_ADD ;
s_srcrgb = GL_ZERO ;
s_dstrgb = one_minus_alpha ;
break ;
}
2010-03-19 00:31:15 +00:00
2010-05-01 20:33:53 +00:00
default :
2010-03-19 00:31:15 +00:00
{
2010-05-01 20:33:53 +00:00
ZZLog : : Error_Log ( " Bad alpha code %d | %d %d %d " , code , a . a , a . b , a . d ) ;
}
}
/*
int t_rgbeq = GL_FUNC_ADD ;
int t_srcrgb = GL_ONE ;
int t_dstrgb = GL_ZERO ;
int tAlphaClamping = 0 ;
2010-03-19 00:31:15 +00:00
2010-05-01 20:33:53 +00:00
if ( a . a = = a . b )
{ // just d remains
if ( a . d = = 0 ) { }
else
2010-03-19 00:31:15 +00:00
{
2010-05-01 20:33:53 +00:00
t_dstrgb = a . d = = 1 ? GL_ONE : GL_ZERO ;
t_srcrgb = GL_ZERO ;
t_rgbeq = GL_FUNC_ADD ; //a) (001) (111) (221) b) (002) (112) (222)
}
goto EndSetAlpha ;
}
else if ( a . d = = 2 )
{ // zero
if ( a . a = = 2 )
{
// zero all color
t_srcrgb = GL_ZERO ;
t_dstrgb = GL_ZERO ;
goto EndSetAlpha ; // (202) (212)
}
else if ( a . b = = 2 )
{
//b2XAlphaTest = 1; // a) (022) // b) (122)
SET_ALPHA_COLOR_FACTOR ( 1 ) ;
if ( bDestAlphaColor = = 2 )
{
t_rgbeq = GL_FUNC_ADD ;
t_srcrgb = a . a = = 0 ? GL_ONE : GL_ZERO ;
t_dstrgb = a . a = = 0 ? GL_ZERO : GL_ONE ;
}
else
{
tAlphaClamping = 2 ;
t_rgbeq = GL_FUNC_ADD ;
t_srcrgb = a . a = = 0 ? blendalpha [ usec ] : GL_ZERO ;
t_dstrgb = a . a = = 0 ? GL_ZERO : blendalpha [ usec ] ;
}
goto EndSetAlpha ;
}
// nothing is zero, so must do some real blending //b2XAlphaTest = 1; //a) (012) //b) (102)
tAlphaClamping = 3 ;
SET_ALPHA_COLOR_FACTOR ( 1 ) ;
t_rgbeq = a . a = = 0 ? GL_FUNC_SUBTRACT : GL_FUNC_REVERSE_SUBTRACT ;
t_srcrgb = bDestAlphaColor = = 2 ? GL_ONE : blendalpha [ usec ] ;
t_dstrgb = bDestAlphaColor = = 2 ? GL_ONE : blendalpha [ usec ] ;
}
else if ( a . a = = 2 )
{ // zero
//b2XAlphaTest = 1;
tAlphaClamping = 1 ; // min testing
SET_ALPHA_COLOR_FACTOR ( 1 ) ;
if ( a . b = = a . d )
{
// can get away with 1-A
// a.a == a.d == 2!! (200) (211)
t_rgbeq = GL_FUNC_ADD ;
t_srcrgb = ( a . b = = 0 & & bDestAlphaColor ! = 2 ) ? blendinvalpha [ usec ] : GL_ZERO ;
t_dstrgb = ( a . b = = 0 | | bDestAlphaColor = = 2 ) ? GL_ZERO : blendinvalpha [ usec ] ;
2010-03-19 00:31:15 +00:00
}
2010-04-25 00:31:27 +00:00
else
2010-03-19 00:31:15 +00:00
{
2010-05-01 20:33:53 +00:00
// a) (201) b)(210)
t_rgbeq = a . b = = 0 ? GL_FUNC_REVERSE_SUBTRACT : GL_FUNC_SUBTRACT ;
t_srcrgb = ( a . b = = 0 & & bDestAlphaColor ! = 2 ) ? blendalpha [ usec ] : GL_ONE ;
t_dstrgb = ( a . b = = 0 | | bDestAlphaColor = = 2 ) ? GL_ONE : blendalpha [ usec ] ;
2010-03-19 00:31:15 +00:00
}
}
2010-05-01 20:33:53 +00:00
else if ( a . b = = 2 )
2010-03-19 00:31:15 +00:00
{
2010-05-01 20:33:53 +00:00
tAlphaClamping = 2 ; // max testing
2010-03-19 00:31:15 +00:00
2010-05-01 20:33:53 +00:00
SET_ALPHA_COLOR_FACTOR ( a . a ! = a . d ) ;
2010-03-19 00:31:15 +00:00
2010-05-01 20:33:53 +00:00
if ( a . a = = a . d )
2010-03-19 00:31:15 +00:00
{
2010-05-01 20:33:53 +00:00
// can get away with 1+A, but need to set alpha to negative
// a)(020)
// b)(121)
t_rgbeq = GL_FUNC_ADD ;
if ( bDestAlphaColor = = 2 )
{
t_srcrgb = ( a . a = = 0 ) ? GL_ONE_MINUS_SRC_ALPHA : GL_ZERO ;
t_dstrgb = ( a . a = = 0 ) ? GL_ZERO : GL_ONE_MINUS_SRC_ALPHA ;
}
else
{
t_srcrgb = a . a = = 0 ? blendinvalpha [ usec ] : GL_ZERO ;
t_dstrgb = a . a = = 0 ? GL_ZERO : blendinvalpha [ usec ] ;
}
2010-03-19 00:31:15 +00:00
}
2010-04-25 00:31:27 +00:00
else
2010-03-19 00:31:15 +00:00
{
2010-05-01 20:33:53 +00:00
//a)(021) //b)(120) //b2XAlphaTest = 1;
t_rgbeq = GL_FUNC_ADD ;
t_srcrgb = ( a . a = = 0 & & bDestAlphaColor ! = 2 ) ? blendalpha [ usec ] : GL_ONE ;
t_dstrgb = ( a . a = = 0 | | bDestAlphaColor = = 2 ) ? GL_ONE : blendalpha [ usec ] ;
2010-03-19 00:31:15 +00:00
}
}
else
{
2010-05-01 20:33:53 +00:00
// all 3 components are valid!
tAlphaClamping = 3 ; // all testing
SET_ALPHA_COLOR_FACTOR ( a . a ! = a . d ) ;
if ( a . a = = a . d )
2010-03-19 00:31:15 +00:00
{
2010-05-01 20:33:53 +00:00
// can get away with 1+A, but need to set alpha to negative // a) 010, // b) 101
t_rgbeq = GL_FUNC_ADD ;
if ( bDestAlphaColor = = 2 )
{
// all ones
t_srcrgb = a . a = = 0 ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA ;
t_dstrgb = a . a = = 0 ? GL_SRC_ALPHA : GL_ONE_MINUS_SRC_ALPHA ;
}
else
{
t_srcrgb = a . a = = 0 ? blendinvalpha [ usec ] : blendalpha [ usec ] ;
t_dstrgb = a . a = = 0 ? blendalpha [ usec ] : blendinvalpha [ usec ] ;
}
2010-03-19 00:31:15 +00:00
}
2010-04-25 00:31:27 +00:00
else
2010-03-19 00:31:15 +00:00
{
2010-05-01 20:33:53 +00:00
t_rgbeq = GL_FUNC_ADD ; // a) 011 // b) 100 //
if ( bDestAlphaColor = = 2 )
{
// all ones
t_srcrgb = a . a ! = 0 ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA ;
t_dstrgb = a . a ! = 0 ? GL_SRC_ALPHA : GL_ONE_MINUS_SRC_ALPHA ;
}
else
{
//b2XAlphaTest = 1;
t_srcrgb = a . a ! = 0 ? blendinvalpha [ usec ] : blendalpha [ usec ] ;
t_dstrgb = a . a ! = 0 ? blendalpha [ usec ] : blendinvalpha [ usec ] ;
}
2010-03-19 00:31:15 +00:00
}
}
2010-05-01 20:33:53 +00:00
EndSetAlpha :
2010-03-19 00:31:15 +00:00
2010-05-01 20:33:53 +00:00
if ( alphaenable & & ( t_rgbeq ! = s_rgbeq | | s_srcrgb ! = t_srcrgb | | t_dstrgb ! = s_dstrgb | | tAlphaClamping ! = bAlphaClamping ) ) {
if ( CheckArray [ code ] [ ( bDestAlphaColor = = 2 ) ] ! = - 1 ) {
2010-10-16 11:10:48 +00:00
ZZLog : : Debug_Log ( " A code %d, 0x%x, 0x%x, 0x%x, 0x%x %d " , code , alpha , one_minus_alpha , one , zero , bDestAlphaColor ) ;
ZZLog : : Debug_Log ( " Difference %d %d %d %d | 0x%x 0x%x | 0x%x 0x%x | 0x%x 0x%x | %d %d " ,
2010-05-01 20:33:53 +00:00
code , a . a , a . b , a . d ,
t_rgbeq , s_rgbeq , t_srcrgb , s_srcrgb , t_dstrgb , s_dstrgb , tAlphaClamping , bAlphaClamping ) ;
CheckArray [ code ] [ ( bDestAlphaColor = = 2 ) ] = - 1 ;
}
2010-03-19 00:31:15 +00:00
}
2010-05-01 20:33:53 +00:00
else
if ( CheckArray [ code ] [ ( bDestAlphaColor = = 2 ) ] = = 0 ) {
2010-10-16 11:10:48 +00:00
ZZLog : : Debug_Log ( " Add good code %d %d, psm %d destA %d " , code , a . c , vb [ icurctx ] . prndr - > psm , bDestAlphaColor ) ;
2010-05-01 20:33:53 +00:00
CheckArray [ code ] [ ( bDestAlphaColor = = 2 ) ] = 1 ;
} */
2010-04-25 00:31:27 +00:00
2010-03-19 00:31:15 +00:00
2010-05-01 20:33:53 +00:00
if ( alphaenable )
{
2010-03-19 00:31:15 +00:00
zgsBlendFuncSeparateEXT ( s_srcrgb , s_dstrgb , s_srcalpha , s_dstalpha ) ;
zgsBlendEquationSeparateEXT ( s_rgbeq , s_alphaeq ) ;
glEnable ( GL_BLEND ) ; // always set
}
2010-04-25 00:31:27 +00:00
else
2010-05-01 20:33:53 +00:00
{
2010-03-19 00:31:15 +00:00
glDisable ( GL_BLEND ) ;
2010-05-01 20:33:53 +00:00
}
2010-03-19 00:31:15 +00:00
INC_ALPHAVARS ( ) ;
}
2010-10-16 11:54:46 +00:00
void SetWriteDepth ( )
2010-05-01 20:33:53 +00:00
{
2010-03-19 00:31:15 +00:00
FUNCLOG
2010-05-01 20:33:53 +00:00
if ( conf . mrtdepth )
{
2010-05-01 23:34:44 +00:00
s_bWriteDepth = true ;
2010-03-19 00:31:15 +00:00
s_nWriteDepthCount = 4 ;
}
}
2010-10-16 11:54:46 +00:00
bool IsWriteDepth ( )
2010-05-01 20:33:53 +00:00
{
2010-03-19 00:31:15 +00:00
FUNCLOG
return s_bWriteDepth ;
}
2010-10-16 11:54:46 +00:00
bool IsWriteDestAlphaTest ( )
2010-05-01 20:33:53 +00:00
{
2010-03-19 00:31:15 +00:00
FUNCLOG
return s_bDestAlphaTest ;
}
2010-10-16 11:54:46 +00:00
void SetDestAlphaTest ( )
2010-05-01 20:33:53 +00:00
{
2010-03-19 00:31:15 +00:00
FUNCLOG
2010-05-01 23:34:44 +00:00
s_bDestAlphaTest = true ;
2010-03-19 00:31:15 +00:00
s_nWriteDestAlphaTest = 4 ;
}
2010-04-25 00:31:27 +00:00
2010-10-16 11:54:46 +00:00
void SetTexFlush ( )
2010-05-01 20:33:53 +00:00
{
2010-03-19 00:31:15 +00:00
FUNCLOG
2010-05-01 23:34:44 +00:00
s_bTexFlush = true ;
2010-03-19 00:31:15 +00:00
// if( PSMT_ISCLUT(vb[0].tex0.psm) )
// texClutWrite(0);
// if( PSMT_ISCLUT(vb[1].tex0.psm) )
// texClutWrite(1);
2010-05-01 20:33:53 +00:00
if ( ! s_bForceTexFlush )
2010-03-19 00:31:15 +00:00
{
if ( s_ptexCurSet [ 0 ] ! = s_ptexNextSet [ 0 ] ) s_ptexCurSet [ 0 ] = s_ptexNextSet [ 0 ] ;
if ( s_ptexCurSet [ 1 ] ! = s_ptexNextSet [ 1 ] ) s_ptexCurSet [ 1 ] = s_ptexNextSet [ 1 ] ;
}
}