Browse Source

Wayland: handle (0,0) surface size (#21863)

pull/22069/head
Julien Lebosquain 1 month ago
committed by GitHub
parent
commit
cc1dbbd062
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 8
      src/Avalonia.Wayland/Server/Persistent/WSurface.cs
  2. 9
      src/Avalonia.Wayland/Server/Transient/Rendering/WaylandEglDmaBufSurface.cs
  3. 17
      src/Avalonia.Wayland/Server/Transient/Rendering/WaylandEglWsiSurface.cs
  4. 4
      src/Avalonia.Wayland/Server/Transient/Rendering/WaylandFramebuffer.cs

8
src/Avalonia.Wayland/Server/Persistent/WSurface.cs

@ -591,6 +591,12 @@ class WXdgShellSurface : WSurface, IWXdgShellSurface
surfaceHeight = (bufferPixelSize.Height + intScale - 1) / intScale;
}
if (surfaceWidth <= 0 || surfaceHeight <= 0)
{
LastWindowGeometry = null;
return;
}
var left = Math.Clamp((int)shadowExtents.Left, 0, surfaceWidth - 1);
var top = Math.Clamp((int)shadowExtents.Top, 0, surfaceHeight - 1);
var right = Math.Clamp(
@ -1101,4 +1107,4 @@ class WXdgPopup : WXdgShellSurface, IWXdgPopup
_pendingBatch = new();
base.OnDisconnected();
}
}
}

9
src/Avalonia.Wayland/Server/Transient/Rendering/WaylandEglDmaBufSurface.cs

@ -55,7 +55,10 @@ internal class WaylandEglDmaBufSurface : EglGlPlatformImageSurfaceBase, IPlatfor
if (!_parent._surface.State.IsReady)
throw new RenderTargetNotReadyException();
EnsureSwapchain(sceneInfo.Size);
var size = sceneInfo.Size;
size = new PixelSize(Math.Max(1, size.Width), Math.Max(1, size.Height));
EnsureSwapchain(size);
// Select least recently used free slot
BufferSlot? freeSlot = null;
@ -70,7 +73,7 @@ internal class WaylandEglDmaBufSurface : EglGlPlatformImageSurfaceBase, IPlatfor
var capturedSlot = freeSlot;
capturedSlot.LastUsedFrame = ++_frameCounter;
return BeginDraw(capturedSlot.EglImage!.Handle, sceneInfo.Size, sceneInfo.Scaling, () =>
return BeginDraw(capturedSlot.EglImage!.Handle, size, sceneInfo.Scaling, () =>
{
// Stage per-frame state (frame callback + ack_configure +
// geometry + viewport/scale + min/max) into the next
@ -79,7 +82,7 @@ internal class WaylandEglDmaBufSurface : EglGlPlatformImageSurfaceBase, IPlatfor
// issues the commit itself.
_parent._surface.OnBeforeNewBufferAttached(sceneInfo);
_parent._surface.WlSurface!.Attach(capturedSlot.WlBuffer!, 0, 0);
_parent._surface.WlSurface.DamageBuffer(0, 0, sceneInfo.Size.Width, sceneInfo.Size.Height);
_parent._surface.WlSurface.DamageBuffer(0, 0, size.Width, size.Height);
capturedSlot.Busy = true;
_parent._surface.WlSurface.Commit();
});

17
src/Avalonia.Wayland/Server/Transient/Rendering/WaylandEglWsiSurface.cs

@ -1,4 +1,5 @@
using System;
using System.Diagnostics;
using Avalonia.OpenGL;
using Avalonia.OpenGL.Egl;
using Avalonia.OpenGL.Surfaces;
@ -64,7 +65,10 @@ internal sealed class WaylandEglWsiSurface : EglGlPlatformSurfaceBase, IPlatform
if (!_surface.State.IsReady)
throw new RenderTargetNotReadyException();
EnsureWindow(sceneInfo.Size);
var size = sceneInfo.Size;
size = new PixelSize(Math.Max(1, size.Width), Math.Max(1, size.Height));
EnsureWindow(size);
// OnBeforeNewBufferAttached must run *immediately* before the
// implicit commit performed by eglSwapBuffers; the base class
@ -73,7 +77,7 @@ internal sealed class WaylandEglWsiSurface : EglGlPlatformSurfaceBase, IPlatform
// SwapInterval(0) is set inside beforeSwap (so it runs with our
// surface current); GTK re-asserts it every frame defensively
// and we follow suit — some drivers reset it on resize.
var session = BeginDraw(_eglSurface!, sceneInfo.Size, sceneInfo.Scaling,
var session = BeginDraw(_eglSurface!, size, sceneInfo.Scaling,
beforeSwap: () =>
{
var display = Context.Display;
@ -86,7 +90,7 @@ internal sealed class WaylandEglWsiSurface : EglGlPlatformSurfaceBase, IPlatform
if (session.Context.Version.Type == GlProfileType.OpenGL)
{
var gl = session.Context.GlInterface;
gl.Viewport(0, 0, sceneInfo.Size.Width, sceneInfo.Size.Height);
gl.Viewport(0, 0, size.Width, size.Height);
if (gl.IsReadBufferAvailable)
gl.ReadBuffer(GL_BACK);
if (gl.IsWriteBufferAvailable)
@ -118,13 +122,15 @@ internal sealed class WaylandEglWsiSurface : EglGlPlatformSurfaceBase, IPlatform
private void EnsureWindow(PixelSize size)
{
Debug.Assert(size.Width > 0 && size.Height > 0);
if (_eglWindow != IntPtr.Zero && _currentSize == size)
return;
if (_eglWindow == IntPtr.Zero)
{
_eglWindow = WaylandEglNativeMethods.wl_egl_window_create(
_surface.WlSurface!.Handle, Math.Max(1, size.Width), Math.Max(1, size.Height));
_surface.WlSurface!.Handle, size.Width, size.Height);
if (_eglWindow == IntPtr.Zero)
throw new OpenGlException("wl_egl_window_create failed");
@ -141,8 +147,7 @@ internal sealed class WaylandEglWsiSurface : EglGlPlatformSurfaceBase, IPlatform
}
else
{
WaylandEglNativeMethods.wl_egl_window_resize(_eglWindow,
Math.Max(1, size.Width), Math.Max(1, size.Height), 0, 0);
WaylandEglNativeMethods.wl_egl_window_resize(_eglWindow, size.Width, size.Height, 0, 0);
}
_currentSize = size;

4
src/Avalonia.Wayland/Server/Transient/Rendering/WaylandFramebuffer.cs

@ -47,7 +47,9 @@ class WaylandFramebuffer(IWaylandFramebufferSurface surface) : IFramebufferPlatf
throw new RenderTargetNotReadyException();
var size = sceneInfo.Size;
var bufferLen = sceneInfo.Size.Width * sceneInfo.Size.Height * 4;
size = new PixelSize(Math.Max(1, size.Width), Math.Max(1, size.Height));
var bufferLen = size.Width * size.Height * 4;
var stride = size.Width * 4;
var fd = memfd_create("avalonia-wayland-framebuffer", MFD_CLOEXEC);

Loading…
Cancel
Save