void glBindTexture(GLenum target, GLuint texture) { //printf("bind texture: %d %08x\n", ctr_state.client_texture_current, texture); if (texture == 0) { DBGPRINT("binding 0 texture\n"); ctr_state.bound_texture[ctr_state.client_texture_current] = 0; return; } CTR_TEXTURE *tx = ctr_handle_get(CTR_HANDLE_TEXTURE, texture); DBGPRINT("bound texture: %d %08x %08x\n", ctr_state.client_texture_current, texture, tx); if (tx == 0) { tx = malloc(sizeof(*tx)); if (tx == 0) { return; } memset(tx, 0, sizeof(*tx)); tx->params = GPU_TEXTURE_MAG_FILTER(GPU_LINEAR) | GPU_TEXTURE_WRAP_S(GPU_REPEAT) | GPU_TEXTURE_WRAP_T(GPU_REPEAT); ctr_handle_set(CTR_HANDLE_TEXTURE, texture, tx); } ctr_state.bound_texture[ctr_state.client_texture_current] = texture; //#ifdef _3DS if (tx->data) { myGPU_SetTexture( __tmu[ctr_state.client_texture_current], osConvertVirtToPhys((u32)tx->data), tx->width, // Width tx->height, // Height tx->params, // Flags tx->format // Pixel format ); } //#endif }
void TextEngine::Initialize(gfxScreen_t scn) { //The two screens are different sizes if(scn == GFX_TOP) { target = C3D_RenderTargetCreate(240, 400, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8); } else { target = C3D_RenderTargetCreate(240, 320, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8); } C3D_RenderTargetSetClear(target, C3D_CLEAR_ALL, CLEAR_COLOR, 0); C3D_RenderTargetSetOutput(target, scn, GFX_LEFT, DISPLAY_TRANSFER_FLAGS); Result res = fontEnsureMapped(); if (R_FAILED(res)) printf("fontEnsureMapped: %08lX\n", res); vshader_dvlb = DVLB_ParseFile((u32*)vshader_v_shbin, vshader_v_shbin_size); shaderProgramInit(&program); shaderProgramSetVsh(&program, &vshader_dvlb->DVLE[0]); C3D_BindProgram(&program); // Get the location of the uniforms uLoc_projection = shaderInstanceGetUniformLocation(program.vertexShader, "projection"); // Configure attributes for use with the vertex shader C3D_AttrInfo* attrInfo = C3D_GetAttrInfo(); AttrInfo_Init(attrInfo); AttrInfo_AddLoader(attrInfo, 0, GPU_FLOAT, 3); // v0=position AttrInfo_AddLoader(attrInfo, 1, GPU_FLOAT, 2); // v1=texcoord if(scn == GFX_TOP) { // Compute the projection matrix Mtx_OrthoTilt(&projection, 0.0, 400.0, 240.0, 0.0, 0.0, 1.0); } else { Mtx_OrthoTilt(&projection, 0.0, 320.0, 240.0, 0.0, 0.0, 1.0); } // Configure depth test to overwrite pixels with the same depth (needed to draw overlapping glyphs) C3D_DepthTest(true, GPU_GEQUAL, GPU_WRITE_ALL); // Load the glyph texture sheets int i; TGLP_s* glyphInfo = fontGetGlyphInfo(); glyphSheets = malloc(sizeof(C3D_Tex)*glyphInfo->nSheets); for (i = 0; i < glyphInfo->nSheets; i ++) { C3D_Tex* tex = &glyphSheets[i]; tex->data = fontGetGlyphSheetTex(i); tex->fmt = glyphInfo->sheetFmt; tex->size = glyphInfo->sheetSize; tex->width = glyphInfo->sheetWidth; tex->height = glyphInfo->sheetHeight; tex->param = 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); } // Create the text vertex array textVtxArray = (textVertex_s*)linearAlloc(sizeof(textVertex_s)*TEXT_VTX_ARRAY_COUNT); }
void initEmancipation(void) { int i; for(i=0;i<NUMEMANCIPATORS;i++) { emancipators[i].used=false; } for(i=0;i<NUMEMANCIPATIONGRIDS;i++) { emancipationGrids[i].used=false; } md2ReadModel(&gridModel, "grid.md2"); textureLoad(&gridTexture, "balllauncher.png", GPU_TEXTURE_MAG_FILTER(GPU_LINEAR)|GPU_TEXTURE_MIN_FILTER(GPU_LINEAR), 0); textureLoad(&gridSurfaceTexture, "grid.png", GPU_TEXTURE_MAG_FILTER(GPU_LINEAR)|GPU_TEXTURE_MIN_FILTER(GPU_LINEAR)|GPU_TEXTURE_WRAP_S(GPU_REPEAT)|GPU_TEXTURE_WRAP_T(GPU_REPEAT), 0); md2InstanceInit(&gridInstance, &gridModel, &gridTexture); emancipationRectangleVertexData = linearAlloc(sizeof(emancipationRectangleData)); memcpy(emancipationRectangleVertexData, emancipationRectangleData, sizeof(emancipationRectangleData)); emancipationDvlb = DVLB_ParseFile((u32*)emancipation_vsh_shbin, emancipation_vsh_shbin_size); if(!emancipationDvlb)return; shaderProgramInit(&emancipationProgram); shaderProgramSetVsh(&emancipationProgram, &emancipationDvlb->DVLE[0]); emancipationUniformTextureDimensions = shaderInstanceGetUniformLocation(emancipationProgram.vertexShader, "textureDimensions"); emancipationSFX=createSFX("emancipation.raw", SOUND_FORMAT_16BIT); }
void glGenTextures(GLsizei n, GLuint * textures) { if (n <= 0 || textures == 0) { return; } GLuint i; for (i = 0; i < n; i++) { CTR_TEXTURE *buf = malloc(sizeof(*buf)); if (buf == 0) { return; } memset(buf, 0, sizeof(*buf)); buf->params = GPU_TEXTURE_MAG_FILTER(GPU_LINEAR) | GPU_TEXTURE_WRAP_S(GPU_REPEAT) | GPU_TEXTURE_WRAP_T(GPU_REPEAT); textures[i] = ctr_handle_new(CTR_HANDLE_TEXTURE, buf); } }
void C3D_TexSetWrap(C3D_Tex* tex, GPU_TEXTURE_WRAP_PARAM wrapS, GPU_TEXTURE_WRAP_PARAM wrapT) { tex->param &= ~(GPU_TEXTURE_WRAP_S(3) | GPU_TEXTURE_WRAP_T(3)); tex->param |= GPU_TEXTURE_WRAP_S(wrapS) | GPU_TEXTURE_WRAP_T(wrapT); }
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; }