Skip to content

Commit 952bc24

Browse files
committed
统一显示缓冲区大小计算与自适应重构
引入 DisplayBufferSizeHelper 辅助类,统一并安全地计算 LVGL 绘制缓冲区和帧缓冲区的字节大小。重构 OffscreenView、WaylandBufferPresenter、MacOsView、RemoteViewBase、X11View、Win32View 等平台相关代码,全部采用新方法分配缓冲区。X11View 和 Win32View 增强了窗口尺寸变更时的缓冲区自适应与资源管理,提升了跨平台显示缓冲区管理的健壮性和可维护性。
1 parent f80337b commit 952bc24

File tree

7 files changed

+231
-55
lines changed

7 files changed

+231
-55
lines changed
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
namespace LVGLSharp;
2+
3+
public static class DisplayBufferSizeHelper
4+
{
5+
/// <summary>
6+
/// Calculates the total pixel count for the specified surface size.
7+
/// </summary>
8+
public static int GetPixelCount(int width, int height)
9+
{
10+
ValidateDimensions(width, height);
11+
return checked(width * height);
12+
}
13+
14+
/// <summary>
15+
/// Calculates the byte size required for a full-frame LVGL RGB565 draw buffer.
16+
/// </summary>
17+
public static uint GetRgb565DrawBufferByteSize(int width, int height)
18+
{
19+
return checked((uint)(GetPixelCount(width, height) * sizeof(ushort)));
20+
}
21+
22+
/// <summary>
23+
/// Calculates the byte size required for a 32-bit host framebuffer.
24+
/// </summary>
25+
public static int GetColor32FrameBufferByteSize(int width, int height)
26+
{
27+
return checked(GetPixelCount(width, height) * sizeof(uint));
28+
}
29+
30+
private static void ValidateDimensions(int width, int height)
31+
{
32+
if (width <= 0)
33+
{
34+
throw new ArgumentOutOfRangeException(nameof(width));
35+
}
36+
37+
if (height <= 0)
38+
{
39+
throw new ArgumentOutOfRangeException(nameof(height));
40+
}
41+
}
42+
}

src/LVGLSharp.Runtime.Headless/OffscreenView.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -234,14 +234,14 @@ private void ApplyBackgroundStyle()
234234

