void drawPlayerGun(player_s* p) { if(!p)return; gsPushMatrix(); useCamera(&p->camera); gsLoadIdentity(); GPU_SetDepthTestAndWriteMask(true, GPU_ALWAYS, GPU_WRITE_DEPTH); gsSwitchRenderMode(-1); GPU_SetAttributeBuffers( 2, // number of attributes (u32*)osConvertVirtToPhys(rectangleBaseAddr), // we use the start of linear heap as base since that's where all our buffers are located GPU_ATTRIBFMT(0, 3, GPU_FLOAT)|GPU_ATTRIBFMT(1, 2, GPU_FLOAT), // we want v0 (vertex position) and v1 (texcoord) 0xFFC, // mask : we want v0 and v1 0x10, // permutation : we use identity 1, // number of buffers : we have one attribute per buffer (u32[]){(u32)rectangleVertexData-rectangleBaseAddr}, // buffer offsets (placeholders) (u64[]){0x10}, // attribute permutations for each buffer (u8[]){2} // number of attributes for each buffer ); gsSetShader(&passthroughProgram); GPU_DrawArray(GPU_TRIANGLES, 6); GPU_SetDepthTestAndWriteMask(true, GPU_ALWAYS, GPU_WRITE_ALL); GPUCMD_AddWrite(GPUREG_ATTRIBBUFFER0_CONFIG0, (u32)crosshairVertexData-rectangleBaseAddr); textureBind(&crosshairTexture, GPU_TEXUNIT0); GPU_DrawArray(GPU_TRIANGLES, 6); GPU_SetDepthTestAndWriteMask(true, GPU_GREATER, GPU_WRITE_ALL); gsSwitchRenderMode(md2GsMode); gsTranslate(1.3, -1.65, -3.1); gsRotateY(p->tempAngle.y); gsRotateX(-p->tempAngle.x); gsRotateX(-0.1); gsRotateZ(M_PI/2); gsRotateY(-M_PI/2); gsRotateX(-M_PI/2); gsScale(3.0f/8, 3.0f/8, 3.0f/8); md2InstanceDraw(&p->gunInstance); gsPopMatrix(); }
static void sceneRender(void) { // Bind the shader program shaderProgramUse(&program); // Configure the first fragment shading substage to just pass through the vertex color // See https://www.opengl.org/sdk/docs/man2/xhtml/glTexEnv.xml for more insight GPU_SetTexEnv(0, GPU_TEVSOURCES(GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR), // RGB channels GPU_TEVSOURCES(GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR), // Alpha GPU_TEVOPERANDS(0, 0, 0), // RGB GPU_TEVOPERANDS(0, 0, 0), // Alpha GPU_REPLACE, GPU_REPLACE, // RGB, Alpha 0xFFFFFFFF); // Configure the "attribute buffers" (that is, the vertex input buffers) GPU_SetAttributeBuffers( 1, // Number of inputs per vertex (u32*)osConvertVirtToPhys((u32)vbo_data), // Location of the VBO GPU_ATTRIBFMT(0, 3, GPU_FLOAT), // Format of the inputs (in this case the only input is a 3-element float vector) 0xFFE, // Unused attribute mask, in our case bit 0 is cleared since it is used 0x0, // Attribute permutations (here it is the identity) 1, // Number of buffers (u32[]) { 0x0 }, // Buffer offsets (placeholders) (u64[]) { 0x0 }, // Attribute permutations for each buffer (identity again) (u8[]) { 1 }); // Number of attributes for each buffer // Upload the projection matrix GPU_SetFloatUniformMatrix(GPU_VERTEX_SHADER, uLoc_projection, &projection); // Draw the VBO GPU_DrawArray(GPU_TRIANGLES, vertex_list_count); }
void sf2d_draw_texture_part(const sf2d_texture *texture, int x, int y, int tex_x, int tex_y, int tex_w, int tex_h) { sf2d_vertex_pos_tex *vertices = sf2d_pool_malloc(4 * sizeof(sf2d_vertex_pos_tex)); vertices[0].position = (sf2d_vector_3f){(float)x, (float)y, 0.5f}; vertices[1].position = (sf2d_vector_3f){(float)x+tex_w, (float)y, 0.5f}; vertices[2].position = (sf2d_vector_3f){(float)x, (float)y+tex_h, 0.5f}; vertices[3].position = (sf2d_vector_3f){(float)x+tex_w, (float)y+tex_h, 0.5f}; float u0 = tex_x/(float)texture->pow2_w; float v0 = tex_y/(float)texture->pow2_h; float u1 = (tex_x+tex_w)/(float)texture->pow2_w; float v1 = (tex_y+tex_h)/(float)texture->pow2_h; vertices[0].texcoord = (sf2d_vector_2f){u0, v0}; vertices[1].texcoord = (sf2d_vector_2f){u1, v0}; vertices[2].texcoord = (sf2d_vector_2f){u0, v1}; vertices[3].texcoord = (sf2d_vector_2f){u1, v1}; sf2d_bind_texture(texture, GPU_TEXUNIT0); GPU_SetAttributeBuffers( 2, // number of attributes (u32*)osConvertVirtToPhys((u32)vertices), GPU_ATTRIBFMT(0, 3, GPU_FLOAT) | GPU_ATTRIBFMT(1, 2, GPU_FLOAT), 0xFFFC, //0b1100 0x10, 1, //number of buffers (u32[]){0x0}, // buffer offsets (placeholders) (u64[]){0x10}, // attribute permutations for each buffer (u8[]){2} // number of attributes for each buffer ); GPU_DrawArray(GPU_TRIANGLE_STRIP, 4); }
void sf2d_draw_texture_rotate_cut_scale(const sf2d_texture *texture, int x, int y, float rad, int tex_x, int tex_y, int tex_w, int tex_h, float x_scale, float y_scale) { sf2d_vertex_pos_tex *vertices = sf2d_pool_malloc(4 * sizeof(sf2d_vertex_pos_tex)); //Don't even try to understand what I'm doing here (because I don't even understand it). //Matrices are boring. int w2 = (texture->width * x_scale)/2.0f; int h2 = (texture->height * y_scale)/2.0f; vertices[0].position = (sf2d_vector_3f){(float)-w2, (float)-h2, 0.5f}; vertices[1].position = (sf2d_vector_3f){(float) w2, (float)-h2, 0.5f}; vertices[2].position = (sf2d_vector_3f){(float)-w2, (float) h2, 0.5f}; vertices[3].position = (sf2d_vector_3f){(float) w2, (float) h2, 0.5f}; float u0 = tex_x/(float)texture->pow2_w; float v0 = tex_y/(float)texture->pow2_h; float u1 = (tex_x+tex_w)/(float)texture->pow2_w; float v1 = (tex_y+tex_h)/(float)texture->pow2_h; vertices[0].texcoord = (sf2d_vector_2f){u0, v0}; vertices[1].texcoord = (sf2d_vector_2f){u1, v0}; vertices[2].texcoord = (sf2d_vector_2f){u0, v1}; vertices[3].texcoord = (sf2d_vector_2f){u1, v1}; float m[4*4]; matrix_set_z_rotation(m, rad); sf2d_vector_3f rot[4]; int i; for (i = 0; i < 4; i++) { vector_mult_matrix4x4(m, &vertices[i].position, &rot[i]); } vertices[0].position = (sf2d_vector_3f){rot[0].x + x + w2, rot[0].y + y + h2, rot[0].z}; vertices[1].position = (sf2d_vector_3f){rot[1].x + x * x_scale + w2, rot[1].y + y + h2, rot[1].z}; vertices[2].position = (sf2d_vector_3f){rot[2].x + x + w2, rot[2].y + y * y_scale + h2, rot[2].z}; vertices[3].position = (sf2d_vector_3f){rot[3].x + x * x_scale + w2, rot[3].y + y * y_scale + h2, rot[3].z}; sf2d_bind_texture(texture, GPU_TEXUNIT0); GPU_SetAttributeBuffers( 2, // number of attributes (u32*)osConvertVirtToPhys((u32)vertices), GPU_ATTRIBFMT(0, 3, GPU_FLOAT) | GPU_ATTRIBFMT(1, 2, GPU_FLOAT), 0xFFFC, //0b1100 0x10, 1, //number of buffers (u32[]){0x0}, // buffer offsets (placeholders) (u64[]){0x10}, // attribute permutations for each buffer (u8[]){2} // number of attributes for each buffer ); GPU_DrawArray(GPU_TRIANGLE_STRIP, 4); }
void drawPortals(portal_s* portals[], int n, renderSceneCallback_t callback, camera_s* c, int depth, u8 stencil) { if(!portals || !portalVertexData || !callback || !c || !depth)return; int i; gsSwitchRenderMode(-1); GPU_SetAttributeBuffers( 1, // number of attributes (u32*)osConvertVirtToPhys(portalBaseAddr), // we use the start of linear heap as base since that's where all our buffers are located GPU_ATTRIBFMT(0, 3, GPU_FLOAT), // we want v0 (vertex position) 0xFFE, // mask : we want v0 0x0, // permutation : we use identity 1, // number of buffers : we have one attribute per buffer (u32[]){(u32)portalOutlineVertexData-portalBaseAddr}, // buffer offsets (placeholders) (u64[]){0x0}, // attribute permutations for each buffer (u8[]){1} // number of attributes for each buffer ); gsPushMatrix(); shaderInstanceSetBool(portalProgram.vertexShader, 0, true); gsSetShader(&portalProgram); //TEMP int colorUniformLoc = shaderInstanceGetUniformLocation(portalProgram.vertexShader, "color"); GPU_SetTexEnv(0, GPU_TEVSOURCES(GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR), GPU_TEVSOURCES(GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR), GPU_TEVOPERANDS(0,0,0), GPU_TEVOPERANDS(0,0,0), GPU_MODULATE, GPU_MODULATE, 0xFFFFFFFF); for(i=0; i<n; i++) { portal_s* p = portals[i]; if(!p->draw)continue; GPU_SetFloatUniform(GPU_VERTEX_SHADER, colorUniformLoc, (u32*)(float[]){1.0f, p->color.z, p->color.y, p->color.x}, 1); gsPushMatrix(); gsTranslate(p->position.x, p->position.y, p->position.z); gsMultMatrix(p->matrix); gsUpdateTransformation(); GPU_DrawArray(GPU_TRIANGLE_STRIP, portalNumVertices); gsPopMatrix(); }
void sf2d_draw_texture_rotate(const sf2d_texture *texture, int x, int y, float rad) { sf2d_vertex_pos_tex *vertices = sf2d_pool_malloc(4 * sizeof(sf2d_vertex_pos_tex)); int w2 = texture->width/2.0f; int h2 = texture->height/2.0f; vertices[0].position = (sf2d_vector_3f){(float)-w2, (float)-h2, 0.5f}; vertices[1].position = (sf2d_vector_3f){(float) w2, (float)-h2, 0.5f}; vertices[2].position = (sf2d_vector_3f){(float)-w2, (float) h2, 0.5f}; vertices[3].position = (sf2d_vector_3f){(float) w2, (float) h2, 0.5f}; float u = texture->width/(float)texture->pow2_w; float v = texture->height/(float)texture->pow2_h; vertices[0].texcoord = (sf2d_vector_2f){0.0f, 0.0f}; vertices[1].texcoord = (sf2d_vector_2f){u, 0.0f}; vertices[2].texcoord = (sf2d_vector_2f){0.0f, v}; vertices[3].texcoord = (sf2d_vector_2f){u, v}; float m[4*4]; matrix_set_z_rotation(m, rad); sf2d_vector_3f rot[4]; int i; for (i = 0; i < 4; i++) { vector_mult_matrix4x4(m, &vertices[i].position, &rot[i]); } for (i = 0; i < 4; i++) { vertices[i].position = (sf2d_vector_3f){rot[i].x + x + w2, rot[i].y + y + h2, rot[i].z}; } sf2d_bind_texture(texture, GPU_TEXUNIT0); GPU_SetAttributeBuffers( 2, // number of attributes (u32*)osConvertVirtToPhys((u32)vertices), GPU_ATTRIBFMT(0, 3, GPU_FLOAT) | GPU_ATTRIBFMT(1, 2, GPU_FLOAT), 0xFFFC, //0b1100 0x10, 1, //number of buffers (u32[]){0x0}, // buffer offsets (placeholders) (u64[]){0x10}, // attribute permutations for each buffer (u8[]){2} // number of attributes for each buffer ); GPU_DrawArray(GPU_TRIANGLE_STRIP, 4); }
void gpuDrawVbo(u32 vbo) { VboData* vboData = (VboData*) vbo; if(vboData == NULL || vboData->data == NULL) { return; } gpuUpdateState(); static u32 attributeBufferOffset = 0; GPU_SetAttributeBuffers(vboData->attributeCount, (u32*) osConvertVirtToPhys((u32) vboData->data), vboData->attributes, vboData->attributeMask, vboData->attributePermutations, 1, &attributeBufferOffset, &vboData->attributePermutations, &vboData->attributeCount); if(vboData->indices != NULL) { GPU_DrawElements((GPU_Primitive_t) vboData->primitive, (u32*) vboData->indices, vboData->numVertices); } else { GPU_DrawArray((GPU_Primitive_t) vboData->primitive, vboData->numVertices); } }
void sf2d_draw_texture_scale(const sf2d_texture *texture, int x, int y, float x_scale, float y_scale) { sf2d_vertex_pos_tex *vertices = sf2d_pool_malloc(4 * sizeof(sf2d_vertex_pos_tex)); int ws = texture->width * x_scale; int hs = texture->height * y_scale; vertices[0].position = (sf2d_vector_3f){(float)x, (float)y, 0.5f}; vertices[1].position = (sf2d_vector_3f){(float)x+ws, (float)y, 0.5f}; vertices[2].position = (sf2d_vector_3f){(float)x, (float)y+hs, 0.5f}; vertices[3].position = (sf2d_vector_3f){(float)x+ws, (float)y+hs, 0.5f}; float u = texture->width/(float)texture->pow2_w; float v = texture->height/(float)texture->pow2_h; vertices[0].texcoord = (sf2d_vector_2f){0.0f, 0.0f}; vertices[1].texcoord = (sf2d_vector_2f){u, 0.0f}; vertices[2].texcoord = (sf2d_vector_2f){0.0f, v}; vertices[3].texcoord = (sf2d_vector_2f){u, v}; sf2d_bind_texture(texture, GPU_TEXUNIT0); GPU_SetAttributeBuffers( 2, // number of attributes (u32*)osConvertVirtToPhys((u32)vertices), GPU_ATTRIBFMT(0, 3, GPU_FLOAT) | GPU_ATTRIBFMT(1, 2, GPU_FLOAT), 0xFFFC, //0b1100 0x10, 1, //number of buffers (u32[]){0x0}, // buffer offsets (placeholders) (u64[]){0x10}, // attribute permutations for each buffer (u8[]){2} // number of attributes for each buffer ); GPU_DrawArray(GPU_TRIANGLE_STRIP, 4); }
void RectangleShape::draw() { if (!_device->isInitialized() || !_visible) return; updateTransform(); if (_color.a > 0) { ShaderProgram::setUniform(UNIFORM_MODELVIEW_NAME, getCombinedTransform()); #ifdef _3DS auto vertices = VertexPool::getInstance()-> pushVertices<VertexPositionTexture>(4); vertices[0].position = Vec2(0, 0); vertices[1].position = Vec2(_size.x, 0); vertices[2].position = Vec2(0, _size.y); vertices[3].position = Vec2(_size.x, _size.y); vertices[0].texcoord = Vec2::Zero; vertices[1].texcoord = Vec2::Zero; vertices[2].texcoord = Vec2::Zero; vertices[3].texcoord = Vec2::Zero; //========================================================================= GPU_SetTexEnv(0, GPU_TEVSOURCES(GPU_CONSTANT, GPU_CONSTANT, GPU_CONSTANT), GPU_TEVSOURCES(GPU_CONSTANT, GPU_CONSTANT, GPU_CONSTANT), GPU_TEVOPERANDS(0, 0, 0), GPU_TEVOPERANDS(0, 0, 0), GPU_REPLACE, GPU_REPLACE, _color.r | _color.g << 8 | _color.b << 16 | _color.a << 24); u32 bufferOffsets[] = { 0x00 }; u64 bufferPermutations[] = { 0x10 }; u8 bufferNumAttributes[] = { 2 }; GPU_SetAttributeBuffers( 2, (u32*)osConvertVirtToPhys((u32)vertices), GPU_ATTRIBFMT(0, 2, GPU_FLOAT) | GPU_ATTRIBFMT(1, 2, GPU_FLOAT), 0xFFFC, 0x10, 1, bufferOffsets, bufferPermutations, bufferNumAttributes); GPU_DrawArray(GPU_TRIANGLE_STRIP, 0, 4); #else Vec4 c = _color.toVector(); float vertices[] = { 0, 0, -0.5f, c.x, c.y, c.z, c.w, 0, 0, _size.x, 0, -0.5f, c.x, c.y, c.z, c.w, 0, 0, 0, _size.y, -0.5f, c.x, c.y, c.z, c.w, 0, 0, _size.x, _size.y, -0.5f, c.x, c.y, c.z, c.w, 0, 0 }; glUniform1i(ShaderProgram::getCurrentProgram()-> getUniformLocation("textureEnabled"), false); glBindBuffer(GL_ARRAY_BUFFER, _vbo); glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float) * 36, vertices); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(_vao); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glBindVertexArray(0); #endif // _3DS } if (getOutlineColor().a > 0) { _outline.setTransform(getCombinedTransform()); _outline.setLine(0, 0, _size.x, 0); _outline.draw(); _outline.setLine(_size.x, 0, _size.x, _size.y); _outline.draw(); _outline.setLine(0, _size.y, _size.x, _size.y); _outline.draw(); _outline.setLine(0, 0, 0, _size.y); _outline.draw(); } Node::draw(); }
static void menu_display_ctr_draw(void *data) { struct ctr_texture *texture = NULL; const float *color = NULL; ctr_video_t *ctr = (ctr_video_t*)video_driver_get_ptr(false); menu_display_ctx_draw_t *draw = (menu_display_ctx_draw_t*)data; if (!ctr || !draw) return; texture = (struct ctr_texture*)draw->texture; color = draw->coords->color; if (!texture) return; ctr_scale_vector_t scale_vector; ctr_set_scale_vector(&scale_vector, CTR_TOP_FRAMEBUFFER_WIDTH, CTR_TOP_FRAMEBUFFER_HEIGHT, texture->width, texture->height); ctrGuSetVertexShaderFloatUniform(0, (float*)&scale_vector, 1); if ((ctr->vertex_cache.size - (ctr->vertex_cache.current - ctr->vertex_cache.buffer)) < 1) ctr->vertex_cache.current = ctr->vertex_cache.buffer; ctr_vertex_t* v = ctr->vertex_cache.current++; v->x0 = draw->x; v->y0 = 240 - draw->height - draw->y; v->x1 = v->x0 + draw->width; v->y1 = v->y0 + draw->height; v->u0 = 0; v->v0 = 0; v->u1 = texture->active_width; v->v1 = texture->active_height; ctrGuSetAttributeBuffers(2, VIRT_TO_PHYS(v), CTRGU_ATTRIBFMT(GPU_SHORT, 4) << 0 | CTRGU_ATTRIBFMT(GPU_SHORT, 4) << 4, sizeof(ctr_vertex_t)); color = draw->coords->color; int colorR = (int)((*color++)*255.f); int colorG = (int)((*color++)*255.f); int colorB = (int)((*color++)*255.f); int colorA = (int)((*color++)*255.f); GPU_SetTexEnv(0, GPU_TEVSOURCES(GPU_TEXTURE0, GPU_CONSTANT, 0), GPU_TEVSOURCES(GPU_TEXTURE0, GPU_CONSTANT, 0), 0, 0, GPU_MODULATE, GPU_MODULATE, COLOR_ABGR(colorR,colorG,colorB,colorA) ); // GPU_SetTexEnv(0, // GPU_TEVSOURCES(GPU_CONSTANT, GPU_CONSTANT, 0), // GPU_TEVSOURCES(GPU_CONSTANT, GPU_CONSTANT, 0), // 0, // GPU_TEVOPERANDS(GPU_TEVOP_RGB_SRC_COLOR, GPU_TEVOP_RGB_SRC_COLOR, 0), // GPU_REPLACE, GPU_REPLACE, // 0x3FFFFFFF); ctrGuSetTexture(GPU_TEXUNIT0, VIRT_TO_PHYS(texture->data), texture->width, texture->height, GPU_TEXTURE_MAG_FILTER(GPU_LINEAR) | GPU_TEXTURE_MIN_FILTER(GPU_LINEAR) | GPU_TEXTURE_WRAP_S(GPU_CLAMP_TO_EDGE) | GPU_TEXTURE_WRAP_T(GPU_CLAMP_TO_EDGE), GPU_RGBA8); GPU_SetViewport(NULL, VIRT_TO_PHYS(ctr->drawbuffers.top.left), 0, 0, CTR_TOP_FRAMEBUFFER_HEIGHT, ctr->video_mode == CTR_VIDEO_MODE_800x240 ? CTR_TOP_FRAMEBUFFER_WIDTH * 2 : CTR_TOP_FRAMEBUFFER_WIDTH); GPU_DrawArray(GPU_GEOMETRY_PRIM, 0, 1); if (ctr->video_mode == CTR_VIDEO_MODE_3D) { GPU_SetViewport(NULL, VIRT_TO_PHYS(ctr->drawbuffers.top.right), 0, 0, CTR_TOP_FRAMEBUFFER_HEIGHT, CTR_TOP_FRAMEBUFFER_WIDTH); GPU_DrawArray(GPU_GEOMETRY_PRIM, 0, 1); } GPU_SetTexEnv(0, GPU_TEXTURE0, GPU_TEXTURE0, 0, 0, GPU_REPLACE, GPU_REPLACE, 0); // printf("(%i,%i,%i,%i) , (%i,%i)\n", (int)draw->x, (int)draw->y, (int)draw->width, (int)draw->height, texture->width, texture->height); }
static bool ctr_frame(void* data, const void* frame, unsigned width, unsigned height, unsigned pitch, const char* msg) { ctr_video_t* ctr = (ctr_video_t*)data; settings_t* settings = config_get_ptr(); static uint64_t currentTick,lastTick; static float fps = 0.0; static int total_frames = 0; static int frames = 0; extern bool select_pressed; if (!width || !height) { gspWaitForEvent(GSPEVENT_VBlank0, true); return true; } if(!aptMainLoop()) { event_command(EVENT_CMD_QUIT); return true; } if (select_pressed) { event_command(EVENT_CMD_QUIT); return true; } svcWaitSynchronization(gspEvents[GSPEVENT_P3D], 20000000); svcClearEvent(gspEvents[GSPEVENT_P3D]); svcWaitSynchronization(gspEvents[GSPEVENT_PPF], 20000000); svcClearEvent(gspEvents[GSPEVENT_PPF]); gfxSwapBuffersGpu(); frames++; if (ctr->vsync) svcWaitSynchronization(gspEvents[GSPEVENT_VBlank0], U64_MAX); svcClearEvent(gspEvents[GSPEVENT_VBlank0]); currentTick = svcGetSystemTick(); uint32_t diff = currentTick - lastTick; if(diff > CTR_CPU_TICKS_PER_SECOND) { fps = (float)frames * ((float) CTR_CPU_TICKS_PER_SECOND / (float) diff); lastTick = currentTick; frames = 0; } printf("fps: %8.4f frames: %i\r", fps, total_frames++); fflush(stdout); ctrGuSetMemoryFill(true, (u32*)CTR_GPU_FRAMEBUFFER, 0x00000000, (u32*)(CTR_GPU_FRAMEBUFFER + CTR_TOP_FRAMEBUFFER_WIDTH * CTR_TOP_FRAMEBUFFER_HEIGHT * sizeof(uint32_t)), 0x201, (u32*)CTR_GPU_DEPTHBUFFER, 0x00000000, (u32*)(CTR_GPU_DEPTHBUFFER + CTR_TOP_FRAMEBUFFER_WIDTH * CTR_TOP_FRAMEBUFFER_HEIGHT * sizeof(uint32_t)), 0x201); GPUCMD_SetBufferOffset(0); if (width > ctr->texture_width) width = ctr->texture_width; if (height > ctr->texture_height) height = ctr->texture_height; if(frame) { if(((((u32)(frame)) >= 0x14000000 && ((u32)(frame)) < 0x1c000000)) /* frame in linear memory */ && !((u32)frame & 0x7F) /* 128-byte aligned */ && !((pitch) & 0xF)) /* 16-byte aligned */ { /* can copy the buffer directly with the GPU */ ctrGuCopyImage(false, frame, pitch / 2, height, CTRGU_RGB565, false, ctr->texture_swizzled, ctr->texture_width, CTRGU_RGB565, true); } else { int i; uint16_t* dst = (uint16_t*)ctr->texture_linear; const uint8_t* src = frame; for (i = 0; i < height; i++) { memcpy(dst, src, width * sizeof(uint16_t)); dst += ctr->texture_width; src += pitch; } GSPGPU_FlushDataCache(NULL, ctr->texture_linear, ctr->texture_width * ctr->texture_height * sizeof(uint16_t)); ctrGuCopyImage(false, ctr->texture_linear, ctr->texture_width, ctr->menu.texture_height, CTRGU_RGB565, false, ctr->texture_swizzled, ctr->texture_width, CTRGU_RGB565, true); } } ctrGuSetTexture(GPU_TEXUNIT0, VIRT_TO_PHYS(ctr->texture_swizzled), ctr->texture_width, ctr->texture_height, GPU_TEXTURE_MAG_FILTER(GPU_LINEAR) | GPU_TEXTURE_MIN_FILTER(GPU_LINEAR) | GPU_TEXTURE_WRAP_S(GPU_CLAMP_TO_EDGE) | GPU_TEXTURE_WRAP_T(GPU_CLAMP_TO_EDGE), GPU_RGB565); ctr->frame_coords->u = width; ctr->frame_coords->v = height; GSPGPU_FlushDataCache(NULL, (u8*)ctr->frame_coords, sizeof(ctr_vertex_t)); ctrGuSetAttributeBuffersAddress(VIRT_TO_PHYS(ctr->frame_coords)); ctrGuSetVertexShaderFloatUniform(0, (float*)&ctr->scale_vector, 1); GPU_DrawArray(GPU_UNKPRIM, 1); if (ctr->menu_texture_enable) { GSPGPU_FlushDataCache(NULL, ctr->menu.texture_linear, ctr->menu.texture_width * ctr->menu.texture_height * sizeof(uint16_t)); ctrGuCopyImage(false, ctr->menu.texture_linear, ctr->menu.texture_width, ctr->menu.texture_height, CTRGU_RGBA4444,false, ctr->menu.texture_swizzled, ctr->menu.texture_width, CTRGU_RGBA4444, true); ctrGuSetTexture(GPU_TEXUNIT0, VIRT_TO_PHYS(ctr->menu.texture_swizzled), ctr->menu.texture_width, ctr->menu.texture_height, GPU_TEXTURE_MAG_FILTER(GPU_LINEAR) | GPU_TEXTURE_MIN_FILTER(GPU_LINEAR) | GPU_TEXTURE_WRAP_S(GPU_CLAMP_TO_EDGE) | GPU_TEXTURE_WRAP_T(GPU_CLAMP_TO_EDGE), GPU_RGBA4); ctrGuSetAttributeBuffersAddress(VIRT_TO_PHYS(ctr->menu.frame_coords)); ctrGuSetVertexShaderFloatUniform(1, (float*)&ctr->menu.scale_vector, 1); GPU_DrawArray(GPU_UNKPRIM, 1); } GPU_FinishDrawing(); GPUCMD_Finalize(); ctrGuFlushAndRun(true); ctrGuDisplayTransfer(true, CTR_GPU_FRAMEBUFFER, 240,400, CTRGU_RGBA8, gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL), 240,400,CTRGU_RGB8, CTRGU_MULTISAMPLE_NONE); ctr->frame_count++; return true; }
static bool ctr_frame(void* data, const void* frame, unsigned width, unsigned height, uint64_t frame_count, unsigned pitch, const char* msg) { uint32_t diff; static uint64_t currentTick,lastTick; ctr_video_t *ctr = (ctr_video_t*)data; settings_t *settings = config_get_ptr(); static float fps = 0.0; static int total_frames = 0; static int frames = 0; static struct retro_perf_counter ctrframe_f = {0}; uint32_t state_tmp; touchPosition state_tmp_touch; extern bool select_pressed; if (!width || !height) { gspWaitForEvent(GSPEVENT_VBlank0, true); return true; } if(!aptMainLoop()) { event_command(EVENT_CMD_QUIT); return true; } if (select_pressed) { event_command(EVENT_CMD_QUIT); return true; } state_tmp = hidKeysDown(); hidTouchRead(&state_tmp_touch); if((state_tmp & KEY_TOUCH) && (state_tmp_touch.py < 120)) { Handle lcd_handle; u8 not_2DS; extern PrintConsole* currentConsole; gfxBottomFramebuffers[0] = ctr->lcd_buttom_on ? (u8*)ctr->empty_framebuffer: (u8*)currentConsole->frameBuffer; CFGU_GetModelNintendo2DS(¬_2DS); if(not_2DS && srvGetServiceHandle(&lcd_handle, "gsp::Lcd") >= 0) { u32 *cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = ctr->lcd_buttom_on? 0x00120040: 0x00110040; cmdbuf[1] = 2; svcSendSyncRequest(lcd_handle); svcCloseHandle(lcd_handle); } ctr->lcd_buttom_on = !ctr->lcd_buttom_on; } svcWaitSynchronization(gspEvents[GSPEVENT_P3D], 20000000); svcClearEvent(gspEvents[GSPEVENT_P3D]); svcWaitSynchronization(gspEvents[GSPEVENT_PPF], 20000000); svcClearEvent(gspEvents[GSPEVENT_PPF]); frames++; if (ctr->vsync) svcWaitSynchronization(gspEvents[GSPEVENT_VBlank0], U64_MAX); svcClearEvent(gspEvents[GSPEVENT_VBlank0]); currentTick = svcGetSystemTick(); diff = currentTick - lastTick; if(diff > CTR_CPU_TICKS_PER_SECOND) { fps = (float)frames * ((float) CTR_CPU_TICKS_PER_SECOND / (float) diff); lastTick = currentTick; frames = 0; } // extern u32 __linear_heap_size; // extern u32 gpuCmdBufOffset; // extern u32 __heap_size; // printf("0x%08X 0x%08X 0x%08X\r", __heap_size, gpuCmdBufOffset, (__linear_heap_size - linearSpaceFree() +0x3FF) & ~0x3FF); // printf("fps: %8.4f frames: %i (%X)\r", fps, total_frames++, (__linear_heap_size - linearSpaceFree())); printf("fps: %8.4f frames: %i\r", fps, total_frames++); fflush(stdout); rarch_perf_init(&ctrframe_f, "ctrframe_f"); retro_perf_start(&ctrframe_f); if (ctr->should_resize) ctr_update_viewport(ctr); ctrGuSetMemoryFill(true, (u32*)CTR_GPU_FRAMEBUFFER, 0x00000000, (u32*)(CTR_GPU_FRAMEBUFFER + CTR_TOP_FRAMEBUFFER_WIDTH * CTR_TOP_FRAMEBUFFER_HEIGHT * sizeof(uint32_t)), 0x201, (u32*)CTR_GPU_DEPTHBUFFER, 0x00000000, (u32*)(CTR_GPU_DEPTHBUFFER + CTR_TOP_FRAMEBUFFER_WIDTH * CTR_TOP_FRAMEBUFFER_HEIGHT * sizeof(uint32_t)), 0x201); GPUCMD_SetBufferOffset(0); if (width > ctr->texture_width) width = ctr->texture_width; if (height > ctr->texture_height) height = ctr->texture_height; if(frame) { if(((((u32)(frame)) >= 0x14000000 && ((u32)(frame)) < 0x40000000)) /* frame in linear memory */ && !((u32)frame & 0x7F) /* 128-byte aligned */ && !((pitch) & 0xF)) /* 16-byte aligned */ { /* can copy the buffer directly with the GPU */ ctrGuCopyImage(false, frame, pitch / (ctr->rgb32? 4: 2), height, ctr->rgb32 ? CTRGU_RGBA8: CTRGU_RGB565, false, ctr->texture_swizzled, ctr->texture_width, ctr->rgb32 ? CTRGU_RGBA8: CTRGU_RGB565, true); } else { int i; uint8_t *dst = (uint8_t*)ctr->texture_linear; const uint8_t *src = frame; for (i = 0; i < height; i++) { memcpy(dst, src, width * (ctr->rgb32? 4: 2)); dst += ctr->texture_width * (ctr->rgb32? 4: 2); src += pitch; } GSPGPU_FlushDataCache(ctr->texture_linear, ctr->texture_width * ctr->texture_height * (ctr->rgb32? 4: 2)); ctrGuCopyImage(false, ctr->texture_linear, ctr->texture_width, ctr->texture_height, ctr->rgb32 ? CTRGU_RGBA8: CTRGU_RGB565, false, ctr->texture_swizzled, ctr->texture_width, ctr->rgb32 ? CTRGU_RGBA8: CTRGU_RGB565, true); } } ctrGuSetTexture(GPU_TEXUNIT0, VIRT_TO_PHYS(ctr->texture_swizzled), ctr->texture_width, ctr->texture_height, (ctr->smooth? GPU_TEXTURE_MAG_FILTER(GPU_LINEAR) | GPU_TEXTURE_MIN_FILTER(GPU_LINEAR) : GPU_TEXTURE_MAG_FILTER(GPU_NEAREST) | GPU_TEXTURE_MIN_FILTER(GPU_NEAREST)) | GPU_TEXTURE_WRAP_S(GPU_CLAMP_TO_EDGE) | GPU_TEXTURE_WRAP_T(GPU_CLAMP_TO_EDGE), ctr->rgb32 ? GPU_RGBA8: GPU_RGB565); ctr->frame_coords->u = width; ctr->frame_coords->v = height; GSPGPU_FlushDataCache(ctr->frame_coords, sizeof(ctr_vertex_t)); ctrGuSetAttributeBuffersAddress(VIRT_TO_PHYS(ctr->frame_coords)); ctrGuSetVertexShaderFloatUniform(0, (float*)&ctr->scale_vector, 1); /* ARGB --> RGBA */ if (ctr->rgb32) { GPU_SetTexEnv(0, GPU_TEVSOURCES(GPU_TEXTURE0, GPU_CONSTANT, 0), GPU_TEVSOURCES(GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR, 0), GPU_TEVOPERANDS(GPU_TEVOP_RGB_SRC_G, 0, 0), GPU_TEVOPERANDS(0, 0, 0), GPU_MODULATE, GPU_MODULATE, 0x0000FF); GPU_SetTexEnv(1, GPU_TEVSOURCES(GPU_TEXTURE0, GPU_CONSTANT, GPU_PREVIOUS), GPU_TEVSOURCES(GPU_PREVIOUS, GPU_PREVIOUS, 0), GPU_TEVOPERANDS(GPU_TEVOP_RGB_SRC_B, 0, 0), GPU_TEVOPERANDS(0, 0, 0), GPU_MULTIPLY_ADD, GPU_MODULATE, 0x00FF00); GPU_SetTexEnv(2, GPU_TEVSOURCES(GPU_TEXTURE0, GPU_CONSTANT, GPU_PREVIOUS), GPU_TEVSOURCES(GPU_PREVIOUS, GPU_PREVIOUS, 0), GPU_TEVOPERANDS(GPU_TEVOP_RGB_SRC_ALPHA, 0, 0), GPU_TEVOPERANDS(0, 0, 0), GPU_MULTIPLY_ADD, GPU_MODULATE, 0xFF0000); } GPU_DrawArray(GPU_GEOMETRY_PRIM, 0, 1); /* restore */ if (ctr->rgb32) { GPU_SetTexEnv(0, GPU_TEVSOURCES(GPU_TEXTURE0, GPU_PRIMARY_COLOR, 0), GPU_TEVSOURCES(GPU_TEXTURE0, GPU_PRIMARY_COLOR, 0), GPU_TEVOPERANDS(0, 0, 0), GPU_TEVOPERANDS(0, 0, 0), GPU_MODULATE, GPU_MODULATE, 0xFFFFFFFF); GPU_SetTexEnv(1, GPU_PREVIOUS,GPU_PREVIOUS, 0, 0, 0, 0, 0); GPU_SetTexEnv(2, GPU_PREVIOUS,GPU_PREVIOUS, 0, 0, 0, 0, 0); } if (ctr->menu_texture_enable) { GSPGPU_FlushDataCache(ctr->menu.texture_linear, ctr->menu.texture_width * ctr->menu.texture_height * sizeof(uint16_t)); ctrGuCopyImage(false, ctr->menu.texture_linear, ctr->menu.texture_width, ctr->menu.texture_height, CTRGU_RGBA4444,false, ctr->menu.texture_swizzled, ctr->menu.texture_width, CTRGU_RGBA4444, true); ctrGuSetTexture(GPU_TEXUNIT0, VIRT_TO_PHYS(ctr->menu.texture_swizzled), ctr->menu.texture_width, ctr->menu.texture_height, GPU_TEXTURE_MAG_FILTER(GPU_LINEAR) | GPU_TEXTURE_MIN_FILTER(GPU_LINEAR) | GPU_TEXTURE_WRAP_S(GPU_CLAMP_TO_EDGE) | GPU_TEXTURE_WRAP_T(GPU_CLAMP_TO_EDGE), GPU_RGBA4); ctrGuSetAttributeBuffersAddress(VIRT_TO_PHYS(ctr->menu.frame_coords)); ctrGuSetVertexShaderFloatUniform(0, (float*)&ctr->menu.scale_vector, 1); GPU_DrawArray(GPU_GEOMETRY_PRIM, 0, 1); } GPU_FinishDrawing(); GPUCMD_Finalize(); ctrGuFlushAndRun(true); ctrGuDisplayTransfer(true, CTR_GPU_FRAMEBUFFER, 240,400, CTRGU_RGBA8, gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL), 240,400,CTRGU_RGB8, CTRGU_MULTISAMPLE_NONE); gfxSwapBuffersGpu(); retro_perf_stop(&ctrframe_f); return true; }
static bool ctr_frame(void* data, const void* frame, unsigned width, unsigned height, uint64_t frame_count, unsigned pitch, const char* msg) { uint32_t diff; static uint64_t currentTick,lastTick; ctr_video_t *ctr = (ctr_video_t*)data; settings_t *settings = config_get_ptr(); static float fps = 0.0; static int total_frames = 0; static int frames = 0; static struct retro_perf_counter ctrframe_f = {0}; uint32_t state_tmp; touchPosition state_tmp_touch; extern bool select_pressed; if (!width || !height) { gspWaitForEvent(GSPGPU_EVENT_VBlank0, true); return true; } if(!aptMainLoop()) { command_event(CMD_EVENT_QUIT, NULL); return true; } if (select_pressed) { command_event(CMD_EVENT_QUIT, NULL); return true; } state_tmp = hidKeysDown(); hidTouchRead(&state_tmp_touch); if((state_tmp & KEY_TOUCH) && (state_tmp_touch.py < 120)) { Handle lcd_handle; u8 not_2DS; extern PrintConsole* currentConsole; gfxBottomFramebuffers[0] = ctr->lcd_buttom_on ? (u8*)ctr->empty_framebuffer: (u8*)currentConsole->frameBuffer; CFGU_GetModelNintendo2DS(¬_2DS); if(not_2DS && srvGetServiceHandle(&lcd_handle, "gsp::Lcd") >= 0) { u32 *cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = ctr->lcd_buttom_on? 0x00120040: 0x00110040; cmdbuf[1] = 2; svcSendSyncRequest(lcd_handle); svcCloseHandle(lcd_handle); } ctr->lcd_buttom_on = !ctr->lcd_buttom_on; } svcWaitSynchronization(gspEvents[GSPGPU_EVENT_P3D], 20000000); svcClearEvent(gspEvents[GSPGPU_EVENT_P3D]); svcWaitSynchronization(gspEvents[GSPGPU_EVENT_PPF], 20000000); svcClearEvent(gspEvents[GSPGPU_EVENT_PPF]); frames++; if (ctr->vsync) svcWaitSynchronization(gspEvents[GSPGPU_EVENT_VBlank0], U64_MAX); svcClearEvent(gspEvents[GSPGPU_EVENT_VBlank0]); currentTick = svcGetSystemTick(); diff = currentTick - lastTick; if(diff > CTR_CPU_TICKS_PER_SECOND) { fps = (float)frames * ((float) CTR_CPU_TICKS_PER_SECOND / (float) diff); lastTick = currentTick; frames = 0; } //#define CTR_INSPECT_MEMORY_USAGE #ifdef CTR_INSPECT_MEMORY_USAGE uint32_t ctr_get_stack_usage(void); void ctr_linear_get_stats(void); extern u32 __linear_heap_size; extern u32 __heap_size; MemInfo mem_info; PageInfo page_info; u32 query_addr = 0x08000000; printf(PRINTFPOS(0,0)); while (query_addr < 0x40000000) { svcQueryMemory(&mem_info, &page_info, query_addr); printf("0x%08X --> 0x%08X (0x%08X) \n", mem_info.base_addr, mem_info.base_addr + mem_info.size, mem_info.size); query_addr = mem_info.base_addr + mem_info.size; if(query_addr == 0x1F000000) query_addr = 0x30000000; } // static u32* dummy_pointer; // if(total_frames == 500) // dummy_pointer = malloc(0x2000000); // if(total_frames == 1000) // free(dummy_pointer); printf("========================================"); printf("0x%08X 0x%08X 0x%08X\n", __heap_size, gpuCmdBufOffset, (__linear_heap_size - linearSpaceFree())); printf("fps: %8.4f frames: %i (%X)\n", fps, total_frames++, (__linear_heap_size - linearSpaceFree())); printf("========================================"); u32 app_memory = *((u32*)0x1FF80040); u64 mem_used; svcGetSystemInfo(&mem_used, 0, 1); printf("total mem : 0x%08X \n", app_memory); printf("used: 0x%08X free: 0x%08X \n", (u32)mem_used, app_memory - (u32)mem_used); static u32 stack_usage = 0; extern u32 __stack_bottom; if(!(total_frames & 0x3F)) stack_usage = ctr_get_stack_usage(); printf("stack total:0x%08X used: 0x%08X\n", 0x10000000 - __stack_bottom, stack_usage); printf("========================================"); ctr_linear_get_stats(); printf("========================================"); #else printf(PRINTFPOS(29,0)"fps: %8.4f frames: %i\r", fps, total_frames++); #endif fflush(stdout); performance_counter_init(&ctrframe_f, "ctrframe_f"); performance_counter_start(&ctrframe_f); if (ctr->should_resize) ctr_update_viewport(ctr); ctrGuSetMemoryFill(true, (u32*)CTR_TOP_FRAMEBUFFER, 0x00000000, (u32*)(CTR_TOP_FRAMEBUFFER + 2 * CTR_TOP_FRAMEBUFFER_WIDTH * CTR_TOP_FRAMEBUFFER_HEIGHT * sizeof(uint32_t)), 0x201, (u32*)CTR_GPU_DEPTHBUFFER, 0x00000000, (u32*)(CTR_GPU_DEPTHBUFFER + CTR_TOP_FRAMEBUFFER_WIDTH * CTR_TOP_FRAMEBUFFER_HEIGHT * sizeof(uint32_t)), 0x201); GPUCMD_SetBufferOffset(0); if (width > ctr->texture_width) width = ctr->texture_width; if (height > ctr->texture_height) height = ctr->texture_height; if(frame) { if(((((u32)(frame)) >= 0x14000000 && ((u32)(frame)) < 0x40000000)) /* frame in linear memory */ && !((u32)frame & 0x7F) /* 128-byte aligned */ && !(pitch & 0xF) /* 16-byte aligned */ && (pitch > 0x40)) { /* can copy the buffer directly with the GPU */ // GSPGPU_FlushDataCache(frame, pitch * height); ctrGuSetCommandList_First(true,(void*)frame, pitch * height,0,0,0,0); ctrGuCopyImage(true, frame, pitch / (ctr->rgb32? 4: 2), height, ctr->rgb32 ? CTRGU_RGBA8: CTRGU_RGB565, false, ctr->texture_swizzled, ctr->texture_width, ctr->rgb32 ? CTRGU_RGBA8: CTRGU_RGB565, true); } else { int i; uint8_t *dst = (uint8_t*)ctr->texture_linear; const uint8_t *src = frame; for (i = 0; i < height; i++) { memcpy(dst, src, width * (ctr->rgb32? 4: 2)); dst += ctr->texture_width * (ctr->rgb32? 4: 2); src += pitch; } GSPGPU_FlushDataCache(ctr->texture_linear, ctr->texture_width * ctr->texture_height * (ctr->rgb32? 4: 2)); ctrGuCopyImage(false, ctr->texture_linear, ctr->texture_width, ctr->texture_height, ctr->rgb32 ? CTRGU_RGBA8: CTRGU_RGB565, false, ctr->texture_swizzled, ctr->texture_width, ctr->rgb32 ? CTRGU_RGBA8: CTRGU_RGB565, true); } ctr->frame_coords->u0 = 0; ctr->frame_coords->v0 = 0; ctr->frame_coords->u1 = width; ctr->frame_coords->v1 = height; GSPGPU_FlushDataCache(ctr->frame_coords, sizeof(ctr_vertex_t)); ctrGuSetVertexShaderFloatUniform(0, (float*)&ctr->scale_vector, 1); } ctrGuSetTexture(GPU_TEXUNIT0, VIRT_TO_PHYS(ctr->texture_swizzled), ctr->texture_width, ctr->texture_height, (ctr->smooth? GPU_TEXTURE_MAG_FILTER(GPU_LINEAR) | GPU_TEXTURE_MIN_FILTER(GPU_LINEAR) : GPU_TEXTURE_MAG_FILTER(GPU_NEAREST) | GPU_TEXTURE_MIN_FILTER(GPU_NEAREST)) | GPU_TEXTURE_WRAP_S(GPU_CLAMP_TO_EDGE) | GPU_TEXTURE_WRAP_T(GPU_CLAMP_TO_EDGE), ctr->rgb32 ? GPU_RGBA8: GPU_RGB565); ctr_check_3D_slider(ctr); /* ARGB --> RGBA */ if (ctr->rgb32) { GPU_SetTexEnv(0, GPU_TEVSOURCES(GPU_TEXTURE0, GPU_CONSTANT, 0), GPU_TEVSOURCES(GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR, 0), GPU_TEVOPERANDS(GPU_TEVOP_RGB_SRC_G, 0, 0), GPU_TEVOPERANDS(0, 0, 0), GPU_MODULATE, GPU_MODULATE, 0x0000FF); GPU_SetTexEnv(1, GPU_TEVSOURCES(GPU_TEXTURE0, GPU_CONSTANT, GPU_PREVIOUS), GPU_TEVSOURCES(GPU_PREVIOUS, GPU_PREVIOUS, 0), GPU_TEVOPERANDS(GPU_TEVOP_RGB_SRC_B, 0, 0), GPU_TEVOPERANDS(0, 0, 0), GPU_MULTIPLY_ADD, GPU_MODULATE, 0x00FF00); GPU_SetTexEnv(2, GPU_TEVSOURCES(GPU_TEXTURE0, GPU_CONSTANT, GPU_PREVIOUS), GPU_TEVSOURCES(GPU_PREVIOUS, GPU_PREVIOUS, 0), GPU_TEVOPERANDS(GPU_TEVOP_RGB_SRC_ALPHA, 0, 0), GPU_TEVOPERANDS(0, 0, 0), GPU_MULTIPLY_ADD, GPU_MODULATE, 0xFF0000); } GPU_SetViewport(VIRT_TO_PHYS(CTR_GPU_DEPTHBUFFER), VIRT_TO_PHYS(CTR_TOP_FRAMEBUFFER), 0, 0, CTR_TOP_FRAMEBUFFER_HEIGHT, ctr->video_mode == CTR_VIDEO_MODE_800x240 ? CTR_TOP_FRAMEBUFFER_WIDTH * 2 : CTR_TOP_FRAMEBUFFER_WIDTH); if (ctr->video_mode == CTR_VIDEO_MODE_3D) { if (ctr->menu_texture_enable) { ctrGuSetAttributeBuffersAddress(VIRT_TO_PHYS(&ctr->frame_coords[1])); GPU_DrawArray(GPU_GEOMETRY_PRIM, 0, 1); ctrGuSetAttributeBuffersAddress(VIRT_TO_PHYS(&ctr->frame_coords[2])); } else { ctrGuSetAttributeBuffersAddress(VIRT_TO_PHYS(ctr->frame_coords)); GPU_DrawArray(GPU_GEOMETRY_PRIM, 0, 1); } GPU_SetViewport(VIRT_TO_PHYS(CTR_GPU_DEPTHBUFFER), VIRT_TO_PHYS(CTR_TOP_FRAMEBUFFER_RIGHT), 0, 0, CTR_TOP_FRAMEBUFFER_HEIGHT, CTR_TOP_FRAMEBUFFER_WIDTH); } else ctrGuSetAttributeBuffersAddress(VIRT_TO_PHYS(ctr->frame_coords)); GPU_DrawArray(GPU_GEOMETRY_PRIM, 0, 1); /* restore */ if (ctr->rgb32) { GPU_SetTexEnv(0, GPU_TEXTURE0, GPU_TEXTURE0, 0, 0, GPU_REPLACE, GPU_REPLACE, 0); GPU_SetTexEnv(1, GPU_PREVIOUS, GPU_PREVIOUS, 0, 0, 0, 0, 0); GPU_SetTexEnv(2, GPU_PREVIOUS, GPU_PREVIOUS, 0, 0, 0, 0, 0); } if (ctr->menu_texture_enable) { GSPGPU_FlushDataCache(ctr->menu.texture_linear, ctr->menu.texture_width * ctr->menu.texture_height * sizeof(uint16_t)); ctrGuCopyImage(false, ctr->menu.texture_linear, ctr->menu.texture_width, ctr->menu.texture_height, CTRGU_RGBA4444,false, ctr->menu.texture_swizzled, ctr->menu.texture_width, CTRGU_RGBA4444, true); ctrGuSetTexture(GPU_TEXUNIT0, VIRT_TO_PHYS(ctr->menu.texture_swizzled), ctr->menu.texture_width, ctr->menu.texture_height, GPU_TEXTURE_MAG_FILTER(GPU_LINEAR) | GPU_TEXTURE_MIN_FILTER(GPU_LINEAR) | GPU_TEXTURE_WRAP_S(GPU_CLAMP_TO_EDGE) | GPU_TEXTURE_WRAP_T(GPU_CLAMP_TO_EDGE), GPU_RGBA4); ctrGuSetVertexShaderFloatUniform(0, (float*)&ctr->menu.scale_vector, 1); GPU_SetViewport(VIRT_TO_PHYS(CTR_GPU_DEPTHBUFFER), VIRT_TO_PHYS(CTR_TOP_FRAMEBUFFER), 0, 0, CTR_TOP_FRAMEBUFFER_HEIGHT, ctr->video_mode == CTR_VIDEO_MODE_800x240 ? CTR_TOP_FRAMEBUFFER_WIDTH * 2 : CTR_TOP_FRAMEBUFFER_WIDTH); ctrGuSetAttributeBuffersAddress(VIRT_TO_PHYS(ctr->menu.frame_coords)); GPU_DrawArray(GPU_GEOMETRY_PRIM, 0, 1); if (ctr->video_mode == CTR_VIDEO_MODE_3D) { GPU_SetViewport(VIRT_TO_PHYS(CTR_GPU_DEPTHBUFFER), VIRT_TO_PHYS(CTR_TOP_FRAMEBUFFER_RIGHT), 0, 0, CTR_TOP_FRAMEBUFFER_HEIGHT, CTR_TOP_FRAMEBUFFER_WIDTH); GPU_DrawArray(GPU_GEOMETRY_PRIM, 0, 1); } } GPU_FinishDrawing(); GPUCMD_Finalize(); ctrGuFlushAndRun(true); ctrGuDisplayTransfer(true, CTR_TOP_FRAMEBUFFER, 240, ctr->video_mode == CTR_VIDEO_MODE_800x240 ? 800 : 400, CTRGU_RGBA8, gfxTopLeftFramebuffers[ctr->current_buffer_top], 240,CTRGU_RGB8, CTRGU_MULTISAMPLE_NONE); if ((ctr->video_mode == CTR_VIDEO_MODE_400x240) || (ctr->video_mode == CTR_VIDEO_MODE_3D)) ctrGuDisplayTransfer(true, CTR_TOP_FRAMEBUFFER_RIGHT, 240, 400, CTRGU_RGBA8, gfxTopRightFramebuffers[ctr->current_buffer_top], 240,CTRGU_RGB8, CTRGU_MULTISAMPLE_NONE); // Swap buffers : ctr->current_buffer_top ^= 1; extern GSPGPU_FramebufferInfo topFramebufferInfo; extern u8* gfxSharedMemory; extern u8 gfxThreadID; topFramebufferInfo.active_framebuf=ctr->current_buffer_top; topFramebufferInfo.framebuf0_vaddr=(u32*)gfxTopLeftFramebuffers[ctr->current_buffer_top]; if(ctr->video_mode == CTR_VIDEO_MODE_800x240) { topFramebufferInfo.framebuf1_vaddr=(u32*)(gfxTopLeftFramebuffers[ctr->current_buffer_top] + 240 * 3); topFramebufferInfo.framebuf_widthbytesize = 240 * 3 * 2; } else { topFramebufferInfo.framebuf1_vaddr=(u32*)gfxTopRightFramebuffers[ctr->current_buffer_top]; topFramebufferInfo.framebuf_widthbytesize = 240 * 3; } topFramebufferInfo.format=(1<<8)|(1<<5)|GSP_BGR8_OES; topFramebufferInfo.framebuf_dispselect=ctr->current_buffer_top; topFramebufferInfo.unk=0x00000000; u8* framebufferInfoHeader=gfxSharedMemory+0x200+gfxThreadID*0x80; GSPGPU_FramebufferInfo* framebufferInfo=(GSPGPU_FramebufferInfo*)&framebufferInfoHeader[0x4]; framebufferInfoHeader[0x0] ^= 1; framebufferInfo[framebufferInfoHeader[0x0]] = topFramebufferInfo; framebufferInfoHeader[0x1]=1; performance_counter_stop(&ctrframe_f); return true; }
void RenderTopScreen() { // notes on the drawing process // GPU hangs if we attempt to draw an even number of arrays :/ which is why we draw the border 'twice' // textures used here are actually 512x256. TODO: investigate if GPU_SetTexture() really has the params in the wrong order // or if we did something wrong. //general setup GPU_SetViewport((u32*)osConvertVirtToPhys((u32)gpuDOut),(u32*)osConvertVirtToPhys((u32)gpuOut),0,0,240*2,400); GPU_DepthRange(-1.0f, 0.0f); GPU_SetFaceCulling(GPU_CULL_BACK_CCW); GPU_SetStencilTest(false, GPU_ALWAYS, 0x00); GPU_SetDepthTest(false, GPU_ALWAYS, 0x1F); // ? GPUCMD_AddSingleParam(0x00010062, 0x00000000); //param always 0x0 according to code GPUCMD_AddSingleParam(0x000F0118, 0x00000000); //setup shader SHDR_UseProgram(shader, 0); //? GPUCMD_AddSingleParam(0x000F0100, 0x00E40100); GPUCMD_AddSingleParam(0x000F0101, 0x01010000); GPUCMD_AddSingleParam(0x000F0104, 0x00000010); //texturing stuff GPUCMD_AddSingleParam(0x0002006F, 0x00000100); GPUCMD_AddSingleParam(0x000F0080, 0x00011001); //enables/disables texturing //texenv GPU_SetTexEnv(0, GPU_TEVSOURCES(GPU_TEXTURE0, 0, 0), GPU_TEVSOURCES(GPU_CONSTANT, 0, 0), GPU_TEVOPERANDS(0,0,0), GPU_TEVOPERANDS(0,0,0), GPU_REPLACE, GPU_REPLACE, 0xFFFFFFFF); GPU_SetDummyTexEnv(1); GPU_SetDummyTexEnv(2); GPU_SetDummyTexEnv(3); GPU_SetDummyTexEnv(4); GPU_SetDummyTexEnv(5); //texturing stuff GPU_SetTexture((u32*)osConvertVirtToPhys((u32)BorderTex),256,512,0,GPU_RGBA8); // texture is actually 512x256 //setup matrices setUniformMatrix(0x24, mvMatrix); setUniformMatrix(0x20, projMatrix); // border GPU_SetAttributeBuffers(2, (u32*)osConvertVirtToPhys((u32)borderVertices), GPU_ATTRIBFMT(0, 3, GPU_FLOAT)|GPU_ATTRIBFMT(1, 2, GPU_FLOAT), 0xFFC, 0x10, 1, (u32[]){0x00000000}, (u64[]){0x10}, (u8[]){2}); GPU_DrawArray(GPU_TRIANGLES, 3); GPU_DrawArray(GPU_TRIANGLES, 2*3); GPU_DepthRange(-1.0f, 0.0f); GPU_SetFaceCulling(GPU_CULL_BACK_CCW); GPU_SetStencilTest(false, GPU_ALWAYS, 0x00); GPU_SetDepthTest(false, GPU_ALWAYS, 0x1F); GPUCMD_AddSingleParam(0x00010062, 0x00000000); GPUCMD_AddSingleParam(0x000F0118, 0x00000000); GPUCMD_AddSingleParam(0x000F0100, 0x00000100); GPUCMD_AddSingleParam(0x000F0101, 0x01010000); GPUCMD_AddSingleParam(0x000F0104, 0x00000010); //texturing stuff GPUCMD_AddSingleParam(0x0002006F, 0x00000700); // enables/disables texcoord output GPUCMD_AddSingleParam(0x000F0080, 0x00011007); //enables/disables texturing // TEXTURE ENV STAGES // --- // blending operation: (Main.Color +- (Sub.Color * Main.Alpha)) * Sub.Alpha // Main.Alpha = 0/255 depending on color math // Sub.Alpha = 128/255 depending on color div2 // note: the main/sub intensities are halved to prevent overflow during the operations. // (each TEV stage output is clamped to [0,255]) // stage 4 makes up for this // --- // STAGE 1: Out.Color = Sub.Color * Main.Alpha, Out.Alpha = Sub.Alpha + (1-Main.Alpha) (cancel out div2 when color math doesn't happen) GPU_SetTexEnv(0, GPU_TEVSOURCES(GPU_TEXTURE1, GPU_TEXTURE0, 0), GPU_TEVSOURCES(GPU_TEXTURE1, GPU_TEXTURE0, 0), GPU_TEVOPERANDS(0,2,0), GPU_TEVOPERANDS(0,1,0), GPU_MODULATE, GPU_ADD, 0xFFFFFFFF); // STAGE 2: Out.Color = Main.Color +- Prev.Color, Out.Alpha = Prev.Alpha GPU_SetTexEnv(1, GPU_TEVSOURCES(GPU_TEXTURE0, GPU_PREVIOUS, 0), GPU_TEVSOURCES(GPU_PREVIOUS, 0, 0), GPU_TEVOPERANDS(0,0,0), GPU_TEVOPERANDS(0,0,0), (PPU_ColorMath & 0x80) ? GPU_SUBTRACT:GPU_ADD, GPU_REPLACE, 0xFFFFFFFF); // STAGE 3: Out.Color = Prev.Color * Prev.Alpha, Out.Alpha = Prev.Alpha GPU_SetTexEnv(2, GPU_TEVSOURCES(GPU_PREVIOUS, GPU_PREVIOUS, 0), GPU_TEVSOURCES(GPU_PREVIOUS, 0, 0), GPU_TEVOPERANDS(0,2,0), GPU_TEVOPERANDS(0,0,0), GPU_MODULATE, GPU_REPLACE, 0xFFFFFFFF); // STAGE 4: Out.Color = Prev.Color + Prev.Color (doubling color intensity), Out.Alpha = Const.Alpha GPU_SetTexEnv(3, GPU_TEVSOURCES(GPU_PREVIOUS, GPU_PREVIOUS, 0), GPU_TEVSOURCES(GPU_CONSTANT, 0, 0), GPU_TEVOPERANDS(0,0,0), GPU_TEVOPERANDS(0,0,0), GPU_ADD, GPU_REPLACE, 0xFFFFFFFF); // STAGE 5: master brightness - Out.Color = Prev.Color * Bright.Alpha, Out.Alpha = Const.Alpha GPU_SetTexEnv(4, GPU_TEVSOURCES(GPU_PREVIOUS, GPU_TEXTURE2, 0), GPU_TEVSOURCES(GPU_CONSTANT, 0, 0), GPU_TEVOPERANDS(0,2,0), GPU_TEVOPERANDS(0,0,0), GPU_MODULATE, GPU_REPLACE, 0xFFFFFFFF); // STAGE 6: dummy GPU_SetDummyTexEnv(5); GPU_SetAttributeBuffers(3, (u32*)osConvertVirtToPhys((u32)screenVertices), GPU_ATTRIBFMT(0, 3, GPU_FLOAT)|GPU_ATTRIBFMT(1, 2, GPU_FLOAT)|GPU_ATTRIBFMT(2, 2, GPU_FLOAT), 0xFFC, 0x210, 1, (u32[]){0x00000000}, (u64[]){0x210}, (u8[]){3}); GPU_SetTexture((u32*)osConvertVirtToPhys((u32)MainScreenTex),256,512,0,GPU_RGBA8); GPU_SetTexture1((u32*)osConvertVirtToPhys((u32)SubScreenTex),256,512,0,GPU_RGBA8); GPU_SetTexture2((u32*)osConvertVirtToPhys((u32)BrightnessTex),256,8,0x200,GPU_A8); GPU_DrawArray(GPU_TRIANGLES, 2*3); }