vcl/inc/skia/osx/gdiimpl.hxx |    2 ++
 vcl/osx/salframe.cxx         |   43 +++++++++++++++++++++++++++++++++++++------
 vcl/skia/osx/gdiimpl.cxx     |    2 ++
 3 files changed, 41 insertions(+), 6 deletions(-)

New commits:
commit a24789f747dc998bd4fd1c0110a89e791ee051c2
Author:     Patrick Luby <guibmac...@gmail.com>
AuthorDate: Sun Apr 27 09:35:37 2025 -0400
Commit:     Patrick Luby <guibomac...@gmail.com>
CommitDate: Sun Apr 27 16:55:06 2025 +0200

    tdf#166258 Refactor throttling of Skia/Metal flushes
    
    Throttling of Skia/Metal flushes is needed for tdf#163945 but the
    throttling logic was being applied to too frequently. So throttle
    based on the time interval of the last Skia/Metal flush and if the
    flush is too soon after the last flush (i.e. 1/200th of a second),
    schedule the flush in the Skia timer.
    
    Change-Id: Ib4e526ec26ec8b8d36bf3a9776bfe49d153d759f
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/184681
    Tested-by: Jenkins
    Reviewed-by: Patrick Luby <guibomac...@gmail.com>

diff --git a/vcl/inc/skia/osx/gdiimpl.hxx b/vcl/inc/skia/osx/gdiimpl.hxx
index 6e1656e59f1c..b189898082ab 100644
--- a/vcl/inc/skia/osx/gdiimpl.hxx
+++ b/vcl/inc/skia/osx/gdiimpl.hxx
@@ -41,6 +41,8 @@ public:
     virtual void Flush(const tools::Rectangle&) override;
     virtual void WindowBackingPropertiesChanged() override;
 
+    void ScheduleFlush();
+
     CGImageRef createCGImageFromRasterSurface(const NSRect& rDirtyRect, 
CGPoint& rImageOrigin,
                                               bool& rImageFlipped);
 
diff --git a/vcl/osx/salframe.cxx b/vcl/osx/salframe.cxx
index 636a07a6a152..08517cb837e7 100644
--- a/vcl/osx/salframe.cxx
+++ b/vcl/osx/salframe.cxx
@@ -59,6 +59,7 @@
 
 #if HAVE_FEATURE_SKIA
 #include <vcl/skia/SkiaHelper.hxx>
+#include "skia/osx/gdiimpl.hxx"
 #endif
 
 const int nMinBlinkCursorDelay = 500;
@@ -1196,20 +1197,50 @@ bool AquaSalFrame::doFlush()
         // rapid dragging, this can lead to creating and queueing
         // up to 200 drawables per second leaving no spare time for
         // the Impress selection box painting timer to fire.
-        // So with Skia/Metal, throttle the rate of flushing by
-        // calling display on the view.
-        bool bDisplay = false;
+        // So with Skia/Metal, throttle the rate of flushing.
+        bool bNeedsFlush = true;
+        bool bFlushed = false;
 #if HAVE_FEATURE_SKIA
         // tdf#164428 Skia/Metal needs flush after drawing progress bar
-        bDisplay = !mbForceFlushProgressBar && SkiaHelper::isVCLSkiaEnabled() 
&& SkiaHelper::renderMethodToUse() != SkiaHelper::RenderRaster;
+        if (!mbForceFlushProgressBar && SkiaHelper::isVCLSkiaEnabled() && 
SkiaHelper::renderMethodToUse() != SkiaHelper::RenderRaster)
+        {
+            AquaSkiaSalGraphicsImpl *pSkiaGraphicsImpl = 
dynamic_cast<AquaSkiaSalGraphicsImpl*>(mpGraphics->GetImpl());
+            if (pSkiaGraphicsImpl)
+            {
+                // Assume 1/200th of a second is the fastest flushing rate
+                // that can be handled with Skia/Metal. Note that the Skia
+                // timer is running separately so the overall flushing rate
+                // may still be faster than this limit.
+                static const CFAbsoluteTime fMinFlushInterval = 0.005f;
+                static CFAbsoluteTime fLastFlushTime = 0;
+
+                CFAbsoluteTime fInterval = CFAbsoluteTimeGetCurrent() - 
fLastFlushTime;
+                if (fInterval >= 0.0f && fInterval < fMinFlushInterval)
+                {
+                    // Just to be safe, schedule the Skia timer to run so that
+                    // a flush is only delayed but never missed
+                    pSkiaGraphicsImpl->ScheduleFlush();
+                }
+                else
+                {
+                    mpGraphics->Flush();
+                    fLastFlushTime = CFAbsoluteTimeGetCurrent();
+                    bFlushed = true;
+                }
+                bNeedsFlush = false;
+            }
+        }
 #endif
-        if (!bDisplay)
+        if (bNeedsFlush)
+        {
             mpGraphics->Flush();
+            bFlushed = true;
+        }
 
         // Related: tdf#155266 skip redisplay of the view when forcing flush
         // It appears that calling -[NSView display] overwhelms some Intel Macs
         // so only flush the graphics and skip immediate redisplay of the view.
-        bRet = bDisplay || ImplGetSVData()->maAppData.mnDispatchLevel <= 0;
+        bRet = !bFlushed || ImplGetSVData()->maAppData.mnDispatchLevel <= 0;
 
         mbForceFlushScrolling = false;
         mbForceFlushProgressBar = false;
diff --git a/vcl/skia/osx/gdiimpl.cxx b/vcl/skia/osx/gdiimpl.cxx
index 8043fb2e2b72..8e7e7b7beecf 100644
--- a/vcl/skia/osx/gdiimpl.cxx
+++ b/vcl/skia/osx/gdiimpl.cxx
@@ -129,6 +129,8 @@ void AquaSkiaSalGraphicsImpl::flushSurfaceToWindowContext()
     }
 }
 
+void AquaSkiaSalGraphicsImpl::ScheduleFlush() { scheduleFlush(); }
+
 // For Raster we use our own screen blitting (see above).
 CGImageRef AquaSkiaSalGraphicsImpl::createCGImageFromRasterSurface(const 
NSRect& rDirtyRect,
                                                                    CGPoint& 
rImageOrigin,

Reply via email to