From 11945dd45018a02fbaf6f010e3d2eba872404d7b Mon Sep 17 00:00:00 2001 From: stuartmorgan Date: Thu, 22 Aug 2019 16:49:23 -0700 Subject: [PATCH] Allow overriding the GLFW pixel ratio (flutter/engine#11388) Allows a client to set a specific pixel ratio rather than using one computed based on the screen details. Fixes https://github.com/flutter/flutter/issues/37620 --- .../include/flutter/flutter_window.h | 8 ++++++ .../testing/stub_flutter_glfw_api.cc | 8 ++++++ .../testing/stub_flutter_glfw_api.h | 3 ++ .../shell/platform/glfw/flutter_glfw.cc | 28 +++++++++++++++++-- .../shell/platform/glfw/public/flutter_glfw.h | 8 ++++++ 5 files changed, 52 insertions(+), 3 deletions(-) diff --git a/engine/src/flutter/shell/platform/glfw/client_wrapper/include/flutter/flutter_window.h b/engine/src/flutter/shell/platform/glfw/client_wrapper/include/flutter/flutter_window.h index a788bc72e69..854e96a4629 100644 --- a/engine/src/flutter/shell/platform/glfw/client_wrapper/include/flutter/flutter_window.h +++ b/engine/src/flutter/shell/platform/glfw/client_wrapper/include/flutter/flutter_window.h @@ -80,6 +80,14 @@ class FlutterWindow { return FlutterDesktopWindowGetScaleFactor(window_); } + // Forces a specific pixel ratio for Flutter rendering, rather than one + // computed automatically from screen information. + // + // To clear a previously set override, pass an override value of zero. + void SetPixelRatioOverride(double pixel_ratio) { + FlutterDesktopWindowSetPixelRatioOverride(window_, pixel_ratio); + } + private: // Handle for interacting with the C API's window. // diff --git a/engine/src/flutter/shell/platform/glfw/client_wrapper/testing/stub_flutter_glfw_api.cc b/engine/src/flutter/shell/platform/glfw/client_wrapper/testing/stub_flutter_glfw_api.cc index a5e1be7c736..02219f59bdf 100644 --- a/engine/src/flutter/shell/platform/glfw/client_wrapper/testing/stub_flutter_glfw_api.cc +++ b/engine/src/flutter/shell/platform/glfw/client_wrapper/testing/stub_flutter_glfw_api.cc @@ -115,6 +115,14 @@ double FlutterDesktopWindowGetScaleFactor( return 1.0; } +void FlutterDesktopWindowSetPixelRatioOverride( + FlutterDesktopWindowRef flutter_window, + double pixel_ratio) { + if (s_stub_implementation) { + return s_stub_implementation->SetPixelRatioOverride(pixel_ratio); + } +} + bool FlutterDesktopRunWindowEventLoopWithTimeout( FlutterDesktopWindowControllerRef controller, uint32_t millisecond_timeout) { diff --git a/engine/src/flutter/shell/platform/glfw/client_wrapper/testing/stub_flutter_glfw_api.h b/engine/src/flutter/shell/platform/glfw/client_wrapper/testing/stub_flutter_glfw_api.h index eaa5409d21e..61ff639eb16 100644 --- a/engine/src/flutter/shell/platform/glfw/client_wrapper/testing/stub_flutter_glfw_api.h +++ b/engine/src/flutter/shell/platform/glfw/client_wrapper/testing/stub_flutter_glfw_api.h @@ -65,6 +65,9 @@ class StubFlutterGlfwApi { // Called for FlutterDesktopWindowGetScaleFactor. virtual double GetWindowScaleFactor() { return 1.0; } + // Called for FlutterDesktopWindowSetPixelRatioOverride. + virtual void SetPixelRatioOverride(double pixel_ratio) {} + // Called for FlutterDesktopRunWindowEventLoopWithTimeout. virtual bool RunWindowEventLoopWithTimeout(uint32_t millisecond_timeout) { return true; diff --git a/engine/src/flutter/shell/platform/glfw/flutter_glfw.cc b/engine/src/flutter/shell/platform/glfw/flutter_glfw.cc index b5f9fe666b5..a5c847f846a 100644 --- a/engine/src/flutter/shell/platform/glfw/flutter_glfw.cc +++ b/engine/src/flutter/shell/platform/glfw/flutter_glfw.cc @@ -92,6 +92,10 @@ struct FlutterDesktopWindow { // The ratio of pixels per screen coordinate for the window. double pixels_per_screen_coordinate = 1.0; + // If non-zero, a forced pixel ratio to use instead of one computed based on + // screen information. + double pixel_ratio_override = 0.0; + // Resizing triggers a window refresh, but the resize already updates Flutter. // To avoid double messages, the refresh after each resize is skipped. bool skip_next_window_refresh = false; @@ -177,9 +181,14 @@ static void SendWindowMetrics(FlutterDesktopWindowControllerState* state, event.struct_size = sizeof(event); event.width = width; event.height = height; - // The Flutter pixel_ratio is defined as DPI/dp. Limit the ratio to a minimum - // of 1 to avoid rendering a smaller UI on standard resolution monitors. - event.pixel_ratio = std::max(dpi / kDpPerInch, 1.0); + if (state->window_wrapper->pixel_ratio_override == 0.0) { + // The Flutter pixel_ratio is defined as DPI/dp. Limit the ratio to a + // minimum of 1 to avoid rendering a smaller UI on standard resolution + // monitors. + event.pixel_ratio = std::max(dpi / kDpPerInch, 1.0); + } else { + event.pixel_ratio = state->window_wrapper->pixel_ratio_override; + } FlutterEngineSendWindowMetricsEvent(state->engine, &event); } @@ -714,6 +723,19 @@ double FlutterDesktopWindowGetScaleFactor( return flutter_window->pixels_per_screen_coordinate; } +void FlutterDesktopWindowSetPixelRatioOverride( + FlutterDesktopWindowRef flutter_window, + double pixel_ratio) { + flutter_window->pixel_ratio_override = pixel_ratio; + // Send a metrics update using the new pixel ratio. + int width_px, height_px; + glfwGetFramebufferSize(flutter_window->window, &width_px, &height_px); + if (width_px > 0 && height_px > 0) { + auto* state = GetSavedWindowState(flutter_window->window); + SendWindowMetrics(state, width_px, height_px); + } +} + bool FlutterDesktopRunWindowEventLoopWithTimeout( FlutterDesktopWindowControllerRef controller, uint32_t timeout_milliseconds) { diff --git a/engine/src/flutter/shell/platform/glfw/public/flutter_glfw.h b/engine/src/flutter/shell/platform/glfw/public/flutter_glfw.h index ef6268376f2..ed6f87fb0d7 100644 --- a/engine/src/flutter/shell/platform/glfw/public/flutter_glfw.h +++ b/engine/src/flutter/shell/platform/glfw/public/flutter_glfw.h @@ -159,6 +159,14 @@ FLUTTER_EXPORT void FlutterDesktopWindowSetFrame( FLUTTER_EXPORT double FlutterDesktopWindowGetScaleFactor( FlutterDesktopWindowRef flutter_window); +// Forces a specific pixel ratio for Flutter rendering in |flutter_window|, +// rather than one computed automatically from screen information. +// +// To clear a previously set override, pass an override value of zero. +FLUTTER_EXPORT void FlutterDesktopWindowSetPixelRatioOverride( + FlutterDesktopWindowRef flutter_window, + double pixel_ratio); + // Runs an instance of a headless Flutter engine. // // Returns a null pointer in the event of an error.