From 78be37f5cdb9993264d5cb3b8a019af536b2e8c7 Mon Sep 17 00:00:00 2001
From: Greg Daniel <egdaniel@google.com>
Date: Tue, 14 Apr 2020 16:40:35 -0400
Subject: [PATCH] Only call glFlush in submit when it is required.

Bug: chromium:1070474
Change-Id: I9131c3d931ec0d861fff4d92549d5d3fce8a123f
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/283503
Commit-Queue: Greg Daniel <egdaniel@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
---
 src/gpu/gl/GrGLGpu.cpp | 17 +++++++++++++----
 src/gpu/gl/GrGLGpu.h   | 15 +++++++++++++++
 2 files changed, 28 insertions(+), 4 deletions(-)

diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index ab1c614dd1..37bbdb380f 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -2867,7 +2867,7 @@ void GrGLGpu::unbindSurfaceFBOForPixelOps(GrSurface* surface, int mipLevel, GrGL
 void GrGLGpu::onFBOChanged() {
     if (this->caps()->workarounds().flush_on_framebuffer_change ||
         this->caps()->workarounds().restore_scissor_on_fbo_change) {
-        GL_CALL(Flush());
+        this->flush(FlushType::kForce);
     }
 #ifdef SK_DEBUG
     if (fIsExecutingCommandBuffer_DebugOnly) {
@@ -3798,6 +3798,13 @@ void GrGLGpu::addFinishedProc(GrGpuFinishedProc finishedProc,
     fFinishCallbacks.push_back(callback);
 }
 
+void GrGLGpu::flush(FlushType flushType) {
+    if (fNeedsGLFlush || flushType == FlushType::kForce) {
+        GL_CALL(Flush());
+        fNeedsGLFlush = false;
+    }
+}
+
 bool GrGLGpu::onSubmitToGpu(bool syncCpu) {
     if (syncCpu || (!fFinishCallbacks.empty() && !this->caps()->fenceSyncSupport())) {
         GL_CALL(Finish());
@@ -3812,7 +3819,7 @@ bool GrGLGpu::onSubmitToGpu(bool syncCpu) {
         }
         fFinishCallbacks.clear();
     } else {
-        GL_CALL(Flush());
+        this->flush();
         // See if any previously inserted finish procs are good to go.
         this->checkFinishProcs();
     }
@@ -3837,6 +3844,7 @@ GrFence SK_WARN_UNUSED_RESULT GrGLGpu::insertFence() {
     } else {
         GL_CALL_RET(sync, FenceSync(GR_GL_SYNC_GPU_COMMANDS_COMPLETE, 0));
     }
+    this->setNeedsFlush();
     static_assert(sizeof(GrFence) >= sizeof(GrGLsync));
     return (GrFence)sync;
 }
@@ -3846,7 +3854,7 @@ bool GrGLGpu::waitSync(GrGLsync sync, uint64_t timeout, bool flush) {
         GrGLuint nvFence = static_cast<GrGLuint>(reinterpret_cast<intptr_t>(sync));
         if (!timeout) {
             if (flush) {
-                GL_CALL(Flush);
+                this->flush(FlushType::kForce);
             }
             GrGLboolean result;
             GL_CALL_RET(result, TestFence(nvFence));
@@ -3892,6 +3900,7 @@ void GrGLGpu::insertSemaphore(GrSemaphore* semaphore) {
     GrGLsync sync;
     GL_CALL_RET(sync, FenceSync(GR_GL_SYNC_GPU_COMMANDS_COMPLETE, 0));
     glSem->setSync(sync);
+    this->setNeedsFlush();
 }
 
 void GrGLGpu::waitSemaphore(GrSemaphore* semaphore) {
@@ -3925,7 +3934,7 @@ std::unique_ptr<GrSemaphore> GrGLGpu::prepareTextureForCrossContextUsage(GrTextu
     SkASSERT(semaphore);
     this->insertSemaphore(semaphore.get());
     // We must call flush here to make sure the GrGLSync object gets created and sent to the gpu.
-    GL_CALL(Flush());
+    this->flush(FlushType::kForce);
 
     return semaphore;
 }
diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h
index 0bceaea3ef..8410b6b240 100644
--- a/src/gpu/gl/GrGLGpu.h
+++ b/src/gpu/gl/GrGLGpu.h
@@ -609,6 +609,16 @@ private:
         return &fHWBufferState[typeAsUInt];
     }
 
+    enum class FlushType {
+        kIfRequired,
+        kForce,
+    };
+
+    // This calls glFlush if it is required for previous operations or kForce is passed.
+    void flush(FlushType flushType = FlushType::kIfRequired);
+
+    void setNeedsFlush() { fNeedsGLFlush = true; }
+
     struct {
         GrBlendEquation fEquation;
         GrBlendCoeff    fSrcCoeff;
@@ -705,6 +715,11 @@ private:
     };
     std::list<FinishCallback> fFinishCallbacks;
 
+    // If we've called a command that requires us to call glFlush than this will be set to true
+    // since we defer calling flush until submit time. When we call submitToGpu if this is true then
+    // we call glFlush and reset this to false.
+    bool fNeedsGLFlush = false;
+
     SkDEBUGCODE(bool fIsExecutingCommandBuffer_DebugOnly = false);
 
     friend class GrGLPathRendering; // For accessing setTextureUnit.