235235
private void AllocateBuffers()
236236
{
237-
_drawBufferByteSize = checked((uint)(_options.Width * _options.Height * sizeof(ushort)));
237+
_drawBufferByteSize = DisplayBufferSizeHelper.GetRgb565DrawBufferByteSize(_options.Width, _options.Height);
238238
_drawBuffer = (byte*)NativeMemory.AllocZeroed((nuint)_drawBufferByteSize);
239239
if (_drawBuffer == null)
240240
{
241241
throw new OutOfMemoryException("Offscreen draw buffer ?????");
242242
}
243243

244-
_frameBuffer = (uint*)NativeMemory.AllocZeroed((nuint)(_options.Width * _options.Height), (nuint)sizeof(uint));
244+
_frameBuffer = (uint*)NativeMemory.AllocZeroed((nuint)DisplayBufferSizeHelper.GetPixelCount(_options.Width, _options.Height), (nuint)sizeof(uint));
245245
if (_frameBuffer == null)
246246
{
247247
throw new OutOfMemoryException("Offscreen frame buffer ?????");

src/LVGLSharp.Runtime.Linux/Wayland/WaylandBufferPresenter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ private void EnsureDrawBuffer()
207207
return;
208208
}
209209

210-
_drawBufferByteSize = checked((uint)(PixelWidth * PixelHeight * sizeof(ushort)));
210+
_drawBufferByteSize = DisplayBufferSizeHelper.GetRgb565DrawBufferByteSize(PixelWidth, PixelHeight);
211211
_drawBuffer = (byte*)NativeMemory.AllocZeroed((nuint)_drawBufferByteSize);
212212
if (_drawBuffer == null)
213213
{

src/LVGLSharp.Runtime.Linux/X11View.cs

Lines changed: 103 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public unsafe partial class X11View : ViewLifetimeBase
2929
private const int ButtonRelease = 5;
3030
private const int MotionNotify = 6;
3131
private const int DestroyNotify = 17;
32+
private const int ConfigureNotify = 22;
3233
private const int ClientMessage = 33;
3334

3435
private const long KeyPressMask = 1L << 0;
@@ -148,6 +149,24 @@ private struct XDestroyWindowEvent
148149
public nuint window;
149150
}
150151

152+
[StructLayout(LayoutKind.Sequential)]
153+
private struct XConfigureEvent
154+
{
155+
public int type;
156+
public nuint serial;
157+
public int send_event;
158+
public IntPtr display;
159+
public nuint @event;
160+
public nuint window;
161+
public int x;
162+
public int y;
163+
public int width;
164+
public int height;
165+
public int border_width;
166+
public nuint above;
167+
public int override_redirect;
168+
}
169+
151170
[StructLayout(LayoutKind.Explicit)]
152171
private struct XClientMessageData
153172
{
@@ -179,6 +198,7 @@ private struct XEvent
179198
[FieldOffset(0)] public XButtonEvent xbutton;
180199
[FieldOffset(0)] public XMotionEvent xmotion;
181200
[FieldOffset(0)] public XClientMessageEvent xclient;
201+
[FieldOffset(0)] public XConfigureEvent xconfigure;
182202
[FieldOffset(0)] public XDestroyWindowEvent xdestroywindow;
183203
}
184204

@@ -328,8 +348,8 @@ private static partial int XChangeProperty(
328348
private static partial int XFree(IntPtr data);
329349

330350
private readonly string _title;
331-
private readonly int _width;
332-
private readonly int _height;
351+
private int _width;
352+
private int _height;
333353
private readonly float _dpi;
334354
private readonly string? _requestedDisplayName;
335355
private readonly bool _borderless;
@@ -495,23 +515,7 @@ protected override void OnCloseCore()
495515
_lvDisplay = null;
496516
}
497517

498-
if (_xImage != IntPtr.Zero)
499-
{
500-
DestroyXImage();
501-
}
502-
503-
if (_frameBuffer != null)
504-
{
505-
NativeMemory.Free(_frameBuffer);
506-
_frameBuffer = null;
507-
}
508-
509-
if (_drawBuffer != null)
510-
{
511-
NativeMemory.Free(_drawBuffer);
512-
_drawBuffer = null;
513-
_drawBufferByteSize = 0;
514-
}
518+
ReleaseBuffers();
515519

516520
if (_gc != IntPtr.Zero && _display != IntPtr.Zero)
517521
{
@@ -610,26 +614,7 @@ private void InitializeWindow()
610614
throw new InvalidOperationException("X11 图形上下文创建失败。");
611615
}
612616

613-
AllocateBuffers();
614-
615-
var visual = XDefaultVisual(_display, _screen);
616-
var depth = XDefaultDepth(_display, _screen);
617-
_xImage = XCreateImage(
618-
_display,
619-
visual,
620-
(uint)depth,
621-
ZPixmap,
622-
0,
623-
(IntPtr)_frameBuffer,
624-
(uint)_width,
625-
(uint)_height,
626-
32,
627-
_width * sizeof(uint));
628-
629-
if (_xImage == IntPtr.Zero)
630-
{
631-
throw new InvalidOperationException("X11 图像缓冲创建失败。");
632-
}
617+
ResizeSurface(_width, _height);
633618

634619
XMapWindow(_display, _window);
635620
XFlush(_display);
@@ -700,20 +685,94 @@ private void InitializeLvgl()
700685

701686
private void AllocateBuffers()
702687
{
703-
_frameBuffer = (uint*)NativeMemory.AllocZeroed((nuint)(_width * _height), (nuint)sizeof(uint));
688+
_frameBuffer = (uint*)NativeMemory.AllocZeroed((nuint)DisplayBufferSizeHelper.GetPixelCount(_width, _height), (nuint)sizeof(uint));
704689
if (_frameBuffer == null)
705690
{
706691
throw new OutOfMemoryException("X11 framebuffer 分配失败。");
707692
}
708693

709-
_drawBufferByteSize = checked((uint)(_width * _height * sizeof(ushort)));
694+
_drawBufferByteSize = DisplayBufferSizeHelper.GetRgb565DrawBufferByteSize(_width, _height);
710695
_drawBuffer = (byte*)NativeMemory.AllocZeroed((nuint)_drawBufferByteSize);
711696
if (_drawBuffer == null)
712697
{
713698
throw new OutOfMemoryException("LVGL draw buffer 分配失败。");
714699
}
715700
}
716701

702+
private void CreateXImage()
703+
{
704+
var visual = XDefaultVisual(_display, _screen);
705+
var depth = XDefaultDepth(_display, _screen);
706+
_xImage = XCreateImage(
707+
_display,
708+
visual,
709+
(uint)depth,
710+
ZPixmap,
711+
0,
712+
(IntPtr)_frameBuffer,
713+
(uint)_width,
714+
(uint)_height,
715+
32,
716+
_width * sizeof(uint));
717+
718+
if (_xImage == IntPtr.Zero)
719+
{
720+
throw new InvalidOperationException("X11 图像缓冲创建失败。");
721+
}
722+
}
723+
724+
private void ReleaseBuffers()
725+
{
726+
if (_xImage != IntPtr.Zero)
727+
{
728+
DestroyXImage();
729+
}
730+
731+
if (_frameBuffer != null)
732+
{
733+
NativeMemory.Free(_frameBuffer);
734+
_frameBuffer = null;
735+
}
736+
737+
if (_drawBuffer != null)
738+
{
739+
NativeMemory.Free(_drawBuffer);
740+
_drawBuffer = null;
741+
_drawBufferByteSize = 0;
742+
}
743+
}
744+
745+
private void ResizeSurface(int width, int height)
746+
{
747+
if (width <= 0 || height <= 0)
748+
{
749+
return;
750+
}
751+
752+
if (width == _width && height == _height && _frameBuffer != null && _drawBuffer != null && _xImage != IntPtr.Zero)
753+
{
754+
return;
755+
}
756+
757+
ReleaseBuffers();
758+
759+
_width = width;
760+
_height = height;
761+
AllocateBuffers();
762+
CreateXImage();
763+
764+
if (_lvDisplay != null)
765+
{
766+
lv_display_set_resolution(_lvDisplay, _width, _height);
767+
lv_display_set_buffers(_lvDisplay, _drawBuffer, null, _drawBufferByteSize, LV_DISPLAY_RENDER_MODE_FULL);
768+
}
769+
770+
if (RootObject != null)
771+
{
772+
lv_obj_invalidate(RootObject);
773+
}
774+
}
775+
717776
private void PollEvents()
718777
{
719778
while (XPending(_display) > 0)
@@ -787,6 +846,9 @@ private void PollEvents()
787846
_running = false;
788847
}
789848
break;
849+
case ConfigureNotify:
850+
ResizeSurface(ev.xconfigure.width, ev.xconfigure.height);
851+
break;
790852
case DestroyNotify:
791853
_running = false;
792854
break;

src/LVGLSharp.Runtime.MacOs/MacOsView.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ private void AllocateBuffers(int width, int height)
258258
}
259259

