From 3ebbbf5a18d663ae697e05611395dbccae81ed28 Mon Sep 17 00:00:00 2001 From: Uladzimir Karpenka Date: Thu, 9 Jul 2026 15:25:53 +0300 Subject: [PATCH] fix(cocoa): real double buffering instead of fake glFlush swap NSOpenGLPFADoubleBuffer was commented out, so DoubleBuffered:=True on the control was silently ignored and the context stayed single-buffered. LOpenGLSwapBuffers then only called glFlush(), leaving the front buffer on screen mid-draw: frames tore and views could show partially rendered content. Request the double-buffer pixel format when DoubleBuffered is set, and present through NSOpenGLContext.flushBuffer. Falls back to glFlush() when no context exists yet. Note: this is a correctness fix, not a performance one -- measured on an M1 Pro the app's CPU usage is unchanged. Co-Authored-By: Claude Opus 4.8 --- glcocoanscontextex.pas | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/glcocoanscontextex.pas b/glcocoanscontextex.pas index 95a1d31..cc787d9 100644 --- a/glcocoanscontextex.pas +++ b/glcocoanscontextex.pas @@ -140,13 +140,23 @@ begin end; procedure LOpenGLSwapBuffers(Handle: HWND); -//var -// View: TCocoaOpenGLView; //TCocoaOpenGLView +var + View: TCocoaOpenGLView; + Ctx: NSOpenGLContext; begin if Handle=0 then exit; - glFlush(); - // View:=TCocoaOpenGLView(Handle); - // View.nsGL.flushBuffer; + View:=TCocoaOpenGLView(Handle); + Ctx:=View.openGLContext; + if Ctx=nil then + begin + // single-buffered fallback (no context yet) + glFlush(); + exit; + end; + // Present the back buffer. The old glFlush() left the single-buffered + // front buffer on screen mid-draw, so frames tore and the view could show + // partially rendered content. + Ctx.flushBuffer; end; function LOpenGLMakeCurrent(Handle: HWND): boolean; @@ -283,8 +293,8 @@ var begin AddUInt32(NSOpenGLPFAAuxBuffers); AddUInt32(AUXBuffers); end; - //if DoubleBuffered then //requires fix for nsGL - // AddUInt32(NSOpenGLPFADoubleBuffer); //this doen't work with Lazarus + if DoubleBuffered then //present via real flushBuffer in LOpenGLSwapBuffers + AddUInt32(NSOpenGLPFADoubleBuffer); AddUInt32(NSOpenGLPFAMaximumPolicy); //allows future changes to make attributes more demanding, e.g. add multisampling AddUInt32(NSOpenGLPFANoRecovery); //see apple web page: "not generally useful" but might help with multisample