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(reinterpret_cast(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 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 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.