//========= 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 #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; } }