static bool xdk_d3d_frame(void *data, const void *frame, unsigned width, unsigned height, unsigned pitch, const char *msg) { if (!frame) return true; xdk_d3d_video_t *d3d = (xdk_d3d_video_t*)data; bool menu_enabled = g_console.menu_enable; bool fps_enable = g_console.fps_info_enable; if (d3d->last_width != width || d3d->last_height != height) //240*160 { D3DLOCKED_RECT d3dlr; d3d->lpTexture->LockRect(0, &d3dlr, NULL, 0); memset(d3dlr.pBits, 0, 512 * d3dlr.Pitch); d3d->lpTexture->UnlockRect(0); float tex_w = width; // / 512.0f; float tex_h = height; // / 512.0f; DrawVerticeFormats verts[] = { { -1.0f, -1.0f, 1.0f, 0.0f, tex_h }, { 1.0f, -1.0f, 1.0f, tex_w, tex_h }, { -1.0f, 1.0f, 1.0f, 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, tex_w, 0.0f }, }; // Align texels and vertices (D3D9 quirk). for (unsigned i = 0; i < 4; i++) { verts[i].x -= 0.5f / 512.0f; verts[i].y += 0.5f / 512.0f; } BYTE *verts_ptr; d3d->vertex_buf->Lock(0, 0, &verts_ptr, 0); memcpy(verts_ptr, verts, sizeof(verts)); d3d->vertex_buf->Unlock(); d3d->last_width = width; d3d->last_height = height; } if (d3d->should_resize) xdk_d3d_set_viewport(false); d3d->frame_count++; d3d->d3d_render_device->SetTexture(0, d3d->lpTexture); D3DLOCKED_RECT d3dlr; d3d->lpTexture->LockRect(0, &d3dlr, NULL, 0); for (unsigned y = 0; y < height; y++) { const uint8_t *in = (const uint8_t*)frame + y * pitch; uint8_t *out = (uint8_t*)d3dlr.pBits + y * d3dlr.Pitch; memcpy(out, in, width * sizeof(uint16_t)); } d3d->lpTexture->UnlockRect(0); d3d->d3d_render_device->SetSamplerState(0, D3DSAMP_MINFILTER, g_settings.video.smooth ? D3DTEXF_LINEAR : D3DTEXF_POINT); d3d->d3d_render_device->SetSamplerState(0, D3DSAMP_MAGFILTER, g_settings.video.smooth ? D3DTEXF_LINEAR : D3DTEXF_POINT); d3d->d3d_render_device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_BORDER); d3d->d3d_render_device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_BORDER); D3DXMATRIX p_out; D3DXMatrixIdentity(&p_out); d3d->d3d_render_device->SetTransform(D3DTS_WORLD, &p_out); d3d->d3d_render_device->SetTransform(D3DTS_VIEW, &p_out); d3d->d3d_render_device->SetTransform(D3DTS_PROJECTION, &p_out); d3d->d3d_render_device->SetVertexShader(D3DFVF_XYZ | D3DFVF_TEX1); d3d->d3d_render_device->SetStreamSource(0, d3d->vertex_buf, sizeof(DrawVerticeFormats)); d3d->d3d_render_device->Clear(0, NULL, D3DCLEAR_TARGET, 0xff000000, 1.0f, 0); d3d->d3d_render_device->BeginScene(); d3d->d3d_render_device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); d3d->d3d_render_device->EndScene(); if(fps_enable) { static MEMORYSTATUS stat; GlobalMemoryStatus(&stat); d3d->d3d_render_device->GetBackBuffer(-1, D3DBACKBUFFER_TYPE_MONO, &d3d->pFrontBuffer); d3d->d3d_render_device->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &d3d->pBackBuffer); //Output memory usage char buf[128], buf2[128], buf_fps_last[128]; bool ret = false; sprintf(buf, "%.2f MB free / %.2f MB total", stat.dwAvailPhys/(1024.0f*1024.0f), stat.dwTotalPhys/(1024.0f*1024.0f)); rarch_convert_char_to_wchar(strw_buffer, buf, sizeof(strw_buffer)); d3d->debug_font->TextOut(d3d->pFrontBuffer, strw_buffer, (unsigned)-1, font_x + 30, font_y + 50 ); d3d->debug_font->TextOut(d3d->pBackBuffer, strw_buffer, (unsigned)-1, font_x + 30, font_y + 50 ); if(ret = gfx_window_title(buf2, sizeof(buf2)) || sizeof(buf_fps_last)) { if(ret) { sprintf(buf_fps_last, buf2); rarch_convert_char_to_wchar(strw_buffer, buf2, sizeof(strw_buffer)); } else if(buf_fps_last) rarch_convert_char_to_wchar(strw_buffer, buf_fps_last, sizeof(strw_buffer)); d3d->debug_font->TextOut(d3d->pFrontBuffer, strw_buffer, (unsigned)-1, font_x + 30, font_y + 70 ); d3d->debug_font->TextOut(d3d->pBackBuffer, strw_buffer, (unsigned)-1, font_x + 30, font_y + 70 ); d3d->pFrontBuffer->Release(); d3d->pBackBuffer->Release(); } } if(!d3d->block_swap) gfx_ctx_swap_buffers(); return true; }
static void *gl_init(const video_info_t *video, const input_driver_t **input, void **input_data) { #ifdef _WIN32 gfx_set_dwm(); #endif if (!sdlwrap_init()) return NULL; const SDL_VideoInfo *video_info = SDL_GetVideoInfo(); rarch_assert(video_info); unsigned full_x = video_info->current_w; unsigned full_y = video_info->current_h; RARCH_LOG("Detecting desktop resolution %ux%u.\n", full_x, full_y); sdlwrap_set_swap_interval(video->vsync ? 1 : 0, false); unsigned win_width = video->width; unsigned win_height = video->height; if (video->fullscreen && (win_width == 0) && (win_height == 0)) { win_width = full_x; win_height = full_y; } if (!sdlwrap_set_video_mode(win_width, win_height, g_settings.video.force_16bit ? 15 : 0, video->fullscreen)) return NULL; gfx_window_title_reset(); char buf[128]; if (gfx_window_title(buf, sizeof(buf))) sdlwrap_wm_set_caption(buf); // Remove that ugly mouse :D SDL_ShowCursor(SDL_DISABLE); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); #if (defined(HAVE_XML) || defined(HAVE_CG)) && defined(_WIN32) // Win32 GL lib doesn't have some functions needed for XML shaders. // Need to load dynamically :( if (!load_gl_proc()) { sdlwrap_destroy(); return NULL; } #endif gl_t *gl = (gl_t*)calloc(1, sizeof(gl_t)); if (!gl) { sdlwrap_destroy(); return NULL; } gl->vsync = video->vsync; gl->fullscreen = video->fullscreen; gl->full_x = full_x; gl->full_y = full_y; gl->win_width = win_width; gl->win_height = win_height; RARCH_LOG("GL: Using resolution %ux%u\n", gl->win_width, gl->win_height); if (!gl_shader_init()) { RARCH_ERR("Shader init failed.\n"); sdlwrap_destroy(); free(gl); return NULL; } RARCH_LOG("GL: Loaded %u program(s).\n", gl_shader_num()); #ifdef HAVE_FBO // Set up render to texture. gl_init_fbo(gl, RARCH_SCALE_BASE * video->input_scale, RARCH_SCALE_BASE * video->input_scale); #endif gl->keep_aspect = video->force_aspect; // Apparently need to set viewport for passes when we aren't using FBOs. gl_shader_use(0); set_viewport(gl, gl->win_width, gl->win_height, false, true); gl_shader_use(1); set_viewport(gl, gl->win_width, gl->win_height, false, true); bool force_smooth; if (gl_shader_filter_type(1, &force_smooth)) gl->tex_filter = force_smooth ? GL_LINEAR : GL_NEAREST; else gl->tex_filter = video->smooth ? GL_LINEAR : GL_NEAREST; gl->texture_type = GL_BGRA; gl->texture_fmt = video->rgb32 ? GL_UNSIGNED_INT_8_8_8_8_REV : GL_UNSIGNED_SHORT_1_5_5_5_REV; gl->base_size = video->rgb32 ? sizeof(uint32_t) : sizeof(uint16_t); glEnable(GL_TEXTURE_2D); glDisable(GL_DEPTH_TEST); glDisable(GL_DITHER); glClearColor(0, 0, 0, 1); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glGenTextures(TEXTURES, gl->texture); for (unsigned i = 0; i < TEXTURES; i++) { glBindTexture(GL_TEXTURE_2D, gl->texture[i]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl->tex_filter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl->tex_filter); } glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glVertexPointer(2, GL_FLOAT, 0, vertexes_flipped); memcpy(gl->tex_coords, tex_coords, sizeof(tex_coords)); glTexCoordPointer(2, GL_FLOAT, 0, gl->tex_coords); glColorPointer(4, GL_FLOAT, 0, white_color); set_lut_texture_coords(tex_coords); gl->tex_w = RARCH_SCALE_BASE * video->input_scale; gl->tex_h = RARCH_SCALE_BASE * video->input_scale; // Empty buffer that we use to clear out the texture with on res change. gl->empty_buf = calloc(gl->tex_w * gl->tex_h, gl->base_size); for (unsigned i = 0; i < TEXTURES; i++) { glBindTexture(GL_TEXTURE_2D, gl->texture[i]); glPixelStorei(GL_UNPACK_ROW_LENGTH, gl->tex_w); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, gl->tex_w, gl->tex_h, 0, gl->texture_type, gl->texture_fmt, gl->empty_buf ? gl->empty_buf : NULL); } glBindTexture(GL_TEXTURE_2D, gl->texture[gl->tex_index]); for (unsigned i = 0; i < TEXTURES; i++) { gl->last_width[i] = gl->tex_w; gl->last_height[i] = gl->tex_h; } for (unsigned i = 0; i < TEXTURES; i++) { gl->prev_info[i].tex = gl->texture[(gl->tex_index - (i + 1)) & TEXTURES_MASK]; gl->prev_info[i].input_size[0] = gl->tex_w; gl->prev_info[i].tex_size[0] = gl->tex_w; gl->prev_info[i].input_size[1] = gl->tex_h; gl->prev_info[i].tex_size[1] = gl->tex_h; memcpy(gl->prev_info[i].coord, tex_coords, sizeof(tex_coords)); } // Hook up SDL input driver to get SDL_QUIT events and RESIZE. sdl_input_t *sdl_input = (sdl_input_t*)input_sdl.init(); if (sdl_input) { *input = &input_sdl; *input_data = sdl_input; } else *input = NULL; gl_init_font(gl, g_settings.video.font_path, g_settings.video.font_size); if (!gl_check_error()) { sdlwrap_destroy(); free(gl); return NULL; } return gl; }
static bool setup_video(ext_t *ext, const video_info_t *video, const input_driver_t **input, void **input_data) { RARCH_LOG("Loaded driver: \"%s\"\n", ext->driver->ident ? ext->driver->ident : "Unknown"); if (RARCH_GRAPHICS_API_VERSION != ext->driver->api_version) { RARCH_ERR("API version mismatch detected.\n"); RARCH_ERR("Required API version: %d, Library version: %d\n", RARCH_GRAPHICS_API_VERSION, ext->driver->api_version); return false; } const char *cg_shader = NULL; const char *xml_shader = NULL; enum rarch_shader_type type = g_settings.video.shader_type; if ((type == RARCH_SHADER_CG || type == RARCH_SHADER_AUTO) && *g_settings.video.cg_shader_path) cg_shader = g_settings.video.cg_shader_path; else if ((type == RARCH_SHADER_BSNES || type == RARCH_SHADER_AUTO) && *g_settings.video.bsnes_shader_path) xml_shader = g_settings.video.bsnes_shader_path; int font_color_r = g_settings.video.msg_color_r * 255; int font_color_g = g_settings.video.msg_color_g * 255; int font_color_b = g_settings.video.msg_color_b * 255; font_color_r = font_color_r > 255 ? 255 : (font_color_r < 0 ? 0 : font_color_r); font_color_g = font_color_g > 255 ? 255 : (font_color_g < 0 ? 0 : font_color_g); font_color_b = font_color_b > 255 ? 255 : (font_color_b < 0 ? 0 : font_color_b); const char *font = NULL; if (g_settings.video.font_enable) { #ifdef HAVE_FREETYPE if (*g_settings.video.font_path) font = g_settings.video.font_path; else font = font_renderer_get_default_font(); #else font = *g_settings.video.font_path ? g_settings.video.font_path : NULL; #endif } char title_buf[128]; gfx_window_title_reset(); gfx_window_title(title_buf, sizeof(title_buf)); rarch_video_info_t info = {0}; info.width = video->width; info.height = video->height; info.fullscreen = video->fullscreen; info.vsync = video->vsync; info.force_aspect = video->force_aspect; info.aspect_ratio = g_settings.video.aspect_ratio; info.smooth = video->smooth; info.input_scale = video->input_scale; info.color_format = video->rgb32 ? RARCH_COLOR_FORMAT_ARGB8888 : RARCH_COLOR_FORMAT_XRGB1555; info.xml_shader = xml_shader; info.cg_shader = cg_shader; info.ttf_font = font; info.ttf_font_size = g_settings.video.font_size; info.ttf_font_color = (font_color_r << 16) | (font_color_g << 8) | (font_color_b << 0); info.title_hint = title_buf; #ifdef HAVE_PYTHON info.python_state_new = py_state_new; info.python_state_get = py_state_get; info.python_state_free = py_state_free; #endif const rarch_input_driver_t *input_driver = NULL; ext->handle = ext->driver->init(&info, &input_driver); if (!ext->handle) return false; *input = input_driver ? &input_ext : NULL; if (input_driver) *input_data = setup_input(ext, input_driver); else *input_data = NULL; return true; }
static bool gl_frame(void *data, const void *frame, unsigned width, unsigned height, unsigned pitch, const char *msg) { gl_t *gl = (gl_t*)data; gl_shader_use(1); gl->frame_count++; glBindTexture(GL_TEXTURE_2D, gl->texture[gl->tex_index]); #ifdef HAVE_FBO // Render to texture in first pass. if (gl->fbo_inited) { // Recompute FBO geometry. // When width/height changes or window sizes change, we have to recalcuate geometry of our FBO. gl_compute_fbo_geometry(gl, width, height, gl->vp_out_width, gl->vp_out_height); gl_start_frame_fbo(gl); } #endif if (gl->should_resize) { gl->should_resize = false; sdlwrap_set_resize(gl->win_width, gl->win_height); // On resize, we might have to recreate our FBOs due to "Viewport" scale, and set a new viewport. gl_update_resize(gl); } gl_update_input_size(gl, width, height, pitch); gl_copy_frame(gl, frame, width, height, pitch); struct gl_tex_info tex_info = {0}; tex_info.tex = gl->texture[gl->tex_index]; tex_info.input_size[0] = width; tex_info.input_size[1] = height; tex_info.tex_size[0] = gl->tex_w; tex_info.tex_size[1] = gl->tex_h; memcpy(tex_info.coord, gl->tex_coords, sizeof(gl->tex_coords)); glClear(GL_COLOR_BUFFER_BIT); gl_shader_set_params(width, height, gl->tex_w, gl->tex_h, gl->vp_width, gl->vp_height, gl->frame_count, &tex_info, gl->prev_info, NULL, 0); glDrawArrays(GL_QUADS, 0, 4); #ifdef HAVE_FBO if (gl->fbo_inited) gl_frame_fbo(gl, &tex_info); #endif gl_next_texture_index(gl, &tex_info); if (msg) gl_render_msg(gl, msg); char buf[128]; if (gfx_window_title(buf, sizeof(buf))) sdlwrap_wm_set_caption(buf); sdlwrap_swap_buffers(); return true; }