Skip to content

Commit b977368

Browse files
kekekeksmaxkatz6
authored andcommitted
[GLX] Resize the platform render target to compositor-provided size (#17779)
We should be doing that for other platforms later as well, since only compositor knows what scene size it's planning to draw
1 parent 261a08a commit b977368

File tree

10 files changed

+112
-25
lines changed

10 files changed

+112
-25
lines changed

src/Avalonia.Base/Platform/IRenderTarget.cs

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,30 +25,39 @@ public interface IRenderTarget : IDisposable
2525
public bool IsCorrupted { get; }
2626
}
2727

28-
[PrivateApi]
28+
[PrivateApi, Obsolete("Use IRenderTarget2", true)]
29+
// TODO12: Remove
2930
public interface IRenderTargetWithProperties : IRenderTarget
31+
{
32+
RenderTargetProperties Properties { get; }
33+
}
34+
35+
[PrivateApi]
36+
// TODO12: Merge into IRenderTarget
37+
public interface IRenderTarget2 : IRenderTarget
3038
{
3139
RenderTargetProperties Properties { get; }
3240

3341
/// <summary>
3442
/// Creates an <see cref="IDrawingContextImpl"/> for a rendering session.
3543
/// </summary>
36-
/// <param name="useScaledDrawing">Apply DPI reported by the render target as a hidden transform matrix</param>
44+
/// <param name="expectedPixelSize">The pixel size of the surface</param>
3745
/// <param name="properties">Returns various properties about the returned drawing context</param>
38-
IDrawingContextImpl CreateDrawingContext(bool useScaledDrawing, out RenderTargetDrawingContextProperties properties);
46+
IDrawingContextImpl CreateDrawingContext(PixelSize expectedPixelSize,
47+
out RenderTargetDrawingContextProperties properties);
3948
}
4049

4150
internal static class RenderTargetExtensions
4251
{
4352
public static IDrawingContextImpl CreateDrawingContextWithProperties(
4453
this IRenderTarget renderTarget,
45-
bool useScaledDrawing,
54+
PixelSize expectedPixelSize,
4655
out RenderTargetDrawingContextProperties properties)
4756
{
48-
if (renderTarget is IRenderTargetWithProperties target)
49-
return target.CreateDrawingContext(useScaledDrawing, out properties);
57+
if (renderTarget is IRenderTarget2 target)
58+
return target.CreateDrawingContext(expectedPixelSize, out properties);
5059
properties = default;
51-
return renderTarget.CreateDrawingContext(useScaledDrawing);
60+
return renderTarget.CreateDrawingContext(false);
5261
}
5362
}
5463
}

src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionTarget.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,15 +141,16 @@ public void Render()
141141
if (!_redrawRequested)
142142
return;
143143

144-
var renderTargetWithProperties = _renderTarget as IRenderTargetWithProperties;
144+
var renderTargetWithProperties = _renderTarget as IRenderTarget2;
145145

146146

147147
var needLayer = _overlays.RequireLayer // Check if we don't need overlays
148148
// Check if render target can be rendered to directly and preserves the previous frame
149149
|| !(renderTargetWithProperties?.Properties.RetainsPreviousFrameContents == true
150150
&& renderTargetWithProperties?.Properties.IsSuitableForDirectRendering == true);
151151

