static bool win32_set_window_opacity(void *data, unsigned opacity) { HWND hwnd = win32_get_window(); dispserv_win32_t *serv = (dispserv_win32_t*)data; if (serv) serv->opacity = opacity; #if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0500 /* Set window transparency on Windows 2000 and above */ if(opacity < 100) { SetWindowLongPtr(hwnd, GWL_EXSTYLE, GetWindowLongPtr(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED); return SetLayeredWindowAttributes(hwnd, 0, (255 * opacity) / 100, LWA_ALPHA); } SetWindowLongPtr(hwnd, GWL_EXSTYLE, GetWindowLongPtr(hwnd, GWL_EXSTYLE) & ~WS_EX_LAYERED); return true; #else return false; #endif }
static void gfx_ctx_wgl_get_video_size(void *data, unsigned *width, unsigned *height) { HWND window = win32_get_window(); (void)data; if (!window) { RECT mon_rect; MONITORINFOEX current_mon; unsigned mon_id = 0; HMONITOR hm_to_use = NULL; win32_monitor_info(¤t_mon, &hm_to_use, &mon_id); mon_rect = current_mon.rcMonitor; *width = mon_rect.right - mon_rect.left; *height = mon_rect.bottom - mon_rect.top; } else { *width = g_win32_resize_width; *height = g_win32_resize_height; } }
static void d3d_free(void *data) { d3d_video_t *d3d = (d3d_video_t*)data; HWND window = win32_get_window(); if (!d3d) return; d3d_deinitialize(d3d); #ifdef HAVE_OVERLAY d3d_free_overlays(d3d); #endif gfx_ctx_free(); #ifndef _XBOX #ifdef HAVE_MENU d3d_free_overlay(d3d, d3d->menu); if (d3d->menu) delete d3d->menu; #endif #endif d3d_device_free(d3d->dev, g_pD3D); d3d->dev = NULL; g_pD3D = NULL; win32_monitor_from_window(window, true); if (d3d) delete d3d; win32_destroy_window(); }
static void gdi_gfx_free(void *data) { gdi_t *gdi = (gdi_t*)data; HWND hwnd = win32_get_window(); if (gdi_menu_frame) { free(gdi_menu_frame); gdi_menu_frame = NULL; } if (!gdi) return; if (gdi->memDC) { DeleteObject(gdi->bmp); DeleteDC(gdi->memDC); gdi->memDC = 0; } if (hwnd && gdi->winDC) { ReleaseDC(hwnd, gdi->winDC); gdi->winDC = 0; } font_driver_free_osd(); video_context_driver_free(); free(gdi); }
static void gfx_ctx_d3d_update_title(void *data) { char buf[128] = {0}; char buffer_fps[128] = {0}; settings_t *settings = config_get_ptr(); HWND window = win32_get_window(); if (video_monitor_get_fps(buf, sizeof(buf), buffer_fps, sizeof(buffer_fps))) { #ifndef _XBOX SetWindowText(window, buf); #endif } if (settings->fps_show) { #ifdef _XBOX MEMORYSTATUS stat; char mem[128] = {0}; GlobalMemoryStatus(&stat); snprintf(mem, sizeof(mem), "|| MEM: %.2f/%.2fMB", stat.dwAvailPhys/(1024.0f*1024.0f), stat.dwTotalPhys/(1024.0f*1024.0f)); strlcat(buffer_fps, mem, sizeof(buffer_fps)); #endif runloop_msg_queue_push(buffer_fps, 1, 1, false); } }
static void gfx_ctx_gdi_destroy(void *data) { HWND window = win32_get_window(); (void)data; switch (win32_gdi_api) { case GFX_CTX_NONE: default: break; } if (window && win32_gdi_hdc) { ReleaseDC(window, win32_gdi_hdc); win32_gdi_hdc = NULL; } if (window) { win32_monitor_from_window(); win32_destroy_window(); } if (g_restore_desktop) { win32_monitor_get_info(); g_restore_desktop = false; } g_inited = false; win32_gdi_major = 0; win32_gdi_minor = 0; }
static bool d3d_init_base(void *data, const video_info_t *info) { D3DPRESENT_PARAMETERS d3dpp; d3d_video_t *d3d = (d3d_video_t*)data; d3d_make_d3dpp(d3d, info, &d3dpp); g_pD3D = D3DCREATE_CTX(D3D_SDK_VERSION); if (!g_pD3D) { RARCH_ERR("Failed to create D3D interface.\n"); return false; } #ifdef _XBOX360 d3d->cur_mon_id = 0; #endif if (FAILED(d3d->d3d_err = g_pD3D->CreateDevice( d3d->cur_mon_id, D3DDEVTYPE_HAL, win32_get_window(), D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &d3d->dev))) { RARCH_WARN("[D3D]: Failed to init device with hardware vertex processing (code: 0x%x). Trying to fall back to software vertex processing.\n", (unsigned)d3d->d3d_err); if (FAILED(d3d->d3d_err = g_pD3D->CreateDevice( d3d->cur_mon_id, D3DDEVTYPE_HAL, win32_get_window(), D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &d3d->dev))) { RARCH_ERR("Failed to initialize device.\n"); return false; } } return true; }
static void gfx_ctx_wgl_update_window_title(void *data) { char buf[128] = {0}; char buf_fps[128] = {0}; settings_t *settings = config_get_ptr(); HWND window = win32_get_window(); (void)data; if (video_monitor_get_fps(buf, sizeof(buf), buf_fps, sizeof(buf_fps))) SetWindowText(window, buf); if (settings->fps_show) runloop_msg_queue_push(buf_fps, 1, 1, false); }
static void gfx_ctx_wgl_destroy(void *data) { HWND window = win32_get_window(); (void)data; if (g_hrc) { glFinish(); wglMakeCurrent(NULL, NULL); if (!video_driver_ctl(RARCH_DISPLAY_CTL_IS_VIDEO_CACHE_CONTEXT, NULL)) { if (g_hw_hrc) wglDeleteContext(g_hw_hrc); wglDeleteContext(g_hrc); g_hrc = NULL; g_hw_hrc = NULL; } } if (window && g_hdc) { ReleaseDC(window, g_hdc); g_hdc = NULL; } if (window) { win32_monitor_from_window(window, true); win32_destroy_window(); } if (g_restore_desktop) { win32_monitor_get_info(); g_restore_desktop = false; } g_core_hw_context_enable = false; g_inited = false; g_major = 0; g_minor = 0; p_swap_interval = NULL; }
static bool win32_set_window_progress(void *data, int progress, bool finished) { HWND hwnd = win32_get_window(); dispserv_win32_t *serv = (dispserv_win32_t*)data; if (serv) serv->progress = progress; #ifdef HAS_TASKBAR_EXT if (!g_taskbarList || !win32_taskbar_is_created()) return false; if (progress == -1) { if (ITaskbarList3_SetProgressState( g_taskbarList, hwnd, TBPF_INDETERMINATE) != S_OK) return false; } else if (finished) { if (ITaskbarList3_SetProgressState( g_taskbarList, hwnd, TBPF_NOPROGRESS) != S_OK) return false; } else if (progress >= 0) { if (ITaskbarList3_SetProgressState( g_taskbarList, hwnd, TBPF_NORMAL) != S_OK) return false; if (ITaskbarList3_SetProgressValue( g_taskbarList, hwnd, progress, 100) != S_OK) return false; } #endif return true; }
void d3d_make_d3dpp(void *data, const video_info_t *info, D3DPRESENT_PARAMETERS *d3dpp) { d3d_video_t *d3d = (d3d_video_t*)data; settings_t *settings = config_get_ptr(); #ifdef _XBOX /* TODO/FIXME - get rid of global state dependencies. */ global_t *global = global_get_ptr(); #endif memset(d3dpp, 0, sizeof(*d3dpp)); d3dpp->Windowed = false; #ifndef _XBOX d3dpp->Windowed = settings->video.windowed_fullscreen || !info->fullscreen; #endif d3dpp->PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; if (info->vsync) { switch (settings->video.swap_interval) { default: case 1: d3dpp->PresentationInterval = D3DPRESENT_INTERVAL_ONE; break; case 2: d3dpp->PresentationInterval = D3DPRESENT_INTERVAL_TWO; break; case 3: d3dpp->PresentationInterval = D3DPRESENT_INTERVAL_THREE; break; case 4: d3dpp->PresentationInterval = D3DPRESENT_INTERVAL_FOUR; break; } } d3dpp->SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp->BackBufferCount = 2; #ifdef _XBOX d3dpp->BackBufferFormat = #ifdef _XBOX360 global->console.screen.gamma_correction ? (D3DFORMAT)MAKESRGBFMT(info->rgb32 ? D3DFMT_X8R8G8B8 : D3DFMT_LIN_R5G6B5) : #endif info->rgb32 ? D3DFMT_X8R8G8B8 : D3DFMT_LIN_R5G6B5; #else d3dpp->hDeviceWindow = win32_get_window(); d3dpp->BackBufferFormat = !d3dpp->Windowed ? D3DFMT_X8R8G8B8 : D3DFMT_UNKNOWN; #endif if (!d3dpp->Windowed) { #ifdef _XBOX unsigned width = 0; unsigned height = 0; gfx_ctx_get_video_size(&width, &height); video_driver_set_size(&width, &height); #endif video_driver_get_size(&d3dpp->BackBufferWidth, &d3dpp->BackBufferHeight); } #ifdef _XBOX d3dpp->MultiSampleType = D3DMULTISAMPLE_NONE; d3dpp->EnableAutoDepthStencil = FALSE; #if defined(_XBOX1) /* Get the "video mode" */ DWORD video_mode = XGetVideoFlags(); /* Check if we are able to use progressive mode. */ if (video_mode & XC_VIDEO_FLAGS_HDTV_480p) d3dpp->Flags = D3DPRESENTFLAG_PROGRESSIVE; else d3dpp->Flags = D3DPRESENTFLAG_INTERLACED; /* Only valid in PAL mode, not valid for HDTV modes. */ if (XGetVideoStandard() == XC_VIDEO_STANDARD_PAL_I) { if (video_mode & XC_VIDEO_FLAGS_PAL_60Hz) d3dpp->FullScreen_RefreshRateInHz = 60; else d3dpp->FullScreen_RefreshRateInHz = 50; } if (XGetAVPack() == XC_AV_PACK_HDTV) { if (video_mode & XC_VIDEO_FLAGS_HDTV_480p) d3dpp->Flags = D3DPRESENTFLAG_PROGRESSIVE; else if (video_mode & XC_VIDEO_FLAGS_HDTV_720p) d3dpp->Flags = D3DPRESENTFLAG_PROGRESSIVE; else if (video_mode & XC_VIDEO_FLAGS_HDTV_1080i) d3dpp->Flags = D3DPRESENTFLAG_INTERLACED; } if (widescreen_mode) d3dpp->Flags |= D3DPRESENTFLAG_WIDESCREEN; #elif defined(_XBOX360) if (!widescreen_mode) d3dpp->Flags |= D3DPRESENTFLAG_NO_LETTERBOX; if (global->console.screen.gamma_correction) d3dpp->FrontBufferFormat = (D3DFORMAT)MAKESRGBFMT(D3DFMT_LE_X8R8G8B8); else d3dpp->FrontBufferFormat = D3DFMT_LE_X8R8G8B8; d3dpp->MultiSampleQuality = 0; #endif #endif }
static void gfx_ctx_wgl_destroy(void *data) { HWND window = win32_get_window(); gfx_ctx_wgl_data_t *wgl = (gfx_ctx_wgl_data_t*)data; switch (win32_api) { case GFX_CTX_OPENGL_API: #ifdef HAVE_OPENGL if (win32_hrc) { glFinish(); wglMakeCurrent(NULL, NULL); if (!video_driver_is_video_cache_context()) { if (win32_hw_hrc) wglDeleteContext(win32_hw_hrc); wglDeleteContext(win32_hrc); win32_hrc = NULL; win32_hw_hrc = NULL; } } #endif break; case GFX_CTX_VULKAN_API: #ifdef HAVE_VULKAN vulkan_context_destroy(&win32_vk, win32_vk.vk_surface != VK_NULL_HANDLE); if (win32_vk.context.queue_lock) slock_free(win32_vk.context.queue_lock); memset(&win32_vk, 0, sizeof(win32_vk)); #endif break; case GFX_CTX_NONE: default: break; } if (window && win32_hdc) { ReleaseDC(window, win32_hdc); win32_hdc = NULL; } if (window) { win32_monitor_from_window(); win32_destroy_window(); } if (g_win32_restore_desktop) { win32_monitor_get_info(); g_win32_restore_desktop = false; } #ifdef HAVE_DYNAMIC dylib_close(dll_handle); #endif if (wgl) free(wgl); wgl_adaptive_vsync = false; win32_core_hw_context_enable = false; g_win32_inited = false; win32_major = 0; win32_minor = 0; p_swap_interval = NULL; }
static bool gdi_gfx_frame(void *data, const void *frame, unsigned frame_width, unsigned frame_height, uint64_t frame_count, unsigned pitch, const char *msg, video_frame_info_t *video_info) { gfx_ctx_mode_t mode; const void *frame_to_copy = frame; unsigned width = 0; unsigned height = 0; unsigned bits = gdi_video_bits; bool draw = true; gdi_t *gdi = (gdi_t*)data; HWND hwnd = win32_get_window(); if (!frame || !frame_width || !frame_height) return true; #ifdef HAVE_MENU menu_driver_frame(video_info); #endif if (gdi_video_width != frame_width || gdi_video_height != frame_height || gdi_video_pitch != pitch) { if (frame_width > 4 && frame_height > 4) { gdi_video_width = frame_width; gdi_video_height = frame_height; gdi_video_pitch = pitch; } } if (gdi_menu_frame && video_info->menu_is_alive) { frame_to_copy = gdi_menu_frame; width = gdi_menu_width; height = gdi_menu_height; pitch = gdi_menu_pitch; bits = gdi_menu_bits; } else { width = gdi_video_width; height = gdi_video_height; pitch = gdi_video_pitch; if (frame_width == 4 && frame_height == 4 && (frame_width < width && frame_height < height)) draw = false; if (video_info->menu_is_alive) draw = false; } if (hwnd && !gdi->winDC) { gdi->winDC = GetDC(hwnd); gdi->memDC = CreateCompatibleDC(gdi->winDC); gdi->video_width = width; gdi->video_height = height; gdi->bmp = CreateCompatibleBitmap(gdi->winDC, gdi->video_width, gdi->video_height); } gdi->bmp_old = (HBITMAP)SelectObject(gdi->memDC, gdi->bmp); if (gdi->video_width != width || gdi->video_height != height) { SelectObject(gdi->memDC, gdi->bmp_old); DeleteObject(gdi->bmp); gdi->video_width = width; gdi->video_height = height; gdi->bmp = CreateCompatibleBitmap(gdi->winDC, gdi->video_width, gdi->video_height); gdi->bmp_old = (HBITMAP)SelectObject(gdi->memDC, gdi->bmp); } video_context_driver_get_video_size(&mode); gdi->screen_width = mode.width; gdi->screen_height = mode.height; BITMAPINFO *info = (BITMAPINFO*)calloc(1, sizeof(*info) + (3 * sizeof(RGBQUAD))); info->bmiHeader.biBitCount = bits; info->bmiHeader.biWidth = pitch / (bits / 8); info->bmiHeader.biHeight = -height; info->bmiHeader.biPlanes = 1; info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); info->bmiHeader.biSizeImage = 0; if (bits == 16) { unsigned *masks = (unsigned*)info->bmiColors; info->bmiHeader.biCompression = BI_BITFIELDS; /* default 16-bit format on Windows is XRGB1555 */ if (frame_to_copy == gdi_menu_frame) { /* map RGB444 color bits for RGUI */ masks[0] = 0xF000; masks[1] = 0x0F00; masks[2] = 0x00F0; } else { /* map RGB565 color bits for core */ masks[0] = 0xF800; masks[1] = 0x07E0; masks[2] = 0x001F; } } else info->bmiHeader.biCompression = BI_RGB; if (draw) { StretchDIBits(gdi->memDC, 0, 0, width, height, 0, 0, width, height, frame_to_copy, info, DIB_RGB_COLORS, SRCCOPY); } SelectObject(gdi->memDC, gdi->bmp_old); free(info); if (msg) font_driver_render_msg(video_info, NULL, msg, NULL); InvalidateRect(hwnd, NULL, false); video_info->cb_update_window_title( video_info->context_data, video_info); return true; }