diff --git a/Makefile.ps3.rgl b/Makefile.ps3.rgl index 124a37a73a..10541eb7c8 100644 --- a/Makefile.ps3.rgl +++ b/Makefile.ps3.rgl @@ -1,10 +1,10 @@ #which compiler to build with - GCC or SNC #set to GCC for debug builds for use with debugger -CELL_BUILD_TOOLS = SNC +CELL_BUILD_TOOLS = GCC CELL_GPU_TYPE = RSX DEBUG = 0 -STRIPPING_ENABLE = 0 +STRIPPING_ENABLE = 1 PC_DEVELOPMENT_IP_ADDRESS = "192.168.1.7" PC_DEVELOPMENT_UDP_PORT = 3490 @@ -15,12 +15,19 @@ include $(CELL_MK_DIR)/sdk.makedef.mk PPU_LIB_TARGET = librgl_ps3.a LDDIRS = -L. -INCDIRS = -I. +INCDIRS = -I. -Iconsole/rgl/include + +RGL_DIR = console/rgl/src + +PPU_SRCS = $(RGL_DIR)/Utils/NameSpace.cpp \ + $(RGL_DIR)/Utils/TexNameSpace.cpp \ + $(RGL_DIR)/Utils/EnumMap.cpp \ + $(RGL_DIR)/libelf/readelf.cpp \ + $(RGL_DIR)/rgl.cpp \ + $(RGL_DIR)/rgl_cg.cpp \ + $(RGL_DIR)/ps3/rgl_ps3.cpp \ + $(RGL_DIR)/ps3/rgl_ps3_raster.cpp -PPU_SRCS = console/rgl/ps3/device_ctx.cpp \ - console/rgl/ps3/rgl.cpp \ - console/rgl/ps3/cgbio.cpp \ - console/rgl/ps3/cgnv2rt.cpp ifeq ($(CELL_BUILD_TOOLS), SNC) PPU_CXXLD = $(CELL_SDK)/host-win32/sn/bin/ps3ppuld.exe @@ -37,9 +44,9 @@ endif PPU_RANLIB = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-ranlib.exe -PPU_LDLIBS = -lio_stub +PPU_LDLIBS = -lio_stub -DEFINES += -D__CELLOS_LV2__ +DEFINES += -D__CELLOS_LV2__ -DJS_PLATFORM_CELL ifeq ($(DEBUG), 1) PPU_OPTIMIZE_LV := -O0 -g diff --git a/Makefile.ps3.rgl2 b/Makefile.ps3.rgl2 deleted file mode 100644 index c7e83fea7b..0000000000 --- a/Makefile.ps3.rgl2 +++ /dev/null @@ -1,63 +0,0 @@ -#which compiler to build with - GCC or SNC -#set to GCC for debug builds for use with debugger -CELL_BUILD_TOOLS = GCC -CELL_GPU_TYPE = RSX - -DEBUG = 0 -STRIPPING_ENABLE = 0 - -PC_DEVELOPMENT_IP_ADDRESS = "192.168.1.7" -PC_DEVELOPMENT_UDP_PORT = 3490 - -CELL_MK_DIR ?= $(CELL_SDK)/samples/mk -include $(CELL_MK_DIR)/sdk.makedef.mk - -PPU_LIB_TARGET = librgl_ps3.a - -LDDIRS = -L. -INCDIRS = -I. -Iconsole/rglv2/include - -RGL_DIR = console/rglv2/src - -PPU_SRCS = $(RGL_DIR)/Utils/Log.cpp \ - $(RGL_DIR)/Utils/NameSpace.cpp \ - $(RGL_DIR)/Utils/TexNameSpace.cpp \ - $(RGL_DIR)/Utils/Report.cpp \ - $(RGL_DIR)/Utils/EnumMap.cpp \ - $(RGL_DIR)/Utils/rbtree.cpp \ - $(RGL_DIR)/libelf/readelf.cpp \ - $(RGL_DIR)/rgl.cpp \ - $(RGL_DIR)/rgl_cg.cpp \ - $(RGL_DIR)/ps3/rgl_ps3.cpp \ - $(RGL_DIR)/ps3/rgl_ps3_raster.cpp - - -ifeq ($(CELL_BUILD_TOOLS), SNC) - PPU_CXXLD = $(CELL_SDK)/host-win32/sn/bin/ps3ppuld.exe - PPU_CXX = $(CELL_SDK)/host-win32/sn/bin/ps3ppusnc.exe - PPU_CC = $(CELL_SDK)/host-win32/sn/bin/ps3ppusnc.exe - SNC_PPU_AR = $(CELL_SDK)/host-win32/sn/bin/ps3snarl.exe -else - PPU_CXX = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-g++.exe - PPU_CC = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-gcc.exe - PPU_CXXLD = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-ld.exe - PPU_AR = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-ar.exe -endif - -PPU_RANLIB = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-ranlib.exe - - -PPU_LDLIBS = -lio_stub - -DEFINES += -D__CELLOS_LV2__ -DJS_PLATFORM_CELL -DJS_LIBRARY_VERSION=\"2.00\" -DJS_LIBRARY_VERSION_NUMBER=200 - -ifeq ($(DEBUG), 1) - PPU_OPTIMIZE_LV := -O0 -g -else - PPU_OPTIMIZE_LV := -O3 -endif - -PPU_CFLAGS = $(PPU_OPTIMIZE_LV) $(INCDIRS) $(DEFINES) -PPU_CXXFLAGS = $(PPU_OPTIMIZE_LV) $(INCDIRS) $(DEFINES) - -include $(CELL_MK_DIR)/sdk.target.mk diff --git a/console/rgl/include/Cg/CgCommon.h b/console/rgl/include/Cg/CgCommon.h new file mode 100644 index 0000000000..f39a8cbc76 --- /dev/null +++ b/console/rgl/include/Cg/CgCommon.h @@ -0,0 +1,569 @@ +#ifndef _cg_common_h +#define _cg_common_h + +#include + +#include "../export/RGL/rgl.h" +#include "../RGL/private.h" + +#include +#include + +#include "Cg/CgInternal.h" +#include "Cg/CgProgramGroup.h" + +// [YLIN] +#include // for memcpy16 +#if (CELL_SDK_VERSION<=0x210001) +using _CSTD memcpy16; // fixed at SDK 220 +#endif // (CELL_SDK_VERSION<=0x210001) + +#ifdef __cplusplus +extern "C" +{ +#endif + + +#define RGL_MAX_VP_SHARED_CONSTANTS 256 +#define RGL_MAX_FP_SHARED_CONSTANTS 1024 +#define RGL_BOOLEAN_REGISTERS_COUNT 32 + + // parameter setter, prototype of functions called when a uniform is set. + typedef void( *_cgSetFunction )( struct CgRuntimeParameter* _RGL_RESTRICT, const void* _RGL_RESTRICT ); + + typedef void( *_cgSetArrayIndexFunction )( struct CgRuntimeParameter* _RGL_RESTRICT, const void* _RGL_RESTRICT, const int index ); + + typedef struct _CgUniform + { + void *pushBufferPtr; + } + _CgUniform; + + typedef struct _CGprogram _CGprogram; + + typedef struct CgRuntimeParameter + { + // sampler + _cgSetArrayIndexFunction samplerSetter; + /*cgSetFunction*/ + + //vector + _cgSetArrayIndexFunction setterIndex; + // matrices + _cgSetArrayIndexFunction settercIndex; + _cgSetArrayIndexFunction setterrIndex; + + void *pushBufferPointer; + const CgParameterEntry *parameterEntry; + _CGprogram *program; + int glType; //tmp... + CGparameter id;//tmp + } + CgRuntimeParameter; + + typedef struct + { + CgRuntimeParameter* child; + CgRuntimeParameter* parent; + CgRuntimeParameter* top; + _cgSetArrayIndexFunction childOnBindSetter; + } + CgParameterConnection; + + typedef struct + { + CgRuntimeParameter* param; + std::vector semantic; + } + CgRuntimeSemantic; + + struct _CGprogram + { + struct _CGprogram* next; // link to next in NULL-terminated singly linked list of programs + CGprogram id; // numerical id for this program object + struct _CGcontext* parentContext; // parent context for this program + void* parentEffect; // parent effect for this program (only used for default program of an effect, containing effect parameters) + bool inLocalMemory; // only pertains to fragment programs which can be in location local, the default, or location main via cgb interfaces + // parameters in the CG_PROGRAM namespace + + unsigned int constantPushBufferWordSize; + unsigned int* constantPushBuffer; + unsigned int lastConstantUpdate; + + // executable program image + void* platformProgram; + + // entire binary program image from compiler + void* platformProgramBinary; + + // extra information to ease the coding of the rgl runtime + // the following are used to know which parameters are samplers, so that we can walk them in a quick way. + unsigned int samplerCount; + unsigned int * samplerIndices; + unsigned int * samplerUnits; + + unsigned int controlFlowBools; + + //binary format additions + //info previously contained in platformProgram ( loadAddress + nvBinary ) + CgProgramHeader header; + const char *name; + const void *ucode; + + GLuint loadProgramId; + // offset into the allocation id above, normally zero for internal use. + // But for psglSetFragmentProgramConfiguration it's possible for + // users to manage sub-heap in allocation and put multiple + // program in each allocation. + GLuint loadProgramOffset; + + int version; //contained a boolean indicating if the structure pointers have been patched or not + + char *parameterResources; + int rtParametersCount; + CgRuntimeParameter *runtimeParameters; + const CgParameterEntry *parametersEntries; + + unsigned short *resources; + unsigned short *pushBufferPointers; + + int defaultValuesIndexCount; + const CgParameterDefaultValue *defaultValuesIndices; + + int semanticCount; + const CgParameterSemantic *semanticIndices; + + int defaultValueCount; + const float *defaultValues; + + const char *stringTable; + + unsigned int **constantPushBufferPointers; + + //tmp + unsigned int *samplerValuesLocation; + void *memoryBlock; + + _CGprogramGroup *programGroup; + int programIndexInGroup; + + // supports runtime created parameters + std::vector runtimeCreatedParameters; + + // supports parameter connections + std::vector connectionTable; + + // supports runtime allocation of semantics + std::vector parameterSemantics; + + //runtime compilation / conversion + void *runtimeElf; + }; + + typedef struct _CGcontext + { + struct _CGcontext* next; // for global linked list of CGcontexts + CGcontext id; // numerical handle for this object + unsigned int programCount; // number of programs in the list + struct _CGprogram* programList; // head of singly linked list of programs + + CGenum compileType; // compile manual, immediate or lazy (unused so far) + + // implementation data for GL + CGbool GLmanageTextures; + + unsigned int controlFlowBoolsSharedMask; + unsigned int controlFlowBoolsShared; + + // default program, fake owner of the context parameters + _CGprogram defaultProgram; + + //groups + CGprogramGroup groupList; + + //"static" variable used to store the values of the last parameter for which getParameterValue has been called + double currentParameterValue[16]; + char currentParameterName[128]; + } + _CGcontext; + + + // prototypes -------------------------------- + + // internal error handling + RGL_EXPORT void rglCgRaiseError( CGerror error ); + // interface between object types + extern void rglCgProgramDestroyAll( _CGcontext* c ); + extern void rglCgDestroyContextParam( CgRuntimeParameter* p ); + RGL_EXPORT CgRuntimeParameter*rglCgCreateParameterInternal( _CGprogram *program, const char* name, CGtype type ); + RGL_EXPORT void rglCgProgramErase( _CGprogram* prog ); + + // default setters + void _cgRaiseInvalidParam( CgRuntimeParameter*p, const void*v ); + void _cgRaiseNotMatrixParam( CgRuntimeParameter*p, const void*v ); + void _cgIgnoreSetParam( CgRuntimeParameter*p, const void*v ); + void _cgRaiseInvalidParamIndex( CgRuntimeParameter*p, const void*v, const int index ); + void _cgRaiseNotMatrixParamIndex( CgRuntimeParameter*p, const void*v, const int index ); + void _cgIgnoreSetParamIndex( CgRuntimeParameter*p, const void*v, const int index ); + + // cg helpers + + // Is macros +#define CG_IS_CONTEXT(_ctx) rglIsName(&_CurrentContext->cgContextNameSpace, (unsigned int)_ctx) +#define CG_IS_PROGRAM(_program) rglIsName(&_CurrentContext->cgProgramNameSpace, (unsigned int)_program) +#define CG_IS_PARAMETER(_param) rglIsName(&_CurrentContext->cgParameterNameSpace, (unsigned int)(((unsigned int)_param)&CG_PARAMETERMASK)) + + //array indices +#define CG_PARAMETERSIZE 22 //22 bits == 4 millions parameters +#define CG_PARAMETERMASK ((1<>CG_PARAMETERSIZE) + + + inline static bool isMatrix( CGtype type ) + { + if (( type >= CG_FLOAT1x1 && type <= CG_FLOAT4x4 ) || + ( type >= CG_HALF1x1 && type <= CG_HALF4x4 ) || + ( type >= CG_INT1x1 && type <= CG_INT4x4 ) || + ( type >= CG_BOOL1x1 && type <= CG_BOOL4x4 ) || + ( type >= CG_FIXED1x1 && type <= CG_FIXED4x4 )) + return true; + return false; + } + + inline static bool isSampler( CGtype type ) + { + return ( type >= CG_SAMPLER1D && type <= CG_SAMPLERCUBE ); + } + + + unsigned int rglCountFloatsInCgType( CGtype type ); + CGbool _cgMatrixDimensions( CGtype type, unsigned int* nrows, unsigned int* ncols ); + + unsigned int rglGetTypeRowCount( CGtype parameterType ); + unsigned int rglGetTypeColCount( CGtype parameterType ); + + // the internal cg conversions + inline static CgRuntimeParameter* _cgGetParamPtr( CGparameter p ) + { + return ( CgRuntimeParameter* )rglGetNamedValue( &_CurrentContext->cgParameterNameSpace, ( unsigned int )((( unsigned int )p )&CG_PARAMETERMASK ) ); + } + + inline static _CGprogram* _cgGetProgPtr( CGprogram p ) + { + return ( _CGprogram* )rglGetNamedValue( &_CurrentContext->cgProgramNameSpace, (unsigned int)p ); + } + + inline static _CGcontext* _cgGetContextPtr( CGcontext c ) + { + return ( _CGcontext* )rglGetNamedValue( &_CurrentContext->cgContextNameSpace, (unsigned int)c ); + } + + inline static CgRuntimeParameter* rglCgGLTestParameter( CGparameter param ) + { + return _cgGetParamPtr( param ); + } + + CgRuntimeParameter* _cgGLTestArrayParameter( CGparameter paramIn, long offset, long nelements ); + CgRuntimeParameter* _cgGLTestTextureParameter( CGparameter param ); + +#ifdef RGL_DEBUG + void rglCgDumpState(); + void rglCgPrintSpaces( unsigned int n ); +#endif + + inline static int rglGetSizeofSubArray( const unsigned short *dimensions, unsigned short count ) + { + int res = 1; + for ( int i = 0;i < count;i++ ) + res *= ( int )( *( dimensions++ ) ); + return res; + } + + inline static CGresource rglGetBaseResource( CGresource resource ) + { + switch ( resource ) + { + case CG_ATTR0: case CG_ATTR1: case CG_ATTR2: case CG_ATTR3: + case CG_ATTR4: case CG_ATTR5: case CG_ATTR6: case CG_ATTR7: + case CG_ATTR8: case CG_ATTR9: case CG_ATTR10: case CG_ATTR11: + case CG_ATTR12: case CG_ATTR13: case CG_ATTR14: case CG_ATTR15: + return CG_ATTR0; + case CG_HPOS: + return CG_HPOS; + case CG_COL0: case CG_COL1: case CG_COL2: case CG_COL3: + return CG_COL0; + case CG_TEXCOORD0: case CG_TEXCOORD1: case CG_TEXCOORD2: case CG_TEXCOORD3: + case CG_TEXCOORD4: case CG_TEXCOORD5: case CG_TEXCOORD6: case CG_TEXCOORD7: + case CG_TEXCOORD8: case CG_TEXCOORD9: + return CG_TEXCOORD0; + case CG_TEXUNIT0: case CG_TEXUNIT1: case CG_TEXUNIT2: case CG_TEXUNIT3: + case CG_TEXUNIT4: case CG_TEXUNIT5: case CG_TEXUNIT6: case CG_TEXUNIT7: + case CG_TEXUNIT8: case CG_TEXUNIT9: case CG_TEXUNIT10: case CG_TEXUNIT11: + case CG_TEXUNIT12: case CG_TEXUNIT13: case CG_TEXUNIT14: case CG_TEXUNIT15: + return CG_TEXUNIT0; + case CG_FOGCOORD: + return CG_FOGCOORD; + case CG_PSIZ: + return CG_PSIZ; + case CG_WPOS: + return CG_WPOS; + case CG_COLOR0: case CG_COLOR1: case CG_COLOR2: case CG_COLOR3: + return CG_COLOR0; + case CG_DEPTH0: + return CG_DEPTH0; + case CG_C: + return CG_C; + case CG_B: + return CG_B; + case CG_CLP0: case CG_CLP1: case CG_CLP2: case CG_CLP3: case CG_CLP4: case CG_CLP5: + return CG_CLP0; + case CG_UNDEFINED: + return CG_UNDEFINED; + default: + return CG_UNDEFINED; + } + } + + // platform API + CGprofile rglPlatformGetLatestProfile( CGGLenum profile_type ); + int rglPlatformCopyProgram( _CGprogram* source, _CGprogram* destination ); + + void rglPlatformProgramErase( void* platformProgram ); + + int rglPlatformGenerateVertexProgram( _CGprogram *program, const CgProgramHeader *programHeader, const void *ucode, const CgParameterTableHeader *parameterHeader, const char *stringTable, const float *defaultValues ); + CGbool rglPlatformSupportsVertexProgram( CGprofile p ); + + int rglPlatformGenerateFragmentProgram( _CGprogram *program, const CgProgramHeader *programHeader, const void *ucode, const CgParameterTableHeader *parameterHeader, const char *stringTable, const float *defaultValues ); + CGbool rglPlatformSupportsFragmentProgram( CGprofile p ); + + + + void rglPlatformSetVertexRegister4fv( unsigned int reg, const float * _RGL_RESTRICT v ); + void rglPlatformSetVertexRegisterBlock( unsigned int reg, unsigned int count, const float * _RGL_RESTRICT v ); + void rglPlatformSetFragmentRegister4fv( unsigned int reg, const float * _RGL_RESTRICT v ); + void rglPlatformSetFragmentRegisterBlock( unsigned int reg, unsigned int count, const float * _RGL_RESTRICT v ); + + void rglPlatformSetBoolVertexRegisters( unsigned int values ); + + // names API + RGL_EXPORT unsigned int _cgHashString( const char *str ); + + inline static void _pullConnectedParameterValues( _CGprogram* ptr ) + { + // we now use a pull method to get the data into the children parameters + // when their program is bound they pull the data from their parents + std::vector::iterator connectionIter = ptr->connectionTable.begin(); + while ( connectionIter != ptr->connectionTable.end() ) + { + // pull data into connectionIter->child from connectionIter->top + connectionIter->childOnBindSetter( connectionIter->child, connectionIter->top->pushBufferPointer, 0 ); + connectionIter++; + } + } + + inline static void _cgGLBindVertexProgram( _CGprogram* program ) + { + // the program is a vertex program, just update the GL state + _CurrentContext->BoundVertexProgram = program; + + // and inform the GL state to re-upload the vertex program + _CurrentContext->needValidate |= PSGL_VALIDATE_VERTEX_PROGRAM; + + // This must happen before the sampler setters so texture parameters have the correct value in their push buffers for that routine + _pullConnectedParameterValues( program ); + + CGbool is_managed = program->parentContext->GLmanageTextures; + // enable texture parameters if the managed flag is set. + if ( is_managed ) + { + for ( GLuint index = 0; index < program->samplerCount; ++index ) + { + // walk the array of sampler parameters + CgRuntimeParameter *rtParameter = program->runtimeParameters + program->samplerIndices[index]; + rtParameter->samplerSetter( rtParameter, NULL, 0 ); + } + } + } + + inline static void _cgGLBindFragmentProgram( _CGprogram* program ) + { + _CurrentContext->BoundFragmentProgram = program; + + // need to revalidate the textures in order to update which targets to fetch from + _CurrentContext->needValidate |= PSGL_VALIDATE_FRAGMENT_PROGRAM | PSGL_VALIDATE_TEXTURES_USED | PSGL_VALIDATE_FRAGMENT_SHARED_CONSTANTS; + + // This must happen before the sampler setters so texture parameters have the correct value in their push buffers for that routine + _pullConnectedParameterValues( program ); + + // TODO: push texture state + // Needs to be done per profile. Can't use glPushAttrib. + + CGbool is_managed = program->parentContext->GLmanageTextures; + + // deal with the texture parameters now. + for ( GLuint index = 0; index < program->samplerCount; ++index ) + { + // walk the array of sampler parameters + CgRuntimeParameter *rtParameter = program->runtimeParameters + program->samplerIndices[index]; + CgParameterResource *parameter = ( CgParameterResource * )( program->parameterResources + rtParameter->parameterEntry->typeIndex ); + // find out which texture unit this parameter has been assigned to + unsigned int unit = parameter->resource - CG_TEXUNIT0; + + _CurrentContext->TextureImageUnits[unit].fragmentTarget = rtParameter->glType; + + // enable texture parameters if the managed flag is set. + if ( is_managed ) + { + //tmp + rtParameter->samplerSetter( rtParameter, NULL, 0 ); + } + else + { + rglUpdateCurrentTextureCache( &_CurrentContext->TextureImageUnits[unit] ); + } + } + } + + inline static void _cgGLUnbindVertexProgram() + { + _CurrentContext->BoundVertexProgram = NULL; + _CurrentContext->needValidate |= PSGL_VALIDATE_VERTEX_PROGRAM; + } + + // XXX this should not be here. + inline static void rglLeaveFFXFP( RGLcontext*LContext ) + { + LContext->FragmentProgram = GL_TRUE; + struct _CGprogram* current = LContext->BoundFragmentProgram; + if ( current ) + { + for ( GLuint i = 0; i < current->samplerCount; ++i ) + { + int unit = current->samplerUnits[i]; + rglUpdateCurrentTextureCache( &_CurrentContext->TextureImageUnits[unit] ); + } + } + LContext->needValidate |= PSGL_VALIDATE_FRAGMENT_PROGRAM | PSGL_VALIDATE_TEXTURES_USED | PSGL_VALIDATE_FRAGMENT_SHARED_CONSTANTS; + } + + inline static void _cgGLUnbindFragmentProgram() + { + _CurrentContext->BoundFragmentProgram = NULL; + } + + static inline GLenum rglCgGetSamplerGLTypeFromCgType( CGtype type ) + { + switch ( type ) + { + case CG_SAMPLER1D: + case CG_SAMPLER2D: + case CG_SAMPLERRECT: + return GL_TEXTURE_2D; + case CG_SAMPLER3D: + return GL_TEXTURE_3D; + case CG_SAMPLERCUBE: + return GL_TEXTURE_CUBE_MAP; + default: + return 0; + } + } + + static inline int is_created_param( CgRuntimeParameter* ptr ) + { + if ( ptr->parameterEntry->flags & CGP_RTCREATED ) + return 1; + return 0; + } + + struct rglNameSpace; + +#define VERTEX_PROFILE_INDEX 0 +#define FRAGMENT_PROFILE_INDEX 1 + int rglNVGenerateProgram( _CGprogram *program, int profileIndex, const CgProgramHeader *programHeader, const void *ucode, + const CgParameterTableHeader *parameterHeader, const CgParameterEntry *parameterEntries, + const char *stringTable, const float *defaultValues ); + + // + // these functions return the statically allocated table of function pointers originally + // written for NV unshared vertex parameter setters, but now also used by runtime + // created parameters cause these setters just do straight copies into the pushbuffer memory + // + _cgSetArrayIndexFunction getVectorTypeIndexSetterFunction( unsigned short a, unsigned short b, unsigned short c, unsigned short d ); + _cgSetArrayIndexFunction getMatrixTypeIndexSetterFunction( unsigned short a, unsigned short b, unsigned short c, unsigned short d, unsigned short e, unsigned short f ); + + // ------------------------------------------- + + typedef void( * CgcontextHookFunction )( _CGcontext *context ); + extern RGL_EXPORT CgcontextHookFunction _cgContextCreateHook; + extern RGL_EXPORT CgcontextHookFunction _cgContextDestroyHook; + + typedef void( * CgparameterHookFunction )( CgRuntimeParameter *parameter ); + extern RGL_EXPORT CgparameterHookFunction _cgParameterCreateHook; + extern RGL_EXPORT CgparameterHookFunction _cgParameterDestroyHook; + + typedef void( * CgprogramHookFunction )( _CGprogram *program ); + typedef void( * CgprogramCopyHookFunction )( _CGprogram *newprogram, _CGprogram *oldprogram ); + extern RGL_EXPORT CgprogramHookFunction _cgProgramCreateHook; + extern RGL_EXPORT CgprogramHookFunction _cgProgramDestroyHook; + extern RGL_EXPORT CgprogramCopyHookFunction _cgProgramCopyHook; + + typedef int( * cgRTCgcCompileHookFunction )( const char*, const char *, const char*, const char**, char** ); + typedef void( * cgRTCgcFreeHookFunction )( char* ); + extern RGL_EXPORT cgRTCgcCompileHookFunction _cgRTCgcCompileProgramHook; + extern RGL_EXPORT cgRTCgcFreeHookFunction _cgRTCgcFreeCompiledProgramHook; + + + //----------------------------------------------- + //inlined helper functions + static inline int rglGetParameterType( const CGprogram *program, const CgParameterEntry *entry ) + { + return ( entry->flags & CGP_TYPE_MASK ); + } + + static inline const CgParameterResource *rglGetParameterResource( const _CGprogram *program, const CgParameterEntry *entry ) + { + return ( CgParameterResource * )( program->parameterResources + entry->typeIndex ); + } + + static inline CGtype rglGetParameterCGtype( const _CGprogram *program, const CgParameterEntry *entry ) + { + if ( entry->flags & CGP_RTCREATED ) + { + return ( CGtype )entry->typeIndex; + } + else + { + const CgParameterResource *parameterResource = rglGetParameterResource( program, entry ); + if ( parameterResource ) + { + return ( CGtype )parameterResource->type; + } + } + return CG_UNKNOWN_TYPE; + } + + static inline const CgParameterArray *rglGetParameterArray( const _CGprogram *program, const CgParameterEntry *entry ) + { + return ( CgParameterArray* )( program->parameterResources + entry->typeIndex ); + } + + static inline const CgParameterStructure *rglGetParameterStructure( const _CGprogram *program, const CgParameterEntry *entry ) + { + return ( CgParameterStructure* )( program->parameterResources + entry->typeIndex ); + } + + inline int rglGetProgramProfileIndex( CGprofile profile ) + { + if ( profile == CG_PROFILE_SCE_FP_TYPEB || profile == CG_PROFILE_SCE_FP_TYPEC || profile == CG_PROFILE_SCE_FP_RSX ) + return FRAGMENT_PROFILE_INDEX; + else if ( profile == CG_PROFILE_SCE_VP_TYPEB || profile == CG_PROFILE_SCE_VP_TYPEC || profile == CG_PROFILE_SCE_VP_RSX ) + return VERTEX_PROFILE_INDEX; + else + return -1; + } + +#ifdef __cplusplus +} // Close scope of 'extern "C"' declaration that encloses file. +#endif + +#endif diff --git a/console/rgl/include/Cg/CgInternal.h b/console/rgl/include/Cg/CgInternal.h new file mode 100644 index 0000000000..b35461525a --- /dev/null +++ b/console/rgl/include/Cg/CgInternal.h @@ -0,0 +1,158 @@ +#ifndef _cg_internal_h +#define _cg_internal_h + +#ifdef __cplusplus +extern "C" +{ +#endif + + //Hardware shader settings +#define CGF_OUTPUTFROMH0 0x01 +#define CGF_DEPTHREPLACE 0x02 +#define CGF_PIXELKILL 0x04 + + //CgParameterEntry flags + + //variability +#define CGPV_MASK 0x03 +#define CGPV_VARYING 0x00 +#define CGPV_UNIFORM 0x01 +#define CGPV_CONSTANT 0x02 +#define CGPV_MIXED 0x03 + + //direction +#define CGPD_MASK 0x0C +#define CGPD_IN 0x00 +#define CGPD_OUT 0x04 +#define CGPD_INOUT 0x08 + + //is_referenced +#define CGPF_REFERENCED 0x10 + //is_shared +#define CGPF_SHARED 0x20 + //is_global +#define CGPF_GLOBAL 0x40 + //internal parameter +#define CGP_INTERNAL 0x80 + + //type +#define CGP_INTRINSIC 0x0000 +#define CGP_STRUCTURE 0x100 +#define CGP_ARRAY 0x200 +#define CGP_TYPE_MASK (CGP_STRUCTURE + CGP_ARRAY) + + //storage +#define CGP_UNROLLED 0x400 +#define CGP_UNPACKED 0x800 +#define CGP_CONTIGUOUS 0x1000 + +#define CGP_NORMALIZE 0x2000 // (attrib) if the usual cgGLSetParameterPointer should normalize the attrib + +#define CGP_RTCREATED 0x4000 // indicates that the parameter was created at runtime + + //static control flow boolean type +#define CGP_SCF_BOOL (CG_TYPE_START_ENUM + 1024) + + //data types + typedef struct _CgParameterTableHeader + { + unsigned short entryCount; + unsigned short resourceTableOffset; + unsigned short defaultValueIndexTableOffset; + unsigned short defaultValueIndexCount; + unsigned short semanticIndexTableOffset; + unsigned short semanticIndexCount; + } + CgParameterTableHeader; + + typedef struct _CgParameterEntry + { + unsigned int nameOffset; + unsigned short typeIndex; + unsigned short flags; + } + CgParameterEntry; + +#ifdef MSVC +#pragma warning( push ) +#pragma warning ( disable : 4200 ) +#endif + + typedef struct _CgParameterArray + { + unsigned short arrayType; + unsigned short dimensionCount; + unsigned short dimensions[]; + } + CgParameterArray; //padded to 4 bytes + +#ifdef MSVC +#pragma warning( pop ) +#endif + + typedef struct _CgParameterStructure + { + unsigned short memberCount; + unsigned short reserved; + } + CgParameterStructure; + + typedef struct _CgParameterResource + { + unsigned short type; + unsigned short resource; + } + CgParameterResource; + + typedef struct _CgParameterSemantic + { + unsigned short entryIndex; + unsigned short reserved; + unsigned int semanticOffset; + } + CgParameterSemantic; + + typedef struct _CgParameterDefaultValue + { + unsigned short entryIndex; + unsigned short defaultValueIndex; + } + CgParameterDefaultValue; + + typedef struct CgProgramHeader + { + //28 bytes + unsigned short profile; // Vertex / Fragment + unsigned short compilerVersion; + unsigned int instructionCount; + unsigned int attributeInputMask; + union + { + struct + { + //16 bytes + unsigned int instructionSlot; + unsigned int registerCount; + unsigned int attributeOutputMask; + } + vertexProgram; + struct + { + //12 bytes + unsigned int partialTexType; + unsigned short texcoordInputMask; + unsigned short texcoord2d; + unsigned short texcoordCentroid; + unsigned char registerCount; + unsigned char flags; //combination of CGF_OUTPUTFROMH0,CGF_DEPTHREPLACE,CGF_PIXELKILL + } + fragmentProgram; + }; + } + CgProgramHeader; + +#ifdef __cplusplus +} // Close scope of 'extern "C"' declaration that encloses file. +#endif + +#endif diff --git a/console/rgl/include/Cg/CgProgramGroup.h b/console/rgl/include/Cg/CgProgramGroup.h new file mode 100644 index 0000000000..734bec2a7e --- /dev/null +++ b/console/rgl/include/Cg/CgProgramGroup.h @@ -0,0 +1,42 @@ +#ifndef CGPROGRAMGROUP_HEADER +#define CGPROGRAMGROUP_HEADER + +#include "Cg/cgBinary.h" + +typedef struct _CGnamedProgram +{ + const char *name; + CGprogram program; + int refCount; +} +_CGnamedProgram; + +typedef struct _CGprogramGroup +{ + struct _CGprogramGroup *next; + CGcontext ctx; + unsigned int *constantTable; + unsigned int *stringTable; + unsigned int programCount; + _CGnamedProgram *programs; + int refCount; //total number of program refCounted + bool userCreated; + char *filedata; + char *name; +} +_CGprogramGroup; + +/* Program groups */ +typedef struct _CGprogramGroup *CGprogramGroup; + +CGprogramGroup rglCgCreateProgramGroup( CGcontext ctx, const char *name, void *ptr, int size ); +CGprogramGroup rglCgCreateProgramGroupFromFile( CGcontext ctx, const char *group_file ); +void rglCgDestroyProgramGroup( CGprogramGroup group ); + +int rglCgGetProgramCount( CGprogramGroup group ); +CGprogram rglCgGetProgram( CGprogramGroup group, const char *name ); +int rglCgGetProgramIndex( CGprogramGroup group, const char *name ); +CGprogram rglCgGetProgramAtIndex( CGprogramGroup group, unsigned int index ); +const char *rglCgGetProgramGroupName( CGprogramGroup group ); + +#endif diff --git a/console/rgl/include/Cg/cgBinary.h b/console/rgl/include/Cg/cgBinary.h new file mode 100644 index 0000000000..59b21df577 --- /dev/null +++ b/console/rgl/include/Cg/cgBinary.h @@ -0,0 +1,115 @@ +#if !defined(_H_CG_BINARY_H_) +#define _H_CG_BINARY_H_ + +#ifdef __cplusplus +extern "C" { +#endif + + /*************************************************************************/ + /*** CgBinaryGL binary data/file format ***/ + /*************************************************************************/ + +#define CG_BINARY_FORMAT_REVISION 0x00000006 + + // we don't encode pointers in the binary file so cross compiling + // with differnt pointer sizes works. + typedef unsigned int CgBinaryOffset; + typedef CgBinaryOffset CgBinaryEmbeddedConstantOffset; + typedef CgBinaryOffset CgBinaryFloatOffset; + typedef CgBinaryOffset CgBinaryStringOffset; + typedef CgBinaryOffset CgBinaryParameterOffset; + + // a few typedefs + typedef struct CgBinaryParameter CgBinaryParameter; + typedef struct CgBinaryEmbeddedConstant CgBinaryEmbeddedConstant; + typedef struct CgBinaryVertexProgram CgBinaryVertexProgram; + typedef struct CgBinaryFragmentProgram CgBinaryFragmentProgram; + typedef struct CgBinaryProgram CgBinaryProgram; + + // fragment programs have their constants embedded in the microcode + struct CgBinaryEmbeddedConstant + { + unsigned int ucodeCount; // occurances + unsigned int ucodeOffset[1]; // offsets that need to be patched follow + }; + + // describe a binary program parameter (CgParameter is opaque) + struct CgBinaryParameter + { + CGtype type; // cgGetParameterType() + CGresource res; // cgGetParameterResource() + CGenum var; // cgGetParameterVariability() + int resIndex; // cgGetParameterResourceIndex() + CgBinaryStringOffset name; // cgGetParameterName() + CgBinaryFloatOffset defaultValue; // default constant value + CgBinaryEmbeddedConstantOffset embeddedConst; // embedded constant information + CgBinaryStringOffset semantic; // cgGetParameterSemantic() + CGenum direction; // cgGetParameterDirection() + int paramno; // 0..n: cgGetParameterIndex() -1: globals + CGbool isReferenced; // cgIsParameterReferenced() + CGbool isShared; // cgIsParameterShared() + }; + + // attributes needed for vshaders + struct CgBinaryVertexProgram + { + unsigned int instructionCount; // #instructions + unsigned int instructionSlot; // load address (indexed reads!) + unsigned int registerCount; // R registers count + unsigned int attributeInputMask; // attributes vs reads from + unsigned int attributeOutputMask; // attributes vs writes (uses SET_VERTEX_ATTRIB_OUTPUT_MASK bits) + }; + + typedef enum { + CgBinaryPTTNone = 0, + CgBinaryPTT2x16 = 1, + CgBinaryPTT1x32 = 2, + } CgBinaryPartialTexType; + + // attributes needed for pshaders + struct CgBinaryFragmentProgram + { + unsigned int instructionCount; // #instructions + unsigned int attributeInputMask; // attributes fp reads (uses SET_VERTEX_ATTRIB_OUTPUT_MASK bits) + unsigned int partialTexType; // texid 0..15 use two bits each marking whether the texture format requires partial load: see CgBinaryPartialTexType + unsigned short texCoordsInputMask; // tex coords used by frag prog. (tex is bit n) + unsigned short texCoords2D; // tex coords that are 2d (tex is bit n) + unsigned short texCoordsCentroid; // tex coords that are centroid (tex is bit n) + unsigned char registerCount; // R registers count + unsigned char outputFromH0; // final color from R0 or H0 + unsigned char depthReplace; // fp generated z epth value + unsigned char pixelKill; // fp uses kill operations + }; + + // defines a binary program -- *all* address/offsets are relative to the begining of CgBinaryProgram + struct CgBinaryProgram + { + // vertex/pixel shader identification (BE/LE as well) + CGprofile profile; + + // binary revision (used to verify binary and driver structs match) + unsigned int binaryFormatRevision; + + // total size of this struct including profile and totalSize field! + unsigned int totalSize; + + // parameter usually queried using cgGet[First/Next]LeafParameter + unsigned int parameterCount; + CgBinaryParameterOffset parameterArray; + + // depending on profile points to a CgBinaryVertexProgram or CgBinaryFragmentProgram struct + CgBinaryOffset program; + + // raw ucode data + unsigned int ucodeSize; + CgBinaryOffset ucode; + + // variable length data follows + unsigned char data[1]; + }; + +#ifdef __cplusplus +} +#endif + +#endif // !_H_CG_BINARY_H_ diff --git a/console/rgl/include/RGL/Base.h b/console/rgl/include/RGL/Base.h new file mode 100644 index 0000000000..f67a042419 --- /dev/null +++ b/console/rgl/include/RGL/Base.h @@ -0,0 +1,78 @@ +#ifndef _BASE_H_ +#define _BASE_H_ + +#include +#include + +namespace RGL +{ + + template class Vector + { + T* array; + unsigned int count; + unsigned int capacity; + unsigned int increment; + public: + void * operator new( size_t size ) { return malloc( size ); } + void * operator new( size_t /*size*/, void *p ) { return p; } + void operator delete( void * /*ptr*/, void * /*p*/ ) { } + Vector(): array( 0 ), count( 0 ), capacity( 0 ), increment( 4 ) {} + ~Vector() { clear(); reallocArray( 0 ); } + + inline void setIncrement( unsigned int i ) { increment = i; } + inline unsigned int getCount() { return count; } + + inline void reallocArray( unsigned int newCapacity ) + { + if ( newCapacity == capacity ) return; + if ( newCapacity > capacity ) newCapacity = ( newCapacity > capacity + increment ) ? newCapacity : ( capacity + increment ); + if ( newCapacity == 0 ) + { + free( array ); + array = 0; + } + else array = static_cast( realloc( static_cast( array ), sizeof( T ) * newCapacity ) ); + capacity = newCapacity; + } + + inline void clear() + { + if ( !array ) return; + for ( unsigned int i = 0;i < count;++i )( array + i )->~T(); + count = 0; + } + + inline unsigned int pushBack( const T &element ) + { + if ( count + 1 > capacity ) reallocArray( count + 1 ); + new(( void * )( array + count ) ) T( element ); + return ++count; + } + + inline void removeElement( const T &element ) + { + for ( unsigned int i = count; i > 0; --i ) + { + if ( array[i-1] == element ) + { + remove( i - 1 ); + return; + } + } + } + + inline void remove( unsigned int index ) + { + ( array + index )->~T(); + --count; + if ( count > index ) memmove( array + index, array + index + 1, ( count - index )*sizeof( T ) ); + } + + inline T *getArray() const { return array; } + inline T& operator []( int i ) const { return array[i]; } + }; + +} + +#endif diff --git a/console/rgl/include/RGL/ReportInternal.h b/console/rgl/include/RGL/ReportInternal.h new file mode 100644 index 0000000000..c3611549f2 --- /dev/null +++ b/console/rgl/include/RGL/ReportInternal.h @@ -0,0 +1,29 @@ +#ifndef _RGLReportInternal_h +#define _RGLReportInternal_h + +#include "../export/RGL/rgl.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + typedef struct + { + GLenum e; + const char *s; + }RGLenumMap; + + const char *rglMapLookupEnum( const RGLenumMap* map, unsigned int count, GLenum e ); + GLenum rglMapLookupString( const RGLenumMap* map, unsigned int count, const char *s ); +#define _RGL_MAP_LOOKUP_ENUM(MAP,ENUM) rglMapLookupEnum(MAP,sizeof(MAP)/sizeof(MAP[0]),ENUM) +#define _RGL_MAP_LOOKUP_STRING(MAP,STRING) rglMapLookupString(MAP,sizeof(MAP)/sizeof(MAP[0]),STRING) + + const char *rglGetGLEnumName( GLenum e ); + const char *rglGetGLErrorName( GLenum e ); + +#ifdef __cplusplus +} // Close scope of 'extern "C"' declaration that encloses file. +#endif + +#endif diff --git a/console/rgl/include/RGL/TypeUtils.h b/console/rgl/include/RGL/TypeUtils.h new file mode 100644 index 0000000000..bf30e9ca71 --- /dev/null +++ b/console/rgl/include/RGL/TypeUtils.h @@ -0,0 +1,88 @@ +#ifndef _TYPE_UTILS_H +#define _TYPE_UTILS_H + +/* Following NV_half_float specification + * The half data type is a floating-point + * data type encoded in an unsigned scalar data type. If the unsigned scalar + * holding a half has a value of N, the corresponding floating point number + * is + + * (-1)^S * 0.0, if E == 0 and M == 0, + * (-1)^S * 2^-14 * (M / 2^10), if E == 0 and M != 0, + * (-1)^S * 2^(E-15) * (1 + M/2^10), if 0 < E < 31, + * (-1)^S * INF, if E == 31 and M == 0, or + * NaN, if E == 31 and M != 0, + * + * where + * + * S = floor((N mod 65536) / 32768), + * E = floor((N mod 32768) / 1024), and + * M = N mod 1024. + * + * INF (Infinity) is a special representation indicating numerical overflow. + * NaN (Not a Number) is a special representation indicating the result of + * illegal arithmetic operations, such as division by zero. Note that all + * normal values, zero, and INF have an associated sign. -0.0 and +0.0 + * should be considered equivalent for the purposes of comparisons. Note + * also that half is not a native type in most CPUs, so some special + * processing may be required to generate or interpret half data. + * + * That is SEEEEEMMMMMMMMMM + */ + +typedef union +{ + unsigned int i; + float f; +} rglIntAndFloat; + +static const rglIntAndFloat rglNan = {i: 0x7fc00000U}; +static const rglIntAndFloat rglInfinity = {i: 0x7f800000U}; +#define RGL_NAN (rglNan.f) +#define RGL_INFINITY (rglInfinity.f) + +static inline GLhalfARB rglFloatToHalf( float v ) +{ + rglIntAndFloat V = {f: v}; + // extract float components + unsigned int S = ( V.i >> 31 ) & 1; + int E = (( V.i >> 23 ) & 0xff ) - 0x7f; + unsigned int M = V.i & 0x007fffff; + if (( E == 0x80 ) && ( M ) ) return 0x7fff; // NaN + else if ( E >= 15 ) return( S << 15 ) | 0x7c00; // Inf + else if ( E <= -14 ) return( S << 15 ) | (( 0x800000 + M ) >> ( -14 - E ) ); // Denorm or zero. Works for input denorms and zero + else return( S << 15 ) | ((( E + 15 )&0x1f ) << 10 ) | ( M >> 13 ); +} + +static inline float rglHalfToFloat( GLhalfARB v ) +{ + unsigned int S = v >> 15; + unsigned int E = ( v & 0x7C00 ) >> 10; + unsigned int M = v & 0x03ff; + float f; + if ( E == 31 ) + { + if ( M == 0 ) f = RGL_INFINITY; + else f = RGL_NAN; + } + else if ( E == 0 ) + { + if ( M == 0 ) f = 0.f; + else f = M * 1.f / ( 1 << 24 ); + } + else f = ( 0x400 + M ) * 1.f / ( 1 << 25 ) * ( 1 << E ); + return S ? -f : f; +} + +//---------------------------------------- +// Fixed Point Conversion Macros +// FixedPoint.c +//---------------------------------------- + +#define rglFixedToFloat 1.f/65536.f +#define rglFloatToFixed 65536.f + +#define X2F(X) (((float)(X))*rglFixedToFloat) +#define F2X(A) ((int)((A)*rglFloatToFixed)) + +#endif // _TYPE_UTILS_H diff --git a/console/rgl/include/RGL/Types.h b/console/rgl/include/RGL/Types.h new file mode 100644 index 0000000000..89b4e6cc72 --- /dev/null +++ b/console/rgl/include/RGL/Types.h @@ -0,0 +1,439 @@ +#ifndef _RGLTypes_h +#define _RGLTypes_h + +#include +#include + +#include "../export/RGL/rgl.h" +#include "Base.h" + +#include + +struct rglFramebufferAttachment +{ + GLenum type; // renderbuffer or texture + GLuint name; + + // only valid for texture attachment + GLenum textureTarget; + rglFramebufferAttachment(): type( GL_NONE ), name( 0 ), textureTarget( GL_NONE ) + {}; +}; + +#define RGL_MAX_COLOR_ATTACHMENTS 4 + +struct rglFramebuffer +{ + rglFramebufferAttachment color[RGL_MAX_COLOR_ATTACHMENTS]; + GLboolean needValidate; + rglFramebuffer(): needValidate( GL_TRUE ) + {}; + virtual ~rglFramebuffer() + {}; +}; + + +#ifdef __cplusplus +extern "C" +{ +#endif + + typedef float RGLFColorComponent; + typedef float RGLCoordinate; + typedef unsigned int rglBitfield; + +#define RGLBIT_GET(f,n) ((f) & (1<<(n))) +#define RGLBIT_TRUE(f,n) ((f) |= (1<<(n))) +#define RGLBIT_FALSE(f,n) ((f) &= ~(1<<(n))) +#define RGLBIT_ASSIGN(f,n,val) do { if(val) RGLBIT_TRUE(f,n); else RGLBIT_FALSE(f,n); } while(0) + + +#define ALIGN16 __attribute__((aligned (16))) +#define _RGL_RESTRICT __restrict + + typedef struct + { + GLfloat R, G, B, A; + } rglColorRGBAf; + + typedef struct + { + int X, Y, XSize, YSize; + } rglViewPort; + + // image location flags + // These are flag bits that indicate where the valid image data is. Data + // can be valid nowhere, on the host, on the GPU, or in both places. + enum { + RGL_IMAGE_DATASTATE_UNSET = 0x0, // not a flag, just a meaningful 0 + RGL_IMAGE_DATASTATE_HOST = 0x1, + RGL_IMAGE_DATASTATE_GPU = 0x2 + }; + + // Image data structure + typedef struct rglImage_ + { + // isSet indicates whether a gl*TexImage* call has been made on that image, + // to know whether calling gl*TexSubImage* is valid or not. + GLboolean isSet; + + GLenum internalFormat; + GLenum format; + GLenum type; + GLsizei width; + GLsizei height; + GLsizei depth; + GLsizei alignment; + + // image storage + // For raster + // storage, the platform driver sets strides (in bytes) between + // lines and layers and the library takes care of the rest. + + // These values are initially zero, but may be set by the platform + // rglPlatformChooseInternalStorage to specify custom storage + // (compressed, swizzled, etc.). They should be considered + // read-only except by the platform driver. + GLsizei storageSize; // minimum allocation + GLsizei xstride, ystride, zstride; // strides + GLuint xblk, yblk; // block storage size + + char *data; + char *mallocData; + GLsizei mallocStorageSize; + GLenum dataState; // valid data location (see enum above) + } + rglImage; + + // Raster data structure + // This struct is used internally to define 3D raster data for writing + // to or reading from a rglImage. The GL-level interface for pixel/texel + // level operations always uses a raster, even though the underlying + // platform-specific storage may not be a raster (e.g. compressed + // blocks). The internal routines rglRasterToImage and rglImageToRaster + // convert between the two. + // + // A clean alternative would have been to use rglImage for everything and + // implement a single rglImageToImage copying function. However, given + // that one side will always be a raster, the implementation cost was + // not seen as worth the generality. + typedef struct + { + GLenum format; + GLenum type; + GLsizei width; + GLsizei height; + GLsizei depth; + GLsizei xstride; + GLsizei ystride; + GLsizei zstride; + void* data; + } rglRaster; + +#define RGL_TEXTURE_REVALIDATE_LAYOUT 0x01 +#define RGL_TEXTURE_REVALIDATE_IMAGES 0x02 +#define RGL_TEXTURE_REVALIDATE_PARAMETERS 0x04 + + typedef struct rglBufferObject rglBufferObject; + + // Texture data structure + typedef struct + { + GLuint revalidate; + GLuint target; + + GLuint minFilter; + GLuint magFilter; + GLfloat minLod; + GLfloat maxLod; + GLuint baseLevel; + GLuint maxLevel; + GLuint wrapS; + GLuint wrapT; + GLuint wrapR; + GLfloat lodBias; + GLfloat maxAnisotropy; + GLenum compareMode; + GLenum compareFunc; + GLuint gammaRemap; + GLenum usage; + + rglColorRGBAf borderColor; + + GLboolean vertexEnable; + GLboolean isRenderTarget; + // this is valid when the revalidate bits do not have any resource bit set. + // the validation of the resources update the bit. + GLboolean isComplete; + + rglBufferObject *referenceBuffer; + intptr_t offset; + + RGL::Vector framebuffers; + + GLuint imageCount; + GLuint faceCount; + rglImage* image; + void * platformTexture[]; // C99 flexible array member + } rglTexture; + + typedef struct + { + GLboolean isSet; + void* platformFenceObject[]; + } rglFenceObject; + + // For now, we'll use a static array for lights + // +#define RGL_MAX_TEXTURE_IMAGE_UNITS 16 +#define RGL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 4 + +#define RGL_MAX_VERTEX_ATTRIBS 16 + + // Texture image unit data structure + typedef struct + { + GLuint bound2D; + + rglTexture* default2D; + + GLboolean enable2D; + + // the current fragment program's target for this unit, if in use. + // this is invalid otherwise + GLenum fragmentTarget; + GLfloat lodBias; + + rglTexture* currentTexture; + } rglTextureImageUnit; + + enum + { + RGL_FRAMEBUFFER_ATTACHMENT_NONE, + RGL_FRAMEBUFFER_ATTACHMENT_RENDERBUFFER, + RGL_FRAMEBUFFER_ATTACHMENT_TEXTURE, + }; + + struct RGLdevice + { + PSGLdeviceParameters deviceParameters; + + GLvoid* rasterDriver; + char platformDevice[]; // C99 flexible array member + }; + + typedef struct + { + // parameters to glDraw* calls + GLenum mode; + GLint firstVertex; + GLsizei vertexCount; + GLuint indexMin; + GLuint indexMax; // 0==glDrawElements; 0!=glDrawRangeElements + GLsizei indexCount; + + // internal draw parameters (set by rglPlatformRequiresSlowPath): + // client-side array transfer buffer params + GLuint xferTotalSize; + GLuint indexXferOffset; + GLuint indexXferSize; + GLuint attribXferTotalSize; + GLuint attribXferOffset[RGL_MAX_VERTEX_ATTRIBS]; + GLuint attribXferSize[RGL_MAX_VERTEX_ATTRIBS]; + } rglDrawParams; + + // define mapping of vertex semantics to attributes + // These indices specify the aliasing of vertex attributes with + // conventional per-vertex parameters. This mapping is the same as + // specified in the NV_vertex_program extension. +#define RGL_ATTRIB_POSITION_INDEX 0 +#define RGL_ATTRIB_WEIGHT_INDEX 1 +#define RGL_ATTRIB_NORMAL_INDEX 2 +#define RGL_ATTRIB_PRIMARY_COLOR_INDEX 3 +#define RGL_ATTRIB_SECONDARY_COLOR_INDEX 4 +#define RGL_ATTRIB_FOG_COORD_INDEX 5 +#define RGL_ATTRIB_POINT_SIZE_INDEX 6 +#define RGL_ATTRIB_BLEND_INDICES_INDEX 7 +#define RGL_ATTRIB_TEX_COORD0_INDEX 8 +#define RGL_ATTRIB_TEX_COORD1_INDEX 9 +#define RGL_ATTRIB_TEX_COORD2_INDEX 10 +#define RGL_ATTRIB_TEX_COORD3_INDEX 11 +#define RGL_ATTRIB_TEX_COORD4_INDEX 12 +#define RGL_ATTRIB_TEX_COORD5_INDEX 13 +#define RGL_ATTRIB_TEX_COORD6_INDEX 14 +#define RGL_ATTRIB_TEX_COORD7_INDEX 15 + + // per-attribute descriptor and data + typedef struct + { + // GL state + GLvoid* clientData; // client-side array pointer or VBO offset + GLuint clientSize; // number of components 1-4 + GLenum clientType; // GL_SHORT, GL_INT, GL_FLOAT + GLsizei clientStride; // element-to-element distance [bytes] + GLuint arrayBuffer; // name of buffer object; 0==none (ie client-side) + GLfloat value[4]; // constant attribute value + GLuint frequency; // instancing divisor + GLboolean normalized; + } ALIGN16 rglAttribute; + + // state for the entire set of vertex attributes, plus + // other AttribSet-encapsulated state. + // (this is the block of state applied en mass during glBindAttribSetSCE()) + typedef struct + { + // Vertex attribute descriptors and data are stored in this array. + // The fixed function attributes are aliased to the array via the + // indices defined by _RGL_ATTRIB_*_INDEX. + rglAttribute attrib[RGL_MAX_VERTEX_ATTRIBS]; + + // bitfields corresponding to the attrib[] array elements: + rglBitfield DirtyMask; // 1 == attribute has changed & needs updating + rglBitfield EnabledMask; // 1 == attribute is enabled for drawing + rglBitfield HasVBOMask; // 1 == attribute is in a VBO (ie server-side) + } ALIGN16 rglAttributeState; + + struct rglBufferObject + { + GLuint refCount; + GLsizeiptr size; + GLboolean mapped; + GLenum internalFormat; + GLuint width; + GLuint height; + RGL::Vector textureReferences; + void *platformBufferObject[]; + }; + + +#define RGL_CONTEXT_RED_MASK 0x01 +#define RGL_CONTEXT_GREEN_MASK 0x02 +#define RGL_CONTEXT_BLUE_MASK 0x04 +#define RGL_CONTEXT_ALPHA_MASK 0x08 +#define RGL_CONTEXT_DEPTH_MASK 0x10 +#define RGL_CONTEXT_COLOR_MASK 0x0F + + + enum + { + RGL_CONTEXT_ACTIVE_SURFACE_COLOR0, + RGL_CONTEXT_ACTIVE_SURFACE_COLOR1, + RGL_CONTEXT_ACTIVE_SURFACE_COLOR2, + RGL_CONTEXT_ACTIVE_SURFACE_COLOR3, + RGL_CONTEXT_ACTIVE_SURFACE_DEPTH, + RGL_CONTEXT_ACTIVE_SURFACE_STENCIL, + RGL_CONTEXT_ACTIVE_SURFACES + }; + +#define rglELEMENTS_IN_MATRIX 16 // 4x4 + + typedef struct rglNameSpace + { + void** data; + void** firstFree; + unsigned long capacity; + } rglNameSpace; + + typedef void *( *rglTexNameSpaceCreateFunction )( void ); + typedef void( *rglTexNameSpaceDestroyFunction )( void * ); + + typedef struct rglTexNameSpace + { + void** data; + GLuint capacity; + rglTexNameSpaceCreateFunction create; + rglTexNameSpaceDestroyFunction destroy; + } rglTexNameSpace; + + // There are 6 clock domains, each with a maximum of 4 experiments, plus 4 elapsed exp. +#define RGL_MAX_DPM_QUERIES (4 * 6 + 4) + + struct RGLcontext + { + GLenum error; + + rglViewPort ViewPort; + GLclampf DepthNear; + GLclampf DepthFar; + + GLenum PerspectiveCorrectHint; + + rglAttributeState defaultAttribs0; // a default rglAttributeState, for bind = 0 + rglAttributeState *attribs; // ptr to current rglAttributeState + + // Frame buffer-related fields + // + GLenum DrawBuffer, ReadBuffer; + + GLboolean ShaderSRGBRemap; + + GLboolean Blending; // enable for mrt color target 0 + GLenum BlendEquationRGB; + GLenum BlendEquationAlpha; + GLenum BlendFactorSrcRGB; + GLenum BlendFactorDestRGB; + GLenum BlendFactorSrcAlpha; + GLenum BlendFactorDestAlpha; + rglColorRGBAf BlendColor; + + GLboolean ColorLogicOp; + GLenum LogicOp; + + GLboolean Dithering; + + GLuint TexCoordReplaceMask; + + rglTexNameSpace textureNameSpace; + GLuint ActiveTexture; + rglTextureImageUnit TextureImageUnits[RGL_MAX_TEXTURE_IMAGE_UNITS]; + rglTextureImageUnit* CurrentImageUnit; + + GLsizei packAlignment; + GLsizei unpackAlignment; + + rglTexNameSpace bufferObjectNameSpace; + GLuint ArrayBuffer; + GLuint PixelUnpackBuffer; + GLuint TextureBuffer; + + // synchronization objects + rglTexNameSpace fenceObjectNameSpace; + + // framebuffer objects + GLuint framebuffer; // GL_FRAMEBUFFER_OES binding + rglTexNameSpace framebufferNameSpace; + + GLboolean VertexProgram; + struct _CGprogram* BoundVertexProgram; + + GLboolean FragmentProgram; + struct _CGprogram* BoundFragmentProgram; + unsigned int LastFPConstantModification; + + GLboolean AllowTXPDemotion; + GLboolean VSync; + GLboolean SkipFirstVSync; + + GLuint needValidate; + GLboolean everAttached; + + CGerror RGLcgLastError; + CGerrorCallbackFunc RGLcgErrorCallbackFunction; + // Cg containers + CGcontext RGLcgContextHead; + rglNameSpace cgContextNameSpace; + rglNameSpace cgProgramNameSpace; + rglNameSpace cgParameterNameSpace; + }; + + +#if defined(MSVC) +#pragma warning ( pop ) +#endif + +#ifdef __cplusplus +} // Close scope of 'extern "C"' declaration which encloses file. +#endif + + +#endif // _RGLTypes_h diff --git a/console/rgl/include/RGL/Utils.h b/console/rgl/include/RGL/Utils.h new file mode 100644 index 0000000000..53aaab5220 --- /dev/null +++ b/console/rgl/include/RGL/Utils.h @@ -0,0 +1,126 @@ +#ifndef _RGLUTILS_H_ +#define _RGLUTILS_H_ + +#include "Types.h" +#include "../export/RGL/export.h" +#include "platform.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +#ifndef MSVC + // MAX that works with side effects. Just in case. +#define MAX(A,B) ({ \ + __typeof__(A) At=(A); \ + __typeof__(B) Bt=(B); \ + At>Bt?At:Bt; }) + +#define MIN(A,B) ({ \ + __typeof__(A) At=(A); \ + __typeof__(B) Bt=(B); \ + At(B)?(A):(B)) +#define MIN(A,B) ((A)<(B)?(A):(B)) +#define RGL_LIKELY(COND) (COND) +#define RGL_UNLIKELY(COND) (COND) +#endif + +#define _RGL_FLOAT_AS_UINT(x) ({union {float f; unsigned int i;} u; u.f=(x); u.i;}) + + static inline float rglClampf( const float value ) + { + return MAX( MIN( value, 1.f ), 0.f ); + } + + static inline unsigned short endianSwapHalf( unsigned short v ) + { + return ( v >> 8 & 0x00ff ) | ( v << 8 & 0xff00 ); + } + + static inline unsigned int endianSwapWord( unsigned int v ) + { + return ( v&0xff ) << 24 | ( v&0xff00 ) << 8 | + ( v&0xff0000 ) >> 8 | ( v&0xff000000 ) >> 24; + } + + static inline unsigned int endianSwapWordByHalf( unsigned int v ) + { + return ( v&0xffff ) << 16 | v >> 16; + } + + static inline int rglLog2( unsigned int i ) + { + int l = 0; + while ( i ) + { + ++l; + i >>= 1; + } + return l -1; + } + + static inline int rglIsPow2( unsigned int i ) + { + return ( i&( i - 1 ) ) == 0; + } + + // Pad argument x to the next multiple of argument pad. + static inline unsigned long rglPad( unsigned long x, unsigned long pad ) + { + return ( x + pad - 1 ) / pad*pad; + } + + // Pad pointer x to the next multiple of argument pad. + static inline char* rglPadPtr( const char* p, unsigned int pad ) + { + intptr_t x = (intptr_t)p; + x = ( x + pad - 1 ) / pad * pad; + return ( char* )x; + } + + // names API + + RGL_EXPORT void rglInitNameSpace( struct rglNameSpace * name ); + RGL_EXPORT void rglFreeNameSpace( struct rglNameSpace * name ); + RGL_EXPORT unsigned int rglCreateName( struct rglNameSpace * ns, void* object ); + RGL_EXPORT unsigned int rglIsName( struct rglNameSpace* ns, unsigned int name ); + RGL_EXPORT void rglEraseName( struct rglNameSpace* ns, unsigned int name ); + static inline void * rglGetNamedValue( struct rglNameSpace* ns, unsigned int name ) + { + return ns->data[name - 1]; + } + + void rglTexNameSpaceInit( rglTexNameSpace *ns, rglTexNameSpaceCreateFunction create, rglTexNameSpaceDestroyFunction destroy ); + void rglTexNameSpaceFree( rglTexNameSpace *ns ); + void rglTexNameSpaceResetNames( rglTexNameSpace *ns ); + GLuint rglTexNameSpaceGetFree( rglTexNameSpace *ns ); + GLboolean rglTexNameSpaceCreateNameLazy( rglTexNameSpace *ns, GLuint name ); + GLboolean rglTexNameSpaceIsName( rglTexNameSpace *ns, GLuint name ); + void rglTexNameSpaceGenNames( rglTexNameSpace *ns, GLsizei n, GLuint *names ); + void rglTexNameSpaceDeleteNames( rglTexNameSpace *ns, GLsizei n, const GLuint *names ); + void rglTexNameSpaceReinit( rglTexNameSpace * saved, rglTexNameSpace * active ); + + +#ifdef __cplusplus +} // Close scope of 'extern "C"' declaration that encloses file. +#endif + +#ifndef RGLT_UNUSED +#ifdef MSVC +#define RGL_UNUSED(value) value; +#else +#define RGL_UNUSED(value) do { \ + __typeof__(value) rglUnused = value; \ + (void)rglUnused; \ +} while(false) +#endif +#endif + +#endif // _RGL_UTILS_H_ diff --git a/console/rgl/include/RGL/platform.h b/console/rgl/include/RGL/platform.h new file mode 100644 index 0000000000..7ff036d2e1 --- /dev/null +++ b/console/rgl/include/RGL/platform.h @@ -0,0 +1,12 @@ +#ifndef _PLATFORM_H +#define _PLATFORM_H + +#include "../export/RGL/rgl.h" + +#define RGL_LITTLE_ENDIAN 0x1234 +#define RGL_BIG_ENDIAN 0x4321 + +#define RGL_ENDIAN RGL_BIG_ENDIAN +#define RGL_ALIGN_FAST_TRANSFER 128 + +#endif diff --git a/console/rgl/include/RGL/private.h b/console/rgl/include/RGL/private.h new file mode 100644 index 0000000000..77abc8e17c --- /dev/null +++ b/console/rgl/include/RGL/private.h @@ -0,0 +1,329 @@ +#ifndef _RGLPrivate_h +#define _RGLPrivate_h + + +#include "../export/RGL/rgl.h" +#include "Types.h" +#include "Utils.h" +#include "ReportInternal.h" + +#ifndef OS_VERSION_NUMERIC +#define OS_VERSION_NUMERIC 0x160 +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + + +#ifdef __cplusplus +#define _RGL_EXTERN_C extern "C" +#else +#define _RGL_EXTERN_C +#endif + + extern RGL_EXPORT RGLcontext* _CurrentContext; + extern RGLdevice* _CurrentDevice; + + extern RGL_EXPORT char* rglVersion; + + + // only for internal purpose +#define GL_UNSIGNED_BYTE_4_4 0x4A00 +#define GL_UNSIGNED_BYTE_4_4_REV 0x4A01 +#define GL_UNSIGNED_BYTE_6_2 0x4A02 +#define GL_UNSIGNED_BYTE_2_6_REV 0x4A03 +#define GL_UNSIGNED_SHORT_12_4 0x4A04 +#define GL_UNSIGNED_SHORT_4_12_REV 0x4A05 +#define GL_UNSIGNED_BYTE_2_2_2_2 0x4A06 +#define GL_UNSIGNED_BYTE_2_2_2_2_REV 0x4A07 + +#define GL_FLOAT_RGBA32 0x888B + //------------------------------------------------------------------------ + // Function prototypes + //------------------------------------------------------------------------ + //---------------------------------------- + // RGL.c + //---------------------------------------- + typedef void( * RGLcontextHookFunction )( RGLcontext *context ); + extern RGL_EXPORT RGLcontextHookFunction rglContextCreateHook; + extern RGL_EXPORT RGLcontextHookFunction rglContextDestroyHook; + + extern RGLcontext* rglContextCreate(); + extern void rglContextFree( RGLcontext* LContext ); + extern void rglSetError( GLenum error ); + extern GLuint rglValidateStates( GLuint mask ); + void rglAttachContext( RGLdevice *device, RGLcontext* context ); + void rglDetachContext( RGLdevice *device, RGLcontext* context ); + void rglInvalidateAllStates( RGLcontext* context ); + void rglResetAttributeState( rglAttributeState* as ); + void rglSetFlipHandler(void (*handler)(const GLuint head), RGLdevice *device); + void rglSetVBlankHandler(void (*handler)(const GLuint head), RGLdevice *device); + + //---------------------------------------- + // Texture.c + //---------------------------------------- + rglTexture *rglAllocateTexture(); + void rglFreeTexture( rglTexture *texture ); + void rglTextureUnbind( RGLcontext* context, GLuint name ); + extern int rglTextureInit( RGLcontext* context, GLuint name ); + extern void rglTextureDelete( RGLcontext* context, GLuint name ); + extern GLboolean rglTextureHasValidLevels( const rglTexture *texture, int levels, int width, int height, int depth, GLenum format, GLenum type, GLenum internalFormat ); + extern GLboolean rglTextureIsValid( const rglTexture* texture ); + GLenum rglGetEnabledTextureMode( const rglTextureImageUnit *unit ); + extern rglTexture *rglGetCurrentTexture( const rglTextureImageUnit *unit, GLenum target ); + RGL_EXPORT void rglUpdateCurrentTextureCache( rglTextureImageUnit *unit ); + void rglReallocateImages( rglTexture *texture, GLint level, GLsizei dimension ); + extern int rglGetImage( GLenum target, GLint level, rglTexture **texture, rglImage **image, GLsizei reallocateSize ); + static inline rglTexture* rglGetTexture( RGLcontext *LContext, GLuint name ) + { + return ( rglTexture* )LContext->textureNameSpace.data[name]; + } + + static inline rglTexture* rglGetTextureSafe( RGLcontext *LContext, GLuint name ) + { + return rglTexNameSpaceIsName( &LContext->textureNameSpace, name ) ? ( rglTexture* )LContext->textureNameSpace.data[name] : NULL; + } + + static inline rglFramebuffer *rglGetFramebuffer( RGLcontext *LContext, GLuint name ); + inline static void rglTextureTouchFBOs( rglTexture *texture ) + { + RGLcontext *LContext = _CurrentContext; + if ( !LContext ) return; // may be called in psglDestroyContext + // check if bound to any framebuffer + GLuint fbCount = texture->framebuffers.getCount(); + if ( fbCount > 0 ) + { + rglFramebuffer *contextFramebuffer = LContext->framebuffer ? rglGetFramebuffer( LContext, LContext->framebuffer ) : NULL; + for ( GLuint i = 0;i < fbCount;++i ) + { + rglFramebuffer* framebuffer = texture->framebuffers[i]; + framebuffer->needValidate = GL_TRUE; + if ( RGL_UNLIKELY( framebuffer == contextFramebuffer ) ) LContext->needValidate |= PSGL_VALIDATE_SCISSOR_BOX | PSGL_VALIDATE_FRAMEBUFFER; + } + } + } + + //---------------------------------------- + // Image.c + //---------------------------------------- + GLboolean rglIsType( GLenum type ); + GLboolean rglIsFormat( GLenum format ); + GLboolean rglIsValidPair( GLenum format, GLenum type ); + void rglImageAllocCPUStorage( rglImage *image ); + void rglImageFreeCPUStorage( rglImage *image ); + extern void rglSetImage( rglImage* image, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLsizei alignment, GLenum format, GLenum type, const GLvoid* pixels ); + extern void rglSetSubImage( GLenum target, GLint level, rglTexture *texture, rglImage* image, GLint x, GLint y, GLint z, GLsizei width, GLsizei height, GLsizei depth, GLsizei alignment, GLenum format, GLenum type, const GLvoid* pixels ); + extern int rglGetPixelSize( GLenum format, GLenum type ); + static inline int rglGetStorageSize( GLenum format, GLenum type, GLsizei width, GLsizei height, GLsizei depth ) + { + return rglGetPixelSize( format, type )*width*height*depth; + } + + extern int rglGetTypeSize( GLenum type ); + extern int rglGetMaxBitSize( GLenum type ); + extern int rglGetStorageSize( GLenum format, GLenum type, GLsizei width, GLsizei height, GLsizei depth ); + extern void rglImageToRaster( const rglImage* image, rglRaster* raster, GLuint x, GLuint y, GLuint z ); + extern void rglRasterToImage( const rglRaster* raster, rglImage* image, GLuint x, GLuint y, GLuint z ); + extern void rglRawRasterToImage( const rglRaster* raster, rglImage* image, GLuint x, GLuint y, GLuint z ); + void rglResampleImage3D( rglImage* src, rglImage* dst ); + + //---------------------------------------- + // Sync.c + //---------------------------------------- + rglFenceObject *rglCreateFenceObject(); + void rglFreeFenceObject( rglFenceObject *fence ); + static inline rglFenceObject *rglGetFenceObject( RGLcontext *LContext, GLuint name ) + { + return ( rglFenceObject * )LContext->fenceObjectNameSpace.data[name]; + } + + //---------------------------------------- + // FramebufferObject.c + //---------------------------------------- + rglFramebuffer *rglCreateFramebuffer( void ); + void rglDestroyFramebuffer( rglFramebuffer *framebuffer ); + static inline rglFramebuffer *rglGetFramebuffer( RGLcontext *LContext, GLuint name ) + { + return ( rglFramebuffer * )LContext->framebufferNameSpace.data[name]; + } + + static inline rglFramebuffer *rglGetFramebufferSafe( RGLcontext *LContext, GLuint name ) + { + return rglTexNameSpaceIsName( &LContext->framebufferNameSpace, name ) ? ( rglFramebuffer * )LContext->framebufferNameSpace.data[name] : NULL; + } + + void rglFramebufferGetAttachmentTexture( RGLcontext* LContext, const rglFramebufferAttachment* attachment, rglTexture** texture, GLuint* face ); + GLenum rglPlatformFramebufferCheckStatus( rglFramebuffer* framebuffer ); + GLboolean rglPlatformGenerateMipmap( rglTexture* texture, GLuint face ); + void rglPlatformFramebufferGetParameteriv( GLenum pname, GLint* params ); + void rglPlatformResolveFramebuffer(); + void rglGetFramebufferSize( GLuint* width, GLuint* height ); + + //---------------------------------------- + // VertexArray.c + //---------------------------------------- + void rglVertexAttrib1fNV( GLuint index, GLfloat x ); + void rglVertexAttrib1fvNV( GLuint index, const GLfloat* v ); + void rglVertexAttrib2fNV( GLuint index, GLfloat x, GLfloat y ); + void rglVertexAttrib2fvNV( GLuint index, const GLfloat* v ); + void rglVertexAttrib3fNV( GLuint index, GLfloat x, GLfloat y, GLfloat z ); + void rglVertexAttrib3fvNV( GLuint index, const GLfloat* v ); + void rglVertexAttrib4fNV( GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w ); + void rglVertexAttrib4fvNV( GLuint index, const GLfloat* v ); + void rglVertexAttribPointerNV( GLuint index, GLint fsize, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* pointer ); + void rglVertexAttribElementFunc( GLuint index, GLenum func, GLuint frequency ); + void rglEnableVertexAttribArrayNV( GLuint index ); + void rglDisableVertexAttribArrayNV( GLuint index ); + GLint rglConvertStream( rglAttributeState* asDst, const rglAttributeState* asSrc, GLuint index, + GLint skip, GLint first, GLint count, + const void* indices, GLenum indexType ); + void rglComputeMinMaxIndices( RGLcontext* LContext, GLuint* min, GLuint* max, const void* indices, GLenum indexType, GLsizei count ); + + //---------------------------------------- + // Platform/Init.c + //---------------------------------------- + extern void rglPlatformInit( PSGLinitOptions* options ); + extern void rglPlatformExit(); + + //---------------------------------------- + // Device/Device.c + //---------------------------------------- + extern void rglDeviceInit( PSGLinitOptions* options ); + extern void rglDeviceExit(); + extern PSGLdeviceParameters * rglShadowDeviceParameters( void ); + + + //---------------------------------------- + // Device/.../PlatformDevice.c + //---------------------------------------- + extern GLboolean rglPlatformDeviceInit( PSGLinitOptions* options ); + extern void rglPlatformDeviceExit(); + extern int rglPlatformDeviceSize(); + extern int rglPlatformCreateDevice( RGLdevice* device ); + extern void rglPlatformDestroyDevice( RGLdevice* device ); + extern void rglPlatformMakeCurrent( void* device ); + extern void rglPlatformSwapBuffers( RGLdevice* device ); + extern const GLvoid* rglPlatformGetProcAddress( const char *funcName ); + + //---------------------------------------- + // Raster/.../PlatformRaster.c + //---------------------------------------- + void* rglPlatformRasterInit(); + void rglPlatformRasterExit( void* driver ); + void rglPlatformRasterDestroyResources(); + void rglPlatformDraw( rglDrawParams* dparams ); + GLboolean rglPlatformNeedsConversion( const rglAttributeState* as, GLuint index ); + // [YLIN] Try to avoid LHS inside this function. + // In oringinal implementation, indexType and indexCount will be stored right before this function + // and since we will load them right after enter this function, there are LHS. + GLboolean rglPlatformRequiresSlowPath( rglDrawParams* dparams, const GLenum indexType, uint32_t indexCount); + void rglPlatformRasterGetIntegerv( GLenum pname, GLint* params ); + void rglPlatformRasterFlush(); + void rglPlatformRasterFinish(); + void rglValidateFragmentProgram(); + void rglValidateFragmentProgramSharedConstants(); + void rglValidateClipPlanes(); + void rglInvalidateAttributes(); + GLuint rglValidateAttributes( const GLvoid* indices, GLboolean *isMain ); + GLuint rglValidateAttributesSlow( rglDrawParams *dparams, GLboolean *isMain ); + + //---------------------------------------- + // Raster/.../PlatformTexture.c + //---------------------------------------- + extern int rglPlatformTextureSize(); + extern int rglPlatformTextureMaxUnits(); + extern void rglPlatformCreateTexture( rglTexture* texture ); + extern void rglPlatformDestroyTexture( rglTexture* texture ); + extern void rglPlatformValidateTextureStage( int unit, rglTexture*texture ); + void rglPlatformValidateVertexTextures(); + extern GLenum rglPlatformChooseInternalStorage( rglImage* image, GLenum internalformat ); + extern GLenum rglPlatformTranslateTextureFormat( GLenum internalFormat ); + extern void rglPlatformCopyTexSubImage3D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height ); + GLenum rglPlatformChooseInternalFormat( GLenum internalformat ); + void rglPlatformExpandInternalFormat( GLenum internalformat, GLenum *format, GLenum *type ); + void rglPlatformGetImageData( GLenum target, GLint level, rglTexture *texture, rglImage *image ); + extern void rglPlatformSetCompressedTexture( + GLenum target, + GLint level, + GLenum internalformat, + GLsizei width, GLsizei height, GLsizei depth, + GLint border, + GLsizei imageSize, + const GLvoid* data ); + extern void rglPlatformSetCompressedTextureSub( + GLenum target, + GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, + GLenum format, + GLsizei imageSize, + const GLvoid* data ); + extern GLboolean rglPlatformTexturePBOImage( + rglTexture* texture, + rglImage* image, + GLint level, + GLint internalformat, + GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLenum type, + const GLvoid *offset ); + extern GLboolean rglPlatformTexturePBOSubImage( + rglTexture* texture, + rglImage* image, + GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLenum type, + const GLvoid *pixels ); + GLboolean rglPlatformTextureReference( rglTexture *texture, GLuint pitch, rglBufferObject *bufferObject, GLintptr offset ); + + //---------------------------------------- + // Raster/.../PlatformFBops.c + //---------------------------------------- + extern void rglFBClear( GLbitfield mask ); + extern void rglValidateFramebuffer( void ); + extern void rglValidateFFXVertexProgram(); + extern void rglValidateFFXFragmentProgram(); + extern void rglPlatformReadPixels( GLint x, GLint y, GLsizei width, GLsizei height, GLboolean flip, GLenum format, GLenum type, GLvoid *pixels ); + extern GLboolean rglPlatformReadPBOPixels( GLint x, GLint y, GLsizei width, GLsizei height, GLboolean flip, GLenum format, GLenum type, GLvoid *pixels ); + + //---------------------------------------- + // Raster/.../PlatformTNL.c + //---------------------------------------- + void rglValidateNormalize(); + void rglValidateVertexProgram(); + void rglValidateVertexConstants(); + + //---------------------------------------- + // Raster/.../PlatformBuffer.c + //---------------------------------------- + int rglPlatformBufferObjectSize(); + GLboolean rglPlatformCreateBufferObject( rglBufferObject* bufferObject ); + void rglPlatformDestroyBufferObject( rglBufferObject* bufferObject ); + void rglPlatformBufferObjectSetData( rglBufferObject* bufferObject, GLintptr offset, GLsizeiptr size, const GLvoid *data, GLboolean tryImmediateCopy ); + GLvoid rglPlatformBufferObjectCopyData( rglBufferObject* bufferObjectDst, rglBufferObject* bufferObjectSrc ); + // map / unmap buffers. Internally refcounted + char *rglPlatformBufferObjectMap( rglBufferObject* bufferObject, GLenum access ); + GLboolean rglPlatformBufferObjectUnmap( rglBufferObject* bufferObject ); + void rglPlatformGetBufferParameteriv( rglBufferObject *bufferObject, GLenum pname, int *params ); + + // this is shared in glBindTexture and cgGL code + RGL_EXPORT void rglBindTextureInternal( rglTextureImageUnit *unit, GLuint name, GLenum target ); + void rglBindVertexTextureInternal( GLuint unit, GLuint name ); + + //---------------------------------------- + // Raster/.../PlatformSync.c + //---------------------------------------- + int rglPlatformFenceObjectSize(); + GLboolean rglPlatformCreateFenceObject( rglFenceObject* fenceObject ); + void rglPlatformDestroyFenceObject( rglFenceObject* fenceObject ); + void rglPlatformSetFence( rglFenceObject* fenceObject ); + GLboolean rglPlatformTestFence( rglFenceObject* fenceObject ); + void rglPlatformFinishFence( rglFenceObject* fenceObject ); + +#ifdef __cplusplus +} // Close scope of 'extern "C"' declaration that encloses file. +#endif + +#endif // _RGLPrivate_h diff --git a/console/rgl/include/export/GLES/gl.h b/console/rgl/include/export/GLES/gl.h new file mode 100644 index 0000000000..505b2c854c --- /dev/null +++ b/console/rgl/include/export/GLES/gl.h @@ -0,0 +1,551 @@ +#ifndef __gl_h_ +#define __gl_h_ + +#ifdef __cplusplus +extern "C" +{ +#endif + + /* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 1.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +#ifdef RGL_EXPORT +#define GLAPI RGL_EXPORT +#endif + +#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SYMBIAN32__) +#define WIN32_LEAN_AND_MEAN 1 +#include +#endif + + +#ifndef APIENTRY +#define APIENTRY +#endif +#ifndef GLAPI +#define GLAPI extern +#endif + + typedef unsigned int GLenum; + typedef unsigned char GLboolean; + typedef unsigned int GLbitfield; + typedef signed char GLbyte; + typedef short GLshort; + typedef int GLint; + typedef int GLsizei; + typedef unsigned char GLubyte; + typedef unsigned short GLushort; + typedef unsigned int GLuint; + typedef float GLfloat; + typedef float GLclampf; + typedef void GLvoid; + typedef int GLfixed; + typedef int GLclampx; + /* Internal convenience typedefs */ + typedef void( *_GLfuncptr )(); + + /*************************************************************/ + + /* Extensions */ +#define GL_OES_VERSION_1_0 1 +#define GL_OES_read_format 1 +#define GL_OES_compressed_paletted_texture 1 + + /* ClearBufferMask */ +#define GL_DEPTH_BUFFER_BIT 0x00000100 +#define GL_STENCIL_BUFFER_BIT 0x00000400 +#define GL_COLOR_BUFFER_BIT 0x00004000 + + /* Boolean */ +#define GL_FALSE 0 +#define GL_TRUE 1 + + /* BeginMode */ +#define GL_POINTS 0x0000 +#define GL_LINES 0x0001 +#define GL_LINE_LOOP 0x0002 +#define GL_LINE_STRIP 0x0003 +#define GL_TRIANGLES 0x0004 +#define GL_TRIANGLE_STRIP 0x0005 +#define GL_TRIANGLE_FAN 0x0006 + + /* AlphaFunction */ +#define GL_NEVER 0x0200 +#define GL_LESS 0x0201 +#define GL_EQUAL 0x0202 +#define GL_LEQUAL 0x0203 +#define GL_GREATER 0x0204 +#define GL_NOTEQUAL 0x0205 +#define GL_GEQUAL 0x0206 +#define GL_ALWAYS 0x0207 + + /* BlendingFactorDest */ +#define GL_ZERO 0 +#define GL_ONE 1 +#define GL_SRC_COLOR 0x0300 +#define GL_ONE_MINUS_SRC_COLOR 0x0301 +#define GL_SRC_ALPHA 0x0302 +#define GL_ONE_MINUS_SRC_ALPHA 0x0303 +#define GL_DST_ALPHA 0x0304 +#define GL_ONE_MINUS_DST_ALPHA 0x0305 + + /* BlendingFactorSrc */ + /* GL_ZERO */ + /* GL_ONE */ +#define GL_DST_COLOR 0x0306 +#define GL_ONE_MINUS_DST_COLOR 0x0307 +#define GL_SRC_ALPHA_SATURATE 0x0308 + /* GL_SRC_ALPHA */ + /* GL_ONE_MINUS_SRC_ALPHA */ + /* GL_DST_ALPHA */ + /* GL_ONE_MINUS_DST_ALPHA */ + + /* ColorMaterialFace */ + /* GL_FRONT_AND_BACK */ + + /* ColorMaterialParameter */ + /* GL_AMBIENT_AND_DIFFUSE */ + + /* ColorPointerType */ + /* GL_UNSIGNED_BYTE */ + /* GL_FLOAT */ + /* GL_FIXED */ + + /* CullFaceMode */ +#define GL_FRONT 0x0404 +#define GL_BACK 0x0405 +#define GL_FRONT_AND_BACK 0x0408 + + /* DepthFunction */ + /* GL_NEVER */ + /* GL_LESS */ + /* GL_EQUAL */ + /* GL_LEQUAL */ + /* GL_GREATER */ + /* GL_NOTEQUAL */ + /* GL_GEQUAL */ + /* GL_ALWAYS */ + + /* EnableCap */ +#define GL_FOG 0x0B60 +#define GL_LIGHTING 0x0B50 +#define GL_TEXTURE_2D 0x0DE1 +#define GL_CULL_FACE 0x0B44 +#define GL_BLEND 0x0BE2 +#define GL_COLOR_LOGIC_OP 0x0BF2 +#define GL_DITHER 0x0BD0 +#define GL_STENCIL_TEST 0x0B90 +#define GL_DEPTH_TEST 0x0B71 + /* GL_LIGHT0 */ + /* GL_LIGHT1 */ + /* GL_LIGHT2 */ + /* GL_LIGHT3 */ + /* GL_LIGHT4 */ + /* GL_LIGHT5 */ + /* GL_LIGHT6 */ + /* GL_LIGHT7 */ +#define GL_POINT_SMOOTH 0x0B10 +#define GL_LINE_SMOOTH 0x0B20 +#define GL_SCISSOR_TEST 0x0C11 +#define GL_COLOR_MATERIAL 0x0B57 +#define GL_NORMALIZE 0x0BA1 +#define GL_RESCALE_NORMAL 0x803A +#define GL_POLYGON_OFFSET_FILL 0x8037 +#define GL_VERTEX_ARRAY 0x8074 +#define GL_NORMAL_ARRAY 0x8075 +#define GL_COLOR_ARRAY 0x8076 +#define GL_TEXTURE_COORD_ARRAY 0x8078 +#define GL_MULTISAMPLE 0x809D +#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE 0x809F +#define GL_SAMPLE_COVERAGE 0x80A0 + + /* ErrorCode */ +#define GL_NO_ERROR 0 +#define GL_INVALID_ENUM 0x0500 +#define GL_INVALID_VALUE 0x0501 +#define GL_INVALID_OPERATION 0x0502 +#define GL_STACK_OVERFLOW 0x0503 +#define GL_STACK_UNDERFLOW 0x0504 +#define GL_OUT_OF_MEMORY 0x0505 + + /* FogMode */ + /* GL_LINEAR */ +#define GL_EXP 0x0800 +#define GL_EXP2 0x0801 + + /* FogParameter */ +#define GL_FOG_DENSITY 0x0B62 +#define GL_FOG_START 0x0B63 +#define GL_FOG_END 0x0B64 +#define GL_FOG_MODE 0x0B65 +#define GL_FOG_COLOR 0x0B66 + + /* FrontFaceDirection */ +#define GL_CW 0x0900 +#define GL_CCW 0x0901 + + /* GetPName */ +#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12 +#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22 +#define GL_ALIASED_POINT_SIZE_RANGE 0x846D +#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E +#define GL_IMPLEMENTATION_COLOR_READ_TYPE_OES 0x8B9A +#define GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES 0x8B9B +#define GL_MAX_LIGHTS 0x0D31 +#define GL_MAX_TEXTURE_SIZE 0x0D33 +#define GL_MAX_MODELVIEW_STACK_DEPTH 0x0D36 +#define GL_MAX_PROJECTION_STACK_DEPTH 0x0D38 +#define GL_MAX_TEXTURE_STACK_DEPTH 0x0D39 +#define GL_MAX_VIEWPORT_DIMS 0x0D3A +#define GL_MAX_ELEMENTS_VERTICES 0x80E8 +#define GL_MAX_ELEMENTS_INDICES 0x80E9 +#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 +#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 +#define GL_SUBPIXEL_BITS 0x0D50 + + /* HintMode */ +#define GL_DONT_CARE 0x1100 +#define GL_FASTEST 0x1101 +#define GL_NICEST 0x1102 + + /* HintTarget */ +#define GL_PERSPECTIVE_CORRECTION_HINT 0x0C50 +#define GL_POINT_SMOOTH_HINT 0x0C51 +#define GL_LINE_SMOOTH_HINT 0x0C52 +#define GL_POLYGON_SMOOTH_HINT 0x0C53 +#define GL_FOG_HINT 0x0C54 + + /* LightModelParameter */ +#define GL_LIGHT_MODEL_AMBIENT 0x0B53 +#define GL_LIGHT_MODEL_TWO_SIDE 0x0B52 + + /* LightParameter */ +#define GL_AMBIENT 0x1200 +#define GL_DIFFUSE 0x1201 +#define GL_SPECULAR 0x1202 +#define GL_POSITION 0x1203 +#define GL_SPOT_DIRECTION 0x1204 +#define GL_SPOT_EXPONENT 0x1205 +#define GL_SPOT_CUTOFF 0x1206 +#define GL_CONSTANT_ATTENUATION 0x1207 +#define GL_LINEAR_ATTENUATION 0x1208 +#define GL_QUADRATIC_ATTENUATION 0x1209 + + /* DataType */ +#define GL_BYTE 0x1400 +#define GL_UNSIGNED_BYTE 0x1401 +#define GL_SHORT 0x1402 +#define GL_UNSIGNED_SHORT 0x1403 +#define GL_FLOAT 0x1406 +#define GL_FIXED 0x140C + + /* LogicOp */ +#define GL_CLEAR 0x1500 +#define GL_AND 0x1501 +#define GL_AND_REVERSE 0x1502 +#define GL_COPY 0x1503 +#define GL_AND_INVERTED 0x1504 +#define GL_NOOP 0x1505 +#define GL_XOR 0x1506 +#define GL_OR 0x1507 +#define GL_NOR 0x1508 +#define GL_EQUIV 0x1509 +#define GL_INVERT 0x150A +#define GL_OR_REVERSE 0x150B +#define GL_COPY_INVERTED 0x150C +#define GL_OR_INVERTED 0x150D +#define GL_NAND 0x150E +#define GL_SET 0x150F + + /* MaterialFace */ + /* GL_FRONT_AND_BACK */ + + /* MaterialParameter */ +#define GL_EMISSION 0x1600 +#define GL_SHININESS 0x1601 +#define GL_AMBIENT_AND_DIFFUSE 0x1602 + /* GL_AMBIENT */ + /* GL_DIFFUSE */ + /* GL_SPECULAR */ + + /* MatrixMode */ +#define GL_MODELVIEW 0x1700 +#define GL_PROJECTION 0x1701 +#define GL_TEXTURE 0x1702 + + /* NormalPointerType */ + /* GL_BYTE */ + /* GL_SHORT */ + /* GL_FLOAT */ + /* GL_FIXED */ + + /* PixelFormat */ +#define GL_ALPHA 0x1906 +#define GL_RGB 0x1907 +#define GL_RGBA 0x1908 + + /* PixelStoreParameter */ +#define GL_UNPACK_ALIGNMENT 0x0CF5 +#define GL_PACK_ALIGNMENT 0x0D05 + + /* PixelType */ + /* GL_UNSIGNED_BYTE */ +#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 +#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 +#define GL_UNSIGNED_SHORT_5_6_5 0x8363 + + /* ShadingModel */ +#define GL_FLAT 0x1D00 +#define GL_SMOOTH 0x1D01 + + /* StencilFunction */ + /* GL_NEVER */ + /* GL_LESS */ + /* GL_EQUAL */ + /* GL_LEQUAL */ + /* GL_GREATER */ + /* GL_NOTEQUAL */ + /* GL_GEQUAL */ + /* GL_ALWAYS */ + + /* StencilOp */ + /* GL_ZERO */ +#define GL_KEEP 0x1E00 +#define GL_REPLACE 0x1E01 +#define GL_INCR 0x1E02 +#define GL_DECR 0x1E03 + /* GL_INVERT */ + + /* StringName */ +#define GL_VENDOR 0x1F00 +#define GL_RENDERER 0x1F01 +#define GL_VERSION 0x1F02 +#define GL_EXTENSIONS 0x1F03 + + /* TexCoordPointerType */ + /* GL_SHORT */ + /* GL_FLOAT */ + /* GL_FIXED */ + /* GL_BYTE */ + + /* TextureEnvMode */ +#define GL_MODULATE 0x2100 +#define GL_DECAL 0x2101 + /* GL_BLEND */ +#define GL_ADD 0x0104 + /* GL_REPLACE */ + + /* TextureEnvParameter */ +#define GL_TEXTURE_ENV_MODE 0x2200 +#define GL_TEXTURE_ENV_COLOR 0x2201 + + /* TextureEnvTarget */ +#define GL_TEXTURE_ENV 0x2300 + + /* TextureMagFilter */ +#define GL_NEAREST 0x2600 +#define GL_LINEAR 0x2601 + + /* TextureMinFilter */ + /* GL_NEAREST */ + /* GL_LINEAR */ +#define GL_NEAREST_MIPMAP_NEAREST 0x2700 +#define GL_LINEAR_MIPMAP_NEAREST 0x2701 +#define GL_NEAREST_MIPMAP_LINEAR 0x2702 +#define GL_LINEAR_MIPMAP_LINEAR 0x2703 + + /* TextureParameterName */ +#define GL_TEXTURE_MAG_FILTER 0x2800 +#define GL_TEXTURE_MIN_FILTER 0x2801 +#define GL_TEXTURE_WRAP_S 0x2802 +#define GL_TEXTURE_WRAP_T 0x2803 + + /* TextureTarget */ + /* GL_TEXTURE_2D */ + + /* TextureUnit */ +#define GL_TEXTURE0 0x84C0 +#define GL_TEXTURE1 0x84C1 +#define GL_TEXTURE2 0x84C2 +#define GL_TEXTURE3 0x84C3 +#define GL_TEXTURE4 0x84C4 +#define GL_TEXTURE5 0x84C5 +#define GL_TEXTURE6 0x84C6 +#define GL_TEXTURE7 0x84C7 +#define GL_TEXTURE8 0x84C8 +#define GL_TEXTURE9 0x84C9 +#define GL_TEXTURE10 0x84CA +#define GL_TEXTURE11 0x84CB +#define GL_TEXTURE12 0x84CC +#define GL_TEXTURE13 0x84CD +#define GL_TEXTURE14 0x84CE +#define GL_TEXTURE15 0x84CF +#define GL_TEXTURE16 0x84D0 +#define GL_TEXTURE17 0x84D1 +#define GL_TEXTURE18 0x84D2 +#define GL_TEXTURE19 0x84D3 +#define GL_TEXTURE20 0x84D4 +#define GL_TEXTURE21 0x84D5 +#define GL_TEXTURE22 0x84D6 +#define GL_TEXTURE23 0x84D7 +#define GL_TEXTURE24 0x84D8 +#define GL_TEXTURE25 0x84D9 +#define GL_TEXTURE26 0x84DA +#define GL_TEXTURE27 0x84DB +#define GL_TEXTURE28 0x84DC +#define GL_TEXTURE29 0x84DD +#define GL_TEXTURE30 0x84DE +#define GL_TEXTURE31 0x84DF + + /* TextureWrapMode */ +#define GL_REPEAT 0x2901 +#define GL_CLAMP_TO_EDGE 0x812F + + /* PixelInternalFormat */ +#define GL_PALETTE4_RGB8_OES 0x8B90 +#define GL_PALETTE4_RGBA8_OES 0x8B91 +#define GL_PALETTE4_R5_G6_B5_OES 0x8B92 +#define GL_PALETTE4_RGBA4_OES 0x8B93 +#define GL_PALETTE4_RGB5_A1_OES 0x8B94 +#define GL_PALETTE8_RGB8_OES 0x8B95 +#define GL_PALETTE8_RGBA8_OES 0x8B96 +#define GL_PALETTE8_R5_G6_B5_OES 0x8B97 +#define GL_PALETTE8_RGBA4_OES 0x8B98 +#define GL_PALETTE8_RGB5_A1_OES 0x8B99 + + /* VertexPointerType */ + /* GL_SHORT */ + /* GL_FLOAT */ + /* GL_FIXED */ + /* GL_BYTE */ + + /* LightName */ +#define GL_LIGHT0 0x4000 +#define GL_LIGHT1 0x4001 +#define GL_LIGHT2 0x4002 +#define GL_LIGHT3 0x4003 +#define GL_LIGHT4 0x4004 +#define GL_LIGHT5 0x4005 +#define GL_LIGHT6 0x4006 +#define GL_LIGHT7 0x4007 + + + /*************************************************************/ + + GLAPI void APIENTRY glActiveTexture( GLenum texture ); + GLAPI void APIENTRY glAlphaFunc( GLenum func, GLclampf ref ); + GLAPI void APIENTRY glAlphaFuncx( GLenum func, GLclampx ref ); + GLAPI void APIENTRY glBindTexture( GLenum target, GLuint texture ); + GLAPI void APIENTRY glBlendFunc( GLenum sfactor, GLenum dfactor ); + GLAPI void APIENTRY glClear( GLbitfield mask ); + GLAPI void APIENTRY glClearColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha ); + GLAPI void APIENTRY glClearColorx( GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha ); + GLAPI void APIENTRY glClearDepthf( GLclampf depth ); + GLAPI void APIENTRY glClearDepthx( GLclampx depth ); + GLAPI void APIENTRY glClearStencil( GLint s ); + GLAPI void APIENTRY glClientActiveTexture( GLenum texture ); + GLAPI void APIENTRY glColor4f( GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha ); + GLAPI void APIENTRY glColor4x( GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha ); + GLAPI void APIENTRY glColorMask( GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha ); + GLAPI void APIENTRY glColorPointer( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer ); + GLAPI void APIENTRY glCopyTexImage2D( GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border ); + GLAPI void APIENTRY glCopyTexSubImage2D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height ); + GLAPI void APIENTRY glCullFace( GLenum mode ); + GLAPI void APIENTRY glDeleteTextures( GLsizei n, const GLuint *textures ); + GLAPI void APIENTRY glDepthFunc( GLenum func ); + GLAPI void APIENTRY glDepthMask( GLboolean flag ); + GLAPI void APIENTRY glDepthRangef( GLclampf zNear, GLclampf zFar ); + GLAPI void APIENTRY glDepthRangex( GLclampx zNear, GLclampx zFar ); + GLAPI void APIENTRY glDisable( GLenum cap ); + GLAPI void APIENTRY glDisableClientState( GLenum array ); + GLAPI void APIENTRY glDrawArrays( GLenum mode, GLint first, GLsizei count ); + GLAPI void APIENTRY glDrawElements( GLenum mode, GLsizei count, GLenum type, const GLvoid *indices ); + GLAPI void APIENTRY glEnable( GLenum cap ); + GLAPI void APIENTRY glEnableClientState( GLenum array ); + GLAPI void APIENTRY glFinish( void ); + GLAPI void APIENTRY glFlush( void ); + GLAPI void APIENTRY glGenTextures( GLsizei n, GLuint *textures ); + GLAPI GLenum APIENTRY glGetError( void ); + GLAPI void APIENTRY glGetIntegerv( GLenum pname, GLint *params ); + GLAPI const GLubyte * APIENTRY glGetString( GLenum name ); + GLAPI void APIENTRY glHint( GLenum target, GLenum mode ); + GLAPI void APIENTRY glLineWidth( GLfloat width ); + GLAPI void APIENTRY glLineWidthx( GLfixed width ); + GLAPI void APIENTRY glLoadIdentity( void ); + GLAPI void APIENTRY glLogicOp( GLenum opcode ); + GLAPI void APIENTRY glMaterialf( GLenum face, GLenum pname, GLfloat param ); + GLAPI void APIENTRY glMaterialfv( GLenum face, GLenum pname, const GLfloat *params ); + GLAPI void APIENTRY glMaterialx( GLenum face, GLenum pname, GLfixed param ); + GLAPI void APIENTRY glMaterialxv( GLenum face, GLenum pname, const GLfixed *params ); + GLAPI void APIENTRY glMatrixMode( GLenum mode ); + GLAPI void APIENTRY glMultiTexCoord4f( GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q ); + GLAPI void APIENTRY glMultiTexCoord4x( GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q ); + GLAPI void APIENTRY glNormal3f( GLfloat nx, GLfloat ny, GLfloat nz ); + GLAPI void APIENTRY glNormal3x( GLfixed nx, GLfixed ny, GLfixed nz ); + GLAPI void APIENTRY glNormalPointer( GLenum type, GLsizei stride, const GLvoid *pointer ); + GLAPI void APIENTRY glOrthof( GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar ); + GLAPI void APIENTRY glOrthox( GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar ); + GLAPI void APIENTRY glPixelStorei( GLenum pname, GLint param ); + GLAPI void APIENTRY glPointSize( GLfloat size ); + GLAPI void APIENTRY glPointSizex( GLfixed size ); + GLAPI void APIENTRY glPolygonOffset( GLfloat factor, GLfloat units ); + GLAPI void APIENTRY glPolygonOffsetx( GLfixed factor, GLfixed units ); + GLAPI void APIENTRY glReadPixels( GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels ); + GLAPI void APIENTRY glRotatef( GLfloat angle, GLfloat x, GLfloat y, GLfloat z ); + GLAPI void APIENTRY glRotatex( GLfixed angle, GLfixed x, GLfixed y, GLfixed z ); + GLAPI void APIENTRY glSampleCoverage( GLclampf value, GLboolean invert ); + GLAPI void APIENTRY glSampleCoveragex( GLclampx value, GLboolean invert ); + GLAPI void APIENTRY glScalef( GLfloat x, GLfloat y, GLfloat z ); + GLAPI void APIENTRY glScalex( GLfixed x, GLfixed y, GLfixed z ); + GLAPI void APIENTRY glScissor( GLint x, GLint y, GLsizei width, GLsizei height ); + GLAPI void APIENTRY glTexCoordPointer( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer ); + GLAPI void APIENTRY glTexEnvf( GLenum target, GLenum pname, GLfloat param ); + GLAPI void APIENTRY glTexEnvfv( GLenum target, GLenum pname, const GLfloat *params ); + GLAPI void APIENTRY glTexEnvx( GLenum target, GLenum pname, GLfixed param ); + GLAPI void APIENTRY glTexEnvxv( GLenum target, GLenum pname, const GLfixed *params ); + GLAPI void APIENTRY glTexImage2D( GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels ); + GLAPI void APIENTRY glTexParameterf( GLenum target, GLenum pname, GLfloat param ); + GLAPI void APIENTRY glTexParameterx( GLenum target, GLenum pname, GLfixed param ); + GLAPI void APIENTRY glTexSubImage2D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels ); + GLAPI void APIENTRY glTranslatef( GLfloat x, GLfloat y, GLfloat z ); + GLAPI void APIENTRY glTranslatex( GLfixed x, GLfixed y, GLfixed z ); + GLAPI void APIENTRY glVertexPointer( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer ); + GLAPI void APIENTRY glViewport( GLint x, GLint y, GLsizei width, GLsizei height ); + +#ifdef __cplusplus +} +#endif + +#endif /* __gl_h_ */ diff --git a/console/rgl/include/export/GLES/glext.h b/console/rgl/include/export/GLES/glext.h new file mode 100644 index 0000000000..8c4ad92822 --- /dev/null +++ b/console/rgl/include/export/GLES/glext.h @@ -0,0 +1,421 @@ +#ifndef __gl_ext_h_ +#define __gl_ext_h_ + + +#ifndef _MSC_VER +#include +#else +#include +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + + typedef intptr_t GLintptr; + typedef intptr_t GLsizeiptr; + typedef unsigned short GLhalfARB; + +#define GL_QUADS 0x0007 +#define GL_QUAD_STRIP 0x0008 + +#define GL_INT 0x1404 +#define GL_UNSIGNED_INT 0x1405 + + /* Image types */ +#define GL_UNSIGNED_BYTE_3_3_2 0x8032 +#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362 +#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364 +#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365 +#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366 +#define GL_UNSIGNED_INT_8_8_8_8 0x8035 +#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367 +#define GL_UNSIGNED_INT_10_10_10_2 0x8036 +#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 +#define GL_UNSIGNED_INT_24_8_SCE 0x6008 +#define GL_UNSIGNED_INT_8_24_REV_SCE 0x6009 + +#define GL_HALF_FLOAT_ARB 0x140B + + /* Image internal formats */ +#define GL_ALPHA4 0x803B +#define GL_ALPHA12 0x803D +#define GL_ALPHA16 0x803E +#define GL_R3_G3_B2 0x2A10 +#define GL_RGB4 0x804F +#define GL_RGB5 0x8050 +#define GL_RGB8 0x8051 +#define GL_RGBA2 0x8055 +#define GL_RGBA4 0x8056 +#define GL_RGB5_A1 0x8057 +#define GL_RGBA12 0x805A +#define GL_RGBA16 0x805B +#define GL_BGR 0x80E0 +#define GL_BGRA 0x80E1 +#define GL_ABGR 0x8000 +#define GL_RED 0x1903 +#define GL_GREEN 0x1904 +#define GL_BLUE 0x1905 +#define GL_ARGB_SCE 0x6007 + +#define GL_RGBA32F_ARB 0x8814 +#define GL_RGB32F_ARB 0x8815 +#define GL_ALPHA32F_ARB 0x8816 +#define GL_RGBA16F_ARB 0x881A +#define GL_RGB16F_ARB 0x881B +#define GL_ALPHA16F_ARB 0x881C + +#define GL_UNSIGNED_SHORT_8_8_SCE 0x600B +#define GL_UNSIGNED_SHORT_8_8_REV_SCE 0x600C +#define GL_UNSIGNED_INT_16_16_SCE 0x600D +#define GL_UNSIGNED_INT_16_16_REV_SCE 0x600E + +#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 +#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 +#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2 +#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 + + + /* TexGen */ +#define GL_EYE_LINEAR 0x2400 +#define GL_OBJECT_LINEAR 0x2401 +#define GL_SPHERE_MAP 0x2402 +#define GL_NORMAL_MAP 0x8511 +#define GL_REFLECTION_MAP 0x8512 +#define GL_S 0x2000 +#define GL_T 0x2001 +#define GL_R 0x2002 +#define GL_Q 0x2003 +#define GL_OBJECT_PLANE 0x2501 +#define GL_EYE_PLANE 0x2502 +#define GL_TEXTURE_GEN_MODE 0x2500 +#define GL_TEXTURE_GEN_S 0x0C60 +#define GL_TEXTURE_GEN_T 0x0C61 +#define GL_TEXTURE_GEN_R 0x0C62 +#define GL_TEXTURE_GEN_Q 0x0C63 + + /* Blending */ +#define GL_CONSTANT_COLOR 0x8001 +#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 +#define GL_CONSTANT_ALPHA 0x8003 +#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 +#define GL_BLEND_EQUATION 0x8009 +#define GL_FUNC_ADD 0x8006 +#define GL_MIN 0x8007 +#define GL_MAX 0x8008 +#define GL_FUNC_SUBTRACT 0x800A +#define GL_FUNC_REVERSE_SUBTRACT 0x800B + + /* Texture3D */ +#define GL_TEXTURE_3D 0x806F +#define GL_TEXTURE_WRAP_R 0x8072 +#define GL_MAX_3D_TEXTURE_SIZE 0x8073 + + /* CubeMap */ +#define GL_TEXTURE_CUBE_MAP 0x8513 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A + + /* PolygonMode */ +#define GL_POINT 0x1B00 +#define GL_LINE 0x1B01 +#define GL_FILL 0x1B02 + + /* PolygonOffset for GL_LINE */ +#define GL_POLYGON_OFFSET_LINE 0x2A02 + + /* Filter Control */ +#define GL_TEXTURE_FILTER_CONTROL 0x8500 +#define GL_TEXTURE_LOD_BIAS 0x8501 +#define GL_TEXTURE_MIN_LOD 0x813A +#define GL_TEXTURE_MAX_LOD 0x813B +#define GL_TEXTURE_MAX_LEVEL 0x813D +#define GL_TEXTURE_BORDER_COLOR 0x1004 + + /* depth/shadow */ +#define GL_NONE 0x0 +#define GL_DEPTH_TEXTURE_MODE_ARB 0x884B +#define GL_TEXTURE_COMPARE_MODE_ARB 0x884C +#define GL_TEXTURE_COMPARE_FUNC_ARB 0x884D +#define GL_COMPARE_R_TO_TEXTURE_ARB 0x884E + + /* Wrap modes */ +#define GL_CLAMP 0x2900 +#define GL_MIRRORED_REPEAT 0x8370 +#define GL_MIRROR_CLAMP_EXT 0x8742 +#define GL_MIRROR_CLAMP_TO_EDGE_EXT 0x8743 +#define GL_MIRROR_CLAMP_TO_BORDER_EXT 0x8912 +#define GL_CLAMP_TO_BORDER 0x812D + + /* Fog Coordinate Source */ +#define GL_FOG_COORDINATE_SOURCE 0x8450 +#define GL_FOG_COORDINATE 0x8451 +#define GL_FRAGMENT_DEPTH 0x8452 + + /* Fragment Control TXP */ +#define GL_FRAGMENT_PROGRAM_CONTROL_CONTROLTXP_SCE 0x8453 + + /* Gets */ +#define GL_MODELVIEW_MATRIX 0x0BA6 +#define GL_TEXTURE_MATRIX 0x0BA8 +#define GL_PROJECTION_MATRIX 0x0BA7 +#define GL_MAX_TEXTURE_IMAGE_UNITS_ARB 0x8872 + + + /* Surface targets */ +#define GL_MAX_DRAW_BUFFERS_ATI 0x8824 +#define GL_DRAW_BUFFER0_ATI 0x8825 +#define GL_DRAW_BUFFER1_ATI 0x8826 +#define GL_DRAW_BUFFER2_ATI 0x8827 +#define GL_DRAW_BUFFER3_ATI 0x8828 +#define GL_DRAW_BUFFER4_ATI 0x8829 +#define GL_DRAW_BUFFER5_ATI 0x882A +#define GL_DRAW_BUFFER6_ATI 0x882B +#define GL_DRAW_BUFFER7_ATI 0x882C +#define GL_DRAW_BUFFER8_ATI 0x882D +#define GL_DRAW_BUFFER9_ATI 0x882E +#define GL_DRAW_BUFFER10_ATI 0x882F +#define GL_DRAW_BUFFER11_ATI 0x8830 +#define GL_DRAW_BUFFER12_ATI 0x8831 +#define GL_DRAW_BUFFER13_ATI 0x8832 +#define GL_DRAW_BUFFER14_ATI 0x8833 +#define GL_DRAW_BUFFER15_ATI 0x8834 +#define GL_DRAW_DEPTH_SCE 0x6004 +#define GL_DRAW_STENCIL_SCE 0x6005 + + +#define GL_RGBA8 0x8058 +#define GL_FLOAT_DEPTH_COMPONENT16_SCE 0x6000 +#define GL_FLOAT_DEPTH_COMPONENT32_SCE 0x6001 +#define GL_DEPTH24_STENCIL8_SCE 0x6002 +#define GL_STENCIL8_SCE 0x6003 +#define GL_DEPTH_COMPONENT 0x1902 +#define GL_DEPTH_COMPONENT16 0x81A5 +#define GL_DEPTH_COMPONENT24 0x81A6 +#define GL_DEPTH_COMPONENT32 0x81A7 +#define GL_STENCIL_INDEX 0x1901 + +#define GL_DRAWABLE_BIT_SCE 0x0001 +#define GL_ALLOW_SCAN_OUT_BIT_SCE 0x0002 +#define GL_TEXTURE_READ_BIT_SCE 0x0004 +#define GL_ANTIALIASED_BIT_SCE 0x0008 + + /* VBO & PBO */ +#define GL_ARRAY_BUFFER 0x8892 +#define GL_ELEMENT_ARRAY_BUFFER 0x8893 +#define GL_PIXEL_PACK_BUFFER_ARB 0x88EB +#define GL_PIXEL_UNPACK_BUFFER_ARB 0x88EC +#define GL_STREAM_DRAW 0x88E0 +#define GL_STREAM_READ 0x88E1 +#define GL_STREAM_COPY 0x88E2 +#define GL_STATIC_DRAW 0x88E4 +#define GL_STATIC_READ 0x88E5 +#define GL_STATIC_COPY 0x88E6 +#define GL_DYNAMIC_DRAW 0x88E8 +#define GL_DYNAMIC_READ 0x88E9 +#define GL_DYNAMIC_COPY 0x88EA +#define GL_SYSTEM_DRAW 0x6020 + + /* Map/Unmap */ +#define GL_READ_ONLY 0x88B8 +#define GL_WRITE_ONLY 0x88B9 +#define GL_READ_WRITE 0x88BA + + /* VSYNC */ +#define GL_VSYNC_SCE 0x6006 + +#define GL_TEXTURE_GAMMA_REMAP_R_SCE 0x6010 +#define GL_TEXTURE_GAMMA_REMAP_G_SCE 0x6011 +#define GL_TEXTURE_GAMMA_REMAP_B_SCE 0x6012 +#define GL_TEXTURE_GAMMA_REMAP_A_SCE 0x6013 + +#define GL_SHADER_SRGB_REMAP_SCE 0x6014 + +#define GL_DIVIDE_SCE 0x6015 +#define GL_MODULO_SCE 0x6016 + +#define GL_TEXTURE_FROM_VERTEX_PROGRAM_SCE 0x6017 + + /* Primitive restart */ +#define GL_PRIMITIVE_RESTART_NV 0x8558 + + /* Anisotropic filtering */ +#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE +#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF + + /* Sync */ +#define GL_ALL_COMPLETED_NV 0x84F2 +#define GL_FENCE_STATUS_NV 0x84F3 +#define GL_FENCE_CONDITION_NV 0x84F4 + + /* User clip planes */ +#define GL_MAX_CLIP_PLANES 0x0D32 +#define GL_CLIP_PLANE0 0x3000 +#define GL_CLIP_PLANE1 0x3001 +#define GL_CLIP_PLANE2 0x3002 +#define GL_CLIP_PLANE3 0x3003 +#define GL_CLIP_PLANE4 0x3004 +#define GL_CLIP_PLANE5 0x3005 + + /* Point Sprites */ +#define GL_POINT_SPRITE_OES 0x8861 +#define GL_COORD_REPLACE_OES 0x8862 +#define GL_VERTEX_PROGRAM_POINT_SIZE_ARB 0x8642 + + /* Framebuffer object */ +#define GL_INVALID_FRAMEBUFFER_OPERATION_OES 0x0506 +#define GL_MAX_RENDERBUFFER_SIZE_OES 0x84E8 +#define GL_FRAMEBUFFER_BINDING_OES 0x8CA6 +#define GL_RENDERBUFFER_BINDING_OES 0x8CA7 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_OES 0x8CD0 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_OES 0x8CD1 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_OES 0x8CD2 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_OES 0x8CD3 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT 0x8CD4 +#define GL_FRAMEBUFFER_COMPLETE_OES 0x8CD5 +#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES 0x8CD6 +#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_OES 0x8CD7 +#define GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_OES 0x8CD8 +#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_OES 0x8CD9 +#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_OES 0x8CDA +#define GL_FRAMEBUFFER_UNSUPPORTED_OES 0x8CDD +#define GL_MAX_COLOR_ATTACHMENTS_OES 0x8CDF +#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0 +#define GL_COLOR_ATTACHMENT1_EXT 0x8CE1 +#define GL_COLOR_ATTACHMENT2_EXT 0x8CE2 +#define GL_COLOR_ATTACHMENT3_EXT 0x8CE3 +#define GL_COLOR_ATTACHMENT4_EXT 0x8CE4 +#define GL_COLOR_ATTACHMENT5_EXT 0x8CE5 +#define GL_COLOR_ATTACHMENT6_EXT 0x8CE6 +#define GL_COLOR_ATTACHMENT7_EXT 0x8CE7 +#define GL_COLOR_ATTACHMENT8_EXT 0x8CE8 +#define GL_COLOR_ATTACHMENT9_EXT 0x8CE9 +#define GL_COLOR_ATTACHMENT10_EXT 0x8CEA +#define GL_COLOR_ATTACHMENT11_EXT 0x8CEB +#define GL_COLOR_ATTACHMENT12_EXT 0x8CEC +#define GL_COLOR_ATTACHMENT13_EXT 0x8CED +#define GL_COLOR_ATTACHMENT14_EXT 0x8CEE +#define GL_COLOR_ATTACHMENT15_EXT 0x8CEF +#define GL_DEPTH_ATTACHMENT_OES 0x8D00 +#define GL_STENCIL_ATTACHMENT_OES 0x8D20 +#define GL_FRAMEBUFFER_OES 0x8D40 +#define GL_RENDERBUFFER_OES 0x8D41 +#define GL_RENDERBUFFER_WIDTH_OES 0x8D42 +#define GL_RENDERBUFFER_HEIGHT_OES 0x8D43 +#define GL_RENDERBUFFER_INTERNAL_FORMAT_OES 0x8D44 +#define GL_STENCIL_INDEX_OES 0x8D45 +#define GL_STENCIL_INDEX4_OES 0x8D47 +#define GL_STENCIL_INDEX8_OES 0x8D48 + + /* multiple render target blend enable enums */ +#define GL_BLEND_MRT0_SCE GL_COLOR_ATTACHMENT0_EXT +#define GL_BLEND_MRT1_SCE GL_COLOR_ATTACHMENT1_EXT +#define GL_BLEND_MRT2_SCE GL_COLOR_ATTACHMENT2_EXT +#define GL_BLEND_MRT3_SCE GL_COLOR_ATTACHMENT3_EXT + + /* Texture usage hint */ +#define GL_TEXTURE_ALLOCATION_HINT_SCE 0x6018 +#define GL_TEXTURE_TILED_GPU_SCE 0x6019 +#define GL_TEXTURE_LINEAR_GPU_SCE 0x601A +#define GL_TEXTURE_SWIZZLED_GPU_SCE 0x601B +#define GL_TEXTURE_LINEAR_SYSTEM_SCE 0x601C +#define GL_TEXTURE_SWIZZLED_SYSTEM_SCE 0x601D + + /* Occlusion query & Conditional rendering */ +#define GL_SAMPLES_PASSED_ARB 0x8914 +#define GL_QUERY_COUNTER_BITS_ARB 0x8864 +#define GL_CURRENT_QUERY_ARB 0x8865 +#define GL_QUERY_RESULT_ARB 0x8866 +#define GL_QUERY_RESULT_AVAILABLE_ARB 0x8867 + + /* Two-sided stencil, Stencil wrap */ +#define GL_STENCIL_TEST_TWO_SIDE_EXT 0x8910 +#define GL_INCR_WRAP 0x8507 +#define GL_DECR_WRAP 0x8508 + + /* depth clamp */ +#define GL_DEPTH_CLAMP_NV 0x864F + + /* 32-bit 3-component attributes (11/11/10) */ +#define GL_FIXED_11_11_10_SCE 0x6020 + + /* Anti-aliasing */ +#define GL_REDUCE_DST_COLOR_SCE 0x6021 +#define GL_TEXTURE_MULTISAMPLING_HINT_SCE 0x6022 +#define GL_FRAMEBUFFER_MULTISAMPLING_MODE_SCE 0x6023 + +#define GL_MULTISAMPLING_NONE_SCE 0x6030 +#define GL_MULTISAMPLING_2X_DIAGONAL_CENTERED_SCE 0x6031 +#define GL_MULTISAMPLING_4X_SQUARE_CENTERED_SCE 0x6032 +#define GL_MULTISAMPLING_4X_SQUARE_ROTATED_SCE 0x6033 + + /* Texture reference buffer */ +#define GL_TEXTURE_REFERENCE_BUFFER_SCE 0x6040 +#define GL_BUFFER_SIZE 0x8764 +#define GL_BUFFER_PITCH_SCE 0x6041 + + /******************************************************************************/ + GLAPI void APIENTRY glBlendEquation( GLenum mode ); + GLAPI void APIENTRY glBlendEquationSeparate( GLenum modeRGB, GLenum modeAlpha ); + GLAPI void APIENTRY glBlendFuncSeparate( GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha ); + GLAPI void APIENTRY glBlendColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha ); + GLAPI void APIENTRY glNormal3fv( const GLfloat* v ); + GLAPI void APIENTRY glColor4fv( const GLfloat* v ); + GLAPI void APIENTRY glColor4ub( GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha ); + GLAPI void APIENTRY glGetBooleanv( GLenum pname, GLboolean* params ); + GLAPI void APIENTRY glGetFloatv( GLenum pname, GLfloat* params ); + GLAPI void APIENTRY glTexParameterfv( GLenum target, GLenum pname, const GLfloat* params ); + GLAPI void APIENTRY glTexParameteri( GLenum target, GLenum pname, GLint param ); + GLAPI void APIENTRY glTexParameteriv( GLenum target, GLenum pname, const GLint* params ); + GLAPI void APIENTRY glTexSubImage3D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels ); + + /* VBO & PBO */ + GLAPI void APIENTRY glBindBuffer( GLenum target, GLuint name ); + GLAPI void APIENTRY glDeleteBuffers( GLsizei n, const GLuint *buffers ); + GLAPI void APIENTRY glGenBuffers( GLsizei n, GLuint *buffers ); + GLAPI void APIENTRY glBufferData( GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage ); + GLAPI void APIENTRY glBufferSubData( GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data ); + GLAPI void APIENTRY glGetBufferParameteriv( GLenum target, GLenum pname, GLint *params ); + /* VBO & PBO map/unmap */ + GLAPI GLvoid* APIENTRY glMapBuffer( GLenum target, GLenum access ); + GLAPI GLboolean APIENTRY glUnmapBuffer( GLenum target ); + + /* Sync */ + GLAPI void APIENTRY glDeleteFencesNV( GLsizei n, const GLuint *fences ); + GLAPI void APIENTRY glGenFencesNV( GLsizei n, GLuint *fences ); + GLAPI GLboolean APIENTRY glIsFenceNV( GLuint fence ); + GLAPI GLboolean APIENTRY glTestFenceNV( GLuint fence ); + GLAPI void APIENTRY glGetFenceivNV( GLuint fence, GLenum pname, GLint *params ); + GLAPI void APIENTRY glFinishFenceNV( GLuint fence ); + GLAPI void APIENTRY glSetFenceNV( GLuint fence, GLenum condition ); + + /* Framebuffer object */ + GLAPI GLboolean APIENTRY glIsRenderbufferOES( GLuint ); + GLAPI void APIENTRY glBindRenderbufferOES( GLenum, GLuint ); + GLAPI void APIENTRY glDeleteRenderbuffersOES( GLsizei, const GLuint * ); + GLAPI void APIENTRY glGenRenderbuffersOES( GLsizei, GLuint * ); + GLAPI void APIENTRY glRenderbufferStorageOES( GLenum, GLenum, GLsizei, GLsizei ); + GLAPI void APIENTRY glGetRenderbufferParameterivOES( GLenum, GLenum, GLint * ); + GLAPI GLboolean APIENTRY glIsFramebufferOES( GLuint ); + GLAPI void APIENTRY glBindFramebufferOES( GLenum, GLuint ); + GLAPI void APIENTRY glDeleteFramebuffersOES( GLsizei, const GLuint * ); + GLAPI void APIENTRY glGenFramebuffersOES( GLsizei, GLuint * ); + GLAPI GLenum APIENTRY glCheckFramebufferStatusOES( GLenum ); + GLAPI void APIENTRY glFramebufferTexture2DOES( GLenum, GLenum, GLenum, GLuint, GLint ); + GLAPI void APIENTRY glFramebufferRenderbufferOES( GLenum, GLenum, GLenum, GLuint ); + GLAPI void APIENTRY glGetFramebufferAttachmentParameterivOES( GLenum, GLenum, GLenum, GLint * ); + GLAPI void APIENTRY glGenerateMipmapOES( GLenum ); + + /* Texture Reference */ + GLAPI void APIENTRY glTextureReferenceSCE( GLenum target, GLuint levels, GLuint baseWidth, GLuint baseHeight, GLuint baseDepth, GLenum internalFormat, GLuint pitch, GLintptr offset ); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/console/rgl/include/export/RGL/export.h b/console/rgl/include/export/RGL/export.h new file mode 100644 index 0000000000..3f52f58954 --- /dev/null +++ b/console/rgl/include/export/RGL/export.h @@ -0,0 +1,7 @@ +#ifndef _RGL_EXPORT_DEFINE_H +#define _RGL_EXPORT_DEFINE_H + +#define PSGL_EXPORT +#define RGL_EXPORT + +#endif diff --git a/console/rgl/include/export/RGL/rgl.h b/console/rgl/include/export/RGL/rgl.h new file mode 100644 index 0000000000..197cd2729e --- /dev/null +++ b/console/rgl/include/export/RGL/rgl.h @@ -0,0 +1,366 @@ +#ifndef _RGL_EXPORT_H +#define _RGL_EXPORT_H + +#include +#include "export.h" +#include +#include +#include +#include + +#include +#include + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + + typedef struct PSGLdevice PSGLdevice; + typedef struct PSGLcontext PSGLcontext; + + typedef enum PSGLtvStandard + { + PSGL_TV_STANDARD_NONE, + PSGL_TV_STANDARD_NTSC_M, + PSGL_TV_STANDARD_NTSC_J, + PSGL_TV_STANDARD_PAL_M, + PSGL_TV_STANDARD_PAL_B, + PSGL_TV_STANDARD_PAL_D, + PSGL_TV_STANDARD_PAL_G, + PSGL_TV_STANDARD_PAL_H, + PSGL_TV_STANDARD_PAL_I, + PSGL_TV_STANDARD_PAL_N, + PSGL_TV_STANDARD_PAL_NC, + PSGL_TV_STANDARD_HD480I, + PSGL_TV_STANDARD_HD480P, + PSGL_TV_STANDARD_HD576I, + PSGL_TV_STANDARD_HD576P, + PSGL_TV_STANDARD_HD720P, + PSGL_TV_STANDARD_HD1080I, + PSGL_TV_STANDARD_HD1080P, + PSGL_TV_STANDARD_1280x720_ON_VESA_1280x768 = 128, + PSGL_TV_STANDARD_1280x720_ON_VESA_1280x1024, + PSGL_TV_STANDARD_1920x1080_ON_VESA_1920x1200, + } PSGLtvStandard; + +#define RGL_TV_STANDARD_NONE (PSGL_TV_STANDARD_NONE) +#define RGL_TV_STANDARD_NTSC_M 1 +#define RGL_TV_STANDARD_NTSC_J 2 +#define RGL_TV_STANDARD_PAL_M 3 +#define RGL_TV_STANDARD_PAL_B 4 +#define RGL_TV_STANDARD_PAL_D 5 +#define RGL_TV_STANDARD_PAL_G 6 +#define RGL_TV_STANDARD_PAL_H 7 +#define RGL_TV_STANDARD_PAL_I 8 +#define RGL_TV_STANDARD_PAL_N 9 +#define RGL_TV_STANDARD_PAL_NC 10 +#define RGL_TV_STANDARD_HD480I 11 +#define RGL_TV_STANDARD_HD480P 12 +#define RGL_TV_STANDARD_HD576I 13 +#define RGL_TV_STANDARD_HD576P 14 +#define RGL_TV_STANDARD_HD720P 15 +#define RGL_TV_STANDARD_HD1080I 16 +#define RGL_TV_STANDARD_HD1080P 17 +#define RGL_TV_STANDARD_1280x720_ON_VESA_1280x768 128 +#define RGL_TV_STANDARD_1280x720_ON_VESA_1280x1024 129 +#define RGL_TV_STANDARD_1920x1080_ON_VESA_1920x1200 130 + + typedef enum PSGLbufferingMode + { + PSGL_BUFFERING_MODE_SINGLE = 1, + PSGL_BUFFERING_MODE_DOUBLE = 2, + PSGL_BUFFERING_MODE_TRIPLE = 3, + } PSGLbufferingMode; + +/* spoof as PSGL */ +#define RGL_BUFFERING_MODE_SINGLE (PSGL_BUFFERING_MODE_SINGLE) +#define RGL_BUFFERING_MODE_DOUBLE (PSGL_BUFFERING_MODE_DOUBLE) +#define RGL_BUFFERING_MODE_TRIPLE (PSGL_BUFFERING_MODE_TRIPLE) + + typedef enum PSGLdeviceConnector + { + PSGL_DEVICE_CONNECTOR_NONE, + PSGL_DEVICE_CONNECTOR_VGA, + PSGL_DEVICE_CONNECTOR_DVI, + PSGL_DEVICE_CONNECTOR_HDMI, + PSGL_DEVICE_CONNECTOR_COMPOSITE, + PSGL_DEVICE_CONNECTOR_SVIDEO, + PSGL_DEVICE_CONNECTOR_COMPONENT, + } PSGLdeviceConnector; + +#define RGL_DEVICE_CONNECTOR_NONE (PSGL_DEVICE_CONNECTOR_NONE) +#define RGL_DEVICE_CONNECTOR_VGA 1 +#define RGL_DEVICE_CONNECTOR_DVI 2 +#define RGL_DEVICE_CONNECTOR_HDMI 3 +#define RGL_DEVICE_CONNECTOR_COMPOSITE 4 +#define RGL_DEVICE_CONNECTOR_SVIDEO 5 +#define RGL_DEVICE_CONNECTOR_COMPONENT 6 + + + + typedef enum RescRatioMode + { + RESC_RATIO_MODE_FULLSCREEN, + RESC_RATIO_MODE_LETTERBOX, // default + RESC_RATIO_MODE_PANSCAN, + } RescRatioMode; + + typedef enum RescPalTemporalMode + { + RESC_PAL_TEMPORAL_MODE_50_NONE, // default - no conversion + RESC_PAL_TEMPORAL_MODE_60_DROP, + RESC_PAL_TEMPORAL_MODE_60_INTERPOLATE, + RESC_PAL_TEMPORAL_MODE_60_INTERPOLATE_30_DROP, + RESC_PAL_TEMPORAL_MODE_60_INTERPOLATE_DROP_FLEXIBLE, + } RescPalTemporalMode; + + typedef enum RescInterlaceMode + { + RESC_INTERLACE_MODE_NORMAL_BILINEAR, + RESC_INTERLACE_MODE_INTERLACE_FILTER, + } RescInterlaceMode; + +#define PSGL_DEVICE_PARAMETERS_COLOR_FORMAT 0x0001 +#define PSGL_DEVICE_PARAMETERS_DEPTH_FORMAT 0x0002 +#define PSGL_DEVICE_PARAMETERS_MULTISAMPLING_MODE 0x0004 +#define PSGL_DEVICE_PARAMETERS_TV_STANDARD 0x0008 +#define PSGL_DEVICE_PARAMETERS_CONNECTOR 0x0010 +#define PSGL_DEVICE_PARAMETERS_BUFFERING_MODE 0x0020 +#define PSGL_DEVICE_PARAMETERS_WIDTH_HEIGHT 0x0040 +#define PSGL_DEVICE_PARAMETERS_RESC_RENDER_WIDTH_HEIGHT 0x0080 +#define PSGL_DEVICE_PARAMETERS_RESC_RATIO_MODE 0x0100 +#define PSGL_DEVICE_PARAMETERS_RESC_PAL_TEMPORAL_MODE 0x0200 +#define PSGL_DEVICE_PARAMETERS_RESC_INTERLACE_MODE 0x0400 +#define PSGL_DEVICE_PARAMETERS_RESC_ADJUST_ASPECT_RATIO 0x0800 + +/* spoof as PSGL */ + +#define RGL_DEVICE_PARAMETERS_COLOR_FORMAT 0x0001 +#define RGL_DEVICE_PARAMETERS_DEPTH_FORMAT 0x0002 +#define RGL_DEVICE_PARAMETERS_MULTISAMPLING_MODE 0x0004 +#define RGL_DEVICE_PARAMETERS_TV_STANDARD 0x0008 +#define RGL_DEVICE_PARAMETERS_CONNECTOR 0x0010 +#define RGL_DEVICE_PARAMETERS_BUFFERING_MODE 0x0020 +#define RGL_DEVICE_PARAMETERS_WIDTH_HEIGHT 0x0040 +#define RGL_DEVICE_PARAMETERS_RESC_RENDER_WIDTH_HEIGHT 0x0080 +#define RGL_DEVICE_PARAMETERS_RESC_RATIO_MODE 0x0100 +#define RGL_DEVICE_PARAMETERS_RESC_PAL_TEMPORAL_MODE 0x0200 +#define RGL_DEVICE_PARAMETERS_RESC_INTERLACE_MODE 0x0400 +#define RGL_DEVICE_PARAMETERS_RESC_ADJUST_ASPECT_RATIO 0x0800 + + + // mask for validation +#define PSGL_VALIDATE_NONE 0x00000000 +#define PSGL_VALIDATE_FRAMEBUFFER 0x00000001 +#define PSGL_VALIDATE_TEXTURES_USED 0x00000002 +#define PSGL_VALIDATE_VERTEX_PROGRAM 0x00000004 +#define PSGL_VALIDATE_VERTEX_CONSTANTS 0x00000008 +#define PSGL_VALIDATE_VERTEX_TEXTURES_USED 0x00000010 +#define PSGL_VALIDATE_FFX_VERTEX_PROGRAM 0x00000020 +#define PSGL_VALIDATE_FRAGMENT_PROGRAM 0x00000040 +#define PSGL_VALIDATE_FFX_FRAGMENT_PROGRAM 0x00000080 +#define PSGL_VALIDATE_FRAGMENT_SHARED_CONSTANTS 0x00000100 +#define PSGL_VALIDATE_VIEWPORT 0x00000200 +#define PSGL_VALIDATE_DEPTH_TEST 0x00000800 +#define PSGL_VALIDATE_WRITE_MASK 0x00001000 +#define PSGL_VALIDATE_STENCIL_TEST 0x00002000 +#define PSGL_VALIDATE_STENCIL_OP_AND_MASK 0x00004000 +#define PSGL_VALIDATE_SCISSOR_BOX 0x00008000 +#define PSGL_VALIDATE_FACE_CULL 0x00010000 +#define PSGL_VALIDATE_BLENDING 0x00020000 +#define PSGL_VALIDATE_POINT_RASTER 0x00040000 +#define PSGL_VALIDATE_LINE_RASTER 0x00080000 +#define PSGL_VALIDATE_POLYGON_OFFSET 0x00100000 +#define PSGL_VALIDATE_SHADE_MODEL 0x00200000 +#define PSGL_VALIDATE_LOGIC_OP 0x00400000 +#define PSGL_VALIDATE_MULTISAMPLING 0x00800000 +#define PSGL_VALIDATE_POLYGON_MODE 0x01000000 +#define PSGL_VALIDATE_PRIMITIVE_RESTART 0x02000000 +#define PSGL_VALIDATE_CLIP_PLANES 0x04000000 +#define PSGL_VALIDATE_SHADER_SRGB_REMAP 0x08000000 +#define PSGL_VALIDATE_POINT_SPRITE 0x10000000 +#define PSGL_VALIDATE_TWO_SIDE_COLOR 0x20000000 +#define PSGL_VALIDATE_ALL 0x3FFFFFFF + +/* spoof as PSGL */ +#define RGL_VALIDATE_NONE 0x00000000 +#define RGL_VALIDATE_FRAMEBUFFER 0x00000001 +#define RGL_VALIDATE_TEXTURES_USED 0x00000002 +#define RGL_VALIDATE_VERTEX_PROGRAM 0x00000004 +#define RGL_VALIDATE_VERTEX_CONSTANTS 0x00000008 +#define RGL_VALIDATE_VERTEX_TEXTURES_USED 0x00000010 +#define RGL_VALIDATE_FFX_VERTEX_PROGRAM 0x00000020 +#define RGL_VALIDATE_FRAGMENT_PROGRAM 0x00000040 +#define RGL_VALIDATE_FFX_FRAGMENT_PROGRAM 0x00000080 +#define RGL_VALIDATE_FRAGMENT_SHARED_CONSTANTS 0x00000100 +#define RGL_VALIDATE_VIEWPORT 0x00000200 +#define RGL_VALIDATE_DEPTH_TEST 0x00000800 +#define RGL_VALIDATE_WRITE_MASK 0x00001000 +#define RGL_VALIDATE_STENCIL_TEST 0x00002000 +#define RGL_VALIDATE_STENCIL_OP_AND_MASK 0x00004000 +#define RGL_VALIDATE_SCISSOR_BOX 0x00008000 +#define RGL_VALIDATE_FACE_CULL 0x00010000 +#define RGL_VALIDATE_BLENDING 0x00020000 +#define RGL_VALIDATE_POINT_RASTER 0x00040000 +#define RGL_VALIDATE_LINE_RASTER 0x00080000 +#define RGL_VALIDATE_POLYGON_OFFSET 0x00100000 +#define RGL_VALIDATE_SHADE_MODEL 0x00200000 +#define RGL_VALIDATE_LOGIC_OP 0x00400000 +#define RGL_VALIDATE_MULTISAMPLING 0x00800000 +#define RGL_VALIDATE_POLYGON_MODE 0x01000000 +#define RGL_VALIDATE_PRIMITIVE_RESTART 0x02000000 +#define RGL_VALIDATE_CLIP_PLANES 0x04000000 +#define RGL_VALIDATE_SHADER_SRGB_REMAP 0x08000000 +#define RGL_VALIDATE_POINT_SPRITE 0x10000000 +#define RGL_VALIDATE_TWO_SIDE_COLOR 0x20000000 +#define RGL_VALIDATE_ALL 0x3FFFFFFF + +#define RGLdevice PSGLdevice +#define RGLdeviceParameters PSGLdeviceParameters +#define RGLcontext PSGLcontext + + typedef struct + { + GLuint enable; + GLenum colorFormat; + GLenum depthFormat; + GLenum multisamplingMode; + PSGLtvStandard TVStandard; + PSGLdeviceConnector connector; + PSGLbufferingMode bufferingMode; + GLuint width; // dimensions of display device (scanout buffer) + GLuint height; + + // dimensions of render buffer. Only set explicitly if the render target buffer + // needs to be different size than display scanout buffer (resolution scaling required). + // These can only be set if PSGL_DEVICE_PARAMETERS_RESC_RENDER_WIDTH_HEIGHT is set in the "enable" mask, + // otherwise, render buffer dimensions are set to device dimensions (width/height). + GLuint renderWidth; + GLuint renderHeight; + + RescRatioMode rescRatioMode; // RESC aspect ratio rescaling mode: full screen, letterbox, or pan & scan + RescPalTemporalMode rescPalTemporalMode; // RESC pal frame rate conversion mode: none, drop frame, interpolate + RescInterlaceMode rescInterlaceMode; // RESC interlace filter mode: normal bilinear or use the anti-flicker interlace filter + + // horizontal and vertical scaling to adjust for the difference in overscan rates for each SD/HD mode or TV + GLfloat horizontalScale; + GLfloat verticalScale; + } PSGLdeviceParameters; + + +#define PSGL_INIT_MAX_SPUS 0x0001 +#define PSGL_INIT_INITIALIZE_SPUS 0x0002 +#define PSGL_INIT_PERSISTENT_MEMORY_SIZE 0x0004 +#define PSGL_INIT_TRANSIENT_MEMORY_SIZE 0x0008 +#define PSGL_INIT_ERROR_CONSOLE 0x0010 +#define PSGL_INIT_FIFO_SIZE 0x0020 +#define PSGL_INIT_HOST_MEMORY_SIZE 0x0040 +#define PSGL_INIT_USE_PMQUERIES 0x0080 + +/* spoof as PSGL */ +#define RGL_INIT_MAX_SPUS 0x0001 +#define RGL_INIT_INITIALIZE_SPUS 0x0002 +#define RGL_INIT_PERSISTENT_MEMORY_SIZE 0x0004 +#define RGL_INIT_TRANSIENT_MEMORY_SIZE 0x0008 +#define RGL_INIT_ERROR_CONSOLE 0x0010 +#define RGL_INIT_FIFO_SIZE 0x0020 +#define RGL_INIT_HOST_MEMORY_SIZE 0x0040 +#define RGL_INIT_USE_PMQUERIES 0x0080 + + typedef struct PSGLinitOptions + { + GLuint enable; // bitfield of options to set + GLuint maxSPUs; + GLboolean initializeSPUs; + GLuint persistentMemorySize; + GLuint transientMemorySize; + int errorConsole; + GLuint fifoSize; + GLuint hostMemorySize; + } PSGLinitOptions; + +#define RGLinitOptions PSGLinitOptions + + typedef void*( *PSGLmallocFunc )( size_t LSize ); // expected to return 16-byte aligned + typedef void*( *PSGLmemalignFunc )( size_t align, size_t LSize ); + typedef void*( *PSGLreallocFunc )( void* LBlock, size_t LSize ); + typedef void( *PSGLfreeFunc )( void* LBlock ); + + extern PSGL_EXPORT void psglInit( PSGLinitOptions* options ); + extern PSGL_EXPORT void psglExit(); + + PSGL_EXPORT PSGLdevice* psglCreateDeviceAuto( GLenum colorFormat, GLenum depthFormat, GLenum multisamplingMode ); + PSGL_EXPORT PSGLdevice* psglCreateDeviceExtended( const PSGLdeviceParameters *parameters ); + PSGL_EXPORT GLfloat psglGetDeviceAspectRatio( const PSGLdevice * device ); + PSGL_EXPORT void psglGetDeviceDimensions( const PSGLdevice * device, GLuint *width, GLuint *height ); + PSGL_EXPORT void psglGetRenderBufferDimensions( const PSGLdevice * device, GLuint *width, GLuint *height ); + PSGL_EXPORT void psglDestroyDevice( PSGLdevice* device ); + + PSGL_EXPORT void psglMakeCurrent( PSGLcontext* context, PSGLdevice* device ); + PSGL_EXPORT PSGLcontext* psglCreateContext(); + PSGL_EXPORT void psglDestroyContext( PSGLcontext* LContext ); + PSGL_EXPORT void psglResetCurrentContext(); + PSGL_EXPORT PSGLcontext* psglGetCurrentContext(); + PSGL_EXPORT PSGLdevice* psglGetCurrentDevice(); + PSGL_EXPORT void psglSwap( void ); + + PSGL_EXPORT void psglLoadShaderLibrary( const char *filename ); + + PSGL_EXPORT void psglSetFlipHandler( void( *handler )( const GLuint head ) ); + PSGL_EXPORT void psglSetVBlankHandler( void( *handler )( const GLuint head ) ); + + PSGL_EXPORT GLboolean psglSetAllocatorFuncs( PSGLmallocFunc mallocFunc, PSGLmemalignFunc memalignFunc, PSGLreallocFunc reallocFunc, PSGLfreeFunc freeFunc ); + + PSGL_EXPORT void psglAddressToOffset(const void *address, GLuint *offset); + PSGL_EXPORT void psglSetVertexProgramRegister(GLuint reg, const void * __restrict value); + PSGL_EXPORT void psglSetVertexProgramRegisterBlock(GLuint reg, GLuint count, const void * __restrict value); + PSGL_EXPORT void psglSetVertexProgramTransformBranchBits(GLuint values); + PSGL_EXPORT void psglSetVertexProgramConfiguration(const CellCgbVertexProgramConfiguration *conf, const void *ucodeStorageAddress); + + PSGL_EXPORT void psglSetFragmentProgramEmbeddedConstant(const GLuint offset, const GLfloat *value, const GLuint sizeInWords); + PSGL_EXPORT void psglSetFragmentProgramConfiguration(const CellCgbFragmentProgramConfiguration *conf); + + PSGL_EXPORT void psglSetFragmentProgramEmbeddedConstantMemoryLocation(const GLuint offset, const GLfloat *value, const GLuint sizeInWords, bool inLocalMemory); + PSGL_EXPORT void psglSetFragmentProgramConfigurationMemoryLocation(const CellCgbFragmentProgramConfiguration *conf, bool inLocalMemory); + + PSGL_EXPORT void psglSetUserClipPlanes( const GLuint userClipControlMask, const GLuint vertexOutputAttributeMask ); + + static inline PSGL_EXPORT void psglRescAdjustAspectRatio( const float horizontalScale, const float verticalScale ) + { cellRescAdjustAspectRatio( horizontalScale, verticalScale ); } + +#define PSGL_ADD_RETURN true +#define PSGL_DO_NOT_ADD_RETURN false + +#define PSGL_STALL true +#define PSGL_DO_NOT_STALL false + + // This funciton validates states specified in mask + // mask - specify states to be validated + // returns mask of states which was NOT validated + PSGL_EXPORT GLuint psglValidateStates( GLuint mask ); + // This function invalidates states specified in mask + // mask - specify states to be invalidateted + PSGL_EXPORT void psglInvalidateStates( GLuint mask ); + + // This funciton validates attributes with index buffer at specified offset + // indices - specify offset to index buffer object + // isMain - true will be set if index buffer object is on main memory, false for local memory + // returns RSX offset of index buffer + PSGL_EXPORT GLuint psglValidateAttributes( const GLvoid* indices, GLboolean *isMain ); + // This function invalidates all attributes + PSGL_EXPORT void psglInvalidateAttributes(); + + /* hw cursor error code */ +#define PSGL_HW_CURSOR_OK CELL_OK +#define PSGL_HW_CURSOR_ERROR_FAILURE CELL_GCM_ERROR_FAILURE +#define PSGL_HW_CURSOR_ERROR_INVALID_VALUE CELL_GCM_ERROR_INVALID_VALUE + + +#ifdef __cplusplus +} // Close scope of 'extern "C"' declaration which encloses file. +#endif + +#endif /* RGL_EXPORT_H */ diff --git a/console/rgl/ps3/base.hpp b/console/rgl/ps3/base.hpp deleted file mode 100644 index 2a103556d5..0000000000 --- a/console/rgl/ps3/base.hpp +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef _BASE_H_ -#define _BASE_H_ - -#include -#include -#include - -namespace RGL -{ - class Base - { - public: - void * operator new( size_t size ) { return malloc( size ); } - void * operator new( size_t /*size*/, void *p ) { return p; } - void operator delete( void *ptr ) { return free( ptr ); } - void operator delete( void * /*ptr*/, void * /*p*/ ) { }}; - - template class Vector: public Base - { - T* array; - unsigned int count; - unsigned int capacity; - unsigned int increment; - public: - Vector(): array( 0 ), count( 0 ), capacity( 0 ), increment( 4 ) {} - ~Vector() { clear(); reallocArray( 0 ); } - - inline unsigned int getCount() { return count; } - - inline void reallocArray( unsigned int newCapacity ) - { - if ( newCapacity == capacity ) return; - if ( newCapacity > capacity ) newCapacity = ( newCapacity > capacity + increment ) ? newCapacity : ( capacity + increment ); - if ( newCapacity == 0 ) - { - free( array ); - array = 0; - } - else array = static_cast( realloc( static_cast( array ), sizeof( T ) * newCapacity ) ); - capacity = newCapacity; - } - - inline void clear() - { - if ( !array ) return; - for ( unsigned int i = 0;i < count;++i )( array + i )->~T(); - count = 0; - } - - inline unsigned int pushBack( const T &element ) - { - if ( count + 1 > capacity ) - reallocArray( count + 1 ); - new(( void * )( array + count ) ) T( element ); - return ++count; - } - - inline unsigned int appendUnique( const T &element ) - { - for ( unsigned int i = 0;i < count;++i ) if ( array[i] == element ) return i; - return pushBack( element ); - } - - inline void removeElement( const T &element ) - { - for ( unsigned int i = count; i > 0; --i ) - { - if ( array[i-1] == element ) - { - remove( i - 1 ); - return; - } - } - } - - inline void remove( unsigned int index ) - { - ( array + index )->~T(); - --count; - if ( count > index ) memmove( array + index, array + index + 1, ( count - index )*sizeof( T ) ); - } - - inline T& operator []( int i ) const { return array[i]; } - }; -} - -#endif diff --git a/console/rgl/ps3/cg.h b/console/rgl/ps3/cg.h deleted file mode 100644 index 2683cacc10..0000000000 --- a/console/rgl/ps3/cg.h +++ /dev/null @@ -1,448 +0,0 @@ -#ifndef _cg_common_h -#define _cg_common_h - -#include -#include - -#include - -#include "rgl.h" -#include "private.h" - -#include - -#define RGL_BOOLEAN_REGISTERS_COUNT 32 -#define VERTEX_PROFILE_INDEX 0 -#define FRAGMENT_PROFILE_INDEX 1 - -#define CGF_OUTPUTFROMH0 0x01 -#define CGF_DEPTHREPLACE 0x02 -#define CGF_PIXELKILL 0x04 - -#define CGPV_MASK 0x03 -#define CGPV_VARYING 0x00 -#define CGPV_UNIFORM 0x01 -#define CGPV_CONSTANT 0x02 -#define CGPV_MIXED 0x03 - -#define CGPF_REFERENCED 0x10 -#define CGPF_SHARED 0x20 -#define CGPF_GLOBAL 0x40 -#define CGP_INTERNAL 0x80 - -#define CGP_INTRINSIC 0x0000 -#define CGP_STRUCTURE 0x100 -#define CGP_ARRAY 0x200 -#define CGP_TYPE_MASK (CGP_STRUCTURE + CGP_ARRAY) - -#define CGP_UNROLLED 0x400 -#define CGP_UNPACKED 0x800 -#define CGP_CONTIGUOUS 0x1000 - -#define CGP_NORMALIZE 0x2000 -#define CGP_RTCREATED 0x4000 - -#define CGP_SCF_BOOL (CG_TYPE_START_ENUM + 1024) -#define CG_BINARY_FORMAT_REVISION 0x00000006 - -#ifdef __cplusplus -extern "C" -{ -#endif - -typedef unsigned int CgBinaryOffset; -typedef CgBinaryOffset CgBinaryEmbeddedConstantOffset; -typedef CgBinaryOffset CgBinaryFloatOffset; -typedef CgBinaryOffset CgBinaryStringOffset; -typedef CgBinaryOffset CgBinaryParameterOffset; - -typedef struct CgBinaryVertexProgram CgBinaryVertexProgram; -typedef struct CgBinaryFragmentProgram CgBinaryFragmentProgram; -typedef struct CgBinaryProgram CgBinaryProgram; - -typedef struct _CGnamedProgram -{ - const char *name; - CGprogram program; - int refCount; -} _CGnamedProgram; - -typedef struct _CGprogramGroup -{ - struct _CGprogramGroup *next; - CGcontext ctx; - unsigned int *constantTable; - unsigned int *stringTable; - unsigned int programCount; - _CGnamedProgram *programs; - int refCount; - bool userCreated; - char *filedata; - char *name; -} _CGprogramGroup; - -typedef struct _CGprogramGroup *CGprogramGroup; - -CGprogramGroup _RGLCgCreateProgramGroup( CGcontext ctx, const char *name, void *ptr, int size ); -CGprogramGroup _RGLCgCreateProgramGroupFromFile( CGcontext ctx, const char *group_file ); -void _RGLCgDestroyProgramGroup( CGprogramGroup group ); - -int _RGLCgGetProgramCount( CGprogramGroup group ); -CGprogram _RGLCgGetProgram( CGprogramGroup group, const char *name ); -int _RGLCgGetProgramIndex( CGprogramGroup group, const char *name ); -CGprogram _RGLCgGetProgramAtIndex( CGprogramGroup group, unsigned int index ); -const char *_RGLCgGetProgramGroupName( CGprogramGroup group ); - -typedef struct _CgParameterTableHeader -{ - unsigned short entryCount; - unsigned short resourceTableOffset; - unsigned short defaultValueIndexTableOffset; - unsigned short defaultValueIndexCount; - unsigned short semanticIndexTableOffset; - unsigned short semanticIndexCount; -} CgParameterTableHeader; - -typedef struct _CgParameterEntry -{ - unsigned int nameOffset; - unsigned short typeIndex; - unsigned short flags; -} CgParameterEntry; - -typedef struct _CgParameterArray -{ - unsigned short arrayType; - unsigned short dimensionCount; - unsigned short dimensions[]; -} CgParameterArray; - -typedef struct _CgParameterStructure -{ - unsigned short memberCount; - unsigned short reserved; -} CgParameterStructure; - -typedef struct _CgParameterResource -{ - unsigned short type; - unsigned short resource; -} CgParameterResource; - -typedef struct _CgParameterSemantic -{ - unsigned short entryIndex; - unsigned short reserved; - unsigned int semanticOffset; -} CgParameterSemantic; - -typedef struct _CgParameterDefaultValue -{ - unsigned short entryIndex; - unsigned short defaultValueIndex; -} CgParameterDefaultValue; - -typedef struct CgProgramHeader -{ - unsigned short profile; - unsigned short compilerVersion; - unsigned int instructionCount; - unsigned int attributeInputMask; - union - { - struct - { - unsigned int instructionSlot; - unsigned int registerCount; - unsigned int attributeOutputMask; - } vertexProgram; - struct - { - unsigned int partialTexType; - unsigned short texcoordInputMask; - unsigned short texcoord2d; - unsigned short texcoordCentroid; - unsigned char registerCount; - unsigned char flags; - } fragmentProgram; - }; -} -CgProgramHeader; - -typedef void( *_cgSetFunction )( struct CgRuntimeParameter* __restrict, const void* __restrict); - -typedef void( *_cgSetArrayIndexFunction )( struct CgRuntimeParameter* __restrict, const void* __restrict, const int index ); - -typedef struct _CgUniform -{ - void *pushBufferPtr; -} _CgUniform; - -typedef struct _CGprogram _CGprogram; - -typedef struct CgRuntimeParameter -{ - _cgSetArrayIndexFunction samplerSetter; - _cgSetArrayIndexFunction setterIndex; - _cgSetArrayIndexFunction settercIndex; - _cgSetArrayIndexFunction setterrIndex; - - void *pushBufferPointer; - const CgParameterEntry *parameterEntry; - _CGprogram *program; - int glType; - CGparameter id; -} CgRuntimeParameter; - -struct _CGprogram -{ - struct _CGprogram* next; - CGprogram id; - struct _CGcontext* parentContext; - void* parentEffect; - bool inLocalMemory; - unsigned int constantPushBufferWordSize; - unsigned int* constantPushBuffer; - void* platformProgram; - void* platformProgramBinary; - unsigned int samplerCount; - unsigned int * samplerIndices; - unsigned int * samplerUnits; - unsigned int controlFlowBools; - CgProgramHeader header; - const char *name; - const void *ucode; - GLuint loadProgramId; - GLuint loadProgramOffset; - int version; - char *parameterResources; - int rtParametersCount; - CgRuntimeParameter *runtimeParameters; - const CgParameterEntry *parametersEntries; - unsigned short *resources; - unsigned short *pushBufferPointers; - int defaultValuesIndexCount; - const CgParameterDefaultValue *defaultValuesIndices; - int defaultValueCount; - const float *defaultValues; - const char *stringTable; - unsigned int **constantPushBufferPointers; - unsigned int *samplerValuesLocation; - void *memoryBlock; - _CGprogramGroup *programGroup; - int programIndexInGroup; - void *runtimeElf; -}; - -typedef struct _CGcontext -{ - struct _CGcontext* next; - CGcontext id; - unsigned int programCount; - struct _CGprogram* programList; - CGenum compileType; - unsigned int controlFlowBoolsSharedMask; - unsigned int controlFlowBoolsShared; - _CGprogram defaultProgram; - CGprogramGroup groupList; - double currentParameterValue[16]; - char currentParameterName[128]; -} _CGcontext; - - -void _RGLCgRaiseError( CGerror error ); -extern void _RGLCgProgramDestroyAll( _CGcontext* c ); -extern void _RGLCgDestroyContextParam( CgRuntimeParameter* p ); -CgRuntimeParameter*_RGLCgCreateParameterInternal( _CGprogram *program, const char* name, CGtype type ); -void _RGLCgProgramErase( _CGprogram* prog ); - -void _cgRaiseInvalidParam( CgRuntimeParameter*p, const void*v ); -void _cgRaiseNotMatrixParam( CgRuntimeParameter*p, const void*v ); -void _cgIgnoreSetParam( CgRuntimeParameter*p, const void*v ); -void _cgRaiseInvalidParamIndex( CgRuntimeParameter*p, const void*v, const int index ); -void _cgRaiseNotMatrixParamIndex( CgRuntimeParameter*p, const void*v, const int index ); -void _cgIgnoreSetParamIndex( CgRuntimeParameter*p, const void*v, const int index ); - -#define CG_IS_CONTEXT(_ctx) _RGLIsName(&_CurrentContext->cgContextNameSpace, (jsName)_ctx) -#define CG_IS_PROGRAM(_program) _RGLIsName(&_CurrentContext->cgProgramNameSpace, (jsName)_program) -#define CG_IS_PARAMETER(_param) _RGLIsName(&_CurrentContext->cgParameterNameSpace, (jsName)(((unsigned int)_param)&CG_PARAMETERMASK)) - -#define CG_PARAMETERSIZE 22 -#define CG_PARAMETERMASK ((1 << CG_PARAMETERSIZE)-1) -#define CG_GETINDEX(param) (int)((unsigned int)(param)>>CG_PARAMETERSIZE) - -static inline bool isMatrix( CGtype type ) -{ - if (( type >= CG_FLOAT1x1 && type <= CG_FLOAT4x4 ) || - ( type >= CG_HALF1x1 && type <= CG_HALF4x4 ) || - ( type >= CG_INT1x1 && type <= CG_INT4x4 ) || - ( type >= CG_BOOL1x1 && type <= CG_BOOL4x4 ) || - ( type >= CG_FIXED1x1 && type <= CG_FIXED4x4 )) - return true; - return false; -} - -unsigned int _RGLCountFloatsInCgType( CGtype type ); -CGbool _cgMatrixDimensions( CGtype type, unsigned int* nrows, unsigned int* ncols ); - -unsigned int _RGLGetTypeRowCount( CGtype parameterType ); -unsigned int _RGLGetTypeColCount( CGtype parameterType ); - -inline static CgRuntimeParameter* _cgGetParamPtr( CGparameter p ) -{ - return ( CgRuntimeParameter* )_RGLGetNamedValue( &_CurrentContext->cgParameterNameSpace, ( jsName )((( unsigned int )p )&CG_PARAMETERMASK ) ); -} - -inline static _CGprogram* _cgGetProgPtr( CGprogram p ) -{ - return ( _CGprogram* )_RGLGetNamedValue( &_CurrentContext->cgProgramNameSpace, ( jsName )p ); -} - -inline static _CGcontext* _cgGetContextPtr( CGcontext c ) -{ - return ( _CGcontext* )_RGLGetNamedValue( &_CurrentContext->cgContextNameSpace, ( jsName )c ); -} - -inline static int _RGLGetSizeofSubArray( const unsigned short *dimensions, unsigned short count ) -{ - int res = 1; - for ( int i = 0;i < count;i++ ) - res *= ( int )( *( dimensions++ ) ); - return res; -} - -inline static CGresource _RGLGetBaseResource( CGresource resource ) -{ - switch ( resource ) - { - case CG_ATTR0: case CG_ATTR1: case CG_ATTR2: case CG_ATTR3: - case CG_ATTR4: case CG_ATTR5: case CG_ATTR6: case CG_ATTR7: - case CG_ATTR8: case CG_ATTR9: case CG_ATTR10: case CG_ATTR11: - case CG_ATTR12: case CG_ATTR13: case CG_ATTR14: case CG_ATTR15: - return CG_ATTR0; - case CG_HPOS: - return CG_HPOS; - case CG_COL0: case CG_COL1: case CG_COL2: case CG_COL3: - return CG_COL0; - case CG_TEXCOORD0: case CG_TEXCOORD1: case CG_TEXCOORD2: case CG_TEXCOORD3: - case CG_TEXCOORD4: case CG_TEXCOORD5: case CG_TEXCOORD6: case CG_TEXCOORD7: - case CG_TEXCOORD8: case CG_TEXCOORD9: - return CG_TEXCOORD0; - case CG_TEXUNIT0: case CG_TEXUNIT1: case CG_TEXUNIT2: case CG_TEXUNIT3: - case CG_TEXUNIT4: case CG_TEXUNIT5: case CG_TEXUNIT6: case CG_TEXUNIT7: - case CG_TEXUNIT8: case CG_TEXUNIT9: case CG_TEXUNIT10: case CG_TEXUNIT11: - case CG_TEXUNIT12: case CG_TEXUNIT13: case CG_TEXUNIT14: case CG_TEXUNIT15: - return CG_TEXUNIT0; - case CG_FOGCOORD: - return CG_FOGCOORD; - case CG_PSIZ: - return CG_PSIZ; - case CG_WPOS: - return CG_WPOS; - case CG_COLOR0: case CG_COLOR1: case CG_COLOR2: case CG_COLOR3: - return CG_COLOR0; - case CG_DEPTH0: - return CG_DEPTH0; - case CG_C: - return CG_C; - case CG_B: - return CG_B; - case CG_CLP0: case CG_CLP1: case CG_CLP2: case CG_CLP3: case CG_CLP4: case CG_CLP5: - return CG_CLP0; - case CG_UNDEFINED: - return CG_UNDEFINED; - default: - //RARCH_WARN("Resource 0x%d is unknown here.\n", resource ); - return CG_UNDEFINED; - } -} - -CGprofile _RGLPlatformGetLatestProfile( CGGLenum profile_type ); -int _RGLPlatformCopyProgram( _CGprogram* source, _CGprogram* destination ); - -void _RGLPlatformProgramErase( void* platformProgram ); - -CGbool _RGLPlatformSupportsFragmentProgram( CGprofile p ); - -void _RGLPlatformSetVertexRegister4fv( unsigned int reg, const float * __restrict v ); -void _RGLPlatformSetVertexRegisterBlock( unsigned int reg, unsigned int count, const float * __restrict v ); -void _RGLPlatformSetFragmentRegister4fv( unsigned int reg, const float * __restrict v ); -void _RGLPlatformSetFragmentRegisterBlock( unsigned int reg, unsigned int count, const float * __restrict v ); - -unsigned int _cgHashString( const char *str ); - -static inline GLenum _RGLCgGetSamplerGLTypeFromCgType( CGtype type ) -{ - switch ( type ) - { - case CG_SAMPLER1D: - case CG_SAMPLER2D: - case CG_SAMPLERRECT: - return GL_TEXTURE_2D; - default: - return 0; - } -} - -struct jsNameSpace; - -int _RGLNVGenerateProgram( _CGprogram *program, int profileIndex, const CgProgramHeader *programHeader, const void *ucode, const CgParameterTableHeader *parameterHeader, const CgParameterEntry *parameterEntries, -const char *stringTable, const float *defaultValues ); - -_cgSetArrayIndexFunction getVectorTypeIndexSetterFunction( unsigned short a, unsigned short b, unsigned short c, unsigned short d ); -_cgSetArrayIndexFunction getMatrixTypeIndexSetterFunction( unsigned short a, unsigned short b, unsigned short c, unsigned short d, unsigned short e, unsigned short f ); - -// ------------------------------------------- - -typedef void( * CgcontextHookFunction )( _CGcontext *context ); -extern CgcontextHookFunction _cgContextCreateHook; -extern CgcontextHookFunction _cgContextDestroyHook; - -typedef void( * CgparameterHookFunction )( CgRuntimeParameter *parameter ); -extern CgparameterHookFunction _cgParameterCreateHook; -extern CgparameterHookFunction _cgParameterDestroyHook; - -typedef void( * CgprogramHookFunction )( _CGprogram *program ); -typedef void( * CgprogramCopyHookFunction )( _CGprogram *newprogram, _CGprogram *oldprogram ); -extern CgprogramHookFunction _cgProgramCreateHook; -extern CgprogramHookFunction _cgProgramDestroyHook; -extern CgprogramCopyHookFunction _cgProgramCopyHook; - -typedef int( * cgRTCgcCompileHookFunction )( const char*, const char *, const char*, const char**, char** ); -typedef void( * cgRTCgcFreeHookFunction )( char* ); -extern cgRTCgcCompileHookFunction _cgRTCgcCompileProgramHook; -extern cgRTCgcFreeHookFunction _cgRTCgcFreeCompiledProgramHook; - - -static inline const CgParameterResource *_RGLGetParameterResource( const _CGprogram *program, const CgParameterEntry *entry ) -{ - return ( CgParameterResource * )( program->parameterResources + entry->typeIndex ); -} - -static inline const CgParameterArray *_RGLGetParameterArray( const _CGprogram *program, const CgParameterEntry *entry ) -{ - return ( CgParameterArray* )( program->parameterResources + entry->typeIndex ); -} - -static inline const CgParameterStructure *_RGLGetParameterStructure( const _CGprogram *program, const CgParameterEntry *entry ) -{ - return ( CgParameterStructure* )( program->parameterResources + entry->typeIndex ); -} - -inline int _RGLGetProgramProfileIndex( CGprofile profile ) -{ - if ( profile == CG_PROFILE_SCE_FP_TYPEB || profile == CG_PROFILE_SCE_FP_TYPEC || profile == CG_PROFILE_SCE_FP_RSX ) - return FRAGMENT_PROFILE_INDEX; - else if ( profile == CG_PROFILE_SCE_VP_TYPEB || profile == CG_PROFILE_SCE_VP_TYPEC || profile == CG_PROFILE_SCE_VP_RSX ) - return VERTEX_PROFILE_INDEX; - else - return -1; -} - -CGGL_API void cgGLSetMatrixParameterfc( CGparameter param, const float *matrix ); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/console/rgl/ps3/cgbio.cpp b/console/rgl/ps3/cgbio.cpp deleted file mode 100644 index 6a4a2d3238..0000000000 --- a/console/rgl/ps3/cgbio.cpp +++ /dev/null @@ -1,368 +0,0 @@ -#include -#include - -#include -#include -#include - -#include "cgbio.hpp" - -using std::fill_n; - -namespace cgc { -namespace bio { - -bin_io* bin_io::instance_ = 0; - -bin_io::bin_io() -{ -} - -bin_io::bin_io( const bin_io& ) -{ -} - -const bin_io* bin_io::instance() -{ - if ( 0 == instance_ ) - { - instance_ = new bin_io; - } - return instance_; -} - -void bin_io::delete_instance() -{ - if ( 0 != instance_ ) - { - delete instance_; - instance_ = 0; - } -} - -CGBIO_ERROR bin_io::new_elf_reader( elf_reader** obj ) const -{ - CGBIO_ERROR ret = CGBIO_ERROR_NO_ERROR; - *obj = new elf_reader_impl; - - if ( 0 == *obj ) - ret = CGBIO_ERROR_MEMORY; - - return ret; -} - -const char* -bin_io::error_string( CGBIO_ERROR error ) const -{ - switch ( error ) - { - case CGBIO_ERROR_NO_ERROR: - return "No error"; - case CGBIO_ERROR_LOADED: - return "Binary file has been loaded earlier"; - case CGBIO_ERROR_FILEIO: - return "File input output error"; - case CGBIO_ERROR_FORMAT: - return "File format error"; - case CGBIO_ERROR_INDEX: - return "Index is out of range"; - case CGBIO_ERROR_MEMORY: - return "Can't allocate memory"; - case CGBIO_ERROR_RELOC: - return "Relocation error"; - case CGBIO_ERROR_SYMBOL: - return "Symbol error"; - case CGBIO_ERROR_UNKNOWN_TYPE: - return "Uknown type"; - default: - return "Unknown error"; - } - return "Unknown error"; -} - -CGBIO_ERROR -bin_io::new_nvb_reader( nvb_reader** obj ) const -{ - CGBIO_ERROR ret = CGBIO_ERROR_NO_ERROR; - *obj = new nvb_reader_impl; - - if ( *obj == 0 ) - ret = CGBIO_ERROR_MEMORY; - - return ret; -} - -nvb_reader_impl::nvb_reader_impl() -{ - ref_count_ = 1; - offset_ = 0; - image_ = 0; - owner_ = false; - loaded_ = false; - endianness_ = host_endianness(); - std::fill_n( reinterpret_cast( &header_ ), sizeof( header_ ), '\0' ); -} - -nvb_reader_impl::~nvb_reader_impl() -{ - if ( image_ != 0 ) - delete [] image_; -} - -ptrdiff_t -nvb_reader_impl::reference() const -{ - return ++ref_count_; -} - -ptrdiff_t -nvb_reader_impl::release() const -{ - ptrdiff_t ret = --ref_count_; - - if ( ref_count_ == 0 ) - delete this; - - return ret; -} - -CGBIO_ERROR -nvb_reader_impl::loadFromString( const char* source, size_t length) -{ - if ( loaded_ ) - { - return CGBIO_ERROR_LOADED; - } - CGBIO_ERROR ret = CGBIO_ERROR_NO_ERROR; - while (1) - { - if (length < sizeof( header_ )) - { - ret = CGBIO_ERROR_FORMAT; - break; - } - memcpy(&header_ ,source,sizeof( header_ )); - if ( CG_BINARY_FORMAT_REVISION != header_.binaryFormatRevision ) - { - endianness_ = ( CGBIODATALSB == endianness_ ) ? CGBIODATAMSB : CGBIODATALSB; - int binaryRevision = convert_endianness( header_.binaryFormatRevision, endianness_ ); - if ( CG_BINARY_FORMAT_REVISION != binaryRevision ) - { - ret = CGBIO_ERROR_FORMAT; - break; - } - } - size_t sz = length; - image_ = new char[sz]; - memcpy(image_,source,sz); - loaded_ = true; - ret = CGBIO_ERROR_NO_ERROR; - break; - } - return ret; -} - -bool -nvb_reader_impl::is_loaded() const -{ - return loaded_; -} - -unsigned char -nvb_reader_impl::endianness() const -{ - return endianness_; -} - -CGprofile -nvb_reader_impl::profile() const -{ - return (CGprofile) convert_endianness( (unsigned int) header_.profile, endianness() ); -} - -unsigned int -nvb_reader_impl::revision() const -{ - return convert_endianness( header_.binaryFormatRevision, endianness() ); -} - -unsigned int nvb_reader_impl::size() const -{ - return convert_endianness( header_.totalSize, endianness() ); -} - -unsigned int nvb_reader_impl::number_of_params() const -{ - return convert_endianness( header_.parameterCount, endianness() ); -} - -unsigned int nvb_reader_impl::ucode_size() const -{ - return convert_endianness( header_.ucodeSize, endianness() ); -} - -const char* nvb_reader_impl::ucode() const -{ - if ( 0 == image_ || 0 == ucode_size() ) - return 0; - - return ( image_ + convert_endianness( header_.ucode, endianness() ) ); -} - -const CgBinaryFragmentProgram* -nvb_reader_impl::fragment_program() const -{ - if ( 0 == image_ ) - return 0; - - return reinterpret_cast( &image_[convert_endianness( header_.program, endianness_ )] ); -} - -const CgBinaryVertexProgram* nvb_reader_impl::vertex_program() const -{ - if ( 0 == image_ ) - return 0; - - return reinterpret_cast( &image_[convert_endianness( header_.program, endianness_ )] ); -} - -CGBIO_ERROR nvb_reader_impl::get_param_name( unsigned int index, const char **name, bool& is_referenced ) const -{ - if ( index >= number_of_params() ) - return CGBIO_ERROR_INDEX; - - if ( 0 == image_ ) - return CGBIO_ERROR_NO_ERROR; - - const CgBinaryParameter* params = reinterpret_cast( &image_[convert_endianness( header_.parameterArray, endianness_ )] ); - const CgBinaryParameter& pp = params[index]; - is_referenced = convert_endianness( pp.isReferenced, endianness() ) != 0; - CgBinaryStringOffset nm_offset = convert_endianness( pp.name,endianness() ); - if ( nm_offset != 0 ) - *name = &image_[nm_offset]; - else - *name = ""; - return CGBIO_ERROR_NO_ERROR; -} - -CGBIO_ERROR -nvb_reader_impl::get_param( unsigned int index, - CGtype& type, - CGresource& resource, - CGenum& variability, - int& resource_index, - const char ** name, - std::vector& default_value, - std::vector& embedded_constants, - const char ** semantic, - int& paramno, - bool& is_referenced, - bool& is_shared ) const -{ - if ( index >= number_of_params() ) - return CGBIO_ERROR_INDEX; - - if ( 0 == image_ ) - return CGBIO_ERROR_NO_ERROR; - - const CgBinaryParameter* params = reinterpret_cast( &image_[convert_endianness( header_.parameterArray, endianness_ )] ); - const CgBinaryParameter& pp = params[index]; - type = static_cast(convert_endianness( static_cast( pp.type ), endianness() ) ); - resource = static_cast(convert_endianness( static_cast( pp.res ), endianness() ) ); - variability = static_cast(convert_endianness( static_cast( pp.var ),endianness() ) ); - resource_index = convert_endianness( pp.resIndex,endianness() ); - paramno = convert_endianness( pp.paramno, endianness() ); - is_referenced = convert_endianness( pp.isReferenced,endianness() ) != 0; - is_shared = convert_endianness( pp.isShared,endianness() ) != 0; - CgBinaryStringOffset nm_offset = convert_endianness( pp.name,endianness() ); - CgBinaryFloatOffset dv_offset = convert_endianness( pp.defaultValue,endianness() ); - CgBinaryEmbeddedConstantOffset ec_offset = convert_endianness( pp.embeddedConst,endianness() ); - CgBinaryStringOffset sm_offset = convert_endianness( pp.semantic,endianness() ); - if ( 0 != nm_offset ) - { - *name = &image_[nm_offset]; - } - else - *name = ""; - - if ( 0 != sm_offset ) - { - *semantic = &image_[sm_offset]; - } - else - *semantic = ""; - if ( 0 != dv_offset ) - { - char *vp = &image_[dv_offset]; - for (int ii = 0; ii < 4; ++ii) - { - int tmp; - memcpy(&tmp,vp+4*ii,4); - tmp = convert_endianness(tmp,endianness()); - float tmp2; - memcpy(&tmp2,&tmp,4); - default_value.push_back( tmp2 ); - } - } - if ( 0 != ec_offset ) - { - void *vp = &image_[ec_offset]; - CgBinaryEmbeddedConstant& ec = *(static_cast( vp )); - for (unsigned int ii = 0; ii < convert_endianness( ec.ucodeCount, endianness() ); ++ii) - { - unsigned int offset = convert_endianness( ec.ucodeOffset[ii], endianness() ); - embedded_constants.push_back( offset ); - } - } - return CGBIO_ERROR_NO_ERROR; -} - -elf_reader_impl::elf_reader_impl() -{ - ref_count_ = 1; - initialized_ = false; - fill_n( reinterpret_cast( &header_ ), sizeof( header_ ), '\0' ); -} - -elf_reader_impl::~elf_reader_impl() -{ -} - -CGBIO_ERROR -elf_reader_impl::load( const char* filename ) -{ - return CGBIO_ERROR_NO_ERROR; -} - -CGBIO_ERROR -elf_reader_impl::load( std::istream* stream, int start ) -{ - return CGBIO_ERROR_NO_ERROR; -} - -bool -elf_reader_impl::is_initialized() const -{ - return initialized_; -} - -ptrdiff_t -elf_reader_impl::reference() const -{ - return ++ref_count_; -} - -ptrdiff_t -elf_reader_impl::release() const -{ - ptrdiff_t ret = --ref_count_; - if ( 0 == ref_count_ ) - { - delete this; - } - - return ret; -} - -} -} diff --git a/console/rgl/ps3/cgbio.hpp b/console/rgl/ps3/cgbio.hpp deleted file mode 100644 index f7dcfca541..0000000000 --- a/console/rgl/ps3/cgbio.hpp +++ /dev/null @@ -1,552 +0,0 @@ -#ifndef CGC_CGBIO_CGBDEFS_HPP -#define CGC_CGBIO_CGBDEFS_HPP - -#include - -#define CGF_OUTPUTFROMH0 0x01 -#define CGF_DEPTHREPLACE 0x02 -#define CGF_PIXELKILL 0x04 - -typedef size_t ptrdiff_t; -typedef size_t ptrdiff_t; - -typedef struct _Elf32_cgParameter -{ - unsigned int cgp_name; - unsigned int cgp_semantic; - unsigned short cgp_default; - unsigned short cgp_reloc; - unsigned short cgp_resource; - unsigned short cgp_resource_index; - unsigned char cgp_type; - unsigned short cgp_info; - unsigned char unused; -} Elf32_cgParameter; - -#define ET_NONE 0 -#define ET_REL 1 -#define ET_EXEC 2 -#define ET_DYN 3 -#define ET_CORE 4 -#define ET_LOOS 0xFE00 -#define ET_HIOS 0xFEFF -#define ET_LOPROC 0xFF00 -#define ET_HIPROC 0xFFFF - -#define EM_NONE 0 -#define EM_RSX 0x528e - -#define EM_RSX_NONE 0 - -#define EI_ABIVERSION_RSX 1 - -#define EV_NONE 0 -#define EV_CURRENT 1 - -#define EI_MAG0 0 -#define EI_MAG1 1 -#define EI_MAG2 2 -#define EI_MAG3 3 -#define EI_CLASS 4 -#define EI_DATA 5 -#define EI_VERSION 6 -#define EI_OSABI 7 -#define EI_ABIVERSION 8 -#define EI_PAD 9 -#define EI_NIDENT 16 - -#define ELFMAG0 0x7F -#define ELFMAG1 'E' -#define ELFMAG2 'L' -#define ELFMAG3 'F' - -#define ELFCLASSNONE 0 -#define ELFCLASS32 1 -#define ELFCLASS64 2 - -#define ELFDATANONE 0 -#define ELFDATA2LSB 1 -#define ELFDATA2MSB 2 - -#define ELFOSABI_NONE 0 -#define ELFOSABI_HPUX 1 -#define ELFOSABI_NETBSD 2 -#define ELFOSABI_LINUX 3 -#define ELFOSABI_SOLARIS 6 -#define ELFOSABI_AIX 7 -#define ELFOSABI_IRIX 8 -#define ELFOSABI_FREEBSD 9 -#define ELFOSABI_TRU64 10 -#define ELFOSABI_MODESTO 11 -#define ELFOSABI_OPENBSD 12 -#define ELFOSABI_CGRUNTIME 19 - -#define SHN_UNDEF 0 -#define SHN_LORESERVE 0xFF00 -#define SHN_LOPROC 0xFF00 -#define SHN_HIPROC 0xFF1F -#define SHN_LOOS 0xFF20 -#define SHN_HIOS 0xFF3F -#define SHN_ABS 0xFFF1 -#define SHN_COMMON 0xFFF2 -#define SHN_XINDEX 0xFFFF -#define SHN_HIRESERVE 0xFFFF - -#define SHT_NULL 0 -#define SHT_PROGBITS 1 -#define SHT_SYMTAB 2 -#define SHT_STRTAB 3 -#define SHT_RELA 4 -#define SHT_HASH 5 -#define SHT_DYNAMIC 6 -#define SHT_NOTE 7 -#define SHT_NOBITS 8 -#define SHT_REL 9 -#define SHT_SHLIB 10 -#define SHT_DYNSYM 11 -#define SHT_INIT_ARRAY 14 -#define SHT_FINI_ARRAY 15 -#define SHT_PREINIT_ARRAY 16 -#define SHT_GROUP 17 -#define SHT_SYMTAB_SHNDX 18 -#define SHT_LOOS 0x60000000 -#define SHT_HIOS 0x6fffffff -#define SHT_LOPROC 0x70000000 -#define SHT_RSX_PARAM 0x70000000 -#define SHT_RSX_SHADERTAB 0x70000001 -#define SHT_RSX_FXTAB 0x70000002 -#define SHT_RSX_ANNOTATE 0x70000003 -#define SHT_HIPROC 0x7FFFFFFF -#define SHT_LOUSER 0x80000000 -#define SHT_HIUSER 0xFFFFFFFF - -#define SHF_WRITE 0x1 -#define SHF_ALLOC 0x2 -#define SHF_EXECINSTR 0x4 -#define SHF_MERGE 0x10 -#define SHF_STRINGS 0x20 -#define SHF_INFO_LINK 0x40 -#define SHF_LINK_ORDER 0x80 -#define SHF_OS_NONCONFORMING 0x100 -#define SHF_GROUP 0x200 -#define SHF_TLS 0x400 -#define SHF_MASKOS 0x0ff00000 -#define SHF_MASKPROC 0xF0000000 - -#define GRP_COMDAT 0x1 -#define GRP_MASKOS 0x0ff00000 -#define GRP_MASKPROC 0xf0000000 - -#define STB_LOCAL 0 -#define STB_GLOBAL 1 -#define STB_WEAK 2 -#define STB_LOOS 10 -#define STB_HIOS 12 -#define STB_LOPROC 13 -#define STB_HIPROC 15 - -#define STT_NOTYPE 0 -#define STT_OBJECT 1 -#define STT_FUNC 2 -#define STT_SECTION 3 -#define STT_FILE 4 -#define STT_COMMON 5 -#define STT_TLS 6 -#define STT_LOOS 10 -#define STT_HIOS 12 -#define STT_LOPROC 13 -#define STT_HIPROC 15 - -#define STV_DEFAULT 0 -#define STV_INTERNAL 1 -#define STV_HIDDEN 2 -#define STV_PROTECTED 3 - -#define STO_RSX_SHADER 0 -#define STO_RSX_EFFECT 1 - -#define STN_UNDEF 0 - -#define R_RSX_NONE 0 -#define R_RSX_FLOAT4 1 - -struct Elf32_Ehdr -{ - unsigned char e_ident[EI_NIDENT]; - unsigned short e_type; - unsigned short e_machine; - unsigned int e_version; - unsigned int e_entry; - unsigned int e_phoff; - unsigned int e_shoff; - unsigned int e_flags; - unsigned short e_ehsize; - unsigned short e_phentsize; - unsigned short e_phnum; - unsigned short e_shentsize; - unsigned short e_shnum; - unsigned short e_shstrndx; -}; - -struct Elf32_Shdr { - unsigned int sh_name; - unsigned int sh_type; - unsigned int sh_flags; - unsigned int sh_addr; - unsigned int sh_offset; - unsigned int sh_size; - unsigned int sh_link; - unsigned int sh_info; - unsigned int sh_addralign; - unsigned int sh_entsize; -}; - -struct Elf32_Phdr { - unsigned int p_type; - unsigned int p_offset; - unsigned int p_vaddr; - unsigned int p_paddr; - unsigned int p_filesz; - unsigned int p_memsz; - unsigned int p_flags; - unsigned int p_align; -}; - -struct Elf32_Sym { - unsigned int st_name; - unsigned int st_value; - unsigned int st_size; - unsigned char st_info; - unsigned char st_other; - unsigned short st_shndx; -}; - -struct Elf32_Note -{ - unsigned int n_namesz; /* Name size */ - unsigned int n_descsz; /* Content size */ - unsigned int n_type; /* Content type */ -}; - - -struct Elf32_Rel { - unsigned int r_offset; - unsigned int r_info; -}; - -struct Elf32_Rela { - unsigned int r_offset; - unsigned int r_info; - signed int r_addend; -}; - -struct Elf32_Dyn { - signed int d_tag; - union { - unsigned int d_val; - unsigned int d_ptr; - } d_un; -}; - -using std::istream; - -namespace cgc { -namespace bio { - -enum CGBIO_ERROR { - CGBIO_ERROR_NO_ERROR, - CGBIO_ERROR_LOADED, - CGBIO_ERROR_FILEIO, - CGBIO_ERROR_FORMAT, - CGBIO_ERROR_INDEX, - CGBIO_ERROR_MEMORY, - CGBIO_ERROR_RELOC, - CGBIO_ERROR_SYMBOL, - CGBIO_ERROR_UNKNOWN_TYPE -}; - -typedef enum { - CGBIODATANONE = ELFDATANONE, - CGBIODATALSB = ELFDATA2LSB, - CGBIODATAMSB = ELFDATA2MSB -} HOST_ENDIANNESS; - -class elf_reader -{ - public: - virtual ptrdiff_t reference() const = 0; - virtual ptrdiff_t release() const = 0; - virtual CGBIO_ERROR load( const char * filename ) = 0; - virtual CGBIO_ERROR load( istream* stream, int start ) = 0; - virtual bool is_initialized() const = 0; - virtual ~elf_reader() {} - -}; - -class nvb_reader -{ - public: - virtual ~nvb_reader() {} - - virtual ptrdiff_t - reference() const = 0; - - virtual ptrdiff_t - release() const = 0; - - virtual CGBIO_ERROR - loadFromString( const char* source, size_t length ) = 0; - - virtual bool - is_loaded() const = 0; - - virtual unsigned char - endianness() const = 0; - - virtual CGprofile - profile() const = 0; - - virtual unsigned int - revision() const = 0; - - virtual unsigned int - size() const = 0; - - virtual unsigned int - number_of_params() const = 0; - - virtual unsigned int - ucode_size() const = 0; - - virtual const char* - ucode() const = 0; - - virtual const CgBinaryFragmentProgram* - fragment_program() const = 0; - - virtual const CgBinaryVertexProgram* - vertex_program() const = 0; - - virtual CGBIO_ERROR - get_param( unsigned int index, - CGtype& type, - CGresource& resource, - CGenum& variability, - int& resource_index, - const char** name, - std::vector& default_value, - std::vector& embedded_constants, - const char** semantic, - int& paramno, - bool& is_referenced, - bool& is_shared ) const = 0; - - virtual CGBIO_ERROR get_param_name( unsigned int index, const char** name, bool& is_referenced) const = 0; - -}; - -class bin_io -{ - public: - static const bin_io* instance(); - static void delete_instance(); - - CGBIO_ERROR new_elf_reader( elf_reader** obj ) const; - - CGBIO_ERROR new_nvb_reader( nvb_reader** obj ) const; - - const char *error_string( CGBIO_ERROR error ) const; - - private: - bin_io(); - bin_io( const bin_io& ); - - static bin_io* instance_; -}; - - -class isection -{ - public: - virtual ~isection() = 0; - - virtual int reference() const = 0; - virtual int release() const = 0; - - virtual unsigned short index() const = 0; - virtual char *name() const = 0; - virtual unsigned int type() const = 0; - virtual unsigned int flags() const = 0; - virtual unsigned int addr() const = 0; - virtual unsigned int size() const = 0; - virtual unsigned int link() const = 0; - virtual unsigned int info() const = 0; - virtual unsigned int addralign() const = 0; - virtual unsigned int entsize() const = 0; - virtual const char* data() const = 0; -}; - -class elf_reader_impl : public elf_reader -{ - public: - elf_reader_impl(); - virtual ~elf_reader_impl(); - virtual CGBIO_ERROR load( const char* filename ); - virtual CGBIO_ERROR load( istream* stream, int start ); - virtual bool is_initialized() const; - virtual ptrdiff_t reference() const; - virtual ptrdiff_t release() const; - private: - mutable ptrdiff_t ref_count_; - istream* stream_; - bool initialized_; - Elf32_Ehdr header_; - std::vector sections_; -}; - -inline HOST_ENDIANNESS host_endianness() -{ - const int ii = 1; - const char* cp = (const char*) ⅈ - return ( 1 == cp[0] ) ? CGBIODATALSB : CGBIODATAMSB; -} - -template< typename T > inline T -convert_endianness( const T value, unsigned char endianness ) -{ - if ( host_endianness() == endianness ) - { - return value; - } - if ( sizeof( T ) == 1 ) - { - return value; - } - if ( sizeof( T ) == 2 ) - { - return ( ((value & 0x00FF) << 8) - | ((value & 0xFF00) >> 8) ); - } - if ( sizeof( T ) == 4 ) - { - return ( ((value & 0x000000FF) << 24) - | ((value & 0x0000FF00) << 8) - | ((value & 0x00FF0000) >> 8) - | ((value & 0xFF000000) >> 24) ); - } - if ( sizeof( T ) == 8 ) - { - T result = value; - for ( int ii = 0; ii < 4; ++ii ) - { - char ch = *( (( char* ) &result) + ii ); - *( (( char* ) &result) + ii ) = *( (( char* ) &result) + (7 - ii) ); - *( (( char* ) &result) + (7 - ii) ) = ch; - } - return result; - } - return value; -} - -template< typename T > inline T -ELF32_ST_BIND( const T idx ) -{ - return ( idx >> 4 ); -} - -template< typename T > inline T -ELF32_ST_TYPE( const T idx ) -{ - return ( idx & 0xf ); -} - -template< typename T > inline T -ELF32_ST_INFO( const T b, const T t ) -{ - return ( ( b << 4 ) + ( t & 0xf ) ); -} - -template< typename T > inline T -ELF32_ST_VISIBILITY( const T o ) -{ - return ( o & 0x3 ); -} - -class nvb_reader_impl : public nvb_reader -{ - public: - nvb_reader_impl(); - - virtual - ~nvb_reader_impl(); - - virtual ptrdiff_t - reference() const; - - virtual ptrdiff_t - release() const; - - virtual CGBIO_ERROR - loadFromString( const char* source, size_t length); - - virtual bool - is_loaded() const; - - virtual unsigned char - endianness() const; - - virtual CGprofile - profile() const; - - virtual unsigned int - revision() const; - - virtual unsigned int - size() const; - - virtual unsigned int - number_of_params() const; - - virtual unsigned int - ucode_size() const; - - virtual const char* - ucode() const; - - virtual const CgBinaryFragmentProgram* - fragment_program() const; - - virtual const CgBinaryVertexProgram* - vertex_program() const; - - virtual CGBIO_ERROR - get_param( unsigned int index, - CGtype& type, - CGresource& resource, - CGenum& variability, - int& resource_index, - const char ** name, - std::vector& default_value, - std::vector& embedded_constants, - const char ** semantic, - int& paramno, - bool& is_referenced, - bool& is_shared ) const; - - virtual CGBIO_ERROR get_param_name( unsigned int index, const char ** name , bool& is_referenced) const; - - private: - mutable ptrdiff_t ref_count_; - int offset_; - bool loaded_; - bool owner_; - bool strStream_; - CgBinaryProgram header_; - unsigned char endianness_; - char* image_; -}; - -} -} - -#endif diff --git a/console/rgl/ps3/cgnv2rt.cpp b/console/rgl/ps3/cgnv2rt.cpp deleted file mode 100644 index a8138e3c43..0000000000 --- a/console/rgl/ps3/cgnv2rt.cpp +++ /dev/null @@ -1,1122 +0,0 @@ -#include "cgnv2rt.h" - -#include -#include -#include - -#include "cgbio.hpp" -#include "cg.h" - -#include - -using namespace cgc::bio; - -class CgBaseType -{ -public: - CgBaseType() {_type = 0;} - virtual ~CgBaseType() {} - unsigned short _type; - short _resourceIndex; - unsigned short _resource; -}; - -class CgArrayType : public CgBaseType -{ -public: - CgArrayType():_elementType(NULL) { _type = (unsigned char)(CG_ARRAY + 128); } - virtual ~CgArrayType() - { - if (_elementType) - delete _elementType; - } - CgBaseType *_elementType; - unsigned char _dimensionCount; - unsigned short _dimensionItemCountsOffset; -}; - -class CgStructureType : public CgBaseType -{ -public: - class CgStructuralElement - { - public: - char _name[256]; - char _semantic[256]; - CgBaseType *_type; - unsigned short _flags; - unsigned short _index; - }; - - CgStructureType() - { - _type = (unsigned char)(CG_STRUCT + 128); - _root = false; - } - - virtual ~CgStructureType() - { - int i=0; - int count = (int)_elements.size(); - for (i=0;i _elements; - bool _insideArray; - bool _root; -}; - -typedef struct -{ - const char *name; - int resIndex; -} BINDLOCATION; - -#define CG_DATATYPE_MACRO(name, compiler_name, enum_name, base_enum, nrows, ncols,classname) \ - classname , -static int classnames[] = { -#include "Cg/cg_datatypes.h" -}; - -#define CG_DATATYPE_MACRO(name, compiler_name, enum_name, base_enum, nrows, ncols,classname) \ - nrows , -static int rows[] = { -#include "Cg/cg_datatypes.h" -}; - -typedef float _float4[4]; - -typedef struct -{ - std::vector _resources; - std::vector _defaultValuesIndices; - std::vector _elfDefaultsIndices; - std::vector _dimensions; - std::vector _semanticIndices; -} _CGNVCONTAINERS; - -static bool bIsVertexProgram = true; - - -static int getStride(CgBaseType *type); -static int getSizeofSubArray(_CGNVCONTAINERS &containers, int dimensionIndex, int dimensionCount, int endianness); - -static unsigned int stringTableFind( std::vector &stringTable, const char* str ) -{ - const char* data = &stringTable[0]; - size_t size = stringTable.size(); - const char *end = data + size; - - size_t length = strlen(str); - - if (length+1 > size) - return 0; - - data += length; - - const char *p = (char*)memchr(data,'\0',end-data); - while (p && (end-data)>0) - { - if (!memcmp(p - length, str, length)) - return (unsigned int)(p - length - &stringTable[0]); - - data = p+1; - p = (char*)memchr(data,'\0',end-data); - } - return 0; -} - -static unsigned int stringTableAdd( std::vector &stringTable, const char* str ) -{ - unsigned int ret = (unsigned int)stringTable.size(); - - if ( ret == 0 ) - { - stringTable.push_back('\0'); - ret = 1; - } - - size_t stringLength = strlen(str) + 1; - stringTable.resize(ret + stringLength); - memcpy(&stringTable[0] + ret,str,stringLength); - - return ret; -} - -static unsigned int stringTableAddUnique( std::vector &stringTable, const char* str ) -{ - if ( stringTable.size() == 0 ) - stringTable.push_back('\0'); - - unsigned int ret = stringTableFind(stringTable, str); - - if (ret == 0 && str[0] != '\0') - ret = stringTableAdd(stringTable, str); - - return ret; -} - -template static size_t array_size(std::vector &array); -template static void array_push(char* ¶meterOffset, std::vector &array); -inline static unsigned int swap16(const unsigned int v); -static unsigned short getFlags(CGenum var, CGenum dir, int no, bool is_referenced, bool is_shared, int paramIndex); - -static void fillStructureItems(_CGNVCONTAINERS &containers, CgStructureType *structure, - int endianness, - std::vector ¶meterEntries, - std::vector ¶meterResources, std::vector &stringTable, unsigned short *arrayResourceIndex = NULL, - unsigned short *arrayDefaultValueIndex = NULL); - - -int convertNvToElfFromMemory(const void *sourceData, size_t size, int endianness, int constTableOffset, void **binaryShader, int *binarySize, - std::vector &stringTable, std::vector &defaultValues) -{ - _CGNVCONTAINERS containers; - - unsigned char elfEndianness = endianness; - - nvb_reader* nvbr = 0; - bin_io::instance()->new_nvb_reader( &nvbr ); - CGBIO_ERROR err = nvbr->loadFromString((const char*)sourceData,size); - if (err != CGBIO_ERROR_NO_ERROR) - return -1; - - bool doSwap = !(nvbr->endianness() == (HOST_ENDIANNESS)elfEndianness); - - CGprofile NVProfile = nvbr->profile(); - if (NVProfile == (CGprofile)7005 ) - NVProfile = CG_PROFILE_SCE_VP_RSX; - if (NVProfile == (CGprofile)7006 ) - NVProfile = CG_PROFILE_SCE_FP_RSX; - if (NVProfile == CG_PROFILE_SCE_VP_TYPEB || NVProfile == CG_PROFILE_SCE_VP_RSX) - { - bIsVertexProgram = true; - } - else if (NVProfile == CG_PROFILE_SCE_FP_TYPEB || NVProfile == CG_PROFILE_SCE_FP_RSX) - { - bIsVertexProgram = false; - } - else - { - return -1; - } - - CgProgramHeader cgShader; - memset(&cgShader,0,sizeof(CgProgramHeader)); - cgShader.profile = CNV2END((unsigned short) NVProfile); - cgShader.compilerVersion = 0;//TODO - if (bIsVertexProgram) - { - const CgBinaryVertexProgram *nvVertex = nvbr->vertex_program(); - if (doSwap) - { - cgShader.instructionCount = ENDSWAP(nvVertex->instructionCount); - cgShader.attributeInputMask = ENDSWAP(nvVertex->attributeInputMask); - cgShader.vertexProgram.instructionSlot = ENDSWAP(nvVertex->instructionSlot); - cgShader.vertexProgram.registerCount = ENDSWAP(nvVertex->registerCount); - cgShader.vertexProgram.attributeOutputMask = ENDSWAP(nvVertex->attributeOutputMask); - } - else - { - cgShader.instructionCount = nvVertex->instructionCount; - cgShader.attributeInputMask = nvVertex->attributeInputMask; - cgShader.vertexProgram.instructionSlot = nvVertex->instructionSlot; - cgShader.vertexProgram.registerCount = nvVertex->registerCount; - cgShader.vertexProgram.attributeOutputMask = nvVertex->attributeOutputMask; - } - } - else - { - const CgBinaryFragmentProgram *nvFragment = nvbr->fragment_program(); - unsigned char flags; - if (doSwap) - { - cgShader.instructionCount = ENDSWAP(nvFragment->instructionCount); - cgShader.attributeInputMask = ENDSWAP(nvFragment->attributeInputMask); - cgShader.fragmentProgram.partialTexType = ENDSWAP(nvFragment->partialTexType); - cgShader.fragmentProgram.texcoordInputMask = ENDSWAP(nvFragment->texCoordsInputMask); - cgShader.fragmentProgram.texcoord2d = ENDSWAP(nvFragment->texCoords2D); - cgShader.fragmentProgram.texcoordCentroid = ENDSWAP(nvFragment->texCoordsCentroid); - cgShader.fragmentProgram.registerCount = ENDSWAP(nvFragment->registerCount); - flags = - (nvFragment->outputFromH0 ? CGF_OUTPUTFROMH0 : 0) | - (nvFragment->depthReplace ? CGF_DEPTHREPLACE : 0) | - (nvFragment->pixelKill ? CGF_PIXELKILL : 0); - } - else - { - cgShader.instructionCount = nvFragment->instructionCount; - cgShader.attributeInputMask = nvFragment->attributeInputMask; - cgShader.fragmentProgram.partialTexType = nvFragment->partialTexType; - cgShader.fragmentProgram.texcoordInputMask = nvFragment->texCoordsInputMask; - cgShader.fragmentProgram.texcoord2d = nvFragment->texCoords2D; - cgShader.fragmentProgram.texcoordCentroid = nvFragment->texCoordsCentroid; - cgShader.fragmentProgram.registerCount = nvFragment->registerCount; - flags = - (nvFragment->outputFromH0 ? CGF_OUTPUTFROMH0 : 0) | - (nvFragment->depthReplace ? CGF_DEPTHREPLACE : 0) | - (nvFragment->pixelKill ? CGF_PIXELKILL : 0); - } - cgShader.fragmentProgram.flags = CNV2END(flags); - } - - unsigned int *tmp = (unsigned int *)nvbr->ucode(); - const char *ucode; - unsigned int *buffer = NULL; - if (doSwap) - { - int size = (int)nvbr->ucode_size()/sizeof(unsigned int); - buffer = new unsigned int[size]; - for (int i=0;iucode_size()/sizeof(unsigned int); - buffer = new unsigned int[size]; - for (int i=0;iucode_size(); - - CgStructureType root; - root._insideArray = false; - root._root = true; - - int paramIndex = -1; - - CgStructureType::CgStructuralElement *current = NULL; - int embeddedConstants = 0; - int rootChildIndex = -1; - - int i; - for (i = 0; i < (int)nvbr->number_of_params(); i++) - { - CGtype type; - CGresource res; - CGenum var; - int rin; - const char *name; - std::vector dv; - std::vector ec; - const char *sem; - CGenum dir; - int no; - bool is_referenced; - bool is_shared; - nvbr->get_param( i, type, res, var, rin, &name, dv, ec, &sem, no, is_referenced, is_shared ); - - - if (strlen(sem)>=2 && sem[0] == 'C') - { - const char *szSem = sem+1; - while (*szSem != '\0') - { - if ( (*szSem) < '0' || (*szSem) > '9') - break; - szSem++; - } - if (*szSem == '\0') - is_shared = 1; - } - - const char *parameterName = name; - const char *structureEnd = NULL; - CgStructureType *container = &root; - int done = 0; - const char * structureStart = parameterName; - while (!done && *structureStart) - { - structureEnd = strpbrk(structureStart, ".["); - - if (structureEnd) - { - if (*structureEnd == '[' && type >= CG_SAMPLER1D && type <= CG_SAMPLERCUBE) - { - const char *closed = strchr(structureEnd, ']'); - const char *somethingElse = strpbrk(closed, ".["); - if (!somethingElse) - structureEnd = NULL; - } - } - - if (structureEnd == NULL) - { - structureEnd = structureStart + strlen(structureStart); - done = 1; - } - - char structName[256]; - int length = (int)(structureEnd - structureStart); - strncpy(structName, structureStart, length); - structName[length] = '\0'; - - CgStructureType::CgStructuralElement *structuralElement = NULL; - int j=0; - int elementCount = (int)container->_elements.size(); - for (j=0;j_elements[j]; - if (!strcmp(structuralElement->_name,structName)) - { - if ( (no == -1 && (structuralElement->_flags & CGPF_GLOBAL)) || - (no != -1 && !(structuralElement->_flags & CGPF_GLOBAL))) - break; - } - } - if (j==elementCount) - { - if (container == &root) - { - if (rootChildIndex != j) - rootChildIndex = j; - } - - container->_elements.resize(elementCount+1); - structuralElement = &container->_elements[elementCount]; - strncpy(structuralElement->_name,structName,sizeof(structuralElement->_name)); - structuralElement->_name[sizeof(structuralElement->_name)-1] = '\0'; - structuralElement->_flags = getFlags(var,dir,no,is_referenced,is_shared,paramIndex); - int dimensionCount = 0; - - if (strncmp(sem, "COLOR", 5) == 0 || strncmp(sem, "NORMAL", 6) == 0) - structuralElement->_flags |= CGP_NORMALIZE; - - - int isStructure = (*structureEnd == '.'); - if (*structureEnd == '[') - { - dimensionCount++; - const char *arrayEnd = strchr(structureEnd,']')+1; - while (*arrayEnd == '[') - { - arrayEnd = strchr(arrayEnd,']')+1; - dimensionCount++; - } - if (*arrayEnd == '.') - isStructure = true; - } - - if (dimensionCount) - { - CgArrayType *arrayType = new CgArrayType; - arrayType->_dimensionCount = dimensionCount; - arrayType->_dimensionItemCountsOffset = (unsigned short)containers._dimensions.size(); - int k; - for (k=0;k_type = arrayType; - if (isStructure) - { - container = new CgStructureType; - container->_insideArray = true; - arrayType->_elementType = container; - } - else - { - arrayType->_elementType = new CgBaseType; - arrayType->_elementType->_type = type - CG_TYPE_START_ENUM; - } - arrayType->_elementType->_resource = res; - arrayType->_elementType->_resourceIndex = -1; - if (bIsVertexProgram && strlen(sem)>=2 && sem[0] == 'C') - { - const char *szSem = sem+1; - while (*szSem != '\0') - { - if ( (*szSem) < '0' || (*szSem) > '9') - break; - szSem++; - } - if (*szSem == '\0') - { - is_shared = 1; - int registerIndex = atoi(sem+1); - structuralElement->_flags |= CGP_CONTIGUOUS; - structuralElement->_flags |= CGPF_SHARED; - structuralElement->_type->_resourceIndex = registerIndex; - } - else - structuralElement->_type->_resourceIndex = (int)containers._resources.size(); - } - else - structuralElement->_type->_resourceIndex = (int)containers._resources.size(); - - structuralElement->_type->_resource = res; - } - else - { - if (isStructure) - { - bool insideArray = container->_insideArray; - container = new CgStructureType; - container->_insideArray = insideArray; - structuralElement->_type = container; - } - else - { - structuralElement->_type = new CgBaseType; - structuralElement->_type->_type = type - CG_TYPE_START_ENUM; - structuralElement->_type->_resource = res; - if (classnames[structuralElement->_type->_type-1] == CG_PARAMETERCLASS_MATRIX) - { - if (bIsVertexProgram) - { - structuralElement->_type->_resourceIndex = (short)rin; - } - else - structuralElement->_type->_resourceIndex = (int)containers._resources.size(); - } - else - { - if (!container->_insideArray) - { - if (bIsVertexProgram) - structuralElement->_type->_resourceIndex = rin; - else - { - if (structuralElement->_flags & CGPV_VARYING) - structuralElement->_type->_resourceIndex = -1; - else - { - structuralElement->_type->_resourceIndex = (int)containers._resources.size(); - containers._resources.push_back(CNV2END((unsigned short)rin)); - int size = (int)ec.size(); - containers._resources.push_back(CNV2END((unsigned short)size)); - int k; - for (k=0;k_type->_resourceIndex = (short)-1; - structuralElement->_type->_resource = (unsigned short)res; - } - } - } - } - } - else - { - if (structuralElement->_type->_type == CG_STRUCT+128) - { - container = (CgStructureType*)structuralElement->_type; - } - else if (structuralElement->_type->_type == CG_ARRAY+128) - { - CgArrayType *arrayType = (CgArrayType *)structuralElement->_type; - if (arrayType->_elementType->_type >128 ) - { - container = (CgStructureType*)arrayType->_elementType; - } - } - } - - if (dv.size()) - { - int size = (int)containers._defaultValuesIndices.size(); - if (!size || (containers._defaultValuesIndices[size-2] != CNV2END((unsigned short)(rootChildIndex)))) - { - containers._defaultValuesIndices.push_back(CNV2END((unsigned short)(rootChildIndex))); - containers._defaultValuesIndices.push_back(CNV2END((unsigned short)defaultValues.size())); - } - } - - if (container->_insideArray && done) - { - if (is_referenced) - { - bool sharedContiguous = (structuralElement->_flags & CGPF_SHARED) && (structuralElement->_flags & CGP_CONTIGUOUS); - structuralElement->_flags = getFlags(var,dir,no,is_referenced,is_shared,paramIndex); - if (sharedContiguous) - structuralElement->_flags |= ( CGP_CONTIGUOUS | CGPF_SHARED); - } - if (bIsVertexProgram) - { - if (!is_shared) - containers._resources.push_back(CNV2END((unsigned short)rin)); - } - else - { - if (structuralElement->_flags & CGPV_VARYING) - containers._resources.push_back(CNV2END((unsigned short)rin)); - else - { - containers._resources.push_back(CNV2END((unsigned short)rin)); - int size = (int)ec.size(); - containers._resources.push_back(CNV2END((unsigned short)size)); - int k; - for (k=0;k_type; - if (itemType->_type >= 128) - { - arrayType = (CgArrayType *)itemType; - int dimensionCount = 0; - while (*arrayStart == '[' && dimensionCount_dimensionCount) - { - arrayEnd = strchr(arrayStart+1,']'); - int length =(int)(arrayEnd - arrayStart - 1); - char indexString[16]; - strncpy(indexString,arrayStart+1,length); - indexString[length] = '\0'; - int index = atoi(indexString); - int dim = CNV2END(containers._dimensions[arrayType->_dimensionItemCountsOffset + dimensionCount]); - if ((index+1) > dim) - containers._dimensions[arrayType->_dimensionItemCountsOffset + dimensionCount] = CNV2END((short)(index+1)); - arrayCellIndex += index*getSizeofSubArray(containers,arrayType->_dimensionItemCountsOffset + dimensionCount,arrayType->_dimensionCount - dimensionCount -1,endianness); - arrayStart = arrayEnd+1; - dimensionCount++; - } - structureEnd = arrayStart; - - itemType = arrayType->_elementType; - if (itemType->_type<128) - { - int rowCount = rows[itemType->_type-1]; - if (!rowCount) - { - bool sharedContiguous = (structuralElement->_flags & CGPF_SHARED) && (structuralElement->_flags & CGP_CONTIGUOUS); - if (!bIsVertexProgram || !sharedContiguous) - { - containers._resources.push_back(CNV2END((unsigned short)rin)); - } - - if (!bIsVertexProgram) - { - int size = (int)ec.size(); - containers._resources.push_back(CNV2END((unsigned short)size)); - int k; - for (k=0;k_type <128) - { - if (structuralElement != current) - { - embeddedConstants = 0; - current = structuralElement; - } - - int length =(int)(arrayEnd - arrayStart - 1); - char indexString[16]; - strncpy(indexString,arrayStart+1,length); - indexString[length] = '\0'; - - if (bIsVertexProgram) - { - if (arrayType) - { - bool sharedContiguous = (structuralElement->_flags & CGPF_SHARED) && (structuralElement->_flags & CGP_CONTIGUOUS); - if (!sharedContiguous) - { - containers._resources.push_back(CNV2END((unsigned short)rin)); - } - } - } - else - { - containers._resources.push_back(CNV2END((unsigned short)rin)); - int size = (int)ec.size(); - containers._resources.push_back(CNV2END((unsigned short)size)); - int k; - for (k=0;k_flags & CGPF_SHARED) && (structuralElement->_flags & CGP_CONTIGUOUS); - - unsigned short flag = getFlags(var,dir,no,is_referenced,is_shared,paramIndex); - structuralElement->_flags = flag; - - if (sharedContiguous) - structuralElement->_flags |= ( CGP_CONTIGUOUS | CGPF_SHARED); - - structuralElement->_type->_resource = res; - if (arrayType) - arrayType->_elementType->_resource = res; - } - } - - - if (done && dv.size()) - { - for ( int jj = 0; jj < (int)dv.size(); ++jj ) - { - defaultValues.push_back(dv[jj]); - } - } - - if (done) - { - if (strlen(sem)) - { - strncpy(structuralElement->_semantic,sem,sizeof(structuralElement->_semantic)); - } - else - structuralElement->_semantic[0] = '\0'; - } - structureStart = structureEnd+1; - } - } - - nvbr->release(); - bin_io::delete_instance(); - - std::vector parameterEntries; - std::vector parameterResources; - fillStructureItems(containers,&root,endianness,parameterEntries,parameterResources,stringTable); - - CgParameterTableHeader header; - memset(&header,0,sizeof(CgParameterTableHeader)); - header.entryCount = (unsigned short)parameterEntries.size(); - header.resourceTableOffset = sizeof(CgParameterTableHeader) + (unsigned short)(parameterEntries.size()*sizeof(parameterEntries[0]) + parameterResources.size()*sizeof(parameterResources[0])); - header.defaultValueIndexTableOffset = header.resourceTableOffset + (unsigned short)containers._resources.size() * sizeof(containers._resources[0]); - header.defaultValueIndexCount = (unsigned short)containers._elfDefaultsIndices.size()/2; - header.semanticIndexTableOffset = header.defaultValueIndexTableOffset + (unsigned short)containers._elfDefaultsIndices.size() * sizeof (containers._elfDefaultsIndices[0]); - header.semanticIndexCount = (unsigned short)containers._semanticIndices.size(); - - header.entryCount = CNV2END(header.entryCount); - header.resourceTableOffset = CNV2END(header.resourceTableOffset); - header.defaultValueIndexTableOffset = CNV2END(header.defaultValueIndexTableOffset); - header.defaultValueIndexCount = CNV2END(header.defaultValueIndexCount); - header.semanticIndexTableOffset = CNV2END(header.semanticIndexTableOffset); - header.semanticIndexCount = CNV2END(header.semanticIndexCount); - - size_t parameterTableSize = sizeof(CgParameterTableHeader); - parameterTableSize += array_size(parameterEntries); - parameterTableSize += array_size(parameterResources); - parameterTableSize += array_size(containers._resources); - parameterTableSize += array_size(containers._elfDefaultsIndices); - parameterTableSize += array_size(containers._semanticIndices); - - int ucodeOffset = (((sizeof(CgProgramHeader)-1)/16)+1)*16; - size_t programSize = ucodeOffset + ucodeSize + parameterTableSize; - char *program = new char[programSize]; - - memcpy(program,&cgShader,sizeof(CgProgramHeader)); - if (ucodeOffset-sizeof(CgProgramHeader)) - memset(program+sizeof(CgProgramHeader),0,ucodeOffset-sizeof(CgProgramHeader)); - - memcpy(program + ucodeOffset,ucode,ucodeSize); - if (!bIsVertexProgram && doSwap) - delete[] buffer; - else - delete[] buffer; - - char *parameterOffset = program + ucodeOffset + ucodeSize; - - memcpy(parameterOffset,&header,sizeof(CgParameterTableHeader)); - parameterOffset += sizeof(CgParameterTableHeader); - array_push(parameterOffset, parameterEntries); - array_push(parameterOffset, parameterResources); - array_push(parameterOffset, containers._resources); - array_push(parameterOffset, containers._elfDefaultsIndices); - array_push(parameterOffset, containers._semanticIndices); - - *binarySize = (int)programSize; - *binaryShader = program; - - return 0; -} - -int convertNvToElfFreeBinaryShader(void *binaryShader) -{ - char *program = (char *)binaryShader; - delete[] program; - return 0; -} - -static void pushbackUnsignedShort(std::vector ¶meterResources, unsigned short value) -{ - size_t size = parameterResources.size(); - parameterResources.resize(size + 2); - *((unsigned short*)¶meterResources[size]) = value; -} - -static void fillStructureItems(_CGNVCONTAINERS &containers, CgStructureType *structure, int endianness, - std::vector ¶meterEntries,std::vector ¶meterResources, - std::vector &stringTable, unsigned short *arrayResourceIndex, unsigned short *arrayDefaultValueIndex) -{ - unsigned char elfEndianness = endianness; - - int currentDefaultIndex = 0; - int count = (int)structure->_elements.size(); - int i; - for (i=0;i_elements[i]; - size_t size = parameterEntries.size(); - parameterEntries.resize(size+1); - CgParameterEntry *parameterEntry = ¶meterEntries[size]; - parameterEntry->nameOffset = CNV2END((int)stringTableAddUnique(stringTable, structuralElement->_name)); - if (structuralElement->_semantic[0]) - { - CgParameterSemantic semantic; - semantic.entryIndex = CNV2END((unsigned short)size); - semantic.reserved = 0; - semantic.semanticOffset = CNV2END((int)stringTableAddUnique(stringTable, structuralElement->_semantic)); - containers._semanticIndices.push_back(semantic); - } - parameterEntry->flags = CNV2END(structuralElement->_flags); - unsigned short typeIndex = ((unsigned short)parameterResources.size()); - parameterEntry->typeIndex = CNV2END(typeIndex); - - CgBaseType *itemType = structuralElement->_type; - unsigned short _resource = itemType->_resource; - unsigned short _resourceIndex = itemType->_resourceIndex; - - int parameterEntryIndex; - - if (itemType->_type-128 == CG_ARRAY) - { - CgArrayType *arrayType = (CgArrayType *)structuralElement->_type; - int arraySize = getSizeofSubArray(containers,arrayType->_dimensionItemCountsOffset,arrayType->_dimensionCount,endianness); - itemType = arrayType->_elementType; - unsigned short arrayFlag = CGP_ARRAY; - parameterEntry->flags |= CNV2END(arrayFlag); - parameterResources.resize(typeIndex+sizeof(CgParameterArray)); - - CgParameterArray *parameterArray = (CgParameterArray *)(¶meterResources[typeIndex]); - if (itemType->_type-128 == CG_STRUCT ) - parameterArray->arrayType = CNV2END((unsigned short)CG_STRUCT); - else - parameterArray->arrayType = CNV2END(itemType->_type+128); - parameterArray->dimensionCount = CNV2END((unsigned short)arrayType->_dimensionCount); - int j; - for (j=0;j_dimensionCount;j++) - { - pushbackUnsignedShort(parameterResources,(unsigned short)containers._dimensions[arrayType->_dimensionItemCountsOffset+j]); - } - if (arrayType->_dimensionCount&1) - pushbackUnsignedShort(parameterResources,CNV2END((unsigned short)0)); - - if (itemType->_type-128 == CG_STRUCT ) - { - unsigned short unrolledFlag = CGP_UNROLLED; - parameterEntry->flags |= CNV2END(unrolledFlag); - CgStructureType *structureType = (CgStructureType*)itemType; - int k; - - unsigned short _arrayResourceIndex = (unsigned short)(arrayType->_resourceIndex); - unsigned short _arrayDefaultValueIndex = 0; - - bool hasDefaults = false; - if (structure->_root && containers._defaultValuesIndices.size()) - { - if (containers._defaultValuesIndices[currentDefaultIndex*2] == CNV2END((unsigned short)i)) - { - hasDefaults = true; - _arrayDefaultValueIndex = containers._defaultValuesIndices[currentDefaultIndex*2+1]; - } - } - - for (k=0;k_name,k); - parameterArrayEntry.nameOffset = CNV2END((int)stringTableAddUnique(stringTable, buffer)); - parameterArrayEntry.flags = CNV2END(structuralElement->_flags); - unsigned short structureFlag = CGP_STRUCTURE; - parameterArrayEntry.flags |= CNV2END(structureFlag); - - unsigned short arrayEntryTypeIndex = (unsigned short)parameterResources.size(); - parameterResources.resize(arrayEntryTypeIndex+sizeof(CgParameterStructure)); - parameterArrayEntry.typeIndex = CNV2END(arrayEntryTypeIndex); - - CgParameterStructure *parameterStructure = (CgParameterStructure*)(¶meterResources[arrayEntryTypeIndex]); - parameterStructure->memberCount = CNV2END((unsigned short)structureType->_elements.size()); - parameterStructure->reserved = CNV2END((unsigned short)0); - - if (hasDefaults) - fillStructureItems(containers,structureType,endianness,parameterEntries,parameterResources,stringTable,&_arrayResourceIndex,&_arrayDefaultValueIndex); - else - fillStructureItems(containers,structureType,endianness,parameterEntries,parameterResources,stringTable,&_arrayResourceIndex); - } - - if (hasDefaults) - { - currentDefaultIndex++; - } - continue; - } - else - { - size_t size = parameterEntries.size(); - parameterEntries.resize(size+1); - parameterEntry = ¶meterEntries[size]; - parameterEntry->nameOffset = CNV2END(0); - parameterEntry->flags = CNV2END(structuralElement->_flags); - - typeIndex = ((unsigned short)parameterResources.size()); - parameterEntry->typeIndex = CNV2END(typeIndex); - - parameterEntryIndex = (int)size - 1; - } - } - else - { - unsigned short contiguousFlag = CGP_CONTIGUOUS; - parameterEntry->flags |= CNV2END(contiguousFlag); - size_t size = parameterEntries.size(); - parameterEntryIndex = (int)size - 1; - } - - if (itemType->_type<128) - { - parameterResources.resize(typeIndex+sizeof(CgParameterResource)); - CgParameterResource *parameterResource = (CgParameterResource*)(¶meterResources[typeIndex]); - - if (itemType->_type + CG_TYPE_START_ENUM == CG_BOOL) - { - parameterResource->type = CNV2END((unsigned short)CGP_SCF_BOOL); - } - else - { - parameterResource->type = CNV2END((unsigned short)(itemType->_type + CG_TYPE_START_ENUM)); - } - - if ((structuralElement->_flags & CGPV_MASK) == CGPV_UNIFORM || (structuralElement->_flags & CGPV_MASK) == CGPV_CONSTANT) - { - if (itemType->_type +CG_TYPE_START_ENUM >= CG_SAMPLER1D && itemType->_type +CG_TYPE_START_ENUM<= CG_SAMPLERCUBE) - parameterResource->resource = CNV2END(_resource); - else - { - if (arrayResourceIndex) - { - unsigned short tmp = *arrayResourceIndex; - unsigned short localflags = CNV2END(parameterEntry->flags); - if (!bIsVertexProgram) - { - parameterResource->resource = CNV2END(tmp); - int embeddedConstantCount = CNV2END(containers._resources[tmp+1]); - (*arrayResourceIndex) = tmp+1+1+embeddedConstantCount; - if (embeddedConstantCount == 0 && (CNV2END(containers._resources[tmp]) == 0)) - { - if (parameterResource->resource == 0xffff) - localflags &= ~CGPF_REFERENCED; - } - } - else - { - - if (structuralElement->_flags & CGPF_SHARED) - { - int stride = getStride(itemType); - parameterResource->resource = *arrayResourceIndex; - (*arrayResourceIndex) = tmp+stride; - } - else - { - parameterResource->resource = containers._resources[tmp]; - (*arrayResourceIndex) = tmp+1; - } - - if (parameterResource->resource == 0xffff) - localflags &= ~CGPF_REFERENCED; - } - parameterEntry->flags = CNV2END(localflags); - } - else - parameterResource->resource = CNV2END(_resourceIndex); - } - } - else - { - parameterResource->resource = CNV2END(itemType->_resource); - } - - if (containers._defaultValuesIndices.size()) - { - if (structure->_root) - { - if (currentDefaultIndex < (int)(containers._defaultValuesIndices.size()/2) && containers._defaultValuesIndices[currentDefaultIndex*2] == CNV2END((unsigned short)i)) - { - containers._elfDefaultsIndices.push_back(CNV2END((unsigned short)(parameterEntryIndex))); - containers._elfDefaultsIndices.push_back(containers._defaultValuesIndices[currentDefaultIndex*2+1]); - currentDefaultIndex++; - } - } - else if (arrayDefaultValueIndex) - { - containers._elfDefaultsIndices.push_back(CNV2END((unsigned short)(parameterEntryIndex))); - containers._elfDefaultsIndices.push_back(*arrayDefaultValueIndex); - - int typeRegisterCount = getStride(itemType); - *arrayDefaultValueIndex = CNV2END( (unsigned short)((CNV2END((*arrayDefaultValueIndex)))+typeRegisterCount*4)); - - } - } - } - else if (itemType->_type == CG_STRUCT + 128) - { - unsigned short structureFlag = CGP_STRUCTURE; - parameterEntry->flags |= CNV2END(structureFlag); - - CgStructureType *structureType = (CgStructureType*)itemType; - parameterResources.resize(typeIndex+sizeof(CgParameterStructure)); - CgParameterStructure *parameterStructure = (CgParameterStructure*)(¶meterResources[typeIndex]); - parameterStructure->memberCount = CNV2END((unsigned short)structureType->_elements.size()); - parameterStructure->reserved = CNV2END((unsigned short)0); - - fillStructureItems(containers,structureType,endianness,parameterEntries,parameterResources,stringTable); - - if (containers._defaultValuesIndices.size() && structure->_root) - { - if (currentDefaultIndex < (int)(containers._defaultValuesIndices.size()/2) && containers._defaultValuesIndices[currentDefaultIndex*2] == CNV2END((unsigned short)i)) - { - containers._elfDefaultsIndices.push_back(CNV2END((unsigned short)(parameterEntryIndex))); - containers._elfDefaultsIndices.push_back(containers._defaultValuesIndices[currentDefaultIndex*2+1]); - currentDefaultIndex++; - } - } - } - } -} - - -static int getStride(CgBaseType *type) -{ - if (type->_type <128) - { - if (classnames[type->_type-1] == CG_PARAMETERCLASS_MATRIX) - return rows[type->_type-1]; - else - return 1; - } - else - { - if (type->_type == CG_STRUCT + 128) - { - CgStructureType *structureType = (CgStructureType *)type; - int res = 0; - int i; - int count = (int)structureType->_elements.size(); - for (i=0;i_elements[i]._type); - return res; - } - else - { - return -9999999; - } - } -} - -static int getSizeofSubArray(_CGNVCONTAINERS &containers, int dimensionIndex, int dimensionCount, int endianness) -{ - unsigned char elfEndianness = endianness; - int res = 1; - int i; - for (i=0;i static size_t array_size(std::vector &array) -{ - return (unsigned int)array.size()*sizeof(array[0]); -} - -template static void array_push(char* ¶meterOffset, std::vector &array) -{ - size_t dataSize = array.size()*sizeof(array[0]); - memcpy(parameterOffset,&array[0],dataSize); - parameterOffset += dataSize; -} - -unsigned int inline static swap16(const unsigned int v) -{ - return (v>>16) | (v<<16); -} - -unsigned short getFlags(CGenum var, CGenum dir, int no, bool is_referenced, bool is_shared, int paramIndex) -{ - (void)paramIndex; - unsigned short flags = 0; - - if (var == CG_VARYING) - flags |= CGPV_VARYING; - else if (var == CG_UNIFORM) - flags |= CGPV_UNIFORM; - else if (var == CG_CONSTANT) - flags |= CGPV_CONSTANT; - else if (var == CG_MIXED) - flags |= CGPV_MIXED; - - if (is_referenced) - flags |= CGPF_REFERENCED; - if (is_shared) - flags |= CGPF_SHARED; - - if (no == -1) - flags |= CGPF_GLOBAL; - else if (no == -2) - flags |= CGP_INTERNAL; - else - { - paramIndex = no; - } - return flags; -} diff --git a/console/rgl/ps3/device_ctx.cpp b/console/rgl/ps3/device_ctx.cpp deleted file mode 100644 index 887d331f3c..0000000000 --- a/console/rgl/ps3/device_ctx.cpp +++ /dev/null @@ -1,1324 +0,0 @@ -#include -#include "rgl.h" -#include "private.h" -#include -#ifdef __PSL1GHT__ -#include -#else -#include -#include -#include -#endif -#include "../../../ps3/sdk_defines.h" - -#ifdef __PSL1GHT__ -#include -#else -#include -#include -#endif - -#include "../../../general.h" - -#ifndef __PSL1GHT__ -using namespace cell::Gcm; -#endif - -#define MAX_TILED_REGIONS 15 - -#define TILED_BUFFER_ALIGNMENT 0x10000 -#define TILED_BUFFER_HEIGHT_ALIGNMENT 64 - -#define FIFO_SIZE (65536) -#define _RGL_DMA_PUSH_BUFFER_PREFETCH_PADDING 0x1000 -#define UTIL_LABEL_INDEX 253 - -extern void _RGLFifoGlSetRenderTarget( RGLRenderTargetEx const * const args ); - -typedef struct -{ - jsTiledRegion region[MAX_TILED_REGIONS]; -} jsTiledMemoryManager; - -PSGLdevice *_CurrentDevice = NULL; - -static GLboolean _RGLDuringDestroyDevice = GL_FALSE; -static jsTiledMemoryManager _RGLTiledMemoryManager; -static RGLResource _RGLResource; -static sys_semaphore_t FlipSem; -static volatile uint32_t *labelAddress = NULL; -static const uint32_t WaitLabelIndex = 111; -extern GLuint nvFenceCounter; -RGLState _RGLState; - -extern GmmAllocator *pGmmLocalAllocator; -extern GmmAllocator *pGmmMainAllocator; - -typedef struct -{ - int width; - int height; - unsigned char hwMode; -} VideoMode; - -static const VideoMode sysutilModes[] = -{ - {720, 480, CELL_VIDEO_OUT_RESOLUTION_480}, - {720, 576, CELL_VIDEO_OUT_RESOLUTION_576}, - {1280, 720, CELL_VIDEO_OUT_RESOLUTION_720}, - {960, 1080, CELL_VIDEO_OUT_RESOLUTION_960x1080}, - {1280, 1080, CELL_VIDEO_OUT_RESOLUTION_1280x1080}, - {1440, 1080, CELL_VIDEO_OUT_RESOLUTION_1440x1080}, - {1600, 1080, CELL_VIDEO_OUT_RESOLUTION_1600x1080}, - {1920, 1080, CELL_VIDEO_OUT_RESOLUTION_1080}, -}; - -static unsigned int validPitch[] = -{ - 0x0200, - 0x0300, - 0x0400, - 0x0500, - 0x0600, - 0x0700, - 0x0800, - 0x0A00, - 0x0C00, - 0x0D00, - 0x0E00, - 0x1000, - 0x1400, - 0x1800, - 0x1A00, - 0x1C00, - 0x2000, - 0x2800, - 0x3000, - 0x3400, - 0x3800, - 0x4000, - 0x5000, - 0x6000, - 0x6800, - 0x7000, - 0x8000, - 0xA000, - 0xC000, - 0xD000, - 0xE000, - 0x10000, -}; - -static const unsigned int validPitchCount = sizeof( validPitch ) / sizeof( validPitch[0] ); - -static const int sysutilModeCount = sizeof( sysutilModes ) / sizeof( sysutilModes[0] ); - -static inline void _RGLPrintIt( unsigned int v ) -{ - RARCH_LOG( "%02x %02x %02x %02x : \n", ( v >> 24 )&0xff, ( v >> 16 )&0xff, ( v >> 8 )&0xff, v&0xff ); - - for ( unsigned int mask = ( 0x1 << 31 ), i = 1; mask != 0; mask >>= 1, i++ ) - RARCH_LOG("%d%s\n", ( v & mask ) ? 1 : 0, ( i % 8 == 0 ) ? " " : ""); -} - -static inline void _RGLPrintFifoFromPut(unsigned int numWords) -{ - for ( int i = -numWords; i <= -1; i++ ) - _RGLPrintIt((( uint32_t* )_RGLState.fifo.current )[i]); -} - -static inline void _RGLPrintFifoFromGet(unsigned int numWords) -{ - for ( int i = -numWords; i <= -1; i++) - _RGLPrintIt((( uint32_t* )_RGLState.fifo.lastGetRead )[i]); -} - -static GLuint _RGLFifoReadReference(RGLFifo *fifo) -{ - GLuint ref = *((volatile GLuint *) & fifo->dmaControl->Reference ); - fifo->lastHWReferenceRead = ref; - return ref; -} - -static GLboolean _RGLFifoReferenceInUse(RGLFifo *fifo, GLuint reference) -{ - if (!((fifo->lastHWReferenceRead - reference) & 0x80000000)) - return GL_FALSE; - - if ((fifo->lastSWReferenceFlushed - reference) & 0x80000000) - _RGLFifoFlush( fifo ); - - _RGLFifoReadReference( fifo ); - - if (!((fifo->lastHWReferenceRead - reference) & 0x80000000)) - return GL_FALSE; - - return GL_TRUE; -} - -static GLuint _RGLFifoPutReference(RGLFifo *fifo) -{ - fifo->lastSWReferenceWritten++; - - cellGcmSetReferenceCommandInline(&_RGLState.fifo, fifo->lastSWReferenceWritten); - - if ((fifo->lastSWReferenceWritten & 0x7fffffff) == 0) - _RGLFifoFinish(fifo); - - return fifo->lastSWReferenceWritten; -} - -void _RGLFifoFinish(RGLFifo *fifo) -{ - GLuint ref = _RGLFifoPutReference(fifo); - - _RGLFifoFlush( fifo ); - - for (;;) - { - if (!_RGLFifoReferenceInUse(fifo, ref)) - break; - } -} - -static void _RGLFifoInit(RGLFifo *fifo, void *dmaControl, unsigned long dmaPushBufferOffset, uint32_t *dmaPushBuffer, GLuint dmaPushBufferSize) -{ - fifo->fifoBlockSize = DEFAULT_FIFO_BLOCK_SIZE; - fifo->begin = ( uint32_t * ) dmaPushBuffer; - fifo->end = fifo->begin + ( fifo->fifoBlockSize / sizeof( uint32_t ) ) - 1; - fifo->current = fifo->begin; - fifo->lastGetRead = fifo->current; - fifo->lastPutWritten = fifo->current; - - fifo->dmaPushBufferBegin = dmaPushBuffer; - fifo->dmaPushBufferEnd = ( uint32_t * )(( size_t )dmaPushBuffer + dmaPushBufferSize ) - 1; - fifo->dmaControl = ( RGLControlDma* )dmaControl; - fifo->dmaPushBufferOffset = dmaPushBufferOffset; - fifo->dmaPushBufferSizeInWords = dmaPushBufferSize / sizeof( uint32_t ); - - fifo->lastHWReferenceRead = 0; - fifo->lastSWReferenceWritten = 0; - fifo->lastSWReferenceFlushed = 0; - - gCellGcmCurrentContext = fifo; - gCellGcmCurrentContext->callback = ( CellGcmContextCallback )_RGLOutOfSpaceCallback; - - if ( _RGLFifoReadReference( fifo ) != 0 ) - { - cellGcmSetReferenceCommandInline ( &_RGLState.fifo, 0); - _RGLFifoFlush( fifo ); - - for ( ;; ) - { - if ( _RGLFifoReadReference( fifo ) == 0 ) - break; - } - } - fifo->dmaPushBufferGPU = dmaPushBuffer; - fifo->spuid = 0; -} - -static GLboolean _RGLInitFromRM( RGLResource *rmResource ) -{ - RGLState *RGLSt = &_RGLState; - RGLInterpolantState *s = &_RGLState.state.interpolant; - RGLBlendState *blend = &_RGLState.state.blend; - GLfloat ref; - GLuint i, hwColor; - - ref = 0.0f; - - memset( RGLSt, 0, sizeof( *RGLSt ) ); - - RGLSt->localAddress = rmResource->localAddress; - RGLSt->hostMemoryBase = rmResource->hostMemoryBase; - RGLSt->hostMemorySize = rmResource->hostMemorySize; - - RGLSt->semaphores = rmResource->semaphores; - - _RGLFifoInit( &RGLSt->fifo, rmResource->dmaControl, rmResource->dmaPushBufferOffset, ( uint32_t * )rmResource->dmaPushBuffer, rmResource->dmaPushBufferSize ); - - _RGLFifoFinish( &RGLSt->fifo ); - - RGL_CALC_COLOR_LE_ARGB8( &hwColor, RGL_CLAMPF_01(0.0f), RGL_CLAMPF_01(0.0f), RGL_CLAMPF_01(0.0f), RGL_CLAMPF_01(0.0f) ); - - blend->alphaFunc = CELL_GCM_ALWAYS; - blend->alphaRef = ref; - - ref = RGL_CLAMPF_01(ref); - - cellGcmSetAlphaFunc( &_RGLState.fifo, CELL_GCM_ALWAYS, RGL_QUICK_FLOAT2UINT( ref * 255.0f )); - cellGcmSetBlendColor( &_RGLState.fifo, hwColor, hwColor); - cellGcmSetBlendEquation( &_RGLState.fifo, CELL_GCM_FUNC_ADD, CELL_GCM_FUNC_ADD ); - cellGcmSetBlendFunc( &_RGLState.fifo, CELL_GCM_ONE, CELL_GCM_ZERO, CELL_GCM_ONE, CELL_GCM_ZERO ); - cellGcmSetClearColor( &_RGLState.fifo, hwColor); - cellGcmSetScissor( &_RGLState.fifo, 0, 0, 4095, 4095); - cellGcmSetVertexAttribOutputMask( &_RGLState.fifo, s->vertexProgramAttribMask & s->fragmentProgramAttribMask); - - cellGcmSetPointSpriteControl( &_RGLState.fifo, CELL_GCM_FALSE, 1, 0); - cellGcmSetFrequencyDividerOperation( &_RGLState.fifo, 0); - - cellGcmSetRestartIndex( &_RGLState.fifo, 0); - cellGcmSetShadeMode( &_RGLState.fifo, CELL_GCM_SMOOTH); - - for (i = 0; i < CELL_GCM_MAX_TEXIMAGE_COUNT; i++) - { - cellGcmSetTextureAddress( &_RGLState.fifo, i, CELL_GCM_TEXTURE_WRAP, CELL_GCM_TEXTURE_WRAP, CELL_GCM_TEXTURE_CLAMP_TO_EDGE, CELL_GCM_TEXTURE_UNSIGNED_REMAP_NORMAL, CELL_GCM_TEXTURE_ZFUNC_NEVER, 0 ); - cellGcmSetTextureFilter( &_RGLState.fifo, i, 0, CELL_GCM_TEXTURE_NEAREST_LINEAR, CELL_GCM_TEXTURE_LINEAR, CELL_GCM_TEXTURE_CONVOLUTION_QUINCUNX ); - cellGcmSetTextureControl( &_RGLState.fifo, i, CELL_GCM_TRUE, 0, 12 << 8, CELL_GCM_TEXTURE_MAX_ANISO_1 ); - } - - _RGLFifoGlViewport( 0, 0, CELL_GCM_MAX_RT_DIMENSION, CELL_GCM_MAX_RT_DIMENSION, 0.0f, 1.0f ); - - _RGLFifoFinish( &RGLSt->fifo ); - - return GL_TRUE; -} - -GLboolean _RGLInit(PSGLinitOptions* options, RGLResource *resource) -{ - if (!_RGLInitFromRM(resource)) - { - RARCH_ERR("RGL GCM failed initialisation.\n"); - return GL_FALSE; - } - - if ( gmmInit( resource->localAddress, - resource->localAddress, - resource->localSize, - resource->hostMemoryBase, - resource->hostMemoryBase + resource->hostMemoryReserved, - resource->hostMemorySize - resource->hostMemoryReserved ) == GMM_ERROR ) - { - RARCH_ERR("Could not initialize GPU memory manager.\n"); - _RGLDestroy(); - return GL_FALSE; - } - - _RGLState.semaphores->userSemaphores[SEMA_FENCE].val = nvFenceCounter; - - _RGLState.labelValue = 1; - - return GL_TRUE; -} - -void _RGLDestroy(void) -{ - RGLState *RGLSt = &_RGLState; - memset( RGLSt, 0, sizeof( *RGLSt ) ); -} - -static inline int rescIsEnabled(PSGLdeviceParameters* params) -{ - return params->enable & ( PSGL_DEVICE_PARAMETERS_RESC_RENDER_WIDTH_HEIGHT | - PSGL_DEVICE_PARAMETERS_RESC_RATIO_MODE | - PSGL_DEVICE_PARAMETERS_RESC_PAL_TEMPORAL_MODE | - PSGL_DEVICE_PARAMETERS_RESC_INTERLACE_MODE | - PSGL_DEVICE_PARAMETERS_RESC_ADJUST_ASPECT_RATIO ); -} - -static inline const VideoMode *findModeByResolution(int width, int height) -{ - for (int i = 0; i < sysutilModeCount; ++i) - { - const VideoMode *vm = sysutilModes + i; - if (( vm->width == width ) && ( vm->height == height ) ) return vm; - } - return NULL; -} - -static const VideoMode *findModeByEnum( GLenum TVStandard ) -{ - const VideoMode *vm = NULL; - switch ( TVStandard ) - { - case PSGL_TV_STANDARD_NTSC_M: - case PSGL_TV_STANDARD_NTSC_J: - case PSGL_TV_STANDARD_HD480P: - case PSGL_TV_STANDARD_HD480I: - vm = &(sysutilModes[0]); - break; - case PSGL_TV_STANDARD_PAL_M: - case PSGL_TV_STANDARD_PAL_B: - case PSGL_TV_STANDARD_PAL_D: - case PSGL_TV_STANDARD_PAL_G: - case PSGL_TV_STANDARD_PAL_H: - case PSGL_TV_STANDARD_PAL_I: - case PSGL_TV_STANDARD_PAL_N: - case PSGL_TV_STANDARD_PAL_NC: - case PSGL_TV_STANDARD_HD576I: - case PSGL_TV_STANDARD_HD576P: - vm = &(sysutilModes[1]); - break; - case PSGL_TV_STANDARD_HD720P: - case PSGL_TV_STANDARD_1280x720_ON_VESA_1280x768: - case PSGL_TV_STANDARD_1280x720_ON_VESA_1280x1024: - vm = &(sysutilModes[2]); - break; - case PSGL_TV_STANDARD_HD1080I: - case PSGL_TV_STANDARD_HD1080P: - case PSGL_TV_STANDARD_1920x1080_ON_VESA_1920x1200: - vm = &(sysutilModes[3]); - break; - default: - vm = &(sysutilModes[2]); - break; - } - - return vm; -} - -static VideoMode _sysutilDetectedVideoMode; - -const VideoMode *_RGLDetectVideoMode (void) -{ - CellVideoOutState videoState; - int ret = cellVideoOutGetState( CELL_VIDEO_OUT_PRIMARY, 0, &videoState ); - if ( ret < 0 ) - { - RARCH_WARN("Couldn't read the video configuration, using a default 720p resolution.\n"); - videoState.displayMode.scanMode = CELL_VIDEO_OUT_SCAN_MODE_PROGRESSIVE; - videoState.displayMode.resolutionId = CELL_VIDEO_OUT_RESOLUTION_720; - } - CellVideoOutResolution resolution; - cellVideoOutGetResolution( videoState.displayMode.resolutionId, &resolution ); - - _sysutilDetectedVideoMode.width = resolution.width; - _sysutilDetectedVideoMode.height = resolution.height; - _sysutilDetectedVideoMode.hwMode = videoState.displayMode.resolutionId; - return &_sysutilDetectedVideoMode; -} - -static void _RGLFlipCallbackFunction(const uint32_t head) -{ - int res = sys_semaphore_post(FlipSem,1); - (void)res; -} - -static void _RGLVblankCallbackFunction(const uint32_t head) -{ - (void)head; - int status = *labelAddress; - - switch(status) - { - case 2: - if (cellGcmGetFlipStatus() == 0) - { - cellGcmResetFlipStatus(); - *labelAddress=1; - } - break; - case 1: - *labelAddress = 0; - break; - default: - break; - } -} - -static void _RGLRescVblankCallbackFunction(const uint32_t head) -{ - (void)head; - int status = *labelAddress; - switch(status) - { - case 2: - if (cellRescGetFlipStatus() == 0) - { - cellRescResetFlipStatus(); - *labelAddress=1; - } - break; - case 1: - *labelAddress = 0; - break; - default: - break; - } -} - -static unsigned int findValidPitch( unsigned int pitch ) -{ - if ( pitch <= validPitch[0] ) return validPitch[0]; - else - { - for ( GLuint i = 0;i < validPitchCount - 1;++i ) - if (( pitch > validPitch[i] ) && ( pitch <= validPitch[i+1] ) ) return validPitch[i+1]; - - return validPitch[validPitchCount-1]; - } -} - -int32_t _RGLOutOfSpaceCallback( struct CellGcmContextData* fifoContext, uint32_t spaceInWords ) -{ - uint32_t *nextbegin, *nextend, nextbeginoffset, nextendoffset; - RGLFifo * fifo = &_RGLState.fifo; - - cellGcmFlushUnsafeInline((CellGcmContextData*)fifo); - - uint32_t * tmp = ( uint32_t * )(( char* )fifo->dmaPushBufferBegin - fifo->dmaPushBufferOffset + ( *(( volatile GLuint* ) & fifo->dmaControl->Get ) ) ); - if (( tmp >= fifo->begin ) && ( tmp <= fifo->end ) ) fifo->lastGetRead = tmp; - - if(fifo->end != fifo->dmaPushBufferEnd) - { - nextbegin = (uint32_t *)fifo->end + 1; - nextend = nextbegin + fifo->fifoBlockSize/sizeof(uint32_t) - 1; - } - else - { - nextbegin = (uint32_t *)fifo->dmaPushBufferBegin; - nextend = nextbegin + (fifo->fifoBlockSize)/sizeof(uint32_t) - 1; - } - - cellGcmAddressToOffset(nextbegin, &nextbeginoffset); - cellGcmAddressToOffset(nextend, &nextendoffset); - - cellGcmSetJumpCommandUnsafeInline((CellGcmContextData*)fifo, nextbeginoffset); - - fifo->begin = nextbegin; - fifo->current = nextbegin; - fifo->end = nextend; - - const GLuint nopsAtBegin = 8; - - uint32_t get = fifo->dmaControl->Get; - - while(((get >= nextbeginoffset) && (get <= nextendoffset)) - || (get < fifo->dmaPushBufferOffset) || (get > fifo->dmaPushBufferOffset + - fifo->dmaPushBufferSizeInWords*sizeof(uint32_t))) - { - get = fifo->dmaControl->Get; - } - - for(GLuint i = 0; i < nopsAtBegin; i++) - { - fifo->current[0] = NOP; - fifo->current++; - } - - return CELL_OK; -}; - -void _RGLGraphicsHandler( const uint32_t head ) -{ - RGLFifo *fifo = &_RGLState.fifo; - - uint32_t *tmp = ( uint32_t * )(( char* )fifo->dmaPushBufferBegin - fifo->dmaPushBufferOffset + ( *(( volatile GLuint* ) & fifo->dmaControl->Get ) ) ); - if (( tmp >= fifo->begin ) && ( tmp <= fifo->end ) ) fifo->lastGetRead = tmp; - - RARCH_ERR("Current PSGL FIFO info:\n" ); - RARCH_ERR("FIFO Begin %p End %p Current %p and Get %p \n", - _RGLState.fifo.begin, _RGLState.fifo.end, _RGLState.fifo.current, - _RGLState.fifo.lastGetRead ); - - RARCH_ERR("Last 10 words of the PSGL Fifo from the ppu put/current position \n" ); - _RGLPrintFifoFromPut( 10 ); - - RARCH_ERR("Last 10 words of the PSGL Fifo from the gpu get position \n" ); - _RGLPrintFifoFromGet( 10 ); -} - -static int _RGLInitRM( RGLResource *gcmResource, unsigned int hostMemorySize, int inSysMem, unsigned int dmaPushBufferSize ) -{ - memset(gcmResource, 0, sizeof(RGLResource)); - - dmaPushBufferSize = _RGLPad(dmaPushBufferSize, HOST_BUFFER_ALIGNMENT); - - gcmResource->hostMemorySize = _RGLPad( FIFO_SIZE + hostMemorySize + dmaPushBufferSize + _RGL_DMA_PUSH_BUFFER_PREFETCH_PADDING + (LM_MAX_TOTAL_QUERIES * sizeof( GLuint )), 1 << 20 ); - - if ( gcmResource->hostMemorySize > 0 ) - gcmResource->hostMemoryBase = ( char * )memalign( 1 << 20, gcmResource->hostMemorySize ); - - if ( cellGcmInit(FIFO_SIZE, gcmResource->hostMemorySize, gcmResource->hostMemoryBase ) != 0 ) - { - RARCH_ERR("RSXIF failed initialization.\n"); - return GL_FALSE; - } - - cellGcmSetDebugOutputLevel( CELL_GCM_DEBUG_LEVEL2 ); - cellGcmSetGraphicsHandler( &_RGLGraphicsHandler ); - - CellGcmConfig config; - cellGcmGetConfiguration( &config ); - - gcmResource->localAddress = ( char * )config.localAddress; - gcmResource->localSize = config.localSize; - gcmResource->MemoryClock = config.memoryFrequency; - gcmResource->GraphicsClock = config.coreFrequency; - - gcmResource->semaphores = ( RGLSemaphoreMemory * )cellGcmGetLabelAddress( 0 ); - gcmResource->dmaControl = ( char* ) cellGcmGetControlRegister() - (( char * ) & (( RGLControlDma* )0 )->Put - ( char * )0 ); - - cellGcmFinish(1); - - gcmResource->hostMemorySize -= dmaPushBufferSize + _RGL_DMA_PUSH_BUFFER_PREFETCH_PADDING; - gcmResource->dmaPushBuffer = gcmResource->hostMemoryBase + gcmResource->hostMemorySize; - gcmResource->dmaPushBufferOffset = ( char * )gcmResource->dmaPushBuffer - ( char * )gcmResource->hostMemoryBase; - gcmResource->dmaPushBufferSize = dmaPushBufferSize; - gcmResource->hostMemoryReserved = FIFO_SIZE; - - cellGcmSetJumpCommand(( char * )gcmResource->dmaPushBuffer - ( char * )gcmResource->hostMemoryBase ); - - gCellGcmCurrentContext->callback = ( CellGcmContextCallback )_RGLOutOfSpaceCallback; - -#ifdef LOG_VERBOSE - RARCH_LOG("MClk: %f Mhz NVClk: %f Mhz.\n", ( float )gcmResource->MemoryClock / 1E6, ( float )gcmResource->GraphicsClock / 1E6 ); - RARCH_LOG("Video Memory: %i MB.\n", gcmResource->localSize / ( 1024*1024 ) ); - RARCH_LOG("Local address mapped at %p.\n", gcmResource->localAddress ); - RARCH_LOG("Push buffer at %p - %p (size = 0x%X), offset=0x%lx.\n", - gcmResource->dmaPushBuffer, ( char* )gcmResource->dmaPushBuffer + gcmResource->dmaPushBufferSize, gcmResource->dmaPushBufferSize, gcmResource->dmaPushBufferOffset ); - RARCH_LOG("DMA control at %p.\n", gcmResource->dmaControl ); -#endif - - return 1; -} - -void _RGLDeviceInit( PSGLinitOptions* options ) -{ - GLuint fifoSize = _RGL_FIFO_SIZE_DEFAULT; - GLuint hostSize = _RGL_HOST_SIZE_DEFAULT; - - if ( options != NULL ) - { - if ( options->enable & PSGL_INIT_FIFO_SIZE ) - fifoSize = options->fifoSize; - if ( options->enable & PSGL_INIT_HOST_MEMORY_SIZE ) - hostSize = options->hostMemorySize; - } - - if ( !_RGLInitRM( &_RGLResource, hostSize, 0, fifoSize ) ) - { - RARCH_ERR("RM resource failed initialization.\n" ); - return; - } - - bool retval = _RGLInit( options, &_RGLResource ); - (void)retval; -} - -static void _RGLDestroyRM( RGLResource* gcmResource ) -{ - if ( gcmResource->hostMemoryBase ) - free( gcmResource->hostMemoryBase ); - - memset(( void* )gcmResource, 0, sizeof( RGLResource ) ); - - return; -} - -void _RGLDeviceExit() -{ - _RGLDestroy(); - _RGLDestroyRM( &_RGLResource ); -} - -static GLuint _RGLAllocCreateRegion(GLuint size, GLint tag, void* data ) -{ - uint32_t id = gmmAlloc(1, size); - - if ( id != GMM_ERROR ) - { - if ( _RGLTryResizeTileRegion( (GLuint)gmmIdToOffset(id), ((GmmBaseBlock *)id)->size, data ) ) - gmmSetTileAttrib( id, tag, data ); - else - { - gmmFree( id ); - id = GMM_ERROR; - } - } - - return id; -} - -GLboolean _RGLAllocateColorSurface( - GLuint width, - GLuint height, - GLuint bitsPerPixel, - GLuint *id, - GLuint *pitchAllocated, - GLuint *bytesAllocated ) -{ - jsTiledMemoryManager* mm = &_RGLTiledMemoryManager; - - const unsigned int pitch = width * bitsPerPixel / 8; - const unsigned int tiledPitch = findValidPitch( pitch ); - if ( tiledPitch < pitch ) - *pitchAllocated = _RGLPad( pitch, tiledPitch ); - else - *pitchAllocated = tiledPitch; - - GLuint padSize = TILED_BUFFER_ALIGNMENT; - while (( padSize % ( tiledPitch*8 ) ) != 0 ) - padSize += TILED_BUFFER_ALIGNMENT; - - height = _RGLPad(height, TILED_BUFFER_HEIGHT_ALIGNMENT); - *bytesAllocated = _RGLPad(( *pitchAllocated ) * height, padSize ); - - const GLuint tag = *pitchAllocated | ( 0x0 ); - - *id = gmmAllocExtendedTileBlock(*bytesAllocated, tag); - - if ( *id == GMM_ERROR ) - { - for ( int i = 0; i < MAX_TILED_REGIONS; ++i ) - { - if ( mm->region[i].size == 0 ) - { - mm->region[i].id = i; - mm->region[i].pitch = *pitchAllocated; - mm->region[i].bank = 0x0; - - *id = _RGLAllocCreateRegion(*bytesAllocated, tag, &mm->region[i] ); - - break; - } - } - } - - if ( *id == GMM_ERROR ) - { - *bytesAllocated = 0; - *pitchAllocated = 0; - } - else - { - RARCH_LOG("Allocating GPU memory (tiled): %d bytes allocated at id 0x%08x.\n", *bytesAllocated, *id ); - } - - return *bytesAllocated > 0; -} - - PSGLdevice* psglCreateDeviceAuto( GLenum colorFormat, GLenum depthFormat, GLenum multisamplingMode ) -{ - PSGLdeviceParameters parameters; - parameters.enable = PSGL_DEVICE_PARAMETERS_COLOR_FORMAT | PSGL_DEVICE_PARAMETERS_DEPTH_FORMAT | PSGL_DEVICE_PARAMETERS_MULTISAMPLING_MODE; - parameters.colorFormat = colorFormat; - parameters.depthFormat = GL_NONE; - parameters.multisamplingMode = GL_MULTISAMPLING_NONE_SCE; - return psglCreateDeviceExtended( ¶meters ); -} - -static void rescInit( const PSGLdeviceParameters* params, RGLDevice *gcmDevice ) -{ - RARCH_WARN("RESC is enabled.\n"); - - CellRescBufferMode dstBufferMode; - if ( params->width == 720 && params->height == 480 ) dstBufferMode = CELL_RESC_720x480; - else if ( params->width == 720 && params->height == 576 ) dstBufferMode = CELL_RESC_720x576; - else if ( params->width == 1280 && params->height == 720 ) dstBufferMode = CELL_RESC_1280x720; - else if ( params->width == 1920 && params->height == 1080 ) dstBufferMode = CELL_RESC_1920x1080; - else - { - dstBufferMode = CELL_RESC_720x480; - RARCH_ERR("Invalid display resolution for resolution conversion: %ux%u. Defaulting to 720x480...\n", params->width, params->height ); - } - - CellRescInitConfig conf; - memset( &conf, 0, sizeof( CellRescInitConfig ) ); - conf.size = sizeof( CellRescInitConfig ); - conf.resourcePolicy = CELL_RESC_MINIMUM_GPU_LOAD | CELL_RESC_CONSTANT_VRAM; - conf.supportModes = CELL_RESC_720x480 | CELL_RESC_720x576 | CELL_RESC_1280x720 | CELL_RESC_1920x1080; - conf.ratioMode = ( params->rescRatioMode == RESC_RATIO_MODE_FULLSCREEN ) ? CELL_RESC_FULLSCREEN : - ( params->rescRatioMode == RESC_RATIO_MODE_PANSCAN ) ? CELL_RESC_PANSCAN : CELL_RESC_LETTERBOX; - conf.palTemporalMode = ( params->rescPalTemporalMode == RESC_PAL_TEMPORAL_MODE_60_DROP ) ? CELL_RESC_PAL_60_DROP : - ( params->rescPalTemporalMode == RESC_PAL_TEMPORAL_MODE_60_INTERPOLATE ) ? CELL_RESC_PAL_60_INTERPOLATE : - ( params->rescPalTemporalMode == RESC_PAL_TEMPORAL_MODE_60_INTERPOLATE_30_DROP ) ? CELL_RESC_PAL_60_INTERPOLATE_30_DROP : - ( params->rescPalTemporalMode == RESC_PAL_TEMPORAL_MODE_60_INTERPOLATE_DROP_FLEXIBLE ) ? CELL_RESC_PAL_60_INTERPOLATE_DROP_FLEXIBLE : CELL_RESC_PAL_50; - conf.interlaceMode = ( params->rescInterlaceMode == RESC_INTERLACE_MODE_INTERLACE_FILTER ) ? CELL_RESC_INTERLACE_FILTER : CELL_RESC_NORMAL_BILINEAR; - cellRescInit( &conf ); - - GLuint size; - GLuint colorBuffersPitch; - uint32_t numColorBuffers = cellRescGetNumColorBuffers( dstBufferMode, ( CellRescPalTemporalMode )conf.palTemporalMode, 0 ); - - _RGLAllocateColorSurface( params->width, params->height * numColorBuffers, - 4*8, &(gcmDevice->RescColorBuffersId), &colorBuffersPitch, &size ); - - CellRescDsts dsts = { CELL_RESC_SURFACE_A8R8G8B8, colorBuffersPitch, 1 }; - cellRescSetDsts( dstBufferMode, &dsts ); - - cellRescSetDisplayMode( dstBufferMode ); - - int32_t colorBuffersSize, vertexArraySize, fragmentShaderSize; - cellRescGetBufferSize( &colorBuffersSize, &vertexArraySize, &fragmentShaderSize ); - gcmDevice->RescVertexArrayId = gmmAlloc(0, vertexArraySize); - - gcmDevice->RescFragmentShaderId = gmmAlloc(0, fragmentShaderSize); - - - cellRescSetBufferAddress( gmmIdToAddress(gcmDevice->RescColorBuffersId), - gmmIdToAddress(gcmDevice->RescVertexArrayId), - gmmIdToAddress(gcmDevice->RescFragmentShaderId) ); - - cellRescAdjustAspectRatio( params->horizontalScale, params->verticalScale ); - - if ((params->enable & PSGL_DEVICE_PARAMETERS_RESC_INTERLACE_MODE) && - (params->rescInterlaceMode == RESC_INTERLACE_MODE_INTERLACE_FILTER)) - { - const unsigned int tableLength = 32; - unsigned int tableSize = sizeof(uint16_t) * 4 * tableLength; - void *interlaceTable = gmmIdToAddress(gmmAlloc(0, tableSize)); - int32_t errorCode = cellRescCreateInterlaceTable(interlaceTable,params->renderHeight,CELL_RESC_ELEMENT_HALF,tableLength); - (void)errorCode; - } -} - -static void _RGLSetDisplayMode( const VideoMode *vm, GLushort bitsPerPixel, GLuint pitch ) -{ - CellVideoOutConfiguration videocfg; - memset( &videocfg, 0, sizeof( videocfg ) ); - videocfg.resolutionId = vm->hwMode; - videocfg.format = ( bitsPerPixel == 32 ) ? CELL_VIDEO_OUT_BUFFER_COLOR_FORMAT_X8R8G8B8 : CELL_VIDEO_OUT_BUFFER_COLOR_FORMAT_R16G16B16X16_FLOAT; - videocfg.pitch = pitch; - videocfg.aspect = CELL_VIDEO_OUT_ASPECT_AUTO; - cellVideoOutConfigure( CELL_VIDEO_OUT_PRIMARY, &videocfg, NULL, 0 ); -} - -static int _RGLPlatformCreateDevice( PSGLdevice* device ) -{ - RGLDevice *gcmDevice = ( RGLDevice * )device->platformDevice; - PSGLdeviceParameters* params = &device->deviceParameters; - jsTiledMemoryManager* mm = &_RGLTiledMemoryManager; - - _RGLDuringDestroyDevice = GL_FALSE; - - memset( mm->region, 0, sizeof( mm->region ) ); - for(int i = 0; i < MAX_TILED_REGIONS; ++i) - cellGcmUnbindTile( i ); - - - const VideoMode *vm = NULL; - if ( params->enable & PSGL_DEVICE_PARAMETERS_TV_STANDARD ) - { - vm = findModeByEnum( params->TVStandard ); - - if(!vm) - return -1; - - params->width = vm->width; - params->height = vm->height; - } - else if ( params->enable & PSGL_DEVICE_PARAMETERS_WIDTH_HEIGHT ) - { - vm = findModeByResolution( params->width, params->height ); - - if(!vm) - return -1; - - } - else - { - vm = _RGLDetectVideoMode(); - - if(!vm) - return -1; - - params->width = vm->width; - params->height = vm->height; - } - - if ( !(params->enable & PSGL_DEVICE_PARAMETERS_RESC_RENDER_WIDTH_HEIGHT) ) - { - params->renderWidth = params->width; - params->renderHeight = params->height; - } - - if ( rescIsEnabled( params ) ) - rescInit( params, gcmDevice ); - - gcmDevice->deviceType = 0; - gcmDevice->TVStandard = params->TVStandard; - - gcmDevice->vsync = rescIsEnabled( params ) ? GL_TRUE : GL_FALSE; - - gcmDevice->ms = NULL; - - const GLuint width = params->renderWidth; - const GLuint height = params->renderHeight; - - for ( int i = 0; i < params->bufferingMode; ++i ) - { - gcmDevice->color[i].source = SURFACE_SOURCE_DEVICE; - gcmDevice->color[i].width = width; - gcmDevice->color[i].height = height; - gcmDevice->color[i].bpp = 4; - gcmDevice->color[i].format = RGL_ARGB8; - gcmDevice->color[i].pool = SURFACE_POOL_LINEAR; - - GLuint size; - _RGLAllocateColorSurface(width, height, - gcmDevice->color[i].bpp*8, &gcmDevice->color[i].dataId, - &gcmDevice->color[i].pitch, &size ); - } - - memset( &gcmDevice->rt, 0, sizeof( RGLRenderTargetEx ) ); - gcmDevice->rt.colorBufferCount = 1; - gcmDevice->rt.yInverted = GL_TRUE; - gcmDevice->rt.width = width; - gcmDevice->rt.height = height; - - _RGLFifoGlViewport( 0, 0, width, height ); - - GLuint hwColor; - - RGL_CALC_COLOR_LE_ARGB8( &hwColor, RGL_CLAMPF_01(0.0f), RGL_CLAMPF_01(0.0f), RGL_CLAMPF_01(0.0f), RGL_CLAMPF_01(0.0f) ); - - cellGcmSetClearColorInline( &_RGLState.fifo, hwColor); - - gcmDevice->rt.colorFormat = RGL_ARGB8; - - for ( int i = 0; i < params->bufferingMode; ++i ) - { - gcmDevice->rt.colorId[0] = gcmDevice->color[i].dataId; - gcmDevice->rt.colorPitch[0] = gcmDevice->color[i].pitch; - _RGLFifoGlSetRenderTarget( &gcmDevice->rt ); - cellGcmSetClearSurfaceInline ( &_RGLState.fifo, CELL_GCM_CLEAR_R | CELL_GCM_CLEAR_G | CELL_GCM_CLEAR_B | CELL_GCM_CLEAR_A); - } - - gcmDevice->scanBuffer = 0; - if ( params->bufferingMode == PSGL_BUFFERING_MODE_SINGLE ) - gcmDevice->drawBuffer = 0; - else if ( params->bufferingMode == PSGL_BUFFERING_MODE_DOUBLE ) - gcmDevice->drawBuffer = 1; - else if ( params->bufferingMode == PSGL_BUFFERING_MODE_TRIPLE ) - gcmDevice->drawBuffer = 2; - - sys_semaphore_attribute_t attr; - sys_semaphore_attribute_initialize(attr); - - sys_semaphore_value_t initial_val = 0; - sys_semaphore_value_t max_val = 1; - switch (device->deviceParameters.bufferingMode) - { - case PSGL_BUFFERING_MODE_SINGLE: - initial_val = 0; - max_val = 1; - break; - case PSGL_BUFFERING_MODE_DOUBLE: - initial_val = 1; - max_val = 2; - break; - case PSGL_BUFFERING_MODE_TRIPLE: - initial_val = 2; - max_val = 3; - break; - default: - break; - } - - int res = sys_semaphore_create(&FlipSem, &attr, initial_val, max_val); - (void)res; - - if(rescIsEnabled(params)) - cellRescSetFlipHandler(_RGLFlipCallbackFunction); - else - cellGcmSetFlipHandler(_RGLFlipCallbackFunction); - - labelAddress = (volatile uint32_t *)cellGcmGetLabelAddress(WaitLabelIndex); - *labelAddress = 0; - - if(rescIsEnabled(params)) - cellRescSetVBlankHandler(_RGLRescVblankCallbackFunction); - else - cellGcmSetVBlankHandler(_RGLVblankCallbackFunction); - - if (rescIsEnabled(params)) - { - for (int i = 0; i < params->bufferingMode; ++i) - { - CellRescSrc rescSrc; - rescSrc.format = CELL_GCM_TEXTURE_A8R8G8B8 | CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_NR; - rescSrc.pitch = gcmDevice->color[i].pitch; - rescSrc.width = width; - rescSrc.height = height; - rescSrc.offset = gmmIdToOffset( gcmDevice->color[i].dataId ); - - if ( cellRescSetSrc( i, &rescSrc ) != CELL_OK ) - { - RARCH_ERR("Registering display buffer %d failed.\n", i ); - return -1; - } - } - } - else - { - _RGLSetDisplayMode(vm, gcmDevice->color[0].bpp*8, gcmDevice->color[0].pitch); - - cellGcmSetFlipMode(gcmDevice->vsync ? CELL_GCM_DISPLAY_VSYNC : CELL_GCM_DISPLAY_HSYNC); - cellGcmSetInvalidateVertexCache( &_RGLState.fifo); - _RGLFifoFinish( &_RGLState.fifo ); - - for (int i = 0; i < params->bufferingMode; ++i) - { - if (cellGcmSetDisplayBuffer( i, gmmIdToOffset( gcmDevice->color[i].dataId ), gcmDevice->color[i].pitch , width, height) != CELL_OK) - { - RARCH_ERR("Registering display buffer %d failed.\n", i ); - return -1; - } - } - } - - gcmDevice->swapFifoRef = _RGLFifoPutReference( &_RGLState.fifo ); - gcmDevice->swapFifoRef2 = gcmDevice->swapFifoRef; - - return 0; -} - -PSGLdevice* psglCreateDeviceExtended(const PSGLdeviceParameters *parameters ) -{ - PSGLdevice *device = (PSGLdevice *)malloc(sizeof(PSGLdevice) + sizeof(RGLDevice)); - - if(!device) - { - _RGLSetError(GL_OUT_OF_MEMORY); - return NULL; - } - memset(device, 0, sizeof(PSGLdevice) + sizeof(RGLDevice)); - - PSGLdeviceParameters defaultParameters; - - defaultParameters.enable = 0; - defaultParameters.colorFormat = GL_ARGB_SCE; - defaultParameters.depthFormat = GL_NONE; - defaultParameters.multisamplingMode = GL_MULTISAMPLING_NONE_SCE; - defaultParameters.TVStandard = PSGL_TV_STANDARD_NONE; - defaultParameters.connector = PSGL_DEVICE_CONNECTOR_NONE; - defaultParameters.bufferingMode = PSGL_BUFFERING_MODE_DOUBLE; - defaultParameters.width = 0; - defaultParameters.height = 0; - defaultParameters.renderWidth = 0; - defaultParameters.renderHeight = 0; - defaultParameters.rescRatioMode = RESC_RATIO_MODE_LETTERBOX; - defaultParameters.rescPalTemporalMode = RESC_PAL_TEMPORAL_MODE_50_NONE; - defaultParameters.rescInterlaceMode = RESC_INTERLACE_MODE_NORMAL_BILINEAR; - defaultParameters.horizontalScale = 1.0f; - defaultParameters.verticalScale = 1.0f; - - memcpy(&device->deviceParameters, parameters, sizeof( PSGLdeviceParameters)); - - if ((parameters->enable & PSGL_DEVICE_PARAMETERS_COLOR_FORMAT) == 0) - device->deviceParameters.colorFormat = defaultParameters.colorFormat; - - if ((parameters->enable & PSGL_DEVICE_PARAMETERS_TV_STANDARD ) == 0) - device->deviceParameters.TVStandard = defaultParameters.TVStandard; - - if ((parameters->enable & PSGL_DEVICE_PARAMETERS_CONNECTOR) == 0) - device->deviceParameters.connector = defaultParameters.connector; - - if (( parameters->enable & PSGL_DEVICE_PARAMETERS_BUFFERING_MODE ) == 0 ) - device->deviceParameters.bufferingMode = defaultParameters.bufferingMode; - - if (( parameters->enable & PSGL_DEVICE_PARAMETERS_WIDTH_HEIGHT ) == 0 ) - { - device->deviceParameters.width = defaultParameters.width; - device->deviceParameters.height = defaultParameters.height; - } - - if (( parameters->enable & PSGL_DEVICE_PARAMETERS_RESC_RENDER_WIDTH_HEIGHT ) == 0 ) - { - device->deviceParameters.renderWidth = defaultParameters.renderWidth; - device->deviceParameters.renderHeight = defaultParameters.renderHeight; - } - - if (( parameters->enable & PSGL_DEVICE_PARAMETERS_RESC_RATIO_MODE ) == 0 ) - device->deviceParameters.rescRatioMode = defaultParameters.rescRatioMode; - - if (( parameters->enable & PSGL_DEVICE_PARAMETERS_RESC_PAL_TEMPORAL_MODE ) == 0 ) - device->deviceParameters.rescPalTemporalMode = defaultParameters.rescPalTemporalMode; - - if (( parameters->enable & PSGL_DEVICE_PARAMETERS_RESC_INTERLACE_MODE ) == 0 ) - device->deviceParameters.rescInterlaceMode = defaultParameters.rescInterlaceMode; - - if (( parameters->enable & PSGL_DEVICE_PARAMETERS_RESC_ADJUST_ASPECT_RATIO ) == 0 ) - { - device->deviceParameters.horizontalScale = defaultParameters.horizontalScale; - device->deviceParameters.verticalScale = defaultParameters.verticalScale; - } - - device->rasterDriver = NULL; - - int result = _RGLPlatformCreateDevice( device ); - if ( result < 0 ) - { - if(device != NULL) - free( device ); - return NULL; - } - return device; -} - -void psglGetDeviceDimensions(const PSGLdevice * device, GLuint *width, GLuint *height) -{ - *width = device->deviceParameters.width; - *height = device->deviceParameters.height; -} - -void psglDestroyDevice(PSGLdevice *device) -{ - if ( _CurrentDevice == device ) psglMakeCurrent( NULL, NULL ); - - if ( device->rasterDriver ) - free( device->rasterDriver ); - - RGLDevice *gcmDevice = ( RGLDevice * )device->platformDevice; - PSGLdeviceParameters* params = &device->deviceParameters; - - cellGcmSetInvalidateVertexCache( &_RGLState.fifo); - _RGLFifoFinish( &_RGLState.fifo ); - - if ( rescIsEnabled( params ) ) - cellRescSetFlipHandler(NULL); - else - cellGcmSetFlipHandler(NULL); - - if ( rescIsEnabled( &device->deviceParameters ) ) - cellRescSetVBlankHandler(NULL); - else - cellGcmSetVBlankHandler(NULL); - - int res = sys_semaphore_destroy(FlipSem); - (void)res; - - if ( rescIsEnabled( params ) ) - { - cellRescExit(); - gmmFree(gcmDevice->RescColorBuffersId); - gmmFree(gcmDevice->RescVertexArrayId); - gmmFree(gcmDevice->RescFragmentShaderId); - } - - _RGLDuringDestroyDevice = GL_TRUE; - for ( int i = 0; i < params->bufferingMode; ++i ) - { - if (gcmDevice->color[i].pool != SURFACE_POOL_NONE) - gmmFree( gcmDevice->color[i].dataId ); - } - _RGLDuringDestroyDevice = GL_FALSE; - - if(device != NULL) - free( device ); -} - -static void *_RGLPlatformRasterInit (void) -{ - RGLDriver *driver = (RGLDriver*)malloc(sizeof(RGLDriver)); - - cellGcmSetInvalidateVertexCache( &_RGLState.fifo); - _RGLFifoFinish( &_RGLState.fifo ); - memset( driver, 0, sizeof( RGLDriver ) ); - driver->rt.yInverted = CELL_GCM_TRUE; - driver->invalidateVertexCache = GL_FALSE; - driver->flushBufferCount = 0; - driver->colorBufferMask = 0x1; - return driver; -} - -void psglMakeCurrent(PSGLcontext *context, PSGLdevice *device) -{ - if ( context && device ) - { - _CurrentContext = context; - _CurrentDevice = device; - if ( !device->rasterDriver ) - device->rasterDriver = _RGLPlatformRasterInit(); - - _RGLAttachContext( device, context ); - } - else - { - _CurrentContext = NULL; - _CurrentDevice = NULL; - } -} - -PSGLdevice *psglGetCurrentDevice(void) -{ - return _CurrentDevice; -} - -static void gmmRemovePendingFree(GmmAllocator *pAllocator, GmmBlock *pBlock) -{ - if (pBlock == pAllocator->pPendingFreeHead) - pAllocator->pPendingFreeHead = pBlock->pNextFree; - - if (pBlock == pAllocator->pPendingFreeTail) - pAllocator->pPendingFreeTail = pBlock->pPrevFree; - - if (pBlock->pNextFree) - pBlock->pNextFree->pPrevFree = pBlock->pPrevFree; - - if (pBlock->pPrevFree) - pBlock->pPrevFree->pNextFree = pBlock->pNextFree; -} - -extern void gmmAddFree(GmmAllocator *pAllocator, GmmBlock *pBlock); - -static void gmmUpdateFreeLists (void) -{ - for(int i = 0; i < 2; i++) - { - uint8_t location = i == 0 ? CELL_GCM_LOCATION_LOCAL : CELL_GCM_LOCATION_MAIN; - GmmAllocator *pAllocator; - const uint32_t fence = _RGLState.semaphores->userSemaphores[SEMA_FENCE].val; - GmmBlock *pBlock = NULL; - GmmBlock *pTemp = NULL; - - pAllocator = (location == CELL_GCM_LOCATION_LOCAL) ? - pGmmLocalAllocator : - pGmmMainAllocator; - - pBlock = pAllocator->pPendingFreeHead; - - while (pBlock) - { - pTemp = pBlock->pNextFree; - - if ( !(( fence - pBlock->fence ) & 0x80000000 ) ) - { - gmmRemovePendingFree(pAllocator, pBlock); - gmmAddFree(pAllocator, pBlock); - } - - pBlock = pTemp; - } - } - -} - -GLAPI void psglSwap(void) -{ - PSGLcontext *LContext = _CurrentContext; - PSGLdevice *device = _CurrentDevice; - RGLFifo *fifo = &_RGLState.fifo; - - gmmUpdateFreeLists(); - - RGLDevice *gcmDevice = ( RGLDevice * )device->platformDevice; - - const GLuint drawBuffer = gcmDevice->drawBuffer; - - GLboolean vsync = _CurrentContext->VSync; - if(vsync != gcmDevice->vsync ) - { - if (!rescIsEnabled( &device->deviceParameters)) - { - cellGcmSetFlipMode( vsync ? CELL_GCM_DISPLAY_VSYNC : CELL_GCM_DISPLAY_HSYNC ); - gcmDevice->vsync = vsync; - } - } - - if(device->deviceParameters.bufferingMode == PSGL_BUFFERING_MODE_TRIPLE ) - { - if (rescIsEnabled( &device->deviceParameters)) - cellRescSetWaitFlip(); - else - cellGcmSetWaitFlip(); - } - - if(rescIsEnabled( &device->deviceParameters)) - { - int32_t res = cellRescSetConvertAndFlip((uint8_t)drawBuffer); - if ( res != CELL_OK ) - { - RARCH_WARN("RESC cellRescSetConvertAndFlip returned error code %d.\n", res); - - if(_CurrentContext) - _CurrentContext->needValidate |= PSGL_VALIDATE_FRAMEBUFFER; - - return; - } - } - else - cellGcmSetFlip(( uint8_t ) drawBuffer ); - - if(device->deviceParameters.bufferingMode != PSGL_BUFFERING_MODE_TRIPLE ) - { - if (rescIsEnabled( &device->deviceParameters)) - cellRescSetWaitFlip(); - else - cellGcmSetWaitFlip(); - } - - LContext->needValidate = PSGL_VALIDATE_ALL; - - LContext->attribs->DirtyMask = (1 << MAX_VERTEX_ATTRIBS) - 1; - - cellGcmSetInvalidateVertexCache( &_RGLState.fifo); - - _RGLFifoFlush(fifo); - - while(sys_semaphore_wait(FlipSem, 1000) != CELL_OK); - - cellGcmSetInvalidateVertexCache(&_RGLState.fifo); - _RGLFifoFlush(fifo); - - if (device->deviceParameters.bufferingMode == PSGL_BUFFERING_MODE_DOUBLE) - { - gcmDevice->drawBuffer = gcmDevice->scanBuffer; - gcmDevice->scanBuffer = drawBuffer; - - gcmDevice->rt.colorId[0] = gcmDevice->color[gcmDevice->drawBuffer].dataId; - gcmDevice->rt.colorPitch[0] = gcmDevice->color[gcmDevice->drawBuffer].pitch; - } - else if(device->deviceParameters.bufferingMode == PSGL_BUFFERING_MODE_TRIPLE) - { - gcmDevice->drawBuffer = gcmDevice->scanBuffer; - if (gcmDevice->scanBuffer == 2) - gcmDevice->scanBuffer = 0; - else - gcmDevice->scanBuffer++; - - gcmDevice->rt.colorId[0] = gcmDevice->color[gcmDevice->drawBuffer].dataId; - gcmDevice->rt.colorPitch[0] = gcmDevice->color[gcmDevice->drawBuffer].pitch; - } -} - -static inline void _RGLUtilWaitForIdle(void) -{ - cellGcmSetWriteBackEndLabelInline( &_RGLState.fifo, UTIL_LABEL_INDEX, _RGLState.labelValue); - cellGcmSetWaitLabelInline( &_RGLState.fifo, UTIL_LABEL_INDEX, _RGLState.labelValue); - - _RGLState.labelValue++; - - cellGcmSetWriteBackEndLabelInline( &_RGLState.fifo, UTIL_LABEL_INDEX, _RGLState.labelValue); - cellGcmFlush(); - - while( *(cellGcmGetLabelAddress(UTIL_LABEL_INDEX)) != _RGLState.labelValue); - - _RGLState.labelValue++; -} - -GLboolean _RGLTryResizeTileRegion(GLuint address, GLuint size, void* data) -{ - jsTiledRegion* region = (jsTiledRegion*)data; - - if (size == 0) - { - region->offset = 0; - region->size = 0; - region->pitch = 0; - - if (!_RGLDuringDestroyDevice) - { - _RGLUtilWaitForIdle(); - cellGcmUnbindTile( region->id ); - _RGLFifoFinish(&_RGLState.fifo); - } - return GL_TRUE; - } - region->offset = address; - region->size = size; - - _RGLUtilWaitForIdle(); - - cellGcmSetTileInfo(region->id, CELL_GCM_LOCATION_LOCAL, - region->offset, region->size, region->pitch, CELL_GCM_COMPMODE_DISABLED, 0, - region->bank ); - - cellGcmBindTile( region->id ); - - _RGLFifoFinish( &_RGLState.fifo ); - - return GL_TRUE; -} diff --git a/console/rgl/ps3/elf.h b/console/rgl/ps3/elf.h deleted file mode 100644 index dd7729db26..0000000000 --- a/console/rgl/ps3/elf.h +++ /dev/null @@ -1,153 +0,0 @@ -#ifndef ELF_H -#define ELF_H 1 - -#define EI_MAG0 0 -#define EI_MAG1 1 -#define EI_MAG2 2 -#define EI_MAG3 3 -#define EI_CLASS 4 -#define EI_DATA 5 -#define EI_VERSION 6 -#define EI_OSABI 7 -#define EI_ABIVERSION 8 -#define EI_PAD 9 -#define EI_NIDENT 16 - -#define ELFMAG0 0x7f -#define ELFMAG1 'E' -#define ELFMAG2 'L' -#define ELFMAG3 'F' - -#define ELFCLASSNONE 0 -#define ELFCLASS32 1 -#define ELFCLASS64 2 - -#define ELFDATANONE 0 -#define ELFDATA2LSB 1 -#define ELFDATA2MSB 2 - -#define EV_NONE 0 -#define EV_CURRENT 1 - -#define ET_NONE 0 -#define ET_REL 1 -#define ET_EXEC 2 -#define ET_DYN 3 -#define ET_CORE 4 - -#define EM_PPC 20 -#define EM_PPC64 21 - -typedef struct { - unsigned char e_ident[EI_NIDENT]; - unsigned short e_type; - unsigned short e_machine; - unsigned int e_version; - unsigned int e_entry; - unsigned int e_phoff; - unsigned int e_shoff; - unsigned int e_flags; - unsigned short e_ehsize; - unsigned short e_phentsize; - unsigned short e_phnum; - unsigned short e_shentsize; - unsigned short e_shnum; - unsigned short e_shstrndx; -} Elf32_Ehdr; - -#define PT_NULL 0 -#define PT_LOAD 1 -#define PT_DYNAMIC 2 -#define PT_INTERP 3 -#define PT_NOTE 4 -#define PT_SHLIB 5 -#define PT_PHDR 6 -#define PT_LOOS 0x60000000 -#define PT_HIOS 0x6fffffff -#define PT_LOPROC 0x70000000 -#define PT_HIPROC 0x7fffffff - -typedef struct { - unsigned int p_type; - unsigned int p_offset; - unsigned int p_vaddr; - unsigned int p_paddr; - unsigned int p_filesz; - unsigned int p_memsz; - unsigned int p_flags; - unsigned int p_align; -} Elf32_Phdr; - -#define SHT_NULL 0 -#define SHT_PROGBITS 1 -#define SHT_SYMTAB 2 -#define SHT_STRTAB 3 -#define SHT_RELA 4 -#define SHT_HASH 5 -#define SHT_DYNAMIC 6 -#define SHT_NOTE 7 -#define SHT_NOBITS 8 -#define SHT_REL 9 -#define SHT_SHLIB 10 -#define SHT_DYNSYM 11 - -#define SHF_WRITE (1 << 0) -#define SHF_ALLOC (1 << 1) -#define SHF_EXECINSTR (1 << 2) -#define SHF_MERGE (1 << 4) -#define SHF_STRINGS (1 << 5) -#define SHF_INFO_LINK (1 << 6) -#define SHF_LINK_ORDER (1 << 7) -#define SHF_OS_NONCONFORMING (1 << 8) -#define SHF_MASKOS 0x0ff00000 -#define SHF_MASKPROC 0xf0000000 - - -typedef struct { - unsigned int sh_name; - unsigned int sh_type; - unsigned int sh_flags; - unsigned int sh_addr; - unsigned int sh_offset; - unsigned int sh_size; - unsigned int sh_link; - unsigned int sh_info; - unsigned int sh_addralign; - unsigned int sh_entsize; -} Elf32_Shdr; - -#define SHN_UNDEF 0 -#define SHN_LORESERVE 0xff00 -#define SHN_LOPROC 0xff00 -#define SHN_HIPROC 0xff1f -#define SHN_LOOS 0xff20 -#define SHN_HIOS 0xff3f -#define SHN_ABS 0xfff1 -#define SHN_COMMON 0xfff2 -#define SHN_XINDEX 0xffff -#define SHN_HIRESERVE 0xffff - -typedef struct { - unsigned int st_name; - unsigned int st_value; - unsigned int st_size; - unsigned char st_info; - unsigned char st_other; - unsigned short st_shndx; -} Elf32_Sym; - - -typedef struct -{ - unsigned int r_offset; - unsigned int r_info; -} Elf32_Rel; - -typedef struct -{ - unsigned int r_offset; - unsigned int r_info; - int r_addend; -} Elf32_Rela; - -#endif /* ELF_H */ diff --git a/console/rgl/ps3/gl.h b/console/rgl/ps3/gl.h deleted file mode 100644 index 5730f7959a..0000000000 --- a/console/rgl/ps3/gl.h +++ /dev/null @@ -1,323 +0,0 @@ -#ifndef __gl_h_ -#define __gl_h_ - -#ifdef __cplusplus -extern "C" -{ -#endif - - /* - ** License Applicability. Except to the extent portions of this file are - ** made subject to an alternative license as permitted in the SGI Free - ** Software License B, Version 1.0 (the "License"), the contents of this - ** file are subject only to the provisions of the License. You may not use - ** this file except in compliance with the License. You may obtain a copy - ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 - ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: - ** - ** http://oss.sgi.com/projects/FreeB - ** - ** Note that, as provided in the License, the Software is distributed on an - ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS - ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND - ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A - ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. - ** - ** Original Code. The Original Code is: OpenGL Sample Implementation, - ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, - ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. - ** Copyright in any portions created by third parties is as indicated - ** elsewhere herein. All Rights Reserved. - ** - ** Additional Notice Provisions: The application programming interfaces - ** established by SGI in conjunction with the Original Code are The - ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released - ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version - ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X - ** Window System(R) (Version 1.3), released October 19, 1998. This software - ** was created using the OpenGL(R) version 1.2.1 Sample Implementation - ** published by SGI, but has not been independently verified as being - ** compliant with the OpenGL(R) version 1.2.1 Specification. - */ - -#ifdef PSGL_EXPORT -#define GLAPI PSGL_EXPORT -#endif - -#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SYMBIAN32__) -#define WIN32_LEAN_AND_MEAN 1 -#include -#endif - - -#ifndef APIENTRY -#define APIENTRY -#endif -#ifndef GLAPI -#define GLAPI extern -#endif - -typedef unsigned int GLenum; -typedef unsigned char GLboolean; -typedef unsigned int GLbitfield; -typedef signed char GLbyte; -typedef short GLshort; -typedef int GLint; -typedef int GLsizei; -typedef unsigned char GLubyte; -typedef unsigned short GLushort; -typedef unsigned int GLuint; -typedef float GLfloat; -typedef float GLclampf; -typedef void GLvoid; -typedef int GLfixed; -typedef int GLclampx; -typedef void( *_GLfuncptr )(); - -#define GL_OES_VERSION_1_0 1 -#define GL_OES_read_format 1 -#define GL_OES_compressed_paletted_texture 1 - -#define GL_DEPTH_BUFFER_BIT 0x00000100 -#define GL_STENCIL_BUFFER_BIT 0x00000400 -#define GL_COLOR_BUFFER_BIT 0x00004000 - -#define GL_FALSE 0 -#define GL_TRUE 1 - -#define GL_POINTS 0x0000 -#define GL_LINES 0x0001 -#define GL_LINE_LOOP 0x0002 -#define GL_LINE_STRIP 0x0003 -#define GL_TRIANGLES 0x0004 -#define GL_TRIANGLE_STRIP 0x0005 -#define GL_TRIANGLE_FAN 0x0006 - -#define GL_NEVER 0x0200 -#define GL_LESS 0x0201 -#define GL_EQUAL 0x0202 -#define GL_LEQUAL 0x0203 -#define GL_GREATER 0x0204 -#define GL_NOTEQUAL 0x0205 -#define GL_GEQUAL 0x0206 -#define GL_ALWAYS 0x0207 - -#define GL_ZERO 0 -#define GL_ONE 1 -#define GL_SRC_COLOR 0x0300 -#define GL_ONE_MINUS_SRC_COLOR 0x0301 -#define GL_SRC_ALPHA 0x0302 -#define GL_ONE_MINUS_SRC_ALPHA 0x0303 -#define GL_DST_ALPHA 0x0304 -#define GL_ONE_MINUS_DST_ALPHA 0x0305 - -#define GL_DST_COLOR 0x0306 -#define GL_ONE_MINUS_DST_COLOR 0x0307 -#define GL_SRC_ALPHA_SATURATE 0x0308 -#define GL_FRONT 0x0404 -#define GL_BACK 0x0405 -#define GL_FRONT_AND_BACK 0x0408 -#define GL_TEXTURE_2D 0x0DE1 -#define GL_BLEND 0x0BE2 -#define GL_DITHER 0x0BD0 -#define GL_POINT_SMOOTH 0x0B10 -#define GL_LINE_SMOOTH 0x0B20 -#define GL_SCISSOR_TEST 0x0C11 -#define GL_COLOR_MATERIAL 0x0B57 -#define GL_NORMALIZE 0x0BA1 -#define GL_RESCALE_NORMAL 0x803A -#define GL_POLYGON_OFFSET_FILL 0x8037 -#define GL_VERTEX_ARRAY 0x8074 -#define GL_NORMAL_ARRAY 0x8075 -#define GL_COLOR_ARRAY 0x8076 -#define GL_TEXTURE_COORD_ARRAY 0x8078 -#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E -#define GL_SAMPLE_ALPHA_TO_ONE 0x809F -#define GL_SAMPLE_COVERAGE 0x80A0 - -#define GL_NO_ERROR 0 -#define GL_INVALID_ENUM 0x0500 -#define GL_INVALID_VALUE 0x0501 -#define GL_INVALID_OPERATION 0x0502 -#define GL_STACK_OVERFLOW 0x0503 -#define GL_STACK_UNDERFLOW 0x0504 -#define GL_OUT_OF_MEMORY 0x0505 - -#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12 -#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22 -#define GL_ALIASED_POINT_SIZE_RANGE 0x846D -#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E -#define GL_IMPLEMENTATION_COLOR_READ_TYPE_OES 0x8B9A -#define GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES 0x8B9B -#define GL_MAX_LIGHTS 0x0D31 -#define GL_MAX_TEXTURE_SIZE 0x0D33 -#define GL_MAX_MODELVIEW_STACK_DEPTH 0x0D36 -#define GL_MAX_PROJECTION_STACK_DEPTH 0x0D38 -#define GL_MAX_TEXTURE_STACK_DEPTH 0x0D39 -#define GL_MAX_VIEWPORT_DIMS 0x0D3A -#define GL_MAX_ELEMENTS_VERTICES 0x80E8 -#define GL_MAX_ELEMENTS_INDICES 0x80E9 -#define GL_MAX_TEXTURE_UNITS 0x84E2 -#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 -#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 -#define GL_SUBPIXEL_BITS 0x0D50 -#define GL_RED_BITS 0x0D52 -#define GL_GREEN_BITS 0x0D53 -#define GL_BLUE_BITS 0x0D54 -#define GL_ALPHA_BITS 0x0D55 -#define GL_DEPTH_BITS 0x0D56 -#define GL_STENCIL_BITS 0x0D57 - -#define GL_DONT_CARE 0x1100 -#define GL_FASTEST 0x1101 -#define GL_NICEST 0x1102 - -#define GL_PERSPECTIVE_CORRECTION_HINT 0x0C50 -#define GL_POINT_SMOOTH_HINT 0x0C51 -#define GL_LINE_SMOOTH_HINT 0x0C52 -#define GL_POLYGON_SMOOTH_HINT 0x0C53 -#define GL_FOG_HINT 0x0C54 - -#define GL_BYTE 0x1400 -#define GL_UNSIGNED_BYTE 0x1401 -#define GL_SHORT 0x1402 -#define GL_UNSIGNED_SHORT 0x1403 -#define GL_FLOAT 0x1406 -#define GL_FIXED 0x140C - -#define GL_CLEAR 0x1500 -#define GL_AND 0x1501 -#define GL_AND_REVERSE 0x1502 -#define GL_COPY 0x1503 -#define GL_AND_INVERTED 0x1504 -#define GL_NOOP 0x1505 -#define GL_XOR 0x1506 -#define GL_OR 0x1507 -#define GL_NOR 0x1508 -#define GL_EQUIV 0x1509 -#define GL_INVERT 0x150A -#define GL_OR_REVERSE 0x150B -#define GL_COPY_INVERTED 0x150C -#define GL_OR_INVERTED 0x150D -#define GL_NAND 0x150E -#define GL_SET 0x150F - -#define GL_EMISSION 0x1600 -#define GL_SHININESS 0x1601 -#define GL_AMBIENT_AND_DIFFUSE 0x1602 -#define GL_MODELVIEW 0x1700 -#define GL_PROJECTION 0x1701 -#define GL_TEXTURE 0x1702 - -#define GL_ALPHA 0x1906 -#define GL_RGB 0x1907 -#define GL_RGBA 0x1908 -#define GL_LUMINANCE 0x1909 -#define GL_LUMINANCE_ALPHA 0x190A - -#define GL_UNPACK_ALIGNMENT 0x0CF5 -#define GL_PACK_ALIGNMENT 0x0D05 - -#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 -#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 -#define GL_UNSIGNED_SHORT_5_6_5 0x8363 - -#define GL_FLAT 0x1D00 -#define GL_SMOOTH 0x1D01 - -#define GL_KEEP 0x1E00 -#define GL_REPLACE 0x1E01 -#define GL_INCR 0x1E02 -#define GL_DECR 0x1E03 -#define GL_VENDOR 0x1F00 -#define GL_RENDERER 0x1F01 -#define GL_VERSION 0x1F02 -#define GL_EXTENSIONS 0x1F03 - -#define GL_MODULATE 0x2100 -#define GL_DECAL 0x2101 -#define GL_ADD 0x0104 -#define GL_TEXTURE_ENV_MODE 0x2200 -#define GL_TEXTURE_ENV_COLOR 0x2201 - -#define GL_TEXTURE_ENV 0x2300 -#define GL_NEAREST 0x2600 -#define GL_LINEAR 0x2601 - -#define GL_NEAREST_MIPMAP_NEAREST 0x2700 -#define GL_LINEAR_MIPMAP_NEAREST 0x2701 -#define GL_NEAREST_MIPMAP_LINEAR 0x2702 -#define GL_LINEAR_MIPMAP_LINEAR 0x2703 - -#define GL_TEXTURE_MAG_FILTER 0x2800 -#define GL_TEXTURE_MIN_FILTER 0x2801 -#define GL_TEXTURE_WRAP_S 0x2802 -#define GL_TEXTURE_WRAP_T 0x2803 - -#define GL_TEXTURE0 0x84C0 -#define GL_TEXTURE1 0x84C1 -#define GL_TEXTURE2 0x84C2 -#define GL_TEXTURE3 0x84C3 -#define GL_TEXTURE4 0x84C4 -#define GL_TEXTURE5 0x84C5 -#define GL_TEXTURE6 0x84C6 -#define GL_TEXTURE7 0x84C7 -#define GL_TEXTURE8 0x84C8 -#define GL_TEXTURE9 0x84C9 -#define GL_TEXTURE10 0x84CA -#define GL_TEXTURE11 0x84CB -#define GL_TEXTURE12 0x84CC -#define GL_TEXTURE13 0x84CD -#define GL_TEXTURE14 0x84CE -#define GL_TEXTURE15 0x84CF -#define GL_TEXTURE16 0x84D0 -#define GL_TEXTURE17 0x84D1 -#define GL_TEXTURE18 0x84D2 -#define GL_TEXTURE19 0x84D3 -#define GL_TEXTURE20 0x84D4 -#define GL_TEXTURE21 0x84D5 -#define GL_TEXTURE22 0x84D6 -#define GL_TEXTURE23 0x84D7 -#define GL_TEXTURE24 0x84D8 -#define GL_TEXTURE25 0x84D9 -#define GL_TEXTURE26 0x84DA -#define GL_TEXTURE27 0x84DB -#define GL_TEXTURE28 0x84DC -#define GL_TEXTURE29 0x84DD -#define GL_TEXTURE30 0x84DE -#define GL_TEXTURE31 0x84DF - -#define GL_REPEAT 0x2901 -#define GL_CLAMP_TO_EDGE 0x812F - -GLAPI void APIENTRY glActiveTexture( GLenum texture ); -GLAPI void APIENTRY glBindTexture( GLenum target, GLuint texture ); -GLAPI void APIENTRY glBlendFunc( GLenum sfactor, GLenum dfactor ); -GLAPI void APIENTRY glClear( GLbitfield mask ); -GLAPI void APIENTRY glClearColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha ); -GLAPI void APIENTRY glClearColorx( GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha ); -GLAPI void APIENTRY glClientActiveTexture( GLenum texture ); -GLAPI void APIENTRY glColorPointer( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer ); -GLAPI void APIENTRY glCopyTexSubImage2D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height ); -GLAPI void APIENTRY glDeleteTextures( GLsizei n, const GLuint *textures ); -GLAPI void APIENTRY glDisable( GLenum cap ); -GLAPI void APIENTRY glDisableClientState( GLenum array ); -GLAPI void APIENTRY glDrawArrays( GLenum mode, GLint first, GLsizei count ); -GLAPI void APIENTRY glEnable( GLenum cap ); -GLAPI void APIENTRY glEnableClientState( GLenum array ); -GLAPI void APIENTRY glFinish( void ); -GLAPI void APIENTRY glFlush( void ); -GLAPI void APIENTRY glGenTextures( GLsizei n, GLuint *textures ); -GLAPI GLenum APIENTRY glGetError( void ); -GLAPI const GLubyte * APIENTRY glGetString( GLenum name ); -GLAPI void APIENTRY glPixelStorei( GLenum pname, GLint param ); -GLAPI void APIENTRY glTexCoordPointer( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer ); -GLAPI void APIENTRY glTexImage2D( GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels ); -GLAPI void APIENTRY glVertexPointer( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer ); -GLAPI void APIENTRY glViewport( GLint x, GLint y, GLsizei width, GLsizei height ); - -#ifdef __cplusplus -} -#endif - -#endif /* __gl_h_ */ diff --git a/console/rgl/ps3/glext.h b/console/rgl/ps3/glext.h deleted file mode 100644 index 5561075f09..0000000000 --- a/console/rgl/ps3/glext.h +++ /dev/null @@ -1,274 +0,0 @@ -#ifndef __gl_ext_h_ -#define __gl_ext_h_ - -#ifndef _MSC_VER -#include -#else -#include -#endif - -#ifdef __cplusplus -extern "C" -{ -#endif - -typedef intptr_t GLintptr; -typedef intptr_t GLsizeiptr; -typedef unsigned short GLhalfARB; - -#define GL_QUADS 0x0007 -#define GL_QUAD_STRIP 0x0008 - -#define GL_INT 0x1404 -#define GL_UNSIGNED_INT 0x1405 - -#define GL_UNSIGNED_BYTE_3_3_2 0x8032 -#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362 -#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364 -#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365 -#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366 -#define GL_UNSIGNED_INT_8_8_8_8 0x8035 -#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367 -#define GL_UNSIGNED_INT_10_10_10_2 0x8036 -#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 -#define GL_UNSIGNED_INT_24_8_SCE 0x6008 -#define GL_UNSIGNED_INT_8_24_REV_SCE 0x6009 - -#define GL_HALF_FLOAT_ARB 0x140B - -#define GL_ALPHA4 0x803B -#define GL_ALPHA8 0x803C -#define GL_ALPHA12 0x803D -#define GL_ALPHA16 0x803E -#define GL_LUMINANCE4 0x803F -#define GL_LUMINANCE8 0x8040 -#define GL_LUMINANCE12 0x8041 -#define GL_LUMINANCE16 0x8042 -#define GL_LUMINANCE4_ALPHA4 0x8043 -#define GL_LUMINANCE6_ALPHA2 0x8044 -#define GL_LUMINANCE8_ALPHA8 0x8045 -#define GL_LUMINANCE12_ALPHA4 0x8046 -#define GL_LUMINANCE12_ALPHA12 0x8047 -#define GL_LUMINANCE16_ALPHA16 0x8048 -#define GL_INTENSITY 0x8049 -#define GL_INTENSITY4 0x804A -#define GL_INTENSITY8 0x804B -#define GL_INTENSITY12 0x804C -#define GL_INTENSITY16 0x804D -#define GL_R3_G3_B2 0x2A10 -#define GL_RGB4 0x804F -#define GL_RGB5 0x8050 -#define GL_RGB8 0x8051 -#define GL_RGB10 0x8052 -#define GL_RGB12 0x8053 -#define GL_RGB16 0x8054 -#define GL_RGBA2 0x8055 -#define GL_RGBA4 0x8056 -#define GL_RGB5_A1 0x8057 -#define GL_RGB10_A2 0x8059 -#define GL_RGBA12 0x805A -#define GL_RGBA16 0x805B -#define GL_BGR 0x80E0 -#define GL_BGRA 0x80E1 -#define GL_ABGR 0x8000 -#define GL_RED 0x1903 -#define GL_GREEN 0x1904 -#define GL_BLUE 0x1905 -#define GL_ARGB_SCE 0x6007 - -#define GL_UNSIGNED_SHORT_8_8_SCE 0x600B -#define GL_UNSIGNED_SHORT_8_8_REV_SCE 0x600C -#define GL_UNSIGNED_INT_16_16_SCE 0x600D -#define GL_UNSIGNED_INT_16_16_REV_SCE 0x600E - -#define GL_CONSTANT_COLOR 0x8001 -#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 -#define GL_CONSTANT_ALPHA 0x8003 -#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 -#define GL_BLEND_EQUATION 0x8009 -#define GL_FUNC_ADD 0x8006 -#define GL_MIN 0x8007 -#define GL_MAX 0x8008 -#define GL_FUNC_SUBTRACT 0x800A -#define GL_FUNC_REVERSE_SUBTRACT 0x800B - -#define GL_TEXTURE_WRAP_R 0x8072 -#define GL_MAX_3D_TEXTURE_SIZE 0x8073 - -#define GL_POINT 0x1B00 -#define GL_LINE 0x1B01 -#define GL_FILL 0x1B02 - -#define GL_TEXTURE_FILTER_CONTROL 0x8500 -#define GL_TEXTURE_LOD_BIAS 0x8501 -#define GL_TEXTURE_MIN_LOD 0x813A -#define GL_TEXTURE_MAX_LOD 0x813B -#define GL_TEXTURE_MAX_LEVEL 0x813D -#define GL_TEXTURE_BORDER_COLOR 0x1004 - -#define GL_NONE 0x0 -#define GL_DEPTH_TEXTURE_MODE_ARB 0x884B -#define GL_TEXTURE_COMPARE_MODE_ARB 0x884C -#define GL_TEXTURE_COMPARE_FUNC_ARB 0x884D -#define GL_COMPARE_R_TO_TEXTURE_ARB 0x884E - -#define GL_CLAMP 0x2900 -#define GL_MIRRORED_REPEAT 0x8370 -#define GL_MIRROR_CLAMP_EXT 0x8742 -#define GL_MIRROR_CLAMP_TO_EDGE_EXT 0x8743 -#define GL_MIRROR_CLAMP_TO_BORDER_EXT 0x8912 -#define GL_CLAMP_TO_BORDER 0x812D - -/* Fragment Control TXP */ -#define GL_FRAGMENT_PROGRAM_CONTROL_CONTROLTXP_SCE 0x8453 - -/* Gets */ -#define GL_MODELVIEW_MATRIX 0x0BA6 -#define GL_TEXTURE_MATRIX 0x0BA8 -#define GL_PROJECTION_MATRIX 0x0BA7 -#define GL_MAX_TEXTURE_COORDS_ARB 0x8871 -#define GL_MAX_TEXTURE_IMAGE_UNITS_ARB 0x8872 - -#define GL_RGBA8 0x8058 - -#define GL_ARRAY_BUFFER 0x8892 -#define GL_ELEMENT_ARRAY_BUFFER 0x8893 -#define GL_PIXEL_PACK_BUFFER_ARB 0x88EB -#define GL_PIXEL_UNPACK_BUFFER_ARB 0x88EC -#define GL_STREAM_DRAW 0x88E0 -#define GL_STREAM_READ 0x88E1 -#define GL_STREAM_COPY 0x88E2 -#define GL_STATIC_DRAW 0x88E4 -#define GL_STATIC_READ 0x88E5 -#define GL_STATIC_COPY 0x88E6 -#define GL_DYNAMIC_DRAW 0x88E8 -#define GL_DYNAMIC_READ 0x88E9 -#define GL_DYNAMIC_COPY 0x88EA -#define GL_SYSTEM_DRAW_SCE 0x6020 - -#define GL_READ_ONLY 0x88B8 -#define GL_WRITE_ONLY 0x88B9 -#define GL_READ_WRITE 0x88BA - -#define GL_VSYNC_SCE 0x6006 -#define GL_SKIP_FIRST_VSYNC_SCE 0x6100 - -#define GL_TEXTURE_GAMMA_REMAP_R_SCE 0x6010 -#define GL_TEXTURE_GAMMA_REMAP_G_SCE 0x6011 -#define GL_TEXTURE_GAMMA_REMAP_B_SCE 0x6012 -#define GL_TEXTURE_GAMMA_REMAP_A_SCE 0x6013 - -#define GL_SHADER_SRGB_REMAP_SCE 0x6014 - -#define GL_TEXTURE_FROM_VERTEX_PROGRAM_SCE 0x6017 - -#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE -#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF - -#define GL_ALL_COMPLETED_NV 0x84F2 -#define GL_FENCE_STATUS_NV 0x84F3 -#define GL_FENCE_CONDITION_NV 0x84F4 - -#define GL_MAX_CLIP_PLANES 0x0D32 -#define GL_CLIP_PLANE0 0x3000 -#define GL_CLIP_PLANE1 0x3001 -#define GL_CLIP_PLANE2 0x3002 -#define GL_CLIP_PLANE3 0x3003 -#define GL_CLIP_PLANE4 0x3004 -#define GL_CLIP_PLANE5 0x3005 - -#define GL_POINT_SPRITE_OES 0x8861 -#define GL_COORD_REPLACE_OES 0x8862 -#define GL_VERTEX_PROGRAM_POINT_SIZE_ARB 0x8642 - -#define GL_INVALID_FRAMEBUFFER_OPERATION_OES 0x0506 -#define GL_MAX_RENDERBUFFER_SIZE_OES 0x84E8 -#define GL_FRAMEBUFFER_BINDING_OES 0x8CA6 -#define GL_RENDERBUFFER_BINDING_OES 0x8CA7 -#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_OES 0x8CD0 -#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_OES 0x8CD1 -#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_OES 0x8CD2 -#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_OES 0x8CD3 -#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT 0x8CD4 -#define GL_FRAMEBUFFER_COMPLETE_OES 0x8CD5 -#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES 0x8CD6 -#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_OES 0x8CD7 -#define GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_OES 0x8CD8 -#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_OES 0x8CD9 -#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_OES 0x8CDA -#define GL_FRAMEBUFFER_UNSUPPORTED_OES 0x8CDD -#define GL_MAX_COLOR_ATTACHMENTS_OES 0x8CDF -#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0 -#define GL_COLOR_ATTACHMENT1_EXT 0x8CE1 -#define GL_COLOR_ATTACHMENT2_EXT 0x8CE2 -#define GL_COLOR_ATTACHMENT3_EXT 0x8CE3 -#define GL_COLOR_ATTACHMENT4_EXT 0x8CE4 -#define GL_COLOR_ATTACHMENT5_EXT 0x8CE5 -#define GL_COLOR_ATTACHMENT6_EXT 0x8CE6 -#define GL_COLOR_ATTACHMENT7_EXT 0x8CE7 -#define GL_COLOR_ATTACHMENT8_EXT 0x8CE8 -#define GL_COLOR_ATTACHMENT9_EXT 0x8CE9 -#define GL_COLOR_ATTACHMENT10_EXT 0x8CEA -#define GL_COLOR_ATTACHMENT11_EXT 0x8CEB -#define GL_COLOR_ATTACHMENT12_EXT 0x8CEC -#define GL_COLOR_ATTACHMENT13_EXT 0x8CED -#define GL_COLOR_ATTACHMENT14_EXT 0x8CEE -#define GL_COLOR_ATTACHMENT15_EXT 0x8CEF -#define GL_DEPTH_ATTACHMENT_OES 0x8D00 -#define GL_STENCIL_ATTACHMENT_OES 0x8D20 -#define GL_FRAMEBUFFER_OES 0x8D40 -#define GL_RENDERBUFFER_OES 0x8D41 -#define GL_RENDERBUFFER_WIDTH_OES 0x8D42 -#define GL_RENDERBUFFER_HEIGHT_OES 0x8D43 -#define GL_RENDERBUFFER_INTERNAL_FORMAT_OES 0x8D44 -#define GL_STENCIL_INDEX_OES 0x8D45 -#define GL_STENCIL_INDEX4_OES 0x8D47 -#define GL_STENCIL_INDEX8_OES 0x8D48 - -#define GL_BLEND_MRT0_SCE GL_COLOR_ATTACHMENT0_EXT -#define GL_BLEND_MRT1_SCE GL_COLOR_ATTACHMENT1_EXT -#define GL_BLEND_MRT2_SCE GL_COLOR_ATTACHMENT2_EXT -#define GL_BLEND_MRT3_SCE GL_COLOR_ATTACHMENT3_EXT - -#define GL_TEXTURE_ALLOCATION_HINT_SCE 0x6018 -#define GL_TEXTURE_LINEAR_GPU_SCE 0x601A - -#define GL_INCR_WRAP 0x8507 -#define GL_DECR_WRAP 0x8508 - -#define GL_DEPTH_CLAMP_NV 0x864F - -#define GL_FIXED_11_11_10_SCE 0x6020 - -#define GL_REDUCE_DST_COLOR_SCE 0x6021 - -#define GL_MULTISAMPLING_NONE_SCE 0x6030 - -#define GL_TEXTURE_REFERENCE_BUFFER_SCE 0x6040 -#define GL_BUFFER_SIZE 0x8764 -#define GL_BUFFER_PITCH_SCE 0x6041 - -GLAPI void APIENTRY glBlendEquation( GLenum mode ); -GLAPI void APIENTRY glBlendColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha ); -GLAPI void APIENTRY glGetFloatv( GLenum pname, GLfloat* params ); -GLAPI void APIENTRY glTexParameteri( GLenum target, GLenum pname, GLint param ); - -GLAPI void APIENTRY glBindBuffer( GLenum target, GLuint name ); -GLAPI void APIENTRY glDeleteBuffers( GLsizei n, const GLuint *buffers ); -GLAPI void APIENTRY glGenBuffers( GLsizei n, GLuint *buffers ); -GLAPI void APIENTRY glBufferData( GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage ); -GLAPI void APIENTRY glBufferSubData( GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data ); - -GLAPI void APIENTRY glBindFramebufferOES( GLenum, GLuint ); -GLAPI void APIENTRY glDeleteFramebuffersOES( GLsizei, const GLuint * ); -GLAPI void APIENTRY glGenFramebuffersOES( GLsizei, GLuint * ); -GLAPI GLenum APIENTRY glCheckFramebufferStatusOES( GLenum ); -GLAPI void APIENTRY glFramebufferTexture2DOES( GLenum, GLenum, GLenum, GLuint, GLint ); - -GLAPI void APIENTRY glTextureReferenceSCE( GLenum target, GLuint levels, GLuint baseWidth, GLuint baseHeight, GLuint baseDepth, GLenum internalFormat, GLuint pitch, GLintptr offset ); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/console/rgl/ps3/private.h b/console/rgl/ps3/private.h deleted file mode 100644 index 82338ae021..0000000000 --- a/console/rgl/ps3/private.h +++ /dev/null @@ -1,387 +0,0 @@ -#ifndef _RGL_PRIVATE_H -#define _RGL_PRIVATE_H - -#include "rgl.h" - -#ifdef __cplusplus -extern "C" -{ -#endif - -extern PSGLcontext *_CurrentContext; -extern PSGLdevice *_CurrentDevice; - -#define GL_UNSIGNED_BYTE_4_4 0x4A00 -#define GL_UNSIGNED_BYTE_4_4_REV 0x4A01 -#define GL_UNSIGNED_BYTE_6_2 0x4A02 -#define GL_UNSIGNED_BYTE_2_6_REV 0x4A03 -#define GL_UNSIGNED_SHORT_12_4 0x4A04 -#define GL_UNSIGNED_SHORT_4_12_REV 0x4A05 -#define GL_UNSIGNED_BYTE_2_2_2_2 0x4A06 -#define GL_UNSIGNED_BYTE_2_2_2_2_REV 0x4A07 - -#define GL_FLOAT_RGBA32 0x888B - -#define RGL_SETRENDERTARGET_MAXCOUNT 4 - -#define NOP (0x00000000) -#define DEFAULT_FIFO_BLOCK_SIZE (0x10000) - -#define RGL_F0_DOT_0 12582912.0f - -#define RGL_CLAMPF_01(x) ((x) >= 0.0f ? ((x) > 1.0f ? 1.0f : (x)) : 0.0f) - -#define ENDIAN_32(X, F) ((F) ? endianSwapWord(X) : (X)) - -#define VERTEX_PROFILE_INDEX 0 -#define FRAGMENT_PROFILE_INDEX 1 - -typedef union -{ - unsigned int i; - float f; -} jsIntAndFloat; - -static const jsIntAndFloat _RGLNan = {i: 0x7fc00000U}; -static const jsIntAndFloat _RGLInfinity = {i: 0x7f800000U}; - - -typedef struct RGLRenderTargetEx RGLRenderTargetEx; -struct RGLRenderTargetEx -{ - RGLEnum colorFormat; - GLuint colorBufferCount; - GLuint colorId[RGL_SETRENDERTARGET_MAXCOUNT]; - GLuint colorIdOffset[RGL_SETRENDERTARGET_MAXCOUNT]; - GLuint colorPitch[RGL_SETRENDERTARGET_MAXCOUNT]; - GLboolean yInverted; - GLuint xOffset; - GLuint yOffset; - GLuint width; - GLuint height; -}; - -struct jsPlatformFramebuffer: public jsFramebuffer -{ - RGLRenderTargetEx rt; - GLuint colorBufferMask; - GLboolean complete; - jsPlatformFramebuffer(): jsFramebuffer() { memset( &rt, 0, sizeof( rt ) ); }; - virtual ~jsPlatformFramebuffer() {}; -}; - -typedef struct _RGLDriver_ -{ - RGLRenderTargetEx rt; - GLuint colorBufferMask; - GLboolean rtValid; - GLboolean invalidateVertexCache; - GLuint flushBufferCount; - GLuint fpLoadProgramId; - GLuint fpLoadProgramOffset; -} -RGLDriver; - -typedef struct -{ - GLuint SET_TEXTURE_CONTROL3; - GLuint SET_TEXTURE_OFFSET; - GLuint SET_TEXTURE_FORMAT; - GLuint SET_TEXTURE_ADDRESS; - GLuint SET_TEXTURE_CONTROL0; - GLuint SET_TEXTURE_CONTROL1; - GLuint SET_TEXTURE_FILTER; - GLuint SET_TEXTURE_IMAGE_RECT; -} RGLTextureMethods; - -struct RGLTextureAddress -{ - GLuint gamma; -}; - -struct RGLTextureFilter -{ - GLuint min; - GLuint mag; - GLint bias; -}; - -struct RGLTextureMethodParams -{ - RGLTextureAddress address; - RGLTextureFilter filter; -}; - - -typedef struct -{ - GLuint baseWidth; - GLuint baseHeight; - RGLEnum internalFormat; - GLuint pixelBits; - GLuint pitch; -} RGLTextureLayout; - -typedef struct -{ - GLenum pool; - RGLTextureMethodParams gcmMethods; - CellGcmTexture gcmTexture; - GLuint gpuAddressId; - GLuint gpuAddressIdOffset; - GLuint gpuSize; - RGLTextureLayout gpuLayout; - jsBufferObject* pbo; -} RGLTexture; - -typedef struct _tagMODESTRUC -{ - GLushort wHorizVisible; - GLushort wVertVisible; - GLushort wInterlacedMode; - GLushort wRefresh; - GLushort wHorizTotal; - GLushort wHorizBlankStart; - GLushort wHorizSyncStart; - GLushort wHorizSyncEnd; - GLushort wHorizBlankEnd; - GLushort wVertTotal; - GLushort wVertBlankStart; - GLushort wVertSyncStart; - GLushort wVertSyncEnd; - GLushort wVertBlankEnd; - GLuint dwDotClock; - GLushort wHSyncPolarity; - GLushort wVSyncPolarity; -} -MODESTRUC; - -enum -{ - SURFACE_SOURCE_TEMPORARY, - SURFACE_SOURCE_DEVICE, - SURFACE_SOURCE_TEXTURE, - SURFACE_SOURCE_PBO, -}; - -enum -{ - SURFACE_POOL_NONE, - SURFACE_POOL_LINEAR, - SURFACE_POOL_SYSTEM, -}; - - -typedef struct -{ - GLenum source; - GLuint width, height; - GLuint bpp; - GLuint pitch; - RGLEnum format; - GLenum pool; - char* ppuData; - GLuint dataId; - GLuint dataIdOffset; -} RGLSurface; - - -typedef struct -{ - RGLRenderTargetEx rt; - RGLSurface color[3]; - GLuint drawBuffer; - GLuint scanBuffer; - GLuint RescColorBuffersId; - GLuint RescVertexArrayId; - GLuint RescFragmentShaderId; - - const MODESTRUC *ms; - GLboolean vsync; - GLenum deviceType; - GLenum TVStandard; - GLenum TVFormat; - GLuint swapFifoRef; - GLuint swapFifoRef2; - GLboolean setOffset; - GLboolean signal; - GLuint semaValue; - unsigned int syncMethod; -} RGLDevice; - -int32_t _RGLOutOfSpaceCallback( struct CellGcmContextData *con, uint32_t space ); - -typedef struct _RGLShader_ -{ - GLuint loadAddressId; - CgBinaryProgram __attribute__(( aligned( 16 ) ) ) program; -} RGLShader; - - -void _RGLFifoFinish( RGLFifo *fifo ); - -#define _RGLFifoFlush(fifo) \ -{ \ - uint32_t offsetInBytes = 0; \ - cellGcmAddressToOffset( fifo->current, &offsetInBytes ); \ - cellGcmFlush( &_RGLState.fifo); \ - fifo->dmaControl->Put = offsetInBytes; \ - fifo->lastPutWritten = fifo->current; \ - fifo->lastSWReferenceFlushed = fifo->lastSWReferenceWritten; \ -} - -#define LM_MAX_TOTAL_QUERIES 800 - -typedef struct RGLTextureState RGLTextureState; - -struct RGLTextureState -{ - GLuint hwTexAddress; - GLuint hwTexFilter; - GLuint hwTexControl0; -}; - -void _RGLDestroy( void ); - -typedef void( * RGLcontextHookFunction )( PSGLcontext *context ); -extern RGLcontextHookFunction _RGLContextCreateHook; -extern RGLcontextHookFunction _RGLContextDestroyHook; - -extern PSGLcontext* _RGLContextCreate (void); -extern void _RGLContextFree( PSGLcontext* LContext ); -extern void _RGLSetError( GLenum error ); -void _RGLAttachContext( PSGLdevice *device, PSGLcontext* context ); - -extern jsTexture *_RGLGetCurrentTexture( const jsTextureImageUnit *unit, GLenum target ); - -void _RGLVertexAttribPointerNV( GLuint index, GLint fsize, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* pointer ); -void _RGLEnableVertexAttribArrayNV( GLuint index ); -void _RGLDisableVertexAttribArrayNV( GLuint index ); - -void _RGLFifoGlSetRenderTarget( RGLRenderTargetEx const * const args ); - -extern void _RGLDeviceInit( PSGLinitOptions* options ); -extern void _RGLDeviceExit (void); - -static inline GLuint RGL_QUICK_FLOAT2UINT( const GLfloat f ) -{ - union - { - GLfloat f; - GLuint ui; - } t; - t.f = f + RGL_F0_DOT_0; - return t.ui & 0xffff; -} - -static inline void RGL_CALC_COLOR_LE_ARGB8( GLuint *color0, const GLfloat r, -const GLfloat g, const GLfloat b, const GLfloat a ) -{ - GLuint r2 = RGL_QUICK_FLOAT2UINT( r * 255.0f ); - GLuint g2 = RGL_QUICK_FLOAT2UINT( g * 255.0f ); - GLuint b2 = RGL_QUICK_FLOAT2UINT( b * 255.0f ); - GLuint a2 = RGL_QUICK_FLOAT2UINT( a * 255.0f ); - *color0 = ( a2 << 24 ) | ( r2 << 16 ) | ( g2 << 8 ) | ( b2 << 0 ); -} - -static inline GLuint _RGLMapMinTextureFilter( GLenum filter ) -{ - switch ( filter ) - { - case GL_NEAREST: - return CELL_GCM_TEXTURE_NEAREST; - case GL_LINEAR: - return CELL_GCM_TEXTURE_LINEAR; - case GL_NEAREST_MIPMAP_NEAREST: - return CELL_GCM_TEXTURE_NEAREST_NEAREST; - case GL_NEAREST_MIPMAP_LINEAR: - return CELL_GCM_TEXTURE_NEAREST_LINEAR; - case GL_LINEAR_MIPMAP_NEAREST: - return CELL_GCM_TEXTURE_LINEAR_NEAREST; - case GL_LINEAR_MIPMAP_LINEAR: - return CELL_GCM_TEXTURE_LINEAR_LINEAR; - } - return filter; -} - -static inline GLuint _RGLMapMagTextureFilter( GLenum filter ) -{ - switch ( filter ) - { - case GL_NEAREST: - return CELL_GCM_TEXTURE_NEAREST; - case GL_LINEAR: - return CELL_GCM_TEXTURE_LINEAR; - } - return filter; -} - -static inline void _RGLMapTextureFormat( GLuint internalFormat, uint8_t & gcmFormat, uint32_t & remap ) -{ - gcmFormat = 0; - - switch ( internalFormat ) - { - case RGL_ALPHA8: // in_rgba = xxAx, out_rgba = 000A - gcmFormat = CELL_GCM_TEXTURE_B8; - remap = CELL_GCM_REMAP_MODE( - CELL_GCM_TEXTURE_REMAP_ORDER_XYXY, - CELL_GCM_TEXTURE_REMAP_FROM_B, - CELL_GCM_TEXTURE_REMAP_FROM_R, - CELL_GCM_TEXTURE_REMAP_FROM_B, - CELL_GCM_TEXTURE_REMAP_FROM_B, - CELL_GCM_TEXTURE_REMAP_REMAP, - CELL_GCM_TEXTURE_REMAP_ZERO, - CELL_GCM_TEXTURE_REMAP_ZERO, - CELL_GCM_TEXTURE_REMAP_ZERO ); - - break; - case RGL_ARGB8: // in_rgba = RGBA, out_rgba = RGBA - gcmFormat = CELL_GCM_TEXTURE_A8R8G8B8; - remap = CELL_GCM_REMAP_MODE( - CELL_GCM_TEXTURE_REMAP_ORDER_XYXY, - CELL_GCM_TEXTURE_REMAP_FROM_A, - CELL_GCM_TEXTURE_REMAP_FROM_R, - CELL_GCM_TEXTURE_REMAP_FROM_G, - CELL_GCM_TEXTURE_REMAP_FROM_B, - CELL_GCM_TEXTURE_REMAP_REMAP, - CELL_GCM_TEXTURE_REMAP_REMAP, - CELL_GCM_TEXTURE_REMAP_REMAP, - CELL_GCM_TEXTURE_REMAP_REMAP ); - break; - case RGL_RGB5_A1_SCE: // in_rgba = RGBA, out_rgba = RGBA - gcmFormat = CELL_GCM_TEXTURE_A1R5G5B5; - remap = CELL_GCM_REMAP_MODE( - CELL_GCM_TEXTURE_REMAP_ORDER_XXXY, - CELL_GCM_TEXTURE_REMAP_FROM_A, - CELL_GCM_TEXTURE_REMAP_FROM_R, - CELL_GCM_TEXTURE_REMAP_FROM_G, - CELL_GCM_TEXTURE_REMAP_FROM_B, - CELL_GCM_TEXTURE_REMAP_REMAP, - CELL_GCM_TEXTURE_REMAP_REMAP, - CELL_GCM_TEXTURE_REMAP_REMAP, - CELL_GCM_TEXTURE_REMAP_REMAP ); - break; - case RGL_RGB565_SCE: // in_rgba = RGBA, out_rgba = RGBA - gcmFormat = CELL_GCM_TEXTURE_R5G6B5; - remap = CELL_GCM_REMAP_MODE( - CELL_GCM_TEXTURE_REMAP_ORDER_XXXY, - CELL_GCM_TEXTURE_REMAP_FROM_A, - CELL_GCM_TEXTURE_REMAP_FROM_R, - CELL_GCM_TEXTURE_REMAP_FROM_G, - CELL_GCM_TEXTURE_REMAP_FROM_B, - CELL_GCM_TEXTURE_REMAP_ONE, - CELL_GCM_TEXTURE_REMAP_REMAP, - CELL_GCM_TEXTURE_REMAP_REMAP, - CELL_GCM_TEXTURE_REMAP_REMAP ); - break; - }; - - return; -} - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/console/rgl/ps3/readelf.h b/console/rgl/ps3/readelf.h deleted file mode 100644 index 2f4001087a..0000000000 --- a/console/rgl/ps3/readelf.h +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef READELF_H -#define READELF_H - -#include "elf.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct _ELF_section_t -{ - Elf32_Shdr header; - const char *name; - char *data; -} ELF_section_t; - -typedef struct _ELF_segment_t -{ - Elf32_Phdr header; - unsigned char *pointer; - unsigned char *data; -} ELF_segment_t; - -typedef struct -{ - const char *name; - unsigned int vma; - unsigned int size; - int section; - unsigned char resolved; - unsigned char foreign; -} ELF_symbol_t; - -typedef struct _ELF_t -{ - unsigned int endian; - unsigned int relocatable; - unsigned int sectionCount; - unsigned int segmentCount; - unsigned int symbolCount; - unsigned int entrypoint; - ELF_section_t *sections; - ELF_segment_t *segments; - ELF_symbol_t *symbols; - unsigned int symbolsSection; - unsigned int symbolNamesSection; - unsigned int paramSection; -} ELF_t; - -typedef struct -{ - unsigned int relative; - unsigned int shift; - unsigned int size; - unsigned int position; - unsigned int mask; -} ELF_rel_type_t; - -ELF_section_t *findSection(const ELF_t *elf, const char *name); -int lookupSymbol(const ELF_t *elf, const char *name); - -#ifdef __cplusplus -} -#endif - -#endif // READELF_H diff --git a/console/rgl/ps3/rgl.cpp b/console/rgl/ps3/rgl.cpp deleted file mode 100644 index c2a12a5f1e..0000000000 --- a/console/rgl/ps3/rgl.cpp +++ /dev/null @@ -1,8183 +0,0 @@ -#include -#include -#include -#include -#include - -#include - -#include - -#include "rgl.h" -#include "private.h" -#include - -#include "cg.h" -#include -#include -#include "readelf.h" -#include "cgnv2rt.h" - -#include - -#include "../../../compat/strl.h" -#include "../../../general.h" - -#define ENDIAN_32(X, F) ((F) ? endianSwapWord(X) : (X)) -#define SWAP_IF_BIG_ENDIAN(arg) endianSwapWordByHalf(arg) - -#define ROW_MAJOR 0 -#define COL_MAJOR 1 - -#define pad(x, pad) (((x) + (pad) - 1 ) / (pad) * (pad)) - -#define GL_UNSIGNED_SHORT_8_8 GL_UNSIGNED_SHORT_8_8_SCE -#define GL_UNSIGNED_SHORT_8_8_REV GL_UNSIGNED_SHORT_8_8_REV_SCE -#define GL_UNSIGNED_INT_16_16 GL_UNSIGNED_INT_16_16_SCE -#define GL_UNSIGNED_INT_16_16_REV GL_UNSIGNED_INT_16_16_REV_SCE - -#define DECLARE_C_TYPES \ -DECLARE_TYPE(GL_BYTE,GLbyte,127.f) \ -DECLARE_TYPE(GL_UNSIGNED_BYTE,GLubyte,255.f) \ -DECLARE_TYPE(GL_SHORT,GLshort,32767.f) \ -DECLARE_TYPE(GL_UNSIGNED_SHORT,GLushort,65535.f) \ -DECLARE_TYPE(GL_INT,GLint,2147483647.f) \ -DECLARE_TYPE(GL_UNSIGNED_INT,GLuint,4294967295.0) \ -DECLARE_TYPE(GL_FIXED,GLfixed,65535.f) - -#define DECLARE_UNPACKED_TYPES \ -DECLARE_UNPACKED_TYPE(GL_BYTE) \ -DECLARE_UNPACKED_TYPE(GL_UNSIGNED_BYTE) \ -DECLARE_UNPACKED_TYPE(GL_SHORT) \ -DECLARE_UNPACKED_TYPE(GL_UNSIGNED_SHORT) \ -DECLARE_UNPACKED_TYPE(GL_INT) \ -DECLARE_UNPACKED_TYPE(GL_UNSIGNED_INT) \ -DECLARE_UNPACKED_TYPE(GL_HALF_FLOAT_ARB) \ -DECLARE_UNPACKED_TYPE(GL_FLOAT) \ -DECLARE_UNPACKED_TYPE(GL_FIXED) - - -#define DECLARE_PACKED_TYPES \ -DECLARE_PACKED_TYPE_AND_REV_2(UNSIGNED_BYTE,4,4) \ -DECLARE_PACKED_TYPE_AND_REV_2(UNSIGNED_BYTE,6,2) \ -DECLARE_PACKED_TYPE_AND_REV_3(UNSIGNED_BYTE,3,3,2) \ -DECLARE_PACKED_TYPE_AND_REV_4(UNSIGNED_BYTE,2,2,2,2) \ -DECLARE_PACKED_TYPE_AND_REV_2(UNSIGNED_SHORT,12,4) \ -DECLARE_PACKED_TYPE_AND_REV_2(UNSIGNED_SHORT,8,8) \ -DECLARE_PACKED_TYPE_AND_REV_3(UNSIGNED_SHORT,5,6,5) \ -DECLARE_PACKED_TYPE_AND_REV_4(UNSIGNED_SHORT,4,4,4,4) \ -DECLARE_PACKED_TYPE_AND_REV_4(UNSIGNED_SHORT,5,5,5,1) \ -DECLARE_PACKED_TYPE_AND_REV_2(UNSIGNED_INT,16,16) \ -DECLARE_PACKED_TYPE_AND_REV_4(UNSIGNED_INT,8,8,8,8) \ -DECLARE_PACKED_TYPE_AND_REV_4(UNSIGNED_INT,10,10,10,2) - -#define DECLARE_FORMATS \ -DECLARE_FORMAT(GL_RGB,3) \ -DECLARE_FORMAT(GL_BGR,3) \ -DECLARE_FORMAT(GL_RGBA,4) \ -DECLARE_FORMAT(GL_BGRA,4) \ -DECLARE_FORMAT(GL_ABGR,4) \ -DECLARE_FORMAT(GL_ARGB_SCE,4) \ -DECLARE_FORMAT(GL_RED,1) \ -DECLARE_FORMAT(GL_GREEN,1) \ -DECLARE_FORMAT(GL_BLUE,1) \ -DECLARE_FORMAT(GL_ALPHA,1) - -static int _RGLInitCompleted = 0; -static char *_RGLVendorString = "Retro Arch"; -static char *_RGLRendererString = "RGL"; -static char *_RGLExtensionsString = ""; -static char *_RGLVersionNumber = "1.0"; - -PSGLcontext* _CurrentContext = NULL; -RGLcontextHookFunction _RGLContextCreateHook = NULL; -RGLcontextHookFunction _RGLContextDestroyHook = NULL; - -GmmAllocator *pGmmLocalAllocator = NULL; -GmmAllocator *pGmmMainAllocator = NULL; -static volatile uint32_t *pLock = NULL; -static uint32_t cachedLockValue = 0; -static GmmFixedAllocData *pGmmFixedAllocData = NULL; -GLuint nvFenceCounter = 0; - -#define CAPACITY_INCR 16 -#define NAME_INCREMENT 4 - -#define DECLARE_TYPE(TYPE,CTYPE,MAXVAL) \ -typedef CTYPE type_##TYPE; \ -static inline type_##TYPE _RGLFloatTo_##TYPE(float v) { return (type_##TYPE)((MAX(MIN(v, 1.f), 0.f)) * MAXVAL); } \ -static inline float _RGLFloatFrom_##TYPE(type_##TYPE v) { return ((float)v)/MAXVAL; } -DECLARE_C_TYPES -#undef DECLARE_TYPE - -typedef GLfloat type_GL_FLOAT; - -static inline type_GL_FLOAT _RGLFloatTo_GL_FLOAT(float v) -{ - return v; -} - -static inline float _RGLFloatFrom_GL_FLOAT(type_GL_FLOAT v) -{ - return v; -} - -typedef GLhalfARB type_GL_HALF_FLOAT_ARB; - -static const char *findSectionInPlace(const char* memory,unsigned int /*size*/,const char *name, size_t *sectionSize) -{ - const Elf32_Ehdr *ehdr = (const Elf32_Ehdr*)memory; - - const char *sectionHeaderStart = (const char*)ehdr + ehdr->e_shoff; - const Elf32_Shdr *shstrtabHeader = (const Elf32_Shdr*)sectionHeaderStart + ehdr->e_shstrndx; - const char *shstrtab = (const char*)ehdr + shstrtabHeader->sh_offset; - - size_t sectionCount = ehdr->e_shnum; - - for(size_t i=0; i < sectionCount; i++) - { - const Elf32_Shdr *sectionHeader = (const Elf32_Shdr *)sectionHeaderStart + i; - const char *sectionName = shstrtab + sectionHeader->sh_name; - if (!strcmp(name,sectionName)) - { - *sectionSize = sectionHeader->sh_size; - return (const char*)ehdr + sectionHeader->sh_offset; - } - } - return NULL; -} - -static const char *findSymbolSectionInPlace(const char *memory, unsigned int /*size*/, size_t *symbolSize, size_t *symbolCount, const char **symbolstrtab) -{ - const Elf32_Ehdr *ehdr = (const Elf32_Ehdr*)memory; - - size_t sectionCount = ehdr->e_shnum; - const char *sectionHeaderStart = (const char*)ehdr + ehdr->e_shoff; - - for(size_t i = 0; ish_type == SHT_SYMTAB) - { - *symbolSize = sectionHeader->sh_entsize; - *symbolCount = sectionHeader->sh_size / sectionHeader->sh_entsize; - - const Elf32_Shdr *symbolStrHeader = (const Elf32_Shdr *)sectionHeaderStart + sectionHeader->sh_link; - *symbolstrtab = (const char*)ehdr + symbolStrHeader->sh_offset; - return (const char*)ehdr + sectionHeader->sh_offset; - } - } - return NULL; -} - -static int lookupSymbolValueInPlace(const char* symbolSection, size_t symbolSize, size_t symbolCount, const char *symbolstrtab, const char *name) -{ - for (size_t i = 0; i < symbolCount; i++) - { - Elf32_Sym* elf_sym = (Elf32_Sym*)symbolSection; - - if (!strcmp(symbolstrtab + elf_sym->st_name, name)) - return elf_sym->st_value; - - symbolSection += symbolSize; - } - return -1; -} - -static const char *getSymbolByIndexInPlace(const char* symbolSection, size_t symbolSize, size_t symbolCount, const char *symbolstrtab, int index) -{ - Elf32_Sym* elf_sym = (Elf32_Sym*)symbolSection + index; - return symbolstrtab + elf_sym->st_name; -} - -static inline type_GL_HALF_FLOAT_ARB _RGLFloatTo_GL_HALF_FLOAT_ARB( float x ) -{ - jsIntAndFloat V = {f: x}; - unsigned int S = ( V.i >> 31 ) & 1; - int E = (( V.i >> 23 ) & 0xff ) - 0x7f; - unsigned int M = V.i & 0x007fffff; - if (( E == 0x80 ) && ( M ) ) return 0x7fff; - else if ( E >= 15 ) return( S << 15 ) | 0x7c00; - else if ( E <= -14 ) return( S << 15 ) | (( 0x800000 + M ) >> ( -14 - E ) ); - else return( S << 15 ) | ((( E + 15 )&0x1f ) << 10 ) | ( M >> 13 ); -} - -static inline float _RGLFloatFrom_GL_HALF_FLOAT_ARB( type_GL_HALF_FLOAT_ARB x ) -{ - unsigned int S = x >> 15; - unsigned int E = ( x & 0x7C00 ) >> 10; - unsigned int M = x & 0x03ff; - float f; - if ( E == 31 ) - { - if ( M == 0 ) f = _RGLInfinity.f; - else f = _RGLNan.f; - } - else if ( E == 0 ) - { - if ( M == 0 ) f = 0.f; - else f = M * 1.f / ( 1 << 24 ); - } - else f = ( 0x400 + M ) * 1.f / ( 1 << 25 ) * ( 1 << E ); - return S ? -f : f; -} - -#define DECLARE_PACKED_TYPE_AND_REV_2(REALTYPE,S1,S2) \ -DECLARE_PACKED_TYPE(GL_##REALTYPE,GL_##REALTYPE##_##S1##_##S2,2,S1,S2,0,0,) \ -DECLARE_PACKED_TYPE(GL_##REALTYPE,GL_##REALTYPE##_##S2##_##S1##_REV,2,S2,S1,0,0,_REV) - -#define DECLARE_PACKED_TYPE_AND_REV_3(REALTYPE,S1,S2,S3) \ -DECLARE_PACKED_TYPE(GL_##REALTYPE,GL_##REALTYPE##_##S1##_##S2##_##S3,3,S1,S2,S3,0,) \ -DECLARE_PACKED_TYPE(GL_##REALTYPE,GL_##REALTYPE##_##S3##_##S2##_##S1##_REV,3,S3,S2,S1,0,_REV) - -#define DECLARE_PACKED_TYPE_AND_REV_4(REALTYPE,S1,S2,S3,S4) \ -DECLARE_PACKED_TYPE(GL_##REALTYPE,GL_##REALTYPE##_##S1##_##S2##_##S3##_##S4,4,S1,S2,S3,S4,) \ -DECLARE_PACKED_TYPE(GL_##REALTYPE,GL_##REALTYPE##_##S4##_##S3##_##S2##_##S1##_REV,4,S4,S3,S2,S1,_REV) - -#define DECLARE_PACKED_TYPE_AND_REALTYPE(REALTYPE,N,S1,S2,S3,S4,REV) \ -DECLARE_PACKED_TYPE(GL_##REALTYPE,PACKED_TYPE(REALTYPE,N,S1,S2,S3,S4,REV),N,S1,S2,S3,S4,REV) - -#define INDEX(N,X) (X) -#define INDEX_REV(N,X) (N-1-X) - -#define GET_BITS(to,from,first,count) if ((count)>0) to=((GLfloat)(((from)>>(first))&((1<<(count))-1)))/(GLfloat)((1<<((count==0)?1:count))-1) -#define PUT_BITS(from,to,first,count) if ((count)>0) to|=((unsigned int)((from)*((GLfloat)((1<<((count==0)?1:count))-1))))<<(first); - -static void _RGLResetAttributeState( jsAttributeState* as ) -{ - for(int i = 0; i < MAX_VERTEX_ATTRIBS; ++i) - { - as->attrib[i].clientSize = 4; - as->attrib[i].clientType = GL_FLOAT; - as->attrib[i].clientStride = 16; - as->attrib[i].clientData = NULL; - - as->attrib[i].value[0] = 0.0f; - as->attrib[i].value[1] = 0.0f; - as->attrib[i].value[2] = 0.0f; - as->attrib[i].value[3] = 1.0f; - - as->attrib[i].normalized = GL_FALSE; - as->attrib[i].frequency = 1; - - as->attrib[i].arrayBuffer = 0; - } - - as->attrib[_RGL_ATTRIB_PRIMARY_COLOR_INDEX].value[0] = 1.0f; - as->attrib[_RGL_ATTRIB_PRIMARY_COLOR_INDEX].value[1] = 1.0f; - as->attrib[_RGL_ATTRIB_PRIMARY_COLOR_INDEX].value[2] = 1.0f; - as->attrib[_RGL_ATTRIB_PRIMARY_COLOR_INDEX].value[3] = 1.0f; - - as->attrib[_RGL_ATTRIB_SECONDARY_COLOR_INDEX].value[0] = 1.0f; - as->attrib[_RGL_ATTRIB_SECONDARY_COLOR_INDEX].value[1] = 1.0f; - as->attrib[_RGL_ATTRIB_SECONDARY_COLOR_INDEX].value[2] = 1.0f; - as->attrib[_RGL_ATTRIB_SECONDARY_COLOR_INDEX].value[3] = 1.0f; - - as->attrib[_RGL_ATTRIB_NORMAL_INDEX].value[0] = 0.f; - as->attrib[_RGL_ATTRIB_NORMAL_INDEX].value[1] = 0.f; - as->attrib[_RGL_ATTRIB_NORMAL_INDEX].value[2] = 1.f; - - as->DirtyMask = (1 << MAX_VERTEX_ATTRIBS) - 1; - as->EnabledMask = 0; - as->NeedsConversionMask = 0; - as->HasVBOMask = 0; - as->ModuloMask = 0; -} - -static jsAttribSet* _RGLCreateAttribSet( void ) -{ - jsAttribSet* attribSet = (jsAttribSet*)memalign(16, sizeof(jsAttribSet)); - - _RGLResetAttributeState(&attribSet->attribs); - - attribSet->dirty = GL_TRUE; - attribSet->beenUpdatedMask = 0; - attribSet->cmdBuffer = NULL; - attribSet->cmdNumWords = 0; - - return attribSet; -} - -static void _RGLDestroyAttribSet( jsAttribSet* attribSet ) -{ - if ( attribSet->cmdBuffer ) - free( attribSet->cmdBuffer ); - free( attribSet ); -} - -static void _RGLAttribSetDeleteBuffer( PSGLcontext *LContext, GLuint buffName ) -{ - jsBufferObject *bufferObject = ( jsBufferObject * )LContext->bufferObjectNameSpace.data[buffName]; - GLuint attrSetCount = bufferObject->attribSets.getCount(); - if ( attrSetCount == 0 ) return; - for ( unsigned int i = 0;i < attrSetCount;++i ) - { - jsAttribSet *attribSet = bufferObject->attribSets[i]; - - for(GLuint j = 0; j < MAX_VERTEX_ATTRIBS; ++j) - { - if(attribSet->attribs.attrib[j].arrayBuffer == buffName) - attribSet->attribs.attrib[j].arrayBuffer = 0; - } - - attribSet->dirty = GL_TRUE; - } - LContext->attribSetDirty = GL_TRUE; - bufferObject->attribSets.clear(); -} - -static jsBufferObject *_RGLCreateBufferObject (void) -{ - GLuint size = sizeof(jsBufferObject) + sizeof(RGLBufferObject); - jsBufferObject *buffer = (jsBufferObject*)malloc(size); - - if( !buffer ) - return NULL; - - memset(buffer, 0, size); - - buffer->refCount = 1; - new( &buffer->textureReferences ) RGL::Vector(); - new( &buffer->attribSets ) RGL::Vector(); - - return buffer; -} - -static void _RGLPlatformDestroyBufferObject( jsBufferObject* bufferObject ) -{ - RGLBufferObject *jsBuffer = (RGLBufferObject*)bufferObject->platformBufferObject; - - switch(jsBuffer->pool) - { - case SURFACE_POOL_SYSTEM: - case SURFACE_POOL_LINEAR: - gmmFree( jsBuffer->bufferId ); - break; - case SURFACE_POOL_NONE: - break; - default: - break; - } - - jsBuffer->pool = SURFACE_POOL_NONE; - jsBuffer->bufferId = GMM_ERROR; -} - -static void _RGLFreeBufferObject( jsBufferObject *buffer ) -{ - if(--buffer->refCount == 0) - { - _RGLPlatformDestroyBufferObject( buffer ); - buffer->textureReferences.~Vector(); - buffer->attribSets.~Vector(); - - if(buffer != NULL) - free( buffer ); - } -} - -GLAPI void APIENTRY glBindBuffer( GLenum target, GLuint name ) -{ - PSGLcontext *LContext = _CurrentContext; - - if(name) - _RGLTexNameSpaceCreateNameLazy( &LContext->bufferObjectNameSpace, name ); - - switch(target) - { - case GL_ARRAY_BUFFER: - LContext->ArrayBuffer = name; - break; - case GL_ELEMENT_ARRAY_BUFFER: - break; - case GL_PIXEL_PACK_BUFFER_ARB: - break; - case GL_PIXEL_UNPACK_BUFFER_ARB: - LContext->PixelUnpackBuffer = name; - break; - case GL_TEXTURE_REFERENCE_BUFFER_SCE: - LContext->TextureBuffer = name; - break; - default: - break; - } -} - -GLAPI void APIENTRY glDeleteBuffers(GLsizei n, const GLuint *buffers) -{ - PSGLcontext *LContext = _CurrentContext; - for(int i = 0; i < n; ++i) - { - if(!_RGLTexNameSpaceIsName( &LContext->bufferObjectNameSpace, buffers[i] ) ) - continue; - - if(buffers[i] ) - { - GLuint name = buffers[i]; - - if(LContext->ArrayBuffer == name) - LContext->ArrayBuffer = 0; - - if(LContext->PixelUnpackBuffer == name) - LContext->PixelUnpackBuffer = 0; - - for(int i = 0;i < MAX_VERTEX_ATTRIBS; ++i) - { - if(LContext->attribs->attrib[i].arrayBuffer == name) - { - LContext->attribs->attrib[i].arrayBuffer = 0; - LContext->attribs->HasVBOMask &= ~( 1 << i ); - } - } - _RGLAttribSetDeleteBuffer( LContext, name ); - } - } - _RGLTexNameSpaceDeleteNames( &LContext->bufferObjectNameSpace, n, buffers ); -} - -GLAPI void APIENTRY glGenBuffers(GLsizei n, GLuint *buffers) -{ - PSGLcontext *LContext = _CurrentContext; - _RGLTexNameSpaceGenNames( &LContext->bufferObjectNameSpace, n, buffers ); -} - -static inline void _RGLTextureTouchFBOs(jsTexture *texture) -{ - PSGLcontext *LContext = _CurrentContext; - if(!LContext) - return; - - GLuint fbCount = texture->framebuffers.getCount(); - - if(fbCount > 0) - { - jsFramebuffer *contextFramebuffer = LContext->framebuffer ? (jsFramebuffer *)LContext->framebufferNameSpace.data[LContext->framebuffer] : NULL; - - for (GLuint i = 0; i < fbCount; ++i) - { - jsFramebuffer* framebuffer = texture->framebuffers[i]; - framebuffer->needValidate = GL_TRUE; - if(RGL_UNLIKELY(framebuffer == contextFramebuffer)) - LContext->needValidate |= PSGL_VALIDATE_FRAMEBUFFER; - } - } -} - -static void _RGLAllocateBuffer(jsBufferObject* bufferObject) -{ - RGLBufferObject *jsBuffer = (RGLBufferObject *)bufferObject->platformBufferObject; - - _RGLPlatformDestroyBufferObject(bufferObject); - - jsBuffer->pool = SURFACE_POOL_LINEAR; - jsBuffer->bufferId = gmmAlloc(0, jsBuffer->bufferSize); - jsBuffer->pitch = 0; - - if(jsBuffer->bufferId == GMM_ERROR) - jsBuffer->pool = SURFACE_POOL_NONE; - - GLuint referenceCount = bufferObject->textureReferences.getCount(); - if(referenceCount > 0) - { - for (GLuint i = 0;i < referenceCount; ++i) - { - jsTexture *texture = bufferObject->textureReferences[i]; - RGLTexture *gcmTexture = ( RGLTexture * )texture->platformTexture; - gcmTexture->gpuAddressId = jsBuffer->bufferId; - gcmTexture->gpuAddressIdOffset = texture->offset; - texture->revalidate |= TEXTURE_REVALIDATE_PARAMETERS; - _RGLTextureTouchFBOs( texture ); - } - _CurrentContext->needValidate |= PSGL_VALIDATE_TEXTURES_USED | PSGL_VALIDATE_VERTEX_TEXTURES_USED ; - } -} - -static void _RGLMemcpy( const GLuint dstId, unsigned dstOffset, unsigned int pitch, const GLuint srcId, unsigned int size ) -{ - pitch = pitch ? : 64; - const GLuint dstOffsetAlign = dstOffset % pitch; - GLuint srcOffset = 0; - - if ( dstOffsetAlign ) - { - const GLuint firstBytes = MIN( pitch - dstOffsetAlign, size ); - - transfer_params_t transfer_params; - - transfer_params.dst_id = dstId; - transfer_params.dst_id_offset = 0; - transfer_params.dst_pitch = pitch; - transfer_params.dst_x = dstOffsetAlign / 2; - transfer_params.dst_y = dstOffset / pitch; - transfer_params.src_id = srcId; - transfer_params.src_id_offset = srcOffset; - transfer_params.src_pitch = pitch; - transfer_params.src_x = 0; - transfer_params.src_y = 0; - transfer_params.width = firstBytes / 2; - transfer_params.height = 1; - transfer_params.bpp = 2; - transfer_params.fifo_ptr = &_RGLState.fifo; - - TransferDataVidToVid(&transfer_params); - - dstOffset += firstBytes; - srcOffset += firstBytes; - size -= firstBytes; - } - - const GLuint fullLines = size / pitch; - const GLuint extraBytes = size % pitch; - - if ( fullLines ) - { - transfer_params_t transfer_params; - - transfer_params.dst_id = dstId; - transfer_params.dst_id_offset = 0; - transfer_params.dst_pitch = pitch; - transfer_params.dst_x = 0; - transfer_params.dst_y = dstOffset / pitch; - transfer_params.src_id = srcId; - transfer_params.src_id_offset = srcOffset; - transfer_params.src_pitch = pitch; - transfer_params.src_x = 0; - transfer_params.src_y = 0; - transfer_params.width = pitch / 2; - transfer_params.height = fullLines; - transfer_params.bpp = 2; - transfer_params.fifo_ptr = &_RGLState.fifo; - - TransferDataVidToVid(&transfer_params); - } - - if ( extraBytes ) - { - transfer_params_t transfer_params; - - transfer_params.dst_id = dstId; - transfer_params.dst_id_offset = 0; - transfer_params.dst_pitch = pitch; - transfer_params.dst_x = 0; - transfer_params.dst_y = fullLines + dstOffset / pitch; - transfer_params.src_id = srcId; - transfer_params.src_id_offset = srcOffset; - transfer_params.src_pitch = pitch; - transfer_params.src_x = 0; - transfer_params.src_y = fullLines; - transfer_params.width = extraBytes / 2; - transfer_params.height = 1; - transfer_params.bpp = 2; - transfer_params.fifo_ptr = &_RGLState.fifo; - - TransferDataVidToVid(&transfer_params); - } -} - -static void _RGLPlatformBufferObjectSetData( jsBufferObject* bufferObject, GLintptr offset, GLsizeiptr size, const GLvoid *data, GLboolean tryImmediateCopy ) -{ - RGLBufferObject *jsBuffer = ( RGLBufferObject * )bufferObject->platformBufferObject; - - if ( size == bufferObject->size && tryImmediateCopy ) - memcpy( gmmIdToAddress( jsBuffer->bufferId ) + offset, data, size ); - else - if ( size >= bufferObject->size ) - { - jsBuffer->bufferSize = _RGLPad( size, _RGL_BUFFER_OBJECT_BLOCK_SIZE ); - _RGLAllocateBuffer( bufferObject ); - - switch ( jsBuffer->pool ) - { - case SURFACE_POOL_NONE: - _RGLSetError( GL_OUT_OF_MEMORY ); - return; - default: - memcpy( gmmIdToAddress( jsBuffer->bufferId ), data, size ); - break; - } - } - else - { - if ( tryImmediateCopy ) - memcpy( gmmIdToAddress( jsBuffer->bufferId ) + offset, data, size ); - else - { - unsigned int dstId = jsBuffer->bufferId; - unsigned int pitch = jsBuffer->pitch; - const char *src = (const char *)data; - - switch ( bufferObject->usage ) - { - case GL_STREAM_DRAW: - case GL_STREAM_READ: - case GL_STREAM_COPY: - case GL_DYNAMIC_DRAW: - case GL_DYNAMIC_READ: - case GL_DYNAMIC_COPY: - { - GLuint id = gmmAlloc(0, size); - - memcpy( gmmIdToAddress(id), src, size ); - _RGLMemcpy( dstId, offset, pitch, id, size ); - - gmmFree( id ); - } - break; - default: - cellGcmSetInvalidateVertexCache( &_RGLState.fifo); - _RGLFifoFinish( &_RGLState.fifo ); - memcpy( gmmIdToAddress( dstId ) + offset, src, size ); - break; - }; - } - } - - ((RGLDriver *)_CurrentDevice->rasterDriver)->invalidateVertexCache = GL_TRUE; -} - -static GLboolean _RGLPlatformCreateBufferObject( jsBufferObject* bufferObject ) -{ - RGLBufferObject *jsBuffer = ( RGLBufferObject * )bufferObject->platformBufferObject; - - jsBuffer->pool = SURFACE_POOL_NONE; - jsBuffer->bufferId = GMM_ERROR; - jsBuffer->mapCount = 0; - jsBuffer->mapAccess = GL_NONE; - jsBuffer->bufferSize = _RGLPad( bufferObject->size, _RGL_BUFFER_OBJECT_BLOCK_SIZE ); - - _RGLAllocateBuffer(bufferObject); - - return jsBuffer->bufferId != GMM_ERROR; -} - -GLAPI void APIENTRY glBufferData( GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage ) -{ - PSGLcontext *LContext = _CurrentContext; - - GLuint name = 0; - switch(target) - { - case GL_ARRAY_BUFFER: - name = LContext->ArrayBuffer; - break; - case GL_ELEMENT_ARRAY_BUFFER: - break; - case GL_PIXEL_PACK_BUFFER_ARB: - break; - case GL_PIXEL_UNPACK_BUFFER_ARB: - name = LContext->PixelUnpackBuffer; - break; - case GL_TEXTURE_REFERENCE_BUFFER_SCE: - name = LContext->TextureBuffer; - break; - default: - _RGLSetError(GL_INVALID_ENUM); - return; - } - - jsBufferObject* bufferObject = (jsBufferObject *)LContext->bufferObjectNameSpace.data[name]; - - if(bufferObject->refCount > 1) - { - _RGLTexNameSpaceDeleteNames( &LContext->bufferObjectNameSpace, 1, &name ); - _RGLTexNameSpaceCreateNameLazy( &LContext->bufferObjectNameSpace, name ); - bufferObject = (jsBufferObject *)LContext->bufferObjectNameSpace.data[name]; - - } - - if (bufferObject->size > 0) - _RGLPlatformDestroyBufferObject( bufferObject ); - - bufferObject->usage = usage; - bufferObject->size = size; - bufferObject->width = 0; - bufferObject->height = 0; - bufferObject->internalFormat = GL_NONE; - - if (size > 0) - { - GLboolean created = _RGLPlatformCreateBufferObject( bufferObject ); - if ( !created ) - { - _RGLSetError( GL_OUT_OF_MEMORY ); - return; - } - if ( data ) - _RGLPlatformBufferObjectSetData( bufferObject, 0, size, data, GL_TRUE ); - } - - GLuint attrSetCount = bufferObject->attribSets.getCount(); - if ( attrSetCount == 0 ) - return; - - for(unsigned int i = 0; i < attrSetCount; ++i) - { - jsAttribSet *attribSet = bufferObject->attribSets[i]; - attribSet->dirty = GL_TRUE; - } - - LContext->attribSetDirty = GL_TRUE; -} - -static GLvoid _RGLPlatformBufferObjectCopyData( jsBufferObject* bufferObjectDst, - jsBufferObject* bufferObjectSrc ) -{ - - RGLBufferObject* dst = ( RGLBufferObject* )bufferObjectDst->platformBufferObject; - RGLBufferObject* src = ( RGLBufferObject* )bufferObjectSrc->platformBufferObject; - - switch ( dst->pool ) - { - case SURFACE_POOL_LINEAR: - _RGLMemcpy( dst->bufferId, 0, dst->pitch, src->bufferId, src->bufferSize ); - break; - case SURFACE_POOL_SYSTEM: - cellGcmSetInvalidateVertexCache( &_RGLState.fifo); - _RGLFifoFinish( &_RGLState.fifo ); - memcpy( gmmIdToAddress( dst->bufferId ), gmmIdToAddress( src->bufferId ), - src->bufferSize ); - break; - } - - ((RGLDriver *)_CurrentDevice->rasterDriver)->invalidateVertexCache = GL_TRUE; -} - -GLAPI void APIENTRY glBufferSubData( GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data ) -{ - PSGLcontext *LContext = _CurrentContext; - GLuint name = 0; - switch ( target ) - { - case GL_ARRAY_BUFFER: - name = LContext->ArrayBuffer; - break; - case GL_ELEMENT_ARRAY_BUFFER: - break; - case GL_PIXEL_PACK_BUFFER_ARB: - break; - case GL_PIXEL_UNPACK_BUFFER_ARB: - name = LContext->PixelUnpackBuffer; - break; - case GL_TEXTURE_REFERENCE_BUFFER_SCE: - name = LContext->TextureBuffer; - break; - default: - _RGLSetError( GL_INVALID_ENUM ); - return; - } - - jsBufferObject* bufferObject = (jsBufferObject *)LContext->bufferObjectNameSpace.data[name]; - - - - if ( bufferObject->refCount > 1 ) - { - jsBufferObject* oldBufferObject = bufferObject; - - _RGLTexNameSpaceDeleteNames( &LContext->bufferObjectNameSpace, 1, &name ); - _RGLTexNameSpaceCreateNameLazy( &LContext->bufferObjectNameSpace, name ); - - bufferObject = (jsBufferObject *)LContext->bufferObjectNameSpace.data[name]; - bufferObject->size = oldBufferObject->size; - bufferObject->usage = oldBufferObject->usage; - - GLboolean created = _RGLPlatformCreateBufferObject( bufferObject ); - if ( !created ) - { - _RGLSetError( GL_OUT_OF_MEMORY ); - return; - } - _RGLPlatformBufferObjectCopyData( bufferObject, oldBufferObject ); - } - _RGLPlatformBufferObjectSetData( bufferObject, offset, size, data, GL_FALSE ); -} - -static void _RGLFramebufferGetAttachmentTexture( - const jsFramebufferAttachment* attachment, - jsTexture** texture) -{ - PSGLcontext* LContext = _CurrentContext; - - switch ( attachment->type ) - { - case FRAMEBUFFER_ATTACHMENT_NONE: - *texture = NULL; - break; - case FRAMEBUFFER_ATTACHMENT_RENDERBUFFER: - break; - case FRAMEBUFFER_ATTACHMENT_TEXTURE: - *texture = _RGLTexNameSpaceIsName( &LContext->textureNameSpace, attachment->name ) ? ( jsTexture* )LContext->textureNameSpace.data[attachment->name] : NULL; - break; - default: - *texture = NULL; - break; - } -} - -static GLboolean _RGLTextureIsValid(const jsTexture* texture) -{ - if(texture->imageCount < 1) - return GL_FALSE; - if ( !texture->image ) - return GL_FALSE; - - const jsImage* image = texture->image; - - int width = image->width; - int height = image->height; - - GLenum format = image->format; - GLenum type = image->type; - GLenum internalFormat = image->internalFormat; - - if (( internalFormat == 0 ) || ( format == 0 ) || ( type == 0 ) ) - return GL_FALSE; - - if(!image->isSet) - return GL_FALSE; - if(width != image->width) - return GL_FALSE; - if(height != image->height) - return GL_FALSE; - if(format != image->format) - return GL_FALSE; - if(type != image->type) - return GL_FALSE; - if(internalFormat != image->internalFormat) - return GL_FALSE; - - return GL_TRUE; -} - -static GLenum _RGLPlatformFramebufferCheckStatus(jsFramebuffer* framebuffer) -{ - GLuint nBuffers = 0; - - jsImage* image[MAX_COLOR_ATTACHMENTS + 2] = {0}; - - GLuint colorFormat = 0; - for ( int i = 0; i < MAX_COLOR_ATTACHMENTS; ++i ) - { - jsTexture* colorTexture = NULL; - _RGLFramebufferGetAttachmentTexture(&framebuffer->color[i], &colorTexture); - - if ( colorTexture != NULL ) - { - if ( !_RGLTextureIsValid( colorTexture ) ) - { - RARCH_ERR("Framebuffer color attachment texture is not complete.\n"); - return GL_FRAMEBUFFER_UNSUPPORTED_OES; - } - - image[nBuffers] = colorTexture->image; - - if ( colorFormat && colorFormat != image[nBuffers]->internalFormat ) - { - RARCH_ERR("Framebuffer attachments have inconsistent color formats.\n" ); - return GL_FRAMEBUFFER_INCOMPLETE_FORMATS_OES; - } - colorFormat = image[nBuffers]->internalFormat; - - ++nBuffers; - } - } - - if ( nBuffers && colorFormat != RGL_ARGB8) - { - RARCH_ERR("Color attachment to framebuffer must be a supported drawable format (GL_ARGB_SCE)\n"); - return GL_FRAMEBUFFER_UNSUPPORTED_OES; - } - - if ( nBuffers == 0 ) - return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_OES; - - for ( GLuint i = 0; i < nBuffers; ++i ) - for ( GLuint j = i + 1; j < nBuffers; ++j ) - if ( image[i] == image[j] ) - return GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_OES; - - return GL_FRAMEBUFFER_COMPLETE_OES; -} - -enum _RGLTextureStrategy -{ - TEXTURE_STRATEGY_END, - TEXTURE_STRATEGY_UNTILED_ALLOC, - TEXTURE_STRATEGY_UNTILED_CLEAR, -}; - -static enum _RGLTextureStrategy linearGPUStrategy[] = -{ - TEXTURE_STRATEGY_UNTILED_ALLOC, - TEXTURE_STRATEGY_UNTILED_CLEAR, - TEXTURE_STRATEGY_UNTILED_ALLOC, - TEXTURE_STRATEGY_END, -}; - -static void _RGLImageAllocCPUStorage( jsImage *image ) -{ - if((image->storageSize > image->mallocStorageSize) || (!image->mallocData)) - { - if(image->mallocData) - free( image->mallocData ); - - image->mallocData = ( char * )malloc( image->storageSize + 128 ); - image->mallocStorageSize = image->storageSize; - } - - intptr_t x = (intptr_t)image->mallocData; - x = ( x + 128 - 1 ) / 128 * 128; - image->data = (char*)x; - -} - -static inline int _RGLGetComponentCount( GLenum format ) -{ - switch ( format ) - { -#define DECLARE_FORMAT(FORMAT,COUNT) \ - case FORMAT: \ - return COUNT; - DECLARE_FORMATS -#undef DECLARE_FORMAT - default: - return 0; - } -} - -typedef void( GetComponentsFunction_t )( const unsigned char *bytes, GLfloat *values, int count ); -typedef void( PutComponentsFunction_t )( unsigned char *bytes, GLfloat *values, int count ); -typedef void( ColorConvertFunction_t )( jsColorRGBAf *color, GLfloat *values ); - - -#define DECLARE_UNPACKED_TYPE(TYPE) \ -static void _RGLGetComponents_##TYPE(const unsigned char *bytes, GLfloat *values, int count) \ -{ \ - int i; \ - for (i=0;iR = v[0]; c->G = v[1]; c->B = v[2]; c->A = 1.f; } -static void _RGLValuesToColor_GL_BGR( jsColorRGBAf *c, GLfloat *v ) { c->B = v[0]; c->G = v[1]; c->R = v[2]; c->A = 1.f; } -static void _RGLValuesToColor_GL_RGBA( jsColorRGBAf *c, GLfloat *v ) { c->R = v[0]; c->G = v[1]; c->B = v[2]; c->A = v[3]; } -static void _RGLValuesToColor_GL_BGRA( jsColorRGBAf *c, GLfloat *v ) { c->B = v[0]; c->G = v[1]; c->R = v[2]; c->A = v[3]; } -static void _RGLValuesToColor_GL_ABGR( jsColorRGBAf *c, GLfloat *v ) { c->A = v[0]; c->B = v[1]; c->G = v[2]; c->R = v[3]; } -static void _RGLValuesToColor_GL_ARGB_SCE( jsColorRGBAf *c, GLfloat *v ) { c->A = v[0]; c->R = v[1]; c->G = v[2]; c->B = v[3]; } -static void _RGLValuesToColor_GL_RED( jsColorRGBAf *c, GLfloat *v ) { c->R = v[0]; c->G = 0.f; c->B = 0.f; c->A = 1.f; } -static void _RGLValuesToColor_GL_GREEN( jsColorRGBAf *c, GLfloat *v ) { c->R = 0.f; c->G = v[0]; c->B = 0.f; c->A = 1.f; } -static void _RGLValuesToColor_GL_BLUE( jsColorRGBAf *c, GLfloat *v ) { c->R = 0.f; c->G = 0.f; c->B = v[0]; c->A = 1.f; } -static void _RGLValuesToColor_GL_ALPHA( jsColorRGBAf *c, GLfloat *v ) { c->R = 0.f; c->G = 0.f; c->B = 0.f; c->A = v[0]; } - -static void _RGLColorToValues_GL_RGB( jsColorRGBAf *c, GLfloat *v ) { v[0] = c->R; v[1] = c->G; v[2] = c->B; } -static void _RGLColorToValues_GL_BGR( jsColorRGBAf *c, GLfloat *v ) { v[0] = c->B; v[1] = c->G; v[2] = c->R; } -static void _RGLColorToValues_GL_RGBA( jsColorRGBAf *c, GLfloat *v ) { v[0] = c->R; v[1] = c->G; v[2] = c->B; v[3] = c->A; } -static void _RGLColorToValues_GL_BGRA( jsColorRGBAf *c, GLfloat *v ) { v[0] = c->B; v[1] = c->G; v[2] = c->R; v[3] = c->A; } -static void _RGLColorToValues_GL_ABGR( jsColorRGBAf *c, GLfloat *v ) { v[0] = c->A; v[1] = c->B; v[2] = c->G; v[3] = c->R; } -static void _RGLColorToValues_GL_ARGB_SCE( jsColorRGBAf *c, GLfloat *v ) { v[0] = c->A; v[1] = c->R; v[2] = c->G; v[3] = c->B; } -static void _RGLColorToValues_GL_RED( jsColorRGBAf *c, GLfloat *v ) { v[0] = c->R; } -static void _RGLColorToValues_GL_GREEN( jsColorRGBAf *c, GLfloat *v ) { v[0] = c->G; } -static void _RGLColorToValues_GL_BLUE( jsColorRGBAf *c, GLfloat *v ) { v[0] = c->B; } -static void _RGLColorToValues_GL_ALPHA( jsColorRGBAf *c, GLfloat *v ) { v[0] = c->A; } - -static inline ColorConvertFunction_t *_RGLFindValuesToColorFunction( GLenum format ) -{ - switch ( format ) - { -#define DECLARE_FORMAT(FORMAT,COUNT) \ - case FORMAT: \ - return &_RGLValuesToColor_##FORMAT; - DECLARE_FORMATS -#undef DECLARE_FORMAT - default: - return NULL; - } -} - -static inline ColorConvertFunction_t *_RGLFindColorToValuesFunction( GLenum format ) -{ - switch ( format ) - { -#define DECLARE_FORMAT(FORMAT,COUNT) \ - case FORMAT: \ - return &_RGLColorToValues_##FORMAT; - DECLARE_FORMATS -#undef DECLARE_FORMAT - default: - return NULL; - } -} - -static void _RGLRasterToImage(const jsRaster* raster, jsImage* image) -{ - const int srcComponents = _RGLGetComponentCount( raster->format ); - const int dstComponents = _RGLGetComponentCount( image->format ); - GetComponentsFunction_t* getComponents = _RGLFindGetComponentsFunction( raster->type ); - PutComponentsFunction_t* putComponents = _RGLFindPutComponentsFunction( image->type ); - ColorConvertFunction_t* valuesToColor = _RGLFindValuesToColorFunction( raster->format ); - ColorConvertFunction_t* colorToValues = _RGLFindColorToValuesFunction( image->format ); - - for ( int j = 0; j < raster->height; ++j ) - { - const unsigned char *src = ( const unsigned char * )raster->data + j * raster->ystride; - unsigned char *dst = ( unsigned char * )image->data + (j) * image->ystride; - - for ( int k = 0; k < raster->width; ++k ) - { - GLfloat values[4]; - jsColorRGBAf color; - getComponents( src, values, srcComponents ); - valuesToColor( &color, values ); - colorToValues( &color, values ); - - if (image->type!=GL_FLOAT && image->type!=GL_HALF_FLOAT_ARB) - { - values[0]= MAX( MIN( values[0], 1.f ), 0.f ); - values[1]= MAX( MIN( values[1], 1.f ), 0.f ); - values[2]= MAX( MIN( values[2], 1.f ), 0.f ); - values[3]= MAX( MIN( values[3], 1.f ), 0.f ); - } - - putComponents( dst, values, dstComponents ); - - src += raster->xstride; - dst += image->xstride; - } - } -} - -static void _RGLPlatformCopyGPUTexture( jsTexture* texture ) -{ - RGLTexture *gcmTexture = ( RGLTexture * )texture->platformTexture; - - if ( gcmTexture->gpuAddressId == GMM_ERROR ) - return; - - RGLTextureLayout *layout = &gcmTexture->gpuLayout; - - jsImage* image = texture->image; - - if ( image->dataState == IMAGE_DATASTATE_GPU ) - { - _RGLImageAllocCPUStorage( image ); - - cellGcmSetInvalidateVertexCache( &_RGLState.fifo); - _RGLFifoFinish( &_RGLState.fifo ); - - char* gpuData = gmmIdToAddress(gcmTexture->gpuAddressId) + gcmTexture->gpuAddressIdOffset; - - jsRaster raster = - { - format : image->format, - type : image->type, - width : image->width, - height : image->height, - xstride : image->xstride, - ystride : layout->pitch, - data : gpuData - }; - - _RGLRasterToImage( &raster, image); - - image->dataState = IMAGE_DATASTATE_HOST; - } -} - -static void _RGLPlatformFreeGcmTexture(jsTexture* texture) -{ - RGLTexture *gcmTexture = (RGLTexture *)texture->platformTexture; - - switch (gcmTexture->pool) - { - case SURFACE_POOL_LINEAR: - case SURFACE_POOL_SYSTEM: - gmmFree(gcmTexture->gpuAddressId); - case SURFACE_POOL_NONE: - break; - default: - break; - } - - gcmTexture->gpuAddressId = GMM_ERROR; - gcmTexture->gpuAddressIdOffset = 0; - gcmTexture->gpuSize = 0; -} - -void _RGLPlatformDropTexture( jsTexture *texture ) -{ - RGLTexture * gcmTexture = (RGLTexture *)texture->platformTexture; - - if(gcmTexture->pbo != NULL) - { - _RGLPlatformCopyGPUTexture(texture); - _RGLFreeBufferObject(gcmTexture->pbo); - gcmTexture->pbo = NULL; - gcmTexture->gpuAddressId = GMM_ERROR; - gcmTexture->gpuAddressIdOffset = 0; - gcmTexture->pool = SURFACE_POOL_NONE; - gcmTexture->gpuSize = 0; - } - - if(gcmTexture->pool != SURFACE_POOL_NONE) - { - _RGLPlatformCopyGPUTexture( texture ); - _RGLPlatformFreeGcmTexture( texture ); - } - - gcmTexture->pool = SURFACE_POOL_NONE; - gcmTexture->gpuAddressId = GMM_ERROR; - gcmTexture->gpuAddressIdOffset = 0; - gcmTexture->gpuSize = 0; - texture->revalidate |= TEXTURE_REVALIDATE_IMAGES; - _RGLTextureTouchFBOs(texture); -} - -int _RGLGetPixelSize( GLenum format, GLenum type ) -{ - int componentSize; - - switch(type) - { - -#define DECLARE_PACKED_TYPE(REALTYPE,TYPE,N,S1,S2,S3,S4,REV) \ - case TYPE: \ - return sizeof(type_##REALTYPE); - DECLARE_PACKED_TYPES -#undef DECLARE_PACKED_TYPE - -#define DECLARE_UNPACKED_TYPE(TYPE) \ - case TYPE: \ - componentSize=sizeof(type_##TYPE); \ - break; - DECLARE_UNPACKED_TYPES -#undef DECLARE_UNPACKED_TYPE - - default: - return 0; - } - - return _RGLGetComponentCount( format )*componentSize; -} - -static void _RGLPlatformChooseGPUFormatAndLayout( - const jsTexture* texture, - GLboolean forceLinear, - GLuint pitch, - RGLTextureLayout* newLayout ) -{ - jsImage *image = texture->image; - - newLayout->baseWidth = image->width; - newLayout->baseHeight = image->height; - newLayout->internalFormat = (RGLEnum)image->internalFormat; - newLayout->pixelBits = _RGLPlatformGetBitsPerPixel( newLayout->internalFormat ); - newLayout->pitch = pitch ? pitch : _RGLPad( _RGLGetPixelSize( texture->image->format, texture->image->type )*texture->image->width, 64); -} - -void _RGLPlatformDropUnboundTextures(GLenum pool) -{ - PSGLcontext* LContext = _CurrentContext; - GLuint i, j; - - for (i = 0; i < LContext->textureNameSpace.capacity; ++i) - { - GLboolean bound = GL_FALSE; - jsTexture *texture = ( jsTexture * )LContext->textureNameSpace.data[i]; - if(!texture || (texture->referenceBuffer != 0)) - continue; - - for (j = 0; j < MAX_VERTEX_TEXTURE_IMAGE_UNITS; ++j) - { - if (LContext->VertexTextureImages[j] == texture) - { - bound = GL_TRUE; - break; - } - } - - for ( j = 0; j < MAX_TEXTURE_IMAGE_UNITS; ++j) - { - jsTextureImageUnit *tu = LContext->TextureImageUnits + j; - if (tu->bound2D == i) - { - bound = GL_TRUE; - break; - } - } - - if ( bound ) - continue; - - RGLTexture *gcmTexture = ( RGLTexture * )texture->platformTexture; - if ( gcmTexture->pbo != NULL && gcmTexture->pbo->refCount > 1 ) - continue; - - if ( pool != SURFACE_POOL_NONE && pool != gcmTexture->pool ) - continue; - - _RGLPlatformDropTexture( texture ); - } -} - -static void _RGLPlatformReallocateGcmTexture( jsTexture* texture ) -{ - RGLTexture *gcmTexture = ( RGLTexture * )texture->platformTexture; - - enum _RGLTextureStrategy *step = linearGPUStrategy; - - GLuint size = 0; - GLuint id = GMM_ERROR; - - const RGLTextureLayout currentLayout = gcmTexture->gpuLayout; - const GLuint currentSize = gcmTexture->gpuSize; - - // process strategy - GLboolean done = GL_FALSE; - while ( !done ) - { - RGLTextureLayout newLayout; - - switch ( *step++ ) - { - case TEXTURE_STRATEGY_UNTILED_ALLOC: - _RGLPlatformChooseGPUFormatAndLayout( texture, GL_TRUE, 0, &newLayout ); - size = _RGLPad( newLayout.baseHeight * newLayout.pitch, 1); - - if ( gcmTexture->pool == SURFACE_POOL_LINEAR ) - { - if ( currentSize >= size && newLayout.pitch == currentLayout.pitch ) - { - gcmTexture->gpuLayout = newLayout; - done = GL_TRUE; - } - else - _RGLPlatformDropTexture( texture ); - } - - if ( !done ) - { - id = gmmAlloc(0, size); - if ( id != GMM_ERROR ) - { - if ( gcmTexture->pool != SURFACE_POOL_NONE ) - _RGLPlatformDropTexture( texture ); - - gcmTexture->pool = SURFACE_POOL_LINEAR; - gcmTexture->gpuAddressId = id; - gcmTexture->gpuAddressIdOffset = 0; - gcmTexture->gpuSize = size; - gcmTexture->gpuLayout = newLayout; - - done = GL_TRUE; - } - } - break; - case TEXTURE_STRATEGY_UNTILED_CLEAR: - _RGLPlatformDropUnboundTextures(SURFACE_POOL_LINEAR); - break; - case TEXTURE_STRATEGY_END: - _RGLSetError( GL_OUT_OF_MEMORY ); - done = GL_TRUE; - break; - default: - break; - } - } - _RGLTextureTouchFBOs( texture ); -} - -static void _RGLImageFreeCPUStorage( jsImage *image ) -{ - if (!image->mallocData) - return; - - if (image->mallocData != NULL) - free( image->mallocData ); - - image->mallocStorageSize = 0; - image->data = NULL; - image->mallocData = NULL; - image->dataState &= ~IMAGE_DATASTATE_HOST; -} - -static void _RGLPlatformValidateTextureResources( jsTexture *texture ) -{ - if ( RGL_UNLIKELY( !_RGLTextureIsValid( texture ) ) ) - { - texture->isComplete = GL_FALSE; - return; - } - texture->isComplete = GL_TRUE; - - if ( texture->revalidate & TEXTURE_REVALIDATE_IMAGES || - texture->revalidate & TEXTURE_REVALIDATE_LAYOUT ) - { - _RGLPlatformReallocateGcmTexture( texture ); - RGLTexture *gcmTexture = ( RGLTexture * )texture->platformTexture; - RGLTextureLayout *layout = &gcmTexture->gpuLayout; - - const GLuint pixelBytes = layout->pixelBits / 8; - - RGLSurface src; - src.source = SURFACE_SOURCE_TEMPORARY; - src.width = 0; - src.height = 0; - src.bpp = pixelBytes; - src.pitch = 0; - src.format = layout->internalFormat; - src.pool = SURFACE_POOL_LINEAR; - src.ppuData = NULL; - src.dataId = GMM_ERROR; - src.dataIdOffset = 0; - - RGLSurface dst; - dst.source = SURFACE_SOURCE_TEXTURE; - dst.width = 0; - dst.height = 0; - dst.bpp = pixelBytes; - dst.pitch = layout->pitch; - dst.format = layout->internalFormat; - dst.pool = SURFACE_POOL_SYSTEM; - dst.ppuData = NULL; - dst.dataId = GMM_ERROR; - dst.dataIdOffset = 0; - - GLuint bounceBufferId = GMM_ERROR; - - jsImage *image = texture->image; - - if(image->dataState == IMAGE_DATASTATE_HOST) - { - src.ppuData = image->data; - - if ( bounceBufferId == GMM_ERROR) - bounceBufferId = gmmAlloc(0, gcmTexture->gpuSize); - - if ( bounceBufferId != GMM_ERROR ) - { - src.dataId = bounceBufferId; - src.dataIdOffset = 0; - - memcpy( gmmIdToAddress( src.dataId ), image->data, - image->storageSize ); - } - - src.width = image->width; - src.height = image->height; - src.pitch = pixelBytes * src.width; - - dst.width = src.width; - dst.height = image->height; - dst.dataId = gcmTexture->gpuAddressId; - dst.dataIdOffset = gcmTexture->gpuAddressIdOffset; - - transfer_params_t transfer_params; - - transfer_params.dst_id = dst.dataId; - transfer_params.dst_id_offset = dst.dataIdOffset; - transfer_params.dst_pitch = dst.pitch ? dst.pitch : (dst.bpp * dst.width); - transfer_params.dst_x = 0; - transfer_params.dst_y = 0; - transfer_params.src_id = src.dataId; - transfer_params.src_id_offset = src.dataIdOffset; - transfer_params.src_pitch = src.pitch ? src.pitch : (src.bpp * src.width); - transfer_params.src_x = 0; - transfer_params.src_y = 0; - transfer_params.width = src.width; - transfer_params.height = src.height; - transfer_params.bpp = src.bpp; - transfer_params.fifo_ptr = &_RGLState.fifo; - - TransferDataVidToVid(&transfer_params); - - _RGLImageFreeCPUStorage( image ); - image->dataState |= IMAGE_DATASTATE_GPU; - } - - if ( bounceBufferId != GMM_ERROR ) - gmmFree( bounceBufferId ); - - cellGcmSetInvalidateTextureCacheInline( &_RGLState.fifo, CELL_GCM_INVALIDATE_TEXTURE); - } - - RGLTexture *platformTexture = ( RGLTexture * )texture->platformTexture; - RGLTextureLayout *layout = &platformTexture->gpuLayout; - - GLuint minFilter = texture->minFilter; - GLuint magFilter = texture->magFilter; - - platformTexture->gcmMethods.filter.min = _RGLMapMinTextureFilter( minFilter ); - platformTexture->gcmMethods.filter.mag = _RGLMapMagTextureFilter( magFilter ); - platformTexture->gcmMethods.filter.bias = ( GLint )(( -.26f ) * 256.0f ); - - GLuint gamma = 0; - GLuint remap = texture->gammaRemap; - gamma |= (remap & RGL_GAMMA_REMAP_RED_BIT) ? CELL_GCM_TEXTURE_GAMMA_R : 0; - gamma |= (remap & RGL_GAMMA_REMAP_GREEN_BIT) ? CELL_GCM_TEXTURE_GAMMA_G : 0; - gamma |= (remap & RGL_GAMMA_REMAP_BLUE_BIT) ? CELL_GCM_TEXTURE_GAMMA_B : 0; - gamma |= (remap & RGL_GAMMA_REMAP_ALPHA_BIT) ? CELL_GCM_TEXTURE_GAMMA_A : 0; - - platformTexture->gcmMethods.address.gamma = gamma; - - GLuint internalFormat = layout->internalFormat; - - _RGLMapTextureFormat( internalFormat, - platformTexture->gcmTexture.format, platformTexture->gcmTexture.remap ); - - if ( layout->pitch ) - platformTexture->gcmTexture.format += 0x20; - - platformTexture->gcmTexture.width = layout->baseWidth; - platformTexture->gcmTexture.height = layout->baseHeight; - platformTexture->gcmTexture.depth = 1; - platformTexture->gcmTexture.pitch = layout->pitch; - platformTexture->gcmTexture.mipmap = 1; - platformTexture->gcmTexture.cubemap = CELL_GCM_FALSE; - platformTexture->gcmTexture.dimension = CELL_GCM_TEXTURE_DIMENSION_2; - - if(gmmIdIsMain(platformTexture->gpuAddressId)) - platformTexture->gcmTexture.location = CELL_GCM_LOCATION_MAIN; - else - platformTexture->gcmTexture.location = CELL_GCM_LOCATION_LOCAL; - - texture->revalidate = 0; -} - -static void jsPlatformFramebuffer_validate( jsPlatformFramebuffer * fb, PSGLcontext *LContext ) -{ - fb->complete = ( _RGLPlatformFramebufferCheckStatus(fb) == GL_FRAMEBUFFER_COMPLETE_OES ); - - if(!fb->complete) - return; - - GLuint width = CELL_GCM_MAX_RT_DIMENSION; - GLuint height = CELL_GCM_MAX_RT_DIMENSION; - - fb->rt.colorBufferCount = 0; - fb->rt.colorFormat = RGL_NONE; - fb->colorBufferMask = 0x0; - GLuint defaultPitch = 0; - GLuint defaultId = GMM_ERROR; - GLuint defaultIdOffset = 0; - - for(int i = 0; i < RGL_SETRENDERTARGET_MAXCOUNT; ++i) - { - jsTexture* colorTexture = NULL; - _RGLFramebufferGetAttachmentTexture(&fb->color[i], &colorTexture); - - if(colorTexture == NULL) - continue; - - RGLTexture* nvTexture = ( RGLTexture * )colorTexture->platformTexture; - - if ( !colorTexture->isRenderTarget ) - { - colorTexture->isRenderTarget = GL_TRUE; - colorTexture->revalidate |= TEXTURE_REVALIDATE_LAYOUT; - } - _RGLPlatformValidateTextureResources( colorTexture ); - colorTexture->image->dataState = IMAGE_DATASTATE_GPU; - - fb->rt.colorId[i] = nvTexture->gpuAddressId; - fb->rt.colorIdOffset[i] = nvTexture->gpuAddressIdOffset; - fb->rt.colorPitch[i] = nvTexture->gpuLayout.pitch ? nvTexture->gpuLayout.pitch : nvTexture->gpuLayout.pixelBits * nvTexture->gpuLayout.baseWidth / 8; - fb->colorBufferMask |= 1 << i; - - width = MIN( width, nvTexture->gpuLayout.baseWidth ); - height = MIN( height, nvTexture->gpuLayout.baseHeight ); - fb->rt.colorFormat = nvTexture->gpuLayout.internalFormat; - fb->rt.colorBufferCount = i + 1; - defaultId = fb->rt.colorId[i]; - defaultIdOffset = fb->rt.colorIdOffset[i]; - defaultPitch = fb->rt.colorPitch[i]; - - if ( !( fb->colorBufferMask & ( 1 << i ) ) ) - { - fb->rt.colorId[i] = defaultId; - fb->rt.colorIdOffset[i] = defaultIdOffset; - fb->rt.colorPitch[i] = defaultPitch; - } - } - - fb->rt.width = width; - fb->rt.height = height; - - fb->rt.yInverted = CELL_GCM_FALSE; - fb->rt.xOffset = 0; - fb->rt.yOffset = 0; - fb->needValidate = GL_FALSE; -} - -static void _RGLValidateFramebuffer( void ) -{ - PSGLdevice *LDevice = _CurrentDevice; - RGLDevice *gcmDevice = ( RGLDevice * )LDevice->platformDevice; - - PSGLcontext* LContext = _CurrentContext; - RGLDriver *driver= (RGLDriver *)_CurrentDevice->rasterDriver; - - driver->rtValid = GL_FALSE; - - if(LContext->framebuffer) - { - jsPlatformFramebuffer* framebuffer = static_cast((jsFramebuffer *)LContext->framebufferNameSpace.data[LContext->framebuffer] ); - - if ( framebuffer->needValidate ) - jsPlatformFramebuffer_validate( framebuffer, LContext ); - - driver->rt = framebuffer->rt; - driver->colorBufferMask = framebuffer->colorBufferMask; - } - else - { - driver->rt = gcmDevice->rt; - driver->colorBufferMask = 0x1; - } - - driver->rtValid = GL_TRUE; - - _RGLFifoGlSetRenderTarget( &driver->rt ); - - LContext->needValidate &= ~PSGL_VALIDATE_FRAMEBUFFER; - _RGLFifoGlViewport(LContext->ViewPort.X, LContext->ViewPort.Y, - LContext->ViewPort.XSize, LContext->ViewPort.YSize, 0.0f, 1.0f); -} - -GLAPI void APIENTRY glClear( GLbitfield mask ) -{ - PSGLcontext *LContext = _CurrentContext; - RGLDriver *driver= (RGLDriver *)_CurrentDevice->rasterDriver; - RGLFifo * fifo = &_RGLState.fifo; - - if ( LContext->needValidate & PSGL_VALIDATE_FRAMEBUFFER ) - _RGLValidateFramebuffer(); - - if ( !driver->rtValid ) - return; - - GLbitfield newmask = 0; - - if(driver->rt.colorBufferCount) - newmask |= RGL_COLOR_BUFFER_BIT; - - if(!newmask) - return; - - GLbitfield clearMask = newmask; - - if(driver->rt.colorBufferCount > 1) - clearMask &= ~RGL_COLOR_BUFFER_BIT; - - if (clearMask) - { - GLuint hwColor; - RGL_CALC_COLOR_LE_ARGB8( &hwColor, RGL_CLAMPF_01(LContext->ClearColor.R), RGL_CLAMPF_01(LContext->ClearColor.G), RGL_CLAMPF_01(LContext->ClearColor.B), RGL_CLAMPF_01(LContext->ClearColor.A) ); - - cellGcmSetClearColorInline( &_RGLState.fifo, hwColor); - cellGcmSetClearSurfaceInline ( &_RGLState.fifo, CELL_GCM_CLEAR_R | CELL_GCM_CLEAR_G | CELL_GCM_CLEAR_B | CELL_GCM_CLEAR_A); - newmask &= ~clearMask; - } - - if ( newmask ) - { - static float _RGLClearVertexBuffer[12] __attribute__((aligned(128))) = - { - -1.f, -1.f, 0.f, - -1.f, 1.f, 0.f, - 1.f, -1.f, 0.f, - 1.f, 1.f, 0.f, - }; - - _RGLClearVertexBuffer[2] = 2.f - 1.f; - _RGLClearVertexBuffer[5] = 2.f - 1.f; - _RGLClearVertexBuffer[8] = 2.f - 1.f; - _RGLClearVertexBuffer[11] = 2.f - 1.f; - - GLuint bufferId = gmmAlloc(0, sizeof(_RGLClearVertexBuffer)); - memcpy( gmmIdToAddress(bufferId), _RGLClearVertexBuffer, sizeof( _RGLClearVertexBuffer ) ); - GmmBaseBlock *pBaseBlock = (GmmBaseBlock *)bufferId; - - cellGcmSetVertexDataArrayInline( &_RGLState.fifo, 0 /* index */, 1/* frequency */, 3 * sizeof(GLfloat)/*stride */, 3 /* size */, CELL_GCM_VERTEX_F /* gcmType */, CELL_GCM_LOCATION_LOCAL, gmmAddressToOffset(pBaseBlock->address, pBaseBlock->isMain)/* offset */); - - RGLBIT_TRUE( LContext->attribs->DirtyMask, 0 ); - - for(int i = 1; i < MAX_VERTEX_ATTRIBS; ++i) - { - cellGcmSetVertexDataArrayInline( &_RGLState.fifo, i/* index */, 0/* frequency */, 0/*stride */, 0/* size */, CELL_GCM_VERTEX_F /*gcmType */, CELL_GCM_LOCATION_LOCAL, 0/* offset */ ); - RGLBIT_TRUE( LContext->attribs->DirtyMask, i ); - } - cellGcmSetVertexData4fInline( &_RGLState.fifo, _RGL_ATTRIB_PRIMARY_COLOR_INDEX, (GLfloat*)&LContext->ClearColor); - - LContext->needValidate |= PSGL_VALIDATE_FRAGMENT_PROGRAM; - - gmmFree( bufferId ); - } - - cellGcmSetInvalidateVertexCache( &_RGLState.fifo); - _RGLFifoFlush( fifo ); -} - -GLAPI void APIENTRY glClearColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha ) -{ - PSGLcontext *LContext = _CurrentContext; - - LContext->ClearColor.R = MAX(MIN(red, 1.f), 0.f); - LContext->ClearColor.G = MAX(MIN(green, 1.f), 0.f); - LContext->ClearColor.B = MAX(MIN(blue, 1.f), 0.f); - LContext->ClearColor.A = MAX(MIN(alpha, 1.f), 0.f); -} - -GLAPI void APIENTRY glBlendEquation( GLenum mode ) -{ - PSGLcontext *LContext = _CurrentContext; - - LContext->BlendEquationRGB = LContext->BlendEquationAlpha = mode; - LContext->needValidate |= PSGL_VALIDATE_BLENDING; -} - -GLAPI void APIENTRY glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) -{ - PSGLcontext* LContext = _CurrentContext; - LContext->BlendColor.R = MAX(MIN(red, 1.f), 0.f); - LContext->BlendColor.G = MAX(MIN(green, 1.f), 0.f); - LContext->BlendColor.B = MAX(MIN(blue, 1.f), 0.f); - LContext->BlendColor.A = MAX(MIN(alpha, 1.f), 0.f); - - LContext->needValidate |= PSGL_VALIDATE_BLENDING; -} - -GLAPI void APIENTRY glBlendFunc(GLenum sfactor, GLenum dfactor) -{ - PSGLcontext *LContext = _CurrentContext; - - LContext->BlendFactorSrcRGB = sfactor; - LContext->BlendFactorSrcAlpha = sfactor; - LContext->BlendFactorDestRGB = dfactor; - LContext->BlendFactorDestAlpha = dfactor; - LContext->needValidate |= PSGL_VALIDATE_BLENDING; -} - - -jsFramebufferAttachment* _RGLFramebufferGetAttachment( jsFramebuffer *framebuffer, GLenum attachment ) -{ - switch ( attachment ) - { - case GL_COLOR_ATTACHMENT0_EXT: - case GL_COLOR_ATTACHMENT1_EXT: - case GL_COLOR_ATTACHMENT2_EXT: - case GL_COLOR_ATTACHMENT3_EXT: - return &framebuffer->color[attachment - GL_COLOR_ATTACHMENT0_EXT]; - case GL_DEPTH_ATTACHMENT_OES: - case GL_STENCIL_ATTACHMENT_OES: - default: - _RGLSetError( GL_INVALID_ENUM ); - return NULL; - } -} - -GLAPI void APIENTRY glBindFramebufferOES( GLenum target, GLuint framebuffer ) -{ - PSGLcontext* LContext = _CurrentContext; - - if ( framebuffer ) - _RGLTexNameSpaceCreateNameLazy( &LContext->framebufferNameSpace, framebuffer ); - - LContext->framebuffer = framebuffer; - LContext->needValidate |= PSGL_VALIDATE_FRAMEBUFFER; -} - -GLAPI void APIENTRY glDeleteFramebuffersOES( GLsizei n, const GLuint *framebuffers ) -{ - - PSGLcontext *LContext = _CurrentContext; - - for(int i = 0; i < n; ++i) - { - if ( framebuffers[i] && framebuffers[i] == LContext->framebuffer ) - glBindFramebufferOES( GL_FRAMEBUFFER_OES, 0 ); - } - - _RGLTexNameSpaceDeleteNames( &LContext->framebufferNameSpace, n, framebuffers ); -} - -GLAPI void APIENTRY glGenFramebuffersOES( GLsizei n, GLuint *framebuffers ) -{ - PSGLcontext *LContext = _CurrentContext; - _RGLTexNameSpaceGenNames( &LContext->framebufferNameSpace, n, framebuffers ); -} - - -GLAPI GLenum APIENTRY glCheckFramebufferStatusOES( GLenum target ) -{ - PSGLcontext *LContext = _CurrentContext; - - if ( LContext->framebuffer ) - { - jsFramebuffer* framebuffer = (jsFramebuffer *)LContext->framebufferNameSpace.data[LContext->framebuffer]; - return _RGLPlatformFramebufferCheckStatus( framebuffer ); - } - - return GL_FRAMEBUFFER_COMPLETE_OES; -} - -GLAPI void APIENTRY glFramebufferTexture2DOES( GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level ) -{ - PSGLcontext* LContext = _CurrentContext; - - jsFramebuffer* framebuffer = (jsFramebuffer *)LContext->framebufferNameSpace.data[LContext->framebuffer]; - - jsFramebufferAttachment* attach = _RGLFramebufferGetAttachment( framebuffer, GL_COLOR_ATTACHMENT0_EXT ); - - if ( !attach ) - return; - - jsTexture *textureObject = NULL; - _RGLFramebufferGetAttachmentTexture(attach, &textureObject); - - if ( textureObject ) - textureObject->framebuffers.removeElement( framebuffer ); - - if ( texture ) - { - attach->type = FRAMEBUFFER_ATTACHMENT_TEXTURE; - textureObject = ( jsTexture* )LContext->textureNameSpace.data[texture]; - textureObject->framebuffers.pushBack( framebuffer ); - } - else - attach->type = FRAMEBUFFER_ATTACHMENT_NONE; - - attach->name = texture; - attach->textureTarget = GL_TEXTURE_2D; - - framebuffer->needValidate = GL_TRUE; - LContext->needValidate |= PSGL_VALIDATE_FRAMEBUFFER; -} - -void cgRTCgcInit( void ) -{ - _cgRTCgcCompileProgramHook = &compile_program_from_string; - _cgRTCgcFreeCompiledProgramHook = &free_compiled_program; -} - -void cgRTCgcFree( void ) -{ - _cgRTCgcCompileProgramHook = 0; - _cgRTCgcFreeCompiledProgramHook = 0; -} - -jsName _RGLCreateName(jsNameSpace * ns, void* object) -{ - if ( ns->firstFree == NULL ) - { - int newCapacity = ns->capacity + NAME_INCREMENT; - - void** newData = ( void** )malloc( newCapacity * sizeof( void* ) ); - if ( newData == NULL ) - { - _RGLCgRaiseError( CG_MEMORY_ALLOC_ERROR ); - return 0; - } - memcpy( newData, ns->data, ns->capacity * sizeof( void* ) ); - - if ( ns->data != NULL ) - free( ns->data ); - - ns->data = newData; - - for ( int index = ns->capacity; index < newCapacity - 1; ++index ) - ns->data[index] = ns->data + index + 1; - - ns->data[newCapacity - 1] = NULL; - ns->firstFree = ns->data + ns->capacity; - ns->capacity = newCapacity; - } - jsName result = ns->firstFree - ns->data; - - ns->firstFree = ( void** ) * ns->firstFree; - ns->data[result] = object; - - return result + 1; -} - -unsigned int _RGLIsName(jsNameSpace* ns, jsName name) -{ - if ( RGL_UNLIKELY( name == 0 ) ) - return 0; - - --name; - - if ( RGL_UNLIKELY( name >= ns->capacity ) ) - return 0; - - void** value = ( void** )ns->data[name]; - - if ( RGL_UNLIKELY( value == NULL || - (value >= ns->data && value < ns->data + ns->capacity))) - return 0; - - return 1; -} - -void _RGLEraseName(jsNameSpace* ns, jsName name) -{ - if(_RGLIsName( ns, name)) - { - --name; - ns->data[name] = ns->firstFree; - ns->firstFree = ns->data + name; - } -} - -void _RGLTexNameSpaceInit( jsTexNameSpace *ns, jsTexNameSpaceCreateFunction create, jsTexNameSpaceDestroyFunction destroy ) -{ - ns->capacity = CAPACITY_INCR; - ns->data = ( void ** )malloc( ns->capacity * sizeof( void* ) ); - memset( ns->data, 0, ns->capacity*sizeof( void* ) ); - ns->create = create; - ns->destroy = destroy; -} - -void _RGLTexNameSpaceFree( jsTexNameSpace *ns ) -{ - for(GLuint i = 1; i < ns->capacity; ++i) - if ( ns->data[i] ) ns->destroy( ns->data[i] ); - - if(ns->data != NULL) - free( ns->data ); - - ns->data = NULL; -} - -void _RGLTexNameSpaceResetNames( jsTexNameSpace *ns ) -{ - for ( GLuint i = 1;i < ns->capacity;++i ) - { - if ( ns->data[i] ) - { - ns->destroy( ns->data[i] ); - ns->data[i] = NULL; - } - } -} - -GLuint _RGLTexNameSpaceGetFree( jsTexNameSpace *ns ) -{ - GLuint i; - - for(i = 1; i < ns->capacity; ++i) - if ( !ns->data[i] ) - break; - - return i; -} - -GLboolean _RGLTexNameSpaceCreateNameLazy( jsTexNameSpace *ns, GLuint name ) -{ - if ( name >= ns->capacity ) - { - int newCapacity = name >= ns->capacity + CAPACITY_INCR ? name + 1 : ns->capacity + CAPACITY_INCR; - void **newData = (void**)realloc(ns->data, newCapacity * sizeof(void*)); - memset( newData + ns->capacity, 0, (newCapacity - ns->capacity )*sizeof(void*)); - ns->data = newData; - ns->capacity = newCapacity; - } - - if (!ns->data[name]) - { - ns->data[name] = ns->create(); - if(ns->data[name]) - return GL_TRUE; - } - return GL_FALSE; -} - -GLboolean _RGLTexNameSpaceIsName( jsTexNameSpace *ns, GLuint name ) -{ - if (( name > 0 ) && (name < ns->capacity)) - return( ns->data[name] != 0 ); - else - return GL_FALSE; -} - -void _RGLTexNameSpaceGenNames( jsTexNameSpace *ns, GLsizei n, GLuint *names ) -{ - for (int i = 0; i < n; ++i) - { - GLuint name = _RGLTexNameSpaceGetFree( ns ); - names[i] = name; - - if(name) - _RGLTexNameSpaceCreateNameLazy( ns, name ); - } -} - -void _RGLTexNameSpaceDeleteNames( jsTexNameSpace *ns, GLsizei n, const GLuint *names ) -{ - for ( int i = 0;i < n;++i ) - { - GLuint name = names[i]; - - if(!_RGLTexNameSpaceIsName(ns, name)) - continue; - - ns->destroy( ns->data[name] ); - ns->data[name] = NULL; - } -} - -static inline unsigned int endianSwapWordByHalf( unsigned int v ) -{ - return (v & 0xffff ) << 16 | v >> 16; -} - -static uint32_t gmmInitFixedAllocator (void) -{ - pGmmFixedAllocData = (GmmFixedAllocData *)malloc(sizeof(GmmFixedAllocData)); - - if (pGmmFixedAllocData == NULL) - return GMM_ERROR; - - memset(pGmmFixedAllocData, 0, sizeof(GmmFixedAllocData)); - - for (int i = 0; i < 2; i++) - { - int blockCount = (i==0) ? GMM_BLOCK_COUNT : GMM_TILE_BLOCK_COUNT; - int blockSize = (i==0) ? sizeof(GmmBlock): sizeof(GmmTileBlock); - - pGmmFixedAllocData->ppBlockList[i] = (char **)malloc(sizeof(char *)); - - if (pGmmFixedAllocData->ppBlockList[i] == NULL) - return GMM_ERROR; - - pGmmFixedAllocData->ppBlockList[i][0] = (char *)malloc(blockSize * blockCount); - - if (pGmmFixedAllocData->ppBlockList[i][0] == NULL) - return GMM_ERROR; - - pGmmFixedAllocData->ppFreeBlockList[i] = (uint16_t **)malloc(sizeof(uint16_t *)); - - if (pGmmFixedAllocData->ppFreeBlockList[i] == NULL) - return GMM_ERROR; - - pGmmFixedAllocData->ppFreeBlockList[i][0] = (uint16_t *)malloc(sizeof(uint16_t) * blockCount); - - if (pGmmFixedAllocData->ppFreeBlockList[i][0] == NULL) - return GMM_ERROR; - - pGmmFixedAllocData->pBlocksUsed[i] = (uint16_t *)malloc(sizeof(uint16_t)); - - if (pGmmFixedAllocData->pBlocksUsed[i] == NULL) - return GMM_ERROR; - - for (int j=0; jppFreeBlockList[i][0][j] = j; - - pGmmFixedAllocData->pBlocksUsed[i][0] = 0; - pGmmFixedAllocData->BlockListCount[i] = 1; - } - - return CELL_OK; -} - -static uint8_t gmmSizeToFreeIndex(uint32_t size) -{ - if (size >= GMM_FREE_BIN_0 && size < GMM_FREE_BIN_1) - return 0; - else if (size >= GMM_FREE_BIN_1 && size < GMM_FREE_BIN_2) - return 1; - else if (size >= GMM_FREE_BIN_2 && size < GMM_FREE_BIN_3) - return 2; - else if (size >= GMM_FREE_BIN_3 && size < GMM_FREE_BIN_4) - return 3; - else if (size >= GMM_FREE_BIN_4 && size < GMM_FREE_BIN_5) - return 4; - else if (size >= GMM_FREE_BIN_5 && size < GMM_FREE_BIN_6) - return 5; - else if (size >= GMM_FREE_BIN_6 && size < GMM_FREE_BIN_7) - return 6; - else if (size >= GMM_FREE_BIN_7 && size < GMM_FREE_BIN_8) - return 7; - else if (size >= GMM_FREE_BIN_8 && size < GMM_FREE_BIN_9) - return 8; - else if (size >= GMM_FREE_BIN_9 && size < GMM_FREE_BIN_10) - return 9; - else if (size >= GMM_FREE_BIN_10 && size < GMM_FREE_BIN_11) - return 10; - else if (size >= GMM_FREE_BIN_11 && size < GMM_FREE_BIN_12) - return 11; - else if (size >= GMM_FREE_BIN_12 && size < GMM_FREE_BIN_13) - return 12; - else if (size >= GMM_FREE_BIN_13 && size < GMM_FREE_BIN_14) - return 13; - else if (size >= GMM_FREE_BIN_14 && size < GMM_FREE_BIN_15) - return 14; - else if (size >= GMM_FREE_BIN_15 && size < GMM_FREE_BIN_16) - return 15; - else if (size >= GMM_FREE_BIN_16 && size < GMM_FREE_BIN_17) - return 16; - else if (size >= GMM_FREE_BIN_17 && size < GMM_FREE_BIN_18) - return 17; - else if (size >= GMM_FREE_BIN_18 && size < GMM_FREE_BIN_19) - return 18; - else if (size >= GMM_FREE_BIN_19 && size < GMM_FREE_BIN_20) - return 19; - else if (size >= GMM_FREE_BIN_20 && size < GMM_FREE_BIN_21) - return 20; - else - return 21; -} - -void gmmAddFree(GmmAllocator *pAllocator, GmmBlock *pBlock) -{ - uint8_t freeIndex = gmmSizeToFreeIndex(pBlock->base.size); - - if (pAllocator->pFreeHead[freeIndex]) - { - GmmBlock *pInsertBefore = pAllocator->pFreeHead[freeIndex]; - - while (pInsertBefore && pInsertBefore->base.size < pBlock->base.size) - { - pInsertBefore = pInsertBefore->pNextFree; - } - - if (pInsertBefore == NULL) - { - pBlock->pNextFree = NULL; - pBlock->pPrevFree = pAllocator->pFreeTail[freeIndex]; - pAllocator->pFreeTail[freeIndex]->pNextFree = pBlock; - pAllocator->pFreeTail[freeIndex] = pBlock; - } - else if (pInsertBefore == pAllocator->pFreeHead[freeIndex]) - { - pBlock->pNextFree = pInsertBefore; - pBlock->pPrevFree = pInsertBefore->pPrevFree; - pInsertBefore->pPrevFree = pBlock; - pAllocator->pFreeHead[freeIndex] = pBlock; - } - else - { - pBlock->pNextFree = pInsertBefore; - pBlock->pPrevFree = pInsertBefore->pPrevFree; - pInsertBefore->pPrevFree->pNextFree = pBlock; - pInsertBefore->pPrevFree = pBlock; - } - } - else - { - pBlock->pNextFree = NULL; - pBlock->pPrevFree = NULL; - pAllocator->pFreeHead[freeIndex] = pBlock; - pAllocator->pFreeTail[freeIndex] = pBlock; - } -} - - -static void *gmmAllocFixed(uint8_t isTile) -{ - int blockCount = isTile ? GMM_TILE_BLOCK_COUNT : GMM_BLOCK_COUNT; - int blockSize = isTile ? sizeof(GmmTileBlock) : sizeof(GmmBlock); - int listCount = pGmmFixedAllocData->BlockListCount[isTile]; - - for (int i=0; ipBlocksUsed[isTile][i] < blockCount) - { - return pGmmFixedAllocData->ppBlockList[isTile][i] + - (pGmmFixedAllocData->ppFreeBlockList[isTile][i][pGmmFixedAllocData->pBlocksUsed[isTile][i]++] * - blockSize); - } - } - - char **ppBlockList = - (char **)realloc(pGmmFixedAllocData->ppBlockList[isTile], - (listCount + 1) * sizeof(char *)); - if (ppBlockList == NULL) - return NULL; - - pGmmFixedAllocData->ppBlockList[isTile] = ppBlockList; - - pGmmFixedAllocData->ppBlockList[isTile][listCount] = - (char *)malloc(blockSize * blockCount); - if (pGmmFixedAllocData->ppBlockList[isTile][listCount] == NULL) - return NULL; - - uint16_t **ppFreeBlockList = - (uint16_t **)realloc(pGmmFixedAllocData->ppFreeBlockList[isTile], - (listCount + 1) * sizeof(uint16_t *)); - if (ppFreeBlockList == NULL) - return NULL; - - pGmmFixedAllocData->ppFreeBlockList[isTile] = ppFreeBlockList; - - pGmmFixedAllocData->ppFreeBlockList[isTile][listCount] = - (uint16_t *)malloc(sizeof(uint16_t) * blockCount); - if (pGmmFixedAllocData->ppFreeBlockList[isTile][listCount] == NULL) - return NULL; - - uint16_t *pBlocksUsed = - (uint16_t *)realloc(pGmmFixedAllocData->pBlocksUsed[isTile], - (listCount + 1) * sizeof(uint16_t)); - if (pBlocksUsed == NULL) - return NULL; - - pGmmFixedAllocData->pBlocksUsed[isTile] = pBlocksUsed; - - for (int i=0; ippFreeBlockList[isTile][listCount][i] = i; - - pGmmFixedAllocData->pBlocksUsed[isTile][listCount] = 0; - pGmmFixedAllocData->BlockListCount[isTile]++; - - return pGmmFixedAllocData->ppBlockList[isTile][listCount] + - (pGmmFixedAllocData->ppFreeBlockList[isTile][listCount][pGmmFixedAllocData->pBlocksUsed[isTile][listCount]++] * - blockSize); -} - -static void gmmFreeFixed(uint8_t isTile, void *pBlock) -{ - int blockCount = isTile ? GMM_TILE_BLOCK_COUNT : GMM_BLOCK_COUNT; - int blockSize = isTile ? sizeof(GmmTileBlock) : sizeof(GmmBlock); - - for (int i=0; iBlockListCount[isTile]; i++) - { - if (pBlock >= pGmmFixedAllocData->ppBlockList[isTile][i] && - pBlock < (pGmmFixedAllocData->ppBlockList[isTile][i] + blockSize * blockCount)) - { - int index = ((char *)pBlock - pGmmFixedAllocData->ppBlockList[isTile][i]) / blockSize; - pGmmFixedAllocData->ppFreeBlockList[isTile][i][--pGmmFixedAllocData->pBlocksUsed[isTile][i]] = index; - } - } -} - -uint32_t gmmInit( - const void *localMemoryBase, - const void *localStartAddress, - const uint32_t localSize, - const void *mainMemoryBase, - const void *mainStartAddress, - const uint32_t mainSize -) -{ - GmmAllocator *pAllocator[2]; - uint32_t alignedLocalSize, alignedMainSize; - uint32_t localEndAddress = (uint32_t)localStartAddress + localSize; - uint32_t mainEndAddress = (uint32_t)mainStartAddress + mainSize; - - localEndAddress = (localEndAddress / GMM_TILE_ALIGNMENT) * GMM_TILE_ALIGNMENT; - mainEndAddress = (mainEndAddress / GMM_TILE_ALIGNMENT) * GMM_TILE_ALIGNMENT; - - alignedLocalSize = localEndAddress - (uint32_t)localStartAddress; - alignedMainSize = mainEndAddress - (uint32_t)mainStartAddress; - - - pAllocator[0] = (GmmAllocator *)malloc(2*sizeof(GmmAllocator)); - pAllocator[1] = pAllocator[0] + 1; - - if (pAllocator[0] == NULL) - return GMM_ERROR; - - memset(pAllocator[0], 0, 2*sizeof(GmmAllocator)); - - if (pAllocator[0]) - { - pAllocator[0]->memoryBase = (uint32_t)localMemoryBase; - pAllocator[1]->memoryBase = (uint32_t)mainMemoryBase; - pAllocator[0]->startAddress = (uint32_t)localStartAddress; - pAllocator[1]->startAddress = (uint32_t)mainStartAddress; - pAllocator[0]->size = alignedLocalSize; - pAllocator[1]->size = alignedMainSize; - pAllocator[0]->freeAddress = pAllocator[0]->startAddress; - pAllocator[1]->freeAddress = pAllocator[1]->startAddress; - pAllocator[0]->tileStartAddress = ((uint32_t)localStartAddress) + alignedLocalSize; - pAllocator[1]->tileStartAddress = ((uint32_t)mainStartAddress) + alignedMainSize; - pAllocator[0]->totalSize = alignedLocalSize; - pAllocator[1]->totalSize = alignedMainSize; - - pGmmLocalAllocator = pAllocator[0]; - pGmmMainAllocator = pAllocator[1]; - } - else - return GMM_ERROR; - - pLock = cellGcmGetLabelAddress(GMM_PPU_WAIT_INDEX); - *pLock = 0; - cachedLockValue = 0; - - return gmmInitFixedAllocator(); -} - -void gmmSetTileAttrib(const uint32_t id, const uint32_t tag, void *pData) -{ - GmmTileBlock *pTileBlock = (GmmTileBlock *)id; - - pTileBlock->tileTag = tag; - pTileBlock->pData = pData; -} - -uint32_t gmmIdToOffset(const uint32_t id) -{ - GmmBaseBlock *pBaseBlock = (GmmBaseBlock *)id; - return gmmAddressToOffset(pBaseBlock->address, pBaseBlock->isMain); -} - -char *gmmIdToAddress(const uint32_t id) -{ - GmmBaseBlock *pBaseBlock = (GmmBaseBlock *)id; - - do - { - if (cachedLockValue == 0) - break; - - cachedLockValue = *pLock; - - if (cachedLockValue == 0) - break; - }while(1); - - return (char *)pBaseBlock->address; -} - -static void _RGLGetTileRegionInfo(void* data, GLuint *address, GLuint *size) -{ - jsTiledRegion* region = ( jsTiledRegion* )data; - - *address = region->offset; - *size = region->size; -} - -static GmmBlock *gmmAllocBlock(GmmAllocator *pAllocator, uint32_t size) -{ - uint32_t address; - GmmBlock *pNewBlock = NULL; - GmmBlock *pBlock = pAllocator->pTail; - - address = pAllocator->freeAddress; - - if (UINT_MAX - address >= size && - address + size <= pAllocator->startAddress + pAllocator->size) - { - pNewBlock = (GmmBlock *)gmmAllocFixed(0); - if (pNewBlock == NULL) - return NULL; - - memset(pNewBlock, 0, sizeof(GmmBlock)); - - pNewBlock->base.address = address; - pNewBlock->base.isMain = (pAllocator == pGmmMainAllocator); - pNewBlock->base.size = size; - pAllocator->freeAddress = address + size; - - if (pBlock) - { - pNewBlock->pPrev = pBlock; - pBlock->pNext = pNewBlock; - pAllocator->pTail = pNewBlock; - } - else - { - pAllocator->pHead = pNewBlock; - pAllocator->pTail = pNewBlock; - } - } - - return pNewBlock; -} - -static GmmTileBlock *gmmFindFreeTileBlock(GmmAllocator *pAllocator, const uint32_t size) -{ - GmmTileBlock *pBlock = pAllocator->pTileHead; - GmmTileBlock *pBestAfterBlock = NULL; - GmmTileBlock *pNewBlock = NULL; - uint32_t bestSize = 0; - uint32_t freeSize = 0; - - while (pBlock && pBlock->pNext) - { - freeSize = pBlock->pNext->base.address - pBlock->base.address - pBlock->base.size; - - if (freeSize >= size && - (pBestAfterBlock == NULL || freeSize < bestSize) && - (pBlock->pNext == NULL || - pBlock->pData != pBlock->pNext->pData)) - { - pBestAfterBlock = pBlock; - bestSize = freeSize; - } - - pBlock = pBlock->pNext; - } - - if (pBestAfterBlock) - { - pNewBlock = (GmmTileBlock *)gmmAllocFixed(1); - - if (pNewBlock == NULL) - return NULL; - - memset(pNewBlock, 0, sizeof(GmmTileBlock)); - - pNewBlock->base.address = pBestAfterBlock->base.address + pBestAfterBlock->base.size; - pNewBlock->base.isMain = (pAllocator == pGmmMainAllocator); - pNewBlock->base.isTile = 1; - pNewBlock->base.size = size; - - pNewBlock->pNext = pBestAfterBlock->pNext; - pNewBlock->pPrev = pBestAfterBlock; - pNewBlock->pPrev->pNext = pNewBlock; - pNewBlock->pNext->pPrev = pNewBlock; - - return pNewBlock; - } - else - return NULL; -} - -static GmmTileBlock *gmmCreateTileBlock(GmmAllocator *pAllocator, const uint32_t size) -{ - GmmTileBlock *pNewBlock; - uint32_t address; - - address = pAllocator->tileStartAddress - size; - - if (address > pAllocator->startAddress + pAllocator->size) - return NULL; - - if (pAllocator->pTail && - pAllocator->pTail->base.address + pAllocator->pTail->base.size > address) - return NULL; - - pAllocator->size = address - pAllocator->startAddress; - pAllocator->tileSize = pAllocator->tileStartAddress + pAllocator->tileSize - address; - pAllocator->tileStartAddress = address; - - pNewBlock = (GmmTileBlock *)gmmAllocFixed(1); - if (pNewBlock == NULL) - return NULL; - - memset(pNewBlock, 0, sizeof(GmmTileBlock)); - - pNewBlock->base.address = address; - pNewBlock->base.isMain = (pAllocator == pGmmMainAllocator); - pNewBlock->base.isTile = 1; - pNewBlock->base.size = size; - pNewBlock->pNext = pAllocator->pTileHead; - - if (pAllocator->pTileHead) - pAllocator->pTileHead->pPrev = pNewBlock; - else - pAllocator->pTileTail = pNewBlock; - - pAllocator->pTileHead = pNewBlock; - - return pNewBlock; -} - -static void gmmFreeTileBlock(GmmTileBlock *pTileBlock) -{ - GmmAllocator *pAllocator; - - if (pTileBlock->pPrev) - pTileBlock->pPrev->pNext = pTileBlock->pNext; - - if (pTileBlock->pNext) - pTileBlock->pNext->pPrev = pTileBlock->pPrev; - - if (pTileBlock->base.isMain) - pAllocator = pGmmMainAllocator; - else - pAllocator = pGmmLocalAllocator; - - if (pAllocator->pTileHead == pTileBlock) - { - pAllocator->pTileHead = pTileBlock->pNext; - - if (pAllocator->pTileHead) - pAllocator->pTileHead->pPrev = NULL; - - pAllocator->size = pAllocator->pTileHead ? - pAllocator->pTileHead->base.address - pAllocator->startAddress : - pAllocator->totalSize; - pAllocator->tileSize = pAllocator->totalSize - pAllocator->size; - pAllocator->tileStartAddress = pAllocator->pTileHead ? - pAllocator->pTileHead->base.address : - pAllocator->startAddress + pAllocator->size; - } - - if (pAllocator->pTileTail == pTileBlock) - { - pAllocator->pTileTail = pTileBlock->pPrev; - - if (pAllocator->pTileTail) - pAllocator->pTileTail->pNext = NULL; - } - - gmmFreeFixed(1, pTileBlock); -} - -uint32_t gmmAllocExtendedTileBlock(const uint32_t size, const uint32_t tag) -{ - GmmAllocator *pAllocator = pGmmLocalAllocator; - uint32_t retId = 0; - uint32_t newSize; - uint8_t resizeSucceed = 1; - - newSize = pad(size, GMM_TILE_ALIGNMENT); - - GmmTileBlock *pBlock = pAllocator->pTileTail; - - while (pBlock) - { - if (pBlock->tileTag == tag) - { - GLuint address, tileSize; - _RGLGetTileRegionInfo(pBlock->pData, &address, &tileSize); - - if ((pBlock->pNext && pBlock->pNext->base.address-pBlock->base.address-pBlock->base.size >= newSize) || - (pBlock->pPrev && pBlock->base.address-pBlock->pPrev->base.address-pBlock->pPrev->base.size >= newSize)) - { - GmmTileBlock *pNewBlock = (GmmTileBlock *)gmmAllocFixed(1); - if (pNewBlock == NULL) - break; - - retId = (uint32_t)pNewBlock; - - memset(pNewBlock, 0, sizeof(GmmTileBlock)); - - pNewBlock->base.isMain = (pAllocator == pGmmMainAllocator); - pNewBlock->base.isTile = 1; - pNewBlock->base.size = newSize; - - if (pBlock->pNext && pBlock->pNext->base.address-pBlock->base.address-pBlock->base.size >= newSize) - { - pNewBlock->base.address = pBlock->base.address+pBlock->base.size; - pNewBlock->pNext = pBlock->pNext; - pNewBlock->pPrev = pBlock; - pBlock->pNext->pPrev = pNewBlock; - pBlock->pNext = pNewBlock; - - if (pNewBlock->pPrev->pData != pNewBlock->pNext->pData) - { - resizeSucceed = _RGLTryResizeTileRegion( address, tileSize+newSize, pBlock->pData ); - } - } - else - { - pNewBlock->base.address = pBlock->base.address-newSize; - pNewBlock->pNext = pBlock; - pNewBlock->pPrev = pBlock->pPrev; - pBlock->pPrev->pNext = pNewBlock; - pBlock->pPrev = pNewBlock; - - if (pNewBlock->pPrev->pData != pNewBlock->pNext->pData) - { - GmmBaseBlock *pBaseBlock = (GmmBaseBlock *)(uint32_t)(pNewBlock); - resizeSucceed = _RGLTryResizeTileRegion((GLuint)gmmAddressToOffset(pBaseBlock->address, pBaseBlock->isMain), tileSize+newSize, pBlock->pData); - } - } - gmmSetTileAttrib( retId, tag, pBlock->pData ); - break; - } - - if (pBlock == pAllocator->pTileHead) - { - retId = (uint32_t)gmmCreateTileBlock(pAllocator, newSize); - if (retId == 0) - break; - - resizeSucceed = _RGLTryResizeTileRegion( (GLuint)gmmIdToOffset(retId), tileSize+newSize, pBlock->pData ); - gmmSetTileAttrib( retId, tag, pBlock->pData ); - break; - } - } - - pBlock = pBlock->pPrev; - } - - if (retId == 0) - return GMM_ERROR; - - if (!resizeSucceed) - { - gmmFreeTileBlock((GmmTileBlock *)retId); - return GMM_ERROR; - } - - return retId; -} - -static GmmTileBlock *gmmAllocTileBlock( - GmmAllocator *pAllocator, - const uint32_t size -) -{ - GmmTileBlock *pBlock = gmmFindFreeTileBlock(pAllocator, size); - - if (pBlock == NULL) - pBlock = gmmCreateTileBlock(pAllocator, size); - - return pBlock; -} - -static void gmmFreeBlock(GmmBlock *pBlock) -{ - GmmAllocator *pAllocator; - - if (pBlock->pPrev) - pBlock->pPrev->pNext = pBlock->pNext; - - if (pBlock->pNext) - pBlock->pNext->pPrev = pBlock->pPrev; - - if (pBlock->base.isMain) - pAllocator = pGmmMainAllocator; - else - pAllocator = pGmmLocalAllocator; - - if (pAllocator->pHead == pBlock) - { - pAllocator->pHead = pBlock->pNext; - - if (pAllocator->pHead) - pAllocator->pHead->pPrev = NULL; - } - - if (pAllocator->pTail == pBlock) - { - pAllocator->pTail = pBlock->pPrev; - - if (pAllocator->pTail) - pAllocator->pTail->pNext = NULL; - } - - if (pBlock->pPrev == NULL) - pAllocator->pSweepHead = pAllocator->pHead; - else if (pBlock->pPrev && - (pAllocator->pSweepHead == NULL || - (pAllocator->pSweepHead && - pAllocator->pSweepHead->base.address > pBlock->pPrev->base.address))) - { - pAllocator->pSweepHead = pBlock->pPrev; - } - - pAllocator->freedSinceSweep += pBlock->base.size; - - gmmFreeFixed(0, pBlock); -} - -static void gmmAddPendingFree(GmmBlock *pBlock) -{ - GmmAllocator *pAllocator; - - if (pBlock->base.isMain) - pAllocator = pGmmMainAllocator; - else - pAllocator = pGmmLocalAllocator; - - if (pAllocator->pPendingFreeTail) - { - pBlock->pNextFree = NULL; - pBlock->pPrevFree = pAllocator->pPendingFreeTail; - pAllocator->pPendingFreeTail->pNextFree = pBlock; - pAllocator->pPendingFreeTail = pBlock; - } - else - { - pBlock->pNextFree = NULL; - pBlock->pPrevFree = NULL; - pAllocator->pPendingFreeHead = pBlock; - pAllocator->pPendingFreeTail = pBlock; - } - - pBlock->isPinned = 0; - - GLuint* ref = &pBlock->fence; - ++nvFenceCounter; - cellGcmSetWriteBackEndLabelInline( &_RGLState.fifo, SEMA_FENCE, nvFenceCounter); - *ref = nvFenceCounter; -} - - - -uint32_t gmmFree(const uint32_t freeId) -{ - GmmBaseBlock *pBaseBlock = (GmmBaseBlock *)freeId; - - if (pBaseBlock->isTile) - { - GmmTileBlock *pTileBlock = (GmmTileBlock *)pBaseBlock; - - if (pTileBlock->pPrev && - pTileBlock->pNext && - pTileBlock->pPrev->pData == pTileBlock->pNext->pData) - { - } - else if (pTileBlock->pPrev && pTileBlock->pPrev->pData == pTileBlock->pData) - { - GLuint address, size; - - _RGLGetTileRegionInfo(pTileBlock->pData, &address, &size); - if ( !_RGLTryResizeTileRegion(address, (size-pTileBlock->base.size), pTileBlock->pData) ) - { - _RGLTryResizeTileRegion(address, 0, pTileBlock->pData); - if ( !_RGLTryResizeTileRegion(address, (size-pTileBlock->base.size), pTileBlock->pData) ) - { - } - } - } - else if (pTileBlock->pNext && pTileBlock->pNext->pData == pTileBlock->pData) - { - GLuint address, size; - - _RGLGetTileRegionInfo(pTileBlock->pData, &address, &size); - if ( !_RGLTryResizeTileRegion((address+pTileBlock->base.size), (size-pTileBlock->base.size), pTileBlock->pData) ) - { - _RGLTryResizeTileRegion(address, 0, pTileBlock->pData); - if ( !_RGLTryResizeTileRegion((address+pTileBlock->base.size), (size-pTileBlock->base.size), pTileBlock->pData) ) - { - } - } - } - else - { - if ( !_RGLTryResizeTileRegion( (GLuint)gmmIdToOffset(freeId), 0, ((GmmTileBlock *)freeId)->pData ) ) - { - } - } - - gmmFreeTileBlock(pTileBlock); - } - else - { - GmmBlock *pBlock = (GmmBlock *)pBaseBlock; - - gmmAddPendingFree(pBlock); - } - - return CELL_OK; -} - -static inline void gmmLocalMemcpy( - const uint32_t dstOffset, - const uint32_t srcOffset, - const uint32_t moveSize -) -{ - CellGcmContextData *thisContext = &_RGLState.fifo; - int32_t offset = 0; - int32_t sizeLeft = moveSize; - int32_t dimension = 4096; - - while (sizeLeft) - { - while(sizeLeft >= dimension*dimension*4) - { - cellGcmSetTransferImage(thisContext, - CELL_GCM_TRANSFER_LOCAL_TO_LOCAL, - dstOffset+offset, - dimension*4, - 0, - 0, - srcOffset+offset, - dimension*4, - 0, - 0, - dimension, - dimension, - 4); - - offset = offset + dimension*dimension*4; - sizeLeft = sizeLeft - (dimension*dimension*4); - } - - dimension = dimension >> 1; - - if (dimension == 32) - break; - } - - if (sizeLeft) - cellGcmSetTransferImage(thisContext, - CELL_GCM_TRANSFER_LOCAL_TO_LOCAL, - dstOffset+offset, - sizeLeft, - 0, - 0, - srcOffset+offset, - sizeLeft, - 0, - 0, - sizeLeft/4, - 1, - 4); -} - -static uint8_t gmmInternalSweep (void) -{ - GmmAllocator *pAllocator = pGmmLocalAllocator; - GmmBlock *pBlock; - GmmBlock *pSrcBlock; - GmmBlock *pTempBlock; - GmmBlock *pTempBlockNext; - uint32_t dstAddress, srcAddress; - uint32_t srcOffset, dstOffset; - uint32_t prevEndAddress; - uint32_t moveSize, moveDistance; - uint8_t ret = 0; - uint32_t totalMoveSize = 0; - - pBlock = pAllocator->pSweepHead; - srcAddress = 0; - dstAddress = 0; - prevEndAddress = 0; - pSrcBlock = pBlock; - - while (pBlock != NULL) - { - if (pBlock->isPinned == 0) - { - if (pBlock->pPrev) - prevEndAddress = pBlock->pPrev->base.address + pBlock->pPrev->base.size; - else - prevEndAddress = pAllocator->startAddress; - - if (pBlock->base.address > prevEndAddress) - { - dstAddress = prevEndAddress; - srcAddress = pBlock->base.address; - pSrcBlock = pBlock; - } - - moveSize = pBlock->base.address + pBlock->base.size - srcAddress; - - if (srcAddress > dstAddress && - (pBlock->pNext == NULL || - pBlock->pNext->base.address > pBlock->base.address + pBlock->base.size || - pBlock->pNext->isPinned)) - { - dstOffset = gmmAddressToOffset(dstAddress, 0); - srcOffset = gmmAddressToOffset(srcAddress, 0); - - totalMoveSize += moveSize; - - if (dstOffset + moveSize <= srcOffset) - gmmLocalMemcpy(dstOffset, srcOffset, moveSize); - else - { - uint32_t moveBlockSize = srcOffset-dstOffset; - uint32_t iterations = (moveSize+moveBlockSize-1)/moveBlockSize; - - for (uint32_t i = 0; i < iterations; i++) - gmmLocalMemcpy(dstOffset+(i*moveBlockSize), srcOffset+(i*moveBlockSize), moveBlockSize); - } - - pTempBlock = pSrcBlock; - - moveDistance = srcOffset - dstOffset; - - while (pTempBlock != pBlock->pNext) - { - pTempBlock->base.address -= moveDistance; - pTempBlock = pTempBlock->pNext; - } - } - } - else - { - uint32_t availableSize; - - srcAddress = 0; - dstAddress = 0; - - if (pBlock->pPrev == NULL) - availableSize = pBlock->base.address - pAllocator->startAddress; - else - availableSize = pBlock->base.address - (pBlock->pPrev->base.address + pBlock->pPrev->base.size); - - pTempBlock = pBlock->pNext; - - while (availableSize >= GMM_ALIGNMENT && pTempBlock) - { - pTempBlockNext = pTempBlock->pNext; - - if (pTempBlock->isPinned == 0 && pTempBlock->base.size <= availableSize) - { - uint32_t pinDstAddress = (pBlock->pPrev == NULL) ? - pAllocator->startAddress : - pBlock->pPrev->base.address + pBlock->pPrev->base.size; - uint32_t pinSrcAddress = pTempBlock->base.address; - uint32_t moveSize = pTempBlock->base.size; - - dstOffset = gmmAddressToOffset(pinDstAddress, 0); - srcOffset = gmmAddressToOffset(pinSrcAddress, 0); - - totalMoveSize += moveSize; - - if (dstOffset + moveSize <= srcOffset) - gmmLocalMemcpy(dstOffset, srcOffset, moveSize); - else - { - uint32_t moveBlockSize = srcOffset-dstOffset; - uint32_t iterations = (moveSize+moveBlockSize-1)/moveBlockSize; - - for (uint32_t i = 0; i < iterations; i++) - gmmLocalMemcpy(dstOffset+(i*moveBlockSize), srcOffset+(i*moveBlockSize), moveBlockSize); - } - - pTempBlock->base.address = pinDstAddress; - - if (pTempBlock == pAllocator->pTail) - { - if (pTempBlock->pNext) - pAllocator->pTail = pTempBlock->pNext; - else - pAllocator->pTail = pTempBlock->pPrev; - } - - if (pTempBlock->pNext) - pTempBlock->pNext->pPrev = pTempBlock->pPrev; - - if (pTempBlock->pPrev) - pTempBlock->pPrev->pNext = pTempBlock->pNext; - - if (pBlock->pPrev) - pBlock->pPrev->pNext = pTempBlock; - else - pAllocator->pHead = pTempBlock; - - pTempBlock->pPrev = pBlock->pPrev; - pTempBlock->pNext = pBlock; - pBlock->pPrev = pTempBlock; - } - - if (pBlock->pPrev) - availableSize = pBlock->base.address - (pBlock->pPrev->base.address + pBlock->pPrev->base.size); - - pTempBlock = pTempBlockNext; - } - - if (availableSize) - { - GmmBlock *pNewBlock = (GmmBlock *)gmmAllocFixed(0); - - if (pNewBlock) - { - memset(pNewBlock, 0, sizeof(GmmBlock)); - pNewBlock->base.address = pBlock->base.address - availableSize; - pNewBlock->base.isMain = pBlock->base.isMain; - pNewBlock->base.size = availableSize; - pNewBlock->pNext = pBlock; - pNewBlock->pPrev = pBlock->pPrev; - - if (pBlock->pPrev) - pBlock->pPrev->pNext = pNewBlock; - - pBlock->pPrev = pNewBlock; - - if (pBlock == pAllocator->pHead) - pAllocator->pHead = pNewBlock; - - gmmAddFree(pAllocator, pNewBlock); - - ret = 1; - } - } - } - - pBlock = pBlock->pNext; - } - - uint32_t newFreeAddress = pAllocator->pTail ? - pAllocator->pTail->base.address + pAllocator->pTail->base.size : - pAllocator->startAddress; - - if (pAllocator->freeAddress != newFreeAddress) - { - pAllocator->freeAddress = newFreeAddress; - ret = 1; - } - - pAllocator->freedSinceSweep = 0; - pAllocator->pSweepHead = NULL; - - - return ret; -} - - -static void gmmFreeAll (void) -{ - GmmAllocator *pAllocator = pGmmLocalAllocator; - GmmBlock *pBlock; - GmmBlock *pTemp; - - pBlock = pAllocator->pPendingFreeHead; - while (pBlock) - { - pTemp = pBlock->pNextFree; - gmmFreeBlock(pBlock); - pBlock = pTemp; - } - pAllocator->pPendingFreeHead = NULL; - pAllocator->pPendingFreeTail = NULL; - - for (int i=0; ipFreeHead[i]; - while (pBlock) - { - pTemp = pBlock->pNextFree; - gmmFreeBlock(pBlock); - pBlock = pTemp; - } - pAllocator->pFreeHead[i] = NULL; - pAllocator->pFreeTail[i] = NULL; - } -} - -static uint32_t gmmFindFreeBlock( - GmmAllocator *pAllocator, - uint32_t size -) -{ - uint32_t retId = GMM_ERROR; - GmmBlock *pBlock; - uint8_t found = 0; - uint8_t freeIndex = gmmSizeToFreeIndex(size); - - pBlock = pAllocator->pFreeHead[freeIndex]; - - while (freeIndex < GMM_NUM_FREE_BINS) - { - if (pBlock) - { - if (pBlock->base.size >= size) - { - found = 1; - break; - } - pBlock = pBlock->pNextFree; - } - else if (++freeIndex < GMM_NUM_FREE_BINS) - pBlock = pAllocator->pFreeHead[freeIndex]; - } - - if (found) - { - if (pBlock->base.size != size) - { - // create a new block here - GmmBlock *pNewBlock = (GmmBlock *)gmmAllocFixed(0); - if (pNewBlock == NULL) - return GMM_ERROR; - - memset(pNewBlock, 0, sizeof(GmmBlock)); - pNewBlock->base.address = pBlock->base.address + size; - pNewBlock->base.isMain = pBlock->base.isMain; - pNewBlock->base.size = pBlock->base.size - size; - pNewBlock->pNext = pBlock->pNext; - pNewBlock->pPrev = pBlock; - - if (pBlock->pNext) - pBlock->pNext->pPrev = pNewBlock; - - pBlock->pNext = pNewBlock; - - if (pBlock == pAllocator->pTail) - pAllocator->pTail = pNewBlock; - - gmmAddFree(pAllocator, pNewBlock); - } - pBlock->base.size = size; - - if (pBlock == pAllocator->pFreeHead[freeIndex]) - pAllocator->pFreeHead[freeIndex] = pBlock->pNextFree; - if (pBlock == pAllocator->pFreeTail[freeIndex]) - pAllocator->pFreeTail[freeIndex] = pBlock->pPrevFree; - if (pBlock->pNextFree) - pBlock->pNextFree->pPrevFree = pBlock->pPrevFree; - if (pBlock->pPrevFree) - pBlock->pPrevFree->pNextFree = pBlock->pNextFree; - - retId = (uint32_t)pBlock; - } - - return retId; -} - -uint32_t gmmAlloc(const uint8_t isTile, const uint32_t size) -{ - CellGcmContextData *thisContext = (CellGcmContextData*)&_RGLState.fifo; - GmmAllocator *pAllocator; - uint32_t retId; - uint32_t newSize; - - if (__builtin_expect((size == 0),0)) - return GMM_ERROR; - - pAllocator = pGmmLocalAllocator; - - if (!isTile) - { - newSize = pad(size, GMM_ALIGNMENT); - retId = gmmFindFreeBlock(pAllocator, newSize); - } - else - { - newSize = pad(size, GMM_TILE_ALIGNMENT); - retId = GMM_ERROR; - } - - if (retId == GMM_ERROR) - { - if (isTile) - retId = (uint32_t)gmmAllocTileBlock(pAllocator, newSize); - else - retId = (uint32_t)gmmAllocBlock(pAllocator, newSize); - - if (retId == MEMORY_ALLOC_ERROR) - { - gmmFreeAll(); - - if (gmmInternalSweep()) - { - *pLock = 1; - cachedLockValue = 1; - cellGcmSetWriteBackEndLabel(thisContext, GMM_PPU_WAIT_INDEX, 0); - - cellGcmFlush(thisContext); - } - - if (isTile) - retId = (uint32_t)gmmAllocTileBlock(pAllocator, newSize); - else - retId = (uint32_t)gmmAllocBlock(pAllocator, newSize); - - if (!isTile && retId == MEMORY_ALLOC_ERROR) - retId = gmmFindFreeBlock(pAllocator, newSize); - } - } - - return retId; -} - -static int _RGLLoadFPShader( _CGprogram *program ) -{ - unsigned int ucodeSize = program->header.instructionCount * 16; - - if ( program->loadProgramId == GMM_ERROR ) - { - program->loadProgramId = gmmAlloc(0, ucodeSize); - program->loadProgramOffset = 0; - } - - unsigned int dstId = program->loadProgramId; - unsigned dstOffset = program->loadProgramOffset; - const char *src = (char*)program->ucode; - - GLuint id = gmmAlloc(0, ucodeSize); - - memcpy( gmmIdToAddress(id), src, ucodeSize ); - _RGLMemcpy( dstId, dstOffset, 0, id, ucodeSize ); - - gmmFree( id ); - return GL_TRUE; -} - -void _RGLPlatformSetVertexRegister4fv( unsigned int reg, const float * __restrict v ) {} -void _RGLPlatformSetVertexRegisterBlock( unsigned int reg, unsigned int count, const float * __restrict v ) {} -void _RGLPlatformSetFragmentRegister4fv( unsigned int reg, const float * __restrict v ) {} -void _RGLPlatformSetFragmentRegisterBlock( unsigned int reg, unsigned int count, const float * __restrict v ) {} - -template inline static void swapandsetfp( int ucodeSize, unsigned int loadProgramId, unsigned int loadProgramOffset, unsigned short *ec, const unsigned int * __restrict v ) -{ - cellGcmSetTransferLocationInline ( &_RGLState.fifo, CELL_GCM_LOCATION_LOCAL); - unsigned short count = *( ec++ ); - for ( unsigned long offsetIndex = 0; offsetIndex < count; ++offsetIndex ) - { - void *ptr = NULL; - const int paddedSIZE = (SIZE + 1) & ~1; - cellGcmSetInlineTransferPointerInline( &_RGLState.fifo, gmmIdToOffset( loadProgramId ) + loadProgramOffset + *(ec++), paddedSIZE, &ptr); - float *fp = (float*)ptr; - float *src = (float*)v; - for (uint32_t j=0; j static void setVectorTypefp( CgRuntimeParameter* __restrict ptr, const void* __restrict v ) -{ - float * __restrict f = ( float* )v; - float * __restrict data = ( float* )ptr->pushBufferPointer; - - for ( long i = 0; i < SIZE; ++i ) - data[i] = f[i]; - - _CGprogram *program = ptr->program; - - CgParameterResource *parameterResource = _RGLGetParameterResource( ptr->program, ptr->parameterEntry ); - unsigned short resource = parameterResource->resource; - unsigned short *ec = ( unsigned short * )( ptr->program->resources ) + resource + 1; - - if ( RGL_LIKELY( *ec ) ) - { - swapandsetfp(program->header.instructionCount*16, program->loadProgramId, program->loadProgramOffset, ec, (unsigned int *)data); - } -} - -template static void setVectorTypeSharedfpIndex( CgRuntimeParameter* __restrict ptr, const void* __restrict v, const int ) {} - -template static void setVectorTypeSharedfpIndexArray( CgRuntimeParameter* __restrict ptr, const void* __restrict v, const int index ) {} - -template static void setVectorTypeSharedvpIndex( CgRuntimeParameter* __restrict ptr, const void* __restrict v, const int ) -{ - const float * __restrict f = ( const float * __restrict )v; - const CgParameterResource *parameterResource = _RGLGetParameterResource( ptr->program, ptr->parameterEntry ); - unsigned short resource = parameterResource->resource; - float * __restrict dst = (float * __restrict)ptr->pushBufferPointer; - for (long i = 0; i < SIZE; ++i) - dst[i] = f[i]; - _RGLPlatformSetVertexRegister4fv( resource, dst ); -} - -template static void setVectorTypeSharedvpIndexArray( CgRuntimeParameter* __restrict ptr, const void* __restrict v, const int index ) -{ - const float * __restrict f = ( const float * __restrict )v; - const CgParameterResource *parameterResource = _RGLGetParameterResource( ptr->program, ptr->parameterEntry ); - unsigned short resource = parameterResource->resource + index; - float * __restrict dst = ( float * __restrict )ptr->pushBufferPointer; - for ( long i = 0; i < SIZE; ++ i ) - dst[i] = f[i]; - _RGLPlatformSetVertexRegister4fv( resource, dst ); -} - -template static void setVectorTypevpIndex( CgRuntimeParameter* __restrict ptr, const void* __restrict v, const int ) -{ - PSGLcontext * LContext = _CurrentContext; - const float * __restrict f = ( const float* )v; - float * __restrict dst = ( float* )ptr->pushBufferPointer; - for ( long i = 0; i < SIZE; ++ i ) - dst[i] = f[i]; - LContext->needValidate |= PSGL_VALIDATE_VERTEX_CONSTANTS; -} -template static void setVectorTypevpIndexArray( CgRuntimeParameter* __restrict ptr, const void* __restrict v, const int index ) -{ - PSGLcontext * LContext = _CurrentContext; - const float * __restrict f = ( const float* )v; - float * __restrict dst = ( float* )( *(( unsigned int ** )ptr->pushBufferPointer + index ) ); - for ( long i = 0; i < SIZE; ++ i ) - dst[i] = f[i]; - LContext->needValidate |= PSGL_VALIDATE_VERTEX_CONSTANTS; -} -template static void setVectorTypefpIndex( CgRuntimeParameter* __restrict ptr, const void* __restrict v, const int ) -{ - float * __restrict f = ( float* )v; - float * __restrict data = ( float* )ptr->pushBufferPointer; - for ( long i = 0; i < SIZE; ++i ) - data[i] = f[i]; - _CGprogram *program = ptr->program; - - const CgParameterResource *parameterResource = _RGLGetParameterResource( program, ptr->parameterEntry ); - unsigned short resource = parameterResource->resource; - unsigned short *ec = ( unsigned short * )( ptr->program->resources ) + resource + 1; - if ( RGL_LIKELY( *ec ) ) - { - swapandsetfp( program->header.instructionCount*16, program->loadProgramId, program->loadProgramOffset, ec, ( unsigned int * )data ); - } -} -template static void setVectorTypefpIndexArray( CgRuntimeParameter* __restrict ptr, const void* __restrict v, const int index ) -{ - float * __restrict f = ( float* )v; - float * __restrict data = ( float* )ptr->pushBufferPointer; - for ( long i = 0; i < SIZE; ++i ) - data[i] = f[i]; - _CGprogram *program = ptr->program; - - const CgParameterResource *parameterResource = _RGLGetParameterResource( program, ptr->parameterEntry ); - unsigned short resource = parameterResource->resource; - unsigned short *ec = ( unsigned short * )( program->resources ) + resource + 1; - int arrayIndex = index; - while ( arrayIndex ) - { - ec += (( *ec ) + 2 ); - arrayIndex--; - } - if ( RGL_LIKELY( *ec ) ) - { - swapandsetfp( program->header.instructionCount*16, program->loadProgramId, program->loadProgramOffset, ec, ( unsigned int * )data ); - } -} - -template static void setMatrixvpIndex( CgRuntimeParameter* __restrict ptr, const void* __restrict v, const int index ) -{ - PSGLcontext * LContext = _CurrentContext; - float * __restrict f = ( float* )v; - float * __restrict dst = ( float* )ptr->pushBufferPointer; - for ( long row = 0; row < ROWS; ++row ) - { - for ( long col = 0; col < COLS; ++col ) - dst[row * 4 + col] = ( ORDER == ROW_MAJOR ) ? f[row * COLS + col] : f[col * ROWS + row]; - } - LContext->needValidate |= PSGL_VALIDATE_VERTEX_CONSTANTS; -} - -template static void setMatrixSharedvpIndex( CgRuntimeParameter* __restrict ptr, const void* __restrict v, const int /*index*/ ) -{ - float * __restrict f = ( float* )v; - float * __restrict dst = ( float* )ptr->pushBufferPointer; - - const CgParameterResource *parameterResource = _RGLGetParameterResource( ptr->program, ptr->parameterEntry ); - unsigned short resource = parameterResource->resource; - - float tmp[ROWS*4]; - for ( long row = 0; row < ROWS; ++row ) - { - for(long col = 0; col < COLS; ++col) - tmp[row*4 + col] = dst[row * 4 + col] = ( ORDER == ROW_MAJOR ) ? f[row * COLS + col] : f[col * ROWS + row]; - for(long col = COLS; col < 4; ++col) - tmp[row*4 + col] = dst[row*4+col]; - } - - cellGcmSetVertexProgramParameterBlockInline( &_RGLState.fifo, resource, ROWS, (const float*)tmp); -} - -template static void setMatrixSharedvpIndexArray( CgRuntimeParameter* __restrict ptr, const void* __restrict v, const int index ) -{ - float * __restrict f = ( float* )v; - float * __restrict dst = ( float* )ptr->pushBufferPointer; - - const CgParameterResource *parameterResource = _RGLGetParameterResource( ptr->program, ptr->parameterEntry ); - unsigned short resource = parameterResource->resource + index * ROWS; - - float tmp[ROWS*4]; - for ( long row = 0; row < ROWS; ++row ) - { - for ( long col = 0; col < COLS; ++col ) - { - tmp[row*4 + col] = dst[row * 4 + col] = ( ORDER == ROW_MAJOR ) ? f[row * COLS + col] : f[col * ROWS + row]; - } - for ( long col = COLS; col < 4; ++col ) tmp[row*4 + col] = dst[row*4+col]; - } - cellGcmSetVertexProgramParameterBlockInline( &_RGLState.fifo, resource, ROWS, (const float*)tmp); -} - -template static void setMatrixSharedfpIndex( CgRuntimeParameter* __restrict ptr, const void* __restrict v, const int /*index*/ ) -{ -} - -template static void setMatrixSharedfpIndexArray( CgRuntimeParameter* __restrict ptr, const void* __restrict v, const int index ) -{ -} - -template static void setMatrixvpIndexArray( CgRuntimeParameter* __restrict ptr, const void* __restrict v, const int index ) -{ - PSGLcontext * LContext = _CurrentContext; - float * __restrict f = ( float* )v; - float * __restrict dst = ( float* )( *(( unsigned int ** )ptr->pushBufferPointer + index ) ); - for ( long row = 0; row < ROWS; ++row ) - { - for ( long col = 0; col < COLS; ++col ) - dst[row * 4 + col] = ( ORDER == ROW_MAJOR ) ? f[row * COLS + col] : f[col * ROWS + row]; - } - LContext->needValidate |= PSGL_VALIDATE_VERTEX_CONSTANTS; -} -template static void setMatrixfpIndex( CgRuntimeParameter* __restrict ptr, const void* __restrict v, const int /*index*/ ) -{ - float * __restrict f = ( float* )v; - float * __restrict dst = ( float* )ptr->pushBufferPointer; - _CGprogram *program = (( CgRuntimeParameter* )ptr )->program; - const CgParameterResource *parameterResource = _RGLGetParameterResource( program, ptr->parameterEntry ); - unsigned short resource = parameterResource->resource; - unsigned short *ec = ( unsigned short * )program->resources + resource + 1; - for ( long row = 0; row < ROWS; ++row ) - { - for ( long col = 0; col < COLS; ++col ) - dst[row * 4 + col] = ( ORDER == ROW_MAJOR ) ? f[row * COLS + col] : f[col * ROWS + row]; - int count = *ec; - if ( RGL_LIKELY( count ) ) - { - swapandsetfp( program->header.instructionCount*16, program->loadProgramId, program->loadProgramOffset, ec, ( unsigned int * )dst + row * 4 ); - } - ec += count + 2; - } -} -template static void setMatrixfpIndexArray( CgRuntimeParameter* __restrict ptr, const void* __restrict v, const int index ) -{ - float * __restrict f = ( float* )v; - float * __restrict dst = ( float* )ptr->pushBufferPointer; - _CGprogram *program = ptr->program; - const CgParameterResource *parameterResource = _RGLGetParameterResource( program, ptr->parameterEntry ); - unsigned short resource = parameterResource->resource; - unsigned short *ec = ( unsigned short * )program->resources + resource + 1; - int arrayIndex = index * ROWS; - while ( arrayIndex ) - { - unsigned short count = ( *ec ); - ec += ( count + 2 ); - arrayIndex--; - } - for ( long row = 0; row < ROWS; ++row ) - { - for ( long col = 0; col < COLS; ++col ) - dst[row * 4 + col] = ( ORDER == ROW_MAJOR ) ? f[row * COLS + col] : f[col * ROWS + row]; - int count = *ec; - if ( RGL_LIKELY( count ) ) - { - swapandsetfp( program->header.instructionCount*16, program->loadProgramId, program->loadProgramOffset, ec, ( unsigned int * )dst + row * 4 ); - } - ec += count + 2; - } -} - -static _cgSetArrayIndexFunction setVectorTypeIndex[2][2][2][4] = - { - { - { - {&setVectorTypevpIndex<1>, &setVectorTypevpIndex<2>, &setVectorTypevpIndex<3>, &setVectorTypevpIndex<4>, }, - {&setVectorTypefpIndex<1>, &setVectorTypefpIndex<2>, &setVectorTypefpIndex<3>, &setVectorTypefpIndex<4>, } - }, - { - {&setVectorTypeSharedvpIndex<1>, &setVectorTypeSharedvpIndex<2>, &setVectorTypeSharedvpIndex<3>, &setVectorTypeSharedvpIndex<4>, }, - {&setVectorTypeSharedfpIndex<1>, &setVectorTypeSharedfpIndex<2>, &setVectorTypeSharedfpIndex<3>, &setVectorTypeSharedfpIndex<4>, } - }, - }, - { - { - {&setVectorTypevpIndexArray<1>, &setVectorTypevpIndexArray<2>, &setVectorTypevpIndexArray<3>, &setVectorTypevpIndexArray<4>, }, - {&setVectorTypefpIndexArray<1>, &setVectorTypefpIndexArray<2>, &setVectorTypefpIndexArray<3>, &setVectorTypefpIndexArray<4>, } - }, - { - {&setVectorTypeSharedvpIndexArray<1>, &setVectorTypeSharedvpIndexArray<2>, &setVectorTypeSharedvpIndexArray<3>, &setVectorTypeSharedvpIndexArray<4>, }, //should be the shared - {&setVectorTypeSharedfpIndexArray<1>, &setVectorTypeSharedfpIndexArray<2>, &setVectorTypeSharedfpIndexArray<3>, &setVectorTypeSharedfpIndexArray<4>, } //should be the shared - }, - }, - }; - -static _cgSetArrayIndexFunction setMatrixTypeIndex[2][2][2][4][4][2] = - { - { - { - { - {{ &setMatrixvpIndex<1, 1, 0>, &setMatrixvpIndex<1, 1, 1>}, { &setMatrixvpIndex<1, 2, 0>, &setMatrixvpIndex<1, 2, 1>}, { &setMatrixvpIndex<1, 3, 0>, &setMatrixvpIndex<1, 3, 1>}, { &setMatrixvpIndex<1, 4, 0>, &setMatrixvpIndex<1, 4, 1>}}, - {{ &setMatrixvpIndex<2, 1, 0>, &setMatrixvpIndex<2, 1, 1>}, { &setMatrixvpIndex<2, 2, 0>, &setMatrixvpIndex<2, 2, 1>}, { &setMatrixvpIndex<2, 3, 0>, &setMatrixvpIndex<2, 3, 1>}, { &setMatrixvpIndex<2, 4, 0>, &setMatrixvpIndex<2, 4, 1>}}, - {{ &setMatrixvpIndex<3, 1, 0>, &setMatrixvpIndex<3, 1, 1>}, { &setMatrixvpIndex<3, 2, 0>, &setMatrixvpIndex<3, 2, 1>}, { &setMatrixvpIndex<3, 3, 0>, &setMatrixvpIndex<3, 3, 1>}, { &setMatrixvpIndex<3, 4, 0>, &setMatrixvpIndex<3, 4, 1>}}, - {{ &setMatrixvpIndex<4, 1, 0>, &setMatrixvpIndex<4, 1, 1>}, { &setMatrixvpIndex<4, 2, 0>, &setMatrixvpIndex<4, 2, 1>}, { &setMatrixvpIndex<4, 3, 0>, &setMatrixvpIndex<4, 3, 1>}, { &setMatrixvpIndex<4, 4, 0>, &setMatrixvpIndex<4, 4, 1>}}, - }, - { - {{ &setMatrixfpIndex<1, 1, 0>, &setMatrixfpIndex<1, 1, 1>}, { &setMatrixfpIndex<1, 2, 0>, &setMatrixfpIndex<1, 2, 1>}, { &setMatrixfpIndex<1, 3, 0>, &setMatrixfpIndex<1, 3, 1>}, { &setMatrixfpIndex<1, 4, 0>, &setMatrixfpIndex<1, 4, 1>}}, - {{ &setMatrixfpIndex<2, 1, 0>, &setMatrixfpIndex<2, 1, 1>}, { &setMatrixfpIndex<2, 2, 0>, &setMatrixfpIndex<2, 2, 1>}, { &setMatrixfpIndex<2, 3, 0>, &setMatrixfpIndex<2, 3, 1>}, { &setMatrixfpIndex<2, 4, 0>, &setMatrixfpIndex<2, 4, 1>}}, - {{ &setMatrixfpIndex<3, 1, 0>, &setMatrixfpIndex<3, 1, 1>}, { &setMatrixfpIndex<3, 2, 0>, &setMatrixfpIndex<3, 2, 1>}, { &setMatrixfpIndex<3, 3, 0>, &setMatrixfpIndex<3, 3, 1>}, { &setMatrixfpIndex<3, 4, 0>, &setMatrixfpIndex<3, 4, 1>}}, - {{ &setMatrixfpIndex<4, 1, 0>, &setMatrixfpIndex<4, 1, 1>}, { &setMatrixfpIndex<4, 2, 0>, &setMatrixfpIndex<4, 2, 1>}, { &setMatrixfpIndex<4, 3, 0>, &setMatrixfpIndex<4, 3, 1>}, { &setMatrixfpIndex<4, 4, 0>, &setMatrixfpIndex<4, 4, 1>}}, - }, - }, - { //should be shared - { - {{ &setMatrixSharedvpIndex<1, 1, 0>, &setMatrixSharedvpIndex<1, 1, 1>}, { &setMatrixSharedvpIndex<1, 2, 0>, &setMatrixSharedvpIndex<1, 2, 1>}, { &setMatrixSharedvpIndex<1, 3, 0>, &setMatrixSharedvpIndex<1, 3, 1>}, { &setMatrixSharedvpIndex<1, 4, 0>, &setMatrixSharedvpIndex<1, 4, 1>}}, - {{ &setMatrixSharedvpIndex<2, 1, 0>, &setMatrixSharedvpIndex<2, 1, 1>}, { &setMatrixSharedvpIndex<2, 2, 0>, &setMatrixSharedvpIndex<2, 2, 1>}, { &setMatrixSharedvpIndex<2, 3, 0>, &setMatrixSharedvpIndex<2, 3, 1>}, { &setMatrixSharedvpIndex<2, 4, 0>, &setMatrixSharedvpIndex<2, 4, 1>}}, - {{ &setMatrixSharedvpIndex<3, 1, 0>, &setMatrixSharedvpIndex<3, 1, 1>}, { &setMatrixSharedvpIndex<3, 2, 0>, &setMatrixSharedvpIndex<3, 2, 1>}, { &setMatrixSharedvpIndex<3, 3, 0>, &setMatrixSharedvpIndex<3, 3, 1>}, { &setMatrixSharedvpIndex<3, 4, 0>, &setMatrixSharedvpIndex<3, 4, 1>}}, - {{ &setMatrixSharedvpIndex<4, 1, 0>, &setMatrixSharedvpIndex<4, 1, 1>}, { &setMatrixSharedvpIndex<4, 2, 0>, &setMatrixSharedvpIndex<4, 2, 1>}, { &setMatrixSharedvpIndex<4, 3, 0>, &setMatrixSharedvpIndex<4, 3, 1>}, { &setMatrixSharedvpIndex<4, 4, 0>, &setMatrixSharedvpIndex<4, 4, 1>}}, - }, - { - {{ &setMatrixSharedfpIndex<1, 1, 0>, &setMatrixSharedfpIndex<1, 1, 1>}, { &setMatrixSharedfpIndex<1, 2, 0>, &setMatrixSharedfpIndex<1, 2, 1>}, { &setMatrixSharedfpIndex<1, 3, 0>, &setMatrixSharedfpIndex<1, 3, 1>}, { &setMatrixSharedfpIndex<1, 4, 0>, &setMatrixSharedfpIndex<1, 4, 1>}}, - {{ &setMatrixSharedfpIndex<2, 1, 0>, &setMatrixSharedfpIndex<2, 1, 1>}, { &setMatrixSharedfpIndex<2, 2, 0>, &setMatrixSharedfpIndex<2, 2, 1>}, { &setMatrixSharedfpIndex<2, 3, 0>, &setMatrixSharedfpIndex<2, 3, 1>}, { &setMatrixSharedfpIndex<2, 4, 0>, &setMatrixSharedfpIndex<2, 4, 1>}}, - {{ &setMatrixSharedfpIndex<3, 1, 0>, &setMatrixSharedfpIndex<3, 1, 1>}, { &setMatrixSharedfpIndex<3, 2, 0>, &setMatrixSharedfpIndex<3, 2, 1>}, { &setMatrixSharedfpIndex<3, 3, 0>, &setMatrixSharedfpIndex<3, 3, 1>}, { &setMatrixSharedfpIndex<3, 4, 0>, &setMatrixSharedfpIndex<3, 4, 1>}}, - {{ &setMatrixSharedfpIndex<4, 1, 0>, &setMatrixSharedfpIndex<4, 1, 1>}, { &setMatrixSharedfpIndex<4, 2, 0>, &setMatrixSharedfpIndex<4, 2, 1>}, { &setMatrixSharedfpIndex<4, 3, 0>, &setMatrixSharedfpIndex<4, 3, 1>}, { &setMatrixSharedfpIndex<4, 4, 0>, &setMatrixSharedfpIndex<4, 4, 1>}}, - }, - }, - }, - { - { - { - {{ &setMatrixvpIndexArray<1, 1, 0>, &setMatrixvpIndexArray<1, 1, 1>}, { &setMatrixvpIndexArray<1, 2, 0>, &setMatrixvpIndexArray<1, 2, 1>}, { &setMatrixvpIndexArray<1, 3, 0>, &setMatrixvpIndexArray<1, 3, 1>}, { &setMatrixvpIndexArray<1, 4, 0>, &setMatrixvpIndexArray<1, 4, 1>}}, - {{ &setMatrixvpIndexArray<2, 1, 0>, &setMatrixvpIndexArray<2, 1, 1>}, { &setMatrixvpIndexArray<2, 2, 0>, &setMatrixvpIndexArray<2, 2, 1>}, { &setMatrixvpIndexArray<2, 3, 0>, &setMatrixvpIndexArray<2, 3, 1>}, { &setMatrixvpIndexArray<2, 4, 0>, &setMatrixvpIndexArray<2, 4, 1>}}, - {{ &setMatrixvpIndexArray<3, 1, 0>, &setMatrixvpIndexArray<3, 1, 1>}, { &setMatrixvpIndexArray<3, 2, 0>, &setMatrixvpIndexArray<3, 2, 1>}, { &setMatrixvpIndexArray<3, 3, 0>, &setMatrixvpIndexArray<3, 3, 1>}, { &setMatrixvpIndexArray<3, 4, 0>, &setMatrixvpIndexArray<3, 4, 1>}}, - {{ &setMatrixvpIndexArray<4, 1, 0>, &setMatrixvpIndexArray<4, 1, 1>}, { &setMatrixvpIndexArray<4, 2, 0>, &setMatrixvpIndexArray<4, 2, 1>}, { &setMatrixvpIndexArray<4, 3, 0>, &setMatrixvpIndexArray<4, 3, 1>}, { &setMatrixvpIndexArray<4, 4, 0>, &setMatrixvpIndexArray<4, 4, 1>}}, - }, - { - {{ &setMatrixfpIndexArray<1, 1, 0>, &setMatrixfpIndexArray<1, 1, 1>}, { &setMatrixfpIndexArray<1, 2, 0>, &setMatrixfpIndexArray<1, 2, 1>}, { &setMatrixfpIndexArray<1, 3, 0>, &setMatrixfpIndexArray<1, 3, 1>}, { &setMatrixfpIndexArray<1, 4, 0>, &setMatrixfpIndexArray<1, 4, 1>}}, - {{ &setMatrixfpIndexArray<2, 1, 0>, &setMatrixfpIndexArray<2, 1, 1>}, { &setMatrixfpIndexArray<2, 2, 0>, &setMatrixfpIndexArray<2, 2, 1>}, { &setMatrixfpIndexArray<2, 3, 0>, &setMatrixfpIndexArray<2, 3, 1>}, { &setMatrixfpIndexArray<2, 4, 0>, &setMatrixfpIndexArray<2, 4, 1>}}, - {{ &setMatrixfpIndexArray<3, 1, 0>, &setMatrixfpIndexArray<3, 1, 1>}, { &setMatrixfpIndexArray<3, 2, 0>, &setMatrixfpIndexArray<3, 2, 1>}, { &setMatrixfpIndexArray<3, 3, 0>, &setMatrixfpIndexArray<3, 3, 1>}, { &setMatrixfpIndexArray<3, 4, 0>, &setMatrixfpIndexArray<3, 4, 1>}}, - {{ &setMatrixfpIndexArray<4, 1, 0>, &setMatrixfpIndexArray<4, 1, 1>}, { &setMatrixfpIndexArray<4, 2, 0>, &setMatrixfpIndexArray<4, 2, 1>}, { &setMatrixfpIndexArray<4, 3, 0>, &setMatrixfpIndexArray<4, 3, 1>}, { &setMatrixfpIndexArray<4, 4, 0>, &setMatrixfpIndexArray<4, 4, 1>}}, - }, - }, - { //should be shared - { - {{ &setMatrixSharedvpIndexArray<1, 1, 0>, &setMatrixSharedvpIndexArray<1, 1, 1>}, { &setMatrixSharedvpIndexArray<1, 2, 0>, &setMatrixSharedvpIndexArray<1, 2, 1>}, { &setMatrixSharedvpIndexArray<1, 3, 0>, &setMatrixSharedvpIndexArray<1, 3, 1>}, { &setMatrixSharedvpIndexArray<1, 4, 0>, &setMatrixSharedvpIndexArray<1, 4, 1>}}, - {{ &setMatrixSharedvpIndexArray<2, 1, 0>, &setMatrixSharedvpIndexArray<2, 1, 1>}, { &setMatrixSharedvpIndexArray<2, 2, 0>, &setMatrixSharedvpIndexArray<2, 2, 1>}, { &setMatrixSharedvpIndexArray<2, 3, 0>, &setMatrixSharedvpIndexArray<2, 3, 1>}, { &setMatrixSharedvpIndexArray<2, 4, 0>, &setMatrixSharedvpIndexArray<2, 4, 1>}}, - {{ &setMatrixSharedvpIndexArray<3, 1, 0>, &setMatrixSharedvpIndexArray<3, 1, 1>}, { &setMatrixSharedvpIndexArray<3, 2, 0>, &setMatrixSharedvpIndexArray<3, 2, 1>}, { &setMatrixSharedvpIndexArray<3, 3, 0>, &setMatrixSharedvpIndexArray<3, 3, 1>}, { &setMatrixSharedvpIndexArray<3, 4, 0>, &setMatrixSharedvpIndexArray<3, 4, 1>}}, - {{ &setMatrixSharedvpIndexArray<4, 1, 0>, &setMatrixSharedvpIndexArray<4, 1, 1>}, { &setMatrixSharedvpIndexArray<4, 2, 0>, &setMatrixSharedvpIndexArray<4, 2, 1>}, { &setMatrixSharedvpIndexArray<4, 3, 0>, &setMatrixSharedvpIndexArray<4, 3, 1>}, { &setMatrixSharedvpIndexArray<4, 4, 0>, &setMatrixSharedvpIndexArray<4, 4, 1>}}, - }, - { - {{ &setMatrixSharedfpIndexArray<1, 1, 0>, &setMatrixSharedfpIndexArray<1, 1, 1>}, { &setMatrixSharedfpIndexArray<1, 2, 0>, &setMatrixSharedfpIndexArray<1, 2, 1>}, { &setMatrixSharedfpIndexArray<1, 3, 0>, &setMatrixSharedfpIndexArray<1, 3, 1>}, { &setMatrixSharedfpIndexArray<1, 4, 0>, &setMatrixSharedfpIndexArray<1, 4, 1>}}, - {{ &setMatrixSharedfpIndexArray<2, 1, 0>, &setMatrixSharedfpIndexArray<2, 1, 1>}, { &setMatrixSharedfpIndexArray<2, 2, 0>, &setMatrixSharedfpIndexArray<2, 2, 1>}, { &setMatrixSharedfpIndexArray<2, 3, 0>, &setMatrixSharedfpIndexArray<2, 3, 1>}, { &setMatrixSharedfpIndexArray<2, 4, 0>, &setMatrixSharedfpIndexArray<2, 4, 1>}}, - {{ &setMatrixSharedfpIndexArray<3, 1, 0>, &setMatrixSharedfpIndexArray<3, 1, 1>}, { &setMatrixSharedfpIndexArray<3, 2, 0>, &setMatrixSharedfpIndexArray<3, 2, 1>}, { &setMatrixSharedfpIndexArray<3, 3, 0>, &setMatrixSharedfpIndexArray<3, 3, 1>}, { &setMatrixSharedfpIndexArray<3, 4, 0>, &setMatrixSharedfpIndexArray<3, 4, 1>}}, - {{ &setMatrixSharedfpIndexArray<4, 1, 0>, &setMatrixSharedfpIndexArray<4, 1, 1>}, { &setMatrixSharedfpIndexArray<4, 2, 0>, &setMatrixSharedfpIndexArray<4, 2, 1>}, { &setMatrixSharedfpIndexArray<4, 3, 0>, &setMatrixSharedfpIndexArray<4, 3, 1>}, { &setMatrixSharedfpIndexArray<4, 4, 0>, &setMatrixSharedfpIndexArray<4, 4, 1>}}, - }, - }, - } - }; - -_cgSetArrayIndexFunction getVectorTypeIndexSetterFunction( unsigned short a, unsigned short b, unsigned short c, unsigned short d ) -{ - return setVectorTypeIndex[a][b][c][d]; -} - -_cgSetArrayIndexFunction getMatrixTypeIndexSetterFunction( unsigned short a, unsigned short b, unsigned short c, unsigned short d, unsigned short e, unsigned short f ) -{ - return setMatrixTypeIndex[a][b][c][d][e][f]; -} - -static void _RGLBindTextureInternal( jsTextureImageUnit *unit, GLuint name) -{ - PSGLcontext* LContext = _CurrentContext; - jsTexture *texture = NULL; - if ( name ) - { - _RGLTexNameSpaceCreateNameLazy( &LContext->textureNameSpace, name ); - texture = ( jsTexture * )LContext->textureNameSpace.data[name]; - texture->target = GL_TEXTURE_2D; - } - - unit->bound2D = name; - - unit->currentTexture = _RGLGetCurrentTexture( unit, GL_TEXTURE_2D ); - LContext->needValidate |= PSGL_VALIDATE_TEXTURES_USED; -} - -static void setSamplerfp( CgRuntimeParameter*ptr, const void*v, int ) -{ - _CGprogram *program = (( CgRuntimeParameter* )ptr )->program; - const CgParameterResource *parameterResource = _RGLGetParameterResource( program, (( CgRuntimeParameter* )ptr )->parameterEntry ); - - if ( v ) - *( GLuint* )ptr->pushBufferPointer = *( GLuint* )v; - else - { - jsTextureImageUnit *unit = _CurrentContext->TextureImageUnits + ( parameterResource->resource - CG_TEXUNIT0 ); - _RGLBindTextureInternal( unit, *( GLuint* )ptr->pushBufferPointer); - } -} - -static void setSamplervp( CgRuntimeParameter*ptr, const void*v, int ) -{ - _CGprogram *program = (( CgRuntimeParameter* )ptr )->program; - const CgParameterResource *parameterResource = _RGLGetParameterResource( program, (( CgRuntimeParameter* )ptr )->parameterEntry ); - - if ( v ) - { - *( GLuint* )ptr->pushBufferPointer = *( GLuint* )v; - } - else - { - GLuint unit = parameterResource->resource - CG_TEXUNIT0; - GLuint name = *( GLuint* )ptr->pushBufferPointer; - PSGLcontext *LContext = _CurrentContext; - jsTexture *texture = NULL; - - if ( name && (name < LContext->textureNameSpace.capacity) ) - texture = ( jsTexture * )LContext->textureNameSpace.data[name]; - - LContext->VertexTextureImages[unit] = texture; - LContext->needValidate |= PSGL_VALIDATE_VERTEX_TEXTURES_USED; - } -} - -static void _RGLCreatePushBuffer( _CGprogram *program ) -{ - int bufferSize = 0; - int programPushBufferPointersSize = 0; - int extraStorageInWords = 0; - int offsetCount = 0; - int samplerCount = 0; - int profileIndex = ( program->header.profile == CG_PROFILE_SCE_FP_TYPEB || - program->header.profile == CG_PROFILE_SCE_FP_RSX ) ? FRAGMENT_PROFILE_INDEX : VERTEX_PROFILE_INDEX; - - bool hasSharedParams = false; - int arrayCount = 1; - for ( int i = 0;i < program->rtParametersCount;i++ ) - { - const CgParameterEntry *parameterEntry = program->parametersEntries + i; - - if (( parameterEntry->flags & CGP_STRUCTURE ) || ( parameterEntry->flags & CGP_UNROLLED ) ) - { - arrayCount = 1; - continue; - } - - if (( parameterEntry->flags & CGPF_REFERENCED ) ) - { - if ( parameterEntry->flags & CGP_ARRAY ) - { - const CgParameterArray *parameterArray = _RGLGetParameterArray( program, parameterEntry ); - arrayCount = _RGLGetSizeofSubArray( parameterArray->dimensions, parameterArray->dimensionCount ); - continue; - } - if (( parameterEntry->flags & CGPV_MASK ) == CGPV_UNIFORM ) - { - const CgParameterResource *parameterResource = _RGLGetParameterResource( program, parameterEntry ); - if ( parameterResource->type >= CG_SAMPLER1D && parameterResource->type <= CG_SAMPLERCUBE ) - { - offsetCount += arrayCount; - samplerCount += arrayCount; - } - else if ( profileIndex == VERTEX_PROFILE_INDEX ) - { - if ( parameterResource->type == CGP_SCF_BOOL ) - { - } - else if ( !( parameterEntry->flags & CGPF_SHARED ) ) - { - int registerStride = isMatrix(( CGtype )parameterResource->type ) ? _RGLGetTypeRowCount(( CGtype )parameterResource->type ) : 1; - if ( parameterEntry->flags & CGP_CONTIGUOUS ) - bufferSize += 3 + 4 * arrayCount * registerStride; - else - { - programPushBufferPointersSize += arrayCount; - int resourceIndex = parameterResource->resource; - int referencedSize = 3 + 4 * registerStride; - int notReferencedSize = 4 * registerStride; - for ( int j = 0;j < arrayCount;j++, resourceIndex += registerStride ) - { - if ( program->resources[resourceIndex] != 0xffff ) - bufferSize += referencedSize; - else - extraStorageInWords += notReferencedSize; - } - } - } - else - { - hasSharedParams = true; - if ( !( parameterEntry->flags & CGP_CONTIGUOUS ) ) - { - programPushBufferPointersSize += arrayCount; - } - } - } - else - { - int registerStride = isMatrix(( CGtype )parameterResource->type ) ? _RGLGetTypeRowCount(( CGtype )parameterResource->type ) : 1; - if ( !( parameterEntry->flags & CGPF_SHARED ) ) - { - extraStorageInWords += 4 * arrayCount * registerStride; - } - else - { - hasSharedParams = true; - unsigned short *resource = program->resources + parameterResource->resource; - for ( int j = 0;j < arrayCount*registerStride;j++ ) - { - resource++; - unsigned short count = *resource++; - bufferSize += 24 * count; - resource += count; - } - } - } - } - } - arrayCount = 1; - } - - if (( profileIndex == FRAGMENT_PROFILE_INDEX ) && ( hasSharedParams ) ) - bufferSize += 8 + 3 + 2; - - bufferSize = _RGLPad( bufferSize, 4 ); - - unsigned int storageSizeInWords = bufferSize + extraStorageInWords; - if ( storageSizeInWords ) - program->memoryBlock = ( unsigned int* )memalign( 16, storageSizeInWords * 4 ); - else - program->memoryBlock = NULL; - - program->samplerCount = samplerCount; - if ( samplerCount ) - { - program->samplerValuesLocation = ( GLuint* )malloc( samplerCount * sizeof( GLuint ) ); - program->samplerIndices = ( GLuint* )malloc( samplerCount * sizeof( GLuint ) ); - program->samplerUnits = ( GLuint* )malloc( samplerCount * sizeof( GLuint ) ); - } - else - { - program->samplerValuesLocation = NULL; - program->samplerIndices = NULL; - program->samplerUnits = NULL; - } - - GLuint *samplerValuesLocation = program->samplerValuesLocation; - GLuint *samplerIndices = program->samplerIndices; - GLuint *samplerUnits = program->samplerUnits; - - if ( programPushBufferPointersSize ) - program->constantPushBufferPointers = ( unsigned int** )malloc( programPushBufferPointersSize * 4 ); - else - program->constantPushBufferPointers = NULL; - - uint32_t *RGLCurrent = ( uint32_t * )program->memoryBlock; - program->constantPushBuffer = ( bufferSize > 0 ) ? ( unsigned int * )RGLCurrent : NULL; - unsigned int **programPushBuffer = program->constantPushBufferPointers; - program->constantPushBufferWordSize = bufferSize; - GLuint *currentStorage = ( GLuint * )( RGLCurrent + bufferSize ); - - arrayCount = 1; - const CgParameterEntry *containerEntry = NULL; - for ( int i = 0;i < program->rtParametersCount;i++ ) - { - CgRuntimeParameter *rtParameter = program->runtimeParameters + i; - const CgParameterEntry *parameterEntry = program->parametersEntries + i; - if ( containerEntry == NULL ) - containerEntry = parameterEntry; - - rtParameter->samplerSetter = _cgRaiseInvalidParamIndex; - rtParameter->setterIndex = _cgRaiseInvalidParamIndex; - rtParameter->setterrIndex = _cgRaiseNotMatrixParamIndex; - rtParameter->settercIndex = _cgRaiseNotMatrixParamIndex; - - CGparameter id = ( CGparameter )_RGLCreateName( &_CurrentContext->cgParameterNameSpace, ( void* )rtParameter ); - if ( !id ) - break; - - rtParameter->id = id; - rtParameter->parameterEntry = parameterEntry; - rtParameter->program = program; - - if (( parameterEntry->flags & CGP_STRUCTURE ) || ( parameterEntry->flags & CGP_UNROLLED ) ) - { - arrayCount = 1; - containerEntry = NULL; - continue; - } - - if ( parameterEntry->flags & CGPF_REFERENCED ) - { - if ( parameterEntry->flags & CGP_ARRAY ) - { - const CgParameterArray *parameterArray = _RGLGetParameterArray( program, parameterEntry ); - arrayCount = _RGLGetSizeofSubArray( parameterArray->dimensions, parameterArray->dimensionCount ); - continue; - } - if (( parameterEntry->flags & CGPV_MASK ) == CGPV_UNIFORM ) - { - rtParameter->glType = GL_NONE; - const CgParameterResource *parameterResource = _RGLGetParameterResource( program, parameterEntry ); - if ( parameterResource->type >= CG_SAMPLER1D && parameterResource->type <= CG_SAMPLERCUBE ) - { - rtParameter->pushBufferPointer = samplerValuesLocation; - - *samplerValuesLocation = 0; - samplerValuesLocation++; - - *samplerIndices = i; - samplerIndices++; - *samplerUnits = parameterResource->resource - CG_TEXUNIT0; - samplerUnits++; - - if ( profileIndex == VERTEX_PROFILE_INDEX ) - { - rtParameter->setterIndex = _cgIgnoreSetParamIndex; - rtParameter->samplerSetter = setSamplervp; - } - else - { - rtParameter->samplerSetter = setSamplerfp; - } - rtParameter->glType = _RGLCgGetSamplerGLTypeFromCgType(( CGtype )( parameterResource->type ) ); - } - else - { - if ( profileIndex == VERTEX_PROFILE_INDEX ) - { - if ( parameterResource->type == CGP_SCF_BOOL ) - { - } - else if ( !( parameterEntry->flags & CGPF_SHARED ) ) - { - int registerStride = isMatrix(( CGtype )parameterResource->type ) ? _RGLGetTypeRowCount(( CGtype )parameterResource->type ) : 1; - int registerCount = arrayCount * registerStride; - if ( parameterEntry->flags & CGP_CONTIGUOUS ) - { - memset( RGLCurrent, 0, 4*( 4*registerCount + 3 ) ); - GCM_FUNC_BUFFERED( cellGcmSetVertexProgramParameterBlock, RGLCurrent, parameterResource->resource, registerCount, ( float* )RGLCurrent ); - rtParameter->pushBufferPointer = RGLCurrent - 4 * registerCount; - } - else - { - rtParameter->pushBufferPointer = programPushBuffer; - int resourceIndex = parameterResource->resource; - for ( int j = 0;j < arrayCount;j++, resourceIndex += registerStride ) - { - if ( program->resources[resourceIndex] != 0xffff ) - { - memset( RGLCurrent, 0, 4*( 4*registerStride + 3 ) ); - GCM_FUNC_BUFFERED( cellGcmSetVertexProgramParameterBlock, RGLCurrent, program->resources[resourceIndex], registerStride, ( float* )RGLCurrent ); - *( programPushBuffer++ ) = ( unsigned int* )( RGLCurrent - 4 * registerStride ); - } - else - { - *( programPushBuffer++ ) = ( unsigned int* )currentStorage; - currentStorage += 4 * registerStride; - } - } - } - } - } - else - { - if ( parameterEntry->flags & CGPF_SHARED ) - { - rtParameter->pushBufferPointer = NULL; - } - else - { - int registerStride = isMatrix(( CGtype )parameterResource->type ) ? _RGLGetTypeRowCount(( CGtype )parameterResource->type ) : 1; - int registerCount = arrayCount * registerStride; - rtParameter->pushBufferPointer = currentStorage; - currentStorage += 4 * registerCount; - } - } - - switch ( parameterResource->type ) - { - case CG_FLOAT: - case CG_FLOAT1: case CG_FLOAT2: case CG_FLOAT3: case CG_FLOAT4: - { - unsigned int floatCount = _RGLCountFloatsInCgType(( CGtype )parameterResource->type ); - rtParameter->setterIndex = setVectorTypeIndex[( containerEntry->flags&CGP_ARRAY ) ? 1 : 0][( containerEntry->flags&CGPF_SHARED ) ? 1 : 0][profileIndex][floatCount - 1]; - } - break; - case CG_FLOAT1x1: case CG_FLOAT1x2: case CG_FLOAT1x3: case CG_FLOAT1x4: - case CG_FLOAT2x1: case CG_FLOAT2x2: case CG_FLOAT2x3: case CG_FLOAT2x4: - case CG_FLOAT3x1: case CG_FLOAT3x2: case CG_FLOAT3x3: case CG_FLOAT3x4: - case CG_FLOAT4x1: case CG_FLOAT4x2: case CG_FLOAT4x3: case CG_FLOAT4x4: - rtParameter->setterrIndex = setMatrixTypeIndex[( containerEntry->flags&CGP_ARRAY ) ? 1 : 0][( containerEntry->flags&CGPF_SHARED ) ? 1 : 0][profileIndex][_RGLGetTypeRowCount(( CGtype )parameterResource->type ) - 1][_RGLGetTypeColCount(( CGtype )parameterResource->type ) - 1][ROW_MAJOR]; - rtParameter->settercIndex = setMatrixTypeIndex[( containerEntry->flags&CGP_ARRAY ) ? 1 : 0][( containerEntry->flags&CGPF_SHARED ) ? 1 : 0][profileIndex][_RGLGetTypeRowCount(( CGtype )parameterResource->type ) - 1][_RGLGetTypeColCount(( CGtype )parameterResource->type ) - 1][COL_MAJOR]; - break; - case CG_SAMPLER1D: case CG_SAMPLER2D: case CG_SAMPLER3D: case CG_SAMPLERRECT: case CG_SAMPLERCUBE: - break; - case CGP_SCF_BOOL: - break; - case CG_HALF: - case CG_HALF1: case CG_HALF2: case CG_HALF3: case CG_HALF4: - case CG_INT: - case CG_INT1: case CG_INT2: case CG_INT3: case CG_INT4: - case CG_BOOL: - case CG_BOOL1: case CG_BOOL2: case CG_BOOL3: case CG_BOOL4: - case CG_FIXED: - case CG_FIXED1: case CG_FIXED2: case CG_FIXED3: case CG_FIXED4: - { - unsigned int floatCount = _RGLCountFloatsInCgType(( CGtype )parameterResource->type ); - rtParameter->setterIndex = setVectorTypeIndex[( containerEntry->flags&CGP_ARRAY ) ? 1 : 0][( containerEntry->flags&CGPF_SHARED ) ? 1 : 0][profileIndex][floatCount - 1]; - } - break; - case CG_HALF1x1: case CG_HALF1x2: case CG_HALF1x3: case CG_HALF1x4: - case CG_HALF2x1: case CG_HALF2x2: case CG_HALF2x3: case CG_HALF2x4: - case CG_HALF3x1: case CG_HALF3x2: case CG_HALF3x3: case CG_HALF3x4: - case CG_HALF4x1: case CG_HALF4x2: case CG_HALF4x3: case CG_HALF4x4: - case CG_INT1x1: case CG_INT1x2: case CG_INT1x3: case CG_INT1x4: - case CG_INT2x1: case CG_INT2x2: case CG_INT2x3: case CG_INT2x4: - case CG_INT3x1: case CG_INT3x2: case CG_INT3x3: case CG_INT3x4: - case CG_INT4x1: case CG_INT4x2: case CG_INT4x3: case CG_INT4x4: - case CG_BOOL1x1: case CG_BOOL1x2: case CG_BOOL1x3: case CG_BOOL1x4: - case CG_BOOL2x1: case CG_BOOL2x2: case CG_BOOL2x3: case CG_BOOL2x4: - case CG_BOOL3x1: case CG_BOOL3x2: case CG_BOOL3x3: case CG_BOOL3x4: - case CG_BOOL4x1: case CG_BOOL4x2: case CG_BOOL4x3: case CG_BOOL4x4: - case CG_FIXED1x1: case CG_FIXED1x2: case CG_FIXED1x3: case CG_FIXED1x4: - case CG_FIXED2x1: case CG_FIXED2x2: case CG_FIXED2x3: case CG_FIXED2x4: - case CG_FIXED3x1: case CG_FIXED3x2: case CG_FIXED3x3: case CG_FIXED3x4: - case CG_FIXED4x1: case CG_FIXED4x2: case CG_FIXED4x3: case CG_FIXED4x4: - rtParameter->setterrIndex = setMatrixTypeIndex[( containerEntry->flags&CGP_ARRAY ) ? 1 : 0][( containerEntry->flags&CGPF_SHARED ) ? 1 : 0][profileIndex][_RGLGetTypeRowCount(( CGtype )parameterResource->type ) - 1][_RGLGetTypeColCount(( CGtype )parameterResource->type ) - 1][ROW_MAJOR]; - rtParameter->settercIndex = setMatrixTypeIndex[( containerEntry->flags&CGP_ARRAY ) ? 1 : 0][( containerEntry->flags&CGPF_SHARED ) ? 1 : 0][profileIndex][_RGLGetTypeRowCount(( CGtype )parameterResource->type ) - 1][_RGLGetTypeColCount(( CGtype )parameterResource->type ) - 1][COL_MAJOR]; - break; - case CG_STRING: - break; - default: - break; - } - } - } - } - else - { - if (( parameterEntry->flags & CGPV_MASK ) == CGPV_UNIFORM ) - { - if ( parameterEntry->flags & CGP_ARRAY ) - continue; - - const CgParameterResource *parameterResource = _RGLGetParameterResource( program, parameterEntry ); - switch ( parameterResource->type ) - { - case CG_FLOAT: - case CG_FLOAT1: case CG_FLOAT2: case CG_FLOAT3: case CG_FLOAT4: - rtParameter->setterIndex = _cgIgnoreSetParamIndex; - break; - case CG_FLOAT1x1: case CG_FLOAT1x2: case CG_FLOAT1x3: case CG_FLOAT1x4: - case CG_FLOAT2x1: case CG_FLOAT2x2: case CG_FLOAT2x3: case CG_FLOAT2x4: - case CG_FLOAT3x1: case CG_FLOAT3x2: case CG_FLOAT3x3: case CG_FLOAT3x4: - case CG_FLOAT4x1: case CG_FLOAT4x2: case CG_FLOAT4x3: case CG_FLOAT4x4: - rtParameter->setterrIndex = _cgIgnoreSetParamIndex; - rtParameter->settercIndex = _cgIgnoreSetParamIndex; - break; - case CG_SAMPLER1D: case CG_SAMPLER2D: case CG_SAMPLER3D: case CG_SAMPLERRECT: case CG_SAMPLERCUBE: - rtParameter->samplerSetter = _cgIgnoreSetParamIndex; - break; - case CGP_SCF_BOOL: - break; - case CG_HALF: - case CG_HALF1: case CG_HALF2: case CG_HALF3: case CG_HALF4: - case CG_INT: - case CG_INT1: case CG_INT2: case CG_INT3: case CG_INT4: - case CG_BOOL: - case CG_BOOL1: case CG_BOOL2: case CG_BOOL3: case CG_BOOL4: - case CG_FIXED: - case CG_FIXED1: case CG_FIXED2: case CG_FIXED3: case CG_FIXED4: - rtParameter->setterIndex = _cgIgnoreSetParamIndex; - break; - case CG_HALF1x1: case CG_HALF1x2: case CG_HALF1x3: case CG_HALF1x4: - case CG_HALF2x1: case CG_HALF2x2: case CG_HALF2x3: case CG_HALF2x4: - case CG_HALF3x1: case CG_HALF3x2: case CG_HALF3x3: case CG_HALF3x4: - case CG_HALF4x1: case CG_HALF4x2: case CG_HALF4x3: case CG_HALF4x4: - case CG_INT1x1: case CG_INT1x2: case CG_INT1x3: case CG_INT1x4: - case CG_INT2x1: case CG_INT2x2: case CG_INT2x3: case CG_INT2x4: - case CG_INT3x1: case CG_INT3x2: case CG_INT3x3: case CG_INT3x4: - case CG_INT4x1: case CG_INT4x2: case CG_INT4x3: case CG_INT4x4: - case CG_BOOL1x1: case CG_BOOL1x2: case CG_BOOL1x3: case CG_BOOL1x4: - case CG_BOOL2x1: case CG_BOOL2x2: case CG_BOOL2x3: case CG_BOOL2x4: - case CG_BOOL3x1: case CG_BOOL3x2: case CG_BOOL3x3: case CG_BOOL3x4: - case CG_BOOL4x1: case CG_BOOL4x2: case CG_BOOL4x3: case CG_BOOL4x4: - case CG_FIXED1x1: case CG_FIXED1x2: case CG_FIXED1x3: case CG_FIXED1x4: - case CG_FIXED2x1: case CG_FIXED2x2: case CG_FIXED2x3: case CG_FIXED2x4: - case CG_FIXED3x1: case CG_FIXED3x2: case CG_FIXED3x3: case CG_FIXED3x4: - case CG_FIXED4x1: case CG_FIXED4x2: case CG_FIXED4x3: case CG_FIXED4x4: - rtParameter->setterrIndex = _cgIgnoreSetParamIndex; - rtParameter->settercIndex = _cgIgnoreSetParamIndex; - break; - case CG_STRING: - break; - default: - break; - } - } - } - arrayCount = 1; - containerEntry = NULL; - } - - if ( bufferSize > 0 ) - { - int nopCount = ( program->constantPushBuffer + bufferSize ) - ( unsigned int * )RGLCurrent; - GCM_FUNC_BUFFERED( cellGcmSetNopCommand, RGLCurrent, nopCount ); - } -} - -static int _RGLGenerateProgram( _CGprogram *program, int profileIndex, const CgProgramHeader *programHeader, const void *ucode, const CgParameterTableHeader *parameterHeader, - const CgParameterEntry *parameterEntries, const char *stringTable, const float *defaultValues ) -{ - CGprofile profile = ( CGprofile )programHeader->profile; - - int need_swapping = 0; - - if ( profile == ( CGprofile )7005 ) - profile = CG_PROFILE_SCE_VP_RSX; - if ( profile == ( CGprofile )7006 ) - profile = CG_PROFILE_SCE_FP_RSX; - - if (( profile != CG_PROFILE_SCE_FP_TYPEB ) && ( profile != CG_PROFILE_SCE_VP_TYPEB ) && - ( profile != CG_PROFILE_SCE_FP_RSX ) && ( profile != CG_PROFILE_SCE_VP_RSX ) ) - { - need_swapping = 1; - } - - int invalidProfile = 0; - switch ( ENDIAN_32( profile, need_swapping ) ) - { - case CG_PROFILE_SCE_VP_TYPEB: - if ( profileIndex != VERTEX_PROFILE_INDEX ) invalidProfile = 1; - break; - case CG_PROFILE_SCE_FP_TYPEB: - if ( profileIndex != FRAGMENT_PROFILE_INDEX ) invalidProfile = 1; - break; - case CG_PROFILE_SCE_VP_RSX: - if ( profileIndex != VERTEX_PROFILE_INDEX ) invalidProfile = 1; - break; - case CG_PROFILE_SCE_FP_RSX: - if ( profileIndex != FRAGMENT_PROFILE_INDEX ) invalidProfile = 1; - break; - default: - invalidProfile = 1; - break; - } - if ( invalidProfile ) - { - _RGLCgRaiseError( CG_UNKNOWN_PROFILE_ERROR ); - return 0; - } - - memcpy( &program->header, programHeader, sizeof( program->header ) ); - - program->ucode = ucode; - program->loadProgramId = GMM_ERROR; - program->loadProgramOffset = 0; - - size_t parameterSize = parameterHeader->entryCount * sizeof( CgRuntimeParameter ); - void *memoryBlock; - if ( parameterSize ) - memoryBlock = memalign( 16, parameterSize ); - else - memoryBlock = NULL; - - program->rtParametersCount = parameterHeader->entryCount; - program->runtimeParameters = ( CgRuntimeParameter* )memoryBlock; - - if ( parameterEntries == NULL ) - parameterEntries = ( CgParameterEntry* )( parameterHeader + 1 ); - - program->parametersEntries = parameterEntries; - program->parameterResources = ( char* )( program->parametersEntries + program->rtParametersCount ); - program->resources = ( unsigned short* )(( char* )program->parametersEntries + ( parameterHeader->resourceTableOffset - sizeof( CgParameterTableHeader ) ) ); - program->defaultValuesIndexCount = parameterHeader->defaultValueIndexCount; - program->defaultValuesIndices = ( CgParameterDefaultValue* )(( char* )program->parametersEntries + ( parameterHeader->defaultValueIndexTableOffset - sizeof( CgParameterTableHeader ) ) ); - - program->defaultValues = NULL; - - memset( program->runtimeParameters, 0, parameterHeader->entryCount*sizeof( CgRuntimeParameter ) ); - - program->stringTable = stringTable; - program->defaultValues = defaultValues; - - _RGLCreatePushBuffer( program ); - - int count = program->defaultValuesIndexCount; - if ( profileIndex == FRAGMENT_PROFILE_INDEX) - { - for ( int i = 0; i < count;i++ ) - { - const void * __restrict pItemDefaultValues = program->defaultValues + program->defaultValuesIndices[i].defaultValueIndex; - const unsigned int * itemDefaultValues = ( const unsigned int * )pItemDefaultValues; - int index = ( int )program->defaultValuesIndices[i].entryIndex; - - CgRuntimeParameter *rtParameter = program->runtimeParameters + index; - float *hostMemoryCopy = ( float * )rtParameter->pushBufferPointer; - - if ( hostMemoryCopy ) - { - const CgParameterEntry *parameterEntry = rtParameter->parameterEntry; - int arrayCount = 1; - if ( parameterEntry->flags & CGP_ARRAY ) - { - const CgParameterArray *parameterArray = _RGLGetParameterArray( program, parameterEntry ); - arrayCount = _RGLGetSizeofSubArray( parameterArray->dimensions, parameterArray->dimensionCount ); - i++; - parameterEntry++; - } - const CgParameterResource *parameterResource = _RGLGetParameterResource( program, parameterEntry ); - unsigned short *resource = program->resources + parameterResource->resource + 1; - int registerStride = isMatrix(( CGtype )parameterResource->type ) ? _RGLGetTypeRowCount(( CGtype )parameterResource->type ) : 1; - int registerCount = arrayCount * registerStride; - int j; - for ( j = 0;j < registerCount;j++ ) - { - unsigned short embeddedConstCount = *( resource++ ); - int k; - for ( k = 0;k < embeddedConstCount;k++ ) - { - unsigned short ucodePatchOffset = *( resource )++; - unsigned int *dst = ( unsigned int* )(( char* )program->ucode + ucodePatchOffset ); - dst[0] = SWAP_IF_BIG_ENDIAN( itemDefaultValues[0] ); - dst[1] = SWAP_IF_BIG_ENDIAN( itemDefaultValues[1] ); - dst[2] = SWAP_IF_BIG_ENDIAN( itemDefaultValues[2] ); - dst[3] = SWAP_IF_BIG_ENDIAN( itemDefaultValues[3] ); - } - memcpy(( void* )hostMemoryCopy, ( void* )itemDefaultValues, sizeof( float )*4 ); - hostMemoryCopy += 4; - itemDefaultValues += 4; - resource++; - } - } - } - } - else - { - for (int i = 0; i < count; i++) - { - int index = ( int )program->defaultValuesIndices[i].entryIndex; - CgRuntimeParameter *rtParameter = program->runtimeParameters + index; - - int arrayCount = 1; - const CgParameterEntry *parameterEntry = rtParameter->parameterEntry; - bool isArray = false; - if ( parameterEntry->flags & CGP_ARRAY ) - { - isArray = true; - const CgParameterArray *parameterArray = _RGLGetParameterArray( program, parameterEntry ); - arrayCount = _RGLGetSizeofSubArray( parameterArray->dimensions, parameterArray->dimensionCount ); - parameterEntry++; - rtParameter++; - } - - if ( rtParameter->pushBufferPointer ) - { - const CgParameterResource *parameterResource = _RGLGetParameterResource( program, parameterEntry ); - const float *itemDefaultValues = program->defaultValues + program->defaultValuesIndices[i].defaultValueIndex; - int registerStride = isMatrix(( CGtype )parameterResource->type ) ? _RGLGetTypeRowCount(( CGtype )parameterResource->type ) : 1; - - if ( parameterEntry->flags & CGP_CONTIGUOUS ) - memcpy( rtParameter->pushBufferPointer, itemDefaultValues, arrayCount * registerStride *4*sizeof( float ) ); - else - { - unsigned int *pushBufferPointer = (( unsigned int * )rtParameter->pushBufferPointer ); - for ( int j = 0;j < arrayCount;j++ ) - { - unsigned int *pushBufferAddress = isArray ? ( *( unsigned int** )pushBufferPointer ) : pushBufferPointer; - memcpy( pushBufferAddress, itemDefaultValues, registerStride*4*sizeof( float ) ); - pushBufferPointer += isArray ? 1 : 3 + registerStride * 4; - itemDefaultValues += 4 * registerStride; - } - } - } - } - } - - program->loadProgramId = GMM_ERROR; - program->loadProgramOffset = 0; - if ( profileIndex == FRAGMENT_PROFILE_INDEX ) - { - int loaded = _RGLLoadFPShader( program ); - if ( ! loaded ) - { - _RGLCgRaiseError( CG_MEMORY_ALLOC_ERROR ); - return 0; - } - } - - program->programGroup = NULL; - program->programIndexInGroup = -1; - - return 1; -} - -void _RGLPlatformVertexProgramErase( void* platformProgram ) -{ - _CGprogram* program = ( _CGprogram* )platformProgram; - if ( program->runtimeParameters ) - free( program->runtimeParameters ); - - if ( program->memoryBlock ) - free( program->memoryBlock ); - - if ( program->samplerIndices ) - { - free( program->samplerValuesLocation ); - free( program->samplerIndices ); - free( program->samplerUnits ); - } - - if ( program->constantPushBufferPointers ) - free( program->constantPushBufferPointers ); -} - -void _RGLPlatformProgramErase( void* platformProgram ) -{ - _CGprogram* program = ( _CGprogram* )platformProgram; - - if ( program->loadProgramId != GMM_ERROR ) - { - if ( program->loadProgramId != GMM_ERROR ) - { - gmmFree( program->loadProgramId ); - program->loadProgramId = GMM_ERROR; - program->loadProgramOffset = 0; - } - } - - if ( program->runtimeParameters ) - { - int i; - int count = ( int )program->rtParametersCount; - for ( i = 0;i < count;i++ ) - { - _RGLEraseName( &_CurrentContext->cgParameterNameSpace, ( jsName )program->runtimeParameters[i].id ); - } - free( program->runtimeParameters ); - } - - if ( program->memoryBlock ) - free( program->memoryBlock ); - - if ( program->samplerIndices ) - { - free( program->samplerValuesLocation ); - free( program->samplerIndices ); - free( program->samplerUnits ); - } - - if ( program->constantPushBufferPointers ) - free( program->constantPushBufferPointers ); -} - - -CGbool _RGLPlatformSupportsFragmentProgram( CGprofile p ) -{ - if ( p == CG_PROFILE_SCE_FP_TYPEB ) - return CG_TRUE; - if ( CG_PROFILE_SCE_FP_RSX == p ) - return CG_TRUE; - return CG_FALSE; -} - -CGprofile _RGLPlatformGetLatestProfile( CGGLenum profile_type ) -{ - switch ( profile_type ) - { - case CG_GL_VERTEX: - return CG_PROFILE_SCE_VP_RSX; - case CG_GL_FRAGMENT: - return CG_PROFILE_SCE_FP_RSX; - default: - break; - } - return CG_PROFILE_UNKNOWN; -} - -int _RGLPlatformCopyProgram( _CGprogram* source, _CGprogram* destination ) -{ - CgParameterTableHeader parameterHeader; - parameterHeader.entryCount = source->rtParametersCount; - parameterHeader.resourceTableOffset = ( uintptr_t )(( char* )source->resources - ( char* )source->parametersEntries + sizeof( CgParameterTableHeader ) ); - parameterHeader.defaultValueIndexCount = source->defaultValuesIndexCount; - parameterHeader.defaultValueIndexTableOffset = ( uintptr_t )(( char* )source->defaultValuesIndices - ( char* )source->parametersEntries + sizeof( CgParameterTableHeader ) ); - - int profileIndex; - - switch ( source->header.profile ) - { - case CG_PROFILE_SCE_VP_TYPEB: - case CG_PROFILE_SCE_VP_RSX: - profileIndex = VERTEX_PROFILE_INDEX; - break; - - case CG_PROFILE_SCE_FP_TYPEB: - case CG_PROFILE_SCE_FP_RSX: - profileIndex = FRAGMENT_PROFILE_INDEX; - break; - default: - return 0; - } - return _RGLGenerateProgram( destination, profileIndex, &source->header, source->ucode, ¶meterHeader, source->parametersEntries, source->stringTable, source->defaultValues ); -} - -static char *_RGLPlatformBufferObjectMap( jsBufferObject* bufferObject, GLenum access ) -{ - RGLBufferObject *jsBuffer = ( RGLBufferObject * )bufferObject->platformBufferObject; - - if ( jsBuffer->mapCount++ == 0 ) - { - if ( access == GL_WRITE_ONLY ) - { - _RGLAllocateBuffer( bufferObject ); - if ( jsBuffer->pool == SURFACE_POOL_NONE ) - { - _RGLSetError( GL_OUT_OF_MEMORY ); - return NULL; - } - } - else - { - cellGcmSetInvalidateVertexCache( &_RGLState.fifo); - _RGLFifoFinish( &_RGLState.fifo ); - } - - jsBuffer->mapAccess = access; - - if ( jsBuffer->mapAccess != GL_READ_ONLY ) - { - RGLDriver *driver= (RGLDriver *)_CurrentDevice->rasterDriver; - ++driver->flushBufferCount; - } - - GmmBaseBlock *pBaseBlock = (GmmBaseBlock *)jsBuffer->bufferId; - - if (!pBaseBlock->isTile) - { - GmmBlock *pBlock = (GmmBlock *)jsBuffer->bufferId; - - pBlock->isPinned = 1; - } - } - - return gmmIdToAddress( jsBuffer->bufferId ); -} - -static jsFramebuffer* _RGLCreateFramebuffer( void ) -{ - jsFramebuffer* framebuffer = new jsPlatformFramebuffer(); - return framebuffer; -} - -static void _RGLDestroyFramebuffer( jsFramebuffer* framebuffer ) -{ - delete framebuffer; -} - -static void _RGLPlatformDestroyTexture( jsTexture* texture ) -{ - if ( !texture->referenceBuffer ) - { - RGLTexture *gcmTexture = ( RGLTexture * )texture->platformTexture; - if ( gcmTexture->pbo != NULL ) - { - _RGLFreeBufferObject( gcmTexture->pbo ); - gcmTexture->pbo = NULL; - gcmTexture->pool = SURFACE_POOL_NONE; - gcmTexture->gpuAddressId = GMM_ERROR; - gcmTexture->gpuAddressIdOffset = 0; - gcmTexture->gpuSize = 0; - } - - _RGLPlatformFreeGcmTexture( texture ); - } - _RGLTextureTouchFBOs( texture ); -} - -#ifndef __PSL1GHT__ -#include -#endif - -static void _RGLPlatformValidateTextureStage( int unit, jsTexture* texture ) -{ - if ( RGL_UNLIKELY( texture->revalidate ) ) - { - _RGLPlatformValidateTextureResources( texture ); - } - - GLboolean isCompleteCache = texture->isComplete; - - if ( RGL_LIKELY( isCompleteCache ) ) - { - RGLTexture *platformTexture = ( RGLTexture * )texture->platformTexture; - GmmBaseBlock *pBaseBlock = (GmmBaseBlock *)platformTexture->gpuAddressId; - const GLuint imageOffset = gmmAddressToOffset(pBaseBlock->address, pBaseBlock->isMain) + platformTexture->gpuAddressIdOffset; - platformTexture->gcmTexture.offset = imageOffset; - - cellGcmSetTexture( &_RGLState.fifo, unit, &platformTexture->gcmTexture); - CellGcmContextData *gcm_context = (CellGcmContextData*)&_RGLState.fifo; - cellGcmReserveMethodSizeInline(gcm_context, 11); - uint32_t *current = gcm_context->current; - current[0] = CELL_GCM_METHOD_HEADER_TEXTURE_OFFSET(unit, 8); - current[1] = CELL_GCM_METHOD_DATA_TEXTURE_OFFSET(platformTexture->gcmTexture.offset); - current[2] = CELL_GCM_METHOD_DATA_TEXTURE_FORMAT(platformTexture->gcmTexture.location, - CELL_GCM_FALSE, - CELL_GCM_TEXTURE_DIMENSION_2, - platformTexture->gcmTexture.format, - 1); - current[3] = CELL_GCM_METHOD_DATA_TEXTURE_ADDRESS( - CELL_GCM_TEXTURE_BORDER, /* wrapS */ - CELL_GCM_TEXTURE_BORDER, /* wrapT */ - CELL_GCM_TEXTURE_BORDER, /* wrapR */ - CELL_GCM_TEXTURE_UNSIGNED_REMAP_NORMAL, /* unsignedRemap */ - CELL_GCM_TEXTURE_ZFUNC_NEVER, - platformTexture->gcmMethods.address.gamma, - 0); - current[4] = CELL_GCM_METHOD_DATA_TEXTURE_CONTROL0(CELL_GCM_TRUE, - 0, /* minLOD */ - 256000, /* maxLOD */ - CELL_GCM_TEXTURE_MAX_ANISO_1); - current[5] = platformTexture->gcmTexture.remap; - current[6] = CELL_GCM_METHOD_DATA_TEXTURE_FILTER( - (platformTexture->gcmMethods.filter.bias & 0x1fff), - platformTexture->gcmMethods.filter.min, - platformTexture->gcmMethods.filter.mag, - CELL_GCM_TEXTURE_CONVOLUTION_QUINCUNX); /* filter */ - current[7] = CELL_GCM_METHOD_DATA_TEXTURE_IMAGE_RECT( - platformTexture->gcmTexture.height, - platformTexture->gcmTexture.width); - current[8] = 0; - current[9] = CELL_GCM_METHOD_HEADER_TEXTURE_CONTROL3(unit,1); - current[10] = CELL_GCM_METHOD_DATA_TEXTURE_CONTROL3( - platformTexture->gcmTexture.pitch, - 1); /* depth */ - gcm_context->current = ¤t[11]; - } - else - { - //RARCH_WARN("Texture bound to unit %d is incomplete.\n", unit); - GLuint remap = CELL_GCM_REMAP_MODE( - CELL_GCM_TEXTURE_REMAP_ORDER_XYXY, - CELL_GCM_TEXTURE_REMAP_FROM_A, - CELL_GCM_TEXTURE_REMAP_FROM_R, - CELL_GCM_TEXTURE_REMAP_FROM_G, - CELL_GCM_TEXTURE_REMAP_FROM_B, - CELL_GCM_TEXTURE_REMAP_ONE, - CELL_GCM_TEXTURE_REMAP_ZERO, - CELL_GCM_TEXTURE_REMAP_ZERO, - CELL_GCM_TEXTURE_REMAP_ZERO ); - - cellGcmSetTextureControlInline( &_RGLState.fifo, unit, CELL_GCM_FALSE, 0, 0, 0); - cellGcmSetTextureRemapInline( &_RGLState.fifo, unit, remap); - } - - -} - -static GLenum _RGLPlatformChooseInternalFormat( GLenum internalFormat ) -{ - switch ( internalFormat ) - { - case GL_ALPHA: - case GL_ALPHA4: - case GL_ALPHA8: - return RGL_ALPHA8; - case GL_RGB10: - case GL_RGB10_A2: - case GL_RGB12: - case GL_RGB16: - return RGL_FLOAT_RGBX32; - case GL_RGBA12: - case GL_RGBA16: - return RGL_FLOAT_RGBA32; - case 3: - case GL_R3_G3_B2: - case GL_RGB4: - case GL_RGB: - case GL_RGB8: - case RGL_RGBX8: - return RGL_RGBX8; - case 4: - case GL_RGBA2: - case GL_RGBA4: - case GL_RGBA8: - case GL_RGBA: - return RGL_RGBA8; - case GL_RGB5_A1: - return RGL_RGB5_A1_SCE; - case GL_RGB5: - return RGL_RGB565_SCE; - case GL_BGRA: - case RGL_BGRA8: - return RGL_BGRA8; - case GL_ARGB_SCE: - return RGL_ARGB8; - default: - return GL_INVALID_ENUM; - } - return GL_INVALID_ENUM; -} - -static void _RGLPlatformExpandInternalFormat( GLenum internalFormat, GLenum *format, GLenum *type ) -{ - switch ( internalFormat ) - { - case RGL_ALPHA8: - *format = GL_ALPHA; - *type = GL_UNSIGNED_BYTE; - break; - case RGL_ARGB8: - *format = GL_BGRA; - *type = GL_UNSIGNED_INT_8_8_8_8_REV; - break; - case RGL_RGB5_A1_SCE: - *format = GL_RGBA; - *type = GL_UNSIGNED_SHORT_1_5_5_5_REV; - break; - case RGL_RGB565_SCE: - *format = GL_RGB; - *type = GL_UNSIGNED_SHORT_5_6_5_REV; - break; - default: - return; - } -} - -static GLenum _RGLPlatformChooseInternalStorage( jsImage* image, GLenum internalFormat ) -{ - image->storageSize = 0; - - GLenum platformInternalFormat = _RGLPlatformChooseInternalFormat( internalFormat ); - - if ( platformInternalFormat == GL_INVALID_ENUM ) - return GL_INVALID_ENUM; - - image->internalFormat = platformInternalFormat; - _RGLPlatformExpandInternalFormat( platformInternalFormat, &image->format, &image->type ); - - image->storageSize = _RGLGetPixelSize(image->format, image->type) * image->width * image->height; - - return GL_NO_ERROR; -} - -static inline GLuint _RGLGetBufferObjectOrigin(GLuint buffer) -{ - PSGLcontext* LContext = _CurrentContext; - jsBufferObject *bufferObject = (jsBufferObject *)LContext->bufferObjectNameSpace.data[buffer]; - - RGLBufferObject *gcmBuffer = ( RGLBufferObject * ) & bufferObject->platformBufferObject; - return gcmBuffer->bufferId; -} - -static void _RGLSetImage( jsImage *image, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei alignment, GLenum format, GLenum type, const GLvoid *pixels ) -{ - image->width = width; - image->height = height; - image->alignment = alignment; - - image->xblk = 0; - image->yblk = 0; - - image->xstride = 0; - image->ystride = 0; - - image->format = 0; - image->type = 0; - image->internalFormat = 0; - const GLenum status = _RGLPlatformChooseInternalStorage( image, internalFormat ); - (( void )status ); - - image->data = NULL; - image->mallocData = NULL; - image->mallocStorageSize = 0; - - image->isSet = GL_TRUE; - - if ( image->xstride == 0 ) - image->xstride = _RGLGetPixelSize( image->format, image->type ); - if ( image->ystride == 0 ) - image->ystride = image->width * image->xstride; - - if ( pixels ) - { - _RGLImageAllocCPUStorage( image ); - if ( !image->data ) - return; - - jsRaster raster; - raster.format = format; - raster.type = type; - raster.width = width; - raster.height = height; - raster.data = ( void * )pixels; - - raster.xstride = _RGLGetPixelSize( raster.format, raster.type ); - raster.ystride = ( raster.width * raster.xstride + alignment - 1 ) / alignment * alignment; - - _RGLRasterToImage( &raster, image); - image->dataState = IMAGE_DATASTATE_HOST; - } - else - image->dataState = IMAGE_DATASTATE_UNSET; -} - -static GLboolean _RGLPlatformTexturePBOImage( - jsTexture* texture, - jsImage* image, - GLint internalFormat, - GLsizei width, GLsizei height, - GLenum format, GLenum type, - const GLvoid *offset ) -{ - PSGLcontext* LContext = _CurrentContext; - - RGLTexture *gcmTexture = ( RGLTexture * )texture->platformTexture; - - image->dataState = IMAGE_DATASTATE_UNSET; - if ( gcmTexture->pbo != NULL ) - _RGLPlatformDropTexture( texture ); - - _RGLSetImage( image, internalFormat, width, height, 1 /* depth */, LContext->unpackAlignment, format, type, NULL ); - - if ( LContext->PixelUnpackBuffer == 0 ) - return GL_FALSE; - - const GLuint pboPitch = _RGLPad(_RGLGetPixelSize(format, type) * width, LContext->unpackAlignment ); - if (( pboPitch&3 ) != 0 ) - { - //RARCH_WARN("PBO image pitch not a multiple of 4, using slow path.\n" ); - return GL_FALSE; - } - - GLuint gpuId = _RGLGetBufferObjectOrigin( LContext->PixelUnpackBuffer ); - GLuint gpuIdOffset = (( GLubyte* )offset - ( GLubyte* )NULL ); - - if ( gmmIdToOffset(gpuId)+gpuIdOffset & 63 ) - { - //RARCH_WARN("PBO offset not 64-byte aligned, using slow path.\n"); - return GL_FALSE; - } - - GLboolean formatOK = GL_FALSE; - switch ( internalFormat ) - { - case 4: - case GL_RGBA: - case GL_RGBA8: - if ( format == GL_RGBA && type == GL_UNSIGNED_INT_8_8_8_8 ) - formatOK = GL_TRUE; - break; - case GL_ALPHA: - case GL_ALPHA8: - if ( format == GL_ALPHA && type == GL_UNSIGNED_BYTE ) - formatOK = GL_TRUE; - break; - case GL_ARGB_SCE: - if ( format == GL_BGRA && type == GL_UNSIGNED_INT_8_8_8_8_REV ) - formatOK = GL_TRUE; - break; - default: - formatOK = GL_FALSE; - } - - if (!formatOK ) - { - //RARCH_WARN("PBO format/type requires conversion to texture internal format, using slow path.\n"); - return GL_FALSE; - } - - if (!_RGLTextureIsValid(texture)) - { - //RARCH_WARN("PBO transfering to incomplete texture, using slow path.\n"); - return GL_FALSE; - } - - RGLTextureLayout newLayout; - _RGLPlatformChooseGPUFormatAndLayout( texture, GL_TRUE, pboPitch, &newLayout ); - - jsBufferObject* bufferObject = (jsBufferObject *)LContext->bufferObjectNameSpace.data[LContext->PixelUnpackBuffer]; - if ( newLayout.pitch != 0 && !bufferObject->mapped ) - { - gcmTexture->gpuLayout = newLayout; - if ( gcmTexture->gpuAddressId != GMM_ERROR && gcmTexture->pbo == NULL ) - _RGLPlatformFreeGcmTexture( texture ); - - gcmTexture->pbo = bufferObject; - gcmTexture->gpuAddressId = gpuId; - gcmTexture->gpuAddressIdOffset = gpuIdOffset; - gcmTexture->pool = SURFACE_POOL_LINEAR; - RGLTexture *gcmTexture = ( RGLTexture * )texture->platformTexture; - // Get size of texture in GPU layout - gcmTexture->gpuSize = _RGLPad( gcmTexture->gpuLayout.baseHeight * gcmTexture->gpuLayout.pitch, 1); - ++bufferObject->refCount; - } - else - { - const GLuint bytesPerPixel = newLayout.pixelBits / 8; - - RGLSurface src; - src.source = SURFACE_SOURCE_PBO; - src.width = image->width; - src.height = image->height; - src.bpp = bytesPerPixel; - src.pitch = pboPitch; - src.format = newLayout.internalFormat; - src.pool = SURFACE_POOL_LINEAR; - src.ppuData = NULL; - src.dataId = gpuId; - src.dataIdOffset = gpuIdOffset; - - texture->revalidate |= TEXTURE_REVALIDATE_LAYOUT; - _RGLPlatformValidateTextureResources( texture ); - - RGLSurface dst; - dst.source = SURFACE_SOURCE_TEXTURE; - dst.width = image->width; - dst.height = image->height; - dst.bpp = bytesPerPixel; - dst.pitch = gcmTexture->gpuLayout.pitch; - dst.format = gcmTexture->gpuLayout.internalFormat; - dst.pool = gcmTexture->pool; - dst.ppuData = NULL; - dst.dataId = gcmTexture->gpuAddressId; - dst.dataIdOffset = gcmTexture->gpuAddressIdOffset; - - transfer_params_t transfer_params; - - transfer_params.dst_id = dst.dataId; - transfer_params.dst_id_offset = dst.dataIdOffset; - transfer_params.dst_pitch = dst.pitch ? dst.pitch : (dst.bpp * dst.width); - transfer_params.dst_x = 0; - transfer_params.dst_y = 0; - transfer_params.src_id = src.dataId; - transfer_params.src_id_offset = src.dataIdOffset; - transfer_params.src_pitch = src.pitch ? src.pitch : (src.bpp * src.width); - transfer_params.src_x = 0; - transfer_params.src_y = 0; - transfer_params.width = width; - transfer_params.height = height; - transfer_params.bpp = src.bpp; - transfer_params.fifo_ptr = &_RGLState.fifo; - - TransferDataVidToVid(&transfer_params); - } - - _RGLImageFreeCPUStorage( image ); - image->dataState = IMAGE_DATASTATE_GPU; - - texture->revalidate &= ~( TEXTURE_REVALIDATE_LAYOUT | TEXTURE_REVALIDATE_IMAGES ); - texture->revalidate |= TEXTURE_REVALIDATE_PARAMETERS; - _RGLTextureTouchFBOs( texture ); - - return GL_TRUE; -} - -static GLboolean _RGLPlatformTextureReference( jsTexture *texture, GLuint pitch, jsBufferObject *bufferObject, GLintptr offset ) -{ - RGLTexture *gcmTexture = (RGLTexture *)texture->platformTexture; - - RGLTextureLayout newLayout; - _RGLPlatformChooseGPUFormatAndLayout(texture, GL_TRUE, pitch, &newLayout); - - texture->isRenderTarget = GL_TRUE; - - if(gcmTexture->gpuAddressId != GMM_ERROR) - _RGLPlatformDestroyTexture( texture ); - - RGLBufferObject *gcmBuffer = (RGLBufferObject *)& bufferObject->platformBufferObject; - - gcmTexture->gpuLayout = newLayout; - gcmTexture->pool = gcmBuffer->pool; - gcmTexture->gpuAddressId = gcmBuffer->bufferId; - gcmTexture->gpuAddressIdOffset = offset; - gcmTexture->gpuSize = _RGLPad( newLayout.baseHeight * newLayout.pitch, 1); - - texture->revalidate &= ~(TEXTURE_REVALIDATE_LAYOUT | TEXTURE_REVALIDATE_IMAGES); - texture->revalidate |= TEXTURE_REVALIDATE_PARAMETERS; - _RGLTextureTouchFBOs(texture); - return GL_TRUE; -} - -static inline void _RGLSetColorDepthBuffers( RGLRenderTarget *rt, RGLRenderTargetEx const * const args ) -{ - CellGcmSurface * grt = &rt->gcmRenderTarget; - - rt->colorBufferCount = args->colorBufferCount; - - GLuint oldHeight; - GLuint oldyInverted; - - oldyInverted = rt->yInverted; - oldHeight = rt->gcmRenderTarget.height; - - GLuint i; - - for ( i = 0; i < args->colorBufferCount; i++ ) - { - if ( args->colorPitch[i] == 0 ) - { - grt->colorOffset[i] = 0; - grt->colorPitch[i] = 0x200; - grt->colorLocation[i] = CELL_GCM_LOCATION_LOCAL; - } - else - { - if ( args->colorId[i] != GMM_ERROR ) - { - if ( gmmIdIsMain(args->colorId[i]) ) - grt->colorLocation[i] = CELL_GCM_LOCATION_MAIN; - else - grt->colorLocation[i] = CELL_GCM_LOCATION_LOCAL; - - grt->colorOffset[i] = gmmIdToOffset(args->colorId[i]) + args->colorIdOffset[i]; - grt->colorPitch[i] = args->colorPitch[i]; - } - } - } - - for ( ; i < RGL_SETRENDERTARGET_MAXCOUNT; i++ ) - { - grt->colorOffset[i] = grt->colorOffset[0]; - grt->colorPitch[i] = grt->colorPitch[0]; - grt->colorLocation[i] = grt->colorLocation[0]; - } - - rt->yInverted = args->yInverted; - grt->x = args->xOffset; - grt->y = args->yOffset; - grt->width = args->width; - grt->height = args->height; - - if (( grt->height != oldHeight ) | ( rt->yInverted != oldyInverted ) ) - { - RGLViewportState *v = &_RGLState.state.viewport; - _RGLFifoGlViewport( v->x, v->y, v->w, v->h ); - } -} - -void _RGLFifoGlSetRenderTarget( RGLRenderTargetEx const * const args ) -{ - RGLRenderTarget *rt = &_RGLState.renderTarget; - CellGcmSurface * grt = &_RGLState.renderTarget.gcmRenderTarget; - - _RGLSetColorDepthBuffers( rt, args ); - - //set color depth formats - grt->colorFormat = CELL_GCM_SURFACE_A8R8G8B8; - grt->depthFormat = CELL_GCM_SURFACE_Z24S8; - grt->depthLocation = CELL_GCM_LOCATION_LOCAL; - grt->depthOffset = 0; - grt->depthPitch = 64; - - grt->antialias = CELL_GCM_SURFACE_CENTER_1; - - grt->type = CELL_GCM_SURFACE_PITCH; - - switch ( rt->colorBufferCount ) - { - case 0: - grt->colorTarget = CELL_GCM_SURFACE_TARGET_NONE; - break; - case 1: - grt->colorTarget = CELL_GCM_SURFACE_TARGET_1; - break; - case 2: - grt->colorTarget = CELL_GCM_SURFACE_TARGET_MRT1; - break; - case 3: - grt->colorTarget = CELL_GCM_SURFACE_TARGET_MRT2; - break; - case 4: - grt->colorTarget = CELL_GCM_SURFACE_TARGET_MRT3; - break; - default: - break; - } - - cellGcmSetSurfaceInline( &_RGLState.fifo, grt); -} - -void _RGLSetError( GLenum error ) -{ - RARCH_ERR("Error code: %d\n", error); -} - -GLAPI GLenum APIENTRY glGetError(void) -{ - if ( !_CurrentContext ) - return GL_INVALID_OPERATION; - else - { - GLenum error = _CurrentContext->error; - - _CurrentContext->error = GL_NO_ERROR; - return error; - } -} - -static inline void _RGLPushProgramPushBuffer( _CGprogram * cgprog ) -{ - RGLFifo *fifo = &_RGLState.fifo; - GLuint spaceInWords = cgprog->constantPushBufferWordSize + 4 + 32; - - if ( fifo->current + spaceInWords + 1024 > fifo->end ) - _RGLOutOfSpaceCallback( fifo, spaceInWords ); - - uint32_t padding_in_word = ( ( 0x10-(((uint32_t)_RGLState.fifo.current)&0xf))&0xf )>>2; - uint32_t padded_size = ( ((cgprog->constantPushBufferWordSize)<<2) + 0xf )&~0xf; - cellGcmSetNopCommandUnsafeInline( &_RGLState.fifo, padding_in_word); - - memcpy(_RGLState.fifo.current, cgprog->constantPushBuffer, padded_size); - _RGLState.fifo.current+=cgprog->constantPushBufferWordSize; -} - -static GLuint _RGLValidateStates( void ) -{ - PSGLcontext* LContext = _CurrentContext; - RGLDriver *driver= (RGLDriver *)_CurrentDevice->rasterDriver; - - LContext->needValidate &= PSGL_VALIDATE_ALL; - GLuint dirty = LContext->needValidate; - GLuint needValidate = LContext->needValidate; - - if ( RGL_UNLIKELY( needValidate & PSGL_VALIDATE_FRAMEBUFFER ) ) - { - _RGLValidateFramebuffer(); - - needValidate = LContext->needValidate; - } - - if ( RGL_UNLIKELY( needValidate & PSGL_VALIDATE_TEXTURES_USED ) ) - { - long unitInUseCount = LContext->BoundFragmentProgram->samplerCount; - const GLuint* unitsInUse = LContext->BoundFragmentProgram->samplerUnits; - - for ( long i = 0; i < unitInUseCount; ++i ) - { - long unit = unitsInUse[i]; - jsTexture* texture = LContext->TextureImageUnits[unit].currentTexture; - - _RGLPlatformValidateTextureStage( unit, texture ); - } - } - - if ( RGL_UNLIKELY( needValidate & PSGL_VALIDATE_VERTEX_PROGRAM ) ) - { - const void *header = LContext->BoundVertexProgram; - const _CGprogram *vs = ( const _CGprogram* ) header; - - __dcbt(vs->ucode); - __dcbt(((uint8_t*)vs->ucode)+128); - __dcbt(((uint8_t*)vs->ucode)+256); - __dcbt(((uint8_t*)vs->ucode)+384); - - CellCgbVertexProgramConfiguration conf; - conf.instructionSlot = vs->header.vertexProgram.instructionSlot; - conf.instructionCount = vs->header.instructionCount; - conf.registerCount = vs->header.vertexProgram.registerCount; - conf.attributeInputMask = vs->header.attributeInputMask; - - RGLFifo *fifo = &_RGLState.fifo; - GLuint spaceInWords = 7 + 5 * conf.instructionCount; - - if ( fifo->current + spaceInWords + 1024 > fifo->end ) - _RGLOutOfSpaceCallback( fifo, spaceInWords ); - - cellGcmSetVertexProgramLoadInline( &_RGLState.fifo, &conf, vs->ucode); - - RGLInterpolantState *s = &_RGLState.state.interpolant; - s->vertexProgramAttribMask = vs->header.vertexProgram.attributeOutputMask; - - cellGcmSetVertexAttribOutputMaskInline( &_RGLState.fifo, s->vertexProgramAttribMask & s->fragmentProgramAttribMask); - - _CGprogram *program = ( _CGprogram* )vs; - int count = program->defaultValuesIndexCount; - for ( int i = 0; i < count; i++ ) - { - const CgParameterEntry *parameterEntry = program->parametersEntries + program->defaultValuesIndices[i].entryIndex; - if (( parameterEntry->flags & CGPF_REFERENCED ) && ( parameterEntry->flags & CGPV_MASK ) == CGPV_CONSTANT ) - { - const float *itemDefaultValues = program->defaultValues + program->defaultValuesIndices[i].defaultValueIndex; - const GLfloat *value = itemDefaultValues; - const CgParameterResource *parameterResource = _RGLGetParameterResource( program, parameterEntry ); - if ( parameterResource->resource != ( unsigned short ) - 1 ) - { - switch ( parameterResource->type ) - { - case CG_FLOAT: - case CG_FLOAT1: - case CG_FLOAT2: - case CG_FLOAT3: - case CG_FLOAT4: - cellGcmSetVertexProgramParameterBlockInline( &_RGLState.fifo, parameterResource->resource, 1, value ); - break; - case CG_FLOAT4x4: - { - GLfloat v2[16]; - v2[0] = value[0];v2[1] = value[4];v2[2] = value[8];v2[3] = value[12]; - v2[4] = value[1];v2[5] = value[5];v2[6] = value[9];v2[7] = value[13]; - v2[8] = value[2];v2[9] = value[6];v2[10] = value[10];v2[11] = value[14]; - v2[12] = value[3];v2[13] = value[7];v2[14] = value[11];v2[15] = value[15]; - cellGcmSetVertexProgramParameterBlockInline( &_RGLState.fifo, parameterResource->resource, 4, v2 ); - } - break; - case CG_FLOAT3x3: - { - GLfloat v2[12]; - v2[0] = value[0];v2[1] = value[3];v2[2] = value[6];v2[3] = 0; - v2[4] = value[1];v2[5] = value[4];v2[6] = value[7];v2[7] = 0; - v2[8] = value[2];v2[9] = value[5];v2[10] = value[8];v2[11] = 0; - cellGcmSetVertexProgramParameterBlockInline( &_RGLState.fifo, parameterResource->resource, 3, v2 ); - } - break; - case CG_HALF: - case CG_HALF1: - case CG_HALF2: - case CG_HALF3: - case CG_HALF4: - case CG_INT: - case CG_INT1: - case CG_INT2: - case CG_INT3: - case CG_INT4: - case CG_BOOL: - case CG_BOOL1: - case CG_BOOL2: - case CG_BOOL3: - case CG_BOOL4: - case CG_FIXED: - case CG_FIXED1: - case CG_FIXED2: - case CG_FIXED3: - case CG_FIXED4: - cellGcmSetVertexProgramParameterBlockInline( &_RGLState.fifo, parameterResource->resource, 1, value ); - break; - case CG_HALF4x4: - case CG_INT4x4: - case CG_BOOL4x4: - case CG_FIXED4x4: - { - GLfloat v2[16]; - v2[0] = value[0];v2[1] = value[4];v2[2] = value[8];v2[3] = value[12]; - v2[4] = value[1];v2[5] = value[5];v2[6] = value[9];v2[7] = value[13]; - v2[8] = value[2];v2[9] = value[6];v2[10] = value[10];v2[11] = value[14]; - v2[12] = value[3];v2[13] = value[7];v2[14] = value[11];v2[15] = value[15]; - cellGcmSetVertexProgramParameterBlockInline( &_RGLState.fifo, parameterResource->resource, 4, v2 ); - } - break; - case CG_HALF3x3: - case CG_INT3x3: - case CG_BOOL3x3: - case CG_FIXED3x3: - { - GLfloat v2[12]; - v2[0] = value[0];v2[1] = value[3];v2[2] = value[6];v2[3] = 0; - v2[4] = value[1];v2[5] = value[4];v2[6] = value[7];v2[7] = 0; - v2[8] = value[2];v2[9] = value[5];v2[10] = value[8];v2[11] = 0; - cellGcmSetVertexProgramParameterBlockInline( &_RGLState.fifo, parameterResource->resource, 3, v2 ); - } - break; - default: - break; - } - } - } - } - - if(!(LContext->needValidate & PSGL_VALIDATE_VERTEX_CONSTANTS) && LContext->BoundVertexProgram->parentContext) - { - cellGcmSetTransformBranchBitsInline( &_RGLState.fifo, LContext->BoundVertexProgram->controlFlowBools | LContext->BoundVertexProgram->parentContext->controlFlowBoolsShared ); - - _RGLPushProgramPushBuffer( LContext->BoundVertexProgram ); - } - } - - if ( RGL_LIKELY( needValidate & PSGL_VALIDATE_VERTEX_CONSTANTS ) && LContext->BoundVertexProgram->parentContext) - { - cellGcmSetTransformBranchBitsInline( &_RGLState.fifo, LContext->BoundVertexProgram->controlFlowBools | LContext->BoundVertexProgram->parentContext->controlFlowBoolsShared ); - - _RGLPushProgramPushBuffer( LContext->BoundVertexProgram ); - } - - if ( RGL_UNLIKELY( needValidate & PSGL_VALIDATE_VERTEX_TEXTURES_USED ) ) - { - for ( int unit = 0; unit < MAX_VERTEX_TEXTURE_IMAGE_UNITS; ++unit ) - { - jsTexture *texture = LContext->VertexTextureImages[unit]; - if ( texture ) - if ( RGL_UNLIKELY( texture->revalidate ) ) - _RGLPlatformValidateTextureResources( texture ); - - cellGcmSetVertexTextureAddressInline( &_RGLState.fifo, unit, CELL_GCM_TEXTURE_WRAP, CELL_GCM_TEXTURE_WRAP); - cellGcmSetVertexTextureControlInline( &_RGLState.fifo, unit, GL_FALSE, 0, 256); - cellGcmSetVertexTextureFilterInline( &_RGLState.fifo, unit, 0); - } - } - - if ( RGL_UNLIKELY( needValidate & PSGL_VALIDATE_FRAGMENT_PROGRAM ) ) - { - _CGprogram *program = LContext->BoundFragmentProgram; - - const GLvoid *header = program; - const _CGprogram *ps = ( const _CGprogram * )header; - - CellCgbFragmentProgramConfiguration conf; - - conf.offset = gmmIdToOffset(ps->loadProgramId) + ps->loadProgramOffset; - - RGLInterpolantState *s = &_RGLState.state.interpolant; - s->fragmentProgramAttribMask |= ps->header.attributeInputMask | CELL_GCM_ATTRIB_OUTPUT_MASK_POINTSIZE; - - conf.attributeInputMask = s->vertexProgramAttribMask & s->fragmentProgramAttribMask; - conf.texCoordsInputMask = ps->header.fragmentProgram.texcoordInputMask; - conf.texCoords2D = ps->header.fragmentProgram.texcoord2d; - conf.texCoordsCentroid = ps->header.fragmentProgram.texcoordCentroid; - - int fragmentControl = ( 1 << 15 ) | ( 1 << 10 ); - fragmentControl |= ps->header.fragmentProgram.flags & CGF_DEPTHREPLACE ? 0xE : 0x0; - fragmentControl |= ps->header.fragmentProgram.flags & CGF_OUTPUTFROMH0 ? 0x00 : 0x40; - fragmentControl |= ps->header.fragmentProgram.flags & CGF_PIXELKILL ? 0x80 : 0x00; - - conf.fragmentControl = fragmentControl; - conf.registerCount = ps->header.fragmentProgram.registerCount < 2 ? 2 : ps->header.fragmentProgram.registerCount; - - uint32_t controlTxp = _CurrentContext->AllowTXPDemotion; - conf.fragmentControl &= ~CELL_GCM_MASK_SET_SHADER_CONTROL_CONTROL_TXP; - conf.fragmentControl |= controlTxp << CELL_GCM_SHIFT_SET_SHADER_CONTROL_CONTROL_TXP; - - cellGcmSetFragmentProgramLoadInline( &_RGLState.fifo, &conf); - cellGcmSetZMinMaxControlInline( &_RGLState.fifo, ( ps->header.fragmentProgram.flags & CGF_DEPTHREPLACE ) ? CELL_GCM_FALSE : CELL_GCM_TRUE, CELL_GCM_FALSE, CELL_GCM_FALSE ); - - - driver->fpLoadProgramId = program->loadProgramId; - driver->fpLoadProgramOffset = program->loadProgramOffset; - } - - if ( RGL_LIKELY(( needValidate & ~( PSGL_VALIDATE_TEXTURES_USED | - PSGL_VALIDATE_VERTEX_PROGRAM | - PSGL_VALIDATE_VERTEX_CONSTANTS | - PSGL_VALIDATE_VERTEX_TEXTURES_USED | - PSGL_VALIDATE_FRAGMENT_PROGRAM ) ) == 0 ) ) - { - LContext->needValidate = 0; - return dirty; - } - - if ( RGL_UNLIKELY( needValidate & PSGL_VALIDATE_BLENDING ) ) - { - if ((LContext->Blending || LContext->BlendingMrt[0] || LContext->BlendingMrt[1] || LContext->BlendingMrt[2])) - { - GLuint hwColor; - cellGcmSetBlendEnableInline( &_RGLState.fifo, LContext->Blending); - cellGcmSetBlendEnableMrtInline( &_RGLState.fifo, LContext->BlendingMrt[0], LContext->BlendingMrt[1], LContext->BlendingMrt[2] ); - - RGL_CALC_COLOR_LE_ARGB8( &hwColor, RGL_CLAMPF_01(LContext->BlendColor.R), RGL_CLAMPF_01(LContext->BlendColor.G), RGL_CLAMPF_01(LContext->BlendColor.B), RGL_CLAMPF_01(LContext->BlendColor.A) ); - cellGcmSetBlendColorInline( &_RGLState.fifo, hwColor, hwColor); - cellGcmSetBlendEquationInline( &_RGLState.fifo, (RGLEnum)LContext->BlendEquationRGB, (RGLEnum)LContext->BlendEquationAlpha ); - cellGcmSetBlendFuncInline( &_RGLState.fifo, (RGLEnum)LContext->BlendFactorSrcRGB, (RGLEnum)LContext->BlendFactorDestRGB, (RGLEnum)LContext->BlendFactorSrcAlpha, (RGLEnum)LContext->BlendFactorDestAlpha); - } - else - { - cellGcmSetBlendEnableInline( &_RGLState.fifo, CELL_GCM_FALSE); - cellGcmSetBlendEnableMrtInline( &_RGLState.fifo, CELL_GCM_FALSE, CELL_GCM_FALSE, CELL_GCM_FALSE ); - } - } - - if ( RGL_UNLIKELY( needValidate & PSGL_VALIDATE_SHADER_SRGB_REMAP ) ) - { - cellGcmSetFragmentProgramGammaEnableInline( &_RGLState.fifo, LContext->ShaderSRGBRemap ? CELL_GCM_TRUE : CELL_GCM_FALSE); - - LContext->needValidate &= ~PSGL_VALIDATE_SHADER_SRGB_REMAP; - } - - LContext->needValidate = 0; - return dirty; -} - -PSGLcontext *psglGetCurrentContext() -{ - return _CurrentContext; -} - -static void _RGLResetContext( PSGLcontext *LContext ) -{ - _RGLTexNameSpaceResetNames( &LContext->textureNameSpace ); - _RGLTexNameSpaceResetNames( &LContext->bufferObjectNameSpace ); - _RGLTexNameSpaceResetNames( &LContext->framebufferNameSpace ); - _RGLTexNameSpaceResetNames( &LContext->attribSetNameSpace ); - - LContext->ViewPort.X = 0; - LContext->ViewPort.Y = 0; - LContext->ViewPort.XSize = 0; - LContext->ViewPort.YSize = 0; - - LContext->ClearColor.R = 0.f; - LContext->ClearColor.G = 0.f; - LContext->ClearColor.B = 0.f; - LContext->ClearColor.A = 0.f; - - LContext->ShaderSRGBRemap = GL_FALSE; - - LContext->Blending = GL_FALSE; - LContext->BlendingMrt[0] = GL_FALSE; - LContext->BlendingMrt[1] = GL_FALSE; - LContext->BlendingMrt[2] = GL_FALSE; - LContext->BlendColor.R = 0.0f; - LContext->BlendColor.G = 0.0f; - LContext->BlendColor.B = 0.0f; - LContext->BlendColor.A = 0.0f; - LContext->BlendEquationRGB = GL_FUNC_ADD; - LContext->BlendEquationAlpha = GL_FUNC_ADD; - LContext->BlendFactorSrcRGB = GL_ONE; - LContext->BlendFactorDestRGB = GL_ZERO; - LContext->BlendFactorSrcAlpha = GL_ONE; - LContext->BlendFactorDestAlpha = GL_ZERO; - - for ( int i = 0;i < MAX_TEXTURE_IMAGE_UNITS;++i ) - { - jsTextureImageUnit *tu = LContext->TextureImageUnits + i; - tu->bound2D = 0; - - tu->fragmentTarget = 0; - - tu->envMode = GL_MODULATE; - tu->envColor.R = 0.f; - tu->envColor.G = 0.f; - tu->envColor.B = 0.f; - tu->envColor.A = 0.f; - - tu->currentTexture = NULL; - } - for(int i = 0; i < MAX_VERTEX_TEXTURE_IMAGE_UNITS; ++i) - LContext->VertexTextureImages[i] = NULL; - - LContext->ActiveTexture = 0; - LContext->CurrentImageUnit = LContext->TextureImageUnits; - - LContext->packAlignment = 4; - LContext->unpackAlignment = 4; - - LContext->CS_ActiveTexture = 0; - - _RGLResetAttributeState( &LContext->defaultAttribs0 ); - LContext->attribs = &LContext->defaultAttribs0; - LContext->attribSetName = 0; - LContext->attribSetDirty = GL_FALSE; - - LContext->framebuffer = 0; - - LContext->VertexProgram = GL_FALSE; - LContext->BoundVertexProgram = 0; - - LContext->FragmentProgram = GL_FALSE; - LContext->BoundFragmentProgram = 0; - - LContext->ArrayBuffer = 0; - LContext->PixelUnpackBuffer = 0; - LContext->TextureBuffer = 0; - - LContext->VSync = GL_FALSE; - - LContext->AllowTXPDemotion = GL_FALSE; -} - -static jsTexture *_RGLAllocateTexture (void) -{ - GLuint size = sizeof( jsTexture ) + sizeof( RGLTexture); - jsTexture *texture = ( jsTexture * )malloc( size ); - memset( texture, 0, size ); - - texture->target = 0; - texture->minFilter = GL_NEAREST_MIPMAP_LINEAR; - texture->magFilter = GL_LINEAR; - texture->gammaRemap = 0; - texture->usage = 0; - texture->isRenderTarget = GL_FALSE; - texture->image = NULL; - texture->isComplete = GL_FALSE; - texture->imageCount = 0; - texture->revalidate = 0; - texture->referenceBuffer = NULL; - new( &texture->framebuffers ) RGL::Vector(); - RGLTexture *gcmTexture = ( RGLTexture * )texture->platformTexture; - memset( gcmTexture, 0, sizeof( RGLTexture ) ); - gcmTexture->gpuAddressId = GMM_ERROR; - return texture; -} - -static void _RGLFreeTexture( jsTexture *texture ) -{ - _RGLTextureTouchFBOs( texture ); - texture->framebuffers.~Vector(); - if ( texture->image ) - { - for ( GLuint i = 0;i < texture->imageCount;++i ) - { - jsImage *image = texture->image + i; - _RGLImageFreeCPUStorage( image ); - } - if(texture->image != NULL) - free( texture->image ); - } - - if ( texture->referenceBuffer ) - texture->referenceBuffer->textureReferences.removeElement( texture ); - - _RGLPlatformDestroyTexture( texture ); - - if(texture != NULL) - free( texture ); -} - -PSGLcontext* psglCreateContext (void) -{ - PSGLcontext* LContext = ( PSGLcontext* )malloc( sizeof( PSGLcontext ) ); - if ( !LContext ) return NULL; - - memset( LContext, 0, sizeof( PSGLcontext ) ); - - LContext->error = GL_NO_ERROR; - _RGLTexNameSpaceInit( &LContext->textureNameSpace, ( jsTexNameSpaceCreateFunction )_RGLAllocateTexture, ( jsTexNameSpaceDestroyFunction )_RGLFreeTexture ); - - for ( int i = 0;i < MAX_TEXTURE_IMAGE_UNITS;++i ) - { - jsTextureImageUnit *tu = LContext->TextureImageUnits + i; - - tu->default2D = _RGLAllocateTexture(); - if ( !tu->default2D ) - { - psglDestroyContext( LContext ); - return NULL; - } - tu->default2D->target = GL_TEXTURE_2D; - } - - _RGLTexNameSpaceInit( &LContext->bufferObjectNameSpace, ( jsTexNameSpaceCreateFunction )_RGLCreateBufferObject, ( jsTexNameSpaceDestroyFunction )_RGLFreeBufferObject ); - _RGLTexNameSpaceInit( &LContext->framebufferNameSpace, ( jsTexNameSpaceCreateFunction )_RGLCreateFramebuffer, ( jsTexNameSpaceDestroyFunction )_RGLDestroyFramebuffer ); - _RGLTexNameSpaceInit( &LContext->attribSetNameSpace, ( jsTexNameSpaceCreateFunction )_RGLCreateAttribSet, ( jsTexNameSpaceDestroyFunction )_RGLDestroyAttribSet ); - - LContext->needValidate = 0; - LContext->everAttached = 0; - - LContext->RGLcgLastError = CG_NO_ERROR; - LContext->RGLcgErrorCallbackFunction = NULL; - LContext->RGLcgContextHead = ( CGcontext )NULL; - - LContext->cgProgramNameSpace.data = NULL; - LContext->cgProgramNameSpace.firstFree = NULL; - LContext->cgProgramNameSpace.capacity = 0; - - LContext->cgParameterNameSpace.data = NULL; - LContext->cgParameterNameSpace.firstFree = NULL; - LContext->cgParameterNameSpace.capacity = 0; - - LContext->cgContextNameSpace.data = NULL; - LContext->cgContextNameSpace.firstFree = NULL; - LContext->cgContextNameSpace.capacity = 0; - - _RGLResetContext( LContext ); - - if ( _RGLContextCreateHook ) - _RGLContextCreateHook( LContext ); - - return( LContext ); -} - -void psglResetCurrentContext (void) -{ - PSGLcontext *context = _CurrentContext; - _RGLResetContext( context ); - context->needValidate |= PSGL_VALIDATE_ALL; -} - -static bool context_shutdown = false; - -void psglDestroyContext( PSGLcontext* LContext ) -{ - context_shutdown = true; - - if ( _CurrentContext == LContext ) - { - cellGcmSetInvalidateVertexCache( &_RGLState.fifo); - _RGLFifoFinish( &_RGLState.fifo ); - } - - while ( LContext->RGLcgContextHead != ( CGcontext )NULL ) - { - PSGLcontext* current = _CurrentContext; - _CurrentContext = LContext; - cgDestroyContext( LContext->RGLcgContextHead ); - _CurrentContext = current; - } - - if (LContext->cgProgramNameSpace.data) - free( LContext->cgProgramNameSpace.data ); - - LContext->cgProgramNameSpace.data = NULL; - LContext->cgProgramNameSpace.capacity = 0; - LContext->cgProgramNameSpace.firstFree = NULL; - - if (LContext->cgParameterNameSpace.data) - free( LContext->cgParameterNameSpace.data ); - - LContext->cgParameterNameSpace.data = NULL; - LContext->cgParameterNameSpace.capacity = 0; - LContext->cgParameterNameSpace.firstFree = NULL; - - if (LContext->cgContextNameSpace.data) - free( LContext->cgContextNameSpace.data ); - - LContext->cgContextNameSpace.data = NULL; - LContext->cgContextNameSpace.capacity = 0; - LContext->cgContextNameSpace.firstFree = NULL; - - if ( _RGLContextDestroyHook ) _RGLContextDestroyHook( LContext ); - - for ( int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; ++i ) - { - jsTextureImageUnit* tu = LContext->TextureImageUnits + i; - if ( tu->default2D ) _RGLFreeTexture( tu->default2D ); - } - - _RGLTexNameSpaceFree( &LContext->textureNameSpace ); - _RGLTexNameSpaceFree( &LContext->bufferObjectNameSpace ); - _RGLTexNameSpaceFree( &LContext->framebufferNameSpace ); - _RGLTexNameSpaceFree( &LContext->attribSetNameSpace ); - - if ( _CurrentContext == LContext ) - psglMakeCurrent( NULL, NULL ); - - if(LContext != NULL) - free( LContext ); -} - -void _RGLAttachContext( PSGLdevice *device, PSGLcontext* context ) -{ - if ( !context->everAttached ) - { - context->ViewPort.XSize = device->deviceParameters.width; - context->ViewPort.YSize = device->deviceParameters.height; - context->everAttached = GL_TRUE; - _RGLFifoGlViewport(context->ViewPort.X, context->ViewPort.Y, - context->ViewPort.XSize, context->ViewPort.YSize, 0.0f, 1.0f); - } - context->needValidate = PSGL_VALIDATE_ALL; - - context->attribs->DirtyMask = ( 1 << MAX_VERTEX_ATTRIBS ) - 1; -} - -GLAPI void APIENTRY glEnable( GLenum cap ) -{ - PSGLcontext* LContext = _CurrentContext; - - switch (cap) - { - case GL_SHADER_SRGB_REMAP_SCE: - LContext->ShaderSRGBRemap = GL_TRUE; - LContext->needValidate |= PSGL_VALIDATE_SHADER_SRGB_REMAP; - break; - case GL_BLEND: - LContext->Blending = GL_TRUE; - LContext->BlendingMrt[0] = GL_TRUE; - LContext->BlendingMrt[1] = GL_TRUE; - LContext->BlendingMrt[2] = GL_TRUE; - LContext->needValidate |= PSGL_VALIDATE_BLENDING; - break; - case GL_BLEND_MRT0_SCE: - LContext->Blending = GL_TRUE; - LContext->needValidate |= PSGL_VALIDATE_BLENDING; - break; - case GL_BLEND_MRT1_SCE: - LContext->BlendingMrt[0] = GL_TRUE; - LContext->needValidate |= PSGL_VALIDATE_BLENDING; - break; - case GL_BLEND_MRT2_SCE: - LContext->BlendingMrt[1] = GL_TRUE; - LContext->needValidate |= PSGL_VALIDATE_BLENDING; - break; - case GL_BLEND_MRT3_SCE: - LContext->BlendingMrt[2] = GL_TRUE; - LContext->needValidate |= PSGL_VALIDATE_BLENDING; - break; - case GL_POINT_SMOOTH: - break; - case GL_DITHER: - break; - case GL_POINT_SPRITE_OES: - case GL_VERTEX_PROGRAM_POINT_SIZE_ARB: - break; - case GL_VSYNC_SCE: - LContext->VSync = GL_TRUE; - break; - case GL_FRAGMENT_PROGRAM_CONTROL_CONTROLTXP_SCE: - LContext->AllowTXPDemotion = GL_TRUE; - LContext->needValidate |= PSGL_VALIDATE_FRAGMENT_PROGRAM; - break; - default: - _RGLSetError( GL_INVALID_ENUM ); - return; - } -} - -GLAPI void APIENTRY glDisable(GLenum cap) -{ - PSGLcontext* LContext = _CurrentContext; - - switch ( cap ) - { - case GL_SHADER_SRGB_REMAP_SCE: - LContext->ShaderSRGBRemap = GL_FALSE; - LContext->needValidate |= PSGL_VALIDATE_SHADER_SRGB_REMAP; - break; - case GL_BLEND: - LContext->Blending = GL_FALSE; - LContext->BlendingMrt[0] = GL_FALSE; - LContext->BlendingMrt[1] = GL_FALSE; - LContext->BlendingMrt[2] = GL_FALSE; - LContext->needValidate |= PSGL_VALIDATE_BLENDING; - break; - - case GL_BLEND_MRT0_SCE: - LContext->Blending = GL_FALSE; - LContext->needValidate |= PSGL_VALIDATE_BLENDING; - break; - - case GL_BLEND_MRT1_SCE: - LContext->BlendingMrt[0] = GL_FALSE; - LContext->needValidate |= PSGL_VALIDATE_BLENDING; - break; - - case GL_BLEND_MRT2_SCE: - LContext->BlendingMrt[1] = GL_FALSE; - LContext->needValidate |= PSGL_VALIDATE_BLENDING; - break; - - case GL_BLEND_MRT3_SCE: - LContext->BlendingMrt[2] = GL_FALSE; - LContext->needValidate |= PSGL_VALIDATE_BLENDING; - break; - case GL_POINT_SMOOTH: - case GL_LINE_SMOOTH: - break; - case GL_DITHER: - break; - case GL_POINT_SPRITE_OES: - case GL_VERTEX_PROGRAM_POINT_SIZE_ARB: - break; - case GL_VSYNC_SCE: - LContext->VSync = GL_FALSE; - break; - case GL_FRAGMENT_PROGRAM_CONTROL_CONTROLTXP_SCE: - LContext->AllowTXPDemotion = GL_FALSE; - LContext->needValidate |= PSGL_VALIDATE_FRAGMENT_PROGRAM; - break; - - default: - _RGLSetError( GL_INVALID_ENUM ); - return; - } -} - -GLAPI void APIENTRY glEnableClientState(GLenum array) -{ - PSGLcontext* LContext = _CurrentContext; - - switch(array) - { - case GL_VERTEX_ARRAY: - _RGLEnableVertexAttribArrayNV( _RGL_ATTRIB_POSITION_INDEX ); - break; - case GL_COLOR_ARRAY: - _RGLEnableVertexAttribArrayNV( _RGL_ATTRIB_PRIMARY_COLOR_INDEX ); - break; - case GL_NORMAL_ARRAY: - _RGLEnableVertexAttribArrayNV( _RGL_ATTRIB_NORMAL_INDEX ); - break; - case GL_TEXTURE_COORD_ARRAY: - _RGLEnableVertexAttribArrayNV( _RGL_ATTRIB_TEX_COORD0_INDEX + LContext->CS_ActiveTexture ); - break; - default: - _RGLSetError( GL_INVALID_ENUM ); - return; - } -} - -GLAPI void APIENTRY glDisableClientState(GLenum array) -{ - PSGLcontext* LContext = _CurrentContext; - - switch ( array ) - { - case GL_VERTEX_ARRAY: - _RGLDisableVertexAttribArrayNV( _RGL_ATTRIB_POSITION_INDEX ); - break; - case GL_COLOR_ARRAY: - _RGLDisableVertexAttribArrayNV( _RGL_ATTRIB_PRIMARY_COLOR_INDEX ); - break; - case GL_NORMAL_ARRAY: - _RGLDisableVertexAttribArrayNV( _RGL_ATTRIB_NORMAL_INDEX ); - break; - case GL_TEXTURE_COORD_ARRAY: - _RGLDisableVertexAttribArrayNV( _RGL_ATTRIB_TEX_COORD0_INDEX + LContext->CS_ActiveTexture ); - break; - default: - _RGLSetError( GL_INVALID_ENUM ); - return; - } -} - -GLAPI void APIENTRY glFlush(void) -{ - PSGLcontext *LContext = _CurrentContext; - RGLFifo *fifo = &_RGLState.fifo; - - if ( RGL_UNLIKELY( LContext->needValidate ) ) - _RGLValidateStates(); - - cellGcmSetInvalidateVertexCache( &_RGLState.fifo); - - _RGLFifoFlush( fifo ); -} - -GLAPI void APIENTRY glFinish(void) -{ - glFlush(); - cellGcmSetInvalidateVertexCache( &_RGLState.fifo); - _RGLFifoFinish( &_RGLState.fifo ); -} - -GLAPI const GLubyte* APIENTRY glGetString( GLenum name ) -{ - switch ( name ) - { - case GL_VENDOR: - return(( GLubyte* )_RGLVendorString ); - case GL_RENDERER: - return(( GLubyte* )_RGLRendererString ); - case GL_VERSION: - return(( GLubyte* )_RGLVersionNumber ); - case GL_EXTENSIONS: - return(( GLubyte* )_RGLExtensionsString ); - default: - { - _RGLSetError( GL_INVALID_ENUM ); - return(( GLubyte* )NULL ); - } - } -} - - -void psglInit( PSGLinitOptions* options ) -{ - if ( !_RGLInitCompleted ) - { - int ret = cellSysmoduleLoadModule( CELL_SYSMODULE_GCM_SYS ); - ret = cellSysmoduleLoadModule( CELL_SYSMODULE_RESC ); - - _RGLDeviceInit( options ); - _CurrentContext = NULL; - _CurrentDevice = NULL; - } - - _RGLInitCompleted = 1; -} - -void psglExit (void) -{ - PSGLcontext* LContext = _CurrentContext; - if ( LContext ) - { - glFlush(); - cellGcmSetInvalidateVertexCache ( &_RGLState.fifo); - _RGLFifoFinish( &_RGLState.fifo ); - - psglMakeCurrent( NULL, NULL ); - _RGLDeviceExit(); - - _CurrentContext = NULL; - - _RGLInitCompleted = 0; - } -} - -#undef __STRICT_ANSI__ - -GLAPI void APIENTRY glVertexPointer( GLint size, GLenum type, GLsizei stride, const GLvoid* pointer ) -{ - _RGLVertexAttribPointerNV( _RGL_ATTRIB_POSITION_INDEX, size, type, GL_FALSE, stride, pointer ); -} - -GLAPI void APIENTRY glTexCoordPointer( GLint size, GLenum type, GLsizei stride, const GLvoid* pointer ) -{ - PSGLcontext* LContext = _CurrentContext; - - _RGLVertexAttribPointerNV( - _RGL_ATTRIB_TEX_COORD0_INDEX + LContext->CS_ActiveTexture, - size, - type, - GL_FALSE, - stride, - pointer ); -} - -GLAPI void APIENTRY glColorPointer( GLint size, GLenum type, GLsizei stride, const GLvoid* pointer ) -{ - _RGLVertexAttribPointerNV( _RGL_ATTRIB_PRIMARY_COLOR_INDEX, size, type, GL_TRUE, stride, pointer ); -} - -static GLboolean _RGLPlatformNeedsConversion( const jsAttributeState* as, GLuint index ) -{ - const jsAttribute* attrib = as->attrib + index; - - switch ( attrib->clientType ) - { - case GL_SHORT: - case GL_HALF_FLOAT_ARB: - case GL_FLOAT: - case GL_FIXED_11_11_10_SCE: - return GL_FALSE; - case GL_UNSIGNED_BYTE: - if ( attrib->normalized || - attrib->clientSize == 4 ) - return GL_FALSE; - break; - default: - break; - } - //RARCH_WARN("Attribute %d needs conversion. Slow path ahead.\n", index); - return GL_TRUE; -} - -static int _RGLGetTypeSize( GLenum type ) -{ - switch ( type ) - { - -#define DECLARE_PACKED_TYPE(REALTYPE,TYPE,N,S1,S2,S3,S4,REV) \ - case TYPE: \ - return sizeof(type_##REALTYPE); - DECLARE_PACKED_TYPES -#undef DECLARE_PACKED_TYPE - -#define DECLARE_UNPACKED_TYPE(TYPE) \ - case TYPE: \ - return sizeof(type_##TYPE); - DECLARE_UNPACKED_TYPES -#undef DECLARE_UNPACKED_TYPE - - default: - return 0; - } -} - -void _RGLVertexAttribPointerNV( - GLuint index, - GLint fsize, - GLenum type, - GLboolean normalized, - GLsizei stride, - const GLvoid* pointer ) -{ - PSGLcontext* LContext = _CurrentContext; - - GLsizei defaultStride = 0; - switch ( type ) - { - case GL_FLOAT: - case GL_HALF_FLOAT_ARB: - case GL_BYTE: - case GL_UNSIGNED_BYTE: - case GL_SHORT: - case GL_FIXED: - defaultStride = fsize * _RGLGetTypeSize( type ); - break; - case GL_FIXED_11_11_10_SCE: - defaultStride = 4; - break; - default: - _RGLSetError( GL_INVALID_ENUM ); - return; - } - - jsAttributeState* as = LContext->attribs; - jsAttribute* attrib = as->attrib + index; - attrib->clientSize = fsize; - attrib->clientType = type; - attrib->clientStride = stride ? stride : defaultStride; - attrib->clientData = ( void* )pointer; - GLuint oldArrayBuffer = attrib->arrayBuffer; - attrib->arrayBuffer = LContext->ArrayBuffer; - attrib->normalized = normalized; - RGLBIT_ASSIGN( as->HasVBOMask, index, attrib->arrayBuffer != 0 ); - GLboolean needConvert = _RGLPlatformNeedsConversion( as, index ); - RGLBIT_ASSIGN( as->NeedsConversionMask, index, needConvert ); - - RGLBIT_TRUE( as->DirtyMask, index ); - - if ( LContext->attribSetName ) - { - jsAttribSet* attribSet = (jsAttribSet*)LContext->attribSetNameSpace.data[LContext->attribSetName]; - - if ( oldArrayBuffer ) - { - int refcount = 0; - for(unsigned int i = 0; i < MAX_VERTEX_ATTRIBS; ++i ) - { - if ( attribSet->attribs.attrib[i].arrayBuffer == oldArrayBuffer ) ++refcount; - } - if(refcount == 1) - { - jsBufferObject *buffer = (jsBufferObject *)LContext->bufferObjectNameSpace.data[oldArrayBuffer]; - buffer->attribSets.removeElement(attribSet); - } - } - - if ( attrib->arrayBuffer ) - { - jsBufferObject *buffer = (jsBufferObject *)LContext->bufferObjectNameSpace.data[attrib->arrayBuffer]; - buffer->attribSets.appendUnique(attribSet); - } - - attribSet->dirty = GL_TRUE; - LContext->attribSetDirty = GL_TRUE; - } -} - -void _RGLEnableVertexAttribArrayNV( GLuint index ) -{ - PSGLcontext *LContext = _CurrentContext; - jsAttribSet* attribSet = (jsAttribSet*)LContext->attribSetNameSpace.data[LContext->attribSetName]; - - RGLBIT_TRUE( LContext->attribs->EnabledMask, index ); - RGLBIT_TRUE( LContext->attribs->DirtyMask, index ); - - if ( LContext->attribSetName ) - { - attribSet->dirty = GL_TRUE; - LContext->attribSetDirty = GL_TRUE; - } -} - -void _RGLDisableVertexAttribArrayNV( GLuint index ) -{ - PSGLcontext *LContext = _CurrentContext; - jsAttribSet* attribSet = (jsAttribSet*)LContext->attribSetNameSpace.data[LContext->attribSetName]; - - RGLBIT_FALSE( LContext->attribs->EnabledMask, index ); - RGLBIT_TRUE( LContext->attribs->DirtyMask, index ); - - if ( LContext->attribSetName ) - { - attribSet->dirty = GL_TRUE; - LContext->attribSetDirty = GL_TRUE; - } -} - -static GLuint _RGLValidateAttributesSlow( jsDrawParams *dparams) -{ - PSGLcontext* LContext = _CurrentContext; - RGLDriver *driver= (RGLDriver *)_CurrentDevice->rasterDriver; - jsAttributeState* as = LContext->attribs; - - void* xferBuffer = NULL; - GLuint xferId = GMM_ERROR; - GLuint VBOId = GMM_ERROR; - GLuint gpuOffset; - - if(RGL_UNLIKELY( dparams->xferTotalSize)) - { - xferId = gmmAlloc(0, dparams->xferTotalSize); - xferBuffer = gmmIdToAddress(xferId); - } - - unsigned int needsUpdateMask = (as->DirtyMask | (as->EnabledMask & ~as->HasVBOMask)); - - LContext->attribSetDirty = GL_FALSE; - - if ( needsUpdateMask ) - { - for ( GLuint i = 0; i < MAX_VERTEX_ATTRIBS; ++i ) - { - if(!RGLBIT_GET(needsUpdateMask, i)) - continue; - - jsAttribute* attrib = as->attrib + i; - - if ( RGLBIT_GET( as->EnabledMask, i ) ) - { - GLsizei stride = attrib->clientStride; - const GLuint freq = attrib->frequency; - - if ( RGL_UNLIKELY( dparams->attribXferSize[i] ) ) - { - GmmBaseBlock *pBaseBlock = (GmmBaseBlock *)xferId; - - GLuint maxElements = dparams->firstVertex + dparams->vertexCount; - - GLuint offset; - if(RGLBIT_GET( as->ModuloMask, i)) - offset = ( maxElements > freq ) ? 0 : dparams->firstVertex * stride; - else - offset = ( dparams->firstVertex / freq ) * stride; - - char *b = (char *)xferBuffer + dparams->attribXferOffset[i]; - memcpy( b + offset, ( char * )attrib->clientData + offset, - dparams->attribXferSize[i] - offset ); - - gpuOffset = gmmAddressToOffset(pBaseBlock->address, pBaseBlock->isMain) + (b - ( char * )xferBuffer); - } - else - { - VBOId = _RGLGetBufferObjectOrigin( attrib->arrayBuffer ); - GmmBaseBlock *pBaseBlock = (GmmBaseBlock *)VBOId; - gpuOffset = gmmAddressToOffset(pBaseBlock->address, pBaseBlock->isMain) + (( const GLubyte* )attrib->clientData - ( const GLubyte* )NULL ); - } - - if(attrib->clientSize == 0) - { - stride = 0; - attrib->normalized = 0; - attrib->clientType = RGL_FLOAT; - gpuOffset = 0; - } - - uint8_t gcmType = 0; - - switch ( (RGLEnum)attrib->clientType ) - { - case RGL_UNSIGNED_BYTE: - gcmType = attrib->normalized ? CELL_GCM_VERTEX_UB : CELL_GCM_VERTEX_UB256; - break; - case RGL_SHORT: - gcmType = attrib->normalized ? CELL_GCM_VERTEX_S1 : CELL_GCM_VERTEX_S32K; - break; - case RGL_FLOAT: - gcmType = CELL_GCM_VERTEX_F; - break; - case RGL_HALF_FLOAT: - gcmType = CELL_GCM_VERTEX_SF; - break; - case RGL_CMP: - attrib->clientSize = 1; - gcmType = CELL_GCM_VERTEX_CMP; - break; - default: - break; - } - - cellGcmSetVertexDataArrayInline( &_RGLState.fifo, i, freq, stride, attrib->clientSize, gcmType, CELL_GCM_LOCATION_LOCAL, gpuOffset ); - } - else - { - cellGcmSetVertexDataArrayInline( &_RGLState.fifo, i, 0, 0, 0, CELL_GCM_VERTEX_F, CELL_GCM_LOCATION_LOCAL, 0); - cellGcmSetVertexData4fInline( &_RGLState.fifo, i,attrib->value); - } - } - cellGcmSetFrequencyDividerOperationInline( &_RGLState.fifo, as->ModuloMask); - driver->invalidateVertexCache = GL_TRUE; - } - - as->DirtyMask = 0; - - if ( xferId != GMM_ERROR ) - gmmFree( xferId ); - - return 0; -} - -GLAPI void APIENTRY glDrawArrays( GLenum mode, GLint first, GLsizei count ) -{ - static uint8_t s_dparams_buff[ (sizeof(jsDrawParams) + 0x7f) & ~0x7f ] __attribute__((aligned(128))); - - PSGLcontext* LContext = _CurrentContext; - jsAttributeState* as = LContext->attribs; - RGLDriver *driver= (RGLDriver *)_CurrentDevice->rasterDriver; - const GLuint clientSideMask = as->EnabledMask & ~as->HasVBOMask; - - if ( RGL_UNLIKELY( ! RGLBIT_GET( LContext->attribs->EnabledMask, _RGL_ATTRIB_POSITION_INDEX ) ) ) return; - - uint32_t _tmp_clear_loop = ((sizeof(jsDrawParams) + 0x7f) & ~0x7f) >> 7; - - do{ - --_tmp_clear_loop; - __dcbz(s_dparams_buff+(_tmp_clear_loop << 7)); - }while(_tmp_clear_loop); - - jsDrawParams *dparams = (jsDrawParams *)s_dparams_buff; - dparams->mode = CELL_GCM_PRIMITIVE_TRIANGLE_STRIP; - dparams->firstVertex = first; - dparams->vertexCount = count; - GLuint maxElements = dparams->firstVertex + dparams->vertexCount; - - if ( LContext->needValidate ) - _RGLValidateStates(); - - if ( RGL_UNLIKELY( clientSideMask ) ) - { - for ( int i = 0; i < MAX_VERTEX_ATTRIBS; ++i ) - { - dparams->attribXferOffset[i] = 0; - dparams->attribXferSize[i] = 0; - - if(clientSideMask & (1 << i)) - { - jsAttribute* attrib = as->attrib + i; - const GLuint freq = attrib->frequency; - GLuint count; - - if (RGLBIT_GET(as->ModuloMask, i)) - count = maxElements > freq ? freq : maxElements; - else - count = ( maxElements + freq - 1 ) / freq; - - const GLuint numBytes = attrib->clientStride * count; - dparams->attribXferOffset[i] = dparams->xferTotalSize; - dparams->attribXferSize[i] = numBytes; - - const GLuint numBytesPadded = _RGLPad( numBytes, 128 ); - dparams->xferTotalSize += numBytesPadded; - dparams->attribXferTotalSize += numBytesPadded; - } - } - } - - if ( driver->flushBufferCount != 0 ) - driver->invalidateVertexCache = GL_TRUE; - - uint32_t totalXfer = 0; - - for (GLuint i = 0; i < MAX_VERTEX_ATTRIBS; ++i) - totalXfer += dparams->attribXferSize[i]; - - GLuint gpuOffset = _RGLValidateAttributesSlow( dparams); - (void)gpuOffset; - - if(driver->invalidateVertexCache) - { - driver->invalidateVertexCache = GL_FALSE; - cellGcmSetInvalidateVertexCache ( &_RGLState.fifo); - } - - GmmBaseBlock *pBaseBlock = (GmmBaseBlock *)driver->fpLoadProgramId; - cellGcmSetUpdateFragmentProgramParameterInline( &_RGLState.fifo, gmmAddressToOffset(pBaseBlock->address, pBaseBlock->isMain) +driver->fpLoadProgramOffset ); - - cellGcmSetDrawArraysInline( &_RGLState.fifo, mode == GL_QUADS ? CELL_GCM_PRIMITIVE_QUADS : CELL_GCM_PRIMITIVE_TRIANGLE_STRIP, dparams->firstVertex, dparams->vertexCount); -} - -GLAPI void APIENTRY glGenTextures( GLsizei n, GLuint *textures ) -{ - PSGLcontext* LContext = _CurrentContext; - _RGLTexNameSpaceGenNames( &LContext->textureNameSpace, n, textures ); -} - -static void _RGLTextureUnbind( PSGLcontext* context, GLuint name ) -{ - int unit; - for (unit = 0; unit < MAX_TEXTURE_IMAGE_UNITS; ++unit) - { - jsTextureImageUnit *tu = context->TextureImageUnits + unit; - GLboolean dirty = GL_FALSE; - if ( tu->bound2D == name ) - { - tu->bound2D = 0; - dirty = GL_TRUE; - } - if ( dirty ) - { - tu->currentTexture = _RGLGetCurrentTexture( tu, GL_TEXTURE_2D ); - context->needValidate |= PSGL_VALIDATE_TEXTURES_USED; - } - } - if(_RGLTexNameSpaceIsName( &context->textureNameSpace, name)) - { - jsTexture*texture = ( jsTexture * )context->textureNameSpace.data[name]; - for ( unit = 0;unit < MAX_VERTEX_TEXTURE_IMAGE_UNITS; ++unit ) - { - if ( context->VertexTextureImages[unit] == texture ) - { - context->VertexTextureImages[unit] = NULL; - context->needValidate |= PSGL_VALIDATE_VERTEX_TEXTURES_USED; - } - } - } -} - -GLAPI void APIENTRY glDeleteTextures( GLsizei n, const GLuint *textures ) -{ - PSGLcontext* LContext = _CurrentContext; - - for(int i = 0;i < n; ++i) - if(textures[i]) - _RGLTextureUnbind(LContext, textures[i]); - - _RGLTexNameSpaceDeleteNames( &LContext->textureNameSpace, n, textures ); -} - -GLAPI void APIENTRY glTexParameteri( GLenum target, GLenum pname, GLint param ) -{ - PSGLcontext* LContext = _CurrentContext; - jsTexture *texture = _RGLGetCurrentTexture( LContext->CurrentImageUnit, target ); - - switch ( pname ) - { - case GL_TEXTURE_MIN_FILTER: - texture->minFilter = param; - if ( texture->referenceBuffer == 0 ) - texture->revalidate |= TEXTURE_REVALIDATE_LAYOUT; - break; - case GL_TEXTURE_MAG_FILTER: - texture->magFilter = param; - break; - case GL_TEXTURE_MAX_LEVEL: - case GL_TEXTURE_WRAP_S: - case GL_TEXTURE_WRAP_T: - case GL_TEXTURE_WRAP_R: - case GL_TEXTURE_FROM_VERTEX_PROGRAM_SCE: - break; - case GL_TEXTURE_ALLOCATION_HINT_SCE: - texture->usage = param; - texture->revalidate |= TEXTURE_REVALIDATE_LAYOUT; - break; - case GL_TEXTURE_MIN_LOD: - case GL_TEXTURE_MAX_LOD: - case GL_TEXTURE_LOD_BIAS: - case GL_TEXTURE_MAX_ANISOTROPY_EXT: - case GL_DEPTH_TEXTURE_MODE_ARB: - case GL_TEXTURE_COMPARE_MODE_ARB: - case GL_TEXTURE_COMPARE_FUNC_ARB: - break; - case GL_TEXTURE_GAMMA_REMAP_R_SCE: - case GL_TEXTURE_GAMMA_REMAP_G_SCE: - case GL_TEXTURE_GAMMA_REMAP_B_SCE: - case GL_TEXTURE_GAMMA_REMAP_A_SCE: - { - GLuint bit = 1 << ( pname - GL_TEXTURE_GAMMA_REMAP_R_SCE ); - if(param) - texture->gammaRemap |= bit; - else - texture->gammaRemap &= ~bit; - } - break; - default: - _RGLSetError( GL_INVALID_ENUM ); - return; - } - - texture->revalidate |= TEXTURE_REVALIDATE_PARAMETERS; - LContext->needValidate |= PSGL_VALIDATE_TEXTURES_USED | PSGL_VALIDATE_VERTEX_TEXTURES_USED; -} - -GLAPI void APIENTRY glBindTexture( GLenum target, GLuint name ) -{ - PSGLcontext* LContext = _CurrentContext; - jsTextureImageUnit *unit = LContext->CurrentImageUnit; - - _RGLBindTextureInternal( unit, name); -} - -static void _RGLReallocateImages( jsTexture *texture, GLsizei dimension ) -{ - GLuint oldCount = texture->imageCount; - - if ( dimension <= 0 ) - dimension = 1; - - GLuint n = 1 + _RGLLog2( dimension ); - n = MAX( n, oldCount ); - - jsImage *images = ( jsImage * )realloc( texture->image, n * sizeof( jsImage ) ); - - memset( images + oldCount, 0, ( n - oldCount )*sizeof( jsImage ) ); - - texture->image = images; - texture->imageCount = n; -} - -GLAPI void APIENTRY glTexImage2D( GLenum target, GLint level, GLint internalFormat, -GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels ) -{ - PSGLcontext* LContext = _CurrentContext; - jsTexture *texture; - jsImage *image; - - jsTextureImageUnit *unit = LContext->CurrentImageUnit; - - jsTexture *tex = _RGLGetCurrentTexture(unit, GL_TEXTURE_2D); - - if(0 >= (int)tex->imageCount) - _RGLReallocateImages(tex, MAX(width, height)); - - image = tex->image; - texture = tex; - - image->dataState = IMAGE_DATASTATE_UNSET; - - GLboolean directPBO = GL_FALSE; - if ( LContext->PixelUnpackBuffer != 0 ) - { - directPBO = _RGLPlatformTexturePBOImage( - texture, - image, - internalFormat, - width, height, - format, type, - pixels ); - } - - if ( !directPBO ) - { - jsBufferObject* bufferObject = NULL; - if ( LContext->PixelUnpackBuffer != 0 ) - { - bufferObject = (jsBufferObject *)LContext->bufferObjectNameSpace.data[LContext->PixelUnpackBuffer]; - pixels = _RGLPlatformBufferObjectMap( bufferObject, GL_READ_ONLY ) + - (( const GLubyte* )pixels - ( const GLubyte* )NULL ); - } - - _RGLSetImage(image, internalFormat, width, height, 1, LContext->unpackAlignment, - format, type, pixels); - - if ( LContext->PixelUnpackBuffer != 0 ) - { - RGLBufferObject *jsBuffer = ( RGLBufferObject * )bufferObject->platformBufferObject; - - if ( --jsBuffer->mapCount == 0 ) - { - if ( jsBuffer->mapAccess != GL_READ_ONLY ) - { - RGLDriver *driver= (RGLDriver *)_CurrentDevice->rasterDriver; - --driver->flushBufferCount; - - driver->invalidateVertexCache = GL_TRUE; - } - - jsBuffer->mapAccess = GL_NONE; - - GmmBaseBlock *pBaseBlock = (GmmBaseBlock *)jsBuffer->bufferId; - - if (!pBaseBlock->isTile) - { - GmmBlock *pBlock = (GmmBlock *)jsBuffer->bufferId; - pBlock->isPinned = 0; - } - } - } - - texture->revalidate |= TEXTURE_REVALIDATE_IMAGES; - } - - _RGLTextureTouchFBOs( texture ); - LContext->needValidate |= PSGL_VALIDATE_TEXTURES_USED | PSGL_VALIDATE_VERTEX_TEXTURES_USED; -} - -GLAPI void APIENTRY glActiveTexture(GLenum texture) -{ - PSGLcontext* LContext = _CurrentContext; - - int unit = texture - GL_TEXTURE0; - LContext->ActiveTexture = unit; - LContext->CurrentImageUnit = unit < MAX_TEXTURE_IMAGE_UNITS ? LContext->TextureImageUnits + unit : NULL; -} - -GLAPI void APIENTRY glClientActiveTexture(GLenum texture) -{ - PSGLcontext* LContext = _CurrentContext; - LContext->CS_ActiveTexture = texture - GL_TEXTURE0; -} - -GLAPI void APIENTRY glPixelStorei(GLenum pname, GLint param) -{ - PSGLcontext* LContext = _CurrentContext; - - switch ( pname ) - { - case GL_PACK_ALIGNMENT: - LContext->packAlignment = param; - break; - case GL_UNPACK_ALIGNMENT: - LContext->unpackAlignment = param; - break; - default: - _RGLSetError( GL_INVALID_ENUM ); - return; - } -} - - -GLAPI void APIENTRY glTextureReferenceSCE( GLenum target, GLuint levels, GLuint baseWidth, GLuint baseHeight, GLuint baseDepth, GLenum internalFormat, GLuint pitch, GLintptr offset ) -{ - PSGLcontext* LContext = _CurrentContext; - - jsTexture *texture = _RGLGetCurrentTexture( LContext->CurrentImageUnit, GL_TEXTURE_2D); - jsBufferObject *bufferObject = (jsBufferObject *)LContext->bufferObjectNameSpace.data[LContext->TextureBuffer]; - _RGLReallocateImages( texture, MAX( baseWidth, MAX( baseHeight, baseDepth ) ) ); - - GLuint width = baseWidth; - GLuint height = baseHeight; - _RGLSetImage(texture->image, GL_RGB5_A1, width, height, 0, LContext->unpackAlignment, - 0, 0, NULL ); - width = MAX( 1U, width / 2 ); - height = MAX( 1U, height / 2 ); - texture->usage = GL_TEXTURE_LINEAR_GPU_SCE; - - GLboolean r = _RGLPlatformTextureReference( texture, pitch, bufferObject, offset ); - - if(!r) - return; - - bufferObject->textureReferences.pushBack( texture ); - texture->referenceBuffer = bufferObject; - texture->offset = offset; - _RGLTextureTouchFBOs( texture ); - LContext->needValidate |= PSGL_VALIDATE_TEXTURES_USED | PSGL_VALIDATE_VERTEX_TEXTURES_USED ; -} - -GLAPI void APIENTRY glViewport( GLint x, GLint y, GLsizei width, GLsizei height ) -{ - PSGLcontext* LContext = _CurrentContext; - - LContext->ViewPort.X = x; - LContext->ViewPort.Y = y; - LContext->ViewPort.XSize = width; - LContext->ViewPort.YSize = height; - - _RGLFifoGlViewport(LContext->ViewPort.X, LContext->ViewPort.Y, - LContext->ViewPort.XSize, LContext->ViewPort.YSize, 0.0f, 1.0f); -} - -jsTexture *_RGLGetCurrentTexture( const jsTextureImageUnit *unit, GLenum target ) -{ - PSGLcontext* LContext = _CurrentContext; - GLuint name = unit->bound2D; - jsTexture *defaultTexture = unit->default2D; - - if ( name ) - return ( jsTexture * )LContext->textureNameSpace.data[name]; - else - return defaultTexture; -} - -CgprogramHookFunction _cgProgramCreateHook = NULL; -CgprogramHookFunction _cgProgramDestroyHook = NULL; -CgprogramCopyHookFunction _cgProgramCopyHook = NULL; - -cgRTCgcCompileHookFunction _cgRTCgcCompileProgramHook = NULL; -cgRTCgcFreeHookFunction _cgRTCgcFreeCompiledProgramHook; - -CgcontextHookFunction _cgContextCreateHook = NULL; -CgcontextHookFunction _cgContextDestroyHook = NULL; - -CgparameterHookFunction _cgParameterCreateHook = NULL; -CgparameterHookFunction _cgParameterDestroyHook = NULL; - -typedef struct RGLcgProfileMapType -{ - CGprofile id; - char* string; - int is_vertex_program; -} RGLcgProfileMapType; - -static void _RGLCgProgramPushFront( _CGcontext* ctx, _CGprogram* prog ) -{ - prog->next = ctx->programList; - ctx->programList = prog; - prog->parentContext = ctx; - ctx->programCount++; -} - -static _CGprogram* _RGLCgProgramFindPrev( _CGcontext* ctx, _CGprogram* prog ) -{ - _CGprogram* ptr = ctx->programList; - - while ( ptr != NULL && prog != ptr->next ) - ptr = ptr->next; - - return ptr; -} - -void _RGLCgProgramErase( _CGprogram* prog ) -{ - if ( _cgProgramDestroyHook ) _cgProgramDestroyHook( prog ); - - switch ( prog->header.profile ) - { - case CG_PROFILE_SCE_VP_TYPEB: - case CG_PROFILE_SCE_VP_RSX: - case CG_PROFILE_SCE_FP_TYPEB: - case CG_PROFILE_SCE_FP_RSX: - _RGLPlatformProgramErase( prog ); - break; - default: - break; - } - - if ( prog->id ) - _RGLEraseName( &_CurrentContext->cgProgramNameSpace, ( jsName )prog->id ); - - if ( prog->runtimeElf ) - free( prog->runtimeElf ); - - memset( prog, 0, sizeof( _CGprogram ) ); -} - -bool _RGLCgCreateProgramChecks( CGcontext ctx, CGprofile profile, CGenum program_type ) -{ - if ( !CG_IS_CONTEXT( ctx ) ) - { - _RGLCgRaiseError( CG_INVALID_CONTEXT_HANDLE_ERROR ); - return false; - } - - switch ( profile ) - { - case CG_PROFILE_SCE_VP_TYPEB: - case CG_PROFILE_SCE_FP_TYPEB: - case CG_PROFILE_SCE_VP_RSX: - case CG_PROFILE_SCE_FP_RSX: - break; - default: - _RGLCgRaiseError( CG_UNKNOWN_PROFILE_ERROR ); - return false; - } - - switch ( program_type ) - { - case CG_BINARY: - case CG_SOURCE: - break; - default: - _RGLCgRaiseError( CG_INVALID_ENUMERANT_ERROR ); - return false; - } - - return true; -} - -typedef struct -{ - const char* elfFile; - size_t elfFileSize; - - const char *symtab; - size_t symbolSize; - size_t symbolCount; - const char *symbolstrtab; - - const char* shadertab; - size_t shadertabSize; - const char* strtab; - size_t strtabSize; - const char* consttab; - size_t consttabSize; -} CGELFBinary; - -typedef struct -{ - const char *texttab; - size_t texttabSize; - const char *paramtab; - size_t paramtabSize; - int index; -} CGELFProgram; - -static bool cgOpenElf( const void *ptr, size_t size, CGELFBinary *elfBinary ) -{ - while(1) - { - size_t shadertabSize; - size_t consttabSize; - size_t strtabSize; - size_t symbolSize; - size_t symbolCount; - const char *symbolstrtab; - - const char *symtab = findSymbolSectionInPlace(( const char * )ptr, size, &symbolSize, &symbolCount, &symbolstrtab ); - if ( !symtab ) - break; - - const char *shadertab = findSectionInPlace(( const char* )ptr, size, ".shadertab", &shadertabSize ); - - if ( !shadertab ) - break; - - const char *strtab = findSectionInPlace(( const char* )ptr, size, ".strtab", &strtabSize ); - - if ( !strtab ) - break; - - const char *consttab = findSectionInPlace(( const char* )ptr, size, ".const", &consttabSize ); - if ( !consttab ) - break; - - elfBinary->elfFile = ( const char* )ptr; - elfBinary->elfFileSize = size; - elfBinary->symtab = symtab; - elfBinary->symbolSize = symbolSize; - elfBinary->symbolCount = symbolCount; - elfBinary->symbolstrtab = symbolstrtab; - - elfBinary->shadertab = shadertab; - elfBinary->shadertabSize = shadertabSize; - elfBinary->strtab = strtab; - elfBinary->strtabSize = strtabSize; - - elfBinary->consttab = consttab; - elfBinary->consttabSize = consttabSize; - - return true; - } - - return false; -} - -static bool cgGetElfProgramByIndex( CGELFBinary *elfBinary, int index, CGELFProgram *elfProgram ) -{ - while(1) - { - char sectionName[64]; - snprintf( sectionName, sizeof(sectionName), ".text%04i", index ); - size_t texttabSize; - const char *texttab = findSectionInPlace( elfBinary->elfFile, elfBinary->elfFileSize, sectionName, &texttabSize ); - if ( !texttab ) - break; - snprintf( sectionName, sizeof(sectionName), ".paramtab%04i", index ); - size_t paramtabSize; - const char *paramtab = findSectionInPlace( elfBinary->elfFile, elfBinary->elfFileSize, sectionName, ¶mtabSize ); - if ( !paramtab ) - break; - - elfProgram->texttab = texttab; - elfProgram->texttabSize = texttabSize; - elfProgram->paramtab = paramtab; - elfProgram->paramtabSize = paramtabSize; - elfProgram->index = index; - return true; - } - return false; -} - -static bool cgGetElfProgramByName( CGELFBinary *elfBinary, const char *name, CGELFProgram *elfProgram ) -{ - //if no name try to return the first program - int ret; - - if ( name == NULL || name[0] == '\0' ) - ret = 0; - else - ret = lookupSymbolValueInPlace( elfBinary->symtab, elfBinary->symbolSize, elfBinary->symbolCount, elfBinary->symbolstrtab, name ); - - if (ret != -1) - return cgGetElfProgramByIndex( elfBinary, ret, elfProgram ); - else - return false; -} - -static CGprogram _RGLCgCreateProgram( CGcontext ctx, CGprofile profile, const CgProgramHeader *programHeader, const void *ucode, const CgParameterTableHeader *parameterHeader, const char *stringTable, const float *defaultValues ) -{ - // Create the program structure. - // all the structural data is filled in here, - // as well as the profile. - // The parameters and the actual program are generated from the ABI specific calls. - - _CGprogram* prog = ( _CGprogram* )malloc( sizeof( _CGprogram ) ); - if(prog == NULL) - { - _RGLCgRaiseError( CG_MEMORY_ALLOC_ERROR ); - return NULL; - } - - // zero out the fields - memset( prog, 0, sizeof( _CGprogram ) ); - - // fill in the fields we know - prog->parentContext = _cgGetContextPtr( ctx ); - prog->header.profile = profile; - - int success = 0; - - // create a name for the program and record it in the object - CGprogram id = ( CGprogram )_RGLCreateName( &_CurrentContext->cgProgramNameSpace, prog ); - if(!id) - { - free(prog); - _RGLCgRaiseError( CG_MEMORY_ALLOC_ERROR ); - return NULL; - } - prog->id = id; - - if ( profile == ( CGprofile )7005 ) - profile = CG_PROFILE_SCE_VP_RSX; - if ( profile == ( CGprofile )7006 ) - profile = CG_PROFILE_SCE_FP_RSX; - - // load the binary into the program object - switch ( profile ) - { - case CG_PROFILE_SCE_VP_TYPEB: - //case CG_PROFILE_SCE_VP_TYPEC: - case CG_PROFILE_SCE_VP_RSX: - // TODO ************** need to include the entry symbol too - success = _RGLGenerateProgram( prog, VERTEX_PROFILE_INDEX, programHeader, - ucode, parameterHeader, NULL, stringTable, defaultValues ); - break; - case CG_PROFILE_SCE_FP_TYPEB: - //case CG_PROFILE_SCE_FP_TYPEC: - case CG_PROFILE_SCE_FP_RSX: - success = _RGLGenerateProgram( prog, FRAGMENT_PROFILE_INDEX, programHeader, ucode, parameterHeader, NULL, stringTable, defaultValues ); - break; - default: - // should never reach here - break; - } - - // if the creation failed, free all resources. - // the error was raised when the error was encoutered. - if ( success == 0 ) - { - // free the program object - free( prog ); - // release the id too - _RGLEraseName( &_CurrentContext->cgProgramNameSpace, ( jsName )id ); - return NULL; - } - - // success! add the program to the program list in the context. - _RGLCgProgramPushFront(prog->parentContext, prog); - - if(_cgProgramCreateHook) - _cgProgramCreateHook(prog); - - // everything worked. - return id; -} - -static CGprogram _RGLCgUpdateProgramAtIndex( CGprogramGroup group, int index, int refcount ); - -CG_API CGprogram cgCreateProgram( CGcontext ctx, - CGenum program_type, - const char* program, - CGprofile profile, - const char* entry, - const char** args ) -{ - // Load a program from a memory pointer. - - if ( profile == ( CGprofile )7005 ) - profile = CG_PROFILE_SCE_VP_RSX; - if ( profile == ( CGprofile )7006 ) - profile = CG_PROFILE_SCE_FP_RSX; - - if ( program_type == CG_ROW_MAJOR ) - program_type = CG_BINARY; - - if ( !_RGLCgCreateProgramChecks( ctx, profile, program_type ) ) - return NULL; - - //data to extract from the buffer passed: - CgProgramHeader *programHeader = NULL; - const void *ucode = NULL; - CgParameterTableHeader *parameterHeader = NULL; - const char *stringTable = NULL; - const float *defaultValues = NULL; - - //first step, compile any source file - const char *binaryBuffer = NULL; - char* compiled_program = NULL; - if ( program_type == CG_SOURCE ) - { - if(_cgRTCgcCompileProgramHook) - { - _cgRTCgcCompileProgramHook( program, cgGetProfileString(profile), entry, args, &compiled_program ); - if(!compiled_program) - { - _RGLCgRaiseError( CG_COMPILER_ERROR ); - return NULL; - } - binaryBuffer = compiled_program; - } - else - { - RARCH_ERR("The CG runtime compiler hasn't been setup. cgRTCgcInit() should be called prior to this function.\n" ); - _RGLCgRaiseError( CG_INVALID_ENUMERANT_ERROR ); - return NULL; - } - } - else - binaryBuffer = program; - - bool bConvertedToElf = false; - - //At that point we have a binary file which is either any ELF or an NV format file - const unsigned int ElfTag = 0x7F454C46; // == MAKEFOURCC(0x7F,'E','L','F'); - - if (!(*( unsigned int* )binaryBuffer == ElfTag)) - { - //convert NV file to the runtime format - - if ( program_type == CG_BINARY ) - { - //RARCH_WARN("A binary shader is being loaded using a deprecated binary format. Please use the cgnv2elf tool to convert to the new, memory-saving, faster-loading format.\n"); - } - - //convert from NV format to the runtime format - int compiled_program_size = 0; - std::vector stringTableArray; - std::vector defaultValuesArray; - CgBinaryProgram* nvProgram = ( CgBinaryProgram* )binaryBuffer; - char *runtimeElfShader = NULL; - - //check the endianness - int totalSize; - - if (( nvProgram->profile != CG_PROFILE_SCE_FP_TYPEB ) && ( nvProgram->profile != CG_PROFILE_SCE_VP_TYPEB ) && - ( nvProgram->profile != ( CGprofile )7006 ) && ( nvProgram->profile != ( CGprofile )7005 ) && - ( nvProgram->profile != CG_PROFILE_SCE_FP_RSX ) && ( nvProgram->profile != CG_PROFILE_SCE_VP_RSX ) ) - { - totalSize = endianSwapWord( nvProgram->totalSize ); - } - else - totalSize = nvProgram->totalSize; - - int res = convertNvToElfFromMemory( binaryBuffer, totalSize, 2, 0, ( void** )&runtimeElfShader, &compiled_program_size, stringTableArray, defaultValuesArray ); - if ( res != 0 ) - { - RARCH_ERR("Invalid CG binary program.\n"); - _RGLCgRaiseError( CG_COMPILER_ERROR ); - if ( compiled_program ) - _cgRTCgcFreeCompiledProgramHook( compiled_program ); - return NULL; - } - - if ( compiled_program ) - _cgRTCgcFreeCompiledProgramHook( compiled_program ); - - size_t stringTableSize = stringTableArray.size() * sizeof( stringTable[0] ); - size_t defaultTableSize = defaultValuesArray.size() * sizeof( defaultValues[0] ); - int paddedSize = _RGLPad( compiled_program_size, 4 ); - - char *runtimeElf = (char*)memalign( 16, paddedSize + stringTableSize + defaultTableSize ); - - if ( !runtimeElf ) - { - _RGLCgRaiseError( CG_MEMORY_ALLOC_ERROR ); - return NULL; - } - bConvertedToElf = true; - memcpy( runtimeElf, runtimeElfShader, compiled_program_size ); - - convertNvToElfFreeBinaryShader( runtimeElfShader ); - - float* pDefaultValues = ( float* )(( char* )runtimeElf + paddedSize ); - defaultValues = pDefaultValues; - - if ( defaultTableSize ) - memcpy( pDefaultValues, &defaultValuesArray[0], defaultTableSize ); - - char *pStringTable = ( char* )runtimeElf + paddedSize + defaultTableSize; - stringTable = pStringTable; - - if ( stringTableSize ) - memcpy( pStringTable, &stringTableArray[0], stringTableSize ); - - programHeader = ( CgProgramHeader* )runtimeElf; - size_t elfUcodeSize = programHeader->instructionCount * 16; - size_t ucodeOffset = _RGLPad( sizeof( CgProgramHeader ), 16 ); - size_t parameterOffset = _RGLPad( ucodeOffset + elfUcodeSize, 16 ); - ucode = ( char* )runtimeElf + ucodeOffset; - parameterHeader = ( CgParameterTableHeader* )(( char* )runtimeElf + parameterOffset ); - } - else - { - CGELFBinary elfBinary; - CGELFProgram elfProgram; - if ((( intptr_t )binaryBuffer ) & 15 ) - { - RARCH_ERR("CG Binary not aligned on 16 bytes, needed for ucode section.\n"); - _RGLCgRaiseError( CG_PROGRAM_LOAD_ERROR ); - return NULL; - } - bool res = cgOpenElf( binaryBuffer, 0, &elfBinary ); - if(!res) - { - RARCH_ERR("Not a valid ELF.\n"); - _RGLCgRaiseError( CG_PROGRAM_LOAD_ERROR ); - return NULL; - } - if(!cgGetElfProgramByName( &elfBinary, entry, &elfProgram)) - { - RARCH_ERR("Couldn't find the shader entry in the CG binary.\n"); - return NULL; - } - - programHeader = ( CgProgramHeader* )elfBinary.shadertab + elfProgram.index; - ucode = ( char* )elfProgram.texttab; - parameterHeader = ( CgParameterTableHeader* )elfProgram.paramtab; - stringTable = elfBinary.strtab; - defaultValues = ( float* )elfBinary.consttab; - } - - CGprogram prog = _RGLCgCreateProgram( ctx, profile, programHeader, ucode, parameterHeader, stringTable, defaultValues ); - - if(bConvertedToElf) - { - _CGprogram* ptr = _cgGetProgPtr( prog ); - ptr->runtimeElf = programHeader; - } - - return prog; -} - -CG_API CGprogram cgCreateProgramFromFile( CGcontext ctx, - CGenum program_type, - const char* program_file, - CGprofile profile, - const char* entry, - const char** args ) -{ - if ( profile == ( CGprofile )7005 ) - profile = CG_PROFILE_SCE_VP_RSX; - if ( profile == ( CGprofile )7006 ) - profile = CG_PROFILE_SCE_FP_RSX; - - if ( program_type == CG_ROW_MAJOR ) - program_type = CG_BINARY; - - if ( !_RGLCgCreateProgramChecks( ctx, profile, program_type ) ) - return NULL; - - FILE* fp = NULL; - if ( RGL_LIKELY( program_type == CG_BINARY ) ) - { - CGprogram ret = NULL; - - _CGcontext *context = _cgGetContextPtr( ctx ); - CGprogramGroup group = NULL; - - group = context->groupList; - while ( group ) - { - const char *groupName = _RGLCgGetProgramGroupName( group ); - if ( groupName && !strcmp( groupName, program_file ) ) - { - int index; - if ( entry == NULL ) - index = 0; - else - index = _RGLCgGetProgramIndex( group, entry ); - if ( index >= 0 ) - { - ret = _RGLCgUpdateProgramAtIndex( group, index, 1 ); - break; - } - else - { - return ( CGprogram )NULL; - } - } - group = group->next; - } - - if ( ret ) - return ret; - else - { - fp = fopen( program_file, "rb"); - - if ( fp == NULL ) - { - _RGLCgRaiseError( CG_FILE_READ_ERROR ); - return (CGprogram)NULL; - } - - unsigned int filetag = 0; - int res = fread( &filetag, sizeof( filetag ), 1, fp ); - if (!res) - { - fclose(fp); - _RGLCgRaiseError( CG_FILE_READ_ERROR ); - return ( CGprogram )NULL; - } - const unsigned int ElfTag = 0x7F454C46; - if ( filetag == ElfTag ) - { - fclose( fp ); - - group = _RGLCgCreateProgramGroupFromFile( ctx, program_file ); - if ( group ) - { - _CGprogramGroup *_group = ( _CGprogramGroup * )group; - _group->userCreated = false; - if ( entry == NULL ) - { - if ( group->programCount == 1 ) - ret = _RGLCgUpdateProgramAtIndex( group, 0, 1 ); - } - else - { - int index = _RGLCgGetProgramIndex( group, entry ); - if ( index == -1 ) - { - RARCH_ERR("Couldn't find the shader entry in the CG binary.\n"); - } - else - ret = _RGLCgUpdateProgramAtIndex( group, index, 1 ); - } - } - return ret; - } - } - } - - if ( !fp ) - { - fp = fopen( program_file, "rb" ); - if ( fp == NULL ) - { - _RGLCgRaiseError( CG_FILE_READ_ERROR ); - return ( CGprogram )NULL; - } - } - - size_t file_size = 0; - fseek(fp, 0, SEEK_END); - file_size = ftell(fp); - rewind(fp); - - char* ptr = (char*)malloc( file_size + 1 ); - if (ptr == NULL) - { - _RGLCgRaiseError( CG_MEMORY_ALLOC_ERROR ); - fclose( fp ); - return ( CGprogram )NULL; - } - - fread( ptr, file_size, 1, fp ); - fclose( fp ); - - if ( program_type == CG_SOURCE ) - ptr[file_size] = '\0'; - - CGprogram ret = cgCreateProgram( ctx, program_type, ptr, profile, entry, args ); - - free( ptr ); - - return ret; -} - -CG_API CGprogram cgCopyProgram( CGprogram program ) -{ - if ( !CG_IS_PROGRAM( program ) ) - { - _RGLCgRaiseError( CG_INVALID_PROGRAM_HANDLE_ERROR ); - return NULL; - } - _CGprogram* prog = _cgGetProgPtr( program ); - if ( prog == NULL ) - { - _RGLCgRaiseError( CG_INVALID_PROGRAM_HANDLE_ERROR ); - return ( CGprogram )NULL; - } - - _CGprogram* newprog; - size_t paddedProgramSize = 0; - size_t ucodeSize = 0; - - if (prog->header.profile == CG_PROFILE_SCE_FP_TYPEB || prog->header.profile == CG_PROFILE_SCE_FP_RSX) - { - paddedProgramSize = _RGLPad( sizeof( _CGprogram ), 16); - ucodeSize = prog->header.instructionCount * 16; - newprog = ( _CGprogram* )malloc(paddedProgramSize + ucodeSize); - } - else - { - newprog = (_CGprogram*)malloc(sizeof(_CGprogram)); - } - - if(newprog == NULL) - { - _RGLCgRaiseError( CG_MEMORY_ALLOC_ERROR ); - return ( CGprogram )NULL; - } - memset( newprog, 0, sizeof( _CGprogram ) ); - - newprog->header.profile = prog->header.profile; - newprog->parentContext = prog->parentContext; - - newprog->id = ( CGprogram )_RGLCreateName( &_CurrentContext->cgProgramNameSpace, newprog ); - - int success = 0; - switch ( prog->header.profile ) - { - case CG_PROFILE_SCE_VP_TYPEB: - case CG_PROFILE_SCE_VP_RSX: - case CG_PROFILE_SCE_FP_TYPEB: - case CG_PROFILE_SCE_FP_RSX: - success = _RGLPlatformCopyProgram( prog, newprog ); - break; - default: - _RGLCgRaiseError( CG_UNKNOWN_PROFILE_ERROR ); - success = 0; - break; - } - - if ( success == 0 ) - { - free( newprog ); - _RGLEraseName( &_CurrentContext->cgProgramNameSpace, ( jsName )newprog->id ); - return ( CGprogram )NULL; - } - - if (prog->header.profile == CG_PROFILE_SCE_FP_TYPEB || prog->header.profile == CG_PROFILE_SCE_FP_RSX) - { - newprog->ucode = (char*)newprog + paddedProgramSize; - memcpy((char*)newprog->ucode, (char*)prog->ucode, ucodeSize); - } - - if ( prog->programGroup ) - { - newprog->programGroup = prog->programGroup; - newprog->programIndexInGroup = -1; - _RGLCgUpdateProgramAtIndex( newprog->programGroup, -1, 1 ); - } - - _RGLCgProgramPushFront(newprog->parentContext, newprog); - - if(_cgProgramCopyHook) - _cgProgramCopyHook(newprog, prog); - - return newprog->id; -} - - -CG_API void cgDestroyProgram( CGprogram program ) -{ - if ( !CG_IS_PROGRAM( program ) ) - { - _RGLCgRaiseError( CG_INVALID_PROGRAM_HANDLE_ERROR ); - return; - } - - _CGprogram* ptr = _cgGetProgPtr( program ); - - if ( ptr == NULL ) - { - _RGLCgRaiseError( CG_INVALID_PROGRAM_HANDLE_ERROR ); - return; - } - - if ( ptr->programGroup ) - { - if ( !ptr->programGroup->userCreated ) - { - if ( ptr->programIndexInGroup != -1 && ptr->programGroup->programs[ptr->programIndexInGroup].refCount == 0 ) - { - _RGLCgRaiseError( CG_INVALID_PROGRAM_HANDLE_ERROR ); - return; - } - else - { - bool isGroupMember = ( ptr->programIndexInGroup != -1 ); - _RGLCgUpdateProgramAtIndex( ptr->programGroup, ptr->programIndexInGroup, -1 ); - if ( isGroupMember ) - return; - } - } - } - - _CGcontext* ctx = ptr->parentContext; - - if ( ptr == ctx->programList ) - { - _CGprogram* p = ctx->programList; - ctx->programList = p->next; - _RGLCgProgramErase( p ); - if(p != NULL) - free( p ); - } - else - { - _CGprogram* p = _RGLCgProgramFindPrev( ctx, ptr ); - - _CGprogram* next = p->next; - if ( next ) - { - p->next = next->next; - _RGLCgProgramErase( next ); - if(next != NULL) - free( next ); - } - } - return; -} - -static CGprogram _RGLCgUpdateProgramAtIndex( CGprogramGroup group, int index, int refcount ) -{ - if ( index < ( int )group->programCount ) - { - if ( index >= 0 ) - { - if ( refcount == 1 && group->programs[index].refCount == 1 ) - { - CGprogram res = cgCopyProgram( group->programs[index].program ); - return res; - } - group->programs[index].refCount += refcount; - } - - group->refCount += refcount; - if ( refcount < 0 ) - { - if ( group->refCount == 0 && !group->userCreated ) - { - _RGLCgDestroyProgramGroup( group ); - } - return NULL; - } - else - return group->programs[index].program; - } - else - return NULL; -} - -static void _RGLCgAddGroup( CGcontext ctx, CGprogramGroup group ) -{ - _CGcontext *context = _cgGetContextPtr( ctx ); - if ( !context->groupList ) - context->groupList = group; - else - { - _CGprogramGroup *current = context->groupList; - while ( current->next ) - current = current->next; - current->next = group; - } -} - -static void _RGLCgRemoveGroup( CGcontext ctx, CGprogramGroup group ) -{ - _CGcontext *context = _cgGetContextPtr( ctx ); - _CGprogramGroup *current = context->groupList; - _CGprogramGroup *previous = NULL; - while ( current && current != group ) - { - previous = current; - current = current->next; - } - if ( current ) - { - if ( !previous ) - context->groupList = current->next; - else - previous->next = current->next; - } -} - -CGprogramGroup _RGLCgCreateProgramGroupFromFile( CGcontext ctx, const char *group_file ) -{ - FILE *fp = fopen(group_file, "rb"); - - if(fp == NULL) - { - _RGLCgRaiseError( CG_FILE_READ_ERROR ); - return ( CGprogramGroup )NULL; - } - - size_t file_size = 0; - fseek( fp, 0, SEEK_END ); - file_size = ftell( fp ); - rewind( fp ); - - char *ptr = ( char* )malloc(file_size + 1); - if(ptr == NULL) - { - _RGLCgRaiseError( CG_MEMORY_ALLOC_ERROR ); - return ( CGprogramGroup )NULL; - } - - fread( ptr, file_size, 1, fp ); - fclose( fp ); - - CGprogramGroup group = _RGLCgCreateProgramGroup( ctx, group_file, ptr, file_size ); - if ( !group ) - free( ptr ); - - return group; -} - -CGprogramGroup _RGLCgCreateProgramGroup( CGcontext ctx, const char *name, void *ptr, int size ) -{ - _CGprogramGroup *group = NULL; - CGELFBinary elfBinary; - elfBinary.elfFile = NULL; - - while ( 1 ) - { - bool res = cgOpenElf( ptr, size, &elfBinary ); - if ( !res ) - break; - - size_t elfConstTableSize = ( size_t )elfBinary.consttabSize; - size_t elfStringTableSize = ( size_t )elfBinary.strtabSize; - - int programCount = elfBinary.shadertabSize / sizeof( CgProgramHeader ); - int i; - - size_t nvProgramNamesOffset = _RGLPad( sizeof( _CGprogramGroup ), sizeof( _CGnamedProgram ) ); - size_t nvDefaultValuesTableOffset = _RGLPad( nvProgramNamesOffset + programCount * sizeof( _CGnamedProgram ), 16 ); - - size_t nvStringTableOffset = nvDefaultValuesTableOffset + elfConstTableSize; - size_t structureSize = nvStringTableOffset + elfStringTableSize; - - group = ( CGprogramGroup )malloc( structureSize ); - if ( !group ) - break; - - group->ctx = ctx; - group->next = NULL; - group->programCount = ( unsigned int )programCount; - group->constantTable = ( unsigned int * )(( char* )group + nvDefaultValuesTableOffset ); - group->stringTable = ( unsigned int * )(( char* )group + nvStringTableOffset ); - group->programs = ( _CGnamedProgram * )(( char* )group + nvProgramNamesOffset ); - group->userCreated = true; - group->refCount = 0; - group->filedata = ( char* )ptr; - if ( name ) - { - int len = strlen( name ); - group->name = ( char* )malloc( len + 1 ); - if ( !group->name ) - break; - strlcpy( group->name, name, sizeof(group->name)); - } - else - group->name = NULL; - - if ( elfConstTableSize ) - memcpy(( char* )group + nvDefaultValuesTableOffset, elfBinary.consttab, elfConstTableSize ); - if ( elfStringTableSize ) - memcpy(( char* )group + nvStringTableOffset, elfBinary.strtab, elfStringTableSize ); - - _RGLCgAddGroup( ctx, group ); - - for ( i = 0;i < ( int )group->programCount;i++ ) - { - CgProgramHeader *cgShader = ( CgProgramHeader* )elfBinary.shadertab + i; - - if ( cgShader->profile == ( CGprofile )7005 ) - cgShader->profile = CG_PROFILE_SCE_VP_RSX; - if ( cgShader->profile == ( CGprofile )7006 ) - cgShader->profile = CG_PROFILE_SCE_FP_RSX; - - CGELFProgram elfProgram; - bool res = cgGetElfProgramByIndex( &elfBinary, i, &elfProgram ); - if ( !res ) - return false; - - CgProgramHeader *programHeader = cgShader; - char *ucode = ( char * )elfProgram.texttab; - CgParameterTableHeader *parameterHeader = ( CgParameterTableHeader * )elfProgram.paramtab; - - const char *programName = getSymbolByIndexInPlace( elfBinary.symtab, elfBinary.symbolSize, elfBinary.symbolCount, elfBinary.symbolstrtab, i + 1 ); - group->programs[i].name = programName; - group->programs[i].program = _RGLCgCreateProgram( ctx, ( CGprofile )cgShader->profile, programHeader, ucode, parameterHeader, ( const char* )group->stringTable, ( const float* )group->constantTable ); - _CGprogram *cgProgram = _cgGetProgPtr( group->programs[i].program ); - cgProgram->programGroup = group; - cgProgram->programIndexInGroup = i; - group->programs[i].refCount = 0; - } - break; - } - - return group; -} - -void _RGLCgDestroyProgramGroup( CGprogramGroup group ) -{ - _CGprogramGroup *_group = ( _CGprogramGroup * )group; - for ( int i = 0;i < ( int )_group->programCount;i++ ) - { - _CGprogram *cgProgram = _cgGetProgPtr( group->programs[i].program ); - cgProgram->programGroup = NULL; - cgDestroyProgram( _group->programs[i].program ); - } - if(_group->filedata != NULL) - free( _group->filedata ); - if ( _group->name ) - free( _group->name ); - - _RGLCgRemoveGroup( group->ctx, group ); - if(_group != NULL) - free( _group ); -} - -const char *_RGLCgGetProgramGroupName( CGprogramGroup group ) -{ - _CGprogramGroup *_group = ( _CGprogramGroup * )group; - return _group->name; -} - -int _RGLCgGetProgramIndex( CGprogramGroup group, const char *name ) -{ - int i; - for ( i = 0;i < ( int )group->programCount;i++ ) - { - if ( !strcmp( name, group->programs[i].name ) ) - return i; - } - return -1; -} - -CGprogram _RGLCgGetProgramAtIndex( CGprogramGroup group, unsigned int index ) -{ - return _RGLCgUpdateProgramAtIndex( group, index, 0 ); -} - -int _RGLCgGetProgramCount( CGprogramGroup group ) -{ - return group->programCount; -} - -static const RGLcgProfileMapType RGLcgProfileMap[] = -{ - {( CGprofile )6144, "CG_PROFILE_START", 1 }, - {( CGprofile )6145, "unknown", 1 }, -#define CG_PROFILE_MACRO(name, compiler_id, compiler_id_caps, compiler_opt,int_id,vertex_profile) \ - {CG_PROFILE_ ## compiler_id_caps, compiler_opt, vertex_profile}, -#include - {( CGprofile )0, "", 0 } -}; - -CG_API const char* cgGetProfileString( CGprofile profile ) -{ - const size_t arraysize = sizeof( RGLcgProfileMap ) / sizeof( RGLcgProfileMapType ); - unsigned int i = 0; - while ( i < arraysize ) - { - if ( profile == RGLcgProfileMap[i].id ) - { - return RGLcgProfileMap[i].string; - } - ++i; - } - return ""; -} - -CG_API CGerror cgGetError(void) -{ - CGerror err = _CurrentContext->RGLcgLastError; - _CurrentContext->RGLcgLastError = CG_NO_ERROR; - return err; -} - - -CG_API const char* cgGetErrorString( CGerror error ) -{ - static char strbuf[256]; - snprintf(strbuf, sizeof(strbuf), "%d", error); - return strbuf; -} - -void _RGLCgDestroyContextParam( CgRuntimeParameter* ptr ) -{ - if ( _cgParameterDestroyHook ) _cgParameterDestroyHook( ptr ); - _RGLEraseName( &_CurrentContext->cgParameterNameSpace, ( jsName )( ptr->id ) ); - free( ptr ); -} - -static int _RGLGetSizeofSubArray( const short *dimensions, int count ) -{ - int res = 1; - for ( int i = 0;i < count;i++ ) - res *= ( int )( *( dimensions++ ) ); - return res; -} - -static _CGparameter *_cgGetNamedParameter( _CGprogram* progPtr, const char* name, CGenum name_space, int *arrayIndex, const CgParameterEntry *_startEntry = NULL, int _entryCount = -1 ) -{ - if ( name == NULL ) - return NULL; - - *arrayIndex = -1; - int done = 0; - const char *structureEnd; - const char *structureStart = name; - int itemIndex = -1; - _CGprogram *program = progPtr; - - const CgParameterEntry *currentEntry; - const CgParameterEntry *lastEntry; - - int containerCount = -2; - if ( _startEntry && _entryCount != -1 ) - { - currentEntry = _startEntry; - containerCount = _entryCount; - } - else - { - currentEntry = program->parametersEntries; - } - lastEntry = program->parametersEntries + program->rtParametersCount; - - bool bWasUnrolled = false; - const char *prevStructureStart = structureStart; - - while (( !done ) && ( *structureStart ) && ( containerCount != -1 ) ) - { - structureEnd = strpbrk( structureStart, ".[" ); - if ( structureEnd == NULL ) - { - structureEnd = structureStart + strlen( structureStart ); - done = 1; - } - - if ( bWasUnrolled ) - { - bWasUnrolled = false; - structureStart = prevStructureStart; - } - char structName[256]; - int length = ( int )( structureEnd - structureStart ); - strncpy( structName, structureStart, length ); - structName[length] = '\0'; - prevStructureStart = structureStart; - structureStart = structureEnd + 1; - - bool found = false; - while ( !found && currentEntry < lastEntry && ( containerCount == -2 || containerCount > 0 ) ) - { - if ( !strncmp( structName, program->stringTable + currentEntry->nameOffset, length ) - && ( name_space == 0 || ( name_space == CG_GLOBAL && ( currentEntry->flags & CGPF_GLOBAL ) ) - || ( name_space == CG_PROGRAM && !( currentEntry->flags & CGPF_GLOBAL ) ) ) ) - { - if (( int )strlen( program->stringTable + currentEntry->nameOffset ) != length ) - { - if ( !strcmp( name, program->stringTable + currentEntry->nameOffset ) ) - { - found = true; - done = 1; - } - - if ( !strncmp( name, program->stringTable + currentEntry->nameOffset, length ) && - !strcmp( "[0]", program->stringTable + currentEntry->nameOffset + length ) ) - { - found = true; - done = 1; - } - } - else - found = true; - } - - if ( !found ) - { - int skipCount = 1; - while ( skipCount && currentEntry < lastEntry ) - { - if ( currentEntry->flags & CGP_STRUCTURE ) - { - const CgParameterStructure *parameterStructure = _RGLGetParameterStructure( program, currentEntry ); - skipCount += parameterStructure->memberCount; - } - else if ( currentEntry->flags & CGP_ARRAY ) - { - if ( currentEntry->flags & CGP_UNROLLED ) - { - const CgParameterArray *parameterArray = _RGLGetParameterArray( program, currentEntry ); - skipCount += _RGLGetSizeofSubArray(( short* )parameterArray->dimensions, parameterArray->dimensionCount ); - } - else - skipCount++; - } - currentEntry++; - skipCount--; - } - } - if ( containerCount != -2 ) - containerCount--; - } - - if ( found ) - { - switch ( currentEntry->flags & CGP_TYPE_MASK ) - { - case 0: - itemIndex = ( int )( currentEntry - program->parametersEntries ); - break; - case CGP_ARRAY: - { - - const CgParameterEntry *arrayEntry = currentEntry; - const CgParameterArray *parameterArray = _RGLGetParameterArray( program, arrayEntry ); - - if ( *structureEnd == '\0' ) - { - itemIndex = ( int )( currentEntry - program->parametersEntries ); - break; - } - - currentEntry++; - if ( currentEntry->flags &CGP_STRUCTURE ) - { - bWasUnrolled = true; - containerCount = _RGLGetSizeofSubArray(( short* )parameterArray->dimensions, parameterArray->dimensionCount ); - break; - } - else - { - const char *arrayStart = structureEnd; - const char *arrayEnd = structureEnd; - - int dimensionCount = 0; - int arrayCellIndex = 0; - while ( *arrayStart == '[' && dimensionCount < parameterArray->dimensionCount ) - { - arrayEnd = strchr( arrayStart + 1, ']' ); - int length = ( int )( arrayEnd - arrayStart - 1 ); - char indexString[16]; - strncpy( indexString, arrayStart + 1, length ); - indexString[length] = '\0'; - int index = atoi( indexString ); - int rowSize = parameterArray->dimensions[dimensionCount]; - if ( index >= rowSize ) - { - return NULL; - } - arrayCellIndex += index * _RGLGetSizeofSubArray(( short* )parameterArray->dimensions + dimensionCount, parameterArray->dimensionCount - dimensionCount - 1 ); - - arrayStart = arrayEnd + 1; - dimensionCount++; - } - structureEnd = arrayStart; - if ( *structureEnd == '\0' ) - done = 1; - - if ( done ) - { - ( *arrayIndex ) = arrayCellIndex; - itemIndex = ( int )( currentEntry - program->parametersEntries ); - } - } - } - break; - case CGP_STRUCTURE: - if ( done ) - itemIndex = ( int )( currentEntry - program->parametersEntries ); - else - { - const CgParameterStructure *parameterStructure = _RGLGetParameterStructure( program, currentEntry ); - containerCount = parameterStructure->memberCount; - } - break; - default: - break; - } - } - if ( found ) - { - if ( !bWasUnrolled ) - currentEntry++; - } - else - break; - } - - if ( itemIndex != -1 ) - return ( _CGparameter* )( program->runtimeParameters + itemIndex ); - else - return NULL; -} - -CG_API CGparameter cgGetNamedParameter( CGprogram prog, const char* name ) -{ - if ( !CG_IS_PROGRAM( prog ) ) - { - _RGLCgRaiseError( CG_INVALID_PROGRAM_HANDLE_ERROR ); - return ( CGparameter )NULL; - } - - _CGprogram* progPtr = _cgGetProgPtr( prog ); - int arrayIndex = -1; - CgRuntimeParameter *param = ( CgRuntimeParameter * )_cgGetNamedParameter( progPtr, name, ( CGenum )0, &arrayIndex ); - if ( param ) - { - int ret = ( int )param->id; - if ( arrayIndex != -1 ) - ret |= ( arrayIndex << CG_PARAMETERSIZE ); - return ( CGparameter )ret; - } - else - return ( CGparameter )NULL; -} - -static CGbool _RGLPlatformSupportsVertexProgram( CGprofile p ) -{ - if ( p == CG_PROFILE_SCE_VP_TYPEB ) - return CG_TRUE; - if ( p == CG_PROFILE_SCE_VP_TYPEC ) - return CG_TRUE; - if ( p == CG_PROFILE_SCE_VP_RSX ) - return CG_TRUE; - return CG_FALSE; -} - -CGGL_API CGbool cgGLIsProfileSupported( CGprofile profile ) -{ - if ( profile == ( CGprofile )7005 ) - profile = CG_PROFILE_SCE_VP_RSX; - if ( profile == ( CGprofile )7006 ) - profile = CG_PROFILE_SCE_FP_RSX; - - switch ( profile ) - { - case CG_PROFILE_SCE_VP_TYPEB: - case CG_PROFILE_SCE_VP_RSX: - return ( CGbool ) _RGLPlatformSupportsVertexProgram( profile ); - case CG_PROFILE_SCE_FP_TYPEB: - case CG_PROFILE_SCE_FP_RSX: - return ( CGbool ) _RGLPlatformSupportsFragmentProgram( profile ); - default: - return CG_FALSE; - } -} - -CGGL_API void cgGLEnableProfile( CGprofile profile ) -{ - if ( profile == ( CGprofile )7005 ) - profile = CG_PROFILE_SCE_VP_RSX; - if ( profile == ( CGprofile )7006 ) - profile = CG_PROFILE_SCE_FP_RSX; - - PSGLcontext* LContext = _CurrentContext; - struct _CGprogram* current = LContext->BoundFragmentProgram; - switch ( profile ) - { - case CG_PROFILE_SCE_VP_TYPEB: - case CG_PROFILE_SCE_VP_RSX: - LContext->VertexProgram = GL_TRUE; - LContext->needValidate |= PSGL_VALIDATE_VERTEX_PROGRAM | PSGL_VALIDATE_VERTEX_TEXTURES_USED; - break; - case CG_PROFILE_SCE_FP_TYPEB: - case CG_PROFILE_SCE_FP_RSX: - LContext->FragmentProgram = GL_TRUE; - if ( current ) - { - for (GLuint i = 0; i < current->samplerCount; ++i) - { - int unit = current->samplerUnits[i]; - _CurrentContext->TextureImageUnits[unit].currentTexture = _RGLGetCurrentTexture( &_CurrentContext->TextureImageUnits[unit], GL_TEXTURE_2D ); - } - } - LContext->needValidate |= PSGL_VALIDATE_FRAGMENT_PROGRAM | PSGL_VALIDATE_TEXTURES_USED; - break; - default: - _RGLCgRaiseError( CG_INVALID_PROFILE_ERROR ); - break; - } -} - -CGGL_API void cgGLDisableProfile( CGprofile profile ) -{ - if ( profile == ( CGprofile )7005 ) - profile = CG_PROFILE_SCE_VP_RSX; - if ( profile == ( CGprofile )7006 ) - profile = CG_PROFILE_SCE_FP_RSX; - - PSGLcontext* LContext = _CurrentContext; - switch ( profile ) - { - case CG_PROFILE_SCE_VP_TYPEB: - case CG_PROFILE_SCE_VP_RSX: - LContext->VertexProgram = GL_FALSE; - LContext->needValidate |= PSGL_VALIDATE_VERTEX_PROGRAM ; - break; - case CG_PROFILE_SCE_FP_TYPEB: - case CG_PROFILE_SCE_FP_RSX: - LContext->FragmentProgram = GL_FALSE; - for (GLuint unit = 0; unit < MAX_TEXTURE_UNITS; ++unit) - LContext->TextureImageUnits[unit].currentTexture = _RGLGetCurrentTexture( &LContext->TextureImageUnits[unit], GL_TEXTURE_2D ); - - LContext->needValidate |= PSGL_VALIDATE_FFX_FRAGMENT_PROGRAM | PSGL_VALIDATE_TEXTURES_USED; - break; - default: - _RGLCgRaiseError( CG_INVALID_PROFILE_ERROR ); - break; - } -} - - -CGGL_API CGprofile cgGLGetLatestProfile( CGGLenum profile_type ) -{ - switch ( profile_type ) - { - case CG_GL_VERTEX: - case CG_GL_FRAGMENT: - return _RGLPlatformGetLatestProfile( profile_type ); - default: - _RGLCgRaiseError( CG_INVALID_ENUMERANT_ERROR ); - return CG_PROFILE_UNKNOWN; - } -} - -CGGL_API void cgGLSetOptimalOptions( CGprofile profile ) -{ -} - -CGGL_API void cgGLLoadProgram( CGprogram program ) -{ -} - -CGGL_API void cgGLBindProgram( CGprogram program ) -{ - _CGprogram* ptr = _cgGetProgPtr( program ); - - switch ( ptr->header.profile ) - { - case CG_PROFILE_SCE_VP_TYPEB: - case 7005: - case CG_PROFILE_SCE_VP_RSX: - _CurrentContext->BoundVertexProgram = ptr; - _CurrentContext->needValidate |= PSGL_VALIDATE_VERTEX_PROGRAM | PSGL_VALIDATE_VERTEX_TEXTURES_USED; - break; - - case CG_PROFILE_SCE_FP_TYPEB: - case 7006: - case CG_PROFILE_SCE_FP_RSX: - _CurrentContext->BoundFragmentProgram = ptr; - _CurrentContext->needValidate |= PSGL_VALIDATE_FRAGMENT_PROGRAM | PSGL_VALIDATE_TEXTURES_USED; - - for ( GLuint index = 0; index < ptr->samplerCount; ++index ) - { - CgRuntimeParameter *rtParameter = ptr->runtimeParameters + ptr->samplerIndices[index]; - CgParameterResource *parameter = ( CgParameterResource * )( ptr->parameterResources + rtParameter->parameterEntry->typeIndex ); - unsigned int unit = parameter->resource - CG_TEXUNIT0; - - _CurrentContext->TextureImageUnits[unit].fragmentTarget = rtParameter->glType; - _CurrentContext->TextureImageUnits[unit].currentTexture = _RGLGetCurrentTexture( &_CurrentContext->TextureImageUnits[unit], GL_TEXTURE_2D ); - } - break; - - default: - _RGLCgRaiseError( CG_INVALID_PROFILE_ERROR ); - return; - } - -} - -CGGL_API void cgGLUnbindProgram( CGprofile profile ) -{ - switch ( profile ) - { - case CG_PROFILE_SCE_VP_TYPEB: - case CG_PROFILE_SCE_VP_RSX: - case 7005: - _CurrentContext->BoundVertexProgram = NULL; - _CurrentContext->needValidate |= PSGL_VALIDATE_VERTEX_PROGRAM; - break; - case CG_PROFILE_SCE_FP_TYPEB: - case CG_PROFILE_SCE_FP_RSX: - case 7006: - _CurrentContext->BoundFragmentProgram = NULL; - for (GLuint unit = 0; unit < MAX_TEXTURE_UNITS; ++unit) - _CurrentContext->TextureImageUnits[unit].currentTexture = _RGLGetCurrentTexture( &_CurrentContext->TextureImageUnits[unit], GL_TEXTURE_2D ); - - _CurrentContext->needValidate |= PSGL_VALIDATE_FFX_FRAGMENT_PROGRAM | PSGL_VALIDATE_TEXTURES_USED; - break; - default: - _RGLCgRaiseError( CG_INVALID_PROFILE_ERROR ); - return; - } - -} - -CGGL_API void cgGLSetParameter1f( CGparameter param, float x ) -{ - CgRuntimeParameter *ptr = _cgGetParamPtr( param ); - - float v[4] = {x, x, x, x}; - ptr->setterIndex( ptr, v, CG_GETINDEX( param ) ); -} - -CGGL_API void cgGLSetParameter2f( CGparameter param, float x, float y ) -{ - CgRuntimeParameter *ptr = _cgGetParamPtr( param ); - - float v[4] = {x, y, y, y}; - ptr->setterIndex( ptr, v, CG_GETINDEX( param ) ); -} - -CGGL_API void cgGLSetParameterPointer -( CGparameter param, - GLint fsize, - GLenum type, - GLsizei stride, - const GLvoid *pointer ) -{ - - CgRuntimeParameter *_ptr = _cgGetParamPtr( param ); - - const CgParameterResource *parameterResource = _RGLGetParameterResource( _ptr->program, _ptr->parameterEntry ); - GLuint index = ( GLuint )( parameterResource->resource - CG_ATTR0 ); - - _RGLVertexAttribPointerNV( - index, - fsize, - type, - ( _ptr->parameterEntry->flags & CGP_NORMALIZE ) ? 1 : 0, - stride, - pointer ); -} - -CGGL_API void cgGLEnableClientState( CGparameter param ) -{ - CgRuntimeParameter *_ptr = _cgGetParamPtr( param ); - - const CgParameterResource *parameterResource = _RGLGetParameterResource( _ptr->program, _ptr->parameterEntry ); - - GLuint index = ( GLuint )( parameterResource->resource - CG_ATTR0 ); - _RGLEnableVertexAttribArrayNV( index ); -} - -CGGL_API void cgGLDisableClientState( CGparameter param ) -{ - CgRuntimeParameter *_ptr = _cgGetParamPtr( param ); - - const CgParameterResource *parameterResource = _RGLGetParameterResource( _ptr->program, _ptr->parameterEntry ); - - GLuint index = ( GLuint )( parameterResource->resource - CG_ATTR0 ); - _RGLDisableVertexAttribArrayNV( index ); -} - -CGGL_API void cgGLSetTextureParameter( CGparameter param, GLuint texobj ) -{ - CgRuntimeParameter* ptr = _cgGetParamPtr(param); - - ptr->samplerSetter( ptr, &texobj, 0 ); -} - -CGGL_API void cgGLEnableTextureParameter( CGparameter param ) -{ - CgRuntimeParameter* ptr = _cgGetParamPtr(param); - ptr->samplerSetter( ptr, NULL, 0 ); -} - -static void _RGLCgContextPushFront(_CGcontext* ctx) -{ - if(_CurrentContext->RGLcgContextHead) - { - _CGcontext* head = _cgGetContextPtr( _CurrentContext->RGLcgContextHead ); - ctx->next = head; - } - _CurrentContext->RGLcgContextHead = ctx->id; -} - -static void destroy_context(_CGcontext*ctx) -{ - if (_cgContextDestroyHook) - _cgContextDestroyHook(ctx); - - _RGLEraseName( &_CurrentContext->cgContextNameSpace, ( jsName )ctx->id ); - memset(ctx, 0, sizeof( *ctx ) ); - ctx->compileType = CG_UNKNOWN; - - free( ctx ); -} - -CG_API CGcontext cgCreateContext(void) -{ - _CGcontext* ptr = NULL; - - ptr = ( _CGcontext* )malloc( sizeof( _CGcontext ) ); - if ( ptr == NULL ) - { - _RGLCgRaiseError( CG_MEMORY_ALLOC_ERROR ); - return ( CGcontext )NULL; - } - - memset( ptr, 0, sizeof( *ptr ) ); - ptr->compileType = CG_UNKNOWN; - - CGcontext result = ( CGcontext )_RGLCreateName( &_CurrentContext->cgContextNameSpace, ptr ); - if ( !result ) - { - free( ptr ); - return NULL; - } - - ptr->id = result; - ptr->defaultProgram.parentContext = ptr; - - _RGLCgContextPushFront( ptr ); - - if ( _cgContextCreateHook ) _cgContextCreateHook( ptr ); - - return result; -} - -CG_API void cgDestroyContext(CGcontext c) -{ - if(!CG_IS_CONTEXT(c)) - { - _RGLCgRaiseError( CG_INVALID_CONTEXT_HANDLE_ERROR ); - return; - } - - _CGcontext* ctx = _cgGetContextPtr( c ); - - _RGLCgProgramErase( &ctx->defaultProgram ); - - while ( ctx->programList ) - { - _CGprogram * p = ctx->programList; - ctx->programList = p->next; - _RGLCgProgramErase( p ); - if(p != NULL) - free( p ); - } - - _CGcontext * const head = _cgGetContextPtr( _CurrentContext->RGLcgContextHead ); - if ( head != ctx ) - { - _CGcontext* ptr = head; - while ( ptr->next != ctx ) ptr = ptr->next; - ptr->next = ctx->next; - destroy_context( ctx ); - } - else - { - - _CGcontext* second = head->next; - destroy_context( head ); - - if ( second ) - _CurrentContext->RGLcgContextHead = second->id; - else - _CurrentContext->RGLcgContextHead = 0; - } -} - -CG_API const char* cgGetLastListing( CGcontext c ) -{ - if ( !CG_IS_CONTEXT( c ) ) - { - _RGLCgRaiseError( CG_INVALID_CONTEXT_HANDLE_ERROR ); - return NULL; - } - - return NULL; -} - -void _RGLCgRaiseError( CGerror error ) -{ - _CurrentContext->RGLcgLastError = error; - - if(!context_shutdown) - { - RARCH_ERR("Cg error: %d.\n", error); - - if ( _CurrentContext->RGLcgErrorCallbackFunction ) - _CurrentContext->RGLcgErrorCallbackFunction(); - } -} - -unsigned int _RGLCountFloatsInCgType( CGtype type ) -{ - int size = 0; - switch ( type ) - { - case CG_FLOAT: - case CG_FLOAT1: - case CG_FLOAT1x1: - size = 1; - break; - case CG_FLOAT2: - case CG_FLOAT2x1: - case CG_FLOAT1x2: - size = 2; - break; - case CG_FLOAT3: - case CG_FLOAT3x1: - case CG_FLOAT1x3: - size = 3; - break; - case CG_FLOAT4: - case CG_FLOAT4x1: - case CG_FLOAT1x4: - case CG_FLOAT2x2: - size = 4; - break; - case CG_FLOAT2x3: - case CG_FLOAT3x2: - size = 6; - break; - case CG_FLOAT2x4: - case CG_FLOAT4x2: - size = 8; - break; - case CG_FLOAT3x3: - size = 9; - break; - case CG_FLOAT3x4: - case CG_FLOAT4x3: - size = 12; - break; - case CG_FLOAT4x4: - size = 16; - break; - case CG_SAMPLER1D: - case CG_SAMPLER2D: - case CG_SAMPLER3D: - case CG_SAMPLERRECT: - case CG_SAMPLERCUBE: - case CG_BOOL: - case CG_HALF: - case CG_HALF1: - case CG_HALF1x1: - size = 1; - break; - case CG_HALF2: - case CG_HALF2x1: - case CG_HALF1x2: - size = 2; - break; - case CG_HALF3: - case CG_HALF3x1: - case CG_HALF1x3: - size = 3; - break; - case CG_HALF4: - case CG_HALF4x1: - case CG_HALF1x4: - case CG_HALF2x2: - size = 4; - break; - case CG_HALF2x3: - case CG_HALF3x2: - size = 6; - break; - case CG_HALF2x4: - case CG_HALF4x2: - size = 8; - break; - case CG_HALF3x3: - size = 9; - break; - case CG_HALF3x4: - case CG_HALF4x3: - size = 12; - break; - case CG_HALF4x4: - size = 16; - break; - case CG_INT: - case CG_INT1: - case CG_INT1x1: - size = 1; - break; - case CG_INT2: - case CG_INT2x1: - case CG_INT1x2: - size = 2; - break; - case CG_INT3: - case CG_INT3x1: - case CG_INT1x3: - size = 3; - break; - case CG_INT4: - case CG_INT4x1: - case CG_INT1x4: - case CG_INT2x2: - size = 4; - break; - case CG_INT2x3: - case CG_INT3x2: - size = 6; - break; - case CG_INT2x4: - case CG_INT4x2: - size = 8; - break; - case CG_INT3x3: - size = 9; - break; - case CG_INT3x4: - case CG_INT4x3: - size = 12; - break; - case CG_INT4x4: - size = 16; - break; - case CG_BOOL1: - case CG_BOOL1x1: - size = 1; - break; - case CG_BOOL2: - case CG_BOOL2x1: - case CG_BOOL1x2: - size = 2; - break; - case CG_BOOL3: - case CG_BOOL3x1: - case CG_BOOL1x3: - size = 3; - break; - case CG_BOOL4: - case CG_BOOL4x1: - case CG_BOOL1x4: - case CG_BOOL2x2: - size = 4; - break; - case CG_BOOL2x3: - case CG_BOOL3x2: - size = 6; - break; - case CG_BOOL2x4: - case CG_BOOL4x2: - size = 8; - break; - case CG_BOOL3x3: - size = 9; - break; - case CG_BOOL3x4: - case CG_BOOL4x3: - size = 12; - break; - case CG_BOOL4x4: - size = 16; - break; - case CG_FIXED: - case CG_FIXED1: - case CG_FIXED1x1: - size = 1; - break; - case CG_FIXED2: - case CG_FIXED2x1: - case CG_FIXED1x2: - size = 2; - break; - case CG_FIXED3: - case CG_FIXED3x1: - case CG_FIXED1x3: - size = 3; - break; - case CG_FIXED4: - case CG_FIXED4x1: - case CG_FIXED1x4: - case CG_FIXED2x2: - size = 4; - break; - case CG_FIXED2x3: - case CG_FIXED3x2: - size = 6; - break; - case CG_FIXED2x4: - case CG_FIXED4x2: - size = 8; - break; - case CG_FIXED3x3: - size = 9; - break; - case CG_FIXED3x4: - case CG_FIXED4x3: - size = 12; - break; - case CG_FIXED4x4: - size = 16; - break; - default: - size = 0; - break; - } - return size; -} - -void _cgRaiseInvalidParam( CgRuntimeParameter*p, const void*v ) -{ - _RGLCgRaiseError( CG_INVALID_PARAMETER_ERROR ); -} -void _cgRaiseInvalidParamIndex( CgRuntimeParameter*p, const void*v, const int index ) -{ - _RGLCgRaiseError( CG_INVALID_PARAMETER_ERROR ); -} - -void _cgRaiseNotMatrixParam( CgRuntimeParameter*p, const void*v ) -{ - _RGLCgRaiseError( CG_NOT_MATRIX_PARAM_ERROR ); -} - -void _cgRaiseNotMatrixParamIndex( CgRuntimeParameter*p, const void*v, const int index ) -{ - _RGLCgRaiseError( CG_NOT_MATRIX_PARAM_ERROR ); -} - -void _cgIgnoreSetParam( CgRuntimeParameter*p, const void*v ) {} -void _cgIgnoreSetParamIndex( CgRuntimeParameter*p, const void*v, const int index ) {} - -#define CG_DATATYPE_MACRO(name, compiler_name, enum_name, base_enum, nrows, ncols,classname) \ - nrows , -static int _typesRowCount[] = - { -#include "Cg/cg_datatypes.h" - }; - -#define CG_DATATYPE_MACRO(name, compiler_name, enum_name, base_enum, nrows, ncols,classname) \ - ncols , -static int _typesColCount[] = - { -#include "Cg/cg_datatypes.h" - }; - -unsigned int _RGLGetTypeRowCount( CGtype parameterType ) -{ - int typeIndex = parameterType - 1 - CG_TYPE_START_ENUM; - return _typesRowCount[typeIndex]; -} - -unsigned int _RGLGetTypeColCount( CGtype parameterType ) -{ - int typeIndex = parameterType - 1 - CG_TYPE_START_ENUM; - return _typesColCount[typeIndex]; -} - -CGGL_API void cgGLSetMatrixParameterfc( CGparameter param, const float *matrix ) -{ - CgRuntimeParameter* ptr = _cgGetParamPtr( param ); - ptr->settercIndex( ptr, matrix, CG_GETINDEX( param ) ); -} diff --git a/console/rgl/ps3/rgl.h b/console/rgl/ps3/rgl.h deleted file mode 100644 index 34977ff6eb..0000000000 --- a/console/rgl/ps3/rgl.h +++ /dev/null @@ -1,1048 +0,0 @@ -#ifndef _RGL_H -#define _RGL_H - -#include "gl.h" -#include "glext.h" -#include "base.hpp" - -#ifdef __PSL1GHT__ -#include -#include -#include -#include -#include "../../../ps3/sdk_defines.h" -#define CGerror int -typedef void (* CGerrorCallbackFunc)(void); -typedef struct _CGcontext *CGcontext; -#else -#include -#endif - -#define MAX_COLOR_ATTACHMENTS 4 -#define SUBPIXEL_ADJUST (0.5/(1<<12)) - -#define gmmIdIsMain(id) (((GmmBaseBlock *)id)->isMain) -#define gmmAddressToOffset(address, isMain) ((isMain) ? (address)-pGmmMainAllocator->memoryBase : (address)-pGmmLocalAllocator->memoryBase) - - -#ifdef __cplusplus -extern "C" -{ -#endif - -typedef enum RGLEnum -{ - RGL_NONE = 0x0000, - RGL_COLOR_BUFFER_BIT = 0x4000, - RGL_ZERO = 0, - RGL_ONE = 1, - RGL_SRC_COLOR = 0x0300, - RGL_ONE_MINUS_SRC_COLOR = 0x0301, - RGL_SRC_ALPHA = 0x0302, - RGL_ONE_MINUS_SRC_ALPHA = 0x0303, - RGL_DST_ALPHA = 0x0304, - RGL_ONE_MINUS_DST_ALPHA = 0x0305, - RGL_DST_COLOR = 0x0306, - RGL_ONE_MINUS_DST_COLOR = 0x0307, - RGL_SRC_ALPHA_SATURATE = 0x0308, - RGL_ONE_MINUS_CONSTANT_COLOR = 0x8002, - RGL_CONSTANT_ALPHA = 0x8003, - RGL_ONE_MINUS_CONSTANT_ALPHA = 0x8004, - RGL_MIN = 0x8007, - RGL_MAX = 0x8008, - RGL_FUNC_SUBTRACT = 0x800A, - RGL_FUNC_REVERSE_SUBTRACT = 0x800B, - RGL_LUMINANCE8 = 0x8040, - RGL_LUMINANCE16 = 0x8042, - RGL_ALPHA8 = 0x803C, - RGL_ALPHA16 = 0x803E, - RGL_INTENSITY8 = 0x804B, - RGL_INTENSITY16 = 0x804D, - RGL_LUMINANCE8_ALPHA8 = 0x8045, - RGL_LUMINANCE16_ALPHA16 = 0x8048, - RGL_HILO8 = 0x885E, - RGL_HILO16 = 0x86F8, - RGL_ARGB8 = 0x6007, - RGL_BGRA8 = 0xff01, - RGL_RGBA8 = 0x8058, - RGL_ABGR8 = 0xff02, - RGL_XBGR8 = 0xff03, - RGL_RGBX8 = 0xff07, - RGL_FLOAT_R32 = 0x8885, - RGL_FLOAT_RGBA16 = 0x888A, - RGL_FLOAT_RGBA32 = 0x888B, - RGL_FLOAT_RGBX16 = 0xff04, - RGL_FLOAT_RGBX32 = 0xff05, - RGL_LUMINANCE32F_ARB = 0x8818, - RGL_ALPHA_LUMINANCE16F_SCE = 0x600B, - RGL_RGB5_A1_SCE = 0x600C, - RGL_RGB565_SCE = 0x600D, - RGL_DITHER = 0x0bd0, - RGL_PSHADER_SRGB_REMAPPING = 0xff06, - RGL_VERTEX_ATTRIB_ARRAY0 = 0x8650, - RGL_VERTEX_ATTRIB_ARRAY1 = 0x8651, - RGL_VERTEX_ATTRIB_ARRAY2 = 0x8652, - RGL_VERTEX_ATTRIB_ARRAY3 = 0x8653, - RGL_VERTEX_ATTRIB_ARRAY4 = 0x8654, - RGL_VERTEX_ATTRIB_ARRAY5 = 0x8655, - RGL_VERTEX_ATTRIB_ARRAY6 = 0x8656, - RGL_VERTEX_ATTRIB_ARRAY7 = 0x8657, - RGL_VERTEX_ATTRIB_ARRAY8 = 0x8658, - RGL_VERTEX_ATTRIB_ARRAY9 = 0x8659, - RGL_VERTEX_ATTRIB_ARRAY10 = 0x865a, - RGL_VERTEX_ATTRIB_ARRAY11 = 0x865b, - RGL_VERTEX_ATTRIB_ARRAY12 = 0x865c, - RGL_VERTEX_ATTRIB_ARRAY13 = 0x865d, - RGL_VERTEX_ATTRIB_ARRAY14 = 0x865e, - RGL_VERTEX_ATTRIB_ARRAY15 = 0x865f, - RGL_CLAMP = 0x2900, - RGL_REPEAT = 0x2901, - RGL_CLAMP_TO_EDGE = 0x812F, - RGL_CLAMP_TO_BORDER = 0x812D, - RGL_MIRRORED_REPEAT = 0x8370, - RGL_MIRROR_CLAMP = 0x8742, - RGL_MIRROR_CLAMP_TO_EDGE = 0x8743, - RGL_MIRROR_CLAMP_TO_BORDER = 0x8912, - RGL_GAMMA_REMAP_RED_BIT = 0x0001, - RGL_GAMMA_REMAP_GREEN_BIT = 0x0002, - RGL_GAMMA_REMAP_BLUE_BIT = 0x0004, - RGL_GAMMA_REMAP_ALPHA_BIT = 0x0008, - RGL_TEXTURE_WRAP_S = 0x2802, - RGL_TEXTURE_WRAP_T = 0x2803, - RGL_TEXTURE_WRAP_R = 0x8072, - RGL_TEXTURE_MIN_FILTER = 0x2801, - RGL_TEXTURE_MAG_FILTER = 0x2800, - RGL_TEXTURE_MAX_ANISOTROPY = 0x84FE, - RGL_TEXTURE_COMPARE_FUNC = 0x884D, - RGL_TEXTURE_MIN_LOD = 0x813A, - RGL_TEXTURE_MAX_LOD = 0x813B, - RGL_TEXTURE_LOD_BIAS = 0x8501, - RGL_TEXTURE_BORDER_COLOR = 0x1004, - RGL_TEXTURE_GAMMA_REMAP = 0xff30, - RGL_VERTEX_PROGRAM = 0x8620, - RGL_FRAGMENT_PROGRAM = 0x8804, - RGL_FLOAT = 0x1406, - RGL_HALF_FLOAT = 0x140B, - RGL_SHORT = 0x1402, - RGL_UNSIGNED_BYTE = 0x1401, - RGL_UNSIGNED_SHORT = 0x1403, - RGL_UNSIGNED_INT = 0x1405, - RGL_BYTE = 0x1400, - RGL_INT = 0x1404, - RGL_CMP = 0x6020, -} RGLEnum; - -typedef struct PSGLdevice PSGLdevice; -typedef struct PSGLcontext PSGLcontext; -typedef struct RGLViewportState RGLViewportState; -struct RGLState; -extern RGLState _RGLState; - -struct RGLViewportState -{ - GLint x, y, w, h; - GLfloat xScale, xCenter; - GLfloat yScale, yCenter; -}; - -struct jsFramebufferAttachment -{ - GLenum type; - GLuint name; - GLenum textureTarget; - jsFramebufferAttachment(): type( GL_NONE ), name( 0 ), textureTarget( GL_NONE ) {}; -}; - - -struct jsFramebuffer -{ - jsFramebufferAttachment color[MAX_COLOR_ATTACHMENTS]; - GLboolean needValidate; - jsFramebuffer(): needValidate( GL_TRUE ) {}; - virtual ~jsFramebuffer() {}; -}; - -#define RGLBIT_GET(f,n) ((f) & (1<<(n))) -#define RGLBIT_TRUE(f,n) ((f) |= (1<<(n))) -#define RGLBIT_FALSE(f,n) ((f) &= ~(1<<(n))) -#define RGLBIT_ASSIGN(f,n,val) do { if(val) RGLBIT_TRUE(f,n); else RGLBIT_FALSE(f,n); } while(0) - -typedef struct -{ - GLfloat X, Y , Z, W; -} jsPositionXYZW; - -typedef struct -{ - GLfloat X, Y , Z; -} jsPositionXYZ; - -typedef struct -{ - GLfloat R, G, B, A; -} jsColorRGBAf; - -typedef struct -{ - int X, Y, XSize, YSize; -} jsViewPort; - -typedef struct -{ - int id; - GLuint offset; - GLuint size; - GLuint pitch; - GLuint bank; -} jsTiledRegion; - -enum -{ - IMAGE_DATASTATE_UNSET = 0x0, - IMAGE_DATASTATE_HOST = 0x1, - IMAGE_DATASTATE_GPU = 0x2 -}; - -typedef struct jsImage_ -{ - GLboolean isSet; - - GLenum internalFormat; - GLenum format; - GLenum type; - GLsizei width; - GLsizei height; - GLsizei alignment; - - GLsizei storageSize; - GLsizei xstride, ystride; - GLuint xblk, yblk; - - char *data; - char *mallocData; - GLsizei mallocStorageSize; - GLenum dataState; -} jsImage; - -typedef struct -{ - GLenum format; - GLenum type; - GLsizei width; - GLsizei height; - GLsizei xstride; - GLsizei ystride; - void* data; -} jsRaster; - -#define TEXTURE_REVALIDATE_LAYOUT 0x01 -#define TEXTURE_REVALIDATE_IMAGES 0x02 -#define TEXTURE_REVALIDATE_PARAMETERS 0x04 - -typedef struct jsBufferObject jsBufferObject; - -typedef struct -{ - GLuint revalidate; - GLuint target; - - GLuint minFilter; - GLuint magFilter; - GLuint gammaRemap; - GLenum usage; - - GLboolean isRenderTarget; - GLboolean isComplete; - - jsBufferObject *referenceBuffer; - GLintptr offset; - - RGL::Vector framebuffers; - - GLuint imageCount; - jsImage* image; - void * platformTexture[]; -} -jsTexture; - -#define MAX_TEXTURE_COORDS 8 -#define MAX_TEXTURE_IMAGE_UNITS 16 -#define MAX_VERTEX_TEXTURE_IMAGE_UNITS 4 - -#define MAX_TEXTURE_UNITS 4 - -#define MAX_VERTEX_ATTRIBS 16 - -typedef struct -{ - GLuint bound2D; - jsTexture* default2D; - GLenum fragmentTarget; - GLenum envMode; - jsColorRGBAf envColor; - jsTexture* currentTexture; -} jsTextureImageUnit; - -enum -{ - FRAMEBUFFER_ATTACHMENT_NONE, - FRAMEBUFFER_ATTACHMENT_RENDERBUFFER, - FRAMEBUFFER_ATTACHMENT_TEXTURE, -}; - -typedef enum PSGLtvStandard -{ - PSGL_TV_STANDARD_NONE, - PSGL_TV_STANDARD_NTSC_M, - PSGL_TV_STANDARD_NTSC_J, - PSGL_TV_STANDARD_PAL_M, - PSGL_TV_STANDARD_PAL_B, - PSGL_TV_STANDARD_PAL_D, - PSGL_TV_STANDARD_PAL_G, - PSGL_TV_STANDARD_PAL_H, - PSGL_TV_STANDARD_PAL_I, - PSGL_TV_STANDARD_PAL_N, - PSGL_TV_STANDARD_PAL_NC, - PSGL_TV_STANDARD_HD480I, - PSGL_TV_STANDARD_HD480P, - PSGL_TV_STANDARD_HD576I, - PSGL_TV_STANDARD_HD576P, - PSGL_TV_STANDARD_HD720P, - PSGL_TV_STANDARD_HD1080I, - PSGL_TV_STANDARD_HD1080P, - PSGL_TV_STANDARD_1280x720_ON_VESA_1280x768 = 128, - PSGL_TV_STANDARD_1280x720_ON_VESA_1280x1024, - PSGL_TV_STANDARD_1920x1080_ON_VESA_1920x1200, -} PSGLtvStandard; - -typedef enum PSGLdeviceConnector -{ - PSGL_DEVICE_CONNECTOR_NONE, - PSGL_DEVICE_CONNECTOR_VGA, - PSGL_DEVICE_CONNECTOR_DVI, - PSGL_DEVICE_CONNECTOR_HDMI, - PSGL_DEVICE_CONNECTOR_COMPOSITE, - PSGL_DEVICE_CONNECTOR_SVIDEO, - PSGL_DEVICE_CONNECTOR_COMPONENT, -} PSGLdeviceConnector; - -typedef enum PSGLbufferingMode -{ - PSGL_BUFFERING_MODE_SINGLE = 1, - PSGL_BUFFERING_MODE_DOUBLE = 2, - PSGL_BUFFERING_MODE_TRIPLE = 3, -} PSGLbufferingMode; - -typedef enum RescRatioMode -{ - RESC_RATIO_MODE_FULLSCREEN, - RESC_RATIO_MODE_LETTERBOX, - RESC_RATIO_MODE_PANSCAN, -} RescRatioMode; - -typedef enum RescPalTemporalMode -{ - RESC_PAL_TEMPORAL_MODE_50_NONE, - RESC_PAL_TEMPORAL_MODE_60_DROP, - RESC_PAL_TEMPORAL_MODE_60_INTERPOLATE, - RESC_PAL_TEMPORAL_MODE_60_INTERPOLATE_30_DROP, - RESC_PAL_TEMPORAL_MODE_60_INTERPOLATE_DROP_FLEXIBLE, -} RescPalTemporalMode; - -typedef enum RescInterlaceMode -{ - RESC_INTERLACE_MODE_NORMAL_BILINEAR, - RESC_INTERLACE_MODE_INTERLACE_FILTER, -} RescInterlaceMode; - -typedef struct -{ - GLuint enable; - GLenum colorFormat; - GLenum depthFormat; - GLenum multisamplingMode; - PSGLtvStandard TVStandard; - PSGLdeviceConnector connector; - PSGLbufferingMode bufferingMode; - GLuint width; - GLuint height; - GLuint renderWidth; - GLuint renderHeight; - RescRatioMode rescRatioMode; - RescPalTemporalMode rescPalTemporalMode; - RescInterlaceMode rescInterlaceMode; - GLfloat horizontalScale; - GLfloat verticalScale; -} PSGLdeviceParameters; - -struct PSGLdevice -{ - PSGLdeviceParameters deviceParameters; - GLvoid* rasterDriver; - char platformDevice[]; -}; - -typedef struct -{ - GLenum mode; - GLint firstVertex; - GLsizei vertexCount; - - GLuint xferTotalSize; - GLuint indexXferOffset; - GLuint indexXferSize; - GLuint attribXferTotalSize; - GLuint attribXferOffset[MAX_VERTEX_ATTRIBS]; - GLuint attribXferSize[MAX_VERTEX_ATTRIBS]; -} jsDrawParams; - -#define _RGL_ATTRIB_POSITION_INDEX 0 -#define _RGL_ATTRIB_WEIGHT_INDEX 1 -#define _RGL_ATTRIB_NORMAL_INDEX 2 -#define _RGL_ATTRIB_PRIMARY_COLOR_INDEX 3 -#define _RGL_ATTRIB_SECONDARY_COLOR_INDEX 4 -#define _RGL_ATTRIB_FOG_COORD_INDEX 5 -#define _RGL_ATTRIB_POINT_SIZE_INDEX 6 -#define _RGL_ATTRIB_BLEND_INDICES_INDEX 7 -#define _RGL_ATTRIB_TEX_COORD0_INDEX 8 -#define _RGL_ATTRIB_TEX_COORD1_INDEX 9 -#define _RGL_ATTRIB_TEX_COORD2_INDEX 10 -#define _RGL_ATTRIB_TEX_COORD3_INDEX 11 -#define _RGL_ATTRIB_TEX_COORD4_INDEX 12 -#define _RGL_ATTRIB_TEX_COORD5_INDEX 13 -#define _RGL_ATTRIB_TEX_COORD6_INDEX 14 -#define _RGL_ATTRIB_TEX_COORD7_INDEX 15 - -typedef struct -{ - GLvoid *clientData; - GLuint clientSize; - GLenum clientType; - GLsizei clientStride; - GLuint arrayBuffer; - GLfloat value[4]; - GLuint frequency; - GLboolean normalized; -} __attribute__((aligned (16))) jsAttribute; - -typedef struct -{ - jsAttribute attrib[MAX_VERTEX_ATTRIBS]; - unsigned int DirtyMask; - unsigned int EnabledMask; - unsigned int NeedsConversionMask; - unsigned int HasVBOMask; - unsigned int ModuloMask; -} __attribute__((aligned (16))) jsAttributeState; - -typedef struct -{ - jsAttributeState attribs; - GLboolean dirty; - unsigned int beenUpdatedMask; - GLvoid *cmdBuffer; - GLuint cmdNumWords; -} __attribute__((aligned (16))) jsAttribSet; - -struct jsBufferObject -{ - GLuint refCount; - GLsizeiptr size; - GLenum usage; - GLboolean mapped; - GLenum internalFormat; - GLuint width; - GLuint height; - RGL::Vector textureReferences; - RGL::Vector attribSets; - void *platformBufferObject[]; -}; - -typedef struct jsNameSpace -{ - void** data; - void** firstFree; - unsigned long capacity; -} jsNameSpace; - -typedef void *(*jsTexNameSpaceCreateFunction)(void); -typedef void(*jsTexNameSpaceDestroyFunction)(void *); - -typedef struct jsTexNameSpace -{ - void** data; - GLuint capacity; - jsTexNameSpaceCreateFunction create; - jsTexNameSpaceDestroyFunction destroy; -} -jsTexNameSpace; - -struct PSGLcontext -{ - GLenum error; - jsViewPort ViewPort; - jsAttributeState defaultAttribs0; - jsAttributeState *attribs; - jsTexNameSpace attribSetNameSpace; - GLuint attribSetName; - GLboolean attribSetDirty; - jsColorRGBAf ClearColor; - GLboolean ShaderSRGBRemap; - GLboolean Blending; - GLboolean BlendingMrt[3]; - GLenum BlendEquationRGB; - GLenum BlendEquationAlpha; - GLenum BlendFactorSrcRGB; - GLenum BlendFactorDestRGB; - GLenum BlendFactorSrcAlpha; - GLenum BlendFactorDestAlpha; - jsColorRGBAf BlendColor; - jsTexNameSpace textureNameSpace; - GLuint ActiveTexture; - GLuint CS_ActiveTexture; - jsTextureImageUnit TextureImageUnits[MAX_TEXTURE_IMAGE_UNITS]; - jsTextureImageUnit* CurrentImageUnit; - jsTexture *VertexTextureImages[MAX_VERTEX_TEXTURE_IMAGE_UNITS]; - GLsizei packAlignment; - GLsizei unpackAlignment; - jsTexNameSpace bufferObjectNameSpace; - GLuint ArrayBuffer; - GLuint PixelUnpackBuffer; - GLuint TextureBuffer; - GLuint framebuffer; - jsTexNameSpace framebufferNameSpace; - GLboolean VertexProgram; - struct _CGprogram* BoundVertexProgram; - GLboolean FragmentProgram; - struct _CGprogram* BoundFragmentProgram; - GLboolean AllowTXPDemotion; - GLboolean VSync; - GLuint needValidate; - GLboolean everAttached; - CGerror RGLcgLastError; - CGerrorCallbackFunc RGLcgErrorCallbackFunction; - CGcontext RGLcgContextHead; - jsNameSpace cgContextNameSpace; - jsNameSpace cgProgramNameSpace; - jsNameSpace cgParameterNameSpace; -}; - -#define MAX(A,B) ((A)>(B)?(A):(B)) -#define MIN(A,B) ((A)<(B)?(A):(B)) -#define RGL_LIKELY(COND) (COND) -#define RGL_UNLIKELY(COND) (COND) - -static inline unsigned int endianSwapWord( unsigned int v ) -{ - return ( v&0xff ) << 24 | ( v&0xff00 ) << 8 | - ( v&0xff0000 ) >> 8 | ( v&0xff000000 ) >> 24; -} - -static inline int _RGLLog2( unsigned int i ) -{ - int l = 0; - while ( i ) - { - ++l; - i >>= 1; - } - return l -1; -} - -static inline unsigned long _RGLPad(unsigned long x, unsigned long pad) -{ - return ( x + pad - 1 ) / pad*pad; -} - -typedef struct MemoryBlockManager_t_ -{ - char *memory; - GLuint size; - GLuint minAlignment; - GLenum method; - GLuint *book; - GLint bookSize; - GLint bookAlloc; -} MemoryBlockManager_t; - -typedef unsigned long jsName; - -jsName _RGLCreateName( struct jsNameSpace * ns, void* object ); -unsigned int _RGLIsName( struct jsNameSpace* ns, jsName name ); -void _RGLEraseName( struct jsNameSpace* ns, jsName name ); - -static inline void * _RGLGetNamedValue( struct jsNameSpace* ns, jsName name ) -{ - return ns->data[name - 1]; -} - -void _RGLTexNameSpaceInit( jsTexNameSpace *ns, jsTexNameSpaceCreateFunction create, jsTexNameSpaceDestroyFunction destroy ); -void _RGLTexNameSpaceFree( jsTexNameSpace *ns ); -void _RGLTexNameSpaceResetNames( jsTexNameSpace *ns ); -GLuint _RGLTexNameSpaceGetFree( jsTexNameSpace *ns ); -GLboolean _RGLTexNameSpaceCreateNameLazy( jsTexNameSpace *ns, GLuint name ); -GLboolean _RGLTexNameSpaceIsName( jsTexNameSpace *ns, GLuint name ); -void _RGLTexNameSpaceGenNames( jsTexNameSpace *ns, GLsizei n, GLuint *names ); -void _RGLTexNameSpaceDeleteNames( jsTexNameSpace *ns, GLsizei n, const GLuint *names ); -void _RGLTexNameSpaceReinit( jsTexNameSpace * saved, jsTexNameSpace * active ); - -#define MEMORY_ALLOC_ERROR 0 - -#define GMM_ERROR 0xFFFFFFFF -#define GMM_TILE_ALIGNMENT 0x10000 -#define GMM_ALIGNMENT 128 -#define GMM_RSX_WAIT_INDEX 254 -#define GMM_PPU_WAIT_INDEX 255 -#define GMM_BLOCK_COUNT 512 -#define GMM_TILE_BLOCK_COUNT 16 - -#define GMM_NUM_FREE_BINS 22 -#define GMM_FREE_BIN_0 0x80 // 0x00 - 0x80 -#define GMM_FREE_BIN_1 0x100 // 0x80 - 0x100 -#define GMM_FREE_BIN_2 0x180 // ... -#define GMM_FREE_BIN_3 0x200 -#define GMM_FREE_BIN_4 0x280 -#define GMM_FREE_BIN_5 0x300 -#define GMM_FREE_BIN_6 0x380 -#define GMM_FREE_BIN_7 0x400 -#define GMM_FREE_BIN_8 0x800 -#define GMM_FREE_BIN_9 0x1000 -#define GMM_FREE_BIN_10 0x2000 -#define GMM_FREE_BIN_11 0x4000 -#define GMM_FREE_BIN_12 0x8000 -#define GMM_FREE_BIN_13 0x10000 -#define GMM_FREE_BIN_14 0x20000 -#define GMM_FREE_BIN_15 0x40000 -#define GMM_FREE_BIN_16 0x80000 -#define GMM_FREE_BIN_17 0x100000 -#define GMM_FREE_BIN_18 0x200000 -#define GMM_FREE_BIN_19 0x400000 -#define GMM_FREE_BIN_20 0x800000 -#define GMM_FREE_BIN_21 0x1000000 - -typedef struct GmmFixedAllocData -{ - char **ppBlockList[2]; - uint16_t **ppFreeBlockList[2]; - uint16_t *pBlocksUsed[2]; - uint16_t BlockListCount[2]; -} GmmFixedAllocData; - -typedef struct GmmBaseBlock -{ - uint8_t isTile; - uint8_t isMain; - uint32_t address; - uint32_t size; -} GmmBaseBlock; - -typedef struct GmmBlock -{ - GmmBaseBlock base; - struct GmmBlock *pPrev; - struct GmmBlock *pNext; - uint8_t isPinned; - struct GmmBlock *pPrevFree; - struct GmmBlock *pNextFree; - uint32_t fence; -} GmmBlock; - -typedef struct GmmTileBlock -{ - GmmBaseBlock base; - struct GmmTileBlock *pPrev; - struct GmmTileBlock *pNext; - - uint32_t tileTag; - void *pData; -} GmmTileBlock; - -typedef struct GmmAllocator -{ - uint32_t memoryBase; - - uint32_t startAddress; - uint32_t size; - uint32_t freeAddress; - - GmmBlock *pHead; - GmmBlock *pTail; - GmmBlock *pSweepHead; - uint32_t freedSinceSweep; - uint32_t tileStartAddress; - uint32_t tileSize; - GmmTileBlock *pTileHead; - GmmTileBlock *pTileTail; - GmmBlock *pPendingFreeHead; - GmmBlock *pPendingFreeTail; - GmmBlock *pFreeHead[GMM_NUM_FREE_BINS]; - GmmBlock *pFreeTail[GMM_NUM_FREE_BINS]; - uint32_t totalSize; -} GmmAllocator; - -extern GmmAllocator *pGmmLocalAllocator; -extern GmmAllocator *pGmmMainAllocator; - -uint32_t gmmInit( - const void *localMemoryBase, - const void *localStartAddress, - const uint32_t localSize, - const void *mainMemoryBase, - const void *mainStartAddress, - const uint32_t mainSize -); - -uint32_t gmmIdToOffset(const uint32_t id); -char *gmmIdToAddress(const uint32_t id); -uint32_t gmmFree(const uint32_t freeId); -uint32_t gmmAlloc(const uint8_t isTile, const uint32_t size); -uint32_t gmmAllocExtendedTileBlock(const uint32_t size, const uint32_t tag); - -void gmmSetTileAttrib(const uint32_t id, const uint32_t tag, void *pData); - -#define GCM_FUNC_BUFFERED( GCM_FUNCTION, COMMAND_BUFFER, ...) \ - { \ - CellGcmContextData gcmContext; \ - gcmContext.current = (uint32_t *)COMMAND_BUFFER; \ - GCM_FUNCTION ## UnsafeInline( &gcmContext, __VA_ARGS__ ); \ - COMMAND_BUFFER = (typeof(COMMAND_BUFFER))gcmContext.current; \ - } - -#define GCM_FUNC_BUFFERED_NO_ARGS( GCM_FUNCTION, COMMAND_BUFFER ) \ - { \ - CellGcmContextData gcmContext; \ - gcmContext.current = (uint32_t *)COMMAND_BUFFER; \ - GCM_FUNCTION ## UnsafeInline( &gcmContext ); \ - COMMAND_BUFFER = (typeof(COMMAND_BUFFER))gcmContext.current; \ - } - -typedef struct -{ - unsigned dst_id; - unsigned dst_id_offset; - unsigned dst_pitch; - unsigned dst_x; - unsigned dst_y; - unsigned src_id; - unsigned src_id_offset; - unsigned src_pitch; - unsigned src_x; - unsigned src_y; - unsigned width; - unsigned height; - unsigned bpp; - void *fifo_ptr; -} transfer_params_t; - -#define HOST_BUFFER_ALIGNMENT 128 - -#define _RGL_TRANSIENT_MEMORY_DEFAULT (32 << 20) -#define _RGL_PERSISTENT_MEMORY_DEFAULT (160 << 20) -#define _RGL_FIFO_SIZE_DEFAULT (256 * 1024) -#define _RGL_HOST_SIZE_DEFAULT (0) -#define _RGL_TRANSIENT_ENTRIES_DEFAULT 64 - -#define _RGL_BUFFER_OBJECT_BLOCK_SIZE 128 - -typedef struct PSGLinitOptions -{ - GLuint enable; - int errorConsole; - GLuint fifoSize; - GLuint hostMemorySize; -} PSGLinitOptions; - -struct RGLSemaphore -{ - GLuint val; - GLuint pad0; - GLuint pad1; - GLuint pad2; -}; - -struct RGLSemaphoreMemory -{ - RGLSemaphore userSemaphores[256]; -}; - -struct RGLResource -{ - char *localAddress; - GLuint localSize; - GLuint MemoryClock; - GLuint GraphicsClock; - char * hostMemoryBase; - GLuint hostMemorySize; - GLuint hostMemoryReserved; - unsigned long dmaPushBufferOffset; - char * dmaPushBuffer; - GLuint dmaPushBufferSize; - void* dmaControl; - RGLSemaphoreMemory *semaphores; -}; - -typedef volatile struct -{ - GLuint Ignored00[0x010]; - GLuint Put; - GLuint Get; - GLuint Reference; - GLuint Ignored01[0x1]; - GLuint SetReference; - GLuint TopLevelGet; - GLuint Ignored02[0x2]; - GLuint SetContextDmaSemaphore; - GLuint SetSemaphoreOffset; - GLuint SetSemaphoreAcquire; - GLuint SetSemaphoreRelease; - GLuint Ignored03[0x7e4]; -} RGLControlDma; - -struct RGLFifo: public CellGcmContextData -{ - RGLControlDma *dmaControl; - uint32_t *dmaPushBufferBegin; - uint32_t *dmaPushBufferEnd; - GLuint fifoBlockSize; - unsigned long dmaPushBufferOffset; - GLuint dmaPushBufferSizeInWords; - uint32_t *lastPutWritten; - uint32_t *lastGetRead; - GLuint lastSWReferenceWritten; - GLuint lastSWReferenceFlushed; - GLuint lastHWReferenceRead; - uint32_t *dmaPushBufferGPU; - int spuid; -}; - -static inline void TransferDataVidToVid(transfer_params_t *params) -{ - GmmBaseBlock *pBaseBlock_dst = (GmmBaseBlock *)params->dst_id; - GmmBaseBlock *pBaseBlock_src = (GmmBaseBlock *)params->src_id; - - GLuint dstOffset_tmp = gmmAddressToOffset(pBaseBlock_dst->address, pBaseBlock_dst->isMain) + params->dst_id_offset; - GLuint srcOffset_tmp = gmmAddressToOffset(pBaseBlock_src->address, pBaseBlock_src->isMain) + params->src_id_offset; - - cellGcmSetTransferImage( (RGLFifo*)params->fifo_ptr, CELL_GCM_TRANSFER_LOCAL_TO_LOCAL, dstOffset_tmp, params->dst_pitch, params->dst_x, params->dst_y, srcOffset_tmp, params->src_pitch, params->src_x, params->src_y, params->width, params->height, params->bpp); -} - -typedef struct RGLRenderTarget RGLRenderTarget; -typedef struct RGLCachedState RGLCachedState; -typedef struct RGLBlendState RGLBlendState; -typedef struct RGLInterpolantState RGLInterpolantState; - -struct RGLInterpolantState -{ - GLuint vertexProgramAttribMask; - GLuint fragmentProgramAttribMask; -}; - -struct RGLBlendState -{ - GLuint alphaFunc; - GLfloat alphaRef; -}; - -struct RGLRenderTarget -{ - GLuint colorFormat; - GLuint colorBufferCount; - GLuint yInverted; - CellGcmSurface gcmRenderTarget; -}; - -struct RGLCachedState -{ - RGLBlendState blend; - RGLViewportState viewport; - RGLInterpolantState interpolant; -}; - -struct RGLState -{ - char *localAddress; - void *hostMemoryBase; - GLuint hostMemorySize; - RGLSemaphoreMemory *semaphores; - RGLFifo fifo; - RGLRenderTarget renderTarget; - RGLCachedState state; - CellGcmConfig config; - GLuint labelValue; -}; - -GLboolean _RGLInit( PSGLinitOptions* options, RGLResource *resource ); - -#define SEMA_NEVENTS 128 -#define SEMA_BASE 64 -#define SEMA_FENCE (SEMA_BASE + SEMA_NEVENTS) - -void _RGLIncFenceRef( GLuint* ref ); - -typedef struct -{ - GLenum pool; - unsigned int bufferId; - unsigned int bufferSize; - unsigned int pitch; - - GLuint mapCount; - GLenum mapAccess; -} RGLBufferObject; - -void _RGLSetNativeCgVertexProgram( const void *header ); -void _RGLSetNativeCgFragmentProgram( const void *header ); - -GLboolean _RGLTryResizeTileRegion( GLuint address, GLuint size, void* data ); - -static inline GLuint _RGLPlatformGetBitsPerPixel( GLenum internalFormat ) -{ - switch ( internalFormat ) - { - case RGL_HILO8: - case RGL_RGB5_A1_SCE: - case RGL_RGB565_SCE: - return 16; - case RGL_ALPHA8: - return 8; - case RGL_RGBX8: - case RGL_RGBA8: - case RGL_ABGR8: - case RGL_ARGB8: - case RGL_BGRA8: - return 32; - default: - return 0; - } -} - - -static inline void _RGLFifoGlViewport( GLint x, GLint y, GLsizei width, GLsizei height, GLclampf zNear = 0.0f, GLclampf zFar = 1.0f ) -{ - RGLViewportState *vp = &_RGLState.state.viewport; - RGLRenderTarget *rt = &_RGLState.renderTarget; - GLint clipX0, clipX1, clipY0, clipY1; - - vp->x = x; - vp->y = y; - vp->w = width; - vp->h = height; - - clipX0 = x; - clipX1 = x + width; - clipY0 = y; - clipY1 = y + height; - - if ( rt->yInverted ) - { - clipY0 = rt->gcmRenderTarget.height - ( y + height ); - clipY1 = rt->gcmRenderTarget.height - y; - } - - if ( clipX0 < 0 ) - clipX0 = 0; - - if ( clipY0 < 0 ) - clipY0 = 0; - - if ( clipX1 >= CELL_GCM_MAX_RT_DIMENSION ) - clipX1 = CELL_GCM_MAX_RT_DIMENSION; - - if ( clipY1 >= CELL_GCM_MAX_RT_DIMENSION ) - clipY1 = CELL_GCM_MAX_RT_DIMENSION; - - if (( clipX1 <= clipX0 ) || ( clipY1 <= clipY0 ) ) - clipX0 = clipY0 = clipX1 = clipY1 = 0; - - vp->xScale = width * 0.5f; - vp->xCenter = (GLfloat)(x + vp->xScale + SUBPIXEL_ADJUST); - vp->yScale = height; - - if ( rt->yInverted ) - { - vp->yScale *= -0.5f; - vp->yCenter = (GLfloat)(rt->gcmRenderTarget.height - y + vp->yScale + SUBPIXEL_ADJUST); - } - else - { - vp->yScale *= 0.5f; - vp->yCenter = (GLfloat)(y + vp->yScale + SUBPIXEL_ADJUST); - } - - float scale[4] = { vp->xScale, vp->yScale, 0.5f, 0.0f }; - float offset[4] = { vp->xCenter, vp->yCenter, 0.5f, 0.0f }; - - cellGcmSetViewportInline( &_RGLState.fifo, clipX0, clipY0, clipX1 - clipX0, - clipY1 - clipY0, zNear, zFar, scale, offset ); -} - -#define PSGL_DEVICE_PARAMETERS_COLOR_FORMAT 0x0001 -#define PSGL_DEVICE_PARAMETERS_DEPTH_FORMAT 0x0002 -#define PSGL_DEVICE_PARAMETERS_MULTISAMPLING_MODE 0x0004 -#define PSGL_DEVICE_PARAMETERS_TV_STANDARD 0x0008 -#define PSGL_DEVICE_PARAMETERS_CONNECTOR 0x0010 -#define PSGL_DEVICE_PARAMETERS_BUFFERING_MODE 0x0020 -#define PSGL_DEVICE_PARAMETERS_WIDTH_HEIGHT 0x0040 -#define PSGL_DEVICE_PARAMETERS_RESC_RENDER_WIDTH_HEIGHT 0x0080 -#define PSGL_DEVICE_PARAMETERS_RESC_RATIO_MODE 0x0100 -#define PSGL_DEVICE_PARAMETERS_RESC_PAL_TEMPORAL_MODE 0x0200 -#define PSGL_DEVICE_PARAMETERS_RESC_INTERLACE_MODE 0x0400 -#define PSGL_DEVICE_PARAMETERS_RESC_ADJUST_ASPECT_RATIO 0x0800 - -// mask for validation -#define PSGL_VALIDATE_NONE 0x00000000 -#define PSGL_VALIDATE_FRAMEBUFFER 0x00000001 -#define PSGL_VALIDATE_TEXTURES_USED 0x00000002 -#define PSGL_VALIDATE_VERTEX_PROGRAM 0x00000004 -#define PSGL_VALIDATE_VERTEX_CONSTANTS 0x00000008 -#define PSGL_VALIDATE_VERTEX_TEXTURES_USED 0x00000010 -#define PSGL_VALIDATE_FFX_VERTEX_PROGRAM 0x00000020 -#define PSGL_VALIDATE_FRAGMENT_PROGRAM 0x00000040 -#define PSGL_VALIDATE_FFX_FRAGMENT_PROGRAM 0x00000080 -#define PSGL_VALIDATE_VIEWPORT 0x00000200 -#define PSGL_VALIDATE_FACE_CULL 0x00010000 -#define PSGL_VALIDATE_BLENDING 0x00020000 -#define PSGL_VALIDATE_POINT_RASTER 0x00040000 -#define PSGL_VALIDATE_LINE_RASTER 0x00080000 -#define PSGL_VALIDATE_POLYGON_OFFSET 0x00100000 -#define PSGL_VALIDATE_SHADE_MODEL 0x00200000 -#define PSGL_VALIDATE_LOGIC_OP 0x00400000 -#define PSGL_VALIDATE_MULTISAMPLING 0x00800000 -#define PSGL_VALIDATE_POLYGON_MODE 0x01000000 -#define PSGL_VALIDATE_PRIMITIVE_RESTART 0x02000000 -#define PSGL_VALIDATE_CLIP_PLANES 0x04000000 -#define PSGL_VALIDATE_SHADER_SRGB_REMAP 0x08000000 -#define PSGL_VALIDATE_POINT_SPRITE 0x10000000 -#define PSGL_VALIDATE_TWO_SIDE_COLOR 0x20000000 -#define PSGL_VALIDATE_ALL 0x3FFFFFFF - - -#define PSGL_INIT_PERSISTENT_MEMORY_SIZE 0x0004 -#define PSGL_INIT_TRANSIENT_MEMORY_SIZE 0x0008 -#define PSGL_INIT_ERROR_CONSOLE 0x0010 -#define PSGL_INIT_FIFO_SIZE 0x0020 -#define PSGL_INIT_HOST_MEMORY_SIZE 0x0040 -#define PSGL_INIT_USE_PMQUERIES 0x0080 - - -extern void psglInit( PSGLinitOptions* options ); -extern void psglExit(); - -PSGLdevice *psglCreateDeviceAuto( GLenum colorFormat, GLenum depthFormat, GLenum multisamplingMode ); -PSGLdevice *psglCreateDeviceExtended( const PSGLdeviceParameters *parameters ); -void psglGetDeviceDimensions(const PSGLdevice *device, GLuint *width, GLuint *height ); -void psglDestroyDevice( PSGLdevice* device ); - -void psglMakeCurrent( PSGLcontext* context, PSGLdevice* device ); -PSGLcontext *psglCreateContext(void); -void psglDestroyContext( PSGLcontext* LContext ); -void psglResetCurrentContext(void); -PSGLcontext *psglGetCurrentContext(void); -PSGLdevice *psglGetCurrentDevice(void); -void psglSwap(void); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/console/rgl/ps3/vector b/console/rgl/ps3/vector deleted file mode 100644 index 6821488a6d..0000000000 --- a/console/rgl/ps3/vector +++ /dev/null @@ -1,1733 +0,0 @@ -#ifndef _VECTOR_ -#define _VECTOR_ - -#include -#include - -namespace RGL -{ - -//_STD_BEGIN - -template > class vector; - -#if _HAS_TRADITIONAL_ITERATORS - -#else /* _HAS_TRADITIONAL_ITERATORS */ -// TEMPLATE CLASS _Vector_const_iterator -template -class _Vector_const_iterator - : public ::std::_Ranit < _Ty, typename _Alloc::difference_type, - typename _Alloc::const_pointer, typename _Alloc::const_reference > -{ // iterator for nonmutable vector -public: - typedef _Vector_const_iterator<_Ty, _Alloc> _Myt; - typedef vector<_Ty, _Alloc> _Myvec; - typedef typename _Alloc::pointer _Tptr; - - typedef ::std::random_access_iterator_tag iterator_category; - typedef _Ty value_type; - typedef typename _Alloc::difference_type difference_type; - typedef typename _Alloc::const_pointer pointer; - typedef typename _Alloc::const_reference reference; - - _Vector_const_iterator() - { // construct with null pointer - _Myptr = 0; - } - - _Vector_const_iterator( _Tptr _Ptr ) - { // construct with pointer _Ptr - _Myptr = _Ptr; - } - - reference operator*() const - { // return designated object - return ( *_Myptr ); - } - - pointer operator->() const - { // return pointer to class object - return ( &**this ); - } - - _Myt& operator++() - { // preincrement - ++_Myptr; - return ( *this ); - } - - _Myt operator++( int ) - { // postincrement - _Myt _Tmp = *this; - ++*this; - return ( _Tmp ); - } - - _Myt& operator--() - { // predecrement - --_Myptr; - return ( *this ); - } - - _Myt operator--( int ) - { // postdecrement - _Myt _Tmp = *this; - --*this; - return ( _Tmp ); - } - - _Myt& operator+=( difference_type _Off ) - { // increment by integer - _Myptr += _Off; - return ( *this ); - } - - _Myt operator+( difference_type _Off ) const - { // return this + integer - _Myt _Tmp = *this; - return ( _Tmp += _Off ); - } - - _Myt& operator-=( difference_type _Off ) - { // decrement by integer - return ( *this += -_Off ); - } - - _Myt operator-( difference_type _Off ) const - { // return this - integer - _Myt _Tmp = *this; - return ( _Tmp -= _Off ); - } - - difference_type operator-( const _Myt& _Right ) const - { // return difference of iterators - return ( _Myptr - _Right._Myptr ); - } - - reference operator[]( difference_type _Off ) const - { // subscript - return ( *( *this + _Off ) ); - } - - bool operator==( const _Myt& _Right ) const - { // test for iterator equality - return ( _Myptr == _Right._Myptr ); - } - - bool operator!=( const _Myt& _Right ) const - { // test for iterator inequality - return ( !( *this == _Right ) ); - } - - bool operator<( const _Myt& _Right ) const - { // test if this < _Right - return ( _Myptr < _Right._Myptr ); - } - - bool operator>( const _Myt& _Right ) const - { // test if this > _Right - return ( _Right < *this ); - } - - bool operator<=( const _Myt& _Right ) const - { // test if this <= _Right - return ( !( _Right < *this ) ); - } - - bool operator>=( const _Myt& _Right ) const - { // test if this >= _Right - return ( !( *this < _Right ) ); - } - - _Tptr _Myptr; // offset of element in vector -}; - -template -inline _Vector_const_iterator<_Ty, _Alloc> operator+( - typename _Vector_const_iterator<_Ty, _Alloc>::difference_type _Off, - _Vector_const_iterator<_Ty, _Alloc> _Next ) -{ // add offset to iterator - return ( _Next += _Off ); -} - -// TEMPLATE CLASS _Vector_iterator -template -class _Vector_iterator - : public _Vector_const_iterator<_Ty, _Alloc> -{ // iterator for mutable vector -public: - typedef _Vector_iterator<_Ty, _Alloc> _Myt; - typedef _Vector_const_iterator<_Ty, _Alloc> _Mybase; - - typedef ::std::random_access_iterator_tag iterator_category; - typedef _Ty value_type; - typedef typename _Alloc::difference_type difference_type; - typedef typename _Alloc::pointer pointer; - typedef typename _Alloc::reference reference; - - _Vector_iterator() - { // construct with null vector pointer - } - - _Vector_iterator( pointer _Ptr ) - : _Mybase( _Ptr ) - { // construct with pointer _Ptr - } - - reference operator*() const - { // return designated object - return (( reference )**( _Mybase * )this ); - } - - pointer operator->() const - { // return pointer to class object - return ( &**this ); - } - - _Myt& operator++() - { // preincrement - ++this->_Myptr; - return ( *this ); - } - - _Myt operator++( int ) - { // postincrement - _Myt _Tmp = *this; - ++*this; - return ( _Tmp ); - } - - _Myt& operator--() - { // predecrement - --this->_Myptr; - return ( *this ); - } - - _Myt operator--( int ) - { // postdecrement - _Myt _Tmp = *this; - --*this; - return ( _Tmp ); - } - - _Myt& operator+=( difference_type _Off ) - { // increment by integer - this->_Myptr += _Off; - return ( *this ); - } - - _Myt operator+( difference_type _Off ) const - { // return this + integer - _Myt _Tmp = *this; - return ( _Tmp += _Off ); - } - - _Myt& operator-=( difference_type _Off ) - { // decrement by integer - return ( *this += -_Off ); - } - - _Myt operator-( difference_type _Off ) const - { // return this - integer - _Myt _Tmp = *this; - return ( _Tmp -= _Off ); - } - - difference_type operator-( const _Mybase& _Right ) const - { // return difference of iterators - return ( *( _Mybase * )this - _Right ); - } - - reference operator[]( difference_type _Off ) const - { // subscript - return ( *( *this + _Off ) ); - } -}; - -template -inline _Vector_iterator<_Ty, _Alloc> operator+( - typename _Vector_iterator<_Ty, _Alloc>::difference_type _Off, - _Vector_iterator<_Ty, _Alloc> _Next ) -{ // add offset to iterator - return ( _Next += _Off ); -} -#endif /* _HAS_TRADITIONAL_ITERATORS */ - -// TEMPLATE CLASS _Vector_val -template -class _Vector_val - : public ::std::_Container_base -{ // base class for vector to hold allocator _Alval -protected: - _Vector_val( _Alloc _Al = _Alloc() ) - : _Alval( _Al ) - { // construct allocator from _Al - } - - typedef typename _Alloc::template - rebind<_Ty>::other _Alty; - - _Alty _Alval; // allocator object for values -}; - -// TEMPLATE CLASS vector -template -class vector - : public _Vector_val<_Ty, _Ax> -{ // varying size array of values -public: - typedef vector<_Ty, _Ax> _Myt; - typedef _Vector_val<_Ty, _Ax> _Mybase; - typedef typename _Mybase::_Alty _Alloc; - typedef _Alloc allocator_type; - typedef typename _Alloc::size_type size_type; - typedef typename _Alloc::difference_type _Dift; - typedef _Dift difference_type; - typedef typename _Alloc::pointer _Tptr; - typedef typename _Alloc::const_pointer _Ctptr; - typedef _Tptr pointer; - typedef _Ctptr const_pointer; - typedef typename _Alloc::reference _Reft; - typedef _Reft reference; - typedef typename _Alloc::const_reference const_reference; - typedef typename _Alloc::value_type value_type; - -#if _HAS_TRADITIONAL_ITERATORS -#define _VEC_ITER_BASE(it) (it) - - typedef pointer iterator; - typedef const_pointer const_iterator; - -#else /* _HAS_TRADITIONAL_ITERATORS */ -#define _VEC_ITER_BASE(it) (it)._Myptr - - typedef _Vector_iterator<_Ty, _Alloc> iterator; - typedef _Vector_const_iterator<_Ty, _Alloc> const_iterator; - - // friend class _Vector_iterator<_Ty, _Alloc>; - friend class _Vector_const_iterator<_Ty, _Alloc>; -#endif /* _HAS_TRADITIONAL_ITERATORS */ - - typedef _STD reverse_iterator reverse_iterator; - typedef _STD reverse_iterator const_reverse_iterator; - - vector() - : _Mybase() - { // construct empty vector - _Buy( 0 ); - } - - explicit vector( const _Alloc& _Al ) - : _Mybase( _Al ) - { // construct empty vector with allocator - _Buy( 0 ); - } - - explicit vector( size_type _Count ) - : _Mybase() - { // construct from _Count * _Ty() - _Construct_n( _Count, _Ty() ); - } - - vector( size_type _Count, const _Ty& _Val ) - : _Mybase() - { // construct from _Count * _Val - _Construct_n( _Count, _Val ); - } - - vector( size_type _Count, const _Ty& _Val, const _Alloc& _Al ) - : _Mybase( _Al ) - { // construct from _Count * _Val, with allocator - _Construct_n( _Count, _Val ); - } - - vector( const _Myt& _Right ) - : _Mybase( _Right._Alval ) - { // construct by copying _Right - if ( _Buy( _Right.size() ) ) - _TRY_BEGIN - _Mylast = _Ucopy( _Right.begin(), _Right.end(), _Myfirst ); - _CATCH_ALL - _Tidy(); - _RERAISE; - _CATCH_END - } - - template - vector( _Iter _First, _Iter _Last ) - : _Mybase() - { // construct from [_First, _Last) - _Construct( _First, _Last, _STD _Iter_cat( _First ) ); - } - - template - vector( _Iter _First, _Iter _Last, const _Alloc& _Al ) - : _Mybase( _Al ) - { // construct from [_First, _Last), with allocator - _Construct( _First, _Last, _STD _Iter_cat( _First ) ); - } - - template - void _Construct( _Iter _Count, _Iter _Val, ::std::_Int_iterator_tag ) - { // initialize with _Count * _Val - size_type _Size = ( size_type )_Count; - _Construct_n( _Size, _Val ); - } - - template - void _Construct( _Iter _First, - _Iter _Last, ::std::input_iterator_tag ) - { // initialize with [_First, _Last), input iterators - _Buy( 0 ); - _TRY_BEGIN - insert( begin(), _First, _Last ); - _CATCH_ALL - _Tidy(); - _RERAISE; - _CATCH_END - } - - void _Construct_n( size_type _Count, const _Ty& _Val ) - { // construct from _Count * _Val - if ( _Buy( _Count ) ) - { // nonzero, fill it - _TRY_BEGIN - _Mylast = _Ufill( _Myfirst, _Count, _Val ); - _CATCH_ALL - _Tidy(); - _RERAISE; - _CATCH_END - } - } - - ~vector() - { // destroy the object - _Tidy(); - } - - _Myt& operator=( const _Myt& _Right ) - { // assign _Right - if ( this != &_Right ) - { // worth doing - - if ( _Right.size() == 0 ) - clear(); // new sequence empty, free storage - else if ( _Right.size() <= size() ) - { // enough elements, copy new and destroy old - pointer _Ptr = _STD copy( _Right._Myfirst, _Right._Mylast, - _Myfirst ); // copy new - _Destroy( _Ptr, _Mylast ); // destroy old - _Mylast = _Myfirst + _Right.size(); - } - else if ( _Right.size() <= capacity() ) - { // enough room, copy and construct new - pointer _Ptr = _Right._Myfirst + size(); - _STD copy( _Right._Myfirst, _Ptr, _Myfirst ); - _Mylast = _Ucopy( _Ptr, _Right._Mylast, _Mylast ); - } - else - { // not enough room, allocate new array and construct new - if ( _Myfirst != 0 ) - { // discard old array - _Destroy( _Myfirst, _Mylast ); - this->_Alval.deallocate( _Myfirst, _Myend - _Myfirst ); - } - if ( _Buy( _Right.size() ) ) - _Mylast = _Ucopy( _Right._Myfirst, _Right._Mylast, - _Myfirst ); - } - } - return ( *this ); - } - - void reserve( size_type _Count ) - { // determine new minimum length of allocated storage - if ( max_size() < _Count ) - _Xlen(); // result too long - else if ( capacity() < _Count ) - { // not enough room, reallocate - pointer _Ptr = this->_Alval.allocate( _Count ); - - _TRY_BEGIN - _Ucopy( begin(), end(), _Ptr ); - _CATCH_ALL - this->_Alval.deallocate( _Ptr, _Count ); - _RERAISE; - _CATCH_END - - size_type _Size = size(); - if ( _Myfirst != 0 ) - { // destroy and deallocate old array - _Destroy( _Myfirst, _Mylast ); - this->_Alval.deallocate( _Myfirst, _Myend - _Myfirst ); - } - - _Myend = _Ptr + _Count; - _Mylast = _Ptr + _Size; - _Myfirst = _Ptr; - } - } - - size_type capacity() const - { // return current length of allocated storage - return ( _Myfirst == 0 ? 0 : _Myend - _Myfirst ); - } - - iterator begin() - { // return iterator for beginning of mutable sequence - return ( iterator( _Myfirst ) ); - } - - const_iterator begin() const - { // return iterator for beginning of nonmutable sequence - return ( const_iterator( _Myfirst ) ); - } - - iterator end() - { // return iterator for end of mutable sequence - return ( iterator( _Mylast ) ); - } - - const_iterator end() const - { // return iterator for end of nonmutable sequence - return ( const_iterator( _Mylast ) ); - } - - reverse_iterator rbegin() - { // return iterator for beginning of reversed mutable sequence - return ( reverse_iterator( end() ) ); - } - - const_reverse_iterator rbegin() const - { // return iterator for beginning of reversed nonmutable sequence - return ( const_reverse_iterator( end() ) ); - } - - reverse_iterator rend() - { // return iterator for end of reversed mutable sequence - return ( reverse_iterator( begin() ) ); - } - - const_reverse_iterator rend() const - { // return iterator for end of reversed nonmutable sequence - return ( const_reverse_iterator( begin() ) ); - } - - void resize( size_type _Newsize ) - { // determine new length, padding with _Ty() elements as needed - resize( _Newsize, _Ty() ); - } - - void resize( size_type _Newsize, _Ty _Val ) - { // determine new length, padding with _Val elements as needed - if ( size() < _Newsize ) - _Insert_n( end(), _Newsize - size(), _Val ); - else if ( _Newsize < size() ) - erase( begin() + _Newsize, end() ); - } - - size_type size() const - { // return length of sequence - return ( _Myfirst == 0 ? 0 : _Mylast - _Myfirst ); - } - - size_type max_size() const - { // return maximum possible length of sequence - return ( this->_Alval.max_size() ); - } - - bool empty() const - { // test if sequence is empty - return ( size() == 0 ); - } - - _Alloc get_allocator() const - { // return allocator object for values - return ( this->_Alval ); - } - - const_reference at( size_type _Pos ) const - { // subscript nonmutable sequence with checking - if ( size() <= _Pos ) - _Xran(); - return ( *( begin() + _Pos ) ); - } - - reference at( size_type _Pos ) - { // subscript mutable sequence with checking - if ( size() <= _Pos ) - _Xran(); - return ( *( begin() + _Pos ) ); - } - - const_reference operator[]( size_type _Pos ) const - { // subscript nonmutable sequence - return ( *( begin() + _Pos ) ); - } - - reference operator[]( size_type _Pos ) - { // subscript mutable sequence - return ( *( begin() + _Pos ) ); - } - - reference front() - { // return first element of mutable sequence - return ( *begin() ); - } - - const_reference front() const - { // return first element of nonmutable sequence - return ( *begin() ); - } - - reference back() - { // return last element of mutable sequence - return ( *( end() - 1 ) ); - } - - const_reference back() const - { // return last element of nonmutable sequence - return ( *( end() - 1 ) ); - } - - void push_back( const _Ty& _Val ) - { // insert element at end - if ( size() < capacity() ) - _Mylast = _Ufill( _Mylast, 1, _Val ); - else - insert( end(), _Val ); - } - - void pop_back() - { // erase element at end - if ( !empty() ) - { // erase last element - _Destroy( _Mylast - 1, _Mylast ); - --_Mylast; - } - } - - template - void assign( _Iter _First, _Iter _Last ) - { // assign [_First, _Last) - _Assign( _First, _Last, _STD _Iter_cat( _First ) ); - } - - template - void _Assign( _Iter _Count, _Iter _Val, ::std::_Int_iterator_tag ) - { // assign _Count * _Val - _Assign_n(( size_type )_Count, ( _Ty )_Val ); - } - - template - void _Assign( _Iter _First, _Iter _Last, ::std::input_iterator_tag ) - { // assign [_First, _Last), input iterators - erase( begin(), end() ); - insert( begin(), _First, _Last ); - } - - void assign( size_type _Count, const _Ty& _Val ) - { // assign _Count * _Val - _Assign_n( _Count, _Val ); - } - - iterator insert( iterator _Where, const _Ty& _Val ) - { // insert _Val at _Where - size_type _Off = size() == 0 ? 0 : _Where - begin(); - _Insert_n( _Where, ( size_type )1, _Val ); - return ( begin() + _Off ); - } - - void insert( iterator _Where, size_type _Count, const _Ty& _Val ) - { // insert _Count * _Val at _Where - _Insert_n( _Where, _Count, _Val ); - } - - template - void insert( iterator _Where, _Iter _First, _Iter _Last ) - { // insert [_First, _Last) at _Where - _Insert( _Where, _First, _Last, _STD _Iter_cat( _First ) ); - } - - template - void _Insert( iterator _Where, _Iter _First, _Iter _Last, - ::std::_Int_iterator_tag ) - { // insert _Count * _Val at _Where - _Insert_n( _Where, ( size_type )_First, ( _Ty )_Last ); - } - - template - void _Insert( iterator _Where, _Iter _First, _Iter _Last, - ::std::input_iterator_tag ) - { // insert [_First, _Last) at _Where, input iterators - for ( ; _First != _Last; ++_First, ++_Where ) - _Where = insert( _Where, *_First ); - } - - template - void _Insert( iterator _Where, - _Iter _First, _Iter _Last, ::std::forward_iterator_tag ) - { // insert [_First, _Last) at _Where, forward iterators - size_type _Count = 0; - _STD _Distance( _First, _Last, _Count ); - size_type _Capacity = capacity(); - - if ( _Count == 0 ) - ; - else if ( max_size() - size() < _Count ) - _Xlen(); // result too long - else if ( _Capacity < size() + _Count ) - { // not enough room, reallocate - _Capacity = max_size() - _Capacity / 2 < _Capacity - ? 0 : _Capacity + _Capacity / 2; // try to grow by 50% - if ( _Capacity < size() + _Count ) - _Capacity = size() + _Count; - pointer _Newvec = this->_Alval.allocate( _Capacity ); - pointer _Ptr = _Newvec; - - _TRY_BEGIN - _Ptr = _Ucopy( _Myfirst, _VEC_ITER_BASE( _Where ), - _Newvec ); // copy prefix - _Ptr = _Ucopy( _First, _Last, _Ptr ); // add new stuff - _Ucopy( _VEC_ITER_BASE( _Where ), _Mylast, _Ptr ); // copy suffix - _CATCH_ALL - _Destroy( _Newvec, _Ptr ); - this->_Alval.deallocate( _Newvec, _Capacity ); - _RERAISE; - _CATCH_END - - _Count += size(); - if ( _Myfirst != 0 ) - { // destroy and deallocate old array - _Destroy( _Myfirst, _Mylast ); - this->_Alval.deallocate( _Myfirst, _Myend - _Myfirst ); - } - - _Myend = _Newvec + _Capacity; - _Mylast = _Newvec + _Count; - _Myfirst = _Newvec; - } - else if (( size_type )( end() - _Where ) < _Count ) - { // new stuff spills off end - _Ucopy( _VEC_ITER_BASE( _Where ), _Mylast, - _VEC_ITER_BASE( _Where ) + _Count ); // copy suffix - _Iter _Mid = _First; - _STD advance( _Mid, end() - _Where ); - - _TRY_BEGIN - _Ucopy( _Mid, _Last, _Mylast ); // insert new stuff off end - _CATCH_ALL - _Destroy( _VEC_ITER_BASE( _Where ) + _Count, _Mylast + _Count ); - _RERAISE; - _CATCH_END - - _Mylast += _Count; - - _STD copy( _First, _Mid, - _VEC_ITER_BASE( _Where ) ); // insert to old end - } - else - { // new stuff can all be assigned - pointer _Oldend = _Mylast; - _Mylast = _Ucopy( _Oldend - _Count, _Oldend, - _Mylast ); // copy suffix - _STD copy_backward( _VEC_ITER_BASE( _Where ), _Oldend - _Count, - _Oldend ); // copy hole - - - _STD copy( _First, _Last, - _VEC_ITER_BASE( _Where ) ); // insert into hole - } - } - - iterator erase( iterator _Where ) - { // erase element at where - _STD copy( _VEC_ITER_BASE( _Where ) + 1, _Mylast, _VEC_ITER_BASE( _Where ) ); - _Destroy( _Mylast - 1, _Mylast ); - --_Mylast; - return ( _Where ); - } - - iterator erase( iterator _First, iterator _Last ) - { // erase [_First, _Last) - if ( _First != _Last ) - { // worth doing, copy down over hole - - pointer _Ptr = _STD copy( _VEC_ITER_BASE( _Last ), _Mylast, - _VEC_ITER_BASE( _First ) ); - - _Destroy( _Ptr, _Mylast ); - _Mylast = _Ptr; - } - return ( _First ); - } - - void clear() - { // erase all - _Tidy(); - } - - void swap( _Myt& _Right ) - { // exchange contents with _Right - if ( this->_Alval == _Right._Alval ) - { // same allocator, swap control information - - _STD swap( _Myfirst, _Right._Myfirst ); - _STD swap( _Mylast, _Right._Mylast ); - _STD swap( _Myend, _Right._Myend ); - } - else - { // different allocator, do multiple assigns - _Myt _Ts = *this; *this = _Right, _Right = _Ts; - } - } - -protected: - void _Assign_n( size_type _Count, const _Ty& _Val ) - { // assign _Count * _Val - _Ty _Tmp = _Val; // in case _Val is in sequence - erase( begin(), end() ); - insert( begin(), _Count, _Tmp ); - } - - bool _Buy( size_type _Capacity ) - { // allocate array with _Capacity elements - _Myfirst = 0, _Mylast = 0, _Myend = 0; - if ( _Capacity == 0 ) - return ( false ); - else if ( max_size() < _Capacity ) - _Xlen(); // result too long - else - { // nonempty array, allocate storage - _Myfirst = this->_Alval.allocate( _Capacity ); - _Mylast = _Myfirst; - _Myend = _Myfirst + _Capacity; - } - return ( true ); - } - - void _Destroy( pointer _First, pointer _Last ) - { // destroy [_First, _Last) using allocator - _Destroy_range( _First, _Last, this->_Alval ); - } - - void _Tidy() - { // free all storage - if ( _Myfirst != 0 ) - { // something to free, destroy and deallocate it - - _Destroy( _Myfirst, _Mylast ); - this->_Alval.deallocate( _Myfirst, _Myend - _Myfirst ); - } - _Myfirst = 0, _Mylast = 0, _Myend = 0; - } - - template - pointer _Ucopy( _Iter _First, _Iter _Last, pointer _Ptr ) - { // copy initializing [_First, _Last), using allocator - return ( _Uninitialized_copy( _First, _Last, - _Ptr, this->_Alval ) ); - } - - void _Insert_n( iterator _Where, - size_type _Count, const _Ty& _Val ) - { // insert _Count * _Val at _Where - - _Ty _Tmp = _Val; // in case _Val is in sequence - size_type _Capacity = capacity(); - - if ( _Count == 0 ) - ; - else if ( max_size() - size() < _Count ) - _Xlen(); // result too long - else if ( _Capacity < size() + _Count ) - { // not enough room, reallocate - _Capacity = max_size() - _Capacity / 2 < _Capacity - ? 0 : _Capacity + _Capacity / 2; // try to grow by 50% - if ( _Capacity < size() + _Count ) - _Capacity = size() + _Count; - pointer _Newvec = this->_Alval.allocate( _Capacity ); - pointer _Ptr = _Newvec; - - _TRY_BEGIN - _Ptr = _Ucopy( _Myfirst, _VEC_ITER_BASE( _Where ), - _Newvec ); // copy prefix - _Ptr = _Ufill( _Ptr, _Count, _Tmp ); // add new stuff - _Ucopy( _VEC_ITER_BASE( _Where ), _Mylast, _Ptr ); // copy suffix - _CATCH_ALL - _Destroy( _Newvec, _Ptr ); - this->_Alval.deallocate( _Newvec, _Capacity ); - _RERAISE; - _CATCH_END - - _Count += size(); - if ( _Myfirst != 0 ) - { // destroy and deallocate old array - _Destroy( _Myfirst, _Mylast ); - this->_Alval.deallocate( _Myfirst, _Myend - _Myfirst ); - } - - _Myend = _Newvec + _Capacity; - _Mylast = _Newvec + _Count; - _Myfirst = _Newvec; - } - else if (( size_type )( _Mylast - _VEC_ITER_BASE( _Where ) ) < _Count ) - { // new stuff spills off end - _Ucopy( _VEC_ITER_BASE( _Where ), _Mylast, - _VEC_ITER_BASE( _Where ) + _Count ); // copy suffix - - _TRY_BEGIN - _Ufill( _Mylast, _Count - ( _Mylast - _VEC_ITER_BASE( _Where ) ), - _Tmp ); // insert new stuff off end - _CATCH_ALL - _Destroy( _VEC_ITER_BASE( _Where ) + _Count, _Mylast + _Count ); - _RERAISE; - _CATCH_END - - _Mylast += _Count; - - _STD fill( _VEC_ITER_BASE( _Where ), _Mylast - _Count, - _Tmp ); // insert up to old end - } - else - { // new stuff can all be assigned - pointer _Oldend = _Mylast; - _Mylast = _Ucopy( _Oldend - _Count, _Oldend, - _Mylast ); // copy suffix - - _STD copy_backward( _VEC_ITER_BASE( _Where ), _Oldend - _Count, - _Oldend ); // copy hole - _STD fill( _VEC_ITER_BASE( _Where ), _VEC_ITER_BASE( _Where ) + _Count, - _Tmp ); // insert into hole - } - } - - pointer _Ufill( pointer _Ptr, size_type _Count, const _Ty &_Val ) - { // copy initializing _Count * _Val, using allocator - _Uninitialized_fill_n( _Ptr, _Count, _Val, this->_Alval ); - return ( _Ptr + _Count ); - } - - void _Xlen() const - { // report a length_error - } - - void _Xran() const - { // report an out_of_range error - } - - pointer _Myfirst; // pointer to beginning of array - pointer _Mylast; // pointer to current end of sequence - pointer _Myend; // pointer to end of array -}; - -// vector TEMPLATE FUNCTIONS -template -inline bool operator==( const vector<_Ty, _Alloc>& _Left, - const vector<_Ty, _Alloc>& _Right ) -{ // test for vector equality - return ( _Left.size() == _Right.size() - && _STD equal( _Left.begin(), _Left.end(), _Right.begin() ) ); -} - -template -inline bool operator!=( const vector<_Ty, _Alloc>& _Left, - const vector<_Ty, _Alloc>& _Right ) -{ // test for vector inequality - return ( !( _Left == _Right ) ); -} - -template -inline bool operator<( const vector<_Ty, _Alloc>& _Left, - const vector<_Ty, _Alloc>& _Right ) -{ // test if _Left < _Right for vectors - return ( _STD lexicographical_compare( _Left.begin(), _Left.end(), - _Right.begin(), _Right.end() ) ); -} - -template -inline bool operator>( const vector<_Ty, _Alloc>& _Left, - const vector<_Ty, _Alloc>& _Right ) -{ // test if _Left > _Right for vectors - return ( _Right < _Left ); -} - -template -inline bool operator<=( const vector<_Ty, _Alloc>& _Left, - const vector<_Ty, _Alloc>& _Right ) -{ // test if _Left <= _Right for vectors - return ( !( _Right < _Left ) ); -} - -template -inline bool operator>=( const vector<_Ty, _Alloc>& _Left, - const vector<_Ty, _Alloc>& _Right ) -{ // test if _Left >= _Right for vectors - return ( !( _Left < _Right ) ); -} - -template -inline void swap( vector<_Ty, _Alloc>& _Left, vector<_Ty, _Alloc>& _Right ) -{ // swap _Left and _Right vectors - _Left.swap( _Right ); -} - -// CLASS vector -typedef unsigned _Vbase; // word type for vector representation -const int _VBITS = 8 * sizeof( _Vbase ); // at least CHAR_BITS bits per word - -template -class vector< ::std::_Bool, _Alloc> - : public ::std::_Container_base -{ // varying size array of bits -public: - typedef typename _Alloc::size_type size_type; - typedef typename _Alloc::difference_type _Dift; - typedef vector < _Vbase, - typename _Alloc::template rebind<_Vbase>::other > - _Vbtype; - typedef vector< _STD _Bool, _Alloc> _Myt; - typedef _Dift difference_type; - typedef _STD _Bool _Ty; - typedef _Alloc allocator_type; - - typedef bool const_reference; - typedef bool value_type; - -#define _VB_TYPENAME typename - - // CLASS _Vb_iter_base - class _Vb_iter_base - : public _STD _Ranit< _STD _Bool, _Dift, value_type *, value_type> - { // store information common to reference and iterators - public: - _Vb_iter_base() - : _Myoff( 0 ), _Myptr( 0 ) - { // construct with null pointer - } - - _Vb_iter_base( const _Vb_iter_base& _Right ) - : _Myptr( _Right._Myptr ), _Myoff( _Right._Myoff ) - { // construct with copy of _Right - } - - _Vb_iter_base( _Vbase *_Ptr ) - : _Myoff( 0 ), _Myptr( _Ptr ) - { // construct with offset and pointer - } - - size_type _Myoff; - _Vbase *_Myptr; - }; - - // CLASS reference - class reference; - friend class reference; - - class reference - : public _Vb_iter_base - { // reference to a bit within a base word - public: - reference() - { // construct with null pointer - } - - reference( const _Vb_iter_base& _Right ) - : _Vb_iter_base( _Right ) - { // construct with base - } - - reference& operator=( const reference& _Right ) - { // assign reference _Right to bit - return ( *this = bool( _Right ) ); - } - - reference& operator=( bool _Val ) - { // assign _Val to bit - if ( _Val ) - *_Getptr() |= _Mask(); - else - *_Getptr() &= ~_Mask(); - return ( *this ); - } - - void flip() - { // toggle the bit - *_Getptr() ^= _Mask(); - } - - bool operator~() const - { // test if bit is reset - return ( !bool( *this ) ); - } - - operator bool() const - { // test if bit is set - return (( *_Getptr() & _Mask() ) != 0 ); - } - - _Vbase *_Getptr() const - { // get pointer to base word - return ( this->_Myptr ); - } - - protected: - _Vbase _Mask() const - { // convert offset to mask - return (( _Vbase )( 1 << this->_Myoff ) ); - } - }; - - typedef reference _Reft; - - // CLASS const_iterator - class const_iterator - : public _Vb_iter_base - { // iterator for nonmutable vector - public: - typedef _STD random_access_iterator_tag iterator_category; - typedef _STD _Bool value_type; - typedef _Dift difference_type; - typedef const_reference *pointer; - typedef const_reference reference; - - const_iterator() - { // construct with null reference - } - - const_iterator( const _Vbase *_Ptr ) - : _Vb_iter_base(( _Vbase * )_Ptr ) - - { // construct with offset and pointer - } - - const_reference operator*() const - { // return (reference to) designated object - return ( _Reft( *this ) ); - } - - const_iterator& operator++() - { // preincrement - _Inc(); - return ( *this ); - } - - const_iterator operator++( int ) - { // postincrement - const_iterator _Tmp = *this; - ++*this; - return ( _Tmp ); - } - - const_iterator& operator--() - { // predecrement - _Dec(); - return ( *this ); - } - - const_iterator operator--( int ) - { // postdecrement - const_iterator _Tmp = *this; - --*this; - return ( _Tmp ); - } - - const_iterator& operator+=( difference_type _Off ) - { // increment by integer - if ( _Off < 0 && this->_Myoff < 0 - ( size_type )_Off ) - { /* add negative increment */ - difference_type _Nwords = - ( 0 - this->_Myoff - ( size_type )_Off - 1 ) / _VBITS; - this->_Myptr -= _Nwords + 1; - this->_Myoff += _Nwords * _VBITS + _VBITS; - } - else - { /* add non-negative increment */ - this->_Myoff += _Off; - this->_Myptr += this->_Myoff / _VBITS; - this->_Myoff %= _VBITS; - } - return ( *this ); - } - - const_iterator operator+( difference_type _Off ) const - { // return this + integer - const_iterator _Tmp = *this; - return ( _Tmp += _Off ); - } - - const_iterator& operator-=( difference_type _Off ) - { // decrement by integer - return ( *this += -_Off ); - } - - const_iterator operator-( difference_type _Off ) const - { // return this - integer - const_iterator _Tmp = *this; - return ( _Tmp -= _Off ); - } - - difference_type operator-( const const_iterator _Right ) const - { // return difference of iterators - - - return ( _VBITS *( this->_Myptr - _Right._Myptr ) - + ( difference_type )this->_Myoff - - ( difference_type )_Right._Myoff ); - } - - const_reference operator[]( difference_type _Off ) const - { // subscript - return ( *( *this + _Off ) ); - } - - bool operator==( const const_iterator& _Right ) const - { // test for iterator equality - - - return ( this->_Myptr == _Right._Myptr - && this->_Myoff == _Right._Myoff ); - } - - bool operator!=( const const_iterator& _Right ) const - { // test for iterator inequality - return ( !( *this == _Right ) ); - } - - bool operator<( const const_iterator& _Right ) const - { // test if this < _Right - - - return ( this->_Myptr < _Right._Myptr - || this->_Myptr == _Right._Myptr - && this->_Myoff < _Right._Myoff ); - } - - bool operator>( const const_iterator& _Right ) const - { // test if this > _Right - return ( _Right < *this ); - } - - bool operator<=( const const_iterator& _Right ) const - { // test if this <= _Right - return ( !( _Right < *this ) ); - } - - bool operator>=( const const_iterator& _Right ) const - { // test if this >= _Right - return ( !( *this < _Right ) ); - } - - protected: - - - void _Dec() - { // decrement bit position - if ( this->_Myoff != 0 ) - --this->_Myoff; - else - this->_Myoff = _VBITS - 1, --this->_Myptr; - } - - void _Inc() - { // increment bit position - if ( this->_Myoff < _VBITS - 1 ) - ++this->_Myoff; - else - this->_Myoff = 0, ++this->_Myptr; - } - }; - - // CLASS iterator - class iterator - : public const_iterator - { // iterator for mutable vector - public: - typedef _STD random_access_iterator_tag iterator_category; - typedef _STD _Bool value_type; - typedef _Dift difference_type; - typedef _Reft *pointer; - typedef _Reft reference; - - iterator() - { // construct with null reference - } - - iterator( _Vbase *_Ptr ) - : const_iterator( _Ptr ) - - { // construct with offset and pointer - } - - reference operator*() const - { // return (reference to) designated object - return ( _Reft( *this ) ); - } - - iterator& operator++() - { // preincrement - ++*( const_iterator * )this; - return ( *this ); - } - - iterator operator++( int ) - { // postincrement - iterator _Tmp = *this; - ++*this; - return ( _Tmp ); - } - - iterator& operator--() - { // predecrement - --*( const_iterator * )this; - return ( *this ); - } - - iterator operator--( int ) - { // postdecrement - iterator _Tmp = *this; - --*this; - return ( _Tmp ); - } - - iterator& operator+=( difference_type _Off ) - { // increment by integer - *( const_iterator * )this += _Off; - return ( *this ); - } - - iterator operator+( difference_type _Off ) const - { // return this + integer - iterator _Tmp = *this; - return ( _Tmp += _Off ); - } - - iterator& operator-=( difference_type _Off ) - { // decrement by integer - return ( *this += -_Off ); - } - - iterator operator-( difference_type _Off ) const - { // return this - integer - iterator _Tmp = *this; - return ( _Tmp -= _Off ); - } - - difference_type operator-( const const_iterator _Right ) const - { // return difference of iterators - return ( *( const_iterator * )this - _Right ); - } - - reference operator[]( difference_type _Off ) const - { // subscript - return ( *( *this + _Off ) ); - } - - }; - - typedef iterator pointer; - typedef const_iterator const_pointer; - typedef _STD reverse_iterator reverse_iterator; - typedef _STD reverse_iterator const_reverse_iterator; - - vector() - : _Mysize( 0 ), _Myvec() - { // construct empty vector - } - - explicit vector( const _Alloc& _Al ) - : _Mysize( 0 ), _Myvec( _Al ) - { // construct empty vector, with allocator - } - - explicit vector( size_type _Count, bool _Val = false ) - : _Mysize( 0 ), _Myvec( _Nw( _Count ), ( _Vbase )( _Val ? -1 : 0 ) ) - { // construct from _Count * _Val - _Trim( _Count ); - } - - vector( size_type _Count, bool _Val, const _Alloc& _Al ) -: _Mysize( 0 ), _Myvec( _Nw( _Count ), ( _Vbase )( _Val ? -1 : 0 ), _Al ) - { // construct from _Count * _Val, with allocator - _Trim( _Count ); - } - - template - vector( _Iter _First, _Iter _Last ) - : _Mysize( 0 ), _Myvec() - { // construct from [_First, _Last) - _BConstruct( _First, _Last, _STD _Iter_cat( _First ) ); - } - - template - vector( _Iter _First, _Iter _Last, const _Alloc& _Al ) - : _Mysize( 0 ), _Myvec( _Al ) - { // construct from [_First, _Last), with allocator - _BConstruct( _First, _Last, _STD _Iter_cat( _First ) ); - } - - template - void _BConstruct( _Iter _Count, _Iter _Val, _STD _Int_iterator_tag ) - { // initialize from _Count * _Val - size_type _Num = ( size_type )_Count; - _Myvec.assign( _Num, ( _Ty )_Val ? -1 : 0 ); - _Trim( _Num ); - } - - template - void _BConstruct( _Iter _First, _Iter _Last, _STD input_iterator_tag ) - { // initialize from [_First, _Last), input iterators - insert( begin(), _First, _Last ); - } - - ~vector() - { // destroy the object - _Mysize = 0; - } - - void reserve( size_type _Count ) - { // determine new minimum length of allocated storage - _Myvec.reserve( _Nw( _Count ) ); - } - - size_type capacity() const - { // return current length of allocated storage - return ( _Myvec.capacity() * _VBITS ); - } - - iterator begin() - { // return iterator for beginning of mutable sequence - return ( iterator( _VEC_ITER_BASE( _Myvec.begin() ) ) ); - } - - const_iterator begin() const - { // return iterator for beginning of nonmutable sequence - return ( const_iterator( _VEC_ITER_BASE( _Myvec.begin() ) ) ); - } - - iterator end() - { // return iterator for end of mutable sequence - iterator _Tmp = begin(); - if ( 0 < _Mysize ) - _Tmp += _Mysize; - return ( _Tmp ); - } - - const_iterator end() const - { // return iterator for end of nonmutable sequence - const_iterator _Tmp = begin(); - if ( 0 < _Mysize ) - _Tmp += _Mysize; - return ( _Tmp ); - } - - reverse_iterator rbegin() - { // return iterator for beginning of reversed mutable sequence - return ( reverse_iterator( end() ) ); - } - - const_reverse_iterator rbegin() const - { // return iterator for beginning of reversed nonmutable sequence - return ( const_reverse_iterator( end() ) ); - } - - reverse_iterator rend() - { // return iterator for end of reversed mutable sequence - return ( reverse_iterator( begin() ) ); - } - - const_reverse_iterator rend() const - { // return iterator for end of reversed nonmutable sequence - return ( const_reverse_iterator( begin() ) ); - } - - void resize( size_type _Newsize, bool _Val = false ) - { // determine new length, padding with _Val elements as needed - if ( size() < _Newsize ) - _Insert_n( end(), _Newsize - size(), _Val ); - else if ( _Newsize < size() ) - erase( begin() + _Newsize, end() ); - } - - size_type size() const - { // return length of sequence - return ( _Mysize ); - } - - size_type max_size() const - { // return maximum possible length of sequence - const size_type _Maxsize = _Myvec.max_size(); - return ( _Maxsize < ( size_type )( -1 ) / _VBITS - ? _Maxsize * _VBITS : ( size_type )( -1 ) ); - } - - bool empty() const - { // test if sequence is empty - return ( size() == 0 ); - } - - _Alloc get_allocator() const - { // return allocator object for values - return ( _Myvec.get_allocator() ); - } - - const_reference at( size_type _Off ) const - { // subscript nonmutable sequence with checking - if ( size() <= _Off ) - _Xran(); - return ( *( begin() + _Off ) ); - } - - reference at( size_type _Off ) - { // subscript mutable sequence with checking - if ( size() <= _Off ) - _Xran(); - return ( *( begin() + _Off ) ); - } - - const_reference operator[]( size_type _Off ) const - { // subscript nonmutable sequence - return ( *( begin() + _Off ) ); - } - - reference operator[]( size_type _Off ) - { // subscript mutable sequence - return ( *( begin() + _Off ) ); - } - - reference front() - { // return first element of mutable sequence - return ( *begin() ); - } - - const_reference front() const - { // return first element of nonmutable sequence - return ( *begin() ); - } - - reference back() - { // return last element of mutable sequence - return ( *( end() - 1 ) ); - } - - const_reference back() const - { // return last element of nonmutable sequence - return ( *( end() - 1 ) ); - } - - void push_back( bool _Val ) - { // insert element at end - insert( end(), _Val ); - } - - void pop_back() - { // erase element at end - if ( !empty() ) - erase( end() - 1 ); - } - - template - void assign( _Iter _First, _Iter _Last ) - { // assign [_First, _Last) - _Assign( _First, _Last, _STD _Iter_cat( _First ) ); - } - - template - void _Assign( _Iter _Count, _Iter _Val, _STD _Int_iterator_tag ) - { // assign _Count * _Val - _Assign_n(( size_type )_Count, ( bool )_Val ); - } - - template - void _Assign( _Iter _First, _Iter _Last, _STD input_iterator_tag ) - { // assign [_First, _Last), input iterators - erase( begin(), end() ); - insert( begin(), _First, _Last ); - } - - void assign( size_type _Count, bool _Val ) - { // assign _Count * _Val - _Assign_n( _Count, _Val ); - } - - iterator insert( iterator _Where, bool _Val ) - { // insert _Val at _Where - size_type _Off = _Where - begin(); - _Insert_n( _Where, ( size_type )1, _Val ); - return ( begin() + _Off ); - } - - void insert( iterator _Where, size_type _Count, bool _Val ) - { // insert _Count * _Val at _Where - _Insert_n( _Where, _Count, _Val ); - } - - template - void insert( iterator _Where, _Iter _First, _Iter _Last ) - { // insert [_First, _Last) at _Where - _Insert( _Where, _First, _Last, _STD _Iter_cat( _First ) ); - } - - template - void _Insert( iterator _Where, _Iter _Count, _Iter _Val, - _STD _Int_iterator_tag ) - { // insert _Count * _Val at _Where - _Insert_n( _Where, ( size_type )_Count, ( bool )_Val ); - } - - template - void _Insert( iterator _Where, _Iter _First, _Iter _Last, - _STD input_iterator_tag ) - { // insert [_First, _Last) at _Where, input iterators - size_type _Off = _Where - begin(); - - for ( ; _First != _Last; ++_First, ++_Off ) - insert( begin() + _Off, *_First ); - } - - template - void _Insert( iterator _Where, - _Iter _First, _Iter _Last, - _STD forward_iterator_tag ) - { // insert [_First, _Last) at _Where, forward iterators - - - size_type _Count = 0; - _Distance( _First, _Last, _Count ); - - size_type _Off = _Insert_x( _Where, _Count ); - copy( _First, _Last, begin() + _Off ); - } - - iterator erase( iterator _Where ) - { // erase element at _Where - size_type _Off = _Where - begin(); - - copy( _Where + 1, end(), _Where ); - - _Trim( _Mysize - 1 ); - return ( begin() + _Off ); - } - - iterator erase( iterator _First, iterator _Last ) - { // erase [_First, _Last) - size_type _Off = _First - begin(); - - iterator _Next = copy( _Last, end(), _First ); - _Trim( _Next - begin() ); - - return ( begin() + _Off ); - } - - void clear() - { // erase all elements - erase( begin(), end() ); - } - - void flip() - { // toggle all elements - for ( typename _Vbtype::iterator _Next = _Myvec.begin(); - _Next != _Myvec.end(); ++_Next ) - *_Next = ( _Vbase )~ * _Next; - _Trim( _Mysize ); - } - - void swap( _Myt& _Right ) - { // exchange contents with right - - _STD swap( _Mysize, _Right._Mysize ); - _Myvec.swap( _Right._Myvec ); - } - - static void swap( reference _Left, reference _Right ) - { // swap _Left and _Right vector elements - bool _Val = _Left; - _Left = _Right; - _Right = _Val; - } - -protected: - void _Assign_n( size_type _Count, bool _Val ) - { // assign _Count * _Val - erase( begin(), end() ); - _Insert_n( begin(), _Count, _Val ); - } - - void _Insert_n( iterator _Where, - size_type _Count, bool _Val ) - { // insert _Count * _Val at _Where - size_type _Off = _Insert_x( _Where, _Count ); - _STD fill( begin() + _Off, begin() + ( _Off + _Count ), _Val ); - } - - size_type _Insert_x( iterator _Where, size_type _Count ) - { // make room to insert _Count elements at _Where - size_type _Off = _Where - begin(); - - if ( _Count == 0 ) - ; - else if ( max_size() - size() < _Count ) - _Xlen(); // result too long - else - { // worth doing - _Myvec.resize( _Nw( size() + _Count ), 0 ); - if ( size() == 0 ) - _Mysize += _Count; - else - { // make room and copy down suffix - iterator _Oldend = end(); - _Mysize += _Count; - _STD copy_backward( begin() + _Off, _Oldend, end() ); - } - - } - return ( _Off ); - } - - static size_type _Nw( size_type _Count ) - { // return number of base words from number of bits - return (( _Count + _VBITS - 1 ) / _VBITS ); - } - - void _Trim( size_type _Size ) - { // trim base vector to exact length in bits - if ( max_size() < _Size ) - _Xlen(); // result too long - size_type _Words = _Nw( _Size ); - - if ( _Words < _Myvec.size() ) - _Myvec.erase( _Myvec.begin() + _Words, _Myvec.end() ); - _Mysize = _Size; - _Size %= _VBITS; - if ( 0 < _Size ) - _Myvec[_Words - 1] &= ( _Vbase )(( 1 << _Size ) - 1 ); - } - - void _Xlen() const - { // report a length_error - } - - void _Xran() const - { // throw an out_of_range error - } - - size_type _Mysize; // current length of sequence - _Vbtype _Myvec; // base vector of words -}; - -typedef vector > _Bvector; - -#if _HAS_TRADITIONAL_STL -typedef _Bvector bit_vector; -#endif /* _HAS_TRADITIONAL_STL */ - -#if _HAS_TRADITIONAL_STL -#define __vector__ vector -#endif /* _HAS_TRADITIONAL_STL */ - -//_STD_END - -} - -#endif /* _VECTOR_ */ diff --git a/console/rgl/src/.rgl_cg.cpp.swp b/console/rgl/src/.rgl_cg.cpp.swp new file mode 100644 index 0000000000..67ec259932 Binary files /dev/null and b/console/rgl/src/.rgl_cg.cpp.swp differ diff --git a/console/rgl/src/Utils/EnumMap.cpp b/console/rgl/src/Utils/EnumMap.cpp new file mode 100644 index 0000000000..667944650d --- /dev/null +++ b/console/rgl/src/Utils/EnumMap.cpp @@ -0,0 +1,23 @@ +#include "../../include/export/RGL/rgl.h" +#include "../../include/RGL/private.h" +#include + +const char *rglMapLookupEnum( const RGLenumMap* map, unsigned int count, GLenum e ) +{ + for (GLuint i = 0; i < count; ++i) + if (map[i].e == e) + return map[i].s; + + return NULL; +} + +GLenum rglMapLookupString( const RGLenumMap* map, unsigned int count, const char *s ) +{ + if (s != NULL) + for (GLuint i = 0;i < count;++i) + if ( strcmp( map[i].s, s) == 0) + return map[i].e; + + return -1U; +} + diff --git a/console/rgl/src/Utils/NameSpace.cpp b/console/rgl/src/Utils/NameSpace.cpp new file mode 100644 index 0000000000..d7e6e1b34b --- /dev/null +++ b/console/rgl/src/Utils/NameSpace.cpp @@ -0,0 +1,106 @@ +#include +#include +#include +#include + +#include + +void rglInitNameSpace( rglNameSpace * name ) +{ + name->data = NULL; + name->firstFree = NULL; + name->capacity = 0; +} + +void rglFreeNameSpace( rglNameSpace * ns ) +{ + // XXX should we verify all names were freed ? + + if ( ns->data ) { free( ns->data ); }; + ns->data = NULL; + ns->capacity = 0; + ns->firstFree = NULL; +} + +static const int NAME_INCREMENT = 4; +unsigned int rglCreateName( rglNameSpace * ns, void* object ) +{ + // NULL is reserved for the guard of the linked list. + if (ns->firstFree == NULL) + { + // need to allocate more pointer space + int newCapacity = ns->capacity + NAME_INCREMENT; + + // realloc the block of pointers + void** newData = ( void** )malloc( newCapacity * sizeof( void* ) ); + if ( newData == NULL ) + { + // XXX what should we generally do here ? + rglCgRaiseError( CG_MEMORY_ALLOC_ERROR ); + return 0; + } + memcpy( newData, ns->data, ns->capacity * sizeof( void* ) ); + if ( ns->data != NULL ) free( ns->data ); + ns->data = newData; + + // initialize the pointers to the next free elements. + // (effectively build a linked list of free elements in place) + // treat the last item differently, by linking it to NULL + for ( int index = ns->capacity; index < newCapacity - 1; ++index ) + ns->data[index] = ns->data + index + 1; + + ns->data[newCapacity - 1] = NULL; + // update the first free element to the new data pointer. + ns->firstFree = ns->data + ns->capacity; + // update the new capacity. + ns->capacity = newCapacity; + } + // firstFree is a pointer, compute the index of it + unsigned int result = ns->firstFree - ns->data; + + // update the first free to the next free element. + ns->firstFree = ( void** ) * ns->firstFree; + + // store the object in data. + ns->data[result] = object; + + // offset the index by 1 to avoid the name 0 + return result + 1; +} + +unsigned int rglIsName( rglNameSpace* ns, unsigned int name ) +{ + // there should always be a namesepace + // 0 is never valid. + if (RGL_UNLIKELY(name == 0)) + return 0; + + // names start numbering from 1, so convert from a name to an index + --name; + + // test whether it is in the namespace range + if ( RGL_UNLIKELY( name >= ns->capacity ) ) + return 0; + + // test whether the pointer is inside the data block. + // if so, it means it is free. + // if it points to NULL, it means it is the last free name in the linked list. + void** value = ( void** )ns->data[name]; + + if ( RGL_UNLIKELY(value == NULL || + ( value >= ns->data && value < ns->data + ns->capacity ) ) ) + return 0; + + // The pointer is not free and allocated, so name is a real name. + return 1; +} + +void rglEraseName( rglNameSpace* ns, unsigned int name ) +{ + if (rglIsName(ns, name)) + { + --name; + ns->data[name] = ns->firstFree; + ns->firstFree = ns->data + name; + } +} diff --git a/console/rgl/src/Utils/TexNameSpace.cpp b/console/rgl/src/Utils/TexNameSpace.cpp new file mode 100644 index 0000000000..af822d5183 --- /dev/null +++ b/console/rgl/src/Utils/TexNameSpace.cpp @@ -0,0 +1,103 @@ +#include +#include "../../include/export/RGL/rgl.h" +#include "../../include/RGL/Types.h" +#include "../../include/RGL/Utils.h" +#include "../../include/RGL/private.h" + +static const unsigned int capacityIncr = 16; + +// Initialize texture namespace ns with creation and destruction functions +void rglTexNameSpaceInit( rglTexNameSpace *ns, rglTexNameSpaceCreateFunction create, rglTexNameSpaceDestroyFunction destroy ) +{ + ns->capacity = capacityIncr; + ns->data = (void **)malloc( ns->capacity * sizeof( void* ) ); + memset( ns->data, 0, ns->capacity*sizeof( void* ) ); + ns->create = create; + ns->destroy = destroy; +} + +// Free texture namespace ns +void rglTexNameSpaceFree( rglTexNameSpace *ns ) +{ + for ( GLuint i = 1;i < ns->capacity;++i ) + if ( ns->data[i] ) ns->destroy( ns->data[i] ); + + free( ns->data ); + ns->data = NULL; +} + +// Reset all names in namespace ns to NULL +void rglTexNameSpaceResetNames( rglTexNameSpace *ns ) +{ + for ( GLuint i = 1;i < ns->capacity;++i ) + { + if ( ns->data[i] ) + { + ns->destroy( ns->data[i] ); + ns->data[i] = NULL; + } + } +} + +// Get an index of the first free name in namespace ns +GLuint rglTexNameSpaceGetFree( rglTexNameSpace *ns ) +{ + GLuint i; + for (i = 1;i < ns->capacity;++i) + if (!ns->data[i]) + break; + return i; +} + +// Add name to namespace by increasing capacity and calling creation call back function +// Return GL_TRUE for success, GL_FALSE for failure +GLboolean rglTexNameSpaceCreateNameLazy( rglTexNameSpace *ns, GLuint name ) +{ + if (name >= ns->capacity) + { + int newCapacity = name >= ns->capacity + capacityIncr ? name + 1 : ns->capacity + capacityIncr; + void **newData = ( void ** )realloc( ns->data, newCapacity * sizeof( void * ) ); + memset( newData + ns->capacity, 0, ( newCapacity - ns->capacity )*sizeof( void * ) ); + ns->data = newData; + ns->capacity = newCapacity; + } + if ( !ns->data[name] ) + { + ns->data[name] = ns->create(); + if ( ns->data[name] ) return GL_TRUE; + } + return GL_FALSE; +} + +// Check if name is a valid name in namespace ns +// Return GL_TRUE if so, GL_FALSE otherwise +GLboolean rglTexNameSpaceIsName( rglTexNameSpace *ns, GLuint name ) +{ + if (( name > 0 ) && ( name < ns->capacity ) ) return( ns->data[name] != 0 ); + else return GL_FALSE; +} + +// Generate new n names in namespace ns +void rglTexNameSpaceGenNames( rglTexNameSpace *ns, GLsizei n, GLuint *names ) +{ + for ( int i = 0;i < n;++i ) + { + GLuint name = rglTexNameSpaceGetFree( ns ); + names[i] = name; + if (name) + rglTexNameSpaceCreateNameLazy( ns, name ); + } +} + +// Delete n names from namespace ns +void rglTexNameSpaceDeleteNames( rglTexNameSpace *ns, GLsizei n, const GLuint *names ) +{ + for ( int i = 0;i < n;++i ) + { + GLuint name = names[i]; + if (!rglTexNameSpaceIsName(ns, name)) + continue; + ns->destroy( ns->data[name] ); + ns->data[name] = NULL; + } +} diff --git a/console/rgl/src/cg/cgbdefs.hpp b/console/rgl/src/cg/cgbdefs.hpp new file mode 100644 index 0000000000..8e0b1a81e7 --- /dev/null +++ b/console/rgl/src/cg/cgbdefs.hpp @@ -0,0 +1,275 @@ +#ifndef _CGC_CGBIO_CGBDEFS_HPP +#define _CGC_CGBIO_CGBDEFS_HPP + +// Platform depended definitions: +typedef unsigned int Elf32_Addr; +typedef unsigned short Elf32_Half; +typedef short Elf32_Shalf; +typedef unsigned int Elf32_Off; +typedef signed int Elf32_Sword; +typedef unsigned int Elf32_Word; + +typedef unsigned short Elf64_Half; +typedef short Elf64_Shalf; + +#ifdef __CELLOS_LV2__ +typedef size_t ptrdiff_t; +typedef size_t ptrdiff_t; +#endif + +/////////////////////// +// ELF Header Constants + +// File type +#define ET_NONE 0 +#define ET_REL 1 +#define ET_EXEC 2 +#define ET_DYN 3 +#define ET_CORE 4 +#define ET_LOOS 0xFE00 +#define ET_HIOS 0xFEFF +#define ET_LOPROC 0xFF00 +#define ET_HIPROC 0xFFFF + +// Machine/Architecture +#define EM_NONE 0 // No machine +#define EM_RSX 0x528e // RSX + +// Machine/Architecture flags +#define EM_RSX_NONE 0 + +// Machine/Architecture ABI version +#define EI_ABIVERSION_RSX 1 + +// ELF File version +#define EV_NONE 0 +#define EV_CURRENT 1 + +// Identification index +#define EI_MAG0 0 +#define EI_MAG1 1 +#define EI_MAG2 2 +#define EI_MAG3 3 +#define EI_CLASS 4 +#define EI_DATA 5 +#define EI_VERSION 6 +#define EI_OSABI 7 +#define EI_ABIVERSION 8 +#define EI_PAD 9 +#define EI_NIDENT 16 + +// Magic number + +#ifndef ELFMAG0 +#define ELFMAG0 0x7F +#endif + +#define ELFMAG1 'E' +#define ELFMAG2 'L' +#define ELFMAG3 'F' + +// File class +#define ELFCLASSNONE 0 +#define ELFCLASS32 1 +#define ELFCLASS64 2 + +// Encoding +#define ELFDATANONE 0 +#define ELFDATA2LSB 1 +#define ELFDATA2MSB 2 + +// OS extensions +#define ELFOSABI_NONE 0 // No extensions or unspecified +#define ELFOSABI_HPUX 1 // Hewlett-Packard HP-UX +#define ELFOSABI_NETBSD 2 // NetBSD +#define ELFOSABI_LINUX 3 // Linux +#define ELFOSABI_SOLARIS 6 // Sun Solaris +#define ELFOSABI_AIX 7 // AIX +#define ELFOSABI_IRIX 8 // IRIX +#define ELFOSABI_FREEBSD 9 // FreeBSD +#define ELFOSABI_TRU64 10 // Compaq TRU64 UNIX +#define ELFOSABI_MODESTO 11 // Novell Modesto +#define ELFOSABI_OPENBSD 12 // Open BSD +#define ELFOSABI_CGRUNTIME 19 // Cg Run-Time + + + +///////////////////// +// Sections constants + +// Section indexes +#ifndef SHN_UNDEF +#define SHN_UNDEF 0 +#endif + +#ifndef SHN_LORESERVE +#define SHN_LORESERVE 0xFF00 +#endif + +#ifndef SHN_LOPROC +#define SHN_LOPROC 0xFF00 +#endif + +#ifndef SHN_HIPROC +#define SHN_HIPROC 0xFF1F +#endif + +#ifndef SHN_LOOS +#define SHN_LOOS 0xFF20 +#endif + +#ifndef SHN_HIOS +#define SHN_HIOS 0xFF3F +#endif + +#ifndef SHN_ABS +#define SHN_ABS 0xFFF1 +#endif + +#ifndef SHN_COMMON +#define SHN_COMMON 0xFFF2 +#endif + +#ifndef SHN_XINDEX +#define SHN_XINDEX 0xFFFF +#endif + +#ifndef SHN_HIRESERVE +#define SHN_HIRESERVE 0xFFFF +#endif + +// Section types +#define SHT_NULL 0 +#define SHT_PROGBITS 1 +#define SHT_SYMTAB 2 +#define SHT_STRTAB 3 +#define SHT_RELA 4 +#define SHT_HASH 5 +#define SHT_DYNAMIC 6 +#define SHT_NOTE 7 +#define SHT_NOBITS 8 +#define SHT_REL 9 +#define SHT_SHLIB 10 +#define SHT_DYNSYM 11 +#define SHT_INIT_ARRAY 14 +#define SHT_FINI_ARRAY 15 +#define SHT_PREINIT_ARRAY 16 +#define SHT_GROUP 17 +#define SHT_SYMTAB_SHNDX 18 +#define SHT_LOOS 0x60000000 +#define SHT_HIOS 0x6fffffff +#define SHT_LOPROC 0x70000000 +#define SHT_RSX_PARAM 0x70000000 +#define SHT_RSX_SHADERTAB 0x70000001 +#define SHT_RSX_FXTAB 0x70000002 +#define SHT_RSX_ANNOTATE 0x70000003 +#define SHT_HIPROC 0x7FFFFFFF +#define SHT_LOUSER 0x80000000 +#define SHT_HIUSER 0xFFFFFFFF + +// Section flags +#ifndef SHF_WRITE +#define SHF_WRITE 0x1 +#endif + +#ifndef SHF_ALLOC +#define SHF_ALLOC 0x2 +#endif + +#ifndef SHF_EXECINSTR +#define SHF_EXECINSTR 0x4 +#endif + +#ifndef SHF_MERGE +#define SHF_MERGE 0x10 +#endif + +#ifndef SHF_STRINGS +#define SHF_STRINGS 0x20 +#endif + +#ifndef SHF_INFO_LINK +#define SHF_INFO_LINK 0x40 +#endif + +#ifndef SHF_LINK_ORDER +#define SHF_LINK_ORDER 0x80 +#endif + +#ifndef SHF_OS_NONCONFORMING +#define SHF_OS_NONCONFORMING 0x100 +#endif + +#define SHF_GROUP 0x200 +#define SHF_TLS 0x400 +#define SHF_MASKOS 0x0ff00000 + +#ifndef SHF_MASKPROC +#define SHF_MASKPROC 0xF0000000 +#endif + +// Section group flags +#define GRP_COMDAT 0x1 +#define GRP_MASKOS 0x0ff00000 +#define GRP_MASKPROC 0xf0000000 + +// Symbol binding +#define STB_LOCAL 0 +#define STB_GLOBAL 1 +#define STB_WEAK 2 +#define STB_LOOS 10 +#define STB_HIOS 12 +#define STB_LOPROC 13 +#define STB_HIPROC 15 + +// Symbol types +#define STT_NOTYPE 0 +#define STT_OBJECT 1 +#define STT_FUNC 2 +#define STT_SECTION 3 +#define STT_FILE 4 +#define STT_COMMON 5 +#define STT_TLS 6 +#define STT_LOOS 10 +#define STT_HIOS 12 +#define STT_LOPROC 13 +#define STT_HIPROC 15 + +// Symbol visibility +#define STV_DEFAULT 0 +#define STV_INTERNAL 1 +#define STV_HIDDEN 2 +#define STV_PROTECTED 3 + +// Shader Function type (st_other field) +#define STO_RSX_SHADER 0 +#define STO_RSX_EFFECT 1 + +// Undefined name +#define STN_UNDEF 0 + +// Relocation types +#define R_RSX_NONE 0 +#define R_RSX_FLOAT4 1 + +/* Note header in a PT_NOTE section */ +struct Elf32_Note { + Elf32_Word n_namesz; /* Name size */ + Elf32_Word n_descsz; /* Content size */ + Elf32_Word n_type; /* Content type */ +}; + + +// Relocation entries + +// Dynamic structure +struct Elf32_Dyn { + Elf32_Sword d_tag; + union { + Elf32_Word d_val; + Elf32_Addr d_ptr; + } d_un; +}; + + +#endif // CGC_CGBIO_CGBDEFS_HPP diff --git a/console/rgl/src/cg/cgbi.hpp b/console/rgl/src/cg/cgbi.hpp new file mode 100644 index 0000000000..b83555c1af --- /dev/null +++ b/console/rgl/src/cg/cgbi.hpp @@ -0,0 +1,53 @@ +#ifndef _CGC_CGBIO_CGBI_HPP +#define _CGC_CGBIO_CGBI_HPP + +#include +#include +#include + +#include "cgbdefs.hpp" + + +using std::istream; + +namespace cgc { +namespace bio { + +class elf_reader { + public: + virtual ptrdiff_t reference() const = 0; + virtual ptrdiff_t release() const = 0; + virtual CGBIO_ERROR load( const char * filename ) = 0; + virtual CGBIO_ERROR load( istream* stream, int start ) = 0; + virtual bool is_initialized() const = 0; + virtual ~elf_reader() {} + +}; // elf_reader + + +class isection +{ + public: + virtual ~isection() = 0; + + virtual int reference() const = 0; + virtual int release() const = 0; + + // Section info functions + virtual Elf32_Half index() const = 0; + virtual char *name() const = 0; + virtual Elf32_Word type() const = 0; + virtual Elf32_Word flags() const = 0; + virtual Elf32_Addr addr() const = 0; + virtual Elf32_Word size() const = 0; + virtual Elf32_Word link() const = 0; + virtual Elf32_Word info() const = 0; + virtual Elf32_Word addralign() const = 0; + virtual Elf32_Word entsize() const = 0; + virtual const char* data() const = 0; +}; + +} // bio namespace +} // cgc namespace + +#endif // CGC_CGBIO_CGBI_HPP diff --git a/console/rgl/src/cg/cgbiimpl.hpp b/console/rgl/src/cg/cgbiimpl.hpp new file mode 100644 index 0000000000..342bb38edb --- /dev/null +++ b/console/rgl/src/cg/cgbiimpl.hpp @@ -0,0 +1,40 @@ +#if !defined(CGC_CGBIO_CGBIIMPL_HPP) +#define CGC_CGBIO_CGBIIMPL_HPP 1 + +#include +#include +#include +#include + +#include "cgbio.hpp" + +using std::istream; + +namespace cgc { +namespace bio { + +class elf_reader_impl : public elf_reader +{ + public: + elf_reader_impl(); + virtual ~elf_reader_impl(); + virtual CGBIO_ERROR load( const char* filename ); + virtual CGBIO_ERROR load( istream* stream, int start ); + virtual bool is_initialized() const; + virtual ptrdiff_t reference() const; + virtual ptrdiff_t release() const; + +// virtual int get_revision() const; + + private: + mutable ptrdiff_t ref_count_; + istream* stream_; + bool initialized_; + Elf32_Ehdr header_; + std::vector sections_; +}; // CGBIImpl + +} // bio namespace +} // cgc namespace + +#endif // CGC_CGBIO_CGBIIMPL_HPP diff --git a/console/rgl/src/cg/cgbio.def b/console/rgl/src/cg/cgbio.def new file mode 100644 index 0000000000..36ebe48c1f --- /dev/null +++ b/console/rgl/src/cg/cgbio.def @@ -0,0 +1,9 @@ +LIBRARY cgbu +EXPORTS +;?CreateCGBI@CGBIO@@QBE?AW4CGBIO_Err@@PAPAVCGBI@@@Z +;?instance@CGBIO@@SAPBV1@XZ +;?get_revision@CGBIImpl@@UBEHXZ +get_revision +instance +CreateCGBI + diff --git a/console/rgl/src/cg/cgbio.hpp b/console/rgl/src/cg/cgbio.hpp new file mode 100644 index 0000000000..e5ed69cf97 --- /dev/null +++ b/console/rgl/src/cg/cgbio.hpp @@ -0,0 +1,66 @@ +/* cgbio.hpp -- interface to the whole cg binary input/output library. + * + * This is the only header file, that an application need to include + * in order to manipulate both elf and nvidia original cg binary + * format. + */ + +#if !defined(CGC_CGBIO_CGBIO_HPP) +#define CGC_CGBIO_CGBIO_HPP 1 + +#include "cgbdefs.hpp" + +#include + + +namespace cgc { +namespace bio { + +enum CGBIO_ERROR { + CGBIO_ERROR_NO_ERROR, + CGBIO_ERROR_LOADED, + CGBIO_ERROR_FILEIO, + CGBIO_ERROR_FORMAT, + CGBIO_ERROR_INDEX, + CGBIO_ERROR_MEMORY, + CGBIO_ERROR_RELOC, + CGBIO_ERROR_SYMBOL, + CGBIO_ERROR_UNKNOWN_TYPE +}; + +} // bio namespace +} // cgc namespace + +#include "cgbi.hpp" +#include "cgbo.hpp" +#include "nvbi.hpp" +#include "nvbo.hpp" + +namespace cgc { +namespace bio { + + class bin_io + { + public: + static const bin_io* instance(); + static void delete_instance(); + + CGBIO_ERROR new_elf_reader( elf_reader** obj ) const; + CGBIO_ERROR new_elf_writer( elf_writer** obj ) const; + + CGBIO_ERROR new_nvb_reader( nvb_reader** obj ) const; + CGBIO_ERROR new_nvb_writer( nvb_writer** obj ) const; + + const char *error_string( CGBIO_ERROR error ) const; + + private: + bin_io(); + bin_io( const bin_io& ); + + static bin_io* instance_; +}; // bin_io + +} // bio namespace +} // cgc namespace + +#endif // CGC_CGBIO_CGBIO_HPP diff --git a/console/rgl/src/cg/cgbo.hpp b/console/rgl/src/cg/cgbo.hpp new file mode 100644 index 0000000000..b00366e677 --- /dev/null +++ b/console/rgl/src/cg/cgbo.hpp @@ -0,0 +1,334 @@ +#if !defined(CGC_CGBIO_CGBO_HPP) +#define CGC_CGBIO_CGBO_HPP 1 + +#include +#include +#include + +#include "cgbdefs.hpp" +#include "cgbtypes.h" + +using std::ofstream; +using std::streampos; + +namespace cgc { +namespace bio { + +class osection; + +class elf_writer { + public: + enum PRODUCER + { + CGBO_HASH, + CGBO_STR, + CGBO_SYM, + CGBO_REL, + CGBO_PARAM, + CGBO_CONST, + CGBO_VP, + CGBO_FP + }; + + virtual ~elf_writer() {} + + virtual ptrdiff_t + reference() = 0; + + virtual ptrdiff_t + release() = 0; + + virtual CGBIO_ERROR + save( ofstream& ofs ) = 0; + + virtual CGBIO_ERROR + save( const char* filename ) = 0; + + virtual CGBIO_ERROR + set_attr( unsigned char file_class, + unsigned char endianness, + unsigned char ELFversion, + unsigned char abi, + unsigned char ABIversion, + Elf32_Half type, + Elf32_Half machine, + Elf32_Word version, + Elf32_Word flags ) = 0; + + virtual Elf32_Addr + get_entry() const = 0; + + virtual CGBIO_ERROR + set_entry( Elf32_Addr entry ) = 0; + + virtual unsigned char + endianness() const = 0; + + virtual Elf32_Half + num_of_sections() const = 0; + + virtual osection* + get_section( Elf32_Half index ) const = 0; + + virtual osection* + get_section( const char* name ) const = 0; + + virtual osection* + add_section( const char *name, + Elf32_Word type, + Elf32_Word flags, + Elf32_Word info, + Elf32_Word align, + Elf32_Word esize ) = 0; + + virtual streampos + section_offset( Elf32_Half index ) const = 0; + + virtual CGBIO_ERROR + new_section_out( PRODUCER producer, + osection* sec, + void** obj ) const = 0; +}; // elf_writer interface class + +class osection +{ + public: + virtual ~osection() {} + + virtual ptrdiff_t + reference() = 0; + + virtual ptrdiff_t + release() = 0; + + virtual CGBIO_ERROR + save( ofstream& of, + streampos header, + streampos data) = 0; + + virtual Elf32_Half + index() const = 0; + + virtual const char* + name() const = 0; + + virtual Elf32_Word + type() const = 0; + + virtual Elf32_Word + flags() const = 0; + + virtual Elf32_Word + info() const = 0; + + virtual Elf32_Word + addralign() const = 0; + + virtual Elf32_Word + entsize() const = 0; + + virtual Elf32_Word + size() const = 0; + + virtual Elf32_Word + get_name_index() const = 0; + + virtual void + set_name_index( Elf32_Word index ) = 0; + + virtual Elf32_Addr + get_address() const = 0; + + virtual void + set_address( Elf32_Addr addr ) = 0; + + virtual Elf32_Word + get_link() const = 0; + + virtual void + set_link( Elf32_Word link ) = 0; + + virtual char* + get_data() const = 0; + + virtual CGBIO_ERROR + set_data( const char* data, Elf32_Word size ) = 0; + + virtual CGBIO_ERROR + add_data( const char* data, Elf32_Word size ) = 0; + +}; // osection interface class + + +class ostring_table +{ + public: + virtual ~ostring_table() {} + + virtual ptrdiff_t + reference() = 0; + + virtual ptrdiff_t + release() = 0; + + virtual const char* + get( Elf32_Word index ) const = 0; + + //search the string table for a given string + virtual Elf32_Word + find( const char *) const = 0; + + //add the string to the table if it's not already there, return the index of the string + virtual Elf32_Word + addUnique( const char* str ) = 0; + + virtual Elf32_Word + add( const char* str ) = 0; +}; // ostring_table + +class oconst_table +{ +public: + virtual ~oconst_table() {} + + virtual ptrdiff_t + reference() = 0; + + virtual ptrdiff_t + release() = 0; + + virtual const Elf32_Word* + get( Elf32_Word index ) const = 0; + + virtual Elf32_Word + add( const Elf32_Word *data, Elf32_Word size ) = 0; +}; + +class osymbol_table +{ + public: + + virtual ~osymbol_table() {} + + virtual ptrdiff_t + reference() = 0; + + virtual ptrdiff_t + release() = 0; + + virtual Elf32_Word + add_entry( Elf32_Word name, + Elf32_Addr value, + Elf32_Word size, + unsigned char info, + unsigned char other, + Elf32_Half shndx ) = 0; + + virtual Elf32_Word + add_entry( Elf32_Word name, + Elf32_Addr value, + Elf32_Word size, + unsigned char bind, + unsigned char type, + unsigned char other, + Elf32_Half shndx ) = 0; + + virtual Elf32_Word + add_entry( ostring_table* strtab, + const char* str, + Elf32_Addr value, + Elf32_Word size, + unsigned char info, + unsigned char other, + Elf32_Half shndx ) = 0; + + virtual Elf32_Word + add_entry( ostring_table* strtab, + const char* str, + Elf32_Addr value, + Elf32_Word size, + unsigned char bind, + unsigned char type, + unsigned char other, + Elf32_Half shndx ) = 0; +}; // osymbol_table + + +class orelocation_table +{ + public: + virtual ~orelocation_table() {} + + virtual ptrdiff_t + reference() = 0; + + virtual ptrdiff_t + release() = 0; + + virtual CGBIO_ERROR + add_entry( Elf32_Addr offset, + Elf32_Word info ) = 0; + + virtual CGBIO_ERROR + add_entry( Elf32_Addr offset, + Elf32_Word symbol, + unsigned char type ) = 0; + + virtual CGBIO_ERROR + add_entry( Elf32_Addr offset, + Elf32_Word info, + Elf32_Sword addend ) = 0; + + virtual CGBIO_ERROR + add_entry( Elf32_Addr offset, + Elf32_Word symbol, + unsigned char type, + Elf32_Sword addend ) = 0; + + virtual CGBIO_ERROR + add_entry( ostring_table* strtab, + const char* str, + osymbol_table* symtab, + Elf32_Addr value, + Elf32_Word size, + unsigned char symInfo, + unsigned char other, + Elf32_Half shndx, + Elf32_Addr offset, + unsigned char type ) = 0; + + virtual CGBIO_ERROR + add_entry( ostring_table* strtab, + const char* str, + osymbol_table* symtab, + Elf32_Addr value, + Elf32_Word size, + unsigned char symInfo, + unsigned char other, + Elf32_Half shndx, + Elf32_Addr offset, + unsigned char type, + Elf32_Sword addend ) = 0; +}; // orelocation_table + + +class oparam_table +{ + public: + virtual ~oparam_table() {} + + virtual ptrdiff_t + reference() = 0; + + virtual ptrdiff_t + release() = 0; + + virtual CGBIO_ERROR + add_entry( Elf32_cgParameter& cgparam ) = 0; +}; // oparam_table + + +} // bio namespace +} // cgc namespace + +#endif // CGC_CGBIO_CGBO_HPP diff --git a/console/rgl/src/cg/cgboimpl.hpp b/console/rgl/src/cg/cgboimpl.hpp new file mode 100644 index 0000000000..dc13ccd54f --- /dev/null +++ b/console/rgl/src/cg/cgboimpl.hpp @@ -0,0 +1,378 @@ +#if !defined(CGC_CGBIO_CGBOIMPL_HPP) +#define CGC_CGBIO_CGBOIMPL_HPP 1 + +#include +#include +#include +#include + +#include "cgbio.hpp" + +namespace cgc { +namespace bio { + +class osection_impl; + +class elf_writer_impl : public elf_writer +{ + public: + + elf_writer_impl(); + virtual + ~elf_writer_impl(); + + virtual ptrdiff_t + reference(); + + virtual ptrdiff_t + release(); + + virtual CGBIO_ERROR + save( ofstream& ofs ); + + virtual CGBIO_ERROR + save( const char* filename ); + + virtual CGBIO_ERROR + set_attr( unsigned char file_class, + unsigned char endianness, + unsigned char ELFversion, + unsigned char abi, + unsigned char ABIversion, + Elf32_Half type, + Elf32_Half machine, + Elf32_Word version, + Elf32_Word flags ); + + virtual Elf32_Addr + get_entry() const; + + virtual CGBIO_ERROR + set_entry( Elf32_Addr entry ); + + virtual unsigned char + endianness() const; + + virtual Elf32_Half + num_of_sections() const; + + virtual osection* + get_section( Elf32_Half index ) const; + + virtual osection* + get_section( const char * name ) const; + + virtual osection* + add_section( const char * name, + Elf32_Word type, + Elf32_Word flags, + Elf32_Word info, + Elf32_Word align, + Elf32_Word esize ); + + virtual streampos + section_offset( Elf32_Half index ) const; + + virtual CGBIO_ERROR + new_section_out( PRODUCER, osection*, void** ) const; + + private: + ptrdiff_t ref_count_; + Elf32_Ehdr header_; + std::vector sections_; +}; // elf_writer_impl + + +class osection_impl : public osection +{ + public: + osection_impl( Elf32_Half index, + elf_writer* cgbo, + const char * name, + Elf32_Word type, + Elf32_Word flags, + Elf32_Word info, + Elf32_Word addrAlign, + Elf32_Word entrySize ); + + virtual + ~osection_impl(); + + virtual ptrdiff_t + reference(); + + virtual ptrdiff_t + release(); + + virtual CGBIO_ERROR + save( ofstream& of, + streampos header, + streampos data); + + virtual Elf32_Half + index() const; + + virtual const char * + name() const; + + virtual Elf32_Word + type() const; + + virtual Elf32_Word + flags() const; + + virtual Elf32_Word + info() const; + + virtual Elf32_Word + addralign() const; + + virtual Elf32_Word + entsize() const; + + virtual Elf32_Word + size() const; + + virtual Elf32_Word + get_name_index() const; + + virtual void + set_name_index( Elf32_Word index ); + + virtual Elf32_Addr + get_address() const; + + virtual void + set_address( Elf32_Addr addr ); + + virtual Elf32_Word + get_link() const; + + virtual void + set_link( Elf32_Word link ); + + virtual char* + get_data() const; + + virtual CGBIO_ERROR + set_data( const char* data, Elf32_Word size ); + + virtual CGBIO_ERROR + add_data( const char* data, Elf32_Word size ); + + private: + Elf32_Half index_; + elf_writer* cgbo_; + Elf32_Shdr sh_; + char name_[512]; + char* data_; +}; + +class ostring_table_impl : public ostring_table +{ + public: + ostring_table_impl( elf_writer* cgbo, osection* section ); + + virtual + ~ostring_table_impl(); + + virtual ptrdiff_t + reference(); + + virtual ptrdiff_t + release(); + + virtual const char* + get( Elf32_Word index ) const; + + //search the string table for a given string + virtual Elf32_Word + find( const char *) const; + + //add the string to the table if it's not already there, return the index of the string + virtual Elf32_Word + addUnique( const char* str ); + + virtual Elf32_Word + add( const char* str ); + + private: + ptrdiff_t ref_count_; + elf_writer* cgbo_; + osection* section_; + std::vector data_; +}; + +class oconst_table_impl : public oconst_table +{ +public: + oconst_table_impl( elf_writer* cgbo, osection* section ); + + virtual + ~oconst_table_impl(); + + virtual ptrdiff_t + reference(); + + virtual ptrdiff_t + release(); + + virtual const Elf32_Word* + get( Elf32_Word index ) const; + + virtual Elf32_Word + add( const Elf32_Word *data, Elf32_Word count ); + +private: + ptrdiff_t ref_count_; + elf_writer* cgbo_; + osection* section_; + std::vector data_; +}; + +class osymbol_table_impl : public osymbol_table +{ + public: + osymbol_table_impl( elf_writer* cgbo, osection* sec ); + + virtual + ~osymbol_table_impl(); + + virtual ptrdiff_t + reference(); + + virtual ptrdiff_t + release(); + + virtual Elf32_Word + add_entry( Elf32_Word name, + Elf32_Addr value, + Elf32_Word size, + unsigned char info, + unsigned char other, + Elf32_Half shndx ); + + virtual Elf32_Word + add_entry( Elf32_Word name, + Elf32_Addr value, + Elf32_Word size, + unsigned char bind, + unsigned char type, + unsigned char other, + Elf32_Half shndx ); + + virtual Elf32_Word + add_entry( ostring_table* strtab, + const char* str, + Elf32_Addr value, + Elf32_Word size, + unsigned char info, + unsigned char other, + Elf32_Half shndx ); + + virtual Elf32_Word + add_entry( ostring_table* strtab, + const char* str, + Elf32_Addr value, + Elf32_Word size, + unsigned char bind, + unsigned char type, + unsigned char other, + Elf32_Half shndx ); + private: + ptrdiff_t ref_count_; + elf_writer* cgbo_; + osection* section_; +}; + +class orelocation_table_impl : public orelocation_table +{ + public: + orelocation_table_impl( elf_writer* cgbo, osection* sec ); + + virtual + ~orelocation_table_impl(); + + virtual ptrdiff_t + reference(); + + virtual ptrdiff_t + release(); + + virtual CGBIO_ERROR + add_entry( Elf32_Addr offset, + Elf32_Word info ); + + virtual CGBIO_ERROR + add_entry( Elf32_Addr offset, + Elf32_Word symbol, + unsigned char type ); + + virtual CGBIO_ERROR + add_entry( Elf32_Addr offset, + Elf32_Word info, + Elf32_Sword addend ); + + virtual CGBIO_ERROR + add_entry( Elf32_Addr offset, + Elf32_Word symbol, + unsigned char type, + Elf32_Sword addend ); + + virtual CGBIO_ERROR + add_entry( ostring_table* pStrWriter, + const char* str, + osymbol_table* pSymWriter, + Elf32_Addr value, + Elf32_Word size, + unsigned char symInfo, + unsigned char other, + Elf32_Half shndx, + Elf32_Addr offset, + unsigned char type ); + + virtual CGBIO_ERROR + add_entry( ostring_table* pStrWriter, + const char* str, + osymbol_table* pSymWriter, + Elf32_Addr value, + Elf32_Word size, + unsigned char symInfo, + unsigned char other, + Elf32_Half shndx, + Elf32_Addr offset, + unsigned char type, + Elf32_Sword addend ); + + private: + ptrdiff_t ref_count_; + elf_writer* cgbo_; + osection* section_; +}; // CGBORelocationTableImpl + +class oparam_table_impl : public oparam_table +{ + public: + oparam_table_impl( elf_writer* cgbo, osection* sec ); + + virtual + ~oparam_table_impl(); + + virtual ptrdiff_t + reference(); + virtual ptrdiff_t + release(); + + virtual CGBIO_ERROR + add_entry( Elf32_cgParameter& cgparam ); + + private: + ptrdiff_t ref_count_; + elf_writer* cgbo_; + osection* section_; +}; + + +} } // bio namespace cgc namespace + +#endif // CGC_CGBIO_CGBOIMPL_HPP diff --git a/console/rgl/src/cg/cgbtypes.h b/console/rgl/src/cg/cgbtypes.h new file mode 100644 index 0000000000..aa483a3c0a --- /dev/null +++ b/console/rgl/src/cg/cgbtypes.h @@ -0,0 +1,21 @@ +#ifndef CGBTYPES_HEADER +#define CGBTYPES_HEADER + +// parameter structure +typedef struct _Elf32_cgParameter { + uint32_t cgp_name; // index of name in strtab + uint32_t cgp_semantic; // index of semantic string in strtab + uint16_t cgp_default; // index of default data in const //Reduced to half + uint16_t cgp_reloc; // index of reloc indices in rel + uint16_t cgp_resource; // index of hardware resource assigned + uint16_t cgp_resource_index; // index of hardware resource assigned + unsigned char cgp_type; + uint16_t cgp_info; + unsigned char unused; +} Elf32_cgParameter; //20 bytes + +#define CGF_OUTPUTFROMH0 0x01 +#define CGF_DEPTHREPLACE 0x02 +#define CGF_PIXELKILL 0x04 + +#endif diff --git a/console/rgl/src/cg/cgbutils.hpp b/console/rgl/src/cg/cgbutils.hpp new file mode 100644 index 0000000000..03c507ccb6 --- /dev/null +++ b/console/rgl/src/cg/cgbutils.hpp @@ -0,0 +1,103 @@ +#if !defined(CGC_CGBIO_CGBUTILS_HPP) +#define CGC_CGBIO_CGBUTILS_HPP 1 + +#include "cgbdefs.hpp" + +namespace cgc { +namespace bio { + +typedef enum { + CGBIODATANONE = ELFDATANONE, + CGBIODATALSB = ELFDATA2LSB, + CGBIODATAMSB = ELFDATA2MSB +} HOST_ENDIANNESS; // endianness + +inline HOST_ENDIANNESS +host_endianness() +{ + const int ii = 1; + const char* cp = (const char*) ⅈ + return ( 1 == cp[0] ) ? CGBIODATALSB : CGBIODATAMSB; +} + +template< typename T > inline T +convert_endianness( const T value, unsigned char endianness ) +{ + if ( host_endianness() == endianness ) + { + return value; + } + if ( sizeof( T ) == 1 ) + { + return value; + } + if ( sizeof( T ) == 2 ) + { + return ( ((value & 0x00FF) << 8) + | ((value & 0xFF00) >> 8) ); + } + if ( sizeof( T ) == 4 ) + { + return ( ((value & 0x000000FF) << 24) + | ((value & 0x0000FF00) << 8) + | ((value & 0x00FF0000) >> 8) + | ((value & 0xFF000000) >> 24) ); + } + if ( sizeof( T ) == 8 ) + { + T result = value; + for ( int ii = 0; ii < 4; ++ii ) + { + char ch = *( (( char* ) &result) + ii ); + *( (( char* ) &result) + ii ) = *( (( char* ) &result) + (7 - ii) ); + *( (( char* ) &result) + (7 - ii) ) = ch; + } + return result; + } + // exception + return value; +} + +template< typename T > inline T +ELF32_ST_BIND( const T idx ) +{ + return ( idx >> 4 ); +} + +template< typename T > inline T +ELF32_ST_TYPE( const T idx ) +{ + return ( idx & 0xf ); +} + +template< typename T > inline T +ELF32_ST_INFO( const T b, const T t ) +{ + return ( ( b << 4 ) + ( t & 0xf ) ); +} + +template< typename T > inline T +ELF32_ST_VISIBILITY( const T o ) +{ + return ( o & 0x3 ); +} + +// these are not used in our relocations, will be replaced by the ones +// we design, will be defined as templates. +#ifndef ELF32_R_SYM +#define ELF32_R_SYM(i) ((i)>>8) +#endif + +#ifndef ELF32_R_TYPE +#define ELF32_R_TYPE(i) ((unsigned char)(i)) +#endif + +#ifndef ELF32_R_INFO +#define ELF32_R_INFO(s,t) (((s)<<8 )+(unsigned char)(t)) +#endif + +} // bio namespace +} // cgc namespace + + +#endif // CGC_CGBIO_CGBUTILS_HPP diff --git a/console/rgl/src/cg/cgnv2elfversion.h b/console/rgl/src/cg/cgnv2elfversion.h new file mode 100644 index 0000000000..47d162b4a2 --- /dev/null +++ b/console/rgl/src/cg/cgnv2elfversion.h @@ -0,0 +1,5 @@ +#ifndef CGNV2ELF_VERSION +#define CGNV2ELF_VERSION 6365 +#define CGNV2ELF_PRODUCT_STRING "SCE cgnv2elf" +#define CGNV2ELF_VERSION_NOTE_TYPE 0 +#endif diff --git a/console/rgl/ps3/cgnv2rt.h b/console/rgl/src/cg/cgnv2rt.h similarity index 55% rename from console/rgl/ps3/cgnv2rt.h rename to console/rgl/src/cg/cgnv2rt.h index cc222c1f2d..683d7ef3c4 100644 --- a/console/rgl/ps3/cgnv2rt.h +++ b/console/rgl/src/cg/cgnv2rt.h @@ -3,19 +3,14 @@ #include #include -#include - -#ifndef CGNV2ELF_VERSION -#define CGNV2ELF_VERSION 6365 -#define CGNV2ELF_PRODUCT_STRING "cgnv2elf" -#define CGNV2ELF_VERSION_NOTE_TYPE 0 -#endif #define CNV2END(val) convert_endianness((val), elfEndianness) #define ENDSWAP(val) convert_endianness((val), (host_endianness() == 1) ? 2 : 1) -int convertNvToElfFromFile(const char *sourceFile, int endianness, int constTableOffset, void **binaryShader, int *size, std::vector &stringTable, std::vector &defaultValues); -int convertNvToElfFromMemory(const void *sourceData, size_t size, int endianness, int constTableOffset, void **binaryShader, int *binarySize, std::vector &stringTable, std::vector &defaultValues); +int convertNvToElfFromFile(const char *sourceFile, int endianness, int constTableOffset, void **binaryShader, int *size, + std::vector &stringTable, std::vector &defaultValues); +int convertNvToElfFromMemory(const void *sourceData, size_t size, int endianness, int constTableOffset, void **binaryShader, int *binarySize, + std::vector &stringTable, std::vector &defaultValues); int convertNvToElfFreeBinaryShader(void *binaryShader); diff --git a/console/rgl/src/cg/nvbi.hpp b/console/rgl/src/cg/nvbi.hpp new file mode 100644 index 0000000000..8fe4fd769d --- /dev/null +++ b/console/rgl/src/cg/nvbi.hpp @@ -0,0 +1,92 @@ +#if !defined(CGC_CGBIO_NVBI_HPP) +#define CGC_CGBIO_NVBI_HPP 1 + +#include "cgbdefs.hpp" + +#include +#include +#include +#include + +#include +#include + + +namespace cgc { +namespace bio { + +class nvb_reader { + public: + virtual ~nvb_reader() {} + + virtual ptrdiff_t + reference() const = 0; + + virtual ptrdiff_t + release() const = 0; + +#ifndef __CELLOS_LV2__ + virtual CGBIO_ERROR + load( std::istream* stream, int start, bool owner = false ) = 0; + + virtual CGBIO_ERROR + load( const char *filename ) = 0; +#endif + + virtual CGBIO_ERROR + loadFromString( const char* source, size_t length ) = 0; + + virtual bool + is_loaded() const = 0; + + virtual unsigned char + endianness() const = 0; + + virtual CGprofile + profile() const = 0; + + virtual unsigned int + revision() const = 0; + + virtual unsigned int + size() const = 0; + + virtual unsigned int + number_of_params() const = 0; + + virtual unsigned int + ucode_size() const = 0; + + virtual const char* + ucode() const = 0; + + virtual const CgBinaryFragmentProgram* + fragment_program() const = 0; + + virtual const CgBinaryVertexProgram* + vertex_program() const = 0; + + virtual CGBIO_ERROR + get_param( unsigned int index, + CGtype& type, + CGresource& resource, + CGenum& variability, + int& resource_index, + const char** name, + std::vector& default_value, + std::vector& embedded_constants, + const char** semantic, + CGenum& direction, + int& paramno, + bool& is_referenced, + bool& is_shared ) const = 0; + + virtual CGBIO_ERROR get_param_name( unsigned int index, const char** name, bool& is_referenced) const = 0; + +}; // nvb_reader + + +} // bio namespace +} // cgc namespace + +#endif // CGC_CGBIO_NVBI_HPP diff --git a/console/rgl/src/cg/nvbiimpl.hpp b/console/rgl/src/cg/nvbiimpl.hpp new file mode 100644 index 0000000000..e04d248734 --- /dev/null +++ b/console/rgl/src/cg/nvbiimpl.hpp @@ -0,0 +1,103 @@ +#if !defined(CGC_CGBIO_NVBIIMPL_HPP) +#define CGC_CGBIO_NVBIIMPL_HPP 1 + +#include +#include +#include +#include + +#include +#include + +#include "cgbio.hpp" + +namespace cgc { +namespace bio { + +class nvb_reader_impl : public nvb_reader +{ + public: + nvb_reader_impl(); + + virtual + ~nvb_reader_impl(); + + virtual ptrdiff_t + reference() const; + + virtual ptrdiff_t + release() const; + +#ifndef __CELLOS_LV2__ + virtual CGBIO_ERROR + load( std::istream* stream, int start ,bool owner = false); + + virtual CGBIO_ERROR + load( const char* filename ); +#endif + + virtual CGBIO_ERROR + loadFromString( const char* source, size_t length); + + virtual bool + is_loaded() const; + + virtual unsigned char + endianness() const; + + virtual CGprofile + profile() const; + + virtual unsigned int + revision() const; + + virtual unsigned int + size() const; + + virtual unsigned int + number_of_params() const; + + virtual unsigned int + ucode_size() const; + + virtual const char* + ucode() const; + + virtual const CgBinaryFragmentProgram* + fragment_program() const; + + virtual const CgBinaryVertexProgram* + vertex_program() const; + + virtual CGBIO_ERROR + get_param( unsigned int index, + CGtype& type, + CGresource& resource, + CGenum& variability, + int& resource_index, + const char ** name, + std::vector& default_value, + std::vector& embedded_constants, + const char ** semantic, + CGenum& direction, + int& paramno, + bool& is_referenced, + bool& is_shared ) const; + + virtual CGBIO_ERROR get_param_name( unsigned int index, const char ** name , bool& is_referenced) const; + + private: + mutable ptrdiff_t ref_count_; + int offset_; + bool loaded_; + bool owner_; + bool strStream_; + CgBinaryProgram header_; + unsigned char endianness_; + char* image_; +}; // nvb_reader_impl + +} // bio namespace +} // cgc namespace + +#endif // CGC_CGBIO_NVBIIMPL_HPP diff --git a/console/rgl/src/cg/nvbo.hpp b/console/rgl/src/cg/nvbo.hpp new file mode 100644 index 0000000000..48656c008f --- /dev/null +++ b/console/rgl/src/cg/nvbo.hpp @@ -0,0 +1,83 @@ +#if !defined(CGC_CGBIO_NVBO_HPP) +#define CGC_CGBIO_NVBO_HPP 1 + +#include +#include +#include + +#include "cgbdefs.hpp" + +using std::ofstream; +using std::streampos; + +namespace cgc { +namespace bio { + +class nvb_writer { + public: + enum PRODUCER + { + CGBO_HASH, + CGBO_STR, + CGBO_SYM, + CGBO_REL, + CGBO_PARAM, + CGBO_VP, + CGBO_FP + }; + + virtual ~nvb_writer () {} + + virtual ptrdiff_t + reference() = 0; + + virtual ptrdiff_t + release() = 0; + + virtual CGBIO_ERROR + save( ofstream& ofs ) = 0; + + virtual CGBIO_ERROR + save( const char* filename ) = 0; + + virtual CGBIO_ERROR + set_attr( unsigned char file_class, + unsigned char endianness, + unsigned char ELFversion, + unsigned char abi, + unsigned char ABIversion, + Elf32_Half type, + Elf32_Half machine, + Elf32_Word version, + Elf32_Word flags ) = 0; + + virtual Elf32_Addr + get_entry() const = 0; + + virtual CGBIO_ERROR + set_entry( Elf32_Addr entry ) = 0; + + virtual unsigned char + endianness() const = 0; +}; // elf_writer interface class + +class oparam_array +{ + public: + virtual ~oparam_array() {} + + virtual ptrdiff_t + reference() = 0; + + virtual ptrdiff_t + release() = 0; + + virtual CGBIO_ERROR + add_entry() = 0; +}; // oparam_table + + +} // bio namespace +} // cgc namespace + +#endif // CGC_CGBIO_NVBO_HPP diff --git a/console/rgl/src/cg/nvboimpl.hpp b/console/rgl/src/cg/nvboimpl.hpp new file mode 100644 index 0000000000..cccf2888d6 --- /dev/null +++ b/console/rgl/src/cg/nvboimpl.hpp @@ -0,0 +1,85 @@ +#if !defined(CGC_CGBIO_NVBOIMPL_HPP) +#define CGC_CGBIO_NVBOIMPL_HPP 1 + +#include +#include +#include +#include + +#include "cgbio.hpp" + +namespace cgc { +namespace bio { + +class nvb_writer_impl : public nvb_writer +{ + public: + + nvb_writer_impl(); + virtual + ~nvb_writer_impl(); + + virtual ptrdiff_t + reference(); + + virtual ptrdiff_t + release(); + + virtual CGBIO_ERROR + save( ofstream& ofs ); + + virtual CGBIO_ERROR + save( const char* filename ); + + virtual CGBIO_ERROR + set_attr( unsigned char file_class, + unsigned char endianness, + unsigned char ELFversion, + unsigned char abi, + unsigned char ABIversion, + Elf32_Half type, + Elf32_Half machine, + Elf32_Word version, + Elf32_Word flags ); + + virtual Elf32_Addr + get_entry() const; + + virtual CGBIO_ERROR + set_entry( Elf32_Addr entry ); + + virtual unsigned char + endianness() const; + + private: + ptrdiff_t ref_count_; + Elf32_Ehdr header_; +}; // elf_writer_impl + + + +class oparam_array_impl : public oparam_array +{ + public: + oparam_array_impl( nvb_writer* cgbo ); + + virtual + ~oparam_array_impl(); + + virtual ptrdiff_t + reference(); + virtual ptrdiff_t + release(); + + virtual CGBIO_ERROR + add_entry(); + + private: + ptrdiff_t ref_count_; + nvb_writer* cgbo_; +}; + + +} } // bio namespace cgc namespace + +#endif // CGC_CGBIO_NVBOIMPL_HPP diff --git a/console/rgl/src/libelf/elf.h b/console/rgl/src/libelf/elf.h new file mode 100644 index 0000000000..4a8af2e8ba --- /dev/null +++ b/console/rgl/src/libelf/elf.h @@ -0,0 +1,254 @@ +#ifndef ELF_H +#define ELF_H + +/* + * Data Representation + */ + +/* + * ELF header + */ + +/* e_ident[] Identification Indexes */ +#define EI_MAG0 0 /* File identification */ +#define EI_MAG1 1 /* File identification */ +#define EI_MAG2 2 /* File identification */ +#define EI_MAG3 3 /* File identification */ +#define EI_CLASS 4 /* File class */ +#define EI_DATA 5 /* Data encoding */ +#define EI_VERSION 6 /* File version */ +#define EI_OSABI 7 /* Operating system/ABI identification */ +#define EI_ABIVERSION 8 /* ABI version */ +#define EI_PAD 9 /* Start of padding bytes */ +#define EI_NIDENT 16 /* Size of e_ident[] */ + +/* e_ident[EI_MAG0] to e_ident[EI_MAG3] */ +#define ELFMAG0 0x7f /* e_ident[EI_MAG0] */ +#define ELFMAG1 'E' /* e_ident[EI_MAG1] */ +#define ELFMAG2 'L' /* e_ident[EI_MAG2] */ +#define ELFMAG3 'F' /* e_ident[EI_MAG3] */ + +/* e_ident[EI_CLASS] */ +#define ELFCLASSNONE 0 /* Invalid class */ +#define ELFCLASS32 1 /* 32-bit objects */ +#define ELFCLASS64 2 /* 64-bit objects */ + +/* e_ident[EI_DATA] */ +#define ELFDATANONE 0 /* Invalid data encoding */ +#define ELFDATA2LSB 1 /* little endian */ +#define ELFDATA2MSB 2 /* big endian */ + +/* e_ident[EI_VERSION] */ +#define EV_NONE 0 /* Invalid version */ +#define EV_CURRENT 1 /* Current version */ + +/* e_type */ +#define ET_NONE 0 /* No file type */ +#define ET_REL 1 /* Relocatable file */ +#define ET_EXEC 2 /* Executable file */ +#define ET_DYN 3 /* Shared object file */ +#define ET_CORE 4 /* Core file */ + +/* e_machine */ +#define EM_PPC 20 /* PowerPC 32-bit */ +#define EM_PPC64 21 /* PowerPC 64-bit */ + +typedef struct { + unsigned char e_ident[EI_NIDENT]; + uint16_t e_type; + uint16_t e_machine; + uint32_t e_version; + uint32_t e_entry; + int32_t e_phoff; + int32_t e_shoff; + uint32_t e_flags; + uint16_t e_ehsize; + uint16_t e_phentsize; + uint16_t e_phnum; + uint16_t e_shentsize; + uint16_t e_shnum; + uint16_t e_shstrndx; +} Elf32_Ehdr; + +typedef struct { + unsigned char e_ident[EI_NIDENT]; + uint16_t e_type; + uint16_t e_machine; + uint32_t e_version; + uint64_t e_entry; + uint64_t e_phoff; + uint64_t e_shoff; + uint32_t e_flags; + uint16_t e_ehsize; + uint16_t e_phentsize; + uint16_t e_phnum; + uint16_t e_shentsize; + uint16_t e_shnum; + uint16_t e_shstrndx; +} Elf64_Ehdr; + +/* + * Program Header + */ + +/* Segment Types, p_type */ +#define PT_NULL 0 +#define PT_LOAD 1 +#define PT_DYNAMIC 2 +#define PT_INTERP 3 +#define PT_NOTE 4 +#define PT_SHLIB 5 +#define PT_PHDR 6 +#define PT_LOOS 0x60000000 +#define PT_HIOS 0x6fffffff +#define PT_LOPROC 0x70000000 +#define PT_HIPROC 0x7fffffff + +typedef struct { + uint32_t p_type; + int32_t p_offset; + uint32_t p_vaddr; + uint32_t p_paddr; + uint32_t p_filesz; + uint32_t p_memsz; + uint32_t p_flags; + uint32_t p_align; +} Elf32_Phdr; + +typedef struct { + uint32_t p_type; + uint32_t p_flags; + uint64_t p_offset; + uint64_t p_vaddr; + uint64_t p_paddr; + uint64_t p_filesz; + uint64_t p_memsz; + uint64_t p_align; +} Elf64_Phdr; + +/* + * Section Header + */ + +/* sh_type */ +#define SHT_NULL 0 /* Section header table entry unused */ +#define SHT_PROGBITS 1 /* Program data */ +#define SHT_SYMTAB 2 /* Symbol table */ +#define SHT_STRTAB 3 /* String table */ +#define SHT_RELA 4 /* Relocation entries with addends */ +#define SHT_HASH 5 /* Symbol hash table */ +#define SHT_DYNAMIC 6 /* Dynamic linking information */ +#define SHT_NOTE 7 /* Notes */ +#define SHT_NOBITS 8 /* Program space with no data (bss) */ +#define SHT_REL 9 /* Relocation entries, no addends */ +#define SHT_SHLIB 10 /* Reserved */ +#define SHT_DYNSYM 11 /* Dynamic linker symbol table */ + +#define SHF_WRITE (1 << 0) /* Writable */ +#define SHF_ALLOC (1 << 1) /* Occupies memory during execution */ +#define SHF_EXECINSTR (1 << 2) /* Executable */ +#define SHF_MERGE (1 << 4) /* Might be merged */ +#define SHF_STRINGS (1 << 5) /* Contains nul-terminated strings */ +#define SHF_INFO_LINK (1 << 6) /* `sh_info' contains SHT index */ +#define SHF_LINK_ORDER (1 << 7) /* Preserve order after combining */ +#define SHF_OS_NONCONFORMING (1 << 8) /* Non-standard OS specific handling + required */ +#define SHF_MASKOS 0x0ff00000 /* OS-specific. */ +#define SHF_MASKPROC 0xf0000000 /* Processor-specific */ + + +typedef struct { + uint32_t sh_name; + uint32_t sh_type; + uint32_t sh_flags; + uint32_t sh_addr; + int32_t sh_offset; + uint32_t sh_size; + uint32_t sh_link; + uint32_t sh_info; + uint32_t sh_addralign; + uint32_t sh_entsize; +} Elf32_Shdr; + +/* Special section indices. */ + +#define SHN_UNDEF 0 /* Undefined section */ +#define SHN_LORESERVE 0xff00 /* Start of reserved indices */ +#define SHN_LOPROC 0xff00 /* Start of processor-specific */ +#define SHN_HIPROC 0xff1f /* End of processor-specific */ +#define SHN_LOOS 0xff20 /* Start of OS-specific */ +#define SHN_HIOS 0xff3f /* End of OS-specific */ +#define SHN_ABS 0xfff1 /* Associated symbol is absolute */ + +#ifndef SHN_COMMON +#define SHN_COMMON 0xfff2 /* Associated symbol is common */ +#endif + +#ifndef SHN_XINDEX +#define SHN_XINDEX 0xffff /* Index is in extra table. */ +#endif + +#ifndef SHN_HIRESERVE +#define SHN_HIRESERVE 0xffff /* End of reserved indices */ +#endif + +/* + * Symbol Header + */ + +typedef struct { + uint32_t st_name; + uint32_t st_value; + uint32_t st_size; + unsigned char st_info; + unsigned char st_other; + uint16_t st_shndx; +} Elf32_Sym; + + +/* Relocation table entry without addend (in section of type SHT_REL). */ + +typedef struct +{ + uint32_t r_offset; /* Address */ + uint32_t r_info; /* Relocation type and symbol index */ +} Elf32_Rel; + +/* I have seen two different definitions of the Elf64_Rel and + Elf64_Rela structures, so we'll leave them out until Novell (or + whoever) gets their act together. */ +/* The following, at least, is used on Sparc v9, MIPS, and Alpha. */ + +typedef struct +{ + uint64_t r_offset; /* Address */ + uint64_t r_info; /* Relocation type and symbol index */ +} Elf64_Rel; + +/* Relocation table entry with addend (in section of type SHT_RELA). */ + +typedef struct +{ + uint32_t r_offset; /* Address */ + uint32_t r_info; /* Relocation type and symbol index */ + int32_t r_addend; /* Addend */ +} Elf32_Rela; + +typedef struct +{ + uint64_t r_offset; /* Address */ + uint64_t r_info; /* Relocation type and symbol index */ + int64_t r_addend; /* Addend */ +} Elf64_Rela; + +/* How to extract and insert information held in the r_info field. */ + +#define ELF32_R_SYM(val) ((val) >> 8) +#define ELF32_R_TYPE(val) ((val) & 0xff) +#define ELF32_R_INFO(sym, type) (((sym) << 8) + ((type) & 0xff)) + +#define ELF64_R_SYM(i) ((i) >> 32) +#define ELF64_R_TYPE(i) ((i) & 0xffffffff) +#define ELF64_R_INFO(sym,type)((((uint64_t) (sym)) << 32) + (type)) + +#endif /* ELF_H */ diff --git a/console/rgl/src/libelf/readelf.cpp b/console/rgl/src/libelf/readelf.cpp new file mode 100644 index 0000000000..6a45d902a1 --- /dev/null +++ b/console/rgl/src/libelf/readelf.cpp @@ -0,0 +1,125 @@ +/* + * Spu simulator library - ELF reader. + * AUTHORS: Antoine Labour, Robin Green + * DATE: 2003-Oct-16 + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include "readelf.h" + +const Elf32_Sym *getSymbolByIndex(const ELF_t *elf,int idx) +{ + if(!elf) + return NULL; + + if(elf->symbolsSection<=0) + return NULL; + + ELF_section_t *section=elf->sections+elf->symbolsSection; + + if(!section->data) + return NULL; + + if ((idx<0) || (idx>=(int)elf->symbolCount)) + return NULL; + + return(Elf32_Sym *)(section->data+section->header.sh_entsize*idx); +} + +int lookupSymbol(const ELF_t *elf,const char *name) +{ + unsigned int i; + + if(!elf||!name) + return -1; + + ELF_symbol_t *symbol=elf->symbols; + + if(!symbol) + return -1; + + for (i = 0; i < elf->symbolCount; ++i, ++symbol) + if (strcmp(name,symbol->name)==0) + return i; + return -1; +} + +static const char *_getStringTable(const Elf32_Ehdr *ehdr) +{ + const char *sectionHeaderStart = (const char*)ehdr + ehdr->e_shoff; + const Elf32_Shdr *shstrtabHeader = (const Elf32_Shdr*)sectionHeaderStart + ehdr->e_shstrndx; + return (const char*)ehdr + shstrtabHeader->sh_offset; +} + +const char *findSectionInPlace(const char* memory, const char *name, size_t *sectionSize) +{ + const Elf32_Ehdr *ehdr = (const Elf32_Ehdr*)memory; + + //first get the string section header + const char *shstrtab = _getStringTable(ehdr); + + //find the section + size_t sectionCount = ehdr->e_shnum; + const char *sectionHeaderStart = (const char*)ehdr + ehdr->e_shoff; + + for (size_t i=0;ish_name; + if (!strcmp(name,sectionName)) + { + *sectionSize = sectionHeader->sh_size; + return (const char*)ehdr + sectionHeader->sh_offset; + } + } + return NULL; +} + +const char *findSymbolSectionInPlace(const char *memory, size_t *symbolSize, size_t *symbolCount, const char **symbolstrtab) +{ + const Elf32_Ehdr *ehdr = (const Elf32_Ehdr*)memory; + + //find the section + size_t sectionCount = ehdr->e_shnum; + const char *sectionHeaderStart = (const char*)ehdr + ehdr->e_shoff; + + for (size_t i = 0; i < sectionCount; i++) + { + const Elf32_Shdr *sectionHeader = (const Elf32_Shdr *)sectionHeaderStart + i; + if (sectionHeader->sh_type == SHT_SYMTAB) + { + *symbolSize = sectionHeader->sh_entsize; + *symbolCount = sectionHeader->sh_size / sectionHeader->sh_entsize; + + const Elf32_Shdr *symbolStrHeader = (const Elf32_Shdr *)sectionHeaderStart + sectionHeader->sh_link; + *symbolstrtab = (const char*)ehdr + symbolStrHeader->sh_offset; + return (const char*)ehdr + sectionHeader->sh_offset; + } + } + + return NULL; +} + + +int lookupSymbolValueInPlace(const char* symbolSection, size_t symbolSize, size_t symbolCount, const char *symbolstrtab, const char *name) +{ + for (size_t i=0;ist_name, name)) + return elf_sym->st_value; + symbolSection+= symbolSize; + } + return -1; +} + +const char *getSymbolByIndexInPlace(const char* symbolSection, size_t symbolSize, size_t symbolCount, const char *symbolstrtab, int index) +{ + Elf32_Sym* elf_sym = (Elf32_Sym*)symbolSection + index; + return symbolstrtab + elf_sym->st_name; +} diff --git a/console/rgl/src/libelf/readelf.h b/console/rgl/src/libelf/readelf.h new file mode 100644 index 0000000000..f09bbda8ca --- /dev/null +++ b/console/rgl/src/libelf/readelf.h @@ -0,0 +1,91 @@ +#ifndef READELF_H +#define READELF_H + +#include "elf.h" + +#ifdef __cplusplus +extern "C" { +#endif + + typedef struct _ELF_section_t + { + Elf32_Shdr header; + const char* name; + char* data; + } ELF_section_t; + + typedef struct _ELF_segment_t + { + Elf32_Phdr header; + unsigned char* pointer; + unsigned char* data; + } ELF_segment_t; + + typedef struct + { + const char* name; + unsigned int vma; + unsigned int size; + int section; + unsigned char resolved; + unsigned char foreign; + } ELF_symbol_t; + + typedef struct _ELF_t + { + unsigned int endian; + unsigned int relocatable; + unsigned int sectionCount; + unsigned int segmentCount; + unsigned int symbolCount; + unsigned int entrypoint; + ELF_section_t* sections; + ELF_segment_t* segments; + ELF_symbol_t* symbols; + unsigned int symbolsSection; + unsigned int symbolNamesSection; + unsigned int paramSection; + } ELF_t; + + typedef struct + { + unsigned int relative; + unsigned int shift; + unsigned int size; + unsigned int position; + unsigned int mask; + } ELF_rel_type_t; + + ELF_t* readElfFromFile(const char* filename); + ELF_t* readElfFromMemory(const char* memory,unsigned int size); + ELF_section_t* findSection(const ELF_t* elf,const char* name); + int lookupSymbol(const ELF_t* elf,const char* name); + int lookupResolvedSymbol(const ELF_t* elf,const char* name); + const Elf32_Sym* getSymbolByIndex(const ELF_t* elf,int idx); + int resolveElf(ELF_t* main_elf,ELF_t* elf); + int relocateSymbols(ELF_t* elf,unsigned int origin); + int loadSectionsToMemory(ELF_t* elf,char* memory,int memorySize,unsigned int origin); + void doRelocations(ELF_t* elf,char* memory,int memorySize,int origin,const ELF_rel_type_t* rel_types,unsigned int rel_types_count); + int loadElfToMemory(unsigned char* memory, unsigned int size, unsigned int load_address, ELF_t* elf); + void freeElf(ELF_t* elf); + + //in place API + const char *findSectionInPlace(const char* memory, const char *name,size_t *sectionSize); + const char *findSymbolSectionInPlace(const char *memory, size_t *symbolSize, size_t *symbolCount, const char **symbolstrtab); + int lookupSymbolValueInPlace(const char* symbolSection, size_t symbolSize, size_t symbolCount, const char *symbolstrtab, const char *name); + const char *getSymbolByIndexInPlace(const char* symbolSection, size_t symbolSize, size_t symbolCount, const char *symbolstrtab, int index); + + void spuDoRelocations(ELF_t* elf,char* memory,int memorySize,int origin); + + uint16_t endian_half(int endian, uint16_t v); + uint32_t endian_word(int endian, uint32_t v); + +#define endian_addr(e, v) endian_word(e, v) +#define endian_off(e, v) endian_word(e, v) +#define endian_size(e, v) endian_half(e, v) + +#ifdef __cplusplus +} +#endif + +#endif // READELF_H diff --git a/console/rgl/src/ps3/include/GmmAlloc.h b/console/rgl/src/ps3/include/GmmAlloc.h new file mode 100644 index 0000000000..97eaf37d70 --- /dev/null +++ b/console/rgl/src/ps3/include/GmmAlloc.h @@ -0,0 +1,189 @@ +#ifndef _GMM_ALLOC_H_ +#define _GMM_ALLOC_H_ + +void gmmPrintState(); // print out all blocks and their current states + +#define GMM_ASSERT(cond) ((void)0) + +#define GMM_ERROR 0xFFFFFFFF +#define GMM_TILE_ALIGNMENT 0x10000 // 16K +#define GMM_ALIGNMENT 128 // non-tile is 128 byte +#define GMM_RSX_WAIT_INDEX 254 // label index +#define GMM_PPU_WAIT_INDEX 255 // label index +#define GMM_BLOCK_COUNT 512 // initial memory block pool +#define GMM_TILE_BLOCK_COUNT 16 // initial tile memory block pool + +#define GMM_NUM_FREE_BINS 22 +#define GMM_FREE_BIN_0 0x80 // 0x00 - 0x80 +#define GMM_FREE_BIN_1 0x100 // 0x80 - 0x100 +#define GMM_FREE_BIN_2 0x180 // ... +#define GMM_FREE_BIN_3 0x200 +#define GMM_FREE_BIN_4 0x280 +#define GMM_FREE_BIN_5 0x300 +#define GMM_FREE_BIN_6 0x380 +#define GMM_FREE_BIN_7 0x400 +#define GMM_FREE_BIN_8 0x800 +#define GMM_FREE_BIN_9 0x1000 +#define GMM_FREE_BIN_10 0x2000 +#define GMM_FREE_BIN_11 0x4000 +#define GMM_FREE_BIN_12 0x8000 +#define GMM_FREE_BIN_13 0x10000 +#define GMM_FREE_BIN_14 0x20000 +#define GMM_FREE_BIN_15 0x40000 +#define GMM_FREE_BIN_16 0x80000 +#define GMM_FREE_BIN_17 0x100000 +#define GMM_FREE_BIN_18 0x200000 +#define GMM_FREE_BIN_19 0x400000 +#define GMM_FREE_BIN_20 0x800000 +#define GMM_FREE_BIN_21 0x1000000 + +// data structure for the fixed allocater +typedef struct GmmFixedAllocData{ + char **ppBlockList[2]; // pre-allocated list of block descriptors + uint16_t **ppFreeBlockList[2]; + uint16_t *pBlocksUsed[2]; + uint16_t BlockListCount[2]; +}GmmFixedAllocData; + +// common shared block descriptor for tile and non-tile block +// "base class" for GmmBlock and GmmTileBlock +typedef struct GmmBaseBlock{ + + uint8_t isTile; + //uint8_t isMain; + uint32_t address; + uint32_t size; +}GmmBaseBlock; + +typedef struct GmmBlock{ + GmmBaseBlock base; // inheritence + struct GmmBlock *pPrev; + struct GmmBlock *pNext; + + uint8_t isPinned; + + // these would only be valid if the block is in + // pending free list or free list + struct GmmBlock *pPrevFree; + struct GmmBlock *pNextFree; + + uint32_t fence; +}GmmBlock; + +typedef struct GmmTileBlock{ + GmmBaseBlock base; // inheritence + struct GmmTileBlock *pPrev; + struct GmmTileBlock *pNext; + + uint32_t tileTag; + void *pData; +}GmmTileBlock; + +typedef struct GmmAllocator{ + uint32_t memoryBase; + + uint32_t startAddress; + uint32_t size; + uint32_t freeAddress; + + GmmBlock *pHead; + GmmBlock *pTail; + GmmBlock *pSweepHead; + uint32_t freedSinceSweep; + + uint32_t tileStartAddress; + uint32_t tileSize; + + GmmTileBlock *pTileHead; + GmmTileBlock *pTileTail; + + GmmBlock *pPendingFreeHead; + GmmBlock *pPendingFreeTail; + + // Acceleration data structure for free blocks + GmmBlock *pFreeHead[GMM_NUM_FREE_BINS]; + GmmBlock *pFreeTail[GMM_NUM_FREE_BINS]; + + uint32_t totalSize; // == size + tileSize +}GmmAllocator; + +uint32_t gmmInit( + const void *localMemoryBase, + const void *localStartAddress, + const uint32_t localSize, + const void *mainMemoryBase, + const void *mainStartAddress, + const uint32_t mainSize + ); + +uint32_t gmmDestroy(); + +uint32_t gmmIdToOffset( + const uint32_t id + ); + +char *gmmIdToAddress( + const uint32_t id + ); + +uint32_t gmmFPOffsetToId( + const uint32_t offset, + uint32_t *pOutOffset, + bool bLocalMemory + ); + +void gmmPinId( + const uint32_t id + ); + +void gmmUnpinId( + const uint32_t id + ); + +uint32_t gmmFree( + const uint32_t freeId + ); + +void gmmUpdateFreeList( + const uint8_t location + ); + +uint32_t gmmAlloc( + CellGcmContextData *thisContext, + const uint8_t location, + const uint8_t isTile, + const uint32_t size + ); + +uint32_t gmmAllocExtendedTileBlock( + const uint8_t location, + const uint32_t size, + const uint32_t tag + ); + +uint32_t gmmGetBlockSize( + const uint32_t id + ); + +void gmmSetTileAttrib( + const uint32_t id, + const uint32_t tag, + void *pData + ); + +void *gmmGetTileData( + const uint32_t id + ); + +void gmmPinAllocations(); + +void gmmUnpinAllocations(); + +static inline uint8_t gmmIdIsMain( + const uint32_t id + ) +{ + return false; +} + +#endif diff --git a/console/rgl/src/ps3/include/rgl-constants.h b/console/rgl/src/ps3/include/rgl-constants.h new file mode 100644 index 0000000000..56c3aaf7ad --- /dev/null +++ b/console/rgl/src/ps3/include/rgl-constants.h @@ -0,0 +1,464 @@ +// This is used to make sure the pass the gpu the +// right endianness. RS +#define RGLGCM_BIG_ENDIAN + +#if RGL_ENDIAN == RGL_BIG_ENDIAN +#define ENDIAN_32(X, F) ((F) ? endianSwapWord(X) : (X)) +#else +#define ENDIAN_32(X, F) (X) +#endif + +#define FRAGMENT_PROFILE_INDEX 1 + +#define RGLP_MAX_TEXTURE_SIZE 4096 + +// GCM RESERVE and no RGLGCM post fifo SKID Check +#define GCM_RESERVE_NO_SKID + +#ifdef GCM_RESERVE_NO_SKID + + +#define GCM_FUNC_RESERVE( count )\ + CELL_GCM_RESERVE(count); + +#define GCM_FUNC_SAFE( GCM_FUNCTION, ...) \ +{ \ + GCM_FUNCTION( (CellGcmContextData*)&rglGcmState_i.fifo, __VA_ARGS__ ); \ +} + +#define GCM_FUNC_SAFE_NO_ARGS( GCM_FUNCTION, ...) \ +{ \ + GCM_FUNCTION( (CellGcmContextData*)&rglGcmState_i.fifo ); \ +} + +#define GCM_FUNC( GCM_FUNCTION, ...) \ +{ \ + GCM_FUNCTION ## Inline( (CellGcmContextData*)&rglGcmState_i.fifo, __VA_ARGS__ ); \ +} + +#define GCM_FUNC_NO_ARGS( GCM_FUNCTION ) \ +{ \ + GCM_FUNCTION ## Inline( (CellGcmContextData*)&rglGcmState_i.fifo ); \ +} +#endif + +/* [RSTENSON] To be able to build up buffered push buffers with GCM we need to use the +// cellGcmSetCurrentBuffer and reset the buffer with cellGcmDefualtCommandBuffer afterwards. +// Buffer size checks are not handled by these macros because they operate on pointers +// to data and not cellGcmContextDmas, thus the use of UnsafeInline versions vs Inline as above */ + +// This for pushing in to a memory buffer verses the actual active fifo +#define GCM_FUNC_BUFFERED_UNSAFE_INLINED + +#ifdef GCM_FUNC_BUFFERED_UNSAFE_INLINED +#define GCM_FUNC_BUFFERED( GCM_FUNCTION, COMMAND_BUFFER, ...) \ +{ \ + CellGcmContextData gcmContext; \ + gcmContext.current = (uint32_t *)COMMAND_BUFFER; \ + GCM_FUNCTION ## UnsafeInline( &gcmContext, __VA_ARGS__ ); \ + COMMAND_BUFFER = (typeof(COMMAND_BUFFER))gcmContext.current; \ +} +#endif + +typedef enum rglGcmEnum +{ + // gleSetRenderTarget + RGLGCM_NONE = 0x0000, + + // glDrawArrays, glDrawElements, glBegin + RGLGCM_POINTS = 0x0000, + RGLGCM_LINES = 0x0001, + RGLGCM_LINE_LOOP = 0x0002, + RGLGCM_LINE_STRIP = 0x0003, + RGLGCM_TRIANGLES = 0x0004, + RGLGCM_TRIANGLE_STRIP = 0x0005, + RGLGCM_TRIANGLE_FAN = 0x0006, + RGLGCM_QUADS = 0x0007, + RGLGCM_QUAD_STRIP = 0x0008, + RGLGCM_POLYGON = 0x0009, + + // glClear + RGLGCM_DEPTH_BUFFER_BIT = 0x0100, + RGLGCM_STENCIL_BUFFER_BIT = 0x0400, + RGLGCM_COLOR_BUFFER_BIT = 0x4000, + + // glBlendFunc, glStencilFunc + RGLGCM_ZERO = 0, + RGLGCM_ONE = 1, + RGLGCM_SRC_COLOR = 0x0300, + RGLGCM_ONE_MINUS_SRC_COLOR = 0x0301, + RGLGCM_SRC_ALPHA = 0x0302, + RGLGCM_ONE_MINUS_SRC_ALPHA = 0x0303, + RGLGCM_DST_ALPHA = 0x0304, + RGLGCM_ONE_MINUS_DST_ALPHA = 0x0305, + RGLGCM_DST_COLOR = 0x0306, + RGLGCM_ONE_MINUS_DST_COLOR = 0x0307, + RGLGCM_SRC_ALPHA_SATURATE = 0x0308, + + // glAlphaFunc, glDepthFunc, glStencilFunc + RGLGCM_NEVER = 0x0200, + RGLGCM_LESS = 0x0201, + RGLGCM_EQUAL = 0x0202, + RGLGCM_LEQUAL = 0x0203, + RGLGCM_GREATER = 0x0204, + RGLGCM_NOTEQUAL = 0x0205, + RGLGCM_GEQUAL = 0x0206, + RGLGCM_ALWAYS = 0x0207, + + // glLogicOp + RGLGCM_CLEAR = 0x1500, + RGLGCM_AND = 0x1501, + RGLGCM_AND_REVERSE = 0x1502, + RGLGCM_COPY = 0x1503, + RGLGCM_AND_INVERTED = 0x1504, + RGLGCM_NOOP = 0x1505, + RGLGCM_XOR = 0x1506, + RGLGCM_OR = 0x1507, + RGLGCM_NOR = 0x1508, + RGLGCM_EQUIV = 0x1509, + RGLGCM_INVERT = 0x150A, + RGLGCM_OR_REVERSE = 0x150B, + RGLGCM_COPY_INVERTED = 0x150C, + RGLGCM_OR_INVERTED = 0x150D, + RGLGCM_NAND = 0x150E, + RGLGCM_SET = 0x150F, + + // BlendFunc + RGLGCM_CONSTANT_COLOR = 0x8001, + RGLGCM_ONE_MINUS_CONSTANT_COLOR = 0x8002, + RGLGCM_CONSTANT_ALPHA = 0x8003, + RGLGCM_ONE_MINUS_CONSTANT_ALPHA = 0x8004, + RGLGCM_BLEND_COLOR = 0x8005, + RGLGCM_FUNC_ADD = 0x8006, + RGLGCM_MIN = 0x8007, + RGLGCM_MAX = 0x8008, + RGLGCM_BLEND_EQUATION = 0x8009, + RGLGCM_FUNC_SUBTRACT = 0x800A, + RGLGCM_FUNC_REVERSE_SUBTRACT = 0x800B, + + // glTexImage binary formats -- keep in sync with glTexImage tables! + RGLGCM_ALPHA8 = 0x803C, + RGLGCM_ALPHA16 = 0x803E, + RGLGCM_HILO8 = 0x885E, + RGLGCM_HILO16 = 0x86F8, + RGLGCM_ARGB8 = 0x6007, // does not exist in classic OpenGL + RGLGCM_BGRA8 = 0xff01, // does not exist in classic OpenGL + RGLGCM_RGBA8 = 0x8058, + RGLGCM_ABGR8 = 0xff02, // does not exist in classic OpenGL + RGLGCM_XBGR8 = 0xff03, // does not exist in classic OpenGL + RGLGCM_RGBX8 = 0xff07, // does not exist in classic OpenGL + RGLGCM_COMPRESSED_RGB_S3TC_DXT1 = 0x83F0, + RGLGCM_COMPRESSED_RGBA_S3TC_DXT1 = 0x83F1, + RGLGCM_COMPRESSED_RGBA_S3TC_DXT3 = 0x83F2, + RGLGCM_COMPRESSED_RGBA_S3TC_DXT5 = 0x83F3, + RGLGCM_DEPTH_COMPONENT16 = 0x81A5, + RGLGCM_DEPTH_COMPONENT24 = 0x81A6, + RGLGCM_FLOAT_R32 = 0x8885, + RGLGCM_RGB5_A1_SCE = 0x600C, + RGLGCM_RGB565_SCE = 0x600D, + + // glEnable/glDisable + RGLGCM_BLEND = 0x0be0, + RGLGCM_COLOR_LOGIC_OP = 0x0bf2, + RGLGCM_DITHER = 0x0bd0, + RGLGCM_PSHADER_SRGB_REMAPPING = 0xff06, + + // glVertexAttribPointer + RGLGCM_VERTEX_ATTRIB_ARRAY0 = 0x8650, + RGLGCM_VERTEX_ATTRIB_ARRAY1 = 0x8651, + RGLGCM_VERTEX_ATTRIB_ARRAY2 = 0x8652, + RGLGCM_VERTEX_ATTRIB_ARRAY3 = 0x8653, + RGLGCM_VERTEX_ATTRIB_ARRAY4 = 0x8654, + RGLGCM_VERTEX_ATTRIB_ARRAY5 = 0x8655, + RGLGCM_VERTEX_ATTRIB_ARRAY6 = 0x8656, + RGLGCM_VERTEX_ATTRIB_ARRAY7 = 0x8657, + RGLGCM_VERTEX_ATTRIB_ARRAY8 = 0x8658, + RGLGCM_VERTEX_ATTRIB_ARRAY9 = 0x8659, + RGLGCM_VERTEX_ATTRIB_ARRAY10 = 0x865a, + RGLGCM_VERTEX_ATTRIB_ARRAY11 = 0x865b, + RGLGCM_VERTEX_ATTRIB_ARRAY12 = 0x865c, + RGLGCM_VERTEX_ATTRIB_ARRAY13 = 0x865d, + RGLGCM_VERTEX_ATTRIB_ARRAY14 = 0x865e, + RGLGCM_VERTEX_ATTRIB_ARRAY15 = 0x865f, + + // glTexImage + RGLGCM_TEXTURE_3D = 0x806F, + RGLGCM_TEXTURE_CUBE_MAP = 0x8513, + RGLGCM_TEXTURE_1D = 0x0DE0, + RGLGCM_TEXTURE_2D = 0x0DE1, + + // glTexParameter/TextureMagFilter + RGLGCM_NEAREST = 0x2600, + RGLGCM_LINEAR = 0x2601, + // glTexParameter/TextureMinFilter + RGLGCM_NEAREST_MIPMAP_NEAREST = 0x2700, + RGLGCM_LINEAR_MIPMAP_NEAREST = 0x2701, + RGLGCM_NEAREST_MIPMAP_LINEAR = 0x2702, + RGLGCM_LINEAR_MIPMAP_LINEAR = 0x2703, + + // glTexParameter/TextureWrapMode + RGLGCM_CLAMP = 0x2900, + RGLGCM_REPEAT = 0x2901, + RGLGCM_CLAMP_TO_EDGE = 0x812F, + RGLGCM_CLAMP_TO_BORDER = 0x812D, + RGLGCM_MIRRORED_REPEAT = 0x8370, + RGLGCM_MIRROR_CLAMP = 0x8742, + RGLGCM_MIRROR_CLAMP_TO_EDGE = 0x8743, + RGLGCM_MIRROR_CLAMP_TO_BORDER = 0x8912, + + // glTexParameter/GammaRemap + RGLGCM_GAMMA_REMAP_RED_BIT = 0x0001, + RGLGCM_GAMMA_REMAP_GREEN_BIT = 0x0002, + RGLGCM_GAMMA_REMAP_BLUE_BIT = 0x0004, + RGLGCM_GAMMA_REMAP_ALPHA_BIT = 0x0008, + + // glTexParameter + RGLGCM_TEXTURE_WRAP_S = 0x2802, + RGLGCM_TEXTURE_WRAP_T = 0x2803, + RGLGCM_TEXTURE_WRAP_R = 0x8072, + RGLGCM_TEXTURE_MIN_FILTER = 0x2801, + RGLGCM_TEXTURE_MAG_FILTER = 0x2800, + RGLGCM_TEXTURE_MAX_ANISOTROPY = 0x84FE, + RGLGCM_TEXTURE_COMPARE_FUNC = 0x884D, + RGLGCM_TEXTURE_MIN_LOD = 0x813A, + RGLGCM_TEXTURE_MAX_LOD = 0x813B, + RGLGCM_TEXTURE_LOD_BIAS = 0x8501, + RGLGCM_TEXTURE_BORDER_COLOR = 0x1004, + RGLGCM_TEXTURE_GAMMA_REMAP = 0xff30, + + // ARB_vertex_program + RGLGCM_VERTEX_PROGRAM = 0x8620, + RGLGCM_FRAGMENT_PROGRAM = 0x8804, + + // glVertexAttribPointer + RGLGCM_FLOAT = 0x1406, + RGLGCM_HALF_FLOAT = 0x140B, + RGLGCM_SHORT = 0x1402, + RGLGCM_UNSIGNED_BYTE = 0x1401, + RGLGCM_UNSIGNED_SHORT = 0x1403, + RGLGCM_UNSIGNED_INT = 0x1405, + RGLGCM_BYTE = 0x1400, + RGLGCM_INT = 0x1404, + + // query support + RGLGCM_SAMPLES_PASSED = 0xff10, + + // semaphore support + RGLGCM_SEMAPHORE_USING_GPU = 0xff20, + RGLGCM_SEMAPHORE_USING_CPU = 0xff21, + RGLGCM_SEMAPHORE_USING_GPU_NO_WRITE_FLUSH = 0xff22, + + // depth clamp + RGLGCM_DEPTH_CLAMP = 0x864F, + + // 11/11/10 bit 3-component attributes + RGLGCM_CMP = 0x6020, +} rglGcmEnum; + +#define RGLGCM_LINEAR_BUFFER_ALIGNMENT 128 +#define RGLGCM_HOST_BUFFER_ALIGNMENT 128 + +#define RGLGCM_TRANSIENT_MEMORY_DEFAULT (32 << 20) +#define RGLGCM_PERSISTENT_MEMORY_DEFAULT (160 << 20) +#define RGLGCM_FIFO_SIZE_DEFAULT (256 * 1024) +#define RGLGCM_HOST_SIZE_DEFAULT (0) +#define RGLGCM_TRANSIENT_ENTRIES_DEFAULT 64 + +// RSX semaphore allocation +// 64-191 events +// 192 fence implementation (independent of nv_glFence) +// 253 used in RGLGcmFifoUtils.h +#define RGLGCM_SEMA_NEVENTS 128 +#define RGLGCM_SEMA_BASE 64 // libgcm uses 0-63 +#define RGLGCM_SEMA_FENCE (RGLGCM_SEMA_BASE+RGLGCM_SEMA_NEVENTS+0) + +// synchronization +// rglGcmSync enables GPU waiting by sending nv_glAcquireSemaphore to the +// GPU and returning a memory mapped pointer to the semaphore. The GPU +// will be released when 0 is written to the memory location. +// +// rglGcm{Inc,Test,Finish}FenceRef are intended to be drop-in replacements +// for the corresponding RGLGCM routines, using a semaphore instead of the +// fence mechanism (so IncFence uses the 3D class). + +#define RGLGCM_FALSE 0 + +#define RGLGCM_MAX_COLOR_SURFACES 4 + +#define RGLGCM_TRUE 1 + +// allocation unit for buffer objects +// Each buffer object is allocated to a multiple of this block size. This +// must be at least 64 so that nv_glTransferDataVidToVid() can be used to +// copy buffer objects within video memory. This function performs a 2D +// blit, and there is a 64-byte minimum pitch constraint. +// +// Swizzled textures require 128-byte alignment, so this takes precedence. +#define RGL_BUFFER_OBJECT_BLOCK_SIZE 128 + +#define VERTEX_PROFILE_INDEX 0 + +// GCM can render to 4 color buffers at once. +#define RGLGCM_SETRENDERTARGET_MAXCOUNT 4 + +// max amount of semaphore we allocate space for +#define RGLGCM_MAX_USER_SEMAPHORES 256 +#define RGLGCM_PAGE_SIZE 0x1000 // 4KB + +#define RGLGCM_LM_MAX_TOTAL_QUERIES 800 +#define RGLGCM_LM_MAX_ZPASS_REPORTS (RGLGCM_LM_MAX_TOTAL_QUERIES - 10) +#define RGLGCM_LM_MAX_USER_QUERIES (RGLGCM_LM_MAX_ZPASS_REPORTS) + +// For main memory query PSGL is going to enable 5000 at any given time +// compared to the 800 currently for the Local memory queries +// However, if you really need more than 5k then change the line below +// and recompile [RSTENSON] +// Maximum value for RGLGCM_MM_MAX_TOTAL_QUERIES is 65,000 +#define RGLGCM_MM_MAX_TOTAL_QUERIES 5000 // Should be plenty. +#define RGLGCM_MM_MAX_ZPASS_REPORTS (RGLGCM_MM_MAX_TOTAL_QUERIES - 10) +#define RGLGCM_MM_MAX_USER_QUERIES (RGLGCM_MM_MAX_ZPASS_REPORTS) + +// For 2.50 PSGL will use reports in main memory by default +// To revert to reports in local memory comment out this define +#define RGLGCM_USE_MAIN_MEMORY_REPORTS +#ifdef RGLGCM_USE_MAIN_MEMORY_REPORTS +#define RGLGCM_MAX_USER_QUERIES RGLGCM_MM_MAX_USER_QUERIES +#else +#define RGLGCM_MAX_USER_QUERIES RGLGCM_LM_MAX_USER_QUERIES +#endif + + +#define RGLGCM_357C_NOTIFIERS_MAXCOUNT 11 + +enum +{ + // dma contexts + RGLGCM_CHANNEL_DMA_SCRATCH_NOTIFIER, + RGLGCM_CONTEXT_DMA_MEMORY_FRAME_BUFFER, + RGLGCM_CONTEXT_DMA_TO_MEMORY_GET_REPORT, + RGLGCM_CONTEXT_DMA_MEMORY_HOST_BUFFER, + RGLGCM_CONTEXT_DMA_MEMORY_SEMAPHORE_RW, + RGLGCM_CONTEXT_DMA_MEMORY_SEMAPHORE_RO, + + // classes + RGLGCM_CURIE_PRIMITIVE, + RGLGCM_MEM2MEM_HOST_TO_VIDEO, + + RGLGCM_IMAGEFROMCPU, + RGLGCM_SCALEDIMAGE, + RGLGCM_CONTEXT_2D_SURFACE, + RGLGCM_CONTEXT_SWIZ_SURFACE, + + RGLGCM_HANDLE_COUNT +}; + +// For quick float->int conversions +#define RGLGCM_F0_DOT_0 12582912.0f + +// some other useful push buf defines/commands +#define RGLGCM_NON_INCREMENT (0x40000000) +#define RGLGCM_NOP() (0x00000000) +#define RGLGCM_JUMP(addr) (0x20000000 | (addr)) +#define RGLGCM_CALL(addr) (0x00000002 | (addr)) +#define RGLGCM_RETURN() (0x00020000) +#define RGLGCM_MAX_METHOD_COUNT (2047) +#define RGLGCM_COUNT_SHIFT (18) +#define RGLGCM_SUBCHANNEL_SHIFT (13) +#define RGLGCM_METHOD_SHIFT (0) + +#define DEFAULT_FIFO_BLOCK_SIZE (0x10000) // 64KB +#define FIFO_RESERVE_SIZE 8 // reserved words needed at the beginning of the fifo + +#define BUFFER_HSYNC_NEGATIVE 0 +#define BUFFER_HSYNC_POSITIVE 1 +#define BUFFER_VSYNC_NEGATIVE 0 +#define BUFFER_VSYNC_POSITIVE 1 + +// This is the format that the mode timing parameters are handed back + +enum { + RGLGCM_SURFACE_SOURCE_TEMPORARY, + RGLGCM_SURFACE_SOURCE_DEVICE, + RGLGCM_SURFACE_SOURCE_TEXTURE, + RGLGCM_SURFACE_SOURCE_RENDERBUFFER, + RGLGCM_SURFACE_SOURCE_PBO, +}; + +enum { + RGLGCM_SURFACE_POOL_NONE, + RGLGCM_SURFACE_POOL_TILED_COLOR, + RGLGCM_SURFACE_POOL_TILED_DEPTH, + RGLGCM_SURFACE_POOL_LINEAR, + RGLGCM_SURFACE_POOL_SYSTEM, // GPU accessible host memory + RGLGCM_SURFACE_POOL_PPU, // generic EA + RGLGCM_SURFACE_POOL_SYSTEM_TILED_COLOR, // tiled color GPU accessible XDR + RGLGCM_SURFACE_POOL_SYSTEM_TILED_DEPTH, // tiled depth GPU accessible XDR +}; + + +#define RGLGCM_DEVICE_SYNC_FENCE 1 +#define RGLGCM_DEVICE_SYNC_COND 2 + +// max surface/scissor/viewport dimension +#define RGLGCM_MAX_RT_DIMENSION (CELL_GCM_MAX_RT_DIMENSION) + +// a few texture consts +#define RGLGCM_MAX_SHADER_TEXCOORD_COUNT (CELL_GCM_MAX_SHADER_TEXCOORD_COUNT) +#define RGLGCM_MAX_TEXIMAGE_COUNT (CELL_GCM_MAX_TEXIMAGE_COUNT) +#define RGLGCM_MAX_LOD_COUNT (CELL_GCM_MAX_LOD_COUNT) +#define RGLGCM_MAX_TEX_DIMENSION (CELL_GCM_MAX_TEX_DIMENSION) + +// max attrib count +#define RGLGCM_ATTRIB_COUNT 16 + +// Names for each of the vertex attributes +#define RGLGCM_ATTRIB_POSITION 0 +#define RGLGCM_ATTRIB_VERTEX_WEIGHT 1 +#define RGLGCM_ATTRIB_NORMAL 2 +#define RGLGCM_ATTRIB_COLOR 3 +#define RGLGCM_ATTRIB_SECONDARY_C OLOR 4 +#define RGLGCM_ATTRIB_FOG_COORD 5 +#define RGLGCM_ATTRIB_PSIZE 6 +#define RGLGCM_ATTRIB_UNUSED1 7 +#define RGLGCM_ATTRIB_TEXCOORD0 8 +#define RGLGCM_ATTRIB_TEXCOORD1 9 +#define RGLGCM_ATTRIB_TEXCOORD2 10 +#define RGLGCM_ATTRIB_TEXCOORD3 11 +#define RGLGCM_ATTRIB_TEXCOORD4 12 +#define RGLGCM_ATTRIB_TEXCOORD5 13 +#define RGLGCM_ATTRIB_TEXCOORD6 14 +#define RGLGCM_ATTRIB_TEXCOORD7 15 + +// Names for the vertex output components: +#define RGLGCM_ATTRIB_OUTPUT_HPOS 0 +#define RGLGCM_ATTRIB_OUTPUT_COL0 1 +#define RGLGCM_ATTRIB_OUTPUT_COL1 2 +#define RGLGCM_ATTRIB_OUTPUT_BFC0 3 +#define RGLGCM_ATTRIB_OUTPUT_BFC1 4 +#define RGLGCM_ATTRIB_OUTPUT_FOGC 5 +#define RGLGCM_ATTRIB_OUTPUT_PSIZ 6 +#define RGLGCM_ATTRIB_OUTPUT_TEX0 7 +#define RGLGCM_ATTRIB_OUTPUT_TEX1 8 +#define RGLGCM_ATTRIB_OUTPUT_TEX2 9 +#define RGLGCM_ATTRIB_OUTPUT_TEX3 10 +#define RGLGCM_ATTRIB_OUTPUT_TEX4 11 +#define RGLGCM_ATTRIB_OUTPUT_TEX5 12 +#define RGLGCM_ATTRIB_OUTPUT_TEX6 13 +#define RGLGCM_ATTRIB_OUTPUT_TEX7 14 + +// viewport adjusting +#define RGLGCM_SUBPIXEL_ADJUST (0.5/(1<<12)) +#define RGLGCM_VIEWPORT_EPSILON 0.0f + +// max vertex program constant slots +#define RGLGCM_VTXPRG_MAX_CONST (CELL_GCM_VTXPRG_MAX_CONST) +#define RGLGCM_VTXPRG_MAX_INST (CELL_GCM_VTXPRG_MAX_INST) + +#define RGLGCM_HAS_INVALIDATE_TILE + +#define RGLGCM_TILED_BUFFER_ALIGNMENT 0x10000 // 64KB +#define RGLGCM_TILED_BUFFER_HEIGHT_ALIGNMENT 64 + +#define RGLGCM_MAX_TILED_REGIONS 15 + +#define RGLP_BUFFER_OBJECT_SIZE() (sizeof(rglGcmBufferObject)) diff --git a/console/rgl/src/ps3/include/rgl-externs.h b/console/rgl/src/ps3/include/rgl-externs.h new file mode 100644 index 0000000000..1b9cc1ee5a --- /dev/null +++ b/console/rgl/src/ps3/include/rgl-externs.h @@ -0,0 +1,41 @@ +void rglGcmFifoFinish(rglGcmFifo *fifo); +GLboolean rglGcmFifoReferenceInUse( rglGcmFifo *fifo, GLuint reference ); +GLuint rglGcmFifoPutReference( rglGcmFifo *fifo ); +void rglGcmFifoFlush( rglGcmFifo *fifo ); +uint32_t * rglGcmFifoWaitForFreeSpace( rglGcmFifo *fifo, GLuint spaceInWords ); +void rglGcmGetTileRegionInfo( void* data, GLuint *address, GLuint *size ); +GLboolean rglGcmTryResizeTileRegion( GLuint address, GLuint size, void* data ); + +void rglGcmTransferData +( + GLuint dstId, + GLuint dstIdOffset, + GLint dstPitch, + GLuint srcId, + GLuint srcIdOffset, + GLint srcPitch, + GLint bytesPerRow, + GLint rowCount + ); + +int32_t rglOutOfSpaceCallback( struct CellGcmContextData* fifoContext, uint32_t spaceInWords ); +void rglGcmFifoGlSetRenderTarget( rglGcmRenderTargetEx const * const args ); +void rglpFifoGlFinish( void ); +void rglCreatePushBuffer( _CGprogram *program ); +void rglSetDefaultValuesFP( _CGprogram *program ); +void rglSetDefaultValuesVP( _CGprogram *program ); +void rglGcmSend( unsigned int dstId, unsigned dstOffset, unsigned int pitch, const char *src, unsigned int size ); +void rglGcmMemcpy( const GLuint dstId, unsigned dstOffset, unsigned int pitch, const GLuint srcId, GLuint srcOffset, unsigned int size ); +void rglPlatformValidateTextureResources( rglTexture *texture ); +GLuint rglGetGcmImageOffset( rglGcmTextureLayout *layout, GLuint face, GLuint level ); +void rglSetNativeCgFragmentProgram( const GLvoid *header ); +void rglGcmFreeTiledSurface( GLuint bufferId ); + +void rglGcmCopySurface( + const rglGcmSurface* src, + GLuint srcX, GLuint srcY, + const rglGcmSurface* dst, + GLuint dstX, GLuint dstY, + GLuint width, GLuint height, + GLboolean writeSync); +void rglSetNativeCgVertexProgram( const void *header ); diff --git a/console/rgl/src/ps3/include/rgl-inline.h b/console/rgl/src/ps3/include/rgl-inline.h new file mode 100644 index 0000000000..151f2dda99 --- /dev/null +++ b/console/rgl/src/ps3/include/rgl-inline.h @@ -0,0 +1,1160 @@ +// Clamp a float to [0,1]: +// The order of clamp comparisons are arranged so that NaN maps to min +// when compiled with VisualC or gcc. IEEE says comparisons with NaN +// should always fail (gcc implements this) but VisualC sometimes uses +// signed integer compares rather than floating-point compares which is +// incorrect in the case of NaN. +#define RGLGCM_CLAMPF_01(x) ((x) >= 0.0f ? ((x) > 1.0f ? 1.0f : (x)) : 0.0f) + +static inline GLboolean rglIsDrawableColorFormat( GLenum colorFormat ) +{ + switch ( colorFormat ) + { + case RGLGCM_ARGB8: + case RGLGCM_FLOAT_R32: + return GL_TRUE; + default: + return GL_FALSE; + } +} + +static inline GLuint rglPlatformGetBitsPerPixel( GLenum internalFormat ) +{ + switch ( internalFormat ) + { + case RGLGCM_ALPHA16: + case RGLGCM_HILO8: + case RGLGCM_RGB5_A1_SCE: + case RGLGCM_RGB565_SCE: + return 16; + case RGLGCM_ALPHA8: + return 8; + case RGLGCM_RGBX8: + case RGLGCM_RGBA8: + case RGLGCM_ABGR8: + case RGLGCM_ARGB8: + case RGLGCM_BGRA8: + case RGLGCM_FLOAT_R32: + case RGLGCM_HILO16: + case RGLGCM_XBGR8: + return 32; + default: + return 0; + } +} + + +#define SUBPIXEL_BITS 12 +#define SUBPIXEL_ADJUST (0.5/(1<x = x; + vp->y = y; + vp->w = width; + vp->h = height; + + // clamp to hw limits + clipX0 = x; + clipX1 = x + width; + if ( rt->yInverted ) + { + clipY0 = rt->gcmRenderTarget.height - ( y + height ); + clipY1 = rt->gcmRenderTarget.height - y; + } + else + { + clipY0 = y; + clipY1 = y + height; + } + if ( clipX0 < 0 ) + { + clipX0 = 0; + } + if ( clipY0 < 0 ) + { + clipY0 = 0; + } + if ( clipX1 >= RGLGCM_MAX_RT_DIMENSION ) + { + clipX1 = RGLGCM_MAX_RT_DIMENSION; + } + if ( clipY1 >= RGLGCM_MAX_RT_DIMENSION ) + { + clipY1 = RGLGCM_MAX_RT_DIMENSION; + } + if (( clipX1 <= clipX0 ) || ( clipY1 <= clipY0 ) ) + { + clipX0 = clipY0 = clipX1 = clipY1 = 0; + } + + // update viewport info + vp->xScale = width * 0.5f; + vp->xCenter = ( GLfloat )( x + vp->xScale + RGLGCM_SUBPIXEL_ADJUST ); + if ( rt->yInverted ) + { + vp->yScale = height * -0.5f; + vp->yCenter = ( GLfloat )( rt->gcmRenderTarget.height - RGLGCM_VIEWPORT_EPSILON - y + vp->yScale + RGLGCM_SUBPIXEL_ADJUST ); + } + else + { + vp->yScale = height * 0.5f; + vp->yCenter = ( GLfloat )( y + vp->yScale + RGLGCM_SUBPIXEL_ADJUST ); + } + + // Clamp depth range to legal values + zNear = RGLGCM_CLAMPF_01( zNear ); + zFar = RGLGCM_CLAMPF_01( zFar ); + + // compute viewport values for hw [no doubles, so we might loose a few lsb] + GLfloat z_scale = ( GLfloat )( 0.5f * ( zFar - zNear ) ); + GLfloat z_center = ( GLfloat )( 0.5f * ( zFar + zNear ) ); + + // hw zNear/zFar clipper + if ( zNear > zFar ) + { + GLclampf tmp = zNear; + zNear = zFar; + zFar = tmp; + } + + float scale[4] = { vp->xScale, vp->yScale, z_scale, 0.0f }; + float offset[4] = { vp->xCenter, vp->yCenter, z_center, 0.0f }; + + GCM_FUNC( cellGcmSetViewport, clipX0, clipY0, clipX1 - clipX0, + clipY1 - clipY0, zNear, zFar, scale, offset ); +} + +/* When you call glDrawArrays, count sequential elements from each enabled + ** array are used to construct a sequence of geometric primitives, beginning + ** with the first element. The mode parameter specifies what kind of primitive + ** to construct and how to use the array elements to construct the primitives. + ** + ** note: + ** - 1:1 port of glDrawArrays (see spec for details) + ** - legal values for mode are RGLGCM_POINTS, RGLGCM_LINES, RGLGCM_LINE_LOOP, RGLGCM_LINE_STRIP, + ** RGLGCM_TRIANGLES, RGLGCM_TRIANGLE_STRIP, RGLGCM_TRIANGLE_FAN, RGLGCM_QUADS, RGLGCM_QUAD_STRIP + ** and RGLGCM_POLYGON + ** - legal values for first, first+Count are [0, 0xfffff] + ** - if vertex reusage exists, glDrawElements is preferred + */ +static inline void rglGcmFifoGlDrawArrays( rglGcmEnum mode, GLint first, GLsizei count ) +{ + uint8_t gcmMode = 0; + switch ( mode ) + { + case RGLGCM_POINTS: + gcmMode = CELL_GCM_PRIMITIVE_POINTS; + break; + case RGLGCM_LINES: + gcmMode = CELL_GCM_PRIMITIVE_LINES; + break; + case RGLGCM_LINE_LOOP: + gcmMode = CELL_GCM_PRIMITIVE_LINE_LOOP; + break; + case RGLGCM_LINE_STRIP: + gcmMode = CELL_GCM_PRIMITIVE_LINE_STRIP; + break; + case RGLGCM_TRIANGLES: + gcmMode = CELL_GCM_PRIMITIVE_TRIANGLES; + break; + case RGLGCM_TRIANGLE_STRIP: + gcmMode = CELL_GCM_PRIMITIVE_TRIANGLE_STRIP; + break; + case RGLGCM_TRIANGLE_FAN: + gcmMode = CELL_GCM_PRIMITIVE_TRIANGLE_FAN; + break; + case RGLGCM_QUADS: + gcmMode = CELL_GCM_PRIMITIVE_QUADS; + break; + case RGLGCM_QUAD_STRIP: + gcmMode = CELL_GCM_PRIMITIVE_QUAD_STRIP; + break; + case RGLGCM_POLYGON: + gcmMode = CELL_GCM_PRIMITIVE_POLYGON; + break; + default: + break; + } + + if ( count ) + { + GCM_FUNC_SAFE( cellGcmSetDrawArrays, gcmMode, first, count ); + } +} + + static inline void rglGcmFifoGlTransferDataVidToVid +( + GLuint dstVidId, + GLuint dstVidIdOffset, + GLuint dstPitch, + GLuint dstX, + GLuint dstY, + GLuint srcVidId, + GLuint srcVidIdOffset, + GLuint srcPitch, + GLuint srcX, + GLuint srcY, + GLuint width, // size in pixel + GLuint height, + GLuint bytesPerPixel + ) +{ + GLuint dstOffset = gmmIdToOffset(dstVidId) + dstVidIdOffset; + GLuint srcOffset = gmmIdToOffset(srcVidId) + srcVidIdOffset; + + GCM_FUNC( cellGcmSetTransferImage, CELL_GCM_TRANSFER_LOCAL_TO_LOCAL, dstOffset, dstPitch, dstX, dstY, srcOffset, srcPitch, srcX, srcY, width, height, bytesPerPixel ); +} + +static inline GLuint rglGcmMapMinTextureFilter( GLenum filter ) +{ + switch ( filter ) + { + case GL_NEAREST: + return CELL_GCM_TEXTURE_NEAREST; + break; + case GL_LINEAR: + return CELL_GCM_TEXTURE_LINEAR; + break; + case GL_NEAREST_MIPMAP_NEAREST: + return CELL_GCM_TEXTURE_NEAREST_NEAREST; + break; + case GL_NEAREST_MIPMAP_LINEAR: + return CELL_GCM_TEXTURE_NEAREST_LINEAR; + break; + case GL_LINEAR_MIPMAP_NEAREST: + return CELL_GCM_TEXTURE_LINEAR_NEAREST; + break; + case GL_LINEAR_MIPMAP_LINEAR: + return CELL_GCM_TEXTURE_LINEAR_LINEAR; + break; + default: + return 0; + } + return filter; +} + +static inline GLuint rglGcmMapMagTextureFilter( GLenum filter ) +{ + switch ( filter ) + { + case GL_NEAREST: + return CELL_GCM_TEXTURE_NEAREST; + break; + case GL_LINEAR: + return CELL_GCM_TEXTURE_LINEAR; + break; + default: + return 0; + } + return filter; +} + +static inline GLuint rglGcmMapAniso( GLuint maxAniso ) +{ + + if ( maxAniso >= 16 ) + return CELL_GCM_TEXTURE_MAX_ANISO_16; + if ( maxAniso == 1 ) + return CELL_GCM_TEXTURE_MAX_ANISO_1; + + switch ( maxAniso / 2 ) + { + case 1: + return CELL_GCM_TEXTURE_MAX_ANISO_2; + break; + case 2: + return CELL_GCM_TEXTURE_MAX_ANISO_4; + break; + case 3: + return CELL_GCM_TEXTURE_MAX_ANISO_6; + break; + case 4: + return CELL_GCM_TEXTURE_MAX_ANISO_8; + break; + case 5: + return CELL_GCM_TEXTURE_MAX_ANISO_10; + break; + case 6: + return CELL_GCM_TEXTURE_MAX_ANISO_12; + break; + case 7: + return CELL_GCM_TEXTURE_MAX_ANISO_16; + break; + default: + return 0; + break; + } + return 0; +} + +static inline GLuint rglGcmMapWrapMode( GLuint mode ) +{ + switch ( mode ) + { + case RGLGCM_CLAMP: + return CELL_GCM_TEXTURE_CLAMP; + break; + case RGLGCM_REPEAT: + return CELL_GCM_TEXTURE_WRAP; + break; + case RGLGCM_CLAMP_TO_EDGE: + return CELL_GCM_TEXTURE_CLAMP_TO_EDGE; + break; + case RGLGCM_CLAMP_TO_BORDER: + return CELL_GCM_TEXTURE_BORDER; + break; + case RGLGCM_MIRRORED_REPEAT: + return CELL_GCM_TEXTURE_MIRROR; + break; + case RGLGCM_MIRROR_CLAMP_TO_EDGE: + return CELL_GCM_TEXTURE_MIRROR_ONCE_CLAMP_TO_EDGE; + break; + case RGLGCM_MIRROR_CLAMP_TO_BORDER: + return CELL_GCM_TEXTURE_MIRROR_ONCE_BORDER; + break; + case RGLGCM_MIRROR_CLAMP: + return CELL_GCM_TEXTURE_MIRROR_ONCE_CLAMP; + break; + default: + return 0; + break; + } + return 0; +} + + +static inline void rglGcmMapTextureFormat( GLuint internalFormat, uint8_t & gcmFormat, uint32_t & remap ) +{ + gcmFormat = 0; + + switch ( internalFormat ) + { + case RGLGCM_ALPHA8: // in_rgba = xxAx, out_rgba = 000A + { + gcmFormat = CELL_GCM_TEXTURE_B8; + remap = CELL_GCM_REMAP_MODE( + CELL_GCM_TEXTURE_REMAP_ORDER_XYXY, + CELL_GCM_TEXTURE_REMAP_FROM_B, + CELL_GCM_TEXTURE_REMAP_FROM_R, + CELL_GCM_TEXTURE_REMAP_FROM_B, + CELL_GCM_TEXTURE_REMAP_FROM_B, + CELL_GCM_TEXTURE_REMAP_REMAP, + CELL_GCM_TEXTURE_REMAP_ZERO, + CELL_GCM_TEXTURE_REMAP_ZERO, + CELL_GCM_TEXTURE_REMAP_ZERO ); + + } + break; + case RGLGCM_ALPHA16: // in_rgba = xAAx, out_rgba = 000A + { + gcmFormat = CELL_GCM_TEXTURE_X16; + remap = CELL_GCM_REMAP_MODE( + CELL_GCM_TEXTURE_REMAP_ORDER_XYXY, + CELL_GCM_TEXTURE_REMAP_FROM_G, + CELL_GCM_TEXTURE_REMAP_FROM_B, + CELL_GCM_TEXTURE_REMAP_FROM_G, + CELL_GCM_TEXTURE_REMAP_FROM_B, + CELL_GCM_TEXTURE_REMAP_REMAP, + CELL_GCM_TEXTURE_REMAP_ZERO, + CELL_GCM_TEXTURE_REMAP_ZERO, + CELL_GCM_TEXTURE_REMAP_ZERO ); + + } + break; + case RGLGCM_HILO8: // in_rgba = HLxx, out_rgba = HL11 + { + gcmFormat = CELL_GCM_TEXTURE_COMPRESSED_HILO8; + remap = CELL_GCM_REMAP_MODE( + CELL_GCM_TEXTURE_REMAP_ORDER_XYXY, + CELL_GCM_TEXTURE_REMAP_FROM_A, + CELL_GCM_TEXTURE_REMAP_FROM_R, + CELL_GCM_TEXTURE_REMAP_FROM_G, + CELL_GCM_TEXTURE_REMAP_FROM_B, + CELL_GCM_TEXTURE_REMAP_ONE, + CELL_GCM_TEXTURE_REMAP_REMAP, + CELL_GCM_TEXTURE_REMAP_REMAP, + CELL_GCM_TEXTURE_REMAP_ONE ); + + } + break; + case RGLGCM_HILO16: // in_rgba = HLxx, out_rgba = HL11 + { + gcmFormat = CELL_GCM_TEXTURE_Y16_X16; + remap = CELL_GCM_REMAP_MODE( + CELL_GCM_TEXTURE_REMAP_ORDER_XYXY, + CELL_GCM_TEXTURE_REMAP_FROM_A, + CELL_GCM_TEXTURE_REMAP_FROM_R, + CELL_GCM_TEXTURE_REMAP_FROM_G, + CELL_GCM_TEXTURE_REMAP_FROM_B, + CELL_GCM_TEXTURE_REMAP_ONE, + CELL_GCM_TEXTURE_REMAP_REMAP, + CELL_GCM_TEXTURE_REMAP_REMAP, + CELL_GCM_TEXTURE_REMAP_ONE ); + + } + break; + case RGLGCM_ARGB8: // in_rgba = RGBA, out_rgba = RGBA + { + gcmFormat = CELL_GCM_TEXTURE_A8R8G8B8; + remap = CELL_GCM_REMAP_MODE( + CELL_GCM_TEXTURE_REMAP_ORDER_XYXY, + CELL_GCM_TEXTURE_REMAP_FROM_A, + CELL_GCM_TEXTURE_REMAP_FROM_R, + CELL_GCM_TEXTURE_REMAP_FROM_G, + CELL_GCM_TEXTURE_REMAP_FROM_B, + CELL_GCM_TEXTURE_REMAP_REMAP, + CELL_GCM_TEXTURE_REMAP_REMAP, + CELL_GCM_TEXTURE_REMAP_REMAP, + CELL_GCM_TEXTURE_REMAP_REMAP ); + + } + break; + case RGLGCM_BGRA8: // in_rgba = GRAB, out_rgba = RGBA ** NEEDS TO BE TESTED + { + gcmFormat = CELL_GCM_TEXTURE_A8R8G8B8; + remap = CELL_GCM_REMAP_MODE( + CELL_GCM_TEXTURE_REMAP_ORDER_XYXY, + CELL_GCM_TEXTURE_REMAP_FROM_B, + CELL_GCM_TEXTURE_REMAP_FROM_G, + CELL_GCM_TEXTURE_REMAP_FROM_R, + CELL_GCM_TEXTURE_REMAP_FROM_A, + CELL_GCM_TEXTURE_REMAP_REMAP, + CELL_GCM_TEXTURE_REMAP_REMAP, + CELL_GCM_TEXTURE_REMAP_REMAP, + CELL_GCM_TEXTURE_REMAP_REMAP ); + + } + break; + case RGLGCM_RGBA8: // in_rgba = GBAR, out_rgba = RGBA ** NEEDS TO BE TESTED + { + gcmFormat = CELL_GCM_TEXTURE_A8R8G8B8; + remap = CELL_GCM_REMAP_MODE( + CELL_GCM_TEXTURE_REMAP_ORDER_XYXY, + CELL_GCM_TEXTURE_REMAP_FROM_B, + CELL_GCM_TEXTURE_REMAP_FROM_A, + CELL_GCM_TEXTURE_REMAP_FROM_R, + CELL_GCM_TEXTURE_REMAP_FROM_G, + CELL_GCM_TEXTURE_REMAP_REMAP, + CELL_GCM_TEXTURE_REMAP_REMAP, + CELL_GCM_TEXTURE_REMAP_REMAP, + CELL_GCM_TEXTURE_REMAP_REMAP ); + } + break; + case RGLGCM_ABGR8: // in_rgba = BGRA, out_rgba = RGBA ** NEEDS TO BE TESTED + { + gcmFormat = CELL_GCM_TEXTURE_A8R8G8B8; + remap = CELL_GCM_REMAP_MODE( + CELL_GCM_TEXTURE_REMAP_ORDER_XYXY, + CELL_GCM_TEXTURE_REMAP_FROM_A, + CELL_GCM_TEXTURE_REMAP_FROM_B, + CELL_GCM_TEXTURE_REMAP_FROM_G, + CELL_GCM_TEXTURE_REMAP_FROM_R, + CELL_GCM_TEXTURE_REMAP_REMAP, + CELL_GCM_TEXTURE_REMAP_REMAP, + CELL_GCM_TEXTURE_REMAP_REMAP, + CELL_GCM_TEXTURE_REMAP_REMAP ); + + } + break; + case RGLGCM_RGBX8: // in_rgba = BGRA, out_rgba = RGB1 ** NEEDS TO BE TESTED + { + gcmFormat = CELL_GCM_TEXTURE_A8R8G8B8; + remap = CELL_GCM_REMAP_MODE( + CELL_GCM_TEXTURE_REMAP_ORDER_XYXY, + CELL_GCM_TEXTURE_REMAP_FROM_B, + CELL_GCM_TEXTURE_REMAP_FROM_A, + CELL_GCM_TEXTURE_REMAP_FROM_R, + CELL_GCM_TEXTURE_REMAP_FROM_G, + CELL_GCM_TEXTURE_REMAP_ONE, + CELL_GCM_TEXTURE_REMAP_REMAP, + CELL_GCM_TEXTURE_REMAP_REMAP, + CELL_GCM_TEXTURE_REMAP_REMAP ); + + } + break; + case RGLGCM_XBGR8: // in_rgba = BGRA, out_rgba = RGB1 ** NEEDS TO BE TESTED + { + gcmFormat = CELL_GCM_TEXTURE_A8R8G8B8; + remap = CELL_GCM_REMAP_MODE( + CELL_GCM_TEXTURE_REMAP_ORDER_XYXY, + CELL_GCM_TEXTURE_REMAP_FROM_A, + CELL_GCM_TEXTURE_REMAP_FROM_B, + CELL_GCM_TEXTURE_REMAP_FROM_G, + CELL_GCM_TEXTURE_REMAP_FROM_R, + CELL_GCM_TEXTURE_REMAP_ONE, + CELL_GCM_TEXTURE_REMAP_REMAP, + CELL_GCM_TEXTURE_REMAP_REMAP, + CELL_GCM_TEXTURE_REMAP_REMAP ); + + } + break; + case RGLGCM_FLOAT_R32: // in_rgba = Rxxx, out_rgba = R001 + { + gcmFormat = CELL_GCM_TEXTURE_X32_FLOAT; + remap = CELL_GCM_REMAP_MODE( + CELL_GCM_TEXTURE_REMAP_ORDER_XYXY, + CELL_GCM_TEXTURE_REMAP_FROM_A, + CELL_GCM_TEXTURE_REMAP_FROM_R, + CELL_GCM_TEXTURE_REMAP_FROM_G, + CELL_GCM_TEXTURE_REMAP_FROM_B, + CELL_GCM_TEXTURE_REMAP_ONE, + CELL_GCM_TEXTURE_REMAP_REMAP, + CELL_GCM_TEXTURE_REMAP_ZERO, + CELL_GCM_TEXTURE_REMAP_ZERO ); + + } + break; + case RGLGCM_RGB5_A1_SCE: // in_rgba = RGBA, out_rgba = RGBA + { + gcmFormat = CELL_GCM_TEXTURE_A1R5G5B5; + remap = CELL_GCM_REMAP_MODE( + CELL_GCM_TEXTURE_REMAP_ORDER_XXXY, + CELL_GCM_TEXTURE_REMAP_FROM_A, + CELL_GCM_TEXTURE_REMAP_FROM_R, + CELL_GCM_TEXTURE_REMAP_FROM_G, + CELL_GCM_TEXTURE_REMAP_FROM_B, + CELL_GCM_TEXTURE_REMAP_REMAP, + CELL_GCM_TEXTURE_REMAP_REMAP, + CELL_GCM_TEXTURE_REMAP_REMAP, + CELL_GCM_TEXTURE_REMAP_REMAP ); + + } + break; + case RGLGCM_RGB565_SCE: // in_rgba = RGBA, out_rgba = RGBA + { + gcmFormat = CELL_GCM_TEXTURE_R5G6B5; + remap = CELL_GCM_REMAP_MODE( + CELL_GCM_TEXTURE_REMAP_ORDER_XXXY, + CELL_GCM_TEXTURE_REMAP_FROM_A, + CELL_GCM_TEXTURE_REMAP_FROM_R, + CELL_GCM_TEXTURE_REMAP_FROM_G, + CELL_GCM_TEXTURE_REMAP_FROM_B, + CELL_GCM_TEXTURE_REMAP_ONE, + CELL_GCM_TEXTURE_REMAP_REMAP, + CELL_GCM_TEXTURE_REMAP_REMAP, + CELL_GCM_TEXTURE_REMAP_REMAP ); + + } + break; + default: + break; + }; + + return; +} + +// Explicitly invalidate the L2 texture cache +static inline void rglGcmFifoGlInvalidateTextureCache( void ) +{ + GCM_FUNC( cellGcmSetInvalidateTextureCache, CELL_GCM_INVALIDATE_TEXTURE ); +} + +/* writes the supplied new semaphore value once the gpu has completed all + ** currently pending work. + ** + ** note: + ** - we do not enforce pairing of Acquire/Release, so you can (ab)use it to + ** write synchronized signal values... + */ + +static inline void rglGcmFifoGlReleaseSemaphore( rglGcmEnum target, GLuint semaphoreId, GLuint newSemphoreValue ) +{ + rglGcmSemaphoreMemory *semaphores = rglGcmState_i.semaphores; + + switch ( target ) + { + case RGLGCM_SEMAPHORE_USING_GPU: + // let the backend(rop/fb) write the release value + // -- guarantees all reads/writes have completed + GCM_FUNC( cellGcmSetWriteBackEndLabel, semaphoreId, newSemphoreValue ); + break; + case RGLGCM_SEMAPHORE_USING_GPU_NO_WRITE_FLUSH: + // write the semaphore value once host/vb/ib/tex are no longer referencing + // any data prior to the method. + // -- does _NOT_ guarantee that read/writes on the render target surfaces + // have completed (iow: cpu read on the color buffer will be undefined) + + GCM_FUNC( cellGcmSetWriteTextureLabel, semaphoreId, newSemphoreValue ); + break; + case RGLGCM_SEMAPHORE_USING_CPU: + semaphores->userSemaphores[semaphoreId].val = newSemphoreValue; + break; + default: + break; + } +} + +/* lets the gpu/cpu wait until the specific semaphore is equal to the requested + ** semaphore value. + ** + ** note: + ** - we do not enforce pairing of Acquire/Release, so you can (ab)use it to + ** - What about aquire timeouts (after a few seconds) ? + */ +void static inline rglGcmFifoGlAcquireSemaphore( rglGcmEnum target, GLuint semaphoreId, GLuint reqSemphoreValue ) +{ + rglGcmSemaphoreMemory *semaphores = rglGcmState_i.semaphores; + + // pick location + switch ( target ) + { + case RGLGCM_SEMAPHORE_USING_GPU: + // let the frontend aquire the semaphore... + GCM_FUNC( cellGcmSetWaitLabel, semaphoreId, reqSemphoreValue ); + break; + case RGLGCM_SEMAPHORE_USING_CPU: + // lame polling for now... + for ( ;semaphores->userSemaphores[semaphoreId].val != reqSemphoreValue; ) + sys_timer_usleep(10); + break; + default: + break; + } +} + +// Fast conversion for values between 0.0 and 65535.0 +GLuint inline static RGLGCM_QUICK_FLOAT2UINT( const GLfloat f ) +{ + union + { + GLfloat f; + GLuint ui; + } t; + t.f = f + RGLGCM_F0_DOT_0; + return t.ui & 0xffff; +} + +// construct a packed unsigned int ARGB8 color +void inline static RGLGCM_CALC_COLOR_LE_ARGB8( GLuint *color0, const GLfloat r, const GLfloat g, const GLfloat b, const GLfloat a ) +{ + GLuint r2 = RGLGCM_QUICK_FLOAT2UINT( r * 255.0f ); + GLuint g2 = RGLGCM_QUICK_FLOAT2UINT( g * 255.0f ); + GLuint b2 = RGLGCM_QUICK_FLOAT2UINT( b * 255.0f ); + GLuint a2 = RGLGCM_QUICK_FLOAT2UINT( a * 255.0f ); + *color0 = ( a2 << 24 ) | ( r2 << 16 ) | ( g2 << 8 ) | ( b2 << 0 ); +} + +// Wait for the gpu to pass the given fence in the command buffer. +static inline void rglGcmFifoGlFinishFenceRef( const GLuint ref ) +{ + rglGcmFifo *fifo = &rglGcmState_i.fifo; + + // wait for completion + for ( ;; ) + { + // gpu passed reference ? + if ( !rglGcmFifoReferenceInUse( fifo, ref ) ) + break; + + // avoid polling on bus (interrupts memory traffic) + sys_timer_usleep(10); + } +} + +#define RGLGCM_UTIL_LABEL_INDEX 253 + +// Utility to let RSX wait for complete RSX pipeline idle +static inline void rglGcmUtilWaitForIdle() +{ + // set write label command in push buffer, and wait + // NOTE: this is for RSX to wailt + GCM_FUNC( cellGcmSetWriteBackEndLabel, RGLGCM_UTIL_LABEL_INDEX, rglGcmState_i.labelValue ); + GCM_FUNC( cellGcmSetWaitLabel, RGLGCM_UTIL_LABEL_INDEX, rglGcmState_i.labelValue ); + + // increment label value for next time. + rglGcmState_i.labelValue++; + + // make sure the entire pipe in clear not just the front end + // Utility function that does GPU 'finish'. + GCM_FUNC( cellGcmSetWriteBackEndLabel, RGLGCM_UTIL_LABEL_INDEX, + rglGcmState_i.labelValue ); + cellGcmFlush(); + + while( *(cellGcmGetLabelAddress( RGLGCM_UTIL_LABEL_INDEX)) != rglGcmState_i.labelValue) + sys_timer_usleep(30); + + rglGcmState_i.labelValue++; +} + +// Sets the source and destination factor used for blending. +static inline void rglGcmFifoGlBlendFunc( rglGcmEnum sf, rglGcmEnum df, rglGcmEnum sfAlpha, rglGcmEnum dfAlpha ) +{ + // syntax check + switch ( sf ) + { + case RGLGCM_ZERO: + case RGLGCM_ONE: + case RGLGCM_SRC_COLOR: + case RGLGCM_ONE_MINUS_SRC_COLOR: + case RGLGCM_SRC_ALPHA: + case RGLGCM_ONE_MINUS_SRC_ALPHA: + case RGLGCM_DST_ALPHA: + case RGLGCM_ONE_MINUS_DST_ALPHA: + case RGLGCM_DST_COLOR: + case RGLGCM_ONE_MINUS_DST_COLOR: + case RGLGCM_SRC_ALPHA_SATURATE: + case RGLGCM_CONSTANT_COLOR: + case RGLGCM_ONE_MINUS_CONSTANT_COLOR: + case RGLGCM_CONSTANT_ALPHA: + case RGLGCM_ONE_MINUS_CONSTANT_ALPHA: + break; + default: + break; + } + switch ( sfAlpha ) + { + case RGLGCM_ZERO: + case RGLGCM_ONE: + case RGLGCM_SRC_COLOR: + case RGLGCM_ONE_MINUS_SRC_COLOR: + case RGLGCM_SRC_ALPHA: + case RGLGCM_ONE_MINUS_SRC_ALPHA: + case RGLGCM_DST_ALPHA: + case RGLGCM_ONE_MINUS_DST_ALPHA: + case RGLGCM_DST_COLOR: + case RGLGCM_ONE_MINUS_DST_COLOR: + case RGLGCM_SRC_ALPHA_SATURATE: + case RGLGCM_CONSTANT_COLOR: + case RGLGCM_ONE_MINUS_CONSTANT_COLOR: + case RGLGCM_CONSTANT_ALPHA: + case RGLGCM_ONE_MINUS_CONSTANT_ALPHA: + break; + default: + break; + } + + switch ( df ) + { + case RGLGCM_ZERO: + case RGLGCM_ONE: + case RGLGCM_SRC_COLOR: + case RGLGCM_ONE_MINUS_SRC_COLOR: + case RGLGCM_SRC_ALPHA: + case RGLGCM_ONE_MINUS_SRC_ALPHA: + case RGLGCM_DST_ALPHA: + case RGLGCM_ONE_MINUS_DST_ALPHA: + case RGLGCM_DST_COLOR: + case RGLGCM_ONE_MINUS_DST_COLOR: + case RGLGCM_SRC_ALPHA_SATURATE: + case RGLGCM_CONSTANT_COLOR: + case RGLGCM_ONE_MINUS_CONSTANT_COLOR: + case RGLGCM_CONSTANT_ALPHA: + case RGLGCM_ONE_MINUS_CONSTANT_ALPHA: + break; + default: + break; + } + switch ( dfAlpha ) + { + case RGLGCM_ZERO: + case RGLGCM_ONE: + case RGLGCM_SRC_COLOR: + case RGLGCM_ONE_MINUS_SRC_COLOR: + case RGLGCM_SRC_ALPHA: + case RGLGCM_ONE_MINUS_SRC_ALPHA: + case RGLGCM_DST_ALPHA: + case RGLGCM_ONE_MINUS_DST_ALPHA: + case RGLGCM_DST_COLOR: + case RGLGCM_ONE_MINUS_DST_COLOR: + case RGLGCM_SRC_ALPHA_SATURATE: + case RGLGCM_CONSTANT_COLOR: + case RGLGCM_ONE_MINUS_CONSTANT_COLOR: + case RGLGCM_CONSTANT_ALPHA: + case RGLGCM_ONE_MINUS_CONSTANT_ALPHA: + break; + default: + break; + } + + GCM_FUNC( cellGcmSetBlendFunc, sf, df, sfAlpha, dfAlpha ); +} + +// Prints out an int in hexedecimal and binary, broken into bytes. +// Can be used for printing out macro and constant values. +// example: rglPrintIt( RGLGCM_3DCONST(SET_SURFACE_FORMAT, COLOR, LE_A8R8G8B8) ); +// 00 00 00 08 : 00000000 00000000 00000000 00001000 */ +void static inline rglPrintIt( unsigned int v ) +{ + // HEX (space between bytes) + printf( "%02x %02x %02x %02x : ", ( v >> 24 )&0xff, ( v >> 16 )&0xff, ( v >> 8 )&0xff, v&0xff ); + + // BINARY (space between bytes) + for ( unsigned int mask = ( 0x1 << 31 ), i = 1; mask != 0; mask >>= 1, i++ ) + printf( "%d%s", ( v & mask ) ? 1 : 0, ( i % 8 == 0 ) ? " " : "" ); + printf( "\n" ); +} + +// prints the last numWords of the command fifo +void static inline rglPrintFifoFromPut( unsigned int numWords ) +{ + for ( int i = -numWords; i <= -1; i++ ) + rglPrintIt((( uint32_t* )rglGcmState_i.fifo.current )[i] ); +} + +// prints the last numWords of the command fifo +void static inline rglPrintFifoFromGet( unsigned int numWords ) +{ + for ( int i = -numWords; i <= -1; i++ ) + rglPrintIt((( uint32_t* )rglGcmState_i.fifo.lastGetRead )[i] ); +} + +// Determine whether a given location in a command buffer has been passed, by +// using reference markers. +GLboolean static inline rglGcmFifoGlTestFenceRef( const GLuint ref ) +{ + rglGcmFifo *fifo = &rglGcmState_i.fifo; + return rglGcmFifoReferenceInUse( fifo, ref ); +} + +// Add a reference marker to the command buffer to determine whether a location +// in the command buffer has been passed +void static inline rglGcmFifoGlIncFenceRef( GLuint *ref ) +{ + rglGcmFifo *fifo = &rglGcmState_i.fifo; + *ref = rglGcmFifoPutReference( fifo ); +} + +// Flush the current FIFO. +void static inline rglGcmFifoGlFlush( void ) +{ + GCM_FUNC_NO_ARGS( cellGcmSetInvalidateVertexCache ); + rglGcmFifoFlush( &rglGcmState_i.fifo ); +} + +// Set blending constant, used for certain blending modes. +static inline void rglGcmFifoGlBlendColor( GLfloat r, GLfloat g, GLfloat b, GLfloat a ) +{ + rglGcmBlendState *blend = &rglGcmState_i.state.blend; + GLuint hwColor; + + // syntax check + blend->r = r; + blend->g = g; + blend->b = b; + blend->a = a; + + // program hw + switch ( rglGcmState_i.renderTarget.colorFormat ) + { + case RGLGCM_ARGB8: + r = RGLGCM_CLAMPF_01( r ); + g = RGLGCM_CLAMPF_01( g ); + b = RGLGCM_CLAMPF_01( b ); + a = RGLGCM_CLAMPF_01( a ); + RGLGCM_CALC_COLOR_LE_ARGB8( &hwColor, r, g, b, a ); + GCM_FUNC( cellGcmSetBlendColor, hwColor, hwColor ); + break; + case RGLGCM_NONE: + case RGLGCM_FLOAT_R32: + // no native support support + break; + default: + break; + } +} + +// Set the current blend equation. +static inline void rglGcmFifoGlBlendEquation( rglGcmEnum mode, rglGcmEnum modeAlpha ) +{ + // syntax check + switch ( mode ) + { + case RGLGCM_FUNC_ADD: + case RGLGCM_MIN: + case RGLGCM_MAX: + case RGLGCM_FUNC_SUBTRACT: + case RGLGCM_FUNC_REVERSE_SUBTRACT: + break; + default: + break; + } + switch ( modeAlpha ) + { + case RGLGCM_FUNC_ADD: + case RGLGCM_MIN: + case RGLGCM_MAX: + case RGLGCM_FUNC_SUBTRACT: + case RGLGCM_FUNC_REVERSE_SUBTRACT: + break; + default: + break; + } + + GCM_FUNC( cellGcmSetBlendEquation, mode, modeAlpha ); +} + + void static inline rglGcmFifoGlVertexAttribPointer +( + GLuint index, + GLint size, + rglGcmEnum type, + GLboolean normalized, + GLsizei stride, + GLushort frequency, + GLboolean isMain, + GLuint offset + ) +{ + // syntax check + switch ( size ) + { + case 0: // disable + stride = 0; + normalized = 0; + type = RGLGCM_FLOAT; + offset = 0; + break; + case 1: + case 2: + case 3: + case 4: + // valid + break; + default: + break; + } + + // mapping to native types + uint8_t gcmType = 0; + switch ( type ) + { + case RGLGCM_UNSIGNED_BYTE: + if (normalized) + { + gcmType = CELL_GCM_VERTEX_UB; + } + else + { + gcmType = CELL_GCM_VERTEX_UB256; + } + break; + + case RGLGCM_SHORT: + gcmType = normalized ? CELL_GCM_VERTEX_S1 : CELL_GCM_VERTEX_S32K; + break; + + case RGLGCM_FLOAT: + gcmType = CELL_GCM_VERTEX_F; + break; + + case RGLGCM_HALF_FLOAT: + gcmType = CELL_GCM_VERTEX_SF; + break; + + case RGLGCM_CMP: + size = 1; // required for this format + gcmType = CELL_GCM_VERTEX_CMP; + break; + + default: + break; + } + + uint8_t location = CELL_GCM_LOCATION_LOCAL; + + if ( isMain ) + location = CELL_GCM_LOCATION_MAIN; + + GCM_FUNC( cellGcmSetVertexDataArray, index, frequency, stride, size, gcmType, location, offset ); +} + +// set the vertex attribute to the specified value. +void static inline rglGcmFifoGlVertexAttrib4fv( GLuint index, const GLfloat v[4] ) +{ + GCM_FUNC( cellGcmSetVertexData4f, index, v ); +} + +static inline void rglGcmFifoGlClearColor( GLfloat r, GLfloat g, GLfloat b, GLfloat a ) +{ + GCM_FUNC( cellGcmSetClearColor, 0 ); +} + +static inline void rglGcmFifoGlClear( GLbitfield mask ) +{ + GLuint hwMask = 0; + + if ( mask & RGLGCM_COLOR_BUFFER_BIT && rglGcmState_i.renderTarget.colorFormat) + hwMask = CELL_GCM_CLEAR_R | CELL_GCM_CLEAR_G | CELL_GCM_CLEAR_B | CELL_GCM_CLEAR_A; + + if ( hwMask ) + { + GCM_FUNC( cellGcmSetClearSurface, hwMask ); + } +} + +static inline void rglGcmFifoGlEnable( rglGcmEnum cap ) +{ + switch ( cap ) + { + case RGLGCM_BLEND: + GCM_FUNC( cellGcmSetBlendEnable, RGLGCM_TRUE ); + GCM_FUNC( cellGcmSetBlendEnableMrt, RGLGCM_TRUE, RGLGCM_TRUE, RGLGCM_TRUE ); + break; + case RGLGCM_DITHER: + GCM_FUNC( cellGcmSetDitherEnable, RGLGCM_TRUE ); + break; + case RGLGCM_PSHADER_SRGB_REMAPPING: + GCM_FUNC( cellGcmSetFragmentProgramGammaEnable, RGLGCM_TRUE ); + break; + default: + break; + } +} + +static inline void rglGcmFifoGlDisable( rglGcmEnum cap ) +{ + + switch ( cap ) + { + case RGLGCM_BLEND: + GCM_FUNC( cellGcmSetBlendEnable, RGLGCM_FALSE ); + GCM_FUNC( cellGcmSetBlendEnableMrt, RGLGCM_FALSE, RGLGCM_FALSE, RGLGCM_FALSE ); + break; + case RGLGCM_DITHER: + GCM_FUNC( cellGcmSetDitherEnable, RGLGCM_FALSE ); + break; + case RGLGCM_PSHADER_SRGB_REMAPPING: + GCM_FUNC( cellGcmSetFragmentProgramGammaEnable, RGLGCM_FALSE ); + break; + default: + break; + } +} + +static inline void rglFifoGlProgramParameterfvVP( const _CGprogram *program, const CgParameterEntry *parameterEntry, const GLfloat *value ) +{ + const CgParameterResource *parameterResource = rglGetParameterResource( program, parameterEntry ); + if ( parameterResource->resource != ( unsigned short ) - 1 ) + { + switch ( parameterResource->type ) + { + case CG_FLOAT: + case CG_FLOAT1: + case CG_FLOAT2: + case CG_FLOAT3: + case CG_FLOAT4: + GCM_FUNC( cellGcmSetVertexProgramParameterBlock, parameterResource->resource, 1, value ); // GCM_PORT_TESTED [Cedric] + break; + case CG_FLOAT4x4: + // set 4 consts + { + GLfloat v2[16]; + v2[0] = value[0];v2[1] = value[4];v2[2] = value[8];v2[3] = value[12]; + v2[4] = value[1];v2[5] = value[5];v2[6] = value[9];v2[7] = value[13]; + v2[8] = value[2];v2[9] = value[6];v2[10] = value[10];v2[11] = value[14]; + v2[12] = value[3];v2[13] = value[7];v2[14] = value[11];v2[15] = value[15]; + GCM_FUNC( cellGcmSetVertexProgramParameterBlock, parameterResource->resource, 4, v2 ); // GCM_PORT_TESTED [Cedric] + } + break; + case CG_FLOAT3x3: + // set 3 consts + { + GLfloat v2[12]; + v2[0] = value[0];v2[1] = value[3];v2[2] = value[6];v2[3] = 0; + v2[4] = value[1];v2[5] = value[4];v2[6] = value[7];v2[7] = 0; + v2[8] = value[2];v2[9] = value[5];v2[10] = value[8];v2[11] = 0; + GCM_FUNC( cellGcmSetVertexProgramParameterBlock, parameterResource->resource, 3, v2 ); + } + break; + case CG_HALF: + case CG_HALF1: + case CG_HALF2: + case CG_HALF3: + case CG_HALF4: + case CG_INT: + case CG_INT1: + case CG_INT2: + case CG_INT3: + case CG_INT4: + case CG_BOOL: + case CG_BOOL1: + case CG_BOOL2: + case CG_BOOL3: + case CG_BOOL4: + case CG_FIXED: + case CG_FIXED1: + case CG_FIXED2: + case CG_FIXED3: + case CG_FIXED4: + GCM_FUNC( cellGcmSetVertexProgramParameterBlock, parameterResource->resource, 1, value ); // GCM_PORT_TESTED [Cedric] + break; + case CG_HALF4x4: + case CG_INT4x4: + case CG_BOOL4x4: + case CG_FIXED4x4: + // set 4 consts + { + GLfloat v2[16]; + v2[0] = value[0];v2[1] = value[4];v2[2] = value[8];v2[3] = value[12]; + v2[4] = value[1];v2[5] = value[5];v2[6] = value[9];v2[7] = value[13]; + v2[8] = value[2];v2[9] = value[6];v2[10] = value[10];v2[11] = value[14]; + v2[12] = value[3];v2[13] = value[7];v2[14] = value[11];v2[15] = value[15]; + GCM_FUNC( cellGcmSetVertexProgramParameterBlock, parameterResource->resource, 4, v2 ); // GCM_PORT_TESTED [Cedric] + } + break; + case CG_HALF3x3: + case CG_INT3x3: + case CG_BOOL3x3: + case CG_FIXED3x3: + // set 3 consts + { + GLfloat v2[12]; + v2[0] = value[0];v2[1] = value[3];v2[2] = value[6];v2[3] = 0; + v2[4] = value[1];v2[5] = value[4];v2[6] = value[7];v2[7] = 0; + v2[8] = value[2];v2[9] = value[5];v2[10] = value[8];v2[11] = 0; + GCM_FUNC( cellGcmSetVertexProgramParameterBlock, parameterResource->resource, 3, v2 ); + } + break; + default: + break; + } + } +} + +// Push a CG program onto the current command buffer +static inline void rglGcmPushProgramPushBuffer( _CGprogram * cgprog ) +{ + // make sure there is space for the pushbuffer + any nops we need to add for alignment + rglGcmFifoWaitForFreeSpace( &rglGcmState_i.fifo, cgprog->constantPushBufferWordSize + 4 + 32); + // first add nops to get us the next alligned position in the fifo + // [YLIN] Use VMX register to copy + uint32_t padding_in_word = ( ( 0x10-(((uint32_t)rglGcmState_i.fifo.current)&0xf))&0xf )>>2; + uint32_t padded_size = ( ((cgprog->constantPushBufferWordSize)<<2) + 0xf )&~0xf; + GCM_FUNC( cellGcmSetNopCommandUnsafe, padding_in_word ); + memcpy16(rglGcmState_i.fifo.current, cgprog->constantPushBuffer, padded_size); + rglGcmState_i.fifo.current+=cgprog->constantPushBufferWordSize; + +} + +// Look up the memory location of a buffer object (VBO, PBO) +static inline GLuint rglGcmGetBufferObjectOrigin( GLuint buffer ) +{ + rglBufferObject *bufferObject = (rglBufferObject*)_CurrentContext->bufferObjectNameSpace.data[buffer]; + rglGcmBufferObject *gcmBuffer = ( rglGcmBufferObject * ) & bufferObject->platformBufferObject; + return gcmBuffer->bufferId; +} + +static inline rglGcmDriver *rglGetGcmDriver(void) +{ + return ( rglGcmDriver * )( _CurrentDevice->rasterDriver ); +} + diff --git a/console/rgl/src/ps3/include/rgl-typedefs.h b/console/rgl/src/ps3/include/rgl-typedefs.h new file mode 100644 index 0000000000..8b16c9444a --- /dev/null +++ b/console/rgl/src/ps3/include/rgl-typedefs.h @@ -0,0 +1,490 @@ +#include "../../../include/export/RGL/rgl.h" +#include "../../../include/RGL/Types.h" + +using namespace cell::Gcm; + +typedef struct _tagMODESTRUC +{ + GLushort wHorizVisible; + GLushort wVertVisible; + GLushort wInterlacedMode; + GLushort wRefresh; + GLushort wHorizTotal; + GLushort wHorizBlankStart; + GLushort wHorizSyncStart; + GLushort wHorizSyncEnd; + GLushort wHorizBlankEnd; + GLushort wVertTotal; + GLushort wVertBlankStart; + GLushort wVertSyncStart; + GLushort wVertSyncEnd; + GLushort wVertBlankEnd; + GLuint dwDotClock; // In 10K Hertz + GLushort wHSyncPolarity; + GLushort wVSyncPolarity; +} MODESTRUC; + +// descriptor for 2D data +typedef struct +{ + GLenum source; // device, texture, renderbuffer + GLuint width, height; + GLuint bpp; // bytes per pixel, derived from format + GLuint pitch; // 0 if swizzled + + rglGcmEnum format; // e.g. RGLGCM_ARGB8 + + GLenum pool; // type of memory + + char* ppuData; // generic EA that's not RSX mem + + GLuint dataId; // id to get address and offset + GLuint dataIdOffset; +} rglGcmSurface; + +// gleSetRenderTarget has enough arguments to define its own struct +typedef struct rglGcmRenderTargetEx rglGcmRenderTargetEx; +struct rglGcmRenderTargetEx +{ + // color buffers + rglGcmEnum colorFormat; + GLuint colorBufferCount; + + GLuint colorId[RGLGCM_SETRENDERTARGET_MAXCOUNT]; + GLuint colorIdOffset[RGLGCM_SETRENDERTARGET_MAXCOUNT]; + GLuint colorPitch[RGLGCM_SETRENDERTARGET_MAXCOUNT]; + + // (0,0) is in the lower left + GLboolean yInverted; + + // window offset + GLuint xOffset; + GLuint yOffset; + + // render dimensions + GLuint width; + GLuint height; +}; + +typedef struct +{ + // TODO: get rid of this member + rglGcmRenderTargetEx rt; + // framebuffers + rglGcmSurface color[3]; + // double/triple buffering management + GLuint drawBuffer; // 0, 1, or 2 + GLuint scanBuffer; // 0, 1, or 2 + // resc buffers (maintain pointers for freeing in rglPlatformDestroyDevice) + GLuint RescColorBuffersId; + GLuint RescVertexArrayId; + GLuint RescFragmentShaderId; + const MODESTRUC *ms; + GLboolean vsync; + GLboolean skipFirstVsync; + GLenum deviceType; + GLenum TVStandard; + GLenum TVFormat; + GLuint swapFifoRef; + GLuint swapFifoRef2; // Added for supporting Triple buffering [RSTENSON] + GLboolean setOffset; + GLboolean signal; + GLuint semaValue; + unsigned int syncMethod; +} rglGcmDevice; + +typedef struct rglGcmDriver_ +{ + rglGcmRenderTargetEx rt; + GLboolean rtValid; + GLboolean invalidateVertexCache; + int xSuperSampling; // supersampling factor in X + int ySuperSampling; // supersampling factor in Y + + GLuint flushBufferCount; // # of mapped buffer objects in bounce buffer + + GLuint fpLoadProgramId; // address of the currently bound fragment program + GLuint fpLoadProgramOffset; + + GLuint sharedFPConstantsId; + char *sharedVPConstants; +} rglGcmDriver; + +struct rglPlatformFramebuffer: public rglFramebuffer +{ + rglGcmRenderTargetEx rt; + GLboolean complete; + rglPlatformFramebuffer(): rglFramebuffer() + { + memset( &rt, 0, sizeof( rt ) ); + }; + virtual ~rglPlatformFramebuffer() {}; + void validate( PSGLcontext *LContext ); +}; + +typedef struct +{ + GLuint SET_TEXTURE_CONTROL3; // pitch and depth + GLuint SET_TEXTURE_OFFSET; // gpu addr (from dma ctx) + GLuint SET_TEXTURE_FORMAT; // which dma ctx, [123]D, border source, mem layout, mip levels + GLuint SET_TEXTURE_ADDRESS; // wrap, signed and unsigned remap control, gamma, zfunc + GLuint SET_TEXTURE_CONTROL0; // enable, lod clamp, aniso, image field, alpha kill, colorkey + GLuint SET_TEXTURE_CONTROL1; // remap and crossbar setup. + GLuint SET_TEXTURE_FILTER; // lod bias, convol filter, min/mag filter, component signedness + GLuint SET_TEXTURE_IMAGE_RECT; // texture width/height +} rglGcmTextureMethods; + +// Gcm Specific function parameter mappings. +// for cellGcmSetControl +struct rglGcmTextureControl0 +{ + GLuint minLOD; + GLuint maxLOD; + GLuint maxAniso; +}; + +// for cellGcmSetAddress +struct rglGcmTextureAddress +{ + GLuint wrapS; + GLuint wrapT; + GLuint wrapR; + GLuint unsignedRemap; + GLuint zfunc; + GLuint gamma; +}; + +// for cellGcmSetTextureFilter +struct rglGcmTextureFilter +{ + GLuint min; + GLuint mag; + GLuint conv; + GLint bias; +}; + +// Structure to contain Gcm Function Parameters for setting later. +// Control1 and Control3 will be set by cellGcmSetTexture +struct rglGcmTextureMethodParams +{ + rglGcmTextureControl0 control0; + rglGcmTextureAddress address; + rglGcmTextureFilter filter; + GLuint borderColor; // texture border color +}; + +typedef struct +{ + // These are enough to describe the GPU format + GLuint faces; + GLuint levels; + GLuint baseWidth; + GLuint baseHeight; + GLuint baseDepth; + rglGcmEnum internalFormat; + GLuint pixelBits; + GLuint pitch; +} rglGcmTextureLayout; + +// GCM texture data structure +typedef struct +{ + GLenum pool; + rglGcmTextureMethods methods; // [RSTENSON] soon to be legacy + rglGcmTextureMethodParams gcmMethods; + CellGcmTexture gcmTexture; + GLuint gpuAddressId; + GLuint gpuAddressIdOffset; + GLuint gpuSize; + rglGcmTextureLayout gpuLayout; +} rglGcmTexture; + +/* pio flow control data structure */ +typedef volatile struct +{ + GLuint Ignored00[0x010]; + GLuint Put; /* put offset, write only 0040-0043*/ + GLuint Get; /* get offset, read only 0044-0047*/ + GLuint Reference; /* reference value, read only 0048-004b*/ + GLuint Ignored01[0x1]; + GLuint SetReference; /* set reference value 0050-0053*/ + GLuint TopLevelGet; /* top level get offset, read only 0054-0057*/ + GLuint Ignored02[0x2]; + GLuint SetContextDmaSemaphore; /* set sema ctxdma, write only 0060-0063*/ + GLuint SetSemaphoreOffset; /* set sema offset, write only 0064-0067*/ + GLuint SetSemaphoreAcquire; /* set sema acquire, write only 0068-006b*/ + GLuint SetSemaphoreRelease; /* set sema release, write only 006c-006f*/ + GLuint Ignored03[0x7e4]; +} rglGcmControlDma; + +// all fifo related data is kept here +struct rglGcmFifo: public CellGcmContextData +{ + // dmaControl for allocated channel + rglGcmControlDma *dmaControl; + + // for storing the start of the push buffer + // begin will be moving around + uint32_t *dmaPushBufferBegin; + uint32_t *dmaPushBufferEnd; + + // Fifo block size + GLuint fifoBlockSize; + + // pushbuffer location etc. + // members around here were moved up + unsigned long dmaPushBufferOffset; + GLuint dmaPushBufferSizeInWords; + + // the last Put value we wrote + uint32_t *lastPutWritten; + + // the last Get value we know of + uint32_t *lastGetRead; + + // cached value of last reference write + GLuint lastSWReferenceWritten; + + // cached value of lastSWReferenceWritten at most + // recent fifo flush + GLuint lastSWReferenceFlushed; + + // cached value of last reference read + GLuint lastHWReferenceRead; + uint32_t *dmaPushBufferGPU; + int spuid; + + public: + inline void updateLastGetRead() + { + uint32_t* tmp = (uint32_t*)(( char* )dmaPushBufferBegin - dmaPushBufferOffset + ( *(( volatile GLuint* ) & dmaControl->Get ) ) ); + // _only_ update lastGetRead if the Get is in our pushbuffer + if (( tmp >= begin ) && ( tmp <= end ) ) lastGetRead = tmp; + } +}; + +typedef volatile struct +{ + struct + { + GLuint nanoseconds[2]; /* nanoseconds since Jan. 1, 1970 0- 7*/ + } + timeStamp; /* -0007*/ + GLuint value; /* info returned depends on method 0008-000b*/ + GLuint zero; /* always written to zero 000c-000f*/ +} +rglGcmGetReport; + +/* memory data structures */ +typedef volatile struct +{ + struct + { /* 0000- */ + GLuint nanoseconds[2]; /* nanoseconds since Jan. 1, 1970 0- 7*/ + } + timeStamp; /* -0007*/ + GLuint info32; /* info returned depends on method 0008-000b*/ + GLushort info16; /* info returned depends on method 000c-000d*/ + GLushort status; /* user sets bit 15, NV sets status 000e-000f*/ +} +rglGcmNotification; + + +// notifiers in host memory +struct rglGcmHostNotifierMemory +{ + // signals channel errors + rglGcmNotification channelDmaError[2]; +}; + + +// 16 byte aligned semaphores +struct rglGcmSemaphore +{ + GLuint val; + GLuint pad0; + GLuint pad1; + GLuint pad2; +}; + +// semaphore storage +struct rglGcmSemaphoreMemory +{ + rglGcmSemaphore userSemaphores[RGLGCM_MAX_USER_SEMAPHORES]; +}; + +struct rglGcmResource +{ + char *localAddress; + GLuint localSize; + GLuint MemoryClock; + GLuint GraphicsClock; + + unsigned long long ioifMappings[32]; + + char * linearMemory; + unsigned int persistentMemorySize; + + // host memory window the gpu can access + char * hostMemoryBase; + GLuint hostMemorySize; + GLuint hostMemoryReserved; + + // offset of dmaPushBuffer relative to its DMA CONTEXT + unsigned long dmaPushBufferOffset; + char * dmaPushBuffer; + GLuint dmaPushBufferSize; + void* dmaControl; + + // all kind of notifers + rglGcmHostNotifierMemory *hostNotifierBuffer; + + // semaphores + rglGcmSemaphoreMemory *semaphores; +}; + +typedef struct +{ + GLuint fence; +} +rglGcmFenceObject; + +typedef struct +{ + GLint sema; // NV semaphore index +} +rglGcmEventObject; + + +typedef struct +{ + GLenum pool; // LINEAR, SYSTEM, or NONE + unsigned int bufferId; // allocated Id + unsigned int bufferSize; + unsigned int pitch; + + GLuint mapCount; // map reference count + GLenum mapAccess; // READ_ONLY, WRITE_ONLY, or READ_WRITE +} +rglGcmBufferObject; + +typedef struct rglGcmShader_ +{ + GLuint loadAddressId; + CgBinaryProgram __attribute__(( aligned( 16 ) ) ) program; +} rglGcmShader; + +// the current rendering surface/target +typedef struct rglGcmRenderTarget rglGcmRenderTarget; + +struct rglGcmRenderTarget +{ + GLuint colorFormat; + GLuint colorBufferCount; + + // (0,0) is in the lower left + GLuint yInverted; + + // gcm render target structure [RSTENSON] + CellGcmSurface gcmRenderTarget; +}; + +// cached state: texture +typedef struct rglGcmTextureState rglGcmTextureState; + +struct rglGcmTextureState +{ + // unforunately to many pieces of state have been put into single + // 32bit registers -- so we need to cache some of them... + GLuint hwTexAddress; + GLuint hwTexFilter; + GLuint hwTexControl0; + //GLuint hwTexCoordCtrl; + +}; + +// cached state: viewport +typedef struct rglGcmViewportState rglGcmViewportState; +struct rglGcmViewportState +{ + // user values given as input to glViewport + GLint x, y, w, h; + // from glViewport + GLfloat xScale, xCenter; + GLfloat yScale, yCenter; +}; + +// cached state: blend +typedef struct rglGcmBlendState rglGcmBlendState; +struct rglGcmBlendState +{ + // current blend color + GLfloat r, g, b, a; + + // alpha blend reference + GLuint alphaFunc; + GLfloat alphaRef; +}; + +typedef struct rglGcmInterpolantState rglGcmInterpolantState; +struct rglGcmInterpolantState +{ + // mask of inputs used by programs + // Uses bits from SET_VERTEX_ATTRIB_OUTPUT_MASK. + GLuint vertexProgramAttribMask; + GLuint fragmentProgramAttribMask; +}; + +// cached state (because no dedecated method exist) +typedef struct rglGcmCachedState rglGcmCachedState; +struct rglGcmCachedState +{ + // our hw<->ogl mapping is ...let's say strange... + //rglGcmTextureState tex[RGLGCM_MAX_TEXIMAGE_COUNT]; + //[RSTENSON] Removing this above. Texturing is all GCM now. + + // we need to track blending color, too + rglGcmBlendState blend; + + // need to cache viewport values, because of yInverted + rglGcmViewportState viewport; + + // all interpolants are enabled/disabled with a single mask + rglGcmInterpolantState interpolant; +}; + +// ** the master instance representing a channel/context ** +struct rglGcmState +{ + char *localAddress; + + // host memory window the gpu can access + void *hostMemoryBase; + GLuint hostMemorySize; + + // all kind of notifers + rglGcmHostNotifierMemory *hostNotifierBuffer; + + + // semaphores + rglGcmSemaphoreMemory *semaphores; + + // -- context state -- + + // fifo + rglGcmFifo fifo; + + // rendering target + rglGcmRenderTarget renderTarget; + + // state + rglGcmCachedState state; + + // Cell Gcm Config + CellGcmConfig config; + + // to use as the back end label value when syncing before cellGcmSetTile, SetZCull, and SetInvalidateTile. + GLuint labelValue; +}; + +extern rglGcmState rglGcmState_i; diff --git a/console/rgl/src/ps3/rgl_ps3.cpp b/console/rgl/src/ps3/rgl_ps3.cpp new file mode 100644 index 0000000000..f4b4ddff59 --- /dev/null +++ b/console/rgl/src/ps3/rgl_ps3.cpp @@ -0,0 +1,3496 @@ +/* RetroArch - A frontend for libretro. + * RGL - An OpenGL subset wrapper library. + * Copyright (C) 2010-2012 - Hans-Kristian Arntzen + * Copyright (C) 2011-2012 - Daniel De Matteis + * + * RetroArch 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 Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch 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 RetroArch. + * If not, see . + */ + +#include "../rgl.h" + +#include + +#include "include/GmmAlloc.h" +#include "include/rgl-constants.h" +#include "include/rgl-typedefs.h" +#include "include/rgl-externs.h" +#include "include/rgl-inline.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +using namespace cell::Gcm; + +static GLuint nvFenceCounter = 0; + +// the global instance of the rglGcmState_i structure +rglGcmState rglGcmState_i; + +/*============================================================ + MEMORY MANAGER + ============================================================ */ + +static GmmAllocator *pGmmLocalAllocator = NULL; +static volatile uint32_t *pLock = NULL; +static uint32_t cachedLockValue = 0; +static uint8_t pinAllocations = 0; +static GmmFixedAllocData *pGmmFixedAllocData = NULL; + +static inline uint32_t pad(uint32_t x, uint32_t pad) +{ + return ( x + pad - 1 ) / pad * pad; +} + +static inline uint32_t gmmAddressToOffset(uint32_t address) +{ + return address - pGmmLocalAllocator->memoryBase; +} + +static uint32_t gmmInitFixedAllocator(void) +{ + + pGmmFixedAllocData = (GmmFixedAllocData *)malloc(sizeof(GmmFixedAllocData)); + + if (pGmmFixedAllocData == NULL) + return GMM_ERROR; + + memset(pGmmFixedAllocData, 0, sizeof(GmmFixedAllocData)); + + for (int i=0; i<2; i++) + { + int blockCount = (i==0) ? GMM_BLOCK_COUNT : GMM_TILE_BLOCK_COUNT; + int blockSize = (i==0) ? sizeof(GmmBlock): sizeof(GmmTileBlock); + + pGmmFixedAllocData->ppBlockList[i] = (char **)malloc(sizeof(char *)); + if (pGmmFixedAllocData->ppBlockList[i] == NULL) + return GMM_ERROR; + + pGmmFixedAllocData->ppBlockList[i][0] = (char *)malloc(blockSize * blockCount); + if (pGmmFixedAllocData->ppBlockList[i][0] == NULL) + return GMM_ERROR; + + pGmmFixedAllocData->ppFreeBlockList[i] = (uint16_t **)malloc(sizeof(uint16_t *)); + if (pGmmFixedAllocData->ppFreeBlockList[i] == NULL) + return GMM_ERROR; + + pGmmFixedAllocData->ppFreeBlockList[i][0] = (uint16_t *)malloc(sizeof(uint16_t) * blockCount); + if (pGmmFixedAllocData->ppFreeBlockList[i][0] == NULL) + return GMM_ERROR; + + pGmmFixedAllocData->pBlocksUsed[i] = (uint16_t *)malloc(sizeof(uint16_t)); + if (pGmmFixedAllocData->pBlocksUsed[i] == NULL) + return GMM_ERROR; + + for (int j=0; jppFreeBlockList[i][0][j] = j; + + pGmmFixedAllocData->pBlocksUsed[i][0] = 0; + pGmmFixedAllocData->BlockListCount[i] = 1; + } + + return CELL_OK; +} + +static void *gmmAllocFixed(uint8_t isTile) +{ + int blockCount = isTile ? GMM_TILE_BLOCK_COUNT : GMM_BLOCK_COUNT; + int blockSize = isTile ? sizeof(GmmTileBlock) : sizeof(GmmBlock); + int listCount = pGmmFixedAllocData->BlockListCount[isTile]; + + for (int i=0; ipBlocksUsed[isTile][i] < blockCount) + { + return pGmmFixedAllocData->ppBlockList[isTile][i] + + (pGmmFixedAllocData->ppFreeBlockList[isTile][i][pGmmFixedAllocData->pBlocksUsed[isTile][i]++] * + blockSize); + } + } + + char **ppBlockList = + (char **)realloc(pGmmFixedAllocData->ppBlockList[isTile], + (listCount + 1) * sizeof(char *)); + + if (ppBlockList == NULL) + return NULL; + + pGmmFixedAllocData->ppBlockList[isTile] = ppBlockList; + + pGmmFixedAllocData->ppBlockList[isTile][listCount] = + (char *)malloc(blockSize * blockCount); + + if (pGmmFixedAllocData->ppBlockList[isTile][listCount] == NULL) + return NULL; + + uint16_t **ppFreeBlockList = + (uint16_t **)realloc(pGmmFixedAllocData->ppFreeBlockList[isTile], + (listCount + 1) * sizeof(uint16_t *)); + + if (ppFreeBlockList == NULL) + return NULL; + + pGmmFixedAllocData->ppFreeBlockList[isTile] = ppFreeBlockList; + + pGmmFixedAllocData->ppFreeBlockList[isTile][listCount] = + (uint16_t *)malloc(sizeof(uint16_t) * blockCount); + + if (pGmmFixedAllocData->ppFreeBlockList[isTile][listCount] == NULL) + return NULL; + + uint16_t *pBlocksUsed = + (uint16_t *)realloc(pGmmFixedAllocData->pBlocksUsed[isTile], + (listCount + 1) * sizeof(uint16_t)); + + if (pBlocksUsed == NULL) + return NULL; + + pGmmFixedAllocData->pBlocksUsed[isTile] = pBlocksUsed; + + for (int i=0; ippFreeBlockList[isTile][listCount][i] = i; + + pGmmFixedAllocData->pBlocksUsed[isTile][listCount] = 0; + pGmmFixedAllocData->BlockListCount[isTile]++; + + return pGmmFixedAllocData->ppBlockList[isTile][listCount] + + (pGmmFixedAllocData->ppFreeBlockList[isTile][listCount][pGmmFixedAllocData->pBlocksUsed[isTile][listCount]++] * + blockSize); +} + +static void gmmFreeFixed(uint8_t isTile, void *pBlock) +{ + int blockCount = isTile ? GMM_TILE_BLOCK_COUNT : GMM_BLOCK_COUNT; + int blockSize = isTile ? sizeof(GmmTileBlock) : sizeof(GmmBlock); + uint8_t found = 0; + + for (int i=0; iBlockListCount[isTile]; i++) + { + if (pBlock >= pGmmFixedAllocData->ppBlockList[isTile][i] && + pBlock < (pGmmFixedAllocData->ppBlockList[isTile][i] + blockSize * blockCount)) + { + int index = ((char *)pBlock - pGmmFixedAllocData->ppBlockList[isTile][i]) / blockSize; + pGmmFixedAllocData->ppFreeBlockList[isTile][i][--pGmmFixedAllocData->pBlocksUsed[isTile][i]] = index; + found = 1; + } + } +} + +static void gmmDestroyFixedAllocator() +{ + if (pGmmFixedAllocData) + { + for (int i=0; i<2; i++) + { + for(int j=0; jBlockListCount[i]; j++) + { + free(pGmmFixedAllocData->ppBlockList[i][j]); + free(pGmmFixedAllocData->ppFreeBlockList[i][j]); + } + free(pGmmFixedAllocData->ppBlockList[i]); + free(pGmmFixedAllocData->ppFreeBlockList[i]); + free(pGmmFixedAllocData->pBlocksUsed[i]); + } + + free(pGmmFixedAllocData); + pGmmFixedAllocData = NULL; + } +} + +static GmmBlock *gmmAllocFixedBlock() +{ + return (GmmBlock *)gmmAllocFixed(0); +} + +static void gmmFreeFixedBlock(GmmBlock *pBlock) +{ + gmmFreeFixed(0, pBlock); +} + +static GmmTileBlock *gmmAllocFixedTileBlock() +{ + return (GmmTileBlock *)gmmAllocFixed(1); +} + +static void gmmFreeFixedTileBlock(GmmTileBlock *pTileBlock) +{ + gmmFreeFixed(1, pTileBlock); +} + +void gmmPinAllocations() +{ + pinAllocations = 1; +} + +void gmmUnpinAllocations() +{ + pinAllocations = 0; +} + +uint32_t gmmInit( + const void *localMemoryBase, + const void *localStartAddress, + const uint32_t localSize, + const void *mainMemoryBase, + const void *mainStartAddress, + const uint32_t mainSize + ) +{ + GmmAllocator *pAllocator; + uint32_t alignedLocalSize, alignedMainSize; + uint32_t localEndAddress = (uint32_t)localStartAddress + localSize; + uint32_t mainEndAddress = (uint32_t)mainStartAddress + mainSize; + + localEndAddress = (localEndAddress / GMM_TILE_ALIGNMENT) * GMM_TILE_ALIGNMENT; + mainEndAddress = (mainEndAddress / GMM_TILE_ALIGNMENT) * GMM_TILE_ALIGNMENT; + + alignedLocalSize = localEndAddress - (uint32_t)localStartAddress; + alignedMainSize = mainEndAddress - (uint32_t)mainStartAddress; + + pAllocator = (GmmAllocator *)malloc(2*sizeof(GmmAllocator)); + + if (pAllocator == NULL) + return GMM_ERROR; + + memset(pAllocator, 0, 1 * sizeof(GmmAllocator)); + + if (pAllocator) + { + pAllocator->memoryBase = (uint32_t)localMemoryBase; + pAllocator->startAddress = (uint32_t)localStartAddress; + pAllocator->size = alignedLocalSize; + pAllocator->freeAddress = pAllocator->startAddress; + pAllocator->tileStartAddress = ((uint32_t)localStartAddress) + alignedLocalSize; + pAllocator->totalSize = alignedLocalSize; + + pGmmLocalAllocator = pAllocator; + } + else + return GMM_ERROR; + + pLock = cellGcmGetLabelAddress(GMM_PPU_WAIT_INDEX); + *pLock = 0; + cachedLockValue = 0; + + return gmmInitFixedAllocator(); +} + +static inline void gmmWaitForSweep() +{ + do + { + if (cachedLockValue == 0) + break; + + cachedLockValue = *pLock; + + if (cachedLockValue == 0) + break; + + sys_timer_usleep(30); + }while(1); +} + +uint32_t gmmDestroy() +{ + GmmBlock *pBlock, *pTmpBlock; + GmmTileBlock *pTileBlock, *pTmpTileBlock; + GmmAllocator *pAllocator; + + pAllocator = pGmmLocalAllocator; + + { + if (pAllocator) + { + pBlock = pAllocator->pHead; + + while (pBlock) + { + pTmpBlock = pBlock; + pBlock = pBlock->pNext; + gmmFreeFixedBlock(pTmpBlock); + } + + pTileBlock = pAllocator->pTileHead; + + while (pTileBlock) + { + pTmpTileBlock = pTileBlock; + pTileBlock = pTileBlock->pNext; + gmmFreeFixedTileBlock(pTmpTileBlock); + } + + free(pAllocator); + } + } + + pGmmLocalAllocator = NULL; + + gmmDestroyFixedAllocator(); + + return CELL_OK; +} + +uint32_t gmmGetBlockSize(const uint32_t id) +{ + return ((GmmBaseBlock *)id)->size; +} + +void *gmmGetTileData(const uint32_t id) +{ + return ((GmmTileBlock *)id)->pData; +} + +void gmmSetTileAttrib(const uint32_t id, const uint32_t tag, + void *pData) +{ + GmmTileBlock *pTileBlock = (GmmTileBlock *)id; + + pTileBlock->tileTag = tag; + pTileBlock->pData = pData; +} + +uint32_t gmmIdToOffset(const uint32_t id) +{ + GmmBaseBlock *pBaseBlock = (GmmBaseBlock *)id; + uint32_t offset; + + if (!pBaseBlock->isTile && pinAllocations) + { + GmmBlock *pBlock = (GmmBlock *)id; + pBlock->isPinned = pinAllocations; + } + + offset = gmmAddressToOffset(pBaseBlock->address); + + return offset; +} + +char *gmmIdToAddress( + const uint32_t id + ) +{ + GmmBaseBlock *pBaseBlock = (GmmBaseBlock *)id; + + gmmWaitForSweep(); + + return (char *)pBaseBlock->address; +} + +void gmmPinId(const uint32_t id) +{ + GmmBaseBlock *pBaseBlock = (GmmBaseBlock *)id; + + if (!pBaseBlock->isTile) + { + GmmBlock *pBlock = (GmmBlock *)id; + + pBlock->isPinned = 1; + } +} + +void gmmUnpinId(const uint32_t id) +{ + GmmBaseBlock *pBaseBlock = (GmmBaseBlock *)id; + + if (!pBaseBlock->isTile) + { + GmmBlock *pBlock = (GmmBlock *)id; + + pBlock->isPinned = 0; + } +} + +static GmmBlock *gmmAllocBlock( + GmmAllocator *pAllocator, + uint32_t size + ) +{ + uint32_t address; + GmmBlock *pNewBlock = NULL; + GmmBlock *pBlock = pAllocator->pTail; + + address = pAllocator->freeAddress; + + if (UINT_MAX - address >= size && + address + size <= pAllocator->startAddress + pAllocator->size) + { + pNewBlock = gmmAllocFixedBlock(); + if (pNewBlock == NULL) + { + return NULL; + } + + memset(pNewBlock, 0, sizeof(GmmBlock)); + + pNewBlock->base.address = address; + pNewBlock->base.size = size; + pAllocator->freeAddress = address + size; + + if (pBlock) + { + pNewBlock->pPrev = pBlock; + pBlock->pNext = pNewBlock; + pAllocator->pTail = pNewBlock; + } + else + { + pAllocator->pHead = pNewBlock; + pAllocator->pTail = pNewBlock; + } + } + + return pNewBlock; +} + +static GmmTileBlock *gmmFindFreeTileBlock( + GmmAllocator *pAllocator, + const uint32_t size + ) +{ + GmmTileBlock *pBlock = pAllocator->pTileHead; + GmmTileBlock *pBestAfterBlock = NULL; + GmmTileBlock *pNewBlock = NULL; + uint32_t bestSize = 0; + uint32_t freeSize = 0; + + while (pBlock && pBlock->pNext) + { + freeSize = pBlock->pNext->base.address - pBlock->base.address - pBlock->base.size; + + if (freeSize >= size && + (pBestAfterBlock == NULL || freeSize < bestSize) && + (pBlock->pNext == NULL || + pBlock->pData != pBlock->pNext->pData)) + { + pBestAfterBlock = pBlock; + bestSize = freeSize; + } + + pBlock = pBlock->pNext; + } + + if (pBestAfterBlock) + { + pNewBlock = gmmAllocFixedTileBlock(); + if (pNewBlock == NULL) + return NULL; + + memset(pNewBlock, 0, sizeof(GmmTileBlock)); + + pNewBlock->base.address = pBestAfterBlock->base.address + pBestAfterBlock->base.size; + pNewBlock->base.isTile = 1; + pNewBlock->base.size = size; + + pNewBlock->pNext = pBestAfterBlock->pNext; + pNewBlock->pPrev = pBestAfterBlock; + pNewBlock->pPrev->pNext = pNewBlock; + pNewBlock->pNext->pPrev = pNewBlock; + + return pNewBlock; + } + else + return NULL; +} + +static GmmTileBlock *gmmCreateTileBlock( + GmmAllocator *pAllocator, + const uint32_t size + ) +{ + GmmTileBlock *pNewBlock; + uint32_t address; + + address = pAllocator->tileStartAddress - size; + + if (address > pAllocator->startAddress + pAllocator->size) + return NULL; + + if (pAllocator->pTail && + pAllocator->pTail->base.address + pAllocator->pTail->base.size > address) + return NULL; + + pAllocator->size = address - pAllocator->startAddress; + pAllocator->tileSize = pAllocator->tileStartAddress + pAllocator->tileSize - address; + pAllocator->tileStartAddress = address; + + pNewBlock = gmmAllocFixedTileBlock(); + if (pNewBlock == NULL) + return NULL; + + memset(pNewBlock, 0, sizeof(GmmTileBlock)); + + pNewBlock->base.address = address; + pNewBlock->base.isTile = 1; + pNewBlock->base.size = size; + pNewBlock->pNext = pAllocator->pTileHead; + + if (pAllocator->pTileHead) + { + pAllocator->pTileHead->pPrev = pNewBlock; + pAllocator->pTileHead = pNewBlock; + } + else + { + pAllocator->pTileHead = pNewBlock; + pAllocator->pTileTail = pNewBlock; + } + + return pNewBlock; +} + +static void gmmFreeTileBlock( + GmmTileBlock *pTileBlock + ) +{ + GmmAllocator *pAllocator; + + if (pTileBlock->pPrev) + pTileBlock->pPrev->pNext = pTileBlock->pNext; + + if (pTileBlock->pNext) + pTileBlock->pNext->pPrev = pTileBlock->pPrev; + + pAllocator = pGmmLocalAllocator; + + if (pAllocator->pTileHead == pTileBlock) + { + pAllocator->pTileHead = pTileBlock->pNext; + + if (pAllocator->pTileHead) + pAllocator->pTileHead->pPrev = NULL; + + uint32_t prevSize; + prevSize = pAllocator->size; + pAllocator->size = pAllocator->pTileHead ? + pAllocator->pTileHead->base.address - pAllocator->startAddress : + pAllocator->totalSize; + pAllocator->tileSize = pAllocator->totalSize - pAllocator->size; + pAllocator->tileStartAddress = pAllocator->pTileHead ? + pAllocator->pTileHead->base.address : + pAllocator->startAddress + pAllocator->size; + } + + if (pAllocator->pTileTail == pTileBlock) + { + pAllocator->pTileTail = pTileBlock->pPrev; + + if (pAllocator->pTileTail) + pAllocator->pTileTail->pNext = NULL; + } + + gmmFreeFixedTileBlock(pTileBlock); +} + +uint32_t gmmAllocExtendedTileBlock( + const uint8_t location, + const uint32_t size, + const uint32_t tag + ) +{ + GmmAllocator *pAllocator; + uint32_t retId = 0; + uint32_t newSize; + uint8_t resizeSucceed = 1; + + + pAllocator = pGmmLocalAllocator; + + + newSize = pad(size, GMM_TILE_ALIGNMENT); + + GmmTileBlock *pBlock = pAllocator->pTileTail; + + while (pBlock) + { + if (pBlock->tileTag == tag) + { + GLuint address, tileSize; + rglGcmGetTileRegionInfo(pBlock->pData, &address, &tileSize); + + if ((pBlock->pNext && pBlock->pNext->base.address-pBlock->base.address-pBlock->base.size >= newSize) || + (pBlock->pPrev && pBlock->base.address-pBlock->pPrev->base.address-pBlock->pPrev->base.size >= newSize)) + { + GmmTileBlock *pNewBlock = gmmAllocFixedTileBlock(); + if (pNewBlock == NULL) + break; + + retId = (uint32_t)pNewBlock; + + memset(pNewBlock, 0, sizeof(GmmTileBlock)); + + pNewBlock->base.isTile = 1; + pNewBlock->base.size = newSize; + + if (pBlock->pNext && pBlock->pNext->base.address-pBlock->base.address-pBlock->base.size >= newSize) + { + pNewBlock->base.address = pBlock->base.address+pBlock->base.size; + pNewBlock->pNext = pBlock->pNext; + pNewBlock->pPrev = pBlock; + pBlock->pNext->pPrev = pNewBlock; + pBlock->pNext = pNewBlock; + + if (pNewBlock->pPrev->pData != pNewBlock->pNext->pData) + resizeSucceed = rglGcmTryResizeTileRegion( address, tileSize+newSize, pBlock->pData ); + } + else + { + pNewBlock->base.address = pBlock->base.address-newSize; + pNewBlock->pNext = pBlock; + pNewBlock->pPrev = pBlock->pPrev; + pBlock->pPrev->pNext = pNewBlock; + pBlock->pPrev = pNewBlock; + + if (pNewBlock->pPrev->pData != pNewBlock->pNext->pData) + resizeSucceed = rglGcmTryResizeTileRegion( (GLuint)gmmIdToOffset((uint32_t)pNewBlock), tileSize+newSize, pBlock->pData ); + } + gmmSetTileAttrib( retId, tag, pBlock->pData ); + break; + } + + if (pBlock == pAllocator->pTileHead) + { + retId = (uint32_t)gmmCreateTileBlock(pAllocator, newSize); + if (retId == 0) + break; + + resizeSucceed = rglGcmTryResizeTileRegion( (GLuint)gmmIdToOffset(retId), tileSize+newSize, pBlock->pData ); + gmmSetTileAttrib( retId, tag, pBlock->pData ); + break; + } + } + + pBlock = pBlock->pPrev; + } + + if (retId == 0) + return GMM_ERROR; + + if (!resizeSucceed) + { + gmmFreeTileBlock((GmmTileBlock *)retId); + return GMM_ERROR; + } + + return retId; +} + +static GmmTileBlock *gmmAllocTileBlock(GmmAllocator *pAllocator, + const uint32_t size) +{ + GmmTileBlock *pBlock = gmmFindFreeTileBlock(pAllocator, size); + + if (pBlock == NULL) + pBlock = gmmCreateTileBlock(pAllocator, size); + + return pBlock; +} + +static void gmmFreeBlock(GmmBlock *pBlock) +{ + GmmAllocator *pAllocator; + + if (pBlock->pPrev) + pBlock->pPrev->pNext = pBlock->pNext; + + if (pBlock->pNext) + pBlock->pNext->pPrev = pBlock->pPrev; + + pAllocator = pGmmLocalAllocator; + + if (pAllocator->pHead == pBlock) + { + pAllocator->pHead = pBlock->pNext; + + if (pAllocator->pHead) + pAllocator->pHead->pPrev = NULL; + } + + if (pAllocator->pTail == pBlock) + { + pAllocator->pTail = pBlock->pPrev; + + if (pAllocator->pTail) + pAllocator->pTail->pNext = NULL; + } + + if (pBlock->pPrev == NULL) + pAllocator->pSweepHead = pAllocator->pHead; + else if (pBlock->pPrev && + (pAllocator->pSweepHead == NULL || + (pAllocator->pSweepHead && + pAllocator->pSweepHead->base.address > pBlock->pPrev->base.address))) + pAllocator->pSweepHead = pBlock->pPrev; + + pAllocator->freedSinceSweep += pBlock->base.size; + + gmmFreeFixedBlock(pBlock); +} + +static void gmmAddPendingFree(GmmBlock *pBlock) +{ + GmmAllocator *pAllocator; + + pAllocator = pGmmLocalAllocator; + + if (pAllocator->pPendingFreeTail) + { + pBlock->pNextFree = NULL; + pBlock->pPrevFree = pAllocator->pPendingFreeTail; + pAllocator->pPendingFreeTail->pNextFree = pBlock; + pAllocator->pPendingFreeTail = pBlock; + } + else + { + pBlock->pNextFree = NULL; + pBlock->pPrevFree = NULL; + pAllocator->pPendingFreeHead = pBlock; + pAllocator->pPendingFreeTail = pBlock; + } + + pBlock->isPinned = 0; + + ++nvFenceCounter; + + /* semaphore ID : RGLGCM_SEMA_FENCE, new fence value: nvFenceCounter */ + GCM_FUNC( cellGcmSetWriteBackEndLabel, RGLGCM_SEMA_FENCE, nvFenceCounter ); + + pBlock->fence = nvFenceCounter; +} + +static uint8_t gmmSizeToFreeIndex( + uint32_t size + ) +{ + if (size >= GMM_FREE_BIN_0 && size < GMM_FREE_BIN_1) + return 0; + else if (size >= GMM_FREE_BIN_1 && size < GMM_FREE_BIN_2) + return 1; + else if (size >= GMM_FREE_BIN_2 && size < GMM_FREE_BIN_3) + return 2; + else if (size >= GMM_FREE_BIN_3 && size < GMM_FREE_BIN_4) + return 3; + else if (size >= GMM_FREE_BIN_4 && size < GMM_FREE_BIN_5) + return 4; + else if (size >= GMM_FREE_BIN_5 && size < GMM_FREE_BIN_6) + return 5; + else if (size >= GMM_FREE_BIN_6 && size < GMM_FREE_BIN_7) + return 6; + else if (size >= GMM_FREE_BIN_7 && size < GMM_FREE_BIN_8) + return 7; + else if (size >= GMM_FREE_BIN_8 && size < GMM_FREE_BIN_9) + return 8; + else if (size >= GMM_FREE_BIN_9 && size < GMM_FREE_BIN_10) + return 9; + else if (size >= GMM_FREE_BIN_10 && size < GMM_FREE_BIN_11) + return 10; + else if (size >= GMM_FREE_BIN_11 && size < GMM_FREE_BIN_12) + return 11; + else if (size >= GMM_FREE_BIN_12 && size < GMM_FREE_BIN_13) + return 12; + else if (size >= GMM_FREE_BIN_13 && size < GMM_FREE_BIN_14) + return 13; + else if (size >= GMM_FREE_BIN_14 && size < GMM_FREE_BIN_15) + return 14; + else if (size >= GMM_FREE_BIN_15 && size < GMM_FREE_BIN_16) + return 15; + else if (size >= GMM_FREE_BIN_16 && size < GMM_FREE_BIN_17) + return 16; + else if (size >= GMM_FREE_BIN_17 && size < GMM_FREE_BIN_18) + return 17; + else if (size >= GMM_FREE_BIN_18 && size < GMM_FREE_BIN_19) + return 18; + else if (size >= GMM_FREE_BIN_19 && size < GMM_FREE_BIN_20) + return 19; + else if (size >= GMM_FREE_BIN_20 && size < GMM_FREE_BIN_21) + return 20; + else + return 21; +} + +static void gmmAddFree( + GmmAllocator *pAllocator, + GmmBlock *pBlock + ) +{ + uint8_t freeIndex = gmmSizeToFreeIndex(pBlock->base.size); + + if (pAllocator->pFreeHead[freeIndex]) + { + GmmBlock *pInsertBefore = pAllocator->pFreeHead[freeIndex]; + + while (pInsertBefore && pInsertBefore->base.size < pBlock->base.size) + pInsertBefore = pInsertBefore->pNextFree; + + if (pInsertBefore == NULL) + { + pBlock->pNextFree = NULL; + pBlock->pPrevFree = pAllocator->pFreeTail[freeIndex]; + pAllocator->pFreeTail[freeIndex]->pNextFree = pBlock; + pAllocator->pFreeTail[freeIndex] = pBlock; + } + else if (pInsertBefore == pAllocator->pFreeHead[freeIndex]) + { + pBlock->pNextFree = pInsertBefore; + pBlock->pPrevFree = pInsertBefore->pPrevFree; + pInsertBefore->pPrevFree = pBlock; + pAllocator->pFreeHead[freeIndex] = pBlock; + } + else + { + pBlock->pNextFree = pInsertBefore; + pBlock->pPrevFree = pInsertBefore->pPrevFree; + pInsertBefore->pPrevFree->pNextFree = pBlock; + pInsertBefore->pPrevFree = pBlock; + } + } + else + { + pBlock->pNextFree = NULL; + pBlock->pPrevFree = NULL; + pAllocator->pFreeHead[freeIndex] = pBlock; + pAllocator->pFreeTail[freeIndex] = pBlock; + } +} + +uint32_t gmmFree(const uint32_t freeId) +{ + GmmBaseBlock *pBaseBlock = (GmmBaseBlock *)freeId; + + if (pBaseBlock->isTile) + { + GmmTileBlock *pTileBlock = (GmmTileBlock *)pBaseBlock; + + if (pTileBlock->pPrev && + pTileBlock->pNext && + pTileBlock->pPrev->pData == pTileBlock->pNext->pData) + { + } + else if (pTileBlock->pPrev && pTileBlock->pPrev->pData == pTileBlock->pData) + { + GLuint address, size; + + rglGcmGetTileRegionInfo(pTileBlock->pData, &address, &size); + if ( !rglGcmTryResizeTileRegion(address, (size-pTileBlock->base.size), pTileBlock->pData) ) + { + rglGcmTryResizeTileRegion(address, 0, pTileBlock->pData); + if ( !rglGcmTryResizeTileRegion(address, (size-pTileBlock->base.size), pTileBlock->pData) ) + { + } + } + } + else if (pTileBlock->pNext && pTileBlock->pNext->pData == pTileBlock->pData) + { + GLuint address, size; + + rglGcmGetTileRegionInfo(pTileBlock->pData, &address, &size); + if ( !rglGcmTryResizeTileRegion((address+pTileBlock->base.size), (size-pTileBlock->base.size), pTileBlock->pData) ) + { + rglGcmTryResizeTileRegion(address, 0, pTileBlock->pData); + if ( !rglGcmTryResizeTileRegion((address+pTileBlock->base.size), (size-pTileBlock->base.size), pTileBlock->pData) ) + { + } + } + } + else + { + if ( !rglGcmTryResizeTileRegion( (GLuint)gmmIdToOffset(freeId), 0, gmmGetTileData(freeId) ) ) + { + } + } + + gmmFreeTileBlock(pTileBlock); + } + else + { + GmmBlock *pBlock = (GmmBlock *)pBaseBlock; + + gmmAddPendingFree(pBlock); + } + + return CELL_OK; +} + +static inline void gmmLocalMemcpy( + CellGcmContextData *thisContext, + const uint32_t dstOffset, + const uint32_t srcOffset, + const uint32_t moveSize + ) +{ + int32_t offset = 0; + int32_t sizeLeft = moveSize; + int32_t dimension = 4096; + + while (sizeLeft > 0) + { + while(sizeLeft >= dimension*dimension*4) + { + cellGcmSetTransferImage(thisContext, + CELL_GCM_TRANSFER_LOCAL_TO_LOCAL, + dstOffset+offset, + dimension*4, + 0, + 0, + srcOffset+offset, + dimension*4, + 0, + 0, + dimension, + dimension, + 4); + + offset = offset + dimension*dimension*4; + sizeLeft = sizeLeft - (dimension*dimension*4); + } + + dimension = dimension >> 1; + + if (dimension == 32) + break; + } + + if (sizeLeft > 0) + { + cellGcmSetTransferImage(thisContext, + CELL_GCM_TRANSFER_LOCAL_TO_LOCAL, + dstOffset+offset, + sizeLeft, + 0, + 0, + srcOffset+offset, + sizeLeft, + 0, + 0, + sizeLeft/4, + 1, + 4); + } +} + +static inline void gmmMemcpy( + CellGcmContextData *thisContext, + const uint8_t mode, + const uint32_t dstOffset, + const uint32_t srcOffset, + const uint32_t moveSize + ) +{ + { + if (dstOffset + moveSize <= srcOffset) + { + gmmLocalMemcpy(thisContext, + dstOffset, + srcOffset, + moveSize); + } + else + { + uint32_t moveBlockSize = srcOffset-dstOffset; + uint32_t iterations = (moveSize+moveBlockSize-1)/moveBlockSize; + + for (uint32_t i=0; ipSweepHead; + srcAddress = 0; + dstAddress = 0; + prevEndAddress = 0; + pSrcBlock = pBlock; + + while (pBlock != NULL) + { + + if (pBlock->isPinned == 0) + { + if (pBlock->pPrev) + prevEndAddress = pBlock->pPrev->base.address + pBlock->pPrev->base.size; + else + prevEndAddress = pAllocator->startAddress; + + if (pBlock->base.address > prevEndAddress) + { + dstAddress = prevEndAddress; + srcAddress = pBlock->base.address; + pSrcBlock = pBlock; + } + + moveSize = pBlock->base.address + pBlock->base.size - srcAddress; + + if (srcAddress > dstAddress && + (pBlock->pNext == NULL || + pBlock->pNext->base.address > pBlock->base.address + pBlock->base.size || + pBlock->pNext->isPinned)) + { + dstOffset = gmmAddressToOffset(dstAddress); + srcOffset = gmmAddressToOffset(srcAddress); + + totalMoveSize += moveSize; + + gmmMemcpy(thisContext, + mode, + dstOffset, + srcOffset, + moveSize); + + pTempBlock = pSrcBlock; + + moveDistance = srcOffset - dstOffset; + + while (pTempBlock != pBlock->pNext) + { + pTempBlock->base.address -= moveDistance; + + + pTempBlock = pTempBlock->pNext; + } + } + } + else + { + uint32_t availableSize; + + srcAddress = 0; + dstAddress = 0; + + if (pBlock->pPrev == NULL) + availableSize = pBlock->base.address - pAllocator->startAddress; + else + availableSize = pBlock->base.address - (pBlock->pPrev->base.address + pBlock->pPrev->base.size); + + pTempBlock = pBlock->pNext; + + while (availableSize >= GMM_ALIGNMENT && + pTempBlock) + { + pTempBlockNext = pTempBlock->pNext; + + if (pTempBlock->isPinned == 0 && + pTempBlock->base.size <= availableSize) + { + uint32_t pinDstAddress = (pBlock->pPrev == NULL) ? + pAllocator->startAddress : + pBlock->pPrev->base.address + pBlock->pPrev->base.size; + uint32_t pinSrcAddress = pTempBlock->base.address; + + dstOffset = gmmAddressToOffset(pinDstAddress); + srcOffset = gmmAddressToOffset(pinSrcAddress); + + totalMoveSize += pTempBlock->base.size; + + gmmMemcpy(thisContext, + mode, + dstOffset, + srcOffset, + pTempBlock->base.size); + + pTempBlock->base.address = pinDstAddress; + + if (pTempBlock == pAllocator->pTail) + { + if (pTempBlock->pNext) + { + pAllocator->pTail = pTempBlock->pNext; + } + else + { + pAllocator->pTail = pTempBlock->pPrev; + } + } + + if (pTempBlock->pNext) + pTempBlock->pNext->pPrev = pTempBlock->pPrev; + if (pTempBlock->pPrev) + pTempBlock->pPrev->pNext = pTempBlock->pNext; + + if (pBlock->pPrev) + pBlock->pPrev->pNext = pTempBlock; + else + pAllocator->pHead = pTempBlock; + pTempBlock->pPrev = pBlock->pPrev; + pTempBlock->pNext = pBlock; + pBlock->pPrev = pTempBlock; + } + + if (pBlock->pPrev) + { + availableSize = pBlock->base.address - (pBlock->pPrev->base.address + pBlock->pPrev->base.size); + } + + pTempBlock = pTempBlockNext; + } + + if (availableSize > 0) + { + GmmBlock *pNewBlock = gmmAllocFixedBlock(); + + if (pNewBlock) + { + memset(pNewBlock, 0, sizeof(GmmBlock)); + pNewBlock->base.address = pBlock->base.address - availableSize; + pNewBlock->base.size = availableSize; + pNewBlock->pNext = pBlock; + pNewBlock->pPrev = pBlock->pPrev; + if (pBlock->pPrev) + pBlock->pPrev->pNext = pNewBlock; + + pBlock->pPrev = pNewBlock; + + if (pBlock == pAllocator->pHead) + pAllocator->pHead = pNewBlock; + + gmmAddFree(pAllocator, pNewBlock); + + ret = 1; + } + } + } + + pBlock = pBlock->pNext; + } + + uint32_t newFreeAddress = pAllocator->pTail ? + pAllocator->pTail->base.address + pAllocator->pTail->base.size : + pAllocator->startAddress; + + if (pAllocator->freeAddress != newFreeAddress) + { + pAllocator->freeAddress = newFreeAddress; + ret = 1; + } + + pAllocator->freedSinceSweep = 0; + pAllocator->pSweepHead = NULL; + + return ret; +} + +static void gmmRemovePendingFree( + GmmAllocator *pAllocator, + GmmBlock *pBlock + ) +{ + if (pBlock == pAllocator->pPendingFreeHead) + pAllocator->pPendingFreeHead = pBlock->pNextFree; + + if (pBlock == pAllocator->pPendingFreeTail) + pAllocator->pPendingFreeTail = pBlock->pPrevFree; + + if (pBlock->pNextFree) + pBlock->pNextFree->pPrevFree = pBlock->pPrevFree; + + if (pBlock->pPrevFree) + pBlock->pPrevFree->pNextFree = pBlock->pNextFree; +} + +void gmmUpdateFreeList(const uint8_t location) +{ + GmmAllocator *pAllocator; + const uint32_t fence = rglGcmState_i.semaphores->userSemaphores[RGLGCM_SEMA_FENCE].val; + GmmBlock *pBlock = NULL; + GmmBlock *pTemp = NULL; + + + pAllocator = pGmmLocalAllocator; + + + pBlock = pAllocator->pPendingFreeHead; + + while (pBlock) + { + pTemp = pBlock->pNextFree; + + if ( !(( fence - pBlock->fence ) & 0x80000000 ) ) + { + gmmRemovePendingFree(pAllocator, pBlock); + gmmAddFree(pAllocator, pBlock); + } + + pBlock = pTemp; + } +} + +static void gmmFreeAll( + const uint8_t location + ) +{ + GmmAllocator *pAllocator; + GmmBlock *pBlock; + GmmBlock *pTemp; + + + pAllocator = pGmmLocalAllocator; + + pBlock = pAllocator->pPendingFreeHead; + while (pBlock) + { + pTemp = pBlock->pNextFree; + gmmFreeBlock(pBlock); + pBlock = pTemp; + } + pAllocator->pPendingFreeHead = NULL; + pAllocator->pPendingFreeTail = NULL; + + for (int i=0; ipFreeHead[i]; + while (pBlock) + { + pTemp = pBlock->pNextFree; + gmmFreeBlock(pBlock); + pBlock = pTemp; + } + pAllocator->pFreeHead[i] = NULL; + pAllocator->pFreeTail[i] = NULL; + } +} + +static void gmmAllocSweep( + CellGcmContextData *thisContext, + const uint8_t location + ) +{ + gmmFreeAll(location); + + if (gmmInternalSweep(thisContext, location)) + { + *pLock = 1; + cachedLockValue = 1; + cellGcmSetWriteBackEndLabel(thisContext, GMM_PPU_WAIT_INDEX, 0); + + cellGcmFlush(thisContext); + } +} + +static uint32_t gmmInternalAlloc( + GmmAllocator *pAllocator, + const uint8_t isTile, + const uint32_t size + ) +{ + uint32_t retId; + + if (isTile) + retId = (uint32_t)gmmAllocTileBlock(pAllocator, size); + else + retId = (uint32_t)gmmAllocBlock(pAllocator, size); + + if (retId == 0) + return GMM_ERROR; + + return retId; +} + +static void gmmRemoveFree( + GmmAllocator *pAllocator, + GmmBlock *pBlock, + uint8_t freeIndex + ) +{ + if (pBlock == pAllocator->pFreeHead[freeIndex]) + pAllocator->pFreeHead[freeIndex] = pBlock->pNextFree; + + if (pBlock == pAllocator->pFreeTail[freeIndex]) + pAllocator->pFreeTail[freeIndex] = pBlock->pPrevFree; + + if (pBlock->pNextFree) + pBlock->pNextFree->pPrevFree = pBlock->pPrevFree; + + if (pBlock->pPrevFree) + pBlock->pPrevFree->pNextFree = pBlock->pNextFree; +} + +static uint32_t gmmFindFreeBlock( + GmmAllocator *pAllocator, + uint32_t size + ) +{ + uint32_t retId = GMM_ERROR; + GmmBlock *pBlock; + uint8_t found = 0; + uint8_t freeIndex = gmmSizeToFreeIndex(size); + + pBlock = pAllocator->pFreeHead[freeIndex]; + + while (freeIndex < GMM_NUM_FREE_BINS) + { + if (pBlock) + { + if (pBlock->base.size >= size) + { + found = 1; + break; + } + pBlock = pBlock->pNextFree; + } + else if (++freeIndex < GMM_NUM_FREE_BINS) + pBlock = pAllocator->pFreeHead[freeIndex]; + } + + if (found) + { + if (pBlock->base.size != size) + { + GmmBlock *pNewBlock = gmmAllocFixedBlock(); + if (pNewBlock == NULL) + return GMM_ERROR; + + memset(pNewBlock, 0, sizeof(GmmBlock)); + pNewBlock->base.address = pBlock->base.address + size; + pNewBlock->base.size = pBlock->base.size - size; + pNewBlock->pNext = pBlock->pNext; + pNewBlock->pPrev = pBlock; + if (pBlock->pNext) + pBlock->pNext->pPrev = pNewBlock; + pBlock->pNext = pNewBlock; + + if (pBlock == pAllocator->pTail) + pAllocator->pTail = pNewBlock; + + gmmAddFree(pAllocator, pNewBlock); + } + pBlock->base.size = size; + gmmRemoveFree(pAllocator, pBlock, freeIndex); + retId = (uint32_t)pBlock; + } + + return retId; +} + +uint32_t gmmAlloc( + CellGcmContextData *thisContext, + const uint8_t location, + const uint8_t isTile, + const uint32_t size + ) +{ + GmmAllocator *pAllocator; + uint32_t retId; + uint32_t newSize; + + if (__builtin_expect((size == 0),0)) + return GMM_ERROR; + + pAllocator = pGmmLocalAllocator; + + if (!isTile) + { + newSize = pad(size, GMM_ALIGNMENT); + + retId = gmmFindFreeBlock(pAllocator, newSize); + } + else + { + newSize = pad(size, GMM_TILE_ALIGNMENT); + retId = GMM_ERROR; + } + + if (retId == GMM_ERROR) + { + retId = gmmInternalAlloc(pAllocator, + isTile, + newSize); + + if (retId == GMM_ERROR) + { + gmmAllocSweep(thisContext, location); + + retId = gmmInternalAlloc(pAllocator, + isTile, + newSize); + + if (!isTile && + retId == GMM_ERROR) + retId = gmmFindFreeBlock(pAllocator, newSize); + } + } + + return retId; +} + +/*============================================================ + FRAGMENT SHADER + ============================================================ */ + +void rglSetNativeCgFragmentProgram( const GLvoid *header ) +{ + const _CGprogram *ps = ( const _CGprogram * )header; + + CellCgbFragmentProgramConfiguration conf; + + conf.offset = gmmIdToOffset(ps->loadProgramId) + ps->loadProgramOffset; + + rglGcmInterpolantState *s = &rglGcmState_i.state.interpolant; + s->fragmentProgramAttribMask |= ps->header.attributeInputMask | CELL_GCM_ATTRIB_OUTPUT_MASK_POINTSIZE; + + conf.attributeInputMask = ( s->vertexProgramAttribMask) & + s->fragmentProgramAttribMask; + + conf.texCoordsInputMask = ps->header.fragmentProgram.texcoordInputMask; + conf.texCoords2D = ps->header.fragmentProgram.texcoord2d; + conf.texCoordsCentroid = ps->header.fragmentProgram.texcoordCentroid; + + int fragmentControl = ( 1 << 15 ) | ( 1 << 10 ); + fragmentControl |= ps->header.fragmentProgram.flags & CGF_DEPTHREPLACE ? 0xE : 0x0; + fragmentControl |= ps->header.fragmentProgram.flags & CGF_OUTPUTFROMH0 ? 0x00 : 0x40; + fragmentControl |= ps->header.fragmentProgram.flags & CGF_PIXELKILL ? 0x80 : 0x00; + + conf.fragmentControl = fragmentControl; + conf.registerCount = ps->header.fragmentProgram.registerCount < 2 ? 2 : ps->header.fragmentProgram.registerCount; + + uint32_t controlTxp = _CurrentContext->AllowTXPDemotion; + conf.fragmentControl &= ~CELL_GCM_MASK_SET_SHADER_CONTROL_CONTROL_TXP; + conf.fragmentControl |= controlTxp << CELL_GCM_SHIFT_SET_SHADER_CONTROL_CONTROL_TXP; + + if ( ps->inLocalMemory ) + { + GCM_FUNC( cellGcmSetFragmentProgramLoad, &conf ); + } + else + { + GCM_FUNC( cellGcmSetFragmentProgramLoadLocation, &conf, CELL_GCM_LOCATION_MAIN ); + } + + GCM_FUNC( cellGcmSetZMinMaxControl, ( ps->header.fragmentProgram.flags & CGF_DEPTHREPLACE ) ? RGLGCM_FALSE : RGLGCM_TRUE, RGLGCM_FALSE, RGLGCM_FALSE ); +} + +/*============================================================ + VERTEX SHADER + ============================================================ */ + +void rglSetNativeCgVertexProgram( const void *header ) +{ + const _CGprogram *vs = ( const _CGprogram* ) header; + + __dcbt(vs->ucode); + __dcbt(((uint8_t*)vs->ucode)+128); + __dcbt(((uint8_t*)vs->ucode)+256); + __dcbt(((uint8_t*)vs->ucode)+384); + + CellCgbVertexProgramConfiguration conf; + conf.instructionSlot = vs->header.vertexProgram.instructionSlot; + conf.instructionCount = vs->header.instructionCount; + conf.registerCount = vs->header.vertexProgram.registerCount; + conf.attributeInputMask = vs->header.attributeInputMask; + + rglGcmFifoWaitForFreeSpace( &rglGcmState_i.fifo, 7 + 5 * conf.instructionCount ); + + GCM_FUNC( cellGcmSetVertexProgramLoad, &conf, vs->ucode ); + + GCM_FUNC( cellGcmSetUserClipPlaneControl, 0, 0, 0, 0, 0, 0 ); + + rglGcmInterpolantState *s = &rglGcmState_i.state.interpolant; + s->vertexProgramAttribMask = vs->header.vertexProgram.attributeOutputMask; + + GCM_FUNC( cellGcmSetVertexAttribOutputMask, (( s->vertexProgramAttribMask) & + s->fragmentProgramAttribMask) ); + + _CGprogram *program = ( _CGprogram* )vs; + int count = program->defaultValuesIndexCount; + for ( int i = 0;i < count;i++ ) + { + const CgParameterEntry *parameterEntry = program->parametersEntries + program->defaultValuesIndices[i].entryIndex; + if (( parameterEntry->flags & CGPF_REFERENCED ) && ( parameterEntry->flags & CGPV_MASK ) == CGPV_CONSTANT ) + { + const float *itemDefaultValues = program->defaultValues + + program->defaultValuesIndices[i].defaultValueIndex; + rglFifoGlProgramParameterfvVP( program, parameterEntry, itemDefaultValues ); + } + } +} + +/*============================================================ + SURFACE COPYING + ============================================================ */ + +void rglGcmCopySurface( + const rglGcmSurface* src, + GLuint srcX, GLuint srcY, + const rglGcmSurface* dst, + GLuint dstX, GLuint dstY, + GLuint width, GLuint height, + GLboolean writeSync ) // don't overwrite dst directly (not used yet) +{ + const GLuint srcPitch = src->pitch ? src->pitch : src->bpp * src->width; + const GLuint dstPitch = dst->pitch ? dst->pitch : dst->bpp * dst->width; + + if (( srcPitch >= 0x10000 ) || ( dstPitch >= 0x10000 ) ) + { + rglGcmTransferData( dst->dataId, dst->dataIdOffset+(dstPitch*dstY+dstX*dst->bpp), dstPitch, + src->dataId, src->dataIdOffset+(srcPitch*srcY+srcX*src->bpp), srcPitch, + width*src->bpp, height ); + return; + } + + switch ( src->bpp ) + { + case 1: + if (( dstX % 2 ) == 0 && ( srcX % 2 ) == 0 && ( width % 2 ) == 0 ) + { + rglGcmFifoGlTransferDataVidToVid( + dst->dataId, dst->dataIdOffset, dstPitch, dstX / 2, dstY, + src->dataId, src->dataIdOffset, srcPitch, srcX / 2, srcY, + width / 2, height, 2 ); + } + else + { + rglGcmTransferData( dst->dataId, dst->dataIdOffset+(dstPitch*dstY+dstX*dst->bpp), dstPitch, + src->dataId, src->dataIdOffset+(srcPitch*srcY+srcX*src->bpp), srcPitch, + width*src->bpp, height ); + } + break; + case 2: + case 4: + rglGcmFifoGlTransferDataVidToVid( dst->dataId, dst->dataIdOffset, dstPitch, dstX, dstY, + src->dataId, src->dataIdOffset, srcPitch, srcX, srcY, + width, height, src->bpp ); + break; + case 8: + case 16: + rglGcmFifoGlTransferDataVidToVid( dst->dataId, dst->dataIdOffset, dstPitch, dstX*4, dstY, + src->dataId, src->dataIdOffset, srcPitch, srcX*4, srcY, + width*4, height, src->bpp / 4 ); + break; + } +} + +/*============================================================ + DATA TRANSFER + ============================================================ */ + + void rglGcmTransferData +( + GLuint dstId, + GLuint dstIdOffset, + GLint dstPitch, + GLuint srcId, + GLuint srcIdOffset, + GLint srcPitch, + GLint bytesPerRow, + GLint rowCount + ) +{ + GLuint dstOffset = gmmIdToOffset(dstId) + dstIdOffset; + GLuint srcOffset = gmmIdToOffset(srcId) + srcIdOffset; + + GCM_FUNC( cellGcmSetTransferData, CELL_GCM_TRANSFER_LOCAL_TO_LOCAL, dstOffset, dstPitch, srcOffset, srcPitch, bytesPerRow, rowCount ); +} + +/*============================================================ + FIFO BUFFER + ============================================================ */ + +const uint32_t c_rounded_size_ofrglDrawParams = (sizeof(rglDrawParams)+0x7f)&~0x7f; + +void rglGcmFifoFinish( rglGcmFifo *fifo ) +{ + GLuint ref = rglGcmFifoPutReference( fifo ); + + rglGcmFifoFlush( fifo ); + + for ( ;; ) + { + if ( !rglGcmFifoReferenceInUse( fifo, ref ) ) + break; + + sys_timer_usleep( 10 ); + } +} + +void rglGcmFifoFlush( rglGcmFifo *fifo ) +{ + unsigned int offsetInBytes = 0; + cellGcmAddressToOffset( fifo->current, ( uint32_t * )&offsetInBytes ); + + cellGcmFlush(); + + fifo->dmaControl->Put = offsetInBytes; + fifo->lastPutWritten = fifo->current; + + fifo->lastSWReferenceFlushed = fifo->lastSWReferenceWritten; +} + +GLuint rglGcmFifoPutReference( rglGcmFifo *fifo ) +{ + fifo->lastSWReferenceWritten++; + + GCM_FUNC( cellGcmSetReferenceCommand, fifo->lastSWReferenceWritten ); + + if (( fifo->lastSWReferenceWritten & 0x7fffffff ) == 0 ) + { + rglGcmFifoFinish( fifo ); + } + + return fifo->lastSWReferenceWritten; +} + +GLuint rglGcmFifoReadReference( rglGcmFifo *fifo ) +{ + GLuint ref = *(( volatile GLuint * ) & fifo->dmaControl->Reference ); + fifo->lastHWReferenceRead = ref; + return ref; +} + +GLboolean rglGcmFifoReferenceInUse( rglGcmFifo *fifo, GLuint reference ) +{ + // compare against cached hw ref value (accounting wrap) + if ( !(( fifo->lastHWReferenceRead - reference ) & 0x80000000 ) ) + return GL_FALSE; + + // has the reference already been flushed out ? + if (( fifo->lastSWReferenceFlushed - reference ) & 0x80000000 ) + { + rglGcmFifoFlush( fifo ); + } + + // read current hw reference + rglGcmFifoReadReference( fifo ); + + // compare against hw ref value (accounting wrap) + if ( !(( fifo->lastHWReferenceRead - reference ) & 0x80000000 ) ) + return GL_FALSE; + + return GL_TRUE; +} + + +// Wait until the requested space is available. +// If not currently available, will call the out of space callback +uint32_t * rglGcmFifoWaitForFreeSpace( rglGcmFifo *fifo, GLuint spaceInWords ) +{ + if ( fifo->current + spaceInWords + 1024 > fifo->end ) + rglOutOfSpaceCallback( fifo, spaceInWords ); + + return rglGcmState_i.fifo.current; +} + +void rglGcmFifoInit( rglGcmFifo *fifo, void *dmaControl, unsigned long dmaPushBufferOffset, uint32_t*dmaPushBuffer, + GLuint dmaPushBufferSize ) +{ + // init fifoBlockSize + fifo->fifoBlockSize = DEFAULT_FIFO_BLOCK_SIZE; + + // init fifo context pointers to first fifo block which will be set at the the dmaPushPuffer position + fifo->begin = (uint32_t*) dmaPushBuffer; + fifo->end = fifo->begin + ( fifo->fifoBlockSize / sizeof( uint32_t ) ) - 1; + // init rest of context + fifo->current = fifo->begin; + fifo->lastGetRead = fifo->current; + fifo->lastPutWritten = fifo->current; + + // store fifo values + fifo->dmaPushBufferBegin = dmaPushBuffer; + fifo->dmaPushBufferEnd = (uint32_t*)(( size_t )dmaPushBuffer + dmaPushBufferSize ) - 1; + fifo->dmaControl = (rglGcmControlDma*)dmaControl; + fifo->dmaPushBufferOffset = dmaPushBufferOffset; + fifo->dmaPushBufferSizeInWords = dmaPushBufferSize / sizeof(uint32_t); + + fifo->lastHWReferenceRead = 0; + fifo->lastSWReferenceWritten = 0; + fifo->lastSWReferenceFlushed = 0; + + // note that rglGcmFifo is-a CellGcmContextData + gCellGcmCurrentContext = fifo; + // setting our own out of space callback here to handle our fifo + gCellGcmCurrentContext->callback = ( CellGcmContextCallback )rglOutOfSpaceCallback; + + // ensure the ref is initted to 0. + if ( rglGcmFifoReadReference( fifo ) != 0 ) + { + GCM_FUNC( cellGcmSetReferenceCommand, 0 ); + rglGcmFifoFlush( fifo ); // Here, we jump to this new buffer + + // a finish that waits for 0 specifically. + for ( ;; ) + { + if ( rglGcmFifoReadReference( fifo ) == 0 ) break; + sys_timer_usleep( 10 ); + } + } + fifo->dmaPushBufferGPU = dmaPushBuffer; + fifo->spuid = 0; + +} + +/*============================================================ + GL INITIALIZATION + ============================================================ */ + + +void rglGcmSetOpenGLState( rglGcmState *rglGcmSt ) +{ + GLuint i; + + // initialize the default OpenGL state + rglGcmFifoGlBlendColor( 0.0f, 0.0f, 0.0f, 0.0f ); + rglGcmFifoGlBlendEquation( RGLGCM_FUNC_ADD, RGLGCM_FUNC_ADD ); + rglGcmFifoGlBlendFunc( RGLGCM_ONE, RGLGCM_ZERO, RGLGCM_ONE, RGLGCM_ZERO ); + rglGcmFifoGlClearColor( 0.0f, 0.0f, 0.0f, 0.0f ); + rglGcmFifoGlDisable( RGLGCM_BLEND ); + rglGcmFifoGlDisable( RGLGCM_PSHADER_SRGB_REMAPPING ); + + for ( i = 0; i < RGLGCM_ATTRIB_COUNT; i++ ) + { + rglGcmFifoGlVertexAttribPointer( i, 0, RGLGCM_FLOAT, RGLGCM_FALSE, 0, 0, 0, 0 ); + } + + + rglGcmFifoGlEnable( RGLGCM_DITHER ); + + for ( i = 0; i < RGLGCM_MAX_TEXIMAGE_COUNT; i++ ) + { + static const GLuint borderColor = 0; + + // update the setTextureAddress Portion + GCM_FUNC( cellGcmSetTextureAddress, i, CELL_GCM_TEXTURE_WRAP, CELL_GCM_TEXTURE_WRAP, CELL_GCM_TEXTURE_CLAMP_TO_EDGE, CELL_GCM_TEXTURE_UNSIGNED_REMAP_NORMAL, CELL_GCM_TEXTURE_ZFUNC_NEVER, 0 ); + + // update the setTextureFilter Portion + GCM_FUNC( cellGcmSetTextureFilter, i, 0, CELL_GCM_TEXTURE_NEAREST_LINEAR, CELL_GCM_TEXTURE_LINEAR, + CELL_GCM_TEXTURE_CONVOLUTION_QUINCUNX ); + + // update the texture control to setup antisotropic settings + GCM_FUNC( cellGcmSetTextureControl, i, CELL_GCM_TRUE, 0, 12 << 8, CELL_GCM_TEXTURE_MAX_ANISO_1 ); + + // update border color + GCM_FUNC( cellGcmSetTextureBorderColor, i, borderColor ); + } + + // Set zNear and zFar to the default 0.0f and 1.0f here + rglGcmFifoGlViewport( 0, 0, RGLGCM_MAX_RT_DIMENSION, RGLGCM_MAX_RT_DIMENSION, 0.0f, 1.0f ); +} + +GLboolean rglGcmInitFromRM( rglGcmResource *rmResource ) +{ + rglGcmState *rglGcmSt = &rglGcmState_i; + memset( rglGcmSt, 0, sizeof( *rglGcmSt ) ); + + rglGcmSt->localAddress = rmResource->localAddress; + rglGcmSt->hostMemoryBase = rmResource->hostMemoryBase; + rglGcmSt->hostMemorySize = rmResource->hostMemorySize; + + rglGcmSt->hostNotifierBuffer = NULL; //rmResource->hostNotifierBuffer; + rglGcmSt->semaphores = rmResource->semaphores; + + rglGcmFifoInit( &rglGcmSt->fifo, rmResource->dmaControl, rmResource->dmaPushBufferOffset, (uint32_t*)rmResource->dmaPushBuffer, rmResource->dmaPushBufferSize ); + + rglGcmFifoFinish( &rglGcmSt->fifo ); + + // Set the GPU to a known state + rglGcmSetOpenGLState( rglGcmSt ); + + // wait for setup to complete + rglGcmFifoFinish( &rglGcmSt->fifo ); + + return GL_TRUE; +} + + +void rglGcmDestroy( void ) +{ + rglGcmState *rglGcmSt = &rglGcmState_i; + memset( rglGcmSt, 0, sizeof( *rglGcmSt ) ); +} + +/*============================================================ + GCM UTILITIES + ============================================================ */ + +static GLuint MemoryClock = 0; +static GLuint GraphicsClock = 0; + +GLuint rglGcmGetMemoryClock() +{ + return MemoryClock; +} + +GLuint rglGcmGetGraphicsClock() +{ + return GraphicsClock; +} + +GLboolean rglGcmInit( RGLinitOptions* options, rglGcmResource *resource ) +{ + if ( !rglGcmInitFromRM( resource ) ) + { + fprintf( stderr, "RGL GCM failed initialisation" ); + return GL_FALSE; + } + MemoryClock = resource->MemoryClock; + GraphicsClock = resource->GraphicsClock; + + if ( gmmInit( resource->localAddress, // pass in the base address, which "could" diff from start address + resource->localAddress, + resource->localSize, + resource->hostMemoryBase, // pass in the base address + resource->hostMemoryBase + resource->hostMemoryReserved, + resource->hostMemorySize - resource->hostMemoryReserved ) == GMM_ERROR ) + { + fprintf( stderr, "Could not init GPU memory manager" ); + rglGcmDestroy(); + return GL_FALSE; + } + + // initialize DMA sync mechanism + // use one semaphore to implement fence + rglGcmSemaphoreMemory *semaphores = rglGcmState_i.semaphores; + semaphores->userSemaphores[RGLGCM_SEMA_FENCE].val = nvFenceCounter; + + // also need to init the labelValue for waiting for idle + rglGcmState_i.labelValue = 1; + + return GL_TRUE; +} + +void rglGcmAllocDestroy() +{ + gmmDestroy(); + + rglGcmDestroy(); +} + +void rglGcmMemcpy( const GLuint dstId, unsigned dstOffset, unsigned int pitch, const GLuint srcId, GLuint srcOffset, unsigned int size ) +{ + // check alignment + // Vid to vid copy requires 64-byte aligned base address (for dst pointer). + if ((gmmIdToOffset(dstId) % 64 ) == 0 && ( dstOffset % 2 ) == 0 && + (gmmIdToOffset(srcId) % 2 ) == 0 && ( srcOffset % 2) == 0 && + ( size % 2 ) == 0 && ( pitch % 64 ) == 0 ) + { + // configure a 2D transfer + // + // align destination + { + pitch = pitch ? : 64; // minimum pitch + // target buffer isn't tiled, we just need to align on pitch + const GLuint dstOffsetAlign = dstOffset % pitch; + if ( dstOffsetAlign ) + { + const GLuint firstBytes = MIN( pitch - dstOffsetAlign, size ); + + rglGcmFifoGlTransferDataVidToVid( + dstId, + 0, + pitch, // dst pitch + dstOffsetAlign / 2, dstOffset / pitch, // dst x,y start + srcId, + srcOffset, + pitch, // src pitch + 0, 0, // src x,y start + firstBytes / 2, 1, // size in pixels + 2 ); // pixel size in bytes + dstOffset += firstBytes; + srcOffset += firstBytes; + size -= firstBytes; + } + } + + const GLuint fullLines = size / pitch; + const GLuint extraBytes = size % pitch; + if ( fullLines ) + rglGcmFifoGlTransferDataVidToVid( + dstId, + 0, + pitch, // dst pitch + 0, dstOffset / pitch, // dst x,y start + srcId, + srcOffset, + pitch, // src pitch + 0, 0, // src x,y start + pitch / 2, fullLines, // size in pixels + 2 ); // pixel size in bytes + if ( extraBytes ) + rglGcmFifoGlTransferDataVidToVid( + dstId, + 0, + pitch, // dst pitch + 0, fullLines + dstOffset / pitch, // dst x,y start + srcId, + srcOffset, + pitch, // src pitch + 0, fullLines, // src x,y start + extraBytes / 2, 1, // size in pixels + 2 ); // pixel size in bytes + } + else + { + rglGcmTransferData( dstId, dstOffset, size, srcId, 0, size, size, 1 ); + } +} + +void rglGcmSend( unsigned int dstId, unsigned dstOffset, unsigned int pitch, const char *src, unsigned int size ) +{ + // try allocating the whole block in the bounce buffer + GLuint id = gmmAlloc((CellGcmContextData*)&rglGcmState_i.fifo, + CELL_GCM_LOCATION_LOCAL, + 0, + size); + + memcpy( gmmIdToAddress(id), src, size ); + rglGcmMemcpy( dstId, dstOffset, pitch, id, 0, size ); + + gmmFree( id ); +} + + +/*============================================================ + PLATFORM INITIALIZATION + ============================================================ */ + +// resc is enabled by setting ANY of the resc related device parameters (using the enable mask) +static inline int rescIsEnabled( RGLdeviceParameters* params ) +{ + return params->enable & ( RGL_DEVICE_PARAMETERS_RESC_RENDER_WIDTH_HEIGHT | + RGL_DEVICE_PARAMETERS_RESC_RATIO_MODE | + RGL_DEVICE_PARAMETERS_RESC_PAL_TEMPORAL_MODE | + RGL_DEVICE_PARAMETERS_RESC_INTERLACE_MODE | + RGL_DEVICE_PARAMETERS_RESC_ADJUST_ASPECT_RATIO ); +} + +uint64_t rglGetLastFlipTime() +{ + // special case for resc + RGLdevice *device = psglGetCurrentDevice(); + if ( rescIsEnabled( &device->deviceParameters ) ) + return cellRescGetLastFlipTime(); + + // general case + return cellGcmGetLastFlipTime(); +} + +// Platform-specific initialization for Cell processor: +// manage allocation/free of SPUs, and optional debugging console. + +void rglPlatformInit( RGLinitOptions* options ) +{ + // option defaults + int consoleEnabled = 0; + + if ( options != NULL ) + { + if ( options->enable & RGL_INIT_ERROR_CONSOLE ) + consoleEnabled = options->errorConsole; + + } +} + + +void rglPlatformExit() +{ +} + +/*============================================================ + PLATFORM REPORTING + ============================================================ */ + +static FILE* consoleHandle = 0; + +void rglInitConsole( GLuint enable ) +{ + //logical_console_open(&console, id); + if ( enable ) + { + consoleHandle = stderr; + fprintf( consoleHandle, "%s\n", "\nRGL console initialized\n" ); + fflush( consoleHandle ); + } + else consoleHandle = 0; +} + +void rglExitConsole() +{ + //if (console!=-1U) logical_console_close(console); + consoleHandle = 0; +} + +/*============================================================ + DEVICE CONTEXT CREATION + ============================================================ */ + +static const RGLdeviceParameters defaultParameters = +{ +enable: 0, + colorFormat: GL_ARGB_SCE, + depthFormat: GL_NONE, + multisamplingMode: GL_MULTISAMPLING_NONE_SCE, + TVStandard: RGL_TV_STANDARD_NONE, + connector: RGL_DEVICE_CONNECTOR_NONE, + bufferingMode: RGL_BUFFERING_MODE_DOUBLE, + width: 0, + height: 0, + renderWidth: 0, + renderHeight: 0, + rescRatioMode: RESC_RATIO_MODE_LETTERBOX, + rescPalTemporalMode: RESC_PAL_TEMPORAL_MODE_50_NONE, + rescInterlaceMode: RESC_INTERLACE_MODE_NORMAL_BILINEAR, + horizontalScale: 1.0f, + verticalScale: 1.0f +}; + +static int rglInitCompleted = 0; +int _getJsInitCompleted(){ return rglInitCompleted; } // accessor + +void rglPsglPlatformInit( RGLinitOptions* options ) +{ + if ( !rglInitCompleted ) + { + int ret = cellSysmoduleLoadModule( CELL_SYSMODULE_GCM_SYS ); + switch ( ret ) + { + case CELL_OK: + //printf( "GCM wasn't loaded; good thing we did\n" ); + break; + case CELL_SYSMODULE_ERROR_DUPLICATED: + //printf( "GCM was loaded already\n" ); + break; + default: + break; + } + + ret = cellSysmoduleLoadModule( CELL_SYSMODULE_RESC ); + switch ( ret ) + { + case CELL_OK: + //printf( "RESC wasn't loaded; good thing we did\n" ); + break; + case CELL_SYSMODULE_ERROR_DUPLICATED: + //printf( "RESC was loaded already\n" ); + break; + default: + break; + } + + rglPlatformInit( options ); + rglDeviceInit( options ); + _CurrentContext = NULL; + _CurrentDevice = NULL; + } + + rglInitCompleted = 1; +} + +void rglPsglPlatformExit() +{ + RGLcontext* LContext = _CurrentContext; + if ( LContext ) + { + glFlush(); + + psglMakeCurrent( NULL, NULL ); + rglDeviceExit(); + rglPlatformExit(); + + _CurrentContext = NULL; + + rglInitCompleted = 0; + } +} + +RGL_EXPORT RGLdevice* rglPlatformCreateDeviceAuto( GLenum colorFormat, GLenum depthFormat, GLenum multisamplingMode ) +{ + RGLdeviceParameters parameters; + parameters.enable = RGL_DEVICE_PARAMETERS_COLOR_FORMAT | RGL_DEVICE_PARAMETERS_DEPTH_FORMAT | RGL_DEVICE_PARAMETERS_MULTISAMPLING_MODE; + parameters.colorFormat = colorFormat; + parameters.depthFormat = depthFormat; + parameters.multisamplingMode = multisamplingMode; + return psglCreateDeviceExtended( ¶meters ); +} + +RGL_EXPORT RGLdevice* rglPlatformCreateDeviceExtended( const RGLdeviceParameters *parameters ) +{ + RGLdevice *device = ( RGLdevice * )malloc( sizeof( RGLdevice ) + rglPlatformDeviceSize() ); + if ( !device ) + { + rglSetError( GL_OUT_OF_MEMORY ); + return NULL; + } + memset( device, 0, sizeof( RGLdevice ) + rglPlatformDeviceSize() ); + + // initialize fields + memcpy( &device->deviceParameters, parameters, sizeof( RGLdeviceParameters ) ); + + if (( parameters->enable & RGL_DEVICE_PARAMETERS_COLOR_FORMAT ) == 0 ) + { + device->deviceParameters.colorFormat = defaultParameters.colorFormat; + } + if (( parameters->enable & RGL_DEVICE_PARAMETERS_DEPTH_FORMAT ) == 0 ) + { + device->deviceParameters.depthFormat = defaultParameters.depthFormat; + } + if (( parameters->enable & RGL_DEVICE_PARAMETERS_MULTISAMPLING_MODE ) == 0 ) + { + device->deviceParameters.multisamplingMode = defaultParameters.multisamplingMode; + } + if (( parameters->enable & RGL_DEVICE_PARAMETERS_TV_STANDARD ) == 0 ) + { + device->deviceParameters.TVStandard = defaultParameters.TVStandard; + } + if (( parameters->enable & RGL_DEVICE_PARAMETERS_CONNECTOR ) == 0 ) + { + device->deviceParameters.connector = defaultParameters.connector; + } + if (( parameters->enable & RGL_DEVICE_PARAMETERS_BUFFERING_MODE ) == 0 ) + { + device->deviceParameters.bufferingMode = defaultParameters.bufferingMode; + } + if (( parameters->enable & RGL_DEVICE_PARAMETERS_WIDTH_HEIGHT ) == 0 ) + { + device->deviceParameters.width = defaultParameters.width; + device->deviceParameters.height = defaultParameters.height; + } + if (( parameters->enable & RGL_DEVICE_PARAMETERS_RESC_RENDER_WIDTH_HEIGHT ) == 0 ) + { + device->deviceParameters.renderWidth = defaultParameters.renderWidth; + device->deviceParameters.renderHeight = defaultParameters.renderHeight; + } + if (( parameters->enable & RGL_DEVICE_PARAMETERS_RESC_RATIO_MODE ) == 0 ) + { + device->deviceParameters.rescRatioMode = defaultParameters.rescRatioMode; + } + if (( parameters->enable & RGL_DEVICE_PARAMETERS_RESC_PAL_TEMPORAL_MODE ) == 0 ) + { + device->deviceParameters.rescPalTemporalMode = defaultParameters.rescPalTemporalMode; + } + if (( parameters->enable & RGL_DEVICE_PARAMETERS_RESC_INTERLACE_MODE ) == 0 ) + { + device->deviceParameters.rescInterlaceMode = defaultParameters.rescInterlaceMode; + } + if (( parameters->enable & RGL_DEVICE_PARAMETERS_RESC_ADJUST_ASPECT_RATIO ) == 0 ) + { + device->deviceParameters.horizontalScale = defaultParameters.horizontalScale; + device->deviceParameters.verticalScale = defaultParameters.verticalScale; + } + + device->rasterDriver = NULL; + + // platform-specific initialization + // This creates the default framebuffer. + int result = rglPlatformCreateDevice( device ); + if ( result < 0 ) + { + free( device ); + return NULL; + } + return device; +} + +RGL_EXPORT GLfloat rglPlatformGetDeviceAspectRatio( const RGLdevice * device ) +{ + CellVideoOutState videoState; + cellVideoOutGetState(CELL_VIDEO_OUT_PRIMARY, 0, &videoState); + + switch (videoState.displayMode.aspect){ + case CELL_VIDEO_OUT_ASPECT_4_3: return 4.0f/3.0f; + case CELL_VIDEO_OUT_ASPECT_16_9: return 16.0f/9.0f; + }; + + return 16.0f/9.0f; +} + +/*============================================================ + DEVICE CONTEXT INITIALIZATION + ============================================================ */ + +#define RGLGCM_DMA_PUSH_BUFFER_PREFETCH_PADDING 0x1000 // 4KB +#define RGLGCM_FIFO_SIZE (64<<10) // 64 kb + +// allocation handles +#define RGLGCM_CHANNEL_HANDLE_ID 0xFACE0001 +#define RGLGCM_FRAME_BUFFER_OBJECT_HANDLE_ID 0xFACE0002 +#define RGLGCM_HOST_BUFFER_OBJECT_HANDLE_ID 0xFACE0003 + +#define RGLGCM_PUSHBUF_MEMORY_HANDLE_ID 0xBEEF1000 +#define RGLGCM_HOST_NOTIFIER_MEMORY_HANDLE_ID 0xBEEF1001 +#define RGLGCM_VID_NOTIFIER_MEMORY_HANDLE_ID 0xBEEF1002 +#define RGLGCM_SEMAPHORE_MEMORY_HANDLE_ID 0xBEEF1003 + +// dma handles +#define RGLGCM_CHANNEL_DMA_SCRATCH_NOTIFIER 0xBEEF2000 +#define RGLGCM_CHANNEL_DMA_ERROR_NOTIFIER 0xBEEF2001 +#define RGLGCM_CONTEXT_DMA_MEMORY_FRAME_BUFFER 0xBEEF2002 +#define RGLGCM_CONTEXT_DMA_FROM_MEMORY_PUSHBUF 0xBEEF2003 +#define RGLGCM_CONTEXT_DMA_TO_MEMORY_GET_REPORT 0xBEEF2004 +#define RGLGCM_CONTEXT_DMA_MEMORY_HOST_BUFFER 0xBEEF2005 +#define RGLGCM_CONTEXT_DMA_MEMORY_SEMAPHORE_RW 0xBEEF2006 +#define RGLGCM_CONTEXT_DMA_MEMORY_SEMAPHORE_RO 0xBEEF2007 + +// clas contexts +#define RGLGCM_CURIE_PRIMITIVE 0xBEEF4097 +#define RGLGCM_MEM2MEM_HOST_TO_VIDEO 0xBBBB0000 +#define RGLGCM_IMAGEFROMCPU 0xBBBB1000 +#define RGLGCM_SCALEDIMAGE 0xBBBB1001 +#define RGLGCM_CONTEXT_2D_SURFACE 0xBBBB2000 +#define RGLGCM_CONTEXT_SWIZ_SURFACE 0xBBBB2001 + +int32_t rglOutOfSpaceCallback( struct CellGcmContextData* fifoContext, uint32_t spaceInWords ) +{ + // NOTE the fifo passed in is our very own rglGcmFifo.fifo + // but let's just make sure + rglGcmFifo * fifo = &rglGcmState_i.fifo; + + // make sure that the space requested will actually fit in to + // a single fifo block! + + // auto flush + cellGcmFlushUnsafeInline((CellGcmContextData*)fifo); + + uint32_t *nextbegin, *nextend, nextbeginoffset, nextendoffset; + + //printf(" rglOutOfSpaceCallback \n" ); + + fifo->updateLastGetRead(); + + + // If the current end isn't the same as the full fifo end we + // aren't at the end. Just go ahead and set the next begin and end + if(fifo->end != fifo->dmaPushBufferEnd) + { + //printf(" Next Block \n" ); + //printf(" b %p e %p c %p g %p \n", + // fifo->begin, fifo->end, fifo->current, fifo->lastGetRead ); + nextbegin = (uint32_t *)fifo->end + 1; + nextend = nextbegin + fifo->fifoBlockSize/sizeof(uint32_t) - 1; + + // printf(" Current RGL FIFO info \n" ); + // printf(" Fifo Begin %p End %p Current %p and Get %p \n", + // rglGcmState_i.fifo.begin, rglGcmState_i.fifo.end,rglGcmState_i.fifo.current,rglGcmState_i.fifo.lastGetRead ); + + // printf(" Last 10 words of the RGL Fifo from the ppu put/current position \n" ); + // rglPrintFifoFromPut( 10 ); + + } + // end up at fifo buffer + else + { + //printf(" Jump To First! \n" ); + //printf(" b %p e %p c %p g %p \n", + // fifo->begin, fifo->end, fifo->current, fifo->lastGetRead ); + nextbegin = (uint32_t *)fifo->dmaPushBufferBegin; + nextend = nextbegin + (fifo->fifoBlockSize)/sizeof(uint32_t) - 1; + } + + cellGcmAddressToOffset(nextbegin, &nextbeginoffset); + cellGcmAddressToOffset(nextend, &nextendoffset); + + //use this version so as not to trigger another callback + cellGcmSetJumpCommandUnsafeInline((CellGcmContextData*)fifo, nextbeginoffset); + + + //set up new context + fifo->begin = nextbegin; + fifo->current = nextbegin; + fifo->end = nextend; + + const GLuint nopsAtBegin = 8; + + //if Gpu busy with the new area, stall and flush + uint32_t get = fifo->dmaControl->Get; + + void * getEA = NULL; + + cellGcmIoOffsetToAddress( get, &getEA ); + + // We are going to stall on 3 things + // 1. If the get is still with in the new fifo block area + // 2. If the get is in gcm's initiazation fifo block + // 3. If the user stall call back returns RGL_STALL/true that + // 3A. the get is in one of their called SCB fifos AND 3B. the last call + // position in RGL's fifo is in the next block we want to jump to + // we have to stall... few! [RSTENSON] + while(((get >= nextbeginoffset) && (get <= nextendoffset)) + || ((0 <= get) && (get < 0x10000))) + { + // Don't be a ppu hog ;) + sys_timer_usleep(30); + get = fifo->dmaControl->Get; + cellGcmIoOffsetToAddress( get, &getEA ); + } + + // need to add some nops here at the beginning for a issue with the get and the put being at the + // same position when the fifo is in GPU memory. + for ( GLuint i = 0; i < nopsAtBegin; i++ ) + { + fifo->current[0] = RGLGCM_NOP(); + fifo->current++; + } + + return CELL_OK; +} + +void rglGcmDestroyRM( rglGcmResource* gcmResource ) +{ + if ( gcmResource->hostMemoryBase ) + free( gcmResource->hostMemoryBase ); + + memset(( void* )gcmResource, 0, sizeof( rglGcmResource ) ); + + return; +} + +void rglGcmGraphicsHandler( const uint32_t head ) +{ + // GCM will call this Graphics Handler if there is a channel error which + // can be caused by bad fifo commands, and GPU error, or GPU memory access. + + printf( "========================================\n" ); + printf( " RGL [rglGcmGraphicsHandler] \n" ); + printf( " GCM triggers this because of RSX error \n" ); + printf( " due to invalid Fifo Commands, \n" ); + printf( " invalid GPU state, or invalid memory access\n" ); + printf( "========================================\n" ); + + // print out the previous 10 words from the current position; + rglGcmState_i.fifo.updateLastGetRead(); + + // Dumping current fifo state + printf(" Current RGL FIFO info \n" ); + printf(" Fifo Begin %p End %p Current %p and Get %p \n", + rglGcmState_i.fifo.begin, + rglGcmState_i.fifo.end, + rglGcmState_i.fifo.current, + rglGcmState_i.fifo.lastGetRead ); + + printf(" Last 10 words of the RGL Fifo from the ppu put/current position \n" ); + rglPrintFifoFromPut( 10 ); + + printf(" Last 10 words of the RGL Fifo from the gpu get position \n" ); + rglPrintFifoFromGet( 10 ); +} + +extern GLboolean _psglDisableCompression; + +int rglGcmInitRM( rglGcmResource *gcmResource, unsigned int hostMemorySize, int inSysMem, unsigned int dmaPushBufferSize ) +{ + memset( gcmResource, 0, sizeof( rglGcmResource ) ); + + const unsigned int iDPM2DataAreaSize = 0; + + // XXX currently we need to decide how much host memory is needed before we know the GPU type + // It sucks because we don't know if the push buffer is in host memory or not. + // So, assume that it is... + dmaPushBufferSize = rglPad( dmaPushBufferSize, RGLGCM_HOST_BUFFER_ALIGNMENT ); + + // in case of host push buffer we need to add padding to avoid GPU push buffer prefetch to + // cause a problem fetching invalid addresses at the end of the push buffer. + gcmResource->hostMemorySize = rglPad( RGLGCM_FIFO_SIZE + hostMemorySize + dmaPushBufferSize + RGLGCM_DMA_PUSH_BUFFER_PREFETCH_PADDING + //+ iDPM2DataAreaSize, 1 << 20 ); // also need to add in the space needed for the report query locations + + iDPM2DataAreaSize + (RGLGCM_LM_MAX_TOTAL_QUERIES * sizeof( GLuint )), 1 << 20 ); + + if ( gcmResource->hostMemorySize > 0 ) + gcmResource->hostMemoryBase = (char *)memalign( 1 << 20, gcmResource->hostMemorySize ); + + // Initialize RSXIF + // 64 KB is minimum fifo size for libgpu (for now) + if (cellGcmInit( RGLGCM_FIFO_SIZE, gcmResource->hostMemorySize, gcmResource->hostMemoryBase ) != 0) + { + fprintf( stderr, "RSXIF failed initialization\n" ); + return GL_FALSE; + } + + cellGcmSetDebugOutputLevel( CELL_GCM_DEBUG_LEVEL2 ); + // set the rglGcm graphics error callback + cellGcmSetGraphicsHandler( &rglGcmGraphicsHandler ); + + // Get Gpu configuration + CellGcmConfig config; + cellGcmGetConfiguration( &config ); + + gcmResource->localAddress = ( char * )config.localAddress; + gcmResource->localSize = config.localSize; + gcmResource->MemoryClock = config.memoryFrequency; + gcmResource->GraphicsClock = config.coreFrequency; + + gcmResource->semaphores = ( rglGcmSemaphoreMemory * )cellGcmGetLabelAddress( 0 ); + gcmResource->dmaControl = ( char* ) cellGcmGetControlRegister() - (( char * ) & (( rglGcmControlDma* )0 )->Put - ( char * )0 ); + int hostPushBuffer = 0; + hostPushBuffer = 1; + + // the IOIF mapping don't work. work-around here. + for ( GLuint i = 0;i < 32;++i ) gcmResource->ioifMappings[i] = ( unsigned long long )( unsigned long )( gcmResource->localAddress + ( 64 << 20 ) * ( i / 4 ) ); + + cellGcmFinish( 1 ); // added just a constant value for now to adjust to the inline libgcm interface change + + if ( hostPushBuffer ) + { + gcmResource->hostMemorySize -= dmaPushBufferSize + RGLGCM_DMA_PUSH_BUFFER_PREFETCH_PADDING; + gcmResource->dmaPushBuffer = gcmResource->hostMemoryBase + gcmResource->hostMemorySize; + gcmResource->dmaPushBufferOffset = ( char * )gcmResource->dmaPushBuffer - ( char * )gcmResource->hostMemoryBase; + gcmResource->linearMemory = ( char* )0x0; + gcmResource->persistentMemorySize = gcmResource->localSize; + } + else + { + // Allocate Fifo at begining of vmem map + gcmResource->dmaPushBuffer = gcmResource->localAddress; + gcmResource->dmaPushBufferOffset = ( char * )gcmResource->dmaPushBuffer - ( char * )gcmResource->localAddress; + gcmResource->linearMemory = ( char* )0x0 + dmaPushBufferSize; + gcmResource->persistentMemorySize = gcmResource->localSize - dmaPushBufferSize; + } + gcmResource->dmaPushBufferSize = dmaPushBufferSize; + gcmResource->hostMemoryReserved = RGLGCM_FIFO_SIZE; + + // Set Jump command to our fifo structure + cellGcmSetJumpCommand(( char * )gcmResource->dmaPushBuffer - ( char * )gcmResource->hostMemoryBase ); + + // Set our Fifo functions + gCellGcmCurrentContext->callback = ( CellGcmContextCallback )rglOutOfSpaceCallback; + + + fprintf(stderr, "RGLGCM resource: MClk: %f Mhz NVClk: %f Mhz\n", ( float )gcmResource->MemoryClock / 1E6, ( float )gcmResource->GraphicsClock / 1E6 ); + fprintf(stderr, "RGLGCM resource: Video Memory: %i MB\n", gcmResource->localSize / ( 1024*1024 ) ); + fprintf(stderr, "RGLGCM resource: localAddress mapped at %p\n", gcmResource->localAddress ); + fprintf(stderr, "RGLGCM resource: push buffer at %p - %p (size = 0x%X), offset=0x%lx\n", + gcmResource->dmaPushBuffer, ( char* )gcmResource->dmaPushBuffer + gcmResource->dmaPushBufferSize, gcmResource->dmaPushBufferSize, gcmResource->dmaPushBufferOffset ); + fprintf(stderr, "RGLGCM resource: dma control at %p\n", gcmResource->dmaControl ); + + return 1; +} + +/*============================================================ + DEVICE CONTEXT IMPLEMENTATION + ============================================================ */ + +// tiled memory manager +typedef struct +{ + int id; + GLuint offset; + GLuint size; // 0 size indicates an unused tile + GLuint pitch; // in bytes + GLenum compression; + GLuint bank; + GLuint memory; // 0 for GPU, 1 for host +} rglTiledRegion; + +typedef struct +{ + rglTiledRegion region[RGLGCM_MAX_TILED_REGIONS]; +} +rglTiledMemoryManager; + + +// TODO: put in device state? +static rglTiledMemoryManager rglGcmTiledMemoryManager; + +static rglGcmResource rglGcmResource; + + +void rglGcmTiledMemoryInit( void ) +{ + rglTiledMemoryManager* mm = &rglGcmTiledMemoryManager; + int32_t retVal; + + memset( mm->region, 0, sizeof( mm->region ) ); + for ( int i = 0;i < RGLGCM_MAX_TILED_REGIONS;++i ) + retVal = cellGcmUnbindTile( i ); +} + +GLboolean rglPlatformDeviceInit( RGLinitOptions* options ) +{ + GLuint fifoSize = RGLGCM_FIFO_SIZE_DEFAULT; + GLuint hostSize = RGLGCM_HOST_SIZE_DEFAULT; + + if ( options != NULL ) + { + if ( options->enable & RGL_INIT_FIFO_SIZE ) + fifoSize = options->fifoSize; + if ( options->enable & RGL_INIT_HOST_MEMORY_SIZE ) + hostSize = options->hostMemorySize; + } + + if ( !rglGcmInitRM( &rglGcmResource, hostSize, 0, fifoSize ) ) + { + fprintf( stderr, "RM resource failed initialisation\n" ); + return GL_FALSE; + } + + return rglGcmInit( options, &rglGcmResource ); +} + + +void rglPlatformDeviceExit() +{ + rglGcmDestroy(); + rglGcmDestroyRM( &rglGcmResource ); +} + + +int rglPlatformDeviceSize() +{ + return sizeof( rglGcmDevice ); +} + + +void rglPlatformMakeCurrent( void *dev ) +{} + + +///////////////////////////////////////////////////////////////////////////// + +static unsigned int validPitch[] = +{ + 0x0200, + 0x0300, + 0x0400, + 0x0500, + 0x0600, + 0x0700, + 0x0800, + 0x0A00, + 0x0C00, + 0x0D00, + 0x0E00, + 0x1000, + 0x1400, + 0x1800, + 0x1A00, + 0x1C00, + 0x2000, + 0x2800, + 0x3000, + 0x3400, + 0x3800, + 0x4000, + 0x5000, + 0x6000, + 0x6800, + 0x7000, + 0x8000, + 0xA000, + 0xC000, + 0xD000, + 0xE000, + 0x10000, +}; +static const unsigned int validPitchCount = sizeof( validPitch ) / sizeof( validPitch[0] ); + +static unsigned int findValidPitch( unsigned int pitch ) +{ + if ( pitch <= validPitch[0] ) return validPitch[0]; + else + { + // dummy linear search + for ( GLuint i = 0;i < validPitchCount - 1;++i ) + { + if (( pitch > validPitch[i] ) && ( pitch <= validPitch[i+1] ) ) return validPitch[i+1]; + } + return validPitch[validPitchCount-1]; + } +} + +static GLboolean rglDuringDestroyDevice = GL_FALSE; + +// region update callback +// This callback is passed to rglGcmAllocCreateRegion to notify when the +// region is resized or deleted. +GLboolean rglGcmTryResizeTileRegion( GLuint address, GLuint size, void* data ) +{ + rglTiledRegion* region = ( rglTiledRegion* )data; + int32_t retVal = 0; + + // delete always succeeds + if ( size == 0 ) + { + region->offset = 0; + region->size = 0; + region->pitch = 0; + region->compression = CELL_GCM_COMPMODE_DISABLED; + region->memory = 0; + + if ( ! rglDuringDestroyDevice ) + { + // must wait until RSX is completely idle before calling cellGcmUnbindTile + rglGcmUtilWaitForIdle(); + + retVal = cellGcmUnbindTile( region->id ); + rglGcmFifoFinish( &rglGcmState_i.fifo ); + } + return GL_TRUE; + } + region->offset = address; + region->size = size; + + // must wait until RSX is completely idle before calling cellGcmSetTileInfo + rglGcmUtilWaitForIdle(); + + retVal = cellGcmSetTileInfo( + region->id, + region->memory, + region->offset, + region->size, + region->pitch, + CELL_GCM_COMPMODE_DISABLED, // if no tag bits, disable compression + 0, + region->bank ); + + retVal = cellGcmBindTile( region->id ); + + rglGcmFifoFinish( &rglGcmState_i.fifo ); + return GL_TRUE; +} + +void rglGcmGetTileRegionInfo( void* data, GLuint *address, GLuint *size ) +{ + rglTiledRegion* region = ( rglTiledRegion* )data; + + *address = region->offset; + *size = region->size; +} + +#define RGLGCM_TILED_BUFFER_ALIGNMENT 0x10000 // 64KB +#define RGLGCM_TILED_BUFFER_HEIGHT_ALIGNMENT 64 + +GLuint rglGcmAllocCreateRegion( + uint8_t memoryLocation, + GLboolean isZBuffer, + GLuint size, + GLint tag, + void* data ) +{ + uint32_t id = gmmAlloc((CellGcmContextData*)&rglGcmState_i.fifo, + memoryLocation, 1, size); + + if ( id != GMM_ERROR ) + { + if ( rglGcmTryResizeTileRegion( (GLuint)gmmIdToOffset(id), gmmGetBlockSize(id), data ) ) + gmmSetTileAttrib( id, tag, data ); + else + { + gmmFree( id ); + id = GMM_ERROR; + } + } + + return id; +} + +///////////////////////////////////////////////////////////////////////////// +// tiled surface allocation + +static void rglGcmAllocateTiledSurface( + rglTiledMemoryManager* mm, + GLboolean isLocalMemory, + GLboolean isZBuffer, + GLuint width, + GLuint height, + GLuint bitsPerPixel, + GLuint antiAliasing, + GLenum compression, + GLuint* id, + GLuint* pitchAllocated, + GLuint* bytesAllocated ) +{ + // XXX no compression on A01 silicon + // also disabled it if not on local memory + compression = CELL_GCM_COMPMODE_DISABLED; + + // determine pitch (in bytes) + const unsigned int pitch = width * bitsPerPixel / 8; + const unsigned int tiledPitch = findValidPitch( pitch ); + if ( tiledPitch < pitch ) + *pitchAllocated = rglPad( pitch, tiledPitch ); + else + *pitchAllocated = tiledPitch; + + // fix alignment + // Render targets must be aligned to 8*pitch from the start of their + // region. In addition, tiled regions must be aligned to 65536. In + // order to keep both requirements satisfied as the region is extended + // or shrunken, the allocation size is padded to the smallest common + // multiple. + // + // This can result in a fairly large percentage of wasted memory for + // certain dimension combinations, but this is simple and may conserve + // tiled region usage over some alternatives. + GLuint padSize = RGLGCM_TILED_BUFFER_ALIGNMENT; // 64KB + + while (( padSize % ( tiledPitch*8 ) ) != 0 ) + padSize += RGLGCM_TILED_BUFFER_ALIGNMENT; + + // determine allocation size + height = rglPad( height, RGLGCM_TILED_BUFFER_HEIGHT_ALIGNMENT ); + *bytesAllocated = rglPad(( *pitchAllocated ) * height, padSize ); + + // attempt to extend an existing region + // The region tag is a hash of the pitch, compression, and isZBuffer. + const GLuint tag = *pitchAllocated | compression | ( isZBuffer ? 0x80000000 : 0x0 ); + + *id = gmmAllocExtendedTileBlock(CELL_GCM_LOCATION_LOCAL, + *bytesAllocated, + tag); + + if ( *id == GMM_ERROR ) + { + // find an unused region + for ( int i = 0; i < RGLGCM_MAX_TILED_REGIONS; ++i ) + { + if ( mm->region[i].size == 0 ) + { + // assign a region + // Address and size will be set in the callback. + mm->region[i].id = i; + mm->region[i].pitch = *pitchAllocated; + mm->region[i].compression = compression; + mm->region[i].bank = isZBuffer ? 0x3 : 0x0; // XXX experiment + mm->region[i].memory = CELL_GCM_LOCATION_LOCAL; + + // allocate space for our region + *id = rglGcmAllocCreateRegion( + mm->region[i].memory, + isZBuffer, + *bytesAllocated, + tag, + &mm->region[i] ); + + break; + } + } // loop to find an unused region + } + + // if we don't have a valid id, give up + if ( *id == GMM_ERROR ) + { + *bytesAllocated = 0; + *pitchAllocated = 0; + } + else + { + //RGL_REPORT_EXTRA( RGL_REPORT_GPU_MEMORY_ALLOC, "Allocating GPU memory (tiled): %d bytes allocated at id 0x%08x", *bytesAllocated, *id ); + } +} + +///////////////////////////////////////////////////////////////////////////// +// color surface allocation + +GLboolean rglGcmAllocateColorSurface( + GLboolean isLocalMemory, + GLuint width, + GLuint height, + GLuint bitsPerPixel, + GLuint scanoutSupported, + GLuint antiAliasing, + GLuint *id, + GLuint *pitchAllocated, + GLuint *bytesAllocated ) +{ + rglTiledMemoryManager* mm = &rglGcmTiledMemoryManager; + + // compression type depends on antialiasing + GLenum compression = CELL_GCM_COMPMODE_DISABLED; + + rglGcmAllocateTiledSurface( + mm, + isLocalMemory, + GL_FALSE, // not a z buffer + width, height, bitsPerPixel, + antiAliasing, + compression, + id, + pitchAllocated, + bytesAllocated ); + + return *bytesAllocated > 0; +} + +void rglGcmFreeTiledSurface( GLuint bufferId ) +{ + gmmFree( bufferId ); +} + +///////////////////////////////////////////////////////////////////////////// +// video mode selection + +typedef struct +{ + int width; + int height; + unsigned char hwMode; +} +VideoMode; + +static const VideoMode sysutilModes[] = +{ + {720, 480, CELL_VIDEO_OUT_RESOLUTION_480}, + {720, 576, CELL_VIDEO_OUT_RESOLUTION_576}, + {1280, 720, CELL_VIDEO_OUT_RESOLUTION_720}, + {1920, 1080, CELL_VIDEO_OUT_RESOLUTION_1080}, +#if (OS_VERSION_NUMERIC >= 0x150) + {1600, 1080, CELL_VIDEO_OUT_RESOLUTION_1600x1080}, // hardware scales to 1920x1080 from 1600x1080 buffer + {1440, 1080, CELL_VIDEO_OUT_RESOLUTION_1440x1080}, // hardware scales to 1920x1080 from 1440x1080 buffer + {1280, 1080, CELL_VIDEO_OUT_RESOLUTION_1280x1080}, // hardware scales to 1920x1080 from 1280x1080 buffer + {960, 1080, CELL_VIDEO_OUT_RESOLUTION_960x1080}, // hardware scales to 1920x1080 from 960x1080 buffer +#endif +}; +static const int sysutilModeCount = sizeof( sysutilModes ) / sizeof( sysutilModes[0] ); + +static const VideoMode *findModeByResolutionInTable( int width, int height, const VideoMode *table, int modeCount ) +{ + for ( int i = 0;i < modeCount;++i ) + { + const VideoMode *vm = table + i; + if (( vm->width == width ) && ( vm->height == height ) ) return vm; + } + return NULL; +} + +static inline const VideoMode *findModeByResolution( int width, int height ) +{ + return findModeByResolutionInTable( width, height, sysutilModes, sysutilModeCount ); +} + +static const VideoMode *findModeByEnum( GLenum TVStandard ) +{ + const VideoMode *vm = NULL; + switch ( TVStandard ) + { + case RGL_TV_STANDARD_NTSC_M: + case RGL_TV_STANDARD_NTSC_J: + case RGL_TV_STANDARD_HD480P: + case RGL_TV_STANDARD_HD480I: + vm = &(sysutilModes[0]); + break; + case RGL_TV_STANDARD_PAL_M: + case RGL_TV_STANDARD_PAL_B: + case RGL_TV_STANDARD_PAL_D: + case RGL_TV_STANDARD_PAL_G: + case RGL_TV_STANDARD_PAL_H: + case RGL_TV_STANDARD_PAL_I: + case RGL_TV_STANDARD_PAL_N: + case RGL_TV_STANDARD_PAL_NC: + case RGL_TV_STANDARD_HD576I: + case RGL_TV_STANDARD_HD576P: + vm = &(sysutilModes[1]); + break; + case RGL_TV_STANDARD_HD720P: + case RGL_TV_STANDARD_1280x720_ON_VESA_1280x768: + case RGL_TV_STANDARD_1280x720_ON_VESA_1280x1024: + vm = &(sysutilModes[2]); + break; + case RGL_TV_STANDARD_HD1080I: + case RGL_TV_STANDARD_HD1080P: + case RGL_TV_STANDARD_1920x1080_ON_VESA_1920x1200: + vm = &(sysutilModes[3]); + break; + default: + vm = &(sysutilModes[2]); + break; // do nothing + } + + return vm; +} + +// XXX ugly global to be returned by the function +static VideoMode _sysutilDetectedVideoMode; + +const VideoMode *rglDetectVideoMode(void) +{ + CellVideoOutState videoState; + int ret = cellVideoOutGetState( CELL_VIDEO_OUT_PRIMARY, 0, &videoState ); + if ( ret < 0 ) + { + //RGL_REPORT_EXTRA( RGL_REPORT_ASSERT, "couldn't read the video configuration, using a default 720p resolution" ); + videoState.displayMode.scanMode = CELL_VIDEO_OUT_SCAN_MODE_PROGRESSIVE; + videoState.displayMode.resolutionId = CELL_VIDEO_OUT_RESOLUTION_720; + } + CellVideoOutResolution resolution; + cellVideoOutGetResolution( videoState.displayMode.resolutionId, &resolution ); + + _sysutilDetectedVideoMode.width = resolution.width; + _sysutilDetectedVideoMode.height = resolution.height; + _sysutilDetectedVideoMode.hwMode = videoState.displayMode.resolutionId; + return &_sysutilDetectedVideoMode; +} + +static void rescInit( const RGLdeviceParameters* params, rglGcmDevice *gcmDevice ) +{ + //RGL_REPORT_EXTRA(RGL_REPORT_RESC,"WARNING: RESC is enabled."); + GLboolean result = 0; + + CellRescBufferMode dstBufferMode; + if ( params->width == 720 && params->height == 480 ) dstBufferMode = CELL_RESC_720x480; + else if ( params->width == 720 && params->height == 576 ) dstBufferMode = CELL_RESC_720x576; + else if ( params->width == 1280 && params->height == 720 ) dstBufferMode = CELL_RESC_1280x720; + else if ( params->width == 1920 && params->height == 1080 ) dstBufferMode = CELL_RESC_1920x1080; + else + { + dstBufferMode = CELL_RESC_720x480; + fprintf( stderr, "Invalid display resolution for resolution conversion: %ux%u. Defaulting to 720x480...\n", params->width, params->height ); + } + + CellRescInitConfig conf; + memset( &conf, 0, sizeof( CellRescInitConfig ) ); + conf.size = sizeof( CellRescInitConfig ); + conf.resourcePolicy = CELL_RESC_MINIMUM_GPU_LOAD | CELL_RESC_CONSTANT_VRAM; + conf.supportModes = CELL_RESC_720x480 | CELL_RESC_720x576 | CELL_RESC_1280x720 | CELL_RESC_1920x1080; + conf.ratioMode = ( params->rescRatioMode == RESC_RATIO_MODE_FULLSCREEN ) ? CELL_RESC_FULLSCREEN : + ( params->rescRatioMode == RESC_RATIO_MODE_PANSCAN ) ? CELL_RESC_PANSCAN : + CELL_RESC_LETTERBOX; + conf.palTemporalMode = ( params->rescPalTemporalMode == RESC_PAL_TEMPORAL_MODE_60_DROP ) ? CELL_RESC_PAL_60_DROP : + ( params->rescPalTemporalMode == RESC_PAL_TEMPORAL_MODE_60_INTERPOLATE ) ? CELL_RESC_PAL_60_INTERPOLATE : + ( params->rescPalTemporalMode == RESC_PAL_TEMPORAL_MODE_60_INTERPOLATE_30_DROP ) ? CELL_RESC_PAL_60_INTERPOLATE_30_DROP : + ( params->rescPalTemporalMode == RESC_PAL_TEMPORAL_MODE_60_INTERPOLATE_DROP_FLEXIBLE ) ? CELL_RESC_PAL_60_INTERPOLATE_DROP_FLEXIBLE : + CELL_RESC_PAL_50; + conf.interlaceMode = ( params->rescInterlaceMode == RESC_INTERLACE_MODE_INTERLACE_FILTER ) ? CELL_RESC_INTERLACE_FILTER : + CELL_RESC_NORMAL_BILINEAR; + cellRescInit( &conf ); + + // allocate all the destination scanout buffers using the RGL memory manager + GLuint size; + GLuint colorBuffersPitch; + uint32_t numColorBuffers = cellRescGetNumColorBuffers( dstBufferMode, ( CellRescPalTemporalMode )conf.palTemporalMode, 0 ); + result = rglGcmAllocateColorSurface( GL_TRUE, params->width, params->height * numColorBuffers, + 4*8, RGLGCM_TRUE, 1, &(gcmDevice->RescColorBuffersId), &colorBuffersPitch, &size ); + + // set the destination buffer format and pitch + CellRescDsts dsts = { CELL_RESC_SURFACE_A8R8G8B8, colorBuffersPitch, 1 }; + cellRescSetDsts( dstBufferMode, &dsts ); + + // set the resc output display mode (destination format) + cellRescSetDisplayMode( dstBufferMode ); + + // allocate space for vertex array and fragment shader for drawing the rescaling texture-mapped quad + int32_t colorBuffersSize, vertexArraySize, fragmentShaderSize; + cellRescGetBufferSize( &colorBuffersSize, &vertexArraySize, &fragmentShaderSize ); + gcmDevice->RescVertexArrayId = gmmAlloc((CellGcmContextData*)&rglGcmState_i.fifo, + CELL_GCM_LOCATION_LOCAL, 0, vertexArraySize); + gcmDevice->RescFragmentShaderId = gmmAlloc((CellGcmContextData*)&rglGcmState_i.fifo, + CELL_GCM_LOCATION_LOCAL, 0, fragmentShaderSize); + + + // tell resc how to access the destination (scanout) buffer + cellRescSetBufferAddress( gmmIdToAddress(gcmDevice->RescColorBuffersId), + gmmIdToAddress(gcmDevice->RescVertexArrayId), + gmmIdToAddress(gcmDevice->RescFragmentShaderId) ); + + // scale to adjust for overscan + cellRescAdjustAspectRatio( params->horizontalScale, params->verticalScale ); + + // allocate an interlace table if interlace filtering is used + if ((params->enable & RGL_DEVICE_PARAMETERS_RESC_INTERLACE_MODE) && + (params->rescInterlaceMode == RESC_INTERLACE_MODE_INTERLACE_FILTER)) + { + const unsigned int tableLength = 32; // this was based on the guidelines in the resc reference guide + unsigned int tableSize = sizeof(uint16_t) * 4 * tableLength; // 2 bytes per FLOAT16 * 4 values per entry * length of table + void *interlaceTable = gmmIdToAddress(gmmAlloc((CellGcmContextData*)&rglGcmState_i.fifo, + CELL_GCM_LOCATION_LOCAL, 0, tableSize)); + int32_t errorCode = cellRescCreateInterlaceTable(interlaceTable,params->renderHeight,CELL_RESC_ELEMENT_HALF,tableLength); + (void)errorCode; + } +} + +// Semaphore for PPU wait +static sys_semaphore_t FlipSem; + +// A flip callback function to release semaphore and write a label to lock the GPU +static void rglFlipCallbackFunction(const uint32_t head) +{ + //printf("Flip callback: label value: %d -> 0\n", *labelAddress); + int res = sys_semaphore_post(FlipSem,1); + (void)res; // unused variable is ok +} + +// A label for GPU to skip VSYNC +static volatile uint32_t *labelAddress = NULL; +static const uint32_t WaitLabelIndex = 111; + +// VBlank callback function to write a label to release GPU +static void rglVblankCallbackFunction(const uint32_t head) +{ + (void)head; + int status = *labelAddress; + switch(status){ + case 2: + if (cellGcmGetFlipStatus()==0){ + cellGcmResetFlipStatus(); + *labelAddress=1; + } + break; + case 1: + *labelAddress = 0; + break; + default: + break; + // wait until rsx set the status to 2 + } +} + +// Resc version of VBlank callback function to write a label to release GPU +static void rglRescVblankCallbackFunction(const uint32_t head) +{ + (void)head; + int status = *labelAddress; + switch(status){ + case 2: + if (cellRescGetFlipStatus()==0){ + cellRescResetFlipStatus(); + *labelAddress=1; + } + break; + case 1: + *labelAddress = 0; + break; + default: + break; + // wait until rsx set the status to 2 + } +} + +///////////////////////////////////////////////////////////////////////////// +// create device + +static void rglSetDisplayMode( const VideoMode *vm, GLushort bitsPerPixel, GLuint pitch ) +{ + CellVideoOutConfiguration videocfg; + memset( &videocfg, 0, sizeof( videocfg ) ); + videocfg.resolutionId = vm->hwMode; + videocfg.format = ( bitsPerPixel == 32 ) ? CELL_VIDEO_OUT_BUFFER_COLOR_FORMAT_X8R8G8B8 : CELL_VIDEO_OUT_BUFFER_COLOR_FORMAT_R16G16B16X16_FLOAT; + videocfg.pitch = pitch; + videocfg.aspect = CELL_VIDEO_OUT_ASPECT_AUTO; + cellVideoOutConfigure( CELL_VIDEO_OUT_PRIMARY, &videocfg, NULL, 0 ); +} + +int rglPlatformCreateDevice( RGLdevice* device ) +{ + rglGcmDevice *gcmDevice = ( rglGcmDevice * )device->platformDevice; + RGLdeviceParameters* params = &device->deviceParameters; + rglDuringDestroyDevice = GL_FALSE; + GLboolean result = 0; + + // Tile memory manager init + rglGcmTiledMemoryInit(); + + const VideoMode *vm = NULL; + if ( params->enable & RGL_DEVICE_PARAMETERS_TV_STANDARD ) + { + vm = findModeByEnum( params->TVStandard ); + if ( !vm ) return -1; + params->width = vm->width; + params->height = vm->height; + } + else if ( params->enable & RGL_DEVICE_PARAMETERS_WIDTH_HEIGHT ) + { + vm = findModeByResolution( params->width, params->height ); + if ( !vm ) return -1; + } + else + { + vm = rglDetectVideoMode(); + if ( !vm ) return -1; + params->width = vm->width; + params->height = vm->height; + } + + // set render width and height to match the display width and height, unless resolution conversion is specified + if ( !(params->enable & RGL_DEVICE_PARAMETERS_RESC_RENDER_WIDTH_HEIGHT) ) + { + params->renderWidth = params->width; + params->renderHeight = params->height; + } + + if ( rescIsEnabled( params ) ) + { + rescInit( params, gcmDevice ); + } + + gcmDevice->deviceType = 0; + gcmDevice->TVStandard = params->TVStandard; + + // if resc enabled, vsync is always enabled + gcmDevice->vsync = rescIsEnabled( params ) ? GL_TRUE : GL_FALSE; + + gcmDevice->skipFirstVsync = GL_FALSE; + + gcmDevice->ms = NULL; + + const GLuint width = params->renderWidth; + const GLuint height = params->renderHeight; + + GLboolean fpColor = GL_FALSE; + switch ( params->colorFormat ) + { + case GL_RGBA16F_ARB: + fpColor = GL_TRUE; + break; + case GL_ARGB_SCE: + break; + // GL_RGBA ? + default: + return -1; + } + + GLuint antiAliasingMode=1; + + // create color buffers + // The default color buffer format is currently always ARGB8. + // single, double, or triple buffering + for ( int i = 0; i < params->bufferingMode; ++i ) + { + gcmDevice->color[i].source = RGLGCM_SURFACE_SOURCE_DEVICE; + gcmDevice->color[i].width = width; + gcmDevice->color[i].height = height; + gcmDevice->color[i].bpp = fpColor ? 8 : 4; + gcmDevice->color[i].format = RGLGCM_ARGB8; + gcmDevice->color[i].pool = RGLGCM_SURFACE_POOL_LINEAR; + + // allocate tiled memory + GLuint size; + result = rglGcmAllocateColorSurface( + GL_TRUE, // create in local memory + width, height, // dimensions + gcmDevice->color[i].bpp*8, // bits per sample + RGLGCM_TRUE, // scan out enable + antiAliasingMode, // antiAliasing + &gcmDevice->color[i].dataId, // returned buffer + &gcmDevice->color[i].pitch, + &size ); + } + + memset( &gcmDevice->rt, 0, sizeof( rglGcmRenderTargetEx ) ); + gcmDevice->rt.colorBufferCount = 1; + gcmDevice->rt.yInverted = GL_TRUE; + gcmDevice->rt.width = width; + gcmDevice->rt.height = height; + + rglGcmFifoGlViewport( 0, 0, width, height ); + rglGcmFifoGlClearColor( 0.f, 0.f, 0.f, 0.f ); + + if ( fpColor ) + { + // we don't yet have a fragment program to clear the buffer with a quad. + // so we'll cheat pretending we have a RGBA buffer with twice the width. + // Since we clear with 0 (which is the same in fp16), it works. + + gcmDevice->rt.width = 2 * width; + gcmDevice->rt.colorFormat = RGLGCM_ARGB8; + for ( int i = 0; i < params->bufferingMode; ++i ) + { + gcmDevice->rt.colorId[0] = gcmDevice->color[i].dataId; + gcmDevice->rt.colorPitch[0] = gcmDevice->color[i].pitch; + rglGcmFifoGlSetRenderTarget( &gcmDevice->rt ); + rglGcmFifoGlClear( RGLGCM_COLOR_BUFFER_BIT ); + } + // restore parameters + gcmDevice->rt.width = width; + gcmDevice->rt.colorFormat = gcmDevice->color[0].format; + } + else + { + // clear the buffers for compression to work best + gcmDevice->rt.colorFormat = RGLGCM_ARGB8; + for ( int i = 0; i < params->bufferingMode; ++i ) + { + gcmDevice->rt.colorId[0] = gcmDevice->color[i].dataId; + gcmDevice->rt.colorPitch[0] = gcmDevice->color[i].pitch; + rglGcmFifoGlSetRenderTarget( &gcmDevice->rt ); + rglGcmFifoGlClear( RGLGCM_COLOR_BUFFER_BIT ); + } + } + + gcmDevice->scanBuffer = 0; + if ( params->bufferingMode == RGL_BUFFERING_MODE_SINGLE ) + gcmDevice->drawBuffer = 0; + else if ( params->bufferingMode == RGL_BUFFERING_MODE_DOUBLE ) + gcmDevice->drawBuffer = 1; + else if ( params->bufferingMode == RGL_BUFFERING_MODE_TRIPLE ) + gcmDevice->drawBuffer = 2; + + + // Create semaphore + sys_semaphore_attribute_t attr;//todo: configure + sys_semaphore_attribute_initialize(attr); + + // Set initial and max count of semaphore based on buffering mode + sys_semaphore_value_t initial_val = 0; + sys_semaphore_value_t max_val = 1; + switch (device->deviceParameters.bufferingMode) + { + case RGL_BUFFERING_MODE_SINGLE: + initial_val = 0; + max_val = 1; + break; + case RGL_BUFFERING_MODE_DOUBLE: + initial_val = 1; + max_val = 2; + break; + case RGL_BUFFERING_MODE_TRIPLE: + initial_val = 2; + max_val = 3; + break; + default: + break; + } + + int res = sys_semaphore_create(&FlipSem, &attr, initial_val, max_val); + (void)res; // unused variable is ok + + // Register flip callback + if ( rescIsEnabled( params ) ) + cellRescSetFlipHandler(rglFlipCallbackFunction); + else + cellGcmSetFlipHandler(rglFlipCallbackFunction); + + // Initialize label by getting address + labelAddress = (volatile uint32_t *)cellGcmGetLabelAddress(WaitLabelIndex); + *labelAddress = 0; + + // Regiter VBlank callback + if ( rescIsEnabled( params ) ) + cellRescSetVBlankHandler(rglRescVblankCallbackFunction); + else + cellGcmSetVBlankHandler(rglVblankCallbackFunction); + + if ( rescIsEnabled( params ) ) + { + for ( int i = 0; i < params->bufferingMode; ++i ) // bufferingMode should always be single, but for now.... + { + // Set the RESC CellRescSrc buffer (source buffer to scale - psgl's render target): + // **NOT SURE WHAT TO DO ABOUT FP BUFFERS YET** case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT for fp16 + + CellRescSrc rescSrc = { CELL_GCM_TEXTURE_A8R8G8B8 | CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_NR, // uint8_t format + gcmDevice->color[i].pitch, // uint32_t pitch + width, // uint16_t width + height, // uint16_t height + gmmIdToOffset( gcmDevice->color[i].dataId ) }; // uint32_t offset + + if ( cellRescSetSrc( i, &rescSrc ) != CELL_OK ) + { + fprintf( stderr, "Registering display buffer %d failed\n", i ); + return -1; + } + } + } + else + { + rglSetDisplayMode( vm, gcmDevice->color[0].bpp*8, gcmDevice->color[0].pitch ); + + cellGcmSetFlipMode( gcmDevice->vsync ? CELL_GCM_DISPLAY_VSYNC : CELL_GCM_DISPLAY_HSYNC ); + rglpFifoGlFinish(); + + for ( int i = 0; i < params->bufferingMode; ++i ) + { + if ( cellGcmSetDisplayBuffer( i, gmmIdToOffset( gcmDevice->color[i].dataId ), gcmDevice->color[i].pitch , width, height ) != CELL_OK ) + { + fprintf( stderr, "Registering display buffer %d failed\n", i ); + return -1; + } + } + } + + rglGcmFifoGlIncFenceRef( &gcmDevice->swapFifoRef ); + + //swapFifoRef2 used for triple buffering + gcmDevice->swapFifoRef2 = gcmDevice->swapFifoRef; + + return 0; +} + +void rglPlatformDestroyDevice( RGLdevice* device ) +{ + rglGcmDevice *gcmDevice = ( rglGcmDevice * )device->platformDevice; + RGLdeviceParameters* params = &device->deviceParameters; + + rglpFifoGlFinish(); + + // Stop flip callback + if ( rescIsEnabled( params ) ) + cellRescSetFlipHandler(NULL); + else + cellGcmSetFlipHandler(NULL); + + // Stop VBlank callback + if ( rescIsEnabled( &device->deviceParameters ) ) + cellRescSetVBlankHandler(NULL); + else + cellGcmSetVBlankHandler(NULL); + + // Destroy semaphore + int res = sys_semaphore_destroy(FlipSem); + (void)res; // prevent unused variable warning in opt build + + if ( rescIsEnabled( params ) ) + { + cellRescExit(); + rglGcmFreeTiledSurface(gcmDevice->RescColorBuffersId); + gmmFree(gcmDevice->RescVertexArrayId); + gmmFree(gcmDevice->RescFragmentShaderId); + } + + rglDuringDestroyDevice = GL_TRUE; + for ( int i = 0; i < params->bufferingMode; ++i ) + { + if ( gcmDevice->color[i].pool != RGLGCM_SURFACE_POOL_NONE ) + rglGcmFreeTiledSurface( gcmDevice->color[i].dataId ); + } + rglDuringDestroyDevice = GL_FALSE; +} + +void rglPlatformSwapBuffers( RGLdevice* device ) +{ + gmmUpdateFreeList(CELL_GCM_LOCATION_LOCAL); + + rglGcmDevice *gcmDevice = (rglGcmDevice *)device->platformDevice; + + const GLuint drawBuffer = gcmDevice->drawBuffer; + + GLboolean vsync = _CurrentContext->VSync; + if ( vsync != gcmDevice->vsync ) + { + if ( ! rescIsEnabled( &device->deviceParameters ) ) + { + cellGcmSetFlipMode( vsync ? CELL_GCM_DISPLAY_VSYNC : CELL_GCM_DISPLAY_HSYNC ); + gcmDevice->vsync = vsync; + } + } + + if ( device->deviceParameters.bufferingMode == RGL_BUFFERING_MODE_TRIPLE ) + { + if ( rescIsEnabled( &device->deviceParameters ) ) + cellRescSetWaitFlip(); // GPU will wait until flip actually occurs + else + cellGcmSetWaitFlip(); // GPU will wait until flip actually occurs + } + + if ( rescIsEnabled( &device->deviceParameters ) ) + { + int32_t res = cellRescSetConvertAndFlip(( uint8_t ) drawBuffer ); + if ( res != CELL_OK ) + { + //RGL_REPORT_EXTRA(RGL_REPORT_RESC_FLIP_ERROR, "WARNING: RESC cellRescSetConvertAndFlip returned error code %d.\n", res); + if ( _CurrentContext ) _CurrentContext->needValidate |= RGL_VALIDATE_FRAMEBUFFER; + return; + } + } + else + cellGcmSetFlip((uint8_t)drawBuffer); + + if ( device->deviceParameters.bufferingMode != RGL_BUFFERING_MODE_TRIPLE ) + { + if ( rescIsEnabled( &device->deviceParameters ) ) + cellRescSetWaitFlip(); // GPU will wait until flip actually occurs + else + cellGcmSetWaitFlip(); // GPU will wait until flip actually occurs + } + + const char * __restrict v = rglGetGcmDriver()->sharedVPConstants; + GCM_FUNC( cellGcmSetVertexProgramParameterBlock, 0, 8, ( float* )v ); // GCM_PORT_UNTESTED [KHOFF] + + rglGcmFifoGlEnable( RGLGCM_DITHER ); + rglInvalidateAllStates( _CurrentContext ); + + rglGcmFifoGlFlush(); + + while (sys_semaphore_wait(FlipSem,1000) != CELL_OK); + + rglGcmFifoGlFlush(); + + if ( device->deviceParameters.bufferingMode == RGL_BUFFERING_MODE_DOUBLE ) + { + gcmDevice->drawBuffer = gcmDevice->scanBuffer; + gcmDevice->scanBuffer = drawBuffer; + + gcmDevice->rt.colorId[0] = gcmDevice->color[gcmDevice->drawBuffer].dataId; + gcmDevice->rt.colorPitch[0] = gcmDevice->color[gcmDevice->drawBuffer].pitch; + } + else if ( device->deviceParameters.bufferingMode == RGL_BUFFERING_MODE_TRIPLE ) + { + gcmDevice->drawBuffer = gcmDevice->scanBuffer; + + if ( gcmDevice->scanBuffer == 2 ) + gcmDevice->scanBuffer = 0; + else + gcmDevice->scanBuffer++; + + gcmDevice->rt.colorId[0] = gcmDevice->color[gcmDevice->drawBuffer].dataId; + gcmDevice->rt.colorPitch[0] = gcmDevice->color[gcmDevice->drawBuffer].pitch; + } +} + +void rglpValidateViewport(void) +{ + RGLcontext* LContext = _CurrentContext; + + rglGcmFifoGlViewport( + LContext->ViewPort.X, + LContext->ViewPort.Y, + LContext->ViewPort.XSize, + LContext->ViewPort.YSize, + LContext->DepthNear, + LContext->DepthFar); +} + +void rglpValidateBlending(void) +{ + RGLcontext* LContext = _CurrentContext; + + if ((LContext->Blending)) + { + GCM_FUNC( cellGcmSetBlendEnable, LContext->Blending ); + + rglGcmFifoGlBlendColor( + LContext->BlendColor.R, + LContext->BlendColor.G, + LContext->BlendColor.B, + LContext->BlendColor.A); + rglGcmFifoGlBlendEquation( + (rglGcmEnum)LContext->BlendEquationRGB, + (rglGcmEnum)LContext->BlendEquationAlpha); + rglGcmFifoGlBlendFunc((rglGcmEnum)LContext->BlendFactorSrcRGB,(rglGcmEnum)LContext->BlendFactorDestRGB,(rglGcmEnum)LContext->BlendFactorSrcAlpha,(rglGcmEnum)LContext->BlendFactorDestAlpha); + } +} + +void rglpValidateShaderSRGBRemap(void) +{ + RGLcontext* LContext = _CurrentContext; + GCM_FUNC( cellGcmSetFragmentProgramGammaEnable, LContext->ShaderSRGBRemap ? CELL_GCM_TRUE : CELL_GCM_FALSE); + LContext->needValidate &= ~RGL_VALIDATE_SHADER_SRGB_REMAP; +} + +#include "rgl_ps3_cg.cpp" diff --git a/console/rgl/src/ps3/rgl_ps3_cg.cpp b/console/rgl/src/ps3/rgl_ps3_cg.cpp new file mode 100644 index 0000000000..606a058fa0 --- /dev/null +++ b/console/rgl/src/ps3/rgl_ps3_cg.cpp @@ -0,0 +1,522 @@ +/* RetroArch - A frontend for libretro. + * RGL - An OpenGL subset wrapper library. + * Copyright (C) 2012 - Hans-Kristian Arntzen + * Copyright (C) 2012 - Daniel De Matteis + * + * RetroArch 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 Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch 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 RetroArch. + * If not, see . + */ + +#include "../rgl_cg.h" + +CGbool rglpSupportsVertexProgram( CGprofile p ) +{ + if ( p == CG_PROFILE_SCE_VP_TYPEB ) + return CG_TRUE; + if ( p == CG_PROFILE_SCE_VP_TYPEC ) + return CG_TRUE; + if ( p == CG_PROFILE_SCE_VP_RSX ) + return CG_TRUE; + return CG_FALSE; +} + +CGbool rglpSupportsFragmentProgram( CGprofile p ) +{ + if ( p == CG_PROFILE_SCE_FP_TYPEB ) + return CG_TRUE; + if ( CG_PROFILE_SCE_FP_RSX == p ) + return CG_TRUE; + return CG_FALSE; +} + +CGprofile rglpGetLatestProfile( CGGLenum profile_type ) +{ + switch ( profile_type ) + { + case CG_GL_VERTEX: + return CG_PROFILE_SCE_VP_RSX; + case CG_GL_FRAGMENT: + return CG_PROFILE_SCE_FP_RSX; + default: + break; + } + return CG_PROFILE_UNKNOWN; +} + +// uploads the given fp shader to gpu memory. Allocates if needed. +// This also builds the shared constants push buffer if needed, since it depends on the load address +static int rglpsLoadFPShader( _CGprogram *program ) +{ + unsigned int ucodeSize = program->header.instructionCount * 16; + if ( program->loadProgramId == GMM_ERROR ) + { + program->loadProgramId = gmmAlloc((CellGcmContextData*)&rglGcmState_i.fifo, + CELL_GCM_LOCATION_LOCAL, 0, ucodeSize); + program->loadProgramOffset = 0; + } + // always upload shader + rglGcmSend( program->loadProgramId, program->loadProgramOffset, 0, ( char* )program->ucode, ucodeSize ); + return GL_TRUE; +} + +static void rglpsUnloadFPShader(_CGprogram *program) +{ + if ( program->loadProgramId != GMM_ERROR ) + { + gmmFree( program->loadProgramId ); + program->loadProgramId = GMM_ERROR; + program->loadProgramOffset = 0; + } +} + +//new binary addition + +int rglGcmGenerateProgram( _CGprogram *program, int profileIndex, const CgProgramHeader *programHeader, const void *ucode, const CgParameterTableHeader *parameterHeader, + const CgParameterEntry *parameterEntries, const char *stringTable, const float *defaultValues ) +{ + // validate the input + CGprofile profile = ( CGprofile )programHeader->profile; + + int need_swapping = 0; + + //hack to counter removal of TypeC during beta + if ( profile == ( CGprofile )7005 ) + profile = CG_PROFILE_SCE_VP_RSX; + if ( profile == ( CGprofile )7006 ) + profile = CG_PROFILE_SCE_FP_RSX; + + // if can't match a known profile, the data may be in wrong endianness + if (( profile != CG_PROFILE_SCE_FP_TYPEB ) && ( profile != CG_PROFILE_SCE_VP_TYPEB ) && + ( profile != CG_PROFILE_SCE_FP_RSX ) && ( profile != CG_PROFILE_SCE_VP_RSX ) ) + { + need_swapping = 1; + } + + // check that this program block is of the right revision + // i.e. that the cgBinary.h header hasn't changed since it was + // compiled. + + // validate the profile + int invalidProfile = 0; + switch ( ENDIAN_32( profile, need_swapping ) ) + { + case CG_PROFILE_SCE_VP_TYPEB: + if ( profileIndex != VERTEX_PROFILE_INDEX ) invalidProfile = 1; + break; + case CG_PROFILE_SCE_FP_TYPEB: + if ( profileIndex != FRAGMENT_PROFILE_INDEX ) invalidProfile = 1; + break; + case CG_PROFILE_SCE_VP_RSX: + if ( profileIndex != VERTEX_PROFILE_INDEX ) invalidProfile = 1; + break; + case CG_PROFILE_SCE_FP_RSX: + if ( profileIndex != FRAGMENT_PROFILE_INDEX ) invalidProfile = 1; + break; + default: + invalidProfile = 1; + break; + } + if ( invalidProfile ) + { + rglCgRaiseError( CG_UNKNOWN_PROFILE_ERROR ); + return 0; + } + + memcpy( &program->header, programHeader, sizeof( program->header ) ); + + program->ucode = ucode; + program->loadProgramId = GMM_ERROR; + program->loadProgramOffset = 0; + program->inLocalMemory = true; + + + size_t parameterSize = parameterHeader->entryCount * sizeof( CgRuntimeParameter ); + void *memoryBlock; + if ( parameterSize ) + memoryBlock = memalign( 16, parameterSize ); + else + memoryBlock = NULL; + + program->rtParametersCount = parameterHeader->entryCount; + program->runtimeParameters = ( CgRuntimeParameter* )memoryBlock; + + if ( parameterEntries == NULL ) // the param entry can be supplied if not right after parameterHeader in memory, it happens when there's a program copy + parameterEntries = ( CgParameterEntry* )( parameterHeader + 1 ); + + program->parametersEntries = parameterEntries; + program->parameterResources = ( char* )( program->parametersEntries + program->rtParametersCount ); + program->resources = ( unsigned short* )(( char* )program->parametersEntries + ( parameterHeader->resourceTableOffset - sizeof( CgParameterTableHeader ) ) ); + program->defaultValuesIndexCount = parameterHeader->defaultValueIndexCount; + program->defaultValuesIndices = ( CgParameterDefaultValue* )(( char* )program->parametersEntries + ( parameterHeader->defaultValueIndexTableOffset - sizeof( CgParameterTableHeader ) ) ); + program->semanticCount = parameterHeader->semanticIndexCount; + program->semanticIndices = ( CgParameterSemantic* )( program->defaultValuesIndices + program->defaultValuesIndexCount ); + + program->defaultValues = NULL; + + memset( program->runtimeParameters, 0, parameterHeader->entryCount*sizeof( CgRuntimeParameter ) ); + + //string table + program->stringTable = stringTable; + //default values + program->defaultValues = defaultValues; + + rglCreatePushBuffer( program ); + if ( profileIndex == FRAGMENT_PROFILE_INDEX ) + rglSetDefaultValuesFP( program ); // modifies the ucode + else + rglSetDefaultValuesVP( program ); // modifies the push buffer + + // not loaded yet + program->loadProgramId = GMM_ERROR; + program->loadProgramOffset = 0; + if ( profileIndex == FRAGMENT_PROFILE_INDEX ) + { + // always load fragment shaders. + int loaded = rglpsLoadFPShader( program ); + if ( ! loaded ) + { + //TODO: what do we need to delete here ? + rglCgRaiseError( CG_MEMORY_ALLOC_ERROR ); + return 0; + } + } + + program->programGroup = NULL; + program->programIndexInGroup = -1; + + return 1; +} + +CGprogram rglpCgUpdateProgramAtIndex( CGprogramGroup group, int index, int refcount ) +{ + if ( index < ( int )group->programCount ) + { + //index can be < 0 , in that case refcount update on the group only, used when destroying a copied program + if ( index >= 0 ) + { + //if it has already been referenced duplicate instead of returning the same index, until the API offer a native support for + //group of programs ( //fixed bug 13007 ) + if ( refcount == 1 && group->programs[index].refCount == 1 ) + { + //it will handle the refcounting + CGprogram res = cgCopyProgram( group->programs[index].program ); + return res; + } + group->programs[index].refCount += refcount; + } + + group->refCount += refcount; + if ( refcount < 0 ) + { + if ( group->refCount == 0 && !group->userCreated ) + { + rglCgDestroyProgramGroup( group ); + } + return NULL; + } + else + return group->programs[index].program; + } + else + return NULL; +} + +//add the group to the context: +static void rglCgAddGroup( CGcontext ctx, CGprogramGroup group ) +{ + _CGcontext *context = _cgGetContextPtr( ctx ); + if ( !context->groupList ) + context->groupList = group; + else + { + _CGprogramGroup *current = context->groupList; + while ( current->next ) + current = current->next; + current->next = group; + } +} + +static void rglCgRemoveGroup( CGcontext ctx, CGprogramGroup group ) +{ + _CGcontext *context = _cgGetContextPtr( ctx ); + _CGprogramGroup *current = context->groupList; + _CGprogramGroup *previous = NULL; + while ( current && current != group ) + { + previous = current; + current = current->next; + } + if ( current ) + { + if ( !previous ) + context->groupList = current->next; + else + previous->next = current->next; + } +} + +CGprogramGroup rglCgCreateProgramGroupFromFile( CGcontext ctx, const char *group_file ) +{ + // check that file exists + FILE* fp = fopen( group_file, "rb" ); + + if ( NULL == fp ) + { + rglCgRaiseError( CG_FILE_READ_ERROR ); + return ( CGprogramGroup )NULL; + } + + // find the file length + size_t file_size = 0; + fseek( fp, 0, SEEK_END ); + file_size = ftell( fp ); + rewind( fp ); + + // alloc memory for new binary program and read the data + char* ptr = ( char* )malloc( file_size + 1 ); + if ( NULL == ptr ) + { + rglCgRaiseError( CG_MEMORY_ALLOC_ERROR ); + return ( CGprogramGroup )NULL; + } + + // read the entire file into memory then close the file + // TODO ********* just loading the file is a bit lame really. We can do better. + fread( ptr, file_size, 1, fp ); + fclose( fp ); + + CGprogramGroup group = rglCgCreateProgramGroup( ctx, group_file, ptr, file_size ); + if ( !group ) + free( ptr ); + + return group; +} + +CGprogramGroup rglCgCreateProgramGroup( CGcontext ctx, const char *name, void *ptr, int size ) +{ + _CGprogramGroup *group = NULL; + CGELFBinary elfBinary; + elfBinary.elfFile = NULL; + + while ( 1 ) + { + bool res = cgOpenElf( ptr, size, &elfBinary ); + if ( !res ) + break; + + size_t elfConstTableSize = ( size_t )elfBinary.consttabSize; + size_t elfStringTableSize = ( size_t )elfBinary.strtabSize; + + //first pass to get the size of each item ( could be faster if the embedded constants index table size was in the header + int programCount = elfBinary.shadertabSize / sizeof( CgProgramHeader ); + int i; + + //structure of the memory buffer storing the group + size_t nvProgramNamesOffset = rglPad( sizeof( _CGprogramGroup ), sizeof( _CGnamedProgram ) ); //program name offset + size_t nvDefaultValuesTableOffset = rglPad( nvProgramNamesOffset + programCount * sizeof( _CGnamedProgram ), 16 );//shared default value table + + size_t nvStringTableOffset = nvDefaultValuesTableOffset + elfConstTableSize; //shared string table + size_t structureSize = nvStringTableOffset + elfStringTableSize;//total structure size + + //create the program group + group = ( CGprogramGroup )malloc( structureSize ); + if ( !group ) //out of memory + break; + + //fill the group structure + group->ctx = ctx; + group->next = NULL; + group->programCount = ( unsigned int )programCount; + group->constantTable = ( unsigned int * )(( char* )group + nvDefaultValuesTableOffset ); + group->stringTable = ( unsigned int * )(( char* )group + nvStringTableOffset ); + group->programs = ( _CGnamedProgram * )(( char* )group + nvProgramNamesOffset ); + group->userCreated = true; + group->refCount = 0; + group->filedata = ( char* )ptr; + if ( name ) + { + int len = strlen( name ); + group->name = ( char* )malloc( len + 1 ); + if ( !group->name )//out of memory + break; + strcpy( group->name, name ); + } + else + group->name = NULL; + + //copy the default values + if ( elfConstTableSize ) + memcpy(( char* )group + nvDefaultValuesTableOffset, elfBinary.consttab, elfConstTableSize ); + //copy the string table + if ( elfStringTableSize ) + memcpy(( char* )group + nvStringTableOffset, elfBinary.strtab, elfStringTableSize ); + + //add the group to the context: + rglCgAddGroup( ctx, group ); + + //create all the shaders contained in the package and add them to the group + for ( i = 0;i < ( int )group->programCount;i++ ) + { + CgProgramHeader *cgShader = ( CgProgramHeader* )elfBinary.shadertab + i; + + //hack to counter removal of TypeC during beta + if ( cgShader->profile == ( CGprofile )7005 ) + cgShader->profile = CG_PROFILE_SCE_VP_RSX; + if ( cgShader->profile == ( CGprofile )7006 ) + cgShader->profile = CG_PROFILE_SCE_FP_RSX; + + CGELFProgram elfProgram; + bool res = cgGetElfProgramByIndex( &elfBinary, i, &elfProgram ); + if ( !res ) + return false; + + //I reference the buffer passed as parameter here, so it will have to stay around + CgProgramHeader *programHeader = cgShader; + char *ucode = ( char * )elfProgram.texttab; + CgParameterTableHeader *parameterHeader = ( CgParameterTableHeader * )elfProgram.paramtab; + + const char *programName = getSymbolByIndexInPlace( elfBinary.symtab, elfBinary.symbolSize, elfBinary.symbolCount, elfBinary.symbolstrtab, i + 1 ); + group->programs[i].name = programName; + group->programs[i].program = rglCgCreateProgram( ctx, ( CGprofile )cgShader->profile, programHeader, ucode, parameterHeader, ( const char* )group->stringTable, ( const float* )group->constantTable ); + _CGprogram *cgProgram = _cgGetProgPtr( group->programs[i].program ); + cgProgram->programGroup = group; + cgProgram->programIndexInGroup = i; + group->programs[i].refCount = 0; + } + break; + } + + return group; +} + +void rglCgDestroyProgramGroup( CGprogramGroup group ) +{ + _CGprogramGroup *_group = ( _CGprogramGroup * )group; + for ( int i = 0;i < ( int )_group->programCount;i++ ) + { + //unlink the program + _CGprogram *cgProgram = _cgGetProgPtr( group->programs[i].program ); + cgProgram->programGroup = NULL; + cgDestroyProgram( _group->programs[i].program ); + } + free( _group->filedata ); + if ( _group->name ) + free( _group->name ); + + //remove the group from the group list + rglCgRemoveGroup( group->ctx, group ); + free( _group ); +} + +const char *rglCgGetProgramGroupName( CGprogramGroup group ) +{ + _CGprogramGroup *_group = ( _CGprogramGroup * )group; + return _group->name; +} + +int rglCgGetProgramIndex( CGprogramGroup group, const char *name ) +{ + int i; + for ( i = 0;i < ( int )group->programCount;i++ ) + { + if ( !strcmp( name, group->programs[i].name ) ) + return i; + } + return -1; +} + +void rglpProgramErase( _CGprogram* platformProgram ) +{ + _CGprogram* program = ( _CGprogram* )platformProgram; + + if ( program->loadProgramId != GMM_ERROR ) + rglpsUnloadFPShader( program ); + + //free the runtime parameters + if ( program->runtimeParameters ) + { + //need to erase all the program parameter "names" + int i; + int count = ( int )program->rtParametersCount; + + for ( i = 0; i < count;i++ ) + rglEraseName( &_CurrentContext->cgParameterNameSpace, (unsigned int)program->runtimeParameters[i].id ); + + free( program->runtimeParameters ); + } + + //free the push buffer block + if ( program->memoryBlock ) + free( program->memoryBlock ); + + //free the samplers lookup tables + if ( program->samplerIndices ) + { + free( program->samplerValuesLocation ); + free( program->samplerIndices ); + free( program->samplerUnits ); + } + + //free the "pointers" on the push buffer used for fast access + if ( program->constantPushBufferPointers ) + free( program->constantPushBufferPointers ); +} + +//TODO: use a ref mechanism for the string table or duplicate it ! +int rglpCopyProgram( _CGprogram* source, _CGprogram* destination ) +{ + //extract the layout of the parameter buffers from the source + CgParameterTableHeader parameterHeader; + parameterHeader.entryCount = source->rtParametersCount; + parameterHeader.resourceTableOffset = ( uintptr_t )(( char* )source->resources - ( char* )source->parametersEntries + sizeof( CgParameterTableHeader ) ); + parameterHeader.defaultValueIndexCount = source->defaultValuesIndexCount; + parameterHeader.defaultValueIndexTableOffset = ( uintptr_t )(( char* )source->defaultValuesIndices - ( char* )source->parametersEntries + sizeof( CgParameterTableHeader ) ); + parameterHeader.semanticIndexCount = source->semanticCount; + parameterHeader.semanticIndexTableOffset = ( uintptr_t )(( char* )source->defaultValuesIndices - ( char* )source->parametersEntries + sizeof( CgParameterTableHeader ) ); + + int profileIndex; + + //allocate the copy of the program + switch ( source->header.profile ) + { + case CG_PROFILE_SCE_VP_TYPEB: + case CG_PROFILE_SCE_VP_RSX: + profileIndex = VERTEX_PROFILE_INDEX; + break; + + case CG_PROFILE_SCE_FP_TYPEB: + case CG_PROFILE_SCE_FP_RSX: + profileIndex = FRAGMENT_PROFILE_INDEX; + break; + default: + return 0; + } + return rglGcmGenerateProgram( destination, profileIndex, &source->header, source->ucode, ¶meterHeader, source->parametersEntries, source->stringTable, source->defaultValues ); +} + +int rglpGenerateVertexProgram( _CGprogram *program, + const CgProgramHeader *programHeader, const void *ucode, + const CgParameterTableHeader *parameterHeader, const char *stringTable, + const float *defaultValues ) +{ + // we currently have the same interface for vertex and fragment programs. + return rglGcmGenerateProgram( program, VERTEX_PROFILE_INDEX, programHeader, + ucode, parameterHeader, NULL, stringTable, defaultValues ); + +} + +int rglpGenerateFragmentProgram( _CGprogram *program, const CgProgramHeader *programHeader, const void *ucode, + const CgParameterTableHeader *parameterHeader, const char *stringTable, const float *defaultValues ) +{ + // we currently have the same interface for vertex and fragment programs. + return rglGcmGenerateProgram( program, FRAGMENT_PROFILE_INDEX, programHeader, ucode, parameterHeader, NULL, stringTable, defaultValues ); + +} diff --git a/console/rgl/src/ps3/rgl_ps3_raster.cpp b/console/rgl/src/ps3/rgl_ps3_raster.cpp new file mode 100644 index 0000000000..29e7e21322 --- /dev/null +++ b/console/rgl/src/ps3/rgl_ps3_raster.cpp @@ -0,0 +1,3079 @@ +/* RetroArch - A frontend for libretro. + * RGL - An OpenGL subset wrapper library. + * Copyright (C) 2010-2012 - Hans-Kristian Arntzen + * Copyright (C) 2011-2012 - Daniel De Matteis + * + * RetroArch 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 Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch 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 RetroArch. + * If not, see . + */ + +#include "../rgl.h" + +#include "include/GmmAlloc.h" +#include "include/rgl-constants.h" +#include "include/rgl-typedefs.h" +#include "include/rgl-externs.h" +#include "include/rgl-inline.h" + +#include +#include +#include + +#include +#include +#include +#include + +using namespace cell::Gcm; + +/*============================================================ + MEMORY MANAGER + ============================================================ */ + +#if RGL_ENDIAN == RGL_BIG_ENDIAN +#define ENDIAN_32(X, F) ((F) ? endianSwapWord(X) : (X)) +#else +#define ENDIAN_32(X, F) (X) +#endif + +int _parameterAlloc = 0; +int _ucodeAlloc = 0; + +int rglGetTypeResource( _CGprogram* program, unsigned short typeIndex, short *resourceIndex ); +int rglGetTypeResourceID( _CGprogram* program, unsigned short typeIndex ); +int rglGetTypeResourceRegisterCountVP( _CGprogram* program, short resourceIndex, int resourceCount, unsigned short *resource ); + +static void setAttribConstantIndex( CgRuntimeParameter* __restrict ptr, const void* __restrict v, const int ) // index +{ + // XXX not sure why it was testing unused res + _CGprogram *program = ptr->program; + const CgParameterResource *parameterResource = rglGetParameterResource( program, ptr->parameterEntry ); + GLuint index = parameterResource->resource - CG_ATTR0; + float * f = ( float* ) v; + rglVertexAttrib4fNV( index, f[0], f[1], f[2], f[3] ); +} + +void rglPlatformSetVertexRegister4fv( unsigned int reg, const float * __restrict v ) +{ + // save to shared memory for context restore after flip + __builtin_memcpy( rglGetGcmDriver()->sharedVPConstants + reg*4*sizeof( float ), v, 4*sizeof( float ) ); + + GCM_FUNC( cellGcmSetVertexProgramParameterBlock, reg, 1, v ); +} + +// endian swapping of the fragment uniforms, if necessary +#if RGL_ENDIAN == RGL_BIG_ENDIAN +#define SWAP_IF_BIG_ENDIAN(arg) endianSwapWordByHalf(arg) +#elif RGL_ENDIAN == RGL_LITTLE_ENDIAN +#define SWAP_IF_BIG_ENDIAN(arg) arg +#else +#error include missing for endianness +#endif + +//here ec has been advanced and is already on top of the embedded constant count +template inline static void swapandsetfp( int ucodeSize, unsigned int loadProgramId, unsigned int loadProgramOffset, unsigned short *ec, const unsigned int * __restrict v ) +{ + //unsigned int v2[4]; + //for (long i=0; i < SIZE; ++i) + //{ + // v2[i] = SWAP_IF_BIG_ENDIAN(v[i]); + //} + GCM_FUNC( cellGcmSetTransferLocation, CELL_GCM_LOCATION_LOCAL ); + unsigned short count = *( ec++ ); + for ( unsigned long offsetIndex = 0; offsetIndex < count; ++offsetIndex ) + { + void *pointer=NULL; + const int paddedSIZE = (SIZE + 1) & ~1; // even width only + GCM_FUNC( cellGcmSetInlineTransferPointer, gmmIdToOffset( loadProgramId ) + loadProgramOffset + *( ec++ ), paddedSIZE, &pointer); + float *fp = (float*)pointer; + float *src = (float*)v; + for (uint32_t j=0; j static void setVectorTypefp( CgRuntimeParameter* __restrict ptr, const void* __restrict v ) +{ + float * __restrict f = ( float* )v; + float * __restrict data = ( float* )ptr->pushBufferPointer;/*(float*)ptr->offset*;*/ + for ( long i = 0; i < SIZE; ++i ) //TODO: ced: find out if this loop for the get or for the reset in a future use of the same shader or just for the alignment??? + data[i] = f[i]; + _CGprogram *program = ptr->program; + + CgParameterResource *parameterResource = rglGetParameterResource( ptr->program, ptr->parameterEntry ); + unsigned short resource = parameterResource->resource; + unsigned short *ec = ( unsigned short * )( ptr->program->resources ) + resource + 1;//+1 to skip the register + if ( RGL_LIKELY( *ec ) ) + { + swapandsetfp( program->header.instructionCount*16, program->loadProgramId, program->loadProgramOffset, ec, ( unsigned int * )data ); + } +} + +template static void setVectorTypeSharedfpIndex( CgRuntimeParameter* __restrict ptr, const void* __restrict v, const int /*index*/ ) +{ + RGLcontext * LContext = _CurrentContext; + rglGcmDriver *driver = rglGetGcmDriver(); + const CgParameterResource *parameterResource = rglGetParameterResource( ptr->program, ptr->parameterEntry ); + unsigned short resource = parameterResource->resource; + unsigned short sharedResource = *(( unsigned short * )( ptr->program->resources ) + resource ); + const unsigned int * __restrict vi = ( const unsigned int* )v; + + GLuint dstVidOffset = gmmIdToOffset( driver->sharedFPConstantsId ) + sharedResource * 16; + unsigned int values[4]; + values[0] = SWAP_IF_BIG_ENDIAN( vi[0] ); + values[1] = ( 1 < SIZE ) ? SWAP_IF_BIG_ENDIAN( vi[1] ) : 0; + values[2] = ( 2 < SIZE ) ? SWAP_IF_BIG_ENDIAN( vi[2] ) : 0; + values[3] = ( 3 < SIZE ) ? SWAP_IF_BIG_ENDIAN( vi[3] ) : 0; + GCM_FUNC( cellGcmInlineTransfer, dstVidOffset, values, 4, 0 ); + + LContext->needValidate |= RGL_VALIDATE_FRAGMENT_SHARED_CONSTANTS; + // XXX we don't care about 32bit wrapping, do we ? + ++LContext->LastFPConstantModification; +} + +template static void setVectorTypeSharedfpIndexArray( CgRuntimeParameter* __restrict ptr, const void* __restrict v, const int index ) +{ + RGLcontext * LContext = _CurrentContext; + rglGcmDriver *driver = rglGetGcmDriver(); + const CgParameterResource *parameterResource = rglGetParameterResource( ptr->program, ptr->parameterEntry ); + unsigned short resource = parameterResource->resource; + + //slow... skip the indices + unsigned short *sharedResourcePtr = (( unsigned short * )( ptr->program->resources ) + resource );//no +1 here, we want the register + int arrayIndex = index; + while ( arrayIndex ) //jump to the right index... this is slow + { + sharedResourcePtr += (( *sharedResourcePtr ) + 2 );////+1 for the register, +1 for the count, +count for the number of embedded consts + arrayIndex--; + } + unsigned short sharedResource = *sharedResourcePtr; + + const unsigned int * __restrict vi = ( const unsigned int* )v; + + GLuint dstVidOffset = gmmIdToOffset( driver->sharedFPConstantsId ) + sharedResource * 16; + unsigned int values[4]; + values[0] = SWAP_IF_BIG_ENDIAN( vi[0] ); + values[1] = ( 1 < SIZE ) ? SWAP_IF_BIG_ENDIAN( vi[1] ) : 0; + values[2] = ( 2 < SIZE ) ? SWAP_IF_BIG_ENDIAN( vi[2] ) : 0; + values[3] = ( 3 < SIZE ) ? SWAP_IF_BIG_ENDIAN( vi[3] ) : 0; + GCM_FUNC( cellGcmInlineTransfer, dstVidOffset, values, 4, 0 ); + + LContext->needValidate |= RGL_VALIDATE_FRAGMENT_SHARED_CONSTANTS; + // XXX we don't care about 32bit wrapping, do we ? + ++LContext->LastFPConstantModification; +} +template static void setVectorTypeSharedvpIndex( CgRuntimeParameter* __restrict ptr, const void* __restrict v, const int /*index*/ ) +{ + const float * __restrict f = ( const float * __restrict )v; + const CgParameterResource *parameterResource = rglGetParameterResource( ptr->program, ptr->parameterEntry ); + unsigned short resource = parameterResource->resource; + float * __restrict dst = ( float * __restrict )ptr->pushBufferPointer; + for ( long i = 0; i < SIZE; ++ i ) + dst[i] = f[i]; + rglPlatformSetVertexRegister4fv( resource, dst ); +} + +template static void setVectorTypeSharedvpIndexArray( CgRuntimeParameter* __restrict ptr, const void* __restrict v, const int index ) +{ + const float * __restrict f = ( const float * __restrict )v; + const CgParameterResource *parameterResource = rglGetParameterResource( ptr->program, ptr->parameterEntry ); + unsigned short resource = parameterResource->resource + index; ///TODO: assume contiguous here , right ? + float * __restrict dst = ( float * __restrict )ptr->pushBufferPointer; + for ( long i = 0; i < SIZE; ++ i ) + dst[i] = f[i]; + rglPlatformSetVertexRegister4fv( resource, dst ); +} + + +// matrix uniforms +// note that Cg generated matrices are 1 row per binary param +// storage within the parameter is row major (so register setting is easier) + +//tmp array tentative + +#define ROW_MAJOR 0 +#define COL_MAJOR 1 + +template static void setVectorTypevpIndex( CgRuntimeParameter* __restrict ptr, const void* __restrict v, const int /*index*/ ) +{ + RGLcontext * LContext = _CurrentContext; + const float * __restrict f = ( const float* )v; + float * __restrict dst = ( float* )ptr->pushBufferPointer; + for ( long i = 0; i < SIZE; ++ i ) + dst[i] = f[i]; + LContext->needValidate |= RGL_VALIDATE_VERTEX_CONSTANTS; +} +template static void setVectorTypevpIndexArray( CgRuntimeParameter* __restrict ptr, const void* __restrict v, const int index ) +{ + RGLcontext * LContext = _CurrentContext; + const float * __restrict f = ( const float* )v; + float * __restrict dst = ( float* )( *(( unsigned int ** )ptr->pushBufferPointer + index ) ); + for ( long i = 0; i < SIZE; ++ i ) + dst[i] = f[i]; + LContext->needValidate |= RGL_VALIDATE_VERTEX_CONSTANTS; +} +template static void setVectorTypefpIndex( CgRuntimeParameter* __restrict ptr, const void* __restrict v, const int /*index*/ ) +{ + float * __restrict f = ( float* )v; + float * __restrict data = ( float* )ptr->pushBufferPointer;/*(float*)ptr->offset*;*/ + for ( long i = 0; i < SIZE; ++i ) //TODO: ced: find out if this loop for the get or for the reset in a future use of the same shader or just for the alignment??? + data[i] = f[i]; + _CGprogram *program = ptr->program; + + const CgParameterResource *parameterResource = rglGetParameterResource( program, ptr->parameterEntry ); + unsigned short resource = parameterResource->resource; + unsigned short *ec = ( unsigned short * )( ptr->program->resources ) + resource + 1; + if ( RGL_LIKELY( *ec ) ) + { + swapandsetfp( program->header.instructionCount*16, program->loadProgramId, program->loadProgramOffset, ec, ( unsigned int * )data ); + } +} +template static void setVectorTypefpIndexArray( CgRuntimeParameter* __restrict ptr, const void* __restrict v, const int index ) +{ + float * __restrict f = ( float* )v; + float * __restrict data = ( float* )ptr->pushBufferPointer;/*(float*)ptr->offset*;*/ + for ( long i = 0; i < SIZE; ++i ) //TODO: ced: find out if this loop for the get or for the reset in a future use of the same shader or just for the alignment??? + data[i] = f[i]; + _CGprogram *program = ptr->program; + + const CgParameterResource *parameterResource = rglGetParameterResource( program, ptr->parameterEntry ); + unsigned short resource = parameterResource->resource; + unsigned short *ec = ( unsigned short * )( program->resources ) + resource + 1; + int arrayIndex = index; + while ( arrayIndex ) //jump to the right index... this is slow + { + ec += (( *ec ) + 2 );//+1 for the register, +1 for the count, +count for the number of embedded consts + arrayIndex--; + } + if ( RGL_LIKELY( *ec ) ) + { + swapandsetfp( program->header.instructionCount*16, program->loadProgramId, program->loadProgramOffset, ec, ( unsigned int * )data ); + } +} + +//matrices +template static void setMatrixvpIndex( CgRuntimeParameter* __restrict ptr, const void* __restrict v, const int index ) +{ + RGLcontext * LContext = _CurrentContext; + float * __restrict f = ( float* )v; + float * __restrict dst = ( float* )ptr->pushBufferPointer; + for ( long row = 0; row < ROWS; ++row ) + { + for ( long col = 0; col < COLS; ++col ) + dst[row * 4 + col] = ( ORDER == ROW_MAJOR ) ? f[row * COLS + col] : f[col * ROWS + row]; + } + LContext->needValidate |= RGL_VALIDATE_VERTEX_CONSTANTS; +} + +template static void setMatrixSharedvpIndex( CgRuntimeParameter* __restrict ptr, const void* __restrict v, const int /*index*/ ) +{ + float * __restrict f = ( float* )v; + float * __restrict dst = ( float* )ptr->pushBufferPointer; + + const CgParameterResource *parameterResource = rglGetParameterResource( ptr->program, ptr->parameterEntry ); + unsigned short resource = parameterResource->resource; + + float tmp[ROWS*4]; + for ( long row = 0; row < ROWS; ++row ) + { + for ( long col = 0; col < COLS; ++col ) + { + tmp[row*4 + col] = dst[row * 4 + col] = ( ORDER == ROW_MAJOR ) ? f[row * COLS + col] : f[col * ROWS + row]; + } + for ( long col = COLS; col < 4; ++col ) tmp[row*4 + col] = dst[row*4+col]; + } + + GCM_FUNC( cellGcmSetVertexProgramParameterBlock, resource, ROWS, ( const float* )tmp ); +} + +template static void setMatrixSharedvpIndexArray( CgRuntimeParameter* __restrict ptr, const void* __restrict v, const int index ) +{ + float * __restrict f = ( float* )v; + float * __restrict dst = ( float* )ptr->pushBufferPointer; + + const CgParameterResource *parameterResource = rglGetParameterResource( ptr->program, ptr->parameterEntry ); + unsigned short resource = parameterResource->resource + index * ROWS; + + float tmp[ROWS*4]; + for ( long row = 0; row < ROWS; ++row ) + { + for ( long col = 0; col < COLS; ++col ) + { + tmp[row*4 + col] = dst[row * 4 + col] = ( ORDER == ROW_MAJOR ) ? f[row * COLS + col] : f[col * ROWS + row]; + } + for ( long col = COLS; col < 4; ++col ) tmp[row*4 + col] = dst[row*4+col]; + } + GCM_FUNC( cellGcmSetVertexProgramParameterBlock, resource, ROWS, tmp ); +} + +template static void setMatrixSharedfpIndex( CgRuntimeParameter* __restrict ptr, const void* __restrict v, const int /*index*/ ) +{ + rglGcmDriver *driver = rglGetGcmDriver(); + + const CgParameterResource *parameterResource = rglGetParameterResource( ptr->program, ptr->parameterEntry ); + unsigned short resource = parameterResource->resource; + unsigned short sharedResource = *(( unsigned short * )( ptr->program->resources ) + resource ); + + GLuint dstVidOffset = gmmIdToOffset( driver->sharedFPConstantsId ) + sharedResource * 16; + //we assume that the assignment is contiguous + const unsigned int * __restrict u = ( const unsigned int* )v; + + unsigned int tmp[ROWS*4]; + for ( long row = 0; row < ROWS; ++row ) + { + tmp[row*4 + 0] = (( ORDER == ROW_MAJOR ) ? u[row * COLS + 0] : u[0 * ROWS + row] ); + tmp[row*4 + 1] = (( 1 < COLS ) ? (( ORDER == ROW_MAJOR ) ? u[row * COLS + 1] : u[1 * ROWS + row] ) : 0 ); + tmp[row*4 + 2] = (( 2 < COLS ) ? (( ORDER == ROW_MAJOR ) ? u[row * COLS + 2] : u[2 * ROWS + row] ) : 0 ); + tmp[row*4 + 3] = (( 3 < COLS ) ? (( ORDER == ROW_MAJOR ) ? u[row * COLS + 3] : u[3 * ROWS + row] ) : 0 ); + } + GCM_FUNC( cellGcmSetTransferLocation, CELL_GCM_LOCATION_LOCAL ); + void *pointer=NULL; + GCM_FUNC( cellGcmSetInlineTransferPointer, dstVidOffset, 4*ROWS, &pointer); + float *fp = (float*)pointer; + float *src = (float*)tmp; + for (uint32_t j=0; jneedValidate |= RGL_VALIDATE_FRAGMENT_SHARED_CONSTANTS; + ++LContext->LastFPConstantModification; +} + +template static void setMatrixSharedfpIndexArray( CgRuntimeParameter* __restrict ptr, const void* __restrict v, const int index ) +{ + //TODO: double check for the semi endian swap... not done here, is it done by the RSX ? + rglGcmDriver *driver = rglGetGcmDriver(); + + const CgParameterResource *parameterResource = rglGetParameterResource( ptr->program, ptr->parameterEntry ); + unsigned short resource = parameterResource->resource; + //slow... skip the indices + unsigned short *sharedResourcePtr = (( unsigned short * )( ptr->program->resources ) + resource ); + int arrayIndex = index * ROWS; + while ( arrayIndex ) //jump to the right index... this is slow + { + sharedResourcePtr += (( *sharedResourcePtr ) + 2 );//+1 for the register, +1 for the count, +count for the number of embedded consts + arrayIndex--; + } + unsigned short sharedResource = *sharedResourcePtr; + + GLuint dstVidOffset = gmmIdToOffset( driver->sharedFPConstantsId ) + sharedResource * 16; + //we assume that the assignment is contiguous + const unsigned int * __restrict u = ( const unsigned int* )v; + + unsigned int tmp[ROWS*4]; + for ( long row = 0; row < ROWS; ++row ) + { + tmp[row*4 + 0] = (( ORDER == ROW_MAJOR ) ? u[row * COLS + 0] : u[0 * ROWS + row] ); + tmp[row*4 + 1] = (( 1 < COLS ) ? (( ORDER == ROW_MAJOR ) ? u[row * COLS + 1] : u[1 * ROWS + row] ) : 0 ); + tmp[row*4 + 2] = (( 2 < COLS ) ? (( ORDER == ROW_MAJOR ) ? u[row * COLS + 2] : u[2 * ROWS + row] ) : 0 ); + tmp[row*4 + 3] = (( 3 < COLS ) ? (( ORDER == ROW_MAJOR ) ? u[row * COLS + 3] : u[3 * ROWS + row] ) : 0 ); + } + + GCM_FUNC( cellGcmSetTransferLocation, CELL_GCM_LOCATION_LOCAL ); + + + void *pointer=NULL; + GCM_FUNC( cellGcmSetInlineTransferPointer, dstVidOffset, 4*ROWS, &pointer); + float *fp = (float*)pointer; + const float *src = (const float*)tmp; + for (uint32_t j=0; j<4*ROWS;j++) + { + *fp = cellGcmSwap16Float32(*src); + fp++;src++; + } + + RGLcontext * LContext = _CurrentContext; + LContext->needValidate |= RGL_VALIDATE_FRAGMENT_SHARED_CONSTANTS; + ++LContext->LastFPConstantModification; +} + +//TODO ?: check: //works only for the consecutive alloc... +template static void setMatrixvpIndexArray( CgRuntimeParameter* __restrict ptr, const void* __restrict v, const int index ) +{ + RGLcontext * LContext = _CurrentContext; + float * __restrict f = ( float* )v; + float * __restrict dst = ( float* )( *(( unsigned int ** )ptr->pushBufferPointer + index ) ); + for ( long row = 0; row < ROWS; ++row ) + { + for ( long col = 0; col < COLS; ++col ) + dst[row * 4 + col] = ( ORDER == ROW_MAJOR ) ? f[row * COLS + col] : f[col * ROWS + row]; + } + LContext->needValidate |= RGL_VALIDATE_VERTEX_CONSTANTS; +} +template static void setMatrixfpIndex( CgRuntimeParameter* __restrict ptr, const void* __restrict v, const int /*index*/ ) +{ + float * __restrict f = ( float* )v; + float * __restrict dst = ( float* )ptr->pushBufferPointer; + _CGprogram *program = (( CgRuntimeParameter* )ptr )->program; + const CgParameterResource *parameterResource = rglGetParameterResource( program, ptr->parameterEntry ); + unsigned short resource = parameterResource->resource; + unsigned short *ec = ( unsigned short * )program->resources + resource + 1; //+1 to skip the register + for ( long row = 0; row < ROWS; ++row ) + { + for ( long col = 0; col < COLS; ++col ) + dst[row * 4 + col] = ( ORDER == ROW_MAJOR ) ? f[row * COLS + col] : f[col * ROWS + row]; + int count = *ec; + if ( RGL_LIKELY( count ) ) + { + swapandsetfp( program->header.instructionCount*16, program->loadProgramId, program->loadProgramOffset, ec, ( unsigned int * )dst + row * 4 ); + } + ec += count + 2; //+1 for the register, +1 for the count, + count for the number of embedded consts + } +} +template static void setMatrixfpIndexArray( CgRuntimeParameter* __restrict ptr, const void* __restrict v, const int index ) +{ + float * __restrict f = ( float* )v; + float * __restrict dst = ( float* )ptr->pushBufferPointer; + _CGprogram *program = ptr->program; + const CgParameterResource *parameterResource = rglGetParameterResource( program, ptr->parameterEntry ); + unsigned short resource = parameterResource->resource; + unsigned short *ec = ( unsigned short * )program->resources + resource + 1;//+1 to skip the register + int arrayIndex = index * ROWS; + while ( arrayIndex ) //jump to the right index... this is slow + { + unsigned short count = ( *ec ); + ec += ( count + 2 ); //+1 for the register, +1 for the count, +count for the number of embedded consts + arrayIndex--; + } + for ( long row = 0; row < ROWS; ++row ) + { + for ( long col = 0; col < COLS; ++col ) + dst[row * 4 + col] = ( ORDER == ROW_MAJOR ) ? f[row * COLS + col] : f[col * ROWS + row]; + int count = *ec; + if ( RGL_LIKELY( count ) ) + { + swapandsetfp( program->header.instructionCount*16, program->loadProgramId, program->loadProgramOffset, ec, ( unsigned int * )dst + row * 4 ); + } + ec += count + 2;//+1 for the register, +1 for the count, +count for the number of embedded consts + } +} + +static _cgSetArrayIndexFunction setVectorTypeIndex[2][2][2][4] = +{ + { + { + {&setVectorTypevpIndex<1>, &setVectorTypevpIndex<2>, &setVectorTypevpIndex<3>, &setVectorTypevpIndex<4>, }, + {&setVectorTypefpIndex<1>, &setVectorTypefpIndex<2>, &setVectorTypefpIndex<3>, &setVectorTypefpIndex<4>, } + }, + { + {&setVectorTypeSharedvpIndex<1>, &setVectorTypeSharedvpIndex<2>, &setVectorTypeSharedvpIndex<3>, &setVectorTypeSharedvpIndex<4>, }, //should be the shared + {&setVectorTypeSharedfpIndex<1>, &setVectorTypeSharedfpIndex<2>, &setVectorTypeSharedfpIndex<3>, &setVectorTypeSharedfpIndex<4>, } //should be the shared + }, + }, + { + { + {&setVectorTypevpIndexArray<1>, &setVectorTypevpIndexArray<2>, &setVectorTypevpIndexArray<3>, &setVectorTypevpIndexArray<4>, }, + {&setVectorTypefpIndexArray<1>, &setVectorTypefpIndexArray<2>, &setVectorTypefpIndexArray<3>, &setVectorTypefpIndexArray<4>, } + }, + { + {&setVectorTypeSharedvpIndexArray<1>, &setVectorTypeSharedvpIndexArray<2>, &setVectorTypeSharedvpIndexArray<3>, &setVectorTypeSharedvpIndexArray<4>, }, //should be the shared + {&setVectorTypeSharedfpIndexArray<1>, &setVectorTypeSharedfpIndexArray<2>, &setVectorTypeSharedfpIndexArray<3>, &setVectorTypeSharedfpIndexArray<4>, } //should be the shared + }, + }, +}; + +static _cgSetArrayIndexFunction setMatrixTypeIndex[2][2][2][4][4][2] = +{ + { + { + { + {{ &setMatrixvpIndex<1, 1, 0>, &setMatrixvpIndex<1, 1, 1>}, { &setMatrixvpIndex<1, 2, 0>, &setMatrixvpIndex<1, 2, 1>}, { &setMatrixvpIndex<1, 3, 0>, &setMatrixvpIndex<1, 3, 1>}, { &setMatrixvpIndex<1, 4, 0>, &setMatrixvpIndex<1, 4, 1>}}, + {{ &setMatrixvpIndex<2, 1, 0>, &setMatrixvpIndex<2, 1, 1>}, { &setMatrixvpIndex<2, 2, 0>, &setMatrixvpIndex<2, 2, 1>}, { &setMatrixvpIndex<2, 3, 0>, &setMatrixvpIndex<2, 3, 1>}, { &setMatrixvpIndex<2, 4, 0>, &setMatrixvpIndex<2, 4, 1>}}, + {{ &setMatrixvpIndex<3, 1, 0>, &setMatrixvpIndex<3, 1, 1>}, { &setMatrixvpIndex<3, 2, 0>, &setMatrixvpIndex<3, 2, 1>}, { &setMatrixvpIndex<3, 3, 0>, &setMatrixvpIndex<3, 3, 1>}, { &setMatrixvpIndex<3, 4, 0>, &setMatrixvpIndex<3, 4, 1>}}, + {{ &setMatrixvpIndex<4, 1, 0>, &setMatrixvpIndex<4, 1, 1>}, { &setMatrixvpIndex<4, 2, 0>, &setMatrixvpIndex<4, 2, 1>}, { &setMatrixvpIndex<4, 3, 0>, &setMatrixvpIndex<4, 3, 1>}, { &setMatrixvpIndex<4, 4, 0>, &setMatrixvpIndex<4, 4, 1>}}, + }, + { + {{ &setMatrixfpIndex<1, 1, 0>, &setMatrixfpIndex<1, 1, 1>}, { &setMatrixfpIndex<1, 2, 0>, &setMatrixfpIndex<1, 2, 1>}, { &setMatrixfpIndex<1, 3, 0>, &setMatrixfpIndex<1, 3, 1>}, { &setMatrixfpIndex<1, 4, 0>, &setMatrixfpIndex<1, 4, 1>}}, + {{ &setMatrixfpIndex<2, 1, 0>, &setMatrixfpIndex<2, 1, 1>}, { &setMatrixfpIndex<2, 2, 0>, &setMatrixfpIndex<2, 2, 1>}, { &setMatrixfpIndex<2, 3, 0>, &setMatrixfpIndex<2, 3, 1>}, { &setMatrixfpIndex<2, 4, 0>, &setMatrixfpIndex<2, 4, 1>}}, + {{ &setMatrixfpIndex<3, 1, 0>, &setMatrixfpIndex<3, 1, 1>}, { &setMatrixfpIndex<3, 2, 0>, &setMatrixfpIndex<3, 2, 1>}, { &setMatrixfpIndex<3, 3, 0>, &setMatrixfpIndex<3, 3, 1>}, { &setMatrixfpIndex<3, 4, 0>, &setMatrixfpIndex<3, 4, 1>}}, + {{ &setMatrixfpIndex<4, 1, 0>, &setMatrixfpIndex<4, 1, 1>}, { &setMatrixfpIndex<4, 2, 0>, &setMatrixfpIndex<4, 2, 1>}, { &setMatrixfpIndex<4, 3, 0>, &setMatrixfpIndex<4, 3, 1>}, { &setMatrixfpIndex<4, 4, 0>, &setMatrixfpIndex<4, 4, 1>}}, + }, + }, + { //should be shared + { + {{ &setMatrixSharedvpIndex<1, 1, 0>, &setMatrixSharedvpIndex<1, 1, 1>}, { &setMatrixSharedvpIndex<1, 2, 0>, &setMatrixSharedvpIndex<1, 2, 1>}, { &setMatrixSharedvpIndex<1, 3, 0>, &setMatrixSharedvpIndex<1, 3, 1>}, { &setMatrixSharedvpIndex<1, 4, 0>, &setMatrixSharedvpIndex<1, 4, 1>}}, + {{ &setMatrixSharedvpIndex<2, 1, 0>, &setMatrixSharedvpIndex<2, 1, 1>}, { &setMatrixSharedvpIndex<2, 2, 0>, &setMatrixSharedvpIndex<2, 2, 1>}, { &setMatrixSharedvpIndex<2, 3, 0>, &setMatrixSharedvpIndex<2, 3, 1>}, { &setMatrixSharedvpIndex<2, 4, 0>, &setMatrixSharedvpIndex<2, 4, 1>}}, + {{ &setMatrixSharedvpIndex<3, 1, 0>, &setMatrixSharedvpIndex<3, 1, 1>}, { &setMatrixSharedvpIndex<3, 2, 0>, &setMatrixSharedvpIndex<3, 2, 1>}, { &setMatrixSharedvpIndex<3, 3, 0>, &setMatrixSharedvpIndex<3, 3, 1>}, { &setMatrixSharedvpIndex<3, 4, 0>, &setMatrixSharedvpIndex<3, 4, 1>}}, + {{ &setMatrixSharedvpIndex<4, 1, 0>, &setMatrixSharedvpIndex<4, 1, 1>}, { &setMatrixSharedvpIndex<4, 2, 0>, &setMatrixSharedvpIndex<4, 2, 1>}, { &setMatrixSharedvpIndex<4, 3, 0>, &setMatrixSharedvpIndex<4, 3, 1>}, { &setMatrixSharedvpIndex<4, 4, 0>, &setMatrixSharedvpIndex<4, 4, 1>}}, + }, + { + {{ &setMatrixSharedfpIndex<1, 1, 0>, &setMatrixSharedfpIndex<1, 1, 1>}, { &setMatrixSharedfpIndex<1, 2, 0>, &setMatrixSharedfpIndex<1, 2, 1>}, { &setMatrixSharedfpIndex<1, 3, 0>, &setMatrixSharedfpIndex<1, 3, 1>}, { &setMatrixSharedfpIndex<1, 4, 0>, &setMatrixSharedfpIndex<1, 4, 1>}}, + {{ &setMatrixSharedfpIndex<2, 1, 0>, &setMatrixSharedfpIndex<2, 1, 1>}, { &setMatrixSharedfpIndex<2, 2, 0>, &setMatrixSharedfpIndex<2, 2, 1>}, { &setMatrixSharedfpIndex<2, 3, 0>, &setMatrixSharedfpIndex<2, 3, 1>}, { &setMatrixSharedfpIndex<2, 4, 0>, &setMatrixSharedfpIndex<2, 4, 1>}}, + {{ &setMatrixSharedfpIndex<3, 1, 0>, &setMatrixSharedfpIndex<3, 1, 1>}, { &setMatrixSharedfpIndex<3, 2, 0>, &setMatrixSharedfpIndex<3, 2, 1>}, { &setMatrixSharedfpIndex<3, 3, 0>, &setMatrixSharedfpIndex<3, 3, 1>}, { &setMatrixSharedfpIndex<3, 4, 0>, &setMatrixSharedfpIndex<3, 4, 1>}}, + {{ &setMatrixSharedfpIndex<4, 1, 0>, &setMatrixSharedfpIndex<4, 1, 1>}, { &setMatrixSharedfpIndex<4, 2, 0>, &setMatrixSharedfpIndex<4, 2, 1>}, { &setMatrixSharedfpIndex<4, 3, 0>, &setMatrixSharedfpIndex<4, 3, 1>}, { &setMatrixSharedfpIndex<4, 4, 0>, &setMatrixSharedfpIndex<4, 4, 1>}}, + }, + }, + }, + { + { + { + {{ &setMatrixvpIndexArray<1, 1, 0>, &setMatrixvpIndexArray<1, 1, 1>}, { &setMatrixvpIndexArray<1, 2, 0>, &setMatrixvpIndexArray<1, 2, 1>}, { &setMatrixvpIndexArray<1, 3, 0>, &setMatrixvpIndexArray<1, 3, 1>}, { &setMatrixvpIndexArray<1, 4, 0>, &setMatrixvpIndexArray<1, 4, 1>}}, + {{ &setMatrixvpIndexArray<2, 1, 0>, &setMatrixvpIndexArray<2, 1, 1>}, { &setMatrixvpIndexArray<2, 2, 0>, &setMatrixvpIndexArray<2, 2, 1>}, { &setMatrixvpIndexArray<2, 3, 0>, &setMatrixvpIndexArray<2, 3, 1>}, { &setMatrixvpIndexArray<2, 4, 0>, &setMatrixvpIndexArray<2, 4, 1>}}, + {{ &setMatrixvpIndexArray<3, 1, 0>, &setMatrixvpIndexArray<3, 1, 1>}, { &setMatrixvpIndexArray<3, 2, 0>, &setMatrixvpIndexArray<3, 2, 1>}, { &setMatrixvpIndexArray<3, 3, 0>, &setMatrixvpIndexArray<3, 3, 1>}, { &setMatrixvpIndexArray<3, 4, 0>, &setMatrixvpIndexArray<3, 4, 1>}}, + {{ &setMatrixvpIndexArray<4, 1, 0>, &setMatrixvpIndexArray<4, 1, 1>}, { &setMatrixvpIndexArray<4, 2, 0>, &setMatrixvpIndexArray<4, 2, 1>}, { &setMatrixvpIndexArray<4, 3, 0>, &setMatrixvpIndexArray<4, 3, 1>}, { &setMatrixvpIndexArray<4, 4, 0>, &setMatrixvpIndexArray<4, 4, 1>}}, + }, + { + {{ &setMatrixfpIndexArray<1, 1, 0>, &setMatrixfpIndexArray<1, 1, 1>}, { &setMatrixfpIndexArray<1, 2, 0>, &setMatrixfpIndexArray<1, 2, 1>}, { &setMatrixfpIndexArray<1, 3, 0>, &setMatrixfpIndexArray<1, 3, 1>}, { &setMatrixfpIndexArray<1, 4, 0>, &setMatrixfpIndexArray<1, 4, 1>}}, + {{ &setMatrixfpIndexArray<2, 1, 0>, &setMatrixfpIndexArray<2, 1, 1>}, { &setMatrixfpIndexArray<2, 2, 0>, &setMatrixfpIndexArray<2, 2, 1>}, { &setMatrixfpIndexArray<2, 3, 0>, &setMatrixfpIndexArray<2, 3, 1>}, { &setMatrixfpIndexArray<2, 4, 0>, &setMatrixfpIndexArray<2, 4, 1>}}, + {{ &setMatrixfpIndexArray<3, 1, 0>, &setMatrixfpIndexArray<3, 1, 1>}, { &setMatrixfpIndexArray<3, 2, 0>, &setMatrixfpIndexArray<3, 2, 1>}, { &setMatrixfpIndexArray<3, 3, 0>, &setMatrixfpIndexArray<3, 3, 1>}, { &setMatrixfpIndexArray<3, 4, 0>, &setMatrixfpIndexArray<3, 4, 1>}}, + {{ &setMatrixfpIndexArray<4, 1, 0>, &setMatrixfpIndexArray<4, 1, 1>}, { &setMatrixfpIndexArray<4, 2, 0>, &setMatrixfpIndexArray<4, 2, 1>}, { &setMatrixfpIndexArray<4, 3, 0>, &setMatrixfpIndexArray<4, 3, 1>}, { &setMatrixfpIndexArray<4, 4, 0>, &setMatrixfpIndexArray<4, 4, 1>}}, + }, + }, + { //should be shared + { + {{ &setMatrixSharedvpIndexArray<1, 1, 0>, &setMatrixSharedvpIndexArray<1, 1, 1>}, { &setMatrixSharedvpIndexArray<1, 2, 0>, &setMatrixSharedvpIndexArray<1, 2, 1>}, { &setMatrixSharedvpIndexArray<1, 3, 0>, &setMatrixSharedvpIndexArray<1, 3, 1>}, { &setMatrixSharedvpIndexArray<1, 4, 0>, &setMatrixSharedvpIndexArray<1, 4, 1>}}, + {{ &setMatrixSharedvpIndexArray<2, 1, 0>, &setMatrixSharedvpIndexArray<2, 1, 1>}, { &setMatrixSharedvpIndexArray<2, 2, 0>, &setMatrixSharedvpIndexArray<2, 2, 1>}, { &setMatrixSharedvpIndexArray<2, 3, 0>, &setMatrixSharedvpIndexArray<2, 3, 1>}, { &setMatrixSharedvpIndexArray<2, 4, 0>, &setMatrixSharedvpIndexArray<2, 4, 1>}}, + {{ &setMatrixSharedvpIndexArray<3, 1, 0>, &setMatrixSharedvpIndexArray<3, 1, 1>}, { &setMatrixSharedvpIndexArray<3, 2, 0>, &setMatrixSharedvpIndexArray<3, 2, 1>}, { &setMatrixSharedvpIndexArray<3, 3, 0>, &setMatrixSharedvpIndexArray<3, 3, 1>}, { &setMatrixSharedvpIndexArray<3, 4, 0>, &setMatrixSharedvpIndexArray<3, 4, 1>}}, + {{ &setMatrixSharedvpIndexArray<4, 1, 0>, &setMatrixSharedvpIndexArray<4, 1, 1>}, { &setMatrixSharedvpIndexArray<4, 2, 0>, &setMatrixSharedvpIndexArray<4, 2, 1>}, { &setMatrixSharedvpIndexArray<4, 3, 0>, &setMatrixSharedvpIndexArray<4, 3, 1>}, { &setMatrixSharedvpIndexArray<4, 4, 0>, &setMatrixSharedvpIndexArray<4, 4, 1>}}, + }, + { + {{ &setMatrixSharedfpIndexArray<1, 1, 0>, &setMatrixSharedfpIndexArray<1, 1, 1>}, { &setMatrixSharedfpIndexArray<1, 2, 0>, &setMatrixSharedfpIndexArray<1, 2, 1>}, { &setMatrixSharedfpIndexArray<1, 3, 0>, &setMatrixSharedfpIndexArray<1, 3, 1>}, { &setMatrixSharedfpIndexArray<1, 4, 0>, &setMatrixSharedfpIndexArray<1, 4, 1>}}, + {{ &setMatrixSharedfpIndexArray<2, 1, 0>, &setMatrixSharedfpIndexArray<2, 1, 1>}, { &setMatrixSharedfpIndexArray<2, 2, 0>, &setMatrixSharedfpIndexArray<2, 2, 1>}, { &setMatrixSharedfpIndexArray<2, 3, 0>, &setMatrixSharedfpIndexArray<2, 3, 1>}, { &setMatrixSharedfpIndexArray<2, 4, 0>, &setMatrixSharedfpIndexArray<2, 4, 1>}}, + {{ &setMatrixSharedfpIndexArray<3, 1, 0>, &setMatrixSharedfpIndexArray<3, 1, 1>}, { &setMatrixSharedfpIndexArray<3, 2, 0>, &setMatrixSharedfpIndexArray<3, 2, 1>}, { &setMatrixSharedfpIndexArray<3, 3, 0>, &setMatrixSharedfpIndexArray<3, 3, 1>}, { &setMatrixSharedfpIndexArray<3, 4, 0>, &setMatrixSharedfpIndexArray<3, 4, 1>}}, + {{ &setMatrixSharedfpIndexArray<4, 1, 0>, &setMatrixSharedfpIndexArray<4, 1, 1>}, { &setMatrixSharedfpIndexArray<4, 2, 0>, &setMatrixSharedfpIndexArray<4, 2, 1>}, { &setMatrixSharedfpIndexArray<4, 3, 0>, &setMatrixSharedfpIndexArray<4, 3, 1>}, { &setMatrixSharedfpIndexArray<4, 4, 0>, &setMatrixSharedfpIndexArray<4, 4, 1>}}, + }, + }, + } +}; + +_cgSetArrayIndexFunction getVectorTypeIndexSetterFunction( unsigned short a, unsigned short b, unsigned short c, unsigned short d ) +{ + return setVectorTypeIndex[a][b][c][d]; +} + +_cgSetArrayIndexFunction getMatrixTypeIndexSetterFunction( unsigned short a, unsigned short b, unsigned short c, unsigned short d, unsigned short e, unsigned short f ) +{ + return setMatrixTypeIndex[a][b][c][d][e][f]; +} + +static void setSamplerfp( CgRuntimeParameter*ptr, const void*v, int ) //index +{ + _CGprogram *program = (( CgRuntimeParameter* )ptr )->program; + const CgParameterResource *parameterResource = rglGetParameterResource( program, (( CgRuntimeParameter* )ptr )->parameterEntry ); + + // the value of v == NULL when it is called from cgGLEnableTextureParameter + // the value of v == NULL when it is called from cgGLSetTextureParameter + // this may be called by a connected param to propagate its value + // the spec says that the set should not cause the bind + // so only do the bind when the call comes from cgGLEnableTextureParameter + if ( v ) + { + *( GLuint* )ptr->pushBufferPointer = *( GLuint* )v; + } + else + { + rglTextureImageUnit *unit = _CurrentContext->TextureImageUnits + ( parameterResource->resource - CG_TEXUNIT0 ); + rglBindTextureInternal( unit, *( GLuint* )ptr->pushBufferPointer, ptr->glType ); + } +} + +static void setSamplervp( CgRuntimeParameter*ptr, const void*v, int ) //index +{ + // the value of v == NULL when it is called from cgGLEnableTextureParameter + // the value of v == NULL when it is called from cgGLSetTextureParameter + // this may be called by a connected param to propagate its value + // the spec says that the set should not cause the bind + // so only do the bind when the call comes from cgGLEnableTextureParameter + if ( v ) + { + *( GLuint* )ptr->pushBufferPointer = *( GLuint* )v; + } +} + + +#undef ROW_MAJOR +#undef COL_MAJOR +// Previously from Shader.cpp + +//--------------------------------------------------------------------------------------------------------- +#define ROW_MAJOR 0 +#define COL_MAJOR 1 + +//This function creates the push buffer and the related structures +void rglCreatePushBuffer( _CGprogram *program ) +{ + //first pass to compute the space needed + int bufferSize = 0; + int programPushBufferPointersSize = 0; + int extraStorageInWords = 0; + int offsetCount = 0; + int samplerCount = 0; + int profileIndex = ( program->header.profile == CG_PROFILE_SCE_FP_TYPEB || //program->header.profile==CG_PROFILE_SCE_FP_TYPEC || + program->header.profile == CG_PROFILE_SCE_FP_RSX ) ? FRAGMENT_PROFILE_INDEX : VERTEX_PROFILE_INDEX; + + bool hasSharedParams = false; + int arrayCount = 1; + for ( int i = 0;i < program->rtParametersCount;i++ ) + { + const CgParameterEntry *parameterEntry = program->parametersEntries + i; + + //skip the unrolled arrays and the structures + if (( parameterEntry->flags & CGP_STRUCTURE ) || ( parameterEntry->flags & CGP_UNROLLED ) ) + { + arrayCount = 1; + continue; + } + + if (( parameterEntry->flags & CGPF_REFERENCED ) ) + { + if ( parameterEntry->flags & CGP_ARRAY ) + { + const CgParameterArray *parameterArray = rglGetParameterArray( program, parameterEntry ); + arrayCount = rglGetSizeofSubArray( parameterArray->dimensions, parameterArray->dimensionCount ); + continue; + } + if (( parameterEntry->flags & CGPV_MASK ) == CGPV_UNIFORM ) + { + const CgParameterResource *parameterResource = rglGetParameterResource( program, parameterEntry ); + if ( parameterResource->type >= CG_SAMPLER1D && parameterResource->type <= CG_SAMPLERCUBE ) + { + // store 1 sampler and 1 offset for texture samplers. + offsetCount += arrayCount; + samplerCount += arrayCount; + } + else if ( profileIndex == VERTEX_PROFILE_INDEX ) + { + if ( parameterResource->type == CGP_SCF_BOOL ) + { + //do nothing + } + else if ( !( parameterEntry->flags & CGPF_SHARED ) ) + { + int registerStride = isMatrix(( CGtype )parameterResource->type ) ? rglGetTypeRowCount(( CGtype )parameterResource->type ) : 1; + if ( parameterEntry->flags & CGP_CONTIGUOUS ) + bufferSize += 3 + 4 * arrayCount * registerStride; + else + { + programPushBufferPointersSize += arrayCount; + int resourceIndex = parameterResource->resource; + int referencedSize = 3 + 4 * registerStride; + int notReferencedSize = 4 * registerStride; + for ( int j = 0;j < arrayCount;j++, resourceIndex += registerStride ) + { + //I use the programPushBuffer pointer so it's valid to have element in an array without any affectation + if ( program->resources[resourceIndex] != 0xffff ) + bufferSize += referencedSize; //referenced: push buffer + else + extraStorageInWords += notReferencedSize; //not referenced , extra storage location + } + } + } + else + { + hasSharedParams = true; + if ( !( parameterEntry->flags & CGP_CONTIGUOUS ) ) + { + programPushBufferPointersSize += arrayCount; + } + } + } + else //profileIndex == FRAGMENT_PROFILE_INDEX + { + int registerStride = isMatrix(( CGtype )parameterResource->type ) ? rglGetTypeRowCount(( CGtype )parameterResource->type ) : 1; + if ( !( parameterEntry->flags & CGPF_SHARED ) ) + { + //TODO: check this case + extraStorageInWords += 4 * arrayCount * registerStride; + } + else + { + hasSharedParams = true; + unsigned short *resource = program->resources + parameterResource->resource; + for ( int j = 0;j < arrayCount*registerStride;j++ ) + { + resource++; + unsigned short count = *resource++; + bufferSize += 24 * count; + resource += count; + } + } + } + } + } + arrayCount = 1; + } + + if (( profileIndex == FRAGMENT_PROFILE_INDEX ) && ( hasSharedParams ) ) + { + bufferSize += 8 + 3 + 2; // GCM_PORT_TESTED [CEDRIC] +3 for the channel switch that gcm does + 2 for the OUT end + } + + bufferSize = rglPad( bufferSize, 4 ); + + //allocate the buffer(s) + unsigned int storageSizeInWords = bufferSize + extraStorageInWords; + if ( storageSizeInWords ) + program->memoryBlock = ( unsigned int* )memalign( 16, storageSizeInWords * 4 ); + else + program->memoryBlock = NULL; + + //TODO: this is tmp + program->samplerCount = samplerCount; + if ( samplerCount ) + { + program->samplerValuesLocation = ( GLuint* )malloc( samplerCount * sizeof( GLuint ) ); + program->samplerIndices = ( GLuint* )malloc( samplerCount * sizeof( GLuint ) ); + program->samplerUnits = ( GLuint* )malloc( samplerCount * sizeof( GLuint ) ); + } + else + { + program->samplerValuesLocation = NULL; + program->samplerIndices = NULL; + program->samplerUnits = NULL; + } + + GLuint *samplerValuesLocation = program->samplerValuesLocation; + GLuint *samplerIndices = program->samplerIndices; + GLuint *samplerUnits = program->samplerUnits; + + if ( programPushBufferPointersSize ) + program->constantPushBufferPointers = ( unsigned int** )malloc( programPushBufferPointersSize * 4 ); + else + program->constantPushBufferPointers = NULL; + + uint32_t *rglGcmCurrent = (uint32_t*)program->memoryBlock; + program->constantPushBuffer = ( bufferSize > 0 ) ? ( unsigned int * )rglGcmCurrent : NULL; + unsigned int **programPushBuffer = program->constantPushBufferPointers; + program->constantPushBufferWordSize = bufferSize; + GLuint *currentStorage = ( GLuint * )( rglGcmCurrent + bufferSize ); + + int outOfMemory = 0; + //second pass to fill the buffer + arrayCount = 1; + const CgParameterEntry *containerEntry = NULL; + for ( int i = 0;i < program->rtParametersCount;i++ ) + { + CgRuntimeParameter *rtParameter = program->runtimeParameters + i; + const CgParameterEntry *parameterEntry = program->parametersEntries + i; + if ( containerEntry == NULL ) + containerEntry = parameterEntry; + + //rtParameter->setter = _cgRaiseInvalidParam; + //rtParameter->setterr = _cgRaiseNotMatrixParam; + //rtParameter->setterc = _cgRaiseNotMatrixParam; + rtParameter->samplerSetter = _cgRaiseInvalidParamIndex; + + //tentative + rtParameter->setterIndex = _cgRaiseInvalidParamIndex; + rtParameter->setterrIndex = _cgRaiseNotMatrixParamIndex; + rtParameter->settercIndex = _cgRaiseNotMatrixParamIndex; + + CGparameter id = ( CGparameter )rglCreateName( &_CurrentContext->cgParameterNameSpace, ( void* )rtParameter ); + if ( !id ) + { + outOfMemory = 1; + break; + } + + rtParameter->id = id; + rtParameter->parameterEntry = parameterEntry; + rtParameter->program = program; + + //skip the unrolled arrays and the structures + if (( parameterEntry->flags & CGP_STRUCTURE ) || ( parameterEntry->flags & CGP_UNROLLED ) ) + { + arrayCount = 1; + containerEntry = NULL; + continue; + } + + if ( parameterEntry->flags & CGPF_REFERENCED ) + { + if ( parameterEntry->flags & CGP_ARRAY ) + { + const CgParameterArray *parameterArray = rglGetParameterArray( program, parameterEntry ); + arrayCount = rglGetSizeofSubArray( parameterArray->dimensions, parameterArray->dimensionCount ); + //continue to the next item + continue; + } + if (( parameterEntry->flags & CGPV_MASK ) == CGPV_UNIFORM ) + { + //TODO: rtParameter->defaultNormalize = CG_FALSE; + rtParameter->glType = GL_NONE; + //TODO: needed ? rtParameter->flags = 0; + const CgParameterResource *parameterResource = rglGetParameterResource( program, parameterEntry ); + if ( parameterResource->type >= CG_SAMPLER1D && parameterResource->type <= CG_SAMPLERCUBE ) + { + //TODO + rtParameter->pushBufferPointer = samplerValuesLocation; + // initialize the texture name to zero, used by the setSamplerfp call to rglBindTextureInternal + *samplerValuesLocation = 0; + samplerValuesLocation++; + + // store the texture unit indices. + *samplerIndices = i; + samplerIndices++; + *samplerUnits = parameterResource->resource - CG_TEXUNIT0; + samplerUnits++; + + // XXX the setter is called when validating vertex programs. + // this would cause a CG error. + // the parameters should have a "validate" function instead + if ( profileIndex == VERTEX_PROFILE_INDEX ) + { + rtParameter->setterIndex = _cgIgnoreSetParamIndex; + rtParameter->samplerSetter = setSamplervp; + } + else + { + rtParameter->samplerSetter = setSamplerfp; + } + rtParameter->glType = rglCgGetSamplerGLTypeFromCgType(( CGtype )( parameterResource->type ) ); + } + else + { + if ( profileIndex == VERTEX_PROFILE_INDEX ) + { + if ( parameterResource->type == CGP_SCF_BOOL ) + { + //do nothing + } + else if ( !( parameterEntry->flags & CGPF_SHARED ) ) + { + int registerStride = isMatrix(( CGtype )parameterResource->type ) ? rglGetTypeRowCount(( CGtype )parameterResource->type ) : 1; + int registerCount = arrayCount * registerStride; + if ( parameterEntry->flags & CGP_CONTIGUOUS ) + { + memset( rglGcmCurrent, 0, 4*( 4*registerCount + 3 ) ); + GCM_FUNC_BUFFERED( cellGcmSetVertexProgramParameterBlock, rglGcmCurrent, parameterResource->resource, registerCount, ( float* )rglGcmCurrent ); + rtParameter->pushBufferPointer = rglGcmCurrent - 4 * registerCount; + } + else + { + rtParameter->pushBufferPointer = programPushBuffer; + int resourceIndex = parameterResource->resource; + for ( int j = 0;j < arrayCount;j++, resourceIndex += registerStride ) + { + //I use the programPushBuffer pointer so it's valid to have element in an array without any affectation + if ( program->resources[resourceIndex] != 0xffff ) + { + memset( rglGcmCurrent, 0, 4*( 4*registerStride + 3 ) ); + GCM_FUNC_BUFFERED( cellGcmSetVertexProgramParameterBlock, rglGcmCurrent, program->resources[resourceIndex], registerStride, ( float* )rglGcmCurrent ); // GCM_PORT_TESTED [KHOFF] + *( programPushBuffer++ ) = ( unsigned int* )( rglGcmCurrent - 4 * registerStride ); + } + else + { + //This case is when there is an array item which is not referenced + //we still call tbe setter function, so we have to store the info somewhere... + //and we need to return the value previously set in case of the user asks for a get + *( programPushBuffer++ ) = ( unsigned int* )currentStorage; + currentStorage += 4 * registerStride; + } + } + } + } + else + { + rglGcmDriver *driver = rglGetGcmDriver(); + if ( parameterEntry->flags & CGP_CONTIGUOUS ) + { + rtParameter->pushBufferPointer = driver->sharedVPConstants + parameterResource->resource * 4 * sizeof( float ); + } + else + { + int registerStride = isMatrix(( CGtype )parameterResource->type ) ? rglGetTypeRowCount(( CGtype )parameterResource->type ) : 1; + int registerCount = arrayCount * registerStride; + for ( int j = 0;j < registerCount;j += registerStride ) + { + *programPushBuffer = ( unsigned int* )driver->sharedVPConstants + program->resources[parameterResource->resource+j] * 4 * sizeof( float ); + rtParameter->pushBufferPointer = programPushBuffer++; + } + } + } + } + else //if (profileIndex == FRAGMENT_PROFILE_INDEX) + { + if ( parameterEntry->flags & CGPF_SHARED ) + { + // XXX needs an offset for the get + rtParameter->pushBufferPointer = NULL; + } + else + { + int registerStride = isMatrix(( CGtype )parameterResource->type ) ? rglGetTypeRowCount(( CGtype )parameterResource->type ) : 1; + int registerCount = arrayCount * registerStride; + rtParameter->pushBufferPointer = currentStorage; + currentStorage += 4 * registerCount; + } + } + + switch ( parameterResource->type ) + { + case CG_FLOAT: + case CG_FLOAT1: case CG_FLOAT2: case CG_FLOAT3: case CG_FLOAT4: + // if this gets updated, don't forget the halfs below + { + unsigned int floatCount = rglCountFloatsInCgType(( CGtype )parameterResource->type ); + rtParameter->setterIndex = setVectorTypeIndex[( containerEntry->flags&CGP_ARRAY ) ? 1 : 0][( containerEntry->flags&CGPF_SHARED ) ? 1 : 0][profileIndex][floatCount - 1]; + } + break; + case CG_FLOAT1x1: case CG_FLOAT1x2: case CG_FLOAT1x3: case CG_FLOAT1x4: + case CG_FLOAT2x1: case CG_FLOAT2x2: case CG_FLOAT2x3: case CG_FLOAT2x4: + case CG_FLOAT3x1: case CG_FLOAT3x2: case CG_FLOAT3x3: case CG_FLOAT3x4: + case CG_FLOAT4x1: case CG_FLOAT4x2: case CG_FLOAT4x3: case CG_FLOAT4x4: + // if this gets updated, don't forget the halfs below + rtParameter->setterrIndex = setMatrixTypeIndex[( containerEntry->flags&CGP_ARRAY ) ? 1 : 0][( containerEntry->flags&CGPF_SHARED ) ? 1 : 0][profileIndex][rglGetTypeRowCount(( CGtype )parameterResource->type ) - 1][rglGetTypeColCount(( CGtype )parameterResource->type ) - 1][ROW_MAJOR]; + rtParameter->settercIndex = setMatrixTypeIndex[( containerEntry->flags&CGP_ARRAY ) ? 1 : 0][( containerEntry->flags&CGPF_SHARED ) ? 1 : 0][profileIndex][rglGetTypeRowCount(( CGtype )parameterResource->type ) - 1][rglGetTypeColCount(( CGtype )parameterResource->type ) - 1][COL_MAJOR]; + break; + case CG_SAMPLER1D: case CG_SAMPLER2D: case CG_SAMPLER3D: case CG_SAMPLERRECT: case CG_SAMPLERCUBE: + // A used sampler that does not have a TEXUNIT resource ? + // not sure if we ever go here. + break; + case CGP_SCF_BOOL: + break; + case CG_HALF: + case CG_HALF1: case CG_HALF2: case CG_HALF3: case CG_HALF4: + case CG_INT: + case CG_INT1: case CG_INT2: case CG_INT3: case CG_INT4: + case CG_BOOL: + case CG_BOOL1: case CG_BOOL2: case CG_BOOL3: case CG_BOOL4: + case CG_FIXED: + case CG_FIXED1: case CG_FIXED2: case CG_FIXED3: case CG_FIXED4: + { + unsigned int floatCount = rglCountFloatsInCgType(( CGtype )parameterResource->type ); + rtParameter->setterIndex = setVectorTypeIndex[( containerEntry->flags&CGP_ARRAY ) ? 1 : 0][( containerEntry->flags&CGPF_SHARED ) ? 1 : 0][profileIndex][floatCount - 1]; + } + break; + case CG_HALF1x1: case CG_HALF1x2: case CG_HALF1x3: case CG_HALF1x4: + case CG_HALF2x1: case CG_HALF2x2: case CG_HALF2x3: case CG_HALF2x4: + case CG_HALF3x1: case CG_HALF3x2: case CG_HALF3x3: case CG_HALF3x4: + case CG_HALF4x1: case CG_HALF4x2: case CG_HALF4x3: case CG_HALF4x4: + case CG_INT1x1: case CG_INT1x2: case CG_INT1x3: case CG_INT1x4: + case CG_INT2x1: case CG_INT2x2: case CG_INT2x3: case CG_INT2x4: + case CG_INT3x1: case CG_INT3x2: case CG_INT3x3: case CG_INT3x4: + case CG_INT4x1: case CG_INT4x2: case CG_INT4x3: case CG_INT4x4: + case CG_BOOL1x1: case CG_BOOL1x2: case CG_BOOL1x3: case CG_BOOL1x4: + case CG_BOOL2x1: case CG_BOOL2x2: case CG_BOOL2x3: case CG_BOOL2x4: + case CG_BOOL3x1: case CG_BOOL3x2: case CG_BOOL3x3: case CG_BOOL3x4: + case CG_BOOL4x1: case CG_BOOL4x2: case CG_BOOL4x3: case CG_BOOL4x4: + case CG_FIXED1x1: case CG_FIXED1x2: case CG_FIXED1x3: case CG_FIXED1x4: + case CG_FIXED2x1: case CG_FIXED2x2: case CG_FIXED2x3: case CG_FIXED2x4: + case CG_FIXED3x1: case CG_FIXED3x2: case CG_FIXED3x3: case CG_FIXED3x4: + case CG_FIXED4x1: case CG_FIXED4x2: case CG_FIXED4x3: case CG_FIXED4x4: + rtParameter->setterrIndex = setMatrixTypeIndex[( containerEntry->flags&CGP_ARRAY ) ? 1 : 0][( containerEntry->flags&CGPF_SHARED ) ? 1 : 0][profileIndex][rglGetTypeRowCount(( CGtype )parameterResource->type ) - 1][rglGetTypeColCount(( CGtype )parameterResource->type ) - 1][ROW_MAJOR]; + rtParameter->settercIndex = setMatrixTypeIndex[( containerEntry->flags&CGP_ARRAY ) ? 1 : 0][( containerEntry->flags&CGPF_SHARED ) ? 1 : 0][profileIndex][rglGetTypeRowCount(( CGtype )parameterResource->type ) - 1][rglGetTypeColCount(( CGtype )parameterResource->type ) - 1][COL_MAJOR]; + break; + // addition to be compatible with cgc 2.0 + case CG_STRING: + break; + default: + break; + } + } + } + else if (( parameterEntry->flags & CGPV_MASK ) == CGPV_VARYING ) + { + if (( parameterEntry->flags & CGPD_MASK ) == CGPD_IN && profileIndex == VERTEX_PROFILE_INDEX ) + { + rtParameter->setterIndex = setAttribConstantIndex; + } + } + } + else + { + if (( parameterEntry->flags & CGPV_MASK ) == CGPV_UNIFORM ) + { + if ( parameterEntry->flags & CGP_ARRAY ) + continue; + + const CgParameterResource *parameterResource = rglGetParameterResource( program, parameterEntry ); + // we silently ignore valid sets on unused parameters. + switch ( parameterResource->type ) + { + case CG_FLOAT: + case CG_FLOAT1: case CG_FLOAT2: case CG_FLOAT3: case CG_FLOAT4: + //rtParameter->setter = _cgIgnoreSetParam; + rtParameter->setterIndex = _cgIgnoreSetParamIndex; + break; + case CG_FLOAT1x1: case CG_FLOAT1x2: case CG_FLOAT1x3: case CG_FLOAT1x4: + case CG_FLOAT2x1: case CG_FLOAT2x2: case CG_FLOAT2x3: case CG_FLOAT2x4: + case CG_FLOAT3x1: case CG_FLOAT3x2: case CG_FLOAT3x3: case CG_FLOAT3x4: + case CG_FLOAT4x1: case CG_FLOAT4x2: case CG_FLOAT4x3: case CG_FLOAT4x4: + //rtParameter->setterr = _cgIgnoreSetParam; + //rtParameter->setterc = _cgIgnoreSetParam; + rtParameter->setterrIndex = _cgIgnoreSetParamIndex; + rtParameter->settercIndex = _cgIgnoreSetParamIndex; + break; + case CG_SAMPLER1D: case CG_SAMPLER2D: case CG_SAMPLER3D: case CG_SAMPLERRECT: case CG_SAMPLERCUBE: + rtParameter->samplerSetter = _cgIgnoreSetParamIndex; + break; + case CGP_SCF_BOOL: + break; + case CG_HALF: + case CG_HALF1: case CG_HALF2: case CG_HALF3: case CG_HALF4: + case CG_INT: + case CG_INT1: case CG_INT2: case CG_INT3: case CG_INT4: + case CG_BOOL: + case CG_BOOL1: case CG_BOOL2: case CG_BOOL3: case CG_BOOL4: + case CG_FIXED: + case CG_FIXED1: case CG_FIXED2: case CG_FIXED3: case CG_FIXED4: + //rtParameter->setter = _cgIgnoreSetParam; + rtParameter->setterIndex = _cgIgnoreSetParamIndex; + break; + case CG_HALF1x1: case CG_HALF1x2: case CG_HALF1x3: case CG_HALF1x4: + case CG_HALF2x1: case CG_HALF2x2: case CG_HALF2x3: case CG_HALF2x4: + case CG_HALF3x1: case CG_HALF3x2: case CG_HALF3x3: case CG_HALF3x4: + case CG_HALF4x1: case CG_HALF4x2: case CG_HALF4x3: case CG_HALF4x4: + case CG_INT1x1: case CG_INT1x2: case CG_INT1x3: case CG_INT1x4: + case CG_INT2x1: case CG_INT2x2: case CG_INT2x3: case CG_INT2x4: + case CG_INT3x1: case CG_INT3x2: case CG_INT3x3: case CG_INT3x4: + case CG_INT4x1: case CG_INT4x2: case CG_INT4x3: case CG_INT4x4: + case CG_BOOL1x1: case CG_BOOL1x2: case CG_BOOL1x3: case CG_BOOL1x4: + case CG_BOOL2x1: case CG_BOOL2x2: case CG_BOOL2x3: case CG_BOOL2x4: + case CG_BOOL3x1: case CG_BOOL3x2: case CG_BOOL3x3: case CG_BOOL3x4: + case CG_BOOL4x1: case CG_BOOL4x2: case CG_BOOL4x3: case CG_BOOL4x4: + case CG_FIXED1x1: case CG_FIXED1x2: case CG_FIXED1x3: case CG_FIXED1x4: + case CG_FIXED2x1: case CG_FIXED2x2: case CG_FIXED2x3: case CG_FIXED2x4: + case CG_FIXED3x1: case CG_FIXED3x2: case CG_FIXED3x3: case CG_FIXED3x4: + case CG_FIXED4x1: case CG_FIXED4x2: case CG_FIXED4x3: case CG_FIXED4x4: + //rtParameter->setterr = _cgIgnoreSetParam; + //rtParameter->setterc = _cgIgnoreSetParam; + rtParameter->setterrIndex = _cgIgnoreSetParamIndex; + rtParameter->settercIndex = _cgIgnoreSetParamIndex; + break; + // addition to be compatible with cgc 2.0 + case CG_STRING: + break; + default: + break; + } + } + else if (( parameterEntry->flags & CGPV_MASK ) == CGPV_VARYING ) + { + if (( parameterEntry->flags & CGPD_MASK ) == CGPD_IN && profileIndex == VERTEX_PROFILE_INDEX ) + { + rtParameter->setterIndex = setAttribConstantIndex; + } + } + } + arrayCount = 1; + containerEntry = NULL; + } + + //add padding + if ( bufferSize > 0 ) + { + int nopCount = ( program->constantPushBuffer + bufferSize ) - ( unsigned int * )rglGcmCurrent; + GCM_FUNC_BUFFERED( cellGcmSetNopCommand, rglGcmCurrent, nopCount ); // GCM_PORT_TESTED [KHOFF] + } +} + +//this function sets the embedded constant to their default value in the ucode of a fragment shader +//it's called at setup time right after loading the program. this function could be removed if the +//default values were already in the shader code +void rglSetDefaultValuesVP( _CGprogram *program ) +{ + + int count = program->defaultValuesIndexCount; + for ( int i = 0;i < count;i++ ) + { + int index = ( int )program->defaultValuesIndices[i].entryIndex; + CgRuntimeParameter *rtParameter = program->runtimeParameters + index; + + int arrayCount = 1; + const CgParameterEntry *parameterEntry = rtParameter->parameterEntry; + bool isArray = false; + if ( parameterEntry->flags & CGP_ARRAY ) + { + isArray = true; + const CgParameterArray *parameterArray = rglGetParameterArray( program, parameterEntry ); + arrayCount = rglGetSizeofSubArray( parameterArray->dimensions, parameterArray->dimensionCount ); + parameterEntry++; + rtParameter++; + } + + if ( rtParameter->pushBufferPointer ) //unreferenced might have default values + { + const CgParameterResource *parameterResource = rglGetParameterResource( program, parameterEntry ); + const float *itemDefaultValues = program->defaultValues + program->defaultValuesIndices[i].defaultValueIndex; + int registerStride = isMatrix(( CGtype )parameterResource->type ) ? rglGetTypeRowCount(( CGtype )parameterResource->type ) : 1; + if ( parameterEntry->flags & CGP_CONTIGUOUS ) + memcpy( rtParameter->pushBufferPointer, itemDefaultValues, arrayCount * registerStride *4*sizeof( float ) ); + else + { + unsigned int *pushBufferPointer = (( unsigned int * )rtParameter->pushBufferPointer ); + for ( int j = 0;j < arrayCount;j++ ) + { + unsigned int *pushBufferAddress = isArray ? ( *( unsigned int** )pushBufferPointer ) : pushBufferPointer; + memcpy( pushBufferAddress, itemDefaultValues, registerStride*4*sizeof( float ) ); + pushBufferPointer += isArray ? 1 : 3 + registerStride * 4; + itemDefaultValues += 4 * registerStride; + } + } + } + } +} + +void rglSetDefaultValuesFP( _CGprogram *program ) +{ + int count = program->defaultValuesIndexCount; + for ( int i = 0;i < count;i++ ) + { + const void * __restrict pItemDefaultValues = program->defaultValues + program->defaultValuesIndices[i].defaultValueIndex; + const unsigned int * itemDefaultValues = ( const unsigned int * )pItemDefaultValues; + int index = ( int )program->defaultValuesIndices[i].entryIndex; + + CgRuntimeParameter *rtParameter = program->runtimeParameters + index; + float *hostMemoryCopy = ( float * )rtParameter->pushBufferPointer; + + if ( hostMemoryCopy ) //certain parameter are not referenced but still have a default value. + { + const CgParameterEntry *parameterEntry = rtParameter->parameterEntry; + int arrayCount = 1; + if ( parameterEntry->flags & CGP_ARRAY ) + { + const CgParameterArray *parameterArray = rglGetParameterArray( program, parameterEntry ); + arrayCount = rglGetSizeofSubArray( parameterArray->dimensions, parameterArray->dimensionCount ); + i++; + parameterEntry++; + } + const CgParameterResource *parameterResource = rglGetParameterResource( program, parameterEntry ); + unsigned short *resource = program->resources + parameterResource->resource + 1; //+1 to skip the register + int registerStride = isMatrix(( CGtype )parameterResource->type ) ? rglGetTypeRowCount(( CGtype )parameterResource->type ) : 1; + int registerCount = arrayCount * registerStride; + int j; + for ( j = 0;j < registerCount;j++ ) + { + unsigned short embeddedConstCount = *( resource++ ); + int k; + for ( k = 0;k < embeddedConstCount;k++ ) + { + unsigned short ucodePatchOffset = *( resource )++; + unsigned int *dst = ( unsigned int* )(( char* )program->ucode + ucodePatchOffset ); + dst[0] = SWAP_IF_BIG_ENDIAN( itemDefaultValues[0] ); + dst[1] = SWAP_IF_BIG_ENDIAN( itemDefaultValues[1] ); + dst[2] = SWAP_IF_BIG_ENDIAN( itemDefaultValues[2] ); + dst[3] = SWAP_IF_BIG_ENDIAN( itemDefaultValues[3] ); + } + memcpy(( void* )hostMemoryCopy, ( void* )itemDefaultValues, sizeof( float )*4 ); + hostMemoryCopy += 4; + itemDefaultValues += 4; + resource++; //skip the register of the next item + } + } + } +} + +/*============================================================ + PLATFORM BUFFER + ============================================================ */ + +static void rglDeallocateBuffer( rglBufferObject* bufferObject ) +{ + rglGcmBufferObject *rglBuffer = ( rglGcmBufferObject * )bufferObject->platformBufferObject; + + switch ( rglBuffer->pool ) + { + case RGLGCM_SURFACE_POOL_LINEAR: + gmmFree( rglBuffer->bufferId ); + break; + case RGLGCM_SURFACE_POOL_NONE: + break; + default: + break; + } + + rglBuffer->pool = RGLGCM_SURFACE_POOL_NONE; + rglBuffer->bufferId = GMM_ERROR; +} + +static void rglpsAllocateBuffer(rglBufferObject* bufferObject) +{ + rglGcmBufferObject *rglBuffer = ( rglGcmBufferObject * )bufferObject->platformBufferObject; + + // free current buffer (if any) + rglDeallocateBuffer( bufferObject ); + + // allocate in GPU memory + rglBuffer->pool = RGLGCM_SURFACE_POOL_LINEAR; + rglBuffer->bufferId = gmmAlloc((CellGcmContextData*)&rglGcmState_i.fifo, + CELL_GCM_LOCATION_LOCAL, 0, rglBuffer->bufferSize); + rglBuffer->pitch = 0; + + if ( rglBuffer->bufferId == GMM_ERROR ) + rglBuffer->pool = RGLGCM_SURFACE_POOL_NONE; + + GLuint referenceCount = bufferObject->textureReferences.getCount(); + if ( referenceCount > 0 ) + { + for ( GLuint i = 0;i < referenceCount;++i ) + { + rglTexture *texture = bufferObject->textureReferences[i]; + rglGcmTexture *gcmTexture = ( rglGcmTexture * )texture->platformTexture; + gcmTexture->gpuAddressId = rglBuffer->bufferId; + gcmTexture->gpuAddressIdOffset = texture->offset; + texture->revalidate |= RGL_TEXTURE_REVALIDATE_PARAMETERS; + rglTextureTouchFBOs( texture ); + } + _CurrentContext->needValidate |= RGL_VALIDATE_TEXTURES_USED; + } +} + +int rglpBufferObjectSize(void) { return sizeof(rglGcmBufferObject); } + +GLboolean rglpCreateBufferObject( rglBufferObject* bufferObject ) +{ + rglGcmBufferObject *rglBuffer = ( rglGcmBufferObject * )bufferObject->platformBufferObject; + + rglBuffer->pool = RGLGCM_SURFACE_POOL_NONE; + rglBuffer->bufferId = GMM_ERROR; + rglBuffer->mapCount = 0; + rglBuffer->mapAccess = GL_NONE; + + // allocate initial buffer + rglBuffer->bufferSize = rglPad( bufferObject->size, RGL_BUFFER_OBJECT_BLOCK_SIZE ); + rglpsAllocateBuffer( bufferObject ); + + return rglBuffer->bufferId != GMM_ERROR; +} + +void rglPlatformDestroyBufferObject( rglBufferObject* bufferObject ) +{ + rglDeallocateBuffer( bufferObject ); +} + +void rglPlatformBufferObjectSetData( rglBufferObject* bufferObject, GLintptr offset, GLsizeiptr size, const GLvoid *data, GLboolean tryImmediateCopy ) +{ + rglGcmBufferObject *rglBuffer = ( rglGcmBufferObject * )bufferObject->platformBufferObject; + + if ( size == bufferObject->size && tryImmediateCopy ) + { + memcpy( gmmIdToAddress( rglBuffer->bufferId ) + offset, data, size ); + } + else + if ( size >= bufferObject->size ) + { + // reallocate the buffer + // To avoid waiting for the GPU to finish with the buffer, just + // allocate a whole new one. + rglBuffer->bufferSize = rglPad( size, RGL_BUFFER_OBJECT_BLOCK_SIZE ); + rglpsAllocateBuffer( bufferObject ); + + // copy directly to newly allocated memory + // TODO: For GPU destination, should we copy to system memory and + // pull from GPU? + switch ( rglBuffer->pool ) + { + case RGLGCM_SURFACE_POOL_NONE: + rglSetError( GL_OUT_OF_MEMORY ); + return; + default: + memcpy( gmmIdToAddress( rglBuffer->bufferId ), data, size ); + break; + } + } + else + { + if ( tryImmediateCopy ) + { + memcpy( gmmIdToAddress( rglBuffer->bufferId ) + offset, data, size ); + } + else + { + // partial buffer write + // STREAM and DYNAMIC buffers get transfer via a bounce buffer. + // copy via bounce buffer + rglGcmSend( rglBuffer->bufferId, offset, rglBuffer->pitch, ( const char * )data, size ); + } + } + + // be conservative here. Whenever we write to any Buffer Object, invalidate the vertex cache + rglGetGcmDriver()->invalidateVertexCache = GL_TRUE; +} + +GLvoid rglPlatformBufferObjectCopyData( + rglBufferObject* bufferObjectDst, + rglBufferObject* bufferObjectSrc ) +{ + rglGcmBufferObject* dst = ( rglGcmBufferObject* )bufferObjectDst->platformBufferObject; + rglGcmBufferObject* src = ( rglGcmBufferObject* )bufferObjectSrc->platformBufferObject; + + // copy data + // There is currently no requirement to copy from one pool to another. + + rglGcmMemcpy( dst->bufferId, 0, dst->pitch, src->bufferId, 0, src->bufferSize ); + + // be conservative here. Whenever we write to any Buffer Object, invalidate the vertex cache + rglGetGcmDriver()->invalidateVertexCache = GL_TRUE; +} + +char *rglPlatformBufferObjectMap( rglBufferObject* bufferObject, GLenum access ) +{ + rglGcmBufferObject *rglBuffer = ( rglGcmBufferObject * )bufferObject->platformBufferObject; + + if ( rglBuffer->mapCount++ == 0 ) + { + if ( access == GL_WRITE_ONLY ) + { + // replace entire buffer + // To avoid waiting for the GPU to finish using the buffer, + // just allocate a new one. + rglpsAllocateBuffer( bufferObject ); + if ( rglBuffer->pool == RGLGCM_SURFACE_POOL_NONE ) + { + rglSetError( GL_OUT_OF_MEMORY ); + return NULL; + } + } + else + rglpFifoGlFinish(); // must wait in order to read + + rglBuffer->mapAccess = access; + + // count writable mapped buffers + // If any buffers are left mapped when a draw is invoked, we must + // flush the vertex cache in case VBO data has been modified. + if ( rglBuffer->mapAccess != GL_READ_ONLY ) + { + rglGcmDriver *driver = rglGetGcmDriver(); + ++driver->flushBufferCount; + } + + // only need to pin the first time we map + gmmPinId( rglBuffer->bufferId ); + } + + return gmmIdToAddress( rglBuffer->bufferId ); +} + +GLboolean rglPlatformBufferObjectUnmap( rglBufferObject* bufferObject ) +{ + // can't unmap if not mapped + rglGcmBufferObject *rglBuffer = ( rglGcmBufferObject * )bufferObject->platformBufferObject; + + if ( --rglBuffer->mapCount == 0 ) + { + // count writable mapped buffers + // If any buffers are left mapped when a draw is invoked, we must + // flush the vertex cache in case VBO data has been modified. + if ( rglBuffer->mapAccess != GL_READ_ONLY ) + { + rglGcmDriver *driver = rglGetGcmDriver(); + --driver->flushBufferCount; + + // make sure we flush for the next draw + driver->invalidateVertexCache = GL_TRUE; + } + + rglBuffer->mapAccess = GL_NONE; + + gmmUnpinId( rglBuffer->bufferId ); + } + + return GL_TRUE; +} + +/*============================================================ + PLATFORM FRAME BUFFER OPERATIONS + ============================================================ */ + +void rglFBClear( GLbitfield mask ) +{ + RGLcontext* LContext = _CurrentContext; + + rglGcmDriver *driver = rglGetGcmDriver(); + if ( !driver->rtValid ) return; + + GLbitfield newmask = 0; + if (( mask & GL_COLOR_BUFFER_BIT ) && driver->rt.colorBufferCount ) newmask |= RGLGCM_COLOR_BUFFER_BIT; + + if ( !newmask ) return; + + GLbitfield clearMask = newmask; + if ( driver->rt.colorFormat != RGLGCM_ARGB8 ) clearMask &= ~RGLGCM_COLOR_BUFFER_BIT; + + // always use quad clear for colors with MRT + // There is one global clear mask for all render targets. This doesn't + // work nicely for all render target combinations, e.g. only the first + // and last targets enabled. Quad clear works because color mask is + // per target. + // + // TODO: Clear could be used if the enabled render targets are + // contiguous from 0, i.e. {0,1}, {0,1,2}, {0,1,2,3}. If this is done, + // parallel changes need to made in rglValidateWriteMask because we + // bypass calling rglGcmFifoGlColorMask there and the mask used by nv_glClear + // is not updated. + if ( driver->rt.colorBufferCount > 1 ) + clearMask &= ~RGLGCM_COLOR_BUFFER_BIT; + + if ( clearMask ) + { + rglGcmFifoGlClearColor( 0, 0, 0, 0); + + rglGcmFifoGlClear( clearMask ); + newmask &= ~clearMask; + } + + if ( newmask ) + { + // draw a quad to erase everything. + + // disable/set up a lot of states + // + + static float rglClearVertexBuffer[4*3] __attribute__(( aligned( RGL_ALIGN_FAST_TRANSFER ) ) ) = + { + -1.f, -1.f, 0.f, + -1.f, 1.f, 0.f, + 1.f, -1.f, 0.f, + 1.f, 1.f, 0.f, + }; + + GLuint bufferId = gmmAlloc((CellGcmContextData*)&rglGcmState_i.fifo, + CELL_GCM_LOCATION_LOCAL, 0, sizeof(rglClearVertexBuffer)); + + memcpy( gmmIdToAddress(bufferId), rglClearVertexBuffer, sizeof( rglClearVertexBuffer ) ); + rglGcmFifoGlVertexAttribPointer( 0, 3, RGLGCM_FLOAT, RGLGCM_FALSE, 3*sizeof( GLfloat ), 1, 0, gmmIdToOffset(bufferId) ); + RGLBIT_TRUE( LContext->attribs->DirtyMask, 0 ); + + for ( int i = 1;i < RGL_MAX_VERTEX_ATTRIBS;++i ) + { + rglGcmFifoGlVertexAttribPointer( i, 0, RGLGCM_FLOAT, 0, 0, 0, 0, 0 ); + RGLBIT_TRUE( LContext->attribs->DirtyMask, i ); + } + int clearcolor = 0; + rglGcmFifoGlVertexAttrib4fv( RGL_ATTRIB_PRIMARY_COLOR_INDEX, ( GLfloat* )&clearcolor ); + + LContext->needValidate |= RGL_VALIDATE_WRITE_MASK | RGL_VALIDATE_FRAGMENT_PROGRAM; + + gmmFree( bufferId ); + } + + rglGcmFifoGlFlush(); +} + +/*============================================================ + PLATFORM FRAMEBUFFER + ============================================================ */ + +rglFramebuffer* rglCreateFramebuffer( void ) +{ + rglFramebuffer* framebuffer = new rglPlatformFramebuffer(); + return framebuffer; +} + +void rglDestroyFramebuffer( rglFramebuffer* framebuffer ) +{ + delete framebuffer; +} + +GLenum rglPlatformFramebufferCheckStatus( rglFramebuffer* framebuffer ) +{ + RGLcontext* LContext = _CurrentContext; + + GLuint nBuffers = 0; // number of attached buffers + int width = 0; + int height = 0; + GLboolean sizeMismatch = GL_FALSE; + + // record attached images + // We have to verify that no image is attached more than once. The + // array is sized for color attachments plus depth and stencil. + rglImage* image[RGL_MAX_COLOR_ATTACHMENTS + 2] = {0}; + + // test colors + GLuint colorFormat = 0; + for ( int i = 0; i < RGL_MAX_COLOR_ATTACHMENTS; ++i ) + { + rglTexture* colorTexture = NULL; + GLuint colorFace = 0; + rglFramebufferGetAttachmentTexture( + LContext, + &framebuffer->color[i], + &colorTexture, + &colorFace ); + // TODO: Complete texture may not be required. + if ( colorTexture != NULL ) + { + if ( colorTexture->referenceBuffer && !colorTexture->isRenderTarget ) + { + //RGL_REPORT_EXTRA( RGL_REPORT_FRAMEBUFFER_UNSUPPORTED, "Framebuffer color attachment texture is a reference in a format that cannot be rendered to (swizzled texture, smaller than 16x16 or with more than 32 bits per pixel)" ); + return GL_FRAMEBUFFER_UNSUPPORTED_OES; + } + + // all attachments must have the same dimensions + image[nBuffers] = colorTexture->image; + if (( width && width != image[nBuffers]->width ) || + ( height && height != image[nBuffers]->height ) ) + sizeMismatch = GL_TRUE; + + width = image[nBuffers]->width; + height = image[nBuffers]->height; + + // all color attachments need the same format + if ( colorFormat && colorFormat != image[nBuffers]->internalFormat ) + { + //RGL_REPORT_EXTRA( RGL_REPORT_FRAMEBUFFER_INCOMPLETE, "Framebuffer attachments have inconsistent color formats" ); + return GL_FRAMEBUFFER_INCOMPLETE_FORMATS_OES; + } + colorFormat = image[nBuffers]->internalFormat; + + ++nBuffers; + } + } + + // check for supported color format + if ( nBuffers ) + { + if ( !rglIsDrawableColorFormat( colorFormat ) ) + { + //RGL_REPORT_EXTRA( RGL_REPORT_FRAMEBUFFER_UNSUPPORTED, "Color attachment to framebuffer must be a supported drawable format (GL_ARGB_SCE, GL_RGB16F_ARB, GL_RGBA16F_ARB, GL_RGB32F_ARB, GL_RGBA32F_ARB, GL_LUMINANCE32F_ARB)" ); + return GL_FRAMEBUFFER_UNSUPPORTED_OES; + } + switch ( colorFormat ) + { + case RGLGCM_ARGB8: + case RGLGCM_RGB5_A1_SCE: + case RGLGCM_RGB565_SCE: + case RGLGCM_FLOAT_R32: + break; + default: + return GL_FRAMEBUFFER_UNSUPPORTED_OES; + } + } + + // at least once attachment is required + if ( nBuffers == 0 ) + return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_OES; + + // verify no image is attached more than once + // This is an n-squared algorithm - n*log(n) is possible but + // probably not necessary (or even faster). + for ( GLuint i = 0; i < nBuffers; ++i ) + for ( GLuint j = i + 1; j < nBuffers; ++j ) + if ( image[i] == image[j] ) + return GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_OES; + + return GL_FRAMEBUFFER_COMPLETE_OES; +} + +void rglPlatformFramebuffer::validate( RGLcontext *LContext ) +{ + complete = ( rglPlatformFramebufferCheckStatus( this ) == GL_FRAMEBUFFER_COMPLETE_OES ); + if ( !complete ) return; + + GLuint width = RGLGCM_MAX_RT_DIMENSION; + GLuint height = RGLGCM_MAX_RT_DIMENSION; + + GLuint xscale = 1; + GLuint yscale = 1; + + // color + rt.colorBufferCount = 0; + rt.colorFormat = RGLGCM_NONE; + GLuint defaultPitch = 0; + GLuint defaultId = GMM_ERROR; + GLuint defaultIdOffset = 0; + for ( int i = 0; i < RGLGCM_SETRENDERTARGET_MAXCOUNT; ++i ) + { + // get the texture and face + rglTexture* colorTexture = NULL; + GLuint face = 0; + rglFramebufferGetAttachmentTexture( LContext, &color[i], &colorTexture, &face ); + if ( colorTexture == NULL ) continue; + + rglGcmTexture* nvTexture = ( rglGcmTexture * )colorTexture->platformTexture; + + // make sure texture is resident in a supported layout + // Some restrictions are added if a texture is used as a + // render target: + // + // - no swizzled semifat or fat formats + // - no swizzled smaller than 16x16 + // - no mipmapped cube maps in tiled memory + // - no cube maps with height not a multiple of 16 in tiled + // memory + // + // We may need to reallocate the texture if any of these + // are true. + // + // TODO: Measure time spent here and optimize if indicated. + if ( !colorTexture->isRenderTarget ) + { + colorTexture->isRenderTarget = GL_TRUE; + colorTexture->revalidate |= RGL_TEXTURE_REVALIDATE_LAYOUT; + } + rglPlatformValidateTextureResources( colorTexture ); + colorTexture->image->dataState = RGL_IMAGE_DATASTATE_GPU; + + // set the render target + rt.colorId[i] = nvTexture->gpuAddressId; + rt.colorIdOffset[i] = nvTexture->gpuAddressIdOffset + rglGetGcmImageOffset( &nvTexture->gpuLayout, face, 0 ); + rt.colorPitch[i] = nvTexture->gpuLayout.pitch ? nvTexture->gpuLayout.pitch : nvTexture->gpuLayout.pixelBits * nvTexture->gpuLayout.baseWidth / 8; + + width = MIN( width, nvTexture->gpuLayout.baseWidth ); + height = MIN( height, nvTexture->gpuLayout.baseHeight ); + rt.colorFormat = nvTexture->gpuLayout.internalFormat; + rt.colorBufferCount = i + 1; + defaultId = rt.colorId[i]; + defaultIdOffset = rt.colorIdOffset[i]; + defaultPitch = rt.colorPitch[i]; + } + + // framebuffer dimensions are the intersection of attachments + rt.width = width / xscale; + rt.height = height / yscale; + + rt.yInverted = RGLGCM_FALSE; + rt.xOffset = 0; + rt.yOffset = 0; + needValidate = GL_FALSE; +} + +// set render targets +void rglValidateFramebuffer( void ) +{ + RGLdevice *LDevice = _CurrentDevice; + rglGcmDevice *gcmDevice = ( rglGcmDevice * )LDevice->platformDevice; + + RGLcontext* LContext = _CurrentContext; + rglGcmDriver * gcmDriver = rglGetGcmDriver(); + + // reset buffer data + gcmDriver->rtValid = GL_FALSE; + // get buffer parameters + // This may come from a framebuffer_object or the default framebuffer. + if ( LContext->framebuffer ) + { + rglPlatformFramebuffer* framebuffer = static_cast( rglGetFramebuffer( LContext, LContext->framebuffer ) ); + + if ( framebuffer->needValidate ) framebuffer->validate( LContext ); + + gcmDriver->rt = framebuffer->rt; + } + else // use default framebuffer + gcmDriver->rt = gcmDevice->rt; + + gcmDriver->rtValid = GL_TRUE; + + // update GPU configuration + rglGcmFifoGlSetRenderTarget( &gcmDriver->rt ); + + LContext->needValidate &= ~RGL_VALIDATE_FRAMEBUFFER; + LContext->needValidate |= RGL_VALIDATE_VIEWPORT | RGL_VALIDATE_SCISSOR_BOX + | RGL_VALIDATE_WRITE_MASK; +} + +/*============================================================ + PLATFORM RASTER + ============================================================ */ + +#define RGL_ATTRIB_BUFFER_ALIGNMENT 16 + +// maximum size for drawing data +#define RGLGCM_MAX_VERTEX_BUFFER_SIZE (2 << 20) +#define RGLGCM_MAX_INDEX_BUFFER_SIZE (1 << 20) + +// Initialize the driver and setup the fixed function pipeline +// shader and needed connections between GL state and the shader +void *rglPlatformRasterInit() +{ + rglpFifoGlFinish(); + rglGcmDriver *driver = ( rglGcmDriver * )malloc( sizeof( rglGcmDriver ) ); + memset( driver, 0, sizeof( rglGcmDriver ) ); + + driver->rt.yInverted = RGLGCM_TRUE; + + driver->invalidateVertexCache = GL_FALSE; + + driver->flushBufferCount = 0; + + // [YLIN] Make it 16 byte align + driver->sharedVPConstants = ( char * )memalign( 16, 4 * sizeof( float ) * RGL_MAX_VP_SHARED_CONSTANTS ); + driver->sharedFPConstantsId = gmmAlloc((CellGcmContextData*)&rglGcmState_i.fifo, + CELL_GCM_LOCATION_LOCAL, 0, 4 * sizeof(float) * RGL_MAX_FP_SHARED_CONSTANTS); + return driver; +} + +// Destroy the driver, and free all its used memory +void rglPlatformRasterExit( void *drv ) +{ + rglGcmDriver *driver = ( rglGcmDriver * )drv; + + gmmFree( driver->sharedFPConstantsId ); + free( driver->sharedVPConstants ); + + if ( driver ) + free( driver ); +} + +/** + * @} + */ + +/////////////////////////////////////////////////////////////////////////// +void rglDumpFifo( char * name ); +extern bool _cellRSXFifoDisassembleToFileMask; + +// Fast rendering path called by several glDraw calls: +// glDrawElements, glDrawRangeElements, glDrawArrays +// Slow rendering calls this function also, though it must also perform various +// memory setup operations first +void rglPlatformDraw( rglDrawParams* dparams ) +{ + rglGcmDriver *driver = rglGetGcmDriver(); + if (RGL_UNLIKELY(!driver->rtValid)) + return; + + // check for any writable mapped buffers + if ( driver->flushBufferCount != 0 ) + driver->invalidateVertexCache = GL_TRUE; + + GLboolean isMain = 0; + GLuint gpuOffset = GMM_ERROR; + + uint32_t totalXfer = 0; + for ( GLuint i = 0; i < RGL_MAX_VERTEX_ATTRIBS; ++i ) + totalXfer += dparams->attribXferSize[i]; + + gpuOffset = rglValidateAttributesSlow( dparams, &isMain ); + + if ( driver->invalidateVertexCache ) + { + driver->invalidateVertexCache = GL_FALSE; + GCM_FUNC_NO_ARGS( cellGcmSetInvalidateVertexCache ); + } + + // if fpLoadProgramId is in main memory need set the CELL_GCM_LOCATION_MAIN + if ( gmmIdIsMain(driver->fpLoadProgramId) ) + { + GCM_FUNC( cellGcmSetUpdateFragmentProgramParameterLocation, + gmmIdToOffset( driver->fpLoadProgramId ) + driver->fpLoadProgramOffset, CELL_GCM_LOCATION_MAIN ); + } + else + { + GCM_FUNC( cellGcmSetUpdateFragmentProgramParameter, + gmmIdToOffset( driver->fpLoadProgramId ) + driver->fpLoadProgramOffset ); + } + + + // glDrawArrays() + rglGcmFifoGlDrawArrays(( rglGcmEnum )dparams->mode, dparams->firstVertex, dparams->vertexCount ); +} + + +// Set up the current fragment program on hardware +void rglValidateFragmentProgram() +{ + RGLcontext* LContext = _CurrentContext; + rglGcmDriver *driver = rglGetGcmDriver(); + _CGprogram *program = LContext->BoundFragmentProgram; + + // params are set directly in the GPU memory, so there is nothing to be done here. + rglSetNativeCgFragmentProgram( program ); + driver->fpLoadProgramId = program->loadProgramId; + driver->fpLoadProgramOffset = program->loadProgramOffset; +} + +// must always call this before rglPlatformDraw() to setup rglDrawParams +GLboolean rglPlatformRequiresSlowPath( rglDrawParams* dparams, const GLenum indexType, uint32_t indexCount) +{ + RGLcontext* LContext = _CurrentContext; + rglAttributeState* as = LContext->attribs; + + // are any enabled attributes on the client-side? + const GLuint clientSideMask = as->EnabledMask & ~as->HasVBOMask; + if ( RGL_UNLIKELY( clientSideMask ) ) + { + // determine transfer buffer requirements for client-side attributes + for ( int i = 0; i < RGL_MAX_VERTEX_ATTRIBS; ++i ) + { + if ( clientSideMask & ( 1 << i ) ) + { + rglAttribute* attrib = as->attrib + i; + const GLuint freq = attrib->frequency; + GLuint count = ( (dparams->firstVertex + dparams->vertexCount) + freq - 1 ) / freq; + + const GLuint numBytes = attrib->clientStride * count; + dparams->attribXferOffset[i] = dparams->xferTotalSize; + dparams->attribXferSize[i] = numBytes; + + const GLuint numBytesPadded = rglPad( numBytes, 128 ); + dparams->xferTotalSize += numBytesPadded; + dparams->attribXferTotalSize += numBytesPadded; + } + else + { + dparams->attribXferOffset[i] = 0; + dparams->attribXferSize[i] = 0; + } + } + } + + return GL_FALSE; // we are finally qualified for the fast path +} + +// Return the current RGLGcmDriver +rglGcmDriver* rglGetRGLGcmDriver() +{ + return ( rglGcmDriver * )( _CurrentDevice->rasterDriver ); +} + +void rglPlatformRasterFlush() +{ + rglGcmFifoGlFlush(); +} + +void rglpFifoGlFinish( void ) +{ + GCM_FUNC_NO_ARGS( cellGcmSetInvalidateVertexCache ); + rglGcmFifoFinish( &rglGcmState_i.fifo ); +} + +// validates attributes for specified draw paramaters +// returns pointer to index buffer +GLuint rglValidateAttributesSlow( rglDrawParams *dparams, GLboolean *isMain ) +{ + RGLcontext* LContext = _CurrentContext; + rglGcmDriver *driver = rglGetGcmDriver(); + rglAttributeState* as = LContext->attribs; + + // allocate upload transfer buffer if necessary + // The higher level bounce buffer allocator is used, which means that + // the buffer will automatically be freed after all RGLGCM calls up to + // the next allocation have finished. + void* xferBuffer = NULL; + GLuint xferId = GMM_ERROR; + GLuint VBOId = GMM_ERROR; + GLuint gpuOffset; + if ( RGL_UNLIKELY( dparams->xferTotalSize ) ) + { + xferId = gmmAlloc((CellGcmContextData*)&rglGcmState_i.fifo, + CELL_GCM_LOCATION_LOCAL, 0, dparams->xferTotalSize); + xferBuffer = gmmIdToAddress(xferId); + } + + + // which attributes are known to need updating? + // (due to being dirty or enabled client-side arrays) + rglBitfield needsUpdateMask = ( as->DirtyMask | ( as->EnabledMask & ~as->HasVBOMask ) ); + + // for any remaining attributes that need updating, do it now. + if ( needsUpdateMask ) + { + for ( GLuint i = 0; i < RGL_MAX_VERTEX_ATTRIBS; ++i ) + { + // skip this attribute if not needing update + if ( ! RGLBIT_GET( needsUpdateMask, i ) ) continue; + + rglAttribute* attrib = as->attrib + i; + if ( RGLBIT_GET( as->EnabledMask, i ) ) + { + const GLsizei stride = attrib->clientStride; + const GLuint freq = attrib->frequency; + + if ( RGL_UNLIKELY( dparams->attribXferSize[i] ) ) + { + // attribute data is client side, need to transfer + + // don't transfer data that is not going to be used, from 0 to first*stride + GLuint offset = ( dparams->firstVertex / freq ) * stride; + + char * b = ( char * )xferBuffer + dparams->attribXferOffset[i]; + memcpy( b + offset, + ( char * )attrib->clientData + offset, + dparams->attribXferSize[i] - offset ); + + // draw directly from bounce buffer + *isMain = gmmIdIsMain(xferId); + gpuOffset = gmmIdToOffset(xferId) + (b - ( char * )xferBuffer); + + } + else + { + // attribute data in VBO, clientData is offset. + VBOId = rglGcmGetBufferObjectOrigin( attrib->arrayBuffer ); + *isMain = gmmIdIsMain(VBOId); + gpuOffset = gmmIdToOffset(VBOId) + + (( const GLubyte* )attrib->clientData - ( const GLubyte* )NULL ); + } + + rglGcmFifoGlVertexAttribPointer( i, attrib->clientSize, + ( rglGcmEnum )attrib->clientType, attrib->normalized, + stride, freq, *isMain, gpuOffset ); + } + else + { + // attribute is disabled + rglGcmFifoGlVertexAttribPointer( i, 0, RGLGCM_FLOAT, 0, 0, 0, 0, 0 ); + rglGcmFifoGlVertexAttrib4fv( i, attrib->value ); + } + } + driver->invalidateVertexCache = GL_TRUE; + } + as->DirtyMask = 0; // all attributes are now clean + + // validate index buffer + GLuint indexOffset = 0; + + if ( xferId != GMM_ERROR ) + gmmFree( xferId ); + + return indexOffset; +} + +/*============================================================ + PLATFORM TEXTURE + ============================================================ */ + +// Calculate required size in bytes for given texture layout +GLuint rglGetGcmTextureSize( rglGcmTextureLayout *layout ) +{ + GLuint bytesNeeded = 0; + GLuint faceAlign = layout->pitch ? 1 : 128; + + GLuint minWidth = 1; + GLuint minHeight = 1; + for ( GLuint face = 0;face < layout->faces;++face ) + { + GLuint width = layout->baseWidth; + GLuint height = layout->baseHeight; + GLuint depth = layout->baseDepth; + for ( GLuint i = 0;i < layout->levels; ++i ) + { + width = MAX( minWidth, width ); + height = MAX( minHeight, height ); + depth = MAX( 1U, depth ); + + if ( !layout->pitch ) + bytesNeeded += layout->pixelBits * width * height * depth / 8; + else + bytesNeeded += height * depth * layout->pitch; + + width >>= 1; + height >>= 1; + depth >>= 1; + } + + bytesNeeded = rglPad( bytesNeeded, faceAlign ); + } + + return bytesNeeded; +} + +// Calculate byte offset for given texture layout, number of faces, and levels +GLuint rglGetGcmImageOffset( rglGcmTextureLayout *layout, GLuint face, GLuint level ) +{ + GLuint bytes = 0; + GLuint faceAlign = layout->pitch ? 1 : 128; + + GLuint minWidth = 1; + GLuint minHeight = 1; + + for ( GLuint f = 0;f < layout->faces;++f ) + { + GLuint width = layout->baseWidth; + GLuint height = layout->baseHeight; + GLuint depth = layout->baseDepth; + for ( GLuint i = 0;i < layout->levels; ++i ) + { + if (( level == i ) && ( face == f ) ) return bytes; + + width = MAX( minWidth, width ); + height = MAX( minHeight, height ); + depth = MAX( 1U, depth ); + + if ( !layout->pitch ) + bytes += layout->pixelBits * width * height * depth / 8; + else + bytes += height * depth * layout->pitch; + + width >>= 1; + height >>= 1; + depth >>= 1; + } + + bytes = rglPad( bytes, faceAlign ); + } + return 0; +} +// Get size of a texture +int rglPlatformTextureSize() +{ + return sizeof( rglGcmTexture ); +} + +// Calculate pitch for a texture +static GLuint _getTexturePitch( const rglTexture * texture ) +{ + return rglPad( rglGetStorageSize( texture->image->format, texture->image->type, texture->image->width, 1, 1 ), 64 ); // TransferVid2Vid needs 64byte pitch alignment +} + +// Return maximum number of texture image units +int rglPlatformTextureMaxUnits() +{ + return RGLGCM_MAX_TEXIMAGE_COUNT; +} + +// Create a gcm texture by initializing memory to 0 +void rglPlatformCreateTexture( rglTexture* texture ) +{ + rglGcmTexture *gcmTexture = ( rglGcmTexture * )texture->platformTexture; + memset( gcmTexture, 0, sizeof( rglGcmTexture ) ); + gcmTexture->gpuAddressId = GMM_ERROR; +} + + +void rglPlatformFreeGcmTexture( rglTexture* texture ); + +// Destroy a texture by freeing a gcm texture and an associated PBO +void rglPlatformDestroyTexture( rglTexture* texture ) +{ + if ( !texture->referenceBuffer ) + rglPlatformFreeGcmTexture( texture ); + + rglTextureTouchFBOs( texture ); +} + +// Get size of texture in GPU layout +inline static GLuint rglPlatformTextureGetGPUSize( const rglTexture* texture ) +{ + rglGcmTexture *gcmTexture = ( rglGcmTexture * )texture->platformTexture; + return rglGetGcmTextureSize( &gcmTexture->gpuLayout ); +} + +// Drop a texture from the GPU memory by detaching it from a PBO +void rglPlatformDropTexture( rglTexture *texture ) +{ + rglGcmTexture *gcmTexture = ( rglGcmTexture * )texture->platformTexture; + + if (gcmTexture->pool != RGLGCM_SURFACE_POOL_NONE) + { + rglPlatformFreeGcmTexture( texture ); + } + + gcmTexture->pool = RGLGCM_SURFACE_POOL_NONE; + gcmTexture->gpuAddressId = GMM_ERROR; + gcmTexture->gpuAddressIdOffset = 0; + gcmTexture->gpuSize = 0; + texture->revalidate |= RGL_TEXTURE_REVALIDATE_IMAGES; + rglTextureTouchFBOs( texture ); +} + +// Drop unbound textures from the GPU memory +// This is kind of slow, but we hit a slow path anyway. +// If the pool argument is not RGLGCM_SURFACE_POOL_NONE, then only textures +// in the specified pool will be dropped. +void rglPlatformDropUnboundTextures( GLenum pool ) +{ + RGLcontext* LContext = _CurrentContext; + GLuint i, j; + for ( i = 0;i < LContext->textureNameSpace.capacity;++i ) + { + GLboolean bound = GL_FALSE; + rglTexture *texture = ( rglTexture * )LContext->textureNameSpace.data[i]; + if ( !texture || ( texture->referenceBuffer != 0 ) ) continue; + + // check if bound + for ( j = 0;j < RGL_MAX_TEXTURE_IMAGE_UNITS;++j ) + { + rglTextureImageUnit *tu = LContext->TextureImageUnits + j; + if ( tu->bound2D == i) + { + bound = GL_TRUE; + break; + } + } + if ( bound ) + continue; + + rglGcmTexture *gcmTexture = ( rglGcmTexture * )texture->platformTexture; + + // check pool + if ( pool != RGLGCM_SURFACE_POOL_NONE && + pool != gcmTexture->pool ) + continue; + + rglPlatformDropTexture( texture ); + } +} + +// Drop filitering mode for FP32 texture +static inline GLenum unFilter( GLenum filter ) +{ + GLenum newFilter; + switch ( filter ) + { + case GL_NEAREST: + case GL_LINEAR: + newFilter = GL_NEAREST; + break; + case GL_NEAREST_MIPMAP_NEAREST: + case GL_NEAREST_MIPMAP_LINEAR: + case GL_LINEAR_MIPMAP_NEAREST: + case GL_LINEAR_MIPMAP_LINEAR: + newFilter = GL_NEAREST_MIPMAP_NEAREST; + break; + default: + newFilter = GL_NEAREST; + } + return newFilter; +} + +// Choose a texture layout and store it to newLayout, based on texture's filtering mode, swizzling, and size +void rglPlatformChooseGPUFormatAndLayout( + const rglTexture* texture, + GLboolean forceLinear, + GLuint pitch, + rglGcmTextureLayout* newLayout ) +{ + rglImage *image = texture->image + texture->baseLevel; + + GLuint levels = rglLog2( MAX( MAX( image->width, image->height ), image->depth ) ) + 1; + levels = MIN( levels, texture->maxLevel + 1 ); + + // if we don't want mipmapping, but still have valid mipmaps, load all the mipmaps. + // This is to avoid a big cost when switching from mipmaps to non-mipmaps. + if (( texture->minFilter == GL_LINEAR ) || ( texture->minFilter == GL_NEAREST ) ) + { + levels = 1; + } + + newLayout->levels = levels; + newLayout->faces = texture->faceCount; + newLayout->baseWidth = image->width; + newLayout->baseHeight = image->height; + newLayout->baseDepth = image->depth; + newLayout->internalFormat = ( rglGcmEnum )image->internalFormat; + newLayout->pixelBits = rglPlatformGetBitsPerPixel( newLayout->internalFormat ); + newLayout->pitch = pitch ? pitch : _getTexturePitch( texture ); +} + +// texture strategy actions +// A texture strategy is a sequence of actions represented by these tokens. +// RGL_TEXTURE_STRATEGY_END must be the last token in any strategy. +enum rglTextureStrategy { + RGL_TEXTURE_STRATEGY_END, // allocation failed, give up + RGL_TEXTURE_STRATEGY_FORCE_LINEAR, + RGL_TEXTURE_STRATEGY_TILED_ALLOC, + RGL_TEXTURE_STRATEGY_TILED_CLEAR, + RGL_TEXTURE_STRATEGY_UNTILED_ALLOC, + RGL_TEXTURE_STRATEGY_UNTILED_CLEAR, + RGL_TEXTURE_STRATEGY_SYSTEM_ALLOC, + RGL_TEXTURE_STRATEGY_SYSTEM_CLEAR, // XXX probably not useful +}; + +static enum rglTextureStrategy tiledGPUStrategy[] = +{ + RGL_TEXTURE_STRATEGY_TILED_ALLOC, // try tiled alloction + RGL_TEXTURE_STRATEGY_FORCE_LINEAR, + RGL_TEXTURE_STRATEGY_UNTILED_ALLOC, // if failure, try linear allocation + RGL_TEXTURE_STRATEGY_UNTILED_CLEAR, // if failure, drop linear textures + RGL_TEXTURE_STRATEGY_UNTILED_ALLOC, // try linear again + RGL_TEXTURE_STRATEGY_END, // give up +}; +static enum rglTextureStrategy linearGPUStrategy[] = +{ + RGL_TEXTURE_STRATEGY_FORCE_LINEAR, + RGL_TEXTURE_STRATEGY_UNTILED_ALLOC, + RGL_TEXTURE_STRATEGY_UNTILED_CLEAR, + RGL_TEXTURE_STRATEGY_UNTILED_ALLOC, + RGL_TEXTURE_STRATEGY_END, +}; +static enum rglTextureStrategy swizzledGPUStrategy[] = +{ + RGL_TEXTURE_STRATEGY_UNTILED_ALLOC, + RGL_TEXTURE_STRATEGY_UNTILED_CLEAR, + RGL_TEXTURE_STRATEGY_UNTILED_ALLOC, + RGL_TEXTURE_STRATEGY_END, +}; +static enum rglTextureStrategy linearSystemStrategy[] = +{ + RGL_TEXTURE_STRATEGY_FORCE_LINEAR, + RGL_TEXTURE_STRATEGY_SYSTEM_ALLOC, + RGL_TEXTURE_STRATEGY_END, +}; +static enum rglTextureStrategy swizzledSystemStrategy[] = +{ + RGL_TEXTURE_STRATEGY_SYSTEM_ALLOC, + RGL_TEXTURE_STRATEGY_END, +}; + +// Reallocate texture based on usage, pool system, and strategy +void rglPlatformReallocateGcmTexture( rglTexture* texture ) +{ + rglGcmTexture *gcmTexture = ( rglGcmTexture * )texture->platformTexture; + + // select the allocation strategy + enum rglTextureStrategy *step = NULL; + switch ( texture->usage ) + { + case GL_TEXTURE_TILED_GPU_SCE: + step = tiledGPUStrategy; + break; + case GL_TEXTURE_LINEAR_GPU_SCE: + step = linearGPUStrategy; + break; + case GL_TEXTURE_SWIZZLED_GPU_SCE: + step = swizzledGPUStrategy; + break; + case GL_TEXTURE_LINEAR_SYSTEM_SCE: + step = linearSystemStrategy; + break; + case GL_TEXTURE_SWIZZLED_SYSTEM_SCE: + step = swizzledSystemStrategy; + break; + default: + step = swizzledGPUStrategy; + break; + } + + GLuint size = 0; + GLuint id = GMM_ERROR; + + // allow swizzled format unless explicitly disallowed + // PBO textures cannot be swizzled. + GLboolean forceLinear = GL_FALSE; + + const rglGcmTextureLayout currentLayout = gcmTexture->gpuLayout; + const GLuint currentSize = gcmTexture->gpuSize; + + // process strategy + GLboolean done = GL_FALSE; + while ( !done ) + { + rglGcmTextureLayout newLayout; + + switch ( *step++ ) + { + case RGL_TEXTURE_STRATEGY_FORCE_LINEAR: + forceLinear = GL_TRUE; + break; + case RGL_TEXTURE_STRATEGY_UNTILED_ALLOC: + // get layout and size compatible with this pool + rglPlatformChooseGPUFormatAndLayout( texture, forceLinear, 0, &newLayout ); + size = rglGetGcmTextureSize( &newLayout ); + + // determine if current allocation already works + // If the current allocation has the right size and pool, we + // don't have to do anything. If not, we only drop from the + // target pool because we may reuse the allocation from a + // different pool in a later step. + if ( gcmTexture->pool == RGLGCM_SURFACE_POOL_LINEAR ) + { + if ( currentSize >= size && newLayout.pitch == currentLayout.pitch ) + { + gcmTexture->gpuLayout = newLayout; + done = GL_TRUE; + } + else + rglPlatformDropTexture( texture ); + } + + if ( !done ) + { + // allocate in the specified pool + id = gmmAlloc((CellGcmContextData*)&rglGcmState_i.fifo, + CELL_GCM_LOCATION_LOCAL, + 0, + size); + if ( id != GMM_ERROR ) + { + // drop old allocation + if ( gcmTexture->pool != RGLGCM_SURFACE_POOL_NONE ) + rglPlatformDropTexture( texture ); + + // set new + gcmTexture->pool = RGLGCM_SURFACE_POOL_LINEAR; + gcmTexture->gpuAddressId = id; + gcmTexture->gpuAddressIdOffset = 0; + gcmTexture->gpuSize = size; + gcmTexture->gpuLayout = newLayout; + + done = GL_TRUE; + } + } + break; + case RGL_TEXTURE_STRATEGY_UNTILED_CLEAR: + rglPlatformDropUnboundTextures( RGLGCM_SURFACE_POOL_LINEAR ); + break; + case RGL_TEXTURE_STRATEGY_END: + rglSetError( GL_OUT_OF_MEMORY ); + done = GL_TRUE; + break; + default: + break; + } + } // while loop for allocation strategy steps + rglTextureTouchFBOs( texture ); +} + +// Free memory pooled by a GCM texture +void rglPlatformFreeGcmTexture( rglTexture* texture ) +{ + rglGcmTexture *gcmTexture = ( rglGcmTexture * )texture->platformTexture; + switch ( gcmTexture->pool ) + { + case RGLGCM_SURFACE_POOL_LINEAR: + gmmFree( gcmTexture->gpuAddressId ); + break; + case RGLGCM_SURFACE_POOL_SYSTEM: + gmmFree( gcmTexture->gpuAddressId ); + break; + case RGLGCM_SURFACE_POOL_TILED_COLOR: + rglGcmFreeTiledSurface( gcmTexture->gpuAddressId ); + break; + case RGLGCM_SURFACE_POOL_NONE: + break; + } + + + gcmTexture->gpuAddressId = GMM_ERROR; + gcmTexture->gpuAddressIdOffset = 0; + gcmTexture->gpuSize = 0; +} + +// Upload texure from host memory to GPU memory +void rglPlatformUploadTexture( rglTexture* texture ) +{ + rglGcmTexture *gcmTexture = ( rglGcmTexture * )texture->platformTexture; + rglGcmTextureLayout *layout = &gcmTexture->gpuLayout; + + const GLuint pixelBytes = layout->pixelBits / 8; + + // host texture requires sync + + // create surface descriptors for image transfer + rglGcmSurface src = { +source: RGLGCM_SURFACE_SOURCE_TEMPORARY, + width: 0, // replaced per image + height: 0, // replaced per image + bpp: pixelBytes, + pitch: 0, // replaced per image + format: layout->internalFormat, + pool: RGLGCM_SURFACE_POOL_LINEAR, // via bounce buffer + ppuData: NULL, // replaced per image + dataId: GMM_ERROR, + dataIdOffset:0, + }; + + rglGcmSurface dst = { +source: RGLGCM_SURFACE_SOURCE_TEXTURE, + width: 0, // replaced per image + height: 0, // replaced per image + bpp: pixelBytes, + pitch: layout->pitch, + format: layout->internalFormat, + pool: gcmTexture->pool, + ppuData: NULL, // replaced per image + dataId: GMM_ERROR, + dataIdOffset:0, + }; + + // use a bounce buffer to transfer to GPU + GLuint bounceBufferId = GMM_ERROR; + { + { + // check if upload is needed for this image + rglImage *image = texture->image; + if ( image->dataState == RGL_IMAGE_DATASTATE_HOST ) + { + // determine image offset from base address + // TODO: compute all offsets at once for efficiency + // This is the offset in bytes for this face/image from the + // texture base address. + const GLuint dataOffset = rglGetGcmImageOffset( layout, 0, 0 ); + + // set source pixel buffer + src.ppuData = image->data; + + // lazy allocation of bounce buffer + if ( bounceBufferId == GMM_ERROR && layout->baseDepth == 1 ) + bounceBufferId = gmmAlloc((CellGcmContextData*)&rglGcmState_i.fifo, + CELL_GCM_LOCATION_LOCAL, 0, gcmTexture->gpuSize); + + if ( bounceBufferId != GMM_ERROR ) + { + // copy image to bounce buffer + src.dataId = bounceBufferId; + src.dataIdOffset = dataOffset; + + // NPOT DXT + memcpy( gmmIdToAddress( src.dataId ) + dataOffset, + image->data, + image->storageSize ); + } + + { + // use surface copy functions + src.width = image->width; + src.height = image->height; + src.pitch = pixelBytes * src.width; + + dst.width = src.width; + dst.height = image->height; + dst.dataId = gcmTexture->gpuAddressId; + dst.dataIdOffset = gcmTexture->gpuAddressIdOffset + dataOffset; + + GLuint offsetHeight = 0; + if ( dst.pitch ) + { + // linear (not swizzled) + // The tiled linear format requires that render + // targets be aligned to 8*pitch from the start of + // the tiled region. + offsetHeight = ( dataOffset / dst.pitch ) % 8; + dst.height += offsetHeight; + dst.dataIdOffset -= offsetHeight * dst.pitch; + } + + rglGcmCopySurface( + &src, 0, 0, + &dst, 0, offsetHeight, + src.width, src.height, + GL_TRUE ); // don't bypass GPU pipeline + } + + // free CPU copy of data + rglImageFreeCPUStorage( image ); + image->dataState |= RGL_IMAGE_DATASTATE_GPU; + } // newer data on host + } // loop over levels + } // loop over faces + + if ( bounceBufferId != GMM_ERROR ) + gmmFree( bounceBufferId ); + + rglGcmFifoGlInvalidateTextureCache(); +} + +// map RGL internal types to GCM +static inline void rglGcmUpdateGcmTexture( rglTexture * texture, rglGcmTextureLayout * layout, rglGcmTexture * platformTexture ) +{ + // use color format for depth with no compare mode + // This hack is needed because the hardware will not read depth + // textures without performing a compare. The depth value will need to + // be reconstructed in the shader from the color components. + GLuint internalFormat = layout->internalFormat; + + // set the format and remap( control 1) + rglGcmMapTextureFormat( internalFormat, + platformTexture->gcmTexture.format, platformTexture->gcmTexture.remap ); + + // This is just to cover the conversion from swizzled to linear + if ( layout->pitch ) + { + platformTexture->gcmTexture.format += 0x20; // see class doc definitions for SZ_NR vs LN_NR... + } + + platformTexture->gcmTexture.width = layout->baseWidth; + platformTexture->gcmTexture.height = layout->baseHeight; + platformTexture->gcmTexture.depth = layout->baseDepth; + platformTexture->gcmTexture.pitch = layout->pitch; + + platformTexture->gcmTexture.mipmap = layout->levels; + + // set the dimention and cubmap settings + // default is false + platformTexture->gcmTexture.cubemap = CELL_GCM_FALSE; + + // set dimension, swizzled implies P2 width/height/depth + switch ( texture->target ) + { + case 0: + case RGLGCM_TEXTURE_2D: + platformTexture->gcmTexture.dimension = CELL_GCM_TEXTURE_DIMENSION_2; + break; + } + + // system or local texture + platformTexture->gcmTexture.location = CELL_GCM_LOCATION_LOCAL; + +} + +// map RGL internal types to GCM +void rglGcmUpdateMethods( rglTexture * texture ) +{ + + rglGcmTexture *platformTexture = ( rglGcmTexture * )texture->platformTexture; + rglGcmTextureLayout *layout = &platformTexture->gpuLayout; + + // max aniso + // revalidate the texture registers cache. + int maxAniso = ( int )texture->maxAnisotropy; + GLuint minFilter = texture->minFilter; + GLuint magFilter = texture->magFilter; + + // XXX make sure that REVALIDATE_PARAMETERS is set if the format of the texture changes + // revalidate the texture registers cache just to ensure we are in the correct filtering mode + // based on the internal format. + switch ( layout->internalFormat ) + { + case RGLGCM_FLOAT_R32: + // float 32 doesn't support filtering + minFilter = unFilter( minFilter ); + magFilter = unFilter( magFilter ); + maxAniso = 1; + break; + default: + break; + } + + // ----------------------------------------------------------------------- + // map the SET_TEXTURE_FILTER method. + // set the min + platformTexture->gcmMethods.filter.min = rglGcmMapMinTextureFilter( minFilter ); + // set the mag + platformTexture->gcmMethods.filter.mag = rglGcmMapMagTextureFilter( magFilter ); + // set the QuinConx by default + platformTexture->gcmMethods.filter.conv = CELL_GCM_TEXTURE_CONVOLUTION_QUINCUNX; + // We don't actually expose this, but still need to set it up properly incase we expose this later + // hw expects a 5.8 twos-complement fixed-point // XXX what is the - .26f ? + platformTexture->gcmMethods.filter.bias = ( GLint )(( texture->lodBias - .26f ) * 256.0f ); + + // ----------------------------------------------------------------------- + // set the SET_TEXTURE_CONTROL0 params + platformTexture->gcmMethods.control0.maxAniso = rglGcmMapAniso( maxAniso ); + const GLfloat minLOD = MAX( texture->minLod, texture->baseLevel ); + const GLfloat maxLOD = MIN( texture->maxLod, texture->maxLevel ); + platformTexture->gcmMethods.control0.minLOD = ( GLuint )( MAX( minLOD, 0 ) * 256.0f ); + platformTexture->gcmMethods.control0.maxLOD = ( GLuint )( MIN( maxLOD, layout->levels ) * 256.0f ); + + // ----------------------------------------------------------------------- + // set the SET_TEXTURE_ADDRESS method params. + platformTexture->gcmMethods.address.wrapS = rglGcmMapWrapMode( texture->wrapS ); + platformTexture->gcmMethods.address.wrapT = rglGcmMapWrapMode( texture->wrapT ); + platformTexture->gcmMethods.address.wrapR = rglGcmMapWrapMode( texture->wrapR ); + platformTexture->gcmMethods.address.unsignedRemap = CELL_GCM_TEXTURE_UNSIGNED_REMAP_NORMAL; + + // now for gamma remap + GLuint gamma = 0; + GLuint remap = texture->gammaRemap; + gamma |= ( remap & RGLGCM_GAMMA_REMAP_RED_BIT ) ? CELL_GCM_TEXTURE_GAMMA_R : 0; + gamma |= ( remap & RGLGCM_GAMMA_REMAP_GREEN_BIT ) ? CELL_GCM_TEXTURE_GAMMA_G : 0; + gamma |= ( remap & RGLGCM_GAMMA_REMAP_BLUE_BIT ) ? CELL_GCM_TEXTURE_GAMMA_B : 0; + gamma |= ( remap & RGLGCM_GAMMA_REMAP_ALPHA_BIT ) ? CELL_GCM_TEXTURE_GAMMA_A : 0; + + platformTexture->gcmMethods.address.gamma = gamma; + + // set border colors + RGLGCM_CALC_COLOR_LE_ARGB8(&(platformTexture->gcmMethods.borderColor), + texture->borderColor.R, texture->borderColor.G, texture->borderColor.B, texture->borderColor.A); + + // ----------------------------------------------------------------------- + // setup the GcmTexture + // format, control1, control3, imagerect; setup for cellGcmSetTexture later + rglGcmUpdateGcmTexture( texture, layout, platformTexture ); + +} + +// Validate texture resources +void rglPlatformValidateTextureResources( rglTexture *texture ) +{ + texture->isComplete = GL_TRUE; + + // We may need to reallocate the texture when the parameters are changed + // from non-mipmap to mipmap filtering, even though the images have not + // changed. + // + // NOTE: If we ever support accessing mipmaps from a PBO, this code + // must be changed. As it is, if the texture has a shared PBO and the + // mipmap flag then the slow path (copy back to host) is invoked. + if ( texture->revalidate & RGL_TEXTURE_REVALIDATE_IMAGES || texture->revalidate & RGL_TEXTURE_REVALIDATE_LAYOUT ) + { + // upload images + rglPlatformReallocateGcmTexture( texture ); + rglPlatformUploadTexture( texture ); + } + + // gcmTexture method command + rglGcmUpdateMethods( texture ); + + texture->revalidate = 0; +} + +// [YLIN] We are going to use gcm macro directly! +#include + +// Set a texture to a gcm texture unit +static inline void rglGcmSetTextureUnit( GLuint unit, rglGcmTexture *platformTexture ) +{ + const GLuint imageOffset = gmmIdToOffset(platformTexture->gpuAddressId) + platformTexture->gpuAddressIdOffset; + platformTexture->gcmTexture.offset = imageOffset; + + // set up the texture unit with the info for the current texture + // bind texture , control 1,3,format and remap + // [YLIN] Contiguous GCM calls in fact will cause LHSs between them + // There is no walkaround for this but not to use GCM functions + + GCM_FUNC_SAFE( cellGcmSetTexture, unit, &platformTexture->gcmTexture ); + CellGcmContextData *gcm_context = (CellGcmContextData*)&rglGcmState_i.fifo; + cellGcmReserveMethodSizeInline(gcm_context, 11); + uint32_t *current = gcm_context->current; + current[0] = CELL_GCM_METHOD_HEADER_TEXTURE_OFFSET(unit, 8); + current[1] = CELL_GCM_METHOD_DATA_TEXTURE_OFFSET(platformTexture->gcmTexture.offset); + current[2] = CELL_GCM_METHOD_DATA_TEXTURE_FORMAT(platformTexture->gcmTexture.location, + platformTexture->gcmTexture.cubemap, + platformTexture->gcmTexture.dimension, + platformTexture->gcmTexture.format, + platformTexture->gcmTexture.mipmap); + current[3] = CELL_GCM_METHOD_DATA_TEXTURE_ADDRESS( platformTexture->gcmMethods.address.wrapS, + platformTexture->gcmMethods.address.wrapT, + platformTexture->gcmMethods.address.wrapR, + platformTexture->gcmMethods.address.unsignedRemap, + platformTexture->gcmMethods.address.zfunc, + platformTexture->gcmMethods.address.gamma, + 0); + current[4] = CELL_GCM_METHOD_DATA_TEXTURE_CONTROL0(CELL_GCM_TRUE, + platformTexture->gcmMethods.control0.minLOD, + platformTexture->gcmMethods.control0.maxLOD, + platformTexture->gcmMethods.control0.maxAniso); + current[5] = platformTexture->gcmTexture.remap; + current[6] = CELL_GCM_METHOD_DATA_TEXTURE_FILTER( + (platformTexture->gcmMethods.filter.bias & 0x1fff), + platformTexture->gcmMethods.filter.min, + platformTexture->gcmMethods.filter.mag, + platformTexture->gcmMethods.filter.conv); + current[7] = CELL_GCM_METHOD_DATA_TEXTURE_IMAGE_RECT( + platformTexture->gcmTexture.height, + platformTexture->gcmTexture.width); + current[8] = CELL_GCM_METHOD_DATA_TEXTURE_BORDER_COLOR( + platformTexture->gcmMethods.borderColor); + current[9] = CELL_GCM_METHOD_HEADER_TEXTURE_CONTROL3(unit,1); + current[10] = CELL_GCM_METHOD_DATA_TEXTURE_CONTROL3( + platformTexture->gcmTexture.pitch, + platformTexture->gcmTexture.depth); + gcm_context->current = ¤t[11]; + + +} + +// Validate incomplete texture by remapping +inline static void rglPlatformValidateIncompleteTexture( GLuint unit ) +{ + + GLuint remap = CELL_GCM_REMAP_MODE( + CELL_GCM_TEXTURE_REMAP_ORDER_XYXY, + CELL_GCM_TEXTURE_REMAP_FROM_A, + CELL_GCM_TEXTURE_REMAP_FROM_R, + CELL_GCM_TEXTURE_REMAP_FROM_G, + CELL_GCM_TEXTURE_REMAP_FROM_B, + CELL_GCM_TEXTURE_REMAP_ONE, + CELL_GCM_TEXTURE_REMAP_ZERO, + CELL_GCM_TEXTURE_REMAP_ZERO, + CELL_GCM_TEXTURE_REMAP_ZERO ); + + // disable control 0 + GCM_FUNC( cellGcmSetTextureControl, unit, CELL_GCM_FALSE, 0, 0, 0 ); + // set texture remap only + GCM_FUNC( cellGcmSetTextureRemap, unit, remap ); + +} + +#undef RGLGCM_REMAP_MODES + +// Valiate resources of a texture and set it to a unit +void rglPlatformValidateTextureStage( int unit, rglTexture* texture ) +{ + if ( RGL_UNLIKELY( texture->revalidate ) ) + { + // this updates the isComplete bit. + rglPlatformValidateTextureResources( texture ); + } + + GLboolean isCompleteCache = texture->isComplete; + + if ( RGL_LIKELY( isCompleteCache ) ) + { + rglGcmTexture *platformTexture = ( rglGcmTexture * )texture->platformTexture; + rglGcmSetTextureUnit( unit, platformTexture ); + } + else + { + //RGL_REPORT_EXTRA( RGL_REPORT_TEXTURE_INCOMPLETE, "Texture %d bound to unit %d(%s) is incomplete.", texture->name, unit, rglGetGLEnumName( texture->target ) ); + rglPlatformValidateIncompleteTexture( unit ); + } + + +} + +// Choose internal format closest to given format +GLenum rglPlatformChooseInternalFormat( GLenum internalFormat ) +{ + switch ( internalFormat ) + { + case GL_ALPHA12: + case GL_ALPHA16: + return RGLGCM_ALPHA16; + case GL_ALPHA: + case GL_ALPHA4: + return RGLGCM_ALPHA8; + case GL_R3_G3_B2: + case GL_RGB4: + case GL_RGB: + case GL_RGB8: + case RGLGCM_RGBX8: + return RGLGCM_RGBX8; + case GL_RGBA2: + case GL_RGBA4: + case GL_RGBA8: + case GL_RGBA: + return RGLGCM_RGBA8; + case GL_RGB5_A1: + return RGLGCM_RGB5_A1_SCE; + case GL_RGB5: + return RGLGCM_RGB565_SCE; + case GL_BGRA: + case RGLGCM_BGRA8: + return RGLGCM_BGRA8; + case GL_ARGB_SCE: + return RGLGCM_ARGB8; + case GL_RGBA32F_ARB: + default: + return GL_INVALID_ENUM; + } + return GL_INVALID_ENUM; +} + +// Expand internal format to format and type +void rglPlatformExpandInternalFormat( GLenum internalFormat, GLenum *format, GLenum *type ) +{ + switch ( internalFormat ) + { + case RGLGCM_ALPHA16: + *format = GL_ALPHA; + *type = GL_UNSIGNED_SHORT; + break; + case RGLGCM_ALPHA8: + *format = GL_ALPHA; + *type = GL_UNSIGNED_BYTE; + break; + case RGLGCM_RGBX8: + *format = GL_RGBA; + *type = GL_UNSIGNED_INT_8_8_8_8; + break; + case RGLGCM_RGBA8: + *format = GL_RGBA; + *type = GL_UNSIGNED_INT_8_8_8_8; + break; + case RGLGCM_ARGB8: + *format = GL_BGRA; + *type = GL_UNSIGNED_INT_8_8_8_8_REV; + break; + case RGLGCM_BGRA8: + *format = GL_BGRA; + *type = GL_UNSIGNED_INT_8_8_8_8; + break; + case RGLGCM_RGB5_A1_SCE: + *format = GL_RGBA; + *type = GL_UNSIGNED_SHORT_1_5_5_5_REV; + break; + case RGLGCM_RGB565_SCE: + *format = GL_RGB; + *type = GL_UNSIGNED_SHORT_5_6_5_REV; + break; + default: + return; + } +} + +// Choose internal storage type and size, and set it to image, based on given format +GLenum rglPlatformChooseInternalStorage( rglImage* image, GLenum internalFormat ) +{ + // see note at bottom concerning storageSize + image->storageSize = 0; + + GLenum platformInternalFormat = rglPlatformChooseInternalFormat( internalFormat ); + + if ( platformInternalFormat == GL_INVALID_ENUM ) return GL_INVALID_ENUM; + image->internalFormat = platformInternalFormat; + rglPlatformExpandInternalFormat( platformInternalFormat, &image->format, &image->type ); + + // Note that it is critical to get the storageSize value correct because + // this member is used to configure texture loads and unloads. If this + // value is wrong (e.g. contains unnecessary padding) it will corrupt + // the GPU memory layout. + image->storageSize = rglGetStorageSize( + image->format, image->type, + image->width, image->height, image->depth ); + + return GL_NO_ERROR; +} + +// Translate platform-specific format to GL enum +GLenum rglPlatformTranslateTextureFormat( GLenum internalFormat ) +{ + switch ( internalFormat ) + { + case RGLGCM_RGBX8: + return GL_RGBA8; + default: // same as GL + return internalFormat; + } +} + +// Implementation of texture reference +// Associate bufferObject to texture by assigning buffer's gpu address to the gcm texture +GLboolean rglPlatformTextureReference( rglTexture *texture, GLuint pitch, rglBufferObject *bufferObject, GLintptr offset ) +{ + rglGcmTexture *gcmTexture = ( rglGcmTexture * )texture->platformTexture; + + // XXX check pitch restrictions ? + + rglGcmTextureLayout newLayout; + rglPlatformChooseGPUFormatAndLayout( texture, true, pitch, &newLayout ); + + + GLboolean isRenderTarget = GL_FALSE; + GLboolean vertexEnable = GL_FALSE; + // can usually be a render target, except for restrictions below + if ( rglIsDrawableColorFormat( newLayout.internalFormat )) + { + isRenderTarget = GL_TRUE; + } + + switch ( newLayout.internalFormat ) + { + case GL_FLOAT_RGBA32: + case GL_RGBA32F_ARB: + vertexEnable = GL_TRUE; + break; + default: + break; + } + + texture->isRenderTarget = isRenderTarget; + texture->vertexEnable = vertexEnable; + + + if ( gcmTexture->gpuAddressId != GMM_ERROR ) + rglPlatformDestroyTexture( texture ); + + rglGcmBufferObject *gcmBuffer = ( rglGcmBufferObject * ) & bufferObject->platformBufferObject; + + gcmTexture->gpuLayout = newLayout; + gcmTexture->pool = gcmBuffer->pool; + gcmTexture->gpuAddressId = gcmBuffer->bufferId; + gcmTexture->gpuAddressIdOffset = offset; + gcmTexture->gpuSize = rglGetGcmTextureSize( &newLayout ); + + texture->revalidate &= ~( RGL_TEXTURE_REVALIDATE_LAYOUT | RGL_TEXTURE_REVALIDATE_IMAGES ); + texture->revalidate |= RGL_TEXTURE_REVALIDATE_PARAMETERS; + rglTextureTouchFBOs( texture ); + return GL_TRUE; +} + + +// GlSetRenderTarget implementation starts here + +// Render target rt's color and depth buffer parameters are updated with args +// Fifo functions are called as required +void static inline rglGcmSetColorDepthBuffers( rglGcmRenderTarget *rt, rglGcmRenderTargetEx const * const args ) +{ + CellGcmSurface * grt = &rt->gcmRenderTarget; + + rt->colorBufferCount = args->colorBufferCount; + + // remember rt for swap and clip related functions + GLuint oldHeight; + GLuint oldyInverted; + + oldyInverted = rt->yInverted; + oldHeight = rt->gcmRenderTarget.height; + + if ( rt->colorFormat != ( GLuint )args->colorFormat ) + { + // ARGB8 and FP16 interpret some registers differently + rglGcmBlendState *blend = &rglGcmState_i.state.blend; + rt->colorFormat = args->colorFormat; + rglGcmFifoGlBlendColor( blend->r, blend->g, blend->b, blend->a ); + } + + GLuint i = 0; + + for ( i = 0; i < args->colorBufferCount; i++ ) + { + // choose context based on top bit of offset + if ( args->colorPitch[i] == 0 ) + { + grt->colorOffset[i] = 0; + grt->colorPitch[i] = 0x200; + grt->colorLocation[i] = CELL_GCM_LOCATION_LOCAL; + } + else + { + if ( args->colorId[i] != GMM_ERROR ) + { + grt->colorLocation[i] = CELL_GCM_LOCATION_LOCAL; + grt->colorOffset[i] = gmmIdToOffset(args->colorId[i]) + args->colorIdOffset[i]; + grt->colorPitch[i] = args->colorPitch[i]; + } + } + } + + // fill in the other render targets that haven't been set + for ( ; i < RGLGCM_SETRENDERTARGET_MAXCOUNT; i++ ) + { + grt->colorOffset[i] = grt->colorOffset[0]; + grt->colorPitch[i] = grt->colorPitch[0]; + grt->colorLocation[i] = grt->colorLocation[0]; + } + + rt->yInverted = args->yInverted; + grt->x = args->xOffset; + grt->y = args->yOffset; + grt->width = args->width; + grt->height = args->height; + + // scissor enabled/viewport and height changed ? obey yInverted + if (( grt->height != oldHeight ) | ( rt->yInverted != oldyInverted ) ) + { + rglGcmViewportState *v = &rglGcmState_i.state.viewport; + rglGcmFifoGlViewport( v->x, v->y, v->w, v->h ); + } +} + + +// Update rt's color and depth format with args +void static inline rglGcmSetColorDepthFormats( rglGcmRenderTarget *rt, rglGcmRenderTargetEx const * const args ) +{ + CellGcmSurface * grt = &rt->gcmRenderTarget; + + // set the color format + switch ( args->colorFormat ) + { + case RGLGCM_NONE: + case RGLGCM_ARGB8: + // choose a fake format + // but choose a 16-bit format if depth is 16-bit + grt->colorFormat = CELL_GCM_SURFACE_A8R8G8B8; + break; + case RGLGCM_FLOAT_R32: + grt->colorFormat = CELL_GCM_SURFACE_F_X32; + break; + default: + break; + } + + // set the depth format + // choose a fake format + grt->depthFormat = CELL_GCM_SURFACE_Z24S8; + grt->depthLocation = CELL_GCM_LOCATION_LOCAL; + grt->depthOffset = 0; + grt->depthPitch = 64; +} + +// Update rt's color targets +static void inline rglGcmSetTarget( rglGcmRenderTarget *rt, rglGcmRenderTargetEx const * const args ) +{ + CellGcmSurface * grt = &rt->gcmRenderTarget; + + // set target combo + switch ( rt->colorBufferCount ) + { + case 0: + grt->colorTarget = CELL_GCM_SURFACE_TARGET_NONE; + break; + case 1: + grt->colorTarget = CELL_GCM_SURFACE_TARGET_1; + break; + case 2: + grt->colorTarget = CELL_GCM_SURFACE_TARGET_MRT1; + break; + case 3: + grt->colorTarget = CELL_GCM_SURFACE_TARGET_MRT2; + break; + case 4: + grt->colorTarget = CELL_GCM_SURFACE_TARGET_MRT3; + break; + } +} + +// Set current render target to args +void rglGcmFifoGlSetRenderTarget( rglGcmRenderTargetEx const * const args ) +{ + rglGcmRenderTarget *rt = &rglGcmState_i.renderTarget; + CellGcmSurface * grt = &rglGcmState_i.renderTarget.gcmRenderTarget; + + rglGcmSetColorDepthBuffers( rt, args ); + rglGcmSetColorDepthFormats( rt, args ); + + // Update rt's AA and Swizzling parameters with args + + GCM_FUNC( cellGcmSetAntiAliasingControl, + CELL_GCM_FALSE, + CELL_GCM_FALSE, + CELL_GCM_FALSE, + 0xFFFF); + + grt->type = CELL_GCM_SURFACE_PITCH; + rglGcmSetTarget( rt, args ); + + // ensure if either width or height is 1 the other is one as well + if ( grt->width == 1 ) + grt->height = 1; + else + if ( grt->height == 1 ) + grt->width = 1; + + GCM_FUNC( cellGcmSetSurface, grt ); +} + +/*============================================================ + PLATFORM TNL + ============================================================ */ + +void rglValidateVertexProgram() +{ + // if validation is required, it means the program has to be downloaded. + RGLcontext* LContext = _CurrentContext; + + rglSetNativeCgVertexProgram(LContext->BoundVertexProgram); + + // Set all uniforms. + if(!(LContext->needValidate & RGL_VALIDATE_VERTEX_CONSTANTS) && LContext->BoundVertexProgram->parentContext) + rglValidateVertexConstants(); +} + +void rglValidateVertexConstants() +{ + RGLcontext* LContext = _CurrentContext; + + rglGcmPushProgramPushBuffer( LContext->BoundVertexProgram ); +} + +/*============================================================ + UTILS + ============================================================ */ + +void rglDrawUtilQuad( GLboolean useFixedVP, GLboolean useFixedFP, GLuint x, GLuint y, GLuint width, GLuint height ) +{ + RGLcontext* LContext = _CurrentContext; + + rglGcmFifoGlDisable( RGLGCM_BLEND ); + + GCM_FUNC( cellGcmSetFrontPolygonMode, CELL_GCM_POLYGON_MODE_FILL ); + GCM_FUNC( cellGcmSetBackPolygonMode, CELL_GCM_POLYGON_MODE_FILL ); + GCM_FUNC( cellGcmSetUserClipPlaneControl, + CELL_GCM_USER_CLIP_PLANE_DISABLE, + CELL_GCM_USER_CLIP_PLANE_DISABLE, + CELL_GCM_USER_CLIP_PLANE_DISABLE, + CELL_GCM_USER_CLIP_PLANE_DISABLE, + CELL_GCM_USER_CLIP_PLANE_DISABLE, + CELL_GCM_USER_CLIP_PLANE_DISABLE ); + + rglGcmFifoGlViewport( x, y, width, height, 0.0f, 1.0f ); + + GCM_FUNC_NO_ARGS( cellGcmSetInvalidateVertexCache ); + rglGcmFifoGlDrawArrays( RGLGCM_TRIANGLE_STRIP, 0, 4 ); + + LContext->needValidate |= RGL_VALIDATE_BLENDING | RGL_VALIDATE_VIEWPORT; +} diff --git a/console/rgl/src/rgl.cpp b/console/rgl/src/rgl.cpp new file mode 100644 index 0000000000..455fa6c098 --- /dev/null +++ b/console/rgl/src/rgl.cpp @@ -0,0 +1,1986 @@ +/* RetroArch - A frontend for libretro. + * RGL - An OpenGL subset wrapper library. + * Copyright (C) 2010-2012 - Hans-Kristian Arntzen + * Copyright (C) 2011-2012 - Daniel De Matteis + * + * RetroArch 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 Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch 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 RetroArch. + * If not, see . + */ + +#include "rgl.h" +#include "rglp.h" + +/*============================================================ + BUFFERS + ============================================================ */ + +static rglBufferObject *rglCreateBufferObject(void) +{ + GLuint size = sizeof( rglBufferObject ) + rglpBufferObjectSize(); + rglBufferObject *buffer = (rglBufferObject*)malloc(size); + + if(!buffer ) + return NULL; + + memset( buffer, 0, size ); + buffer->refCount = 1; + new( &buffer->textureReferences ) RGL::Vector(); + + return buffer; +} + +static void rglFreeBufferObject( rglBufferObject *buffer ) +{ + if ( --buffer->refCount == 0 ) + { + rglPlatformDestroyBufferObject( buffer ); + buffer->textureReferences.~Vector(); + free( buffer ); + } +} + +static void rglUnbindBufferObject( RGLcontext *LContext, GLuint name ) +{ + if ( LContext->ArrayBuffer == name ) LContext->ArrayBuffer = 0; + if ( LContext->PixelUnpackBuffer == name ) LContext->PixelUnpackBuffer = 0; + for ( int i = 0;i < RGL_MAX_VERTEX_ATTRIBS;++i ) + { + if ( LContext->attribs->attrib[i].arrayBuffer == name ) + { + LContext->attribs->attrib[i].arrayBuffer = 0; + LContext->attribs->HasVBOMask &= ~( 1 << i ); + } + } +} + +GLAPI void APIENTRY glBindBuffer( GLenum target, GLuint name ) +{ + RGLcontext *LContext = _CurrentContext; + if ( name ) rglTexNameSpaceCreateNameLazy( &LContext->bufferObjectNameSpace, name ); + + switch ( target ) + { + case GL_ARRAY_BUFFER: + LContext->ArrayBuffer = name; + break; + case GL_PIXEL_UNPACK_BUFFER_ARB: + LContext->PixelUnpackBuffer = name; + break; + case GL_TEXTURE_REFERENCE_BUFFER_SCE: + LContext->TextureBuffer = name; + break; + default: + break; + } +} + +GLAPI GLvoid* APIENTRY glMapBuffer( GLenum target, GLenum access ) +{ + RGLcontext *LContext = _CurrentContext; + GLuint name = 0; + switch ( target ) + { + case GL_ARRAY_BUFFER: + name = LContext->ArrayBuffer; + break; + case GL_PIXEL_UNPACK_BUFFER_ARB: + name = LContext->PixelUnpackBuffer; + break; + case GL_TEXTURE_REFERENCE_BUFFER_SCE: + name = LContext->TextureBuffer; + break; + default: + rglSetError( GL_INVALID_ENUM ); + return NULL; + } + rglBufferObject* bufferObject = (rglBufferObject*)LContext->bufferObjectNameSpace.data[name]; + + + switch ( access ) + { + case GL_READ_ONLY: + case GL_WRITE_ONLY: + case GL_READ_WRITE: + break; + default: + rglSetError( GL_INVALID_ENUM ); + return NULL; + } + + bufferObject->mapped = GL_TRUE; + void *result = rglPlatformBufferObjectMap( bufferObject, access ); + + return result; +} + + + +GLAPI GLboolean APIENTRY glUnmapBuffer( GLenum target ) +{ + RGLcontext *LContext = _CurrentContext; + GLuint name = 0; + switch ( target ) + { + case GL_ARRAY_BUFFER: + name = LContext->ArrayBuffer; + break; + case GL_TEXTURE_REFERENCE_BUFFER_SCE: + name = LContext->TextureBuffer; + break; + default: + rglSetError( GL_INVALID_ENUM ); + return GL_FALSE; + } + rglBufferObject* bufferObject = (rglBufferObject*)LContext->bufferObjectNameSpace.data[name]; + + bufferObject->mapped = GL_FALSE; + + GLboolean result = rglPlatformBufferObjectUnmap( bufferObject ); + + return result; +} + +GLAPI void APIENTRY glDeleteBuffers( GLsizei n, const GLuint *buffers ) +{ + RGLcontext *LContext = _CurrentContext; + for ( int i = 0;i < n;++i ) + { + if(!rglTexNameSpaceIsName( &LContext->bufferObjectNameSpace, buffers[i] ) ) continue; + if (buffers[i]) + rglUnbindBufferObject( LContext, buffers[i] ); + } + rglTexNameSpaceDeleteNames( &LContext->bufferObjectNameSpace, n, buffers ); +} + +GLAPI void APIENTRY glGenBuffers( GLsizei n, GLuint *buffers ) +{ + RGLcontext *LContext = _CurrentContext; + rglTexNameSpaceGenNames( &LContext->bufferObjectNameSpace, n, buffers ); +} + +GLAPI void APIENTRY glBufferData( GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage ) +{ + RGLcontext *LContext = _CurrentContext; + + GLuint name = 0; + switch ( target ) + { + case GL_ARRAY_BUFFER: + name = LContext->ArrayBuffer; + break; + case GL_PIXEL_UNPACK_BUFFER_ARB: + name = LContext->PixelUnpackBuffer; + break; + case GL_TEXTURE_REFERENCE_BUFFER_SCE: + name = LContext->TextureBuffer; + break; + default: + rglSetError( GL_INVALID_ENUM ); + return; + } + rglBufferObject* bufferObject = (rglBufferObject*)LContext->bufferObjectNameSpace.data[name]; + + if ( bufferObject->refCount > 1 ) + { + rglTexNameSpaceDeleteNames( &LContext->bufferObjectNameSpace, 1, &name ); + rglTexNameSpaceCreateNameLazy( &LContext->bufferObjectNameSpace, name ); + + bufferObject = (rglBufferObject*)LContext->bufferObjectNameSpace.data[name]; + } + + if ( bufferObject->size > 0 ) rglPlatformDestroyBufferObject( bufferObject ); + bufferObject->size = size; + bufferObject->width = 0; + bufferObject->height = 0; + bufferObject->internalFormat = GL_NONE; + + if ( size > 0 ) + { + GLboolean created = rglpCreateBufferObject(bufferObject); + if ( !created ) + { + rglSetError( GL_OUT_OF_MEMORY ); + return; + } + if ( data ) rglPlatformBufferObjectSetData( bufferObject, 0, size, data, GL_TRUE ); + } +} + +GLAPI void APIENTRY glBufferSubData( GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data ) +{ + RGLcontext *LContext = _CurrentContext; + GLuint name = 0; + switch ( target ) + { + case GL_ARRAY_BUFFER: + name = LContext->ArrayBuffer; + break; + case GL_PIXEL_UNPACK_BUFFER_ARB: + name = LContext->PixelUnpackBuffer; + break; + case GL_TEXTURE_REFERENCE_BUFFER_SCE: + name = LContext->TextureBuffer; + break; + default: + rglSetError( GL_INVALID_ENUM ); + return; + } + + rglBufferObject* bufferObject = (rglBufferObject*)LContext->bufferObjectNameSpace.data[name]; + + if ( bufferObject->refCount > 1 ) + { + rglBufferObject* oldBufferObject = bufferObject; + + rglTexNameSpaceDeleteNames( &LContext->bufferObjectNameSpace, 1, &name ); + rglTexNameSpaceCreateNameLazy( &LContext->bufferObjectNameSpace, name ); + + bufferObject = (rglBufferObject*)LContext->bufferObjectNameSpace.data[name]; + bufferObject->size = oldBufferObject->size; + + GLboolean created = rglpCreateBufferObject(bufferObject); + if ( !created ) + { + rglSetError( GL_OUT_OF_MEMORY ); + return; + } + rglPlatformBufferObjectCopyData( bufferObject, oldBufferObject ); + } + + rglPlatformBufferObjectSetData( bufferObject, offset, size, data, GL_FALSE ); +} + +/*============================================================ + FRAMEBUFFER + ============================================================ */ + +GLAPI void APIENTRY glClear( GLbitfield mask ) +{ + RGLcontext* LContext = _CurrentContext; + + if ( LContext->needValidate & RGL_VALIDATE_FRAMEBUFFER ) + rglValidateFramebuffer(); + rglFBClear( mask ); + +} + +GLAPI void APIENTRY glClearColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha ) +{ +} + +GLAPI void APIENTRY glBlendColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha ) +{ + RGLcontext* LContext = _CurrentContext; + LContext->BlendColor.R = rglClampf( red ); + LContext->BlendColor.G = rglClampf( green ); + LContext->BlendColor.B = rglClampf( blue ); + LContext->BlendColor.A = rglClampf( alpha ); + + LContext->needValidate |= RGL_VALIDATE_BLENDING; +} + +GLAPI void APIENTRY glBlendFunc( GLenum sfactor, GLenum dfactor ) +{ + RGLcontext* LContext = _CurrentContext; + + LContext->BlendFactorSrcRGB = sfactor; + LContext->BlendFactorSrcAlpha = sfactor; + LContext->BlendFactorDestRGB = dfactor; + LContext->BlendFactorDestAlpha = dfactor; + LContext->needValidate |= RGL_VALIDATE_BLENDING; +} + +/*============================================================ + FRAMEBUFFER OBJECTS + ============================================================ */ + +void rglFramebufferGetAttachmentTexture( + RGLcontext* LContext, + const rglFramebufferAttachment* attachment, + rglTexture** texture, + GLuint* face ) +{ + switch ( attachment->type ) + { + case RGL_FRAMEBUFFER_ATTACHMENT_NONE: + *texture = NULL; + *face = 0; + break; + case RGL_FRAMEBUFFER_ATTACHMENT_RENDERBUFFER: + break; + case RGL_FRAMEBUFFER_ATTACHMENT_TEXTURE: + *texture = rglGetTextureSafe( LContext, attachment->name ); + *face = 0; + if ( *texture ) + { + switch ( attachment->textureTarget ) + { + case GL_TEXTURE_2D: + break; + default: + *texture = NULL; + } + } + break; + default: + *face = 0; + *texture = NULL; + } +} + +rglFramebufferAttachment* rglFramebufferGetAttachment( rglFramebuffer *framebuffer, GLenum attachment ) +{ + switch ( attachment ) + { + case GL_COLOR_ATTACHMENT0_EXT: + case GL_COLOR_ATTACHMENT1_EXT: + case GL_COLOR_ATTACHMENT2_EXT: + case GL_COLOR_ATTACHMENT3_EXT: + return &framebuffer->color[attachment - GL_COLOR_ATTACHMENT0_EXT]; + default: + rglSetError( GL_INVALID_ENUM ); + return NULL; + } +} + +void rglGetFramebufferSize( GLuint* width, GLuint* height ) +{ + RGLcontext* LContext = _CurrentContext; + + *width = *height = 0; + + if ( LContext->framebuffer ) + { + rglFramebuffer* framebuffer = rglGetFramebuffer( LContext, LContext->framebuffer ); + + if ( rglPlatformFramebufferCheckStatus( framebuffer ) != GL_FRAMEBUFFER_COMPLETE_OES ) + return; + + for ( int i = 0; i < RGL_MAX_COLOR_ATTACHMENTS; ++i ) + { + rglTexture* colorTexture = NULL; + GLuint face = 0; + rglFramebufferGetAttachmentTexture( LContext, &framebuffer->color[i], &colorTexture, &face ); + if (colorTexture == NULL) + continue; + + unsigned texture_width = colorTexture->image->width; + unsigned texture_height = colorTexture->image->height; + *width = MIN( *width, texture_width); + *height = MIN( *height, texture_height); + } + } + else + { + RGLdevice *LDevice = _CurrentDevice; + *width = LDevice->deviceParameters.width; + *height = LDevice->deviceParameters.height; + } +} + +GLAPI GLboolean APIENTRY glIsFramebufferOES( GLuint framebuffer ) +{ + RGLcontext* LContext = _CurrentContext; + + if ( !rglTexNameSpaceIsName( &LContext->framebufferNameSpace, framebuffer ) ) + return GL_FALSE; + + return GL_TRUE; +} + +GLAPI void APIENTRY glBindFramebufferOES( GLenum target, GLuint framebuffer ) +{ + RGLcontext* LContext = _CurrentContext; + + if ( framebuffer ) + rglTexNameSpaceCreateNameLazy( &LContext->framebufferNameSpace, framebuffer ); + + LContext->framebuffer = framebuffer; + LContext->needValidate |= RGL_VALIDATE_SCISSOR_BOX | RGL_VALIDATE_FRAMEBUFFER; +} + +GLAPI void APIENTRY glDeleteFramebuffersOES( GLsizei n, const GLuint *framebuffers ) +{ + RGLcontext *LContext = _CurrentContext; + + for ( int i = 0; i < n; ++i ) + { + if ( framebuffers[i] && framebuffers[i] == LContext->framebuffer ) + glBindFramebufferOES( GL_FRAMEBUFFER_OES, 0 ); + } + + rglTexNameSpaceDeleteNames( &LContext->framebufferNameSpace, n, framebuffers ); +} + +GLAPI void APIENTRY glGenFramebuffersOES( GLsizei n, GLuint *framebuffers ) +{ + RGLcontext *LContext = _CurrentContext; + rglTexNameSpaceGenNames( &LContext->framebufferNameSpace, n, framebuffers ); +} + +GLAPI GLenum APIENTRY glCheckFramebufferStatusOES( GLenum target ) +{ + RGLcontext* LContext = _CurrentContext; + + if ( LContext->framebuffer ) + { + rglFramebuffer* framebuffer = rglGetFramebuffer( LContext, LContext->framebuffer ); + + return rglPlatformFramebufferCheckStatus( framebuffer ); + } + + return GL_FRAMEBUFFER_COMPLETE_OES; +} + +GLAPI void APIENTRY glFramebufferTexture2DOES( GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level ) +{ + RGLcontext* LContext = _CurrentContext; + + rglFramebuffer* framebuffer = rglGetFramebuffer( LContext, LContext->framebuffer ); + + rglFramebufferAttachment* attach = rglFramebufferGetAttachment( framebuffer, attachment ); + if ( !attach ) return; + + rglTexture *textureObject = NULL; + GLuint face; + rglFramebufferGetAttachmentTexture( LContext, attach, &textureObject, &face ); + if ( textureObject ) textureObject->framebuffers.removeElement( framebuffer ); + + if ( texture ) + { + attach->type = RGL_FRAMEBUFFER_ATTACHMENT_TEXTURE; + textureObject = rglGetTexture( LContext, texture ); + textureObject->framebuffers.pushBack( framebuffer ); + } + else attach->type = RGL_FRAMEBUFFER_ATTACHMENT_NONE; + attach->name = texture; + attach->textureTarget = textarget; + + framebuffer->needValidate = GL_TRUE; + LContext->needValidate |= RGL_VALIDATE_SCISSOR_BOX | RGL_VALIDATE_FRAMEBUFFER; +} + + +/*============================================================ + IMAGE CONVERSION + ============================================================ */ + +#define GL_UNSIGNED_INT_24_8 GL_UNSIGNED_INT_24_8_SCE +#define GL_UNSIGNED_INT_8_24_REV GL_UNSIGNED_INT_8_24_REV_SCE + +#define GL_UNSIGNED_SHORT_8_8 GL_UNSIGNED_SHORT_8_8_SCE +#define GL_UNSIGNED_SHORT_8_8_REV GL_UNSIGNED_SHORT_8_8_REV_SCE +#define GL_UNSIGNED_INT_16_16 GL_UNSIGNED_INT_16_16_SCE +#define GL_UNSIGNED_INT_16_16_REV GL_UNSIGNED_INT_16_16_REV_SCE + +#define DECLARE_C_TYPES \ + DECLARE_TYPE(GL_BYTE,GLbyte,127.f) \ +DECLARE_TYPE(GL_UNSIGNED_BYTE,GLubyte,255.f) \ +DECLARE_TYPE(GL_SHORT,GLshort,32767.f) \ +DECLARE_TYPE(GL_UNSIGNED_SHORT,GLushort,65535.f) \ +DECLARE_TYPE(GL_INT,GLint,2147483647.f) \ +DECLARE_TYPE(GL_UNSIGNED_INT,GLuint,4294967295.0) \ +DECLARE_TYPE(GL_FIXED,GLfixed,65535.f) + +#define DECLARE_UNPACKED_TYPES \ + DECLARE_UNPACKED_TYPE(GL_BYTE) \ +DECLARE_UNPACKED_TYPE(GL_UNSIGNED_BYTE) \ +DECLARE_UNPACKED_TYPE(GL_SHORT) \ +DECLARE_UNPACKED_TYPE(GL_UNSIGNED_SHORT) \ +DECLARE_UNPACKED_TYPE(GL_INT) \ +DECLARE_UNPACKED_TYPE(GL_UNSIGNED_INT) \ +DECLARE_UNPACKED_TYPE(GL_HALF_FLOAT_ARB) \ +DECLARE_UNPACKED_TYPE(GL_FLOAT) \ +DECLARE_UNPACKED_TYPE(GL_FIXED) + + +#define DECLARE_PACKED_TYPES \ + DECLARE_PACKED_TYPE_AND_REV_2(UNSIGNED_BYTE,4,4) \ +DECLARE_PACKED_TYPE_AND_REV_2(UNSIGNED_BYTE,6,2) \ +DECLARE_PACKED_TYPE_AND_REV_3(UNSIGNED_BYTE,3,3,2) \ +DECLARE_PACKED_TYPE_AND_REV_4(UNSIGNED_BYTE,2,2,2,2) \ +DECLARE_PACKED_TYPE_AND_REV_2(UNSIGNED_SHORT,12,4) \ +DECLARE_PACKED_TYPE_AND_REV_2(UNSIGNED_SHORT,8,8) \ +DECLARE_PACKED_TYPE_AND_REV_3(UNSIGNED_SHORT,5,6,5) \ +DECLARE_PACKED_TYPE_AND_REV_4(UNSIGNED_SHORT,4,4,4,4) \ +DECLARE_PACKED_TYPE_AND_REV_4(UNSIGNED_SHORT,5,5,5,1) \ +DECLARE_PACKED_TYPE_AND_REV_2(UNSIGNED_INT,16,16) \ +DECLARE_PACKED_TYPE_AND_REV_2(UNSIGNED_INT,24,8) \ +DECLARE_PACKED_TYPE_AND_REV_4(UNSIGNED_INT,8,8,8,8) \ +DECLARE_PACKED_TYPE_AND_REV_4(UNSIGNED_INT,10,10,10,2) + +#define DECLARE_FORMATS \ + DECLARE_FORMAT(GL_RGB,3) \ +DECLARE_FORMAT(GL_BGR,3) \ +DECLARE_FORMAT(GL_RGBA,4) \ +DECLARE_FORMAT(GL_BGRA,4) \ +DECLARE_FORMAT(GL_ABGR,4) \ +DECLARE_FORMAT(GL_ARGB_SCE,4) \ +DECLARE_FORMAT(GL_RED,1) \ +DECLARE_FORMAT(GL_GREEN,1) \ +DECLARE_FORMAT(GL_BLUE,1) \ +DECLARE_FORMAT(GL_ALPHA,1) + +#define DECLARE_TYPE(TYPE,CTYPE,MAXVAL) \ + typedef CTYPE type_##TYPE; \ +static inline type_##TYPE rglFloatTo_##TYPE(float v) { return (type_##TYPE)(rglClampf(v)*MAXVAL); } \ +static inline float rglFloatFrom_##TYPE(type_##TYPE v) { return ((float)v)/MAXVAL; } +DECLARE_C_TYPES +#undef DECLARE_TYPE + +typedef GLfloat type_GL_FLOAT; +static inline type_GL_FLOAT rglFloatTo_GL_FLOAT( float v ) {return v;} +static inline float rglFloatFrom_GL_FLOAT( type_GL_FLOAT v ) {return v;} + +typedef GLhalfARB type_GL_HALF_FLOAT_ARB; +static inline type_GL_HALF_FLOAT_ARB rglFloatTo_GL_HALF_FLOAT_ARB( float x ) {return rglFloatToHalf( x );} +static inline float rglFloatFrom_GL_HALF_FLOAT_ARB( type_GL_HALF_FLOAT_ARB x ) {return rglHalfToFloat( x );} + +#define DECLARE_PACKED_TYPE_AND_REV_2(REALTYPE,S1,S2) \ + DECLARE_PACKED_TYPE(GL_##REALTYPE,GL_##REALTYPE##_##S1##_##S2,2,S1,S2,0,0,) \ +DECLARE_PACKED_TYPE(GL_##REALTYPE,GL_##REALTYPE##_##S2##_##S1##_REV,2,S2,S1,0,0,_REV) + +#define DECLARE_PACKED_TYPE_AND_REV_3(REALTYPE,S1,S2,S3) \ + DECLARE_PACKED_TYPE(GL_##REALTYPE,GL_##REALTYPE##_##S1##_##S2##_##S3,3,S1,S2,S3,0,) \ +DECLARE_PACKED_TYPE(GL_##REALTYPE,GL_##REALTYPE##_##S3##_##S2##_##S1##_REV,3,S3,S2,S1,0,_REV) + +#define DECLARE_PACKED_TYPE_AND_REV_4(REALTYPE,S1,S2,S3,S4) \ + DECLARE_PACKED_TYPE(GL_##REALTYPE,GL_##REALTYPE##_##S1##_##S2##_##S3##_##S4,4,S1,S2,S3,S4,) \ +DECLARE_PACKED_TYPE(GL_##REALTYPE,GL_##REALTYPE##_##S4##_##S3##_##S2##_##S1##_REV,4,S4,S3,S2,S1,_REV) + +#define DECLARE_PACKED_TYPE_AND_REALTYPE(REALTYPE,N,S1,S2,S3,S4,REV) \ + DECLARE_PACKED_TYPE(GL_##REALTYPE,PACKED_TYPE(REALTYPE,N,S1,S2,S3,S4,REV),N,S1,S2,S3,S4,REV) + +#define INDEX(N,X) (X) +#define INDEX_REV(N,X) (N-1-X) + +#define GET_BITS(to,from,first,count) if ((count)>0) to=((GLfloat)(((from)>>(first))&((1<<(count))-1)))/(GLfloat)((1<<((count==0)?1:count))-1) +#define PUT_BITS(from,to,first,count) if ((count)>0) to|=((unsigned int)((from)*((GLfloat)((1<<((count==0)?1:count))-1))))<<(first); + +inline static int rglGetComponentCount( GLenum format ) +{ + switch ( format ) + { +#define DECLARE_FORMAT(FORMAT,COUNT) \ + case FORMAT: \ + return COUNT; + DECLARE_FORMATS +#undef DECLARE_FORMAT + case GL_PALETTE8_RGB8_OES: + case GL_PALETTE8_RGBA8_OES: + case GL_PALETTE8_R5_G6_B5_OES: + case GL_PALETTE8_RGBA4_OES: + case GL_PALETTE8_RGB5_A1_OES: + return 1; + default: + return 0; + } +} + +int rglGetTypeSize( GLenum type ) +{ + switch ( type ) + { + +#define DECLARE_PACKED_TYPE(REALTYPE,TYPE,N,S1,S2,S3,S4,REV) \ + case TYPE: \ + return sizeof(type_##REALTYPE); + DECLARE_PACKED_TYPES +#undef DECLARE_PACKED_TYPE + +#define DECLARE_UNPACKED_TYPE(TYPE) \ + case TYPE: \ + return sizeof(type_##TYPE); + DECLARE_UNPACKED_TYPES +#undef DECLARE_UNPACKED_TYPE + + default: + return 0; + } +} +int rglGetPixelSize( GLenum format, GLenum type ) +{ + int componentSize; + switch ( type ) + { + +#define DECLARE_PACKED_TYPE(REALTYPE,TYPE,N,S1,S2,S3,S4,REV) \ + case TYPE: \ + return sizeof(type_##REALTYPE); + DECLARE_PACKED_TYPES +#undef DECLARE_PACKED_TYPE + +#define DECLARE_UNPACKED_TYPE(TYPE) \ + case TYPE: \ + componentSize=sizeof(type_##TYPE); \ + break; + DECLARE_UNPACKED_TYPES +#undef DECLARE_UNPACKED_TYPE + + default: + return 0; + } + return rglGetComponentCount( format )*componentSize; +} + +void rglRawRasterToImage( + const rglRaster* raster, + rglImage* image, + GLuint x, GLuint y, GLuint z ) +{ + const int pixelBits = rglGetPixelSize( image->format, image->type ) * 8; + + const GLuint size = pixelBits / 8; + + { + if ( raster->xstride == image->xstride && + raster->ystride == image->ystride && + raster->zstride == image->zstride ) + { + memcpy( + ( char * )image->data + + x*image->xstride + y*image->ystride + z*image->zstride, + raster->data, + raster->depth*raster->zstride ); + + return; + } + else if ( raster->xstride == image->xstride ) + { + const GLuint lineBytes = raster->width * raster->xstride; + for ( int i = 0; i < raster->depth; ++i ) + { + for ( int j = 0; j < raster->height; ++j ) + { + const char *src = ( const char * )raster->data + + i * raster->zstride + j * raster->ystride; + char *dst = ( char * )image->data + + ( i + z ) * image->zstride + + ( j + y ) * image->ystride + + x * image->xstride; + memcpy( dst, src, lineBytes ); + } + } + + return; + } + } + + for ( int i = 0; i < raster->depth; ++i ) + { + for ( int j = 0; j < raster->height; ++j ) + { + const char *src = ( const char * )raster->data + + i * raster->zstride + j * raster->ystride; + char *dst = ( char * )image->data + + ( i + z ) * image->zstride + + ( j + y ) * image->ystride + + x * image->xstride; + + for ( int k = 0; k < raster->width; ++k ) + { + memcpy( dst, src, size ); + + src += raster->xstride; + dst += image->xstride; + } + } + } +} + +void rglImageAllocCPUStorage( rglImage *image ) +{ + if (( image->storageSize > image->mallocStorageSize ) || ( !image->mallocData ) ) + { + if (image->mallocData) + free( image->mallocData ); + + image->mallocData = (char *)malloc( image->storageSize + 128 ); + image->mallocStorageSize = image->storageSize; + } + image->data = rglPadPtr( image->mallocData, 128 ); +} + +void rglImageFreeCPUStorage( rglImage *image ) +{ + if (!image->mallocData) + return; + + free( image->mallocData ); + image->mallocStorageSize = 0; + image->data = NULL; + image->mallocData = NULL; + image->dataState &= ~RGL_IMAGE_DATASTATE_HOST; +} + +static inline void rglSetImageTexRef( rglImage *image, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei alignment) +{ + image->width = width; + image->height = height; + image->depth = depth; + image->alignment = alignment; + + image->xblk = 0; + image->yblk = 0; + + image->xstride = 0; + image->ystride = 0; + image->zstride = 0; + + image->format = 0; + image->type = 0; + image->internalFormat = 0; + const GLenum status = rglPlatformChooseInternalStorage( image, internalFormat ); + (( void )status ); + + image->data = NULL; + image->mallocData = NULL; + image->mallocStorageSize = 0; + + image->isSet = GL_TRUE; + + { + if ( image->xstride == 0 ) + image->xstride = rglGetPixelSize( image->format, image->type ); + if ( image->ystride == 0 ) + image->ystride = image->width * image->xstride; + if ( image->zstride == 0 ) + image->zstride = image->height * image->ystride; + } + + image->dataState = RGL_IMAGE_DATASTATE_UNSET; +} + +void rglSetImage( rglImage *image, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei alignment, GLenum format, GLenum type, const GLvoid *pixels ) +{ + image->width = width; + image->height = height; + image->depth = depth; + image->alignment = alignment; + + image->xblk = 0; + image->yblk = 0; + + image->xstride = 0; + image->ystride = 0; + image->zstride = 0; + + image->format = 0; + image->type = 0; + image->internalFormat = 0; + const GLenum status = rglPlatformChooseInternalStorage( image, internalFormat ); + (( void )status ); + + image->data = NULL; + image->mallocData = NULL; + image->mallocStorageSize = 0; + + image->isSet = GL_TRUE; + + { + if ( image->xstride == 0 ) + image->xstride = rglGetPixelSize( image->format, image->type ); + if ( image->ystride == 0 ) + image->ystride = image->width * image->xstride; + if ( image->zstride == 0 ) + image->zstride = image->height * image->ystride; + } + + if ( pixels ) + { + rglImageAllocCPUStorage( image ); + if ( !image->data ) + return; + + rglRaster raster; + raster.format = format; + raster.type = type; + raster.width = width; + raster.height = height; + raster.depth = depth; + raster.data = ( void * )pixels; + + raster.xstride = rglGetPixelSize( raster.format, raster.type ); + raster.ystride = ( raster.width * raster.xstride + alignment - 1 ) / alignment * alignment; + raster.zstride = raster.height * raster.ystride; + + rglRawRasterToImage( &raster, image, 0, 0, 0 ); + image->dataState = RGL_IMAGE_DATASTATE_HOST; + } + else + image->dataState = RGL_IMAGE_DATASTATE_UNSET; +} + +/*============================================================ + ENGINE + ============================================================ */ + +static char* rglVendorString = "RetroArch"; + +static char* rglRendererString = "RGL"; +static char* rglExtensionsString = ""; + +static char* rglVersionNumber = "2.00"; +char* rglVersion = "2.00"; + + +RGLcontext* _CurrentContext = NULL; + +RGL_EXPORT RGLcontextHookFunction rglContextCreateHook = NULL; +RGL_EXPORT RGLcontextHookFunction rglContextDestroyHook = NULL; + +void rglSetError( GLenum error ) +{ +} + +GLAPI GLenum APIENTRY glGetError(void) +{ + if (!_CurrentContext ) + return GL_INVALID_OPERATION; + else + { + GLenum error = _CurrentContext->error; + + _CurrentContext->error = GL_NO_ERROR; + return error; + } +} + +static void rglGetTextureIntegerv( GLenum pname, GLint* params ) +{ + switch ( pname ) + { + case GL_MAX_TEXTURE_SIZE: + params[0] = RGLP_MAX_TEXTURE_SIZE; + break; + default: + fprintf(stderr, "rglGetTextureIntegerv: enum not supported.\n"); + return; + } +} + +GLAPI void APIENTRY glGetIntegerv(GLenum pname, GLint* params) +{ + switch (pname) + { + case GL_MAX_TEXTURE_SIZE: + rglGetTextureIntegerv(pname, params); + break; + default: + fprintf(stderr, "glGetIntegerv: enum not supported.\n"); + break; + } +} + +GLuint rglValidateStates (GLuint mask) +{ + RGLcontext* LContext = _CurrentContext; + + GLuint dirty = LContext->needValidate & ~mask; + LContext->needValidate &= mask; + + GLuint needValidate = LContext->needValidate; + + if ( RGL_UNLIKELY( needValidate & RGL_VALIDATE_FRAMEBUFFER ) ) + { + rglValidateFramebuffer(); + needValidate = LContext->needValidate; + } + + if ( RGL_UNLIKELY( needValidate & RGL_VALIDATE_TEXTURES_USED ) ) + { + long unitInUseCount = LContext->BoundFragmentProgram->samplerCount; + const GLuint* unitsInUse = LContext->BoundFragmentProgram->samplerUnits; + for ( long i = 0; i < unitInUseCount; ++i ) + { + long unit = unitsInUse[i]; + rglTexture* texture = LContext->TextureImageUnits[unit].currentTexture; + + if ( texture ) + rglPlatformValidateTextureStage( unit, texture ); + } + } + + if ( RGL_UNLIKELY( needValidate & RGL_VALIDATE_VERTEX_PROGRAM ) ) + { + rglValidateVertexProgram(); + } + + if ( RGL_LIKELY( needValidate & RGL_VALIDATE_VERTEX_CONSTANTS ) ) + { + rglValidateVertexConstants(); + } + + if ( RGL_UNLIKELY( needValidate & RGL_VALIDATE_FRAGMENT_PROGRAM ) ) + { + rglValidateFragmentProgram(); + } + + if ( RGL_LIKELY(( needValidate & ~( RGL_VALIDATE_TEXTURES_USED | + RGL_VALIDATE_VERTEX_PROGRAM | + RGL_VALIDATE_VERTEX_CONSTANTS | + RGL_VALIDATE_FRAGMENT_PROGRAM ) ) == 0 ) ) + { + LContext->needValidate = 0; + return dirty; + } + + if ( RGL_UNLIKELY( needValidate & RGL_VALIDATE_VIEWPORT ) ) + rglpValidateViewport(); + + if ( RGL_UNLIKELY( needValidate & RGL_VALIDATE_BLENDING ) ) + rglpValidateBlending(); + + if ( RGL_UNLIKELY( needValidate & RGL_VALIDATE_SHADER_SRGB_REMAP ) ) + rglpValidateShaderSRGBRemap(); + + LContext->needValidate = 0; + return dirty; +} + +void rglResetAttributeState( rglAttributeState* as ) +{ + for ( int i = 0; i < RGL_MAX_VERTEX_ATTRIBS; ++i ) + { + as->attrib[i].clientSize = 4; + as->attrib[i].clientType = GL_FLOAT; + as->attrib[i].clientStride = 16; + as->attrib[i].clientData = NULL; + + as->attrib[i].value[0] = 0.0f; + as->attrib[i].value[1] = 0.0f; + as->attrib[i].value[2] = 0.0f; + as->attrib[i].value[3] = 1.0f; + + as->attrib[i].normalized = GL_FALSE; + as->attrib[i].frequency = 1; + + as->attrib[i].arrayBuffer = 0; + } + + as->attrib[RGL_ATTRIB_PRIMARY_COLOR_INDEX].value[0] = 1.0f; + as->attrib[RGL_ATTRIB_PRIMARY_COLOR_INDEX].value[1] = 1.0f; + as->attrib[RGL_ATTRIB_PRIMARY_COLOR_INDEX].value[2] = 1.0f; + as->attrib[RGL_ATTRIB_PRIMARY_COLOR_INDEX].value[3] = 1.0f; + + as->attrib[RGL_ATTRIB_SECONDARY_COLOR_INDEX].value[0] = 1.0f; + as->attrib[RGL_ATTRIB_SECONDARY_COLOR_INDEX].value[1] = 1.0f; + as->attrib[RGL_ATTRIB_SECONDARY_COLOR_INDEX].value[2] = 1.0f; + as->attrib[RGL_ATTRIB_SECONDARY_COLOR_INDEX].value[3] = 1.0f; + + as->attrib[RGL_ATTRIB_NORMAL_INDEX].value[0] = 0.f; + as->attrib[RGL_ATTRIB_NORMAL_INDEX].value[1] = 0.f; + as->attrib[RGL_ATTRIB_NORMAL_INDEX].value[2] = 1.f; + + as->DirtyMask = ( 1 << RGL_MAX_VERTEX_ATTRIBS ) - 1; + as->EnabledMask = 0; + as->HasVBOMask = 0; +} + +static void rglResetContext( RGLcontext *LContext ) +{ + rglTexNameSpaceResetNames( &LContext->textureNameSpace ); + rglTexNameSpaceResetNames( &LContext->bufferObjectNameSpace ); + rglTexNameSpaceResetNames( &LContext->framebufferNameSpace ); + rglTexNameSpaceResetNames( &LContext->fenceObjectNameSpace ); + + LContext->ViewPort.X = 0; + LContext->ViewPort.Y = 0; + LContext->ViewPort.XSize = 0; + LContext->ViewPort.YSize = 0; + + LContext->PerspectiveCorrectHint = GL_DONT_CARE; + + LContext->DepthNear = 0.f; + LContext->DepthFar = 1.f; + + LContext->DrawBuffer = LContext->ReadBuffer = GL_COLOR_ATTACHMENT0_EXT; + + LContext->ShaderSRGBRemap = GL_FALSE; + + LContext->Blending = GL_FALSE; + LContext->BlendColor.R = 0.0f; + LContext->BlendColor.G = 0.0f; + LContext->BlendColor.B = 0.0f; + LContext->BlendColor.A = 0.0f; + LContext->BlendEquationRGB = GL_FUNC_ADD; + LContext->BlendEquationAlpha = GL_FUNC_ADD; + LContext->BlendFactorSrcRGB = GL_ONE; + LContext->BlendFactorDestRGB = GL_ZERO; + LContext->BlendFactorSrcAlpha = GL_ONE; + LContext->BlendFactorDestAlpha = GL_ZERO; + + LContext->ColorLogicOp = GL_FALSE; + LContext->LogicOp = GL_COPY; + + LContext->Dithering = GL_TRUE; + + LContext->TexCoordReplaceMask = 0; + + for ( int i = 0;i < RGL_MAX_TEXTURE_IMAGE_UNITS;++i ) + { + rglTextureImageUnit *tu = LContext->TextureImageUnits + i; + tu->bound2D = 0; + + tu->enable2D = GL_FALSE; + tu->fragmentTarget = 0; + + tu->lodBias = 0.f; + tu->currentTexture = NULL; + } + + LContext->ActiveTexture = 0; + LContext->CurrentImageUnit = LContext->TextureImageUnits; + + LContext->packAlignment = 4; + LContext->unpackAlignment = 4; + + rglResetAttributeState( &LContext->defaultAttribs0 ); + LContext->attribs = &LContext->defaultAttribs0; + + LContext->framebuffer = 0; + + LContext->VertexProgram = GL_FALSE; + LContext->BoundVertexProgram = 0; + + LContext->FragmentProgram = GL_FALSE; + LContext->BoundFragmentProgram = 0; + + LContext->ArrayBuffer = 0; + LContext->PixelUnpackBuffer = 0; + LContext->TextureBuffer = 0; + + LContext->VSync = GL_FALSE; + + LContext->AllowTXPDemotion = GL_FALSE; + +} + +RGLcontext* psglCreateContext(void) +{ + RGLcontext* LContext = ( RGLcontext* )malloc( sizeof( RGLcontext ) ); + if ( !LContext ) return NULL; + + memset( LContext, 0, sizeof( RGLcontext ) ); + + LContext->error = GL_NO_ERROR; + + rglTexNameSpaceInit( &LContext->textureNameSpace, ( rglTexNameSpaceCreateFunction )rglAllocateTexture, ( rglTexNameSpaceDestroyFunction )rglFreeTexture ); + + for ( int i = 0;i < RGL_MAX_TEXTURE_IMAGE_UNITS;++i ) + { + rglTextureImageUnit *tu = LContext->TextureImageUnits + i; + + tu->default2D = rglAllocateTexture(); + if ( !tu->default2D ) + { + psglDestroyContext( LContext ); + return NULL; + } + tu->default2D->target = GL_TEXTURE_2D; + } + + rglTexNameSpaceInit( &LContext->bufferObjectNameSpace, ( rglTexNameSpaceCreateFunction )rglCreateBufferObject, ( rglTexNameSpaceDestroyFunction )rglFreeBufferObject ); + rglTexNameSpaceInit( &LContext->framebufferNameSpace, ( rglTexNameSpaceCreateFunction )rglCreateFramebuffer, ( rglTexNameSpaceDestroyFunction )rglDestroyFramebuffer ); + + LContext->needValidate = 0; + LContext->everAttached = 0; + + LContext->RGLcgLastError = CG_NO_ERROR; + LContext->RGLcgErrorCallbackFunction = NULL; + LContext->RGLcgContextHead = ( CGcontext )NULL; + + rglInitNameSpace( &LContext->cgProgramNameSpace ); + rglInitNameSpace( &LContext->cgParameterNameSpace ); + rglInitNameSpace( &LContext->cgContextNameSpace ); + + rglResetContext( LContext ); + + if ( rglContextCreateHook ) rglContextCreateHook( LContext ); + + return( LContext ); +} + +void RGL_EXPORT psglResetCurrentContext(void) +{ + RGLcontext *context = _CurrentContext; + rglResetContext(context); + context->needValidate |= RGL_VALIDATE_ALL; +} + +RGLcontext *psglGetCurrentContext(void) +{ + return _CurrentContext; +} + +void RGL_EXPORT psglDestroyContext( RGLcontext* LContext ) +{ + if ( _CurrentContext == LContext ) + rglpFifoGlFinish(); + + while ( LContext->RGLcgContextHead != ( CGcontext )NULL ) + { + RGLcontext* current = _CurrentContext; + _CurrentContext = LContext; + cgDestroyContext( LContext->RGLcgContextHead ); + _CurrentContext = current; + } + rglFreeNameSpace( &LContext->cgProgramNameSpace ); + rglFreeNameSpace( &LContext->cgParameterNameSpace ); + rglFreeNameSpace( &LContext->cgContextNameSpace ); + + if ( rglContextDestroyHook ) rglContextDestroyHook( LContext ); + + for ( int i = 0; i < RGL_MAX_TEXTURE_IMAGE_UNITS; ++i ) + { + rglTextureImageUnit* tu = LContext->TextureImageUnits + i; + if ( tu->default2D ) rglFreeTexture( tu->default2D ); + } + + rglTexNameSpaceFree( &LContext->textureNameSpace ); + rglTexNameSpaceFree( &LContext->bufferObjectNameSpace ); + rglTexNameSpaceFree( &LContext->fenceObjectNameSpace ); + rglTexNameSpaceFree( &LContext->framebufferNameSpace ); + + if ( _CurrentContext == LContext ) + { + psglMakeCurrent( NULL, NULL ); + } + + free( LContext ); +} + +void rglInvalidateAllStates( RGLcontext* context ) +{ + context->needValidate = RGL_VALIDATE_ALL; + context->attribs->DirtyMask = ( 1 << RGL_MAX_VERTEX_ATTRIBS ) - 1; +} + +void rglAttachContext( RGLdevice *device, RGLcontext* context ) +{ + if ( !context->everAttached ) + { + context->ViewPort.XSize = device->deviceParameters.width; + context->ViewPort.YSize = device->deviceParameters.height; + context->needValidate |= RGL_VALIDATE_VIEWPORT | RGL_VALIDATE_SCISSOR_BOX; + context->everAttached = GL_TRUE; + } + rglInvalidateAllStates( context ); +} + +GLAPI void APIENTRY glEnable( GLenum cap ) +{ + RGLcontext* LContext = _CurrentContext; + + switch ( cap ) + { + case GL_TEXTURE_2D: + LContext->CurrentImageUnit->enable2D = GL_TRUE; + rglUpdateCurrentTextureCache( LContext->CurrentImageUnit ); + LContext->needValidate |= RGL_VALIDATE_TEXTURES_USED; + break; + case GL_SHADER_SRGB_REMAP_SCE: + LContext->ShaderSRGBRemap = GL_TRUE; + LContext->needValidate |= RGL_VALIDATE_SHADER_SRGB_REMAP; + break; + case GL_BLEND: + LContext->Blending = GL_TRUE; + LContext->needValidate |= RGL_VALIDATE_BLENDING; + break; + case GL_DITHER: + LContext->Dithering = GL_TRUE; + break; + case GL_VSYNC_SCE: + LContext->VSync = GL_TRUE; + break; + default: + rglSetError( GL_INVALID_ENUM ); + return; + } +} + +GLAPI void APIENTRY glDisable( GLenum cap ) +{ + RGLcontext* LContext = _CurrentContext; + + switch ( cap ) + { + case GL_TEXTURE_2D: + LContext->CurrentImageUnit->enable2D = GL_FALSE; + rglUpdateCurrentTextureCache( LContext->CurrentImageUnit ); + LContext->needValidate |= RGL_VALIDATE_TEXTURES_USED; + break; + case GL_SHADER_SRGB_REMAP_SCE: + LContext->ShaderSRGBRemap = GL_FALSE; + LContext->needValidate |= RGL_VALIDATE_SHADER_SRGB_REMAP; + break; + case GL_BLEND: + LContext->Blending = GL_FALSE; + LContext->needValidate |= RGL_VALIDATE_BLENDING; + break; + case GL_DITHER: + LContext->Dithering = GL_FALSE; + break; + case GL_VSYNC_SCE: + LContext->VSync = GL_FALSE; + break; + default: + rglSetError( GL_INVALID_ENUM ); + return; + } +} + +GLAPI void APIENTRY glEnableClientState( GLenum array ) +{ + switch ( array ) + { + case GL_VERTEX_ARRAY: + rglEnableVertexAttribArrayNV( RGL_ATTRIB_POSITION_INDEX ); + break; + case GL_COLOR_ARRAY: + rglEnableVertexAttribArrayNV( RGL_ATTRIB_PRIMARY_COLOR_INDEX ); + break; + case GL_NORMAL_ARRAY: + rglEnableVertexAttribArrayNV( RGL_ATTRIB_NORMAL_INDEX ); + break; + default: + rglSetError( GL_INVALID_ENUM ); + return; + } +} + +GLAPI void APIENTRY glDisableClientState( GLenum array ) +{ + switch ( array ) + { + case GL_VERTEX_ARRAY: + rglDisableVertexAttribArrayNV( RGL_ATTRIB_POSITION_INDEX ); + break; + case GL_COLOR_ARRAY: + rglDisableVertexAttribArrayNV( RGL_ATTRIB_PRIMARY_COLOR_INDEX ); + break; + case GL_NORMAL_ARRAY: + rglDisableVertexAttribArrayNV( RGL_ATTRIB_NORMAL_INDEX ); + break; + default: + rglSetError( GL_INVALID_ENUM ); + return; + } +} + +GLAPI void APIENTRY glFlush(void) +{ + RGLcontext* LContext = _CurrentContext; + if (RGL_UNLIKELY(LContext->needValidate)) + rglValidateStates( RGL_VALIDATE_ALL ); + rglPlatformRasterFlush(); +} + +GLAPI const GLubyte* APIENTRY glGetString( GLenum name ) +{ + switch ( name ) + { + case GL_VENDOR: + return(( GLubyte* )rglVendorString ); + case GL_RENDERER: + return(( GLubyte* )rglRendererString ); + case GL_VERSION: + return(( GLubyte* )rglVersionNumber ); + case GL_EXTENSIONS: + return(( GLubyte* )rglExtensionsString ); + default: + { + rglSetError( GL_INVALID_ENUM ); + return(( GLubyte* )NULL ); + } + } +} + +void psglInit( RGLinitOptions* options ) +{ + rglPsglPlatformInit(options); +} + +void psglExit(void) +{ + rglPsglPlatformExit(); +} + +/*============================================================ + RASTER + ============================================================ */ + +GLAPI void APIENTRY glViewport( GLint x, GLint y, GLsizei width, GLsizei height ) +{ + RGLcontext* LContext = _CurrentContext; + + LContext->ViewPort.X = x; + LContext->ViewPort.Y = y; + LContext->ViewPort.XSize = width; + LContext->ViewPort.YSize = height; + LContext->needValidate |= RGL_VALIDATE_VIEWPORT; +} + +/*============================================================ + TEXTURES (INTERNAL) + ============================================================ */ + +rglTexture *rglAllocateTexture(void) +{ + GLuint size = sizeof( rglTexture ) + rglPlatformTextureSize(); + rglTexture *texture = ( rglTexture * )malloc( size ); + memset( texture, 0, size ); + texture->target = 0; + texture->minFilter = GL_NEAREST_MIPMAP_LINEAR; + texture->magFilter = GL_LINEAR; + texture->minLod = -1000.f; + texture->maxLod = 1000.f; + texture->baseLevel = 0; + texture->maxLevel = 1000; + texture->wrapS = GL_REPEAT; + texture->wrapT = GL_REPEAT; + texture->wrapR = GL_REPEAT; + texture->lodBias = 0.f; + texture->maxAnisotropy = 1.f; + texture->compareMode = GL_NONE; + texture->compareFunc = GL_LEQUAL; + texture->gammaRemap = 0; + texture->vertexEnable = GL_FALSE; + texture->usage = 0; + texture->isRenderTarget = GL_FALSE; + texture->image = NULL; + texture->isComplete = GL_FALSE; + texture->imageCount = 0; + texture->faceCount = 1; + texture->revalidate = 0; + texture->referenceBuffer = NULL; + new( &texture->framebuffers ) RGL::Vector(); + rglPlatformCreateTexture( texture ); + return texture; +} + +void rglFreeTexture( rglTexture *texture ) +{ + rglTextureTouchFBOs( texture ); + texture->framebuffers.~Vector(); + + if ( texture->image ) + { + rglImage *image = texture->image; + rglImageFreeCPUStorage( image ); + free( texture->image ); + } + if ( texture->referenceBuffer ) + texture->referenceBuffer->textureReferences.removeElement( texture ); + rglPlatformDestroyTexture( texture ); + free( texture ); +} + +void rglTextureUnbind( RGLcontext* context, GLuint name ) +{ + int unit; + for ( unit = 0;unit < RGL_MAX_TEXTURE_IMAGE_UNITS;++unit ) + { + rglTextureImageUnit *tu = context->TextureImageUnits + unit; + GLboolean dirty = GL_FALSE; + if ( tu->bound2D == name ) + { + tu->bound2D = 0; + dirty = GL_TRUE; + } + if ( dirty ) + { + rglUpdateCurrentTextureCache( tu ); + context->needValidate |= RGL_VALIDATE_TEXTURES_USED; + } + } +} + +GLboolean rglTextureIsValid( const rglTexture* texture ) +{ + if ( texture->imageCount < 1 + texture->baseLevel ) + return GL_FALSE; + if ( !texture->image ) + return GL_FALSE; + const rglImage* image = texture->image + texture->baseLevel; + + GLenum format = image->format; + GLenum type = image->type; + GLenum internalFormat = image->internalFormat; + if (( texture->vertexEnable ) && ( internalFormat != GL_FLOAT_RGBA32 ) + && ( internalFormat != GL_RGBA32F_ARB )) + return GL_FALSE; + if (( internalFormat == 0 ) || ( format == 0 ) || ( type == 0 ) ) + return GL_FALSE; + + // don't need more than max level + if ( texture->imageCount < 1 ) + return GL_FALSE; + + return GL_TRUE; +} + +// Reallocate images held by a texture +void rglReallocateImages( rglTexture *texture, GLint level, GLsizei dimension ) +{ + GLuint oldCount = texture->imageCount; + if ( dimension <= 0 ) dimension = 1; + GLuint n = level + 1 + rglLog2( dimension ); + n = MAX( n, oldCount ); + + rglImage *image = ( rglImage * )realloc( texture->image, n * sizeof( rglImage ) ); + memset( image + oldCount, 0, ( n - oldCount )*sizeof( rglImage ) ); + + texture->image = image; + texture->imageCount = n; +} + +// Get an enabled texture mode of a texture image unit +GLenum rglGetEnabledTextureMode( const rglTextureImageUnit *unit ) +{ + // here, if fragment program is enabled and a valid program is set, get the enabled + // units from the program instead of the texture units. + if ( _CurrentContext->BoundFragmentProgram != NULL && _CurrentContext->FragmentProgram != GL_FALSE) + { + return unit->fragmentTarget; + } + else if ( unit->enable2D ) return GL_TEXTURE_2D; + else return 0; +} + +rglTexture *rglGetCurrentTexture( const rglTextureImageUnit *unit, GLenum target ) +{ + RGLcontext* LContext = _CurrentContext; + GLuint name = 0; + rglTexture *defaultTexture = NULL; + switch ( target ) + { + case GL_TEXTURE_2D: + name = unit->bound2D; + defaultTexture = unit->default2D; + break; + default: + return NULL; + } + if (name) + return ( rglTexture * )LContext->textureNameSpace.data[name]; + else + return defaultTexture; +} + +void rglUpdateCurrentTextureCache( rglTextureImageUnit *unit ) +{ + GLenum target = rglGetEnabledTextureMode( unit ); + unit->currentTexture = rglGetCurrentTexture( unit, target ); +} + +int rglGetImage( GLenum target, GLint level, rglTexture **texture, rglImage **image, GLsizei reallocateSize ) +{ + RGLcontext* LContext = _CurrentContext; + rglTextureImageUnit *unit = LContext->CurrentImageUnit; + + GLenum expectedTarget = 0; + switch ( target ) + { + case GL_TEXTURE_2D: + expectedTarget = GL_TEXTURE_2D; + break; + default: + rglSetError( GL_INVALID_ENUM ); + return -1; + } + + rglTexture *tex = rglGetCurrentTexture( unit, expectedTarget ); + + if (level >= ( int )tex->imageCount) + rglReallocateImages( tex, level, reallocateSize ); + + *image = tex->image + level; + *texture = tex; + return 0; +} + +void rglBindTextureInternal( rglTextureImageUnit *unit, GLuint name, GLenum target ) +{ + RGLcontext* LContext = _CurrentContext; + rglTexture *texture = NULL; + if ( name ) + { + rglTexNameSpaceCreateNameLazy( &LContext->textureNameSpace, name ); + texture = ( rglTexture * )LContext->textureNameSpace.data[name]; + + if ( !texture->target ) + { + texture->target = target; + texture->faceCount = 1; + } + } + + switch ( target ) + { + case GL_TEXTURE_2D: + unit->bound2D = name; + break; + default: + break; + } + rglUpdateCurrentTextureCache( unit ); + LContext->needValidate |= RGL_VALIDATE_TEXTURES_USED; +} + +/*============================================================ + TEXTURES + ============================================================ */ + +GLAPI void APIENTRY glGenTextures( GLsizei n, GLuint *textures ) +{ + RGLcontext* LContext = _CurrentContext; + rglTexNameSpaceGenNames( &LContext->textureNameSpace, n, textures ); +} + +GLAPI void APIENTRY glDeleteTextures( GLsizei n, const GLuint *textures ) +{ + RGLcontext* LContext = _CurrentContext; + for ( int i = 0;i < n;++i ) + { + if ( textures[i] ) rglTextureUnbind( LContext, textures[i] ); + } + rglTexNameSpaceDeleteNames( &LContext->textureNameSpace, n, textures ); +} + +GLAPI void APIENTRY glTexParameteri( GLenum target, GLenum pname, GLint param ) +{ + RGLcontext* LContext = _CurrentContext; + rglTexture *texture = rglGetCurrentTexture( LContext->CurrentImageUnit, target ); + switch ( pname ) + { + case GL_TEXTURE_MIN_FILTER: + texture->minFilter = param; + if ( texture->referenceBuffer == 0 ) + { + texture->revalidate |= RGL_TEXTURE_REVALIDATE_LAYOUT; + } + break; + case GL_TEXTURE_MAG_FILTER: + texture->magFilter = param; + break; + case GL_TEXTURE_MAX_LEVEL: + texture->maxLevel = param; + break; + case GL_TEXTURE_WRAP_S: + texture->wrapS = param; + break; + case GL_TEXTURE_WRAP_T: + texture->wrapT = param; + break; + case GL_TEXTURE_WRAP_R: + texture->wrapR = param; + break; + case GL_TEXTURE_FROM_VERTEX_PROGRAM_SCE: + if ( param != 0 ) + { + texture->vertexEnable = GL_TRUE; + } + else texture->vertexEnable = GL_FALSE; + texture->revalidate |= RGL_TEXTURE_REVALIDATE_LAYOUT; + break; + case GL_TEXTURE_ALLOCATION_HINT_SCE: + texture->usage = param; + texture->revalidate |= RGL_TEXTURE_REVALIDATE_LAYOUT; + break; + case GL_TEXTURE_COMPARE_MODE_ARB: + texture->compareMode = param; + break; + case GL_TEXTURE_COMPARE_FUNC_ARB: + texture->compareFunc = param; + break; + case GL_TEXTURE_GAMMA_REMAP_R_SCE: + case GL_TEXTURE_GAMMA_REMAP_G_SCE: + case GL_TEXTURE_GAMMA_REMAP_B_SCE: + case GL_TEXTURE_GAMMA_REMAP_A_SCE: + { + GLuint bit = 1 << ( pname - GL_TEXTURE_GAMMA_REMAP_R_SCE ); + if ( param ) texture->gammaRemap |= bit; + else texture->gammaRemap &= ~bit; + } + break; + default: + rglSetError( GL_INVALID_ENUM ); + return; + } + texture->revalidate |= RGL_TEXTURE_REVALIDATE_PARAMETERS; + LContext->needValidate |= RGL_VALIDATE_TEXTURES_USED; +} + +GLAPI void APIENTRY glBindTexture( GLenum target, GLuint name ) +{ + RGLcontext* LContext = _CurrentContext; + rglTextureImageUnit *unit = LContext->CurrentImageUnit; + + rglBindTextureInternal( unit, name, target ); +} + +GLAPI void APIENTRY glTexImage2D( GLenum target, GLint level, GLint internalFormat, + GLsizei width, GLsizei height, GLint border, GLenum format, + GLenum type, const GLvoid *pixels ) +{ + RGLcontext* LContext = _CurrentContext; + + rglTexture *texture; + rglImage *image; + if (rglGetImage(target, level, &texture, &image, MAX(width, height))) + return; + + image->dataState = RGL_IMAGE_DATASTATE_UNSET; + + rglBufferObject* bufferObject = NULL; + if ( LContext->PixelUnpackBuffer != 0 ) + { + bufferObject = + (rglBufferObject*)LContext->bufferObjectNameSpace.data[LContext->PixelUnpackBuffer]; + pixels = rglPlatformBufferObjectMap( bufferObject, GL_READ_ONLY ) + + (( const GLubyte* )pixels - ( const GLubyte* )NULL ); + } + + rglSetImage( + image, + internalFormat, + width, height, 1, + LContext->unpackAlignment, + format, type, + pixels ); + + + if ( LContext->PixelUnpackBuffer != 0 ) + { + rglPlatformBufferObjectUnmap( bufferObject ); + } + + texture->revalidate |= RGL_TEXTURE_REVALIDATE_IMAGES; + + rglTextureTouchFBOs( texture ); + + LContext->needValidate |= RGL_VALIDATE_TEXTURES_USED; +} + +GLAPI void APIENTRY glActiveTexture( GLenum texture ) +{ + RGLcontext* LContext = _CurrentContext; + + int unit = texture - GL_TEXTURE0; + LContext->ActiveTexture = unit; + + if(unit < RGL_MAX_TEXTURE_IMAGE_UNITS) + LContext->CurrentImageUnit = LContext->TextureImageUnits + unit; + else + LContext->CurrentImageUnit = NULL; +} + +GLAPI void APIENTRY glTextureReferenceSCE( GLenum target, GLuint levels, + GLuint baseWidth, GLuint baseHeight, GLuint baseDepth, GLenum internalFormat, GLuint pitch, GLintptr offset ) +{ + RGLcontext* LContext = _CurrentContext; + + rglTexture *texture = rglGetCurrentTexture( LContext->CurrentImageUnit, target ); + rglBufferObject *bufferObject = + (rglBufferObject*)LContext->bufferObjectNameSpace.data[LContext->TextureBuffer]; + rglReallocateImages( texture, 0, MAX( baseWidth, MAX( baseHeight, baseDepth ) ) ); + + rglSetImageTexRef(texture->image, internalFormat, baseWidth, baseHeight, + baseDepth, LContext->unpackAlignment); + texture->maxLevel = 0; + texture->usage = GL_TEXTURE_LINEAR_GPU_SCE; + + GLboolean r = rglPlatformTextureReference( texture, pitch, bufferObject, offset ); + if ( !r ) return; + bufferObject->textureReferences.pushBack( texture ); + texture->referenceBuffer = bufferObject; + texture->offset = offset; + rglTextureTouchFBOs( texture ); + LContext->needValidate |= RGL_VALIDATE_TEXTURES_USED; +} + +/*============================================================ + VERTEX ARRAYS + ============================================================ */ + +#include /* TODO: move to platform-specific code */ + +const uint32_t c_rounded_size_ofrglDrawParams = (sizeof(rglDrawParams)+0x7f)&~0x7f; +static uint8_t s_dparams_buff[ c_rounded_size_ofrglDrawParams ] __attribute__((aligned(128))); + +GLAPI void APIENTRY glVertexPointer( GLint size, GLenum type, GLsizei stride, const GLvoid* pointer ) +{ + rglVertexAttribPointerNV( RGL_ATTRIB_POSITION_INDEX, size, type, GL_FALSE, stride, pointer ); +} + +GLAPI void APIENTRY glNormalPointer( GLenum type, GLsizei stride, const GLvoid* pointer ) +{ + rglVertexAttribPointerNV( RGL_ATTRIB_NORMAL_INDEX, 3, type, GL_TRUE, stride, pointer ); +} + +GLAPI void APIENTRY glColor4f( GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha ) +{ + rglVertexAttrib4fNV( RGL_ATTRIB_PRIMARY_COLOR_INDEX, red, green, blue, alpha ); +} + +GLAPI void APIENTRY glColor4ub( GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha ) +{ + const float f = 1.f / 255.f; + rglVertexAttrib4fNV( RGL_ATTRIB_PRIMARY_COLOR_INDEX, f*red, f*green, f*blue, f*alpha ); +} + +GLAPI void APIENTRY glColor4fv( const GLfloat *v ) +{ + rglVertexAttrib4fvNV( RGL_ATTRIB_PRIMARY_COLOR_INDEX, v ); +} + +void rglVertexAttribPointerNV( + GLuint index, + GLint fsize, + GLenum type, + GLboolean normalized, + GLsizei stride, + const GLvoid* pointer ) +{ + RGLcontext* LContext = _CurrentContext; + + GLsizei defaultStride = 0; + switch ( type ) + { + case GL_FLOAT: + case GL_HALF_FLOAT_ARB: + case GL_BYTE: + case GL_UNSIGNED_BYTE: + case GL_SHORT: + case GL_FIXED: + defaultStride = fsize * rglGetTypeSize( type ); + break; + case GL_FIXED_11_11_10_SCE: + defaultStride = 4; + break; + default: + rglSetError( GL_INVALID_ENUM ); + return; + } + + rglAttributeState* as = LContext->attribs; + rglAttribute* attrib = as->attrib + index; + attrib->clientSize = fsize; + attrib->clientType = type; + attrib->clientStride = stride ? stride : defaultStride; + attrib->clientData = ( void* )pointer; + attrib->arrayBuffer = LContext->ArrayBuffer; + attrib->normalized = normalized; + RGLBIT_ASSIGN( as->HasVBOMask, index, attrib->arrayBuffer != 0 ); + + RGLBIT_TRUE( as->DirtyMask, index ); +} + +void rglEnableVertexAttribArrayNV( GLuint index ) +{ + RGLcontext *LContext = _CurrentContext; + + RGLBIT_TRUE( LContext->attribs->EnabledMask, index ); + RGLBIT_TRUE( LContext->attribs->DirtyMask, index ); + +} + +void rglDisableVertexAttribArrayNV( GLuint index ) +{ + RGLcontext *LContext = _CurrentContext; + + RGLBIT_FALSE( LContext->attribs->EnabledMask, index ); + RGLBIT_TRUE( LContext->attribs->DirtyMask, index ); + +} + +void rglVertexAttrib1fNV( GLuint index, GLfloat x ) +{ + + RGLcontext* LContext = _CurrentContext; + + rglAttribute* attrib = LContext->attribs->attrib + index; + attrib->value[0] = x; + attrib->value[1] = 0.0f; + attrib->value[2] = 0.0f; + attrib->value[3] = 1.0f; + RGLBIT_TRUE( LContext->attribs->DirtyMask, index ); + +} + +void rglVertexAttrib2fNV( GLuint index, GLfloat x, GLfloat y ) +{ + RGLcontext* LContext = _CurrentContext; + + rglAttribute* attrib = LContext->attribs->attrib + index; + attrib->value[0] = x; + attrib->value[1] = y; + attrib->value[2] = 0.0f; + attrib->value[3] = 1.0f; + RGLBIT_TRUE( LContext->attribs->DirtyMask, index ); +} + +void rglVertexAttrib3fNV( GLuint index, GLfloat x, GLfloat y, GLfloat z ) +{ + RGLcontext* LContext = _CurrentContext; + + rglAttribute* attrib = LContext->attribs->attrib + index; + attrib->value[0] = x; + attrib->value[1] = y; + attrib->value[2] = z; + attrib->value[3] = 1.0f; + RGLBIT_TRUE( LContext->attribs->DirtyMask, index ); + +} + +void rglVertexAttrib4fNV( GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w ) +{ + RGLcontext* LContext = _CurrentContext; + + rglAttribute* attrib = LContext->attribs->attrib + index; + attrib->value[0] = x; + attrib->value[1] = y; + attrib->value[2] = z; + attrib->value[3] = w; + RGLBIT_TRUE( LContext->attribs->DirtyMask, index ); +} + +void rglVertexAttrib1fvNV( GLuint index, const GLfloat* v ) +{ + rglVertexAttrib1fNV( index, v[0] ); +} + +void rglVertexAttrib2fvNV( GLuint index, const GLfloat* v ) +{ + rglVertexAttrib2fNV( index, v[0], v[1] ); +} + +void rglVertexAttrib3fvNV( GLuint index, const GLfloat* v ) +{ + rglVertexAttrib3fNV( index, v[0], v[1], v[2] ); +} + +void rglVertexAttrib4fvNV( GLuint index, const GLfloat* v ) +{ + rglVertexAttrib4fNV( index, v[0], v[1], v[2], v[3] ); +} + +GLAPI void APIENTRY glDrawArrays( GLenum mode, GLint first, GLsizei count ) +{ + RGLcontext* LContext = _CurrentContext; + + if (RGL_UNLIKELY(!RGLBIT_GET(LContext->attribs->EnabledMask, RGL_ATTRIB_POSITION_INDEX))) + return; + + uint32_t _tmp_clear_loop = c_rounded_size_ofrglDrawParams>>7; + do{ + --_tmp_clear_loop; + __dcbz(s_dparams_buff+(_tmp_clear_loop<<7)); + }while(_tmp_clear_loop); + + rglDrawParams *dparams = (rglDrawParams *)s_dparams_buff; + dparams->mode = mode; + dparams->firstVertex = first; + dparams->vertexCount = count; + + if ( LContext->needValidate ) rglValidateStates( RGL_VALIDATE_ALL ); + + GLboolean slowPath = rglPlatformRequiresSlowPath( dparams, 0, 0); + (void)slowPath; + + rglPlatformDraw( dparams ); +} + +/*============================================================ + DEVICE CONTEXT CREATION + ============================================================ */ + +RGLdevice *_CurrentDevice = NULL; + +void rglDeviceInit( RGLinitOptions* options ) +{ + rglPlatformDeviceInit( options ); +} + +void rglDeviceExit(void) +{ + rglPlatformDeviceExit(); +} + +RGL_EXPORT RGLdevice* psglCreateDeviceAuto( GLenum colorFormat, GLenum depthFormat, GLenum multisamplingMode ) +{ + return rglPlatformCreateDeviceAuto(colorFormat, depthFormat, multisamplingMode); +} + +RGL_EXPORT RGLdevice* psglCreateDeviceExtended( const RGLdeviceParameters *parameters ) +{ + return rglPlatformCreateDeviceExtended(parameters); +} + +RGL_EXPORT GLfloat psglGetDeviceAspectRatio( const RGLdevice * device ) +{ + return rglPlatformGetDeviceAspectRatio(device); +} + +RGL_EXPORT void psglGetDeviceDimensions( const RGLdevice * device, GLuint *width, GLuint *height ) +{ + *width = device->deviceParameters.width; + *height = device->deviceParameters.height; +} + +RGL_EXPORT void psglGetRenderBufferDimensions( const RGLdevice * device, GLuint *width, GLuint *height ) +{ + *width = device->deviceParameters.renderWidth; + *height = device->deviceParameters.renderHeight; +} + +RGL_EXPORT void psglDestroyDevice( RGLdevice *device ) +{ + if ( _CurrentDevice == device ) psglMakeCurrent( NULL, NULL ); + + if ( device->rasterDriver ) rglPlatformRasterExit( device->rasterDriver ); + rglPlatformDestroyDevice( device ); + + free( device ); +} + +void RGL_EXPORT psglMakeCurrent( RGLcontext *context, RGLdevice *device ) +{ + if ( context && device ) + { + rglPlatformMakeCurrent( device->platformDevice ); + _CurrentContext = context; + _CurrentDevice = device; + if ( !device->rasterDriver ) + { + device->rasterDriver = rglPlatformRasterInit(); + } + rglAttachContext( device, context ); + } + else + { + rglPlatformMakeCurrent( NULL ); + _CurrentContext = NULL; + _CurrentDevice = NULL; + } +} + +RGLdevice *psglGetCurrentDevice(void) +{ + return _CurrentDevice; +} + +GLAPI void RGL_EXPORT psglSwap( void ) +{ + if ( _CurrentDevice != NULL ) + rglPlatformSwapBuffers( _CurrentDevice ); +} diff --git a/console/rgl/src/rgl.h b/console/rgl/src/rgl.h new file mode 100644 index 0000000000..4c076339f2 --- /dev/null +++ b/console/rgl/src/rgl.h @@ -0,0 +1,39 @@ +/* RetroArch - A frontend for libretro. + * RGL - An OpenGL subset wrapper library. + * Copyright (C) 2012 - Hans-Kristian Arntzen + * Copyright (C) 2012 - Daniel De Matteis + * + * RetroArch 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 Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch 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 RetroArch. + * If not, see . + */ + +#ifndef _RGL_H +#define _RGL_H + +#include "../include/export/RGL/rgl.h" +#include "../include/RGL/Types.h" +#include "../include/RGL/TypeUtils.h" +#include "../include/RGL/private.h" +#include "../include/RGL/Utils.h" +#include +#include +#include + +#include + +void rglPsglPlatformInit( RGLinitOptions* options ); +void rglPsglPlatformExit(void); + +RGL_EXPORT RGLdevice* rglPlatformCreateDeviceAuto( GLenum colorFormat, GLenum depthFormat, GLenum multisamplingMode ); +RGL_EXPORT RGLdevice* rglPlatformCreateDeviceExtended( const RGLdeviceParameters *parameters ); +RGL_EXPORT GLfloat rglPlatformGetDeviceAspectRatio( const RGLdevice * device ); + +#endif diff --git a/console/rgl/src/rgl_cg.cpp b/console/rgl/src/rgl_cg.cpp new file mode 100644 index 0000000000..29ba178a41 --- /dev/null +++ b/console/rgl/src/rgl_cg.cpp @@ -0,0 +1,9787 @@ +/* RetroArch - A frontend for libretro. + * RGL - An OpenGL subset wrapper library. + * Copyright (C) 2012 - Hans-Kristian Arntzen + * Copyright (C) 2012 - Daniel De Matteis + * + * RetroArch 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 Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch 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 RetroArch. + * If not, see . + */ + +#include "rgl_cg.h" + +/*============================================================ + RTC CGC + ============================================================ */ + +void cgRTCgcInit( void ) +{ + _cgRTCgcCompileProgramHook = &compile_program_from_string; + _cgRTCgcFreeCompiledProgramHook = &free_compiled_program; +} + +void cgRTCgcFree( void ) +{ + _cgRTCgcCompileProgramHook = 0; + _cgRTCgcFreeCompiledProgramHook = 0; +} + +/*============================================================ + CG COMMON + ============================================================ */ + +void rglCgRaiseError( CGerror error ) +{ + _CurrentContext->RGLcgLastError = error; + + //_RGL_REPORT_EXTRA( RGL_REPORT_CG_ERROR, "Cg error:%s", cgGetErrorString( error ) ); + + if ( _CurrentContext->RGLcgErrorCallbackFunction ) + _CurrentContext->RGLcgErrorCallbackFunction(); +} + +unsigned int rglCountFloatsInCgType( CGtype type ) +{ + int size = 0; + switch ( type ) + { + case CG_FLOAT: + case CG_FLOAT1: + case CG_FLOAT1x1: + size = 1; + break; + case CG_FLOAT2: + case CG_FLOAT2x1: + case CG_FLOAT1x2: + size = 2; + break; + case CG_FLOAT3: + case CG_FLOAT3x1: + case CG_FLOAT1x3: + size = 3; + break; + case CG_FLOAT4: + case CG_FLOAT4x1: + case CG_FLOAT1x4: + case CG_FLOAT2x2: + size = 4; + break; + case CG_FLOAT2x3: + case CG_FLOAT3x2: + size = 6; + break; + case CG_FLOAT2x4: + case CG_FLOAT4x2: + size = 8; + break; + case CG_FLOAT3x3: + size = 9; + break; + case CG_FLOAT3x4: + case CG_FLOAT4x3: + size = 12; + break; + case CG_FLOAT4x4: + size = 16; + break; + case CG_SAMPLER1D: + case CG_SAMPLER2D: + case CG_SAMPLER3D: + case CG_SAMPLERRECT: + case CG_SAMPLERCUBE: + size = 1; + break; + case CG_BOOL: + size = 1; + break; + case CG_HALF: + case CG_HALF1: + case CG_HALF1x1: + size = 1; + break; + case CG_HALF2: + case CG_HALF2x1: + case CG_HALF1x2: + size = 2; + break; + case CG_HALF3: + case CG_HALF3x1: + case CG_HALF1x3: + size = 3; + break; + case CG_HALF4: + case CG_HALF4x1: + case CG_HALF1x4: + case CG_HALF2x2: + size = 4; + break; + case CG_HALF2x3: + case CG_HALF3x2: + size = 6; + break; + case CG_HALF2x4: + case CG_HALF4x2: + size = 8; + break; + case CG_HALF3x3: + size = 9; + break; + case CG_HALF3x4: + case CG_HALF4x3: + size = 12; + break; + case CG_HALF4x4: + size = 16; + break; + case CG_INT: + case CG_INT1: + case CG_INT1x1: + size = 1; + break; + case CG_INT2: + case CG_INT2x1: + case CG_INT1x2: + size = 2; + break; + case CG_INT3: + case CG_INT3x1: + case CG_INT1x3: + size = 3; + break; + case CG_INT4: + case CG_INT4x1: + case CG_INT1x4: + case CG_INT2x2: + size = 4; + break; + case CG_INT2x3: + case CG_INT3x2: + size = 6; + break; + case CG_INT2x4: + case CG_INT4x2: + size = 8; + break; + case CG_INT3x3: + size = 9; + break; + case CG_INT3x4: + case CG_INT4x3: + size = 12; + break; + case CG_INT4x4: + size = 16; + break; + case CG_BOOL1: + case CG_BOOL1x1: + size = 1; + break; + case CG_BOOL2: + case CG_BOOL2x1: + case CG_BOOL1x2: + size = 2; + break; + case CG_BOOL3: + case CG_BOOL3x1: + case CG_BOOL1x3: + size = 3; + break; + case CG_BOOL4: + case CG_BOOL4x1: + case CG_BOOL1x4: + case CG_BOOL2x2: + size = 4; + break; + case CG_BOOL2x3: + case CG_BOOL3x2: + size = 6; + break; + case CG_BOOL2x4: + case CG_BOOL4x2: + size = 8; + break; + case CG_BOOL3x3: + size = 9; + break; + case CG_BOOL3x4: + case CG_BOOL4x3: + size = 12; + break; + case CG_BOOL4x4: + size = 16; + break; + case CG_FIXED: + case CG_FIXED1: + case CG_FIXED1x1: + size = 1; + break; + case CG_FIXED2: + case CG_FIXED2x1: + case CG_FIXED1x2: + size = 2; + break; + case CG_FIXED3: + case CG_FIXED3x1: + case CG_FIXED1x3: + size = 3; + break; + case CG_FIXED4: + case CG_FIXED4x1: + case CG_FIXED1x4: + case CG_FIXED2x2: + size = 4; + break; + case CG_FIXED2x3: + case CG_FIXED3x2: + size = 6; + break; + case CG_FIXED2x4: + case CG_FIXED4x2: + size = 8; + break; + case CG_FIXED3x3: + size = 9; + break; + case CG_FIXED3x4: + case CG_FIXED4x3: + size = 12; + break; + case CG_FIXED4x4: + size = 16; + break; + default: + size = 0; + break; + } + return size; +} + +void _cgRaiseInvalidParam( CgRuntimeParameter*p, const void*v ) +{ + rglCgRaiseError( CG_INVALID_PARAMETER_ERROR ); +} +void _cgRaiseInvalidParamIndex( CgRuntimeParameter*p, const void*v, const int index ) +{ + rglCgRaiseError( CG_INVALID_PARAMETER_ERROR ); +} + +void _cgRaiseNotMatrixParam( CgRuntimeParameter*p, const void*v ) +{ + rglCgRaiseError( CG_NOT_MATRIX_PARAM_ERROR ); +} +void _cgRaiseNotMatrixParamIndex( CgRuntimeParameter*p, const void*v, const int index ) +{ + rglCgRaiseError( CG_NOT_MATRIX_PARAM_ERROR ); +} + +void _cgIgnoreSetParamIndex( CgRuntimeParameter*p, const void*v, const int index ) +{ + // nothing +} + +CGbool _cgMatrixDimensions( CGtype type, unsigned int* nrows, unsigned int* ncols ) +{ + CGbool isMatrixType = CG_TRUE; + switch ( type ) + { + case CG_FLOAT: *nrows = 1; *ncols = 1; isMatrixType = CG_FALSE; break; + case CG_FLOAT1: *nrows = 1; *ncols = 1; isMatrixType = CG_FALSE; break; + case CG_HALF: *nrows = 1; *ncols = 1; isMatrixType = CG_FALSE; break; + case CG_HALF1: *nrows = 1; *ncols = 1; isMatrixType = CG_FALSE; break; + case CG_INT: *nrows = 1; *ncols = 1; isMatrixType = CG_FALSE; break; + case CG_INT1: *nrows = 1; *ncols = 1; isMatrixType = CG_FALSE; break; + case CG_BOOL: *nrows = 1; *ncols = 1; isMatrixType = CG_FALSE; break; + case CG_BOOL1: *nrows = 1; *ncols = 1; isMatrixType = CG_FALSE; break; + case CG_FIXED: *nrows = 1; *ncols = 1; isMatrixType = CG_FALSE; break; + case CG_FIXED1: *nrows = 1; *ncols = 2; isMatrixType = CG_FALSE; break; + + + case CG_FLOAT1x1: *nrows = 1; *ncols = 1; break; + case CG_FLOAT1x2: *nrows = 1; *ncols = 2; break; + case CG_FLOAT1x3: *nrows = 1; *ncols = 3; break; + case CG_FLOAT1x4: *nrows = 1; *ncols = 4; break; + case CG_FLOAT2x1: *nrows = 2; *ncols = 1; break; + case CG_FLOAT2x2: *nrows = 2; *ncols = 2; break; + case CG_FLOAT2x3: *nrows = 2; *ncols = 3; break; + case CG_FLOAT2x4: *nrows = 2; *ncols = 4; break; + case CG_FLOAT3x1: *nrows = 3; *ncols = 1; break; + case CG_FLOAT3x2: *nrows = 3; *ncols = 2; break; + case CG_FLOAT3x3: *nrows = 3; *ncols = 3; break; + case CG_FLOAT3x4: *nrows = 3; *ncols = 4; break; + case CG_FLOAT4x1: *nrows = 4; *ncols = 1; break; + case CG_FLOAT4x2: *nrows = 4; *ncols = 2; break; + case CG_FLOAT4x3: *nrows = 4; *ncols = 3; break; + case CG_FLOAT4x4: *nrows = 4; *ncols = 4; break; + case CG_HALF1x1: *nrows = 1; *ncols = 1; break; + case CG_HALF1x2: *nrows = 1; *ncols = 2; break; + case CG_HALF1x3: *nrows = 1; *ncols = 3; break; + case CG_HALF1x4: *nrows = 1; *ncols = 4; break; + case CG_HALF2x1: *nrows = 2; *ncols = 1; break; + case CG_HALF2x2: *nrows = 2; *ncols = 2; break; + case CG_HALF2x3: *nrows = 2; *ncols = 3; break; + case CG_HALF2x4: *nrows = 2; *ncols = 4; break; + case CG_HALF3x1: *nrows = 3; *ncols = 1; break; + case CG_HALF3x2: *nrows = 3; *ncols = 2; break; + case CG_HALF3x3: *nrows = 3; *ncols = 3; break; + case CG_HALF3x4: *nrows = 3; *ncols = 4; break; + case CG_HALF4x1: *nrows = 4; *ncols = 1; break; + case CG_HALF4x2: *nrows = 4; *ncols = 2; break; + case CG_HALF4x3: *nrows = 4; *ncols = 3; break; + case CG_HALF4x4: *nrows = 4; *ncols = 4; break; + case CG_INT1x1: *nrows = 1; *ncols = 1; break; + case CG_INT1x2: *nrows = 1; *ncols = 2; break; + case CG_INT1x3: *nrows = 1; *ncols = 3; break; + case CG_INT1x4: *nrows = 1; *ncols = 4; break; + case CG_INT2x1: *nrows = 2; *ncols = 1; break; + case CG_INT2x2: *nrows = 2; *ncols = 2; break; + case CG_INT2x3: *nrows = 2; *ncols = 3; break; + case CG_INT2x4: *nrows = 2; *ncols = 4; break; + case CG_INT3x1: *nrows = 3; *ncols = 1; break; + case CG_INT3x2: *nrows = 3; *ncols = 2; break; + case CG_INT3x3: *nrows = 3; *ncols = 3; break; + case CG_INT3x4: *nrows = 3; *ncols = 4; break; + case CG_INT4x1: *nrows = 4; *ncols = 1; break; + case CG_INT4x2: *nrows = 4; *ncols = 2; break; + case CG_INT4x3: *nrows = 4; *ncols = 3; break; + case CG_INT4x4: *nrows = 4; *ncols = 4; break; + case CG_BOOL1x1: *nrows = 1; *ncols = 1; break; + case CG_BOOL1x2: *nrows = 1; *ncols = 2; break; + case CG_BOOL1x3: *nrows = 1; *ncols = 3; break; + case CG_BOOL1x4: *nrows = 1; *ncols = 4; break; + case CG_BOOL2x1: *nrows = 2; *ncols = 1; break; + case CG_BOOL2x2: *nrows = 2; *ncols = 2; break; + case CG_BOOL2x3: *nrows = 2; *ncols = 3; break; + case CG_BOOL2x4: *nrows = 2; *ncols = 4; break; + case CG_BOOL3x1: *nrows = 3; *ncols = 1; break; + case CG_BOOL3x2: *nrows = 3; *ncols = 2; break; + case CG_BOOL3x3: *nrows = 3; *ncols = 3; break; + case CG_BOOL3x4: *nrows = 3; *ncols = 4; break; + case CG_BOOL4x1: *nrows = 4; *ncols = 1; break; + case CG_BOOL4x2: *nrows = 4; *ncols = 2; break; + case CG_BOOL4x3: *nrows = 4; *ncols = 3; break; + case CG_BOOL4x4: *nrows = 4; *ncols = 4; break; + case CG_FIXED1x1: *nrows = 1; *ncols = 1; break; + case CG_FIXED1x2: *nrows = 1; *ncols = 2; break; + case CG_FIXED1x3: *nrows = 1; *ncols = 3; break; + case CG_FIXED1x4: *nrows = 1; *ncols = 4; break; + case CG_FIXED2x1: *nrows = 2; *ncols = 1; break; + case CG_FIXED2x2: *nrows = 2; *ncols = 2; break; + case CG_FIXED2x3: *nrows = 2; *ncols = 3; break; + case CG_FIXED2x4: *nrows = 2; *ncols = 4; break; + case CG_FIXED3x1: *nrows = 3; *ncols = 1; break; + case CG_FIXED3x2: *nrows = 3; *ncols = 2; break; + case CG_FIXED3x3: *nrows = 3; *ncols = 3; break; + case CG_FIXED3x4: *nrows = 3; *ncols = 4; break; + case CG_FIXED4x1: *nrows = 4; *ncols = 1; break; + case CG_FIXED4x2: *nrows = 4; *ncols = 2; break; + case CG_FIXED4x3: *nrows = 4; *ncols = 3; break; + case CG_FIXED4x4: *nrows = 4; *ncols = 4; break; + default: *nrows = 0; *ncols = 0; break; + } + + return isMatrixType; +} + + +CgRuntimeParameter* _cgGLTestArrayParameter( CGparameter paramIn, long offset, long nelements ) +{ + CgRuntimeParameter* param = rglCgGLTestParameter( paramIn ); + + return param; +} + +CgRuntimeParameter* _cgGLTestTextureParameter( CGparameter param ) +{ + CgRuntimeParameter* ptr = rglCgGLTestParameter( param ); + return ptr; +} + + +#define CG_DATATYPE_MACRO(name, compiler_name, enum_name, base_enum, nrows, ncols,classname) \ + nrows , +static int _typesRowCount[] = +{ +#include "Cg/cg_datatypes.h" +}; + +#define CG_DATATYPE_MACRO(name, compiler_name, enum_name, base_enum, nrows, ncols,classname) \ + ncols , +static int _typesColCount[] = +{ +#include "Cg/cg_datatypes.h" +}; + +unsigned int rglGetTypeRowCount( CGtype parameterType ) +{ + int typeIndex = parameterType - 1 - CG_TYPE_START_ENUM; + return _typesRowCount[typeIndex]; +} + +unsigned int rglGetTypeColCount( CGtype parameterType ) +{ + int typeIndex = parameterType - 1 - CG_TYPE_START_ENUM; + return _typesColCount[typeIndex]; +} + +/*============================================================ + CG PARAMETER + ============================================================ */ + +static const CGenum var_table[] = {CG_VARYING, CG_UNIFORM, CG_CONSTANT, CG_MIXED}; +static const CGenum dir_table[] = {CG_IN, CG_OUT, CG_INOUT, CG_ERROR}; + +RGL_EXPORT CgparameterHookFunction _cgParameterCreateHook = NULL; +RGL_EXPORT CgparameterHookFunction _cgParameterDestroyHook = NULL; + +static void rglCgGetParameterResourceInfo( CgRuntimeParameter *rtParameter, int arrayIndex, CGresource *resource, unsigned long *resourceIndex, unsigned short* numEmbeddedConstants) +{ + const CgParameterEntry *paramEntry = rtParameter->parameterEntry; + const CgParameterResource *paramResource = rglGetParameterResource( rtParameter->program, paramEntry ); + + const unsigned short *paramResourceTable = rtParameter->program->resources; + + if (( paramEntry->flags & CGPV_MASK ) == CGPV_VARYING ) + { + *resource = ( CGresource )paramResource->resource; + *resourceIndex = -1U; + } + else if ((( paramEntry->flags & CGPV_MASK ) & CGPV_CONSTANT ) || (( paramEntry->flags & CGPV_MASK ) & CGPV_UNIFORM ) ) + { + CGtype parameterResourceType = rglGetParameterCGtype( rtParameter->program, paramEntry ); + + if ( parameterResourceType >= CG_SAMPLER1D && parameterResourceType <= CG_SAMPLERCUBE ) + { + *resource = ( CGresource )paramResource->resource; + *resourceIndex = 0; + } + else + { + if ( parameterResourceType == CGP_SCF_BOOL ) + *resource = CG_B; + else + *resource = CG_C; + + bool bIsVertexProgram; + switch ( rtParameter->program->header.profile ) + { + case CG_PROFILE_SCE_VP_TYPEB: + case ( CGprofile )7005: + case CG_PROFILE_SCE_VP_RSX: + bIsVertexProgram = true; + break; + default: + bIsVertexProgram = false; + break; + } + + + unsigned int rows = rglGetTypeRowCount( parameterResourceType ); + if ( rows == 0 ) + rows = 1; + + *numEmbeddedConstants = 0; + + if ( bIsVertexProgram ) + { + if ( arrayIndex >= 0 ) + { + if ( paramEntry->flags & CGP_CONTIGUOUS ) + { + *resourceIndex = paramResource->resource + arrayIndex * rows; + } + else + { + unsigned short tempResIndex = *( paramResourceTable + paramResource->resource + arrayIndex * rows ); + *resourceIndex = ( tempResIndex == 0xFFFF ) ? -1U : ( int )tempResIndex; + } + } + else + { + unsigned short tempResIndex = paramResource->resource; + *resourceIndex = ( tempResIndex == 0xFFFF ) ? -1 : ( int )tempResIndex; + } + } + else + { + const unsigned short* resPtr = paramResourceTable + paramResource->resource; + if ( arrayIndex < 0 ) + arrayIndex = 0; + + int skipCount = arrayIndex * rows; + while ( skipCount ) + { + resPtr++; + int embeddedCount = *( resPtr++ ); + resPtr += embeddedCount; + skipCount--; + } + unsigned short tempResIndex = *( resPtr ); + + while (rows) + { + resPtr++; // skip register + unsigned short ecCount = *resPtr; + resPtr++; + *numEmbeddedConstants += ecCount; + resPtr += ecCount; + rows--; + } + + *resourceIndex = ( tempResIndex == 0xFFFF ) ? -1 : ( int )tempResIndex; + } + } + + } +} + +static CGparameter rglAdvanceParameter( CGparameter param, int distance ) +{ + CgRuntimeParameter *rtParameter = ( CgRuntimeParameter* )rglCgGLTestParameter( param ); + if ( !rtParameter ) + return NULL; + + if ( distance == 0 ) + return param; + + if ( rtParameter > rtParameter->program->runtimeParameters ) + { + CgRuntimeParameter *previousParameter = rtParameter - 1; + if (( previousParameter->parameterEntry->flags & CGP_ARRAY ) && + !( previousParameter->parameterEntry->flags & CGP_UNROLLED ) ) + { + int arrayIndex = CG_GETINDEX( param ); + arrayIndex += distance; + const CgParameterArray *parameterArray = rglGetParameterArray( previousParameter->program, previousParameter->parameterEntry ); + int arraySize = rglGetSizeofSubArray( parameterArray->dimensions, parameterArray->dimensionCount ); + if ( arrayIndex < arraySize ) + { + int ret = ( int )rtParameter->id; + ret |= ( arrayIndex << CG_PARAMETERSIZE ); + return ( CGparameter )ret; + } + else + { + return ( CGparameter )NULL; + } + } + } + + //stop when the distance is 0 + const CgParameterEntry *endEntry = rtParameter->program->parametersEntries + rtParameter->program->rtParametersCount; + const CgParameterEntry *paramEntry = rtParameter->parameterEntry; + + while ( distance && paramEntry < endEntry ) + { + switch ( paramEntry->flags & CGP_TYPE_MASK ) + { + case CGP_ARRAY: + { + if ( paramEntry->flags & CGP_UNROLLED ) + { + const CgParameterArray *parameterArray = rglGetParameterArray( rtParameter->program, paramEntry ); + int arraySize = ( int )rglGetSizeofSubArray( parameterArray->dimensions, parameterArray->dimensionCount ); + + paramEntry++; + distance--; + + paramEntry++; + distance += arraySize; + } + else + { + paramEntry++; + distance--; + paramEntry++; + } + break; + } + case CGP_STRUCTURE: + { + const CgParameterStructure *parameterStructure = rglGetParameterStructure( rtParameter->program, paramEntry ); + paramEntry++; + distance--; + distance += parameterStructure->memberCount; + break; + } + case CGP_INTRINSIC: + paramEntry++; + distance--; + break; + } + } + + if ( paramEntry < endEntry ) + { + size_t offset = ( paramEntry - rtParameter->parameterEntry ); + CgRuntimeParameter *nextParameter = rtParameter + offset; + return nextParameter->id; + } + else + { + return ( CGparameter )NULL; + } +} + +unsigned int _cgHashString( const char *str ) +{ + unsigned int h = 0; + unsigned int g; + while ( *str ) + { + h = ( h << 4 ) + *str++; + if (( g = h & 0xf0000000 ) ) h ^= g >> 24; + h &= ~g; + } + return h; +} + +static int connection_creates_cycle( CgRuntimeParameter* paramFrom, CgRuntimeParameter* paramTo ) +{ + CgRuntimeParameter* paramHierarchyIter = paramFrom; + while ( paramHierarchyIter != NULL ) + { + if ( paramHierarchyIter == paramTo ) + { + return 1; + } + + std::vector::iterator paramConnectionTableIter = paramHierarchyIter->program->connectionTable.begin(); + while ( paramConnectionTableIter != paramHierarchyIter->program->connectionTable.end() ) + { + if ( paramConnectionTableIter->child == paramHierarchyIter ) + { + paramHierarchyIter = paramConnectionTableIter->parent; + break; + } + paramConnectionTableIter++; + } + if ( paramConnectionTableIter == paramHierarchyIter->program->connectionTable.end() ) + { + paramHierarchyIter = NULL; + } + } + return 0; +} + +void rglCgDestroyContextParam( CgRuntimeParameter* ptr ) +{ + std::vector::iterator semanticIter = ptr->program->parameterSemantics.begin(); + while ( semanticIter != ptr->program->parameterSemantics.end() ) + { + if ( semanticIter->param == ptr ) + { + ptr->program->parameterSemantics.erase( semanticIter ); + break; + } + semanticIter++; + } + + std::vector::iterator paramConnectionTableIter = ptr->program->connectionTable.begin(); + while ( paramConnectionTableIter != ptr->program->connectionTable.end() ) + { + if ( paramConnectionTableIter->child == ptr ) + { + ptr->program->connectionTable.erase( paramConnectionTableIter ); + break; + } + paramConnectionTableIter++; + } + + if ( _cgParameterDestroyHook ) _cgParameterDestroyHook( ptr ); + + std::vector::iterator rtCreatedIter = ptr->program->runtimeCreatedParameters.begin(); + while ( rtCreatedIter != ptr->program->runtimeCreatedParameters.end() ) + { + if ( *rtCreatedIter == ptr ) + { + ptr->program->runtimeCreatedParameters.erase( rtCreatedIter ); + break; + } + rtCreatedIter++; + } + + rglEraseName( &_CurrentContext->cgParameterNameSpace, (unsigned int)( ptr->id ) ); + + free( ptr ); +} + +static void _setSamplerRuntimeParameter( CgRuntimeParameter*ptr, const void*v, int /*index*/ ) +{ + if ( v ) + { + *( GLuint* )ptr->pushBufferPointer = *( GLuint* )v; + } +} + +CgRuntimeParameter* rglCgCreateParameterInternal( _CGprogram *program, const char* name, CGtype type ) +{ + CgRuntimeParameter* param = NULL; + int isSampler = 0; + switch ( type ) + { + case CG_SAMPLER2D: + case CG_SAMPLER3D: + case CG_SAMPLERCUBE: + isSampler = 1; + case CG_FLOAT: // fall through + case CG_FLOAT1: + case CG_FLOAT2: + case CG_FLOAT3: + case CG_FLOAT4: + case CG_FLOAT1x1: + case CG_FLOAT2x1: + case CG_FLOAT1x2: + case CG_FLOAT3x1: + case CG_FLOAT1x3: + case CG_FLOAT4x1: + case CG_FLOAT1x4: + case CG_FLOAT2x2: + case CG_FLOAT2x3: + case CG_FLOAT3x2: + case CG_FLOAT2x4: + case CG_FLOAT4x2: + case CG_FLOAT3x3: + case CG_FLOAT3x4: + case CG_FLOAT4x3: + case CG_FLOAT4x4: + { + unsigned int size = sizeof( CgRuntimeParameter ) + sizeof( CgParameterEntry ) + + ( rglCountFloatsInCgType( type ) * sizeof( float ) ) + ( name ? strlen( name ) + 1 : 1 ); + + param = ( CgRuntimeParameter* ) malloc( size ); + + if ( !param ) { rglCgRaiseError( CG_MEMORY_ALLOC_ERROR ); return NULL; } + memset( param, 0, size ); + + CGparameter id = ( CGparameter )rglCreateName( &_CurrentContext->cgParameterNameSpace, param ); + if ( !id ) { free( param ); return NULL;} + + param->id = id; + + param->program = program; + + param->parameterEntry = ( CgParameterEntry * )(( char* )param + sizeof( CgRuntimeParameter ) ); + param->pushBufferPointer = ( void * )(( char* )param->parameterEntry + sizeof( CgParameterEntry ) ); + + CgParameterEntry* paramEntryInitializer = const_cast( param->parameterEntry ); + + paramEntryInitializer->nameOffset = ( unsigned int )(( char* )param->pushBufferPointer + rglCountFloatsInCgType( type ) * sizeof( float ) ); + + program->runtimeCreatedParameters.push_back( param ); + + if ( name ) + { + strcpy( reinterpret_cast( paramEntryInitializer->nameOffset ), name ); + } + + paramEntryInitializer->typeIndex = ( unsigned short )type; + + paramEntryInitializer->flags = 0; + paramEntryInitializer->flags |= CGP_RTCREATED; + paramEntryInitializer->flags |= CGPD_IN | CGPV_UNIFORM; + paramEntryInitializer->flags |= CGPF_GLOBAL; + + if ( isSampler ) + { + param->glType = rglCgGetSamplerGLTypeFromCgType( type ); + paramEntryInitializer->flags |= CGPF_REFERENCED; + } + + param->setterIndex = _cgRaiseInvalidParamIndex; + param->settercIndex = _cgRaiseNotMatrixParamIndex; + param->setterrIndex = _cgRaiseNotMatrixParamIndex; + param->samplerSetter = _cgRaiseInvalidParamIndex; + + switch ( type ) + { + case CG_FLOAT: + case CG_FLOAT1: case CG_FLOAT2: case CG_FLOAT3: case CG_FLOAT4: + { + unsigned int floatCount = rglCountFloatsInCgType( type ); + param->setterIndex = getVectorTypeIndexSetterFunction( 0, 0, VERTEX_PROFILE_INDEX, floatCount - 1 ); + } + break; + case CG_FLOAT1x1: case CG_FLOAT1x2: case CG_FLOAT1x3: case CG_FLOAT1x4: + case CG_FLOAT2x1: case CG_FLOAT2x2: case CG_FLOAT2x3: case CG_FLOAT2x4: + case CG_FLOAT3x1: case CG_FLOAT3x2: case CG_FLOAT3x3: case CG_FLOAT3x4: + case CG_FLOAT4x1: case CG_FLOAT4x2: case CG_FLOAT4x3: case CG_FLOAT4x4: + param->setterrIndex = getMatrixTypeIndexSetterFunction( 0, 0, VERTEX_PROFILE_INDEX, rglGetTypeRowCount( type ) - 1, rglGetTypeColCount( type ) - 1, 0 ); + param->settercIndex = getMatrixTypeIndexSetterFunction( 0, 0, VERTEX_PROFILE_INDEX, rglGetTypeRowCount( type ) - 1, rglGetTypeColCount( type ) - 1, 1 ); + break; + case CG_SAMPLER1D: case CG_SAMPLER2D: case CG_SAMPLER3D: case CG_SAMPLERRECT: case CG_SAMPLERCUBE: + param->samplerSetter = _setSamplerRuntimeParameter; + break; + case CGP_SCF_BOOL: + break; + default: + break; + } + + if ( _cgParameterCreateHook ) _cgParameterCreateHook( param ); + break; + } + default: + rglCgRaiseError( CG_INVALID_VALUE_TYPE_ERROR ); + break; + } + return param; +} + +static int rglGetSizeofSubArray( const short *dimensions, int count ) +{ + int res = 1; + for ( int i = 0;i < count;i++ ) + res *= ( int )( *( dimensions++ ) ); + return res; +} + + +static _CGparameter *_cgGetNamedParameter( _CGprogram* progPtr, const char* name, CGenum name_space, int *arrayIndex, const CgParameterEntry *_startEntry = NULL, int _entryCount = -1 ) +{ + if ( name == NULL ) + return NULL; + + *arrayIndex = -1; + int done = 0; + const char *structureEnd; + const char *structureStart = name; + int itemIndex = -1; + _CGprogram *program = progPtr; + + const CgParameterEntry *currentEntry; + const CgParameterEntry *lastEntry; + + int containerCount = -2; + if ( _startEntry && _entryCount != -1 ) + { + currentEntry = _startEntry; + containerCount = _entryCount; + } + else + { + currentEntry = program->parametersEntries; + } + lastEntry = program->parametersEntries + program->rtParametersCount; + + int isInArray = 0; + bool bWasUnrolled = false; + const char *prevStructureStart = structureStart; //for unrolled + + while (( !done ) && ( *structureStart ) && ( containerCount != -1 ) ) + { + structureEnd = strpbrk( structureStart, ".[" ); + if ( structureEnd == NULL ) + { + structureEnd = structureStart + strlen( structureStart ); + done = 1; + } + + if ( bWasUnrolled ) + { + bWasUnrolled = false; + structureStart = prevStructureStart; + } + char structName[256]; + int length = ( int )( structureEnd - structureStart ); + strncpy( structName, structureStart, length ); + structName[length] = '\0'; + prevStructureStart = structureStart; //for unrolled + structureStart = structureEnd + 1; + + bool found = false; + while ( !found && currentEntry < lastEntry && ( containerCount == -2 || containerCount > 0 ) ) + { + if ( !strncmp( structName, program->stringTable + currentEntry->nameOffset, length ) + && ( name_space == 0 || ( name_space == CG_GLOBAL && ( currentEntry->flags & CGPF_GLOBAL ) ) + || ( name_space == CG_PROGRAM && !( currentEntry->flags & CGPF_GLOBAL ) ) ) ) + { + if (( int )strlen( program->stringTable + currentEntry->nameOffset ) != length ) + { + if ( !strcmp( name, program->stringTable + currentEntry->nameOffset ) ) + { + found = true; + done = 1; + } + + if ( !strncmp( name, program->stringTable + currentEntry->nameOffset, length ) && + !strcmp( "[0]", program->stringTable + currentEntry->nameOffset + length ) ) + { + found = true; + done = 1; + } + } + else + found = true; + } + + if ( !found ) + { + //we are skipping entries here, the search stays at the same level + int skipCount = 1; + while ( skipCount && currentEntry < lastEntry ) + { + //skip as many entry as necessary + if ( currentEntry->flags & CGP_STRUCTURE ) + { + const CgParameterStructure *parameterStructure = rglGetParameterStructure( program, currentEntry ); + skipCount += parameterStructure->memberCount; + } + else if ( currentEntry->flags & CGP_ARRAY ) + { + if ( currentEntry->flags & CGP_UNROLLED ) + { + const CgParameterArray *parameterArray = rglGetParameterArray( program, currentEntry ); + skipCount += rglGetSizeofSubArray(( short* )parameterArray->dimensions, parameterArray->dimensionCount ); + } + else + skipCount++; //the following item will be the type ( can't be a structure as they are always enrolled at the moment ) + } + currentEntry++; + skipCount--; + } + } + if ( containerCount != -2 ) //denotes that we are in a structure or in an array and that we shouldn't look beyond + containerCount--; + } + //at that point we failed or we succeeded to find the entry at that level. + //if we have succeed we continue in the lower level if needed. if we have failed, we return not found. + + if ( found ) + { + switch ( currentEntry->flags & CGP_TYPE_MASK ) { + case 0: + itemIndex = ( int )( currentEntry - program->parametersEntries ); + break; + case CGP_ARRAY: + { + + const CgParameterEntry *arrayEntry = currentEntry; + const CgParameterArray *parameterArray = rglGetParameterArray( program, arrayEntry ); + + if ( *structureEnd == '\0' ) //if we are asked for the array parameter itself and not an array item: + { + itemIndex = ( int )( currentEntry - program->parametersEntries ); + break; + } + + //go inside: + currentEntry++; + if ( currentEntry->flags &CGP_STRUCTURE ) + { + //continue to look into the list, but we should stop before the end of the array + bWasUnrolled = true; + containerCount = rglGetSizeofSubArray(( short* )parameterArray->dimensions, parameterArray->dimensionCount ); + break; + } + else + { + //the array contains base types + isInArray = 1; + const char *arrayStart = structureEnd; + const char *arrayEnd = structureEnd; + + int dimensionCount = 0; + int arrayCellIndex = 0; + while ( *arrayStart == '[' && dimensionCount < parameterArray->dimensionCount ) + { + arrayEnd = strchr( arrayStart + 1, ']' ); + int length = ( int )( arrayEnd - arrayStart - 1 ); + char indexString[16]; + strncpy( indexString, arrayStart + 1, length ); + indexString[length] = '\0'; + int index = atoi( indexString ); + int rowSize = parameterArray->dimensions[dimensionCount]; + if ( index >= rowSize ) + { + //index out of range: not found + return NULL; + } + arrayCellIndex += index * rglGetSizeofSubArray(( short* )parameterArray->dimensions + dimensionCount, parameterArray->dimensionCount - dimensionCount - 1 ); + + arrayStart = arrayEnd + 1; + dimensionCount++; + } + structureEnd = arrayStart; + if ( *structureEnd == '\0' ) + done = 1; + + if ( done ) + { + //found the item in the array + ( *arrayIndex ) = arrayCellIndex; + itemIndex = ( int )( currentEntry - program->parametersEntries ); + } + //else... don't know what to do, it's a array of structure not unrolled + } + } + break; + case CGP_STRUCTURE: + if ( done ) + { + //the user is getting back a strut... not sure that all the checks are in place for such a return value + itemIndex = ( int )( currentEntry - program->parametersEntries ); + } + else + { + const CgParameterStructure *parameterStructure = rglGetParameterStructure( program, currentEntry ); + containerCount = parameterStructure->memberCount; + } + break; + default: + break; + } + } + if ( found ) + { + if ( !bWasUnrolled ) + currentEntry++; + } + else + break;//not found + } + + //have we found it ? + if ( itemIndex != -1 ) + return ( _CGparameter* )( program->runtimeParameters + itemIndex ); + else + return NULL; +} +// API functions ---------------------------------------- + +CG_API CGparameter cgCreateParameter( CGcontext ctx, CGtype type ) +{ + // This routine is currently (release 0.2.1) a nop. When it is changed to generate new parameters this will impact the + // debugger runtime because all cg routines that take parameters as inputs must be matched to their production. + // See the discussion of producer-consumer deficiencies in the design document for the debugger runtime (RGLPerfTool). + + // check context handle + if ( !CG_IS_CONTEXT( ctx ) ) + { + rglCgRaiseError( CG_INVALID_CONTEXT_HANDLE_ERROR ); + return ( CGparameter )NULL; + } + _CGcontext * ctxPtr = _cgGetContextPtr( ctx ); + _CGprogram * program = &ctxPtr->defaultProgram; + CgRuntimeParameter *param = rglCgCreateParameterInternal( program, NULL, type ); + return param ? param->id : NULL; +} + +CG_API CGparameter cgCreateParameterArray( CGcontext ctx, CGtype type, int length ) +{ + // check context handle + if ( !CG_IS_CONTEXT( ctx ) ) + { + rglCgRaiseError( CG_INVALID_CONTEXT_HANDLE_ERROR ); + return ( CGparameter )NULL; + } + + // TODO ********** + return ( CGparameter )NULL; +} + +CG_API CGparameter cgCreateParameterMultiDimArray( CGcontext ctx, CGtype type, int dim, const int* lengths ) +{ + // check context handle + if ( !CG_IS_CONTEXT( ctx ) ) + { + rglCgRaiseError( CG_INVALID_CONTEXT_HANDLE_ERROR ); + return ( CGparameter )NULL; + } + + // TODO ********** + return ( CGparameter )NULL; +} + + +CG_API void cgDestroyParameter( CGparameter param ) +{ + // check parameter handle + if ( !CG_IS_PARAMETER( param ) ) + { + rglCgRaiseError( CG_INVALID_PARAM_HANDLE_ERROR ); + return; + } + + CgRuntimeParameter *rtParam = ( CgRuntimeParameter* )rglCgGLTestParameter( param ); + + // check that the param was created via cgCreateParameter + if ( !is_created_param( rtParam ) ) + { + rglCgRaiseError( CG_PARAMETER_IS_NOT_SHARED_ERROR ); + return; + } + + // check to see if parameter is not a source before deletion + bool isConnectionParent = false; + struct _CGprogram* programIter = rtParam->program->parentContext->programList; + while ( programIter != NULL ) + { + // search the program's connection table to find if this is a parent param to anybody + std::vector::iterator paramConnectionTableIter = programIter->connectionTable.begin(); + while ( paramConnectionTableIter != programIter->connectionTable.end() ) + { + if ( paramConnectionTableIter->parent == rtParam ) + { + isConnectionParent = true; + break; + } + paramConnectionTableIter++; + } + programIter = programIter->next; + } + if ( isConnectionParent ) + { + rglCgRaiseError( CG_CANNOT_DESTROY_PARAMETER_ERROR ); + return; + } + + // this call will call a hook function to clean up the fx if needed + rglCgDestroyContextParam( rtParam ); + +} + +CG_API void cgConnectParameter( CGparameter from, CGparameter to ) +{ + // check parameter handles + if ( !CG_IS_PARAMETER( from ) || !CG_IS_PARAMETER( to ) ) + { + rglCgRaiseError( CG_INVALID_PARAM_HANDLE_ERROR ); + return; + } + + // check and get parameter handles + CgRuntimeParameter *rtParamFrom = ( CgRuntimeParameter* )rglCgGLTestParameter( from ); + CgRuntimeParameter *rtParamTo = ( CgRuntimeParameter* )rglCgGLTestParameter( to ); + + // check that the param was created via cgCreateParameter + if ( !is_created_param( rtParamFrom ) ) + { + rglCgRaiseError( CG_PARAMETER_IS_NOT_SHARED_ERROR ); + return; + } + + if ( connection_creates_cycle( rtParamFrom, rtParamTo ) ) + { + rglCgRaiseError( CG_BIND_CREATES_CYCLE_ERROR ); + return; + } + + // type index is actually the offset into the block of memory following the entries + CGtype typeFrom = rglGetParameterCGtype( rtParamFrom->program, rtParamFrom->parameterEntry ); + CGtype typeTo = rglGetParameterCGtype( rtParamTo->program, rtParamTo->parameterEntry ); + if ( typeFrom != typeTo ) + { + // simple for now. + rglCgRaiseError( CG_PARAMETERS_DO_NOT_MATCH_ERROR ); + return; + } + + // (for array types) check that types match + // rglCgRaiseError(CG_ARRAY_TYPES_DO_NOT_MATCH_ERROR); + + // (for array types) check that all dimensions match + // rglCgRaiseError(CG_ARRAY_DIMENSIONS_DO_NOT_MATCH_ERROR); + + // we will need the top param to all for quick pull from arbitrarily deep hierarchies + // it gets updated if top gets disconnected from parent + // all the checks will have already happened when the initial connection was made + CgRuntimeParameter *rtParamTop = rtParamFrom; + // search parent connections in parent program and walk up to top + std::vector::iterator paramConnectionTableIter = rtParamTop->program->connectionTable.begin(); + while ( paramConnectionTableIter != rtParamTop->program->connectionTable.end() ) + { + // if this parameter is the child in a table, return its parent + if ( paramConnectionTableIter->child == rtParamTop ) + { + rtParamTop = paramConnectionTableIter->parent; + paramConnectionTableIter = rtParamTop->program->connectionTable.begin(); + } + else + { + paramConnectionTableIter++; + } + } + + // add new entry to the destination param's program's connection table + CgParameterConnection newConnection; + newConnection.child = rtParamTo; + newConnection.parent = rtParamFrom; + newConnection.top = rtParamTop; + newConnection.childOnBindSetter = _cgRaiseInvalidParamIndex; + switch ( typeTo ) + { + case CG_FLOAT: + case CG_FLOAT1: case CG_FLOAT2: case CG_FLOAT3: case CG_FLOAT4: + newConnection.childOnBindSetter = rtParamTo->setterIndex; + break; + case CG_FLOAT1x1: case CG_FLOAT1x2: case CG_FLOAT1x3: case CG_FLOAT1x4: + case CG_FLOAT2x1: case CG_FLOAT2x2: case CG_FLOAT2x3: case CG_FLOAT2x4: + case CG_FLOAT3x1: case CG_FLOAT3x2: case CG_FLOAT3x3: case CG_FLOAT3x4: + case CG_FLOAT4x1: case CG_FLOAT4x2: case CG_FLOAT4x3: case CG_FLOAT4x4: + newConnection.childOnBindSetter = rtParamTo->setterrIndex; + break; + case CG_SAMPLER1D: case CG_SAMPLER2D: case CG_SAMPLER3D: case CG_SAMPLERRECT: case CG_SAMPLERCUBE: + newConnection.childOnBindSetter = rtParamTo->samplerSetter; + break; + case CGP_SCF_BOOL: + break; + default: + break; + } + + rtParamTo->program->connectionTable.push_back( newConnection ); +} + +CG_API void cgDisconnectParameter( CGparameter param ) +{ + // check parameter handle + if ( !CG_IS_PARAMETER( param ) ) + { + rglCgRaiseError( CG_INVALID_PARAM_HANDLE_ERROR ); + return; + } + + // check and get parameter handles + CgRuntimeParameter *rtParamTo = ( CgRuntimeParameter* )rglCgGLTestParameter( param ); + + // check parameter handles + if ( !CG_IS_PARAMETER( rtParamTo ) ) + { + rglCgRaiseError( CG_INVALID_PARAM_HANDLE_ERROR ); + return; + } + + // search the program's connection table to find the connection info for this parameter + // each parameter only ever has one parent + std::vector::iterator paramConnectionTableIter = rtParamTo->program->connectionTable.begin(); + while ( paramConnectionTableIter != rtParamTo->program->connectionTable.end() ) + { + if ( paramConnectionTableIter->child == rtParamTo ) + break; + paramConnectionTableIter++; + } + + // if the parameter is not found in the connection table, it was never connected in the first place + if ( paramConnectionTableIter == rtParamTo->program->connectionTable.end() ) + { + rglCgRaiseError( CG_INVALID_PARAM_HANDLE_ERROR ); + return; + } + + // parameter was found to be connected, delete its entry from the table to disconnect + rtParamTo->program->connectionTable.erase( paramConnectionTableIter ); + + // check to see if parameter is a parent to for anyone in an arbitrarily deep hierarchy + // if it is, we must update all the children's top pointers to point to this param + struct _CGprogram* programIter = rtParamTo->program->parentContext->programList; + while ( programIter != NULL ) + { + // search the connection table of all the programs in this context to find if this is a parent param to anybody + paramConnectionTableIter = programIter->connectionTable.begin(); + while ( paramConnectionTableIter != programIter->connectionTable.end() ) + { + if ( paramConnectionTableIter->parent == rtParamTo ) + { + // this is the case where rt was the parent, and now must be the top because + // it was just disconnected from its own parent + paramConnectionTableIter->top = rtParamTo; + } + paramConnectionTableIter++; + } + programIter = programIter->next; + } +} + +CG_API CGparameter cgGetConnectedParameter( CGparameter param ) +{ + // check parameter handle + if ( !CG_IS_PARAMETER( param ) ) + { + rglCgRaiseError( CG_INVALID_PARAM_HANDLE_ERROR ); + return ( CGparameter )NULL; + } + + CgRuntimeParameter* ptr = ( CgRuntimeParameter* )rglCgGLTestParameter( param ); + std::vector::iterator paramConnectionTableIter = ptr->program->connectionTable.begin(); + while ( paramConnectionTableIter != ptr->program->connectionTable.end() ) + { + // if this parameter is the child in a table, return its parent + if ( paramConnectionTableIter->child == ptr ) + return paramConnectionTableIter->parent->id; + paramConnectionTableIter++; + } + + // not found in connection table, has no parent + return NULL; +} + +CG_API int cgGetNumConnectedToParameters( CGparameter param ) +{ + // check parameter handle + if ( !CG_IS_PARAMETER( param ) ) + { + rglCgRaiseError( CG_INVALID_PARAM_HANDLE_ERROR ); + return 0; + } + + int ret = 0; + CgRuntimeParameter *ptr = ( CgRuntimeParameter* )rglCgGLTestParameter( param ); + + _CGprogram* prog = ptr->program; + _CGcontext* context = prog->parentContext; + + // must iterate over all the programs in this context to see which of them + // have parameters which are connected to this parent + _CGprogram* programIter = context->programList; + while ( programIter != NULL ) + { + std::vector::iterator paramConnectionTableIter = programIter->connectionTable.begin(); + while ( paramConnectionTableIter != programIter->connectionTable.end() ) + { + // if this connection uses the param ptr as the parent, increment the count + if ( paramConnectionTableIter->parent == ptr ) + { + ret++; + } + paramConnectionTableIter++; + } + + programIter = programIter->next; + } + + return ret; +} + +CG_API CGparameter cgGetConnectedToParameter( CGparameter param, int index ) +{ + // check parameter handle + if ( !CG_IS_PARAMETER( param ) ) + { + rglCgRaiseError( CG_INVALID_PARAM_HANDLE_ERROR ); + return ( CGparameter )NULL; + } + + if ( index < 0 ) + { + rglCgRaiseError( CG_OUT_OF_ARRAY_BOUNDS_ERROR ); + return ( CGparameter )NULL; + } + + + int ret = 0; + CgRuntimeParameter *ptr = ( CgRuntimeParameter* )rglCgGLTestParameter( param ); + + _CGprogram* prog = ptr->program; + _CGcontext* context = prog->parentContext; + + // must iterate over all the programs in this context to see which of them + // have parameters which are connected to this parent + _CGprogram* programIter = context->programList; + while ( programIter != NULL ) + { + std::vector::iterator paramConnectionTableIter = programIter->connectionTable.begin(); + while ( paramConnectionTableIter != programIter->connectionTable.end() ) + { + // if this is the n'th child, where n == index, return its id + if ( paramConnectionTableIter->parent == ptr ) + { + if ( ret == index ) + { + return paramConnectionTableIter->child->id; + } + ret++; + } + paramConnectionTableIter++; + } + + programIter = programIter->next; + } + + // else the index is greater than the number of children of this parameter + rglCgRaiseError( CG_OUT_OF_ARRAY_BOUNDS_ERROR ); + + return ( CGparameter )NULL; +} + + +CG_API CGparameter cgGetNamedParameter( CGprogram prog, const char* name ) +{ + // check program handle + if ( !CG_IS_PROGRAM( prog ) ) + { + rglCgRaiseError( CG_INVALID_PROGRAM_HANDLE_ERROR ); + return ( CGparameter )NULL; + } + + _CGprogram* progPtr = _cgGetProgPtr( prog ); + // 0 means don't care + int arrayIndex = -1; + CgRuntimeParameter *param = ( CgRuntimeParameter * )_cgGetNamedParameter( progPtr, name, ( CGenum )0, &arrayIndex ); + if ( param ) + { + int ret = ( int )param->id; + if ( arrayIndex != -1 ) + ret |= ( arrayIndex << CG_PARAMETERSIZE ); + return ( CGparameter )ret; + } + else + return ( CGparameter )NULL; +} + +CG_API CGparameter cgGetNamedProgramParameter( CGprogram prog, CGenum name_space, const char* name ) +{ + // Same as cgGetNamedParameter, but restricts search to a specific namespace + // i.e. only return parameters of this CGprogram that are global. + // + // Valid namespaces are CG_GLOBAL and CG_PROGRAM, + + // check program handle + if ( !CG_IS_PROGRAM( prog ) ) + { + rglCgRaiseError( CG_INVALID_PROGRAM_HANDLE_ERROR ); + return ( CGparameter )NULL; + } + + // check namespace + switch ( name_space ) + { + case CG_GLOBAL : + break; + case CG_PROGRAM : + break; + default : + // ********* NOTE: docs say nothing about this check. + return NULL; + break; + } + _CGprogram* progPtr = _cgGetProgPtr( prog ); + int arrayIndex = -1; + CgRuntimeParameter *param = ( CgRuntimeParameter * )_cgGetNamedParameter( progPtr, name, name_space, &arrayIndex ); + if ( param ) + { + int ret = ( int )param->id; + if ( arrayIndex != -1 ) + ret |= ( arrayIndex << CG_PARAMETERSIZE ); + return ( CGparameter )ret; + } + else + return ( CGparameter )NULL; +} + +CG_API CGparameter cgGetFirstParameter( CGprogram prog, CGenum name_space ) +{ + // check program handle + if ( !CG_IS_PROGRAM( prog ) ) + { + rglCgRaiseError( CG_INVALID_PROGRAM_HANDLE_ERROR ); + return ( CGparameter )NULL; + } + + _CGprogram* progPtr = _cgGetProgPtr( prog ); + + CgRuntimeParameter *rtParameter = ( CgRuntimeParameter* )progPtr->runtimeParameters; + + // find the first param of the requested namespace + for ( int i = 0; i < progPtr->rtParametersCount; ++i ) + { + // check parameter handle + bool isGlobal = ( rtParameter->parameterEntry->flags & CGPF_GLOBAL ) == CGPF_GLOBAL; + if ( isGlobal && name_space == CG_GLOBAL ) + { + return ( CGparameter )rtParameter->id; + } + if ( !isGlobal && name_space == CG_PROGRAM ) + { + return ( CGparameter )rtParameter->id; + } + rtParameter++; + } + return ( CGparameter )NULL; +} + +//this function returns the parent array if the parameter passed is member of an array as well as the position in the array +//returns null other wise +static CgRuntimeParameter *rglGetArrayItemParent( CGparameter param, int *arrayIndex ) +{ + CgRuntimeParameter *rtParameter = ( CgRuntimeParameter* )rglCgGLTestParameter( param ); + if ( !rtParameter ) + return NULL; + + // the case of the array element is easy to solve: + if ( rtParameter > rtParameter->program->runtimeParameters ) + { + CgRuntimeParameter *previousParameter = rtParameter - 1; + if ( previousParameter->parameterEntry->flags & CGP_ARRAY ) + { + if ( previousParameter->parameterEntry->flags & CGP_UNROLLED ) + { + //that's easy, we are on the first item of the array + //the other positions will be discovered by the main loop later + if ( arrayIndex ) + *arrayIndex = 0; + return previousParameter; + } + else + { + //we have an array item + if ( arrayIndex ) + *arrayIndex = CG_GETINDEX( param ); + return previousParameter; + } + } + } + + //we are in the case where we don't have the first item of an unrolled array and where we don't have an item of a compact array + //the algorithm it to walk back the parameter list until we found the parent. + //if the parent is a structure or if there is no parent, returns NULL, else return the parent and the index, + + //get the parent of the current as well as its location + const CgParameterEntry *paramEntry = rtParameter->parameterEntry; + const CgParameterEntry *firstEntry = rtParameter->program->parametersEntries; + + //we have already treated the current entry at that point, the loop starts on the previous one, the distance is 1 + int distance = 1; + paramEntry--; + + *arrayIndex = 0; + bool haveResult = false; + while ( paramEntry >= firstEntry && !haveResult ) + { + switch ( paramEntry->flags & CGP_TYPE_MASK ) + { + case CGP_ARRAY: + //we found it + haveResult = true; + break; + case CGP_STRUCTURE: + { + const CgParameterStructure *parameterStructure = rglGetParameterStructure( rtParameter->program, paramEntry ); + if ( distance >= parameterStructure->memberCount ) + { + //the parameter is not in this structure, so I need to remove from the distance all the structure item + distance -= parameterStructure->memberCount; + //I need to patch the array Index, we have counted some items which were not in the array + //this struct should count just for one + //so basically it means we are in an array of struct if this struct is one item. + //if we only have homogeneous array, we can speed up that function, I don't do it, + //in case we extend the behaviour in the future + ( *arrayIndex ) -= parameterStructure->memberCount; + //increment the arrayIndex + ( *arrayIndex )++; + } + else + { + //so we are in the structure, not in an array + ( *arrayIndex ) = -1; + return NULL; + } + break; + } + case CGP_INTRINSIC: + //increment the arrayIndex + ( *arrayIndex )++; + break; + } + distance++; + paramEntry--; + } + + if ( haveResult ) + { + size_t offset = ( rtParameter->parameterEntry - paramEntry ); + CgRuntimeParameter *parentParameter = rtParameter - offset; + return parentParameter; + } + else + { + ( *arrayIndex ) = -1; + return NULL; + } +} + +CG_API CGparameter cgGetNextParameter( CGparameter param ) +{ + //check parameter handle + CgRuntimeParameter *rtParameter = ( CgRuntimeParameter* )rglCgGLTestParameter( param ); + if ( !rtParameter ) + return ( CGparameter )NULL; + + // runtime created parameters are treated separately because they are in a different namespace + // as such, you never need to traverse from a program param to a runtime param, or visa-versa + if ( rtParameter->parameterEntry->flags & CGP_RTCREATED ) + { + // we have a runtime created parameter + std::vector::iterator rtCreatedIter = rtParameter->program->runtimeCreatedParameters.begin(); + while ( rtCreatedIter != rtParameter->program->runtimeCreatedParameters.end() ) + { + if ( *rtCreatedIter == rtParameter ) + { + rtCreatedIter++; + if ( rtCreatedIter == rtParameter->program->runtimeCreatedParameters.end() ) + { + break; + } + return ( *rtCreatedIter )->id; + } + rtCreatedIter++; + } + // no next parameter for this one + return ( CGparameter )NULL; + } + + // the case of the array element of a compact array is easy to solve + int arrayIndex = -1; + if ( rtParameter > rtParameter->program->runtimeParameters ) + { + CgRuntimeParameter *previousParameter = rtParameter - 1; + if (( previousParameter->parameterEntry->flags & CGP_ARRAY ) && + !( previousParameter->parameterEntry->flags & CGP_UNROLLED ) ) + { + //we have an array item + arrayIndex = CG_GETINDEX( param ); + const CgParameterArray *parameterArray = rglGetParameterArray( previousParameter->program, previousParameter->parameterEntry ); + int arraySize = rglGetSizeofSubArray(( short* )parameterArray->dimensions, parameterArray->dimensionCount ); + arrayIndex++; + if ( arrayIndex < arraySize ) + { + int ret = ( int )rtParameter->id; + ret |= ( arrayIndex << CG_PARAMETERSIZE ); + return ( CGparameter )ret; + } + else + return ( CGparameter )NULL; + } + } + + //get the parent of the current as well as its location + const CgParameterEntry *paramEntry = rtParameter->parameterEntry; + const CgParameterEntry *firstEntry = rtParameter->program->parametersEntries; + + int distance = 1; + paramEntry--; + + bool bNextExists = false; + while ( paramEntry >= firstEntry && !bNextExists ) + { + switch ( paramEntry->flags & CGP_TYPE_MASK ) + { + case CGP_ARRAY: + distance--; // the array has one extra item, whether it's a structure or if it's an intrinsic type + //Ced: not it's not true, if it's unrolled there is no extra item + break; + case CGP_STRUCTURE: + { + const CgParameterStructure *parameterStructure = rglGetParameterStructure( rtParameter->program, paramEntry ); + //+1 because of the structure element, there's structure + if ( distance >= ( parameterStructure->memberCount + 1 ) ) + { + //the parameter is not in this structure, so I need to remove from the distance all the structure item + //so this structure will count for a distance of just one ( the distance is the level distance ) + distance -= parameterStructure->memberCount; + } + else + { + //We are going to exit here + //ok so we were in this structure, so check if we have more item in the structure after the current one + if ( distance < parameterStructure->memberCount ) + { + //we still have some items in the structure, take the next item + bNextExists = true; + break; + } + else + { + //no more items at this level return null + return ( CGparameter )NULL; + } + } + break; + } + case CGP_INTRINSIC: + break; + } + distance++; + paramEntry--; + } + //we have now elimated the case where we were in a struct and there were no more items, now if the item has a successor, + //this is what we are looking for + + //we have already treated the current entry at that point, the loop starts on the previous one, the distance is 1 + CGparameter nextParam = rglAdvanceParameter( rtParameter->id, 1 ); + + if ( nextParam ) + { + CgRuntimeParameter *nextParameter = ( CgRuntimeParameter* )rglCgGLTestParameter( nextParam ); + + //check that next param is still in the same namespace as param + bool isCurrentGlobal = ( rtParameter->parameterEntry->flags & CGPF_GLOBAL ) == CGPF_GLOBAL; + bool isNextGlobal = ( nextParameter->parameterEntry->flags & CGPF_GLOBAL ) == CGPF_GLOBAL; + if ( isNextGlobal != isCurrentGlobal ) + { + //the next item doesn't have the same global flag... since they are grouped, it means we have quitted the current struct + return ( CGparameter )NULL; + } + else + return nextParam; + } + else + { + //case where we were at the root and there is no more items + return ( CGparameter )NULL; + } +} + +CG_API CGparameter cgGetFirstStructParameter( CGparameter param ) +{ + //check parameter handle + CgRuntimeParameter *rtParameter = ( CgRuntimeParameter* )rglCgGLTestParameter( param ); + if ( !rtParameter ) + return ( CGparameter )NULL; + + const CgParameterEntry *parameterEntry = rtParameter->parameterEntry; + if (( parameterEntry->flags & CGP_STRUCTURE ) != CGP_STRUCTURE ) + { + // failure, there was no child. + rglCgRaiseError( CG_INVALID_PARAM_HANDLE_ERROR ); + return ( CGparameter )NULL; + } + + const CgParameterStructure *parameterStructure = rglGetParameterStructure( rtParameter->program, parameterEntry ); + if ( parameterStructure->memberCount > 0 ) //is is needed ? + { + CgRuntimeParameter *firstStructureItem = rtParameter + 1; + return firstStructureItem->id; + } + else + return ( CGparameter )NULL; //we have a struct with 0 items ? +} + +CG_API CGparameter cgGetNamedStructParameter( CGparameter param, const char* name ) +{ + // check parameter handle + CgRuntimeParameter *rtParameter = ( CgRuntimeParameter* )rglCgGLTestParameter( param ); + if ( !rtParameter ) + return ( CGparameter )NULL; + + // check input string + if ( NULL == name ) + { + rglCgRaiseError( CG_INVALID_PARAMETER_ERROR ); + return ( CGparameter )NULL; + } + + if ( !( rtParameter->parameterEntry->flags & CGP_STRUCTURE ) ) + { + rglCgRaiseError( CG_INVALID_PARAMETER_ERROR ); + return ( CGparameter )NULL; + } + + + const CgParameterStructure *parameterStructure = rglGetParameterStructure( rtParameter->program, rtParameter->parameterEntry ); + + int arrayIndex = -1; + CgRuntimeParameter *structParam = ( CgRuntimeParameter * )_cgGetNamedParameter( rtParameter->program, name, ( CGenum )0, &arrayIndex, rtParameter->parameterEntry + 1, parameterStructure->memberCount ); + if ( structParam ) + { + int ret = ( int )structParam->id; + if ( arrayIndex != -1 ) + ret |= ( arrayIndex << CG_PARAMETERSIZE ); + return ( CGparameter )ret; + } + else + return ( CGparameter )NULL; +} + +CG_API CGparameter cgGetFirstDependentParameter( CGparameter param ) +{ + // check parameter handle + if ( !CG_IS_PARAMETER( param ) ) + { + rglCgRaiseError( CG_INVALID_PARAM_HANDLE_ERROR ); + return ( CGparameter )NULL; + } + return ( CGparameter )NULL; +} + +CG_API CGparameter cgGetArrayParameter( CGparameter param, int arrayIndex ) +{ + // check parameter handle + CgRuntimeParameter *rtParameter = ( CgRuntimeParameter* )_cgGLTestArrayParameter( param, arrayIndex, 1 ); + if ( !rtParameter ) + return ( CGparameter )NULL; + + CGparameter arrayFirstItemID; + if ( rtParameter->parameterEntry->flags & CGP_UNROLLED ) + { + //move over the first item of the array and starts from here + rtParameter++; + arrayFirstItemID = rtParameter->id; + } + else + { + // SPECIAL CASE FOR ARRAY_OF_SAMPLERS + if ( RGL_UNLIKELY( !( rtParameter->parameterEntry->flags & ( CGP_STRUCTURE | CGP_ARRAY ) ) ) && + isSampler( rglGetParameterCGtype( rtParameter->program, rtParameter->parameterEntry ) ) ) + { + for ( int i = 0; i < arrayIndex; ++i ) + { + rtParameter++; + } + return rtParameter->id; + } + // END SPECIAL CASE FOR ARRAY_OF_SAMPLERS + + //move to the type item + rtParameter++; + //and create the ID for the item 0 + //I know this is stupid, and that this really the same as the previous case, but that's to make the code understandable + arrayFirstItemID = ( CGparameter )((( unsigned int )rtParameter->id ) | ( 0 << CG_PARAMETERSIZE ) ); + } + CGparameter arrayItemID = rglAdvanceParameter( arrayFirstItemID, arrayIndex ); + return arrayItemID; +} + +CG_API int cgGetArrayDimension( CGparameter param ) +{ + // return how many dimensions this array has. + // TODO: API should be an unsigned int. + + // check parameter handle + CgRuntimeParameter *rtParameter = ( CgRuntimeParameter* )rglCgGLTestParameter( param ); + if ( !rtParameter ) + return -1; + + // ***** NOT IN CG DOCUMENTATION, but should be **** + + // this is a rarely queried value, so we do not store it. + // instead we calculate it every time it is requested. + // recurse down the array tree until the parameter type is not CG_ARRAY + // counting the depth as we go. + + const CgParameterEntry *parameterEntry = rtParameter->parameterEntry; + if (( parameterEntry->flags & CGP_ARRAY ) == 0 ) + { + // ***** NOT IN CG DOCUMENTATION, but should be **** + rglCgRaiseError( CG_ARRAY_PARAM_ERROR ); + return 0; + } + else + { + const CgParameterArray *parameterArray = rglGetParameterArray( rtParameter->program, parameterEntry ); + return ( int )parameterArray->dimensionCount; + } + return 0; +} + +CG_API CGtype cgGetArrayType( CGparameter param ) +{ + // return the type of the leaf node of this CG_ARRAY type + + // check parameter handle + CgRuntimeParameter *rtParameter = ( CgRuntimeParameter* )rglCgGLTestParameter( param ); + if ( !rtParameter ) + return CG_UNKNOWN_TYPE; + + // ***** NOT IN CG DOCUMENTATION, but should be **** + + // this is a rarely queried value, so we do not store it. + // instead we calculate it every time it is requested. + // recurse down the array tree until the parameter type is not CG_ARRAY + // and return the first child that is not a CG_ARRAY type. + + const CgParameterEntry *parameterEntry = rtParameter->parameterEntry; + if (( parameterEntry->flags & CGP_ARRAY ) == 0 ) + { + // ***** NOT IN CG DOCUMENTATION, but should be **** + rglCgRaiseError( CG_ARRAY_PARAM_ERROR ); + return CG_UNKNOWN_TYPE; + } + else + { + //get the parameter type inside the array + rtParameter++; + parameterEntry = rtParameter->parameterEntry; + if ( parameterEntry->flags & CGP_STRUCTURE ) + { + return CG_STRUCT; + } + else + { + // when we are able to support runtime created arrays of params we must handle that here + const CgParameterResource *parameterResource = rglGetParameterResource( rtParameter->program, parameterEntry ); + return ( CGtype )parameterResource->type; + } + } + return CG_UNKNOWN_TYPE; +} + +CG_API int cgGetArraySize( CGparameter param, int dimension ) +{ + // check parameter handle + CgRuntimeParameter *rtParameter = ( CgRuntimeParameter* )rglCgGLTestParameter( param ); + if ( !rtParameter ) + return -1; + + // this is another rarely queried value (see also cgGetArrayDimension), so we + // do not store it. Instead we calculate it every time it is requested. + // recurse down the array tree decrementing "dimension" until either it reached zero + // and we return the arraySize or we fail to find a child in which case the + // dimension was invalid. + + const CgParameterEntry *parameterEntry = rtParameter->parameterEntry; + if (( parameterEntry->flags & CGP_ARRAY ) == 0 ) + { + // ***** NOT IN CG DOCUMENTATION, but should be **** + rglCgRaiseError( CG_ARRAY_PARAM_ERROR ); + return CG_UNKNOWN_TYPE; + } + else + { + const CgParameterArray *parameterArray = rglGetParameterArray( rtParameter->program, parameterEntry ); + if ( dimension < 0 || dimension >= parameterArray->dimensionCount ) + { + rglCgRaiseError( CG_INVALID_DIMENSION_ERROR ); + return -1; + } + else + { + return ( int )parameterArray->dimensions[dimension]; + } + } + return -1; +} + +CG_API void cgSetArraySize( CGparameter param, int size ) +{ + // check parameter handle + if ( !CG_IS_PARAMETER( param ) ) + { + rglCgRaiseError( CG_INVALID_PARAM_HANDLE_ERROR ); + } +} + +CG_API void cgSetMultiDimArraySize( CGparameter param, const int* sizes ) +{ + // check parameter handle + if ( !CG_IS_PARAMETER( param ) ) + { + rglCgRaiseError( CG_INVALID_PARAM_HANDLE_ERROR ); + } +} + +CG_API CGprogram cgGetParameterProgram( CGparameter param ) +{ + // check parameter handle + CgRuntimeParameter *rtParameter = ( CgRuntimeParameter* )rglCgGLTestParameter( param ); + if ( !rtParameter ) + { + return ( CGprogram )NULL; + } + else if ( RGL_UNLIKELY( rtParameter->parameterEntry->flags & CGP_RTCREATED ) ) + { + // I don't think we want to expose the fact that we internally store runtime created effect and context parameters in a program + return ( CGprogram )NULL; + } + else + { + return rtParameter->program->id; + } + return ( CGprogram )NULL; +} + +CG_API CGcontext cgGetParameterContext( CGparameter param ) +{ + // check parameter handle + if ( !CG_IS_PARAMETER( param ) ) + { + rglCgRaiseError( CG_INVALID_PARAM_HANDLE_ERROR ); + return ( CGcontext )NULL; + } + + CGcontext result = cgGetProgramContext( cgGetParameterProgram( param ) ); + + return result; +} + +CG_API CGbool cgIsParameter( CGparameter param ) +{ + if ( RGL_LIKELY( CG_IS_PARAMETER( param ) ) ) + { + return CG_TRUE; + } + return CG_FALSE; +} + +CG_API CGtype cgGetParameterType( CGparameter param ) +{ + CgRuntimeParameter *rtParameter = ( CgRuntimeParameter* )rglCgGLTestParameter( param ); + if ( !rtParameter ) + return CG_UNKNOWN_TYPE; + else + { + if ( rtParameter->parameterEntry->flags & CGP_ARRAY ) + return CG_ARRAY; + else if ( rtParameter->parameterEntry->flags & CGP_STRUCTURE ) + return CG_STRUCT; + else + { + return rglGetParameterCGtype( rtParameter->program, rtParameter->parameterEntry ); + } + } +} + +CG_API CGtype cgGetParameterNamedType( CGparameter param ) +{ + return cgGetParameterType( param ); +} + +CG_API const char* cgGetParameterSemantic( CGparameter param ) +{ + // check parameter handle + CgRuntimeParameter *rtParameter = ( CgRuntimeParameter* )rglCgGLTestParameter( param ); + if ( !rtParameter ) + return NULL; + else + { + const CgParameterEntry *parameterEntry = rtParameter->parameterEntry; + + unsigned short type = parameterEntry->flags & CGP_TYPE_MASK; + if ( type == CGP_STRUCTURE || CGP_STRUCTURE == CGP_ARRAY ) + { + rglCgRaiseError( CG_INVALID_PARAMETER_ERROR ); + return NULL; + } + + // this table holds semantics that were created at runtime for either program or context or effect scope parameters + // this search happens first because you can overwrite what was set in the binary at runtime + // and we won't remove the entry from the binary representation of semantics + // but we will add an entry into this table which should be returned here. + std::vector::iterator semanticIter = rtParameter->program->parameterSemantics.begin(); + while ( semanticIter != rtParameter->program->parameterSemantics.end() ) + { + if ( semanticIter->param == rtParameter ) + { + return &semanticIter->semantic[0]; + } + semanticIter++; + } + + size_t entryIndex = ( parameterEntry - rtParameter->program->parametersEntries ); + + //look for the parameter semantic in the semantic table for semantics set in the compiled source + int count = rtParameter->program->semanticCount; + int i; + for ( i = 0;i < count;i++ ) + { + const CgParameterSemantic *semantic = rtParameter->program->semanticIndices + i; + if ( semantic->entryIndex == ( unsigned short )entryIndex ) + { + //found + return rtParameter->program->stringTable + semantic->semanticOffset; + } + } + + //not found, we don't have the semantic for this parameter, returns empty strings + return ""; + } +} + +CG_API CGresource cgGetParameterBaseResource( CGparameter param ) +{ + // check parameter handle + CgRuntimeParameter *rtParameter = ( CgRuntimeParameter* )rglCgGLTestParameter( param ); + if ( !rtParameter ) + return CG_UNDEFINED; + else + { + const CgParameterEntry *parameterEntry = rtParameter->parameterEntry; + + unsigned short type = parameterEntry->flags & CGP_TYPE_MASK; + if ( type == CGP_STRUCTURE || type == CGP_ARRAY ) + { + rglCgRaiseError( CG_INVALID_PARAMETER_ERROR ); + return CG_UNDEFINED; + } + + CGresource resource = cgGetParameterResource( param ); + return rglGetBaseResource( resource ); + } +} + +CG_API CGparameter cgGetFirstLeafParameter( CGprogram prog, CGenum name_space ) +{ + // check program handle + if ( !CG_IS_PROGRAM( prog ) ) + { + rglCgRaiseError( CG_INVALID_PROGRAM_HANDLE_ERROR ); + return ( CGparameter )NULL; + } + + _CGprogram* progPtr = _cgGetProgPtr( prog ); + CgRuntimeParameter *rtParameter = ( CgRuntimeParameter* )progPtr->runtimeParameters; + + //find the first leaf param of the requested namespace + for ( int i = 0; i < progPtr->rtParametersCount; ++i ) + { + // check parameter handle + bool isGlobal = ( rtParameter->parameterEntry->flags & CGPF_GLOBAL ) == CGPF_GLOBAL; + if (( isGlobal && name_space == CG_GLOBAL ) || ( !isGlobal && name_space == CG_PROGRAM ) ) + { + int type = ( rtParameter->parameterEntry->flags & CGP_TYPE_MASK ); + if ( type == CGP_INTRINSIC ) + return ( CGparameter )rtParameter->id; + else if ( type == CGP_ARRAY ) + { + if ( !( rtParameter->parameterEntry->flags & CGP_UNROLLED ) ) + { + //can we have a parameter of size 0 ? + const CgParameterArray *parameterArray = rglGetParameterArray( rtParameter->program, rtParameter->parameterEntry ); + int arraySize = ( int )rglGetSizeofSubArray( parameterArray->dimensions, parameterArray->dimensionCount ); + rtParameter++; //we move on the type parameter + if ( arraySize ) + { + //sending back ARRAY ITEM 0 here, should really use a macro to create the CGparameter handle + return rtParameter->id; + } + //else we just continue + } + //else unrolled, just continue + } + //else if (type == CGP_STRUCTURE) //just continue + } + rtParameter++; + } + return ( CGparameter )NULL; +} + +CG_API CGparameter cgGetNextLeafParameter( CGparameter param ) +{ + // check parameter handle + CgRuntimeParameter *rtParameter = ( CgRuntimeParameter* )rglCgGLTestParameter( param ); + if ( !rtParameter ) + return ( CGparameter )NULL; + + //this parameter should be an intrinsic + if (( rtParameter->parameterEntry->flags & CGP_TYPE_MASK ) != CGP_INTRINSIC ) + { + rglCgRaiseError( CG_INVALID_PARAMETER_ERROR ); + return ( CGparameter )NULL; + } + + // runtime created parameters are treated separately because they are in a different namespace + // as such, you never need to traverse from a program param to a runtime param, or visa-versa + // additionally, in the current implementation, we only support creation of leaf types. + if ( rtParameter->parameterEntry->flags & CGP_RTCREATED ) + { + // we have a runtime created parameter + std::vector::iterator rtCreatedIter = rtParameter->program->runtimeCreatedParameters.begin(); + while ( rtCreatedIter != rtParameter->program->runtimeCreatedParameters.end() ) + { + if ( *rtCreatedIter == rtParameter ) + { + rtCreatedIter++; + if ( rtCreatedIter == rtParameter->program->runtimeCreatedParameters.end() ) + { + break; + } + return ( *rtCreatedIter )->id; + } + rtCreatedIter++; + } + // no next parameter for this one + return ( CGparameter )NULL; + } + + // the case of the array element is easy to solve: + if ( rtParameter > rtParameter->program->runtimeParameters ) + { + CgRuntimeParameter *previousParameter = rtParameter - 1; + if (( previousParameter->parameterEntry->flags & CGP_ARRAY ) && !( previousParameter->parameterEntry->flags & CGP_UNROLLED ) ) + { + //we have an array item + int arrayIndex = CG_GETINDEX( param ); + arrayIndex++; + const CgParameterArray *parameterArray = rglGetParameterArray( previousParameter->program, previousParameter->parameterEntry ); + int arraySize = rglGetSizeofSubArray(( short* )parameterArray->dimensions, parameterArray->dimensionCount ); + if ( arrayIndex < arraySize ) + { + int ret = ( int )rtParameter->id; + ret |= ( arrayIndex << CG_PARAMETERSIZE ); + return ( CGparameter )ret; + } + //else + //we need to leave this array and continue the traversal + } + } + + bool isCurrentGlobal = ( rtParameter->parameterEntry->flags & CGPF_GLOBAL ) == CGPF_GLOBAL; + + const CgParameterEntry *endEntry = rtParameter->program->parametersEntries + rtParameter->program->rtParametersCount; + const CgParameterEntry *paramEntry = rtParameter->parameterEntry + 1; + while ( paramEntry < endEntry ) + { + size_t offset = ( paramEntry - rtParameter->parameterEntry ); + CgRuntimeParameter *nextParameter = rtParameter + offset; + bool isNextGlobal = ( nextParameter->parameterEntry->flags & CGPF_GLOBAL ) == CGPF_GLOBAL; + if ( isNextGlobal != isCurrentGlobal ) + { + paramEntry++; // let's not quit, but continue to look for a matching namespace + continue; + //return ( CGparameter )NULL; //the items are gathered by namespace, so if different namespace then we quit + } + switch ( paramEntry->flags & CGP_TYPE_MASK ) + { + case CGP_ARRAY: + { + if ( paramEntry->flags & CGP_UNROLLED ) + { + //we skip unrolled array + break; + } + else + { + //we need to go inside and send back the first array item + //check how many item do we have in the array + const CgParameterArray *parameterArray = rglGetParameterArray( rtParameter->program, paramEntry ); + int arraySize = ( int )rglGetSizeofSubArray( parameterArray->dimensions, parameterArray->dimensionCount ); + if ( arraySize ) + { + nextParameter++; //go on the array time + //sending back ARRAY ITEM 0 here, should really use a macro to create the CGparameter handle + return nextParameter->id; + } + else + { + //no item in the array skip the item time continue + nextParameter++; //go on the array time, will be skipped + } + } + break; + } + case CGP_STRUCTURE: + { + //we just skip structures + break; + } + case CGP_INTRINSIC: + //we are done we found an intrinsic + return nextParameter->id; + break; + } + paramEntry++; + } + return ( CGparameter )NULL; +} + +static bool rglPrependString( char *dst, const char *src, size_t size ) +{ + int len = strlen( src ); + int previousLen = strlen( dst ); + int spaceLeft = size - ( previousLen + 1 ); //+1 for white space + if ( spaceLeft < len ) + { + return false; + } + memmove( dst + len, dst, previousLen + 1 ); + strncpy( dst, src, len ); + return true; +} + +CG_API const char* cgGetParameterName( CGparameter param ) +{ + // check parameter handle + CgRuntimeParameter *rtParameter = ( CgRuntimeParameter* )rglCgGLTestParameter( param ); + if ( !rtParameter ) + return NULL; + + // runtime created parameters have their names stored in the entry differently than compile created params + if ( rtParameter->parameterEntry->flags & CGP_RTCREATED ) + { + return reinterpret_cast( rtParameter->parameterEntry->nameOffset ); + } + + char *currentParameterName = rtParameter->program->parentContext->currentParameterName; + currentParameterName[0] = '\0'; + size_t stringSize = sizeof( rtParameter->program->parentContext->currentParameterName ); + + //I walk down the parameterEntry list until I find the root + const CgParameterEntry *paramEntry = rtParameter->parameterEntry; + const CgParameterEntry *firstEntry = rtParameter->program->parametersEntries; + + //start by the current name + bool res = rglPrependString( currentParameterName, rtParameter->program->stringTable + paramEntry->nameOffset, stringSize ); + if ( !res ) + return NULL; + //are we starting from an array ? + if ( paramEntry > firstEntry ) + { + const CgParameterEntry *previousEntry = paramEntry - 1; + if (( previousEntry->flags & CGP_ARRAY ) && !( previousEntry->flags & CGP_UNROLLED ) ) + { + //ok we are in an non unrolled array + //I need to append the array index, I should use the dimensions , no time for now + int index = CG_GETINDEX( param ); + //should divide the index on the dimensions... later... + char buffer[256]; + sprintf( buffer, "[%i]", index ); + if ( strlen( currentParameterName ) + strlen( buffer ) + 1 < stringSize ) + strcat( currentParameterName, buffer ); + else + { + return NULL; + } + //prepend array name + res = rglPrependString( currentParameterName, rtParameter->program->stringTable + previousEntry->nameOffset, stringSize ); + if ( !res ) + return NULL; + paramEntry--; + } + } + + //we have already treated the current entry at that point, the loop starts on the previous one, the distance is 1 + int distance = 1; + paramEntry--; + + while ( paramEntry >= firstEntry ) + { + switch ( paramEntry->flags & CGP_TYPE_MASK ) + { + case CGP_ARRAY: + distance--; // the array has one extra item, whether it's a structure or if it's an intrinsic type + break; + case CGP_STRUCTURE: + { + const CgParameterStructure *parameterStructure = rglGetParameterStructure( rtParameter->program, paramEntry ); + if ( distance > parameterStructure->memberCount ) + { + //the parameter is not in this structure, so I need to remove from the distance all the structure item + distance -= parameterStructure->memberCount; + } + else + { + //the parameter is in this structure, prepend the name + res = rglPrependString( currentParameterName, ".", stringSize ); + if ( !res ) return NULL; + res = rglPrependString( currentParameterName, rtParameter->program->stringTable + paramEntry->nameOffset, stringSize ); + if ( !res ) return NULL; + distance = 0; + } + break; + } + case CGP_INTRINSIC: + break; + } + distance++; + paramEntry--; + } + return currentParameterName; + +} + +CG_API CGresource cgGetParameterResource( CGparameter param ) +{ + // check parameter handle + CgRuntimeParameter *rtParameter = ( CgRuntimeParameter* )rglCgGLTestParameter( param ); + if ( !rtParameter ) + { + return CG_UNDEFINED; + } + + const CgParameterEntry *parameterEntry = rtParameter->parameterEntry; + + if ( parameterEntry->flags & CGP_RTCREATED ) + { + // runtime created parameters do not have resources + rglCgRaiseError( CG_INVALID_PARAMETER_ERROR ); + return CG_UNDEFINED; + } + + unsigned short type = parameterEntry->flags & CGP_TYPE_MASK; + if ( type == CGP_STRUCTURE || type == CGP_ARRAY ) + { + rglCgRaiseError( CG_INVALID_PARAMETER_ERROR ); + return CG_UNDEFINED; + } + + // TODO ************* docs say something incoherent about returning + // CG_INVALID_VALUE if cgIsParameterReferenced() == CG_FALSE? + if ( !( parameterEntry->flags & CGPF_REFERENCED ) ) + { + return CG_UNDEFINED; + } + + int arrayIndex = -1; + if ( rtParameter > rtParameter->program->runtimeParameters ) + { + CgRuntimeParameter *previousParameter = rtParameter - 1; + if ( previousParameter->parameterEntry->flags & CGP_ARRAY ) + { + //we have an array item + arrayIndex = CG_GETINDEX( param ); + } + } + + unsigned long resourceIndex = 0; + CGresource resource = ( CGresource )0; + unsigned short numEmbeddedConstants = 0; + rglCgGetParameterResourceInfo( rtParameter, arrayIndex, &resource, &resourceIndex, &numEmbeddedConstants ); + + // this returns undefined for array items that are not allocated + if (arrayIndex >= 0 && resourceIndex == -1U && numEmbeddedConstants == 0) + return CG_UNDEFINED; + + return resource; +} + +CG_API unsigned long cgGetParameterResourceIndex( CGparameter param ) +{ + // check parameter handle + CgRuntimeParameter *rtParameter = ( CgRuntimeParameter* )rglCgGLTestParameter( param ); + if ( !rtParameter ) + { + return CG_UNDEFINED; + } + + const CgParameterEntry *parameterEntry = rtParameter->parameterEntry; + + if ( parameterEntry->flags & CGP_RTCREATED ) + { + // runtime created parameters do not have resources + rglCgRaiseError( CG_INVALID_PARAMETER_ERROR ); + return CG_UNDEFINED; + } + + unsigned short type = parameterEntry->flags & CGP_TYPE_MASK; + if ( type == CGP_STRUCTURE || CGP_STRUCTURE == CGP_ARRAY ) + { + rglCgRaiseError( CG_INVALID_PARAMETER_ERROR ); + return -1U; + } + + // TODO ************* docs say something incoherent about returning + // CG_INVALID_VALUE if cgIsParameterReferenced() == CG_FALSE? + if ( !( parameterEntry->flags & CGPF_REFERENCED ) ) + { + return -1U; + } + + int arrayIndex = -1; + if ( rtParameter > rtParameter->program->runtimeParameters ) + { + CgRuntimeParameter *previousParameter = rtParameter - 1; + if ( previousParameter->parameterEntry->flags & CGP_ARRAY ) + { + //we have an array item + arrayIndex = CG_GETINDEX( param ); + } + } + + unsigned long resourceIndex = 0; + CGresource resource = ( CGresource )0; + unsigned short numEmbeddedConstants; + rglCgGetParameterResourceInfo( rtParameter, arrayIndex, &resource, &resourceIndex, &numEmbeddedConstants ); + if ( resource == CG_B || resource == CG_C ) + return ( unsigned long )resourceIndex; + else + return ( unsigned long )( resource - rglGetBaseResource( resource ) ); + +} + +CG_API CGenum cgGetParameterVariability( CGparameter param ) +{ + // check parameter handle + CgRuntimeParameter *rtParameter = ( CgRuntimeParameter* )rglCgGLTestParameter( param ); + if ( !rtParameter ) + return ( CGenum )0; + else + { + unsigned int variability = rtParameter->parameterEntry->flags & CGPV_MASK; + if ( variability == CGPV_UNIFORM ) + return CG_UNIFORM; + else if ( variability == CGPV_VARYING ) + return CG_VARYING; + else if ( variability == CGPV_CONSTANT ) + return CG_CONSTANT; + else if ( variability == CGPV_MIXED ) + return CG_MIXED; + else + return ( CGenum )0; + } +} + +CG_API CGenum cgGetParameterDirection( CGparameter param ) +{ + // check parameter handle + CgRuntimeParameter *rtParameter = ( CgRuntimeParameter* )rglCgGLTestParameter( param ); + if ( !rtParameter ) + return CG_ERROR; + else + { + unsigned int direction = rtParameter->parameterEntry->flags & CGPD_MASK; + if ( direction == CGPD_IN ) + return CG_IN; + else if ( direction == CGPD_OUT ) + return CG_OUT; + else if ( direction == CGPD_INOUT ) + return CG_INOUT; + else + return CG_ERROR; + } +} + +CG_API CGbool cgIsParameterReferenced( CGparameter param ) +{ + // check parameter handle + CgRuntimeParameter *rtParameter = ( CgRuntimeParameter* )rglCgGLTestParameter( param ); + if ( !rtParameter ) + return CG_FALSE; + else + { + return (( rtParameter->parameterEntry->flags & CGPF_REFERENCED ) != 0 ); + } +} + +CG_API CGbool cgIsParameterUsed( CGparameter param, CGhandle handle ) +{ + // check parameter handle + CgRuntimeParameter *rtParameter = ( CgRuntimeParameter* )rglCgGLTestParameter( param ); + + // TODO: make a more accurate and general definition of "used", including runtime created parameters. + if ( !rtParameter ) + { + return CG_FALSE; + } + + if ( !CG_IS_PROGRAM( (CGprogram)handle ) ) + { + rglCgRaiseError( CG_INVALID_PROGRAM_HANDLE_ERROR ); + return CG_FALSE; + } + + // adding support for effect handles would require moving this to RGLFX or something that would break the abstraction of that library + _CGprogram* progPtr = _cgGetProgPtr( (CGprogram)handle ); + + if ( !progPtr ) + { + return CG_FALSE; + } + + if (rtParameter->program != progPtr) + { + return CG_FALSE; + } + + return (( rtParameter->parameterEntry->flags & CGPF_REFERENCED ) != 0 ); +} + +CG_API const double* cgGetParameterValues( CGparameter paramIn, CGenum value_type, int *nvalues ) +{ + // check parameter handle + CgRuntimeParameter *rtParameter = ( CgRuntimeParameter* )rglCgGLTestParameter( paramIn ); + if ( !rtParameter ) + return NULL; + + // check nvalues pointer + if ( NULL == nvalues ) + { + rglCgRaiseError( CG_INVALID_PARAMETER_ERROR ); + return NULL; + } + + // check if we are trying to get the current value of a uniform that is + // unreferenced and unbound (happens when compiler folds global constants), + // we can only return the default value in this case. + if ( value_type == CG_CURRENT ) + { + int var = ( rtParameter->parameterEntry->flags & CGPV_MASK ); + if ( var == CGPV_UNIFORM && + !( rtParameter->parameterEntry->flags & CGPF_REFERENCED ) && + !( rtParameter->parameterEntry->flags & CGP_RTCREATED ) && + !( rtParameter->parameterEntry->flags & CGP_ARRAY ) ) + { + const CgParameterResource* parameterResource = rglGetParameterResource( rtParameter->program, rtParameter->parameterEntry ); + if ( parameterResource ) + { + if ( parameterResource->resource == 0xffff ) + { + value_type = CG_DEFAULT; + } + } + } + + // this is the case for const parameters that never have a push buffer allocated + // because they can not be set since they are const in the shader, so the value + // will always be the defaults. + if ( rtParameter->pushBufferPointer == NULL ) + { + value_type = CG_DEFAULT; + } + } + + // as this function returns a pointer to an array of doubles we have + // to allocate space for this array, make sure it's never re-allocated for + // this parameter, plus make sure it is deleted when the CGcontext is + // destroyed. + // + // All in all a nasty API function. + + double values[16]; + *nvalues = 0; + _CGprogram *program = rtParameter->program; + + // check value type then copy the approriate values into the local values buffer + switch ( value_type ) + { + case CG_CONSTANT: + break; + + case CG_DEFAULT: + // return contents of default value field. + { + if ( rtParameter->parameterEntry->flags & CGP_RTCREATED ) + { + // runtime created parameters do not have default values + break; + } + // if there are defaults, they will only be in the platformParam + //do a slow linear search in the constants we have + int count = program->defaultValuesIndexCount; + for ( int i = 0;i < count;i++ ) + { + int index = ( int )program->defaultValuesIndices[i].entryIndex; + CgRuntimeParameter *tmp = program->runtimeParameters + index; + if ( tmp == rtParameter ) + { + //found + const CgParameterEntry *parameterEntry = rtParameter->parameterEntry; + if ( parameterEntry->flags & CGP_ARRAY ) + return NULL; + const float *itemDefaultValues = program->defaultValues + program->defaultValuesIndices[i].defaultValueIndex; + CGtype parameterResourceType = rglGetParameterCGtype( program, parameterEntry ); + unsigned int cols = rglGetTypeColCount( parameterResourceType ); + unsigned int rows = rglGetTypeRowCount( parameterResourceType ); + if ( rows == 0 ) + rows = 1; //flat types versus matrices + + // the defaults must be copied out for each row, from each successive child + for ( GLuint r = 0; r < rows; r++ ) + { + const float* src = itemDefaultValues + 4 * r;//right now default values always come by 4 + // copy the values into the local buffer, just the right number of values for the column + for ( GLuint floatIndex = 0; floatIndex < cols; ++floatIndex ) + values[floatIndex + r * cols] = src[floatIndex]; + } + *nvalues = rows * cols; + break; //loop to find the defaults of the parameter + } + } + break; + } + case CG_CURRENT: + // return contents of current value field. + // **** this is documented in cgSetParameter docs, but not the cgGetParameterValues docs. + { + if ( rtParameter->pushBufferPointer ) + { + const CgParameterEntry *parameterEntry = rtParameter->parameterEntry; + if ( parameterEntry->flags & CGP_ARRAY ) + return NULL; + + CGtype parameterResourceType = rglGetParameterCGtype( program, parameterEntry ); + + unsigned int cols = rglGetTypeColCount( parameterResourceType ); + unsigned int rows = rglGetTypeRowCount( parameterResourceType ); + if ( rows == 0 ) + rows = 1; //flat types versus matrices + + int floatcount = cols * rows; + // take the padding in the matrices into account + int colCount = 4; + int paddingSize = 0; + if ( cols ) + { + colCount = cols; + paddingSize = 4 - cols; + } + + bool isInArray = false; + unsigned int testParam = ((( unsigned int )paramIn ) & CG_PARAMETERMASK ); + // array parameter handle = ( base array handle + 1 ) + ((parameter index)<< 22) + if (( testParam != ( unsigned int )paramIn ) || // masking it like this will chop the index off the array + (( rtParameter > rtParameter->program->runtimeParameters ) && ( rtParameter - 1 )->parameterEntry->flags & CGP_ARRAY ) ) // this handles the case of the first array element at index 0 (and hopefully compact arrays i think) + { + isInArray = true; + } + + // if this parameter is connected as the child to a parent parameter, + // it is possible that the values will not have been pulled into the pushbuffer yet + // if the program that owns this parameter has not been bound since the parent was set. + // pull the values, just to be sure, even though this will pull values for + // every parameter in this program. it's a slow call anyway. + _pullConnectedParameterValues( rtParameter->program ); + + float *source; + + if ( isInArray ) + { + source = ( float* )( *(( unsigned int ** )rtParameter->pushBufferPointer + CG_GETINDEX( paramIn ) ) ); + } + else + { + source = ( float* )rtParameter->pushBufferPointer; + } + + for ( int i = 0; i < floatcount; ++i ) + { + values[i] = source[i + ( i / colCount ) * paddingSize]; + } + + *nvalues = floatcount; + } + break; + } + default: + rglCgRaiseError( CG_INVALID_ENUMERANT_ERROR ); + return NULL; + break; + } + + if ( *nvalues > 0 ) + { + double *parameterValues = rtParameter->program->parentContext->currentParameterValue; + for ( int i = 0; i < *nvalues; i++ ) + { + parameterValues[i] = values[i]; + } + return parameterValues; + } + return NULL; +} + +CG_API int cgGetParameterOrdinalNumber( CGparameter param ) +{ + // check parameter handle + if ( !CG_IS_PARAMETER( param ) ) + { + rglCgRaiseError( CG_INVALID_PARAM_HANDLE_ERROR ); + return CG_FALSE; + } + + CgRuntimeParameter *rtParameter = ( CgRuntimeParameter* )rglCgGLTestParameter( param ); + if ( !rtParameter ) + { + rglCgRaiseError( CG_INVALID_PARAM_HANDLE_ERROR ); + return CG_FALSE; + } + + // not implemented yet on the new runtime + // AND the spec on what this function does has actually been changed + // for globals and constants according to more recent nv documentation. + // yuck. + return -123; + + // if param of a CG_CONSTANT, return 0. We do not currently expose + // constants, and I am not sure why we would raise any error + // anyways. + +} + +CG_API CGbool cgIsParameterGlobal( CGparameter param ) +{ + CgRuntimeParameter *rtParameter = ( CgRuntimeParameter* )rglCgGLTestParameter( param ); + if ( !rtParameter ) + return CG_FALSE; + else + { + return (( rtParameter->parameterEntry->flags & CGPF_GLOBAL ) != 0 ); + } +} + +CG_API int cgGetParameterIndex( CGparameter param ) +{ + CgRuntimeParameter *rtParameter = ( CgRuntimeParameter* )rglCgGLTestParameter( param ); + if ( !rtParameter ) + return -1; + + // currently we don't support the runtime creation of array parameters so runtime created params never have an array index + if ( rtParameter->parameterEntry->flags & CGP_RTCREATED ) + return -1; + + int arrayIndex = -1; + CgRuntimeParameter *parent = rglGetArrayItemParent( param, &arrayIndex ); + if ( parent ) + return arrayIndex; + else + return -1; +} + +CG_API void cgSetParameterVariability( CGparameter param, CGenum vary ) +{ + // check parameter handle + if ( !CG_IS_PARAMETER( param ) ) + { + rglCgRaiseError( CG_INVALID_PARAM_HANDLE_ERROR ); + return; + } + + // check vary enum for validity. + switch ( vary ) + { + case CG_UNIFORM: + case CG_LITERAL: + case CG_DEFAULT: + break; + default: + rglCgRaiseError( CG_INVALID_ENUMERANT_ERROR ); + return; + } + + // check that requested variability can be applied to this param + CGenum var = cgGetParameterVariability( param ); + if ( CG_VARYING == var ) + { + rglCgRaiseError( CG_INVALID_PARAMETER_VARIABILITY_ERROR ); + return; + } + else + { + switch ( vary ) + { + case CG_UNIFORM: + case CG_LITERAL: + // **** record the change of variability, forcing a recompile. + // **** but we're pre-compiled so it does nothing to us. + break; + case CG_DEFAULT: + // **** if the param is connected, we can change the target + // **** param back to its default variability. + // **** but we got no connected params yet. So give up. + break; + default: + rglCgRaiseError( CG_INVALID_ENUMERANT_ERROR ); + break; + } + } + return; +} + +CG_API void cgSetParameterSemantic( CGparameter param, const char* semantic ) +{ + // check parameter handle + if ( RGL_UNLIKELY( !CG_IS_PARAMETER( param ) ) ) + { + rglCgRaiseError( CG_INVALID_PARAM_HANDLE_ERROR ); + return; + } + + CgRuntimeParameter* rtParameter = ( CgRuntimeParameter* )rglCgGLTestParameter( param ); + + unsigned short type = rtParameter->parameterEntry->flags & CGP_TYPE_MASK; + if ( type == CGP_STRUCTURE || CGP_STRUCTURE == CGP_ARRAY ) + { + rglCgRaiseError( CG_INVALID_PARAMETER_ERROR ); + return; + } + + // first see if the parameter already has this semantic set from compile time, in which case, just return, it is already set + size_t entryIndex = ( rtParameter->parameterEntry - rtParameter->program->parametersEntries ) / sizeof( CgParameterEntry ); + //look for the parameter semantic in the semantic table for semantics set in the compiled source + int count = rtParameter->program->semanticCount; + int i; + for ( i = 0;i < count;i++ ) + { + const CgParameterSemantic *semanticEntry = rtParameter->program->semanticIndices + i; + if ( semanticEntry->entryIndex == ( unsigned short )entryIndex ) + { + //found the semantic for this parameter + if ( strcmp( semantic, rtParameter->program->stringTable + semanticEntry->semanticOffset ) == 0 ) + { + // if it already has the value we want, just return + return; + } + else + { + // if it has a different value, break out of this loop and give it a new one + break; + } + } + } + + // this table holds semantics that were created at runtime for either program or context or effect scope parameters + // must check this table to see if the param already has one set, in which case the semantic should just be updated + std::vector::iterator semanticIter = rtParameter->program->parameterSemantics.begin(); + while ( semanticIter != rtParameter->program->parameterSemantics.end() ) + { + if ( semanticIter->param == rtParameter ) + { + // we found this parameter already has a runtime set semantic, reassign it. + semanticIter->semantic.clear(); + semanticIter->semantic.insert( semanticIter->semantic.end(), semantic, semantic + strlen( semantic ) + 1 ); + return; + } + semanticIter++; + } + + // finally, if this parameter has no semantic yet, create an entry in the semantics table to store this semantic + CgRuntimeSemantic newSemanticEntry; + newSemanticEntry.param = rtParameter; + newSemanticEntry.semantic.clear(); + newSemanticEntry.semantic.insert( newSemanticEntry.semantic.end(), semantic, semantic + strlen( semantic ) + 1 ); + rtParameter->program->parameterSemantics.push_back( newSemanticEntry ); +} + +/*============================================================ + CG TOKENS + ============================================================ */ + +typedef struct RGLcgProfileMapType +{ + CGprofile id; + char* string; + int is_vertex_program; +} +RGLcgProfileMapType; + +typedef struct RGLcgTypeMapType +{ + CGtype id; + char* string; + CGparameterclass parameter_class; +} +RGLcgTypeMapType; + +// string tables ------------------------ +// string tables map enum values to printable strings + +static const RGLcgTypeMapType RGLcgTypeMap[] = +{ + { CG_UNKNOWN_TYPE, "unknown", CG_PARAMETERCLASS_UNKNOWN}, + { CG_STRUCT, "struct", CG_PARAMETERCLASS_STRUCT}, + { CG_ARRAY, "array", CG_PARAMETERCLASS_ARRAY}, + + //NOTE: string is compiler friendly lower-case version of type name +#define CG_DATATYPE_MACRO(name, compiler_name, enum_name, base_enum, nrows, ncols,classname) \ + { enum_name, #compiler_name, classname }, +#include + + // note: assumes CG_UNKNOWN_TYPE == 0 + { CGtype( 0 ), "", CG_PARAMETERCLASS_UNKNOWN } +}; + +static const RGLenumMap RGLcgResourceMap[] = +{ + +#define CG_BINDLOCATION_MACRO(name,enum_name,compiler_name,enum_int,addressable,param_type) \ + { enum_name, compiler_name }, +#include + + { CG_UNDEFINED, "undefined" }, + { 0, "" } +}; + +static const RGLenumMap RGLcgEnumMap[] = +{ + +#define CG_ENUM_MACRO(enum_name, enum_val) \ + { enum_val, #enum_name }, +#include + + { 0, "" } +}; + +static const RGLcgProfileMapType RGLcgProfileMap[] = +{ + {( CGprofile )6144, "CG_PROFILE_START", 1 }, + {( CGprofile )6145, "unknown", 1 }, + +#define CG_PROFILE_MACRO(name, compiler_id, compiler_id_caps, compiler_opt,int_id,vertex_profile) \ + {CG_PROFILE_ ## compiler_id_caps, compiler_opt, vertex_profile}, + //#include +#include + + {( CGprofile )0, "", 0 } +}; + +static const RGLenumMap RGLcgErrorMap[] = +{ + +#define CG_ERROR_MACRO(code, enum_name, message) \ + { enum_name, message }, +#include + + { 0, "" } +}; + + + + +// templated map lookup functions --------- + + + template +const T*rglLookupEnum( const T( &map )[N], const int key ) +{ + const unsigned int count = sizeof( map ) / sizeof( map[0] ); + for ( unsigned int i = 0; i < count; ++i ) + { + if ( map[i].id == key ) + { + return map + i; + } + } + return 0; +} + + + template +const T* rglLookupString( const T( &map )[N], const char *key ) +{ + const unsigned int count = sizeof( map ) / sizeof( map[0] ); + if (key != NULL) + { + for ( unsigned int i = 0; i < count; ++i ) + { + if (strcmp( map[i].string, key) == 0) + return map + i; + } + } + return 0; +} + + + + + + +// API type functions ----------------------- + +CG_API const char* cgGetTypeString( CGtype type ) +{ + const RGLcgTypeMapType *ptr = rglLookupEnum( RGLcgTypeMap, type ); + if (ptr != 0) + return const_cast( ptr->string ); + return ""; +} + +CG_API CGtype cgGetType( const char* type_string ) +{ + const RGLcgTypeMapType *ptr = rglLookupString( RGLcgTypeMap, type_string ); + if (ptr != 0) + return static_cast( ptr->id ); + return CG_UNKNOWN_TYPE; +} + + +// User type functions ---------------------- + +CG_API CGtype cgGetNamedUserType( CGhandle handle, const char* name ) +{ + // TODO ************** + return CG_UNKNOWN_TYPE; +} + +CG_API int cgGetNumUserTypes( CGhandle handle ) +{ + // TODO ************** + return 0; +} + +CG_API CGtype cgGetUserType( CGhandle handle, int index ) +{ + // TODO ************** + return CG_UNKNOWN_TYPE; +} + +CG_API int cgGetNumParentTypes( CGtype type ) +{ + // TODO ************** + return 0; +} + +CG_API CGtype cgGetParentType( CGtype type, int index ) +{ + // TODO ************** + return CG_UNKNOWN_TYPE; +} + +CG_API CGbool cgIsParentType( CGtype parent, CGtype child ) +{ + // TODO ************** + return CG_FALSE; +} + +CG_API CGbool cgIsInterfaceType( CGtype type ) +{ + + // TODO ************** + return CG_FALSE; +} + + +// Resource Functions ----------------------- + +CG_API const char* cgGetResourceString( CGresource resource ) +{ + return _RGL_MAP_LOOKUP_ENUM( RGLcgResourceMap, resource ); +} + +CG_API CGresource cgGetResource( const char* resource_string ) +{ + GLenum r = _RGL_MAP_LOOKUP_STRING( RGLcgResourceMap, resource_string ); + return ( r == -1U ) ? CG_UNDEFINED : ( CGresource )r; +} + + +// Enum Functions ---------------------------- + +CG_API const char* cgGetEnumString( CGenum en ) +{ + return _RGL_MAP_LOOKUP_ENUM( RGLcgEnumMap, en ); +} + +CG_API CGenum cgGetEnum( const char* enum_string ) +{ + if ( !enum_string ) { rglCgRaiseError( CG_INVALID_PARAMETER_ERROR ); return CG_UNKNOWN; } + GLenum r = _RGL_MAP_LOOKUP_STRING( RGLcgEnumMap, enum_string ); + return ( r == -1U ) ? CG_UNKNOWN : ( CGenum )r; +} + + +// Profile functions ------------------------- + + +// profiles are the only tokens not stored in a RGLenumMap. Instead +// they use a RGLcgProfileMap which contains extra information about +// whether the profile is a vertex or a fragment program. + +CG_API const char* cgGetProfileString( CGprofile profile ) +{ + const size_t arraysize = sizeof( RGLcgProfileMap ) / sizeof( RGLcgProfileMapType ); + unsigned int i = 0; + while ( i < arraysize ) + { + if ( profile == RGLcgProfileMap[i].id ) + { + // id found. + return RGLcgProfileMap[i].string; + } + ++i; + } + // id not found, return an empty string + return ""; +} + +CG_API CGprofile cgGetProfile( const char* profile_string ) +{ + size_t arraysize = sizeof( RGLcgProfileMap ) / sizeof( RGLcgProfileMapType ); + unsigned int i = 0; + while ( i < arraysize ) + { + if (strcmp( RGLcgProfileMap[i].string, profile_string) == 0) + return RGLcgProfileMap[i].id; // string found. + ++i; + } + // string not found, return fail code. + return CG_PROFILE_UNKNOWN; +} + + +// ErrorFunctions ---------------------------- +CG_API CGerror cgGetError( void ) +{ + CGerror err = _CurrentContext->RGLcgLastError; + _CurrentContext->RGLcgLastError = CG_NO_ERROR; + return err; +} + +CG_API const char* cgGetErrorString( CGerror error ) +{ + return _RGL_MAP_LOOKUP_ENUM( RGLcgErrorMap, error ); +} + +CG_API const char* cgGetLastErrorString( CGerror* error ) +{ + // return both the error id and string. + *error = _CurrentContext->RGLcgLastError; + _CurrentContext->RGLcgLastError = CG_NO_ERROR; + const char * result = _RGL_MAP_LOOKUP_ENUM( RGLcgErrorMap, *error ); + return result; +} + +CG_API void cgSetErrorCallback( CGerrorCallbackFunc func ) +{ + _CurrentContext->RGLcgErrorCallbackFunction = func; +} + +CG_API CGerrorCallbackFunc cgGetErrorCallback( void ) +{ + return _CurrentContext->RGLcgErrorCallbackFunction; +} + + +// Misc Functions ----------------------------- + +CG_API const char* cgGetString( CGenum sname ) +{ + if ( sname == CG_VERSION ) + { + // this should return the version of the runtime or perhaps more meaninfully, the runtime compiler + static char versionstring[8]; + sprintf( versionstring, "%d", CG_VERSION_NUM ); + return versionstring; + } + + rglCgRaiseError( CG_INVALID_ENUMERANT_ERROR ); + return NULL; +} + + + +CG_API CGdomain cgGetProfileDomain( CGprofile profile ) +{ + const size_t arraysize = sizeof( RGLcgProfileMap ) / sizeof( RGLcgProfileMapType ); + unsigned int i = 0; + while ( i < arraysize ) + { + if ( profile == RGLcgProfileMap[i].id ) + { + // id found, check whether this is a vertex or fragment program + if ( RGLcgProfileMap[i].is_vertex_program ) + return CG_VERTEX_DOMAIN; + else + return CG_FRAGMENT_DOMAIN; + } + ++i; + } + // id not found, return an unknown domain + rglCgRaiseError( CG_UNKNOWN_PROFILE_ERROR ); + return CG_UNKNOWN_DOMAIN; +} + + + +CG_API CGparameterclass cgGetTypeClass( CGtype type ) +{ + const RGLcgTypeMapType *ptr = rglLookupEnum( RGLcgTypeMap, type ); + if (ptr == 0) + return CG_PARAMETERCLASS_UNKNOWN; + return ptr->parameter_class; +} + +CG_API CGtype cgGetTypeBase( CGtype type ) +{ + // get the base type of a usertype without having to create + // a parameter of that type. + + // TODO: usertypes not supported in Jetstream + return CG_UNKNOWN_TYPE; +} + + +CG_API CGbool cgGetTypeSizes( CGtype type, int *nrows, int *ncols ) +{ + // TODO ***************** + return _cgMatrixDimensions( type, ( unsigned int* )nrows, ( unsigned int* )ncols ); + +} + +CG_API void cgGetMatrixSize( CGtype type, int *nrows, int *ncols ) +{ + if (( nrows == 0 ) || ( ncols == 0 ) ) + { + rglCgRaiseError( CG_INVALID_POINTER_ERROR ); + return; + } + + if (( type >= CG_FLOAT1x1 && type <= CG_FLOAT4x4 ) || + ( type >= CG_HALF1x1 && type <= CG_HALF4x4 ) || + ( type >= CG_INT1x1 && type <= CG_INT4x4 ) || + ( type >= CG_BOOL1x1 && type <= CG_BOOL4x4 ) || + ( type >= CG_FIXED1x1 && type <= CG_FIXED4x4 )) + { + _cgMatrixDimensions( type, ( unsigned int* )nrows, ( unsigned int* )ncols ); + return; + } + + // type supplied is not a recognised matrix type + rglCgRaiseError( CG_NOT_MATRIX_PARAM_ERROR ); + // NOTE: but fall through to return 0,0... + *nrows = 0; + *ncols = 0; + +} + +/*============================================================ + CG CONTEXT + ============================================================ */ + +RGL_EXPORT CgcontextHookFunction _cgContextCreateHook = NULL; +RGL_EXPORT CgcontextHookFunction _cgContextDestroyHook = NULL; + +void rglCgContextZero( _CGcontext* p ) +{ + memset( p, 0, sizeof( *p ) ); + p->compileType = CG_UNKNOWN; + +} + +void rglCgContextPushFront( _CGcontext* ctx ) +{ + if ( _CurrentContext->RGLcgContextHead ) + { + _CGcontext* head = _cgGetContextPtr( _CurrentContext->RGLcgContextHead ); + // insert this context at the head of the list + ctx->next = head; + } + _CurrentContext->RGLcgContextHead = ctx->id; +} + +static void destroy_context( _CGcontext*ctx ) +{ + if ( _cgContextDestroyHook ) _cgContextDestroyHook( ctx ); + // free the id + rglEraseName( &_CurrentContext->cgContextNameSpace, (unsigned int)ctx->id ); + // zero the memory + rglCgContextZero( ctx ); + // return context to free store + free( ctx ); +} + +void rglCgContextPopFront() +{ + // remove and delete the context at the head of the list + if ( _CurrentContext->RGLcgContextHead ) + { + _CGcontext* head = _cgGetContextPtr( _CurrentContext->RGLcgContextHead ); + _CGcontext* temp = head->next; + // free the id as well + destroy_context( head ); + + if ( temp ) + { + // this is not the end of the list, feel free to dereference it. + _CurrentContext->RGLcgContextHead = temp->id; + } + else + { + // nothing left, no dereferenceing for you, mister. + _CurrentContext->RGLcgContextHead = 0; + } + } +} + + +void rglCgContextEraseAfter( _CGcontext* c ) +{ + _CGcontext* eraseme = c->next; + c->next = eraseme->next; + + destroy_context( eraseme ); +} + +// API functions ---------------------------------------- + +CG_API CGcontext cgCreateContext( void ) +{ + // create a context out of thin air and add it to the hidden global list. + + _CGcontext* ptr = NULL; + + // alloc new context + ptr = ( _CGcontext* )malloc( sizeof( _CGcontext ) ); + if ( NULL == ptr ) + { + rglCgRaiseError( CG_MEMORY_ALLOC_ERROR ); + return ( CGcontext )NULL; + } + + // initialise member variables + rglCgContextZero( ptr ); + + // get a new id for the object + CGcontext result = ( CGcontext )rglCreateName( &_CurrentContext->cgContextNameSpace, ptr ); + if ( !result ) { free( ptr ); return NULL; } + + ptr->id = result; + ptr->defaultProgram.parentContext = ptr; + + // insert context at head of global list + rglCgContextPushFront( ptr ); + + if ( _cgContextCreateHook ) _cgContextCreateHook( ptr ); + + return result; +} + +CG_API void cgDestroyContext( CGcontext c ) +{ + // check if context is valid + if ( !CG_IS_CONTEXT( c ) ) + { + rglCgRaiseError( CG_INVALID_CONTEXT_HANDLE_ERROR ); + return; + } + + _CGcontext* ctx = _cgGetContextPtr( c ); + + // if we are really destroying the context, let's remove all the connections first. + // if we don't do this first, I think the clean up gets grumpy. + ctx->defaultProgram.connectionTable.clear(); + struct _CGprogram* programIter = ctx->programList; + while ( programIter != NULL ) + { + programIter->connectionTable.clear(); + programIter = programIter->next; + } + + + rglCgProgramErase( &ctx->defaultProgram ); + + // destroy all programs + rglCgProgramDestroyAll( ctx ); + + // unlink from global CGContext list + _CGcontext * const head = _cgGetContextPtr( _CurrentContext->RGLcgContextHead ); + if ( head != ctx ) + { + // node is not the head, find and erase it + + // find the context that occurs before this one + _CGcontext* ptr = head; + while ( ptr->next != ctx ) ptr = ptr->next; + // relink + ptr->next = ctx->next; + destroy_context( ctx ); + } + else + { + + // node is the head, erase it + _CGcontext* second = head->next; + destroy_context( head ); + + if ( second ) + { + // link to second element + _CurrentContext->RGLcgContextHead = second->id; + } + else + { + // nothing left + _CurrentContext->RGLcgContextHead = 0; + } + } +} + +CG_API CGbool cgIsContext( CGcontext ctx ) +{ + // is the pointer valid? + if ( CG_IS_CONTEXT( ctx ) ) + { + return CG_TRUE; + } + return CG_FALSE; +} + +CG_API const char* cgGetLastListing( CGcontext c ) +{ + // check to see if context is a valid one + // NOTE: Cg API Reference docs omit this test for this API function. + if ( !CG_IS_CONTEXT( c ) ) + { + rglCgRaiseError( CG_INVALID_CONTEXT_HANDLE_ERROR ); + return NULL; + } + + // currently does nothing + // TODO **************************** + + return NULL; +} + + +CG_API void cgSetAutoCompile( CGcontext c, CGenum flag ) +{ + // check to see if context is a valid one + if ( !CG_IS_CONTEXT( c ) ) + { + rglCgRaiseError( CG_INVALID_CONTEXT_HANDLE_ERROR ); + return; + } + + // check if enum has any meaning here + switch ( flag ) + { + case CG_COMPILE_MANUAL: + case CG_COMPILE_IMMEDIATE: + case CG_COMPILE_LAZY: + // set the value and return + _cgGetContextPtr( c )->compileType = flag; + break; + default: + rglCgRaiseError( CG_INVALID_ENUMERANT_ERROR ); + } +} + +/*============================================================ + CG PROGRAM + ============================================================ */ + +RGL_EXPORT CgprogramHookFunction _cgProgramCreateHook = NULL; +RGL_EXPORT CgprogramHookFunction _cgProgramDestroyHook = NULL; +RGL_EXPORT CgprogramCopyHookFunction _cgProgramCopyHook = NULL; + +RGL_EXPORT cgRTCgcCompileHookFunction _cgRTCgcCompileProgramHook = NULL; +RGL_EXPORT cgRTCgcFreeHookFunction _cgRTCgcFreeCompiledProgramHook; + +// Program list functions +// The context can contain many programs, but each one is a variable sized +// chunk of data produced by the CGC compiler and loaded at runtime. We cannot +// include intrusive "next" pointers in this data block so instead we'll use +// a non-intrusive list. The list is walked using cgGetFirstProgram() and +// cgGetNextProgram() + +void rglCgProgramZero( _CGprogram* p ) +{ + // zero all pointers in the node and enclosed binary program + // this makes sure cgIsProgram calls on invalid pointers always fail + memset( p, 0, sizeof( _CGprogram ) ); + return; +} + +void rglCgProgramPushFront( _CGcontext* ctx, _CGprogram* prog ) +{ + // push the program to the context. + // updates the linked list and program count + + // link the node into the head of the list + prog->next = ctx->programList; + ctx->programList = prog; + + // update the parent context + prog->parentContext = ctx; + + // update the program count + ctx->programCount++; +} + +_CGprogram* rglCgProgramFindPrev( _CGcontext* ctx, _CGprogram* prog ) +{ + // get a pointer the the list element *before* prog in the list + // this allows us to unlink it safely. + + _CGprogram* ptr = ctx->programList; + + while ( ptr != NULL && prog != ptr->next ) + ptr = ptr->next; + + return ptr; +} + +inline void rglCgProgramEraseAndFree( _CGprogram* prog ) +{ + rglCgProgramErase( prog ); + free( prog ); +} + +void rglCgProgramErase( _CGprogram* prog ) +{ + // remove the program from the linked list and deallocate it's storage. + + if ( _cgProgramDestroyHook ) _cgProgramDestroyHook( prog ); + + switch ( prog->header.profile ) + { + case CG_PROFILE_SCE_VP_TYPEB: + //case CG_PROFILE_SCE_VP_TYPEC: + case CG_PROFILE_SCE_VP_RSX: + case CG_PROFILE_SCE_FP_TYPEB: + //case CG_PROFILE_SCE_FP_TYPEC: + case CG_PROFILE_SCE_FP_RSX: + rglpProgramErase( prog ); + break; + default: + // default program + break; + } + + // check to see if each effect parameter is a parent in a connection and remove that reference before deletion + // + // for every effect param, check every program in its context and every connection in each program, + // then remove any where the effect param is a parent + std::vector::iterator effectParamIter = prog->runtimeCreatedParameters.begin(); + while ( effectParamIter != prog->runtimeCreatedParameters.end() ) + { + struct _CGprogram* programIter = prog->parentContext->programList; + while ( programIter != NULL ) + { + // search the program's connection table to find if this is a parent param to anybody + std::vector::iterator paramConnectionTableIter = programIter->connectionTable.begin(); + while ( paramConnectionTableIter != programIter->connectionTable.end() ) + { + if ( paramConnectionTableIter->parent == *effectParamIter ) + { + // Use iterator returned by erase() function as "nextParam" iterator + paramConnectionTableIter = programIter->connectionTable.erase( paramConnectionTableIter ); + } + else + { + paramConnectionTableIter++; + } + } + programIter = programIter->next; + } + //rglCgDestroyContextParam(*effectParamIter); + effectParamIter++; + } + + while ( prog->runtimeCreatedParameters.size() > 0 ) + { + // this routine removes the parameter from the array + rglCgDestroyContextParam( prog->runtimeCreatedParameters[0] ); + } + + // free allocated memory in these stl containers. + // Current clear() implementation deallocates the memory. + // Is it better to explicitly call a "destructor" of this prog before freeing its memory? + prog->runtimeCreatedParameters.clear(); + prog->connectionTable.clear(); + prog->parameterSemantics.clear(); + + // return program and node to free store + if ( prog->id ) rglEraseName( &_CurrentContext->cgProgramNameSpace, (unsigned int)prog->id ); + + //free ELF data obtained from the runtime converter + if ( prog->runtimeElf ) + free( prog->runtimeElf ); + + // zero out all pointers + rglCgProgramZero( prog ); +} + +void rglCgProgramEraseAfter( _CGprogram* prog ) +{ + // delete the list entry after the current pointer. + // (use in conjunction with find_prev for full effect!) + + _CGprogram* next = prog->next; + if ( next ) + { + prog->next = next->next; + rglCgProgramEraseAndFree( next ); + } +} + +void rglCgProgramDestroyAll( _CGcontext* ctx ) +{ + // destroy all programs in this context + while ( ctx->programList ) + { + _CGprogram * p = ctx->programList; + ctx->programList = p->next; + // erase the program + rglCgProgramEraseAndFree( p ); + } +} + + +static inline unsigned int getMatrixRowCount( CGtype type ) +{ + unsigned int rc = 0; + switch ( type ) + { + case CG_FLOAT1x1: + case CG_FLOAT1x2: + case CG_FLOAT1x3: + case CG_FLOAT1x4: + rc = 1; + break; + case CG_FLOAT2x1: + case CG_FLOAT2x2: + case CG_FLOAT2x3: + case CG_FLOAT2x4: + rc = 2; + break; + case CG_FLOAT3x1: + case CG_FLOAT3x2: + case CG_FLOAT3x3: + case CG_FLOAT3x4: + rc = 3; + break; + case CG_FLOAT4x1: + case CG_FLOAT4x2: + case CG_FLOAT4x3: + case CG_FLOAT4x4: + rc = 4; + break; + case CG_HALF1x1: + case CG_HALF1x2: + case CG_HALF1x3: + case CG_HALF1x4: + case CG_INT1x1: + case CG_INT1x2: + case CG_INT1x3: + case CG_INT1x4: + case CG_BOOL1x1: + case CG_BOOL1x2: + case CG_BOOL1x3: + case CG_BOOL1x4: + case CG_FIXED1x1: + case CG_FIXED1x2: + case CG_FIXED1x3: + case CG_FIXED1x4: + rc = 1; + break; + case CG_HALF2x1: + case CG_HALF2x2: + case CG_HALF2x3: + case CG_HALF2x4: + case CG_INT2x1: + case CG_INT2x2: + case CG_INT2x3: + case CG_INT2x4: + case CG_BOOL2x1: + case CG_BOOL2x2: + case CG_BOOL2x3: + case CG_BOOL2x4: + case CG_FIXED2x1: + case CG_FIXED2x2: + case CG_FIXED2x3: + case CG_FIXED2x4: + rc = 2; + break; + case CG_HALF3x1: + case CG_HALF3x2: + case CG_HALF3x3: + case CG_HALF3x4: + case CG_INT3x1: + case CG_INT3x2: + case CG_INT3x3: + case CG_INT3x4: + case CG_BOOL3x1: + case CG_BOOL3x2: + case CG_BOOL3x3: + case CG_BOOL3x4: + case CG_FIXED3x1: + case CG_FIXED3x2: + case CG_FIXED3x3: + case CG_FIXED3x4: + rc = 3; + break; + case CG_HALF4x1: + case CG_HALF4x2: + case CG_HALF4x3: + case CG_HALF4x4: + case CG_INT4x1: + case CG_INT4x2: + case CG_INT4x3: + case CG_INT4x4: + case CG_BOOL4x1: + case CG_BOOL4x2: + case CG_BOOL4x3: + case CG_BOOL4x4: + case CG_FIXED4x1: + case CG_FIXED4x2: + case CG_FIXED4x3: + case CG_FIXED4x4: + rc = 4; + break; + default: + break; + } + return rc; +} + +CGtype getMatrixRowType( CGtype type ) +{ + CGtype rt = ( CGtype )0; + switch ( type ) + { + case CG_FLOAT1x1: + case CG_FLOAT2x1: + case CG_FLOAT3x1: + case CG_FLOAT4x1: + rt = CG_FLOAT1; + break; + case CG_FLOAT1x2: + case CG_FLOAT2x2: + case CG_FLOAT3x2: + case CG_FLOAT4x2: + rt = CG_FLOAT2; + break; + case CG_FLOAT1x3: + case CG_FLOAT2x3: + case CG_FLOAT3x3: + case CG_FLOAT4x3: + rt = CG_FLOAT3; + break; + case CG_FLOAT1x4: + case CG_FLOAT2x4: + case CG_FLOAT3x4: + case CG_FLOAT4x4: + rt = CG_FLOAT4; + break; + case CG_HALF1x1: + case CG_HALF2x1: + case CG_HALF3x1: + case CG_HALF4x1: + rt = CG_HALF1; + break; + case CG_HALF1x2: + case CG_HALF2x2: + case CG_HALF3x2: + case CG_HALF4x2: + rt = CG_HALF2; + break; + case CG_HALF1x3: + case CG_HALF2x3: + case CG_HALF3x3: + case CG_HALF4x3: + rt = CG_HALF3; + break; + case CG_HALF1x4: + case CG_HALF2x4: + case CG_HALF3x4: + case CG_HALF4x4: + rt = CG_HALF4; + break; + case CG_INT1x1: + case CG_INT2x1: + case CG_INT3x1: + case CG_INT4x1: + rt = CG_INT1; + break; + case CG_INT1x2: + case CG_INT2x2: + case CG_INT3x2: + case CG_INT4x2: + rt = CG_INT2; + break; + case CG_INT1x3: + case CG_INT2x3: + case CG_INT3x3: + case CG_INT4x3: + rt = CG_INT3; + break; + case CG_INT1x4: + case CG_INT2x4: + case CG_INT3x4: + case CG_INT4x4: + rt = CG_INT4; + break; + case CG_BOOL1x1: + case CG_BOOL2x1: + case CG_BOOL3x1: + case CG_BOOL4x1: + rt = CG_BOOL1; + break; + case CG_BOOL1x2: + case CG_BOOL2x2: + case CG_BOOL3x2: + case CG_BOOL4x2: + rt = CG_BOOL2; + break; + case CG_BOOL1x3: + case CG_BOOL2x3: + case CG_BOOL3x3: + case CG_BOOL4x3: + rt = CG_BOOL3; + break; + case CG_BOOL1x4: + case CG_BOOL2x4: + case CG_BOOL3x4: + case CG_BOOL4x4: + rt = CG_BOOL4; + break; + case CG_FIXED1x1: + case CG_FIXED2x1: + case CG_FIXED3x1: + case CG_FIXED4x1: + rt = CG_FIXED1; + break; + case CG_FIXED1x2: + case CG_FIXED2x2: + case CG_FIXED3x2: + case CG_FIXED4x2: + rt = CG_FIXED2; + break; + case CG_FIXED1x3: + case CG_FIXED2x3: + case CG_FIXED3x3: + case CG_FIXED4x3: + rt = CG_FIXED3; + break; + case CG_FIXED1x4: + case CG_FIXED2x4: + case CG_FIXED3x4: + case CG_FIXED4x4: + rt = CG_FIXED4; + break; + default: + break; + } + return rt; +} + + +// forward declaration for recursion +void AccumulateSizeForParams( CgParameterEntry* paramEntry, CgParameterEntry* paramEntries, unsigned int paramEntriesCount, + unsigned short* paramResourceTable, ELF_section_t* strtab, CgParameterEntry** nextEntry, + unsigned int prefixLength, int elementResourceIndex, + size_t* nvParamSize, size_t* nvParamStringsSize, size_t* nvParamOffsetsSize, + CgParameterSemantic* semanticIndexTable, unsigned int semanticIndexCount, + CgParameterDefaultValue* defaultIndexTable, unsigned int defaultIndexCount, size_t* nvParamDefaultsSize, + ELF_section_t* consttab ); + +void AccumulateSizeForParamResource( CgParameterEntry* paramEntry, CgParameterEntry* paramEntries, unsigned int paramEntriesCount, + unsigned short* paramResourceTable, ELF_section_t* strtab, CgParameterEntry** nextEntry, + unsigned int prefixLength, int elementResourceIndex, + size_t* nvParamSize, size_t* nvParamStringsSize, size_t* nvParamOffsetsSize, + CgParameterSemantic* semanticIndexTable, unsigned int semanticIndexCount, + CgParameterDefaultValue* defaultIndexTable, unsigned int defaultIndexCount, size_t* nvParamDefaultsSize, + ELF_section_t* consttab ) +{ + // type index is actually the offset into the block of memory following the entries + CgParameterResource* paramResource = ( CgParameterResource* )(( char* )( paramEntries + paramEntriesCount ) + paramEntry->typeIndex ); + + unsigned int rowCount = getMatrixRowCount(( CGtype )paramResource->type ); + + // param + *nvParamSize += sizeof( CgBinaryParameter ); + // and for the row params of a matrix + *nvParamSize += rowCount * sizeof( CgBinaryParameter ); + + // name + *nvParamStringsSize += ( prefixLength + strlen( strtab->data + paramEntry->nameOffset ) + 1 ); + // and for each row of a matrix which assumes just an extra 3 characters for [i] + *nvParamStringsSize += ( rowCount * ( prefixLength + strlen( strtab->data + paramEntry->nameOffset ) + 3 + 1 ) ); + + + // semantic + + // totally inefficient, but easiest implementation for now is to do the On^2 search + // in the semantic and default tables for the data associated with this parameter + unsigned int entryIndex = paramEntry - paramEntries; + + // semantic + char* semantic = NULL; + for ( unsigned int sem = 0; sem < semanticIndexCount; sem++ ) + { + CgParameterSemantic* semanticIndex = semanticIndexTable + sem; + if ( semanticIndex->entryIndex == entryIndex ) + { + // found the semantic for this parameter + semantic = strtab->data + semanticIndex->semanticOffset; + break; + } + } + if ( semantic ) + { + // increment the names size buffer + *nvParamStringsSize += strlen( semantic ) + 1; + } + + // default + float* defaults = NULL; + for ( unsigned int def = 0; def < defaultIndexCount; def++ ) + { + CgParameterDefaultValue* defaultIndex = defaultIndexTable + def; + if ( defaultIndex->entryIndex == entryIndex ) + { + // found the default for this parameter + defaults = ( float* )consttab->data + defaultIndex->defaultValueIndex; + } + } + if ( defaults ) + { + // defaults are always padded to 4 floats per param + unsigned int defaultsCount = ( rowCount ? rowCount : 1 ) * 4; + *nvParamDefaultsSize += sizeof( float ) * defaultsCount; + } + + // offsets + // fragment programs + // do we want this referenced param test??? + if ( nvParamOffsetsSize != NULL && paramEntry->flags & CGPF_REFERENCED ) + { + // non varying params + if ( paramEntry->flags & CGPV_CONSTANT || paramEntry->flags & CGPV_UNIFORM ) + { + // non sampler types + if ( !isSampler(( CGtype )paramResource->type ) ) + { + unsigned short* resPtr = paramResourceTable + paramResource->resource; + + if ( elementResourceIndex >= 0 ) + { + //advance resPtr to the arrayIndex + int skipCount = elementResourceIndex; + while ( skipCount ) + { + resPtr++; + int embeddedCount = *( resPtr++ ); + resPtr += embeddedCount; + // if an array of matrices, must skip row parameter resources too + for ( int row = 1; row <= ( int )rowCount; row++ ) + { + resPtr++; + int embeddedCount = *( resPtr++ ); + resPtr += embeddedCount; + } + skipCount--; + } + //resPtr points to the resource of the arrayIndex + } + + if ( !isMatrix(( CGtype )( paramResource->type ) ) ) + { + // advance past register to second field that contains embedded count + resPtr++; + unsigned int embeddedConstantCount = *( resPtr++ ); + *nvParamOffsetsSize += sizeof( CgBinaryEmbeddedConstant ) + sizeof( unsigned int ) * ( embeddedConstantCount - 1 ); + } + else + { + for ( int row = 1; row <= ( int )rowCount; row++ ) + { + // advance past register to second field that contains embedded count + resPtr++; + unsigned int embeddedConstantCount = *( resPtr++ ); + *nvParamOffsetsSize += sizeof( CgBinaryEmbeddedConstant ) + sizeof( unsigned int ) * ( embeddedConstantCount - 1 ); + } + } + + } + } + + } + + + // entry cursor + *nextEntry = paramEntry + 1; +} + +void AccumulateSizeForParamArray( CgParameterEntry* paramEntry, CgParameterEntry* paramEntries, unsigned int paramEntriesCount, + unsigned short* paramResourceTable, ELF_section_t* strtab, CgParameterEntry** nextEntry, + unsigned int prefixLength, int elementResourceIndex, + size_t* nvParamSize, size_t* nvParamStringsSize, size_t* nvParamOffsetsSize, + CgParameterSemantic* semanticIndexTable, unsigned int semanticIndexCount, + CgParameterDefaultValue* defaultIndexTable, unsigned int defaultIndexCount, size_t* nvParamDefaultsSize, + ELF_section_t* consttab ) +{ + // type index is actually the offset into the block of memory following the entries + CgParameterArray* paramArray = ( CgParameterArray* )(( char* )( paramEntries + paramEntriesCount ) + paramEntry->typeIndex ); + + // this parameter's entry says it's an array + // this parameter's entry says its packing in the flags + // the next entry specifies its type... + // ... either a list of every element in the array + // ... or a single element in the array to represent all because they are the same + // ... or a single element to specify the layout of the parameter, but not every element has a resource + + // this would give the number of intrinsics OR structs, but if base type is struct + // to get the number of parameters, must recurse over struct fields + unsigned int numElements = 1; + for ( unsigned int dim = 0; dim < paramArray->dimensionCount; dim++ ) + { + numElements *= paramArray->dimensions[dim]; + }; + + unsigned int prefixLengthIn = prefixLength; + + // next entry will always be either an intrinsic or a struct + + if ( !( paramEntry->flags & CGP_UNROLLED ) ) // one bit is not enough cause there are 3 representations! + { + // all elements are the same so have one entry to represent all of them + CgParameterEntry* elementEntry = paramEntry + 1; + + // entries are same type, and packed, so just repeat same param + for ( unsigned int element = 0; element < numElements; element++ ) + { + // name length for prefixIn + rest of array name for array + 16 bytes generously for [index] + prefixLength = prefixLengthIn + strlen( strtab->data + paramEntry->nameOffset ) + 16; + + // right now i think this is always intrinsics for the not unrolled case, current limitation + AccumulateSizeForParamResource( elementEntry, paramEntries, paramEntriesCount, + paramResourceTable, strtab, nextEntry, + prefixLength, element, + nvParamSize, nvParamStringsSize, nvParamOffsetsSize, + semanticIndexTable, semanticIndexCount, + defaultIndexTable, defaultIndexCount, nvParamDefaultsSize, + consttab ); + + *nextEntry = *nextEntry - 1; // undo the increment on the next entry for this special case of shared entries + } + *nextEntry = *nextEntry + 1; // redo the increment upon exiting the loop, could be smarter, whatever + } + else if ( paramEntry->flags & CGP_UNROLLED ) + { + // here everything is unrolled + + CgParameterEntry* elementEntry = paramEntry + 1; + + for ( unsigned int element = 0; element < numElements; element++ ) + { + // name length for prefixIn + rest of array name for array + 16 bytes generously for [index] + prefixLength = prefixLengthIn + strlen( strtab->data + paramEntry->nameOffset ) + 16; + + AccumulateSizeForParams( elementEntry, paramEntries, paramEntriesCount, + paramResourceTable, strtab, nextEntry, + prefixLength, -1, + nvParamSize, nvParamStringsSize, nvParamOffsetsSize, + semanticIndexTable, semanticIndexCount, + defaultIndexTable, defaultIndexCount, nvParamDefaultsSize, + consttab ); + + elementEntry = *nextEntry; + } + } +} + +void AccumulateSizeForParamStruct( CgParameterEntry* paramEntry, CgParameterEntry* paramEntries, unsigned int paramEntriesCount, + unsigned short* paramResourceTable, ELF_section_t* strtab, CgParameterEntry** nextEntry, + unsigned int prefixLength, int elementResourceIndex, + size_t* nvParamSize, size_t* nvParamStringsSize, size_t* nvParamOffsetsSize, + CgParameterSemantic* semanticIndexTable, unsigned int semanticIndexCount, + CgParameterDefaultValue* defaultIndexTable, unsigned int defaultIndexCount, size_t* nvParamDefaultsSize, + ELF_section_t* consttab ) +{ + // type index is actually the offset into the block of memory following the entries + CgParameterStructure* paramStruct = ( CgParameterStructure* )(( char* )( paramEntries + paramEntriesCount ) + paramEntry->typeIndex ); + + // add prefix of struct name and . + // !!! but what about if we are inside an array??? then no struct name + if ( paramEntry->nameOffset > 0 ) // is this the right test??? + { + prefixLength += strlen( strtab->data + paramEntry->nameOffset ); + } + prefixLength += 1; // allow for the dot + + unsigned short memberCount = paramStruct->memberCount; + CgParameterEntry* memberEntry = paramEntry + 1; + + for ( unsigned int member = 0; member < memberCount; member++ ) + { + AccumulateSizeForParams( memberEntry, paramEntries, paramEntriesCount, + paramResourceTable, strtab, nextEntry, + prefixLength, -1, + nvParamSize, nvParamStringsSize, nvParamOffsetsSize, + semanticIndexTable, semanticIndexCount, + defaultIndexTable, defaultIndexCount, nvParamDefaultsSize, + consttab ); + + memberEntry = *nextEntry; + } +} + +void AccumulateSizeForParams( CgParameterEntry* paramEntry, CgParameterEntry* paramEntries, unsigned int paramEntriesCount, + unsigned short* paramResourceTable, ELF_section_t* strtab, CgParameterEntry** nextEntry, + unsigned int prefixLength, int elementResourceIndex, + size_t* nvParamSize, size_t* nvParamStringsSize, size_t* nvParamOffsetsSize, + CgParameterSemantic* semanticIndexTable, unsigned int semanticIndexCount, + CgParameterDefaultValue* defaultIndexTable, unsigned int defaultIndexCount, size_t* nvParamDefaultsSize, + ELF_section_t* consttab ) +{ + // expand for intrinsics, arrays, and structs + // flags hold which type of parameter it is (along with other information) + switch ( paramEntry->flags & CGP_TYPE_MASK ) + { + case CGP_INTRINSIC: + { + //printf("resource --- %p\n", paramEntry); + AccumulateSizeForParamResource( paramEntry, paramEntries, paramEntriesCount, + paramResourceTable, strtab, nextEntry, + prefixLength, elementResourceIndex, + nvParamSize, nvParamStringsSize, nvParamOffsetsSize, + semanticIndexTable, semanticIndexCount, + defaultIndexTable, defaultIndexCount, nvParamDefaultsSize, + consttab ); + break; + } + case CGP_ARRAY: + { + //printf("array --- %p\n", paramEntry); + AccumulateSizeForParamArray( paramEntry, paramEntries, paramEntriesCount, + paramResourceTable, strtab, nextEntry, + prefixLength, elementResourceIndex, + nvParamSize, nvParamStringsSize, nvParamOffsetsSize, + semanticIndexTable, semanticIndexCount, + defaultIndexTable, defaultIndexCount, nvParamDefaultsSize, + consttab ); + break; + } + case CGP_STRUCTURE: + { + //printf("structure --- %p\n", paramEntry); + AccumulateSizeForParamStruct( paramEntry, paramEntries, paramEntriesCount, + paramResourceTable, strtab, nextEntry, + prefixLength, elementResourceIndex, + nvParamSize, nvParamStringsSize, nvParamOffsetsSize, + semanticIndexTable, semanticIndexCount, + defaultIndexTable, defaultIndexCount, nvParamDefaultsSize, + consttab ); + break; + } + default: + { + break; + } + + } + +} + +// forward declaration for recursion +void PopulateDataForParams( CgParameterEntry* paramEntry, CgParameterEntry* paramEntries, unsigned int paramEntriesCount, + unsigned short* paramResourceTable, ELF_section_t* strtab, CgParameterEntry** nextEntry, + int elementResourceIndex, unsigned int* localParamNo, char* nvBinary, + CgBinaryParameter** nvParams, char** nvParamStrings, + CgBinaryEmbeddedConstant** nvParamOffsets, float** nvParamDefaults, + char* prefix, unsigned int prefixLength, + CgParameterSemantic* semanticIndexTable, unsigned int semanticIndexCount, + CgParameterDefaultValue* defaultIndexTable, unsigned int defaultIndexCount, + ELF_section_t* consttab ); + +void PopulateDataForParamResource( CgParameterEntry* paramEntry, CgParameterEntry* paramEntries, unsigned int paramEntriesCount, + unsigned short* paramResourceTable, ELF_section_t* strtab, CgParameterEntry** nextEntry, + int elementResourceIndex, unsigned int* localParamNo, char* nvBinary, + CgBinaryParameter** nvParams, char** nvParamStrings, + CgBinaryEmbeddedConstant** nvParamOffsets, float** nvParamDefaults, + char* prefix, unsigned int prefixLength, + CgParameterSemantic* semanticIndexTable, unsigned int semanticIndexCount, + CgParameterDefaultValue* defaultIndexTable, unsigned int defaultIndexCount, + ELF_section_t* consttab ) +{ + // type index is actually the offset into the block of memory following the entries + CgParameterResource* paramResource = ( CgParameterResource* )(( char* )( paramEntries + paramEntriesCount ) + paramEntry->typeIndex ); + + unsigned int rowCount = getMatrixRowCount(( CGtype )paramResource->type ); + + // type + ( *nvParams )->type = ( CGtype )( paramResource->type ); + // sub type for row params of matrix + for ( int row = 1; row <= ( int )rowCount; row++ ) + { + ( *nvParams + row )->type = getMatrixRowType(( CGtype )paramResource->type ); + } + + // varying parameters + if (( paramEntry->flags & CGPV_MASK ) == CGPV_VARYING ) + { + ( *nvParams )->res = ( CGresource )paramResource->resource; + ( *nvParams )->resIndex = -1; + } + else if ((( paramEntry->flags & CGPV_MASK ) & CGPV_CONSTANT ) || (( paramEntry->flags & CGPV_MASK ) & CGPV_UNIFORM ) ) + { + // sampler types + if ( isSampler(( CGtype )paramResource->type ) ) + { + ( *nvParams )->res = ( CGresource )paramResource->resource; //should be CG_TEXUNIT0 .. 15 + ( *nvParams )->resIndex = 0; + } + // nonsampler types + else + { + // CG_B requires support too + for ( int row = 0; row <= ( int )rowCount; row++ ) + { + if ( paramResource->type == CGP_SCF_BOOL ) //(paramEntry->flags & CGP_SCFBOOL) + { + ( *nvParams + row )->res = CG_B; + ( *nvParams )->type = CG_BOOL; + } + else + { + ( *nvParams + row )->res = CG_C; + } + } + + // vertex programs + if ( nvParamOffsets == NULL ) + { + // element of an array + if ( elementResourceIndex >= 0 ) + { + if ( !isMatrix(( CGtype )( paramResource->type ) ) ) + { + unsigned short tempResIndex = *( paramResourceTable + paramResource->resource + elementResourceIndex ); + ( *nvParams )->resIndex = ( tempResIndex == 0xFFFF ) ? -1 : ( int )tempResIndex; + } + else if ( paramEntry->flags & CGP_CONTIGUOUS ) + { + unsigned short tempResIndex = *( paramResourceTable + paramResource->resource + elementResourceIndex ); + ( *nvParams )->resIndex = ( tempResIndex == 0xFFFF ) ? -1 : ( int )tempResIndex; + for ( int row = 1; row <= ( int )rowCount; row++ ) + { + unsigned short tempResIndex = *( paramResourceTable + paramResource->resource + elementResourceIndex ) + row - 1; + ( *nvParams + row )->resIndex = ( tempResIndex == 0xFFFF ) ? -1 : ( int )tempResIndex; + } + } + else + { + unsigned short tempResIndex = *( paramResourceTable + paramResource->resource + elementResourceIndex * rowCount ); + ( *nvParams )->resIndex = ( tempResIndex == 0xFFFF ) ? -1 : ( int )tempResIndex; + for ( int row = 1; row <= ( int )rowCount; row++ ) + { + unsigned short tempResIndex = *( paramResourceTable + paramResource->resource + elementResourceIndex * rowCount + row - 1 ); + ( *nvParams + row )->resIndex = ( tempResIndex == 0xFFFF ) ? -1 : ( int )tempResIndex; + } + } + } + // not array + else + { + if ( !isMatrix(( CGtype )( paramResource->type ) ) ) + { + unsigned short tempResIndex = paramResource->resource; + ( *nvParams )->resIndex = ( tempResIndex == 0xFFFF ) ? -1 : ( int )tempResIndex; + } + else + { + if ( paramEntry->flags & CGP_CONTIGUOUS ) + { + unsigned short tempResIndex = paramResource->resource; + ( *nvParams )->resIndex = ( tempResIndex == 0xFFFF ) ? -1 : ( int )tempResIndex; + for ( int row = 1; row <= ( int )rowCount; row++ ) + { + unsigned short tempResIndex = paramResource->resource + row - 1; + ( *nvParams + row )->resIndex = ( tempResIndex == 0xFFFF ) ? -1 : ( int )tempResIndex; + } + } + else + { + unsigned short tempResIndex = *( paramResourceTable + paramResource->resource ); + ( *nvParams )->resIndex = ( tempResIndex == 0xFFFF ) ? -1 : ( int )tempResIndex; + for ( int row = 1; row <= ( int )rowCount; row++ ) + { + unsigned short tempResIndex = *( paramResourceTable + paramResource->resource + row - 1 ); + ( *nvParams + row )->resIndex = ( tempResIndex == 0xFFFF ) ? -1 : ( int )tempResIndex; + } + } + } + } + } + // fragment programs + else + { + unsigned short* resPtr = paramResourceTable + paramResource->resource; + + if ( elementResourceIndex >= 0 ) + { + // !!! matrices should be handled here too, i think + //advance resPtr to the arrayIndex + int skipCount = elementResourceIndex; + while ( skipCount ) + { + resPtr++; + int embeddedCount = *( resPtr++ ); + resPtr += embeddedCount; + // if an array of matrices, must skip row parameter resources too + for ( int row = 1; row <= ( int )rowCount; row++ ) + { + resPtr++; + int embeddedCount = *( resPtr++ ); + resPtr += embeddedCount; + } + skipCount--; + } + //resPtr points to the resource of the arrayIndex + } + + if ( !isMatrix(( CGtype )( paramResource->type ) ) ) + { + unsigned short tempResIndex = *( resPtr++ ); + ( *nvParams )->resIndex = ( tempResIndex == 0xFFFF ) ? -1 : ( int )tempResIndex; + unsigned int embeddedConstantCount = *( resPtr++ ); + ( *nvParamOffsets )->ucodeCount = embeddedConstantCount; + unsigned int ec = 0; + for ( ec = 0; ec < embeddedConstantCount; ec++ ) + { + ( *nvParamOffsets )->ucodeOffset[ec] = *( resPtr++ ); + } + // set the field in the nv param + ( *nvParams )->embeddedConst = ( char* )( *nvParamOffsets ) - nvBinary; + // forward pointer to nvParamOffsets + *nvParamOffsets = ( CgBinaryEmbeddedConstant* )( &(( *nvParamOffsets )->ucodeOffset[ec] ) ); + } + else + { + for ( int row = 1; row <= ( int )rowCount; row++ ) + { + unsigned short tempResIndex = *( resPtr++ ); + ( *nvParams + row )->resIndex = ( tempResIndex == 0xFFFF ) ? -1 : ( int )tempResIndex; + unsigned int embeddedConstantCount = *( resPtr++ ); + ( *nvParamOffsets )->ucodeCount = embeddedConstantCount; + unsigned int ec = 0; + for ( ec = 0; ec < embeddedConstantCount; ec++ ) + { + ( *nvParamOffsets )->ucodeOffset[ec] = *( resPtr++ ); + } + // set the field in the nv param + ( *nvParams + row )->embeddedConst = ( char* )( *nvParamOffsets ) - nvBinary; + // forward pointer to nvParamOffsets + *nvParamOffsets = ( CgBinaryEmbeddedConstant* )( &(( *nvParamOffsets )->ucodeOffset[ec] ) ); + } + } + } + } + + } + // RESOURCE DECODING ALGORTITHM END + + + // name + if ( paramEntry->nameOffset ) + { + // copy the name and store its offset in the param + // i think prefix is already handled for this base case + strcpy( *nvParamStrings, strtab->data + paramEntry->nameOffset ); + } + // set the name offset in the param, starting from the prefix + char* namebase = NULL; + if ( prefix ) + { + ( *nvParams )->name = prefix - nvBinary; + namebase = prefix; + } + else + { + ( *nvParams )->name = *nvParamStrings - nvBinary; + namebase = *nvParamStrings; + } + + + // increment the names cursor + *nvParamStrings += strlen( *nvParamStrings ) + 1; + + // and now handle the matrix rows + for ( int row = 1; row <= ( int )rowCount; row++ ) + { + // copy the name and store its offset in the param + sprintf( *nvParamStrings, "%s[%d]", namebase, row - 1 ); + // set the name offset in the param + ( *nvParams + row )->name = *nvParamStrings - nvBinary; + // increment the names cursor + *nvParamStrings += strlen( *nvParamStrings ) + 1; + } + + // totally inefficient, but easiest implementation for now is to do the On^2 search + // in the semantic and default tables for the data associated with this parameter + unsigned int entryIndex = paramEntry - paramEntries; + + // semantic + char* semantic = NULL; + for ( unsigned int sem = 0; sem < semanticIndexCount; sem++ ) + { + CgParameterSemantic* semanticIndex = semanticIndexTable + sem; + if ( semanticIndex->entryIndex == entryIndex ) + { + // found the semantic for this parameter + semantic = strtab->data + semanticIndex->semanticOffset; + break; + } + } + if ( semantic ) + { + // copy the name and store its offset in the param + strcpy( *nvParamStrings, semantic ); + // set the name offset in the param (or params if a matrix) + for ( int row = 0; row <= ( int )rowCount; row++ ) + { + ( *nvParams )->semantic = *nvParamStrings - nvBinary; + } + // increment the names cursor + *nvParamStrings += strlen( semantic ) + 1; + } + + // default + float* defaults = NULL; + for ( unsigned int def = 0; def < defaultIndexCount; def++ ) + { + CgParameterDefaultValue* defaultIndex = defaultIndexTable + def; + if ( defaultIndex->entryIndex == entryIndex ) + { + // found the default for this parameter + defaults = ( float* )consttab->data + defaultIndex->defaultValueIndex; + } + } + if ( defaults ) + { + // defaults are always padded to 4 floats per param + unsigned int defaultsCount = ( rowCount ? rowCount : 1 ) * 4; + // copy the values into the right place in the buffer + memcpy( *nvParamDefaults, defaults, defaultsCount * sizeof( float ) ); + // set the field in the param to point to them + if ( rowCount == 0 ) + { + ( *nvParams )->defaultValue = ( char* )( *nvParamDefaults ) - nvBinary; + } + else + { + for ( int row = 1; row <= ( int )rowCount; row++ ) + { + ( *nvParams + row )->defaultValue = ( char* )( *nvParamDefaults + 4 * ( row - 1 ) ) - nvBinary; + } + } + + // forward the buffer pointer + *nvParamDefaults += defaultsCount; + } + + + // fill other fields, once for the matrix and once for every row + for ( int row = 0; row <= ( int )rowCount; row++ ) + { + + // var + unsigned int variability = paramEntry->flags & CGPV_MASK; + if ( variability == CGPV_VARYING ) + ( *nvParams )->var = CG_VARYING; + else if ( variability == CGPV_UNIFORM ) + ( *nvParams )->var = CG_UNIFORM; + else if ( variability == CGPV_CONSTANT ) + ( *nvParams )->var = CG_CONSTANT; + else if ( variability == CGPV_MIXED ) + ( *nvParams )->var = CG_MIXED; + else + { + ( *nvParams )->var = ( CGenum )0; + } + + //direction + unsigned int direction = paramEntry->flags & CGPD_MASK; + if ( direction == CGPD_IN ) + ( *nvParams )->direction = CG_IN; + else if ( direction == CGPD_OUT ) + ( *nvParams )->direction = CG_OUT; + else if ( direction == CGPD_INOUT ) + ( *nvParams )->direction = CG_INOUT; + else + { + ( *nvParams )->direction = ( CGenum )0; + } + + // paramno + if ( paramEntry->flags & CGPF_GLOBAL ) + ( *nvParams )->paramno = -1; + else if ( paramEntry->flags & CGP_INTERNAL ) + ( *nvParams )->paramno = -2; + else + { + ( *nvParams )->paramno = *localParamNo; + if ( row == 0 ) + { + *localParamNo += 1; + } + } + + // isReferenced + ( *nvParams )->isReferenced = (( paramEntry->flags & CGPF_REFERENCED ) != 0 ); + + // isShared + ( *nvParams )->isShared = (( paramEntry->flags & CGPF_SHARED ) != 0 ); + + + // increment param cursor + *nvParams += 1; + + + } + + // entry cursor + *nextEntry = paramEntry + 1; + +} + +void PopulateDataForParamArray( CgParameterEntry* paramEntry, CgParameterEntry* paramEntries, unsigned int paramEntriesCount, + unsigned short* paramResourceTable, ELF_section_t* strtab, CgParameterEntry** nextEntry, + int elementResourceIndex, unsigned int* localParamNo, char* nvBinary, + CgBinaryParameter** nvParams, char** nvParamStrings, + CgBinaryEmbeddedConstant** nvParamOffsets, float** nvParamDefaults, + char* prefix, unsigned int prefixLength, + CgParameterSemantic* semanticIndexTable, unsigned int semanticIndexCount, + CgParameterDefaultValue* defaultIndexTable, unsigned int defaultIndexCount, + ELF_section_t* consttab ) +{ + // type index is actually the offset into the block of memory following the entries + CgParameterArray* paramArray = ( CgParameterArray* )(( char* )( paramEntries + paramEntriesCount ) + paramEntry->typeIndex ); + + // this would give the number of intrinsics OR structs, but if base type is struct + // to get the number of parameters, must recurse over struct fields + unsigned int numElements = 1; + for ( unsigned int dim = 0; dim < paramArray->dimensionCount; dim++ ) + { + numElements *= paramArray->dimensions[dim]; + }; + + // for name handling + char* prefixIn = prefix; + unsigned int prefixLengthIn = prefixLength; + + if ( !( paramEntry->flags & CGP_UNROLLED ) ) // one bit is not enough cause there are 3 representations! + { + // all elements are the same so have one entry to represent all of them + CgParameterEntry* elementEntry = paramEntry + 1; + + // entries are same type, and packed, so just repeat same param + for ( unsigned int element = 0; element < numElements; element++ ) + { + // where is the array name??? in paramEntry or elementEntry??? + + // name + // copy prefix if it's not the first element whose prefix is already in place + if ( element > 0 ) + { + strncpy( *nvParamStrings, prefixIn, prefixLengthIn ); + prefix = *nvParamStrings; + *nvParamStrings += prefixLengthIn; + } + // rest of array name for array and index + sprintf( *nvParamStrings, "%s[%d]", ( strtab->data + paramEntry->nameOffset ), element ); + + if ( prefix == NULL ) + { + prefix = *nvParamStrings; + } + + *nvParamStrings += strlen( *nvParamStrings ); + + prefixLength = strlen( prefix ); + + PopulateDataForParamResource( elementEntry, paramEntries, paramEntriesCount, + paramResourceTable, strtab, nextEntry, + element, localParamNo, nvBinary, + nvParams, nvParamStrings, nvParamOffsets, nvParamDefaults, + prefix, prefixLength, + semanticIndexTable, semanticIndexCount, + defaultIndexTable, defaultIndexCount, + consttab ); + + *nextEntry = *nextEntry - 1; // undo the increment on the next entry for this special case of shared entries + } + *nextEntry = *nextEntry + 1; // redo the increment on the next entry upon leaving the loop + } + else if ( paramEntry->flags & CGP_UNROLLED ) + { + // here everything is unrolled + + CgParameterEntry* elementEntry = paramEntry + 1; + + for ( unsigned int element = 0; element < numElements; element++ ) + { + // where is the array name??? in paramEntry or elementEntry??? + + // name + // copy prefix if it's not the first element whose prefix is already in place + if ( element > 0 ) + { + strncpy( *nvParamStrings, prefixIn, prefixLengthIn ); + prefix = *nvParamStrings; + *nvParamStrings += prefixLengthIn; + } + // rest of array name for array and index + sprintf( *nvParamStrings, "%s[%d]", ( strtab->data + paramEntry->nameOffset ), element ); + *nvParamStrings += strlen( *nvParamStrings ); + prefixLength = strlen( prefix ); + + PopulateDataForParams( elementEntry, paramEntries, paramEntriesCount, + paramResourceTable, strtab, nextEntry, + -1, localParamNo, nvBinary, + nvParams, nvParamStrings, nvParamOffsets, nvParamDefaults, + prefix, prefixLength, + semanticIndexTable, semanticIndexCount, + defaultIndexTable, defaultIndexCount, + consttab ); + + elementEntry = *nextEntry; + } + } +} + +void PopulateDataForParamStruct( CgParameterEntry* paramEntry, CgParameterEntry* paramEntries, unsigned int paramEntriesCount, + unsigned short* paramResourceTable, ELF_section_t* strtab, CgParameterEntry** nextEntry, + int elementResourceIndex, unsigned int* localParamNo, char* nvBinary, + CgBinaryParameter** nvParams, char** nvParamStrings, + CgBinaryEmbeddedConstant** nvParamOffsets, float** nvParamDefaults, + char* prefix, unsigned int prefixLength, + CgParameterSemantic* semanticIndexTable, unsigned int semanticIndexCount, + CgParameterDefaultValue* defaultIndexTable, unsigned int defaultIndexCount, + ELF_section_t* consttab ) +{ + // type index is actually the offset into the block of memory following the entries + CgParameterStructure* paramStruct = ( CgParameterStructure* )(( char* )( paramEntries + paramEntriesCount ) + paramEntry->typeIndex ); + + unsigned short memberCount = paramStruct->memberCount; + CgParameterEntry* memberEntry = paramEntry + 1; + + // set the prefix pointer if it is not already set + if ( prefix == NULL ) + { + prefix = *nvParamStrings; + } + // add prefix of struct name and . + // !!! but what about if we are inside an array??? then no struct name? or is . built in? + if ( paramEntry->nameOffset > 0 ) // is this the right test??? + { + // name + unsigned int nameLength = strlen( strtab->data + paramEntry->nameOffset ); + // copy the name and store its offset in the param + strcpy( *nvParamStrings, strtab->data + paramEntry->nameOffset ); + + // increment the names cursor but don't include null term + *nvParamStrings += nameLength; + prefixLength += nameLength; + } + + // add the dot + strcpy( *nvParamStrings, "." ); + *nvParamStrings += 1; + prefixLength += 1; + + for ( unsigned int member = 0; member < memberCount; member++ ) + { + // put the prefix in place for each subsequent member + if ( member > 0 ) + { + strncpy( *nvParamStrings, prefix, prefixLength ); + prefix = *nvParamStrings; + *nvParamStrings += prefixLength; + } + + PopulateDataForParams( memberEntry, paramEntries, paramEntriesCount, + paramResourceTable, strtab, nextEntry, + -1, localParamNo, nvBinary, + nvParams, nvParamStrings, nvParamOffsets, nvParamDefaults, + prefix, prefixLength, + semanticIndexTable, semanticIndexCount, + defaultIndexTable, defaultIndexCount, + consttab ); + + memberEntry = *nextEntry; + } +} + +void PopulateDataForParams( CgParameterEntry* paramEntry, CgParameterEntry* paramEntries, unsigned int paramEntriesCount, + unsigned short* paramResourceTable, ELF_section_t* strtab, CgParameterEntry** nextEntry, + int elementResourceIndex, unsigned int* localParamNo, char* nvBinary, + CgBinaryParameter** nvParams, char** nvParamStrings, + CgBinaryEmbeddedConstant** nvParamOffsets, float** nvParamDefaults, + char* prefix, unsigned int prefixLength, + CgParameterSemantic* semanticIndexTable, unsigned int semanticIndexCount, + CgParameterDefaultValue* defaultIndexTable, unsigned int defaultIndexCount, + ELF_section_t* consttab ) +{ + + // expand for intrinsics, arrays, and structs + // flags hold which type of parameter it is (along with other information) + switch ( paramEntry->flags & CGP_TYPE_MASK ) + { + case CGP_INTRINSIC: + { + //printf("resource --- %p\n", paramEntry); + PopulateDataForParamResource( paramEntry, paramEntries, paramEntriesCount, + paramResourceTable, strtab, nextEntry, + elementResourceIndex, localParamNo, nvBinary, + nvParams, nvParamStrings, nvParamOffsets, nvParamDefaults, + prefix, prefixLength, + semanticIndexTable, semanticIndexCount, + defaultIndexTable, defaultIndexCount, + consttab ); + break; + } + case CGP_ARRAY: + { + //printf("array --- %p\n", paramEntry); + PopulateDataForParamArray( paramEntry, paramEntries, paramEntriesCount, + paramResourceTable, strtab, nextEntry, + elementResourceIndex, localParamNo, nvBinary, + nvParams, nvParamStrings, nvParamOffsets, nvParamDefaults, + prefix, prefixLength, + semanticIndexTable, semanticIndexCount, + defaultIndexTable, defaultIndexCount, + consttab ); + break; + } + case CGP_STRUCTURE: + { + //printf("structure --- %p\n", paramEntry); + PopulateDataForParamStruct( paramEntry, paramEntries, paramEntriesCount, + paramResourceTable, strtab, nextEntry, + elementResourceIndex, localParamNo, nvBinary, + nvParams, nvParamStrings, nvParamOffsets, nvParamDefaults, + prefix, prefixLength, + semanticIndexTable, semanticIndexCount, + defaultIndexTable, defaultIndexCount, + consttab ); + break; + } + default: + { + break; + } + + } +} + +bool rglCgCreateProgramChecks( CGcontext ctx, CGprofile profile, CGenum program_type ) +{ + // check context + if ( !CG_IS_CONTEXT( ctx ) ) + { + rglCgRaiseError( CG_INVALID_CONTEXT_HANDLE_ERROR ); + return false; + } + + // check the profile. + switch ( profile ) + { + case CG_PROFILE_SCE_VP_TYPEB: + case CG_PROFILE_SCE_FP_TYPEB: + case CG_PROFILE_SCE_VP_RSX: + case CG_PROFILE_SCE_FP_RSX: + break; + default: + rglCgRaiseError( CG_UNKNOWN_PROFILE_ERROR ); + return false; + } + + // check the program_type + switch ( program_type ) + { + case CG_BINARY: + case CG_SOURCE: + break; + default: // currently reject CG_OBJECT (assembly code in ASCII) and CG_UNDEFINED + rglCgRaiseError( CG_INVALID_ENUMERANT_ERROR ); + return false; + } + + return true; +} + +bool cgOpenElf( const void *ptr, size_t size, CGELFBinary *elfBinary ) +{ + while ( 1 ) + { + size_t symbolSize; + size_t symbolCount; + const char *symbolstrtab; + const char *symtab = findSymbolSectionInPlace((const char *)ptr, &symbolSize, &symbolCount, &symbolstrtab ); + if ( !symtab ) + break; + + size_t shadertabSize; + const char *shadertab = findSectionInPlace((const char*)ptr, ".shadertab", &shadertabSize ); + if ( !shadertab ) + break; + size_t strtabSize; + const char *strtab = findSectionInPlace((const char*)ptr, ".strtab", &strtabSize ); + if ( !strtab ) + break; + size_t consttabSize; + const char *consttab = findSectionInPlace((const char* )ptr, ".const", &consttabSize ); + if ( !consttab ) + break; + + elfBinary->elfFile = ( const char* )ptr; + elfBinary->elfFileSize = size; + elfBinary->symtab = symtab; + elfBinary->symbolSize = symbolSize; + elfBinary->symbolCount = symbolCount; + elfBinary->symbolstrtab = symbolstrtab; + + elfBinary->shadertab = shadertab; + elfBinary->shadertabSize = shadertabSize; + elfBinary->strtab = strtab; + elfBinary->strtabSize = strtabSize; + + elfBinary->consttab = consttab; + elfBinary->consttabSize = consttabSize; + + return true; + } + + return false; +} + +bool cgGetElfProgramByIndex( CGELFBinary *elfBinary, int index, CGELFProgram *elfProgram ) +{ + while ( true ) + { + char sectionName[64]; + sprintf( sectionName, ".text%04i", index ); + size_t texttabSize; + const char *texttab = findSectionInPlace( elfBinary->elfFile, sectionName, &texttabSize ); + if ( !texttab ) + break; + sprintf( sectionName, ".paramtab%04i", index ); + size_t paramtabSize; + const char *paramtab = findSectionInPlace( elfBinary->elfFile, sectionName, ¶mtabSize ); + if ( !paramtab ) + break; + + elfProgram->texttab = texttab; + elfProgram->texttabSize = texttabSize; + elfProgram->paramtab = paramtab; + elfProgram->paramtabSize = paramtabSize; + elfProgram->index = index; + return true; + } + return false; +} + +static bool cgGetElfProgramByName( CGELFBinary *elfBinary, const char *name, CGELFProgram *elfProgram ) +{ + //if no name try to return the first program + int res; + if ( name == NULL || name[0] == '\0' ) + res = 0; + else + res = lookupSymbolValueInPlace( elfBinary->symtab, elfBinary->symbolSize, elfBinary->symbolCount, elfBinary->symbolstrtab, name ); + + if ( res != -1 ) + return cgGetElfProgramByIndex( elfBinary, res, elfProgram ); + else + return false; +} + +CGprogram rglCgCreateProgram( CGcontext ctx, CGprofile profile, const CgProgramHeader *programHeader, const void *ucode, const CgParameterTableHeader *parameterHeader, const char *stringTable, const float *defaultValues ) +{ + // Create the program structure. + // all the structural data is filled in here, + // as well as the profile. + // The parameters and the actual program are generated from the ABI specific calls. + + _CGprogram* prog = ( _CGprogram* )malloc( sizeof( _CGprogram ) ); + if ( NULL == prog ) + { + rglCgRaiseError( CG_MEMORY_ALLOC_ERROR ); + return NULL; + } + + // zero out the fields + rglCgProgramZero( prog ); + + // fill in the fields we know + prog->parentContext = _cgGetContextPtr( ctx ); + prog->header.profile = profile; + + int success = 0; + + // create a name for the program and record it in the object + CGprogram id = ( CGprogram )rglCreateName( &_CurrentContext->cgProgramNameSpace, prog ); + if ( !id ) + { + free( prog ); + rglCgRaiseError( CG_MEMORY_ALLOC_ERROR ); + return NULL; + } + prog->id = id; + + //hack to counter removal of TypeC during beta + if ( profile == ( CGprofile )7005 ) + profile = CG_PROFILE_SCE_VP_RSX; + if ( profile == ( CGprofile )7006 ) + profile = CG_PROFILE_SCE_FP_RSX; + + // load the binary into the program object + switch ( profile ) + { + case CG_PROFILE_SCE_VP_TYPEB: + //case CG_PROFILE_SCE_VP_TYPEC: + case CG_PROFILE_SCE_VP_RSX: + // TODO ************** need to include the entry symbol too + success = rglpGenerateVertexProgram( prog, programHeader, ucode, parameterHeader, stringTable, defaultValues ); + break; + case CG_PROFILE_SCE_FP_TYPEB: + //case CG_PROFILE_SCE_FP_TYPEC: + case CG_PROFILE_SCE_FP_RSX: + success = rglpGenerateFragmentProgram( prog, programHeader, ucode, parameterHeader, stringTable, defaultValues ); + break; + default: + // should never reach here + break; + } + + // if the creation failed, free all resources. + // the error was raised when the error was encoutered. + if ( success == 0 ) + { + // free the program object + free( prog ); + // release the id too + rglEraseName( &_CurrentContext->cgProgramNameSpace, (unsigned int)id ); + return NULL; + } + + // success! add the program to the program list in the context. + rglCgProgramPushFront( prog->parentContext, prog ); + if ( _cgProgramCreateHook ) _cgProgramCreateHook( prog ); + + // everything worked. + return id; +} + +CG_API CGprogram cgCreateProgram( CGcontext ctx, + CGenum program_type, + const char* program, + CGprofile profile, + const char* entry, + const char** args ) +{ + // Load a program from a memory pointer. + // NOTE: in our API all programs are pre-compiled binaries + // so entry point and compiler arguments are ignored. + + //hack to counter removal of TypeC during beta + if ( profile == ( CGprofile )7005 ) + profile = CG_PROFILE_SCE_VP_RSX; + if ( profile == ( CGprofile )7006 ) + profile = CG_PROFILE_SCE_FP_RSX; + + //hack to counter change of defines for program_type at r5294 + // previously CG_BINARY was defined the same as CG_ROW_MAJOR + // if those values are passed in here, move them to the new values and remove this hack after we have + // an sdk that incorporates these changes so that prebuild libs (aka debugfont) can be used meanwhile + if ( program_type == CG_ROW_MAJOR ) + program_type = CG_BINARY; + + if ( !rglCgCreateProgramChecks( ctx, profile, program_type ) ) + return NULL; + + //data to extract from the buffer passed: + CgProgramHeader *programHeader = NULL; + const void *ucode = NULL; + CgParameterTableHeader *parameterHeader = NULL; + const char *stringTable = NULL; + const float *defaultValues = NULL; + + //first step, compile any source file + const char *binaryBuffer = NULL; + char* compiled_program = NULL; + if ( program_type == CG_SOURCE ) + { + if ( _cgRTCgcCompileProgramHook ) + { + _cgRTCgcCompileProgramHook( program, cgGetProfileString( profile ), entry, args, &compiled_program ); + if ( !compiled_program ) + { + rglCgRaiseError( CG_COMPILER_ERROR ); + return NULL; + } + binaryBuffer = compiled_program; + } + else + { + //_RGL_REPORT_EXTRA( RGL_REPORT_CG_ERROR, "The CG runtime compiler hasn't been setup. cgRTCgcInit() should be called prior to this function." ); + rglCgRaiseError( CG_INVALID_ENUMERANT_ERROR ); + return NULL; + } + } + else + binaryBuffer = program; + + bool bConvertedToElf = false; + + //At that point we have a binary file which is either any ELF or an NV format file + const unsigned int ElfTag = 0x7F454C46; // == MAKEFOURCC(0x7F,'E','L','F'); + if ( !( *( unsigned int* )binaryBuffer == ElfTag ) ) + { + //we have an NV file, convert it to the runtime format + + // if it was initially binary, throw warning about old format and recommend conversion to new with cgnv2elf + // don't throw the warning if it was source, cause clearly that would have been on purpose. + if ( program_type == CG_BINARY ) + { + //_RGL_REPORT_EXTRA( RGL_REPORT_CG_ERROR, "A binary shader is being loaded using a deprecated binary format. Please use the cgnv2elf tool to convert to the new, memory-saving, faster-loading format." ); + } + + //convert from NV format to the runtime format + int compiled_program_size = 0; + std::vector stringTableArray; + std::vector defaultValuesArray; + CgBinaryProgram* nvProgram = ( CgBinaryProgram* )binaryBuffer; + char *runtimeElfShader = NULL; + //check the endianness + int totalSize; + if (( nvProgram->profile != CG_PROFILE_SCE_FP_TYPEB ) && ( nvProgram->profile != CG_PROFILE_SCE_VP_TYPEB ) && + ( nvProgram->profile != ( CGprofile )7006 ) && ( nvProgram->profile != ( CGprofile )7005 ) && + ( nvProgram->profile != CG_PROFILE_SCE_FP_RSX ) && ( nvProgram->profile != CG_PROFILE_SCE_VP_RSX ) ) + { + totalSize = endianSwapWord( nvProgram->totalSize ); + } + else + totalSize = nvProgram->totalSize; + int res = convertNvToElfFromMemory( binaryBuffer, totalSize, 2, 0, ( void** ) & runtimeElfShader, &compiled_program_size, stringTableArray, defaultValuesArray ); + if (res != 0) + { + //_RGL_REPORT_EXTRA( RGL_REPORT_CG_ERROR, "invalid CG binary program" ); + rglCgRaiseError( CG_COMPILER_ERROR ); + if ( compiled_program ) + _cgRTCgcFreeCompiledProgramHook( compiled_program ); + return NULL; + } + + if ( compiled_program ) + _cgRTCgcFreeCompiledProgramHook( compiled_program ); + + //TODO: remove all the unnecessary data shuffling, when this gets included in the compiler + //prepare the same buffer as the one that would be extracted from the binary file + size_t stringTableSize = stringTableArray.size() * sizeof( stringTable[0] ); + size_t defaultTableSize = defaultValuesArray.size() * sizeof( defaultValues[0] ); + int paddedSize = rglPad( compiled_program_size, 4 ); + //the following pointer will be remembered in the _CGprogram structure to be freed when the + //program will be deleted, the ucode and the param info are used in place at runtime + char *runtimeElf = ( char* )memalign( 16, paddedSize + stringTableSize + defaultTableSize ); + if ( !runtimeElf ) + { + rglCgRaiseError( CG_MEMORY_ALLOC_ERROR ); + return NULL; + } + bConvertedToElf = true; //to free the memalign + //program header, ucode and parameters + memcpy( runtimeElf, runtimeElfShader, compiled_program_size ); + + //we can free the intermediate buffer used to receive the converted program //may be we should keep it rather than reallocating ? + convertNvToElfFreeBinaryShader( runtimeElfShader ); + + //default values + //the pointer is stored right after the program data ( padded to 4 ) and after the string table pointer + float* pDefaultValues = ( float* )(( char* )runtimeElf + paddedSize ); + defaultValues = pDefaultValues; + + if ( defaultTableSize ) + memcpy( pDefaultValues, &defaultValuesArray[0], defaultTableSize ); + + //string table + //the pointer is stored right after the program data ( padded to 4 ) + char *pStringTable = ( char* )runtimeElf + paddedSize + defaultTableSize; + stringTable = pStringTable; + + if ( stringTableSize ) + memcpy( pStringTable, &stringTableArray[0], stringTableSize ); + + + //success + programHeader = ( CgProgramHeader* )runtimeElf; + size_t elfUcodeSize = programHeader->instructionCount * 16; + size_t ucodeOffset = rglPad( sizeof( CgProgramHeader ), 16 ); + size_t parameterOffset = rglPad( ucodeOffset + elfUcodeSize, 16 ); + ucode = ( char* )runtimeElf + ucodeOffset; + parameterHeader = ( CgParameterTableHeader* )(( char* )runtimeElf + parameterOffset ); + } + else + { + //we have an ELF file, it will be used in place ( case where the elf file has been passed as a memory pointer ) + CGELFBinary elfBinary; + CGELFProgram elfProgram; + if ((( intptr_t )binaryBuffer ) & 15 ) + { + //_RGL_REPORT_EXTRA( RGL_REPORT_CG_ERROR, "CG Binary not aligned on 16 bytes, needed for ucode section" ); + rglCgRaiseError( CG_PROGRAM_LOAD_ERROR ); + return NULL; + } + bool res = cgOpenElf( binaryBuffer, 0, &elfBinary ); + if ( !res ) + { + //_RGL_REPORT_EXTRA( RGL_REPORT_CG_ERROR, "not a valid ELF" ); + rglCgRaiseError( CG_PROGRAM_LOAD_ERROR ); + return NULL; + } + if ( !cgGetElfProgramByName( &elfBinary, entry, &elfProgram ) ) + { + //_RGL_REPORT_EXTRA( RGL_REPORT_CG_ERROR, "couldn't find the shader entry in the CG binary" ); + return NULL; + } + + //success + programHeader = ( CgProgramHeader* )elfBinary.shadertab + elfProgram.index; + ucode = ( char* )elfProgram.texttab; + parameterHeader = ( CgParameterTableHeader* )elfProgram.paramtab; + stringTable = elfBinary.strtab; + defaultValues = ( float* )elfBinary.consttab; + } + + CGprogram prog = rglCgCreateProgram( ctx, profile, programHeader, ucode, parameterHeader, stringTable, defaultValues ); + + //if we used the runtime compiler/converter we need to delete the buffer on exit + if ( bConvertedToElf ) + { + _CGprogram* ptr = _cgGetProgPtr( prog ); + ptr->runtimeElf = programHeader; + } + + return prog; +} + +CG_API CGprogram cgCreateProgramFromFile( CGcontext ctx, + CGenum program_type, + const char* program_file, + CGprofile profile, + const char* entry, + const char** args ) +{ + //hack to counter removal of TypeC during beta + if ( profile == ( CGprofile )7005 ) + profile = CG_PROFILE_SCE_VP_RSX; + if ( profile == ( CGprofile )7006 ) + profile = CG_PROFILE_SCE_FP_RSX; + + //hack to counter change of defines for program_type at r5294 + // previously CG_BINARY was defined the same as CG_ROW_MAJOR + // if those values are passed in here, move them to the new values and remove this hack after we have + // an sdk that incorporates these changes so that prebuild libs (aka debugfont) can be used meanwhile + if ( program_type == CG_ROW_MAJOR ) + program_type = CG_BINARY; + + if ( !rglCgCreateProgramChecks( ctx, profile, program_type ) ) + return NULL; + + // load a program from a file + // NOTE: in our API all programs are pre-compiled binaries + // so profile and compiler arguments are ignored. + FILE* fp = NULL; + if ( RGL_LIKELY( program_type == CG_BINARY ) ) + { + CGprogram ret = NULL; + //assume we have an elf at that point + //if (filetag == ElfTag) + + _CGcontext *context = _cgGetContextPtr( ctx ); + CGprogramGroup group = NULL; + + //can we find it in the groups already loaded ? + group = context->groupList; + while ( group ) + { + //check the group name + const char *groupName = rglCgGetProgramGroupName( group ); + if ( groupName && !strcmp( groupName, program_file ) ) + { + int index; + if ( entry == NULL ) + index = 0; + else + index = rglCgGetProgramIndex( group, entry ); + if ( index >= 0 ) + { + ret = rglpCgUpdateProgramAtIndex( group, index, 1 ); + break; + } + else + { + //we couldn't find the entry in the group which has the right name + return ( CGprogram )NULL; + } + } + group = group->next; + } + + if ( ret ) + return ret; + else + { + //do we have an elf file ? + //read file tag: + // check that file exists + fp = fopen( program_file, "rb" ); + + if ( NULL == fp ) + { + rglCgRaiseError( CG_FILE_READ_ERROR ); + return ( CGprogram )NULL; + } + + unsigned int filetag = 0; + int res = fread( &filetag, sizeof( filetag ), 1, fp ); + if ( !res ) + { + fclose( fp ); + rglCgRaiseError( CG_FILE_READ_ERROR ); + return ( CGprogram )NULL; + } + const unsigned int ElfTag = 0x7F454C46; // == MAKEFOURCC(0x7F,'E','L','F'); + if ( filetag == ElfTag ) + { + fclose( fp ); + + group = rglCgCreateProgramGroupFromFile( ctx, program_file ); + if ( group ) + { + _CGprogramGroup *_group = ( _CGprogramGroup * )group; + _group->userCreated = false; + if ( entry == NULL ) + { + if ( group->programCount == 1 ) + { + ret = rglpCgUpdateProgramAtIndex( group, 0, 1 ); + } + } + else + { + int index = rglCgGetProgramIndex( group, entry ); + if ( index == -1 ) + { + //_RGL_REPORT_EXTRA( RGL_REPORT_CG_ERROR, "couldn't find the shader entry in the CG binary" ); + } + else + { + ret = rglpCgUpdateProgramAtIndex( group, index, 1 ); + } + } + } + return ret; + } + //else + //rewind(); //we should rewind here, but no need since we are doing fseek after + } + } + + //we have a NV file or a CG source: + if ( !fp ) + { + fp = fopen( program_file, "rb" ); + if ( NULL == fp ) + { + rglCgRaiseError( CG_FILE_READ_ERROR ); + return ( CGprogram )NULL; + } + } + + // find the file length + size_t file_size = 0; + fseek( fp, 0, SEEK_END ); + file_size = ftell( fp ); + rewind( fp ); + + // alloc memory for the file + char* ptr = ( char* )malloc( file_size + 1 ); + if ( NULL == ptr ) + { + rglCgRaiseError( CG_MEMORY_ALLOC_ERROR ); + fclose( fp ); + return ( CGprogram )NULL; + } + + // read the entire file into memory then close the file + // TODO ********* just loading the file is a bit lame really. We can do better. + fread( ptr, file_size, 1, fp ); + fclose( fp ); + + if ( program_type == CG_SOURCE ) + { + ptr[file_size] = '\0'; + } + + // call the CreateProgram API to do the rest of the job. + CGprogram ret = cgCreateProgram( ctx, program_type, ptr, profile, entry, args ); + + // free the memory for the file, we're done with it + free( ptr ); + + return ret; +} + +CG_API CGprogram cgCopyProgram( CGprogram program ) +{ + // check input parameter + + if ( !CG_IS_PROGRAM( program ) ) + { + rglCgRaiseError( CG_INVALID_PROGRAM_HANDLE_ERROR ); + return NULL; + } + _CGprogram* prog = _cgGetProgPtr( program ); + if ( NULL == prog ) + { + rglCgRaiseError( CG_INVALID_PROGRAM_HANDLE_ERROR ); + return ( CGprogram )NULL; + } + + _CGprogram* newprog; + size_t paddedProgramSize = 0; + size_t ucodeSize = 0; + + if (prog->header.profile == CG_PROFILE_SCE_FP_TYPEB || prog->header.profile == CG_PROFILE_SCE_FP_RSX) + { + paddedProgramSize = rglPad( sizeof( _CGprogram ), 16); + ucodeSize = prog->header.instructionCount * 16; + newprog = ( _CGprogram* )malloc( paddedProgramSize + ucodeSize ); + } + else + { + newprog = ( _CGprogram* )malloc( sizeof( _CGprogram ) ); + } + + if ( NULL == newprog ) + { + rglCgRaiseError( CG_MEMORY_ALLOC_ERROR ); + return ( CGprogram )NULL; + } + rglCgProgramZero( newprog ); + + // copy information from the old program + newprog->header.profile = prog->header.profile; + newprog->parentContext = prog->parentContext; + + // generate a new id + newprog->id = ( CGprogram )rglCreateName( &_CurrentContext->cgProgramNameSpace, newprog ); + + // copy all the parameter information + + + // copy the binary program information + // TODO ******** copy the entire elf here, not just the executable. + int success = 0; + switch ( prog->header.profile ) + { + case CG_PROFILE_SCE_VP_TYPEB: + //case CG_PROFILE_SCE_VP_TYPEC: + case CG_PROFILE_SCE_VP_RSX: + case CG_PROFILE_SCE_FP_TYPEB: + //case CG_PROFILE_SCE_FP_TYPEC: + case CG_PROFILE_SCE_FP_RSX: + success = rglpCopyProgram( prog, newprog ); + break; + default: + rglCgRaiseError( CG_UNKNOWN_PROFILE_ERROR ); + success = 0; + break; + } + + if ( success == 0 ) + { + // we failed to create a new program object, clean up + free( newprog ); + rglEraseName( &_CurrentContext->cgProgramNameSpace, (unsigned int)newprog->id ); + return ( CGprogram )NULL; + } + + if (prog->header.profile == CG_PROFILE_SCE_FP_TYPEB || prog->header.profile == CG_PROFILE_SCE_FP_RSX) + { + newprog->ucode = (char*)newprog + paddedProgramSize; + memcpy((char*)newprog->ucode, (char*)prog->ucode, ucodeSize); + } + + //handle refcounting for string table and default values + if ( prog->programGroup ) + { + //refcount for the string and the default table + newprog->programGroup = prog->programGroup; + newprog->programIndexInGroup = -1; + rglpCgUpdateProgramAtIndex( newprog->programGroup, -1, 1 ); + } + + // add the new program object to the program list in the context + rglCgProgramPushFront( newprog->parentContext, newprog ); + + if ( _cgProgramCopyHook ) _cgProgramCopyHook( newprog, prog ); + + return newprog->id; +} + + +CG_API void cgDestroyProgram( CGprogram program ) +{ + // remove the program from the program list + + // check the program input + if ( !CG_IS_PROGRAM( program ) ) + { + rglCgRaiseError( CG_INVALID_PROGRAM_HANDLE_ERROR ); + return; + } + _CGprogram* ptr = _cgGetProgPtr( program ); + if ( NULL == ptr ) + { + rglCgRaiseError( CG_INVALID_PROGRAM_HANDLE_ERROR ); + return; + } + + if ( ptr->programGroup ) + { + if ( !ptr->programGroup->userCreated ) + { + if ( ptr->programIndexInGroup != -1 && ptr->programGroup->programs[ptr->programIndexInGroup].refCount == 0 ) + { + //not a valid handle, the refcount is 0, this handle has already been freed + rglCgRaiseError( CG_INVALID_PROGRAM_HANDLE_ERROR ); + return; + } + else + { + bool isGroupMember = ( ptr->programIndexInGroup != -1 ); + rglpCgUpdateProgramAtIndex( ptr->programGroup, ptr->programIndexInGroup, -1 ); + if ( isGroupMember ) + return; + //else continue, it needs to be deleted here, the group won't delete it. + //such program which have a programGroup but are not member of the group are + //clone of a program coming from a group. but those program still need the group + //because the group holds their stringtable and their default table. + } + } + } + + // get the context that this program belongs to. + _CGcontext* ctx = ptr->parentContext; + + // find and unlink the program from the program list + if ( ptr == ctx->programList ) + { + // node is the head of the list, so unlink it. + _CGprogram* p = ctx->programList; + ctx->programList = p->next; + // erase the program + rglCgProgramEraseAndFree( p ); + } + else + { + // node not the head, so use find_previous and delete_after + // NOTE: if the program is not found in the list, returns silently. + _CGprogram* p = rglCgProgramFindPrev( ctx, ptr ); + rglCgProgramEraseAfter( p ); + } + return; +} + + +CG_API CGprogram cgGetFirstProgram( CGcontext ctx ) +{ + if ( !CG_IS_CONTEXT( ctx ) ) + { + rglCgRaiseError( CG_INVALID_CONTEXT_HANDLE_ERROR ); + return ( CGprogram )NULL; + } + // check context + _CGcontext* c = _cgGetContextPtr( ctx ); + + // return the id of the head of the program list in the context (got all that? good) + _CGprogram* ptr = c->programList; + if ( ptr ) + { + // if any programs have been allocated... + return c->programList->id; + } + + return ( CGprogram )NULL; +} + +CG_API CGprogram cgGetNextProgram( CGprogram current ) +{ + // check the program input + if ( !CG_IS_PROGRAM( current ) ) + { + rglCgRaiseError( CG_INVALID_PROGRAM_HANDLE_ERROR ); + return NULL; + } + _CGprogram* ptr = _cgGetProgPtr( current ); + + // increment the iterator down the program list + if ( ptr->next != NULL ) + { + return ptr->next->id; + } + + // failed, so return an empty program + return NULL; +} + +CG_API CGcontext cgGetProgramContext( CGprogram prog ) +{ + // check the program input + if ( !CG_IS_PROGRAM( prog ) ) + { + rglCgRaiseError( CG_INVALID_PROGRAM_HANDLE_ERROR ); + return NULL; + } + _CGprogram* ptr = _cgGetProgPtr( prog ); + + return ptr->parentContext->id; +} + +CG_API CGbool cgIsProgram( CGprogram program ) +{ + if ( CG_IS_PROGRAM( program ) ) + { + // the id was valid. + return CG_TRUE; + } + // failed to find a valid id. + return CG_FALSE; +} + +CG_API void cgCompileProgram( CGprogram program ) +{ + // check the program input + if ( !CG_IS_PROGRAM( program ) ) + { + rglCgRaiseError( CG_INVALID_PROGRAM_HANDLE_ERROR ); + return; + } + + // TODO ****** use this function to re-link our program after creating parameter objects? + + return; +} + +CG_API CGbool cgIsProgramCompiled( CGprogram program ) +{ + // check the program input + if ( !CG_IS_PROGRAM( program ) ) + { + rglCgRaiseError( CG_INVALID_PROGRAM_HANDLE_ERROR ); + return CG_FALSE; + } + + // TODO ********** use this function to find out if our program has unresolved symbols? + + return CG_TRUE; +} + +CG_API const char* cgGetProgramString( CGprogram prog, CGenum pname ) +{ + // check the program input + if ( !CG_IS_PROGRAM( prog ) ) + { + rglCgRaiseError( CG_INVALID_PROGRAM_HANDLE_ERROR ); + return NULL; + } + + //hack to counter change of defines for program_type at r5294 + // previously CG_PROGRAM_FILENAME was defined the same as CG_COLUMN_MAJOR + // if those values are passed in here, move them to the new values and remove this hack after we have + // an sdk that incorporates these changes so that prebuild libs (aka debugfont) can be used meanwhile + if ( pname == CG_COLUMN_MAJOR ) + pname = CG_PROGRAM_FILENAME; + + switch ( pname ) + { + case CG_PROGRAM_SOURCE: + // the original Cg source program is returned + // all programs in our API are pre-compiled and come without source. + return NULL; + + case CG_PROGRAM_ENTRY: + // the main entry point for the program is returned + // TODO *********** return the name of the entry point + return NULL; + + case CG_PROGRAM_PROFILE: + // the profile for the program is returned + { + const char *result = cgGetProfileString(( CGprofile )_cgGetProgPtr( prog )->header.profile ); + return result; + } + + case CG_COMPILED_PROGRAM: + // the string for the object program is returned + return NULL; + + case CG_PROGRAM_FILENAME: + // TODO *************** + // Return the filename of the source ELF this program came from + return ( char* )_cgGetProgPtr( prog )->platformProgram; + + case CG_BINARY: + // TODO *************** + // Create a whole new function for handling binaries - return charand length. + // we'll return an image pointer for now... + return ( char* )_cgGetProgPtr( prog )->platformProgram; + + default: + rglCgRaiseError( CG_INVALID_ENUMERANT_ERROR ); + } + + return NULL; +} + +CG_API void CGENTRY cgSetLastListing( CGhandle handle, const char *listing ) +{ + return; +} + +CG_API CGprofile cgGetProgramProfile( CGprogram prog ) +{ + // check the program input + if ( !CG_IS_PROGRAM( prog ) ) + { + rglCgRaiseError( CG_INVALID_PROGRAM_HANDLE_ERROR ); + return CG_PROFILE_UNKNOWN; + } + + // return the profile the program was compiled under + return ( CGprofile )_cgGetProgPtr( prog )->header.profile; +} + +CG_API int cgGetNumProgramDomains( CGprogram program ) +{ + // check the program input + if ( !CG_IS_PROGRAM( program ) ) + { + rglCgRaiseError( CG_INVALID_PROGRAM_HANDLE_ERROR ); + return CG_PROFILE_UNKNOWN; + } + // under Jetstream, unlike GLSL, all programs have a single domain. + return 1; +} + +CG_API CGprogram cgCombinePrograms( int n, const CGprogram *exeList ) +{ + // jetstream does not support combination of GLSL programs. + return 0; +} + +CG_API CGprogram cgCombinePrograms2( const CGprogram exe1, const CGprogram exe2 ) +{ + // jetstream does not support combination of GLSL programs. + return 0; +} + +CG_API CGprogram cgCombinePrograms3( const CGprogram exe1, const CGprogram exe2, const CGprogram exe3 ) +{ + // jetstream does not support combination of GLSL programs. + return 0; +} + +CG_API CGprofile cgGetProgramDomainProfile( CGprogram program, int index ) +{ + // check the program input + if ( !CG_IS_PROGRAM( program ) ) + { + rglCgRaiseError( CG_INVALID_PROGRAM_HANDLE_ERROR ); + return CG_PROFILE_UNKNOWN; + } + + if ( index >= 1 ) + { + // jetstream programs can only have a single domain + return CG_PROFILE_UNKNOWN; + } + + // return the single profile under which the shader was compiled. + return ( CGprofile )_cgGetProgPtr( program )->header.profile; +} + +CG_API char const * const * cgGetProgramOptions( CGprogram program ) +{ + // check the program input + if ( !CG_IS_PROGRAM( program ) ) + { + rglCgRaiseError( CG_INVALID_PROGRAM_HANDLE_ERROR ); + return NULL; + } + + // NOTE: currently unsupported by Jetstream precompiled programs + // TODO: get program options from ".note.MyShader" section of CG ELF Binary + // or from compiler arguments of a runtime-compiled program. + return NULL; +} + +/*============================================================ + CG GL + ============================================================ */ + +inline static float *rglGetUniformValuePtr( CGparameter param, CgRuntimeParameter *rtParameter ) +{ + float* value = ( float* )( rtParameter->pushBufferPointer ); + + // check in bounds to know if you should even bother checking that it is in an array + if ( rtParameter > rtParameter->program->runtimeParameters ) + { + CgRuntimeParameter *rtInArrayCheckParameter = rtParameter - 1; + // check is array + if ( rtInArrayCheckParameter->parameterEntry->flags & CGP_ARRAY ) + { + value = *(( float** )( rtParameter->pushBufferPointer ) + CG_GETINDEX( param ) ); + } + } + return value; +} + + +// endian swapping of the fragment uniforms, if necessary +#if RGL_ENDIAN == RGL_BIG_ENDIAN +#define SWAP_IF_BE(arg) endianSwapWordByHalf(arg) +#else +#define SWAP_IF_BE(arg) arg +#endif + + +/****************************************************************************** + *** Profile Functions + *****************************************************************************/ + +CGGL_API CGbool cgGLIsProfileSupported( CGprofile profile ) +{ + //hack to counter removal of TypeC during beta + if ( profile == ( CGprofile )7005 ) + profile = CG_PROFILE_SCE_VP_RSX; + if ( profile == ( CGprofile )7006 ) + profile = CG_PROFILE_SCE_FP_RSX; + + switch ( profile ) + { + case CG_PROFILE_SCE_VP_TYPEB: + //case CG_PROFILE_SCE_VP_TYPEC: + case CG_PROFILE_SCE_VP_RSX: + return ( CGbool ) rglpSupportsVertexProgram( profile ); + case CG_PROFILE_SCE_FP_TYPEB: + //case CG_PROFILE_SCE_FP_TYPEC: + case CG_PROFILE_SCE_FP_RSX: + return ( CGbool ) rglpSupportsFragmentProgram( profile ); + default: + return CG_FALSE; + } +} + +CGGL_API void cgGLEnableProfile( CGprofile profile ) +{ + //hack to counter removal of TypeC during beta + if ( profile == ( CGprofile )7005 ) + profile = CG_PROFILE_SCE_VP_RSX; + if ( profile == ( CGprofile )7006 ) + profile = CG_PROFILE_SCE_FP_RSX; + + // this is a logical extension to glEnable + RGLcontext* LContext = _CurrentContext; + switch ( profile ) + { + case CG_PROFILE_SCE_VP_TYPEB: + case CG_PROFILE_SCE_VP_RSX: + LContext->VertexProgram = GL_TRUE; + LContext->needValidate |= RGL_VALIDATE_VERTEX_PROGRAM; + break; + + case CG_PROFILE_SCE_FP_TYPEB: + case CG_PROFILE_SCE_FP_RSX: + rglLeaveFFXFP( LContext ); + break; + default: + rglCgRaiseError( CG_INVALID_PROFILE_ERROR ); + break; + } +} + +CGGL_API void cgGLDisableProfile( CGprofile profile ) +{ + //hack to counter removal of TypeC during beta + if ( profile == ( CGprofile )7005 ) + profile = CG_PROFILE_SCE_VP_RSX; + if ( profile == ( CGprofile )7006 ) + profile = CG_PROFILE_SCE_FP_RSX; + + // this is a logical extension to glDisable + RGLcontext* LContext = _CurrentContext; + switch ( profile ) + { + case CG_PROFILE_SCE_VP_TYPEB: + //case CG_PROFILE_SCE_VP_TYPEC: + case CG_PROFILE_SCE_VP_RSX: + LContext->VertexProgram = GL_FALSE; + // no need to invalidate textures because they are only available on programmable pipe. + LContext->needValidate |= RGL_VALIDATE_VERTEX_PROGRAM ; + break; + case CG_PROFILE_SCE_FP_TYPEB: + //case CG_PROFILE_SCE_FP_TYPEC: + case CG_PROFILE_SCE_FP_RSX: + LContext->FragmentProgram = GL_FALSE; + break; + default: + rglCgRaiseError( CG_INVALID_PROFILE_ERROR ); + break; + } +} + + +CGGL_API CGprofile cgGLGetLatestProfile( CGGLenum profile_type ) +{ + switch ( profile_type ) + { + case CG_GL_VERTEX: + case CG_GL_FRAGMENT: + return rglpGetLatestProfile( profile_type ); + default: + rglCgRaiseError( CG_INVALID_ENUMERANT_ERROR ); + return CG_PROFILE_UNKNOWN; + } +} + +CGGL_API void cgGLSetOptimalOptions( CGprofile profile ) +{ + // This does nothing because we don't compile at run-time. +} + +/****************************************************************************** + *** Program Managment Functions + *****************************************************************************/ + +CGGL_API void cgGLLoadProgram( CGprogram program ) +{ + // noop since there is integration of cg in js. +} + +CGGL_API CGbool cgGLIsProgramLoaded( CGprogram program ) +{ + // TODO: for now a valid program is always loaded. + return CG_TRUE; +} + + +CGGL_API void cgGLBindProgram( CGprogram program ) +{ + _CGprogram* ptr = _cgGetProgPtr( program ); + + // now do the binding. + switch ( ptr->header.profile ) + { + case CG_PROFILE_SCE_VP_TYPEB: + //hack to counter removal of TypeC during beta + case 7005: + case CG_PROFILE_SCE_VP_RSX: + _cgGLBindVertexProgram( ptr ); + break; + + case CG_PROFILE_SCE_FP_TYPEB: + //hack to counter removal of TypeC during beta + case 7006: + case CG_PROFILE_SCE_FP_RSX: + _cgGLBindFragmentProgram( ptr ); + break; + + default: + rglCgRaiseError( CG_INVALID_PROFILE_ERROR ); + return; + } + +} + +CGGL_API void cgGLUnbindProgram( CGprofile profile ) +{ + switch ( profile ) + { + case CG_PROFILE_SCE_VP_TYPEB: + //case CG_PROFILE_SCE_VP_TYPEC: + case CG_PROFILE_SCE_VP_RSX: + //hack to counter removal of TypeC during beta + case 7005: + _cgGLUnbindVertexProgram(); + // no need to invalidate textures because they are only available on programmable pipe. + break; + case CG_PROFILE_SCE_FP_TYPEB: + //case CG_PROFILE_SCE_FP_TYPEC: + case CG_PROFILE_SCE_FP_RSX: + //hack to counter removal of TypeC during beta + case 7006: + _cgGLUnbindFragmentProgram(); + + break; + default: + rglCgRaiseError( CG_INVALID_PROFILE_ERROR ); + return; + } + +} + + +// this API exposes internal implementation of Cg. +// Since we do not rely on program objects, always return 0. +CGGL_API GLuint cgGLGetProgramID( CGprogram program ) +{ + return 0; +} + +CGGL_API void cgGLEnableProgramProfiles( CGprogram program ) +{ + // TODO: unsupported in Jetstream + return; +} + +CGGL_API void cgGLDisableProgramProfiles( CGprogram program ) +{ + // TODO: unsupported in Jetstream + return; +} + + +/****************************************************************************** + *** Parameter Managment Functions + *****************************************************************************/ + +CGGL_API void cgGLSetParameter1f( CGparameter param, float x ) +{ + // check to see if the parameter is a good one + CgRuntimeParameter *ptr = rglCgGLTestParameter( param ); + + // otherwise apply the values to the parameter + float v[4] = {x, x, x, x}; + ptr->setterIndex( ptr, v, CG_GETINDEX( param ) ); +} + +CGGL_API void cgGLSetParameter2f( CGparameter param, float x, float y ) +{ + CgRuntimeParameter *ptr = rglCgGLTestParameter( param ); + + // otherwise apply the values to the parameter + float v[4] = {x, y, y, y}; + ptr->setterIndex( ptr, v, CG_GETINDEX( param ) ); +} + +CGGL_API void cgGLSetParameter3f( CGparameter param, float x, float y, float z ) +{ + CgRuntimeParameter *ptr = rglCgGLTestParameter( param ); + + // otherwise apply the values to the parameter + float v[4] = {x, y, z, z}; + ptr->setterIndex( ptr, v, CG_GETINDEX( param ) ); +} + +CGGL_API void cgGLSetParameter4f( CGparameter param, float x, float y, float z, float w ) +{ + CgRuntimeParameter *ptr = rglCgGLTestParameter( param ); + + // otherwise apply the values to the parameter + float v[4] = {x, y, z, w}; + ptr->setterIndex( ptr, v, CG_GETINDEX( param ) ); +} + +CGGL_API void cgGLSetParameter1fv( CGparameter param, const float *v ) +{ + CgRuntimeParameter *ptr = rglCgGLTestParameter( param ); + + float v2[4] = { v[0], v[0], v[0], v[0]}; + ptr->setterIndex( ptr, v2, CG_GETINDEX( param ) ); +} + +CGGL_API void cgGLSetParameter2fv( CGparameter param, const float *v ) +{ + CgRuntimeParameter *ptr = rglCgGLTestParameter( param ); + + float v2[4] = { v[0], v[1], v[1], v[1]}; + ptr->setterIndex( ptr, v2, CG_GETINDEX( param ) ); +} + +CGGL_API void cgGLSetParameter3fv( CGparameter param, const float *v ) +{ + CgRuntimeParameter *ptr = rglCgGLTestParameter( param ); + + float v2[4] = { v[0], v[1], v[2], v[2]}; + ptr->setterIndex( ptr, v2, CG_GETINDEX( param ) ); +} + +CGGL_API void cgGLSetParameter4fv( CGparameter param, const float *v ) +{ + CgRuntimeParameter *ptr = rglCgGLTestParameter( param ); + + float v2[4] = { v[0], v[1], v[2], v[3]}; + ptr->setterIndex( ptr, v2, CG_GETINDEX( param ) ); +} + +CGGL_API void cgGLGetParameter1f( CGparameter param, float *v ) +{ + //check parameter handle + CgRuntimeParameter *rtParameter = rglCgGLTestParameter( param ); + if ( !rtParameter ) + return; + + const CgParameterEntry *parameterEntry = rtParameter->parameterEntry; + if (( parameterEntry->flags & CGP_TYPE_MASK ) != CGP_INTRINSIC || + (( parameterEntry->flags & CGPV_MASK ) != CGPV_UNIFORM && ( parameterEntry->flags & CGPV_MASK ) != CGPV_CONSTANT ) ) + { + rglCgRaiseError( CG_INVALID_PARAMETER_ERROR ); + return; + } + + // uniforms only + float* value = rglGetUniformValuePtr( param, rtParameter ); + if ( !value ) + { + rglCgRaiseError( CG_INVALID_PARAMETER_ERROR ); + return; + } + + const CgParameterResource *parameterResource = rglGetParameterResource( rtParameter->program, parameterEntry ); + + switch ( parameterResource->type ) + { + case CG_FLOAT4: + case CG_FLOAT3: + case CG_FLOAT2: + case CG_FLOAT: + case CG_HALF4: + case CG_HALF3: + case CG_HALF2: + case CG_HALF: + case CG_INT4: + case CG_INT3: + case CG_INT2: + case CG_INT: + case CG_BOOL4: + case CG_BOOL3: + case CG_BOOL2: + case CG_BOOL: + case CG_FIXED4: + case CG_FIXED3: + case CG_FIXED2: + case CG_FIXED: + *v = *value; // fall through... + break; + default: + rglCgRaiseError( CG_INVALID_PARAMETER_ERROR ); + } +} + +CGGL_API void cgGLGetParameter2f( CGparameter param, float *v ) +{ + //check parameter handle + CgRuntimeParameter *rtParameter = rglCgGLTestParameter( param ); + if ( !rtParameter ) + return; + + const CgParameterEntry *parameterEntry = rtParameter->parameterEntry; + if (( parameterEntry->flags & CGP_TYPE_MASK ) != CGP_INTRINSIC || + (( parameterEntry->flags & CGPV_MASK ) != CGPV_UNIFORM && ( parameterEntry->flags & CGPV_MASK ) != CGPV_CONSTANT ) ) + { + rglCgRaiseError( CG_INVALID_PARAMETER_ERROR ); + return; + } + + // uniforms only + float* value = rglGetUniformValuePtr( param, rtParameter ); + if ( !value ) + { + rglCgRaiseError( CG_INVALID_PARAMETER_ERROR ); + return; + } + + // peek into image for value + const CgParameterResource *parameterResource = rglGetParameterResource( rtParameter->program, parameterEntry ); + switch ( parameterResource->type ) + { + case CG_FLOAT2: + case CG_FLOAT3: + case CG_FLOAT4: + case CG_HALF2: + case CG_HALF3: + case CG_HALF4: + case CG_INT2: + case CG_INT3: + case CG_INT4: + case CG_BOOL2: + case CG_BOOL3: + case CG_BOOL4: + case CG_FIXED2: + case CG_FIXED3: + case CG_FIXED4: + v[0] = value[0]; + v[1] = value[1]; + break; + default: + rglCgRaiseError( CG_INVALID_PARAMETER_ERROR ); + break; + } +} + +CGGL_API void cgGLGetParameter3f( CGparameter param, float *v ) +{ + //check parameter handle + CgRuntimeParameter *rtParameter = rglCgGLTestParameter( param ); + if ( !rtParameter ) + return; + + const CgParameterEntry *parameterEntry = rtParameter->parameterEntry; + if (( parameterEntry->flags & CGP_TYPE_MASK ) != CGP_INTRINSIC || + (( parameterEntry->flags & CGPV_MASK ) != CGPV_UNIFORM && ( parameterEntry->flags & CGPV_MASK ) != CGPV_CONSTANT ) ) + { + rglCgRaiseError( CG_INVALID_PARAMETER_ERROR ); + return; + } + + // uniforms only + float* value = rglGetUniformValuePtr( param, rtParameter ); + if ( !value ) + { + rglCgRaiseError( CG_INVALID_PARAMETER_ERROR ); + return; + } + + // peek into image for value + const CgParameterResource *parameterResource = rglGetParameterResource( rtParameter->program, parameterEntry ); + switch ( parameterResource->type ) + { + case CG_FLOAT3: + case CG_FLOAT4: + case CG_HALF3: + case CG_HALF4: + case CG_INT3: + case CG_INT4: + case CG_BOOL3: + case CG_BOOL4: + case CG_FIXED3: + case CG_FIXED4: + v[0] = value[0]; + v[1] = value[1]; + v[2] = value[2]; + break; + default: + rglCgRaiseError( CG_INVALID_PARAMETER_ERROR ); + break; + } +} + +CGGL_API void cgGLGetParameter4f( CGparameter param, float *v ) +{ + //check parameter handle + CgRuntimeParameter *rtParameter = rglCgGLTestParameter( param ); + if ( !rtParameter ) + return; + + const CgParameterEntry *parameterEntry = rtParameter->parameterEntry; + if (( parameterEntry->flags & CGP_TYPE_MASK ) != CGP_INTRINSIC || + (( parameterEntry->flags & CGPV_MASK ) != CGPV_UNIFORM && ( parameterEntry->flags & CGPV_MASK ) != CGPV_CONSTANT ) ) + { + rglCgRaiseError( CG_INVALID_PARAMETER_ERROR ); + return; + } + + // uniforms only + float* value = rglGetUniformValuePtr( param, rtParameter ); + if ( !value ) + { + rglCgRaiseError( CG_INVALID_PARAMETER_ERROR ); + return; + } + + // peek into image for value + const CgParameterResource *parameterResource = rglGetParameterResource( rtParameter->program, parameterEntry ); + switch ( parameterResource->type ) + { + case CG_FLOAT4: + case CG_HALF4: + case CG_INT4: + case CG_BOOL4: + case CG_FIXED4: + v[0] = value[0]; + v[1] = value[1]; + v[2] = value[2]; + v[3] = value[3]; + break; + default: + rglCgRaiseError( CG_INVALID_PARAMETER_ERROR ); + break; + } +} + +CGGL_API void cgGLSetParameterArray1f( CGparameter param, + long offset, + long nelements, + const float *v ) +{ + CgRuntimeParameter* ptr = _cgGLTestArrayParameter( param, offset, nelements ); + + + if ( nelements == 0 ) + { + const CgParameterArray *parameterArray = rglGetParameterArray( ptr->program, ptr->parameterEntry ); + nelements = rglGetSizeofSubArray( parameterArray->dimensions, parameterArray->dimensionCount ) - offset; + } + + //we have an array here, the parameterEntry of the type is the next one + ptr++; + + // loop over array elements + for ( int i = 0; i < nelements; ++i ) + { + ptr->setterIndex( ptr, v + i, i + offset ); + } +} + +CGGL_API void cgGLSetParameterArray2f( CGparameter param, + long offset, + long nelements, + const float *v ) +{ + CgRuntimeParameter* ptr = _cgGLTestArrayParameter( param, offset, nelements ); + + if ( nelements == 0 ) + { + const CgParameterArray *parameterArray = rglGetParameterArray( ptr->program, ptr->parameterEntry ); + nelements = rglGetSizeofSubArray( parameterArray->dimensions, parameterArray->dimensionCount ) - offset; + } + + //we have an array here, the parameterEntry of the type is the next one + ptr++; + + // loop over array elements + for ( int i = 0; i < nelements; ++i ) + { + ptr->setterIndex( ptr, v + 2 * i, i + offset ); + } +} + +CGGL_API void cgGLSetParameterArray3f( CGparameter param, + long offset, + long nelements, + const float *v ) +{ + + CgRuntimeParameter* ptr = _cgGLTestArrayParameter( param, offset, nelements ); + if ( nelements == 0 ) + { + const CgParameterArray *parameterArray = rglGetParameterArray( ptr->program, ptr->parameterEntry ); + nelements = rglGetSizeofSubArray( parameterArray->dimensions, parameterArray->dimensionCount ) - offset; + } + + //we have an array here, the parameterEntry of the type is the next one + ptr++; + // loop over array elements + for ( int i = 0; i < nelements; ++i ) + { + ptr->setterIndex( ptr, v + 3 * i, i + offset ); + } +} + +CGGL_API void cgGLSetParameterArray4f( CGparameter param, + long offset, + long nelements, + const float *v ) +{ + + CgRuntimeParameter* ptr = _cgGLTestArrayParameter( param, offset, nelements ); + if ( nelements == 0 ) + { + const CgParameterArray *parameterArray = rglGetParameterArray( ptr->program, ptr->parameterEntry ); + nelements = rglGetSizeofSubArray( parameterArray->dimensions, parameterArray->dimensionCount ) - offset; + } + + //we have an array here, the parameterEntry of the type is the next one + ptr++; + // loop over array elements + for ( int i = 0; i < nelements; ++i ) + { + ptr->setterIndex( ptr, v + 4 * i, i + offset ); + } +} + +CGGL_API void cgGLGetParameterArray1f( CGparameter param, + long offset, + long nelements, + float *v ) +{ + if ( nelements == 0 ) nelements = cgGetArraySize( param, 0 ) - offset; + // loop over array elements + for ( int i = 0; i < nelements; ++i ) + { + CGparameter p = cgGetArrayParameter( param, i + offset ); + cgGLGetParameter1f( p, v + i ); + } +} + +CGGL_API void cgGLGetParameterArray2f( CGparameter param, + long offset, + long nelements, + float *v ) +{ + if ( nelements == 0 ) nelements = cgGetArraySize( param, 0 ) - offset; + // loop over array elements + for ( int i = 0; i < nelements; ++i ) + { + CGparameter p = cgGetArrayParameter( param, i + offset ); + cgGLGetParameter2f( p, v + 2*i ); + } +} + +CGGL_API void cgGLGetParameterArray3f( CGparameter param, + long offset, + long nelements, + float *v ) +{ + + if ( nelements == 0 ) nelements = cgGetArraySize( param, 0 ) - offset; + // loop over array elements + for ( int i = 0; i < nelements; ++i ) + { + CGparameter p = cgGetArrayParameter( param, i + offset ); + cgGLGetParameter3f( p, v + 3*i ); + } +} + +CGGL_API void cgGLGetParameterArray4f( CGparameter param, + long offset, + long nelements, + float *v ) +{ + + if ( nelements == 0 ) nelements = cgGetArraySize( param, 0 ) - offset; + // loop over array elements + for ( int i = 0; i < nelements; ++i ) + { + CGparameter p = cgGetArrayParameter( param, i + offset ); + cgGLGetParameter4f( p, v + 4*i ); + } +} + +CGGL_API void cgGLSetParameterPointer( CGparameter param, + GLint fsize, + GLenum type, + GLsizei stride, + const GLvoid *pointer ) +{ + CgRuntimeParameter *_ptr = rglCgGLTestParameter( param ); + + const CgParameterResource *parameterResource = rglGetParameterResource( _ptr->program, _ptr->parameterEntry ); + GLuint index = ( GLuint )( parameterResource->resource - CG_ATTR0 ); + + rglVertexAttribPointerNV( + index, // attribute index + fsize, // element size + type, // GL_FLOAT + ( _ptr->parameterEntry->flags & CGP_NORMALIZE ) ? 1 : 0, // from the semantic of the param + stride, // element to element in bytes + pointer ); // data pointer +} + +CGGL_API void cgGLAttribPointer( GLuint index, GLint fsize, GLenum type, GLboolean normalize, GLsizei stride, const GLvoid *pointer ) +{ + rglVertexAttribPointerNV( + index, // attribute index + fsize, // element size + type, // GL_FLOAT + normalize, + stride, // element to element in bytes + pointer ); // data pointer +} + +CGGL_API void cgGLAttribValues( GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w ) +{ + rglVertexAttrib4fNV( index, x, y, z, w ); +} + +CGGL_API void cgGLEnableAttrib( GLuint index ) +{ + rglEnableVertexAttribArrayNV( index ); +} + +CGGL_API void cgGLDisableAttrib( GLuint index ) +{ + rglDisableVertexAttribArrayNV( index ); +} + +CGGL_API void cgGLEnableClientState( CGparameter param ) +{ + CgRuntimeParameter *_ptr = rglCgGLTestParameter( param ); + + const CgParameterResource *parameterResource = rglGetParameterResource( _ptr->program, _ptr->parameterEntry ); + + GLuint index = ( GLuint )( parameterResource->resource - CG_ATTR0 ); + rglEnableVertexAttribArrayNV( index ); +} + +CGGL_API void cgGLDisableClientState( CGparameter param ) +{ + CgRuntimeParameter *_ptr = rglCgGLTestParameter( param ); + + const CgParameterResource *parameterResource = rglGetParameterResource( _ptr->program, _ptr->parameterEntry ); + + GLuint index = ( GLuint )( parameterResource->resource - CG_ATTR0 ); + rglDisableVertexAttribArrayNV( index ); +} + +/****************************************************************************** + *** Matrix Parameter Managment Functions + *****************************************************************************/ + +CGGL_API void cgGLSetMatrixParameterfc( CGparameter param, const float *matrix ) +{ + + CgRuntimeParameter* ptr = rglCgGLTestParameter( param ); + ptr->settercIndex( ptr, matrix, CG_GETINDEX( param ) ); +} + +CGGL_API void cgGLSetMatrixParameterfr( CGparameter param, const float *matrix ) +{ + + CgRuntimeParameter *ptr = rglCgGLTestParameter( param ); + ptr->setterrIndex( ptr, matrix, CG_GETINDEX( param ) ); +} + +CGGL_API void cgGLGetMatrixParameterfr( CGparameter param, float *matrix ) +{ + + //check parameter handle + CgRuntimeParameter *rtParameter = ( CgRuntimeParameter* )rglCgGLTestParameter( param ); + if ( !rtParameter ) + return; + + const CgParameterEntry *parameterEntry = rtParameter->parameterEntry; + if (( parameterEntry->flags & CGP_TYPE_MASK ) != CGP_INTRINSIC || + (( parameterEntry->flags & CGPV_MASK ) != CGPV_UNIFORM && ( parameterEntry->flags & CGPV_MASK ) != CGPV_CONSTANT ) ) + { + rglCgRaiseError( CG_INVALID_PARAMETER_ERROR ); + return; + } + + // uniforms only + float* value = rglGetUniformValuePtr( param, rtParameter ); + if ( !value ) + { + rglCgRaiseError( CG_INVALID_PARAMETER_ERROR ); + return; + } + + CGtype parameterType = rglGetParameterCGtype( rtParameter->program, parameterEntry ); + unsigned int rows = rglGetTypeRowCount( parameterType ); + unsigned int cols = rglGetTypeColCount( parameterType ); + + if ( rows == 0 ) + { + rglCgRaiseError( CG_NOT_MATRIX_PARAM_ERROR ); + return; + } + + /* peek into argument block */ + for ( GLuint i = 0; i < rows; ++i ) + for ( GLuint j = 0; j < cols; ++j ) + matrix[i*cols + j] = value[i * 4 + j]; +} + +CGGL_API void cgGLGetMatrixParameterfc( CGparameter param, float *matrix ) +{ + + //check parameter handle + CgRuntimeParameter *rtParameter = ( CgRuntimeParameter* )rglCgGLTestParameter( param ); + if ( !rtParameter ) + return; + + const CgParameterEntry *parameterEntry = rtParameter->parameterEntry; + if (( parameterEntry->flags & CGP_TYPE_MASK ) != CGP_INTRINSIC || + (( parameterEntry->flags & CGPV_MASK ) != CGPV_UNIFORM && ( parameterEntry->flags & CGPV_MASK ) != CGPV_CONSTANT ) ) + { + rglCgRaiseError( CG_INVALID_PARAMETER_ERROR ); + return; + } + + float* value = rglGetUniformValuePtr( param, rtParameter ); + if ( !value ) + { + rglCgRaiseError( CG_INVALID_PARAMETER_ERROR ); + return; + } + + CGtype parameterType = rglGetParameterCGtype( rtParameter->program, parameterEntry ); + unsigned int rows = rglGetTypeRowCount( parameterType ); + unsigned int cols = rglGetTypeColCount( parameterType ); + + if ( rows == 0 ) + { + rglCgRaiseError( CG_NOT_MATRIX_PARAM_ERROR ); + return; + } + + /* peek into argument block */ + for ( GLuint i = 0; i < rows; ++i ) + for ( GLuint j = 0; j < cols; ++j ) + matrix[i*cols + j] = value[i + j * 4]; +} + +CGGL_API void cgGLSetMatrixParameterArrayfc( CGparameter param, + long offset, + long nelements, + const float *matrices ) +{ + + CgRuntimeParameter* _ptr = _cgGLTestArrayParameter( param, offset, nelements ); + const CgParameterEntry *parameterEntry = _ptr->parameterEntry; + + if ( nelements == 0 ) + { + const CgParameterArray *parameterArray = rglGetParameterArray( _ptr->program, parameterEntry ); + nelements = rglGetSizeofSubArray( parameterArray->dimensions, parameterArray->dimensionCount ) - offset; + } + //we have an array here, the parameterEntry of the type is the next one + _ptr++; + //get the type stride + CGtype parameterType = rglGetParameterCGtype( _ptr->program, _ptr->parameterEntry ); + unsigned int melems = rglGetTypeRowCount( parameterType ) * rglGetTypeColCount( parameterType ); + + // loop over array elements + for ( int i = 0; i < nelements; ++i ) + { + _ptr->settercIndex( _ptr, matrices + i * melems, i + offset ); + } +} + +CGGL_API void cgGLSetMatrixParameterArrayfr( CGparameter param, + long offset, + long nelements, + const float *matrices ) +{ + + CgRuntimeParameter *_ptr = _cgGLTestArrayParameter( param, offset, nelements ); + const CgParameterEntry *parameterEntry = _ptr->parameterEntry; + + if ( nelements == 0 ) + { + const CgParameterArray *parameterArray = rglGetParameterArray( _ptr->program, parameterEntry ); + nelements = rglGetSizeofSubArray( parameterArray->dimensions, parameterArray->dimensionCount ) - offset; + } + //we have an array here, the parameterEntry of the type is the next one + _ptr++; + //get the type stride + CGtype parameterType = rglGetParameterCGtype( _ptr->program, _ptr->parameterEntry ); + unsigned int melems = rglGetTypeRowCount( parameterType ) * rglGetTypeColCount( parameterType ); + + // loop over array elements + for ( int i = 0; i < nelements; ++i ) + { + _ptr->setterrIndex( _ptr, matrices + i * melems, i + offset ); + } +} + +CGGL_API void cgGLGetMatrixParameterArrayfc( CGparameter param, + long offset, + long nelements, + float *matrices ) +{ + CgRuntimeParameter *_ptr = _cgGLTestArrayParameter( param, offset, nelements ); + if ( RGL_LIKELY( _ptr != NULL ) ) + { + const CgParameterEntry *parameterEntry = _ptr->parameterEntry; + if ( nelements == 0 ) + { + const CgParameterArray *parameterArray = rglGetParameterArray( _ptr->program, parameterEntry ); + nelements = rglGetSizeofSubArray( parameterArray->dimensions, parameterArray->dimensionCount ) - offset; + } + //we have an array here, the parameterEntry of the type is the next one + _ptr++; + + parameterEntry = _ptr->parameterEntry; + if (( parameterEntry->flags & CGP_TYPE_MASK ) != CGP_INTRINSIC || + (( parameterEntry->flags & CGPV_MASK ) != CGPV_UNIFORM && ( parameterEntry->flags & CGPV_MASK ) != CGPV_CONSTANT ) ) + { + rglCgRaiseError( CG_NOT_MATRIX_PARAM_ERROR ); + return; + } + + int arrayID = ( int )_ptr->id; + + //get the type stride + CGtype parameterType = rglGetParameterCGtype( _ptr->program, _ptr->parameterEntry ); + unsigned int melems = rglGetTypeRowCount( parameterType ) * rglGetTypeColCount( parameterType ); + if ( !melems ) + { + rglCgRaiseError( CG_NOT_MATRIX_PARAM_ERROR ); + return ; + } + // loop over array elements + for ( int i = 0; i < nelements; ++i ) + { + int arrayParameter = arrayID | (( i + offset ) << CG_PARAMETERSIZE ); + cgGLGetMatrixParameterfc(( CGparameter )arrayParameter, matrices + i*melems ); + } + } + +} + +CGGL_API void cgGLGetMatrixParameterArrayfr( CGparameter param, + long offset, + long nelements, + float *matrices ) +{ + CgRuntimeParameter *_ptr = _cgGLTestArrayParameter( param, offset, nelements ); + if ( RGL_LIKELY( _ptr != NULL ) ) + { + const CgParameterEntry *parameterEntry = _ptr->parameterEntry; + if ( nelements == 0 ) + { + const CgParameterArray *parameterArray = rglGetParameterArray( _ptr->program, parameterEntry ); + nelements = rglGetSizeofSubArray( parameterArray->dimensions, parameterArray->dimensionCount ) - offset; + } + //we have an array here, the parameterEntry of the type is the next one + _ptr++; + parameterEntry = _ptr->parameterEntry; + if (( parameterEntry->flags & CGP_TYPE_MASK ) != CGP_INTRINSIC || + (( parameterEntry->flags & CGPV_MASK ) != CGPV_UNIFORM && ( parameterEntry->flags & CGPV_MASK ) != CGPV_CONSTANT ) ) + { + rglCgRaiseError( CG_NOT_MATRIX_PARAM_ERROR ); + return; + } + + int arrayID = ( int )_ptr->id; + + //get the type stride + CGtype parameterType = rglGetParameterCGtype( _ptr->program, _ptr->parameterEntry ); + unsigned int melems = rglGetTypeRowCount( parameterType ) * rglGetTypeColCount( parameterType ); + if ( !melems ) + { + rglCgRaiseError( CG_NOT_MATRIX_PARAM_ERROR ); + return ; + } + // loop over array elements + for ( int i = 0; i < nelements; ++i ) + { + int arrayParameter = arrayID | (( i + offset ) << CG_PARAMETERSIZE ); + cgGLGetMatrixParameterfr(( CGparameter )arrayParameter, matrices + i*melems ); + } + } + +} + +CGGL_API void cgGLSetTextureParameter( CGparameter param, GLuint texobj ) +{ + // According to the cg implementation from nvidia, set just stores the obj. + // Enable does the actual work. + CgRuntimeParameter* ptr = _cgGLTestTextureParameter( param ); + + ptr->samplerSetter( ptr, &texobj, 0 ); +} + +CGGL_API GLuint cgGLGetTextureParameter( CGparameter param ) +{ + CgRuntimeParameter* ptr = _cgGLTestTextureParameter( param ); + if ( ptr == NULL ) return 0; + if ( !( ptr->parameterEntry->flags & CGPF_REFERENCED ) ) { rglCgRaiseError( CG_INVALID_PARAMETER_ERROR ); return 0; } + return *( GLuint* )ptr->pushBufferPointer; + return 0; +} + +CGGL_API void cgGLEnableTextureParameter( CGparameter param ) +{ + CgRuntimeParameter* ptr = _cgGLTestTextureParameter( param ); + ptr->samplerSetter( ptr, NULL, 0 ); +} + +CGGL_API void cgGLDisableTextureParameter( CGparameter param ) +{ + if ( _cgGLTestTextureParameter( param ) ) + { + // this does not do anything on nvidia's implementation + } +} + +CGGL_API GLenum cgGLGetTextureEnum( CGparameter param ) +{ + // The returned value is the texture unit assigned to this parameter + // by the Cg compiler. + CgRuntimeParameter* ptr = _cgGLTestTextureParameter( param ); + if ( ptr == NULL ) return GL_INVALID_OPERATION; + + if ( ptr->parameterEntry->flags & CGP_RTCREATED ) + { + // runtime created texture parameters do not have allocated texture units + rglCgRaiseError( CG_INVALID_PARAMETER_ERROR ); + return GL_INVALID_OPERATION; + } + + // XXX what about the vertex texture enums !? + if (( ptr->program->header.profile == CG_PROFILE_SCE_VP_TYPEB ) + //|| (ptr->program->header.profile==CG_PROFILE_SCE_VP_TYPEC) + || ( ptr->program->header.profile == CG_PROFILE_SCE_VP_RSX ) ) + { + return GL_INVALID_OPERATION; + } + + if ( !( ptr->parameterEntry->flags & CGPF_REFERENCED ) || !(( ptr->parameterEntry->flags & CGPV_MASK ) == CGPV_UNIFORM ) ) { rglCgRaiseError( CG_INVALID_PARAMETER_ERROR ); return GL_INVALID_OPERATION; } + const CgParameterResource *parameterResource = rglGetParameterResource( ptr->program, ptr->parameterEntry ); + return GL_TEXTURE0 + parameterResource->resource - CG_TEXUNIT0; +} + +CGGL_API void cgGLSetManageTextureParameters( CGcontext ctx, CGbool flag ) +{ + _cgGetContextPtr( ctx )->GLmanageTextures = flag; +} + +CGGL_API CGbool cgGLGetManageTextureParameters( CGcontext ctx ) +{ + return _cgGetContextPtr( ctx )->GLmanageTextures; +} + + +void cgGLSetParameter1b( CGparameter param, CGbool v ) +{ + CgRuntimeParameter* ptr = rglCgGLTestParameter( param ); + if ( !ptr->parameterEntry->flags & CGPF_REFERENCED ) //ignore + return; + + _CGprogram* program = ptr->program; + + const CgParameterResource *parameterResource = rglGetParameterResource( program, ptr->parameterEntry ); + + // not sure what to do if no program like for global effect params that can be connected + // maybe actually do the propagation?! + if ( program ) + { + unsigned short resource = parameterResource->resource; + + unsigned int isShared = ( 1 << resource ) & ( program->parentContext->controlFlowBoolsSharedMask ); + unsigned int mask = ( 1 << resource ); + + // if the parameter is shared, initialize bools from context, otherwise from program + unsigned int bools = isShared ? program->parentContext->controlFlowBoolsShared : program->controlFlowBools; + + // set or unset the appropriate bit + if ( v ) + { + bools |= mask; + } + else + { + mask = ~mask; + bools &= mask; + } + + if ( isShared ) + { + program->parentContext->controlFlowBoolsShared = bools; + } + else + { + program->controlFlowBools = bools; + } + + _CurrentContext->needValidate |= RGL_VALIDATE_VERTEX_CONSTANTS; + } +} + +CGGL_API void cgGLSetDebugMode( CGbool debug ) +{ +} + +unsigned int cgGLGetRegisterCount( CGprogram program ) +{ + _CGprogram* ptr = _cgGetProgPtr( program ); + return rglGetProgramProfileIndex(( CGprofile )ptr->header.profile ) == FRAGMENT_PROFILE_INDEX ? + ptr->header.fragmentProgram.registerCount : ptr->header.vertexProgram.registerCount; +} + + +void cgGLSetRegisterCount( CGprogram program, const unsigned int regCount ) +{ + _CGprogram* ptr = _cgGetProgPtr( program ); + if ( rglGetProgramProfileIndex(( CGprofile )ptr->header.profile ) == FRAGMENT_PROFILE_INDEX ) + { + ptr->header.fragmentProgram.registerCount = regCount; + if ( _CurrentContext->BoundFragmentProgram == program ) + _CurrentContext->needValidate |= RGL_VALIDATE_FRAGMENT_PROGRAM; + } +} + +/*============================================================ + CG NV2ELF + ============================================================ */ + +using namespace cgc::bio; + +class CgBaseType +{ + public: + CgBaseType() {_type = 0;} + virtual ~CgBaseType() {} + unsigned short _type; //index of the type in the types array of the program if >= STRUCT, else it's a BASETYPE + short _resourceIndex; //index of the type in the types array of the program if >= STRUCT, else it's a BASETYPE + unsigned short _resource; //index of the type in the types array of the program if >= STRUCT, else it's a BASETYPE +}; + +//array +class CgArrayType : public CgBaseType +{ + public: + CgArrayType():_elementType(NULL) { _type = (unsigned char)(CG_ARRAY + 128); } + virtual ~CgArrayType() + { + if (_elementType) + delete _elementType; + } + CgBaseType *_elementType; + unsigned char _dimensionCount; + unsigned short _dimensionItemCountsOffset; +}; + +//structure +class CgStructureType : public CgBaseType +{ + public: + //definitions + class CgStructuralElement + { + public: + char _name[256]; + char _semantic[256]; + CgBaseType *_type; + unsigned short _flags; //in,out,global,varying,const,uniform,shared, hasDefaults(base types only) -> consecutive reg allocation flag + unsigned short _index; //helper index ? + }; + + //implementation + CgStructureType() + { + _type = (unsigned char)(CG_STRUCT + 128); + _root = false; + } + + virtual ~CgStructureType() + { + int i=0; + int count = (int)_elements.size(); + for (i=0;i _elements; + bool _insideArray; //modifies the way the resources are stored, they should be sent directly to the resources, + //the array is keeping track of the resource offset in that case + bool _root; +}; + +typedef struct +{ + const char *name; + int resIndex; +} BINDLOCATION; + + + +////////////////////////////////////////////////////////////////////////////// +// static arrays containing type information + +#define CG_DATATYPE_MACRO(name, compiler_name, enum_name, base_enum, nrows, ncols,classname) \ + classname , +static int classnames[] = { +#include "Cg/cg_datatypes.h" +}; + +#define CG_DATATYPE_MACRO(name, compiler_name, enum_name, base_enum, nrows, ncols,classname) \ + nrows , +static int rows[] = { +#include "Cg/cg_datatypes.h" +}; + +typedef float _float4[4]; + +////////////////////////////////////////////////////////////////////////////// +// static buffers containing the information extracted from the shaders + +typedef struct +{ + std::vector _resources; + std::vector _defaultValuesIndices; + std::vector _elfDefaultsIndices; + std::vector _dimensions; + std::vector _semanticIndices; +} _CGNVCONTAINERS; + +static bool bIsVertexProgram = true; + + +////////////////////////////////////////////////////////////////////////////// +// forward declarations + +static int getStride(CgBaseType *type); +static int getSizeofSubArray(_CGNVCONTAINERS &containers, int dimensionIndex, int dimensionCount, int endianness); + +static unsigned int stringTableFind( std::vector &stringTable, const char* str ) +{ + const char* data = &stringTable[0]; + size_t size = stringTable.size(); + const char *end = data + size; + + size_t length = strlen(str); + if (length+1 > size) + return 0; + data += length; + + const char *p = (char*)memchr(data,'\0',end-data); + while (p && (end-data)>0) + { + if (!memcmp(p - length, str, length)) + { + //found + return (unsigned int)(p - length - &stringTable[0]); + } + data = p+1; + p = (char*)memchr(data,'\0',end-data); + } + return 0; +} + +static unsigned int stringTableAdd( std::vector &stringTable, const char* str ) +{ + unsigned int ret = (unsigned int)stringTable.size(); + + if ( ret == 0 ) + { + stringTable.push_back('\0'); //add the empty string + ret = 1; + } + + size_t stringLength = strlen(str) + 1; + stringTable.resize(ret + stringLength); + memcpy(&stringTable[0] + ret,str,stringLength); + + return ret; +} + +static unsigned int stringTableAddUnique( std::vector &stringTable, const char* str ) +{ + if ( stringTable.size() == 0 ) + stringTable.push_back('\0'); //add the empty string + unsigned int ret = stringTableFind(stringTable, str); + if (ret == 0 && str[0] != '\0') + ret = stringTableAdd(stringTable, str); + return ret; +} + +template static size_t array_size(std::vector &array); +template static void array_push(char* ¶meterOffset, std::vector &array); +inline static uint32_t swap16(const uint32_t v); +static unsigned short getFlags(CGenum var, CGenum dir, int no, bool is_referenced, bool is_shared, int paramIndex); + +////////////////////////////////////////////////////////////////////////////// +// implementation + +static void fillStructureItems(_CGNVCONTAINERS &containers, CgStructureType *structure, + int endianness, + std::vector ¶meterEntries, + std::vector ¶meterResources, std::vector &stringTable, unsigned short *arrayResourceIndex = NULL, + unsigned short *arrayDefaultValueIndex = NULL); + + +int convertNvToElfFromFile(const char *sourceFile, int endianness, int constTableOffset, void **binaryShader, int *size, + std::vector &stringTable, std::vector &defaultValues) +{ + FILE *fp = fopen(sourceFile, "rb"); + if (fp) + { + fseek(fp,0,SEEK_END); + size_t filesize = ftell(fp); + fseek(fp,0,SEEK_SET); + void *data = malloc(filesize); + if (data == NULL) + { + fclose(fp); + //RGL_ASSERT2(0,("not enough memory to read the shader source")); + return -2; + } + fread(data,filesize,1,fp); + fclose(fp); + + int res = convertNvToElfFromMemory(data,filesize,endianness,constTableOffset, binaryShader, size,stringTable,defaultValues); + free(data); + return res; + } + //RGL_ASSERT2(0,("couldn't open source file %s\n",sourceFile)); + return -1; +} + +int convertNvToElfFromMemory(const void *sourceData, size_t size, int endianness, int constTableOffset, void **binaryShader, int *binarySize, + std::vector &stringTable, std::vector &defaultValues) +{ + _CGNVCONTAINERS containers; + + unsigned char elfEndianness = endianness; //used in the macro CNVEND + + nvb_reader* nvbr = 0; + bin_io::instance()->new_nvb_reader( &nvbr ); + CGBIO_ERROR err = nvbr->loadFromString((const char*)sourceData,size); + if (err != CGBIO_ERROR_NO_ERROR) + return -1; + + //flag which tells if we have to swap data coming from nv and going to elf + bool doSwap = !(nvbr->endianness() == (HOST_ENDIANNESS)elfEndianness); + + CGprofile NVProfile = nvbr->profile(); + //hack to counter removal of TypeC during beta + if (NVProfile == (CGprofile)7005 ) + NVProfile = CG_PROFILE_SCE_VP_RSX; + if (NVProfile == (CGprofile)7006 ) + NVProfile = CG_PROFILE_SCE_FP_RSX; + if (NVProfile == CG_PROFILE_SCE_VP_TYPEB || NVProfile == CG_PROFILE_SCE_VP_RSX) + { + bIsVertexProgram = true; + } + else if (NVProfile == CG_PROFILE_SCE_FP_TYPEB || NVProfile == CG_PROFILE_SCE_FP_RSX) + { + bIsVertexProgram = false; + } + else + { + //RGL_ASSERT2(0,("error: unknown shader profile\n")); + return -1; + } + + //Fill the shader header structure and save it into the shadertab + CgProgramHeader cgShader; + memset(&cgShader,0,sizeof(CgProgramHeader)); + cgShader.profile = CNV2END((unsigned short) NVProfile); //ok cnv2end here we go from platform endiannes to elf endiannes + cgShader.compilerVersion = 0;//TODO + if (bIsVertexProgram) + { + const CgBinaryVertexProgram *nvVertex = nvbr->vertex_program(); + if (doSwap) //here we go directly from nv to elf endiannes without going to the platform endianness + { + cgShader.instructionCount = ENDSWAP(nvVertex->instructionCount); + cgShader.attributeInputMask = ENDSWAP(nvVertex->attributeInputMask); + //vertex program specific + cgShader.vertexProgram.instructionSlot = ENDSWAP(nvVertex->instructionSlot); + cgShader.vertexProgram.registerCount = ENDSWAP(nvVertex->registerCount); + cgShader.vertexProgram.attributeOutputMask = ENDSWAP(nvVertex->attributeOutputMask); + } + else + { + cgShader.instructionCount = nvVertex->instructionCount; + cgShader.attributeInputMask = nvVertex->attributeInputMask; + //vertex program specific + cgShader.vertexProgram.instructionSlot = nvVertex->instructionSlot; + cgShader.vertexProgram.registerCount = nvVertex->registerCount; + cgShader.vertexProgram.attributeOutputMask = nvVertex->attributeOutputMask; + } + } + else + { + const CgBinaryFragmentProgram *nvFragment = nvbr->fragment_program(); + unsigned char flags; + if (doSwap) + { + cgShader.instructionCount = ENDSWAP(nvFragment->instructionCount); + cgShader.attributeInputMask = ENDSWAP(nvFragment->attributeInputMask); + //fragment program specific + cgShader.fragmentProgram.partialTexType = ENDSWAP(nvFragment->partialTexType); + cgShader.fragmentProgram.texcoordInputMask = ENDSWAP(nvFragment->texCoordsInputMask); + cgShader.fragmentProgram.texcoord2d = ENDSWAP(nvFragment->texCoords2D); + cgShader.fragmentProgram.texcoordCentroid = ENDSWAP(nvFragment->texCoordsCentroid); + cgShader.fragmentProgram.registerCount = ENDSWAP(nvFragment->registerCount); + flags = + (nvFragment->outputFromH0 ? CGF_OUTPUTFROMH0 : 0) | + (nvFragment->depthReplace ? CGF_DEPTHREPLACE : 0) | + (nvFragment->pixelKill ? CGF_PIXELKILL : 0); + } + else + { + cgShader.instructionCount = nvFragment->instructionCount; + cgShader.attributeInputMask = nvFragment->attributeInputMask; + //fragment program specific + cgShader.fragmentProgram.partialTexType = nvFragment->partialTexType; + cgShader.fragmentProgram.texcoordInputMask = nvFragment->texCoordsInputMask; + cgShader.fragmentProgram.texcoord2d = nvFragment->texCoords2D; + cgShader.fragmentProgram.texcoordCentroid = nvFragment->texCoordsCentroid; + cgShader.fragmentProgram.registerCount = nvFragment->registerCount; + flags = + (nvFragment->outputFromH0 ? CGF_OUTPUTFROMH0 : 0) | + (nvFragment->depthReplace ? CGF_DEPTHREPLACE : 0) | + (nvFragment->pixelKill ? CGF_PIXELKILL : 0); + } + cgShader.fragmentProgram.flags = CNV2END(flags); + } + + //shader specific info ( the shader header is in the shader tab ) + + //ucode + uint32_t *tmp = (uint32_t *)nvbr->ucode(); + const char *ucode; + uint32_t *buffer = NULL; + if (doSwap) + { + int size = (int)nvbr->ucode_size()/sizeof(uint32_t); + buffer = new uint32_t[size]; + for (int i=0;iucode_size()/sizeof(uint32_t); + buffer = new uint32_t[size]; + for (int i=0;iucode_size(); + + //ucode, ucodeSize; + + //RGL_ASSERT2(CNV2END(cgShader.instructionCount)*16 ==nvbr->ucode_size(),("%i, %i",CNV2END(cgShader.instructionCount)*16,nvbr->ucode_size())); + + //parameters + CgStructureType root; + root._insideArray = false; + root._root = true; + + //we don't have the names of the user structures, so to share structures we will have to rely on the + //layout of the data, we might do mistakes, but it's not important, since what we want to represent is + //the structure layout. + //parameters + //the parameters represents a hierarchical structure, I am reconstructing this structure + + int paramIndex = -1; + + //just for sanity check purpose: it's use to detect when there's a change of structural element to reset the embedded constant counter + CgStructureType::CgStructuralElement *current = NULL; + int embeddedConstants = 0; + bool rootChildDefaultValues = false; + int rootChildIndex = -1; + + char currentRefStructureName[256]; + currentRefStructureName[0] = '\0'; + + int i; + for (i = 0; i < (int)nvbr->number_of_params(); i++) + { + CGtype type; + CGresource res; + CGenum var; + int rin; + const char *name; + std::vector dv; + std::vector ec; + const char *sem; + CGenum dir; + int no; + bool is_referenced; + bool is_shared; + nvbr->get_param( i, type, res, var, rin, &name, dv, ec, &sem, dir, no, is_referenced, is_shared ); + + //This code is there twice, + //here it fixes a sce-cgc "bug" or weak feature, the user has asked for a shared parameter, but the flag is not set + //it happens for unreferenced item in a structure + //it will break if we support unshared with the semantic 'C###' + //later it will be there to fix the contiguity for arrays and the "share" part, but it's actually 2 different problems. + if (strlen(sem)>=2 && sem[0] == 'C') + { + const char *szSem = sem+1; + //check if we have a number + while (*szSem != '\0') + { + if ( (*szSem) < '0' || (*szSem) > '9') + break; + szSem++; + } + if (*szSem == '\0') + is_shared = 1; + } + + const char *parameterName = name; + const char *structureEnd = NULL; + CgStructureType *container = &root; + int done = 0; + const char * structureStart = parameterName; + while (!done && *structureStart) + { + // process the next structural element + structureEnd = strpbrk(structureStart, ".["); + + if (structureEnd) + { + //there's a special case for sampler, we don't support arrays of sampler, so unrolled the array here + //and don't even register the structure as being an array + if (*structureEnd == '[' && type >= CG_SAMPLER1D && type <= CG_SAMPLERCUBE) + { + //do we have an array of samplers and are we at the end ? + const char *closed = strchr(structureEnd, ']'); + //RGL_ASSERT2(closed,("name error for parameter %s",parameterName)); + const char *somethingElse = strpbrk(closed, ".["); + if (!somethingElse) + structureEnd = NULL; //so we are at the end we are in an array of samplers + } + } + + // test if we are done finding structural information + if (structureEnd == NULL) + { + //set structureEnd correctly so that the rest of the function performs correctly + structureEnd = structureStart + strlen(structureStart); + //set the done flag to exit the loop + done = 1; + } + + //extract the current structural element name + char structName[256]; + int length = (int)(structureEnd - structureStart); + strncpy(structName, structureStart, length); + structName[length] = '\0'; + + //do we already have it in the structure ? + CgStructureType::CgStructuralElement *structuralElement = NULL; + int j=0; + int elementCount = (int)container->_elements.size(); + for (j=0;j_elements[j]; + if (!strcmp(structuralElement->_name,structName)) + { + //same name, we need to check that this is the same scope ( program versus global ) + if ( (no == -1 && (structuralElement->_flags & CGPF_GLOBAL)) || + (no != -1 && !(structuralElement->_flags & CGPF_GLOBAL))) + break; + } + } + if (j==elementCount) + { + if (container == &root) + { + if (rootChildIndex != j) + { + rootChildDefaultValues = false; + rootChildIndex = j; + } + } + + //we don't have it yet, add it + container->_elements.resize(elementCount+1); + structuralElement = &container->_elements[elementCount]; + strncpy(structuralElement->_name,structName,sizeof(structuralElement->_name)); + structuralElement->_name[sizeof(structuralElement->_name)-1] = '\0'; + structuralElement->_flags = getFlags(var,dir,no,is_referenced,is_shared,paramIndex); + int dimensionCount = 0; + + if (strncmp(sem, "COLOR", 5) == 0 || strncmp(sem, "NORMAL", 6) == 0) + structuralElement->_flags |= CGP_NORMALIZE; + + + //check if we have a structure or an array of structure or an array of basetypes + //then: + // - create an array type if we have an array + // - update the container if we have a structure or an array of structure + int isStructure = (*structureEnd == '.'); + if (*structureEnd == '[') + { + dimensionCount++; + const char *arrayEnd = strchr(structureEnd,']')+1; + while (*arrayEnd == '[') + { + arrayEnd = strchr(arrayEnd,']')+1; + dimensionCount++; + } + if (*arrayEnd == '.') + isStructure = true; + } + + //we have an array, create an array type + if (dimensionCount) + { + CgArrayType *arrayType = new CgArrayType; + arrayType->_dimensionCount = dimensionCount; + arrayType->_dimensionItemCountsOffset = (unsigned short)containers._dimensions.size(); + //initialize the dimension count; + int k; + for (k=0;k_type = arrayType; + if (isStructure) + { + //we have a structure inside the array + container = new CgStructureType; + container->_insideArray = true; + arrayType->_elementType = container; + } + else + { + //we have a base type inside the array + arrayType->_elementType = new CgBaseType; + arrayType->_elementType->_type = type - CG_TYPE_START_ENUM; + } + arrayType->_elementType->_resource = res; + arrayType->_elementType->_resourceIndex = -1; + //special case here for shared vertex array ??? I consider them contiguous and referenced + //I need to detect this case and it's complex + if (bIsVertexProgram && strlen(sem)>=2 && sem[0] == 'C') + { + //I have to parse the semantic !!!! that's the only info I have at that level from sce-cgc... + //TODO: it's going to break if we support unshared with the semantic 'C###' + const char *szSem = sem+1; + //check if we have a number + while (*szSem != '\0') + { + if ( (*szSem) < '0' || (*szSem) > '9') + break; + szSem++; + } + if (*szSem == '\0') + { + //fix the is_shared variable.... sce-cgc doesn't set it that's why I am doing this parsing + is_shared = 1; + int registerIndex = atoi(sem+1); + structuralElement->_flags |= CGP_CONTIGUOUS; + structuralElement->_flags |= CGPF_SHARED; + structuralElement->_type->_resourceIndex = registerIndex; + } + else + structuralElement->_type->_resourceIndex = (int)containers._resources.size(); + } + else + structuralElement->_type->_resourceIndex = (int)containers._resources.size(); + + structuralElement->_type->_resource = res; + } + else + { + //we have a structure + if (isStructure) + { + bool insideArray = container->_insideArray; + container = new CgStructureType; + container->_insideArray = insideArray; + structuralElement->_type = container; + } + else + { + //assign the basetype and resource + structuralElement->_type = new CgBaseType; + structuralElement->_type->_type = type - CG_TYPE_START_ENUM; + structuralElement->_type->_resource = res; + if (classnames[structuralElement->_type->_type-1] == CG_PARAMETERCLASS_MATRIX) + { + //TODO, Cedric: for vertexprogram assume the matrices are always fully allocated and that they have consecuttive assignements + if (bIsVertexProgram) + { + structuralElement->_type->_resourceIndex = (short)rin; + } + else + structuralElement->_type->_resourceIndex = (int)containers._resources.size(); + } + else + { + if (!container->_insideArray) + { + //vertex program + if (bIsVertexProgram) + structuralElement->_type->_resourceIndex = rin; + else + { + //fragment program + if (structuralElement->_flags & CGPV_VARYING) + structuralElement->_type->_resourceIndex = -1; + else + { + structuralElement->_type->_resourceIndex = (int)containers._resources.size(); + containers._resources.push_back(CNV2END((unsigned short)rin)); + int size = (int)ec.size(); + containers._resources.push_back(CNV2END((unsigned short)size)); + int k; + for (k=0;k_type->_resourceIndex = (short)-1; + structuralElement->_type->_resource = (unsigned short)res; + } + } + } + } + } + else + { + if (structuralElement->_type->_type == CG_STRUCT+128) + { + container = (CgStructureType*)structuralElement->_type; + } + else if (structuralElement->_type->_type == CG_ARRAY+128) + { + CgArrayType *arrayType = (CgArrayType *)structuralElement->_type; + if (arrayType->_elementType->_type >128 ) + { + if (arrayType->_elementType->_type != CG_STRUCT+128) //we can't have arrays of arrays + { + //RGL_ASSERT2(0,("arrays of arrays not supported")); + } + container = (CgStructureType*)arrayType->_elementType; + } + } + } + + //default values should only be at the root of the hierarchical parameter structure + //RGL_ASSERT2(!rootChildDefaultValues || dv.size(),("all the parameter below a root child should have a default value")); + //if (dv.size() && !rootChildDefaultValues) + if (dv.size()) + { + int size = (int)containers._defaultValuesIndices.size(); + if (!size || (containers._defaultValuesIndices[size-2] != CNV2END((unsigned short)(rootChildIndex)))) + { + //assert for default values on structures: + //now supported: + /*RGL_ASSERT2(structuralElement->_type->_type != CG_STRUCT + 128,("default values on structure not yet supported")); + RGL_ASSERT2(structuralElement->_type->_type != CG_ARRAY + 128 || + ((CgArrayType *)structuralElement->_type)->_elementType->_type != CG_STRUCT + 128, + ("default values on arrays of structures not yet supported"));*/ + + //push the index of the parameter in the global structure + containers._defaultValuesIndices.push_back(CNV2END((unsigned short)(rootChildIndex))); + //push the index of the default value ( could add the size if necessary ) + containers._defaultValuesIndices.push_back(CNV2END((unsigned short)defaultValues.size())); + } + } + + //this case is for when we have item within a struct which is in an array, we don't duplicate the struct + //but we still need to save the resources at the array level, so with this code when we reach the end of the parameter + //name, we only need to save the resources + if (container->_insideArray && done) + { + //the reason of the reset of the flag is because the first item of the array might unreferenced + //so it doesn't has the correct resource type + if (is_referenced) + { + bool sharedContiguous = (structuralElement->_flags & CGPF_SHARED) && (structuralElement->_flags & CGP_CONTIGUOUS); + structuralElement->_flags = getFlags(var,dir,no,is_referenced,is_shared,paramIndex); + //special case here for shared vertex array ??? I consider them contiguous and referenced + if (sharedContiguous) //reset the contiguous flag too then + structuralElement->_flags |= ( CGP_CONTIGUOUS | CGPF_SHARED); + } + if (bIsVertexProgram) + { + //special case here for shared vertex array ??? I consider them contiguous and referenced + if (!is_shared) //if shared it's contiguous and we don't have to do that + containers._resources.push_back(CNV2END((unsigned short)rin)); + } + else + { + //fragment program + if (structuralElement->_flags & CGPV_VARYING) + containers._resources.push_back(CNV2END((unsigned short)rin)); + else + { + containers._resources.push_back(CNV2END((unsigned short)rin)); + int size = (int)ec.size(); + containers._resources.push_back(CNV2END((unsigned short)size)); + int k; + for (k=0;k_type; + if (itemType->_type >= 128) + { + arrayType = (CgArrayType *)itemType; + int dimensionCount = 0; + while (*arrayStart == '[' && dimensionCount_dimensionCount) + { + arrayEnd = strchr(arrayStart+1,']'); + int length =(int)(arrayEnd - arrayStart - 1); + char indexString[16]; + strncpy(indexString,arrayStart+1,length); + indexString[length] = '\0'; + int index = atoi(indexString); + int dim = CNV2END(containers._dimensions[arrayType->_dimensionItemCountsOffset + dimensionCount]); + if ((index+1) > dim) + containers._dimensions[arrayType->_dimensionItemCountsOffset + dimensionCount] = CNV2END((short)(index+1)); + arrayCellIndex += index*getSizeofSubArray(containers,arrayType->_dimensionItemCountsOffset + dimensionCount,arrayType->_dimensionCount - dimensionCount -1,endianness); + arrayStart = arrayEnd+1; + dimensionCount++; + } + structureEnd = arrayStart; + + itemType = arrayType->_elementType; + if (itemType->_type<128) + { + int rowCount = rows[itemType->_type-1]; + if (!rowCount) //no matrix here + { + //special case here for shared vertex array ??? I consider them contiguous and referenced + //so I add this if and don't add the resource if we have a shared here + //this is part of a big workaround around sce_cgc ... + bool sharedContiguous = (structuralElement->_flags & CGPF_SHARED) && (structuralElement->_flags & CGP_CONTIGUOUS); + if (!bIsVertexProgram || !sharedContiguous) + { + //add the resource index ... scary + containers._resources.push_back(CNV2END((unsigned short)rin)); + } + + //fragment program + if (!bIsVertexProgram) + { + int size = (int)ec.size(); + containers._resources.push_back(CNV2END((unsigned short)size)); + int k; + for (k=0;k_type <128)//matrix + { + if (structuralElement != current) + { + embeddedConstants = 0; + current = structuralElement; + } + + int length =(int)(arrayEnd - arrayStart - 1); + char indexString[16]; + strncpy(indexString,arrayStart+1,length); + indexString[length] = '\0'; + + //TODO: Cedric: for vertex program and matrices not in array, I am not adding any resource: + if (bIsVertexProgram) + { + if (arrayType) + { + //special case here for shared vertex array ??? I consider them contiguous and referenced + //so I add this if and don't add the resource if we have a shared here + //this is part of a big workaround around sce_cgc ... + bool sharedContiguous = (structuralElement->_flags & CGPF_SHARED) && (structuralElement->_flags & CGP_CONTIGUOUS); + if (!sharedContiguous) + { + //RGL_ASSERT2((int)containers._resources.size() == structuralElement->_type->_resourceIndex + arrayCellIndex*rows[itemType->_type-1] + embeddedConstants + index,("matrix index mismatch. some indices have been skipped")); + //add the resource index ... scary + containers._resources.push_back(CNV2END((unsigned short)rin)); + } + } + } + else + { + containers._resources.push_back(CNV2END((unsigned short)rin)); + int size = (int)ec.size(); + containers._resources.push_back(CNV2END((unsigned short)size)); + int k; + for (k=0;k_flags & CGPF_SHARED) && (structuralElement->_flags & CGP_CONTIGUOUS); + + unsigned short flag = getFlags(var,dir,no,is_referenced,is_shared,paramIndex); + structuralElement->_flags = flag; + + //special case here for shared vertex array ??? I consider them contiguous and referenced + if (sharedContiguous) //reset the contiguous flag too then + structuralElement->_flags |= ( CGP_CONTIGUOUS | CGPF_SHARED); + + structuralElement->_type->_resource = res; + //if array + if (arrayType) + arrayType->_elementType->_resource = res; + } + } + + + if (done && dv.size()) + { + //very difficult to check that there is no mistake done... should do a diff with + //containers._defaultValuesIndices[containers._defaultValuesIndices.size()-1] and the current parameter position in + //the structure + for ( int jj = 0; jj < (int)dv.size(); ++jj ) + { +#ifndef __CELLOS_LV2__ + unsigned int val = *(unsigned int*)&dv[jj]; + unsigned int tmp = CNV2END(val); + float tmp2 = *(float*)&tmp; + defaultValues.push_back(tmp2); +#else + defaultValues.push_back(dv[jj]); +#endif + } + } + + if (done) + { + if (strlen(sem)) + { + strncpy(structuralElement->_semantic,sem,sizeof(structuralElement->_semantic)); + } + else + structuralElement->_semantic[0] = '\0'; + } + structureStart = structureEnd+1; + } + } + + //we are done with the reader + nvbr->release(); + //release singleton + bin_io::delete_instance(); + + //print the structure that we have extracted + + //transform the extracted structure into the file format + std::vector parameterEntries; + std::vector parameterResources; + fillStructureItems(containers,&root,endianness,parameterEntries,parameterResources,stringTable); + + //save it + CgParameterTableHeader header; + memset(&header,0,sizeof(CgParameterTableHeader)); + header.entryCount = (unsigned short)parameterEntries.size(); + header.resourceTableOffset = sizeof(CgParameterTableHeader) + (unsigned short)(parameterEntries.size()*sizeof(parameterEntries[0]) + parameterResources.size()*sizeof(parameterResources[0])); + header.defaultValueIndexTableOffset = header.resourceTableOffset + (unsigned short)containers._resources.size() * sizeof(containers._resources[0]); + header.defaultValueIndexCount = (unsigned short)containers._elfDefaultsIndices.size()/2; + header.semanticIndexTableOffset = header.defaultValueIndexTableOffset + (unsigned short)containers._elfDefaultsIndices.size() * sizeof (containers._elfDefaultsIndices[0]); + header.semanticIndexCount = (unsigned short)containers._semanticIndices.size(); + + header.entryCount = CNV2END(header.entryCount); + header.resourceTableOffset = CNV2END(header.resourceTableOffset); + header.defaultValueIndexTableOffset = CNV2END(header.defaultValueIndexTableOffset); + header.defaultValueIndexCount = CNV2END(header.defaultValueIndexCount); + header.semanticIndexTableOffset = CNV2END(header.semanticIndexTableOffset); + header.semanticIndexCount = CNV2END(header.semanticIndexCount); + + //fill the parameter section + size_t parameterTableSize = sizeof(CgParameterTableHeader); + parameterTableSize += array_size(parameterEntries); + parameterTableSize += array_size(parameterResources); + parameterTableSize += array_size(containers._resources); + //parameterTableSize += array_size(containers._defaultValuesIndices); + parameterTableSize += array_size(containers._elfDefaultsIndices); + parameterTableSize += array_size(containers._semanticIndices); + + //Allocate the binary file + int ucodeOffset = (((sizeof(CgProgramHeader)-1)/16)+1)*16; + size_t programSize = ucodeOffset + ucodeSize + parameterTableSize; + char *program = new char[programSize]; + + //header + memcpy(program,&cgShader,sizeof(CgProgramHeader)); + if (ucodeOffset-sizeof(CgProgramHeader)) + memset(program+sizeof(CgProgramHeader),0,ucodeOffset-sizeof(CgProgramHeader)); + + //ucode + memcpy(program + ucodeOffset,ucode,ucodeSize); + //we can delete buffer ( memory block pointed by ucode ) + if (!bIsVertexProgram && doSwap) + delete[] buffer; + // !!!xxx this is to workaround what appears to be a linux platform specific bug + // that manifests as a memory overwrite in properly allocated memory during a std::vector resize + else + delete[] buffer; + // end workaround + + //parameters + char *parameterOffset = program + ucodeOffset + ucodeSize; + + memcpy(parameterOffset,&header,sizeof(CgParameterTableHeader)); + parameterOffset += sizeof(CgParameterTableHeader); + array_push(parameterOffset, parameterEntries); + array_push(parameterOffset, parameterResources); + array_push(parameterOffset, containers._resources); + //TODO: Tmp: patch the default Value indices, no sharing yet + /*unsigned short offset = (unsigned short)constTableOffset; + for (int i=0;i<(int)containers._defaultValuesIndices.size();i+=2) + { + unsigned short value = CNV2END(containers._defaultValuesIndices[i+1]); + containers._defaultValuesIndices[i+1] = CNV2END((unsigned short)(value + offset)); + }*/ + //array_push(parameterOffset, containers._defaultValuesIndices); + array_push(parameterOffset, containers._elfDefaultsIndices); + array_push(parameterOffset, containers._semanticIndices); + + //RGL_ASSERT2(parameterOffset == program + programSize,("error\n")); + //set the return values + *binarySize = (int)programSize; + *binaryShader = program; + + return 0; +} + +int convertNvToElfFreeBinaryShader(void *binaryShader) +{ + char *program = (char *)binaryShader; + delete[] program; + return 0; +} + +static void pushbackUnsignedShort(std::vector ¶meterResources, unsigned short value) +{ + size_t size = parameterResources.size(); + parameterResources.resize(size + 2); + *((unsigned short*)¶meterResources[size]) = value; +} + +//This function fill the parameter tables that will be written to the files +static void fillStructureItems(_CGNVCONTAINERS &containers, CgStructureType *structure, int endianness, + std::vector ¶meterEntries,std::vector ¶meterResources, + std::vector &stringTable, unsigned short *arrayResourceIndex, unsigned short *arrayDefaultValueIndex) +{ + unsigned char elfEndianness = endianness; //used in the macro CNVEND + + int currentDefaultIndex = 0; + int count = (int)structure->_elements.size(); + int i; + for (i=0;i_elements[i]; + size_t size = parameterEntries.size(); + parameterEntries.resize(size+1); + CgParameterEntry *parameterEntry = ¶meterEntries[size]; + parameterEntry->nameOffset = CNV2END((int)stringTableAddUnique(stringTable, structuralElement->_name)); + if (structuralElement->_semantic[0]) + { + CgParameterSemantic semantic; + semantic.entryIndex = CNV2END((unsigned short)size); + semantic.reserved = 0; + semantic.semanticOffset = CNV2END((int)stringTableAddUnique(stringTable, structuralElement->_semantic)); + containers._semanticIndices.push_back(semantic); + } + parameterEntry->flags = CNV2END(structuralElement->_flags); + //prepare the typeIndex + unsigned short typeIndex = ((unsigned short)parameterResources.size()); + //RGL_ASSERT2((typeIndex&3) == 0,("typeindex must be aligned on 4 bytes")); + parameterEntry->typeIndex = CNV2END(typeIndex); + + CgBaseType *itemType = structuralElement->_type; + unsigned short _resource = itemType->_resource; + unsigned short _resourceIndex = itemType->_resourceIndex; + + //will contain the parameterEntry for this item, for simple type arrays the value will be corrected + //parameterEntry.size() is not parameterEntryIndex in that case. + int parameterEntryIndex; + + if (itemType->_type-128 == CG_ARRAY) + { + CgArrayType *arrayType = (CgArrayType *)structuralElement->_type; + int arraySize = getSizeofSubArray(containers,arrayType->_dimensionItemCountsOffset,arrayType->_dimensionCount,endianness); + itemType = arrayType->_elementType; + //RGL_ASSERT2(!(itemType->_type +CG_TYPE_START_ENUM >= CG_SAMPLER1D && itemType->_type +CG_TYPE_START_ENUM<= CG_SAMPLERCUBE),("array of samplers not yet supported")); + unsigned short arrayFlag = CGP_ARRAY; + parameterEntry->flags |= CNV2END(arrayFlag); + parameterResources.resize(typeIndex+sizeof(CgParameterArray)); + + CgParameterArray *parameterArray = (CgParameterArray *)(¶meterResources[typeIndex]); + if (itemType->_type-128 == CG_STRUCT ) + parameterArray->arrayType = CNV2END((unsigned short)CG_STRUCT); + else + parameterArray->arrayType = CNV2END(itemType->_type+128); + parameterArray->dimensionCount = CNV2END((unsigned short)arrayType->_dimensionCount); + int j; + for (j=0;j_dimensionCount;j++) + { + pushbackUnsignedShort(parameterResources,(unsigned short)containers._dimensions[arrayType->_dimensionItemCountsOffset+j]); //already endian-swapped + } + //padding + if (arrayType->_dimensionCount&1) + pushbackUnsignedShort(parameterResources,CNV2END((unsigned short)0)); + + //unroll the array of structure here, create one structure for each item of the array + if (itemType->_type-128 == CG_STRUCT ) + { + unsigned short unrolledFlag = CGP_UNROLLED; + parameterEntry->flags |= CNV2END(unrolledFlag); + CgStructureType *structureType = (CgStructureType*)itemType; + int k; + + //those lines won't work for arrays of structures containing arrays + unsigned short _arrayResourceIndex = (unsigned short)(arrayType->_resourceIndex); + unsigned short _arrayDefaultValueIndex = 0; + + bool hasDefaults = false; + if (structure->_root && containers._defaultValuesIndices.size()) + { + if (containers._defaultValuesIndices[currentDefaultIndex*2] == CNV2END((unsigned short)i)) + { + hasDefaults = true; + _arrayDefaultValueIndex = containers._defaultValuesIndices[currentDefaultIndex*2+1]; + //containers._defaultValuesIndices[currentDefaultIndex*2] = CNV2END((unsigned short)(parameterEntries.size() - 1)); + //currentDefaultIndex++; + } + } + + for (k=0;k_name,k); + parameterArrayEntry.nameOffset = CNV2END((int)stringTableAddUnique(stringTable, buffer)); + parameterArrayEntry.flags = CNV2END(structuralElement->_flags); + unsigned short structureFlag = CGP_STRUCTURE; + parameterArrayEntry.flags |= CNV2END(structureFlag); + + unsigned short arrayEntryTypeIndex = (unsigned short)parameterResources.size(); + //RGL_ASSERT2((arrayEntryTypeIndex&3) == 0,("typeindex must be aligned on 4 bytes")); + parameterResources.resize(arrayEntryTypeIndex+sizeof(CgParameterStructure)); + parameterArrayEntry.typeIndex = CNV2END(arrayEntryTypeIndex); + + CgParameterStructure *parameterStructure = (CgParameterStructure*)(¶meterResources[arrayEntryTypeIndex]); + parameterStructure->memberCount = CNV2END((unsigned short)structureType->_elements.size()); + parameterStructure->reserved = CNV2END((unsigned short)0); + + if (hasDefaults) + fillStructureItems(containers,structureType,endianness,parameterEntries,parameterResources,stringTable,&_arrayResourceIndex,&_arrayDefaultValueIndex); + else + fillStructureItems(containers,structureType,endianness,parameterEntries,parameterResources,stringTable,&_arrayResourceIndex); + } + + if (hasDefaults) + { + //should check this value, but it's not really easy, need the entire size of the complex structure in registers + //unsigned short ArrayBaseTypeCount = _arrayDefaultValueIndex -containers._defaultValuesIndices[currentDefaultIndex*2+1]; + currentDefaultIndex++; + } + //containers._defaultValuesIndices[currentDefaultIndex*2] = CNV2END((unsigned short)(parameterEntries.size() - 1)); + //currentDefaultIndex++; + + + //default value expansion: we have an array of struct: we have one default value index for the array + //since the array is unrolled we don't give any resource to the array, but instead we give the resource to each item of each structure + //those items can be arrays or structure themselves + + //we have already output the content of the array continue to the next structure item + continue; + } + else + { + //create the type item following the array , the type section will fill typeindex value + size_t size = parameterEntries.size(); + parameterEntries.resize(size+1); + parameterEntry = ¶meterEntries[size]; + parameterEntry->nameOffset = CNV2END(0); + parameterEntry->flags = CNV2END(structuralElement->_flags); + + //prepare a typeIndex for this type + typeIndex = ((unsigned short)parameterResources.size()); + //RGL_ASSERT2((typeIndex&3) == 0,("typeindex must be aligned on 4 bytes")); + parameterEntry->typeIndex = CNV2END(typeIndex); + + //keep the parameterEntryIndex to assign the default values to the proper item + parameterEntryIndex = (int)size - 1; + } + } + else + { + unsigned short contiguousFlag = CGP_CONTIGUOUS; + parameterEntry->flags |= CNV2END(contiguousFlag); + size_t size = parameterEntries.size(); + parameterEntryIndex = (int)size - 1; + } + + if (itemType->_type<128) + { + parameterResources.resize(typeIndex+sizeof(CgParameterResource)); + CgParameterResource *parameterResource = (CgParameterResource*)(¶meterResources[typeIndex]); + + if (itemType->_type + CG_TYPE_START_ENUM == CG_BOOL) // checking _resource == CG_B only works if referenced + { + parameterResource->type = CNV2END((unsigned short)CGP_SCF_BOOL); + } + else + { + parameterResource->type = CNV2END((unsigned short)(itemType->_type + CG_TYPE_START_ENUM)); + } + + if ((structuralElement->_flags & CGPV_MASK) == CGPV_UNIFORM || (structuralElement->_flags & CGPV_MASK) == CGPV_CONSTANT) + { + //use the resource index of the array if we are in an array: pbl with arrays containing samplers... + if (itemType->_type +CG_TYPE_START_ENUM >= CG_SAMPLER1D && itemType->_type +CG_TYPE_START_ENUM<= CG_SAMPLERCUBE) + parameterResource->resource = CNV2END(_resource); //sampler we need the texture unit + else + { + if (arrayResourceIndex) + { + unsigned short tmp = *arrayResourceIndex; + unsigned short localflags = CNV2END(parameterEntry->flags); + if (!bIsVertexProgram) + { + parameterResource->resource = CNV2END(tmp); + int embeddedConstantCount = CNV2END(containers._resources[tmp+1]); + (*arrayResourceIndex) = tmp+1+1+embeddedConstantCount; + if (embeddedConstantCount == 0 && (CNV2END(containers._resources[tmp]) == 0)) + { + //we are unrolling an array of struct, so we get individual items + //we should mark if they are referenced individually + if (parameterResource->resource == 0xffff) + localflags &= ~CGPF_REFERENCED; + } + } + else + { + //if it's not contiguous , I am not sure what to do + //RGL_ASSERT2(CNV2END(parameterEntry->flags) & CGP_CONTIGUOUS,("assumed parameterEntry->flags & CGP_CONTIGUOUS")); + + if (structuralElement->_flags & CGPF_SHARED) + { + int stride = getStride(itemType); + parameterResource->resource = *arrayResourceIndex; + (*arrayResourceIndex) = tmp+stride; + } + else + { + //this is a hack, the info will be at 2 places + parameterResource->resource = containers._resources[tmp];//_resources is already converted + (*arrayResourceIndex) = tmp+1; + } + + //we are unrolling an array of struct, so we get individual items + //we should mark if they are referenced individually + if (parameterResource->resource == 0xffff) + localflags &= ~CGPF_REFERENCED; + } + //update the flags + parameterEntry->flags = CNV2END(localflags); + } + else + parameterResource->resource = CNV2END(_resourceIndex); //uniform not a sampler we need the register + } + } + else + { + //RGL_ASSERT2((structuralElement->_flags & CGPV_MASK) == CGPV_VARYING,("assumed varying")); + //RGL_ASSERT2(arrayResourceIndex == NULL,("varying within array of structures not yet supported")); + parameterResource->resource = CNV2END(itemType->_resource); //we need the bind location for the varying + } + + if (containers._defaultValuesIndices.size()) + { + if (structure->_root) + { + //TODO: what about default values on structures at the root level, the structure will flatten out so the default should go on the individual items + //but they are not at root so the indices cannot be represented right now I guess. + //semantics and default values indices need to be updated: + //we are trying to find the index in the sorted array of default value indices, if we are already at the end of the array we stop here + if (currentDefaultIndex < (int)(containers._defaultValuesIndices.size()/2) && containers._defaultValuesIndices[currentDefaultIndex*2] == CNV2END((unsigned short)i)) + { + containers._elfDefaultsIndices.push_back(CNV2END((unsigned short)(parameterEntryIndex))); + containers._elfDefaultsIndices.push_back(containers._defaultValuesIndices[currentDefaultIndex*2+1]); + //containers._defaultValuesIndices[currentDefaultIndex*2] = CNV2END((unsigned short)(parameterEntries.size() - 1)); + currentDefaultIndex++; + } + } + else if (arrayDefaultValueIndex) + { + //we are in a struct or in an array of struct which has a top level default, each time we have a basic type we need to increase + //the index + + containers._elfDefaultsIndices.push_back(CNV2END((unsigned short)(parameterEntryIndex))); + containers._elfDefaultsIndices.push_back(*arrayDefaultValueIndex); + //increment the default values index by the number of defaultValues slot used by this type + + int typeRegisterCount = getStride(itemType); + *arrayDefaultValueIndex = CNV2END( (unsigned short)((CNV2END((*arrayDefaultValueIndex)))+typeRegisterCount*4)); + + //no handling of the currentDefaultIndex, which is only valid at root. + } + } + } + else if (itemType->_type == CG_STRUCT + 128) + { + //RGL_ASSERT2(arrayResourceIndex == NULL,("struct within array of structures not yet supported")); + unsigned short structureFlag = CGP_STRUCTURE; + parameterEntry->flags |= CNV2END(structureFlag); + + CgStructureType *structureType = (CgStructureType*)itemType; + parameterResources.resize(typeIndex+sizeof(CgParameterStructure)); + CgParameterStructure *parameterStructure = (CgParameterStructure*)(¶meterResources[typeIndex]); + parameterStructure->memberCount = CNV2END((unsigned short)structureType->_elements.size()); + parameterStructure->reserved = CNV2END((unsigned short)0); + + fillStructureItems(containers,structureType,endianness,parameterEntries,parameterResources,stringTable); + + if (containers._defaultValuesIndices.size() && structure->_root) + { + if (currentDefaultIndex < (int)(containers._defaultValuesIndices.size()/2) && containers._defaultValuesIndices[currentDefaultIndex*2] == CNV2END((unsigned short)i)) + { + containers._elfDefaultsIndices.push_back(CNV2END((unsigned short)(parameterEntryIndex))); + containers._elfDefaultsIndices.push_back(containers._defaultValuesIndices[currentDefaultIndex*2+1]); + currentDefaultIndex++; + } + } + } + } + //RGL_ASSERT2(!structure->_root || currentDefaultIndex == (int)containers._defaultValuesIndices.size()/2,("error\n")); +} + + +static int getStride(CgBaseType *type) +{ + if (type->_type <128) + { + if (classnames[type->_type-1] == CG_PARAMETERCLASS_MATRIX) + return rows[type->_type-1]; + else + return 1; + } + else + { + if (type->_type == CG_STRUCT + 128) + { + CgStructureType *structureType = (CgStructureType *)type; + int res = 0; + int i; + int count = (int)structureType->_elements.size(); + for (i=0;i_elements[i]._type); + return res; + } + else + { + //RGL_ASSERT2(0,("arrays of arrays not supported")); + return -9999999; + } + //if array ?? + } +} + +static int getSizeofSubArray(_CGNVCONTAINERS &containers, int dimensionIndex, int dimensionCount, int endianness) +{ + unsigned char elfEndianness = endianness; //used in the macro CNVEND + int res = 1; + int i; + for (i=0;i static size_t array_size(std::vector &array) +{ + return (unsigned int)array.size()*sizeof(array[0]); +} + +template static void array_push(char* ¶meterOffset, std::vector &array) +{ + size_t dataSize = array.size()*sizeof(array[0]); + memcpy(parameterOffset,&array[0],dataSize); + parameterOffset += dataSize; +} + +uint32_t inline static swap16(const uint32_t v) +{ + return (v>>16) | (v<<16); +} + +unsigned short getFlags(CGenum var, CGenum dir, int no, bool is_referenced, bool is_shared, int paramIndex) +{ + //the following is error prone, use 2 enum array to do the matching instead + //variability + uint16_t flags = 0; + if (var == CG_VARYING) + flags |= CGPV_VARYING; + else if (var == CG_UNIFORM) + flags |= CGPV_UNIFORM; + else if (var == CG_CONSTANT) + flags |= CGPV_CONSTANT; + else if (var == CG_MIXED) + flags |= CGPV_MIXED; + + //direction + if (dir == CG_IN) + flags |= CGPD_IN; + else if (dir == CG_OUT) + flags |= CGPD_OUT; + else if (dir == CG_INOUT) + flags |= CGPD_INOUT; + + //boolean + if (is_referenced) + flags |= CGPF_REFERENCED; + if (is_shared) + flags |= CGPF_SHARED; + + //is it a global parameter ? + if (no == -1) + flags |= CGPF_GLOBAL; + else if (no == -2) + flags |= CGP_INTERNAL; + else + { + //RGL_ASSERT2(no>=0,("error\n")); + /*if ( no == paramIndex ) //means that a previous parameter already had the same param index, it's an aggregated type + flags |= CGP_AGGREGATED;*/ + paramIndex = no; + } + return flags; +} + +/*============================================================ + CGBIO + ============================================================ */ + +namespace cgc { + namespace bio { + + bin_io* bin_io::instance_ = 0; + + bin_io::bin_io() + { + } + + bin_io::bin_io( const bin_io& ) + { + } + + const bin_io* + bin_io::instance() + { + if (instance_ == 0) + instance_ = new bin_io; + return instance_; + } + + void + bin_io::delete_instance() + { + if (instance_ != 0) + { + delete instance_; + instance_ = 0; + } + } + + CGBIO_ERROR + bin_io::new_elf_reader( elf_reader** obj ) const + { + CGBIO_ERROR ret = CGBIO_ERROR_NO_ERROR; + *obj = new elf_reader_impl; + if ( *obj == 0 ) + ret = CGBIO_ERROR_MEMORY; + return ret; + } + + CGBIO_ERROR + bin_io::new_elf_writer( elf_writer** obj ) const + { + CGBIO_ERROR ret = CGBIO_ERROR_NO_ERROR; + *obj = new elf_writer_impl; + if ( *obj == 0 ) + ret = CGBIO_ERROR_MEMORY; + return ret; + } + + const char* + bin_io::error_string( CGBIO_ERROR error ) const + { + switch ( error ) + { + case CGBIO_ERROR_NO_ERROR: + return "No error"; + case CGBIO_ERROR_LOADED: + return "Binary file has been loaded earlier"; + case CGBIO_ERROR_FILEIO: + return "File input output error"; + case CGBIO_ERROR_FORMAT: + return "File format error"; + case CGBIO_ERROR_INDEX: + return "Index is out of range"; + case CGBIO_ERROR_MEMORY: + return "Can't allocate memory"; + case CGBIO_ERROR_RELOC: + return "Relocation error"; + case CGBIO_ERROR_SYMBOL: + return "Symbol error"; + case CGBIO_ERROR_UNKNOWN_TYPE: + return "Uknown type"; + default: + return "Unknown error"; + } + return "Unknown error"; + } + + CGBIO_ERROR + bin_io::new_nvb_reader( nvb_reader** obj ) const + { + CGBIO_ERROR ret = CGBIO_ERROR_NO_ERROR; + *obj = new nvb_reader_impl; + if (*obj == 0) + ret = CGBIO_ERROR_MEMORY; + return ret; + } + + CGBIO_ERROR + bin_io::new_nvb_writer( nvb_writer** obj ) const + { + CGBIO_ERROR ret = CGBIO_ERROR_NO_ERROR; + *obj = new nvb_writer_impl; + if (*obj == 0) + ret = CGBIO_ERROR_MEMORY; + return ret; + } + + + } // bio namespace +} // cgc namespace + +/*============================================================ + CGBII IMPLEMENTATION + ============================================================ */ + +using std::fill_n; + +namespace cgc { + namespace bio { + + elf_reader_impl::elf_reader_impl() + { + ref_count_ = 1; + initialized_ = false; + fill_n( reinterpret_cast( &header_ ), sizeof( header_ ), '\0' ); + } + + elf_reader_impl::~elf_reader_impl() + { + if (initialized_) + { + // NYI + } + } + + CGBIO_ERROR + elf_reader_impl::load( const char* filename ) + { + // NYI + return CGBIO_ERROR_NO_ERROR; + } + + CGBIO_ERROR + elf_reader_impl::load( std::istream* stream, int start ) + { + // NYI + return CGBIO_ERROR_NO_ERROR; + } + + bool + elf_reader_impl::is_initialized() const + { + return initialized_; + } + + ptrdiff_t + elf_reader_impl::reference() const + { + return ++ref_count_; + } + + ptrdiff_t + elf_reader_impl::release() const + { + ptrdiff_t ret = --ref_count_; + if (ref_count_ == 0) + delete this; + + return ret; + } + + } // bio namespace +} // cgc namespace + +/*============================================================ + CGBO IMPLEMENTATION + ============================================================ */ + +namespace cgc { + namespace bio { + + elf_writer_impl::elf_writer_impl() + { + ref_count_ = 1; + std::fill_n( reinterpret_cast( &header_ ), sizeof( header_ ), '\0' ); + } + + elf_writer_impl::~elf_writer_impl() + { + std::vector::iterator it; + for ( it = sections_.begin(); it != sections_.end(); ++it) + { + delete (*it); + } + } + + ptrdiff_t + elf_writer_impl::reference() + { + return ++ref_count_; + } + + ptrdiff_t + elf_writer_impl::release() + { + ptrdiff_t ret = --ref_count_; + if (ref_count_ == 0) + delete this; + return ret; + } + + CGBIO_ERROR + elf_writer_impl::save( ofstream& ofs ) + { + CGBIO_ERROR ret = CGBIO_ERROR_NO_ERROR; + if ( !ofs ) + { + return CGBIO_ERROR_FILEIO; + } + header_.e_shoff = convert_endianness( (uint32_t) sizeof( Elf32_Ehdr ), endianness() ); + header_.e_phnum = convert_endianness( (uint16_t)0, endianness() ); + header_.e_shnum = convert_endianness( (uint16_t)num_of_sections(), endianness() ); + + streampos header = convert_endianness( header_.e_shoff, endianness() ); + for ( unsigned int ii = 0; ii < sections_.size(); ++ii ) + { + sections_[ii]->save( ofs, header, section_offset( ii ) ); + header += sizeof( Elf32_Shdr ); + } + + ofs.seekp( 0 ); + ofs.write( reinterpret_cast( &header_ ), sizeof( Elf32_Ehdr ) ); + ofs.close(); + + return ret; + } + + CGBIO_ERROR + elf_writer_impl::save( const char* filename ) + { + ofstream ofs( filename, std::ios::out | std::ios::binary ); + return save( ofs ); + } + + CGBIO_ERROR + elf_writer_impl::set_attr( const unsigned char file_class, + const unsigned char endianness, + const unsigned char ELFversion, + const unsigned char abi, + const unsigned char ABIversion, + const uint16_t type, + const uint16_t machine, + const uint32_t version, + const uint32_t flags ) + { + header_.e_ident[EI_MAG0] = ELFMAG0; + header_.e_ident[EI_MAG1] = ELFMAG1; + header_.e_ident[EI_MAG2] = ELFMAG2; + header_.e_ident[EI_MAG3] = ELFMAG3; + header_.e_ident[EI_CLASS] = file_class; + header_.e_ident[EI_DATA] = endianness; + header_.e_ident[EI_VERSION] = ELFversion; + header_.e_ident[EI_OSABI] = abi; + header_.e_ident[EI_ABIVERSION] = ABIversion; + + header_.e_type = convert_endianness( type, endianness ); + header_.e_machine = convert_endianness( machine, endianness ); + header_.e_version = convert_endianness( version, endianness ); + header_.e_flags = convert_endianness( flags, endianness ); + + header_.e_ehsize = convert_endianness( (uint16_t)(sizeof( header_ )), endianness ); + header_.e_phentsize = convert_endianness( (uint16_t)(sizeof( Elf32_Phdr )), endianness ); + header_.e_shentsize = convert_endianness( (uint16_t)(sizeof( Elf32_Shdr )), endianness ); + header_.e_shstrndx = convert_endianness( (uint16_t)1, endianness ); + + // Create empty and section header string table sections + osection_impl* sec0 = new osection_impl( 0, this, "", 0, 0, 0, 0, 0 ); + sections_.push_back( sec0 ); + sec0->set_name_index( 0 ); + + + osection_impl* shstrtab = new osection_impl( 1, this, ".shstrtab", SHT_STRTAB, 0, 0, 0, 0 ); + sections_.push_back( shstrtab ); + + // Add the name to the section header string table + ostring_table* strtbl = 0; + void* vp = strtbl; + if ( CGBIO_ERROR_NO_ERROR == new_section_out( CGBO_STR, shstrtab, &vp ) ) + { + strtbl = static_cast( vp ); + uint32_t index = strtbl->add(shstrtab->name()); + shstrtab->set_name_index( index ); + strtbl->release(); + } + return CGBIO_ERROR_NO_ERROR; + } + + Elf32_Addr + elf_writer_impl::get_entry() const + { + return convert_endianness( header_.e_entry, endianness() ); + } + + CGBIO_ERROR + elf_writer_impl::set_entry( Elf32_Addr entry ) + { + header_.e_entry = convert_endianness( entry, endianness() ); + return CGBIO_ERROR_NO_ERROR; + } + + unsigned char + elf_writer_impl::endianness() const + { + return header_.e_ident[EI_DATA]; + } + + uint16_t + elf_writer_impl::num_of_sections() const + { + return (uint16_t)sections_.size(); + } + + osection* + elf_writer_impl::get_section( uint16_t index ) const + { + osection* ret = 0; + if ( index < num_of_sections() ) + { + ret = sections_[index]; + ret->reference(); + } + return ret; + } + + osection* + elf_writer_impl::get_section( const char* name ) const + { + osection* ret = 0; + + std::vector::const_iterator it; + for ( it = sections_.begin(); it != sections_.end(); ++it ) + { + if ( (*it)->name() == name ) + { + ret = *it; + ret->reference(); + break; + } + } + return ret; + } + + osection* + elf_writer_impl::add_section( const char* name, + uint32_t type, + uint32_t flags, + uint32_t info, + uint32_t align, + uint32_t esize ) + { + osection_impl* sec = new osection_impl( (uint16_t)sections_.size(), this, name, type, flags, info, align, esize ); + if (sec == 0) + return sec; + sec->reference(); + sections_.push_back( sec ); + osection* shstrtab = get_section( 1 ); + ostring_table* strtbl; + void* vp; + if ( CGBIO_ERROR_NO_ERROR == new_section_out( CGBO_STR, shstrtab, &vp ) ) + { + strtbl = static_cast( vp ); + uint32_t index = strtbl->add( name ); + sec->set_name_index( index ); + strtbl->release(); + } + shstrtab->release(); + return sec; + } + + streampos + elf_writer_impl::section_offset( uint16_t index ) const + { + streampos ret = sizeof( Elf32_Ehdr ) + sizeof( Elf32_Shdr ) * num_of_sections(); + uint16_t size = (uint16_t)sections_.size(); + uint32_t align = 0; + for ( uint16_t ii = 0; ii < size && ii < index; ++ii ) + { + if ( sections_[ii]->type() != SHT_NOBITS && sections_[ii]->type() != SHT_NULL ) + { + align = sections_[ii]->addralign(); + if ( align > 1 && ret % align != 0 ) + { + ret += align - ret % align; + } + ret += sections_[ii]->size(); + } + } + if ( sections_[index]->type() != SHT_NOBITS && sections_[index]->type() != SHT_NULL ) + { + align = sections_[index]->addralign(); + if ( align > 1 && ret % align != 0 ) + { + ret += align - ret % align; + } + } + return ret; + } + + CGBIO_ERROR + elf_writer_impl::new_section_out( PRODUCER type, osection* sec, void** obj ) const + { + CGBIO_ERROR ret = CGBIO_ERROR_NO_ERROR; + + switch ( type ) + { + case CGBO_STR: + *obj = new ostring_table_impl( const_cast( this ), sec ); + break; + case CGBO_SYM: + *obj = new osymbol_table_impl( const_cast( this ), sec ); + break; + case CGBO_REL: + *obj = new orelocation_table_impl( const_cast( this ), sec ); + break; + case CGBO_PARAM: + *obj = new oparam_table_impl( const_cast( this ), sec ); + break; + case CGBO_CONST: + *obj = new oconst_table_impl( const_cast( this ), sec ); + break; + default: + ret = CGBIO_ERROR_UNKNOWN_TYPE; + obj = 0; + } + return ret; + } + + + osection_impl::osection_impl( uint16_t index, + elf_writer* cgbo, + const char* name, + uint32_t type, + uint32_t flags, + uint32_t info, + uint32_t align, + uint32_t esize ) : + index_( index ), + cgbo_( cgbo ), + data_( 0 ) + { + strncpy(name_, name,sizeof(name_)); + name_[sizeof(name_)-1] = '\0'; + std::fill_n( reinterpret_cast( &sh_ ), sizeof( sh_ ), '\0' ); + sh_.sh_type = convert_endianness( type, cgbo_->endianness() ); + sh_.sh_flags = convert_endianness( flags, cgbo_->endianness() ); + sh_.sh_info = convert_endianness( info, cgbo_->endianness() ); + sh_.sh_addralign = convert_endianness( align, cgbo_->endianness() ); + sh_.sh_entsize = convert_endianness( esize, cgbo_->endianness() ); + } + + osection_impl::~osection_impl() + { + delete [] data_; + } + + ptrdiff_t + osection_impl::reference() + { + return cgbo_->reference(); + } + + ptrdiff_t + osection_impl::release() + { + return cgbo_->release(); + } + + CGBIO_ERROR + osection_impl::save(ofstream& of, streampos header, streampos data) + { + CGBIO_ERROR ret = CGBIO_ERROR_NO_ERROR; + + if (index() != 0 && SHT_NOBITS != type()) + { + sh_.sh_offset = convert_endianness( (uint32_t)data, cgbo_->endianness() ); + } + of.seekp( header ); + of.write( reinterpret_cast( &sh_ ), sizeof( Elf32_Shdr ) ); + if ( SHT_NOBITS != type() ) + { + of.seekp( data ); + of.write( get_data(), size() ); + } + return ret; + } + + uint16_t + osection_impl::index() const + { + return index_; + } + + const char * + osection_impl::name() const + { + return name_; + } + + uint32_t + osection_impl::type() const + { + return convert_endianness( sh_.sh_type, cgbo_->endianness() ); + } + + uint32_t + osection_impl::flags() const + { + return convert_endianness( sh_.sh_flags, cgbo_->endianness() ); + } + + uint32_t + osection_impl::info() const + { + return convert_endianness( sh_.sh_info, cgbo_->endianness() ); + } + + uint32_t + osection_impl::addralign() const + { + return convert_endianness( sh_.sh_addralign, cgbo_->endianness() ); + } + + uint32_t + osection_impl::entsize() const + { + return convert_endianness( sh_.sh_entsize, cgbo_->endianness() ); + } + + uint32_t + osection_impl::size() const + { + return convert_endianness( sh_.sh_size, cgbo_->endianness() ); + } + + uint32_t + osection_impl::get_name_index() const + { + return convert_endianness( sh_.sh_name, cgbo_->endianness() ); + } + + void + osection_impl::set_name_index( uint32_t index ) + { + sh_.sh_name = convert_endianness( index, cgbo_->endianness() ); + } + + Elf32_Addr + osection_impl::get_address() const + { + return convert_endianness( sh_.sh_addr, cgbo_->endianness() ); + } + + void + osection_impl::set_address( Elf32_Addr addr ) + { + sh_.sh_addr = convert_endianness( addr, cgbo_->endianness() ); + } + + uint32_t + osection_impl::get_link() const + { + return convert_endianness( sh_.sh_link, cgbo_->endianness() ); + } + + void + osection_impl::set_link( uint32_t link ) + { + sh_.sh_link = convert_endianness( link, cgbo_->endianness() ); + } + + char* + osection_impl::get_data() const + { + return data_; + } + + CGBIO_ERROR + osection_impl::set_data( const char* data, const uint32_t size ) + { + CGBIO_ERROR ret = CGBIO_ERROR_NO_ERROR; + sh_.sh_size = convert_endianness( size, cgbo_->endianness() ); + + if ( SHT_NOBITS == type() ) + { + return ret; + } + delete [] data_; + data_ = new char[size]; + if (size != 0) + { + if (data_ == 0) + { + sh_.sh_size = 0; + ret = CGBIO_ERROR_MEMORY; + } + else if (data != 0) + std::copy( data, data + size, data_ ); + } + + return ret; + } + + CGBIO_ERROR + osection_impl::add_data( const char* data, const uint32_t size ) + { + CGBIO_ERROR ret = CGBIO_ERROR_NO_ERROR; + + char* new_data = new char[ osection_impl::size() + size]; + if (new_data == 0) + ret = CGBIO_ERROR_MEMORY; + else + { + std::copy( data_, data_ + osection_impl::size(), new_data ); + std::copy( data, data + size, new_data + osection_impl::size() ); + delete [] data_; + data_ = new_data; + sh_.sh_size = convert_endianness(osection_impl::size()+size, cgbo_->endianness() ); + } + + return ret; + } + + ostring_table_impl::ostring_table_impl( elf_writer* cgbo, osection* section ) + : ref_count_( 1 ) + , cgbo_( cgbo ) + , section_( section ) + { + if ( section->get_data() != 0 && section->size() != 0) + { + data_.insert(data_.end(), section->get_data(),section->get_data() + section->size()); + //data_.append( section->get_data(), section->size() ); + } + cgbo_->reference(); + section_->reference(); + } + + ostring_table_impl::~ostring_table_impl() + { + } + + ptrdiff_t + ostring_table_impl::reference() + { + cgbo_->reference(); + section_->reference(); + return ++ref_count_; + } + + ptrdiff_t + ostring_table_impl::release() + { + ptrdiff_t ret = --ref_count_; + elf_writer* cgbo = cgbo_; + osection* sec = section_; + + if (ref_count_ == 0) + { + section_->set_data( &data_[0], (uint32_t)data_.size() ); + delete this; + } + sec->release(); + cgbo->release(); + return ret; + } + + const char* + ostring_table_impl::get( uint32_t index ) const + { + if ( index < data_.size() ) + { + const char* data = &data_[0]; + if (data != 0) + return data + index; + } + return 0; + } + + uint32_t + ostring_table_impl::find( const char* str ) const + { + const char* data = &data_[0]; + size_t size = data_.size(); + const char *end = data + size; + + size_t length = strlen(str); + if (length+1 > size) + return 0; + data += length; + + const char *p = (char*)memchr(data,'\0',end-data); + while (p && (end-data)>0) + { + if (!memcmp(p - length, str, length)) + { +#ifdef MSVC +#pragma warning( push ) +#pragma warning ( disable : 4311 ) +#endif + return (uint32_t)(p - length - &data_[0]); +#ifdef MSVC +#pragma warning ( pop ) +#endif + } + data = p+1; + p = (char*)memchr(data,'\0',end-data); + } + return 0; + } + + uint32_t + ostring_table_impl::addUnique( const char* str ) + { + if ( data_.size() == 0 ) + data_.push_back('\0'); + uint32_t ret = find(str); + if (ret == 0 && str[0] != '\0') + ret = add(str); + return ret; + } + + uint32_t + ostring_table_impl::add( const char* str ) + { + uint32_t ret = (uint32_t)data_.size(); + + if ( data_.size() == 0 ) + { + data_.push_back('\0'); + ret = 1; + } + + data_.insert( data_.end(), str ,str + strlen(str) + 1); + + return ret; + } + + oconst_table_impl::oconst_table_impl( elf_writer* cgbo, osection* section ) + : ref_count_( 1 ) + , cgbo_( cgbo ) + , section_( section ) + { + if (section->get_data() != 0 && section->size() != 0) + { + size_t count = section->size()/sizeof(uint32_t); + data_.resize(count); + memcpy(&data_[0],section->get_data(),count*sizeof(uint32_t)); + } + cgbo_->reference(); + section_->reference(); + } + + oconst_table_impl::~oconst_table_impl() + { + } + + ptrdiff_t + oconst_table_impl::reference() + { + cgbo_->reference(); + section_->reference(); + return ++ref_count_; + } + + ptrdiff_t + oconst_table_impl::release() + { + ptrdiff_t ret = --ref_count_; + elf_writer* cgbo = cgbo_; + osection* sec = section_; + + if (ref_count_ == 0) + { + section_->set_data( (const char*)&data_[0], (uint32_t)(data_.size()*sizeof(uint32_t)) ); + delete this; + } + sec->release(); + cgbo->release(); + return ret; + } + + const uint32_t* + oconst_table_impl::get( uint32_t index ) const + { + if ( index < data_.size() ) + { + return &data_[index]; + } + return NULL; + } + + uint32_t + oconst_table_impl::add( const uint32_t *data, uint32_t count) + { + uint32_t ret = (uint32_t)data_.size(); + data_.resize(ret+count); + memcpy(&data_[ret],data,count*sizeof(uint32_t)); + return ret; + } + + osymbol_table_impl::osymbol_table_impl( elf_writer* cgbo, osection* sec ) : + ref_count_( 1 ), cgbo_( cgbo ), section_( sec ) + { + cgbo_->reference(); + section_->reference(); + if (section_->size() == 0) + { + Elf32_Sym entry; + entry.st_name = 0; + entry.st_value = 0; + entry.st_size = 0; + entry.st_info = 0; + entry.st_other = 0; + entry.st_shndx = 0; + CGBIO_ERROR err = section_->add_data( reinterpret_cast( &entry ), sizeof( entry ) ); + if ( CGBIO_ERROR_NO_ERROR != err ) + { + ; + } + } + } + + osymbol_table_impl::~osymbol_table_impl() + { + } + + ptrdiff_t + osymbol_table_impl::reference() + { + cgbo_->reference(); + section_->reference(); + return ++ref_count_; + } + + ptrdiff_t + osymbol_table_impl::release() + { + ptrdiff_t ret = --ref_count_; + elf_writer* cgbo = cgbo_; + osection* sec = section_; + if (ref_count_ == 0 ) + { + delete this; + } + sec->release(); + cgbo->release(); + return ret; + } + + uint32_t + osymbol_table_impl::add_entry( uint32_t name, + Elf32_Addr value, + uint32_t size, + unsigned char info, + unsigned char other, + uint16_t shndx ) + { + Elf32_Sym entry; + entry.st_name = convert_endianness( name, cgbo_->endianness() ); + entry.st_value = convert_endianness( value, cgbo_->endianness() ); + entry.st_size = convert_endianness( size, cgbo_->endianness() );; + entry.st_info = info; + entry.st_other = other; + entry.st_shndx = convert_endianness( shndx, cgbo_->endianness() ); + CGBIO_ERROR err = section_->add_data( reinterpret_cast( &entry ), sizeof( entry ) ); + if ( CGBIO_ERROR_NO_ERROR != err ) + { + ; + } + uint32_t ret = section_->size() / sizeof(Elf32_Sym) - 1; + return ret; + } + + uint32_t + osymbol_table_impl::add_entry( uint32_t name, + Elf32_Addr value, + uint32_t size, + unsigned char bind, + unsigned char type, + unsigned char other, + uint16_t shndx ) + { + return 0; + } + + uint32_t + osymbol_table_impl::add_entry( ostring_table* strtab, + const char* str, + Elf32_Addr value, + uint32_t size, + unsigned char info, + unsigned char other, + uint16_t shndx ) + { + return 0; + } + + uint32_t + osymbol_table_impl::add_entry( ostring_table* strtab, + const char* str, + Elf32_Addr value, + uint32_t size, + unsigned char bind, + unsigned char type, + unsigned char other, + uint16_t shndx ) + { + return 0; + } + + + orelocation_table_impl::orelocation_table_impl( elf_writer* cgbo, osection* sec ) + { + } + + orelocation_table_impl::~orelocation_table_impl() + { + } + + ptrdiff_t + orelocation_table_impl::reference() + { + return 0; + } + + ptrdiff_t + orelocation_table_impl::release() + { + return 0; + } + + CGBIO_ERROR + orelocation_table_impl::add_entry( Elf32_Addr offset, + uint32_t info ) + { + return CGBIO_ERROR_NO_ERROR; + } + + CGBIO_ERROR + orelocation_table_impl::add_entry( Elf32_Addr offset, + uint32_t symbol, + unsigned char type ) + { + return CGBIO_ERROR_NO_ERROR; + } + + CGBIO_ERROR + orelocation_table_impl::add_entry( Elf32_Addr offset, + uint32_t info, + Elf32_Sword addend ) + { + return CGBIO_ERROR_NO_ERROR; + } + + + CGBIO_ERROR + orelocation_table_impl::add_entry( Elf32_Addr offset, + uint32_t symbol, + unsigned char type, + Elf32_Sword addend ) + { + return CGBIO_ERROR_NO_ERROR; + } + + + CGBIO_ERROR + orelocation_table_impl::add_entry( ostring_table* pStrWriter, + const char* str, + osymbol_table* pSymWriter, + Elf32_Addr value, + uint32_t size, + unsigned char symInfo, + unsigned char other, + uint16_t shndx, + Elf32_Addr offset, + unsigned char type ) + { + return CGBIO_ERROR_NO_ERROR; + } + + + CGBIO_ERROR + orelocation_table_impl::add_entry( ostring_table* pStrWriter, + const char* str, + osymbol_table* pSymWriter, + Elf32_Addr value, + uint32_t size, + unsigned char symInfo, + unsigned char other, + uint16_t shndx, + Elf32_Addr offset, + unsigned char type, + Elf32_Sword addend ) + { + return CGBIO_ERROR_NO_ERROR; + } + + + oparam_table_impl::oparam_table_impl( elf_writer* cgbo, osection* sec ) : + ref_count_( 1 ), cgbo_( cgbo ), section_( sec ) + { + cgbo_->reference(); + section_->reference(); + } + + oparam_table_impl::~oparam_table_impl() + { + } + + ptrdiff_t + oparam_table_impl::reference() + { + cgbo_->reference(); + section_->reference(); + return ++ref_count_; + } + + ptrdiff_t + oparam_table_impl::release() + { + ptrdiff_t ret = --ref_count_; + elf_writer* cgbo = cgbo_; + osection* sec = section_; + if (ref_count_ == 0) + delete this; + sec->release(); + cgbo->release(); + return ret; + } + + CGBIO_ERROR + oparam_table_impl::add_entry( Elf32_cgParameter& parameter ) + { + void* vp = ¶meter; + return section_->add_data( static_cast( vp ), sizeof( parameter ) ); + } + + + } // bio namespace +} // cgc namespace + +/*============================================================ + NVBI IMPLEMENTATION + ============================================================ */ + +namespace cgc { + namespace bio { + + nvb_reader_impl::nvb_reader_impl() + { + ref_count_ = 1; + offset_ = 0; + image_ = 0; + owner_ = false; + loaded_ = false; + endianness_ = host_endianness(); + std::fill_n( reinterpret_cast( &header_ ), sizeof( header_ ), '\0' ); + } + + nvb_reader_impl::~nvb_reader_impl() + { + if (image_ != 0) + delete [] image_; + } + + ptrdiff_t + nvb_reader_impl::reference() const + { + return ++ref_count_; + } + + ptrdiff_t + nvb_reader_impl::release() const + { + ptrdiff_t ret = --ref_count_; + if (ref_count_ == 0) + { + delete this; + } + return ret; + } + + CGBIO_ERROR + nvb_reader_impl::loadFromString( const char* source, size_t length) + { + if ( loaded_ ) + { + return CGBIO_ERROR_LOADED; + } +#if defined(RGL_USE_STD_STRING) && !(defined(__CELLOS_LV2__)) + std::ios_base::openmode mode = std::ios_base::in | std::ios_base::binary; + std::istringstream* iss = new std::istringstream(mode); + if (iss == 0) + { + return CGBIO_ERROR_MEMORY; + } + + std::string sourceString((const char*)source,length); + iss->str(sourceString); + if ( !*iss ) + { + return CGBIO_ERROR_FILEIO; + } + strStream_ = true; + owner_ = true; + CGBIO_ERROR ret = load( iss, 0 ); +#else + CGBIO_ERROR ret = CGBIO_ERROR_NO_ERROR; + while (1) + { + if (length < sizeof( header_ )) + { + ret = CGBIO_ERROR_FORMAT; + break; + } + memcpy(&header_ ,source,sizeof( header_ )); + if ( CG_BINARY_FORMAT_REVISION != header_.binaryFormatRevision ) + { + endianness_ = ( CGBIODATALSB == endianness_ ) ? CGBIODATAMSB : CGBIODATALSB; + int binaryRevision = convert_endianness( header_.binaryFormatRevision, endianness_ ); + if ( CG_BINARY_FORMAT_REVISION != binaryRevision ) + { + ret = CGBIO_ERROR_FORMAT; + break; + } + } + size_t sz = length; + image_ = new char[sz]; + memcpy(image_,source,sz); + loaded_ = true; + ret = CGBIO_ERROR_NO_ERROR; + break; + } +#endif + return ret; + } + +#ifndef __CELLOS_LV2__ + + CGBIO_ERROR + nvb_reader_impl::load( const char* filename ) + { + if ( loaded_ ) + return CGBIO_ERROR_LOADED; + std::ifstream* ifs = new std::ifstream; + if (ifs == 0) + return CGBIO_ERROR_MEMORY; + ifs->open( filename, std::ios::in | std::ios::binary ); + if ( !*ifs ) + { + return CGBIO_ERROR_FILEIO; + } + CGBIO_ERROR ret = load( ifs, 0 ); + strStream_ = false; + owner_ = true; + return ret; + } + + CGBIO_ERROR + nvb_reader_impl::load( std::istream* stream, int start, bool owner ) + { + if ( loaded_ ) + { + return CGBIO_ERROR_LOADED; + } + owner_ = owner; + offset_ = start; + stream->seekg( offset_ ); + stream->read( reinterpret_cast( &header_ ), sizeof( header_ ) ); + if ( stream->gcount() != sizeof( header_ ) ) + { + return CGBIO_ERROR_FORMAT; + } + if ( CG_BINARY_FORMAT_REVISION != header_.binaryFormatRevision ) + { + endianness_ = ( CGBIODATALSB == endianness_ ) ? CGBIODATAMSB : CGBIODATALSB; + + int binaryRevision = convert_endianness( header_.binaryFormatRevision, endianness_ ); + if ( CG_BINARY_FORMAT_REVISION != binaryRevision ) + { + return CGBIO_ERROR_FORMAT; + } + } + unsigned int sz = size(); + image_ = new char[sz]; + stream->seekg( offset_ ); + stream->read( image_, sz ); + loaded_ = true; + + if (owner_) + { + ((std::ifstream*) stream)->close(); + delete stream; + } + return CGBIO_ERROR_NO_ERROR; + } + +#endif + + bool + nvb_reader_impl::is_loaded() const + { + return loaded_; + } + + unsigned char + nvb_reader_impl::endianness() const + { + return endianness_; + } + + CGprofile + nvb_reader_impl::profile() const + { + return (CGprofile) convert_endianness( (unsigned int) header_.profile, endianness() ); + } + + unsigned int + nvb_reader_impl::revision() const + { + return convert_endianness( header_.binaryFormatRevision, endianness() ); + } + + unsigned int + nvb_reader_impl::size() const + { + return convert_endianness( header_.totalSize, endianness() ); + } + + unsigned int + nvb_reader_impl::number_of_params() const + { + return convert_endianness( header_.parameterCount, endianness() ); + } + + unsigned int + nvb_reader_impl::ucode_size() const + { + return convert_endianness( header_.ucodeSize, endianness() ); + } + + const char* + nvb_reader_impl::ucode() const + { + if (image_ == 0 || ucode_size() == 0) + return 0; + return ( image_ + convert_endianness( header_.ucode, endianness() ) ); + } + + const CgBinaryFragmentProgram* + nvb_reader_impl::fragment_program() const + { + if (image_ == 0) + return 0; + return reinterpret_cast( &image_[convert_endianness( header_.program, endianness_ )] ); + } + + const CgBinaryVertexProgram* + nvb_reader_impl::vertex_program() const + { + if (image_ == 0) + return 0; + return reinterpret_cast( &image_[convert_endianness( header_.program, endianness_ )] ); + } + + CGBIO_ERROR + nvb_reader_impl::get_param_name( unsigned int index, const char **name, bool& is_referenced ) const + { + if (index >= number_of_params()) + return CGBIO_ERROR_INDEX; + + if (image_ == 0) + return CGBIO_ERROR_NO_ERROR; + + const CgBinaryParameter* params = reinterpret_cast( &image_[convert_endianness( header_.parameterArray, endianness_ )] ); + const CgBinaryParameter& pp = params[index]; + is_referenced = convert_endianness( pp.isReferenced, endianness() ) != 0; + CgBinaryStringOffset nm_offset = convert_endianness( pp.name,endianness() ); + if (nm_offset != 0) + *name = &image_[nm_offset]; + else + *name = ""; + return CGBIO_ERROR_NO_ERROR; + } + + CGBIO_ERROR + nvb_reader_impl::get_param( unsigned int index, + CGtype& type, + CGresource& resource, + CGenum& variability, + int& resource_index, + const char ** name, + std::vector& default_value, + std::vector& embedded_constants, + const char ** semantic, + CGenum& direction, + int& paramno, + bool& is_referenced, + bool& is_shared ) const + { + if (index >= number_of_params()) + return CGBIO_ERROR_INDEX; + + if (image_ == 0) + return CGBIO_ERROR_NO_ERROR; + + const CgBinaryParameter* params = reinterpret_cast( &image_[convert_endianness( header_.parameterArray, endianness_ )] ); + const CgBinaryParameter& pp = params[index]; + type = static_cast( convert_endianness( static_cast( pp.type ), endianness() ) ); + resource = static_cast( convert_endianness( static_cast( pp.res ), endianness() ) ); + variability = static_cast( convert_endianness( static_cast( pp.var ), endianness() ) ); + resource_index = convert_endianness( pp.resIndex, endianness() ); + direction = static_cast( convert_endianness( static_cast( pp.direction ), endianness() ) ); + paramno = convert_endianness( pp.paramno, endianness() ); + is_referenced = convert_endianness( pp.isReferenced, endianness() ) != 0; + is_shared = convert_endianness( pp.isShared, endianness() ) != 0; + CgBinaryStringOffset nm_offset = convert_endianness( pp.name, endianness() ); + CgBinaryFloatOffset dv_offset = convert_endianness( pp.defaultValue, endianness() ); + CgBinaryEmbeddedConstantOffset ec_offset = convert_endianness( pp.embeddedConst, endianness() ); + CgBinaryStringOffset sm_offset = convert_endianness( pp.semantic, endianness() ); + if (nm_offset != 0) + *name = &image_[nm_offset]; + else + *name = ""; + + if (sm_offset != 0) + *semantic = &image_[sm_offset]; + else + *semantic = ""; + if (dv_offset != 0) + { + char *vp = &image_[dv_offset]; + for (int ii = 0; ii < 4; ++ii) + { + /*#ifndef __CELLOS_LV2__ + float *fv = static_cast( vp ); + float f = fv[ii]; + unsigned int tmp = *(unsigned int*)&f; + tmp = convert_endianness(tmp,endianness()); + default_value.push_back( *(float*)&tmp ); +#else*/ + int tmp; + memcpy(&tmp,vp+4*ii,4); + tmp = convert_endianness(tmp,endianness()); + float tmp2; + memcpy(&tmp2,&tmp,4); + default_value.push_back( tmp2 ); + //#endif + } + } + if (ec_offset != 0) + { + void *vp = &image_[ec_offset]; + CgBinaryEmbeddedConstant& ec = *(static_cast( vp )); + for (unsigned int ii = 0; ii < convert_endianness( ec.ucodeCount, endianness() ); ++ii) + { + unsigned int offset = convert_endianness( ec.ucodeOffset[ii], endianness() ); + embedded_constants.push_back( offset ); + } + } + return CGBIO_ERROR_NO_ERROR; + } + + + } +} + +/*============================================================ + NVBO IMPLEMENTATION + ============================================================ */ + +using std::copy; +using std::fill_n; + +namespace cgc { + namespace bio { + + nvb_writer_impl::nvb_writer_impl() + { + ref_count_ = 1; + fill_n( reinterpret_cast( &header_ ), sizeof( header_ ), '\0' ); + } + + nvb_writer_impl::~nvb_writer_impl() + { + } + + ptrdiff_t + nvb_writer_impl::reference() + { + return ++ref_count_; + } + + ptrdiff_t + nvb_writer_impl::release() + { + ptrdiff_t ret = --ref_count_; + if (ref_count_ == 0) + delete this; + return ret; + } + + CGBIO_ERROR + nvb_writer_impl::save( ofstream& ofs ) + { + CGBIO_ERROR ret = CGBIO_ERROR_NO_ERROR; + if ( !ofs ) + { + return CGBIO_ERROR_FILEIO; + } + header_.e_shoff = convert_endianness( (uint32_t)sizeof( Elf32_Ehdr ), endianness() ); + header_.e_phnum = convert_endianness( 0, endianness() ); + ofs.seekp( 0 ); + ofs.write( reinterpret_cast( &header_ ), sizeof( Elf32_Ehdr ) ); + ofs.close(); + + return ret; + } + + CGBIO_ERROR + nvb_writer_impl::save( const char* filename ) + { + ofstream ofs( filename, std::ios::out | std::ios::binary ); + return save( ofs ); + } + + CGBIO_ERROR + nvb_writer_impl::set_attr( const unsigned char file_class, + const unsigned char endianness, + const unsigned char ELFversion, + const unsigned char abi, + const unsigned char ABIversion, + const uint16_t type, + const uint16_t machine, + const uint32_t version, + const uint32_t flags ) + { + header_.e_ident[EI_MAG0] = ELFMAG0; + header_.e_ident[EI_MAG1] = ELFMAG1; + header_.e_ident[EI_MAG2] = ELFMAG2; + header_.e_ident[EI_MAG3] = ELFMAG3; + header_.e_ident[EI_CLASS] = file_class; + header_.e_ident[EI_DATA] = endianness; + header_.e_ident[EI_VERSION] = ELFversion; + header_.e_ident[EI_OSABI] = abi; + header_.e_ident[EI_ABIVERSION] = ABIversion; + + header_.e_type = convert_endianness( type, endianness ); + header_.e_machine = convert_endianness( machine, endianness ); + header_.e_version = convert_endianness( version, endianness ); + header_.e_flags = convert_endianness( flags, endianness ); + + header_.e_ehsize = convert_endianness( (uint16_t)sizeof( header_ ), endianness ); + header_.e_phentsize = convert_endianness( (uint16_t)sizeof( Elf32_Phdr ), endianness ); + header_.e_shentsize = convert_endianness( (uint16_t)sizeof( Elf32_Shdr ), endianness ); + header_.e_shstrndx = convert_endianness( 1, endianness ); + return CGBIO_ERROR_NO_ERROR; + } + + Elf32_Addr + nvb_writer_impl::get_entry() const + { + return convert_endianness( header_.e_entry, endianness() ); + } + + CGBIO_ERROR + nvb_writer_impl::set_entry( Elf32_Addr entry ) + { + header_.e_entry = convert_endianness( entry, endianness() ); + return CGBIO_ERROR_NO_ERROR; + } + + unsigned char + nvb_writer_impl::endianness() const + { + return header_.e_ident[EI_DATA]; + } + + oparam_array_impl::oparam_array_impl( nvb_writer* cgbo ) : + ref_count_( 1 ), cgbo_( cgbo ) + { + cgbo_->reference(); + } + + oparam_array_impl::~oparam_array_impl() + { + } + + ptrdiff_t oparam_array_impl::reference() + { + cgbo_->reference(); + return ++ref_count_; + } + + ptrdiff_t + oparam_array_impl::release() + { + ptrdiff_t ret = --ref_count_; + nvb_writer* cgbo = cgbo_; + + if (ref_count_ == 0) + delete this; + + cgbo->release(); + return ret; + } + + CGBIO_ERROR + oparam_array_impl::add_entry() + { + CGBIO_ERROR ret = CGBIO_ERROR_NO_ERROR; + return ret; + } + + + } +} diff --git a/console/rgl/src/rgl_cg.h b/console/rgl/src/rgl_cg.h new file mode 100644 index 0000000000..f4db023831 --- /dev/null +++ b/console/rgl/src/rgl_cg.h @@ -0,0 +1,105 @@ +/* RetroArch - A frontend for libretro. + * RGL - An OpenGL subset wrapper library. + * Copyright (C) 2012 - Hans-Kristian Arntzen + * Copyright (C) 2012 - Daniel De Matteis + * + * RetroArch 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 Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch 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 RetroArch. + * If not, see . + */ + +#ifndef _RGL_CG_H +#define _RGL_CG_H + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "../include/export/RGL/rgl.h" +#include "../include/RGL/private.h" +#include "../include/RGL/Types.h" +#include "../include/RGL/Utils.h" +#include "libelf/readelf.h" + +#include "cg/cgbtypes.h" +#include "cg/cgnv2rt.h" +#include "cg/cgnv2elfversion.h" + +#include "cg/cgbio.hpp" +#include "cg/cgbiimpl.hpp" +#include "cg/cgboimpl.hpp" +#include "cg/nvbiimpl.hpp" +#include "cg/nvboimpl.hpp" +#include "cg/cgbutils.hpp" +#include "cg/cgbtypes.h" + +typedef struct +{ + const char* elfFile; + size_t elfFileSize; + + const char *symtab; + size_t symbolSize; + size_t symbolCount; + const char *symbolstrtab; + + const char* shadertab; + size_t shadertabSize; + const char* strtab; + size_t strtabSize; + const char* consttab; + size_t consttabSize; +} CGELFBinary; + +typedef struct +{ + const char *texttab; + size_t texttabSize; + const char *paramtab; + size_t paramtabSize; + int index; +} CGELFProgram; + +extern CGbool rglpSupportsVertexProgram( CGprofile p ); +extern CGbool rglpSupportsFragmentProgram( CGprofile p ); +extern CGprofile rglpGetLatestProfile( CGGLenum profile_type ); +extern int rglpCopyProgram( _CGprogram* source, _CGprogram* destination ); +extern int rglpGenerateFragmentProgram( _CGprogram *program, + const CgProgramHeader *programHeader, const void *ucode, + const CgParameterTableHeader *parameterHeader, + const char *stringTable, const float *defaultValues ); + +extern int rglpGenerateVertexProgram( _CGprogram *program, + const CgProgramHeader *programHeader, const void *ucode, + const CgParameterTableHeader *parameterHeader, const char *stringTable, + const float *defaultValues ); + +extern CGprogram rglpCgUpdateProgramAtIndex( CGprogramGroup group, int index, + int refcount ); + +extern void rglpProgramErase( _CGprogram* prog ); + +extern bool cgOpenElf( const void *ptr, size_t size, CGELFBinary *elfBinary ); +extern bool cgGetElfProgramByIndex( CGELFBinary *elfBinary, int index, CGELFProgram *elfProgram ); + +extern CGprogram rglCgCreateProgram( CGcontext ctx, CGprofile profile, const CgProgramHeader *programHeader, const void *ucode, const CgParameterTableHeader *parameterHeader, const char *stringTable, const float *defaultValues ); + +#endif diff --git a/console/rgl/src/rglp.h b/console/rgl/src/rglp.h new file mode 100644 index 0000000000..15742e41cf --- /dev/null +++ b/console/rgl/src/rglp.h @@ -0,0 +1,34 @@ +/* RetroArch - A frontend for libretro. + * RGL - An OpenGL subset wrapper library. + * Copyright (C) 2012 - Hans-Kristian Arntzen + * Copyright (C) 2012 - Daniel De Matteis + * + * RetroArch 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 Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch 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 RetroArch. + * If not, see . + */ + +#ifndef _RGLP_H_ +#define _RGLP_H_ + +#if defined(__CELLOS_LV2__) +#include "ps3/include/rgl-constants.h" +#endif + +extern void rglpValidateViewport(void); +extern void rglpValidateBlending(void); +extern void rglpValidateShaderSRGBRemap(void); + +extern int rglpBufferObjectSize(void); +extern GLboolean rglpCreateBufferObject(rglBufferObject* bufferObject); + +void rglpFifoGlFinish( void ); + +#endif