//================================================================
// E3D
//
// Shading language (GLSL, Cg etc.) common definitions
//
// AUTHOR:  Gabor Nagy
// DATE:    2025-Feb-27 21:28:06
//
// Copyright (C) 2014-2026 by Gabor Nagy. All rights reserved.
//================================================================
#ifndef _E3D_SL_h
#define _E3D_SL_h

#include <E3D/Light.h>  // For E3dShadowMap

#if defined (__cplusplus) && (!(defined (__CPLUSLIBS)))
extern "C" {
#endif


// Global state for error reporting
//
typedef struct
{
	char*              StateString;
	E3dMaterial*       Material;
	E3dShader*         Shader;
	E3dShaderVariant*  ShaderVariant;
	char*              ParameterName;

	const char*        File;
	const char*        Function;int	Line;
	E3dRenderer*       Renderer;
} E3dSLDebugRec;



typedef struct E3dShaderDevice_S  E3dShaderDevice;

typedef void   (*E3dShaderVariantInitFunc)(E3dShaderVariant* PShaderVariant);
typedef int    (*E3dVertexProgramInitFunc)(E3dStageProgram*  PVertexProgram);
typedef void   (*E3dStageProgramFreeFunc)(E3dStageProgram* PVertexProgram);
typedef void   (*E3dShaderCheckNeededTermsFunc)(const E3dGeometry* PGeometry, const EObject* PShadeable,  const E3dShaderClassRendererBinding* PShaderClassBinding, E3dShaderVariant* PShaderVariant, E3dSLCodeGenParams* PCodeGenParams);


#define E3dSLMAX_NUM_OF_LIGHTS              1  // Max # of shadowable lights per shader pass. Must be <= E3dMAX_NUM_OF_LIGHTS
#define E3dSLMAX_NUM_OF_2DTEXTURES         16  // Max # of texture samplers. Used for statically allocated arrays. EpGL_MAX_TEXTURE_IMAGE_UNITS provides the actual number.
#define E3dSLMAX_NUM_OF_TEXCOORDS           4  // Max # of texture coordinate sets.
#define E3dSLMAX_NUM_OF_PARAMETERS        256
#define E3dSLMAX_NUM_OF_ARRAY_PARAMETERS   32
#define E3dSLMAX_NUM_OF_SKINNING_JOINTS    30

#define E3dSL_COMPILE_ERROR         0x01
#define E3dSL_SYMBOL_RESOLVE_ERROR  0x02
#define E3dSL_ALWAYS                0x07

//------------------------------------------------
// Shader target back-end description
// This struct is specified under a RendererClass and it describes how to generate Shader code for that RendererClass.
//------------------------------------------------
struct E3dShaderDevice_S
{
	char*                          LanguageName;
	char*                          LanguageVersionString;

	EBool                          CodeGeneratorInitialized;

	const char*                    FragmentFunctionPrefix;
	const char*                    FragmentHeader;
	const char*                    FragmentEntryPointName;

	EBool                          ParametersGlobal;                 // Vertex/fragment program uniforms are global variables (GLSL)
	EBool                          SupportsConstForLocalVariables;

	const char*                    VertexHeader;

	const char*                    Precision;

	const char*                    VertexAttributeQualifier;
	const char*                    VertexAttributePrefix;
	const char*                    VertexProgramOutParamQualifier;
	const char*                    VtxUParamQualifier;
	const char*                    BuiltIn_VertexPositionInParamName;const char*  BuiltIn_VertexPositionOutParamName;
	const char*                    BuiltIn_VertexColorInParamName;
	const char*                    BuiltIn_VertexNormalInParamName;const char*  BuiltIn_VertexNormalOutParamName;
	const char*                    BuiltIn_VertexModelViewProjectionMatrixParamName;
	const char*                    BuiltIn_VertexTexCoordInParamName;

	const char*                    BuiltIn_FragmentOutColorName;

	const char*                    VtxFParamPrefix;                    // Prefix for vertex-fragment interface parameters (a.k.a. interpolants / varying params)
	const char*                    VtxUParamPrefix;                    // Prefix for vertex program uniform parameters
	const char*                    FrgUParamQualifier;                 // Fragment program uniform parameter qualifier. E.g. "uniform"
	const char*                    FrgUParamPrefix;                    // Prefix for fragment program uniform parameters

	EBool                          HasSwizzle;                       // Language supports a.xyz etc.
	char                           XName, YName, ZName, WName,       // Vector component names
																 RName, GName, BName, AName;

	const char*                    Param_DefFormatString;
	const char*                    Sampler2D_DefFormatString;
	const char*                    Sampler2DShadow_DefFormatString;
	EBool                          ShadowMappingAutoColor;           // If TRUE, looking up a texel in a shadow map will already do the disntance check

	EBool                          Sampler_PassCoordinatesAsVector;
	EBool                          VectorOperators;                  // If TRUE, we can use standard operators on vectors (+,-,* etc.)
	const char*                    WorldShadingNormalString;
	int                            MaxNumOfTextures;
	EResResourceHandlerFunc        RT_sampler2D, RT_sampler2DShadow, RT_sampler3D, RT_samplerCUBE, RT_float3x3, RT_float3x4;  // Resource translators for special data types

	EBool                          AccumulateLightPerShadeCall;

	EList_s(, EpPixelFormat,       NormalMapPixelFormats);

	E3dShaderVariantInitFunc       ShaderVariantInit;

	E3dVertexProgramInitFunc       VertexProgramInit;
	E3dStageProgramFreeFunc        VertexProgramFree;
	int                            VertexProgramSize;

	int                            GeometryProgramSize;

	int                            FragmentProgramSize;
	E3dShaderCheckNeededTermsFunc  ShaderCheckNeededTerms;
};



extern E3dSLDebugRec  E3dSL_DebugRec;          // Struct for debugging shaders
extern EBool          E3dSL_ProceduralPlanar;


static inline void E3dSL_ClearDebugRec(void)
{
	memset(&E3dSL_DebugRec, 0, sizeof(E3dSLDebugRec));
}


#define E3dSL_Location() do\
{\
	E3dSL_DebugRec.Function = __FUNCTION__;E3dSL_DebugRec.File = __FILE__;E3dSL_DebugRec.Line = __LINE__;\
} while(0)


extern const char  E3dSLSemantic_CompileTime[];

extern const char  E3dSLSemantic_Position[];
extern const char  E3dSLSemantic_Normal[];
extern const char  E3dSLSemantic_Tangent[];
extern const char  E3dSLSemantic_Bitangent[];

extern const char  E3dSLSemantic_PointToEye[];
extern const char  E3dSLSemantic_EYE_Position[];
extern const char  E3dSLSemantic_Fresnel[];

extern const char  E3dSLSemantic_LightColor[];
extern const char  E3dSLSemantic_LightDiffuseSpecularFactors[];

extern const char  E3dSLSemantic_VertexAttribute[];
extern const char  E3dSLSemantic_VertexAttributeVS[];
extern const char  E3dSLSemantic_PolyGroupVertexAttribute[];


static inline E3dStageProgram* E3dVertexProgram_New(E3dShaderDevice* PShaderDevice)
{
	E3dStageProgram*  LVertexProgram = (E3dStageProgram*)EMallocClr(PShaderDevice->VertexProgramSize);
	if(PShaderDevice->VertexProgramInit) PShaderDevice->VertexProgramInit(LVertexProgram);
	return(LVertexProgram);
}


extern EBool  (*E3dSL_IsTextureUsed)(const E3dMaterial* PMaterial, const EIndex PTxC, const E3dTextureMapper* PMapper, const E3dShaderVariant* PShaderVariant);
extern E3dShaderCheckNeededTermsFunc  E3dSL_ShaderCheckNeededTerms;

extern EIndex  E3dShaderVariant_NumOfAttributesBySemantic(const E3dGeometry* PGeometry, const EObject* PShadeable,  const E3dMaterial* PMaterial,  const char* PSemantic);


#if defined (__cplusplus) && (!(defined (__CPLUSLIBS)))
}	// Close scope of 'extern "C"' declaration
#endif

#endif	// _E3D_SL_h
