mirror of
https://github.com/libretro/RetroArch
synced 2025-04-16 17:43:02 +00:00
1161 lines
36 KiB
C
1161 lines
36 KiB
C
// Clamp a float to [0,1]:
|
|
// The order of clamp comparisons are arranged so that NaN maps to min
|
|
// when compiled with VisualC or gcc. IEEE says comparisons with NaN
|
|
// should always fail (gcc implements this) but VisualC sometimes uses
|
|
// signed integer compares rather than floating-point compares which is
|
|
// incorrect in the case of NaN.
|
|
#define RGLGCM_CLAMPF_01(x) ((x) >= 0.0f ? ((x) > 1.0f ? 1.0f : (x)) : 0.0f)
|
|
|
|
static inline GLboolean rglIsDrawableColorFormat( GLenum colorFormat )
|
|
{
|
|
switch ( colorFormat )
|
|
{
|
|
case RGLGCM_ARGB8:
|
|
case RGLGCM_FLOAT_R32:
|
|
return GL_TRUE;
|
|
default:
|
|
return GL_FALSE;
|
|
}
|
|
}
|
|
|
|
static inline GLuint rglPlatformGetBitsPerPixel( GLenum internalFormat )
|
|
{
|
|
switch ( internalFormat )
|
|
{
|
|
case RGLGCM_ALPHA16:
|
|
case RGLGCM_HILO8:
|
|
case RGLGCM_RGB5_A1_SCE:
|
|
case RGLGCM_RGB565_SCE:
|
|
return 16;
|
|
case RGLGCM_ALPHA8:
|
|
return 8;
|
|
case RGLGCM_RGBX8:
|
|
case RGLGCM_RGBA8:
|
|
case RGLGCM_ABGR8:
|
|
case RGLGCM_ARGB8:
|
|
case RGLGCM_BGRA8:
|
|
case RGLGCM_FLOAT_R32:
|
|
case RGLGCM_HILO16:
|
|
case RGLGCM_XBGR8:
|
|
return 32;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
#define SUBPIXEL_BITS 12
|
|
#define SUBPIXEL_ADJUST (0.5/(1<<SUBPIXEL_BITS))
|
|
|
|
/* the affine transformation of x and y from normalized device coordinates to
|
|
** window coordinates.
|
|
**
|
|
** notes:
|
|
** - 1:1 port of glViewport (see spec for details)
|
|
** - x, y, width, height are clamped to the surface limits
|
|
** - initially, x, y width and height are zero!!
|
|
** - (0,0) is in the lower left [yInverted == TRUE]
|
|
** - important: because there is no concept of a window it is the callers
|
|
** responsibility to set the viewport to non zero values
|
|
** - [Jun] Two new paramenters zNear and zFar with default values to make
|
|
** this function compatible with cellGcmSetViewport
|
|
*/
|
|
static inline void rglGcmFifoGlViewport( GLint x, GLint y, GLsizei width, GLsizei height, GLclampf zNear = 0.0f, GLclampf zFar = 1.0f )
|
|
{
|
|
rglGcmViewportState *vp = &rglGcmState_i.state.viewport;
|
|
rglGcmRenderTarget *rt = &rglGcmState_i.renderTarget;
|
|
GLint clipX0, clipX1, clipY0, clipY1;
|
|
|
|
// keep for yInverted handling/disable+enable
|
|
vp->x = x;
|
|
vp->y = y;
|
|
vp->w = width;
|
|
vp->h = height;
|
|
|
|
// clamp to hw limits
|
|
clipX0 = x;
|
|
clipX1 = x + width;
|
|
if ( rt->yInverted )
|
|
{
|
|
clipY0 = rt->gcmRenderTarget.height - ( y + height );
|
|
clipY1 = rt->gcmRenderTarget.height - y;
|
|
}
|
|
else
|
|
{
|
|
clipY0 = y;
|
|
clipY1 = y + height;
|
|
}
|
|
if ( clipX0 < 0 )
|
|
{
|
|
clipX0 = 0;
|
|
}
|
|
if ( clipY0 < 0 )
|
|
{
|
|
clipY0 = 0;
|
|
}
|
|
if ( clipX1 >= RGLGCM_MAX_RT_DIMENSION )
|
|
{
|
|
clipX1 = RGLGCM_MAX_RT_DIMENSION;
|
|
}
|
|
if ( clipY1 >= RGLGCM_MAX_RT_DIMENSION )
|
|
{
|
|
clipY1 = RGLGCM_MAX_RT_DIMENSION;
|
|
}
|
|
if (( clipX1 <= clipX0 ) || ( clipY1 <= clipY0 ) )
|
|
{
|
|
clipX0 = clipY0 = clipX1 = clipY1 = 0;
|
|
}
|
|
|
|
// update viewport info
|
|
vp->xScale = width * 0.5f;
|
|
vp->xCenter = ( GLfloat )( x + vp->xScale + RGLGCM_SUBPIXEL_ADJUST );
|
|
if ( rt->yInverted )
|
|
{
|
|
vp->yScale = height * -0.5f;
|
|
vp->yCenter = ( GLfloat )( rt->gcmRenderTarget.height - RGLGCM_VIEWPORT_EPSILON - y + vp->yScale + RGLGCM_SUBPIXEL_ADJUST );
|
|
}
|
|
else
|
|
{
|
|
vp->yScale = height * 0.5f;
|
|
vp->yCenter = ( GLfloat )( y + vp->yScale + RGLGCM_SUBPIXEL_ADJUST );
|
|
}
|
|
|
|
// Clamp depth range to legal values
|
|
zNear = RGLGCM_CLAMPF_01( zNear );
|
|
zFar = RGLGCM_CLAMPF_01( zFar );
|
|
|
|
// compute viewport values for hw [no doubles, so we might loose a few lsb]
|
|
GLfloat z_scale = ( GLfloat )( 0.5f * ( zFar - zNear ) );
|
|
GLfloat z_center = ( GLfloat )( 0.5f * ( zFar + zNear ) );
|
|
|
|
// hw zNear/zFar clipper
|
|
if ( zNear > zFar )
|
|
{
|
|
GLclampf tmp = zNear;
|
|
zNear = zFar;
|
|
zFar = tmp;
|
|
}
|
|
|
|
float scale[4] = { vp->xScale, vp->yScale, z_scale, 0.0f };
|
|
float offset[4] = { vp->xCenter, vp->yCenter, z_center, 0.0f };
|
|
|
|
GCM_FUNC( cellGcmSetViewport, clipX0, clipY0, clipX1 - clipX0,
|
|
clipY1 - clipY0, zNear, zFar, scale, offset );
|
|
}
|
|
|
|
/* When you call glDrawArrays, count sequential elements from each enabled
|
|
** array are used to construct a sequence of geometric primitives, beginning
|
|
** with the first element. The mode parameter specifies what kind of primitive
|
|
** to construct and how to use the array elements to construct the primitives.
|
|
**
|
|
** note:
|
|
** - 1:1 port of glDrawArrays (see spec for details)
|
|
** - legal values for mode are RGLGCM_POINTS, RGLGCM_LINES, RGLGCM_LINE_LOOP, RGLGCM_LINE_STRIP,
|
|
** RGLGCM_TRIANGLES, RGLGCM_TRIANGLE_STRIP, RGLGCM_TRIANGLE_FAN, RGLGCM_QUADS, RGLGCM_QUAD_STRIP
|
|
** and RGLGCM_POLYGON
|
|
** - legal values for first, first+Count are [0, 0xfffff]
|
|
** - if vertex reusage exists, glDrawElements is preferred
|
|
*/
|
|
static inline void rglGcmFifoGlDrawArrays( rglGcmEnum mode, GLint first, GLsizei count )
|
|
{
|
|
uint8_t gcmMode = 0;
|
|
switch ( mode )
|
|
{
|
|
case RGLGCM_POINTS:
|
|
gcmMode = CELL_GCM_PRIMITIVE_POINTS;
|
|
break;
|
|
case RGLGCM_LINES:
|
|
gcmMode = CELL_GCM_PRIMITIVE_LINES;
|
|
break;
|
|
case RGLGCM_LINE_LOOP:
|
|
gcmMode = CELL_GCM_PRIMITIVE_LINE_LOOP;
|
|
break;
|
|
case RGLGCM_LINE_STRIP:
|
|
gcmMode = CELL_GCM_PRIMITIVE_LINE_STRIP;
|
|
break;
|
|
case RGLGCM_TRIANGLES:
|
|
gcmMode = CELL_GCM_PRIMITIVE_TRIANGLES;
|
|
break;
|
|
case RGLGCM_TRIANGLE_STRIP:
|
|
gcmMode = CELL_GCM_PRIMITIVE_TRIANGLE_STRIP;
|
|
break;
|
|
case RGLGCM_TRIANGLE_FAN:
|
|
gcmMode = CELL_GCM_PRIMITIVE_TRIANGLE_FAN;
|
|
break;
|
|
case RGLGCM_QUADS:
|
|
gcmMode = CELL_GCM_PRIMITIVE_QUADS;
|
|
break;
|
|
case RGLGCM_QUAD_STRIP:
|
|
gcmMode = CELL_GCM_PRIMITIVE_QUAD_STRIP;
|
|
break;
|
|
case RGLGCM_POLYGON:
|
|
gcmMode = CELL_GCM_PRIMITIVE_POLYGON;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if ( count )
|
|
{
|
|
GCM_FUNC_SAFE( cellGcmSetDrawArrays, gcmMode, first, count );
|
|
}
|
|
}
|
|
|
|
static inline void rglGcmFifoGlTransferDataVidToVid
|
|
(
|
|
GLuint dstVidId,
|
|
GLuint dstVidIdOffset,
|
|
GLuint dstPitch,
|
|
GLuint dstX,
|
|
GLuint dstY,
|
|
GLuint srcVidId,
|
|
GLuint srcVidIdOffset,
|
|
GLuint srcPitch,
|
|
GLuint srcX,
|
|
GLuint srcY,
|
|
GLuint width, // size in pixel
|
|
GLuint height,
|
|
GLuint bytesPerPixel
|
|
)
|
|
{
|
|
GLuint dstOffset = gmmIdToOffset(dstVidId) + dstVidIdOffset;
|
|
GLuint srcOffset = gmmIdToOffset(srcVidId) + srcVidIdOffset;
|
|
|
|
GCM_FUNC( cellGcmSetTransferImage, CELL_GCM_TRANSFER_LOCAL_TO_LOCAL, dstOffset, dstPitch, dstX, dstY, srcOffset, srcPitch, srcX, srcY, width, height, bytesPerPixel );
|
|
}
|
|
|
|
static inline GLuint rglGcmMapMinTextureFilter( GLenum filter )
|
|
{
|
|
switch ( filter )
|
|
{
|
|
case GL_NEAREST:
|
|
return CELL_GCM_TEXTURE_NEAREST;
|
|
break;
|
|
case GL_LINEAR:
|
|
return CELL_GCM_TEXTURE_LINEAR;
|
|
break;
|
|
case GL_NEAREST_MIPMAP_NEAREST:
|
|
return CELL_GCM_TEXTURE_NEAREST_NEAREST;
|
|
break;
|
|
case GL_NEAREST_MIPMAP_LINEAR:
|
|
return CELL_GCM_TEXTURE_NEAREST_LINEAR;
|
|
break;
|
|
case GL_LINEAR_MIPMAP_NEAREST:
|
|
return CELL_GCM_TEXTURE_LINEAR_NEAREST;
|
|
break;
|
|
case GL_LINEAR_MIPMAP_LINEAR:
|
|
return CELL_GCM_TEXTURE_LINEAR_LINEAR;
|
|
break;
|
|
default:
|
|
return 0;
|
|
}
|
|
return filter;
|
|
}
|
|
|
|
static inline GLuint rglGcmMapMagTextureFilter( GLenum filter )
|
|
{
|
|
switch ( filter )
|
|
{
|
|
case GL_NEAREST:
|
|
return CELL_GCM_TEXTURE_NEAREST;
|
|
break;
|
|
case GL_LINEAR:
|
|
return CELL_GCM_TEXTURE_LINEAR;
|
|
break;
|
|
default:
|
|
return 0;
|
|
}
|
|
return filter;
|
|
}
|
|
|
|
static inline GLuint rglGcmMapAniso( GLuint maxAniso )
|
|
{
|
|
|
|
if ( maxAniso >= 16 )
|
|
return CELL_GCM_TEXTURE_MAX_ANISO_16;
|
|
if ( maxAniso == 1 )
|
|
return CELL_GCM_TEXTURE_MAX_ANISO_1;
|
|
|
|
switch ( maxAniso / 2 )
|
|
{
|
|
case 1:
|
|
return CELL_GCM_TEXTURE_MAX_ANISO_2;
|
|
break;
|
|
case 2:
|
|
return CELL_GCM_TEXTURE_MAX_ANISO_4;
|
|
break;
|
|
case 3:
|
|
return CELL_GCM_TEXTURE_MAX_ANISO_6;
|
|
break;
|
|
case 4:
|
|
return CELL_GCM_TEXTURE_MAX_ANISO_8;
|
|
break;
|
|
case 5:
|
|
return CELL_GCM_TEXTURE_MAX_ANISO_10;
|
|
break;
|
|
case 6:
|
|
return CELL_GCM_TEXTURE_MAX_ANISO_12;
|
|
break;
|
|
case 7:
|
|
return CELL_GCM_TEXTURE_MAX_ANISO_16;
|
|
break;
|
|
default:
|
|
return 0;
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static inline GLuint rglGcmMapWrapMode( GLuint mode )
|
|
{
|
|
switch ( mode )
|
|
{
|
|
case RGLGCM_CLAMP:
|
|
return CELL_GCM_TEXTURE_CLAMP;
|
|
break;
|
|
case RGLGCM_REPEAT:
|
|
return CELL_GCM_TEXTURE_WRAP;
|
|
break;
|
|
case RGLGCM_CLAMP_TO_EDGE:
|
|
return CELL_GCM_TEXTURE_CLAMP_TO_EDGE;
|
|
break;
|
|
case RGLGCM_CLAMP_TO_BORDER:
|
|
return CELL_GCM_TEXTURE_BORDER;
|
|
break;
|
|
case RGLGCM_MIRRORED_REPEAT:
|
|
return CELL_GCM_TEXTURE_MIRROR;
|
|
break;
|
|
case RGLGCM_MIRROR_CLAMP_TO_EDGE:
|
|
return CELL_GCM_TEXTURE_MIRROR_ONCE_CLAMP_TO_EDGE;
|
|
break;
|
|
case RGLGCM_MIRROR_CLAMP_TO_BORDER:
|
|
return CELL_GCM_TEXTURE_MIRROR_ONCE_BORDER;
|
|
break;
|
|
case RGLGCM_MIRROR_CLAMP:
|
|
return CELL_GCM_TEXTURE_MIRROR_ONCE_CLAMP;
|
|
break;
|
|
default:
|
|
return 0;
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
static inline void rglGcmMapTextureFormat( GLuint internalFormat, uint8_t & gcmFormat, uint32_t & remap )
|
|
{
|
|
gcmFormat = 0;
|
|
|
|
switch ( internalFormat )
|
|
{
|
|
case RGLGCM_ALPHA8: // in_rgba = xxAx, out_rgba = 000A
|
|
{
|
|
gcmFormat = CELL_GCM_TEXTURE_B8;
|
|
remap = CELL_GCM_REMAP_MODE(
|
|
CELL_GCM_TEXTURE_REMAP_ORDER_XYXY,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_B,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_R,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_B,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_B,
|
|
CELL_GCM_TEXTURE_REMAP_REMAP,
|
|
CELL_GCM_TEXTURE_REMAP_ZERO,
|
|
CELL_GCM_TEXTURE_REMAP_ZERO,
|
|
CELL_GCM_TEXTURE_REMAP_ZERO );
|
|
|
|
}
|
|
break;
|
|
case RGLGCM_ALPHA16: // in_rgba = xAAx, out_rgba = 000A
|
|
{
|
|
gcmFormat = CELL_GCM_TEXTURE_X16;
|
|
remap = CELL_GCM_REMAP_MODE(
|
|
CELL_GCM_TEXTURE_REMAP_ORDER_XYXY,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_G,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_B,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_G,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_B,
|
|
CELL_GCM_TEXTURE_REMAP_REMAP,
|
|
CELL_GCM_TEXTURE_REMAP_ZERO,
|
|
CELL_GCM_TEXTURE_REMAP_ZERO,
|
|
CELL_GCM_TEXTURE_REMAP_ZERO );
|
|
|
|
}
|
|
break;
|
|
case RGLGCM_HILO8: // in_rgba = HLxx, out_rgba = HL11
|
|
{
|
|
gcmFormat = CELL_GCM_TEXTURE_COMPRESSED_HILO8;
|
|
remap = CELL_GCM_REMAP_MODE(
|
|
CELL_GCM_TEXTURE_REMAP_ORDER_XYXY,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_A,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_R,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_G,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_B,
|
|
CELL_GCM_TEXTURE_REMAP_ONE,
|
|
CELL_GCM_TEXTURE_REMAP_REMAP,
|
|
CELL_GCM_TEXTURE_REMAP_REMAP,
|
|
CELL_GCM_TEXTURE_REMAP_ONE );
|
|
|
|
}
|
|
break;
|
|
case RGLGCM_HILO16: // in_rgba = HLxx, out_rgba = HL11
|
|
{
|
|
gcmFormat = CELL_GCM_TEXTURE_Y16_X16;
|
|
remap = CELL_GCM_REMAP_MODE(
|
|
CELL_GCM_TEXTURE_REMAP_ORDER_XYXY,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_A,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_R,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_G,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_B,
|
|
CELL_GCM_TEXTURE_REMAP_ONE,
|
|
CELL_GCM_TEXTURE_REMAP_REMAP,
|
|
CELL_GCM_TEXTURE_REMAP_REMAP,
|
|
CELL_GCM_TEXTURE_REMAP_ONE );
|
|
|
|
}
|
|
break;
|
|
case RGLGCM_ARGB8: // in_rgba = RGBA, out_rgba = RGBA
|
|
{
|
|
gcmFormat = CELL_GCM_TEXTURE_A8R8G8B8;
|
|
remap = CELL_GCM_REMAP_MODE(
|
|
CELL_GCM_TEXTURE_REMAP_ORDER_XYXY,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_A,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_R,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_G,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_B,
|
|
CELL_GCM_TEXTURE_REMAP_REMAP,
|
|
CELL_GCM_TEXTURE_REMAP_REMAP,
|
|
CELL_GCM_TEXTURE_REMAP_REMAP,
|
|
CELL_GCM_TEXTURE_REMAP_REMAP );
|
|
|
|
}
|
|
break;
|
|
case RGLGCM_BGRA8: // in_rgba = GRAB, out_rgba = RGBA ** NEEDS TO BE TESTED
|
|
{
|
|
gcmFormat = CELL_GCM_TEXTURE_A8R8G8B8;
|
|
remap = CELL_GCM_REMAP_MODE(
|
|
CELL_GCM_TEXTURE_REMAP_ORDER_XYXY,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_B,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_G,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_R,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_A,
|
|
CELL_GCM_TEXTURE_REMAP_REMAP,
|
|
CELL_GCM_TEXTURE_REMAP_REMAP,
|
|
CELL_GCM_TEXTURE_REMAP_REMAP,
|
|
CELL_GCM_TEXTURE_REMAP_REMAP );
|
|
|
|
}
|
|
break;
|
|
case RGLGCM_RGBA8: // in_rgba = GBAR, out_rgba = RGBA ** NEEDS TO BE TESTED
|
|
{
|
|
gcmFormat = CELL_GCM_TEXTURE_A8R8G8B8;
|
|
remap = CELL_GCM_REMAP_MODE(
|
|
CELL_GCM_TEXTURE_REMAP_ORDER_XYXY,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_B,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_A,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_R,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_G,
|
|
CELL_GCM_TEXTURE_REMAP_REMAP,
|
|
CELL_GCM_TEXTURE_REMAP_REMAP,
|
|
CELL_GCM_TEXTURE_REMAP_REMAP,
|
|
CELL_GCM_TEXTURE_REMAP_REMAP );
|
|
}
|
|
break;
|
|
case RGLGCM_ABGR8: // in_rgba = BGRA, out_rgba = RGBA ** NEEDS TO BE TESTED
|
|
{
|
|
gcmFormat = CELL_GCM_TEXTURE_A8R8G8B8;
|
|
remap = CELL_GCM_REMAP_MODE(
|
|
CELL_GCM_TEXTURE_REMAP_ORDER_XYXY,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_A,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_B,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_G,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_R,
|
|
CELL_GCM_TEXTURE_REMAP_REMAP,
|
|
CELL_GCM_TEXTURE_REMAP_REMAP,
|
|
CELL_GCM_TEXTURE_REMAP_REMAP,
|
|
CELL_GCM_TEXTURE_REMAP_REMAP );
|
|
|
|
}
|
|
break;
|
|
case RGLGCM_RGBX8: // in_rgba = BGRA, out_rgba = RGB1 ** NEEDS TO BE TESTED
|
|
{
|
|
gcmFormat = CELL_GCM_TEXTURE_A8R8G8B8;
|
|
remap = CELL_GCM_REMAP_MODE(
|
|
CELL_GCM_TEXTURE_REMAP_ORDER_XYXY,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_B,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_A,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_R,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_G,
|
|
CELL_GCM_TEXTURE_REMAP_ONE,
|
|
CELL_GCM_TEXTURE_REMAP_REMAP,
|
|
CELL_GCM_TEXTURE_REMAP_REMAP,
|
|
CELL_GCM_TEXTURE_REMAP_REMAP );
|
|
|
|
}
|
|
break;
|
|
case RGLGCM_XBGR8: // in_rgba = BGRA, out_rgba = RGB1 ** NEEDS TO BE TESTED
|
|
{
|
|
gcmFormat = CELL_GCM_TEXTURE_A8R8G8B8;
|
|
remap = CELL_GCM_REMAP_MODE(
|
|
CELL_GCM_TEXTURE_REMAP_ORDER_XYXY,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_A,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_B,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_G,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_R,
|
|
CELL_GCM_TEXTURE_REMAP_ONE,
|
|
CELL_GCM_TEXTURE_REMAP_REMAP,
|
|
CELL_GCM_TEXTURE_REMAP_REMAP,
|
|
CELL_GCM_TEXTURE_REMAP_REMAP );
|
|
|
|
}
|
|
break;
|
|
case RGLGCM_FLOAT_R32: // in_rgba = Rxxx, out_rgba = R001
|
|
{
|
|
gcmFormat = CELL_GCM_TEXTURE_X32_FLOAT;
|
|
remap = CELL_GCM_REMAP_MODE(
|
|
CELL_GCM_TEXTURE_REMAP_ORDER_XYXY,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_A,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_R,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_G,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_B,
|
|
CELL_GCM_TEXTURE_REMAP_ONE,
|
|
CELL_GCM_TEXTURE_REMAP_REMAP,
|
|
CELL_GCM_TEXTURE_REMAP_ZERO,
|
|
CELL_GCM_TEXTURE_REMAP_ZERO );
|
|
|
|
}
|
|
break;
|
|
case RGLGCM_RGB5_A1_SCE: // in_rgba = RGBA, out_rgba = RGBA
|
|
{
|
|
gcmFormat = CELL_GCM_TEXTURE_A1R5G5B5;
|
|
remap = CELL_GCM_REMAP_MODE(
|
|
CELL_GCM_TEXTURE_REMAP_ORDER_XXXY,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_A,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_R,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_G,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_B,
|
|
CELL_GCM_TEXTURE_REMAP_REMAP,
|
|
CELL_GCM_TEXTURE_REMAP_REMAP,
|
|
CELL_GCM_TEXTURE_REMAP_REMAP,
|
|
CELL_GCM_TEXTURE_REMAP_REMAP );
|
|
|
|
}
|
|
break;
|
|
case RGLGCM_RGB565_SCE: // in_rgba = RGBA, out_rgba = RGBA
|
|
{
|
|
gcmFormat = CELL_GCM_TEXTURE_R5G6B5;
|
|
remap = CELL_GCM_REMAP_MODE(
|
|
CELL_GCM_TEXTURE_REMAP_ORDER_XXXY,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_A,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_R,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_G,
|
|
CELL_GCM_TEXTURE_REMAP_FROM_B,
|
|
CELL_GCM_TEXTURE_REMAP_ONE,
|
|
CELL_GCM_TEXTURE_REMAP_REMAP,
|
|
CELL_GCM_TEXTURE_REMAP_REMAP,
|
|
CELL_GCM_TEXTURE_REMAP_REMAP );
|
|
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
};
|
|
|
|
return;
|
|
}
|
|
|
|
// Explicitly invalidate the L2 texture cache
|
|
static inline void rglGcmFifoGlInvalidateTextureCache( void )
|
|
{
|
|
GCM_FUNC( cellGcmSetInvalidateTextureCache, CELL_GCM_INVALIDATE_TEXTURE );
|
|
}
|
|
|
|
/* writes the supplied new semaphore value once the gpu has completed all
|
|
** currently pending work.
|
|
**
|
|
** note:
|
|
** - we do not enforce pairing of Acquire/Release, so you can (ab)use it to
|
|
** write synchronized signal values...
|
|
*/
|
|
|
|
static inline void rglGcmFifoGlReleaseSemaphore( rglGcmEnum target, GLuint semaphoreId, GLuint newSemphoreValue )
|
|
{
|
|
rglGcmSemaphoreMemory *semaphores = rglGcmState_i.semaphores;
|
|
|
|
switch ( target )
|
|
{
|
|
case RGLGCM_SEMAPHORE_USING_GPU:
|
|
// let the backend(rop/fb) write the release value
|
|
// -- guarantees all reads/writes have completed
|
|
GCM_FUNC( cellGcmSetWriteBackEndLabel, semaphoreId, newSemphoreValue );
|
|
break;
|
|
case RGLGCM_SEMAPHORE_USING_GPU_NO_WRITE_FLUSH:
|
|
// write the semaphore value once host/vb/ib/tex are no longer referencing
|
|
// any data prior to the method.
|
|
// -- does _NOT_ guarantee that read/writes on the render target surfaces
|
|
// have completed (iow: cpu read on the color buffer will be undefined)
|
|
|
|
GCM_FUNC( cellGcmSetWriteTextureLabel, semaphoreId, newSemphoreValue );
|
|
break;
|
|
case RGLGCM_SEMAPHORE_USING_CPU:
|
|
semaphores->userSemaphores[semaphoreId].val = newSemphoreValue;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* lets the gpu/cpu wait until the specific semaphore is equal to the requested
|
|
** semaphore value.
|
|
**
|
|
** note:
|
|
** - we do not enforce pairing of Acquire/Release, so you can (ab)use it to
|
|
** - What about aquire timeouts (after a few seconds) ?
|
|
*/
|
|
void static inline rglGcmFifoGlAcquireSemaphore( rglGcmEnum target, GLuint semaphoreId, GLuint reqSemphoreValue )
|
|
{
|
|
rglGcmSemaphoreMemory *semaphores = rglGcmState_i.semaphores;
|
|
|
|
// pick location
|
|
switch ( target )
|
|
{
|
|
case RGLGCM_SEMAPHORE_USING_GPU:
|
|
// let the frontend aquire the semaphore...
|
|
GCM_FUNC( cellGcmSetWaitLabel, semaphoreId, reqSemphoreValue );
|
|
break;
|
|
case RGLGCM_SEMAPHORE_USING_CPU:
|
|
// lame polling for now...
|
|
for ( ;semaphores->userSemaphores[semaphoreId].val != reqSemphoreValue; )
|
|
sys_timer_usleep(10);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Fast conversion for values between 0.0 and 65535.0
|
|
GLuint inline static RGLGCM_QUICK_FLOAT2UINT( const GLfloat f )
|
|
{
|
|
union
|
|
{
|
|
GLfloat f;
|
|
GLuint ui;
|
|
} t;
|
|
t.f = f + RGLGCM_F0_DOT_0;
|
|
return t.ui & 0xffff;
|
|
}
|
|
|
|
// construct a packed unsigned int ARGB8 color
|
|
void inline static RGLGCM_CALC_COLOR_LE_ARGB8( GLuint *color0, const GLfloat r, const GLfloat g, const GLfloat b, const GLfloat a )
|
|
{
|
|
GLuint r2 = RGLGCM_QUICK_FLOAT2UINT( r * 255.0f );
|
|
GLuint g2 = RGLGCM_QUICK_FLOAT2UINT( g * 255.0f );
|
|
GLuint b2 = RGLGCM_QUICK_FLOAT2UINT( b * 255.0f );
|
|
GLuint a2 = RGLGCM_QUICK_FLOAT2UINT( a * 255.0f );
|
|
*color0 = ( a2 << 24 ) | ( r2 << 16 ) | ( g2 << 8 ) | ( b2 << 0 );
|
|
}
|
|
|
|
// Wait for the gpu to pass the given fence in the command buffer.
|
|
static inline void rglGcmFifoGlFinishFenceRef( const GLuint ref )
|
|
{
|
|
rglGcmFifo *fifo = &rglGcmState_i.fifo;
|
|
|
|
// wait for completion
|
|
for ( ;; )
|
|
{
|
|
// gpu passed reference ?
|
|
if ( !rglGcmFifoReferenceInUse( fifo, ref ) )
|
|
break;
|
|
|
|
// avoid polling on bus (interrupts memory traffic)
|
|
sys_timer_usleep(10);
|
|
}
|
|
}
|
|
|
|
#define RGLGCM_UTIL_LABEL_INDEX 253
|
|
|
|
// Utility to let RSX wait for complete RSX pipeline idle
|
|
static inline void rglGcmUtilWaitForIdle()
|
|
{
|
|
// set write label command in push buffer, and wait
|
|
// NOTE: this is for RSX to wailt
|
|
GCM_FUNC( cellGcmSetWriteBackEndLabel, RGLGCM_UTIL_LABEL_INDEX, rglGcmState_i.labelValue );
|
|
GCM_FUNC( cellGcmSetWaitLabel, RGLGCM_UTIL_LABEL_INDEX, rglGcmState_i.labelValue );
|
|
|
|
// increment label value for next time.
|
|
rglGcmState_i.labelValue++;
|
|
|
|
// make sure the entire pipe in clear not just the front end
|
|
// Utility function that does GPU 'finish'.
|
|
GCM_FUNC( cellGcmSetWriteBackEndLabel, RGLGCM_UTIL_LABEL_INDEX,
|
|
rglGcmState_i.labelValue );
|
|
cellGcmFlush();
|
|
|
|
while( *(cellGcmGetLabelAddress( RGLGCM_UTIL_LABEL_INDEX)) != rglGcmState_i.labelValue)
|
|
sys_timer_usleep(30);
|
|
|
|
rglGcmState_i.labelValue++;
|
|
}
|
|
|
|
// Sets the source and destination factor used for blending.
|
|
static inline void rglGcmFifoGlBlendFunc( rglGcmEnum sf, rglGcmEnum df, rglGcmEnum sfAlpha, rglGcmEnum dfAlpha )
|
|
{
|
|
// syntax check
|
|
switch ( sf )
|
|
{
|
|
case RGLGCM_ZERO:
|
|
case RGLGCM_ONE:
|
|
case RGLGCM_SRC_COLOR:
|
|
case RGLGCM_ONE_MINUS_SRC_COLOR:
|
|
case RGLGCM_SRC_ALPHA:
|
|
case RGLGCM_ONE_MINUS_SRC_ALPHA:
|
|
case RGLGCM_DST_ALPHA:
|
|
case RGLGCM_ONE_MINUS_DST_ALPHA:
|
|
case RGLGCM_DST_COLOR:
|
|
case RGLGCM_ONE_MINUS_DST_COLOR:
|
|
case RGLGCM_SRC_ALPHA_SATURATE:
|
|
case RGLGCM_CONSTANT_COLOR:
|
|
case RGLGCM_ONE_MINUS_CONSTANT_COLOR:
|
|
case RGLGCM_CONSTANT_ALPHA:
|
|
case RGLGCM_ONE_MINUS_CONSTANT_ALPHA:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
switch ( sfAlpha )
|
|
{
|
|
case RGLGCM_ZERO:
|
|
case RGLGCM_ONE:
|
|
case RGLGCM_SRC_COLOR:
|
|
case RGLGCM_ONE_MINUS_SRC_COLOR:
|
|
case RGLGCM_SRC_ALPHA:
|
|
case RGLGCM_ONE_MINUS_SRC_ALPHA:
|
|
case RGLGCM_DST_ALPHA:
|
|
case RGLGCM_ONE_MINUS_DST_ALPHA:
|
|
case RGLGCM_DST_COLOR:
|
|
case RGLGCM_ONE_MINUS_DST_COLOR:
|
|
case RGLGCM_SRC_ALPHA_SATURATE:
|
|
case RGLGCM_CONSTANT_COLOR:
|
|
case RGLGCM_ONE_MINUS_CONSTANT_COLOR:
|
|
case RGLGCM_CONSTANT_ALPHA:
|
|
case RGLGCM_ONE_MINUS_CONSTANT_ALPHA:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
switch ( df )
|
|
{
|
|
case RGLGCM_ZERO:
|
|
case RGLGCM_ONE:
|
|
case RGLGCM_SRC_COLOR:
|
|
case RGLGCM_ONE_MINUS_SRC_COLOR:
|
|
case RGLGCM_SRC_ALPHA:
|
|
case RGLGCM_ONE_MINUS_SRC_ALPHA:
|
|
case RGLGCM_DST_ALPHA:
|
|
case RGLGCM_ONE_MINUS_DST_ALPHA:
|
|
case RGLGCM_DST_COLOR:
|
|
case RGLGCM_ONE_MINUS_DST_COLOR:
|
|
case RGLGCM_SRC_ALPHA_SATURATE:
|
|
case RGLGCM_CONSTANT_COLOR:
|
|
case RGLGCM_ONE_MINUS_CONSTANT_COLOR:
|
|
case RGLGCM_CONSTANT_ALPHA:
|
|
case RGLGCM_ONE_MINUS_CONSTANT_ALPHA:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
switch ( dfAlpha )
|
|
{
|
|
case RGLGCM_ZERO:
|
|
case RGLGCM_ONE:
|
|
case RGLGCM_SRC_COLOR:
|
|
case RGLGCM_ONE_MINUS_SRC_COLOR:
|
|
case RGLGCM_SRC_ALPHA:
|
|
case RGLGCM_ONE_MINUS_SRC_ALPHA:
|
|
case RGLGCM_DST_ALPHA:
|
|
case RGLGCM_ONE_MINUS_DST_ALPHA:
|
|
case RGLGCM_DST_COLOR:
|
|
case RGLGCM_ONE_MINUS_DST_COLOR:
|
|
case RGLGCM_SRC_ALPHA_SATURATE:
|
|
case RGLGCM_CONSTANT_COLOR:
|
|
case RGLGCM_ONE_MINUS_CONSTANT_COLOR:
|
|
case RGLGCM_CONSTANT_ALPHA:
|
|
case RGLGCM_ONE_MINUS_CONSTANT_ALPHA:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
GCM_FUNC( cellGcmSetBlendFunc, sf, df, sfAlpha, dfAlpha );
|
|
}
|
|
|
|
// Prints out an int in hexedecimal and binary, broken into bytes.
|
|
// Can be used for printing out macro and constant values.
|
|
// example: rglPrintIt( RGLGCM_3DCONST(SET_SURFACE_FORMAT, COLOR, LE_A8R8G8B8) );
|
|
// 00 00 00 08 : 00000000 00000000 00000000 00001000 */
|
|
void static inline rglPrintIt( unsigned int v )
|
|
{
|
|
// HEX (space between bytes)
|
|
printf( "%02x %02x %02x %02x : ", ( v >> 24 )&0xff, ( v >> 16 )&0xff, ( v >> 8 )&0xff, v&0xff );
|
|
|
|
// BINARY (space between bytes)
|
|
for ( unsigned int mask = ( 0x1 << 31 ), i = 1; mask != 0; mask >>= 1, i++ )
|
|
printf( "%d%s", ( v & mask ) ? 1 : 0, ( i % 8 == 0 ) ? " " : "" );
|
|
printf( "\n" );
|
|
}
|
|
|
|
// prints the last numWords of the command fifo
|
|
void static inline rglPrintFifoFromPut( unsigned int numWords )
|
|
{
|
|
for ( int i = -numWords; i <= -1; i++ )
|
|
rglPrintIt((( uint32_t* )rglGcmState_i.fifo.current )[i] );
|
|
}
|
|
|
|
// prints the last numWords of the command fifo
|
|
void static inline rglPrintFifoFromGet( unsigned int numWords )
|
|
{
|
|
for ( int i = -numWords; i <= -1; i++ )
|
|
rglPrintIt((( uint32_t* )rglGcmState_i.fifo.lastGetRead )[i] );
|
|
}
|
|
|
|
// Determine whether a given location in a command buffer has been passed, by
|
|
// using reference markers.
|
|
GLboolean static inline rglGcmFifoGlTestFenceRef( const GLuint ref )
|
|
{
|
|
rglGcmFifo *fifo = &rglGcmState_i.fifo;
|
|
return rglGcmFifoReferenceInUse( fifo, ref );
|
|
}
|
|
|
|
// Add a reference marker to the command buffer to determine whether a location
|
|
// in the command buffer has been passed
|
|
void static inline rglGcmFifoGlIncFenceRef( GLuint *ref )
|
|
{
|
|
rglGcmFifo *fifo = &rglGcmState_i.fifo;
|
|
*ref = rglGcmFifoPutReference( fifo );
|
|
}
|
|
|
|
// Flush the current FIFO.
|
|
void static inline rglGcmFifoGlFlush( void )
|
|
{
|
|
GCM_FUNC_NO_ARGS( cellGcmSetInvalidateVertexCache );
|
|
rglGcmFifoFlush( &rglGcmState_i.fifo );
|
|
}
|
|
|
|
// Set blending constant, used for certain blending modes.
|
|
static inline void rglGcmFifoGlBlendColor( GLfloat r, GLfloat g, GLfloat b, GLfloat a )
|
|
{
|
|
rglGcmBlendState *blend = &rglGcmState_i.state.blend;
|
|
GLuint hwColor;
|
|
|
|
// syntax check
|
|
blend->r = r;
|
|
blend->g = g;
|
|
blend->b = b;
|
|
blend->a = a;
|
|
|
|
// program hw
|
|
switch ( rglGcmState_i.renderTarget.colorFormat )
|
|
{
|
|
case RGLGCM_ARGB8:
|
|
r = RGLGCM_CLAMPF_01( r );
|
|
g = RGLGCM_CLAMPF_01( g );
|
|
b = RGLGCM_CLAMPF_01( b );
|
|
a = RGLGCM_CLAMPF_01( a );
|
|
RGLGCM_CALC_COLOR_LE_ARGB8( &hwColor, r, g, b, a );
|
|
GCM_FUNC( cellGcmSetBlendColor, hwColor, hwColor );
|
|
break;
|
|
case RGLGCM_NONE:
|
|
case RGLGCM_FLOAT_R32:
|
|
// no native support support
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Set the current blend equation.
|
|
static inline void rglGcmFifoGlBlendEquation( rglGcmEnum mode, rglGcmEnum modeAlpha )
|
|
{
|
|
// syntax check
|
|
switch ( mode )
|
|
{
|
|
case RGLGCM_FUNC_ADD:
|
|
case RGLGCM_MIN:
|
|
case RGLGCM_MAX:
|
|
case RGLGCM_FUNC_SUBTRACT:
|
|
case RGLGCM_FUNC_REVERSE_SUBTRACT:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
switch ( modeAlpha )
|
|
{
|
|
case RGLGCM_FUNC_ADD:
|
|
case RGLGCM_MIN:
|
|
case RGLGCM_MAX:
|
|
case RGLGCM_FUNC_SUBTRACT:
|
|
case RGLGCM_FUNC_REVERSE_SUBTRACT:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
GCM_FUNC( cellGcmSetBlendEquation, mode, modeAlpha );
|
|
}
|
|
|
|
void static inline rglGcmFifoGlVertexAttribPointer
|
|
(
|
|
GLuint index,
|
|
GLint size,
|
|
rglGcmEnum type,
|
|
GLboolean normalized,
|
|
GLsizei stride,
|
|
GLushort frequency,
|
|
GLboolean isMain,
|
|
GLuint offset
|
|
)
|
|
{
|
|
// syntax check
|
|
switch ( size )
|
|
{
|
|
case 0: // disable
|
|
stride = 0;
|
|
normalized = 0;
|
|
type = RGLGCM_FLOAT;
|
|
offset = 0;
|
|
break;
|
|
case 1:
|
|
case 2:
|
|
case 3:
|
|
case 4:
|
|
// valid
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
// mapping to native types
|
|
uint8_t gcmType = 0;
|
|
switch ( type )
|
|
{
|
|
case RGLGCM_UNSIGNED_BYTE:
|
|
if (normalized)
|
|
{
|
|
gcmType = CELL_GCM_VERTEX_UB;
|
|
}
|
|
else
|
|
{
|
|
gcmType = CELL_GCM_VERTEX_UB256;
|
|
}
|
|
break;
|
|
|
|
case RGLGCM_SHORT:
|
|
gcmType = normalized ? CELL_GCM_VERTEX_S1 : CELL_GCM_VERTEX_S32K;
|
|
break;
|
|
|
|
case RGLGCM_FLOAT:
|
|
gcmType = CELL_GCM_VERTEX_F;
|
|
break;
|
|
|
|
case RGLGCM_HALF_FLOAT:
|
|
gcmType = CELL_GCM_VERTEX_SF;
|
|
break;
|
|
|
|
case RGLGCM_CMP:
|
|
size = 1; // required for this format
|
|
gcmType = CELL_GCM_VERTEX_CMP;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
uint8_t location = CELL_GCM_LOCATION_LOCAL;
|
|
|
|
if ( isMain )
|
|
location = CELL_GCM_LOCATION_MAIN;
|
|
|
|
GCM_FUNC( cellGcmSetVertexDataArray, index, frequency, stride, size, gcmType, location, offset );
|
|
}
|
|
|
|
// set the vertex attribute to the specified value.
|
|
void static inline rglGcmFifoGlVertexAttrib4fv( GLuint index, const GLfloat v[4] )
|
|
{
|
|
GCM_FUNC( cellGcmSetVertexData4f, index, v );
|
|
}
|
|
|
|
static inline void rglGcmFifoGlClearColor( GLfloat r, GLfloat g, GLfloat b, GLfloat a )
|
|
{
|
|
GCM_FUNC( cellGcmSetClearColor, 0 );
|
|
}
|
|
|
|
static inline void rglGcmFifoGlClear( GLbitfield mask )
|
|
{
|
|
GLuint hwMask = 0;
|
|
|
|
if ( mask & RGLGCM_COLOR_BUFFER_BIT && rglGcmState_i.renderTarget.colorFormat)
|
|
hwMask = CELL_GCM_CLEAR_R | CELL_GCM_CLEAR_G | CELL_GCM_CLEAR_B | CELL_GCM_CLEAR_A;
|
|
|
|
if ( hwMask )
|
|
{
|
|
GCM_FUNC( cellGcmSetClearSurface, hwMask );
|
|
}
|
|
}
|
|
|
|
static inline void rglGcmFifoGlEnable( rglGcmEnum cap )
|
|
{
|
|
switch ( cap )
|
|
{
|
|
case RGLGCM_BLEND:
|
|
GCM_FUNC( cellGcmSetBlendEnable, RGLGCM_TRUE );
|
|
GCM_FUNC( cellGcmSetBlendEnableMrt, RGLGCM_TRUE, RGLGCM_TRUE, RGLGCM_TRUE );
|
|
break;
|
|
case RGLGCM_DITHER:
|
|
GCM_FUNC( cellGcmSetDitherEnable, RGLGCM_TRUE );
|
|
break;
|
|
case RGLGCM_PSHADER_SRGB_REMAPPING:
|
|
GCM_FUNC( cellGcmSetFragmentProgramGammaEnable, RGLGCM_TRUE );
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static inline void rglGcmFifoGlDisable( rglGcmEnum cap )
|
|
{
|
|
|
|
switch ( cap )
|
|
{
|
|
case RGLGCM_BLEND:
|
|
GCM_FUNC( cellGcmSetBlendEnable, RGLGCM_FALSE );
|
|
GCM_FUNC( cellGcmSetBlendEnableMrt, RGLGCM_FALSE, RGLGCM_FALSE, RGLGCM_FALSE );
|
|
break;
|
|
case RGLGCM_DITHER:
|
|
GCM_FUNC( cellGcmSetDitherEnable, RGLGCM_FALSE );
|
|
break;
|
|
case RGLGCM_PSHADER_SRGB_REMAPPING:
|
|
GCM_FUNC( cellGcmSetFragmentProgramGammaEnable, RGLGCM_FALSE );
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static inline void rglFifoGlProgramParameterfvVP( const _CGprogram *program, const CgParameterEntry *parameterEntry, const GLfloat *value )
|
|
{
|
|
const CgParameterResource *parameterResource = rglGetParameterResource( program, parameterEntry );
|
|
if ( parameterResource->resource != ( unsigned short ) - 1 )
|
|
{
|
|
switch ( parameterResource->type )
|
|
{
|
|
case CG_FLOAT:
|
|
case CG_FLOAT1:
|
|
case CG_FLOAT2:
|
|
case CG_FLOAT3:
|
|
case CG_FLOAT4:
|
|
GCM_FUNC( cellGcmSetVertexProgramParameterBlock, parameterResource->resource, 1, value ); // GCM_PORT_TESTED [Cedric]
|
|
break;
|
|
case CG_FLOAT4x4:
|
|
// set 4 consts
|
|
{
|
|
GLfloat v2[16];
|
|
v2[0] = value[0];v2[1] = value[4];v2[2] = value[8];v2[3] = value[12];
|
|
v2[4] = value[1];v2[5] = value[5];v2[6] = value[9];v2[7] = value[13];
|
|
v2[8] = value[2];v2[9] = value[6];v2[10] = value[10];v2[11] = value[14];
|
|
v2[12] = value[3];v2[13] = value[7];v2[14] = value[11];v2[15] = value[15];
|
|
GCM_FUNC( cellGcmSetVertexProgramParameterBlock, parameterResource->resource, 4, v2 ); // GCM_PORT_TESTED [Cedric]
|
|
}
|
|
break;
|
|
case CG_FLOAT3x3:
|
|
// set 3 consts
|
|
{
|
|
GLfloat v2[12];
|
|
v2[0] = value[0];v2[1] = value[3];v2[2] = value[6];v2[3] = 0;
|
|
v2[4] = value[1];v2[5] = value[4];v2[6] = value[7];v2[7] = 0;
|
|
v2[8] = value[2];v2[9] = value[5];v2[10] = value[8];v2[11] = 0;
|
|
GCM_FUNC( cellGcmSetVertexProgramParameterBlock, parameterResource->resource, 3, v2 );
|
|
}
|
|
break;
|
|
case CG_HALF:
|
|
case CG_HALF1:
|
|
case CG_HALF2:
|
|
case CG_HALF3:
|
|
case CG_HALF4:
|
|
case CG_INT:
|
|
case CG_INT1:
|
|
case CG_INT2:
|
|
case CG_INT3:
|
|
case CG_INT4:
|
|
case CG_BOOL:
|
|
case CG_BOOL1:
|
|
case CG_BOOL2:
|
|
case CG_BOOL3:
|
|
case CG_BOOL4:
|
|
case CG_FIXED:
|
|
case CG_FIXED1:
|
|
case CG_FIXED2:
|
|
case CG_FIXED3:
|
|
case CG_FIXED4:
|
|
GCM_FUNC( cellGcmSetVertexProgramParameterBlock, parameterResource->resource, 1, value ); // GCM_PORT_TESTED [Cedric]
|
|
break;
|
|
case CG_HALF4x4:
|
|
case CG_INT4x4:
|
|
case CG_BOOL4x4:
|
|
case CG_FIXED4x4:
|
|
// set 4 consts
|
|
{
|
|
GLfloat v2[16];
|
|
v2[0] = value[0];v2[1] = value[4];v2[2] = value[8];v2[3] = value[12];
|
|
v2[4] = value[1];v2[5] = value[5];v2[6] = value[9];v2[7] = value[13];
|
|
v2[8] = value[2];v2[9] = value[6];v2[10] = value[10];v2[11] = value[14];
|
|
v2[12] = value[3];v2[13] = value[7];v2[14] = value[11];v2[15] = value[15];
|
|
GCM_FUNC( cellGcmSetVertexProgramParameterBlock, parameterResource->resource, 4, v2 ); // GCM_PORT_TESTED [Cedric]
|
|
}
|
|
break;
|
|
case CG_HALF3x3:
|
|
case CG_INT3x3:
|
|
case CG_BOOL3x3:
|
|
case CG_FIXED3x3:
|
|
// set 3 consts
|
|
{
|
|
GLfloat v2[12];
|
|
v2[0] = value[0];v2[1] = value[3];v2[2] = value[6];v2[3] = 0;
|
|
v2[4] = value[1];v2[5] = value[4];v2[6] = value[7];v2[7] = 0;
|
|
v2[8] = value[2];v2[9] = value[5];v2[10] = value[8];v2[11] = 0;
|
|
GCM_FUNC( cellGcmSetVertexProgramParameterBlock, parameterResource->resource, 3, v2 );
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Push a CG program onto the current command buffer
|
|
static inline void rglGcmPushProgramPushBuffer( _CGprogram * cgprog )
|
|
{
|
|
// make sure there is space for the pushbuffer + any nops we need to add for alignment
|
|
rglGcmFifoWaitForFreeSpace( &rglGcmState_i.fifo, cgprog->constantPushBufferWordSize + 4 + 32);
|
|
// first add nops to get us the next alligned position in the fifo
|
|
// [YLIN] Use VMX register to copy
|
|
uint32_t padding_in_word = ( ( 0x10-(((uint32_t)rglGcmState_i.fifo.current)&0xf))&0xf )>>2;
|
|
uint32_t padded_size = ( ((cgprog->constantPushBufferWordSize)<<2) + 0xf )&~0xf;
|
|
GCM_FUNC( cellGcmSetNopCommandUnsafe, padding_in_word );
|
|
memcpy16(rglGcmState_i.fifo.current, cgprog->constantPushBuffer, padded_size);
|
|
rglGcmState_i.fifo.current+=cgprog->constantPushBufferWordSize;
|
|
|
|
}
|
|
|
|
// Look up the memory location of a buffer object (VBO, PBO)
|
|
static inline GLuint rglGcmGetBufferObjectOrigin( GLuint buffer )
|
|
{
|
|
rglBufferObject *bufferObject = (rglBufferObject*)_CurrentContext->bufferObjectNameSpace.data[buffer];
|
|
rglGcmBufferObject *gcmBuffer = ( rglGcmBufferObject * ) & bufferObject->platformBufferObject;
|
|
return gcmBuffer->bufferId;
|
|
}
|
|
|
|
static inline rglGcmDriver *rglGetGcmDriver(void)
|
|
{
|
|
return ( rglGcmDriver * )( _CurrentDevice->rasterDriver );
|
|
}
|
|
|