mirror of
https://github.com/CTCaer/RetroArch.git
synced 2024-12-22 10:49:02 +00:00
1333 lines
44 KiB
C++
1333 lines
44 KiB
C++
|
#include <stdio.h>
|
||
|
#include "rgl.h"
|
||
|
#include "private.h"
|
||
|
#include <string.h>
|
||
|
#include <sdk_version.h>
|
||
|
#include <cell/gcm.h>
|
||
|
#include <cell/resc.h>
|
||
|
#include <sysutil/sysutil_sysparam.h>
|
||
|
#include <sys/synchronization.h>
|
||
|
|
||
|
using namespace cell::Gcm;
|
||
|
|
||
|
#define _RGL_MAX_TILED_REGIONS 15
|
||
|
|
||
|
#define _RGL_TILED_BUFFER_ALIGNMENT 0x10000
|
||
|
#define _RGL_TILED_BUFFER_HEIGHT_ALIGNMENT 64
|
||
|
|
||
|
#define _RGL_FIFO_SIZE (65536)
|
||
|
#define _RGL_DMA_PUSH_BUFFER_PREFETCH_PADDING 0x1000
|
||
|
#define RGL_UTIL_LABEL_INDEX 253
|
||
|
|
||
|
extern void _RGLFifoGlSetRenderTarget( RGLRenderTargetEx const * const args );
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
int id;
|
||
|
GLuint offset;
|
||
|
GLuint size;
|
||
|
GLuint pitch;
|
||
|
GLuint bank;
|
||
|
} jsTiledRegion;
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
jsTiledRegion region[_RGL_MAX_TILED_REGIONS];
|
||
|
} jsTiledMemoryManager;
|
||
|
|
||
|
PSGLdevice *_CurrentDevice = NULL;
|
||
|
|
||
|
static GLboolean _RGLDuringDestroyDevice = GL_FALSE;
|
||
|
static jsTiledMemoryManager _RGLTiledMemoryManager;
|
||
|
static RGLResource _RGLResource;
|
||
|
static sys_semaphore_t FlipSem;
|
||
|
static volatile uint32_t *labelAddress = NULL;
|
||
|
static const uint32_t WaitLabelIndex = 111;
|
||
|
extern GLuint nvFenceCounter;
|
||
|
RGLState _RGLState;
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
int width;
|
||
|
int height;
|
||
|
unsigned char hwMode;
|
||
|
} VideoMode;
|
||
|
|
||
|
static const VideoMode sysutilModes[] =
|
||
|
{
|
||
|
{720, 480, CELL_VIDEO_OUT_RESOLUTION_480},
|
||
|
{720, 576, CELL_VIDEO_OUT_RESOLUTION_576},
|
||
|
{1280, 720, CELL_VIDEO_OUT_RESOLUTION_720},
|
||
|
{960, 1080, CELL_VIDEO_OUT_RESOLUTION_960x1080},
|
||
|
{1280, 1080, CELL_VIDEO_OUT_RESOLUTION_1280x1080},
|
||
|
{1440, 1080, CELL_VIDEO_OUT_RESOLUTION_1440x1080},
|
||
|
{1600, 1080, CELL_VIDEO_OUT_RESOLUTION_1600x1080},
|
||
|
{1920, 1080, CELL_VIDEO_OUT_RESOLUTION_1080},
|
||
|
};
|
||
|
|
||
|
static unsigned int validPitch[] =
|
||
|
{
|
||
|
0x0200,
|
||
|
0x0300,
|
||
|
0x0400,
|
||
|
0x0500,
|
||
|
0x0600,
|
||
|
0x0700,
|
||
|
0x0800,
|
||
|
0x0A00,
|
||
|
0x0C00,
|
||
|
0x0D00,
|
||
|
0x0E00,
|
||
|
0x1000,
|
||
|
0x1400,
|
||
|
0x1800,
|
||
|
0x1A00,
|
||
|
0x1C00,
|
||
|
0x2000,
|
||
|
0x2800,
|
||
|
0x3000,
|
||
|
0x3400,
|
||
|
0x3800,
|
||
|
0x4000,
|
||
|
0x5000,
|
||
|
0x6000,
|
||
|
0x6800,
|
||
|
0x7000,
|
||
|
0x8000,
|
||
|
0xA000,
|
||
|
0xC000,
|
||
|
0xD000,
|
||
|
0xE000,
|
||
|
0x10000,
|
||
|
};
|
||
|
|
||
|
static const unsigned int validPitchCount = sizeof( validPitch ) / sizeof( validPitch[0] );
|
||
|
|
||
|
static const int sysutilModeCount = sizeof( sysutilModes ) / sizeof( sysutilModes[0] );
|
||
|
|
||
|
static inline void _RGLPrintIt( unsigned int v )
|
||
|
{
|
||
|
printf( "%02x %02x %02x %02x : ", ( v >> 24 )&0xff, ( v >> 16 )&0xff, ( v >> 8 )&0xff, v&0xff );
|
||
|
|
||
|
for ( unsigned int mask = ( 0x1 << 31 ), i = 1; mask != 0; mask >>= 1, i++ )
|
||
|
printf( "%d%s", ( v & mask ) ? 1 : 0, ( i % 8 == 0 ) ? " " : "" );
|
||
|
printf( "\n" );
|
||
|
}
|
||
|
|
||
|
static inline void _RGLPrintFifoFromPut( unsigned int numWords )
|
||
|
{
|
||
|
for ( int i = -numWords; i <= -1; i++ )
|
||
|
_RGLPrintIt((( uint32_t* )_RGLState.fifo.current )[i] );
|
||
|
}
|
||
|
|
||
|
static inline void _RGLPrintFifoFromGet( unsigned int numWords )
|
||
|
{
|
||
|
for ( int i = -numWords; i <= -1; i++ )
|
||
|
_RGLPrintIt((( uint32_t* )_RGLState.fifo.lastGetRead )[i] );
|
||
|
}
|
||
|
|
||
|
static GLuint _RGLFifoReadReference( RGLFifo *fifo )
|
||
|
{
|
||
|
GLuint ref = *(( volatile GLuint * ) & fifo->dmaControl->Reference );
|
||
|
fifo->lastHWReferenceRead = ref;
|
||
|
return ref;
|
||
|
}
|
||
|
|
||
|
static GLboolean _RGLFifoReferenceInUse( RGLFifo *fifo, GLuint reference )
|
||
|
{
|
||
|
if ( !(( fifo->lastHWReferenceRead - reference ) & 0x80000000 ) )
|
||
|
return GL_FALSE;
|
||
|
|
||
|
if (( fifo->lastSWReferenceFlushed - reference ) & 0x80000000 )
|
||
|
{
|
||
|
_RGLFifoFlush( fifo );
|
||
|
}
|
||
|
|
||
|
_RGLFifoReadReference( fifo );
|
||
|
|
||
|
if ( !(( fifo->lastHWReferenceRead - reference ) & 0x80000000 ) )
|
||
|
return GL_FALSE;
|
||
|
|
||
|
return GL_TRUE;
|
||
|
}
|
||
|
|
||
|
static GLuint _RGLFifoPutReference( RGLFifo *fifo )
|
||
|
{
|
||
|
fifo->lastSWReferenceWritten++;
|
||
|
|
||
|
cellGcmSetReferenceCommandInline ( &_RGLState.fifo, fifo->lastSWReferenceWritten );
|
||
|
|
||
|
if (( fifo->lastSWReferenceWritten & 0x7fffffff ) == 0 )
|
||
|
{
|
||
|
_RGLFifoFinish( fifo );
|
||
|
}
|
||
|
|
||
|
return fifo->lastSWReferenceWritten;
|
||
|
}
|
||
|
|
||
|
void _RGLFifoFinish( RGLFifo *fifo )
|
||
|
{
|
||
|
GLuint ref = _RGLFifoPutReference( fifo );
|
||
|
|
||
|
_RGLFifoFlush( fifo );
|
||
|
|
||
|
for ( ;; )
|
||
|
{
|
||
|
if ( !_RGLFifoReferenceInUse( fifo, ref ) )
|
||
|
break;
|
||
|
|
||
|
sys_timer_usleep( 10 );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void _RGLFifoInit( RGLFifo *fifo, void *dmaControl, unsigned long dmaPushBufferOffset, uint32_t *dmaPushBuffer, GLuint dmaPushBufferSize )
|
||
|
{
|
||
|
fifo->fifoBlockSize = DEFAULT_FIFO_BLOCK_SIZE;
|
||
|
fifo->begin = ( uint32_t * ) dmaPushBuffer;
|
||
|
fifo->end = fifo->begin + ( fifo->fifoBlockSize / sizeof( uint32_t ) ) - 1;
|
||
|
fifo->current = fifo->begin;
|
||
|
fifo->lastGetRead = fifo->current;
|
||
|
fifo->lastPutWritten = fifo->current;
|
||
|
|
||
|
fifo->dmaPushBufferBegin = dmaPushBuffer;
|
||
|
fifo->dmaPushBufferEnd = ( uint32_t * )(( size_t )dmaPushBuffer + dmaPushBufferSize ) - 1;
|
||
|
fifo->dmaControl = ( RGLControlDma* )dmaControl;
|
||
|
fifo->dmaPushBufferOffset = dmaPushBufferOffset;
|
||
|
fifo->dmaPushBufferSizeInWords = dmaPushBufferSize / sizeof( uint32_t );
|
||
|
|
||
|
fifo->lastHWReferenceRead = 0;
|
||
|
fifo->lastSWReferenceWritten = 0;
|
||
|
fifo->lastSWReferenceFlushed = 0;
|
||
|
|
||
|
gCellGcmCurrentContext = fifo;
|
||
|
gCellGcmCurrentContext->callback = ( CellGcmContextCallback )_RGLOutOfSpaceCallback;
|
||
|
|
||
|
if ( _RGLFifoReadReference( fifo ) != 0 )
|
||
|
{
|
||
|
cellGcmSetReferenceCommandInline ( &_RGLState.fifo, 0);
|
||
|
_RGLFifoFlush( fifo );
|
||
|
|
||
|
for ( ;; )
|
||
|
{
|
||
|
if ( _RGLFifoReadReference( fifo ) == 0 )
|
||
|
break;
|
||
|
sys_timer_usleep( 10 );
|
||
|
}
|
||
|
}
|
||
|
fifo->dmaPushBufferGPU = dmaPushBuffer;
|
||
|
fifo->spuid = 0;
|
||
|
}
|
||
|
|
||
|
static GLboolean _RGLInitFromRM( RGLResource *rmResource )
|
||
|
{
|
||
|
RGLState *RGLSt = &_RGLState;
|
||
|
RGLInterpolantState *s = &_RGLState.state.interpolant;
|
||
|
RGLBlendState *blend = &_RGLState.state.blend;
|
||
|
GLfloat ref;
|
||
|
GLuint i, hwColor;
|
||
|
|
||
|
ref = 0.0f;
|
||
|
|
||
|
memset( RGLSt, 0, sizeof( *RGLSt ) );
|
||
|
|
||
|
RGLSt->localAddress = rmResource->localAddress;
|
||
|
RGLSt->hostMemoryBase = rmResource->hostMemoryBase;
|
||
|
RGLSt->hostMemorySize = rmResource->hostMemorySize;
|
||
|
|
||
|
RGLSt->semaphores = rmResource->semaphores;
|
||
|
|
||
|
_RGLFifoInit( &RGLSt->fifo, rmResource->dmaControl, rmResource->dmaPushBufferOffset, ( uint32_t * )rmResource->dmaPushBuffer, rmResource->dmaPushBufferSize );
|
||
|
|
||
|
_RGLFifoFinish( &RGLSt->fifo );
|
||
|
|
||
|
RGL_CALC_COLOR_LE_ARGB8( &hwColor, RGL_CLAMPF_01(0.0f), RGL_CLAMPF_01(0.0f), RGL_CLAMPF_01(0.0f), RGL_CLAMPF_01(0.0f) );
|
||
|
|
||
|
blend->alphaFunc = CELL_GCM_ALWAYS;
|
||
|
blend->alphaRef = ref;
|
||
|
|
||
|
ref = RGL_CLAMPF_01( ref );
|
||
|
|
||
|
cellGcmSetAlphaFuncInline( &_RGLState.fifo, CELL_GCM_ALWAYS, RGL_QUICK_FLOAT2UINT( ref * 255.0f ));
|
||
|
|
||
|
cellGcmSetBlendColorInline( &_RGLState.fifo, hwColor, hwColor);
|
||
|
cellGcmSetBlendEquationInline( &_RGLState.fifo, CELL_GCM_FUNC_ADD, CELL_GCM_FUNC_ADD );
|
||
|
cellGcmSetBlendFuncInline( &_RGLState.fifo, CELL_GCM_ONE, CELL_GCM_ZERO, CELL_GCM_ONE, CELL_GCM_ZERO );
|
||
|
cellGcmSetClearColorInline( &_RGLState.fifo, hwColor);
|
||
|
cellGcmSetAlphaTestEnableInline( &_RGLState.fifo, CELL_GCM_FALSE);
|
||
|
cellGcmSetBlendEnableInline( &_RGLState.fifo, CELL_GCM_FALSE);
|
||
|
cellGcmSetAlphaTestEnableInline( &_RGLState.fifo, CELL_GCM_FALSE);
|
||
|
cellGcmSetBlendEnableMrtInline( &_RGLState.fifo, CELL_GCM_FALSE, CELL_GCM_FALSE, CELL_GCM_FALSE);
|
||
|
cellGcmSetLogicOpEnableInline( &_RGLState.fifo, CELL_GCM_FALSE);
|
||
|
cellGcmSetCullFaceEnableInline( &_RGLState.fifo, CELL_GCM_FALSE);
|
||
|
cellGcmSetCullFaceEnableInline( &_RGLState.fifo, CELL_GCM_FALSE);
|
||
|
cellGcmSetDepthBoundsTestEnableInline( &_RGLState.fifo, CELL_GCM_FALSE);
|
||
|
cellGcmSetDepthTestEnableInline( &_RGLState.fifo, CELL_GCM_FALSE);
|
||
|
cellGcmSetPolygonOffsetFillEnableInline( &_RGLState.fifo, CELL_GCM_FALSE);
|
||
|
cellGcmSetPolygonOffsetLineEnableInline( &_RGLState.fifo, CELL_GCM_FALSE);
|
||
|
cellGcmSetRestartIndexEnableInline( &_RGLState.fifo, CELL_GCM_FALSE);
|
||
|
cellGcmSetFragmentProgramGammaEnableInline( &_RGLState.fifo, CELL_GCM_FALSE);
|
||
|
cellGcmSetScissorInline( &_RGLState.fifo, 0, 0, 4095, 4095);
|
||
|
cellGcmSetStencilTestEnableInline( &_RGLState.fifo, CELL_GCM_FALSE);
|
||
|
cellGcmSetTwoSidedStencilTestEnableInline( &_RGLState.fifo, CELL_GCM_FALSE);
|
||
|
cellGcmSetTwoSideLightEnableInline( &_RGLState.fifo, CELL_GCM_FALSE);
|
||
|
cellGcmSetVertexAttribOutputMaskInline( &_RGLState.fifo, s->vertexProgramAttribMask & s->fragmentProgramAttribMask);
|
||
|
|
||
|
cellGcmSetPointSpriteControlInline( &_RGLState.fifo, CELL_GCM_FALSE, 1, 0);
|
||
|
cellGcmSetFrequencyDividerOperationInline( &_RGLState.fifo, 0);
|
||
|
|
||
|
cellGcmSetDitherEnableInline( &_RGLState.fifo, CELL_GCM_TRUE);
|
||
|
cellGcmSetRestartIndexInline( &_RGLState.fifo, 0);
|
||
|
cellGcmSetShadeModeInline( &_RGLState.fifo, CELL_GCM_SMOOTH);
|
||
|
|
||
|
for ( i = 0; i < CELL_GCM_MAX_TEXIMAGE_COUNT; i++ )
|
||
|
{
|
||
|
cellGcmSetTextureAddressInline( &_RGLState.fifo, i, CELL_GCM_TEXTURE_WRAP, CELL_GCM_TEXTURE_WRAP, CELL_GCM_TEXTURE_CLAMP_TO_EDGE, CELL_GCM_TEXTURE_UNSIGNED_REMAP_NORMAL, CELL_GCM_TEXTURE_ZFUNC_NEVER, 0 );
|
||
|
cellGcmSetTextureFilterInline( &_RGLState.fifo, i, 0, CELL_GCM_TEXTURE_NEAREST_LINEAR, CELL_GCM_TEXTURE_LINEAR, CELL_GCM_TEXTURE_CONVOLUTION_QUINCUNX );
|
||
|
cellGcmSetTextureControlInline( &_RGLState.fifo, i, CELL_GCM_TRUE, 0, 12 << 8, CELL_GCM_TEXTURE_MAX_ANISO_1 );
|
||
|
}
|
||
|
|
||
|
_RGLFifoGlViewport( 0, 0, CELL_GCM_MAX_RT_DIMENSION, CELL_GCM_MAX_RT_DIMENSION, 0.0f, 1.0f );
|
||
|
|
||
|
_RGLFifoFinish( &RGLSt->fifo );
|
||
|
|
||
|
return GL_TRUE;
|
||
|
}
|
||
|
|
||
|
GLboolean _RGLInit( PSGLinitOptions* options, RGLResource *resource )
|
||
|
{
|
||
|
if ( !_RGLInitFromRM( resource ) )
|
||
|
{
|
||
|
fprintf( stderr, "PSGL GCM failed initialisation" );
|
||
|
return GL_FALSE;
|
||
|
}
|
||
|
|
||
|
if ( gmmInit( resource->localAddress,
|
||
|
resource->localAddress,
|
||
|
resource->localSize,
|
||
|
resource->hostMemoryBase,
|
||
|
resource->hostMemoryBase + resource->hostMemoryReserved,
|
||
|
resource->hostMemorySize - resource->hostMemoryReserved ) == GMM_ERROR )
|
||
|
{
|
||
|
fprintf( stderr, "Could not init GPU memory manager" );
|
||
|
_RGLDestroy();
|
||
|
return GL_FALSE;
|
||
|
}
|
||
|
|
||
|
_RGLState.semaphores->userSemaphores[_RGL_SEMA_FENCE].val = nvFenceCounter;
|
||
|
|
||
|
_RGLState.labelValue = 1;
|
||
|
|
||
|
return GL_TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
void _RGLDestroy( void )
|
||
|
{
|
||
|
RGLState *RGLSt = &_RGLState;
|
||
|
memset( RGLSt, 0, sizeof( *RGLSt ) );
|
||
|
}
|
||
|
|
||
|
static inline int rescIsEnabled( PSGLdeviceParameters* params )
|
||
|
{
|
||
|
return params->enable & ( PSGL_DEVICE_PARAMETERS_RESC_RENDER_WIDTH_HEIGHT |
|
||
|
PSGL_DEVICE_PARAMETERS_RESC_RATIO_MODE |
|
||
|
PSGL_DEVICE_PARAMETERS_RESC_PAL_TEMPORAL_MODE |
|
||
|
PSGL_DEVICE_PARAMETERS_RESC_INTERLACE_MODE |
|
||
|
PSGL_DEVICE_PARAMETERS_RESC_ADJUST_ASPECT_RATIO );
|
||
|
}
|
||
|
|
||
|
static inline const VideoMode *findModeByResolution( int width, int height )
|
||
|
{
|
||
|
for ( int i = 0;i < sysutilModeCount;++i )
|
||
|
{
|
||
|
const VideoMode *vm = sysutilModes + i;
|
||
|
if (( vm->width == width ) && ( vm->height == height ) ) return vm;
|
||
|
}
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
static const VideoMode *findModeByEnum( GLenum TVStandard )
|
||
|
{
|
||
|
const VideoMode *vm = NULL;
|
||
|
switch ( TVStandard )
|
||
|
{
|
||
|
case PSGL_TV_STANDARD_NTSC_M:
|
||
|
case PSGL_TV_STANDARD_NTSC_J:
|
||
|
case PSGL_TV_STANDARD_HD480P:
|
||
|
case PSGL_TV_STANDARD_HD480I:
|
||
|
vm = &(sysutilModes[0]);
|
||
|
break;
|
||
|
case PSGL_TV_STANDARD_PAL_M:
|
||
|
case PSGL_TV_STANDARD_PAL_B:
|
||
|
case PSGL_TV_STANDARD_PAL_D:
|
||
|
case PSGL_TV_STANDARD_PAL_G:
|
||
|
case PSGL_TV_STANDARD_PAL_H:
|
||
|
case PSGL_TV_STANDARD_PAL_I:
|
||
|
case PSGL_TV_STANDARD_PAL_N:
|
||
|
case PSGL_TV_STANDARD_PAL_NC:
|
||
|
case PSGL_TV_STANDARD_HD576I:
|
||
|
case PSGL_TV_STANDARD_HD576P:
|
||
|
vm = &(sysutilModes[1]);
|
||
|
break;
|
||
|
case PSGL_TV_STANDARD_HD720P:
|
||
|
case PSGL_TV_STANDARD_1280x720_ON_VESA_1280x768:
|
||
|
case PSGL_TV_STANDARD_1280x720_ON_VESA_1280x1024:
|
||
|
vm = &(sysutilModes[2]);
|
||
|
break;
|
||
|
case PSGL_TV_STANDARD_HD1080I:
|
||
|
case PSGL_TV_STANDARD_HD1080P:
|
||
|
case PSGL_TV_STANDARD_1920x1080_ON_VESA_1920x1200:
|
||
|
vm = &(sysutilModes[3]);
|
||
|
break;
|
||
|
default:
|
||
|
vm = &(sysutilModes[2]);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return vm;
|
||
|
}
|
||
|
|
||
|
static VideoMode _sysutilDetectedVideoMode;
|
||
|
|
||
|
const VideoMode *_RGLDetectVideoMode (void)
|
||
|
{
|
||
|
CellVideoOutState videoState;
|
||
|
int ret = cellVideoOutGetState( CELL_VIDEO_OUT_PRIMARY, 0, &videoState );
|
||
|
if ( ret < 0 )
|
||
|
{
|
||
|
printf("RGL WARN: couldn't read the video configuration, using a default 720p resolution.\n");
|
||
|
videoState.displayMode.scanMode = CELL_VIDEO_OUT_SCAN_MODE_PROGRESSIVE;
|
||
|
videoState.displayMode.resolutionId = CELL_VIDEO_OUT_RESOLUTION_720;
|
||
|
}
|
||
|
CellVideoOutResolution resolution;
|
||
|
cellVideoOutGetResolution( videoState.displayMode.resolutionId, &resolution );
|
||
|
|
||
|
_sysutilDetectedVideoMode.width = resolution.width;
|
||
|
_sysutilDetectedVideoMode.height = resolution.height;
|
||
|
_sysutilDetectedVideoMode.hwMode = videoState.displayMode.resolutionId;
|
||
|
return &_sysutilDetectedVideoMode;
|
||
|
}
|
||
|
|
||
|
static void _RGLFlipCallbackFunction(const uint32_t head)
|
||
|
{
|
||
|
int res = sys_semaphore_post(FlipSem,1);
|
||
|
(void)res;
|
||
|
}
|
||
|
|
||
|
static void _RGLVblankCallbackFunction(const uint32_t head)
|
||
|
{
|
||
|
(void)head;
|
||
|
int status = *labelAddress;
|
||
|
|
||
|
switch(status)
|
||
|
{
|
||
|
case 2:
|
||
|
if (cellGcmGetFlipStatus()==0)
|
||
|
{
|
||
|
cellGcmResetFlipStatus();
|
||
|
*labelAddress=1;
|
||
|
}
|
||
|
break;
|
||
|
case 1:
|
||
|
*labelAddress = 0;
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void _RGLRescVblankCallbackFunction(const uint32_t head)
|
||
|
{
|
||
|
(void)head;
|
||
|
int status = *labelAddress;
|
||
|
switch(status)
|
||
|
{
|
||
|
case 2:
|
||
|
if (cellRescGetFlipStatus()==0)
|
||
|
{
|
||
|
cellRescResetFlipStatus();
|
||
|
*labelAddress=1;
|
||
|
}
|
||
|
break;
|
||
|
case 1:
|
||
|
*labelAddress = 0;
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static unsigned int findValidPitch( unsigned int pitch )
|
||
|
{
|
||
|
if ( pitch <= validPitch[0] ) return validPitch[0];
|
||
|
else
|
||
|
{
|
||
|
for ( GLuint i = 0;i < validPitchCount - 1;++i )
|
||
|
{
|
||
|
if (( pitch > validPitch[i] ) && ( pitch <= validPitch[i+1] ) ) return validPitch[i+1];
|
||
|
}
|
||
|
return validPitch[validPitchCount-1];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int32_t _RGLOutOfSpaceCallback( struct CellGcmContextData* fifoContext, uint32_t spaceInWords )
|
||
|
{
|
||
|
uint32_t *nextbegin, *nextend, nextbeginoffset, nextendoffset;
|
||
|
RGLFifo * fifo = &_RGLState.fifo;
|
||
|
|
||
|
cellGcmFlushUnsafeInline((CellGcmContextData*)fifo);
|
||
|
|
||
|
uint32_t * tmp = ( uint32_t * )(( char* )fifo->dmaPushBufferBegin - fifo->dmaPushBufferOffset + ( *(( volatile GLuint* ) & fifo->dmaControl->Get ) ) );
|
||
|
if (( tmp >= fifo->begin ) && ( tmp <= fifo->end ) ) fifo->lastGetRead = tmp;
|
||
|
|
||
|
if(fifo->end != fifo->dmaPushBufferEnd)
|
||
|
{
|
||
|
nextbegin = (uint32_t *)fifo->end + 1;
|
||
|
nextend = nextbegin + fifo->fifoBlockSize/sizeof(uint32_t) - 1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
nextbegin = (uint32_t *)fifo->dmaPushBufferBegin;
|
||
|
nextend = nextbegin + (fifo->fifoBlockSize)/sizeof(uint32_t) - 1;
|
||
|
}
|
||
|
|
||
|
cellGcmAddressToOffset(nextbegin, &nextbeginoffset);
|
||
|
cellGcmAddressToOffset(nextend, &nextendoffset);
|
||
|
|
||
|
cellGcmSetJumpCommandUnsafeInline((CellGcmContextData*)fifo, nextbeginoffset);
|
||
|
|
||
|
fifo->begin = nextbegin;
|
||
|
fifo->current = nextbegin;
|
||
|
fifo->end = nextend;
|
||
|
|
||
|
const GLuint nopsAtBegin = 8;
|
||
|
|
||
|
uint32_t get = fifo->dmaControl->Get;
|
||
|
|
||
|
while(((get >= nextbeginoffset) && (get <= nextendoffset))
|
||
|
|| (get < fifo->dmaPushBufferOffset) || (get > fifo->dmaPushBufferOffset +
|
||
|
fifo->dmaPushBufferSizeInWords*sizeof(uint32_t)))
|
||
|
{
|
||
|
sys_timer_usleep(30);
|
||
|
get = fifo->dmaControl->Get;
|
||
|
}
|
||
|
|
||
|
for ( GLuint i = 0; i < nopsAtBegin; i++ )
|
||
|
{
|
||
|
fifo->current[0] = RGL_NOP;
|
||
|
fifo->current++;
|
||
|
}
|
||
|
|
||
|
return CELL_OK;
|
||
|
};
|
||
|
|
||
|
void _RGLGraphicsHandler( const uint32_t head )
|
||
|
{
|
||
|
RGLFifo *fifo = &_RGLState.fifo;
|
||
|
|
||
|
uint32_t *tmp = ( uint32_t * )(( char* )fifo->dmaPushBufferBegin - fifo->dmaPushBufferOffset + ( *(( volatile GLuint* ) & fifo->dmaControl->Get ) ) );
|
||
|
if (( tmp >= fifo->begin ) && ( tmp <= fifo->end ) ) fifo->lastGetRead = tmp;
|
||
|
|
||
|
printf("RGL: Current PSGL FIFO info \n" );
|
||
|
printf("RGL: Fifo Begin %p End %p Current %p and Get %p \n",
|
||
|
_RGLState.fifo.begin, _RGLState.fifo.end, _RGLState.fifo.current,
|
||
|
_RGLState.fifo.lastGetRead );
|
||
|
|
||
|
printf("RGL: Last 10 words of the PSGL Fifo from the ppu put/current position \n" );
|
||
|
_RGLPrintFifoFromPut( 10 );
|
||
|
|
||
|
printf("RGL: Last 10 words of the PSGL Fifo from the gpu get position \n" );
|
||
|
_RGLPrintFifoFromGet( 10 );
|
||
|
}
|
||
|
|
||
|
static int _RGLInitRM( RGLResource *gcmResource, unsigned int hostMemorySize, int inSysMem, unsigned int dmaPushBufferSize )
|
||
|
{
|
||
|
memset( gcmResource, 0, sizeof( RGLResource ) );
|
||
|
|
||
|
const unsigned int iDPM2DataAreaSize = 0;
|
||
|
|
||
|
dmaPushBufferSize = _RGLPad( dmaPushBufferSize, _RGL_HOST_BUFFER_ALIGNMENT );
|
||
|
|
||
|
gcmResource->hostMemorySize = _RGLPad( _RGL_FIFO_SIZE + hostMemorySize + dmaPushBufferSize + _RGL_DMA_PUSH_BUFFER_PREFETCH_PADDING + iDPM2DataAreaSize + (RGL_LM_MAX_TOTAL_QUERIES * sizeof( GLuint )), 1 << 20 );
|
||
|
|
||
|
if ( gcmResource->hostMemorySize > 0 )
|
||
|
gcmResource->hostMemoryBase = ( char * )memalign( 1 << 20, gcmResource->hostMemorySize );
|
||
|
|
||
|
if ( cellGcmInit( _RGL_FIFO_SIZE, gcmResource->hostMemorySize, gcmResource->hostMemoryBase ) != 0 )
|
||
|
{
|
||
|
printf("RGL: RSXIF failed initialization\n" );
|
||
|
return GL_FALSE;
|
||
|
}
|
||
|
|
||
|
cellGcmSetDebugOutputLevel( CELL_GCM_DEBUG_LEVEL2 );
|
||
|
cellGcmSetGraphicsHandler( &_RGLGraphicsHandler );
|
||
|
|
||
|
CellGcmConfig config;
|
||
|
cellGcmGetConfiguration( &config );
|
||
|
|
||
|
gcmResource->localAddress = ( char * )config.localAddress;
|
||
|
gcmResource->localSize = config.localSize;
|
||
|
gcmResource->MemoryClock = config.memoryFrequency;
|
||
|
gcmResource->GraphicsClock = config.coreFrequency;
|
||
|
|
||
|
gcmResource->semaphores = ( RGLSemaphoreMemory * )cellGcmGetLabelAddress( 0 );
|
||
|
gcmResource->dmaControl = ( char* ) cellGcmGetControlRegister() - (( char * ) & (( RGLControlDma* )0 )->Put - ( char * )0 );
|
||
|
|
||
|
cellGcmFinish( 1 );
|
||
|
|
||
|
gcmResource->hostMemorySize -= dmaPushBufferSize + _RGL_DMA_PUSH_BUFFER_PREFETCH_PADDING;
|
||
|
gcmResource->dmaPushBuffer = gcmResource->hostMemoryBase + gcmResource->hostMemorySize;
|
||
|
gcmResource->dmaPushBufferOffset = ( char * )gcmResource->dmaPushBuffer - ( char * )gcmResource->hostMemoryBase;
|
||
|
gcmResource->dmaPushBufferSize = dmaPushBufferSize;
|
||
|
gcmResource->hostMemoryReserved = _RGL_FIFO_SIZE;
|
||
|
|
||
|
cellGcmSetJumpCommand(( char * )gcmResource->dmaPushBuffer - ( char * )gcmResource->hostMemoryBase );
|
||
|
|
||
|
gCellGcmCurrentContext->callback = ( CellGcmContextCallback )_RGLOutOfSpaceCallback;
|
||
|
|
||
|
|
||
|
printf( "RGL: MClk: %f Mhz NVClk: %f Mhz\n", ( float )gcmResource->MemoryClock / 1E6, ( float )gcmResource->GraphicsClock / 1E6 );
|
||
|
printf( "RGL: Video Memory: %i MB\n", gcmResource->localSize / ( 1024*1024 ) );
|
||
|
printf( "RGL: localAddress mapped at %p\n", gcmResource->localAddress );
|
||
|
printf( "RGL: push buffer at %p - %p (size = 0x%X), offset=0x%lx\n",
|
||
|
gcmResource->dmaPushBuffer, ( char* )gcmResource->dmaPushBuffer + gcmResource->dmaPushBufferSize, gcmResource->dmaPushBufferSize, gcmResource->dmaPushBufferOffset );
|
||
|
printf( "RGL: dma control at %p\n", gcmResource->dmaControl );
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
void _RGLDeviceInit( PSGLinitOptions* options )
|
||
|
{
|
||
|
GLuint fifoSize = _RGL_FIFO_SIZE_DEFAULT;
|
||
|
GLuint hostSize = _RGL_HOST_SIZE_DEFAULT;
|
||
|
|
||
|
if ( options != NULL )
|
||
|
{
|
||
|
if ( options->enable & PSGL_INIT_FIFO_SIZE )
|
||
|
fifoSize = options->fifoSize;
|
||
|
if ( options->enable & PSGL_INIT_HOST_MEMORY_SIZE )
|
||
|
hostSize = options->hostMemorySize;
|
||
|
}
|
||
|
|
||
|
if ( !_RGLInitRM( &_RGLResource, hostSize, 0, fifoSize ) )
|
||
|
{
|
||
|
printf("RGL: RM resource failed initialisation\n" );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
bool retval = _RGLInit( options, &_RGLResource );
|
||
|
(void)retval;
|
||
|
}
|
||
|
|
||
|
static void _RGLDestroyRM( RGLResource* gcmResource )
|
||
|
{
|
||
|
if ( gcmResource->hostMemoryBase )
|
||
|
free( gcmResource->hostMemoryBase );
|
||
|
|
||
|
memset(( void* )gcmResource, 0, sizeof( RGLResource ) );
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
void _RGLDeviceExit()
|
||
|
{
|
||
|
_RGLDestroy();
|
||
|
_RGLDestroyRM( &_RGLResource );
|
||
|
}
|
||
|
|
||
|
static GLuint _RGLAllocCreateRegion(GLuint size, GLint tag, void* data )
|
||
|
{
|
||
|
uint32_t id = gmmAlloc(1, size);
|
||
|
|
||
|
if ( id != GMM_ERROR )
|
||
|
{
|
||
|
if ( _RGLTryResizeTileRegion( (GLuint)gmmIdToOffset(id), ((GmmBaseBlock *)id)->size, data ) )
|
||
|
gmmSetTileAttrib( id, tag, data );
|
||
|
else
|
||
|
{
|
||
|
gmmFree( id );
|
||
|
id = GMM_ERROR;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return id;
|
||
|
}
|
||
|
|
||
|
GLboolean _RGLAllocateColorSurface(
|
||
|
GLuint width,
|
||
|
GLuint height,
|
||
|
GLuint bitsPerPixel,
|
||
|
GLuint *id,
|
||
|
GLuint *pitchAllocated,
|
||
|
GLuint *bytesAllocated )
|
||
|
{
|
||
|
jsTiledMemoryManager* mm = &_RGLTiledMemoryManager;
|
||
|
|
||
|
const unsigned int pitch = width * bitsPerPixel / 8;
|
||
|
const unsigned int tiledPitch = findValidPitch( pitch );
|
||
|
if ( tiledPitch < pitch )
|
||
|
*pitchAllocated = _RGLPad( pitch, tiledPitch );
|
||
|
else
|
||
|
*pitchAllocated = tiledPitch;
|
||
|
|
||
|
GLuint padSize = _RGL_TILED_BUFFER_ALIGNMENT;
|
||
|
while (( padSize % ( tiledPitch*8 ) ) != 0 )
|
||
|
padSize += _RGL_TILED_BUFFER_ALIGNMENT;
|
||
|
|
||
|
height = _RGLPad( height, _RGL_TILED_BUFFER_HEIGHT_ALIGNMENT );
|
||
|
*bytesAllocated = _RGLPad(( *pitchAllocated ) * height, padSize );
|
||
|
|
||
|
const GLuint tag = *pitchAllocated | ( 0x0 );
|
||
|
|
||
|
*id = gmmAllocExtendedTileBlock(*bytesAllocated, tag);
|
||
|
|
||
|
if ( *id == GMM_ERROR )
|
||
|
{
|
||
|
for ( int i = 0; i < _RGL_MAX_TILED_REGIONS; ++i )
|
||
|
{
|
||
|
if ( mm->region[i].size == 0 )
|
||
|
{
|
||
|
mm->region[i].id = i;
|
||
|
mm->region[i].pitch = *pitchAllocated;
|
||
|
mm->region[i].bank = 0x0;
|
||
|
|
||
|
*id = _RGLAllocCreateRegion(*bytesAllocated, tag, &mm->region[i] );
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( *id == GMM_ERROR )
|
||
|
{
|
||
|
*bytesAllocated = 0;
|
||
|
*pitchAllocated = 0;
|
||
|
}
|
||
|
else
|
||
|
printf("RGL: Allocating GPU memory (tiled): %d bytes allocated at id 0x%08x.\n", *bytesAllocated, *id );
|
||
|
|
||
|
return *bytesAllocated > 0;
|
||
|
}
|
||
|
|
||
|
PSGLdevice* psglCreateDeviceAuto( GLenum colorFormat, GLenum depthFormat, GLenum multisamplingMode )
|
||
|
{
|
||
|
PSGLdeviceParameters parameters;
|
||
|
parameters.enable = PSGL_DEVICE_PARAMETERS_COLOR_FORMAT | PSGL_DEVICE_PARAMETERS_DEPTH_FORMAT | PSGL_DEVICE_PARAMETERS_MULTISAMPLING_MODE;
|
||
|
parameters.colorFormat = colorFormat;
|
||
|
parameters.depthFormat = GL_NONE;
|
||
|
parameters.multisamplingMode = GL_MULTISAMPLING_NONE_SCE;
|
||
|
return psglCreateDeviceExtended( ¶meters );
|
||
|
}
|
||
|
|
||
|
static void rescInit( const PSGLdeviceParameters* params, RGLDevice *gcmDevice )
|
||
|
{
|
||
|
printf("RGL WARN: RESC is enabled.\n");
|
||
|
GLboolean result = 0;
|
||
|
|
||
|
CellRescBufferMode dstBufferMode;
|
||
|
if ( params->width == 720 && params->height == 480 ) dstBufferMode = CELL_RESC_720x480;
|
||
|
else if ( params->width == 720 && params->height == 576 ) dstBufferMode = CELL_RESC_720x576;
|
||
|
else if ( params->width == 1280 && params->height == 720 ) dstBufferMode = CELL_RESC_1280x720;
|
||
|
else if ( params->width == 1920 && params->height == 1080 ) dstBufferMode = CELL_RESC_1920x1080;
|
||
|
else
|
||
|
{
|
||
|
dstBufferMode = CELL_RESC_720x480;
|
||
|
printf("RGL: Invalid display resolution for resolution conversion: %ux%u. Defaulting to 720x480...\n", params->width, params->height );
|
||
|
}
|
||
|
|
||
|
CellRescInitConfig conf;
|
||
|
memset( &conf, 0, sizeof( CellRescInitConfig ) );
|
||
|
conf.size = sizeof( CellRescInitConfig );
|
||
|
conf.resourcePolicy = CELL_RESC_MINIMUM_GPU_LOAD | CELL_RESC_CONSTANT_VRAM;
|
||
|
conf.supportModes = CELL_RESC_720x480 | CELL_RESC_720x576 | CELL_RESC_1280x720 | CELL_RESC_1920x1080;
|
||
|
conf.ratioMode = ( params->rescRatioMode == RESC_RATIO_MODE_FULLSCREEN ) ? CELL_RESC_FULLSCREEN :
|
||
|
( params->rescRatioMode == RESC_RATIO_MODE_PANSCAN ) ? CELL_RESC_PANSCAN : CELL_RESC_LETTERBOX;
|
||
|
conf.palTemporalMode = ( params->rescPalTemporalMode == RESC_PAL_TEMPORAL_MODE_60_DROP ) ? CELL_RESC_PAL_60_DROP :
|
||
|
( params->rescPalTemporalMode == RESC_PAL_TEMPORAL_MODE_60_INTERPOLATE ) ? CELL_RESC_PAL_60_INTERPOLATE :
|
||
|
( params->rescPalTemporalMode == RESC_PAL_TEMPORAL_MODE_60_INTERPOLATE_30_DROP ) ? CELL_RESC_PAL_60_INTERPOLATE_30_DROP :
|
||
|
( params->rescPalTemporalMode == RESC_PAL_TEMPORAL_MODE_60_INTERPOLATE_DROP_FLEXIBLE ) ? CELL_RESC_PAL_60_INTERPOLATE_DROP_FLEXIBLE : CELL_RESC_PAL_50;
|
||
|
conf.interlaceMode = ( params->rescInterlaceMode == RESC_INTERLACE_MODE_INTERLACE_FILTER ) ? CELL_RESC_INTERLACE_FILTER : CELL_RESC_NORMAL_BILINEAR;
|
||
|
cellRescInit( &conf );
|
||
|
|
||
|
GLuint size;
|
||
|
GLuint colorBuffersPitch;
|
||
|
uint32_t numColorBuffers = cellRescGetNumColorBuffers( dstBufferMode, ( CellRescPalTemporalMode )conf.palTemporalMode, 0 );
|
||
|
|
||
|
result = _RGLAllocateColorSurface( params->width, params->height * numColorBuffers,
|
||
|
4*8, &(gcmDevice->RescColorBuffersId), &colorBuffersPitch, &size );
|
||
|
|
||
|
CellRescDsts dsts = { CELL_RESC_SURFACE_A8R8G8B8, colorBuffersPitch, 1 };
|
||
|
cellRescSetDsts( dstBufferMode, &dsts );
|
||
|
|
||
|
cellRescSetDisplayMode( dstBufferMode );
|
||
|
|
||
|
int32_t colorBuffersSize, vertexArraySize, fragmentShaderSize;
|
||
|
cellRescGetBufferSize( &colorBuffersSize, &vertexArraySize, &fragmentShaderSize );
|
||
|
gcmDevice->RescVertexArrayId = gmmAlloc(0, vertexArraySize);
|
||
|
|
||
|
gcmDevice->RescFragmentShaderId = gmmAlloc(0, fragmentShaderSize);
|
||
|
|
||
|
|
||
|
cellRescSetBufferAddress( gmmIdToAddress(gcmDevice->RescColorBuffersId),
|
||
|
gmmIdToAddress(gcmDevice->RescVertexArrayId),
|
||
|
gmmIdToAddress(gcmDevice->RescFragmentShaderId) );
|
||
|
|
||
|
cellRescAdjustAspectRatio( params->horizontalScale, params->verticalScale );
|
||
|
|
||
|
if ((params->enable & PSGL_DEVICE_PARAMETERS_RESC_INTERLACE_MODE) &&
|
||
|
(params->rescInterlaceMode == RESC_INTERLACE_MODE_INTERLACE_FILTER))
|
||
|
{
|
||
|
const unsigned int tableLength = 32;
|
||
|
unsigned int tableSize = sizeof(uint16_t) * 4 * tableLength;
|
||
|
void *interlaceTable = gmmIdToAddress(gmmAlloc(0, tableSize));
|
||
|
int32_t errorCode = cellRescCreateInterlaceTable(interlaceTable,params->renderHeight,CELL_RESC_ELEMENT_HALF,tableLength);
|
||
|
(void)errorCode;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void _RGLSetDisplayMode( const VideoMode *vm, GLushort bitsPerPixel, GLuint pitch )
|
||
|
{
|
||
|
CellVideoOutConfiguration videocfg;
|
||
|
memset( &videocfg, 0, sizeof( videocfg ) );
|
||
|
videocfg.resolutionId = vm->hwMode;
|
||
|
videocfg.format = ( bitsPerPixel == 32 ) ? CELL_VIDEO_OUT_BUFFER_COLOR_FORMAT_X8R8G8B8 : CELL_VIDEO_OUT_BUFFER_COLOR_FORMAT_R16G16B16X16_FLOAT;
|
||
|
videocfg.pitch = pitch;
|
||
|
videocfg.aspect = CELL_VIDEO_OUT_ASPECT_AUTO;
|
||
|
cellVideoOutConfigure( CELL_VIDEO_OUT_PRIMARY, &videocfg, NULL, 0 );
|
||
|
}
|
||
|
|
||
|
|
||
|
static int _RGLPlatformCreateDevice( PSGLdevice* device )
|
||
|
{
|
||
|
RGLDevice *gcmDevice = ( RGLDevice * )device->platformDevice;
|
||
|
PSGLdeviceParameters* params = &device->deviceParameters;
|
||
|
jsTiledMemoryManager* mm = &_RGLTiledMemoryManager;
|
||
|
|
||
|
_RGLDuringDestroyDevice = GL_FALSE;
|
||
|
GLboolean result = 0;
|
||
|
|
||
|
int32_t retVal;
|
||
|
|
||
|
memset( mm->region, 0, sizeof( mm->region ) );
|
||
|
for ( int i = 0;i < _RGL_MAX_TILED_REGIONS;++i )
|
||
|
retVal = cellGcmUnbindTile( i );
|
||
|
|
||
|
|
||
|
const VideoMode *vm = NULL;
|
||
|
if ( params->enable & PSGL_DEVICE_PARAMETERS_TV_STANDARD )
|
||
|
{
|
||
|
vm = findModeByEnum( params->TVStandard );
|
||
|
if ( !vm ) return -1;
|
||
|
params->width = vm->width;
|
||
|
params->height = vm->height;
|
||
|
}
|
||
|
else if ( params->enable & PSGL_DEVICE_PARAMETERS_WIDTH_HEIGHT )
|
||
|
{
|
||
|
vm = findModeByResolution( params->width, params->height );
|
||
|
if ( !vm ) return -1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
vm = _RGLDetectVideoMode();
|
||
|
if ( !vm ) return -1;
|
||
|
params->width = vm->width;
|
||
|
params->height = vm->height;
|
||
|
}
|
||
|
|
||
|
if ( !(params->enable & PSGL_DEVICE_PARAMETERS_RESC_RENDER_WIDTH_HEIGHT) )
|
||
|
{
|
||
|
params->renderWidth = params->width;
|
||
|
params->renderHeight = params->height;
|
||
|
}
|
||
|
|
||
|
if ( rescIsEnabled( params ) )
|
||
|
rescInit( params, gcmDevice );
|
||
|
|
||
|
gcmDevice->deviceType = 0;
|
||
|
gcmDevice->TVStandard = params->TVStandard;
|
||
|
|
||
|
gcmDevice->vsync = rescIsEnabled( params ) ? GL_TRUE : GL_FALSE;
|
||
|
|
||
|
gcmDevice->ms = NULL;
|
||
|
|
||
|
const GLuint width = params->renderWidth;
|
||
|
const GLuint height = params->renderHeight;
|
||
|
|
||
|
for ( int i = 0; i < params->bufferingMode; ++i )
|
||
|
{
|
||
|
gcmDevice->color[i].source = _RGL_SURFACE_SOURCE_DEVICE;
|
||
|
gcmDevice->color[i].width = width;
|
||
|
gcmDevice->color[i].height = height;
|
||
|
gcmDevice->color[i].bpp = 4;
|
||
|
gcmDevice->color[i].format = RGL_ARGB8;
|
||
|
gcmDevice->color[i].pool = _RGL_SURFACE_POOL_LINEAR;
|
||
|
|
||
|
GLuint size;
|
||
|
result = _RGLAllocateColorSurface(width, height,
|
||
|
gcmDevice->color[i].bpp*8, &gcmDevice->color[i].dataId,
|
||
|
&gcmDevice->color[i].pitch, &size );
|
||
|
}
|
||
|
|
||
|
memset( &gcmDevice->rt, 0, sizeof( RGLRenderTargetEx ) );
|
||
|
gcmDevice->rt.colorBufferCount = 1;
|
||
|
gcmDevice->rt.yInverted = GL_TRUE;
|
||
|
gcmDevice->rt.width = width;
|
||
|
gcmDevice->rt.height = height;
|
||
|
|
||
|
_RGLFifoGlViewport( 0, 0, width, height );
|
||
|
|
||
|
GLuint hwColor;
|
||
|
|
||
|
RGL_CALC_COLOR_LE_ARGB8( &hwColor, RGL_CLAMPF_01(0.0f), RGL_CLAMPF_01(0.0f), RGL_CLAMPF_01(0.0f), RGL_CLAMPF_01(0.0f) );
|
||
|
|
||
|
cellGcmSetClearColorInline( &_RGLState.fifo, hwColor);
|
||
|
|
||
|
gcmDevice->rt.colorFormat = RGL_ARGB8;
|
||
|
for ( int i = 0; i < params->bufferingMode; ++i )
|
||
|
{
|
||
|
gcmDevice->rt.colorId[0] = gcmDevice->color[i].dataId;
|
||
|
gcmDevice->rt.colorPitch[0] = gcmDevice->color[i].pitch;
|
||
|
_RGLFifoGlSetRenderTarget( &gcmDevice->rt );
|
||
|
cellGcmSetClearSurfaceInline ( &_RGLState.fifo, CELL_GCM_CLEAR_R | CELL_GCM_CLEAR_G | CELL_GCM_CLEAR_B | CELL_GCM_CLEAR_A);
|
||
|
}
|
||
|
|
||
|
gcmDevice->scanBuffer = 0;
|
||
|
if ( params->bufferingMode == PSGL_BUFFERING_MODE_SINGLE )
|
||
|
gcmDevice->drawBuffer = 0;
|
||
|
else if ( params->bufferingMode == PSGL_BUFFERING_MODE_DOUBLE )
|
||
|
gcmDevice->drawBuffer = 1;
|
||
|
else if ( params->bufferingMode == PSGL_BUFFERING_MODE_TRIPLE )
|
||
|
gcmDevice->drawBuffer = 2;
|
||
|
|
||
|
sys_semaphore_attribute_t attr;
|
||
|
sys_semaphore_attribute_initialize(attr);
|
||
|
|
||
|
sys_semaphore_value_t initial_val = 0;
|
||
|
sys_semaphore_value_t max_val = 1;
|
||
|
switch (device->deviceParameters.bufferingMode)
|
||
|
{
|
||
|
case PSGL_BUFFERING_MODE_SINGLE:
|
||
|
initial_val = 0;
|
||
|
max_val = 1;
|
||
|
break;
|
||
|
case PSGL_BUFFERING_MODE_DOUBLE:
|
||
|
initial_val = 1;
|
||
|
max_val = 2;
|
||
|
break;
|
||
|
case PSGL_BUFFERING_MODE_TRIPLE:
|
||
|
initial_val = 2;
|
||
|
max_val = 3;
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
int res = sys_semaphore_create(&FlipSem, &attr, initial_val, max_val);
|
||
|
(void)res;
|
||
|
|
||
|
if ( rescIsEnabled( params ) )
|
||
|
cellRescSetFlipHandler(_RGLFlipCallbackFunction);
|
||
|
else
|
||
|
cellGcmSetFlipHandler(_RGLFlipCallbackFunction);
|
||
|
|
||
|
labelAddress = (volatile uint32_t *)cellGcmGetLabelAddress(WaitLabelIndex);
|
||
|
*labelAddress = 0;
|
||
|
|
||
|
if ( rescIsEnabled( params ) )
|
||
|
cellRescSetVBlankHandler(_RGLRescVblankCallbackFunction);
|
||
|
else
|
||
|
cellGcmSetVBlankHandler(_RGLVblankCallbackFunction);
|
||
|
|
||
|
if ( rescIsEnabled( params ) )
|
||
|
{
|
||
|
for ( int i = 0; i < params->bufferingMode; ++i )
|
||
|
{
|
||
|
CellRescSrc rescSrc;
|
||
|
rescSrc.format = CELL_GCM_TEXTURE_A8R8G8B8 | CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_NR;
|
||
|
rescSrc.pitch = gcmDevice->color[i].pitch;
|
||
|
rescSrc.width = width;
|
||
|
rescSrc.height = height;
|
||
|
rescSrc.offset = gmmIdToOffset( gcmDevice->color[i].dataId );
|
||
|
|
||
|
if ( cellRescSetSrc( i, &rescSrc ) != CELL_OK )
|
||
|
{
|
||
|
printf("RGL: Registering display buffer %d failed\n", i );
|
||
|
return -1;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
_RGLSetDisplayMode( vm, gcmDevice->color[0].bpp*8, gcmDevice->color[0].pitch );
|
||
|
|
||
|
cellGcmSetFlipMode( gcmDevice->vsync ? CELL_GCM_DISPLAY_VSYNC : CELL_GCM_DISPLAY_HSYNC );
|
||
|
cellGcmSetInvalidateVertexCacheInline( &_RGLState.fifo);
|
||
|
_RGLFifoFinish( &_RGLState.fifo );
|
||
|
|
||
|
for ( int i = 0; i < params->bufferingMode; ++i )
|
||
|
{
|
||
|
if ( cellGcmSetDisplayBuffer( i, gmmIdToOffset( gcmDevice->color[i].dataId ), gcmDevice->color[i].pitch , width, height ) != CELL_OK )
|
||
|
{
|
||
|
printf("RGL: Registering display buffer %d failed\n", i );
|
||
|
return -1;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
gcmDevice->swapFifoRef = _RGLFifoPutReference( &_RGLState.fifo );
|
||
|
|
||
|
gcmDevice->swapFifoRef2 = gcmDevice->swapFifoRef;
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
PSGLdevice* psglCreateDeviceExtended( const PSGLdeviceParameters *parameters )
|
||
|
{
|
||
|
PSGLdevice *device = ( PSGLdevice * )malloc( sizeof( PSGLdevice ) + sizeof(RGLDevice) );
|
||
|
if ( !device )
|
||
|
{
|
||
|
_RGLSetError( GL_OUT_OF_MEMORY );
|
||
|
return NULL;
|
||
|
}
|
||
|
memset( device, 0, sizeof( PSGLdevice ) + sizeof(RGLDevice) );
|
||
|
|
||
|
PSGLdeviceParameters defaultParameters;
|
||
|
defaultParameters.enable = 0;
|
||
|
defaultParameters.colorFormat = GL_ARGB_SCE;
|
||
|
defaultParameters.depthFormat = GL_NONE;
|
||
|
defaultParameters.multisamplingMode = GL_MULTISAMPLING_NONE_SCE;
|
||
|
defaultParameters.TVStandard = PSGL_TV_STANDARD_NONE;
|
||
|
defaultParameters.connector = PSGL_DEVICE_CONNECTOR_NONE;
|
||
|
defaultParameters.bufferingMode = PSGL_BUFFERING_MODE_DOUBLE;
|
||
|
defaultParameters.width = 0;
|
||
|
defaultParameters.height = 0;
|
||
|
defaultParameters.renderWidth = 0;
|
||
|
defaultParameters.renderHeight = 0;
|
||
|
defaultParameters.rescRatioMode = RESC_RATIO_MODE_LETTERBOX;
|
||
|
defaultParameters.rescPalTemporalMode = RESC_PAL_TEMPORAL_MODE_50_NONE;
|
||
|
defaultParameters.rescInterlaceMode = RESC_INTERLACE_MODE_NORMAL_BILINEAR;
|
||
|
defaultParameters.horizontalScale = 1.0f;
|
||
|
defaultParameters.verticalScale = 1.0f;
|
||
|
|
||
|
memcpy( &device->deviceParameters, parameters, sizeof( PSGLdeviceParameters ) );
|
||
|
|
||
|
if (( parameters->enable & PSGL_DEVICE_PARAMETERS_COLOR_FORMAT ) == 0 )
|
||
|
device->deviceParameters.colorFormat = defaultParameters.colorFormat;
|
||
|
|
||
|
if (( parameters->enable & PSGL_DEVICE_PARAMETERS_TV_STANDARD ) == 0 )
|
||
|
device->deviceParameters.TVStandard = defaultParameters.TVStandard;
|
||
|
|
||
|
if (( parameters->enable & PSGL_DEVICE_PARAMETERS_CONNECTOR ) == 0 )
|
||
|
device->deviceParameters.connector = defaultParameters.connector;
|
||
|
|
||
|
if (( parameters->enable & PSGL_DEVICE_PARAMETERS_BUFFERING_MODE ) == 0 )
|
||
|
device->deviceParameters.bufferingMode = defaultParameters.bufferingMode;
|
||
|
|
||
|
if (( parameters->enable & PSGL_DEVICE_PARAMETERS_WIDTH_HEIGHT ) == 0 )
|
||
|
{
|
||
|
device->deviceParameters.width = defaultParameters.width;
|
||
|
device->deviceParameters.height = defaultParameters.height;
|
||
|
}
|
||
|
|
||
|
if (( parameters->enable & PSGL_DEVICE_PARAMETERS_RESC_RENDER_WIDTH_HEIGHT ) == 0 )
|
||
|
{
|
||
|
device->deviceParameters.renderWidth = defaultParameters.renderWidth;
|
||
|
device->deviceParameters.renderHeight = defaultParameters.renderHeight;
|
||
|
}
|
||
|
|
||
|
if (( parameters->enable & PSGL_DEVICE_PARAMETERS_RESC_RATIO_MODE ) == 0 )
|
||
|
device->deviceParameters.rescRatioMode = defaultParameters.rescRatioMode;
|
||
|
|
||
|
if (( parameters->enable & PSGL_DEVICE_PARAMETERS_RESC_PAL_TEMPORAL_MODE ) == 0 )
|
||
|
device->deviceParameters.rescPalTemporalMode = defaultParameters.rescPalTemporalMode;
|
||
|
|
||
|
if (( parameters->enable & PSGL_DEVICE_PARAMETERS_RESC_INTERLACE_MODE ) == 0 )
|
||
|
device->deviceParameters.rescInterlaceMode = defaultParameters.rescInterlaceMode;
|
||
|
|
||
|
if (( parameters->enable & PSGL_DEVICE_PARAMETERS_RESC_ADJUST_ASPECT_RATIO ) == 0 )
|
||
|
{
|
||
|
device->deviceParameters.horizontalScale = defaultParameters.horizontalScale;
|
||
|
device->deviceParameters.verticalScale = defaultParameters.verticalScale;
|
||
|
}
|
||
|
|
||
|
device->rasterDriver = NULL;
|
||
|
|
||
|
int result = _RGLPlatformCreateDevice( device );
|
||
|
if ( result < 0 )
|
||
|
{
|
||
|
if(device != NULL)
|
||
|
free( device );
|
||
|
return NULL;
|
||
|
}
|
||
|
return device;
|
||
|
}
|
||
|
|
||
|
GLfloat psglGetDeviceAspectRatio( const PSGLdevice * device )
|
||
|
{
|
||
|
CellVideoOutState videoState;
|
||
|
cellVideoOutGetState(CELL_VIDEO_OUT_PRIMARY, 0, &videoState);
|
||
|
|
||
|
switch (videoState.displayMode.aspect)
|
||
|
{
|
||
|
case CELL_VIDEO_OUT_ASPECT_4_3:
|
||
|
return 4.0f/3.0f;
|
||
|
case CELL_VIDEO_OUT_ASPECT_16_9:
|
||
|
return 16.0f/9.0f;
|
||
|
}
|
||
|
|
||
|
return 16.0f/9.0f;
|
||
|
}
|
||
|
|
||
|
void psglGetDeviceDimensions( const PSGLdevice * device, GLuint *width, GLuint *height )
|
||
|
{
|
||
|
*width = device->deviceParameters.width;
|
||
|
*height = device->deviceParameters.height;
|
||
|
}
|
||
|
|
||
|
void psglGetRenderBufferDimensions( const PSGLdevice * device, GLuint *width, GLuint *height )
|
||
|
{
|
||
|
*width = device->deviceParameters.renderWidth;
|
||
|
*height = device->deviceParameters.renderHeight;
|
||
|
}
|
||
|
|
||
|
void psglDestroyDevice( PSGLdevice *device )
|
||
|
{
|
||
|
if ( _CurrentDevice == device ) psglMakeCurrent( NULL, NULL );
|
||
|
|
||
|
if ( device->rasterDriver )
|
||
|
free( device->rasterDriver );
|
||
|
|
||
|
RGLDevice *gcmDevice = ( RGLDevice * )device->platformDevice;
|
||
|
PSGLdeviceParameters* params = &device->deviceParameters;
|
||
|
|
||
|
cellGcmSetInvalidateVertexCacheInline( &_RGLState.fifo);
|
||
|
_RGLFifoFinish( &_RGLState.fifo );
|
||
|
|
||
|
if ( rescIsEnabled( params ) )
|
||
|
cellRescSetFlipHandler(NULL);
|
||
|
else
|
||
|
cellGcmSetFlipHandler(NULL);
|
||
|
|
||
|
if ( rescIsEnabled( &device->deviceParameters ) )
|
||
|
cellRescSetVBlankHandler(NULL);
|
||
|
else
|
||
|
cellGcmSetVBlankHandler(NULL);
|
||
|
|
||
|
int res = sys_semaphore_destroy(FlipSem);
|
||
|
(void)res;
|
||
|
|
||
|
if ( rescIsEnabled( params ) )
|
||
|
{
|
||
|
cellRescExit();
|
||
|
gmmFree(gcmDevice->RescColorBuffersId);
|
||
|
gmmFree(gcmDevice->RescVertexArrayId);
|
||
|
gmmFree(gcmDevice->RescFragmentShaderId);
|
||
|
}
|
||
|
|
||
|
_RGLDuringDestroyDevice = GL_TRUE;
|
||
|
for ( int i = 0; i < params->bufferingMode; ++i )
|
||
|
{
|
||
|
if ( gcmDevice->color[i].pool != _RGL_SURFACE_POOL_NONE )
|
||
|
gmmFree( gcmDevice->color[i].dataId );
|
||
|
}
|
||
|
_RGLDuringDestroyDevice = GL_FALSE;
|
||
|
|
||
|
if(device != NULL)
|
||
|
free( device );
|
||
|
}
|
||
|
|
||
|
static void *_RGLPlatformRasterInit (void)
|
||
|
{
|
||
|
RGLDriver *driver = ( RGLDriver * )malloc( sizeof( RGLDriver ) );
|
||
|
|
||
|
cellGcmSetInvalidateVertexCacheInline( &_RGLState.fifo);
|
||
|
_RGLFifoFinish( &_RGLState.fifo );
|
||
|
memset( driver, 0, sizeof( RGLDriver ) );
|
||
|
driver->rt.yInverted = CELL_GCM_TRUE;
|
||
|
driver->invalidateVertexCache = GL_FALSE;
|
||
|
driver->flushBufferCount = 0;
|
||
|
driver->colorBufferMask = 0x1;
|
||
|
return driver;
|
||
|
}
|
||
|
|
||
|
void psglMakeCurrent( PSGLcontext *context, PSGLdevice *device )
|
||
|
{
|
||
|
if ( context && device )
|
||
|
{
|
||
|
_CurrentContext = context;
|
||
|
_CurrentDevice = device;
|
||
|
if ( !device->rasterDriver )
|
||
|
device->rasterDriver = _RGLPlatformRasterInit();
|
||
|
|
||
|
_RGLAttachContext( device, context );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
_CurrentContext = NULL;
|
||
|
_CurrentDevice = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
PSGLdevice *psglGetCurrentDevice()
|
||
|
{
|
||
|
return _CurrentDevice;
|
||
|
}
|
||
|
|
||
|
extern void gmmUpdateFreeList (const uint8_t location);
|
||
|
|
||
|
GLAPI void psglSwap( void )
|
||
|
{
|
||
|
PSGLcontext *LContext = _CurrentContext;
|
||
|
PSGLdevice *device = _CurrentDevice;
|
||
|
RGLFifo *fifo = &_RGLState.fifo;
|
||
|
|
||
|
gmmUpdateFreeList(CELL_GCM_LOCATION_LOCAL);
|
||
|
gmmUpdateFreeList(CELL_GCM_LOCATION_MAIN);
|
||
|
|
||
|
RGLDevice *gcmDevice = ( RGLDevice * )device->platformDevice;
|
||
|
|
||
|
const GLuint drawBuffer = gcmDevice->drawBuffer;
|
||
|
|
||
|
GLboolean vsync = _CurrentContext->VSync;
|
||
|
if ( vsync != gcmDevice->vsync )
|
||
|
{
|
||
|
if ( ! rescIsEnabled( &device->deviceParameters ) )
|
||
|
{
|
||
|
cellGcmSetFlipMode( vsync ? CELL_GCM_DISPLAY_VSYNC : CELL_GCM_DISPLAY_HSYNC );
|
||
|
gcmDevice->vsync = vsync;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( device->deviceParameters.bufferingMode == PSGL_BUFFERING_MODE_TRIPLE )
|
||
|
{
|
||
|
if ( rescIsEnabled( &device->deviceParameters ) )
|
||
|
cellRescSetWaitFlip();
|
||
|
else
|
||
|
cellGcmSetWaitFlip();
|
||
|
}
|
||
|
|
||
|
if ( rescIsEnabled( &device->deviceParameters ) )
|
||
|
{
|
||
|
int32_t res = cellRescSetConvertAndFlip(( uint8_t ) drawBuffer );
|
||
|
if ( res != CELL_OK )
|
||
|
{
|
||
|
printf("RGL WARN: RESC cellRescSetConvertAndFlip returned error code %d.\n", res);
|
||
|
if ( _CurrentContext ) _CurrentContext->needValidate |= PSGL_VALIDATE_FRAMEBUFFER;
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
cellGcmSetFlip(( uint8_t ) drawBuffer );
|
||
|
|
||
|
if ( device->deviceParameters.bufferingMode != PSGL_BUFFERING_MODE_TRIPLE )
|
||
|
{
|
||
|
if ( rescIsEnabled( &device->deviceParameters ) )
|
||
|
cellRescSetWaitFlip();
|
||
|
else
|
||
|
cellGcmSetWaitFlip();
|
||
|
}
|
||
|
|
||
|
cellGcmSetPolySmoothEnableInline( &_RGLState.fifo, CELL_GCM_FALSE);
|
||
|
cellGcmSetLineStippleEnableInline( &_RGLState.fifo, CELL_GCM_FALSE );
|
||
|
cellGcmSetPolygonStippleEnableInline( &_RGLState.fifo, CELL_GCM_FALSE);
|
||
|
cellGcmSetDepthBoundsTestEnable( &_RGLState.fifo, CELL_GCM_FALSE);
|
||
|
cellGcmSetDitherEnableInline( &_RGLState.fifo, CELL_GCM_FALSE);
|
||
|
|
||
|
LContext->needValidate = PSGL_VALIDATE_ALL;
|
||
|
|
||
|
for ( int unit = 0;unit < _RGL_MAX_TEXTURE_UNITS;unit++ )
|
||
|
LContext->TextureCoordsUnits[unit].TextureMatrixStack.dirty = GL_TRUE;
|
||
|
|
||
|
LContext->ModelViewMatrixStack.dirty = GL_TRUE;
|
||
|
LContext->ProjectionMatrixStack.dirty = GL_TRUE;
|
||
|
LContext->attribs->DirtyMask = ( 1 << _RGL_MAX_VERTEX_ATTRIBS ) - 1;
|
||
|
|
||
|
cellGcmSetInvalidateVertexCacheInline( &_RGLState.fifo);
|
||
|
|
||
|
_RGLFifoFlush( fifo );
|
||
|
|
||
|
while(sys_semaphore_wait(FlipSem, 1000) != CELL_OK);
|
||
|
|
||
|
cellGcmSetInvalidateVertexCacheInline( &_RGLState.fifo);
|
||
|
_RGLFifoFlush( fifo );
|
||
|
|
||
|
if ( device->deviceParameters.bufferingMode == PSGL_BUFFERING_MODE_DOUBLE )
|
||
|
{
|
||
|
gcmDevice->drawBuffer = gcmDevice->scanBuffer;
|
||
|
gcmDevice->scanBuffer = drawBuffer;
|
||
|
|
||
|
gcmDevice->rt.colorId[0] = gcmDevice->color[gcmDevice->drawBuffer].dataId;
|
||
|
gcmDevice->rt.colorPitch[0] = gcmDevice->color[gcmDevice->drawBuffer].pitch;
|
||
|
}
|
||
|
else if ( device->deviceParameters.bufferingMode == PSGL_BUFFERING_MODE_TRIPLE )
|
||
|
{
|
||
|
gcmDevice->drawBuffer = gcmDevice->scanBuffer;
|
||
|
if ( gcmDevice->scanBuffer == 2 )
|
||
|
gcmDevice->scanBuffer = 0;
|
||
|
else
|
||
|
gcmDevice->scanBuffer++;
|
||
|
|
||
|
gcmDevice->rt.colorId[0] = gcmDevice->color[gcmDevice->drawBuffer].dataId;
|
||
|
gcmDevice->rt.colorPitch[0] = gcmDevice->color[gcmDevice->drawBuffer].pitch;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static inline void _RGLUtilWaitForIdle (void)
|
||
|
{
|
||
|
cellGcmSetWriteBackEndLabelInline( &_RGLState.fifo, RGL_UTIL_LABEL_INDEX, _RGLState.labelValue);
|
||
|
cellGcmSetWaitLabelInline( &_RGLState.fifo, RGL_UTIL_LABEL_INDEX, _RGLState.labelValue);
|
||
|
|
||
|
_RGLState.labelValue++;
|
||
|
|
||
|
cellGcmSetWriteBackEndLabelInline( &_RGLState.fifo, RGL_UTIL_LABEL_INDEX, _RGLState.labelValue);
|
||
|
cellGcmFlush();
|
||
|
|
||
|
while( *(cellGcmGetLabelAddress( RGL_UTIL_LABEL_INDEX)) != _RGLState.labelValue)
|
||
|
sys_timer_usleep(30);
|
||
|
|
||
|
_RGLState.labelValue++;
|
||
|
}
|
||
|
|
||
|
GLboolean _RGLTryResizeTileRegion( GLuint address, GLuint size, void* data )
|
||
|
{
|
||
|
jsTiledRegion* region = ( jsTiledRegion* )data;
|
||
|
int32_t retVal = 0;
|
||
|
|
||
|
if ( size == 0 )
|
||
|
{
|
||
|
region->offset = 0;
|
||
|
region->size = 0;
|
||
|
region->pitch = 0;
|
||
|
|
||
|
if ( ! _RGLDuringDestroyDevice )
|
||
|
{
|
||
|
_RGLUtilWaitForIdle();
|
||
|
retVal = cellGcmUnbindTile( region->id );
|
||
|
_RGLFifoFinish( &_RGLState.fifo );
|
||
|
}
|
||
|
return GL_TRUE;
|
||
|
}
|
||
|
region->offset = address;
|
||
|
region->size = size;
|
||
|
|
||
|
_RGLUtilWaitForIdle();
|
||
|
|
||
|
retVal = cellGcmSetTileInfo(region->id, CELL_GCM_LOCATION_LOCAL,
|
||
|
region->offset, region->size, region->pitch, CELL_GCM_COMPMODE_DISABLED, 0,
|
||
|
region->bank );
|
||
|
|
||
|
retVal = cellGcmBindTile( region->id );
|
||
|
|
||
|
_RGLFifoFinish( &_RGLState.fifo );
|
||
|
|
||
|
return GL_TRUE;
|
||
|
}
|
||
|
|
||
|
void _RGLGetTileRegionInfo( void* data, GLuint *address, GLuint *size )
|
||
|
{
|
||
|
jsTiledRegion* region = ( jsTiledRegion* )data;
|
||
|
|
||
|
*address = region->offset;
|
||
|
*size = region->size;
|
||
|
}
|