Browse Source

[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
pull/17446/head
Nikita Tsukanov 1 year ago
committed by GitHub
parent
commit
eada7ba983
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 23
      src/Avalonia.Base/Platform/IRenderTarget.cs
  2. 5
      src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionTarget.cs
  3. 8
      src/Avalonia.OpenGL/Surfaces/IGlPlatformSurfaceRenderTarget.cs
  4. 2
      src/Avalonia.X11/Glx/GlxDisplay.cs
  5. 33
      src/Avalonia.X11/Glx/GlxGlPlatformSurface.cs
  6. 11
      src/Avalonia.X11/X11Window.cs
  7. 13
      src/Skia/Avalonia.Skia/FramebufferRenderTarget.cs
  8. 8
      src/Skia/Avalonia.Skia/Gpu/ISkiaGpuRenderTarget.cs
  9. 13
      src/Skia/Avalonia.Skia/Gpu/OpenGl/GlRenderTarget.cs
  10. 21
      src/Skia/Avalonia.Skia/Gpu/SkiaGpuRenderTarget.cs

23
src/Avalonia.Base/Platform/IRenderTarget.cs

@ -25,30 +25,39 @@ namespace Avalonia.Platform
public bool IsCorrupted { get; }
}
[PrivateApi]
[PrivateApi, Obsolete("Use IRenderTarget2", true)]
// TODO12: Remove
public interface IRenderTargetWithProperties : IRenderTarget
{
RenderTargetProperties Properties { get; }
}
[PrivateApi]
// TODO12: Merge into IRenderTarget
public interface IRenderTarget2 : IRenderTarget
{
RenderTargetProperties Properties { get; }
/// <summary>
/// Creates an <see cref="IDrawingContextImpl"/> for a rendering session.
/// </summary>
/// <param name="useScaledDrawing">Apply DPI reported by the render target as a hidden transform matrix</param>
/// <param name="expectedPixelSize">The pixel size of the surface</param>
/// <param name="properties">Returns various properties about the returned drawing context</param>
IDrawingContextImpl CreateDrawingContext(bool useScaledDrawing, out RenderTargetDrawingContextProperties properties);
IDrawingContextImpl CreateDrawingContext(PixelSize expectedPixelSize,
out RenderTargetDrawingContextProperties properties);
}
internal static class RenderTargetExtensions
{
public static IDrawingContextImpl CreateDrawingContextWithProperties(
this IRenderTarget renderTarget,
bool useScaledDrawing,
PixelSize expectedPixelSize,
out RenderTargetDrawingContextProperties properties)
{
if (renderTarget is IRenderTargetWithProperties target)
return target.CreateDrawingContext(useScaledDrawing, out properties);
if (renderTarget is IRenderTarget2 target)
return target.CreateDrawingContext(expectedPixelSize, out properties);
properties = default;
return renderTarget.CreateDrawingContext(useScaledDrawing);
return renderTarget.CreateDrawingContext(false);
}
}
}

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