152-
using (var renderTargetContext = _renderTarget.CreateDrawingContextWithProperties(false, out var properties))
152+
using (var renderTargetContext = _renderTarget.CreateDrawingContextWithProperties(
153+
this.PixelSize, out var properties))
153154
{
154155
if(needLayer && (PixelSize != _layerSize || _layer == null || _layer.IsCorrupted))
155156
{

src/Avalonia.OpenGL/Surfaces/IGlPlatformSurfaceRenderTarget.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using Avalonia.Metadata;
23

34
namespace Avalonia.OpenGL.Surfaces
45
{
@@ -11,4 +12,11 @@ public interface IGlPlatformSurfaceRenderTargetWithCorruptionInfo : IGlPlatformS
1112
{
1213
bool IsCorrupted { get; }
1314
}
15+
16+
[PrivateApi]
17+
public interface IGlPlatformSurfaceRenderTarget2 : IGlPlatformSurfaceRenderTargetWithCorruptionInfo
18+
{
19+
IGlPlatformSurfaceRenderingSession BeginDraw(PixelSize expectedPixelSize);
20+
}
21+
1422
}

src/Avalonia.X11/Glx/GlxDisplay.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ internal unsafe class GlxDisplay
1818
public XVisualInfo* VisualInfo => _visual;
1919
public GlxContext DeferredContext { get; }
2020
public GlxInterface Glx { get; } = new GlxInterface();
21+
public X11Info X11Info => _x11;
22+
public IntPtr FbConfig => _fbconfig;
2123
public GlxDisplay(X11Info x11, IList<GlVersion> probeProfiles)
2224
{
2325
_x11 = x11;

src/Avalonia.X11/Glx/GlxGlPlatformSurface.cs

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,11 @@ public IGlPlatformSurfaceRenderTarget CreateGlRenderTarget(IGlContext context)
2121
return new RenderTarget((GlxContext)context, _info);
2222
}
2323

24-
private class RenderTarget : IGlPlatformSurfaceRenderTarget
24+
private class RenderTarget : IGlPlatformSurfaceRenderTarget2
2525
{
2626
private readonly GlxContext _context;
2727
private readonly EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo _info;
28+
private PixelSize? _lastSize;
2829

2930
public RenderTarget(GlxContext context, EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo info)
3031
{
@@ -36,29 +37,51 @@ public void Dispose()
3637
{
3738
// No-op
3839
}
39-
40-
public IGlPlatformSurfaceRenderingSession BeginDraw()
40+
41+
public bool IsCorrupted => false;
42+
public IGlPlatformSurfaceRenderingSession BeginDraw(PixelSize size) => BeginDrawCore(size);
43+
public IGlPlatformSurfaceRenderingSession BeginDraw() => BeginDrawCore(null);
44+
public IGlPlatformSurfaceRenderingSession BeginDrawCore(PixelSize? expectedSize)
4145
{
46+
var size = expectedSize ?? _info.Size;
47+
if (expectedSize.HasValue)
48+
{
49+
XLib.XConfigureResizeWindow(_context.Display.X11Info.DeferredDisplay,
50+
_info.Handle, size.Width, size.Height);
51+
XLib.XFlush(_context.Display.X11Info.DeferredDisplay);
52+
53+
if (_lastSize != size)
54+
{
55+
XLib.XSync(_context.Display.X11Info.DeferredDisplay, true);
56+
_lastSize = size;
57+
}
58+
_context.Glx.WaitX();
59+
}
60+
61+
4262
var oldContext = _context.MakeCurrent(_info.Handle);
4363

4464
// Reset to default FBO first
4565
_context.GlInterface.BindFramebuffer(GL_FRAMEBUFFER, 0);
4666

47-
return new Session(_context, _info, oldContext);
67+
return new Session(_context, _info, size, oldContext);
4868
}
4969

5070
private class Session : IGlPlatformSurfaceRenderingSession
5171
{
5272
private readonly GlxContext _context;
5373
private readonly EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo _info;
74+
private readonly PixelSize? _size;
5475
private readonly IDisposable _clearContext;
5576
public IGlContext Context => _context;
5677

5778
public Session(GlxContext context, EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo info,
79+
PixelSize? size,
5880
IDisposable clearContext)
5981
{
6082
_context = context;
6183
_info = info;
84+
_size = size;
6285
_clearContext = clearContext;
6386
}
6487

@@ -71,7 +94,7 @@ public void Dispose()
7194
_clearContext.Dispose();
7295
}
7396

74-
public PixelSize Size => _info.Size;
97+
public PixelSize Size => _size ?? _info.Size;
7598
public double Scaling => _info.Scaling;
7699
public bool IsYFlipped { get; }
77100
}

src/Avalonia.X11/X11Window.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ internal unsafe partial class X11Window : IWindowImpl, IPopupImpl, IXI2Client,
6767
private TransparencyHelper? _transparencyHelper;
6868
private RawEventGrouper? _rawEventGrouper;
6969
private bool _useRenderWindow = false;
70+
private bool _useCompositorDrivenRenderWindowResize = false;
7071
private bool _usePositioningFlags = false;
7172
private X11FocusProxy? _focusProxy;
7273

@@ -111,7 +112,12 @@ public X11Window(AvaloniaX11Platform platform, IWindowImpl? popupParent, bool ov
111112

112113
var glx = glfeature as GlxPlatformGraphics;
113114
if (glx != null)
115+
{
114116
visualInfo = *glx.Display.VisualInfo;
117+
// TODO: We should query this from the active render surface, however we don't actually track what
118+
// the target sufrace currently is
119+
_useCompositorDrivenRenderWindowResize = true;
120+
}
115121
else if (glfeature == null)
116122
visualInfo = _x11.TransparentVisualInfo;
117123

@@ -569,7 +575,8 @@ private void OnEvent(ref XEvent ev)
569575
Resized?.Invoke(ClientSize, WindowResizeReason.Unspecified);
570576

571577
}, DispatcherPriority.AsyncRenderTargetResize);
572-
if (_useRenderWindow)
578+
579+
if (_useRenderWindow && !_useCompositorDrivenRenderWindowResize)
573580
XConfigureResizeWindow(_x11.Display, _renderHandle, ev.ConfigureEvent.width,
574581
ev.ConfigureEvent.height);
575582
if (_xSyncState == XSyncState.WaitConfigure)
@@ -1081,7 +1088,7 @@ private void Resize(Size clientSize, bool force, WindowResizeReason reason)
10811088
var pixelSize = ToPixelSize(clientSize);
10821089
UpdateSizeHints(pixelSize);
10831090
XConfigureResizeWindow(_x11.Display, _handle, pixelSize);
1084-
if (_useRenderWindow)
1091+
if (_useRenderWindow && !_useCompositorDrivenRenderWindowResize)
10851092
XConfigureResizeWindow(_x11.Display, _renderHandle, pixelSize);
10861093
XFlush(_x11.Display);
10871094

src/Skia/Avalonia.Skia/FramebufferRenderTarget.cs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ namespace Avalonia.Skia
1010
/// <summary>
1111
/// Skia render target that renders to a framebuffer surface. No gpu acceleration available.
1212
/// </summary>
13-
internal class FramebufferRenderTarget : IRenderTargetWithProperties
13+
internal class FramebufferRenderTarget : IRenderTarget2
1414
{
1515
private SKImageInfo _currentImageInfo;
1616
private IntPtr _currentFramebufferAddress;
@@ -50,10 +50,15 @@ public void Dispose()
5050

5151
/// <inheritdoc />
5252
public IDrawingContextImpl CreateDrawingContext(bool scaleDrawingToDpi) =>
53-
CreateDrawingContext(scaleDrawingToDpi, out _);
53+
CreateDrawingContextCore(scaleDrawingToDpi, out _);
5454

5555
/// <inheritdoc />
56-
public IDrawingContextImpl CreateDrawingContext(bool useScaledDrawing, out RenderTargetDrawingContextProperties properties)
56+
public IDrawingContextImpl CreateDrawingContext(PixelSize expectedPixelSize,
57+
out RenderTargetDrawingContextProperties properties)
58+
=> CreateDrawingContextCore(false, out properties);
59+
60+
IDrawingContextImpl CreateDrawingContextCore(bool scaleDrawingToDpi,
61+
out RenderTargetDrawingContextProperties properties)
5762
{
5863
if (_renderTarget == null)
5964
throw new ObjectDisposedException(nameof(FramebufferRenderTarget));
@@ -77,7 +82,7 @@ public IDrawingContextImpl CreateDrawingContext(bool useScaledDrawing, out Rende
7782
{
7883
Surface = _framebufferSurface,
7984
Dpi = framebuffer.Dpi,
80-
ScaleDrawingToDpi = useScaledDrawing
85+
ScaleDrawingToDpi = scaleDrawingToDpi
8186
};
8287

8388
properties = new()

src/Skia/Avalonia.Skia/Gpu/ISkiaGpuRenderTarget.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using Avalonia.Metadata;
23
using SkiaSharp;
34

45
namespace Avalonia.Skia
@@ -16,4 +17,11 @@ public interface ISkiaGpuRenderTarget : IDisposable
1617

1718
bool IsCorrupted { get; }
1819
}
20+
21+
[PrivateApi]
22+
//TODO12: Merge with ISkiaGpuRenderTarget
23+
public interface ISkiaGpuRenderTarget2 : ISkiaGpuRenderTarget
24+
{
25+
ISkiaGpuRenderSession BeginRenderingSession(PixelSize pixelSize);
26+
}
1927
}

src/Skia/Avalonia.Skia/Gpu/OpenGl/GlRenderTarget.cs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
namespace Avalonia.Skia
1111
{
12-
internal class GlRenderTarget : ISkiaGpuRenderTarget
12+
internal class GlRenderTarget : ISkiaGpuRenderTarget2
1313
{
1414
private readonly GRContext _grContext;
1515
private IGlPlatformSurfaceRenderTarget _surface;
@@ -59,9 +59,16 @@ public void Dispose()
5959
public double ScaleFactor => _glSession.Scaling;
6060
}
6161

62-
public ISkiaGpuRenderSession BeginRenderingSession()
62+
public ISkiaGpuRenderSession BeginRenderingSession(PixelSize size) => BeginRenderingSessionCore(size);
63+
public ISkiaGpuRenderSession BeginRenderingSession() => BeginRenderingSessionCore(null);
64+
65+
ISkiaGpuRenderSession BeginRenderingSessionCore(PixelSize? expectedSize)
6366
{
64-
var glSession = _surface.BeginDraw();
67+
var glSession =
68+
expectedSize != null && _surface is IGlPlatformSurfaceRenderTarget2 surface2
69+
? surface2.BeginDraw(expectedSize.Value)
70+
: _surface.BeginDraw();
71+
6572
bool success = false;
6673
try
6774
{

src/Skia/Avalonia.Skia/Gpu/SkiaGpuRenderTarget.cs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ namespace Avalonia.Skia
55
/// <summary>
66
/// Adapts <see cref="ISkiaGpuRenderTarget"/> to be used within our rendering pipeline.
77
/// </summary>
8-
internal class SkiaGpuRenderTarget : IRenderTarget
8+
internal class SkiaGpuRenderTarget : IRenderTarget2
99
{
1010
private readonly ISkiaGpu _skiaGpu;
1111
private readonly ISkiaGpuRenderTarget _renderTarget;
@@ -21,9 +21,23 @@ public void Dispose()
2121
_renderTarget.Dispose();
2222
}
2323

24+
public IDrawingContextImpl CreateDrawingContext(PixelSize expectedPixelSize,
25+
out RenderTargetDrawingContextProperties properties) =>
26+
CreateDrawingContextCore(expectedPixelSize, false, out properties);
27+
2428
public IDrawingContextImpl CreateDrawingContext(bool useScaledDrawing)
29+
=> CreateDrawingContextCore(null, useScaledDrawing, out _);
30+
31+
32+
IDrawingContextImpl CreateDrawingContextCore(PixelSize? expectedPixelSize,
33+
bool useScaledDrawing,
34+
out RenderTargetDrawingContextProperties properties)
2535
{
26-
var session = _renderTarget.BeginRenderingSession();
36+
properties = default;
37+
var session =
38+
expectedPixelSize.HasValue && _renderTarget is ISkiaGpuRenderTarget2 target2
39+
? target2.BeginRenderingSession(expectedPixelSize.Value)
40+
: _renderTarget.BeginRenderingSession();
2741

2842
var nfo = new DrawingContextImpl.CreateInfo
2943
{
@@ -39,5 +53,8 @@ public IDrawingContextImpl CreateDrawingContext(bool useScaledDrawing)
3953
}
4054

4155
public bool IsCorrupted => _renderTarget.IsCorrupted;
56+
public RenderTargetProperties Properties { get; }
57+
58+
4259
}
4360
}

0 commit comments

Comments
 (0)