Forum

Strange aspect of Skia renderer bounds / How to set renderer to exact size and pos in pixel?

Currently trying to set the skia-renderer position and scale inside the patch.

First thing, I do not get: What is the unit of the width/height-settings rectangle? Can’t be pixel, since my screen is 4k and the renderer is bigger than 100px. One guess could be, that it’s somehoe scaled by windows-scaling settings? Or is it something else?

Second problem: Setting the rectangle to an square (fe. 100 by 100) results in an rectangle but not a perfect square. 100 by 170 gives me in my case a square. Which let me guess, it’s also relative to my resolution aspect (16:9). But why? Shouldn’t it be absolute in pixel no mater which aspect my resolution has.

Did anyone tried the same already and found a solution to set the window to an exact position and scale in pixel?

Doodled a little. Seems to work, but needs some magic numbers I can’t explain.

HowTo set render window size in pixels.vl (44.2 KB)

1 Like

Ha, great! I see many interesting nodes in your patch. :)

I did another version without any borders and without titlebar. in this case everything works as expected without further adding of magic numbers.

Only problem left: because my scaling factor is 1.5 I end up with after-comma-rounding-issue. but tried it with 100% and this was fine. Needed to restart gamma to get the correct new scaling value after changing this in the windows-display-settings.

HowTo set render window size in pixels.vl (49.3 KB)

Tested only with 2560x1440 and 125%.

Not sure if this will return the correct result when the screens don’t have the same resolution and scaling settings:
image

Unfortunately VL.Skia isn’t open source. But I took a peek at VL.Skia.dll to see what SetSize [Graphics.Skia.SkiaRenderer] is doing.

public void SetSize(Rectangle boundsInDIP)
    {
      Rectangle boundsinPix = DIPHelpers.DIPToPixel(boundsInDIP);
      if (!((IEnumerable<Screen>) Screen.AllScreens).Any<Screen>((Func<Screen, bool>) (s => s.Bounds.IntersectsWith(boundsinPix))))
      {
        boundsInDIP = SkiaRenderer.GetCenteredBoundsInDIP(boundsInDIP.Width, boundsInDIP.Height);
        boundsinPix = DIPHelpers.DIPToPixel(boundsInDIP);
      }
      if (!(boundsinPix != this.Bounds))
        return;
      this.Bounds = boundsinPix;
    }

Turns out there is already a class called DIPHelpers (inside VL.UI.Core.dll). So If you reference it you can just use the helpers.
image

It basically does the same as I did here:
image

public static float DIPFactor()
    {
      if ((double) DIPHelpers.FDIPFactor == -1.0)
      {
        using (Graphics graphics = Graphics.FromHwnd(IntPtr.Zero))
          DIPHelpers.FDIPFactor = graphics.DpiX / 96f;
      }
      return DIPHelpers.FDIPFactor;
    }

From what I can tell it might also fail when having multiple screens with different scaling settings (and/or resolutions).

Also since some pixel values cannot be set when using fractional scaling and DIP, it would be nice to have something like SetSize(Rectangle boundsInPixel).
@devvvvs

HowTo set render window size in pixels 2.vl (40.6 KB)

5 Likes

Sorry for the silence. VL.Skia recently got some love and now upcoming builds will have a node SetBounds that allows setting the size in pixels.

This operation can be connected to the Renderer node like so:
grafik

The rectangle type is the standard Stride rectangle.
The white Input pin “Bounds” for now still is the System.Drawing.Rectangle.

I also added an experimental node “RenderWindow”, that has a Stride Rectangle Bounds input pin. But probably you don’t need this as you want to set the size manually. Right?

4 Likes