@ -141,7 +141,7 @@ namespace Avalonia.Rendering.Composition.Server
if (!_redrawRequested)
return;
var renderTargetWithProperties = _renderTarget as IRenderTargetWithProperties;
var renderTargetWithProperties = _renderTarget as IRenderTarget2;
var needLayer = _overlays.RequireLayer // Check if we don't need overlays
@ -149,7 +149,8 @@ namespace Avalonia.Rendering.Composition.Server
|| !(renderTargetWithProperties?.Properties.RetainsPreviousFrameContents == true
&& renderTargetWithProperties?.Properties.IsSuitableForDirectRendering == true);
using (var renderTargetContext = _renderTarget.CreateDrawingContextWithProperties(false, out var properties))
using (var renderTargetContext = _renderTarget.CreateDrawingContextWithProperties(
this.PixelSize, out var properties))
{
if(needLayer && (PixelSize != _layerSize || _layer == null || _layer.IsCorrupted))
{

8
src/Avalonia.OpenGL/Surfaces/IGlPlatformSurfaceRenderTarget.cs

@ -1,4 +1,5 @@
using System;
using Avalonia.Metadata;
namespace Avalonia.OpenGL.Surfaces
{
@ -11,4 +12,11 @@ namespace Avalonia.OpenGL.Surfaces
{
bool IsCorrupted { get; }
}
[PrivateApi]
public interface IGlPlatformSurfaceRenderTarget2 : IGlPlatformSurfaceRenderTargetWithCorruptionInfo
{
IGlPlatformSurfaceRenderingSession BeginDraw(PixelSize expectedPixelSize);
}
}

2
src/Avalonia.X11/Glx/GlxDisplay.cs

@ -18,6 +18,8 @@ namespace Avalonia.X11.Glx
public XVisualInfo* VisualInfo => _visual;
public GlxContext DeferredContext { get; }
public GlxInterface Glx { get; } = new GlxInterface();
public X11Info X11Info => _x11;
public IntPtr FbConfig => _fbconfig;
public GlxDisplay(X11Info x11, IList<GlVersion> probeProfiles)
{
_x11 = x11;

33
src/Avalonia.X11/Glx/GlxGlPlatformSurface.cs

@ -21,10 +21,11 @@ namespace Avalonia.X11.Glx
return new RenderTarget((GlxContext)context, _info);
}
private class RenderTarget : IGlPlatformSurfaceRenderTarget
private class RenderTarget : IGlPlatformSurfaceRenderTarget2
{
private readonly GlxContext _context;
private readonly EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo _info;
private PixelSize? _lastSize;
public RenderTarget(GlxContext context, EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo info)
{
@ -36,29 +37,51 @@ namespace Avalonia.X11.Glx
{
// No-op
}
public IGlPlatformSurfaceRenderingSession BeginDraw()
public bool IsCorrupted => false;
public IGlPlatformSurfaceRenderingSession BeginDraw(PixelSize size) => BeginDrawCore(size);
public IGlPlatformSurfaceRenderingSession BeginDraw() => BeginDrawCore(null);
public IGlPlatformSurfaceRenderingSession BeginDrawCore(PixelSize? expectedSize)
{
var size = expectedSize ?? _info.Size;
if (expectedSize.HasValue)
{
XLib.XConfigureResizeWindow(_context.Display.X11Info.DeferredDisplay,
_info.Handle, size.Width, size.Height);
XLib.XFlush(_context.Display.X11Info.DeferredDisplay);
if (_lastSize != size)
{
XLib.XSync(_context.Display.X11Info.DeferredDisplay, true);
_lastSize = size;
}
_context.Glx.WaitX();
}
var oldContext = _context.MakeCurrent(_info.Handle);
// Reset to default FBO first
_context.GlInterface.BindFramebuffer(GL_FRAMEBUFFER, 0);
return new Session(_context, _info, oldContext);
return new Session(_context, _info, size, oldContext);
}
private class Session : IGlPlatformSurfaceRenderingSession
{
private readonly GlxContext _context;
private readonly EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo _info;
private readonly PixelSize? _size;
private readonly IDisposable _clearContext;
public IGlContext Context => _context;
public Session(GlxContext context, EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo info,
PixelSize? size,
IDisposable clearContext)
{
_context = context;
_info = info;
_size = size;
_clearContext = clearContext;
}
@ -71,7 +94,7 @@ namespace Avalonia.X11.Glx
_clearContext.Dispose();
}
public PixelSize Size => _info.Size;
public PixelSize Size => _size ?? _info.Size;
public double Scaling => _info.Scaling;
public bool IsYFlipped { get; }
}

11
src/Avalonia.X11/X11Window.cs

@ -67,6 +67,7 @@ namespace Avalonia.X11
private TransparencyHelper? _transparencyHelper;
private RawEventGrouper? _rawEventGrouper;
private bool _useRenderWindow = false;
private bool _useCompositorDrivenRenderWindowResize = false;
private bool _usePositioningFlags = false;
private X11FocusProxy? _focusProxy;
@ -111,7 +112,12 @@ namespace Avalonia.X11
var glx = glfeature as GlxPlatformGraphics;
if (glx != null)
{
visualInfo = *glx.Display.VisualInfo;
// TODO: We should query this from the active render surface, however we don't actually track what
// the target sufrace currently is
_useCompositorDrivenRenderWindowResize = true;
}
else if (glfeature == null)
visualInfo = _x11.TransparentVisualInfo;
@ -569,7 +575,8 @@ namespace Avalonia.X11
Resized?.Invoke(ClientSize, WindowResizeReason.Unspecified);
}, DispatcherPriority.AsyncRenderTargetResize);
if (_useRenderWindow)
if (_useRenderWindow && !_useCompositorDrivenRenderWindowResize)
XConfigureResizeWindow(_x11.Display, _renderHandle, ev.ConfigureEvent.width,
ev.ConfigureEvent.height);
if (_xSyncState == XSyncState.WaitConfigure)
@ -1081,7 +1088,7 @@ namespace Avalonia.X11
var pixelSize = ToPixelSize(clientSize);
UpdateSizeHints(pixelSize);
XConfigureResizeWindow(_x11.Display, _handle, pixelSize);
if (_useRenderWindow)
if (_useRenderWindow && !_useCompositorDrivenRenderWindowResize)
XConfigureResizeWindow(_x11.Display, _renderHandle, pixelSize);
XFlush(_x11.Display);

13
src/Skia/Avalonia.Skia/FramebufferRenderTarget.cs

@ -10,7 +10,7 @@ namespace Avalonia.Skia
/// <summary>
/// Skia render target that renders to a framebuffer surface. No gpu acceleration available.
/// </summary>
internal class FramebufferRenderTarget : IRenderTargetWithProperties
internal class FramebufferRenderTarget : IRenderTarget2
{
private SKImageInfo _currentImageInfo;
private IntPtr _currentFramebufferAddress;
@ -50,10 +50,15 @@ namespace Avalonia.Skia
/// <inheritdoc />
public IDrawingContextImpl CreateDrawingContext(bool scaleDrawingToDpi) =>
CreateDrawingContext(scaleDrawingToDpi, out _);
CreateDrawingContextCore(scaleDrawingToDpi, out _);
/// <inheritdoc />
public IDrawingContextImpl CreateDrawingContext(bool useScaledDrawing, out RenderTargetDrawingContextProperties properties)
public IDrawingContextImpl CreateDrawingContext(PixelSize expectedPixelSize,
out RenderTargetDrawingContextProperties properties)
=> CreateDrawingContextCore(false, out properties);
IDrawingContextImpl CreateDrawingContextCore(bool scaleDrawingToDpi,
out RenderTargetDrawingContextProperties properties)
{
if (_renderTarget == null)
throw new ObjectDisposedException(nameof(FramebufferRenderTarget));
@ -77,7 +82,7 @@ namespace Avalonia.Skia
{
Surface = _framebufferSurface,
Dpi = framebuffer.Dpi,
ScaleDrawingToDpi = useScaledDrawing
ScaleDrawingToDpi = scaleDrawingToDpi
};
properties = new()

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

@ -1,4 +1,5 @@
using System;
using Avalonia.Metadata;
using SkiaSharp;
namespace Avalonia.Skia
@ -16,4 +17,11 @@ namespace Avalonia.Skia
bool IsCorrupted { get; }
}
[PrivateApi]
//TODO12: Merge with ISkiaGpuRenderTarget
public interface ISkiaGpuRenderTarget2 : ISkiaGpuRenderTarget
{
ISkiaGpuRenderSession BeginRenderingSession(PixelSize pixelSize);
}
}

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

@ -9,7 +9,7 @@ using static Avalonia.OpenGL.GlConsts;
namespace Avalonia.Skia
{
internal class GlRenderTarget : ISkiaGpuRenderTarget
internal class GlRenderTarget : ISkiaGpuRenderTarget2
{
private readonly GRContext _grContext;
private IGlPlatformSurfaceRenderTarget _surface;
@ -59,9 +59,16 @@ namespace Avalonia.Skia
public double ScaleFactor => _glSession.Scaling;
}
public ISkiaGpuRenderSession BeginRenderingSession()
public ISkiaGpuRenderSession BeginRenderingSession(PixelSize size) => BeginRenderingSessionCore(size);
public ISkiaGpuRenderSession BeginRenderingSession() => BeginRenderingSessionCore(null);
ISkiaGpuRenderSession BeginRenderingSessionCore(PixelSize? expectedSize)
{
var glSession = _surface.BeginDraw();
var glSession =
expectedSize != null && _surface is IGlPlatformSurfaceRenderTarget2 surface2
? surface2.BeginDraw(expectedSize.Value)
: _surface.BeginDraw();
bool success = false;
try
{

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

@ -5,7 +5,7 @@ namespace Avalonia.Skia
/// <summary>
/// Adapts <see cref="ISkiaGpuRenderTarget"/> to be used within our rendering pipeline.
/// </summary>
internal class SkiaGpuRenderTarget : IRenderTarget
internal class SkiaGpuRenderTarget : IRenderTarget2
{
private readonly ISkiaGpu _skiaGpu;
private readonly ISkiaGpuRenderTarget _renderTarget;
@ -21,9 +21,23 @@ namespace Avalonia.Skia
_renderTarget.Dispose();
}
public IDrawingContextImpl CreateDrawingContext(PixelSize expectedPixelSize,
out RenderTargetDrawingContextProperties properties) =>
CreateDrawingContextCore(expectedPixelSize, false, out properties);
public IDrawingContextImpl CreateDrawingContext(bool useScaledDrawing)
=> CreateDrawingContextCore(null, useScaledDrawing, out _);
IDrawingContextImpl CreateDrawingContextCore(PixelSize? expectedPixelSize,
bool useScaledDrawing,
out RenderTargetDrawingContextProperties properties)
{
var session = _renderTarget.BeginRenderingSession();
properties = default;
var session =
expectedPixelSize.HasValue && _renderTarget is ISkiaGpuRenderTarget2 target2
? target2.BeginRenderingSession(expectedPixelSize.Value)
: _renderTarget.BeginRenderingSession();
var nfo = new DrawingContextImpl.CreateInfo
{
@ -39,5 +53,8 @@ namespace Avalonia.Skia
}
public bool IsCorrupted => _renderTarget.IsCorrupted;
public RenderTargetProperties Properties { get; }
}
}

Loading…
Cancel
Save