int SDLScreenDPI(int screen) { int screens = max(1, SDL_GetNumVideoDisplays()); float ddpi = 200; // Reasonable default just in case screen 0 gives an error. #ifndef __EMSCRIPTEN__ SDL_GetDisplayDPI(screen, &ddpi, nullptr, nullptr); #endif return screen >= screens ? 0 // Screen not present. : (int)(ddpi + 0.5f); }
GHOST_TUns16 GHOST_WindowSDL::getDPIHint() { int displayIndex = SDL_GetWindowDisplayIndex(m_sdl_win); if (displayIndex < 0) { return 96; } float ddpi; if (SDL_GetDisplayDPI(displayIndex, &ddpi, NULL, NULL) != 0) { return 96; } return (int)ddpi; }
float RocketRenderingInterface::GetPixelsPerInch() { #if SDL_VERSION_ATLEAST(2, 0, 4) auto display = os_config_read_uint("Video", "Display", 0); float ddpi; if (SDL_GetDisplayDPI(display, &ddpi, nullptr, nullptr) != 0) { mprintf(("Failed to determine display DPI: %s\n", SDL_GetError())); return 96.f; } // Diagonal DPI should be accurate enough return ddpi; #else // return a default value return 96.f; #endif }
math::vector<float, 2> window::get_dpi() const { // On macOS we always get a 2x (or larger?) backbuffer on hi-DPI // systems, and this is then downsampled by the compositor, depending on // the display scale factor. 72 is the default DPI on macOS. // On Windows this is not the case; we get a 1x backbuffer on all // systems, and we'll have to render the graphics at the proper DPI, // which is the DPI of the screen that the window currently resides on. #if defined(__APPLE__) return get_backbuffer_size() / get_size() * 72; #elif defined (_WIN32) int display = SDL_GetWindowDisplayIndex(handle.get()); assert(display != -1); float dpi_x, dpi_y; assert(SDL_GetDisplayDPI(display, nullptr, &dpi_x, &dpi_y) != -1); return { dpi_x, dpi_y }; #endif }
value System::GetDisplay (int id) { if (!init) { id_bounds = val_id ("bounds"); id_currentMode = val_id ("currentMode"); id_dpi = val_id ("dpi"); id_height = val_id ("height"); id_name = val_id ("name"); id_pixelFormat = val_id ("pixelFormat"); id_refreshRate = val_id ("refreshRate"); id_supportedModes = val_id ("supportedModes"); id_width = val_id ("width"); init = true; } int numDisplays = GetNumDisplays (); if (id < 0 || id >= numDisplays) { return alloc_null (); } value display = alloc_empty_object (); alloc_field (display, id_name, alloc_string (SDL_GetDisplayName (id))); SDL_Rect bounds = { 0, 0, 0, 0 }; SDL_GetDisplayBounds (id, &bounds); alloc_field (display, id_bounds, Rectangle (bounds.x, bounds.y, bounds.w, bounds.h).Value ()); float dpi = 72.0; #ifndef EMSCRIPTEN SDL_GetDisplayDPI (id, &dpi, NULL, NULL); #endif alloc_field (display, id_dpi, alloc_float (dpi)); SDL_DisplayMode currentDisplayMode = { SDL_PIXELFORMAT_UNKNOWN, 0, 0, 0, 0 }; SDL_DisplayMode displayMode = { SDL_PIXELFORMAT_UNKNOWN, 0, 0, 0, 0 }; SDL_GetCurrentDisplayMode (id, ¤tDisplayMode); int numDisplayModes = SDL_GetNumDisplayModes (id); value supportedModes = alloc_array (numDisplayModes); value mode; for (int i = 0; i < numDisplayModes; i++) { SDL_GetDisplayMode (id, i, &displayMode); if (displayMode.format == currentDisplayMode.format && displayMode.w == currentDisplayMode.w && displayMode.h == currentDisplayMode.h && displayMode.refresh_rate == currentDisplayMode.refresh_rate) { alloc_field (display, id_currentMode, alloc_int (i)); } mode = alloc_empty_object (); alloc_field (mode, id_height, alloc_int (displayMode.h)); switch (displayMode.format) { case SDL_PIXELFORMAT_ARGB8888: alloc_field (mode, id_pixelFormat, alloc_int (ARGB32)); break; case SDL_PIXELFORMAT_BGRA8888: case SDL_PIXELFORMAT_BGRX8888: alloc_field (mode, id_pixelFormat, alloc_int (BGRA32)); break; default: alloc_field (mode, id_pixelFormat, alloc_int (RGBA32)); } alloc_field (mode, id_refreshRate, alloc_int (displayMode.refresh_rate)); alloc_field (mode, id_width, alloc_int (displayMode.w)); val_array_set_i (supportedModes, i, mode); } alloc_field (display, id_supportedModes, supportedModes); return display; }
int SDLHardwareRenderDevice::createContextInternal() { bool settings_changed = (fullscreen != settings->fullscreen || hwsurface != settings->hwsurface || vsync != settings->vsync || texture_filter != settings->texture_filter || ignore_texture_filter != eset->resolutions.ignore_texture_filter); Uint32 w_flags = 0; Uint32 r_flags = 0; int window_w = settings->screen_w; int window_h = settings->screen_h; if (settings->fullscreen) { w_flags = w_flags | SDL_WINDOW_FULLSCREEN_DESKTOP; // make the window the same size as the desktop resolution SDL_DisplayMode desktop; if (SDL_GetDesktopDisplayMode(0, &desktop) == 0) { window_w = desktop.w; window_h = desktop.h; } } else if (fullscreen && is_initialized) { // if the game was previously in fullscreen, resize the window when returning to windowed mode window_w = eset->resolutions.min_screen_w; window_h = eset->resolutions.min_screen_h; w_flags = w_flags | SDL_WINDOW_SHOWN; } else { w_flags = w_flags | SDL_WINDOW_SHOWN; } w_flags = w_flags | SDL_WINDOW_RESIZABLE; if (settings->hwsurface) { r_flags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE; } else { r_flags = SDL_RENDERER_SOFTWARE | SDL_RENDERER_TARGETTEXTURE; settings->vsync = false; // can't have software mode & vsync at the same time } if (settings->vsync) r_flags = r_flags | SDL_RENDERER_PRESENTVSYNC; if (settings_changed || !is_initialized) { destroyContext(); window = SDL_CreateWindow(NULL, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, window_w, window_h, w_flags); if (window) { renderer = SDL_CreateRenderer(window, -1, r_flags); if (renderer) { if (settings->texture_filter && !eset->resolutions.ignore_texture_filter) SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1"); else SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0"); windowResize(); } SDL_SetWindowMinimumSize(window, eset->resolutions.min_screen_w, eset->resolutions.min_screen_h); // setting minimum size might move the window, so set position again SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED); } if (window && renderer) { if (!is_initialized) { // save the system gamma levels if we just created the window SDL_GetWindowGammaRamp(window, gamma_r, gamma_g, gamma_b); Utils::logInfo("RenderDevice: Window size is %dx%d", settings->screen_w, settings->screen_h); } fullscreen = settings->fullscreen; hwsurface = settings->hwsurface; vsync = settings->vsync; texture_filter = settings->texture_filter; ignore_texture_filter = eset->resolutions.ignore_texture_filter; is_initialized = true; Utils::logInfo("RenderDevice: Fullscreen=%d, Hardware surfaces=%d, Vsync=%d, Texture Filter=%d", fullscreen, hwsurface, vsync, texture_filter); #if SDL_VERSION_ATLEAST(2, 0, 4) SDL_GetDisplayDPI(0, &ddpi, 0, 0); Utils::logInfo("RenderDevice: Display DPI is %f", ddpi); #else Utils::logError("RenderDevice: The SDL version used to compile Flare does not support SDL_GetDisplayDPI(). The virtual_dpi setting will be ignored."); #endif } } if (is_initialized) { // update minimum window size if it has changed if (min_screen.x != eset->resolutions.min_screen_w || min_screen.y != eset->resolutions.min_screen_h) { min_screen.x = eset->resolutions.min_screen_w; min_screen.y = eset->resolutions.min_screen_h; SDL_SetWindowMinimumSize(window, eset->resolutions.min_screen_w, eset->resolutions.min_screen_h); SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED); } windowResize(); // update title bar text and icon updateTitleBar(); // load persistent resources delete icons; icons = new IconManager(); delete curs; curs = new CursorManager(); if (settings->change_gamma) setGamma(settings->gamma); else { resetGamma(); settings->change_gamma = false; settings->gamma = 1.0; } } return (is_initialized ? 0 : -1); }
/* inits sdl and creates an opengl window */ static void initSDL(VideoMode *video) { if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER) < 0) { LOGE("Failed to init SDL2: %s", SDL_GetError()); exit(1); } #ifdef _WIN32 float ddpi; if (!SDL_GetDisplayDPI(0, &ddpi, nullptr, nullptr)) { const float WINDOWS_DEFAULT_DPI = 96.0f; video->pixel_scale = ddpi / WINDOWS_DEFAULT_DPI; } #endif SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); //SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); //SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4); #ifdef EMSCRIPTEN SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); #else SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY); #endif int window_flags = SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL | SDL_WINDOW_ALLOW_HIGHDPI; if (video->fullscreen) window_flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; sdl_window = SDL_CreateWindow(WINDOW_TITLE, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, video->pixel_scale * video->width, video->pixel_scale * video->height, window_flags); if (!sdl_window) { LOGE("Failed to create an OpenGL window: %s", SDL_GetError()); exit(1); } sdl_gl_context = SDL_GL_CreateContext(sdl_window); if (!sdl_gl_context) { LOGE("Failed to create an OpenGL context: %s", SDL_GetError()); exit(1); } int drawable_width, drawable_height; SDL_GL_GetDrawableSize(sdl_window, &drawable_width, &drawable_height); if (drawable_width != video->width) { LOGI("Created high DPI window. (%dx%d)", drawable_width, drawable_height); video->pixel_scale = (float)drawable_width / (float)video->width; } else { video->pixel_scale = 1.0f; } if (SDL_GL_SetSwapInterval(1) == -1) { // sync with monitor refresh rate LOGW("Could not enable VSync."); } #ifndef __APPLE__ glewInit(); #endif }