static void wiiu_gfx_free(void* data) { wiiu_video_t* wiiu = (wiiu_video_t*) data; if (!wiiu) return; /* clear leftover image */ GX2ClearColor(&wiiu->color_buffer, 0.0f, 0.0f, 0.0f, 1.0f); GX2CopyColorBufferToScanBuffer(&wiiu->color_buffer, GX2_SCAN_TARGET_DRC); GX2CopyColorBufferToScanBuffer(&wiiu->color_buffer, GX2_SCAN_TARGET_TV); GX2SwapScanBuffers(); GX2Flush(); GX2DrawDone(); GX2WaitForVsync(); GX2Shutdown(); GX2SetTVEnable(GX2_DISABLE); GX2SetDRCEnable(GX2_DISABLE); MEM2_free(wiiu->ctx_state); MEM2_free(wiiu->cmd_buffer); MEM2_free(wiiu->texture.surface.image); MEM2_free(wiiu->menu.texture.surface.image); MEM1_free(wiiu->color_buffer.surface.image); MEMBucket_free(wiiu->tv_scan_buffer); MEMBucket_free(wiiu->drc_scan_buffer); MEM2_free(wiiu->shader->fs.program); #ifndef GX2_CAN_ACCESS_DATA_SECTION MEM2_free(wiiu->shader->vs.program); MEM2_free(wiiu->shader->vs.attribVars); MEM2_free(wiiu->shader->ps.program); MEM2_free(wiiu->shader->ps.samplerVars); MEM2_free(wiiu->shader); #endif MEM2_free(wiiu->position); MEM2_free(wiiu->tex_coord); MEM2_free(wiiu->menu.position); MEM2_free(wiiu->menu.tex_coord); free(wiiu); }
static bool wiiu_gfx_frame(void* data, const void* frame, unsigned width, unsigned height, uint64_t frame_count, unsigned pitch, const char* msg) { (void)msg; int i; wiiu_video_t* wiiu = (wiiu_video_t*) data; if (!width || !height) { GX2WaitForVsync(); return true; } if(wiiu->vsync) { uint32_t swap_count; uint32_t flip_count; OSTime last_flip; OSTime last_vsync; GX2GetSwapStatus(&swap_count, &flip_count, &last_flip, &last_vsync); if(wiiu->last_vsync >= last_vsync) { GX2WaitForVsync(); wiiu->last_vsync = last_vsync + ms_to_ticks(17); } else wiiu->last_vsync = last_vsync; } GX2WaitForFlip(); static u32 lastTick , currentTick; currentTick = OSGetSystemTick(); u32 diff = currentTick - lastTick; static float fps; static u32 frames; frames++; if(diff > wiiu_timer_clock) { fps = (float)frames * ((float) wiiu_timer_clock / (float) diff); lastTick = currentTick; frames = 0; } #if 0 static u32 last_frame_tick; if (!(wiiu->menu.enable)) printf("\r frame time : %10.6f ms \n", (float)(currentTick - last_frame_tick) * 1000.0f / (float)wiiu_timer_clock); last_frame_tick = currentTick; #endif printf("\rfps: %8.8f frames : %5i", fps, wiiu->frames++); fflush(stdout); static struct retro_perf_counter gfx_frame_perf = {0}; performance_counter_init(&gfx_frame_perf, "gfx_frame"); performance_counter_start(&gfx_frame_perf); if (wiiu->should_resize) wiiu_gfx_update_viewport(wiiu); GX2ClearColor(&wiiu->color_buffer, 0.0f, 0.0f, 0.0f, 1.0f); /* can't call GX2ClearColor after GX2SetContextState for whatever reason */ GX2SetContextState(wiiu->ctx_state); if(frame) { if (width > wiiu->texture.surface.width) width = wiiu->texture.surface.width; if (height > wiiu->texture.surface.height) height = wiiu->texture.surface.height; wiiu->width = width; wiiu->height = height; if(wiiu->rgb32) { const uint32_t* src = frame; uint32_t* dst = (uint32_t*)wiiu->texture.surface.image; for (i = 0; i < height; i++) { int j; for(j = 0; j < width; j++) dst[j] = src[j]; dst += wiiu->texture.surface.pitch; src += pitch / 4; } } else { const uint16_t* src = frame; uint16_t* dst = (uint16_t*)wiiu->texture.surface.image; for (i = 0; i < height; i++) { int j; for(j = 0; j < width; j++) dst[j] = __builtin_bswap16(src[j]); dst += wiiu->texture.surface.pitch; src += pitch / 2; } } GX2Invalidate(GX2_INVALIDATE_MODE_CPU_TEXTURE, wiiu->texture.surface.image, wiiu->texture.surface.imageSize); wiiu_set_tex_coords(wiiu->tex_coord, &wiiu->texture, 0, 0, width, height); } GX2SetAttribBuffer(0, 4 * sizeof(*wiiu->position), sizeof(*wiiu->position), wiiu->position); GX2SetAttribBuffer(1, 4 * sizeof(*wiiu->tex_coord), sizeof(*wiiu->tex_coord), wiiu->tex_coord); GX2SetPixelTexture(&wiiu->texture, wiiu->shader->sampler.location); GX2SetPixelSampler(wiiu->smooth? &wiiu->sampler_linear : &wiiu->sampler_nearest, wiiu->shader->sampler.location); GX2DrawEx(GX2_PRIMITIVE_MODE_QUADS, 4, 0, 1); if (wiiu->menu.enable) { GX2SetAttribBuffer(0, 4 * sizeof(*wiiu->menu.position), sizeof(*wiiu->menu.position), wiiu->menu.position); GX2SetAttribBuffer(1, 4 * sizeof(*wiiu->menu.tex_coord), sizeof(*wiiu->menu.tex_coord), wiiu->menu.tex_coord); GX2SetPixelTexture(&wiiu->menu.texture, wiiu->shader->sampler.location); GX2SetPixelSampler(&wiiu->sampler_linear, wiiu->shader->sampler.location); GX2DrawEx(GX2_PRIMITIVE_MODE_QUADS, 4, 0, 1); GX2DrawDone(); } GX2CopyColorBufferToScanBuffer(&wiiu->color_buffer, GX2_SCAN_TARGET_DRC); GX2CopyColorBufferToScanBuffer(&wiiu->color_buffer, GX2_SCAN_TARGET_TV); GX2SwapScanBuffers(); GX2Flush(); performance_counter_stop(&gfx_frame_perf); return true; }
void myGXthread(int argc, int *argv) { if(argc != 2) OSFatal("GX Thread did not start proper!"); unsigned int *tv_fb = (unsigned int*)argv[0]; unsigned int *drc_fb = (unsigned int*)argv[1]; unsigned int coreinit_handle, gx2_handle; OSDynLoad_Acquire("coreinit", &coreinit_handle); OSDynLoad_Acquire("gx2", &gx2_handle); void(*GX2Init)(void *args); OSDynLoad_FindExport(gx2_handle, 0, "GX2Init", &GX2Init); GX2Init((void*)0); int(*OSGetCoreId)(); OSDynLoad_FindExport(coreinit_handle, 0, "OSGetCoreId", &OSGetCoreId); void(*GX2SwapScanBuffers)(); OSDynLoad_FindExport(gx2_handle, 0, "GX2SwapScanBuffers", &GX2SwapScanBuffers); void(*GX2Shutdown)(); OSDynLoad_FindExport(gx2_handle, 0, "GX2Shutdown", &GX2Shutdown); int(*GX2GetMainCoreId)(); OSDynLoad_FindExport(gx2_handle, 0, "GX2GetMainCoreId", &GX2GetMainCoreId); if(OSGetCoreId() != GX2GetMainCoreId()) OSFatal("GX Not switched!"); void(*GX2DrawDone)(); OSDynLoad_FindExport(gx2_handle, 0, "GX2DrawDone", &GX2DrawDone); void(*GX2Flush)(); OSDynLoad_FindExport(gx2_handle, 0, "GX2Flush", &GX2Flush); //void(*GX2SwapScanBuffers)(); //OSDynLoad_FindExport(gx2_handle, 0, "GX2SwapScanBuffers", &GX2SwapScanBuffers); void(*GX2WaitForVsync)(); OSDynLoad_FindExport(gx2_handle, 0, "GX2WaitForVsync", &GX2WaitForVsync); //Make sure buffer is usable for GX void(*GX2Invalidate)(unsigned int flags,void *buffer,unsigned int size); OSDynLoad_FindExport(gx2_handle, 0, "GX2Invalidate", &GX2Invalidate); GX2Invalidate(0x40,tv_fb,(1280*720*4)*2); GX2Invalidate(0x40,drc_fb,(854*480*4)*2); //set it! int(*GX2SetTVBuffer)(void *buffer,unsigned int size,unsigned int flag1,unsigned int flag2,unsigned int flag3); OSDynLoad_FindExport(gx2_handle, 0, "GX2SetTVBuffer", &GX2SetTVBuffer); int(*GX2SetDRCBuffer)(void *buffer,unsigned int size,unsigned int flag1,unsigned int flag2,unsigned int flag3); OSDynLoad_FindExport(gx2_handle, 0, "GX2SetDRCBuffer", &GX2SetDRCBuffer); GX2SetTVBuffer(tv_fb,(1280*720*4)*2,3,0x1A,2); //test gradient demo setup for show GX2SetDRCBuffer(drc_fb,(854*480*4)*2,1,0x1A,2); //will look broken, no color buffer setup yet /* Draw is far from complete */ /*void(*GX2DrawEx)(int type, int count, int start, int instances); OSDynLoad_FindExport(gx2_handle, 0, "GX2DrawEx", &GX2DrawEx); void(*GX2SetAttribBuffer)(int index, int size, int vtxStride, void *buf); OSDynLoad_FindExport(gx2_handle, 0, "GX2SetAttribBuffer", &GX2SetAttribBuffer); float myclearer[8] = { 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f }; GX2Invalidate(0x40, myclearer, sizeof(myclearer));*/ GX2ColorBuffer myCBuf; setupColorBuffer(&myCBuf, gx2_handle); void(*GX2ClearColor)(GX2ColorBuffer *buffer, float r, float g, float b, float a); OSDynLoad_FindExport(gx2_handle, 0, "GX2ClearColor", &GX2ClearColor); void(*GX2SwapBuffers)(GX2ColorBuffer *buffer); OSDynLoad_FindExport(gx2_handle, 0, "GX2SwapBuffers", &GX2SwapBuffers); void(*GX2CopyColorBufferToScanBuffer)(GX2ColorBuffer *buffer, unsigned int target); OSDynLoad_FindExport(gx2_handle, 0, "GX2CopyColorBufferToScanBuffer", &GX2CopyColorBufferToScanBuffer); float val = 1; float valInc = -0.005; val += valInc; while(val < 1) { val += valInc; //GX2SetAttribBuffer(0,sizeof(mybuf),8,mybuf); //GX2DrawEx(6,4,0,1); GX2ClearColor(&myCBuf, val, val, val, 1); GX2Invalidate(0x40, myCBuf.surface.imagePtr,myCBuf.surface.imageSize); GX2DrawDone(); GX2Flush(); GX2CopyColorBufferToScanBuffer(&myCBuf,1); GX2SwapScanBuffers(); GX2Flush(); GX2WaitForVsync(); if(val <= 0) valInc = 0.005; } //clear for browser (needed?) GX2Shutdown(); void(*_Exit)(); OSDynLoad_FindExport(coreinit_handle, 0, "_Exit", &_Exit); _Exit(); }