Shader3D::Shader3D() : vertexShader(cuAttributeCount) { //! create pixel shader pixelShader.setProgram(cPixelShaderProgram, sizeof(cPixelShaderProgram), cPixelShaderRegs, sizeof(cPixelShaderRegs)); colorIntensityLocation = 0; fadeDistanceLocation = 4; fadeOutLocation = 8; pixelShader.addUniformVar((GX2UniformVar){ "unf_color_intensity", GX2_VAR_TYPE_VEC4, 1, colorIntensityLocation, 0xffffffff }); pixelShader.addUniformVar((GX2UniformVar){ "unf_fade_distance", GX2_VAR_TYPE_FLOAT, 1, fadeDistanceLocation, 0xffffffff }); pixelShader.addUniformVar((GX2UniformVar){ "unf_fade_out_alpha", GX2_VAR_TYPE_VEC4, 1, fadeOutLocation, 0xffffffff }); samplerLocation = 0; pixelShader.addSamplerVar((GX2SamplerVar){ "sampl_texture", GX2_SAMPLER_TYPE_2D, samplerLocation }); //! create vertex shader vertexShader.setProgram(cpVertexShaderProgram, sizeof(cpVertexShaderProgram), cpVertexShaderRegs, sizeof(cpVertexShaderRegs)); modelMatrixLocation = 0; projectionMatrixLocation = 16; viewMatrixLocation = 32; vertexShader.addUniformVar((GX2UniformVar){ "modelMatrix", GX2_VAR_TYPE_MAT4, 1, modelMatrixLocation, 0xffffffff }); vertexShader.addUniformVar((GX2UniformVar){ "viewMatrix", GX2_VAR_TYPE_MAT4, 1, projectionMatrixLocation, 0xffffffff }); vertexShader.addUniformVar((GX2UniformVar){ "projectionMatrix", GX2_VAR_TYPE_MAT4, 1, viewMatrixLocation, 0xffffffff }); positionLocation = 0; texCoordLocation = 1; vertexShader.addAttribVar((GX2AttribVar){ "attr_position", GX2_VAR_TYPE_VEC3, 0, positionLocation }); vertexShader.addAttribVar((GX2AttribVar){ "attr_texture_coord", GX2_VAR_TYPE_VEC2, 0, texCoordLocation }); //! setup attribute streams GX2InitAttribStream(vertexShader.getAttributeBuffer(0), positionLocation, 0, 0, GX2_ATTRIB_FORMAT_32_32_32_FLOAT); GX2InitAttribStream(vertexShader.getAttributeBuffer(1), texCoordLocation, 1, 0, GX2_ATTRIB_FORMAT_32_32_FLOAT); //! create fetch shader fetchShader = new FetchShader(vertexShader.getAttributeBuffer(), vertexShader.getAttributesCount()); //! initialize default quad texture vertexes as those are very commonly used //! model vertex has to be align and cannot be in unknown regions for GX2 like 0xBCAE1000 posVtxs = (f32*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, ciPositionVtxsSize); texCoords = (f32*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, ciTexCoordsVtxsSize); //! position vertex structure and texture coordinate vertex structure int i = 0; posVtxs[i++] = -1.0f; posVtxs[i++] = -1.0f; posVtxs[i++] = 0.0f; posVtxs[i++] = 1.0f; posVtxs[i++] = -1.0f; posVtxs[i++] = 0.0f; posVtxs[i++] = 1.0f; posVtxs[i++] = 1.0f; posVtxs[i++] = 0.0f; posVtxs[i++] = -1.0f; posVtxs[i++] = 1.0f; posVtxs[i++] = 0.0f; GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, posVtxs, ciPositionVtxsSize); i = 0; texCoords[i++] = 0.0f; texCoords[i++] = 1.0f; texCoords[i++] = 1.0f; texCoords[i++] = 1.0f; texCoords[i++] = 1.0f; texCoords[i++] = 0.0f; texCoords[i++] = 0.0f; texCoords[i++] = 0.0f; GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, texCoords, ciTexCoordsVtxsSize); }
GridBackground::GridBackground(GuiImageData *img) : GuiImage(img) { colorIntensity = glm::vec4(1.0f, 1.0f, 1.0f, 0.9f); alphaFadeOut = glm::vec4(0.0f); distanceFadeOut = 0.15f; vtxCount = 4; //! texture and vertex coordinates f32 *m_posVtxs = (f32*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, vtxCount * Shader3D::cuVertexAttrSize); f32 *m_texCoords = (f32*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, vtxCount * Shader3D::cuTexCoordAttrSize); if(m_posVtxs) { int i = 0; m_posVtxs[i++] = -1.0f; m_posVtxs[i++] = 0.0f; m_posVtxs[i++] = 1.0f; m_posVtxs[i++] = 1.0f; m_posVtxs[i++] = 0.0f; m_posVtxs[i++] = 1.0f; m_posVtxs[i++] = 1.0f; m_posVtxs[i++] = 0.0f; m_posVtxs[i++] = -1.0f; m_posVtxs[i++] = -1.0f; m_posVtxs[i++] = 0.0f; m_posVtxs[i++] = -1.0f; GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, m_posVtxs, vtxCount * Shader3D::cuVertexAttrSize); } if(m_texCoords) { glm::vec2 texCoordVec[4]; texCoordVec[0][0] = -0.5f * bgRepeat; texCoordVec[0][1] = 0.5f * bgRepeat; texCoordVec[1][0] = 0.5f * bgRepeat; texCoordVec[1][1] = 0.5f * bgRepeat; texCoordVec[2][0] = 0.5f * bgRepeat; texCoordVec[2][1] = -0.5f * bgRepeat; texCoordVec[3][0] = -0.5f * bgRepeat; texCoordVec[3][1] = -0.5f * bgRepeat; const float cosRot = cosf(DegToRad(bgTexRotate)); const float sinRot = sinf(DegToRad(bgTexRotate)); glm::mat2 texRotateMtx({ cosRot, -sinRot, sinRot, cosRot }); for(int i = 0; i < 4; i++) { texCoordVec[i] = texRotateMtx * texCoordVec[i]; m_texCoords[i*2 + 0] = texCoordVec[i][0]; m_texCoords[i*2 + 1] = texCoordVec[i][1]; } GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, m_texCoords, vtxCount * Shader3D::cuTexCoordAttrSize); } //! assign to internal variables which are const but oh well posVtxs = m_posVtxs; texCoords = m_texCoords; }
static void* wiiu_font_init_font(void* data, const char* font_path, float font_size, bool is_threaded) { uint32_t i; wiiu_font_t* font = (wiiu_font_t*)calloc(1, sizeof(*font)); if (!font) return NULL; if (!font_renderer_create_default( &font->font_driver, &font->font_data, font_path, font_size)) { RARCH_WARN("Couldn't initialize font renderer.\n"); free(font); return NULL; } font->atlas = font->font_driver->get_atlas(font->font_data); font->texture.surface.width = font->atlas->width; font->texture.surface.height = font->atlas->height; font->texture.surface.depth = 1; font->texture.surface.dim = GX2_SURFACE_DIM_TEXTURE_2D; font->texture.surface.tileMode = GX2_TILE_MODE_LINEAR_ALIGNED; font->texture.viewNumSlices = 1; font->texture.surface.format = GX2_SURFACE_FORMAT_UNORM_R8; font->texture.compMap = GX2_COMP_SEL(_R, _R, _R, _R); GX2CalcSurfaceSizeAndAlignment(&font->texture.surface); GX2InitTextureRegs(&font->texture); font->texture.surface.image = MEM1_alloc(font->texture.surface.imageSize, font->texture.surface.alignment); for (i = 0; (i < font->atlas->height) && (i < font->texture.surface.height); i++) memcpy((uint8_t*)font->texture.surface.image + (i * font->texture.surface.pitch), font->atlas->buffer + (i * font->atlas->width), font->atlas->width); GX2Invalidate(GX2_INVALIDATE_MODE_CPU_TEXTURE, font->texture.surface.image, font->texture.surface.imageSize); font->atlas->dirty = false; font->ubo_tex = MEM1_alloc(sizeof(*font->ubo_tex), GX2_UNIFORM_BLOCK_ALIGNMENT); font->ubo_tex->width = font->texture.surface.width; font->ubo_tex->height = font->texture.surface.height; GX2Invalidate(GX2_INVALIDATE_MODE_CPU_UNIFORM_BLOCK, font->ubo_tex, sizeof(*font->ubo_tex)); return font; }
void GX2InitShader(GX2Shader *shader) { if (shader->fs.program) return; shader->fs.size = GX2CalcFetchShaderSizeEx(shader->vs.attribVarCount, GX2_FETCH_SHADER_TESSELLATION_NONE, GX2_TESSELLATION_MODE_DISCRETE); #ifdef GX2_CAN_ACCESS_DATA_SECTION shader->fs.program = MEM2_alloc(shader->fs.size, GX2_SHADER_ALIGNMENT); #else shader->fs.program = MEM2_alloc(shader->fs.size + sizeof(org_programs_t), GX2_SHADER_ALIGNMENT); #endif GX2InitFetchShaderEx(&shader->fs, (uint8_t *)shader->fs.program, shader->vs.attribVarCount, shader->attribute_stream, GX2_FETCH_SHADER_TESSELLATION_NONE, GX2_TESSELLATION_MODE_DISCRETE); GX2Invalidate(GX2_INVALIDATE_MODE_CPU_SHADER, shader->fs.program, shader->fs.size); #ifndef GX2_CAN_ACCESS_DATA_SECTION org_programs_t *org = (org_programs_t *)(shader->fs.program + shader->fs.size); org->vs_program = shader->vs.program; org->ps_program = shader->ps.program; org->gs_program = shader->gs.program; org->gs_copy_program = shader->gs.copyProgram; shader->vs.program = MEM2_alloc(shader->vs.size, GX2_SHADER_ALIGNMENT); memcpy(shader->vs.program, org->vs_program, shader->vs.size); GX2Invalidate(GX2_INVALIDATE_MODE_CPU_SHADER, shader->vs.program, shader->vs.size); shader->ps.program = MEM2_alloc(shader->ps.size, GX2_SHADER_ALIGNMENT); memcpy(shader->ps.program, org->ps_program, shader->ps.size); GX2Invalidate(GX2_INVALIDATE_MODE_CPU_SHADER, shader->ps.program, shader->ps.size); if (org->gs_program) { shader->gs.program = MEM2_alloc(shader->gs.size, GX2_SHADER_ALIGNMENT); memcpy(shader->gs.program, org->gs_program, shader->gs.size); GX2Invalidate(GX2_INVALIDATE_MODE_CPU_SHADER, shader->gs.program, shader->gs.size); shader->gs.copyProgram = MEM2_alloc(shader->gs.copyProgramSize, GX2_SHADER_ALIGNMENT); memcpy(shader->gs.copyProgram, org->gs_copy_program, shader->gs.copyProgramSize); GX2Invalidate(GX2_INVALIDATE_MODE_CPU_SHADER, shader->gs.copyProgram, shader->gs.copyProgramSize); } #endif }
FXAAShader::FXAAShader() : vertexShader(cuAttributeCount) { //! create pixel shader pixelShader.setProgram(cpPixelShaderProgram, sizeof(cpPixelShaderProgram), cpPixelShaderRegs, sizeof(cpPixelShaderRegs)); resolutionLocation = 0; pixelShader.addUniformVar((GX2UniformVar){ "unf_resolution", GX2_VAR_TYPE_VEC2, 1, resolutionLocation, 0xffffffff }); samplerLocation = 0; pixelShader.addSamplerVar((GX2SamplerVar){ "sampl_texture", GX2_SAMPLER_TYPE_2D, samplerLocation }); //! create vertex shader vertexShader.setProgram(cpVertexShaderProgram, sizeof(cpVertexShaderProgram), cpVertexShaderRegs, sizeof(cpVertexShaderRegs)); positionLocation = 0; texCoordLocation = 1; vertexShader.addAttribVar((GX2AttribVar){ "attr_position", GX2_VAR_TYPE_VEC3, 0, positionLocation }); vertexShader.addAttribVar((GX2AttribVar){ "attr_texture_coord", GX2_VAR_TYPE_VEC2, 0, texCoordLocation }); //! setup attribute streams GX2InitAttribStream(vertexShader.getAttributeBuffer(0), positionLocation, 0, 0, GX2_ATTRIB_FORMAT_32_32_32_FLOAT); GX2InitAttribStream(vertexShader.getAttributeBuffer(1), texCoordLocation, 1, 0, GX2_ATTRIB_FORMAT_32_32_FLOAT); //! create fetch shader fetchShader = new FetchShader(vertexShader.getAttributeBuffer(), vertexShader.getAttributesCount()); //! model vertex has to be align and cannot be in unknown regions for GX2 like 0xBCAE1000 posVtxs = (f32*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, ciPositionVtxsSize); texCoords = (f32*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, ciTexCoordsVtxsSize); //! position vertex structure and texture coordinate vertex structure int i = 0; posVtxs[i++] = -1.0f; posVtxs[i++] = -1.0f; posVtxs[i++] = 0.0f; posVtxs[i++] = 1.0f; posVtxs[i++] = -1.0f; posVtxs[i++] = 0.0f; posVtxs[i++] = 1.0f; posVtxs[i++] = 1.0f; posVtxs[i++] = 0.0f; posVtxs[i++] = -1.0f; posVtxs[i++] = 1.0f; posVtxs[i++] = 0.0f; GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, posVtxs, ciPositionVtxsSize); i = 0; texCoords[i++] = 0.0f; texCoords[i++] = 1.0f; texCoords[i++] = 1.0f; texCoords[i++] = 1.0f; texCoords[i++] = 1.0f; texCoords[i++] = 0.0f; texCoords[i++] = 0.0f; texCoords[i++] = 0.0f; GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, texCoords, ciTexCoordsVtxsSize); }
void init_cursor(){ if(!gCursorInitDone){ if(!cursor_colorVtxs){ cursor_colorVtxs = (u8*)memalign(0x40, sizeof(u8) * 16); if(cursor_colorVtxs == NULL) return; } memset(cursor_colorVtxs,0xFF,16*sizeof(u8)); GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, cursor_colorVtxs, 16 * sizeof(u8)); gCursorInitDone = 1; } }
static wiiu_set_position(position_t* position, GX2ColorBuffer* draw_buffer, float x0, float y0, float x1, float y1) { position[0].x = (2.0f * x0 / draw_buffer->surface.width) - 1.0f; position[0].y = (2.0f * y0 / draw_buffer->surface.height) - 1.0f; position[1].x = (2.0f * x1 / draw_buffer->surface.width) - 1.0f;; position[1].y = (2.0f * y0 / draw_buffer->surface.height) - 1.0f; position[2].x = (2.0f * x1 / draw_buffer->surface.width) - 1.0f;; position[2].y = (2.0f * y1 / draw_buffer->surface.height) - 1.0f; position[3].x = (2.0f * x0 / draw_buffer->surface.width) - 1.0f;; position[3].y = (2.0f * y1 / draw_buffer->surface.height) - 1.0f; GX2Invalidate(GX2_INVALIDATE_MODE_CPU_ATTRIBUTE_BUFFER, position, 4 * sizeof(*position)); }
static void wiiu_set_tex_coords(tex_coord_t* tex_coord, GX2Texture* texture, float u0, float v0, float u1, float v1) { tex_coord[0].u = u0 / texture->surface.width; tex_coord[0].v = (v1 / texture->surface.height); tex_coord[1].u = u1 / texture->surface.width; tex_coord[1].v = (v1 / texture->surface.height); tex_coord[2].u = u1 / texture->surface.width; tex_coord[2].v = (v0 / texture->surface.height); tex_coord[3].u = u0 / texture->surface.width; tex_coord[3].v = (v0 / texture->surface.height); GX2Invalidate(GX2_INVALIDATE_MODE_CPU_ATTRIBUTE_BUFFER, tex_coord, 4 * sizeof(*tex_coord)); }
static void wiiu_gfx_set_texture_frame(void* data, const void* frame, bool rgb32, unsigned width, unsigned height, float alpha) { int i; wiiu_video_t* wiiu = (wiiu_video_t*) data; if (!wiiu) return; if (!frame || !width || !height) return; if (width > wiiu->menu.texture.surface.width) width = wiiu->menu.texture.surface.width; if (height > wiiu->menu.texture.surface.height) height = wiiu->menu.texture.surface.height; wiiu->menu.width = width; wiiu->menu.height = height; const uint16_t* src = frame; uint16_t* dst = (uint16_t*)wiiu->menu.texture.surface.image; for (i = 0; i < height; i++) { memcpy(dst, src, width * sizeof(uint16_t)); dst += wiiu->menu.texture.surface.pitch; src += width; } GX2Invalidate(GX2_INVALIDATE_MODE_CPU_TEXTURE, wiiu->menu.texture.surface.image, wiiu->menu.texture.surface.imageSize); wiiu_set_tex_coords(wiiu->menu.tex_coord, &wiiu->menu.texture, 0, 0, width, height); // wiiu_set_tex_coords(wiiu->menu.tex_coord, &wiiu->menu.texture, 0, 0, wiiu->menu.texture.surface.width, wiiu->menu.texture.surface.height); }
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; }
static void* wiiu_gfx_init(const video_info_t* video, const input_driver_t** input, void** input_data) { int i; *input = NULL; *input_data = NULL; wiiu_video_t* wiiu = calloc(1, sizeof(*wiiu)); if (!wiiu) return NULL; void* wiiuinput = NULL; if (input && input_data) { wiiuinput = input_wiiu.init(); *input = wiiuinput ? &input_wiiu : NULL; *input_data = wiiuinput; } /* video init */ wiiu->cmd_buffer = MEM2_alloc(0x400000, 0x40); u32 init_attributes[] = { GX2_INIT_CMD_BUF_BASE, (u32)wiiu->cmd_buffer, GX2_INIT_CMD_BUF_POOL_SIZE, 0x400000, GX2_INIT_ARGC, 0, GX2_INIT_ARGV, 0, GX2_INIT_END }; GX2Init(init_attributes); /* setup scanbuffers */ u32 size = 0; u32 tmp = 0; wiiu->render_mode = wiiu_render_mode_map[GX2GetSystemTVScanMode()]; GX2CalcTVSize(wiiu->render_mode.mode, GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8, GX2_BUFFERING_MODE_DOUBLE, &size, &tmp); wiiu->tv_scan_buffer = MEMBucket_alloc(size, GX2_SCAN_BUFFER_ALIGNMENT); GX2Invalidate(GX2_INVALIDATE_MODE_CPU, wiiu->tv_scan_buffer, size); GX2SetTVBuffer(wiiu->tv_scan_buffer, size, wiiu->render_mode.mode, GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8, GX2_BUFFERING_MODE_DOUBLE); GX2CalcDRCSize(GX2_DRC_RENDER_MODE_SINGLE, GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8, GX2_BUFFERING_MODE_DOUBLE, &size, &tmp); wiiu->drc_scan_buffer = MEMBucket_alloc(size, GX2_SCAN_BUFFER_ALIGNMENT); GX2Invalidate(GX2_INVALIDATE_MODE_CPU, wiiu->drc_scan_buffer, size); GX2SetDRCBuffer(wiiu->drc_scan_buffer, size, GX2_DRC_RENDER_MODE_SINGLE, GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8, GX2_BUFFERING_MODE_DOUBLE); memset(&wiiu->color_buffer, 0, sizeof(GX2ColorBuffer)); wiiu->color_buffer.surface.dim = GX2_SURFACE_DIM_TEXTURE_2D; wiiu->color_buffer.surface.width = wiiu->render_mode.width; wiiu->color_buffer.surface.height = wiiu->render_mode.height; wiiu->color_buffer.surface.depth = 1; wiiu->color_buffer.surface.mipLevels = 1; wiiu->color_buffer.surface.format = GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8; wiiu->color_buffer.surface.use = GX2_SURFACE_USE_TEXTURE_COLOR_BUFFER_TV; wiiu->color_buffer.viewNumSlices = 1; GX2CalcSurfaceSizeAndAlignment(&wiiu->color_buffer.surface); GX2InitColorBufferRegs(&wiiu->color_buffer); wiiu->color_buffer.surface.image = MEM1_alloc(wiiu->color_buffer.surface.imageSize, wiiu->color_buffer.surface.alignment); GX2Invalidate(GX2_INVALIDATE_MODE_CPU, wiiu->color_buffer.surface.image, wiiu->color_buffer.surface.imageSize); wiiu->ctx_state = (GX2ContextState*)MEM2_alloc(sizeof(GX2ContextState), GX2_CONTEXT_STATE_ALIGNMENT); GX2SetupContextStateEx(wiiu->ctx_state, GX2_TRUE); GX2SetContextState(wiiu->ctx_state); GX2SetColorBuffer(&wiiu->color_buffer, GX2_RENDER_TARGET_0); GX2SetViewport(0.0f, 0.0f, wiiu->color_buffer.surface.width, wiiu->color_buffer.surface.height, 0.0f, 1.0f); GX2SetScissor(0, 0, wiiu->color_buffer.surface.width, wiiu->color_buffer.surface.height); GX2SetDepthOnlyControl(GX2_DISABLE, GX2_DISABLE, GX2_COMPARE_FUNC_ALWAYS); GX2SetColorControl(GX2_LOGIC_OP_COPY, 1, GX2_DISABLE, GX2_ENABLE); #if 1 GX2SetBlendControl(GX2_RENDER_TARGET_0, GX2_BLEND_MODE_SRC_ALPHA, GX2_BLEND_MODE_INV_SRC_ALPHA, GX2_BLEND_COMBINE_MODE_ADD, GX2_ENABLE, GX2_BLEND_MODE_SRC_ALPHA, GX2_BLEND_MODE_INV_SRC_ALPHA, GX2_BLEND_COMBINE_MODE_ADD); #else GX2SetBlendControl(GX2_RENDER_TARGET_0, GX2_BLEND_MODE_ONE, GX2_BLEND_MODE_ZERO, GX2_BLEND_COMBINE_MODE_ADD, GX2_DISABLE, GX2_BLEND_MODE_ONE, GX2_BLEND_MODE_ZERO, GX2_BLEND_COMBINE_MODE_ADD); #endif GX2SetCullOnlyControl(GX2_FRONT_FACE_CCW, GX2_DISABLE, GX2_DISABLE); #ifdef GX2_CAN_ACCESS_DATA_SECTION wiiu->shader = &tex_shader; #else /* init shader */ // wiiu->shader = MEM2_alloc(sizeof(*wiiu->shader), GX2_VERTEX_BUFFER_ALIGNMENT); wiiu->shader = MEM2_alloc(sizeof(tex_shader), 0x1000); memcpy(wiiu->shader, &tex_shader, sizeof(tex_shader)); GX2Invalidate(GX2_INVALIDATE_MODE_CPU, wiiu->shader, sizeof(tex_shader)); wiiu->shader->vs.program = MEM2_alloc(wiiu->shader->vs.size, GX2_SHADER_ALIGNMENT); memcpy(wiiu->shader->vs.program, tex_shader.vs.program, wiiu->shader->vs.size); GX2Invalidate(GX2_INVALIDATE_MODE_CPU_SHADER, wiiu->shader->vs.program, wiiu->shader->vs.size); wiiu->shader->vs.attribVars = MEM2_alloc(wiiu->shader->vs.attribVarCount * sizeof(GX2AttribVar), GX2_SHADER_ALIGNMENT); memcpy(wiiu->shader->vs.attribVars, tex_shader.vs.attribVars , wiiu->shader->vs.attribVarCount * sizeof(GX2AttribVar)); wiiu->shader->ps.program = MEM2_alloc(wiiu->shader->ps.size, GX2_SHADER_ALIGNMENT); memcpy(wiiu->shader->ps.program, tex_shader.ps.program, wiiu->shader->ps.size); GX2Invalidate(GX2_INVALIDATE_MODE_CPU_SHADER, wiiu->shader->ps.program, wiiu->shader->ps.size); wiiu->shader->ps.samplerVars = MEM2_alloc(wiiu->shader->ps.samplerVarCount * sizeof(GX2SamplerVar), GX2_SHADER_ALIGNMENT); memcpy(wiiu->shader->ps.samplerVars, tex_shader.ps.samplerVars, wiiu->shader->ps.samplerVarCount * sizeof(GX2SamplerVar)); #endif wiiu->shader->fs.size = GX2CalcFetchShaderSizeEx(2, GX2_FETCH_SHADER_TESSELLATION_NONE, GX2_TESSELLATION_MODE_DISCRETE); wiiu->shader->fs.program = MEM2_alloc(wiiu->shader->fs.size, GX2_SHADER_ALIGNMENT); GX2InitFetchShaderEx(&wiiu->shader->fs, (uint8_t*)wiiu->shader->fs.program, sizeof(wiiu->shader->attribute_stream) / sizeof(GX2AttribStream), (GX2AttribStream*)&wiiu->shader->attribute_stream, GX2_FETCH_SHADER_TESSELLATION_NONE, GX2_TESSELLATION_MODE_DISCRETE); GX2Invalidate(GX2_INVALIDATE_MODE_CPU_SHADER, wiiu->shader->fs.program, wiiu->shader->fs.size); GX2SetVertexShader(&wiiu->shader->vs); GX2SetPixelShader(&wiiu->shader->ps); GX2SetFetchShader(&wiiu->shader->fs); wiiu->position = MEM2_alloc(4 * sizeof(*wiiu->position), GX2_VERTEX_BUFFER_ALIGNMENT); wiiu_set_position(wiiu->position, &wiiu->color_buffer, 0, 0, wiiu->color_buffer.surface.width, wiiu->color_buffer.surface.height); wiiu->tex_coord = MEM2_alloc(4 * sizeof(*wiiu->tex_coord), GX2_VERTEX_BUFFER_ALIGNMENT); wiiu_set_tex_coords(wiiu->tex_coord, &wiiu->texture, 0, 0, wiiu->texture.surface.width, wiiu->texture.surface.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); wiiu->menu.position = MEM2_alloc(4 * sizeof(*wiiu->menu.position), GX2_VERTEX_BUFFER_ALIGNMENT); wiiu_set_position(wiiu->menu.position, &wiiu->color_buffer, 0, 0, wiiu->color_buffer.surface.width, wiiu->color_buffer.surface.height); wiiu->menu.tex_coord = MEM2_alloc(4 * sizeof(*wiiu->menu.tex_coord), GX2_VERTEX_BUFFER_ALIGNMENT); wiiu_set_tex_coords(wiiu->menu.tex_coord, &wiiu->menu.texture, 0, 0, wiiu->menu.texture.surface.width, wiiu->menu.texture.surface.height); /* init frame texture */ memset(&wiiu->texture, 0, sizeof(GX2Texture)); wiiu->texture.surface.width = video->input_scale * RARCH_SCALE_BASE; wiiu->texture.surface.height = video->input_scale * RARCH_SCALE_BASE; wiiu->texture.surface.depth = 1; wiiu->texture.surface.dim = GX2_SURFACE_DIM_TEXTURE_2D; wiiu->texture.surface.tileMode = GX2_TILE_MODE_LINEAR_ALIGNED; wiiu->texture.viewNumSlices = 1; wiiu->rgb32 = video->rgb32; if(wiiu->rgb32) { wiiu->texture.surface.format = GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8; wiiu->texture.compMap = GX2_COMP_SEL(_G, _B, _A, _1); } else { wiiu->texture.surface.format = GX2_SURFACE_FORMAT_UNORM_R5_G6_B5; wiiu->texture.compMap = GX2_COMP_SEL(_B, _G, _R, _1); } GX2CalcSurfaceSizeAndAlignment(&wiiu->texture.surface); GX2InitTextureRegs(&wiiu->texture); wiiu->texture.surface.image = MEM2_alloc(wiiu->texture.surface.imageSize, wiiu->texture.surface.alignment); memset(wiiu->texture.surface.image, 0x0, wiiu->texture.surface.imageSize); GX2Invalidate(GX2_INVALIDATE_MODE_CPU_TEXTURE, wiiu->texture.surface.image, wiiu->texture.surface.imageSize); /* init menu texture */ memset(&wiiu->menu.texture, 0, sizeof(GX2Texture)); wiiu->menu.texture.surface.width = 512; wiiu->menu.texture.surface.height = 512; wiiu->menu.texture.surface.depth = 1; wiiu->menu.texture.surface.dim = GX2_SURFACE_DIM_TEXTURE_2D; wiiu->menu.texture.surface.format = GX2_SURFACE_FORMAT_UNORM_R4_G4_B4_A4; wiiu->menu.texture.surface.tileMode = GX2_TILE_MODE_LINEAR_ALIGNED; wiiu->menu.texture.viewNumSlices = 1; wiiu->menu.texture.compMap = GX2_COMP_SEL(_A, _R, _G, _B); GX2CalcSurfaceSizeAndAlignment(&wiiu->menu.texture.surface); GX2InitTextureRegs(&wiiu->menu.texture); wiiu->menu.texture.surface.image = MEM2_alloc(wiiu->menu.texture.surface.imageSize, wiiu->menu.texture.surface.alignment); memset(wiiu->menu.texture.surface.image, 0x0, wiiu->menu.texture.surface.imageSize); GX2Invalidate(GX2_INVALIDATE_MODE_CPU_TEXTURE, wiiu->menu.texture.surface.image, wiiu->menu.texture.surface.imageSize); /* init samplers */ GX2InitSampler(&wiiu->sampler_nearest, GX2_TEX_CLAMP_MODE_CLAMP, GX2_TEX_XY_FILTER_MODE_POINT); GX2InitSampler(&wiiu->sampler_linear, GX2_TEX_CLAMP_MODE_CLAMP, GX2_TEX_XY_FILTER_MODE_LINEAR); /* set Texture and Sampler */ GX2SetPixelTexture(&wiiu->texture, wiiu->shader->sampler.location); GX2SetPixelSampler(&wiiu->sampler_linear, wiiu->shader->sampler.location); /* 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(); GX2WaitForVsync(); GX2SetTVEnable(GX2_ENABLE); GX2SetDRCEnable(GX2_ENABLE); wiiu->keep_aspect = true; wiiu->should_resize = true; wiiu->smooth = video->smooth; wiiu->vsync = video->vsync; GX2SetSwapInterval(!!video->vsync); wiiu->vp.x = 0; wiiu->vp.y = 0; wiiu->vp.width = 854; wiiu->vp.height = 480; wiiu->vp.full_width = 854; wiiu->vp.full_height = 480; video_driver_set_size(&wiiu->vp.width, &wiiu->vp.height); float refresh_rate = 60.0f / 1.001f; driver_ctl(RARCH_DRIVER_CTL_SET_REFRESH_RATE, &refresh_rate); return wiiu; }
static void wiiu_font_render_line( video_frame_info_t *video_info, wiiu_font_t* font, const char* msg, unsigned msg_len, float scale, const unsigned int color, float pos_x, float pos_y, unsigned text_align) { unsigned i; wiiu_video_t* wiiu = (wiiu_video_t*)video_info->userdata; unsigned width = video_info->width; unsigned height = video_info->height; int x = roundf(pos_x * width); int y = roundf((1.0 - pos_y) * height); if( !wiiu || wiiu->vertex_cache.current + (msg_len * 4) > wiiu->vertex_cache.size) return; switch (text_align) { case TEXT_ALIGN_RIGHT: x -= wiiu_font_get_message_width(font, msg, msg_len, scale); break; case TEXT_ALIGN_CENTER: x -= wiiu_font_get_message_width(font, msg, msg_len, scale) / 2; break; } sprite_vertex_t* v = wiiu->vertex_cache.v + wiiu->vertex_cache.current; for (i = 0; i < msg_len; i++) { const char* msg_tmp = &msg[i]; unsigned code = utf8_walk(&msg_tmp); unsigned skip = msg_tmp - &msg[i]; if (skip > 1) i += skip - 1; const struct font_glyph* glyph = font->font_driver->get_glyph(font->font_data, code); if (!glyph) /* Do something smarter here ... */ glyph = font->font_driver->get_glyph(font->font_data, '?'); if (!glyph) continue; v->pos.x = x + glyph->draw_offset_x * scale; v->pos.y = y + glyph->draw_offset_y * scale; v->pos.width = glyph->width * scale; v->pos.height = glyph->height * scale; v->coord.u = glyph->atlas_offset_x; v->coord.v = glyph->atlas_offset_y; v->coord.width = glyph->width; v->coord.height = glyph->height; v->color = color; v++; x += glyph->advance_x * scale; y += glyph->advance_y * scale; } int count = v - wiiu->vertex_cache.v - wiiu->vertex_cache.current; if (!count) return; GX2Invalidate(GX2_INVALIDATE_MODE_CPU_ATTRIBUTE_BUFFER, wiiu->vertex_cache.v + wiiu->vertex_cache.current, count * sizeof(wiiu->vertex_cache.v)); if(font->atlas->dirty) { for (i = 0; (i < font->atlas->height) && (i < font->texture.surface.height); i++) memcpy(font->texture.surface.image + (i * font->texture.surface.pitch), font->atlas->buffer + (i * font->atlas->width), font->atlas->width); GX2Invalidate(GX2_INVALIDATE_MODE_CPU_TEXTURE, font->texture.surface.image, font->texture.surface.imageSize); font->atlas->dirty = false; } GX2SetPixelTexture(&font->texture, sprite_shader.ps.samplerVars[0].location); GX2SetVertexUniformBlock(sprite_shader.vs.uniformBlocks[1].offset, sprite_shader.vs.uniformBlocks[1].size, font->ubo_tex); GX2DrawEx(GX2_PRIMITIVE_MODE_POINTS, count, wiiu->vertex_cache.current, 1); GX2SetVertexUniformBlock(sprite_shader.vs.uniformBlocks[1].offset, sprite_shader.vs.uniformBlocks[1].size, wiiu->ubo_tex); wiiu->vertex_cache.current = v - wiiu->vertex_cache.v; }
void GX2InitFetchShaderEx(GX2FetchShader *fetchShader, uint8_t *buffer, uint32_t attribCount, GX2AttribStream *attribs, GX2FetchShaderType type, GX2TessellationMode tessMode) { if (type != GX2FetchShaderType::NoTessellation) { decaf_abort(fmt::format("Invalid GX2FetchShaderType {}", enumAsString(type))); } if (tessMode != GX2TessellationMode::Discrete) { decaf_abort(fmt::format("Invalid GX2TessellationMode {}", enumAsString(tessMode))); } auto someTessVar1 = 128u; auto someTessVar2 = 128u; auto numGPRs = 0u; auto barrier = false; // Calculate instruction pointers auto fetchCount = GX2FSCalcNumFetchInsts(attribCount, type); auto aluCount = 0; // GX2FSCalcNumAluInsts(type, tessMode); auto cfCount = GX2FSCalcNumCFInsts(fetchCount, type); auto fetchSize = fetchCount * sizeof(latte::VertexFetchInst); auto cfSize = cfCount * sizeof(latte::ControlFlowInst); auto aluSize = aluCount * sizeof(latte::AluInst); auto cfOffset = 0u; auto aluOffset = cfSize; auto fetchOffset = align_up(cfSize + aluSize, 0x10u); auto cfPtr = reinterpret_cast<latte::ControlFlowInst *>(buffer + cfOffset); auto aluPtr = reinterpret_cast<latte::AluInst *>(buffer + aluOffset); auto fetchPtr = reinterpret_cast<latte::VertexFetchInst *>(buffer + fetchOffset); // Setup fetch shader fetchShader->type = type; fetchShader->attribCount = attribCount; fetchShader->data = buffer; fetchShader->size = GX2CalcFetchShaderSizeEx(attribCount, type, tessMode); // Generate fetch instructions auto indexMap = GX2FSGetIndexGprMap(type, tessMode); for (auto i = 0u; i < attribCount; ++i) { latte::VertexFetchInst vfetch; auto &attrib = attribs[i]; std::memset(&vfetch, 0, sizeof(vfetch)); if (attrib.buffer == 16) { // TODO: Figure out what these vars are for if (attrib.offset) { if (attrib.offset == 1) { someTessVar1 = attrib.location; } } else { someTessVar2 = attrib.location; } } else { // Semantic vertex fetch vfetch.word0 = vfetch.word0 .VTX_INST(latte::SQ_VTX_INST_SEMANTIC) .BUFFER_ID(latte::SQ_RES_OFFSET::VS_ATTRIB_RESOURCE_0 + attrib.buffer - latte::SQ_RES_OFFSET::VS_TEX_RESOURCE_0); vfetch.word2 = vfetch.word2 .OFFSET(attribs[i].offset); if (attrib.type) { auto selX = latte::SQ_SEL::SEL_X; auto fetchType = latte::SQ_VTX_FETCH_TYPE::VERTEX_DATA; if (attrib.type == GX2AttribIndexType::PerInstance) { if (attrib.aluDivisor == 1) { fetchType = latte::SQ_VTX_FETCH_TYPE::INSTANCE_DATA; selX = latte::SQ_SEL::SEL_W; } else if (attrib.aluDivisor == fetchShader->divisors[0]) { fetchType = latte::SQ_VTX_FETCH_TYPE::INSTANCE_DATA; selX = latte::SQ_SEL::SEL_Y; } else if (attrib.aluDivisor == fetchShader->divisors[1]) { fetchType = latte::SQ_VTX_FETCH_TYPE::INSTANCE_DATA; selX = latte::SQ_SEL::SEL_Z; } else { fetchShader->divisors[fetchShader->numDivisors] = attrib.aluDivisor; if (fetchShader->numDivisors == 0) { selX = latte::SQ_SEL::SEL_Y; } else if (fetchShader->numDivisors == 1) { selX = latte::SQ_SEL::SEL_Z; } fetchShader->numDivisors++; } } vfetch.word0 = vfetch.word0 .FETCH_TYPE(fetchType) .SRC_SEL_X(selX); } else { vfetch.word0 = vfetch.word0 .SRC_GPR(indexMap[0].gpr) .SRC_SEL_X(static_cast<latte::SQ_SEL>(indexMap[0].chan)); } // Setup dest vfetch.gpr = vfetch.gpr .DST_GPR(attrib.location); vfetch.word1 = vfetch.word1 .DST_SEL_W(static_cast<latte::SQ_SEL>(attrib.mask & 0x7)) .DST_SEL_Z(static_cast<latte::SQ_SEL>((attrib.mask >> 8) & 0x7)) .DST_SEL_Y(static_cast<latte::SQ_SEL>((attrib.mask >> 16) & 0x7)) .DST_SEL_X(static_cast<latte::SQ_SEL>((attrib.mask >> 24) & 0x7)); // Setup mega fetch vfetch.word2 = vfetch.word2 .MEGA_FETCH(1); vfetch.word0 = vfetch.word0 .MEGA_FETCH_COUNT(internal::getAttribFormatBytes(attrib.format) - 1); // Setup format auto dataFormat = internal::getAttribFormatDataFormat(attrib.format); auto numFormat = latte::SQ_NUM_FORMAT::NORM; auto formatComp = latte::SQ_FORMAT_COMP::UNSIGNED; if (attribs[i].format & GX2AttribFormatFlags::SCALED) { numFormat = latte::SQ_NUM_FORMAT::SCALED; } else if (attribs[i].format & GX2AttribFormatFlags::INTEGER) { numFormat = latte::SQ_NUM_FORMAT::INT; } if (attribs[i].format & GX2AttribFormatFlags::SIGNED) { formatComp = latte::SQ_FORMAT_COMP::SIGNED; } vfetch.word1 = vfetch.word1 .DATA_FORMAT(dataFormat) .NUM_FORMAT_ALL(numFormat) .FORMAT_COMP_ALL(formatComp); auto swapMode = internal::getSwapModeEndian(attribs[i].endianSwap & 3); if (attribs[i].endianSwap == latte::SQ_ENDIAN::AUTO) { swapMode = internal::getAttribFormatEndian(attribs[i].format); } vfetch.word2 = vfetch.word2 .ENDIAN_SWAP(swapMode); // Append to program *(fetchPtr++) = vfetch; // Add extra tesselation vertex fetches if (type != GX2FetchShaderType::NoTessellation && attrib.type != GX2AttribIndexType::PerInstance) { auto perAttrib = GX2FetchInstsPerAttrib(type); for (auto j = 1u; j < perAttrib; ++j) { latte::VertexFetchInst vfetch2 = vfetch; // Update src/dst vfetch2.word0 = vfetch2.word0 .SRC_GPR(indexMap[j].gpr) .SRC_SEL_X(static_cast<latte::SQ_SEL>(indexMap[j].chan)); vfetch2.gpr = vfetch2.gpr .DST_GPR(j + attrib.location); // Append to program *(fetchPtr++) = vfetch; } } } } // Generate tessellation ALU ops if (type != GX2FetchShaderType::NoTessellation) { numGPRs = 2; if (tessMode == GX2TessellationMode::Adaptive) { switch (type) { case GX2FetchShaderType::LineTessellation: numGPRs = 3; break; case GX2FetchShaderType::TriangleTessellation: numGPRs = 7; break; case GX2FetchShaderType::QuadTessellation: numGPRs = 7; break; } } // TODO: GX2FSGenTessAluOps barrier = true; } // Generate a VTX CF per 16 VFETCH if (fetchCount) { for (auto i = 0u; i < cfCount - 1; ++i) { auto fetches = FetchesPerControlFlow; if (fetchCount < (i + 1) * FetchesPerControlFlow) { // Don't overrun our fetches! fetches = fetchCount % FetchesPerControlFlow; } latte::ControlFlowInst inst; std::memset(&inst, 0, sizeof(inst)); inst.word0.ADDR = static_cast<uint32_t>((fetchOffset + sizeof(latte::VertexFetchInst) * i * FetchesPerControlFlow) / 8); inst.word1 = inst.word1 .COUNT((fetches - 1) & 0x7) .COUNT_3(((fetches - 1) >> 3) & 0x1) .CF_INST(latte::SQ_CF_INST_VTX_TC) .BARRIER(barrier ? 1 : 0); *(cfPtr++) = inst; } } // Generate tessellation "post" ALU ops if (numGPRs) { // TODO: GX2FSGenPostAluOps } // Generate an EOP latte::ControlFlowInst eop; std::memset(&eop, 0, sizeof(eop)); eop.word1 = eop.word1 .BARRIER(1) .CF_INST(latte::SQ_CF_INST_RETURN); *(cfPtr++) = eop; // Set sq_pgm_resources_fs auto sq_pgm_resources_fs = fetchShader->regs.sq_pgm_resources_fs.value(); sq_pgm_resources_fs = sq_pgm_resources_fs .NUM_GPRS(numGPRs); fetchShader->regs.sq_pgm_resources_fs = sq_pgm_resources_fs; GX2Invalidate(GX2InvalidateMode::CPU, fetchShader->data, fetchShader->size); }
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(); }
GFDFile *gfd_open(const char *filename) { GFDFile* gfd = calloc(1, sizeof(*gfd)); FILE *fp = fopen(filename, "rb"); if (!fp) goto error; fseek(fp, 0, SEEK_END); int size = ftell(fp); fseek(fp, 0, SEEK_SET); gfd->data = MEM2_alloc(size, GX2_SHADER_ALIGNMENT); fread(gfd->data, 1, size, fp); fclose(fp); GFDFileHeader *header = (GFDFileHeader *)gfd->data; if (header->magic != GFD_FILE_MAGIC) { printf("wrong file magic number.\n"); goto error; } if (header->headerSize != sizeof(GFDFileHeader)) { printf("wrong file header size.\n"); goto error; } if (header->majorVersion != GFD_FILE_MAJOR_VERSION) { printf("file version not supported.\n"); goto error; } if (header->gpuVersion != GFD_FILE_GPU_VERSION) { printf("gpu version not supported.\n"); goto error; } if (!header->align) { printf("data is not aligned.\n"); goto error; } GFDBlock *block = (GFDBlock *)(gfd->data + header->headerSize); while (block->header.type != GFD_BLOCK_TYPE_END_OF_FILE) { if (block->header.magic != GFD_BLOCK_MAGIC) { printf("wrong block magic number.\n"); goto error; } if (block->header.headerSize != sizeof(GFDBlockHeader)) { printf("wrong block header size.\n"); goto error; } if (block->header.majorVersion != GFD_BLOCK_MAJOR_VERSION) { printf("block version not supported.\n"); goto error; } switch (block->header.type) { case GFD_BLOCK_TYPE_VERTEX_SHADER_HEADER: if (gfd->vs) continue; gfd->vs = (GX2VertexShader*)block->data; if(!gfd_relocate_block(block)) goto error; break; case GFD_BLOCK_TYPE_VERTEX_SHADER_PROGRAM: if(gfd->vs->program) continue; GX2Invalidate(GX2_INVALIDATE_MODE_CPU_SHADER, block->data, block->header.dataSize); gfd->vs->program = block->data; break; case GFD_BLOCK_TYPE_PIXEL_SHADER_HEADER: if (gfd->ps) continue; gfd->ps = (GX2PixelShader*)block->data; if(!gfd_relocate_block(block)) goto error; break; case GFD_BLOCK_TYPE_PIXEL_SHADER_PROGRAM: if(gfd->ps->program) continue; GX2Invalidate(GX2_INVALIDATE_MODE_CPU_SHADER, block->data, block->header.dataSize); gfd->ps->program = block->data; break; default: break; } block = (GFDBlock *)((u8 *)block + block->header.headerSize + block->header.dataSize); } if(!gfd->vs) { printf("vertex shader is missing.\n"); goto error; } if(!gfd->vs->program) { printf("vertex shader program is missing.\n"); goto error; } if(!gfd->ps) { printf("pixel shader is missing.\n"); goto error; } if(!gfd->ps->program) { printf("pixel shader program is missing.\n"); goto error; } return gfd; error: printf("failed to open file : %s\n", filename); gfd_free(gfd); return NULL; }
static void wiiu_font_render_line( video_frame_info_t *video_info, wiiu_font_t* font, const char* msg, unsigned msg_len, float scale, const unsigned int color, float pos_x, float pos_y, unsigned text_align) { unsigned i; wiiu_video_t* wiiu = (wiiu_video_t*)video_driver_get_ptr(false); unsigned width = video_info->width; unsigned height = video_info->height; int x = roundf(pos_x * width); int y = roundf((1.0f - pos_y) * height); int delta_x = 0; int delta_y = 0; if(wiiu->vertex_cache.current + (msg_len * 4) > wiiu->vertex_cache.size) return; switch (text_align) { case TEXT_ALIGN_RIGHT: x -= wiiu_font_get_message_width(font, msg, msg_len, scale); break; case TEXT_ALIGN_CENTER: x -= wiiu_font_get_message_width(font, msg, msg_len, scale) / 2; break; } position_t* pos = wiiu->vertex_cache.positions + wiiu->vertex_cache.current; tex_coord_t* coord = wiiu->vertex_cache.tex_coords + wiiu->vertex_cache.current; for (i = 0; i < msg_len; i++) { int off_x, off_y, tex_x, tex_y, width, height; const char* msg_tmp = &msg[i]; unsigned code = utf8_walk(&msg_tmp); unsigned skip = msg_tmp - &msg[i]; if (skip > 1) i += skip - 1; const struct font_glyph* glyph = font->font_driver->get_glyph(font->font_data, code); if (!glyph) /* Do something smarter here ... */ glyph = font->font_driver->get_glyph(font->font_data, '?'); if (!glyph) continue; off_x = glyph->draw_offset_x; off_y = glyph->draw_offset_y; tex_x = glyph->atlas_offset_x; tex_y = glyph->atlas_offset_y; width = glyph->width; height = glyph->height; float x0 = x + off_x + delta_x * scale; float y0 = y + off_y + delta_y * scale + height * scale; float u0 = tex_x; float v0 = tex_y; float x1 = x0 + width * scale; float y1 = y0 - height * scale; float u1 = u0 + width; float v1 = v0 + height; pos[0].x = (2.0f * x0 / wiiu->color_buffer.surface.width) - 1.0f; pos[0].y = (-2.0f * y0 / wiiu->color_buffer.surface.height) + 1.0f; pos[1].x = (2.0f * x1 / wiiu->color_buffer.surface.width) - 1.0f;; pos[1].y = (-2.0f * y0 / wiiu->color_buffer.surface.height) + 1.0f; pos[2].x = (2.0f * x1 / wiiu->color_buffer.surface.width) - 1.0f;; pos[2].y = (-2.0f * y1 / wiiu->color_buffer.surface.height) + 1.0f; pos[3].x = (2.0f * x0 / wiiu->color_buffer.surface.width) - 1.0f;; pos[3].y = (-2.0f * y1 / wiiu->color_buffer.surface.height) + 1.0f; pos += 4; coord[0].u = u0 / font->texture.surface.width; coord[0].v = v1 / font->texture.surface.height; coord[1].u = u1 / font->texture.surface.width; coord[1].v = v1 / font->texture.surface.height; coord[2].u = u1 / font->texture.surface.width; coord[2].v = v0 / font->texture.surface.height; coord[3].u = u0 / font->texture.surface.width; coord[3].v = v0 / font->texture.surface.height; coord += 4; delta_x += glyph->advance_x; delta_y += glyph->advance_y; } int count = pos - wiiu->vertex_cache.positions - wiiu->vertex_cache.current; if (!count) return; GX2Invalidate(GX2_INVALIDATE_MODE_CPU_ATTRIBUTE_BUFFER, wiiu->vertex_cache.positions + wiiu->vertex_cache.current, count * sizeof(position_t)); GX2Invalidate(GX2_INVALIDATE_MODE_CPU_ATTRIBUTE_BUFFER, wiiu->vertex_cache.tex_coords + wiiu->vertex_cache.current, count * sizeof(tex_coord_t)); if(font->atlas->dirty) { for (i = 0; (i < font->atlas->height) && (i < font->texture.surface.height); i++) memcpy(font->texture.surface.image + (i * font->texture.surface.pitch), font->atlas->buffer + (i * font->atlas->width), font->atlas->width); GX2Invalidate(GX2_INVALIDATE_MODE_CPU_TEXTURE, font->texture.surface.image, font->texture.surface.imageSize); font->atlas->dirty = false; } #if 0 printf("%s\n", msg); DEBUG_VAR(color); #endif GX2SetPixelTexture(&font->texture, wiiu->shader->sampler.location); GX2SetBlendConstantColor(((color >> 0) & 0xFF) / 255.0f, ((color >> 8) & 0xFF) / 255.0f, ((color >> 16) & 0xFF) / 255.0f, ((color >> 24) & 0xFF) / 255.0f); GX2SetBlendControl(GX2_RENDER_TARGET_0, GX2_BLEND_MODE_BLEND_FACTOR, GX2_BLEND_MODE_INV_SRC_ALPHA, GX2_BLEND_COMBINE_MODE_ADD, GX2_ENABLE, GX2_BLEND_MODE_SRC_ALPHA, GX2_BLEND_MODE_INV_SRC_ALPHA, GX2_BLEND_COMBINE_MODE_ADD); GX2DrawEx(GX2_PRIMITIVE_MODE_QUADS, count, wiiu->vertex_cache.current, 1); GX2SetBlendControl(GX2_RENDER_TARGET_0, GX2_BLEND_MODE_SRC_ALPHA, GX2_BLEND_MODE_INV_SRC_ALPHA, GX2_BLEND_COMBINE_MODE_ADD, GX2_ENABLE, GX2_BLEND_MODE_SRC_ALPHA, GX2_BLEND_MODE_INV_SRC_ALPHA, GX2_BLEND_COMBINE_MODE_ADD); wiiu->vertex_cache.current = pos - wiiu->vertex_cache.positions; }