819 lines
23 KiB
C++
819 lines
23 KiB
C++
//========= Copyright (c) 2010, Valve Corporation, All rights reserved. ============//
|
|
/* SCE CONFIDENTIAL */
|
|
/* PlayStation(R)3 Programmer Tool Runtime Library 350.001 */
|
|
/* Copyright (C) 2009 Sony Computer Entertainment Inc. */
|
|
/* All Rights Reserved. */
|
|
/* File: main.cpp
|
|
* Description:
|
|
* simple graphics to show how to use libgcm
|
|
*
|
|
*/
|
|
#include "errorrenderloop.h"
|
|
#include <ppu_intrinsics.h>
|
|
|
|
#define ARRAYSIZE( ARRAY ) ( sizeof( ARRAY ) / sizeof( ( ARRAY )[0] ) )
|
|
|
|
|
|
#ifdef _DEBUG
|
|
#define CELL_GCMUTIL_ASSERT(X) do{ if( !( X ) ) {printf( "Assert(%s)\n%s:%d\n", #X, __FILE__, __LINE__ ); __builtin_snpause(); } }while(0)
|
|
#define CELL_GCMUTIL_CHECK_ASSERT(X) CELL_GCMUTIL_ASSERT( X == CELL_OK )
|
|
#define CELL_GCMUTIL_CG_PARAMETER_CHECK_ASSERT(X) CELL_GCMUTIL_ASSERT(X != 0 )
|
|
#else
|
|
#define CELL_GCMUTIL_ASSERT(X)
|
|
#define CELL_GCMUTIL_CHECK_ASSERT(X) (X)
|
|
#define CELL_GCMUTIL_CG_PARAMETER_CHECK_ASSERT(X) (void)(X)
|
|
#endif
|
|
|
|
|
|
// For exit routine
|
|
static void sysutil_exit_callback(uint64_t status, uint64_t param, void* userdata);
|
|
|
|
extern uint32_t _binary_errorshader_vpo_start;
|
|
extern uint32_t _binary_errorshader_vpo_end;
|
|
extern uint32_t _binary_errorshader_fpo_start;
|
|
extern uint32_t _binary_errorshader_fpo_end;
|
|
|
|
PS3_GcmSharedData g_gcmSharedData;
|
|
|
|
using namespace cell::Gcm;
|
|
|
|
|
|
ErrorRenderLoop::ErrorRenderLoop()
|
|
{
|
|
m_keepRunning = true;
|
|
m_nLocalMemHeap = 0;
|
|
vertex_program_ptr =
|
|
(unsigned char *)&_binary_errorshader_vpo_start;
|
|
fragment_program_ptr =
|
|
(unsigned char *)&_binary_errorshader_fpo_start;
|
|
frame_index = 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
/* local memory allocation */
|
|
void *ErrorRenderLoop::localMemoryAlloc(const uint32_t size)
|
|
{
|
|
uint32_t allocated_size = (size + 1023) & (~1023);
|
|
uint32_t base = m_nLocalMemHeap;
|
|
m_nLocalMemHeap += allocated_size;
|
|
return (void*)base;
|
|
}
|
|
|
|
void *ErrorRenderLoop::localMemoryAlign(const uint32_t alignment,
|
|
const uint32_t size)
|
|
{
|
|
m_nLocalMemHeap = (m_nLocalMemHeap + alignment-1) & (~(alignment-1));
|
|
return (void*)localMemoryAlloc(size);
|
|
}
|
|
|
|
|
|
|
|
|
|
void ErrorRenderLoop::setRenderTarget(const uint32_t Index)
|
|
{
|
|
CellGcmSurface sf;
|
|
sf.colorFormat = CELL_GCM_SURFACE_A8R8G8B8;
|
|
sf.colorTarget = CELL_GCM_SURFACE_TARGET_0;
|
|
sf.colorLocation[0] = CELL_GCM_LOCATION_LOCAL;
|
|
sf.colorOffset[0] = color_offset[Index];
|
|
sf.colorPitch[0] = color_pitch;
|
|
|
|
sf.colorLocation[1] = CELL_GCM_LOCATION_LOCAL;
|
|
sf.colorLocation[2] = CELL_GCM_LOCATION_LOCAL;
|
|
sf.colorLocation[3] = CELL_GCM_LOCATION_LOCAL;
|
|
sf.colorOffset[1] = 0;
|
|
sf.colorOffset[2] = 0;
|
|
sf.colorOffset[3] = 0;
|
|
sf.colorPitch[1] = 64;
|
|
sf.colorPitch[2] = 64;
|
|
sf.colorPitch[3] = 64;
|
|
|
|
sf.depthFormat = CELL_GCM_SURFACE_Z24S8;
|
|
sf.depthLocation = CELL_GCM_LOCATION_LOCAL;
|
|
sf.depthOffset = depth_offset;
|
|
sf.depthPitch = depth_pitch;
|
|
|
|
sf.type = CELL_GCM_SURFACE_PITCH;
|
|
sf.antialias = CELL_GCM_SURFACE_CENTER_1;
|
|
|
|
sf.width = display_width;
|
|
sf.height = display_height;
|
|
sf.x = 0;
|
|
sf.y = 0;
|
|
cellGcmSetSurface(&sf);
|
|
//cellGcmSetAntiAliasingControl(CELL_GCM_TRUE, CELL_GCM_FALSE, CELL_GCM_FALSE, 0xffff);
|
|
}
|
|
|
|
/* wait until flip */
|
|
static void waitFlip(void)
|
|
{
|
|
while (cellGcmGetFlipStatus()!=0){
|
|
sys_timer_usleep(300);
|
|
}
|
|
cellGcmResetFlipStatus();
|
|
}
|
|
|
|
|
|
void ErrorRenderLoop::flip(void)
|
|
{
|
|
static int first=1;
|
|
|
|
// wait until the previous flip executed
|
|
if (first!=1) waitFlip();
|
|
else cellGcmResetFlipStatus();
|
|
|
|
if(cellGcmSetFlip(frame_index) != CELL_OK) return;
|
|
cellGcmFlush();
|
|
|
|
// resend status
|
|
setDrawEnv();
|
|
setRenderState();
|
|
|
|
cellGcmSetWaitFlip();
|
|
|
|
// New render target
|
|
frame_index = (frame_index+1)%COLOR_BUFFER_NUM;
|
|
setRenderTarget(frame_index);
|
|
|
|
first=0;
|
|
}
|
|
|
|
|
|
void ErrorRenderLoop::initShader(void)
|
|
{
|
|
vertex_program = (CGprogram)vertex_program_ptr;
|
|
fragment_program = (CGprogram)fragment_program_ptr;
|
|
|
|
// init
|
|
cellGcmCgInitProgram(vertex_program);
|
|
cellGcmCgInitProgram(fragment_program);
|
|
|
|
uint32_t ucode_size;
|
|
void *ucode;
|
|
cellGcmCgGetUCode(fragment_program, &ucode, &ucode_size);
|
|
// 64B alignment required
|
|
void *ret = localMemoryAlign(64, ucode_size);
|
|
fragment_program_ucode = ret;
|
|
memcpy(fragment_program_ucode, ucode, ucode_size);
|
|
|
|
cellGcmCgGetUCode(vertex_program, &ucode, &ucode_size);
|
|
vertex_program_ucode = ucode;
|
|
}
|
|
|
|
static void buildProjection(float *M,
|
|
const float top,
|
|
const float bottom,
|
|
const float left,
|
|
const float right,
|
|
const float near,
|
|
const float far)
|
|
{
|
|
memset(M, 0, 16*sizeof(float));
|
|
|
|
M[0*4+0] = (2.0f*near) / (right - left);
|
|
M[1*4+1] = (2.0f*near) / (bottom - top);
|
|
|
|
float A = (right + left) / (right - left);
|
|
float B = (top + bottom) / (top - bottom);
|
|
float C = -(far + near) / (far - near);
|
|
float D = -(2.0f*far*near) / (far - near);
|
|
|
|
M[0*4 + 2] = A;
|
|
M[1*4 + 2] = B;
|
|
M[2*4 + 2] = C;
|
|
M[3*4 + 2] = -1.0f;
|
|
M[2*4 + 3] = D;
|
|
}
|
|
|
|
static void matrixMul(float *Dest, float *A, float *B)
|
|
{
|
|
for (int i=0; i < 4; i++) {
|
|
for (int j=0; j < 4; j++) {
|
|
Dest[i*4+j]
|
|
= A[i*4+0]*B[0*4+j]
|
|
+ A[i*4+1]*B[1*4+j]
|
|
+ A[i*4+2]*B[2*4+j]
|
|
+ A[i*4+3]*B[3*4+j];
|
|
}
|
|
}
|
|
}
|
|
|
|
static void matrixTranslate(float *M,
|
|
const float x,
|
|
const float y,
|
|
const float z)
|
|
{
|
|
memset(M, 0, sizeof(float)*16);
|
|
M[0*4+3] = x;
|
|
M[1*4+3] = y;
|
|
M[2*4+3] = z;
|
|
|
|
M[0*4+0] = 1.0f;
|
|
M[1*4+1] = 1.0f;
|
|
M[2*4+2] = 1.0f;
|
|
M[3*4+3] = 1.0f;
|
|
}
|
|
|
|
/*
|
|
static void unitMatrix(float *M)
|
|
{
|
|
M[0*4+0] = 1.0f;
|
|
M[0*4+1] = 0.0f;
|
|
M[0*4+2] = 0.0f;
|
|
M[0*4+3] = 0.0f;
|
|
|
|
M[1*4+0] = 0.0f;
|
|
M[1*4+1] = 1.0f;
|
|
M[1*4+2] = 0.0f;
|
|
M[1*4+3] = 0.0f;
|
|
|
|
M[2*4+0] = 0.0f;
|
|
M[2*4+1] = 0.0f;
|
|
M[2*4+2] = 1.0f;
|
|
M[2*4+3] = 0.0f;
|
|
|
|
M[3*4+0] = 0.0f;
|
|
M[3*4+1] = 0.0f;
|
|
M[3*4+2] = 0.0f;
|
|
M[3*4+3] = 1.0f;
|
|
}
|
|
|
|
*/
|
|
#define CB_SIZE (0x10000)
|
|
|
|
int32_t ErrorRenderLoop::initDisplay(void)
|
|
{
|
|
uint32_t color_depth=4; // ARGB8
|
|
uint32_t z_depth=4; // COMPONENT24
|
|
void *color_base_addr;
|
|
void *depth_base_addr;
|
|
void *color_addr[COLOR_BUFFER_NUM];
|
|
void *depth_addr;
|
|
CellVideoOutResolution resolution;
|
|
|
|
// display initialize
|
|
|
|
// read the current video status
|
|
// INITIAL DISPLAY MODE HAS TO BE SET BY RUNNING SETMONITOR.SELF
|
|
CellVideoOutState videoState;
|
|
CELL_GCMUTIL_CHECK_ASSERT(cellVideoOutGetState(CELL_VIDEO_OUT_PRIMARY, 0, &videoState));
|
|
CELL_GCMUTIL_CHECK_ASSERT(cellVideoOutGetResolution(videoState.displayMode.resolutionId, &resolution));
|
|
|
|
display_width = resolution.width;
|
|
display_height = resolution.height;
|
|
color_pitch = display_width*color_depth;
|
|
depth_pitch = display_width*z_depth;
|
|
|
|
uint32_t color_size = color_pitch*display_height;
|
|
uint32_t depth_size = depth_pitch*display_height;
|
|
|
|
CellVideoOutConfiguration videocfg;
|
|
memset(&videocfg, 0, sizeof(CellVideoOutConfiguration));
|
|
videocfg.resolutionId = videoState.displayMode.resolutionId;
|
|
videocfg.format = CELL_VIDEO_OUT_BUFFER_COLOR_FORMAT_X8R8G8B8;
|
|
videocfg.pitch = color_pitch;
|
|
|
|
// set video out configuration with waitForEvent set to 0 (4th parameter)
|
|
CELL_GCMUTIL_CHECK_ASSERT(cellVideoOutConfigure(CELL_VIDEO_OUT_PRIMARY, &videocfg, NULL, 0));
|
|
CELL_GCMUTIL_CHECK_ASSERT(cellVideoOutGetState(CELL_VIDEO_OUT_PRIMARY, 0, &videoState));
|
|
|
|
switch (videoState.displayMode.aspect){
|
|
case CELL_VIDEO_OUT_ASPECT_4_3:
|
|
display_aspect_ratio=4.0f/3.0f;
|
|
break;
|
|
case CELL_VIDEO_OUT_ASPECT_16_9:
|
|
display_aspect_ratio=16.0f/9.0f;
|
|
break;
|
|
default:
|
|
printf("unknown aspect ratio %x\n", videoState.displayMode.aspect);
|
|
display_aspect_ratio=16.0f/9.0f;
|
|
}
|
|
|
|
cellGcmSetFlipMode(CELL_GCM_DISPLAY_VSYNC);
|
|
|
|
// get config
|
|
CellGcmConfig config;
|
|
cellGcmGetConfiguration(&config);
|
|
// buffer memory allocation
|
|
m_nLocalMemHeap = (uint32_t)config.localAddress;
|
|
|
|
color_base_addr = localMemoryAlign(64, COLOR_BUFFER_NUM*color_size);
|
|
|
|
for (int i = 0; i < COLOR_BUFFER_NUM; i++) {
|
|
color_addr[i]= (void *)((uint32_t)color_base_addr+ (i*color_size));
|
|
CELL_GCMUTIL_CHECK_ASSERT(cellGcmAddressToOffset(color_addr[i], &color_offset[i]));
|
|
}
|
|
|
|
// regist surface
|
|
for (int i = 0; i < COLOR_BUFFER_NUM; i++) {
|
|
CELL_GCMUTIL_CHECK_ASSERT(cellGcmSetDisplayBuffer(i, color_offset[i], color_pitch, display_width, display_height));
|
|
}
|
|
|
|
depth_base_addr = localMemoryAlign(64, depth_size);
|
|
depth_addr = depth_base_addr;
|
|
CELL_GCMUTIL_CHECK_ASSERT(cellGcmAddressToOffset(depth_addr, &depth_offset));
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
// 65 verts in polySurfaceShape1
|
|
ErrorRenderLoop::Vertex_t g_verts_polySurfaceShape1[65] = {
|
|
{0.287,2.232,-0.144, 0.398,0.702,-0.590, 0xFFFF5FFF },
|
|
{-0.287,2.232,-0.144, -0.404,0.699,-0.590, 0xFFFF00FF },
|
|
{-1.634,-0.134,-0.134, -0.808,-0.006,-0.588, 0xFFFF00FF },
|
|
{-1.366,-0.598,-0.134, -0.413,-0.695,-0.589, 0xFFFF00FF },
|
|
{1.345,-0.635,-0.155, 0.400,-0.700,-0.592, 0xFFFF00FF },
|
|
{1.655,-0.097,-0.155, 0.806,0.001,-0.592, 0xFFFF00FF },
|
|
{0.287,2.232,0.144, 0.455,0.835,0.308, 0xFFFF5FFF },
|
|
{-0.287,2.232,0.144, -0.462,0.832,0.309, 0xFFFF5FFF },
|
|
{-1.634,-0.134,0.134, -0.937,-0.034,0.347, 0xFFFF00FF },
|
|
{-1.366,-0.598,0.134, -0.484,-0.795,0.367, 0xFFFF5FFF },
|
|
{1.345,-0.635,0.155, 0.470,-0.802,0.369, 0xFFFF5FFF },
|
|
{1.655,-0.097,0.155, 0.937,-0.027,0.348, 0xFFFF00FF },
|
|
{0.000,0.500,-0.257, -0.007,0.000,-1.000, 0xFFFF00FF },
|
|
{0.000,0.274,0.422, 0.000,0.962,0.272, 0xFF0076FF },
|
|
{0.000,-0.085,0.422, 0.000,-0.962,0.272, 0xFF0076FF },
|
|
{-0.173,0.094,0.422, -0.964,0.000,0.266, 0xFF0076FF },
|
|
{0.173,0.094,0.422, 0.964,0.000,0.266, 0xFF0076FF },
|
|
{-0.058,0.445,0.422, -0.592,-0.698,0.404, 0xFF0076FF },
|
|
{0.058,0.445,0.422, 0.591,-0.698,0.404, 0xFF0076FF },
|
|
{0.002,2.002,0.422, 0.019,0.915,0.403, 0xFF0000FF },
|
|
{0.173,1.774,0.422, 0.871,0.278,0.405, 0xFF0000FF },
|
|
{-0.172,1.789,0.422, -0.864,0.296,0.407, 0xFF0000FF },
|
|
{0.088,0.787,0.422, 0.963,-0.084,0.256, 0xFF0076FF },
|
|
{-0.088,0.787,0.422, -0.963,-0.082,0.256, 0xFF0076FF },
|
|
{0.124,1.192,0.422, 0.949,-0.082,0.304, 0xFF0000FF },
|
|
{-0.123,1.192,0.422, -0.950,-0.081,0.302, 0xFF0000FF },
|
|
{0.161,1.597,0.422, 0.935,-0.070,0.347, 0xFF0000FF },
|
|
{-0.159,1.597,0.422, -0.936,-0.071,0.345, 0xFF0000FF },
|
|
{0.000,0.274,0.349, 0.000,0.818,-0.575, 0xFFFFFFFF },
|
|
{-0.173,0.094,0.349, -0.815,0.000,-0.579, 0xFFFFFFFF },
|
|
{0.000,-0.085,0.349, 0.000,-0.818,-0.575, 0xFF0076FF },
|
|
{0.173,0.094,0.349, 0.815,0.000,-0.579, 0xFF0076FF },
|
|
{0.173,1.774,0.349, 0.739,0.219,-0.637, 0xFFFFFFFF },
|
|
{0.002,2.002,0.349, 0.018,0.825,-0.566, 0xFFFFFFFF },
|
|
{-0.172,1.789,0.349, -0.738,0.235,-0.633, 0xFFFFFFFF },
|
|
{0.058,0.445,0.349, 0.549,-0.600,-0.582, 0xFFFFFFFF },
|
|
{0.088,0.787,0.349, 0.704,-0.063,-0.707, 0xFFFFFFFF },
|
|
{-0.088,0.787,0.349, -0.704,-0.062,-0.707, 0xFFFFFFFF },
|
|
{0.124,1.192,0.349, 0.704,-0.063,-0.707, 0xFFFFFFFF },
|
|
{-0.123,1.192,0.349, -0.704,-0.062,-0.707, 0xFFFFFFFF },
|
|
{0.161,1.597,0.349, 0.708,-0.055,-0.704, 0xFFFFFFFF },
|
|
{-0.159,1.597,0.349, -0.707,-0.056,-0.705, 0xFFFFFFFF },
|
|
{-0.058,0.445,0.349, -0.549,-0.600,-0.582, 0xFFFFFFFF },
|
|
{0.280,2.195,0.188, 0.318,0.461,0.828, 0xFFFF5FFF },
|
|
{-0.279,2.195,0.188, -0.323,0.457,0.829, 0xFFFF5FFF },
|
|
{0.000,0.508,0.298, -0.007,0.000,1.000, 0xFFFF00FF },
|
|
{-1.591,-0.110,0.178, -0.535,0.082,0.841, 0xFFFF00FF },
|
|
{-1.331,-0.561,0.178, -0.213,-0.432,0.877, 0xFFFF5FFF },
|
|
{1.310,-0.597,0.199, 0.199,-0.432,0.880, 0xFFFF5FFF },
|
|
{1.612,-0.074,0.199, 0.529,0.089,0.844, 0xFFFF00FF },
|
|
{-0.150,1.762,0.445, -0.414,0.061,0.908, 0xFF0000FF },
|
|
{0.150,1.747,0.445, 0.414,0.057,0.909, 0xFF0000FF },
|
|
{0.002,1.965,0.445, 0.016,0.404,0.915, 0xFF0000FF },
|
|
{-0.076,0.808,0.445, -0.498,-0.043,0.866, 0xFF0076FF },
|
|
{0.050,0.482,0.445, 0.464,-0.229,0.856, 0xFF0076FF },
|
|
{0.077,0.808,0.445, 0.497,-0.043,0.866, 0xFF0076FF },
|
|
{-0.107,1.194,0.445, -0.459,-0.037,0.888, 0xFF0000FF },
|
|
{0.108,1.194,0.445, 0.457,-0.037,0.888, 0xFF0000FF },
|
|
{-0.138,1.580,0.445, -0.423,-0.034,0.905, 0xFF0000FF },
|
|
{0.140,1.580,0.445, 0.422,-0.034,0.906, 0xFF0000FF },
|
|
{-0.050,0.482,0.445, -0.464,-0.229,0.856, 0xFF0076FF },
|
|
{0.000,-0.067,0.447, 0.000,-0.599,0.800, 0xFF0076FF },
|
|
{0.000,0.255,0.447, 0.000,0.599,0.800, 0xFF0076FF },
|
|
{-0.155,0.094,0.447, -0.603,0.000,0.798, 0xFF0076FF },
|
|
{0.155,0.094,0.447, 0.603,0.000,0.798, 0xFF0076FF },
|
|
};
|
|
// 118 triangles
|
|
uint16_t g_tris_polySurfaceShape1[118][3] = {
|
|
{ 0, 1, 6 }
|
|
, { 6, 1, 7 }
|
|
, { 1, 2, 7 }
|
|
, { 7, 2, 8 }
|
|
, { 2, 3, 8 }
|
|
, { 8, 3, 9 }
|
|
, { 3, 4, 9 }
|
|
, { 9, 4, 10 }
|
|
, { 4, 5, 10 }
|
|
, { 10, 5, 11 }
|
|
, { 5, 0, 11 }
|
|
, { 11, 0, 6 }
|
|
, { 1, 0, 12 }
|
|
, { 2, 1, 12 }
|
|
, { 3, 2, 12 }
|
|
, { 4, 3, 12 }
|
|
, { 5, 4, 12 }
|
|
, { 0, 5, 12 }
|
|
, { 43, 44, 45 }
|
|
, { 44, 46, 45 }
|
|
, { 46, 47, 45 }
|
|
, { 47, 48, 45 }
|
|
, { 48, 49, 45 }
|
|
, { 49, 43, 45 }
|
|
, { 28, 30, 29 }
|
|
, { 30, 28, 31 }
|
|
, { 32, 34, 33 }
|
|
, { 35, 37, 36 }
|
|
, { 36, 39, 38 }
|
|
, { 38, 41, 40 }
|
|
, { 34, 40, 41 }
|
|
, { 40, 34, 32 }
|
|
, { 37, 35, 42 }
|
|
, { 39, 36, 37 }
|
|
, { 41, 38, 39 }
|
|
, { 62, 63, 61 }
|
|
, { 61, 64, 62 }
|
|
, { 51, 52, 50 }
|
|
, { 54, 55, 53 }
|
|
, { 55, 57, 56 }
|
|
, { 57, 59, 58 }
|
|
, { 50, 58, 59 }
|
|
, { 59, 51, 50 }
|
|
, { 53, 60, 54 }
|
|
, { 56, 53, 55 }
|
|
, { 58, 56, 57 }
|
|
, { 13, 28, 15 }
|
|
, { 28, 29, 15 }
|
|
, { 15, 29, 14 }
|
|
, { 29, 30, 14 }
|
|
, { 14, 30, 16 }
|
|
, { 30, 31, 16 }
|
|
, { 16, 31, 13 }
|
|
, { 31, 28, 13 }
|
|
, { 20, 32, 19 }
|
|
, { 32, 33, 19 }
|
|
, { 19, 33, 21 }
|
|
, { 33, 34, 21 }
|
|
, { 18, 35, 22 }
|
|
, { 35, 36, 22 }
|
|
, { 22, 36, 24 }
|
|
, { 36, 38, 24 }
|
|
, { 24, 38, 26 }
|
|
, { 38, 40, 26 }
|
|
, { 21, 34, 27 }
|
|
, { 34, 41, 27 }
|
|
, { 26, 40, 20 }
|
|
, { 40, 32, 20 }
|
|
, { 23, 37, 17 }
|
|
, { 37, 42, 17 }
|
|
, { 17, 42, 18 }
|
|
, { 42, 35, 18 }
|
|
, { 25, 39, 23 }
|
|
, { 39, 37, 23 }
|
|
, { 27, 41, 25 }
|
|
, { 41, 39, 25 }
|
|
, { 7, 44, 6 }
|
|
, { 6, 44, 43 }
|
|
, { 8, 46, 7 }
|
|
, { 7, 46, 44 }
|
|
, { 9, 47, 8 }
|
|
, { 8, 47, 46 }
|
|
, { 9, 10, 47 }
|
|
, { 47, 10, 48 }
|
|
, { 10, 11, 48 }
|
|
, { 48, 11, 49 }
|
|
, { 11, 6, 49 }
|
|
, { 49, 6, 43 }
|
|
, { 19, 21, 52 }
|
|
, { 21, 50, 52 }
|
|
, { 19, 52, 20 }
|
|
, { 52, 51, 20 }
|
|
, { 18, 22, 54 }
|
|
, { 22, 55, 54 }
|
|
, { 22, 24, 55 }
|
|
, { 24, 57, 55 }
|
|
, { 26, 59, 24 }
|
|
, { 59, 57, 24 }
|
|
, { 21, 27, 50 }
|
|
, { 27, 58, 50 }
|
|
, { 20, 51, 26 }
|
|
, { 51, 59, 26 }
|
|
, { 18, 54, 17 }
|
|
, { 54, 60, 17 }
|
|
, { 17, 60, 23 }
|
|
, { 60, 53, 23 }
|
|
, { 23, 53, 25 }
|
|
, { 53, 56, 25 }
|
|
, { 27, 25, 58 }
|
|
, { 25, 56, 58 }
|
|
, { 14, 61, 15 }
|
|
, { 61, 63, 15 }
|
|
, { 13, 15, 62 }
|
|
, { 15, 63, 62 }
|
|
, { 13, 62, 16 }
|
|
, { 62, 64, 16 }
|
|
, { 14, 16, 61 }
|
|
, { 16, 64, 61 }
|
|
};
|
|
|
|
|
|
|
|
void ErrorRenderLoop::setDrawEnv(void)
|
|
{
|
|
cellGcmSetColorMask(CELL_GCM_COLOR_MASK_B|
|
|
CELL_GCM_COLOR_MASK_G|
|
|
CELL_GCM_COLOR_MASK_R|
|
|
CELL_GCM_COLOR_MASK_A);
|
|
|
|
cellGcmSetColorMaskMrt(0);
|
|
uint16_t x,y,w,h;
|
|
float min, max;
|
|
float scale[4],offset[4];
|
|
|
|
x = 0;
|
|
y = 0;
|
|
w = display_width;
|
|
h = display_height;
|
|
min = 0.0f;
|
|
max = 1.0f;
|
|
scale[0] = w * 0.5f;
|
|
scale[1] = h * -0.5f;
|
|
scale[2] = (max - min) * 0.5f;
|
|
scale[3] = 0.0f;
|
|
offset[0] = x + scale[0];
|
|
offset[1] = y + h * 0.5f;
|
|
offset[2] = (max + min) * 0.5f;
|
|
offset[3] = 0.0f;
|
|
|
|
cellGcmSetViewport(x, y, w, h, min, max, scale, offset);
|
|
cellGcmSetClearColor((64<<0)|(64<<8)|(64<<16)|(64<<24));
|
|
|
|
cellGcmSetDepthTestEnable(CELL_GCM_TRUE);
|
|
cellGcmSetDepthFunc(CELL_GCM_LESS);
|
|
|
|
}
|
|
|
|
void ErrorRenderLoop::setRenderState(void)
|
|
{
|
|
cellGcmSetVertexProgram(vertex_program, vertex_program_ucode);
|
|
cellGcmSetVertexDataArray(position_index,
|
|
0,
|
|
sizeof(Vertex_t),
|
|
3,
|
|
CELL_GCM_VERTEX_F,
|
|
CELL_GCM_LOCATION_LOCAL,
|
|
m_nVertPositionOffset);
|
|
cellGcmSetVertexDataArray(normal_index,
|
|
0,
|
|
sizeof(Vertex_t),
|
|
3,
|
|
CELL_GCM_VERTEX_F,
|
|
CELL_GCM_LOCATION_LOCAL,
|
|
m_nVertNormalOffset);
|
|
cellGcmSetVertexDataArray(color_index,
|
|
0,
|
|
sizeof(Vertex_t),
|
|
4,
|
|
CELL_GCM_VERTEX_UB,
|
|
CELL_GCM_LOCATION_LOCAL,
|
|
m_nVertColorOffset );
|
|
|
|
|
|
|
|
cellGcmSetFragmentProgram(fragment_program, fragment_offset);
|
|
|
|
}
|
|
|
|
|
|
void AngleMatrix( float yaw, float pitch, float roll, float matrix[16] )
|
|
{
|
|
float sy = sinf(yaw),cy = cosf( yaw ),sp = sinf( pitch ),cp = cosf( pitch ),sr = sinf( roll ),cr = cosf( roll );
|
|
|
|
// matrix = (YAW * PITCH) * ROLL
|
|
matrix[0*4+0] = cp*cy;
|
|
matrix[1*4+0] = cp*sy;
|
|
matrix[2*4+0] = -sp;
|
|
|
|
// NOTE: Do not optimize this to reduce multiplies! optimizer bug will screw this up.
|
|
matrix[0*4+1] = sr*sp*cy+cr*-sy;
|
|
matrix[1*4+1] = sr*sp*sy+cr*cy;
|
|
matrix[2*4+1] = sr*cp;
|
|
matrix[0*4+2] = (cr*sp*cy+-sr*-sy);
|
|
matrix[1*4+2] = (cr*sp*sy+-sr*cy);
|
|
matrix[2*4+2] = cr*cp;
|
|
|
|
matrix[0*4+3] = 0.0f;
|
|
matrix[1*4+3] = 0.0f;
|
|
matrix[2*4+3] = 0.0f;
|
|
|
|
matrix[3*4+0] = 0;
|
|
matrix[3*4+1] = 0;
|
|
matrix[3*4+2] = 0;
|
|
matrix[3*4+3] = 1;
|
|
}
|
|
|
|
|
|
|
|
// call this AFTER setRenderState and setRenderObject
|
|
void ErrorRenderLoop::setTransforms(float *M)
|
|
{
|
|
// transform
|
|
float P[16];
|
|
float V[16];
|
|
float VP[16];
|
|
|
|
// projection
|
|
buildProjection(P, -1.0f, 1.0f, -1.0f, 1.0f, 1.0, 10000.0f);
|
|
|
|
// 16:9 scale or 4:3 scale
|
|
matrixTranslate(V, 0.0f, 0.0f, -4.0);
|
|
V[0*4 + 0] = 1.0f / display_aspect_ratio;
|
|
V[1*4 + 1] = 1.0f;
|
|
|
|
// model view
|
|
matrixMul(VP, P, V);
|
|
|
|
matrixMul(MVP, VP, M);
|
|
|
|
cellGcmSetVertexProgramParameter(model_view_projection, MVP);
|
|
}
|
|
|
|
int32_t ErrorRenderLoop::setRenderObject(void)
|
|
{
|
|
void *ret = localMemoryAlign(128, sizeof(Vertex_t) * ARRAYSIZE( g_verts_polySurfaceShape1 ) );
|
|
m_pVertexBuffer = (Vertex_t*)ret;
|
|
memcpy( m_pVertexBuffer, g_verts_polySurfaceShape1, sizeof( g_verts_polySurfaceShape1 ) );
|
|
|
|
m_pIndexBuffer = (uint16_t *)localMemoryAlign( 128, sizeof( uint16_t ) * ARRAYSIZE( g_tris_polySurfaceShape1 ) * 3 );
|
|
memcpy( m_pIndexBuffer, g_tris_polySurfaceShape1, sizeof( g_tris_polySurfaceShape1 ) );
|
|
|
|
model_view_projection = cellGcmCgGetNamedParameter(vertex_program, "modelViewProj");
|
|
CELL_GCMUTIL_CG_PARAMETER_CHECK_ASSERT(model_view_projection);
|
|
CGparameter position = cellGcmCgGetNamedParameter(vertex_program, "position");
|
|
CELL_GCMUTIL_CG_PARAMETER_CHECK_ASSERT(position);
|
|
CGparameter normal = cellGcmCgGetNamedParameter(vertex_program, "normal");
|
|
CELL_GCMUTIL_CG_PARAMETER_CHECK_ASSERT(normal);
|
|
CGparameter color = cellGcmCgGetNamedParameter(vertex_program, "color");
|
|
CELL_GCMUTIL_CG_PARAMETER_CHECK_ASSERT(color);
|
|
|
|
// get Vertex Attribute index
|
|
position_index = cellGcmCgGetParameterResource(vertex_program, position) - CG_ATTR0;
|
|
normal_index = cellGcmCgGetParameterResource(vertex_program, normal) - CG_ATTR0;
|
|
color_index = cellGcmCgGetParameterResource(vertex_program, color) - CG_ATTR0;
|
|
|
|
// fragment program offset
|
|
CELL_GCMUTIL_CHECK_ASSERT(cellGcmAddressToOffset(fragment_program_ucode, &fragment_offset));
|
|
CELL_GCMUTIL_CHECK_ASSERT(cellGcmAddressToOffset(&m_pVertexBuffer->x, &m_nVertPositionOffset));
|
|
CELL_GCMUTIL_CHECK_ASSERT(cellGcmAddressToOffset(&m_pVertexBuffer->nx, &m_nVertNormalOffset));
|
|
CELL_GCMUTIL_CHECK_ASSERT(cellGcmAddressToOffset(&m_pVertexBuffer->rgba, &m_nVertColorOffset));
|
|
CELL_GCMUTIL_CHECK_ASSERT(cellGcmAddressToOffset(m_pIndexBuffer, &m_nIndexBufferLocalMemoryOffset));
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
const uint32_t g_nInitCmdBuffer = 0x1000;
|
|
|
|
int32_t SimpleContextCallback( struct CellGcmContextData *pData, uint32_t nSize )
|
|
{
|
|
*pData->current = CELL_GCM_JUMP( g_nInitCmdBuffer );
|
|
__sync();
|
|
CellGcmControl * pControlRegister = cellGcmGetControlRegister();
|
|
pControlRegister->put = g_nInitCmdBuffer;
|
|
do
|
|
{
|
|
sys_timer_usleep( 60 );
|
|
} while ( pControlRegister->get != g_nInitCmdBuffer );
|
|
pData->current = pData->begin;
|
|
return CELL_OK;
|
|
}
|
|
|
|
|
|
int ErrorRenderLoop::Run( void )
|
|
{
|
|
// Exit routines
|
|
{
|
|
// register sysutil exit callback
|
|
CELL_GCMUTIL_CHECK_ASSERT( cellSysutilRegisterCallback( 0, sysutil_exit_callback, this ) );
|
|
|
|
CELL_GCMUTIL_CHECK_ASSERT( cellSysutilCheckCallback() );
|
|
if ( !m_keepRunning )
|
|
return 0;
|
|
}
|
|
|
|
if( g_gcmSharedData.m_pIoMemory )
|
|
{
|
|
// GCM has already been initialized, no need to reinitialize it.
|
|
// But we have to drive RSX to our new command buffer
|
|
const uint32_t nCmdBufferOverfetchSlack = 1024;
|
|
//printf( "Entering Error Render Loop, reusing IO memory @%p size 0x%X; initial ctx={%p,%p,%p;fn=%p}\n", g_gcmSharedData.m_pIoMemory, g_gcmSharedData.m_nIoMemorySize, gCellGcmCurrentContext->begin, gCellGcmCurrentContext->current, gCellGcmCurrentContext->end, gCellGcmCurrentContext->callback );
|
|
cellGcmSetCurrentBuffer(
|
|
// start command buffer right after initialization fixed command buffer (always the first 4 k of IO memory)
|
|
( uint32_t* )( uint32_t( g_gcmSharedData.m_pIoMemory ) + g_nInitCmdBuffer ),
|
|
// the size is all of IO memory, minus initialization command buffer, minus overfetch amount in the end of command buffer to avoid a crash,
|
|
// minus 4 bytes to insert a JUMP to the start of command buffer when we run out of space
|
|
g_gcmSharedData.m_nIoMemorySize - nCmdBufferOverfetchSlack - g_nInitCmdBuffer - sizeof( uint32_t ) );
|
|
CellGcmContextData *pCurrentContext = gCellGcmCurrentContext;
|
|
pCurrentContext->callback = SimpleContextCallback;
|
|
|
|
CellGcmControl * pControlRegister = cellGcmGetControlRegister();
|
|
uint32_t nPut = pControlRegister->put;
|
|
uint32_t * pCurrentCmd = ( uint32_t* )( uint32_t( g_gcmSharedData.m_pIoMemory ) + nPut );
|
|
pCurrentContext->current = pCurrentCmd; // de facto current
|
|
|
|
// #ifndef _CERT
|
|
// if ( pControlRegister->put != g_nInitCmdBuffer || gCellGcmCurrentContext->current != ( uint32_t* )( uint32_t( g_gcmSharedData.m_pIoMemory ) + g_nInitCmdBuffer ) )
|
|
// {
|
|
// __builtin_snpause();
|
|
// }
|
|
// #endif
|
|
}
|
|
else
|
|
{
|
|
sys_addr_t allocatedAddress = NULL;
|
|
int smaResult = sys_memory_allocate( 1 * 1024 * 1024, SYS_MEMORY_PAGE_SIZE_1M, &allocatedAddress );
|
|
if( smaResult != CELL_OK )
|
|
return smaResult;
|
|
void* host_addr = (void*)allocatedAddress;
|
|
printf( "Entering Error Render loop, IO memory @%p...\n", host_addr );
|
|
CELL_GCMUTIL_ASSERT(host_addr != NULL);
|
|
CELL_GCMUTIL_CHECK_ASSERT(cellGcmInit(CB_SIZE, HOST_SIZE, host_addr));
|
|
}
|
|
|
|
if (initDisplay()!=0) return -1;
|
|
|
|
initShader();
|
|
|
|
setDrawEnv();
|
|
|
|
if (setRenderObject())
|
|
return -1;
|
|
|
|
setRenderState();
|
|
|
|
// 1st time
|
|
setRenderTarget(frame_index);
|
|
|
|
// rendering loop
|
|
CELL_GCMUTIL_ASSERT(m_keepRunning);
|
|
float flTime = 0;
|
|
uint32_t nFrames = 0;
|
|
while (m_keepRunning) {
|
|
// check system event
|
|
CELL_GCMUTIL_CHECK_ASSERT( cellSysutilCheckCallback() );
|
|
|
|
// clear frame buffer
|
|
cellGcmSetClearSurface(
|
|
CELL_GCM_CLEAR_Z |
|
|
CELL_GCM_CLEAR_R |
|
|
CELL_GCM_CLEAR_G |
|
|
CELL_GCM_CLEAR_B |
|
|
CELL_GCM_CLEAR_A
|
|
);
|
|
float tm[16];
|
|
AngleMatrix(0.1f * sinf( flTime * 0.5f ), 0.5f * sinf( flTime * 0.45f ), 0.1f * sinf( flTime*0.02f ), tm);
|
|
setTransforms(tm);
|
|
// set draw command
|
|
if( flTime > 4.0f )
|
|
{
|
|
cellGcmSetDrawIndexArray(CELL_GCM_PRIMITIVE_TRIANGLES, 3 * ARRAYSIZE( g_tris_polySurfaceShape1 ), CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16, CELL_GCM_LOCATION_LOCAL, m_nIndexBufferLocalMemoryOffset );
|
|
}
|
|
|
|
// start reading the command buffer
|
|
flip();
|
|
flTime += 1/60.0f;
|
|
nFrames ++;
|
|
}
|
|
printf( "Exiting Error Render loop, %u frames rendered", nFrames );
|
|
cellSysutilUnregisterCallback( 0 );
|
|
|
|
// Let RSX wait for final flip
|
|
cellGcmSetWaitFlip();
|
|
|
|
// Let PPU wait for all commands done (include waitFlip)
|
|
cellGcmFinish(1);
|
|
|
|
// let's just leak this memory to avoid problems due to initializing GCM in different places, it doesn't matter
|
|
//sys_memory_free( g_gcmSharedData.m_pIoMemory );
|
|
|
|
printf(".\n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
void sysutil_exit_callback(uint64_t status, uint64_t param, void* userdata)
|
|
{
|
|
(void) param;
|
|
(void) userdata;
|
|
|
|
switch(status) {
|
|
case CELL_SYSUTIL_REQUEST_EXITGAME:
|
|
((ErrorRenderLoop*)userdata)->m_keepRunning = false;
|
|
break;
|
|
case CELL_SYSUTIL_DRAWING_BEGIN:
|
|
case CELL_SYSUTIL_DRAWING_END:
|
|
case CELL_SYSUTIL_SYSTEM_MENU_OPEN:
|
|
case CELL_SYSUTIL_SYSTEM_MENU_CLOSE:
|
|
case CELL_SYSUTIL_BGMPLAYBACK_PLAY:
|
|
case CELL_SYSUTIL_BGMPLAYBACK_STOP:
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
|