godot icon indicating copy to clipboard operation
godot copied to clipboard

[WIP] Implement native DPI scaling.

Open bruvzg opened this issue 1 year ago • 8 comments

  • Removes global oversampling in favor of per-viewport oversampling to allow different windows to use different oversampling factor.
  • Implement scalable SVG texture (affected by oversampling factor). Use it for theme element and editor icons.
  • Add support for DPI scaling on macOS and Windows (instead of down scaling for the max DPI screen, content is always rendered at native resolution on all screens).

TODO:

  • [x] LRU for auto-scaled textures.
  • [ ] Fix all window/screen coordinate usage.
  • [ ] Match scale for embedded windows.
  • [x] Update docs.

bruvzg avatar Dec 11 '23 07:12 bruvzg

Tested locally on https://github.com/godotengine/godot-demo-projects/tree/master/3d/antialiasing, there are some issues when using the canvas_items stretch mode on the root window:

  • Outline size and spacing doesn't seem to be adjusted for oversampling, which means characters get larger but the spacing isn't adjusted to account for it.
  • Popup dialogs are still blurry at high resolutions after resizing the window to a higher size than the default.

Screenshot_20231211_131930

Calinou avatar Dec 11 '23 12:12 Calinou

Outline size and spacing doesn't seem to be adjusted for oversampling, which means characters get larger but the spacing isn't adjusted to account for it.

Should be working now.

https://github.com/godotengine/godot/issues/54030 after resizing the window to a higher size than the default.

I'm looking to fix it, but it's not directly related to the oversampling changes (but it should prevent unnecessary cache cleanup and regeneration in cases like this). It's never applied to the child windows, since use_font_oversampling, content_scale_mode and other related properties are only set for the root window (probably should add some sort of "inherited" option for these).

bruvzg avatar Dec 12 '23 08:12 bruvzg

By the way, does this help resolve https://github.com/godotengine/godot/issues/76450?

Calinou avatar Dec 22 '23 15:12 Calinou

FYI: This going to take a bit longer than I have expected. Viewport and various popup related methods are absolute mess, different places are using different (and non-equivalent) transforms and methods to the same thing. And most of it breaks as soon as screen and viewport coordinates have different scale (which is necessary to have consistent multi-monitor handling, due to the way the native API is working).

bruvzg avatar Jan 10 '24 21:01 bruvzg

This would address https://github.com/godotengine/godot/issues/41839, right?

MewPurPur avatar Jan 21 '24 16:01 MewPurPur

This would address https://github.com/godotengine/godot/issues/41839, right?

Yes, this PR should fix it.

bruvzg avatar Jan 21 '24 16:01 bruvzg

The auto-scaling SVGTextures are very interesting to me, I've made something similar for displaying scaled SVG content using existing SVG image generation functionalities. But it's not very efficient and quite complicated tracking scale changes and it requires generating a new image and texture on each scale change, so I'd really love to have something more efficient and better integrated in the engine.

However, my version does have one key functionality this new SVGTexture seems to miss: async updating. If I've understood your code correctly SVGTexture::_ensure_scale() is called on draw and this is where a new SVG image is rendered and a texture is generated for this scale if there isn't one. However, ImageLoaderSVG::create_image_from_string can be quite slow for more complex images. So what I'd really love to see for my use case would be an option to do this rendering in the background. Basically ensure that there is at least a first rendered size of the texture on load. In _ensure_scale, instead pick the closest suitable scaled version from existing ones, and when appropriate instead start generating a new image/texture on a background thread and add that to the list of scaled textures once it's rendered (which will cause it to start being used then in rendering). In other words keep using a different sized texture while the desired scaled texture is being rendered in the background instead of blocking.

lostminds avatar Feb 15 '24 08:02 lostminds

When rendering the SVGTexture ImageLoaderSVG::create_image_from_string and the underlying functions first loads/parses the SVG content into a ThorVG Picture representation of some sort. This representation is then rendered into a pixel buffer of the desired size for the image texture. Since the SVGTexture will be redrawing the same SVG content it seems like it should be possible to reuse the parsed representation instead of reloading it from the SVG string each resize.

Maybe the SVGTexture could be complemented with an SVGImage class used for this purpose? Basically a subclass of Image that retains the parsed svg representation to allow re-rendering the same svg content at a different resolution without needing to parse it from string. For simple SVGs it might not make much difference, but complex svgs can contain a lot of stuff like base64-encoded bitmap images, embedded fonts etc where the parsing/loading is a bottleneck it would be nice to avoid on each re-render.

lostminds avatar Feb 15 '24 08:02 lostminds