From 77bfce7cc73d0d25e2e32114586ace8c829f3228 Mon Sep 17 00:00:00 2001 From: Twinaphex Date: Sun, 6 May 2012 03:46:55 +0200 Subject: [PATCH] (PS3) Add RGL video driver - compile with Makefile.ps3.rgl before compiling RetroArch itself --- Makefile.ps3 | 10 +- Makefile.ps3.rgl | 70 + console/rgl/ps3/base.hpp | 87 + console/rgl/ps3/cg.h | 501 ++ console/rgl/ps3/cgbio.cpp | 368 ++ console/rgl/ps3/cgbio.hpp | 560 ++ console/rgl/ps3/cgnv2rt.cpp | 1068 ++++ console/rgl/ps3/cgnv2rt.h | 79 + console/rgl/ps3/device_ctx.cpp | 1332 +++++ console/rgl/ps3/elf.h | 161 + console/rgl/ps3/gl.h | 326 ++ console/rgl/ps3/glext.h | 274 + console/rgl/ps3/private.h | 429 ++ console/rgl/ps3/readelf.h | 72 + console/rgl/ps3/rgl.cpp | 8808 ++++++++++++++++++++++++++++++++ console/rgl/ps3/rgl.h | 1179 +++++ console/rgl/ps3/vector | 1739 +++++++ ps3/ps3_video_psgl.c | 9 - 18 files changed, 17058 insertions(+), 14 deletions(-) create mode 100644 Makefile.ps3.rgl create mode 100644 console/rgl/ps3/base.hpp create mode 100644 console/rgl/ps3/cg.h create mode 100644 console/rgl/ps3/cgbio.cpp create mode 100644 console/rgl/ps3/cgbio.hpp create mode 100644 console/rgl/ps3/cgnv2rt.cpp create mode 100644 console/rgl/ps3/cgnv2rt.h create mode 100644 console/rgl/ps3/device_ctx.cpp create mode 100644 console/rgl/ps3/elf.h create mode 100644 console/rgl/ps3/gl.h create mode 100644 console/rgl/ps3/glext.h create mode 100644 console/rgl/ps3/private.h create mode 100644 console/rgl/ps3/readelf.h create mode 100644 console/rgl/ps3/rgl.cpp create mode 100644 console/rgl/ps3/rgl.h create mode 100644 console/rgl/ps3/vector diff --git a/Makefile.ps3 b/Makefile.ps3 index 9fe66edac2..a154ed892e 100644 --- a/Makefile.ps3 +++ b/Makefile.ps3 @@ -9,7 +9,7 @@ CELL_PSGL_VERSION = ultra-opt DEBUG = 0 DOWNLOAD_SHADERS = 1 STRIPPING_ENABLE = 0 -HAVE_RARCH_GL = 0 +HAVE_RGL = 1 HAVE_LOGGER = 0 CONTENT_ID_FULL = UP0001-SSNE10000_00-0000000000000001 @@ -48,9 +48,9 @@ endif PPU_SRCS = console/griffin/griffin.c \ console/szlib/szlib.c -ifeq ($(HAVE_RARCH_GL), 1) -DEFINES = -DHAVE_RARCH_GL -GL_LIBS := -lRARCHGL -lRARCHGLcgc +ifeq ($(HAVE_RGL), 1) +DEFINES = -DHAVE_RGL +GL_LIBS := -lrgl else GL_LIBS := -L$(CELL_SDK)/target/ppu/lib/PSGL/RSX/ultra-opt -lPSGL -lPSGLcgc endif @@ -68,7 +68,7 @@ endif PPU_LDLIBS = -ldbgfont $(GL_LIBS) -lretro -lcgc -lgcm_cmd -lgcm_sys_stub -lresc_stub -lm -lio_stub -lfs_stub -lsysutil_stub -lsysutil_game_stub -lsysutil_screenshot_stub -lsysutil_np_stub -lpngdec_stub -ljpgdec_stub -lsysmodule_stub -laudio_stub -lnet_stub -lnetctl_stub -lpthread -DEFINES += -DRARCH_CONSOLE -DHAVE_OPENGL -DHAVE_CG -DHAVE_FBO -DHAVE_RARCH_MAIN_WRAP -DHAVE_RARCH_EXEC -DHAVE_LIBRETRO_MANAGEMENT -DHAVE_RSOUND -DHAVE_ZLIB -D__CELLOS_LV2__ -DHAVE_CONFIGFILE=1 -DHAVE_NETPLAY=1 -DHAVE_SOCKET_LEGACY=1 -DHAVE_GRIFFIN=1 -DPACKAGE_VERSION=\"$(RARCH_VERSION)\" -Dmain=rarch_main -DPC_DEVELOPMENT_IP_ADDRESS=\"$(PC_DEVELOPMENT_IP_ADDRESS)\" -DPC_DEVELOPMENT_UDP_PORT=$(PC_DEVELOPMENT_UDP_PORT) +DEFINES += -DRARCH_CONSOLE -DHAVE_OPENGL -DHAVE_CG -DHAVE_FBO -DHAVE_RARCH_MAIN_WRAP -DHAVE_RARCH_EXEC -DHAVE_RGL -DHAVE_LIBRETRO_MANAGEMENT -DHAVE_RSOUND -DHAVE_ZLIB -D__CELLOS_LV2__ -DHAVE_CONFIGFILE=1 -DHAVE_NETPLAY=1 -DHAVE_SOCKET_LEGACY=1 -DHAVE_GRIFFIN=1 -DPACKAGE_VERSION=\"$(RARCH_VERSION)\" -Dmain=rarch_main -DPC_DEVELOPMENT_IP_ADDRESS=\"$(PC_DEVELOPMENT_IP_ADDRESS)\" -DPC_DEVELOPMENT_UDP_PORT=$(PC_DEVELOPMENT_UDP_PORT) ifeq ($(DEBUG), 1) PPU_OPTIMIZE_LV := -O0 -g diff --git a/Makefile.ps3.rgl b/Makefile.ps3.rgl new file mode 100644 index 0000000000..5f380ea603 --- /dev/null +++ b/Makefile.ps3.rgl @@ -0,0 +1,70 @@ +#which compiler to build with - GCC or SNC +#set to GCC for debug builds for use with debugger +CELL_BUILD_TOOLS = SNC +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.a + +LDDIRS = -L. +INCDIRS = -I. + +PKG_SCRIPT = ps3/ps3py/pkg.py +ifeq ($(shell uname), Linux) +PKG_FINALIZE = package_finalize +MAKE_SELF_WC = make_self_wc +MAKE_SELF = make_self_npdrm +PYTHON2 = python2 +GIT = git +else +PKG_FINALIZE = package_finalize.exe +MAKE_SELF_WC = make_self_wc.exe +MAKE_SELF = make_self_npdrm.exe +PYTHON2 = python2.exe +GIT = git.exe +endif + +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 + 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_LDLIBS = -lio_stub + +DEFINES += -D__CELLOS_LV2__ + +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 + +MAKE_FSELF = $(CELL_SDK)/host-win32/bin/make_fself.exe +MAKE_FSELF_NPDRM = $(CELL_SDK)/host-win32/bin/make_fself_npdrm.exe +MAKE_PACKAGE_NPDRM = $(CELL_SDK)/host-win32/bin/make_package_npdrm.exe diff --git a/console/rgl/ps3/base.hpp b/console/rgl/ps3/base.hpp new file mode 100644 index 0000000000..2a103556d5 --- /dev/null +++ b/console/rgl/ps3/base.hpp @@ -0,0 +1,87 @@ +#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 new file mode 100644 index 0000000000..a3586289e8 --- /dev/null +++ b/console/rgl/ps3/cg.h @@ -0,0 +1,501 @@ +#ifndef _cg_common_h +#define _cg_common_h + +#include +#include + +#include + +#include "rgl.h" +#include "private.h" + +#ifndef STL_NAMESPACE +#define STL_NAMESPACE std:: +#endif + +#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; + +#ifdef MSVC +#pragma warning( push ) +#pragma warning ( disable : 4200 ) +#endif + +typedef struct _CgParameterArray +{ + unsigned short arrayType; + unsigned short dimensionCount; + unsigned short dimensions[]; +} CgParameterArray; + +#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 +{ + 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* _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 +{ + _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) + +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; +} + +static inline 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 ); + +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 CgRuntimeParameter* _RGLCgGLTestParameter( CGparameter param ) +{ + return _cgGetParamPtr( param ); +} + +CgRuntimeParameter* _cgGLTestArrayParameter( CGparameter paramIn, long offset, long nelements ); +CgRuntimeParameter* _cgGLTestTextureParameter( CGparameter param ); + +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: + printf("RGL 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 ); + +int _RGLPlatformGenerateVertexProgram( _CGprogram *program, const CgProgramHeader *programHeader, const void *ucode, const CgParameterTableHeader *parameterHeader, const char *stringTable, const float *defaultValues ); + +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 ); + +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 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 +} +#endif + +#endif diff --git a/console/rgl/ps3/cgbio.cpp b/console/rgl/ps3/cgbio.cpp new file mode 100644 index 0000000000..cee05b6abf --- /dev/null +++ b/console/rgl/ps3/cgbio.cpp @@ -0,0 +1,368 @@ +#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, + STL_NAMESPACE vector& default_value, + STL_NAMESPACE 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 new file mode 100644 index 0000000000..07c6b349d1 --- /dev/null +++ b/console/rgl/ps3/cgbio.hpp @@ -0,0 +1,560 @@ +#ifndef CGC_CGBIO_CGBDEFS_HPP +#define CGC_CGBIO_CGBDEFS_HPP + +#include + +#ifndef STL_NAMESPACE +#define STL_NAMESPACE ::std:: +#endif + +#define CGF_OUTPUTFROMH0 0x01 +#define CGF_DEPTHREPLACE 0x02 +#define CGF_PIXELKILL 0x04 + +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 size_t ptrdiff_t; +typedef size_t ptrdiff_t; + +typedef struct _Elf32_cgParameter { + Elf32_Word cgp_name; + Elf32_Word cgp_semantic; + Elf32_Half cgp_default; + Elf32_Half cgp_reloc; + Elf32_Half cgp_resource; + Elf32_Half cgp_resource_index; + unsigned char cgp_type; + Elf32_Half 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]; + Elf32_Half e_type; + Elf32_Half e_machine; + Elf32_Word e_version; + Elf32_Addr e_entry; + Elf32_Off e_phoff; + Elf32_Off e_shoff; + Elf32_Word e_flags; + Elf32_Half e_ehsize; + Elf32_Half e_phentsize; + Elf32_Half e_phnum; + Elf32_Half e_shentsize; + Elf32_Half e_shnum; + Elf32_Half e_shstrndx; +}; + +struct Elf32_Shdr { + Elf32_Word sh_name; + Elf32_Word sh_type; + Elf32_Word sh_flags; + Elf32_Addr sh_addr; + Elf32_Off sh_offset; + Elf32_Word sh_size; + Elf32_Word sh_link; + Elf32_Word sh_info; + Elf32_Word sh_addralign; + Elf32_Word sh_entsize; +}; + +struct Elf32_Phdr { + Elf32_Word p_type; + Elf32_Off p_offset; + Elf32_Addr p_vaddr; + Elf32_Addr p_paddr; + Elf32_Word p_filesz; + Elf32_Word p_memsz; + Elf32_Word p_flags; + Elf32_Word p_align; +}; + +struct Elf32_Sym { + Elf32_Word st_name; + Elf32_Addr st_value; + Elf32_Word st_size; + unsigned char st_info; + unsigned char st_other; + Elf32_Half st_shndx; +}; + +struct Elf32_Note { + Elf32_Word n_namesz; /* Name size */ + Elf32_Word n_descsz; /* Content size */ + Elf32_Word n_type; /* Content type */ +}; + + +struct Elf32_Rel { + Elf32_Addr r_offset; + Elf32_Word r_info; +}; + +struct Elf32_Rela { + Elf32_Addr r_offset; + Elf32_Word r_info; + Elf32_Sword r_addend; +}; + +struct Elf32_Dyn { + Elf32_Sword d_tag; + union { + Elf32_Word d_val; + Elf32_Addr 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, + STL_NAMESPACE vector& default_value, + STL_NAMESPACE 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 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; +}; + +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_; + STL_NAMESPACE 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, + STL_NAMESPACE vector& default_value, + STL_NAMESPACE 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 new file mode 100644 index 0000000000..6abd11dfe6 --- /dev/null +++ b/console/rgl/ps3/cgnv2rt.cpp @@ -0,0 +1,1068 @@ +#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 +{ + STL_NAMESPACE vector _resources; + STL_NAMESPACE vector _defaultValuesIndices; + STL_NAMESPACE vector _elfDefaultsIndices; + STL_NAMESPACE vector _dimensions; + STL_NAMESPACE 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( STL_NAMESPACE vector &stringTable, const char* str); +static unsigned int stringTableAdd( STL_NAMESPACE vector &stringTable, const char* str ); +static unsigned int stringTableAddUnique( STL_NAMESPACE vector &stringTable, const char* str ); +template static size_t array_size(STL_NAMESPACE vector &array); +template static void array_push(char* ¶meterOffset, STL_NAMESPACE vector &array); +inline static Elf32_Word swap16(const Elf32_Word 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, + STL_NAMESPACE vector ¶meterEntries, + STL_NAMESPACE vector ¶meterResources, STL_NAMESPACE 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, + STL_NAMESPACE vector &stringTable, STL_NAMESPACE 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); + } + + Elf32_Word *tmp = (Elf32_Word *)nvbr->ucode(); + const char *ucode; + Elf32_Word *buffer = NULL; + if (doSwap) + { + int size = (int)nvbr->ucode_size()/sizeof(Elf32_Word); + buffer = new Elf32_Word[size]; + for (int i=0;iucode_size()/sizeof(Elf32_Word); + buffer = new Elf32_Word[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; + STL_NAMESPACE vector dv; + STL_NAMESPACE 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(); + + STL_NAMESPACE vector parameterEntries; + STL_NAMESPACE 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(STL_NAMESPACE 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, + STL_NAMESPACE vector ¶meterEntries,STL_NAMESPACE vector ¶meterResources, + STL_NAMESPACE 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(STL_NAMESPACE vector &array) +{ + return (unsigned int)array.size()*sizeof(array[0]); +} + +template static void array_push(char* ¶meterOffset, STL_NAMESPACE vector &array) +{ + size_t dataSize = array.size()*sizeof(array[0]); + memcpy(parameterOffset,&array[0],dataSize); + parameterOffset += dataSize; +} + +Elf32_Word inline static swap16(const Elf32_Word 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; + Elf32_Half 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/cgnv2rt.h b/console/rgl/ps3/cgnv2rt.h new file mode 100644 index 0000000000..7f015cfae1 --- /dev/null +++ b/console/rgl/ps3/cgnv2rt.h @@ -0,0 +1,79 @@ +#ifndef CGNV2RT_HEADER +#define CGNV2RT_HEADER + +#include +#include +#include + +#ifndef STL_NAMESPACE +#define STL_NAMESPACE ::std:: +#endif + +#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) + +static unsigned int stringTableAdd( STL_NAMESPACE 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 stringTableFind( STL_NAMESPACE 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 stringTableAddUnique( STL_NAMESPACE 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; +} + +int convertNvToElfFromFile(const char *sourceFile, int endianness, int constTableOffset, void **binaryShader, int *size, + STL_NAMESPACE vector &stringTable, STL_NAMESPACE vector &defaultValues); +int convertNvToElfFromMemory(const void *sourceData, size_t size, int endianness, int constTableOffset, void **binaryShader, int *binarySize, + STL_NAMESPACE vector &stringTable, STL_NAMESPACE vector &defaultValues); + +int convertNvToElfFreeBinaryShader(void *binaryShader); + +#endif diff --git a/console/rgl/ps3/device_ctx.cpp b/console/rgl/ps3/device_ctx.cpp new file mode 100644 index 0000000000..f2028956b4 --- /dev/null +++ b/console/rgl/ps3/device_ctx.cpp @@ -0,0 +1,1332 @@ +#include +#include "rgl.h" +#include "private.h" +#include +#include +#include +#include +#include +#include + +using namespace cell::Gcm; + +#define _RGL_MAX_TILED_REGIONS 15 + +#define _RGL_TILED_BUFFER_ALIGNMENT 0x10000 +#define _RGL_TILED_BUFFER_HEIGHT_ALIGNMENT 64 + +#define _RGL_FIFO_SIZE (65536) +#define _RGL_DMA_PUSH_BUFFER_PREFETCH_PADDING 0x1000 +#define RGL_UTIL_LABEL_INDEX 253 + +extern void _RGLFifoGlSetRenderTarget( RGLRenderTargetEx const * const args ); + +typedef struct +{ + int id; + GLuint offset; + GLuint size; + GLuint pitch; + GLuint bank; +} jsTiledRegion; + +typedef struct +{ + jsTiledRegion region[_RGL_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; + +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 ) +{ + printf( "%02x %02x %02x %02x : ", ( v >> 24 )&0xff, ( v >> 16 )&0xff, ( v >> 8 )&0xff, v&0xff ); + + 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" ); +} + +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; + + sys_timer_usleep( 10 ); + } +} + +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; + sys_timer_usleep( 10 ); + } + } + 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 ); + + cellGcmSetAlphaFuncInline( &_RGLState.fifo, CELL_GCM_ALWAYS, RGL_QUICK_FLOAT2UINT( ref * 255.0f )); + + cellGcmSetBlendColorInline( &_RGLState.fifo, hwColor, hwColor); + cellGcmSetBlendEquationInline( &_RGLState.fifo, CELL_GCM_FUNC_ADD, CELL_GCM_FUNC_ADD ); + cellGcmSetBlendFuncInline( &_RGLState.fifo, CELL_GCM_ONE, CELL_GCM_ZERO, CELL_GCM_ONE, CELL_GCM_ZERO ); + cellGcmSetClearColorInline( &_RGLState.fifo, hwColor); + cellGcmSetAlphaTestEnableInline( &_RGLState.fifo, CELL_GCM_FALSE); + cellGcmSetBlendEnableInline( &_RGLState.fifo, CELL_GCM_FALSE); + cellGcmSetAlphaTestEnableInline( &_RGLState.fifo, CELL_GCM_FALSE); + cellGcmSetBlendEnableMrtInline( &_RGLState.fifo, CELL_GCM_FALSE, CELL_GCM_FALSE, CELL_GCM_FALSE); + cellGcmSetLogicOpEnableInline( &_RGLState.fifo, CELL_GCM_FALSE); + cellGcmSetCullFaceEnableInline( &_RGLState.fifo, CELL_GCM_FALSE); + cellGcmSetCullFaceEnableInline( &_RGLState.fifo, CELL_GCM_FALSE); + cellGcmSetDepthBoundsTestEnableInline( &_RGLState.fifo, CELL_GCM_FALSE); + cellGcmSetDepthTestEnableInline( &_RGLState.fifo, CELL_GCM_FALSE); + cellGcmSetPolygonOffsetFillEnableInline( &_RGLState.fifo, CELL_GCM_FALSE); + cellGcmSetPolygonOffsetLineEnableInline( &_RGLState.fifo, CELL_GCM_FALSE); + cellGcmSetRestartIndexEnableInline( &_RGLState.fifo, CELL_GCM_FALSE); + cellGcmSetFragmentProgramGammaEnableInline( &_RGLState.fifo, CELL_GCM_FALSE); + cellGcmSetScissorInline( &_RGLState.fifo, 0, 0, 4095, 4095); + cellGcmSetStencilTestEnableInline( &_RGLState.fifo, CELL_GCM_FALSE); + cellGcmSetTwoSidedStencilTestEnableInline( &_RGLState.fifo, CELL_GCM_FALSE); + cellGcmSetTwoSideLightEnableInline( &_RGLState.fifo, CELL_GCM_FALSE); + cellGcmSetVertexAttribOutputMaskInline( &_RGLState.fifo, s->vertexProgramAttribMask & s->fragmentProgramAttribMask); + + cellGcmSetPointSpriteControlInline( &_RGLState.fifo, CELL_GCM_FALSE, 1, 0); + cellGcmSetFrequencyDividerOperationInline( &_RGLState.fifo, 0); + + cellGcmSetDitherEnableInline( &_RGLState.fifo, CELL_GCM_TRUE); + cellGcmSetRestartIndexInline( &_RGLState.fifo, 0); + cellGcmSetShadeModeInline( &_RGLState.fifo, CELL_GCM_SMOOTH); + + for ( i = 0; i < CELL_GCM_MAX_TEXIMAGE_COUNT; i++ ) + { + cellGcmSetTextureAddressInline( &_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 ); + cellGcmSetTextureFilterInline( &_RGLState.fifo, i, 0, CELL_GCM_TEXTURE_NEAREST_LINEAR, CELL_GCM_TEXTURE_LINEAR, CELL_GCM_TEXTURE_CONVOLUTION_QUINCUNX ); + cellGcmSetTextureControlInline( &_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 ) ) + { + fprintf( stderr, "PSGL GCM failed initialisation" ); + return GL_FALSE; + } + + if ( gmmInit( resource->localAddress, + resource->localAddress, + resource->localSize, + resource->hostMemoryBase, + resource->hostMemoryBase + resource->hostMemoryReserved, + resource->hostMemorySize - resource->hostMemoryReserved ) == GMM_ERROR ) + { + fprintf( stderr, "Could not init GPU memory manager" ); + _RGLDestroy(); + return GL_FALSE; + } + + _RGLState.semaphores->userSemaphores[_RGL_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 ) + { + printf("RGL 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))) + { + sys_timer_usleep(30); + get = fifo->dmaControl->Get; + } + + for ( GLuint i = 0; i < nopsAtBegin; i++ ) + { + fifo->current[0] = RGL_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; + + printf("RGL: Current PSGL FIFO info \n" ); + printf("RGL: Fifo Begin %p End %p Current %p and Get %p \n", + _RGLState.fifo.begin, _RGLState.fifo.end, _RGLState.fifo.current, + _RGLState.fifo.lastGetRead ); + + printf("RGL: Last 10 words of the PSGL Fifo from the ppu put/current position \n" ); + _RGLPrintFifoFromPut( 10 ); + + printf("RGL: 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 ) ); + + const unsigned int iDPM2DataAreaSize = 0; + + dmaPushBufferSize = _RGLPad( dmaPushBufferSize, _RGL_HOST_BUFFER_ALIGNMENT ); + + gcmResource->hostMemorySize = _RGLPad( _RGL_FIFO_SIZE + hostMemorySize + dmaPushBufferSize + _RGL_DMA_PUSH_BUFFER_PREFETCH_PADDING + iDPM2DataAreaSize + (RGL_LM_MAX_TOTAL_QUERIES * sizeof( GLuint )), 1 << 20 ); + + if ( gcmResource->hostMemorySize > 0 ) + gcmResource->hostMemoryBase = ( char * )memalign( 1 << 20, gcmResource->hostMemorySize ); + + if ( cellGcmInit( _RGL_FIFO_SIZE, gcmResource->hostMemorySize, gcmResource->hostMemoryBase ) != 0 ) + { + printf("RGL: 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 = _RGL_FIFO_SIZE; + + cellGcmSetJumpCommand(( char * )gcmResource->dmaPushBuffer - ( char * )gcmResource->hostMemoryBase ); + + gCellGcmCurrentContext->callback = ( CellGcmContextCallback )_RGLOutOfSpaceCallback; + + + printf( "RGL: MClk: %f Mhz NVClk: %f Mhz\n", ( float )gcmResource->MemoryClock / 1E6, ( float )gcmResource->GraphicsClock / 1E6 ); + printf( "RGL: Video Memory: %i MB\n", gcmResource->localSize / ( 1024*1024 ) ); + printf( "RGL: localAddress mapped at %p\n", gcmResource->localAddress ); + printf( "RGL: push buffer at %p - %p (size = 0x%X), offset=0x%lx\n", + gcmResource->dmaPushBuffer, ( char* )gcmResource->dmaPushBuffer + gcmResource->dmaPushBufferSize, gcmResource->dmaPushBufferSize, gcmResource->dmaPushBufferOffset ); + printf( "RGL: dma control at %p\n", gcmResource->dmaControl ); + + 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 ) ) + { + printf("RGL: RM resource failed initialisation\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 = _RGL_TILED_BUFFER_ALIGNMENT; + while (( padSize % ( tiledPitch*8 ) ) != 0 ) + padSize += _RGL_TILED_BUFFER_ALIGNMENT; + + height = _RGLPad( height, _RGL_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 < _RGL_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 + printf("RGL: 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 ) +{ + printf("RGL WARN: RESC is enabled.\n"); + 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; + printf("RGL: 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 ); + + result = _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; + GLboolean result = 0; + + int32_t retVal; + + memset( mm->region, 0, sizeof( mm->region ) ); + for ( int i = 0;i < _RGL_MAX_TILED_REGIONS;++i ) + retVal = 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 = _RGL_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 = _RGL_SURFACE_POOL_LINEAR; + + GLuint size; + result = _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 ) + { + printf("RGL: 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 ); + cellGcmSetInvalidateVertexCacheInline( &_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 ) + { + printf("RGL: 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; +} + + GLfloat psglGetDeviceAspectRatio( const PSGLdevice * 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; +} + + void psglGetDeviceDimensions( const PSGLdevice * device, GLuint *width, GLuint *height ) +{ + *width = device->deviceParameters.width; + *height = device->deviceParameters.height; +} + + void psglGetRenderBufferDimensions( const PSGLdevice * device, GLuint *width, GLuint *height ) +{ + *width = device->deviceParameters.renderWidth; + *height = device->deviceParameters.renderHeight; +} + + 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; + + cellGcmSetInvalidateVertexCacheInline( &_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 != _RGL_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 ) ); + + cellGcmSetInvalidateVertexCacheInline( &_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() +{ + return _CurrentDevice; +} + +extern void gmmUpdateFreeList (const uint8_t location); + +GLAPI void psglSwap( void ) +{ + PSGLcontext *LContext = _CurrentContext; + PSGLdevice *device = _CurrentDevice; + RGLFifo *fifo = &_RGLState.fifo; + + gmmUpdateFreeList(CELL_GCM_LOCATION_LOCAL); + gmmUpdateFreeList(CELL_GCM_LOCATION_MAIN); + + 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 ) + { + printf("RGL 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(); + } + + cellGcmSetPolySmoothEnableInline( &_RGLState.fifo, CELL_GCM_FALSE); + cellGcmSetLineStippleEnableInline( &_RGLState.fifo, CELL_GCM_FALSE ); + cellGcmSetPolygonStippleEnableInline( &_RGLState.fifo, CELL_GCM_FALSE); + cellGcmSetDepthBoundsTestEnable( &_RGLState.fifo, CELL_GCM_FALSE); + cellGcmSetDitherEnableInline( &_RGLState.fifo, CELL_GCM_FALSE); + + LContext->needValidate = PSGL_VALIDATE_ALL; + + for ( int unit = 0;unit < _RGL_MAX_TEXTURE_UNITS;unit++ ) + LContext->TextureCoordsUnits[unit].TextureMatrixStack.dirty = GL_TRUE; + + LContext->ModelViewMatrixStack.dirty = GL_TRUE; + LContext->ProjectionMatrixStack.dirty = GL_TRUE; + LContext->attribs->DirtyMask = ( 1 << _RGL_MAX_VERTEX_ATTRIBS ) - 1; + + cellGcmSetInvalidateVertexCacheInline( &_RGLState.fifo); + + _RGLFifoFlush( fifo ); + + while(sys_semaphore_wait(FlipSem, 1000) != CELL_OK); + + cellGcmSetInvalidateVertexCacheInline( &_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, RGL_UTIL_LABEL_INDEX, _RGLState.labelValue); + cellGcmSetWaitLabelInline( &_RGLState.fifo, RGL_UTIL_LABEL_INDEX, _RGLState.labelValue); + + _RGLState.labelValue++; + + cellGcmSetWriteBackEndLabelInline( &_RGLState.fifo, RGL_UTIL_LABEL_INDEX, _RGLState.labelValue); + cellGcmFlush(); + + while( *(cellGcmGetLabelAddress( RGL_UTIL_LABEL_INDEX)) != _RGLState.labelValue) + sys_timer_usleep(30); + + _RGLState.labelValue++; +} + +GLboolean _RGLTryResizeTileRegion( GLuint address, GLuint size, void* data ) +{ + jsTiledRegion* region = ( jsTiledRegion* )data; + int32_t retVal = 0; + + if ( size == 0 ) + { + region->offset = 0; + region->size = 0; + region->pitch = 0; + + if ( ! _RGLDuringDestroyDevice ) + { + _RGLUtilWaitForIdle(); + retVal = cellGcmUnbindTile( region->id ); + _RGLFifoFinish( &_RGLState.fifo ); + } + return GL_TRUE; + } + region->offset = address; + region->size = size; + + _RGLUtilWaitForIdle(); + + retVal = cellGcmSetTileInfo(region->id, CELL_GCM_LOCATION_LOCAL, + region->offset, region->size, region->pitch, CELL_GCM_COMPMODE_DISABLED, 0, + region->bank ); + + retVal = cellGcmBindTile( region->id ); + + _RGLFifoFinish( &_RGLState.fifo ); + + return GL_TRUE; +} + +void _RGLGetTileRegionInfo( void* data, GLuint *address, GLuint *size ) +{ + jsTiledRegion* region = ( jsTiledRegion* )data; + + *address = region->offset; + *size = region->size; +} diff --git a/console/rgl/ps3/elf.h b/console/rgl/ps3/elf.h new file mode 100644 index 0000000000..fc3ff6e1ff --- /dev/null +++ b/console/rgl/ps3/elf.h @@ -0,0 +1,161 @@ +#ifndef ELF_H +#define ELF_H 1 + +#define RGL_ALIGN_FAST_TRANSFER 128 + +typedef unsigned int Elf32_Addr; +typedef unsigned int Elf32_Off; +typedef unsigned short Elf32_Half; +typedef unsigned int Elf32_Word; +typedef int Elf32_Sword; + +#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]; + Elf32_Half e_type; + Elf32_Half e_machine; + Elf32_Word e_version; + Elf32_Addr e_entry; + Elf32_Off e_phoff; + Elf32_Off e_shoff; + Elf32_Word e_flags; + Elf32_Half e_ehsize; + Elf32_Half e_phentsize; + Elf32_Half e_phnum; + Elf32_Half e_shentsize; + Elf32_Half e_shnum; + Elf32_Half 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 { + Elf32_Word p_type; + Elf32_Off p_offset; + Elf32_Addr p_vaddr; + Elf32_Addr p_paddr; + Elf32_Word p_filesz; + Elf32_Word p_memsz; + Elf32_Word p_flags; + Elf32_Word 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 { + Elf32_Word sh_name; + Elf32_Word sh_type; + Elf32_Word sh_flags; + Elf32_Addr sh_addr; + Elf32_Off sh_offset; + Elf32_Word sh_size; + Elf32_Word sh_link; + Elf32_Word sh_info; + Elf32_Word sh_addralign; + Elf32_Word 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 { + Elf32_Word st_name; + Elf32_Word st_value; + Elf32_Word st_size; + unsigned char st_info; + unsigned char st_other; + Elf32_Half st_shndx; +} Elf32_Sym; + + +typedef struct +{ + Elf32_Addr r_offset; + Elf32_Word r_info; +} Elf32_Rel; + +typedef struct +{ + Elf32_Addr r_offset; + Elf32_Word r_info; + Elf32_Sword r_addend; +} Elf32_Rela; + +#endif /* ELF_H */ diff --git a/console/rgl/ps3/gl.h b/console/rgl/ps3/gl.h new file mode 100644 index 0000000000..17f4eb9abc --- /dev/null +++ b/console/rgl/ps3/gl.h @@ -0,0 +1,326 @@ +#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 glLoadIdentity( void ); + GLAPI void APIENTRY glMatrixMode( GLenum mode ); + GLAPI void APIENTRY glOrthof( GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar ); + 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 new file mode 100644 index 0000000000..e2d87c6418 --- /dev/null +++ b/console/rgl/ps3/glext.h @@ -0,0 +1,274 @@ +#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 new file mode 100644 index 0000000000..e368a9ec14 --- /dev/null +++ b/console/rgl/ps3/private.h @@ -0,0 +1,429 @@ +#ifndef _RGL_PRIVATE_H +#define _RGL_PRIVATE_H + +#include "rgl.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 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 RGL_NOP (0x00000000) +#define DEFAULT_FIFO_BLOCK_SIZE (0x10000) + +#define RGL_ATTRIB_COUNT 16 + +#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 { + _RGL_SURFACE_SOURCE_TEMPORARY, + _RGL_SURFACE_SOURCE_DEVICE, + _RGL_SURFACE_SOURCE_TEXTURE, + _RGL_SURFACE_SOURCE_PBO, +}; + +enum { + _RGL_SURFACE_POOL_NONE, + _RGL_SURFACE_POOL_LINEAR, + _RGL_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 RGL_PAGE_SIZE 0x1000 +#define RGL_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; + 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 _RGLMapMagTextureFilter( 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 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; + default: + break; + }; + + return; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/console/rgl/ps3/readelf.h b/console/rgl/ps3/readelf.h new file mode 100644 index 0000000000..c33dd3373b --- /dev/null +++ b/console/rgl/ps3/readelf.h @@ -0,0 +1,72 @@ +#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); +const Elf32_Sym* getSymbolByIndex(const ELF_t* elf,int idx); + +const char *findSectionInPlace(const char* memory,unsigned int size,const char *name,size_t *sectionSize); +const char *findSymbolSectionInPlace(const char *memory, unsigned int size, 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); + +#ifdef __cplusplus +} +#endif + +#endif // READELF_H diff --git a/console/rgl/ps3/rgl.cpp b/console/rgl/ps3/rgl.cpp new file mode 100644 index 0000000000..e44182a7d0 --- /dev/null +++ b/console/rgl/ps3/rgl.cpp @@ -0,0 +1,8808 @@ +#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 + +#define RGL_ALIGN_FAST_TRANSFER 128 + +#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 gmmAddressToOffset(address, isMain) ((isMain) ? (address)-pGmmMainAllocator->memoryBase : (address)-pGmmLocalAllocator->memoryBase) + +#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) + +#define jsMATRIX_SIZEf (sizeof(GLfloat)*ELEMENTS_IN_MATRIX) + +enum +{ + M10 = 1, M20, M30, + M01, M11, M21, M31, + M02, M12, M22, M32, + M03, M13, M23, M33 +}; + +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; +static const unsigned int capacityIncr = 16; +static const int NAME_INCREMENT = 4; + +#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 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,unsigned int /*size*/,const char *name, size_t *sectionSize) +{ + const Elf32_Ehdr *ehdr = (const Elf32_Ehdr*)memory; + + const char *shstrtab = _getStringTable(ehdr); + + 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, 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; +} + + +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; +} + +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 inline void _RGLFifoGlVertexAttribPointer +( + GLuint index, + GLint size, + RGLEnum type, + GLboolean normalized, + GLsizei stride, + GLushort frequency, + GLboolean isMain, + GLuint offset +) +{ + switch ( size ) + { + case 0: + stride = 0; + normalized = 0; + type = RGL_FLOAT; + offset = 0; + break; + case 1: + case 2: + case 3: + case 4: + break; + default: + break; + } + + uint8_t gcmType = 0; + switch ( type ) + { + case RGL_UNSIGNED_BYTE: + if (normalized) + gcmType = CELL_GCM_VERTEX_UB; + else + gcmType = CELL_GCM_VERTEX_UB256; + break; + + case RGL_SHORT: + gcmType = 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: + size = 1; + gcmType = CELL_GCM_VERTEX_CMP; + break; + + default: + break; + } + + uint8_t location = CELL_GCM_LOCATION_LOCAL; + + if ( isMain ) + location = CELL_GCM_LOCATION_MAIN; + + cellGcmSetVertexDataArrayInline( &_RGLState.fifo, index, frequency, stride, size, gcmType, location, offset ); +} + +static void _RGLResetAttributeState( jsAttributeState* 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->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 inline jsBufferObject *_RGLGetBufferObject( PSGLcontext *LContext, GLuint name ) +{ + return ( jsBufferObject * )LContext->bufferObjectNameSpace.data[name]; +} + +static void _RGLAttribSetDeleteBuffer( PSGLcontext *LContext, GLuint buffName ) +{ + jsBufferObject *bufferObject = _RGLGetBufferObject( LContext, 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 < _RGL_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 inline jsAttribSet* _RGLGetAttribSet( GLuint name ) +{ + PSGLcontext* LContext = _CurrentContext; + return ( jsAttribSet* ) LContext->attribSetNameSpace.data[name]; +} + +static void _RGLAttribSetMarkDirty (void) +{ + PSGLcontext* LContext = _CurrentContext; + jsAttribSet* attribSet = _RGLGetAttribSet( LContext->attribSetName ); + attribSet->dirty = GL_TRUE; + LContext->attribSetDirty = GL_TRUE; +} + +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 _RGL_SURFACE_POOL_SYSTEM: + case _RGL_SURFACE_POOL_LINEAR: + gmmFree( jsBuffer->bufferId ); + break; + case _RGL_SURFACE_POOL_NONE: + break; + default: + break; + } + + jsBuffer->pool = _RGL_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 ); + } +} + +static void _RGLUnbindBufferObject( PSGLcontext *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 ); + } + } + _RGLAttribSetDeleteBuffer( LContext, name ); +} + +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] ) + _RGLUnbindBufferObject( LContext, buffers[i] ); + } + _RGLTexNameSpaceDeleteNames( &LContext->bufferObjectNameSpace, n, buffers ); +} + +GLAPI void APIENTRY glGenBuffers( GLsizei n, GLuint *buffers ) +{ + PSGLcontext *LContext = _CurrentContext; + _RGLTexNameSpaceGenNames( &LContext->bufferObjectNameSpace, n, buffers ); +} + +static inline jsFramebuffer *_RGLGetFramebuffer( PSGLcontext *LContext, GLuint name ) +{ + return ( jsFramebuffer * )LContext->framebufferNameSpace.data[name]; +} + +static inline void _RGLTextureTouchFBOs( jsTexture *texture ) +{ + PSGLcontext *LContext = _CurrentContext; + if ( !LContext ) return; + GLuint fbCount = texture->framebuffers.getCount(); + if ( fbCount > 0 ) + { + jsFramebuffer *contextFramebuffer = LContext->framebuffer ? _RGLGetFramebuffer( LContext, 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 = _RGL_SURFACE_POOL_LINEAR; + jsBuffer->bufferId = gmmAlloc(0, jsBuffer->bufferSize); + jsBuffer->pitch = 0; + + if ( jsBuffer->bufferId == GMM_ERROR ) + jsBuffer->pool = _RGL_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 |= _RGL_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 ); + + _RGLTransferDataVidToVid( + dstId, + 0, + pitch, + dstOffsetAlign / 2, dstOffset / pitch, + srcId, + srcOffset, + pitch, + 0, 0, + firstBytes / 2, 1, + 2 ); + dstOffset += firstBytes; + srcOffset += firstBytes; + size -= firstBytes; + } + + const GLuint fullLines = size / pitch; + const GLuint extraBytes = size % pitch; + if ( fullLines ) + _RGLTransferDataVidToVid( + dstId, + 0, + pitch, + 0, dstOffset / pitch, + srcId, + srcOffset, + pitch, + 0, 0, + pitch / 2, fullLines, + 2 ); + if ( extraBytes ) + _RGLTransferDataVidToVid( + dstId, + 0, + pitch, + 0, fullLines + dstOffset / pitch, + srcId, + srcOffset, + pitch, + 0, fullLines, + extraBytes / 2, 1, + 2 ); +} + +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 _RGL_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: + cellGcmSetInvalidateVertexCacheInline( &_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 = _RGL_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 = _RGLGetBufferObject( LContext, name ); + + if ( bufferObject->refCount > 1 ) + { + _RGLTexNameSpaceDeleteNames( &LContext->bufferObjectNameSpace, 1, &name ); + _RGLTexNameSpaceCreateNameLazy( &LContext->bufferObjectNameSpace, name ); + bufferObject = _RGLGetBufferObject( LContext, 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 _RGL_SURFACE_POOL_LINEAR: + _RGLMemcpy( dst->bufferId, 0, dst->pitch, src->bufferId, src->bufferSize ); + break; + case _RGL_SURFACE_POOL_SYSTEM: + cellGcmSetInvalidateVertexCacheInline( &_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 = _RGLGetBufferObject( LContext, name ); + + + if ( bufferObject->refCount > 1 ) + { + jsBufferObject* oldBufferObject = bufferObject; + + _RGLTexNameSpaceDeleteNames( &LContext->bufferObjectNameSpace, 1, &name ); + _RGLTexNameSpaceCreateNameLazy( &LContext->bufferObjectNameSpace, name ); + + bufferObject = _RGLGetBufferObject( LContext, 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 inline jsTexture* _RGLGetTexture( PSGLcontext *LContext, GLuint name ) +{ + return ( jsTexture* )LContext->textureNameSpace.data[name]; +} + +static inline jsTexture* _RGLGetTextureSafe( PSGLcontext *LContext, GLuint name ) +{ + return _RGLTexNameSpaceIsName( &LContext->textureNameSpace, name ) ? ( jsTexture* )LContext->textureNameSpace.data[name] : NULL; +} + +static void _RGLFramebufferGetAttachmentTexture( + const jsFramebufferAttachment* attachment, + jsTexture** texture, + GLuint* face ) +{ + PSGLcontext* LContext = _CurrentContext; + 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; + break; + default: + *face = 0; + *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; + int width = 0; + int height = 0; + + jsImage* image[_RGL_MAX_COLOR_ATTACHMENTS + 2] = {0}; + + GLuint colorFormat = 0; + for ( int i = 0; i < _RGL_MAX_COLOR_ATTACHMENTS; ++i ) + { + jsTexture* colorTexture = NULL; + GLuint colorFace = 0; + _RGLFramebufferGetAttachmentTexture(&framebuffer->color[i], &colorTexture, &colorFace ); + + if ( colorTexture != NULL ) + { + if ( !_RGLTextureIsValid( colorTexture ) ) + { + printf("RGL ERR: Framebuffer color attachment texture is not complete.\n"); + return GL_FRAMEBUFFER_UNSUPPORTED_OES; + } + + image[nBuffers] = colorTexture->image; + width = image[nBuffers]->width; + height = image[nBuffers]->height; + + if ( colorFormat && colorFormat != image[nBuffers]->internalFormat ) + { + printf("RGL ERR: Framebuffer attachments have inconsistent color formats.\n" ); + return GL_FRAMEBUFFER_INCOMPLETE_FORMATS_OES; + } + colorFormat = image[nBuffers]->internalFormat; + + ++nBuffers; + } + } + + if ( nBuffers && colorFormat != RGL_ARGB8) + { + printf("RGL: 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 { + _RGL_TEXTURE_STRATEGY_END, + _RGL_TEXTURE_STRATEGY_UNTILED_ALLOC, + _RGL_TEXTURE_STRATEGY_UNTILED_CLEAR, +}; + +static enum _RGLTextureStrategy linearGPUStrategy[] = + { + _RGL_TEXTURE_STRATEGY_UNTILED_ALLOC, + _RGL_TEXTURE_STRATEGY_UNTILED_CLEAR, + _RGL_TEXTURE_STRATEGY_UNTILED_ALLOC, + _RGL_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; + } + image->data = _RGLPadPtr( image->mallocData, 128 ); +} + +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 + + 0 * image->xstride; + + 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 == _RGL_IMAGE_DATASTATE_GPU ) + { + _RGLImageAllocCPUStorage( image ); + + cellGcmSetInvalidateVertexCacheInline( &_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 = _RGL_IMAGE_DATASTATE_HOST; + } +} + +static void _RGLPlatformFreeGcmTexture( jsTexture* texture ) +{ + RGLTexture *gcmTexture = ( RGLTexture * )texture->platformTexture; + switch ( gcmTexture->pool ) + { + case _RGL_SURFACE_POOL_LINEAR: + case _RGL_SURFACE_POOL_SYSTEM: + gmmFree( gcmTexture->gpuAddressId ); + case _RGL_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 = _RGL_SURFACE_POOL_NONE; + gcmTexture->gpuSize = 0; + } + + if ( gcmTexture->pool != _RGL_SURFACE_POOL_NONE ) + { + _RGLPlatformCopyGPUTexture( texture ); + _RGLPlatformFreeGcmTexture( texture ); + } + + gcmTexture->pool = _RGL_SURFACE_POOL_NONE; + gcmTexture->gpuAddressId = GMM_ERROR; + gcmTexture->gpuAddressIdOffset = 0; + gcmTexture->gpuSize = 0; + texture->revalidate |= _RGL_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 inline int _RGLGetStorageSize( GLenum format, GLenum type, GLsizei width, GLsizei height, GLsizei depth ) +{ + return _RGLGetPixelSize( format, type )*width*height*depth; +} + +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( _RGLGetStorageSize( texture->image->format, texture->image->type, texture->image->width, 1, 1 ), 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 < _RGL_MAX_VERTEX_TEXTURE_IMAGE_UNITS; ++j ) + { + if ( LContext->VertexTextureImages[j] == texture ) + { + bound = GL_TRUE; + break; + } + } + for ( j = 0;j < _RGL_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 != _RGL_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 _RGL_TEXTURE_STRATEGY_UNTILED_ALLOC: + _RGLPlatformChooseGPUFormatAndLayout( texture, GL_TRUE, 0, &newLayout ); + size = _RGLPad( newLayout.baseHeight * newLayout.pitch, 1); + + if ( gcmTexture->pool == _RGL_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 != _RGL_SURFACE_POOL_NONE ) + _RGLPlatformDropTexture( texture ); + + gcmTexture->pool = _RGL_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( _RGL_SURFACE_POOL_LINEAR ); + break; + case _RGL_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 &= ~_RGL_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 & _RGL_TEXTURE_REVALIDATE_IMAGES || texture->revalidate & _RGL_TEXTURE_REVALIDATE_LAYOUT ) + { + _RGLPlatformReallocateGcmTexture( texture ); + RGLTexture *gcmTexture = ( RGLTexture * )texture->platformTexture; + RGLTextureLayout *layout = &gcmTexture->gpuLayout; + + const GLuint pixelBytes = layout->pixelBits / 8; + + RGLSurface src = { +source: _RGL_SURFACE_SOURCE_TEMPORARY, + width: 0, + height: 0, + bpp: pixelBytes, + pitch: 0, + format: layout->internalFormat, + pool: _RGL_SURFACE_POOL_LINEAR, + ppuData: NULL, + dataId: GMM_ERROR, + dataIdOffset:0, + }; + + RGLSurface dst = { +source: _RGL_SURFACE_SOURCE_TEXTURE, + width: 0, + height: 0, + bpp: pixelBytes, + pitch: layout->pitch, + format: layout->internalFormat, + pool: _RGL_SURFACE_POOL_SYSTEM, + ppuData: NULL, + dataId: GMM_ERROR, + dataIdOffset:0, + }; + + GLuint bounceBufferId = GMM_ERROR; + jsImage *image = texture->image; + if ( image->dataState == _RGL_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; + + _RGLTransferDataVidToVid( dst.dataId, dst.dataIdOffset, dst.pitch ? dst.pitch : (dst.bpp * dst.width), 0, 0, src.dataId, src.dataIdOffset, src.pitch ? src.pitch : (src.bpp * src.width), 0, 0, src.width, src.height, src.bpp ); + + _RGLImageFreeCPUStorage( image ); + image->dataState |= _RGL_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; + GLuint face = 0; + _RGLFramebufferGetAttachmentTexture(&fb->color[i], &colorTexture, &face ); + if ( colorTexture == NULL ) continue; + + RGLTexture* nvTexture = ( RGLTexture * )colorTexture->platformTexture; + + if ( !colorTexture->isRenderTarget ) + { + colorTexture->isRenderTarget = GL_TRUE; + colorTexture->revalidate |= _RGL_TEXTURE_REVALIDATE_LAYOUT; + } + _RGLPlatformValidateTextureResources( colorTexture ); + colorTexture->image->dataState = _RGL_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( _RGLGetFramebuffer( LContext, 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 ) + { + cellGcmSetScissorInline( &_RGLState.fifo, 0, 0, 4095, 4095); + cellGcmSetDepthTestEnableInline( &_RGLState.fifo, CELL_GCM_FALSE); + cellGcmSetStencilTestEnableInline( &_RGLState.fifo, CELL_GCM_FALSE); + + static float _RGLClearVertexBuffer[12] __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, + }; + + _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 ) ); + _RGLFifoGlVertexAttribPointer( 0, 3, RGL_FLOAT, CELL_GCM_FALSE, 3*sizeof( GLfloat ), 1, 0, gmmIdToOffset(bufferId) ); + RGLBIT_TRUE( LContext->attribs->DirtyMask, 0 ); + + for ( int i = 1; i < _RGL_MAX_VERTEX_ATTRIBS;++i ) + { + _RGLFifoGlVertexAttribPointer( i, 0, RGL_FLOAT, 0, 0, 0, 0, 0 ); + 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 ); + } + + cellGcmSetInvalidateVertexCacheInline( &_RGLState.fifo); + _RGLFifoFlush( fifo ); +} + +GLAPI void APIENTRY glClearColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha ) +{ + PSGLcontext *LContext = _CurrentContext; + + LContext->ClearColor.R = _RGLClampf( red ); + LContext->ClearColor.G = _RGLClampf( green ); + LContext->ClearColor.B = _RGLClampf( blue ); + LContext->ClearColor.A = _RGLClampf( alpha ); +} + +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 = _RGLClampf( red ); + LContext->BlendColor.G = _RGLClampf( green ); + LContext->BlendColor.B = _RGLClampf( blue ); + LContext->BlendColor.A = _RGLClampf( alpha ); + + 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 = _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 ) +{ + PSGLcontext* LContext = _CurrentContext; + + jsFramebuffer* framebuffer = _RGLGetFramebuffer( LContext, LContext->framebuffer ); + + jsFramebufferAttachment* attach = _RGLFramebufferGetAttachment( framebuffer, GL_COLOR_ATTACHMENT0_EXT ); + + if ( !attach ) + return; + + jsTexture *textureObject = NULL; + GLuint face; + _RGLFramebufferGetAttachmentTexture(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 = 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; +} + +void _RGLInitNameSpace( jsNameSpace * name ) +{ + name->data = NULL; + name->firstFree = NULL; + name->capacity = 0; +} + +void _RGLFreeNameSpace( jsNameSpace * ns ) +{ + if ( ns->data ) + free( ns->data ); + + ns->data = NULL; + ns->capacity = 0; + ns->firstFree = NULL; +} + +jsName _RGLCreateName( jsNameSpace * ns, void* object ) +{ + if ( NULL == ns->firstFree ) + { + 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( 0 == name ) ) + return 0; + + --name; + + if ( RGL_UNLIKELY( name >= ns->capacity ) ) + return 0; + + void** value = ( void** )ns->data[name]; + + if ( RGL_UNLIKELY( NULL == value || + ( 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 = capacityIncr; + 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 + 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; +} + +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 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; +} + +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; + } +} + +void gmmUpdateFreeList (const uint8_t location) +{ + GmmAllocator *pAllocator; + const uint32_t fence = _RGLState.semaphores->userSemaphores[_RGL_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; + } + +} + +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; + + sys_timer_usleep(30); + }while(1); + + return (char *)pBaseBlock->address; +} + +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; + 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; + } + + 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) + { + resizeSucceed = _RGLTryResizeTileRegion( (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 = _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, _RGL_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 inline void gmmMemcpy(const uint32_t dstOffset, const uint32_t srcOffset, const uint32_t 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; 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, 0); + srcOffset = gmmAddressToOffset(srcAddress, 0); + + totalMoveSize += moveSize; + + gmmMemcpy(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, 0); + srcOffset = gmmAddressToOffset(pinSrcAddress, 0); + + totalMoveSize += pTempBlock->base.size; + + gmmMemcpy(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) + { + 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 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) + { + // 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; + gmmRemoveFree(pAllocator, pBlock, freeIndex); + 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 == RGL_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 == RGL_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; +} + +static void _RGLUnloadFPShader( _CGprogram *program ) +{ + if ( program->loadProgramId != GMM_ERROR ) + { + gmmFree( program->loadProgramId ); + program->loadProgramId = GMM_ERROR; + program->loadProgramOffset = 0; + } +} + +typedef struct RGLparamUIDRec +{ + char * string; + GLboolean global; +} RGLparamUID; + +typedef struct RGLparamUIDTableRec +{ + int count; + RGLparamUID* uids; +} RGLparamUIDTable; + + +RGLparamUID getParamUIDByIndex( const RGLparamUIDTable* st, int index ) +{ + return st->uids[index]; +} + +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 *pointer=NULL; + const int paddedSIZE = (SIZE + 1) & ~1; + cellGcmSetInlineTransferPointerInline( &_RGLState.fifo, 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; + + 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; +} + + +int _RGLPlatformGenerateFragmentProgram( _CGprogram *program, const CgProgramHeader *programHeader, const void *ucode, + const CgParameterTableHeader *parameterHeader, const char *stringTable, const float *defaultValues ) +{ + return _RGLGenerateProgram( program, FRAGMENT_PROFILE_INDEX, programHeader, ucode, parameterHeader, NULL, stringTable, defaultValues ); + +} + +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 ) + _RGLUnloadFPShader( program ); + + 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 == _RGL_SURFACE_POOL_NONE ) + { + _RGLSetError( GL_OUT_OF_MEMORY ); + return NULL; + } + } + else + { + cellGcmSetInvalidateVertexCacheInline( &_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 = _RGL_SURFACE_POOL_NONE; + gcmTexture->gpuAddressId = GMM_ERROR; + gcmTexture->gpuAddressIdOffset = 0; + gcmTexture->gpuSize = 0; + } + + _RGLPlatformFreeGcmTexture( texture ); + } + _RGLTextureTouchFBOs( texture ); +} + +// Get size of texture in GPU layout +static inline GLuint _RGLPlatformTextureGetGPUSize( const jsTexture* texture ) +{ + RGLTexture *gcmTexture = ( RGLTexture * )texture->platformTexture; + return _RGLPad( gcmTexture->gpuLayout.baseHeight * gcmTexture->gpuLayout.pitch, 1); +} + +#include + +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; + const GLuint imageOffset = gmmIdToOffset(platformTexture->gpuAddressId) + 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] = CELL_GCM_METHOD_DATA_TEXTURE_BORDER_COLOR(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 + { + //printf("RGL 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 = _RGLGetStorageSize( + image->format, image->type, + image->width, image->height, 1 ); + + return GL_NO_ERROR; +} + +static inline GLuint _RGLGetBufferObjectOrigin( GLuint buffer ) +{ + jsBufferObject *bufferObject = _RGLGetBufferObject( _CurrentContext, 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 = _RGL_IMAGE_DATASTATE_HOST; + } + else + image->dataState = _RGL_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 = _RGL_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( + _RGLGetStorageSize( format, type, width, 1, 1 ), + LContext->unpackAlignment ); + if (( pboPitch&3 ) != 0 ) + { + printf("RGL 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 ) + { + printf("RGL: 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 ) + { + printf("RGL: PBO format/type requires conversion to texture internal format, using slow path.\n"); + return GL_FALSE; + } + + if ( !_RGLTextureIsValid( texture ) ) + { + printf("RGL: PBO transfering to incomplete texture, using slow path.\n"); + return GL_FALSE; + } + + RGLTextureLayout newLayout; + _RGLPlatformChooseGPUFormatAndLayout( texture, GL_TRUE, pboPitch, &newLayout ); + + jsBufferObject* bufferObject = _RGLGetBufferObject( LContext, 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 = _RGL_SURFACE_POOL_LINEAR; + gcmTexture->gpuSize = _RGLPlatformTextureGetGPUSize( texture ); + ++bufferObject->refCount; + } + else + { + const GLuint bytesPerPixel = newLayout.pixelBits / 8; + RGLSurface src = + { +source: _RGL_SURFACE_SOURCE_PBO, + width: image->width, + height: image->height, + bpp: bytesPerPixel, + pitch: pboPitch, + format: newLayout.internalFormat, + pool: _RGL_SURFACE_POOL_LINEAR, + ppuData: NULL, + dataId: gpuId, + dataIdOffset: gpuIdOffset, + }; + + texture->revalidate |= _RGL_TEXTURE_REVALIDATE_LAYOUT; + _RGLPlatformValidateTextureResources( texture ); + + RGLSurface dst = + { +source: _RGL_SURFACE_SOURCE_TEXTURE, + width: image->width, + height: image->height, + bpp: bytesPerPixel, + pitch: gcmTexture->gpuLayout.pitch, + format: gcmTexture->gpuLayout.internalFormat, + pool: gcmTexture->pool, + ppuData: NULL, + dataId: gcmTexture->gpuAddressId, + dataIdOffset: gcmTexture->gpuAddressIdOffset, + }; + + _RGLTransferDataVidToVid( dst.dataId, dst.dataIdOffset, dst.pitch ? dst.pitch : (dst.bpp * dst.width), 0, 0, src.dataId, src.dataIdOffset, src.pitch ? src.pitch : (src.bpp * src.width), 0, 0, width, height, src.bpp ); + } + + _RGLImageFreeCPUStorage( image ); + image->dataState = _RGL_IMAGE_DATASTATE_GPU; + + texture->revalidate &= ~( _RGL_TEXTURE_REVALIDATE_LAYOUT | _RGL_TEXTURE_REVALIDATE_IMAGES ); + texture->revalidate |= _RGL_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 &= ~( _RGL_TEXTURE_REVALIDATE_LAYOUT | _RGL_TEXTURE_REVALIDATE_IMAGES ); + texture->revalidate |= _RGL_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 ); + } +} + +static inline void _RGLSetColorDepthFormats( RGLRenderTarget *rt, RGLRenderTargetEx const * const args ) +{ + CellGcmSurface * grt = &rt->gcmRenderTarget; + + grt->colorFormat = CELL_GCM_SURFACE_A8R8G8B8; + grt->depthFormat = CELL_GCM_SURFACE_Z24S8; + grt->depthLocation = CELL_GCM_LOCATION_LOCAL; + grt->depthOffset = 0; + grt->depthPitch = 64; +} + +static inline void _RGLSetTarget( RGLRenderTarget *rt, RGLRenderTargetEx const * const args ) +{ + CellGcmSurface * grt = &rt->gcmRenderTarget; + + 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; + } +} + +void _RGLFifoGlSetRenderTarget( RGLRenderTargetEx const * const args ) +{ + RGLRenderTarget *rt = &_RGLState.renderTarget; + CellGcmSurface * grt = &_RGLState.renderTarget.gcmRenderTarget; + + _RGLSetColorDepthBuffers( rt, args ); + _RGLSetColorDepthFormats( rt, args ); + + grt->antialias = CELL_GCM_SURFACE_CENTER_1; + + cellGcmSetAntiAliasingControlInline( &_RGLState.fifo, CELL_GCM_FALSE, CELL_GCM_FALSE, CELL_GCM_FALSE, 0xFFFF); + + grt->type = CELL_GCM_SURFACE_PITCH; + _RGLSetTarget( rt, args ); + + cellGcmSetSurfaceInline( &_RGLState.fifo, grt); + cellGcmSetDepthTestEnableInline( &_RGLState.fifo, CELL_GCM_FALSE); +} + +void _RGLSetError( GLenum error ) +{ +} + +GLAPI GLenum APIENTRY glGetError() +{ + if ( !_CurrentContext ) + return GL_INVALID_OPERATION; + else + { + GLenum error = _CurrentContext->error; + + _CurrentContext->error = GL_NO_ERROR; + return error; + } +} + +static uint32_t * _RGLFifoWaitForFreeSpace( RGLFifo *fifo, GLuint spaceInWords ) +{ + if ( fifo->current + spaceInWords + 1024 > fifo->end ) + _RGLOutOfSpaceCallback( fifo, spaceInWords ); + + return _RGLState.fifo.current; +} + +static inline void _RGLPushProgramPushBuffer( _CGprogram * cgprog ) +{ + _RGLFifoWaitForFreeSpace( &_RGLState.fifo, cgprog->constantPushBufferWordSize + 4 + 32); + 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); + memcpy16(_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; + + _RGLFifoWaitForFreeSpace( &_RGLState.fifo, 7 + 5 * conf.instructionCount ); + + cellGcmSetVertexProgramLoadInline( &_RGLState.fifo, &conf, vs->ucode); + cellGcmSetUserClipPlaneControlInline( &_RGLState.fifo, 0, 0, 0, 0, 0, 0 ); + + 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 < _RGL_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; +} + + +const GLfloat _RGLIdentityMatrixf[ELEMENTS_IN_MATRIX] = +{ + 1.f, 0.f, 0.f, 0.f, + 0.f, 1.f, 0.f, 0.f, + 0.f, 0.f, 1.f, 0.f, + 0.f, 0.f, 0.f, 1.f +}; + +static void _RGLMatrixStackReset( jsMatrixStack* LMatrixStack ) +{ + LMatrixStack->MatrixStackPtr = 0; + memcpy( LMatrixStack->MatrixStackf, _RGLIdentityMatrixf, jsMATRIX_SIZEf ); + LMatrixStack->dirty = GL_TRUE; +} + +static void _RGLResetContext( PSGLcontext *LContext ) +{ + _RGLMatrixStackReset( &( LContext->ModelViewMatrixStack ) ); + _RGLMatrixStackReset( &( LContext->ProjectionMatrixStack ) ); + _RGLTexNameSpaceResetNames( &LContext->textureNameSpace ); + _RGLTexNameSpaceResetNames( &LContext->bufferObjectNameSpace ); + _RGLTexNameSpaceResetNames( &LContext->framebufferNameSpace ); + _RGLTexNameSpaceResetNames( &LContext->attribSetNameSpace ); + + LContext->InverseModelViewValid = GL_FALSE; + LContext->ScalingFactor = 1.f; + + 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->AccumClearColor.R = 0.f; + LContext->AccumClearColor.G = 0.f; + LContext->AccumClearColor.B = 0.f; + LContext->AccumClearColor.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; + + LContext->Dithering = GL_TRUE; + + for ( int i = 0;i < _RGL_MAX_TEXTURE_COORDS;++i ) + { + jsTextureCoordsUnit *tu = LContext->TextureCoordsUnits + i; + tu->revalidate = 0; + _RGLMatrixStackReset( &( tu->TextureMatrixStack ) ); + } + for ( int i = 0;i < _RGL_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 < _RGL_MAX_VERTEX_TEXTURE_IMAGE_UNITS;++i ) + { + LContext->VertexTextureImages[i] = NULL; + } + + LContext->ActiveTexture = 0; + LContext->CurrentImageUnit = LContext->TextureImageUnits; + LContext->CurrentCoordsUnit = LContext->TextureCoordsUnits; + + 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 void _RGLMatrixStackInit( jsMatrixStack* LMatrixStack, GLuint depth ) +{ + LMatrixStack->MatrixStackf = ( GLfloat * )malloc( jsMATRIX_SIZEf * depth ); + if ( !LMatrixStack->MatrixStackf ) return; + + _RGLMatrixStackReset( LMatrixStack ); +} + +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; + LContext->MatrixMode = GL_MODELVIEW; + + _RGLMatrixStackInit( &( LContext->ModelViewMatrixStack ), _RGL_MAX_MODELVIEW_STACK_DEPTH ); + if ( !LContext->ModelViewMatrixStack.MatrixStackf ) + { + psglDestroyContext( LContext ); + return NULL; + } + _RGLMatrixStackInit( &( LContext->ProjectionMatrixStack ), _RGL_MAX_PROJECTION_STACK_DEPTH ); + if ( !LContext->ProjectionMatrixStack.MatrixStackf ) + { + psglDestroyContext( LContext ); + return NULL; + } + + for ( int i = 0; i < _RGL_MAX_TEXTURE_COORDS; i++ ) + { + _RGLMatrixStackInit( &( LContext->TextureCoordsUnits[i].TextureMatrixStack ), _RGL_MAX_TEXTURE_STACK_DEPTH ); + if ( !LContext->TextureCoordsUnits[i].TextureMatrixStack.MatrixStackf ) + { + psglDestroyContext( LContext ); + return NULL; + } + } + + _RGLTexNameSpaceInit( &LContext->textureNameSpace, ( jsTexNameSpaceCreateFunction )_RGLAllocateTexture, ( jsTexNameSpaceDestroyFunction )_RGLFreeTexture ); + + for ( int i = 0;i < _RGL_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; + + _RGLInitNameSpace( &LContext->cgProgramNameSpace ); + _RGLInitNameSpace( &LContext->cgParameterNameSpace ); + _RGLInitNameSpace( &LContext->cgContextNameSpace ); + + _RGLResetContext( LContext ); + + if ( _RGLContextCreateHook ) _RGLContextCreateHook( LContext ); + + return( LContext ); +} + +void psglResetCurrentContext (void) +{ + PSGLcontext *context = _CurrentContext; + _RGLResetContext( context ); + context->needValidate |= PSGL_VALIDATE_ALL; +} + +static void _RGLMatrixStackClear( jsMatrixStack* LMatrixStack ) +{ + if ( LMatrixStack->MatrixStackf ) free( LMatrixStack->MatrixStackf ); + LMatrixStack->MatrixStackf = NULL; + LMatrixStack->MatrixStackPtr = 0; + LMatrixStack->dirty = GL_FALSE; +} + +void psglDestroyContext( PSGLcontext* LContext ) +{ + if ( _CurrentContext == LContext ) + { + cellGcmSetInvalidateVertexCacheInline( &_RGLState.fifo); + _RGLFifoFinish( &_RGLState.fifo ); + } + + while ( LContext->RGLcgContextHead != ( CGcontext )NULL ) + { + PSGLcontext* current = _CurrentContext; + _CurrentContext = LContext; + cgDestroyContext( LContext->RGLcgContextHead ); + _CurrentContext = current; + } + _RGLFreeNameSpace( &LContext->cgProgramNameSpace ); + _RGLFreeNameSpace( &LContext->cgParameterNameSpace ); + _RGLFreeNameSpace( &LContext->cgContextNameSpace ); + + if ( _RGLContextDestroyHook ) _RGLContextDestroyHook( LContext ); + + _RGLMatrixStackClear( &( LContext->ModelViewMatrixStack ) ); + _RGLMatrixStackClear( &( LContext->ProjectionMatrixStack ) ); + + for ( int i = 0; i < _RGL_MAX_TEXTURE_COORDS; i++ ) + _RGLMatrixStackClear( &( LContext->TextureCoordsUnits[i].TextureMatrixStack ) ); + + for ( int i = 0; i < _RGL_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; + + for ( int unit = 0;unit < _RGL_MAX_TEXTURE_UNITS;unit++ ) + context->TextureCoordsUnits[unit].TextureMatrixStack.dirty = GL_TRUE; + + context->ModelViewMatrixStack.dirty = GL_TRUE; + context->ProjectionMatrixStack.dirty = GL_TRUE; + context->attribs->DirtyMask = ( 1 << _RGL_MAX_VERTEX_ATTRIBS ) - 1; +} + +GLAPI void APIENTRY glGetFloatv( GLenum pname, GLfloat* params ) +{ + PSGLcontext* LContext = _CurrentContext; + jsMatrixStack* LMatrixStack = NULL; + GLfloat *LMatrix = NULL; + + switch ( pname ) + { + case GL_MODELVIEW_MATRIX: + jsContextGetMatrixf( LContext, GL_MODELVIEW, LMatrixStack, LMatrix ); + break; + + case GL_PROJECTION_MATRIX: + jsContextGetMatrixf( LContext, GL_PROJECTION, LMatrixStack, LMatrix ); + break; + + case GL_TEXTURE_MATRIX: + jsContextGetMatrixf( LContext, GL_TEXTURE, LMatrixStack, LMatrix ); + break; + case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT: + return; + default: + _RGLSetError( GL_INVALID_ENUM ); + return; + } + memcpy( params, LMatrixStack->MatrixStackf + LMatrixStack->MatrixStackPtr * ELEMENTS_IN_MATRIX, jsMATRIX_SIZEf ); +} + +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: + LContext->Dithering = GL_TRUE; + 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: + LContext->Dithering = GL_FALSE; + 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() +{ + PSGLcontext *LContext = _CurrentContext; + RGLFifo *fifo = &_RGLState.fifo; + + if ( RGL_UNLIKELY( LContext->needValidate ) ) + _RGLValidateStates(); + + cellGcmSetInvalidateVertexCacheInline( &_RGLState.fifo); + + _RGLFifoFlush( fifo ); +} + +GLAPI void APIENTRY glFinish (void) +{ + glFlush(); + cellGcmSetInvalidateVertexCacheInline( &_RGLState.fifo); + _RGLFifoFinish( &_RGLState.fifo ); +} + +PSGLuint64 psglGetSystemTime() +{ + return sys_time_get_system_time(); +} + +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(); + cellGcmSetInvalidateVertexCacheInline ( &_RGLState.fifo); + _RGLFifoFinish( &_RGLState.fifo ); + + psglMakeCurrent( NULL, NULL ); + _RGLDeviceExit(); + + _CurrentContext = NULL; + + _RGLInitCompleted = 0; + } +} + +#undef __STRICT_ANSI__ + +GLAPI void APIENTRY glLoadIdentity() +{ + PSGLcontext* LContext = _CurrentContext; + jsMatrixStack* LMatrixStack = NULL; + + jsContextGetMatrixStack(LContext, LContext->MatrixMode, LMatrixStack); + memcpy( LMatrixStack->MatrixStackf + LMatrixStack->MatrixStackPtr*ELEMENTS_IN_MATRIX, _RGLIdentityMatrixf, jsMATRIX_SIZEf ); + + LMatrixStack->dirty = GL_TRUE; +} + +GLAPI void APIENTRY glMatrixMode( GLenum mode ) +{ + PSGLcontext* LContext = _CurrentContext; + LContext->MatrixMode = mode; +} + +GLAPI void APIENTRY glOrthof( GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar ) +{ + PSGLcontext* LContext = _CurrentContext; + jsMatrixStack* LMatrixStack = NULL; + GLfloat *LMatrix = NULL; + + jsContextGetMatrixStack(LContext, LContext->MatrixMode, LMatrixStack); + if (LMatrixStack) + LMatrix = LMatrixStack->MatrixStackf + LMatrixStack->MatrixStackPtr * ELEMENTS_IN_MATRIX; + + GLfloat L00, L01, L02, L03, L10, L11, L12, L13, L20, L21, L22, L23, L30, L31, L32, L33; + + + GLfloat m00 = 2.f / ( right - left ); + GLfloat m03 = -( right + left ) / ( right - left ); + GLfloat m11 = 2.f / ( top - bottom ); + GLfloat m13 = -( top + bottom ) / ( top - bottom ); + GLfloat m22 = -2.f / ( zFar - zNear ); + GLfloat m23 = -( zFar + zNear ) / ( zFar - zNear ); + + L00 = LMatrix[0]; + L01 = LMatrix[M01]; + L02 = LMatrix[M02]; + L03 = LMatrix[M03]; + L10 = LMatrix[M10]; + L11 = LMatrix[M11]; + L12 = LMatrix[M12]; + L13 = LMatrix[M13]; + L20 = LMatrix[M20]; + L21 = LMatrix[M21]; + L22 = LMatrix[M22]; + L23 = LMatrix[M23]; + L30 = LMatrix[M30]; + L31 = LMatrix[M31]; + L32 = LMatrix[M32]; + L33 = LMatrix[M33]; + + LMatrix[0] = L00 * m00; + LMatrix[M01] = L01 * m11; + LMatrix[M02] = L02 * m22; + LMatrix[M03] = L00 * m03 + L01 * m13 + L02 * m23 + L03; + + LMatrix[M10] = L10 * m00; + LMatrix[M11] = L11 * m11; + LMatrix[M12] = L12 * m22; + LMatrix[M13] = L10 * m03 + L11 * m13 + L12 * m23 + L13; + + LMatrix[M20] = L20 * m00; + LMatrix[M21] = L21 * m11; + LMatrix[M22] = L22 * m22; + LMatrix[M23] = L20 * m03 + L21 * m13 + L22 * m23 + L23; + + LMatrix[M30] = L30 * m00; + LMatrix[M31] = L31 * m11; + LMatrix[M32] = L32 * m22; + LMatrix[M33] = L30 * m03 + L31 * m13 + L32 * m23 + L33; + + LMatrixStack->dirty = GL_TRUE; + if ( LContext->MatrixMode == GL_MODELVIEW ) + LContext->InverseModelViewValid = GL_FALSE; +} + +const uint32_t c_rounded_size_of_RGLDrawParams = (sizeof(jsDrawParams)+0x7f)&~0x7f; +static uint8_t s_dparams_buff[ c_rounded_size_of_RGLDrawParams ] __attribute__((aligned(128))); + +int _psglCheckDrawElementsVBOBounds = 0; + +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; + } + printf("RGL 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 = _RGLGetAttribSet( LContext->attribSetName ); + + if ( oldArrayBuffer ) + { + int refcount = 0; + for ( unsigned int i = 0; i < _RGL_MAX_VERTEX_ATTRIBS; ++i ) + { + if ( attribSet->attribs.attrib[i].arrayBuffer == oldArrayBuffer ) ++refcount; + } + if ( refcount == 1 ) _RGLGetBufferObject( LContext, oldArrayBuffer )->attribSets.removeElement( attribSet ); + } + + if ( attrib->arrayBuffer ) + { + _RGLGetBufferObject( LContext, attrib->arrayBuffer )->attribSets.appendUnique( attribSet ); + } + + _RGLAttribSetMarkDirty(); + } +} + +void _RGLEnableVertexAttribArrayNV( GLuint index ) +{ + PSGLcontext *LContext = _CurrentContext; + + RGLBIT_TRUE( LContext->attribs->EnabledMask, index ); + RGLBIT_TRUE( LContext->attribs->DirtyMask, index ); + + if ( LContext->attribSetName ) + _RGLAttribSetMarkDirty(); +} + +void _RGLDisableVertexAttribArrayNV( GLuint index ) +{ + PSGLcontext *LContext = _CurrentContext; + + RGLBIT_FALSE( LContext->attribs->EnabledMask, index ); + RGLBIT_TRUE( LContext->attribs->DirtyMask, index ); + + if ( LContext->attribSetName ) + _RGLAttribSetMarkDirty(); +} + +static GLuint _RGLValidateAttributesSlow( jsDrawParams *dparams, GLboolean *isMain ) +{ + 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 < _RGL_MAX_VERTEX_ATTRIBS; ++i ) + { + if ( ! RGLBIT_GET( needsUpdateMask, i ) ) + continue; + + jsAttribute* 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] ) ) + { + 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 ); + + *isMain = gmmIdIsMain(xferId); + gpuOffset = gmmIdToOffset(xferId) + (b - ( char * )xferBuffer); + + } + else + { + VBOId = _RGLGetBufferObjectOrigin( attrib->arrayBuffer ); + *isMain = gmmIdIsMain(VBOId); + gpuOffset = gmmIdToOffset(VBOId) + + (( const GLubyte* )attrib->clientData - ( const GLubyte* )NULL ); + } + + _RGLFifoGlVertexAttribPointer( i, attrib->clientSize, + ( RGLEnum )attrib->clientType, attrib->normalized, + stride, freq, *isMain, gpuOffset ); + } + else + { + _RGLFifoGlVertexAttribPointer( i, 0, RGL_FLOAT, 0, 0, 0, 0, 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 ) +{ + 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 = c_rounded_size_of_RGLDrawParams>>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 = mode; + 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 < _RGL_MAX_VERTEX_ATTRIBS; ++i ) + { + 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; + } + else + { + dparams->attribXferOffset[i] = 0; + dparams->attribXferSize[i] = 0; + } + } + } + + if ( driver->flushBufferCount != 0 ) + driver->invalidateVertexCache = GL_TRUE; + + GLboolean isMain = 0; + + if ( LContext->attribSetDirty && LContext->attribSetName ) + { + jsAttribSet* attribSet = _RGLGetAttribSet( LContext->attribSetName ); + } + uint32_t totalXfer = 0; + for ( GLuint i = 0; i < _RGL_MAX_VERTEX_ATTRIBS; ++i ) + totalXfer += dparams->attribXferSize[i]; + + GLuint gpuOffset = _RGLValidateAttributesSlow( dparams, &isMain ); + (void)gpuOffset; + + if ( driver->invalidateVertexCache ) + { + driver->invalidateVertexCache = GL_FALSE; + cellGcmSetInvalidateVertexCacheInline ( &_RGLState.fifo); + } + + cellGcmSetUpdateFragmentProgramParameterInline( &_RGLState.fifo, gmmIdToOffset( driver->fpLoadProgramId) +driver->fpLoadProgramOffset ); + + cellGcmSetDrawArraysInline( &_RGLState.fifo, CELL_GCM_PRIMITIVE_QUADS, 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 < _RGL_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 < _RGL_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 |= _RGL_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 |= _RGL_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 |= _RGL_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; +} + +static int _RGLGetImage( GLenum target, GLint level, jsTexture **texture, jsImage **image, GLsizei reallocateSize ) +{ + PSGLcontext* LContext = _CurrentContext; + jsTextureImageUnit *unit = LContext->CurrentImageUnit; + + jsTexture *tex = _RGLGetCurrentTexture( unit, GL_TEXTURE_2D ); + + if ( level >= ( int )tex->imageCount ) + _RGLReallocateImages( tex, reallocateSize ); + + *image = tex->image; + *texture = tex; + return 0; +} + + +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; + + _RGLGetImage( GL_TEXTURE_2D, 0, &texture, &image, MAX( width, height ) ); + + image->dataState = _RGL_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 = _RGLGetBufferObject( LContext, 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 |= _RGL_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 < _RGL_MAX_TEXTURE_IMAGE_UNITS ? LContext->TextureImageUnits + unit : NULL; + LContext->CurrentCoordsUnit = unit < _RGL_MAX_TEXTURE_COORDS ? LContext->TextureCoordsUnits + 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 = _RGLGetBufferObject( LContext, 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 ( NULL != ptr && 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 symbolSize; + size_t symbolCount; + const char *symbolstrtab; + const char *symtab = findSymbolSectionInPlace(( const char * )ptr, size, &symbolSize, &symbolCount, &symbolstrtab ); + if ( !symtab ) + break; + + size_t shadertabSize; + const char *shadertab = findSectionInPlace(( const char* )ptr, size, ".shadertab", &shadertabSize ); + if ( !shadertab ) + break; + size_t strtabSize; + const char *strtab = findSectionInPlace(( const char* )ptr, size, ".strtab", &strtabSize ); + if ( !strtab ) + break; + size_t consttabSize; + 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 ( true ) + { + char sectionName[64]; + sprintf( sectionName, ".text%04i", index ); + size_t texttabSize; + const char *texttab = findSectionInPlace( elfBinary->elfFile, elfBinary->elfFileSize, sectionName, &texttabSize ); + if ( !texttab ) + break; + sprintf( 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 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; +} + +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 ( NULL == prog ) + { + _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; + + //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 = _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 = _RGLPlatformGenerateFragmentProgram( 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 ( 0 == success ) + { + // 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. + // 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 + { + printf("RGL 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 ) ) + { + //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 ) + { + printf("RGL 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; + STL_NAMESPACE vector stringTableArray; + STL_NAMESPACE 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 ) + { + printf("RGL 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 ) + { + printf("RGL 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 ) + { + printf("RGL ERR: not a valid ELF.\n"); + _RGLCgRaiseError( CG_PROGRAM_LOAD_ERROR ); + return NULL; + } + if ( !cgGetElfProgramByName( &elfBinary, entry, &elfProgram ) ) + { + printf("RGL 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 ( 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; + 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 ) + { + printf("RGL 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 ( NULL == fp ) + { + _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 ( NULL == ptr ) + { + _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 ( 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; + } + 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 ( 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 ) + { + _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; +} + +CG_API CGprofile cgGetProgramProfile( CGprogram prog ) +{ + if ( !CG_IS_PROGRAM( prog ) ) + { + _RGLCgRaiseError( CG_INVALID_PROGRAM_HANDLE_ERROR ); + return CG_PROFILE_UNKNOWN; + } + + return ( CGprofile )_cgGetProgPtr( prog )->header.profile; +} + +CG_API CGprofile cgGetProgramDomainProfile( CGprogram program, int index ) +{ + if ( !CG_IS_PROGRAM( program ) ) + { + _RGLCgRaiseError( CG_INVALID_PROGRAM_HANDLE_ERROR ); + return CG_PROFILE_UNKNOWN; + } + + if ( index >= 1 ) + return CG_PROFILE_UNKNOWN; + + return ( CGprofile )_cgGetProgPtr( program )->header.profile; +} + +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 ( NULL == fp ) + { + _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 ( NULL == ptr ) + { + _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; + strcpy( group->name, 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 CGprofile cgGetProfile( const char* profile_string ) +{ + size_t arraysize = sizeof( RGLcgProfileMap ) / sizeof( RGLcgProfileMapType ); + unsigned int i = 0; + while ( i < arraysize ) + { + if ( 0 == strcmp( RGLcgProfileMap[i].string, profile_string ) ) + { + return RGLcgProfileMap[i].id; + } + ++i; + } + return CG_PROFILE_UNKNOWN; +} + +CG_API CGerror cgGetError( void ) +{ + CGerror err = _CurrentContext->RGLcgLastError; + _CurrentContext->RGLcgLastError = CG_NO_ERROR; + return err; +} + +CG_API const char* cgGetErrorString( CGerror error ) +{ + return "cgGetErrorString: N/A\n"; +} + +CG_API const char* cgGetLastErrorString( CGerror* error ) +{ + return "cgGetErrorString: N/A\n"; +} + +CG_API void cgSetErrorCallback( CGerrorCallbackFunc func ) +{ + _CurrentContext->RGLcgErrorCallbackFunction = func; +} + + +CG_API CGerrorCallbackFunc cgGetErrorCallback( void ) +{ + return _CurrentContext->RGLcgErrorCallbackFunction; +} + +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 < _RGL_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 CGbool cgGLIsProgramLoaded( CGprogram program ) +{ + return CG_TRUE; +} + + +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 < _RGL_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 GLuint cgGLGetProgramID( CGprogram program ) +{ + + return 0; +} + +CGGL_API void cgGLEnableProgramProfiles( CGprogram program ) +{ + return; +} + +CGGL_API void cgGLDisableProgramProfiles( CGprogram program ) +{ + return; +} + + +CGGL_API void cgGLSetParameter1f( CGparameter param, float x ) +{ + + CgRuntimeParameter *ptr = _RGLCgGLTestParameter( 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 = _RGLCgGLTestParameter( 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 = _RGLCgGLTestParameter( 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 = _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 ); +} + +CGGL_API void cgGLSetStateMatrixParameter( CGparameter param, + CGGLenum matrix, + CGGLenum transform ) +{ + float m[4][4]; + switch ( matrix ) + { + case CG_GL_MODELVIEW_MATRIX: + glGetFloatv( GL_MODELVIEW_MATRIX, ( float* )m ); + break; + case CG_GL_PROJECTION_MATRIX: + glGetFloatv( GL_PROJECTION_MATRIX, ( float* )m ); + break; + case CG_GL_TEXTURE_MATRIX: + glGetFloatv( GL_TEXTURE_MATRIX, ( float* )m ); + break; + case CG_GL_MODELVIEW_PROJECTION_MATRIX: + { + float mv[4][4], p[4][4]; + glGetFloatv( GL_MODELVIEW_MATRIX, ( float* )mv ); + glGetFloatv( GL_PROJECTION_MATRIX, ( float* )p ); + +#define M(I,J) \ + m[I][J] = mv[I][0]*p[0][J] + mv[I][1]*p[1][J] + mv[I][2]*p[2][J] + mv[I][3]*p[3][J] + M( 0, 0 ); M( 0, 1 ); M( 0, 2 ); M( 0, 3 ); + M( 1, 0 ); M( 1, 1 ); M( 1, 2 ); M( 1, 3 ); + M( 2, 0 ); M( 2, 1 ); M( 2, 2 ); M( 2, 3 ); + M( 3, 0 ); M( 3, 1 ); M( 3, 2 ); M( 3, 3 ); +#undef M + } + break; + default: + _RGLCgRaiseError( CG_INVALID_ENUMERANT_ERROR ); + return; + } + + CgRuntimeParameter* ptr = _RGLCgGLTestParameter( param ); + + CGtype parameterType = _RGLGetParameterCGtype( ptr->program, ptr->parameterEntry ); + if ( RGL_LIKELY( parameterType == CG_FLOAT4x4 ) ) + { + ptr->settercIndex( ptr, m, CG_GETINDEX( param ) ); + } + else + { + float packedmatrix[16]; + unsigned int rows = _RGLGetTypeRowCount( parameterType ); + unsigned int cols = _RGLGetTypeColCount( parameterType ); + for ( GLuint row = 0; row < rows; ++row ) + for ( GLuint j = 0; j < cols; ++j ) + packedmatrix[row*cols + j] = m[j][row]; + ptr->setterrIndex( ptr, packedmatrix, CG_GETINDEX( param ) ); + } +} + +CGGL_API void cgGLSetTextureParameter( CGparameter param, GLuint texobj ) +{ + 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 ) ) + { + } +} + +CGGL_API void cgGLSetDebugMode( CGbool debug ) +{ + return; +} + +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 ); + ctx->next = head; + } + _CurrentContext->RGLcgContextHead = ctx->id; +} + +static void destroy_context( _CGcontext*ctx ) +{ + if ( _cgContextDestroyHook ) _cgContextDestroyHook( ctx ); + _RGLEraseName( &_CurrentContext->cgContextNameSpace, ( jsName )ctx->id ); + _RGLCgContextZero( ctx ); + free( ctx ); +} + +void _RGLCgContextPopFront() +{ + if ( _CurrentContext->RGLcgContextHead ) + { + _CGcontext* head = _cgGetContextPtr( _CurrentContext->RGLcgContextHead ); + _CGcontext* temp = head->next; + destroy_context( head ); + + if ( temp ) + { + _CurrentContext->RGLcgContextHead = temp->id; + } + else + { + _CurrentContext->RGLcgContextHead = 0; + } + } +} + +CG_API CGcontext cgCreateContext( void ) +{ + _CGcontext* ptr = NULL; + + ptr = ( _CGcontext* )malloc( sizeof( _CGcontext ) ); + if ( NULL == ptr ) + { + _RGLCgRaiseError( CG_MEMORY_ALLOC_ERROR ); + return ( CGcontext )NULL; + } + + _RGLCgContextZero( ptr ); + + 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; + + + printf("RGL: Cg error:%s.\n", 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: + 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 ) +{ +} + +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]; +} diff --git a/console/rgl/ps3/rgl.h b/console/rgl/ps3/rgl.h new file mode 100644 index 0000000000..4bb325bd09 --- /dev/null +++ b/console/rgl/ps3/rgl.h @@ -0,0 +1,1179 @@ +#ifndef _RGL_H +#define _RGL_H + +#include "gl.h" +#include "glext.h" +#include "base.hpp" + +#include + +#define RGL_ALIGN_FAST_TRANSFER 128 +#define _RGL_MAX_COLOR_ATTACHMENTS 4 +#define RGL_SUBPIXEL_ADJUST (0.5/(1<<12)) +#define RGL_VIEWPORT_EPSILON (0.0f) + +#define gmmIdIsMain(id) (((GmmBaseBlock *)id)->isMain) + +#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[_RGL_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) + +#ifndef MSVC + +#define ALIGN16 __attribute__((aligned (16))) +#define _RGL_RESTRICT __restrict + +#if defined(_WIN64) + typedef __int64 RGLintptr; + typedef __int64 RGLsizeiptr; +#else + typedef long RGLintptr; + typedef long RGLsizeiptr; +#endif + +#else + +#define ALIGN16 +#define _RGL_RESTRICT +#pragma warning( push ) +#pragma warning ( disable : 4200 ) + typedef intptr_t RGLintptr; + typedef size_t RGLsizeiptr; +#endif + +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 +{ + GLfloat * MatrixStackf; + int MatrixStackPtr; + GLboolean dirty; +} jsMatrixStack; + +typedef struct +{ + int X, Y, XSize, YSize; +} jsViewPort; + +#define _RGL_IMAGE_STORAGE_RASTER 0 +#define _RGL_IMAGE_STORAGE_BLOCK 1 + +enum { + _RGL_IMAGE_DATASTATE_UNSET = 0x0, + _RGL_IMAGE_DATASTATE_HOST = 0x1, + _RGL_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 _RGL_TEXTURE_REVALIDATE_LAYOUT 0x01 +#define _RGL_TEXTURE_REVALIDATE_IMAGES 0x02 +#define _RGL_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 _RGL_MAX_TEXTURE_COORDS 8 +#define _RGL_MAX_TEXTURE_IMAGE_UNITS 16 +#define _RGL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 4 + +#define _RGL_MAX_TEXTURE_UNITS 4 + +#define _RGL_MAX_TEXTURE_SIZE_LOG2 12 +#define _RGL_MAX_TEXTURE_SIZE (4096) +#define _RGL_MAX_TEXTURE_SIZE_3D_LOG2 9 +#define _RGL_MAX_TEXTURE_SIZE_3D (512) +#define _RGL_MAX_MODELVIEW_STACK_DEPTH 16 +#define _RGL_MAX_PROJECTION_STACK_DEPTH 2 +#define _RGL_MAX_TEXTURE_STACK_DEPTH 2 + +#define _RGL_MAX_VERTEX_ATTRIBS 16 + +typedef struct +{ + GLuint bound2D; + + jsTexture* default2D; + + GLenum fragmentTarget; + + GLenum envMode; + jsColorRGBAf envColor; + + jsTexture* currentTexture; +} jsTextureImageUnit; + +typedef struct +{ + GLuint revalidate; + jsMatrixStack TextureMatrixStack; +} jsTextureCoordsUnit; + +enum +{ + _RGL_FRAMEBUFFER_ATTACHMENT_NONE, + _RGL_FRAMEBUFFER_ATTACHMENT_RENDERBUFFER, + _RGL_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[_RGL_MAX_VERTEX_ATTRIBS]; + GLuint attribXferSize[_RGL_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; + } + ALIGN16 jsAttribute; + + typedef struct + { + jsAttribute attrib[_RGL_MAX_VERTEX_ATTRIBS]; + unsigned int DirtyMask; + unsigned int EnabledMask; + unsigned int NeedsConversionMask; + unsigned int HasVBOMask; + unsigned int ModuloMask; + } + ALIGN16 jsAttributeState; + + typedef struct + { + jsAttributeState attribs; + GLboolean dirty; + unsigned int beenUpdatedMask; + GLvoid* cmdBuffer; + GLuint cmdNumWords; + } + ALIGN16 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[]; + }; + + +#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 + +#define ELEMENTS_IN_MATRIX 16 + + 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; + int MatrixMode; + jsMatrixStack ModelViewMatrixStack; + jsMatrixStack ProjectionMatrixStack; + GLfloat LocalToScreenMatrixf[ELEMENTS_IN_MATRIX]; + GLfloat InverseModelViewMatrixf[ELEMENTS_IN_MATRIX]; + GLboolean InverseModelViewValid; + GLfloat ScalingFactor; + jsViewPort ViewPort; + jsAttributeState defaultAttribs0; + jsAttributeState *attribs; + jsTexNameSpace attribSetNameSpace; + GLuint attribSetName; + GLboolean attribSetDirty; + jsColorRGBAf ClearColor; + jsColorRGBAf AccumClearColor; + GLboolean ShaderSRGBRemap; + GLboolean Blending; + GLboolean BlendingMrt[3]; + GLenum BlendEquationRGB; + GLenum BlendEquationAlpha; + GLenum BlendFactorSrcRGB; + GLenum BlendFactorDestRGB; + GLenum BlendFactorSrcAlpha; + GLenum BlendFactorDestAlpha; + jsColorRGBAf BlendColor; + GLboolean Dithering; + jsTexNameSpace textureNameSpace; + GLuint ActiveTexture; + GLuint CS_ActiveTexture; + jsTextureImageUnit TextureImageUnits[_RGL_MAX_TEXTURE_IMAGE_UNITS]; + jsTextureImageUnit* CurrentImageUnit; + jsTextureCoordsUnit TextureCoordsUnits[_RGL_MAX_TEXTURE_COORDS]; + jsTextureCoordsUnit* CurrentCoordsUnit; + jsTexture *VertexTextureImages[_RGL_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 jsContextGetMatrixStack(mContext, mMatrixMode, mMatrixStack) do \ +{\ + switch(mMatrixMode)\ + {\ + case GL_MODELVIEW:\ + mMatrixStack = &((mContext)->ModelViewMatrixStack);\ + break;\ + case GL_PROJECTION:\ + mMatrixStack = &((mContext)->ProjectionMatrixStack);\ + break;\ + case GL_TEXTURE:\ + if ((mContext)->CurrentCoordsUnit) mMatrixStack = &((mContext)->CurrentCoordsUnit->TextureMatrixStack);\ + else mMatrixStack=NULL; \ + break;\ + default: \ + break; \ + }\ +} while(0) + +#define jsContextGetMatrixf(mContext, mMatrixMode, mMatrixStack, mMatrix) do \ +{\ + jsContextGetMatrixStack(mContext, mMatrixMode, mMatrixStack);\ + if (mMatrixStack) mMatrix = (mMatrixStack)->MatrixStackf+(mMatrixStack)->MatrixStackPtr*ELEMENTS_IN_MATRIX;\ +} while (0) + +#if defined(MSVC) +#pragma warning ( pop ) +#endif + +#ifndef MSVC +#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_ALLOC_FIRST_FIT 0 +#define _RGL_ALLOC_BEST_FIT 1 + + static inline float _RGLClampf( const float value ) + { + return MAX( MIN( value, 1.f ), 0.f ); + } + + 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; + } + + static inline char* _RGLPadPtr( const char* p, unsigned int pad ) + { + RGLintptr x = ( RGLintptr )p; + x = ( x + pad - 1 ) / pad * pad; + return ( char* )x; + } + + typedef struct MemoryBlockManager_t_ + { + char *memory; + GLuint size; + GLuint minAlignment; + GLenum method; + GLuint *book; + GLint bookSize; + GLint bookAlloc; + } + MemoryBlockManager_t; + + + typedef unsigned long jsName; + + void _RGLInitNameSpace( struct jsNameSpace * name ); + void _RGLFreeNameSpace( struct jsNameSpace * name ); + 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 RGL_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; + +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; \ + } + +#define _RGLTransferDataVidToVid(dstId, dstIdOffset, dstPitch, dstX, dstY, srcId, srcIdOffset, srcPitch, srcX, srcY, width, height, bytesPerPixel) \ +{ \ + GLuint dstOffset_tmp, srcOffset_tmp; \ + uint8_t mode; \ + dstOffset_tmp = gmmIdToOffset(dstId) + dstIdOffset; \ + srcOffset_tmp = gmmIdToOffset(srcId) + srcIdOffset; \ + mode = CELL_GCM_TRANSFER_LOCAL_TO_LOCAL; \ + if ( gmmIdIsMain(srcId) && gmmIdIsMain(dstId) ) \ + mode = CELL_GCM_TRANSFER_MAIN_TO_MAIN; \ + else if ( gmmIdIsMain(srcId) ) /* choose source DMA context */ \ + mode = CELL_GCM_TRANSFER_MAIN_TO_LOCAL; \ + else if ( gmmIdIsMain(dstId) ) /* choose destination DMA context */ \ + mode = CELL_GCM_TRANSFER_LOCAL_TO_MAIN; \ + cellGcmSetTransferImageInline( &_RGLState.fifo, mode, dstOffset_tmp, (dstPitch), (dstX), (dstY), (srcOffset_tmp), (srcPitch), (srcX), (srcY), (width), (height), (bytesPerPixel) ); \ +} + +#define RGL_BIG_ENDIAN + +#define _RGL_LINEAR_BUFFER_ALIGNMENT 128 +#define _RGL_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 +#define SUBPIXEL_ADJUST (0.5/4096) + +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; +}; + +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 _RGL_SEMA_NEVENTS 128 +#define _RGL_SEMA_BASE 64 +#define _RGL_SEMA_FENCE (_RGL_SEMA_BASE+_RGL_SEMA_NEVENTS+0) + +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 ); + void _RGLGetTileRegionInfo( void* data, GLuint *address, GLuint *size ); + + 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; + } + } + + + void static inline _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 + RGL_SUBPIXEL_ADJUST ); + if ( rt->yInverted ) + { + vp->yScale = height * -0.5f; + vp->yCenter = ( GLfloat )( rt->gcmRenderTarget.height - RGL_VIEWPORT_EPSILON - y + vp->yScale + RGL_SUBPIXEL_ADJUST ); + } + else + { + vp->yScale = height * 0.5f; + vp->yCenter = ( GLfloat )( y + vp->yScale + RGL_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 + + +typedef unsigned long long int PSGLuint64; + +extern void psglInit( PSGLinitOptions* options ); +extern void psglExit(); + +PSGLdevice* psglCreateDeviceAuto( GLenum colorFormat, GLenum depthFormat, GLenum multisamplingMode ); +PSGLdevice* psglCreateDeviceExtended( const PSGLdeviceParameters *parameters ); +GLfloat psglGetDeviceAspectRatio( const PSGLdevice * device ); +void psglGetDeviceDimensions( const PSGLdevice * device, GLuint *width, GLuint *height ); +void psglGetRenderBufferDimensions( const PSGLdevice * device, GLuint *width, GLuint *height ); +void psglDestroyDevice( PSGLdevice* device ); + +void psglMakeCurrent( PSGLcontext* context, PSGLdevice* device ); +PSGLcontext* psglCreateContext(); +void psglDestroyContext( PSGLcontext* LContext ); +void psglResetCurrentContext(); +PSGLcontext* psglGetCurrentContext(); +PSGLdevice* psglGetCurrentDevice(); +void psglSwap( void ); + +PSGLuint64 psglGetSystemTime(); + +static inline void psglRescAdjustAspectRatio( const float horizontalScale, const float verticalScale ) + { cellRescAdjustAspectRatio( horizontalScale, verticalScale ); } + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/console/rgl/ps3/vector b/console/rgl/ps3/vector new file mode 100644 index 0000000000..d375ac48a2 --- /dev/null +++ b/console/rgl/ps3/vector @@ -0,0 +1,1739 @@ +// vector standard header + +#ifndef _VECTOR_ +#define _VECTOR_ + +#define RGL_STD_VECTOR + +#include +#include + +#define STL_NAMESPACE ::RGL:: + +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/ps3/ps3_video_psgl.c b/ps3/ps3_video_psgl.c index 985550fadb..fd3297e1b2 100644 --- a/ps3/ps3_video_psgl.c +++ b/ps3/ps3_video_psgl.c @@ -1201,15 +1201,6 @@ void ps3graphics_set_overscan(bool overscan_enable, float amount, bool recalcula } } - -/* PS3 needs a working graphics stack before RetroArch even starts. - - To deal with this main.c, the top level module owns the instance, - and is created beforehand. When RetroArch gets around to init it, it - is already allocated. - - When RetroArch wants to free it, it is ignored. */ - void ps3graphics_video_init(bool get_all_resolutions) { video_info_t video_info = {0};