2010-09-15 16:54:19 +00:00
/* ZZ Open GL graphics plugin
* Copyright ( c ) 2009 - 2010 zeydlitz @ gmail . com , arcum42 @ gmail . com
* Based on Zerofrog ' s ZeroGS KOSMOS ( c ) 2005 - 2008
*
* 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
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA
*/
# ifndef __ZEROGS_SHADERS_H__
# define __ZEROGS_SHADERS_H__
// -- Not very important things, but we keep it to enumerate shader
# define NUM_FILTERS 2 // texture filtering
# define NUM_TYPES 5 // types of texture read modes
# define NUM_TEXWRAPS 4 // texture wrapping
# define NUM_SHADERS (NUM_FILTERS*NUM_TYPES*NUM_TEXWRAPS*32) // # shaders for a given ps
// Just bitmask for different type of shaders
# define SHADER_REDUCED 1 // equivalent to ps2.0
# define SHADER_ACCURATE 2 // for older cards with less accurate math (ps2.x+)
2010-10-18 11:24:40 +00:00
2012-05-07 19:51:58 +00:00
# include <math.h>
2010-10-18 11:24:40 +00:00
# include "ZZoglMath.h"
# include "GS.h"
2012-04-19 21:22:08 +00:00
// By default enable nvidia cg api
# if !defined(GLSL_API) && !defined(NVIDIA_CG_API)
2010-09-15 16:54:19 +00:00
# define NVIDIA_CG_API
2012-04-19 21:22:08 +00:00
# endif
2010-09-15 16:54:19 +00:00
// --------------------------- API abstraction level --------------------------------
# ifdef NVIDIA_CG_API // Code for NVIDIA cg-toolkit API
# include <Cg/cg.h>
# include <Cg/cgGL.h>
# define ZZshProgram CGprogram
# define ZZshShader CGprogram
# define ZZshShaderLink CGprogram
# define ZZshParameter CGparameter
# define ZZshContext CGcontext
# define ZZshProfile CGprofile
# define ZZshError CGerror
# define pZero 0 // Zero parameter
# define sZero 0 // Zero program
# define SAFE_RELEASE_PROG(x) { if( (x) != NULL ) { cgDestroyProgram(x); x = NULL; } }
inline bool ZZshActiveParameter ( ZZshParameter param ) { return ( param ! = NULL ) ; }
# endif // end NVIDIA cg-toolkit API
2012-05-13 17:09:18 +00:00
# ifdef GLSL4_API
# include "GSUniformBufferOGL.h"
2012-05-13 20:22:15 +00:00
# include "GSVertexArrayOGL.h"
2012-05-13 17:09:18 +00:00
# endif
2012-06-01 08:21:31 +00:00
// GLSL only
// Set it to 0 to diable context usage, 1 -- to enable. FFX-1 have a strange issue with ClampExt.
# define NOCONTEXT 0
2012-04-19 21:22:08 +00:00
# ifdef GLSL_API
enum ZZshPARAMTYPE {
ZZ_UNDEFINED ,
ZZ_TEXTURE_2D ,
ZZ_TEXTURE_RECT ,
ZZ_TEXTURE_3D ,
ZZ_FLOAT4 ,
} ;
typedef struct {
const char * ShName ; // Name of uniform
ZZshPARAMTYPE type ; // Choose between parameter type
float fvalue [ 4 ] ;
GLuint sampler ; // Number of texture unit in array
GLint texid ; // Number of texture - texid.
bool Constant ; // Uniform could be constants, does not change at program flow
bool Settled ; // Check if Uniform value was set.
} ZZshParamInfo ;
typedef struct {
void * link ;
bool isFragment ;
} ZZshShaderLink ;
# define ZZshProgram GLuint
# define ZZshShader GLuint
# define ZZshParameter GLint
# define ZZshContext int
# define ZZshProfile int
# define ZZshError int
# define ZZshIndex GLuint
const ZZshParamInfo qZero = { ShName : " " , type : ZZ_UNDEFINED , fvalue : { 0 } , sampler : - 1 , texid : 0 , Constant : false , Settled : false } ;
# define pZero 0
const ZZshShaderLink sZero = { link : NULL , isFragment : false } ;
inline bool ZZshActiveParameter ( ZZshParameter param ) { return ( param > - 1 ) ; }
2012-06-12 18:14:01 +00:00
# ifndef GLSL4_API
2012-04-19 21:22:08 +00:00
# define SAFE_RELEASE_PROG(x) { /*don't know what to do*/ }
2012-06-12 18:14:01 +00:00
# endif
2012-04-19 21:22:08 +00:00
// ---------------------------
# endif
2012-05-07 19:51:58 +00:00
extern float4 g_vdepth ;
extern float4 vlogz ;
# ifdef GLSL4_API
enum {
ZZSH_CTX_0 = 0 ,
ZZSH_CTX_1 = 1 ,
ZZSH_CTX_ALL = 2
} ;
// Note A nice template could be better
// Warning order is important for buffer (see GLSL)
// Note must be keep POD (so you can map it to GLSL)
struct GlobalUniform {
union {
struct {
// VS
float g_fPosXY [ 4 ] ; // dual context
// PS
float g_fFogColor [ 4 ] ;
} ;
float linear [ 2 * 4 ] ;
} ;
2012-05-15 06:40:45 +00:00
void SettleFloat ( uint indice , const float * v ) {
2012-05-21 06:43:28 +00:00
assert ( indice + 3 < 2 * 4 ) ;
2012-05-07 19:51:58 +00:00
linear [ indice + 0 ] = v [ 0 ] ;
linear [ indice + 1 ] = v [ 1 ] ;
linear [ indice + 2 ] = v [ 2 ] ;
linear [ indice + 3 ] = v [ 3 ] ;
}
} ;
struct ConstantUniform {
union {
struct {
// Both VS/PS
float g_fBilinear [ 4 ] ;
float g_fZbias [ 4 ] ;
float g_fc0 [ 4 ] ;
float g_fMult [ 4 ] ;
// VS
float g_fZ [ 4 ] ;
float g_fZMin [ 4 ] ;
float g_fZNorm [ 4 ] ;
// PS
float g_fExactColor [ 4 ] ;
} ;
float linear [ 8 * 4 ] ;
} ;
2012-05-15 06:40:45 +00:00
void SettleFloat ( uint indice , const float * v ) {
2012-05-21 06:43:28 +00:00
assert ( indice + 3 < 8 * 4 ) ;
2012-05-07 19:51:58 +00:00
linear [ indice + 0 ] = v [ 0 ] ;
linear [ indice + 1 ] = v [ 1 ] ;
linear [ indice + 2 ] = v [ 2 ] ;
linear [ indice + 3 ] = v [ 3 ] ;
}
} ;
struct FragmentUniform {
union {
struct {
float g_fTexAlpha2 [ 4 ] ; // dual context
float g_fTexOffset [ 4 ] ; // dual context
float g_fTexDims [ 4 ] ; // dual context
float g_fTexBlock [ 4 ] ; // dual context
float g_fClampExts [ 4 ] ; // dual context
float g_fTexWrapMode [ 4 ] ; // dual context
float g_fRealTexDims [ 4 ] ; // dual context
float g_fTestBlack [ 4 ] ; // dual context
float g_fPageOffset [ 4 ] ; // dual context
float g_fTexAlpha [ 4 ] ; // dual context
float g_fInvTexDims [ 4 ] ;
float g_fBitBltZ [ 4 ] ;
float g_fOneColor [ 4 ] ;
} ;
float linear [ 13 * 4 ] ;
} ;
2012-05-15 06:40:45 +00:00
void SettleFloat ( uint indice , const float * v ) {
2012-05-21 06:43:28 +00:00
assert ( indice + 3 < 13 * 4 ) ;
2012-05-07 19:51:58 +00:00
linear [ indice + 0 ] = v [ 0 ] ;
linear [ indice + 1 ] = v [ 1 ] ;
linear [ indice + 2 ] = v [ 2 ] ;
linear [ indice + 3 ] = v [ 3 ] ;
}
} ;
struct VertexUniform {
union {
struct {
float g_fBitBltPos [ 4 ] ;
float g_fBitBltTex [ 4 ] ;
float g_fBitBltTrans [ 4 ] ;
} ;
float linear [ 3 * 4 ] ;
} ;
2012-05-15 06:40:45 +00:00
void SettleFloat ( uint indice , const float * v ) {
2012-05-21 06:43:28 +00:00
assert ( indice + 3 < 3 * 4 ) ;
2012-05-07 19:51:58 +00:00
linear [ indice + 0 ] = v [ 0 ] ;
linear [ indice + 1 ] = v [ 1 ] ;
linear [ indice + 2 ] = v [ 2 ] ;
linear [ indice + 3 ] = v [ 3 ] ;
}
} ;
# endif
2012-04-19 21:22:08 +00:00
2010-10-23 04:14:19 +00:00
//const static char* g_pPsTexWrap[] = { "-DREPEAT", "-DCLAMP", "-DREGION_REPEAT", NULL };
2010-09-15 16:54:19 +00:00
2012-04-19 21:22:08 +00:00
enum ZZshShaderType { ZZ_SH_ZERO , ZZ_SH_REGULAR , ZZ_SH_REGULAR_FOG , ZZ_SH_TEXTURE , ZZ_SH_TEXTURE_FOG , ZZ_SH_CRTC , ZZ_SH_NONE } ;
2010-09-19 08:01:48 +00:00
// We have "compatible" shaders, as RegularFogVS and RegularFogPS. if don't need to wory about incompatible shaders
// It used only in GLSL mode.
2010-09-15 16:54:19 +00:00
// ------------------------- Variables -------------------------------
2010-09-19 08:01:48 +00:00
extern int g_nPixelShaderVer ;
extern ZZshShaderLink pvs [ 16 ] , g_vsprog , g_psprog ;
extern ZZshParameter g_vparamPosXY [ 2 ] , g_fparamFogColor ;
2010-09-15 16:54:19 +00:00
# define MAX_ACTIVE_UNIFORMS 600
# define MAX_ACTIVE_SHADERS 400
2012-05-07 19:51:58 +00:00
# ifndef GLSL4_API
2010-09-15 16:54:19 +00:00
struct FRAGMENTSHADER
{
FRAGMENTSHADER ( ) : prog ( sZero ) , Shader ( 0 ) , sMemory ( pZero ) , sFinal ( pZero ) , sBitwiseANDX ( pZero ) , sBitwiseANDY ( pZero ) , sInterlace ( pZero ) , sCLUT ( pZero ) , sOneColor ( pZero ) , sBitBltZ ( pZero ) ,
fTexAlpha2 ( pZero ) , fTexOffset ( pZero ) , fTexDims ( pZero ) , fTexBlock ( pZero ) , fClampExts ( pZero ) , fTexWrapMode ( pZero ) ,
2010-09-19 08:01:48 +00:00
fRealTexDims ( pZero ) , fTestBlack ( pZero ) , fPageOffset ( pZero ) , fTexAlpha ( pZero ) { }
ZZshShaderLink prog ; // it link to FRAGMENTSHADER structure, for compability between GLSL and CG
ZZshShader Shader ; // GLSL store shader's not as ready programs, but as shaders compilated object. VS and PS should be linked together to
// made a program.
2010-09-15 16:54:19 +00:00
ZZshShaderType ShaderType ; // Not every PS and VS are used together, only compatible ones.
ZZshParameter sMemory , sFinal , sBitwiseANDX , sBitwiseANDY , sInterlace , sCLUT ;
ZZshParameter sOneColor , sBitBltZ , sInvTexDims ;
ZZshParameter fTexAlpha2 , fTexOffset , fTexDims , fTexBlock , fClampExts , fTexWrapMode , fRealTexDims , fTestBlack , fPageOffset , fTexAlpha ;
2010-09-19 08:01:48 +00:00
int ParametersStart , ParametersFinish ; // this is part of UniformsIndex array in which parameters of this shader stored. Last one is ParametersFinish-1
2010-09-15 16:54:19 +00:00
# ifdef _DEBUG
string filename ;
# endif
2012-04-19 21:22:08 +00:00
# ifdef NVIDIA_CG_API
2010-09-15 16:54:19 +00:00
void set_uniform_param ( ZZshParameter & var , const char * name )
{
ZZshParameter p ;
p = cgGetNamedParameter ( prog , name ) ;
if ( p ! = NULL & & cgIsParameterUsed ( p , prog ) = = CG_TRUE ) var = p ;
}
bool set_texture ( GLuint texobj , const char * name )
{
ZZshParameter p ;
p = cgGetNamedParameter ( prog , name ) ;
if ( p ! = NULL & & cgIsParameterUsed ( p , prog ) = = CG_TRUE )
{
cgGLSetTextureParameter ( p , texobj ) ;
cgGLEnableTextureParameter ( p ) ;
return true ;
}
return false ;
}
bool connect ( ZZshParameter & tex , const char * name )
{
ZZshParameter p ;
p = cgGetNamedParameter ( prog , name ) ;
if ( p ! = NULL & & cgIsParameterUsed ( p , prog ) = = CG_TRUE )
{
cgConnectParameter ( tex , p ) ;
return true ;
}
return false ;
}
bool set_texture ( ZZshParameter & tex , const char * name )
{
ZZshParameter p ;
p = cgGetNamedParameter ( prog , name ) ;
if ( p ! = NULL & & cgIsParameterUsed ( p , prog ) = = CG_TRUE )
{
//cgGLEnableTextureParameter(p);
tex = p ;
return true ;
}
return false ;
}
2010-09-19 08:01:48 +00:00
bool set_shader_const ( float4 v , const char * name )
2010-09-15 16:54:19 +00:00
{
ZZshParameter p ;
p = cgGetNamedParameter ( prog , name ) ;
if ( p ! = NULL & & cgIsParameterUsed ( p , prog ) = = CG_TRUE )
{
cgGLSetParameter4fv ( p , v ) ;
return true ;
}
return false ;
}
2012-04-19 21:22:08 +00:00
# endif
2010-09-15 16:54:19 +00:00
} ;
2012-05-07 19:51:58 +00:00
# else
2012-05-27 15:34:48 +00:00
const GLenum g_texture_target [ 11 ] = { GL_TEXTURE_RECTANGLE , GL_TEXTURE_RECTANGLE , GL_TEXTURE_2D , GL_TEXTURE_2D , GL_TEXTURE_2D , GL_TEXTURE_3D , GL_TEXTURE_RECTANGLE , GL_TEXTURE_RECTANGLE , GL_TEXTURE_RECTANGLE , GL_TEXTURE_2D , GL_TEXTURE_RECTANGLE } ;
2012-05-07 19:51:58 +00:00
2012-06-01 08:21:31 +00:00
extern uint g_current_texture_bind [ 11 ] ;
2012-05-07 19:51:58 +00:00
struct SamplerParam {
int unit ;
GLuint texid ;
GLenum target ;
SamplerParam ( ) : unit ( - 1 ) , texid ( 0 ) , target ( 0 ) { }
2012-05-21 06:43:28 +00:00
void set_unit ( int new_unit ) {
2012-05-27 15:34:48 +00:00
assert ( new_unit < 11 ) ;
2012-05-07 19:51:58 +00:00
unit = new_unit ;
target = g_texture_target [ new_unit ] ;
}
void enable_texture ( ) {
assert ( unit > = 0 ) ;
2012-05-27 15:34:48 +00:00
assert ( unit < 11 ) ;
2012-05-07 19:51:58 +00:00
if ( texid ) {
2012-06-18 22:13:22 +00:00
// Unfortunately there is a nastly corner case
// 1/ Attach a texture to the unit
// 2/ delete the texture
// 3/ recreate a texture (with same id)
// 4/ => texture need to be reattached again...
#if 0
2012-05-27 15:34:48 +00:00
if ( g_current_texture_bind [ unit ] ! = texid ) {
glActiveTexture ( GL_TEXTURE0 + unit ) ;
glBindTexture ( target , texid ) ;
g_current_texture_bind [ unit ] = texid ;
}
2012-06-18 22:13:22 +00:00
# else
glActiveTexture ( GL_TEXTURE0 + unit ) ;
glBindTexture ( target , texid ) ;
# endif
2012-05-07 19:51:58 +00:00
}
}
2012-05-15 06:40:45 +00:00
void set_texture ( GLuint new_texid ) {
texid = new_texid ;
2012-05-07 19:51:58 +00:00
}
2012-05-21 06:43:28 +00:00
void release_texture ( ) {
texid = 0 ;
}
2012-05-07 19:51:58 +00:00
} ;
struct FRAGMENTSHADER
{
2012-05-13 17:14:05 +00:00
FRAGMENTSHADER ( ) : prog ( sZero )
, program ( 0 )
2012-05-15 06:40:45 +00:00
, context ( 0 )
, sMemory ( 0 ) // dual context need 2 slots
2012-05-07 19:51:58 +00:00
, sFinal ( 2 )
, sBitwiseANDX ( 3 )
, sBitwiseANDY ( 4 )
, sInterlace ( 5 )
, sCLUT ( 6 )
{
// Uniform
sOneColor = ( ZZshParameter ) offsetof ( struct FragmentUniform , g_fOneColor ) / 4 ;
sBitBltZ = ( ZZshParameter ) offsetof ( struct FragmentUniform , g_fBitBltZ ) / 4 ;
sInvTexDims = ( ZZshParameter ) offsetof ( struct FragmentUniform , g_fInvTexDims ) / 4 ;
fTexAlpha = ( ZZshParameter ) offsetof ( struct FragmentUniform , g_fTexAlpha ) / 4 ;
fTexAlpha2 = ( ZZshParameter ) offsetof ( struct FragmentUniform , g_fTexAlpha2 ) / 4 ;
fTexOffset = ( ZZshParameter ) offsetof ( struct FragmentUniform , g_fTexOffset ) / 4 ;
fTexDims = ( ZZshParameter ) offsetof ( struct FragmentUniform , g_fTexDims ) / 4 ;
fTexBlock = ( ZZshParameter ) offsetof ( struct FragmentUniform , g_fTexBlock ) / 4 ;
fClampExts = ( ZZshParameter ) offsetof ( struct FragmentUniform , g_fClampExts ) / 4 ; // FIXME: There is a bug, that lead FFX-1 to incorrect CLAMP if this uniform have context.
fTexWrapMode = ( ZZshParameter ) offsetof ( struct FragmentUniform , g_fTexWrapMode ) / 4 ;
fRealTexDims = ( ZZshParameter ) offsetof ( struct FragmentUniform , g_fRealTexDims ) / 4 ;
fTestBlack = ( ZZshParameter ) offsetof ( struct FragmentUniform , g_fTestBlack ) / 4 ;
fPageOffset = ( ZZshParameter ) offsetof ( struct FragmentUniform , g_fPageOffset ) / 4 ;
//sFinal = 2;
//sBitwiseANDX = 3;
//sBitwiseANDY = 4;
//sInterlace = 5;
//sCLUT = 6;
2012-05-27 15:34:48 +00:00
samplers [ sMemory ] . set_unit ( 10 ) ;
samplers [ sMemory + 1 ] . set_unit ( 10 ) ; // Dual context. Use same unit
2012-05-07 19:51:58 +00:00
samplers [ sFinal ] . set_unit ( 1 ) ;
samplers [ sBitwiseANDX ] . set_unit ( 6 ) ;
samplers [ sBitwiseANDY ] . set_unit ( 7 ) ;
samplers [ sInterlace ] . set_unit ( 8 ) ;
samplers [ sCLUT ] . set_unit ( 9 ) ;
2012-05-24 06:39:39 +00:00
prog . isFragment = true ;
prog . link = ( void * ) this ;
2012-05-07 19:51:58 +00:00
}
ZZshShaderLink prog ; // it link to FRAGMENTSHADER structure, for compability between GLSL and CG
2012-05-13 17:14:05 +00:00
ZZshProgram program ;
2012-05-15 06:40:45 +00:00
uint context ;
2012-05-07 19:51:58 +00:00
FragmentUniform uniform_buffer [ ZZSH_CTX_ALL ] ;
// sampler
2012-05-15 06:40:45 +00:00
const ZZshParameter sMemory ;
2012-05-07 19:51:58 +00:00
const ZZshParameter sFinal , sBitwiseANDX , sBitwiseANDY , sInterlace , sCLUT ;
SamplerParam samplers [ 7 ] ;
// uniform
ZZshParameter sOneColor , sBitBltZ , sInvTexDims ;
ZZshParameter fTexAlpha2 , fTexOffset , fTexDims , fTexBlock , fClampExts , fTexWrapMode , fRealTexDims , fTestBlack , fPageOffset , fTexAlpha ;
# ifdef _DEBUG
string filename ;
# endif
2012-05-15 06:40:45 +00:00
void ZZshSetParameter4fv ( ZZshParameter param , const float * v ) {
if ( IsDualContext ( param ) )
2012-05-07 19:51:58 +00:00
uniform_buffer [ context ] . SettleFloat ( ( int ) param , v ) ;
else
for ( int i = 0 ; i < ZZSH_CTX_ALL ; i + + )
uniform_buffer [ i ] . SettleFloat ( ( int ) param , v ) ;
}
2012-05-15 06:40:45 +00:00
bool IsDualContext ( ZZshParameter param ) {
if ( param = = sInvTexDims | | param = = sBitBltZ | | param = = sOneColor )
return false ;
else
return true ;
}
void enable_texture ( ) {
2012-05-21 06:43:28 +00:00
samplers [ sMemory + context ] . enable_texture ( ) ; // sMemory is dual context
2012-05-07 19:51:58 +00:00
for ( int i = 2 ; i < 7 ; i + + )
samplers [ i ] . enable_texture ( ) ;
}
void set_texture ( ZZshParameter param , GLuint texid ) {
2012-05-21 06:43:28 +00:00
if ( param = = sMemory ) // sMemory is dual context
samplers [ sMemory + context ] . set_texture ( texid ) ;
2012-05-15 06:40:45 +00:00
else
samplers [ param ] . set_texture ( texid ) ;
2012-05-07 19:51:58 +00:00
}
2012-05-21 06:43:28 +00:00
void release_prog ( ) {
if ( program ) {
glDeleteProgram ( program ) ;
program = 0 ;
}
for ( uint i = 0 ; i < 7 ; i + + )
samplers [ i ] . release_texture ( ) ;
}
2012-06-01 08:21:31 +00:00
void set_context ( uint new_context ) { context = new_context * NOCONTEXT ; }
2012-05-07 19:51:58 +00:00
} ;
# endif
# ifdef GLSL4_API
struct COMMONSHADER
{
2012-05-15 06:40:45 +00:00
COMMONSHADER ( ) : context ( 0 )
, sBlocks ( 0 )
2012-05-07 19:51:58 +00:00
, sBilinearBlocks ( 1 )
, sConv16to32 ( 2 )
, sConv32to16 ( 3 )
{
// sBlocks = 0;
// sBilinearBlocks = 1;
// sConv16to32 = 2;
// sConv32to16 = 3;
samplers [ sBlocks ] . set_unit ( 2 ) ;
samplers [ sBilinearBlocks ] . set_unit ( 3 ) ;
samplers [ sConv16to32 ] . set_unit ( 4 ) ;
samplers [ sConv32to16 ] . set_unit ( 5 ) ;
g_fparamFogColor = ( ZZshParameter ) offsetof ( struct GlobalUniform , g_fFogColor ) / 4 ;
g_vparamPosXY = ( ZZshParameter ) offsetof ( struct GlobalUniform , g_fPosXY ) / 4 ;
g_fBilinear = ( ZZshParameter ) offsetof ( struct ConstantUniform , g_fBilinear ) / 4 ;
g_fZBias = ( ZZshParameter ) offsetof ( struct ConstantUniform , g_fZbias ) / 4 ;
g_fc0 = ( ZZshParameter ) offsetof ( struct ConstantUniform , g_fc0 ) / 4 ;
g_fMult = ( ZZshParameter ) offsetof ( struct ConstantUniform , g_fMult ) / 4 ;
g_fZ = ( ZZshParameter ) offsetof ( struct ConstantUniform , g_fZ ) / 4 ;
g_fZMin = ( ZZshParameter ) offsetof ( struct ConstantUniform , g_fZMin ) / 4 ;
g_fZNorm = ( ZZshParameter ) offsetof ( struct ConstantUniform , g_fZNorm ) / 4 ;
g_fExactColor = ( ZZshParameter ) offsetof ( struct ConstantUniform , g_fExactColor ) / 4 ;
// Setup the constant buffer
// Set Z-test, log or no log;
if ( conf . settings ( ) . no_logz ) {
g_vdepth = float4 ( 255.0 / 256.0f , 255.0 / 65536.0f , 255.0f / ( 65535.0f * 256.0f ) , 1.0f / ( 65536.0f * 65536.0f ) ) ;
vlogz = float4 ( 1.0f , 0.0f , 0.0f , 0.0f ) ;
}
else {
g_vdepth = float4 ( 256.0f * 65536.0f , 65536.0f , 256.0f , 65536.0f * 65536.0f ) ;
vlogz = float4 ( 0.0f , 1.0f , 0.0f , 0.0f ) ;
}
uniform_buffer_constant . SettleFloat ( g_fZ , g_vdepth ) ;
uniform_buffer_constant . SettleFloat ( g_fZMin , vlogz ) ;
const float g_filog32 = 0.999f / ( 32.0f * logf ( 2.0f ) ) ;
float4 vnorm = float4 ( g_filog32 , 0 , 0 , 0 ) ;
uniform_buffer_constant . SettleFloat ( g_fZNorm , vnorm ) ;
uniform_buffer_constant . SettleFloat ( g_fBilinear , float4 ( - 0.2f , - 0.65f , 0.9f , 1.0f / 32767.0f ) ) ;
uniform_buffer_constant . SettleFloat ( g_fZBias , float4 ( 1.0f / 256.0f , 1.0004f , 1 , 0.5f ) ) ;
uniform_buffer_constant . SettleFloat ( g_fc0 , float4 ( 0 , 1 , 0.001f , 0.5f ) ) ;
uniform_buffer_constant . SettleFloat ( g_fExactColor , float4 ( 0.5f , ( conf . settings ( ) . exact_color ) ? 0.9f / 256.0f : 0.5f / 256.0f , 0 , 1 / 255.0f ) ) ;
uniform_buffer_constant . SettleFloat ( g_fMult , float4 ( 1 / 1024.0f , 0.2f / 1024.0f , 1 / 128.0f , 1 / 512.0f ) ) ;
}
ZZshParameter g_fparamFogColor , g_vparamPosXY ;
ZZshParameter g_fBilinear , g_fZBias , g_fc0 , g_fMult , g_fZ , g_fZMin , g_fZNorm , g_fExactColor ;
2012-05-15 06:40:45 +00:00
uint context ;
2012-05-07 19:51:58 +00:00
GlobalUniform uniform_buffer [ ZZSH_CTX_ALL ] ;
ConstantUniform uniform_buffer_constant ;
// Sampler
const ZZshParameter sBlocks , sBilinearBlocks , sConv16to32 , sConv32to16 ;
SamplerParam samplers [ 4 ] ;
2012-05-15 06:40:45 +00:00
void ZZshSetParameter4fv ( ZZshParameter param , const float * v ) {
if ( IsDualContext ( param ) )
2012-05-07 19:51:58 +00:00
uniform_buffer [ context ] . SettleFloat ( ( int ) param , v ) ;
else
for ( int i = 0 ; i < ZZSH_CTX_ALL ; i + + )
uniform_buffer [ i ] . SettleFloat ( ( int ) param , v ) ;
}
2012-05-15 06:40:45 +00:00
bool IsDualContext ( ZZshParameter param ) {
if ( param = = g_vparamPosXY ) return true ;
else return false ;
}
2012-05-07 19:51:58 +00:00
void set_texture ( ZZshParameter param , GLuint texid ) {
samplers [ param ] . set_texture ( texid ) ;
}
void enable_texture ( ) {
for ( int i = 0 ; i < 4 ; i + + )
samplers [ i ] . enable_texture ( ) ;
}
2012-06-01 08:21:31 +00:00
void set_context ( uint new_context ) { context = new_context * NOCONTEXT ; }
2012-05-07 19:51:58 +00:00
} ;
# endif
2010-09-15 16:54:19 +00:00
2012-05-07 19:51:58 +00:00
# ifndef GLSL4_API
2010-09-15 16:54:19 +00:00
struct VERTEXSHADER
{
VERTEXSHADER ( ) : prog ( sZero ) , Shader ( 0 ) , sBitBltPos ( pZero ) , sBitBltTex ( pZero ) { }
ZZshShaderLink prog ;
ZZshShader Shader ;
ZZshShaderType ShaderType ;
ZZshParameter sBitBltPos , sBitBltTex , fBitBltTrans ; // vertex shader constants
int ParametersStart , ParametersFinish ;
} ;
2012-05-07 19:51:58 +00:00
# else
struct VERTEXSHADER
{
2012-05-15 06:40:45 +00:00
VERTEXSHADER ( ) : prog ( sZero ) , program ( 0 ) , context ( 0 )
2012-05-07 19:51:58 +00:00
{
sBitBltPos = ( ZZshParameter ) offsetof ( struct VertexUniform , g_fBitBltPos ) / 4 ;
sBitBltTex = ( ZZshParameter ) offsetof ( struct VertexUniform , g_fBitBltTex ) / 4 ;
fBitBltTrans = ( ZZshParameter ) offsetof ( struct VertexUniform , g_fBitBltTrans ) / 4 ;
// Default value not sure it is needed
uniform_buffer [ 0 ] . SettleFloat ( fBitBltTrans , float4 ( 0.5f , - 0.5f , 0.5 , 0.5 + 0.4 / 416.0f ) ) ;
uniform_buffer [ 1 ] . SettleFloat ( fBitBltTrans , float4 ( 0.5f , - 0.5f , 0.5 , 0.5 + 0.4 / 416.0f ) ) ;
2012-05-24 06:39:39 +00:00
prog . isFragment = false ;
prog . link = ( void * ) this ;
2012-05-07 19:51:58 +00:00
}
VertexUniform uniform_buffer [ ZZSH_CTX_ALL ] ;
ZZshShaderLink prog ;
2012-05-13 17:14:05 +00:00
ZZshProgram program ;
2012-05-15 06:40:45 +00:00
uint context ;
2012-05-07 19:51:58 +00:00
ZZshParameter sBitBltPos , sBitBltTex , fBitBltTrans ; // vertex shader constants
2012-05-15 06:40:45 +00:00
void ZZshSetParameter4fv ( ZZshParameter param , const float * v ) {
if ( IsDualContext ( param ) )
2012-05-07 19:51:58 +00:00
uniform_buffer [ context ] . SettleFloat ( ( int ) param , v ) ;
else
for ( int i = 0 ; i < ZZSH_CTX_ALL ; i + + )
uniform_buffer [ i ] . SettleFloat ( ( int ) param , v ) ;
}
2012-05-15 06:40:45 +00:00
bool IsDualContext ( ZZshParameter param ) { return false ; }
2012-06-01 08:21:31 +00:00
void set_context ( uint new_context ) { context = new_context * NOCONTEXT ; }
2012-06-12 18:14:01 +00:00
void release_prog ( ) {
if ( program ) {
glDeleteProgram ( program ) ;
program = 0 ;
}
}
2012-05-07 19:51:58 +00:00
} ;
2012-06-12 18:14:01 +00:00
# endif
# ifdef GLSL4_API
# define SAFE_RELEASE_PROG(x) { \
if ( ( x . link ) ! = NULL ) { \
if ( x . isFragment ) { \
FRAGMENTSHADER * shader = ( FRAGMENTSHADER * ) x . link ; \
shader - > release_prog ( ) ; \
} else { \
VERTEXSHADER * shader = ( VERTEXSHADER * ) x . link ; \
shader - > release_prog ( ) ; \
} \
} \
}
2012-05-07 19:51:58 +00:00
# endif
2010-09-15 16:54:19 +00:00
extern VERTEXSHADER pvsBitBlt ;
extern FRAGMENTSHADER ppsBitBlt [ 2 ] , ppsBitBltDepth , ppsOne ; // ppsOne used to stop using shaders for draw
extern FRAGMENTSHADER ppsBaseTexture , ppsConvert16to32 , ppsConvert32to16 ;
2010-09-19 08:01:48 +00:00
extern FRAGMENTSHADER ppsRegular [ 4 ] , ppsTexture [ NUM_SHADERS ] ;
2012-04-19 21:22:08 +00:00
extern FRAGMENTSHADER ppsCRTC [ 2 ] , /*ppsCRTC24[2],*/ ppsCRTCTarg [ 2 ] ;
2012-05-07 19:51:58 +00:00
# ifdef GLSL4_API
extern COMMONSHADER g_cs ;
# endif
2012-04-19 21:22:08 +00:00
extern int interlace_mode ;
2010-09-15 16:54:19 +00:00
2012-04-19 21:22:08 +00:00
enum CRTC_TYPE
{
CRTC_RENDER ,
//CRTC_RENDER_24,
CRTC_RENDER_TARG
} ;
static __forceinline FRAGMENTSHADER * curr_ppsCRTC ( ) { return & ppsCRTC [ interlace_mode ] ; }
//static __forceinline FRAGMENTSHADER* curr_ppsCRTC24() { return &ppsCRTC24[interlace_mode]; }
static __forceinline FRAGMENTSHADER * curr_ppsCRTCTarg ( ) { return & ppsCRTCTarg [ interlace_mode ] ; }
static __forceinline FRAGMENTSHADER * curr_pps ( CRTC_TYPE render_type )
{
switch ( render_type )
{
case CRTC_RENDER : return curr_ppsCRTC ( ) ;
//case CRTC_RENDER_24: return curr_ppsCRTC24();
case CRTC_RENDER_TARG : return curr_ppsCRTCTarg ( ) ;
default : return NULL ;
}
}
2010-09-15 16:54:19 +00:00
// ------------------------- Functions -------------------------------
# ifdef NVIDIA_CG_API
inline bool ZZshExistProgram ( FRAGMENTSHADER * pf ) { return ( pf - > prog ! = NULL ) ; } ; // We don't check ps != NULL, so be warned,
inline bool ZZshExistProgram ( VERTEXSHADER * pf ) { return ( pf - > prog ! = NULL ) ; } ;
inline bool ZZshExistProgram ( ZZshShaderLink prog ) { return ( prog ! = NULL ) ; } ;
# endif
2012-05-13 17:14:05 +00:00
# if defined(GLSL_API) && !defined(GLSL4_API)
2012-04-19 21:22:08 +00:00
inline bool ZZshExistProgram ( FRAGMENTSHADER * pf ) { return ( pf - > Shader ! = 0 ) ; } ;
inline bool ZZshExistProgram ( VERTEXSHADER * pf ) { return ( pf - > Shader ! = 0 ) ; } ;
inline bool ZZshExistProgram ( ZZshShaderLink prog ) { return ( prog . link ! = NULL ) ; } // This is used for pvs mainly. No NULL means that we do LOAD_VS
# endif
2012-05-13 17:14:05 +00:00
# if defined(GLSL4_API)
inline bool ZZshExistProgram ( FRAGMENTSHADER * pf ) { return ( pf - > program ! = 0 ) ; } ;
inline bool ZZshExistProgram ( VERTEXSHADER * pf ) { return ( pf - > program ! = 0 ) ; } ;
inline bool ZZshExistProgram ( ZZshShaderLink prog ) { return ( prog . link ! = NULL ) ; } // This is used for pvs mainly. No NULL means that we do LOAD_VS
# endif
2010-09-15 16:54:19 +00:00
extern const char * ShaderCallerName ;
extern const char * ShaderHandleName ;
2010-09-19 08:01:48 +00:00
inline void SetShaderCaller ( const char * Name ) {
2010-09-15 16:54:19 +00:00
ShaderCallerName = Name ;
}
inline void SetHandleName ( const char * Name ) {
ShaderHandleName = Name ;
}
inline void ResetShaderCounters ( ) {
// g_vsprog = g_psprog = sZero;
}
2012-04-29 18:50:07 +00:00
/////////////////////////////////////////////////////////////////
// Improvement:
// * store the location of uniform. Avoid to call glGetUniformLocation a lots of time
// * Use separate shader build pipeline: current code emulate this behavior but with the recent opengl4
// it would be much more easier to code it.
/////////////////////////////////////////////////////////////////
// GLSL: Stub
2010-09-15 16:54:19 +00:00
extern bool ZZshCheckProfilesSupport ( ) ;
2012-04-29 18:50:07 +00:00
// Try various Shader to choose supported configuration
// g_nPixelShaderVer -> SHADER_ACCURATE and SHADER_REDUCED
// Honestly we can probably stop supporting those cards.
2010-09-15 16:54:19 +00:00
extern bool ZZshStartUsingShaders ( ) ;
2012-04-29 18:50:07 +00:00
// Open the shader file into an source array
2010-09-19 08:01:48 +00:00
extern bool ZZshCreateOpenShadersFile ( ) ;
2012-04-29 18:50:07 +00:00
// Those 2 functions are used to stop/start shader. The idea is to draw the HUD text.
// Enable is not implemented and it is likely to stop everythings
2010-09-15 16:54:19 +00:00
extern void ZZshGLDisableProfile ( ) ;
extern void ZZshGLEnableProfile ( ) ;
2012-04-29 18:50:07 +00:00
// Set the Uniform parameter in host (NOT GL)
// Param seem to be an absolute index inside a table of uniform
2012-05-07 19:51:58 +00:00
extern void ZZshSetParameter4fv ( ZZshShaderLink & prog , ZZshParameter param , const float * v , const char * name ) ;
2010-09-15 16:54:19 +00:00
extern void ZZshSetParameter4fv ( ZZshParameter param , const float * v , const char * name ) ;
2012-05-07 19:51:58 +00:00
extern void ZZshSetParameter4fvWithRetry ( ZZshParameter * param , ZZshShaderLink & prog , const float * v , const char * name ) ;
2012-04-29 18:50:07 +00:00
// Set the Texture parameter in host (NOT GL)
2010-09-19 08:01:48 +00:00
extern void ZZshGLSetTextureParameter ( ZZshShaderLink prog , ZZshParameter param , GLuint texobj , const char * name ) ;
2010-09-15 16:54:19 +00:00
extern void ZZshGLSetTextureParameter ( ZZshParameter param , GLuint texobj , const char * name ) ;
2012-04-29 18:50:07 +00:00
// Set a default value for 1 uniform in host (NOT GL)
2012-05-07 19:51:58 +00:00
extern void ZZshDefaultOneColor ( FRAGMENTSHADER & ptr ) ;
2012-04-29 18:50:07 +00:00
// Link then run with the new Vertex/Fragment Shader
2010-09-19 08:01:48 +00:00
extern void ZZshSetVertexShader ( ZZshShaderLink prog ) ;
extern void ZZshSetPixelShader ( ZZshShaderLink prog ) ;
2012-04-29 18:50:07 +00:00
// Compile standalone Fragment/Vertex shader program
// Note It also init all the Uniform parameter in host (NOT GL)
2010-09-19 08:01:48 +00:00
extern bool ZZshLoadExtraEffects ( ) ;
2012-04-29 18:50:07 +00:00
// Clean some stuff on exit
2012-04-19 21:22:08 +00:00
extern void ZZshExitCleaning ( ) ;
2010-09-15 16:54:19 +00:00
2010-09-19 08:01:48 +00:00
extern FRAGMENTSHADER * ZZshLoadShadeEffect ( int type , int texfilter , int fog , int testaem , int exactcolor , const clampInfo & clamp , int context , bool * pbFailed ) ;
2010-09-15 16:54:19 +00:00
2012-04-19 21:22:08 +00:00
// only sets a limited amount of state (for Update)
void SetTexVariablesInt ( int context , int bilinear , const tex0Info & tex0 , bool CheckVB , FRAGMENTSHADER * pfragment , int force ) ;
extern u32 ptexBlocks ; // holds information on block tiling. It's texture number in OpenGL -- if 0 than such texture
extern u32 ptexConv16to32 ; // does not exists. This textures should be created on start and released on finish.
extern u32 ptexBilinearBlocks ;
extern u32 ptexConv32to16 ;
2012-05-07 19:51:58 +00:00
# ifdef GLSL4_API
extern GSUniformBufferOGL * constant_buffer ;
extern GSUniformBufferOGL * common_buffer ;
extern GSUniformBufferOGL * vertex_buffer ;
extern GSUniformBufferOGL * fragment_buffer ;
2012-05-13 20:22:15 +00:00
extern GSVertexBufferStateOGL * vertex_array ;
2012-05-07 19:51:58 +00:00
2012-05-27 15:34:48 +00:00
extern GLenum g_current_vs ;
extern GLenum g_current_ps ;
2012-05-15 06:40:45 +00:00
extern void init_shader ( ) ;
extern void PutParametersInProgram ( VERTEXSHADER * vs , FRAGMENTSHADER * ps ) ;
extern void init_shader ( ) ;
2012-05-15 06:45:26 +00:00
extern void ZZshSetupShader ( ) ;
2012-05-07 19:51:58 +00:00
# endif
2010-10-16 11:54:46 +00:00
2010-09-15 16:54:19 +00:00
# endif