RetroArch/console/rgl/ps3/rgl.cpp
2012-05-27 23:57:16 +02:00

8679 lines
291 KiB
C++

#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <math.h>
#include <float.h>
#include <cell/gcm.h>
#include <sys/sys_time.h>
#include "rgl.h"
#include "private.h"
#include <ppu_intrinsics.h>
#include "cg.h"
#include <Cg/cgc.h>
#include <Cg/cgGL.h>
#include "readelf.h"
#include "cgnv2rt.h"
#include <cell/sysmodule.h>
#include "../../../compat/strl.h"
#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;i<sectionCount;i++)
{
const Elf32_Shdr *sectionHeader = (const Elf32_Shdr *)sectionHeaderStart + i;
const char *sectionName = shstrtab + sectionHeader->sh_name;
if (!strcmp(name,sectionName))
{
*sectionSize = sectionHeader->sh_size;
return (const char*)ehdr + sectionHeader->sh_offset;
}
}
return NULL;
}
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;i<sectionCount;i++)
{
const Elf32_Shdr *sectionHeader = (const Elf32_Shdr *)sectionHeaderStart + i;
if (sectionHeader->sh_type == SHT_SYMTAB)
{
*symbolSize = sectionHeader->sh_entsize;
*symbolCount = sectionHeader->sh_size / sectionHeader->sh_entsize;
const Elf32_Shdr *symbolStrHeader = (const Elf32_Shdr *)sectionHeaderStart + sectionHeader->sh_link;
*symbolstrtab = (const char*)ehdr + symbolStrHeader->sh_offset;
return (const char*)ehdr + sectionHeader->sh_offset;
}
}
return NULL;
}
int lookupSymbolValueInPlace(const char* symbolSection, size_t symbolSize, size_t symbolCount, const char *symbolstrtab, const char *name)
{
for (size_t i=0;i<symbolCount;i++)
{
Elf32_Sym* elf_sym = (Elf32_Sym*)symbolSection;
if (!strcmp(symbolstrtab + elf_sym->st_name, name))
{
return elf_sym->st_value;
}
symbolSection+= symbolSize;
}
return -1;
}
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<jsTexture *>();
new( &buffer->attribSets ) RGL::Vector<jsAttribSet *>();
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<jsTexture *>();
buffer->attribSets.~Vector<jsAttribSet *>();
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;
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;
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;i<count;++i) \
{ \
const type_##TYPE data=*(const type_##TYPE *)bytes; \
values[i]=_RGLFloatFrom_##TYPE(data); \
bytes+=sizeof(type_##TYPE); \
} \
}
DECLARE_UNPACKED_TYPES
#undef DECLARE_UNPACKED_TYPE
#define DECLARE_PACKED_TYPE(REALTYPE,TYPE,N,S1,S2,S3,S4,REV) \
static void _RGLGetComponents_##TYPE(const unsigned char *bytes, GLfloat *values, int count) \
{ \
const type_##REALTYPE data=*(const type_##REALTYPE *)bytes; \
GET_BITS(values[INDEX##REV(N,0)],data,S2+S3+S4,S1); \
GET_BITS(values[INDEX##REV(N,1)],data,S3+S4,S2); \
GET_BITS(values[INDEX##REV(N,2)],data,S4,S3); \
GET_BITS(values[INDEX##REV(N,3)],data,0,S4); \
}
DECLARE_PACKED_TYPES
#undef DECLARE_PACKED_TYPE
#define DECLARE_UNPACKED_TYPE(TYPE) \
static void _RGLPutComponents_##TYPE(unsigned char *bytes, GLfloat *values, int count) \
{ \
int i; \
for (i=0;i<count;++i) \
{ \
type_##TYPE *data=(type_##TYPE *)bytes; \
*data=_RGLFloatTo_##TYPE(values[i]); \
bytes+=sizeof(type_##TYPE); \
} \
}
DECLARE_UNPACKED_TYPES
#undef DECLARE_UNPACKED_TYPE
#define DECLARE_PACKED_TYPE(REALTYPE,TYPE,N,S1,S2,S3,S4,REV) \
static void _RGLPutComponents_##TYPE(unsigned char *bytes, GLfloat *values, int count) \
{ \
type_##REALTYPE *data=(type_##REALTYPE *)bytes; \
*data=0; \
PUT_BITS(values[INDEX##REV(N,0)],*data,S2+S3+S4,S1); \
PUT_BITS(values[INDEX##REV(N,1)],*data,S3+S4,S2); \
PUT_BITS(values[INDEX##REV(N,2)],*data,S4,S3); \
PUT_BITS(values[INDEX##REV(N,3)],*data,0,S4); \
}
DECLARE_PACKED_TYPES
#undef DECLARE_PACKED_TYPE
static inline GetComponentsFunction_t *_RGLFindGetComponentsFunction( GLenum type )
{
switch ( type )
{
#define DECLARE_UNPACKED_TYPE(TYPE) \
case TYPE: \
return &_RGLGetComponents_##TYPE;
DECLARE_UNPACKED_TYPES
#undef DECLARE_UNPACKED_TYPE
#define DECLARE_PACKED_TYPE(REALTYPE,TYPE,N,S1,S2,S3,S4,REV) \
case TYPE: \
return &_RGLGetComponents_##TYPE;
DECLARE_PACKED_TYPES
#undef DECLARE_PACKED_TYPE
default:
return NULL;
}
}
static inline PutComponentsFunction_t *_RGLFindPutComponentsFunction( GLenum type )
{
switch ( type )
{
#define DECLARE_UNPACKED_TYPE(TYPE) \
case TYPE: \
return &_RGLPutComponents_##TYPE;
DECLARE_UNPACKED_TYPES
#undef DECLARE_UNPACKED_TYPE
#define DECLARE_PACKED_TYPE(REALTYPE,TYPE,N,S1,S2,S3,S4,REV) \
case TYPE: \
return &_RGLPutComponents_##TYPE;
DECLARE_PACKED_TYPES
#undef DECLARE_PACKED_TYPE
default:
return NULL;
}
}
static void _RGLValuesToColor_GL_RGB( jsColorRGBAf *c, GLfloat *v ) { c->R = 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<jsPlatformFramebuffer *>( _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; j<blockCount; j++)
{
pGmmFixedAllocData->ppFreeBlockList[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; i<listCount; i++)
{
if (pGmmFixedAllocData->pBlocksUsed[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; i<blockCount; i++)
{
pGmmFixedAllocData->ppFreeBlockList[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; i<pGmmFixedAllocData->BlockListCount[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; i<iterations; i++)
gmmLocalMemcpy(dstOffset+(i*moveBlockSize), srcOffset+(i*moveBlockSize), moveBlockSize);
}
}
static uint8_t gmmInternalSweep (void)
{
GmmAllocator *pAllocator = pGmmLocalAllocator;
GmmBlock *pBlock;
GmmBlock *pSrcBlock;
GmmBlock *pTempBlock;
GmmBlock *pTempBlockNext;
uint32_t dstAddress, srcAddress;
uint32_t srcOffset, dstOffset;
uint32_t prevEndAddress;
uint32_t moveSize, moveDistance;
uint8_t ret = 0;
uint32_t totalMoveSize = 0;
pBlock = pAllocator->pSweepHead;
srcAddress = 0;
dstAddress = 0;
prevEndAddress = 0;
pSrcBlock = pBlock;
while (pBlock != NULL)
{
if (pBlock->isPinned == 0)
{
if (pBlock->pPrev)
prevEndAddress = pBlock->pPrev->base.address + pBlock->pPrev->base.size;
else
prevEndAddress = pAllocator->startAddress;
if (pBlock->base.address > prevEndAddress)
{
dstAddress = prevEndAddress;
srcAddress = pBlock->base.address;
pSrcBlock = pBlock;
}
moveSize = pBlock->base.address + pBlock->base.size - srcAddress;
if (srcAddress > dstAddress &&
(pBlock->pNext == NULL ||
pBlock->pNext->base.address > pBlock->base.address + pBlock->base.size ||
pBlock->pNext->isPinned))
{
dstOffset = gmmAddressToOffset(dstAddress, 0);
srcOffset = gmmAddressToOffset(srcAddress, 0);
totalMoveSize += moveSize;
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; i<GMM_NUM_FREE_BINS; i++)
{
pBlock = pAllocator->pFreeHead[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<int SIZE> 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<SIZE;j++)
{
*fp = cellGcmSwap16Float32(*src);
fp++;src++;
}
}
}
template<int SIZE> 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<SIZE>( program->header.instructionCount*16, program->loadProgramId, program->loadProgramOffset, ec, ( unsigned int * )data );
}
}
template<int SIZE> static void setVectorTypeSharedfpIndex( CgRuntimeParameter* __restrict ptr, const void* __restrict v, const int )
{
}
template<int SIZE> static void setVectorTypeSharedfpIndexArray( CgRuntimeParameter* __restrict ptr, const void* __restrict v, const int index )
{
}
template<int SIZE> 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<int SIZE> 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 <int SIZE> 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 <int SIZE> 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<int SIZE> 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<SIZE>( program->header.instructionCount*16, program->loadProgramId, program->loadProgramOffset, ec, ( unsigned int * )data );
}
}
template<int SIZE> 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<SIZE>( program->header.instructionCount*16, program->loadProgramId, program->loadProgramOffset, ec, ( unsigned int * )data );
}
}
template <int ROWS, int COLS, int ORDER> 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 <int ROWS, int COLS, int ORDER> 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 <int ROWS, int COLS, int ORDER> 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 <int ROWS, int COLS, int ORDER> static void setMatrixSharedfpIndex( CgRuntimeParameter* __restrict ptr, const void* __restrict v, const int /*index*/ )
{
}
template <int ROWS, int COLS, int ORDER> static void setMatrixSharedfpIndexArray( CgRuntimeParameter* __restrict ptr, const void* __restrict v, const int index )
{
}
template <int ROWS, int COLS, int ORDER> 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 <int ROWS, int COLS, int ORDER> 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<COLS>( program->header.instructionCount*16, program->loadProgramId, program->loadProgramOffset, ec, ( unsigned int * )dst + row * 4 );
}
ec += count + 2;
}
}
template <int ROWS, int COLS, int ORDER> 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<COLS>( 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, &parameterHeader, 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 <cell/gcm/gcm_method_data.h>
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 = &current[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<jsFramebuffer *>();
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<jsFramebuffer *>();
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 );
}
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];
snprintf( sectionName, sizeof(sectionName), ".text%04i", index );
size_t texttabSize;
const char *texttab = findSectionInPlace( elfBinary->elfFile, elfBinary->elfFileSize, sectionName, &texttabSize );
if ( !texttab )
break;
snprintf( sectionName, sizeof(sectionName), ".paramtab%04i", index );
size_t paramtabSize;
const char *paramtab = findSectionInPlace( elfBinary->elfFile, elfBinary->elfFileSize, sectionName, &paramtabSize );
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<char> stringTableArray;
STL_NAMESPACE vector<float> 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;
}
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;
strlcpy( group->name, name, sizeof(group->name));
}
else
group->name = NULL;
if ( elfConstTableSize )
memcpy(( char* )group + nvDefaultValuesTableOffset, elfBinary.consttab, elfConstTableSize );
if ( elfStringTableSize )
memcpy(( char* )group + nvStringTableOffset, elfBinary.strtab, elfStringTableSize );
_RGLCgAddGroup( ctx, group );
for ( i = 0;i < ( int )group->programCount;i++ )
{
CgProgramHeader *cgShader = ( CgProgramHeader* )elfBinary.shadertab + i;
if ( cgShader->profile == ( CGprofile )7005 )
cgShader->profile = CG_PROFILE_SCE_VP_RSX;
if ( cgShader->profile == ( CGprofile )7006 )
cgShader->profile = CG_PROFILE_SCE_FP_RSX;
CGELFProgram elfProgram;
bool res = cgGetElfProgramByIndex( &elfBinary, i, &elfProgram );
if ( !res )
return false;
CgProgramHeader *programHeader = cgShader;
char *ucode = ( char * )elfProgram.texttab;
CgParameterTableHeader *parameterHeader = ( CgParameterTableHeader * )elfProgram.paramtab;
const char *programName = getSymbolByIndexInPlace( elfBinary.symtab, elfBinary.symbolSize, elfBinary.symbolCount, elfBinary.symbolstrtab, i + 1 );
group->programs[i].name = programName;
group->programs[i].program = _RGLCgCreateProgram( ctx, ( CGprofile )cgShader->profile, programHeader, ucode, parameterHeader, ( const char* )group->stringTable, ( const float* )group->constantTable );
_CGprogram *cgProgram = _cgGetProgPtr( group->programs[i].program );
cgProgram->programGroup = group;
cgProgram->programIndexInGroup = i;
group->programs[i].refCount = 0;
}
break;
}
return group;
}
void _RGLCgDestroyProgramGroup( CGprogramGroup group )
{
_CGprogramGroup *_group = ( _CGprogramGroup * )group;
for ( int i = 0;i < ( int )_group->programCount;i++ )
{
_CGprogram *cgProgram = _cgGetProgPtr( group->programs[i].program );
cgProgram->programGroup = NULL;
cgDestroyProgram( _group->programs[i].program );
}
if(_group->filedata != NULL)
free( _group->filedata );
if ( _group->name )
free( _group->name );
_RGLCgRemoveGroup( group->ctx, group );
if(_group != NULL)
free( _group );
}
const char *_RGLCgGetProgramGroupName( CGprogramGroup group )
{
_CGprogramGroup *_group = ( _CGprogramGroup * )group;
return _group->name;
}
int _RGLCgGetProgramIndex( CGprogramGroup group, const char *name )
{
int i;
for ( i = 0;i < ( int )group->programCount;i++ )
{
if ( !strcmp( name, group->programs[i].name ) )
return i;
}
return -1;
}
CGprogram _RGLCgGetProgramAtIndex( CGprogramGroup group, unsigned int index )
{
return _RGLCgUpdateProgramAtIndex( group, index, 0 );
}
int _RGLCgGetProgramCount( CGprogramGroup group )
{
return group->programCount;
}
static const RGLcgProfileMapType RGLcgProfileMap[] =
{
{( CGprofile )6144, "CG_PROFILE_START", 1 },
{( CGprofile )6145, "unknown", 1 },
#define CG_PROFILE_MACRO(name, compiler_id, compiler_id_caps, compiler_opt,int_id,vertex_profile) \
{CG_PROFILE_ ## compiler_id_caps, compiler_opt, vertex_profile},
#include <Cg/cg_profiles.h>
{( 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 void cgGLEnableTextureParameter( CGparameter param )
{
CgRuntimeParameter* ptr = _cgGLTestTextureParameter( param );
ptr->samplerSetter( ptr, NULL, 0 );
}
static void _RGLCgContextZero( _CGcontext* p )
{
memset( p, 0, sizeof( *p ) );
p->compileType = CG_UNKNOWN;
}
static void _RGLCgContextPushFront( _CGcontext* ctx )
{
if ( _CurrentContext->RGLcgContextHead )
{
_CGcontext* head = _cgGetContextPtr( _CurrentContext->RGLcgContextHead );
ctx->next = head;
}
_CurrentContext->RGLcgContextHead = ctx->id;
}
static void destroy_context( _CGcontext*ctx )
{
if ( _cgContextDestroyHook ) _cgContextDestroyHook( ctx );
_RGLEraseName( &_CurrentContext->cgContextNameSpace, ( jsName )ctx->id );
_RGLCgContextZero( ctx );
free( ctx );
}
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];
}