260260
_frameBuffer = new MacOsFrameBuffer(width, height);
261-
_drawBufferByteSize = checked((uint)(width * height * sizeof(ushort)));
261+
_drawBufferByteSize = DisplayBufferSizeHelper.GetRgb565DrawBufferByteSize(width, height);
262262
_drawBuffer = (byte*)NativeMemory.AllocZeroed((nuint)_drawBufferByteSize);
263263
if (_drawBuffer == null)
264264
{

src/LVGLSharp.Runtime.Remote/Views/RemoteViewBase.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -284,14 +284,14 @@ void IRemoteInputSink.PostInput(RemoteInputEvent inputEvent)
284284

285285
private void AllocateBuffers()
286286
{
287-
_drawBufferByteSize = checked((uint)(_width * _height * sizeof(ushort)));
287+
_drawBufferByteSize = DisplayBufferSizeHelper.GetRgb565DrawBufferByteSize(_width, _height);
288288
_drawBuffer = (byte*)NativeMemory.AllocZeroed((nuint)_drawBufferByteSize);
289289
if (_drawBuffer == null)
290290
{
291291
throw new OutOfMemoryException("Remote draw buffer 分配失败。");
292292
}
293293

294-
_frameBuffer = (uint*)NativeMemory.AllocZeroed((nuint)(_width * _height), (nuint)sizeof(uint));
294+
_frameBuffer = (uint*)NativeMemory.AllocZeroed((nuint)DisplayBufferSizeHelper.GetPixelCount(_width, _height), (nuint)sizeof(uint));
295295
if (_frameBuffer == null)
296296
{
297297
throw new OutOfMemoryException("Remote frame buffer 分配失败。");

0 commit comments

Comments
 (0)