diff options
Diffstat (limited to 'src/core/delegated_frame_node.cpp')
-rw-r--r-- | src/core/delegated_frame_node.cpp | 92 |
1 files changed, 68 insertions, 24 deletions
diff --git a/src/core/delegated_frame_node.cpp b/src/core/delegated_frame_node.cpp index 57ce581f1..3d3e0dd8f 100644 --- a/src/core/delegated_frame_node.cpp +++ b/src/core/delegated_frame_node.cpp @@ -202,42 +202,74 @@ static QSGNode *buildLayerChain(QSGNode *chainParent, const cc::SharedQuadState return layerChain; } -static void waitAndDeleteChromiumSync(FenceSync *sync) +static void waitChromiumSync(gfx::TransferableFence *sync) { // Chromium uses its own GL bindings and stores in in thread local storage. // For that reason, let chromium_gpu_helper.cpp contain the producing code that will run in the Chromium // GPU thread, and put the sync consuming code here that will run in the QtQuick SG or GUI thread. switch (sync->type) { - case FenceSync::NoSync: + case gfx::TransferableFence::NoSync: break; - case FenceSync::EglSync: + case gfx::TransferableFence::EglSync: #ifdef EGL_KHR_reusable_sync { static bool resolved = false; static PFNEGLCLIENTWAITSYNCKHRPROC eglClientWaitSyncKHR = 0; - static PFNEGLDESTROYSYNCKHRPROC eglDestroySyncKHR = 0; if (!resolved) { if (gfx::GLSurfaceQt::HasEGLExtension("EGL_KHR_reusable_sync")) { QOpenGLContext *context = QOpenGLContext::currentContext(); eglClientWaitSyncKHR = (PFNEGLCLIENTWAITSYNCKHRPROC)context->getProcAddress("eglClientWaitSyncKHR"); - eglDestroySyncKHR = (PFNEGLDESTROYSYNCKHRPROC)context->getProcAddress("eglDestroySyncKHR"); } resolved = true; } - if (eglClientWaitSyncKHR && eglDestroySyncKHR) { + if (eglClientWaitSyncKHR) // FIXME: Use the less wasteful eglWaitSyncKHR once we have a device that supports EGL_KHR_wait_sync. eglClientWaitSyncKHR(sync->egl.display, sync->egl.sync, 0, EGL_FOREVER_KHR); + } +#endif + break; + case gfx::TransferableFence::ArbSync: +#ifdef GL_ARB_sync + glWaitSync(sync->arb.sync, 0, GL_TIMEOUT_IGNORED); +#endif + break; + } +} + +static void deleteChromiumSync(gfx::TransferableFence *sync) +{ + // Chromium uses its own GL bindings and stores in in thread local storage. + // For that reason, let chromium_gpu_helper.cpp contain the producing code that will run in the Chromium + // GPU thread, and put the sync consuming code here that will run in the QtQuick SG or GUI thread. + switch (sync->type) { + case gfx::TransferableFence::NoSync: + break; + case gfx::TransferableFence::EglSync: +#ifdef EGL_KHR_reusable_sync + { + static bool resolved = false; + static PFNEGLDESTROYSYNCKHRPROC eglDestroySyncKHR = 0; + + if (!resolved) { + if (gfx::GLSurfaceQt::HasEGLExtension("EGL_KHR_reusable_sync")) { + QOpenGLContext *context = QOpenGLContext::currentContext(); + eglDestroySyncKHR = (PFNEGLDESTROYSYNCKHRPROC)context->getProcAddress("eglDestroySyncKHR"); + } + resolved = true; + } + + if (eglDestroySyncKHR) { + // FIXME: Use the less wasteful eglWaitSyncKHR once we have a device that supports EGL_KHR_wait_sync. eglDestroySyncKHR(sync->egl.display, sync->egl.sync); sync->reset(); } } #endif break; - case FenceSync::ArbSync: + case gfx::TransferableFence::ArbSync: #ifdef GL_ARB_sync - glWaitSync(sync->arb.sync, 0, GL_TIMEOUT_IGNORED); glDeleteSync(sync->arb.sync); sync->reset(); #endif @@ -385,20 +417,33 @@ void DelegatedFrameNode::preprocess() mailboxesToFetch.append(mailboxTexture.data()); if (!mailboxesToFetch.isEmpty()) { - QMutexLocker lock(&m_mutex); - base::MessageLoop *gpuMessageLoop = gpu_message_loop(); - content::SyncPointManager *syncPointManager = sync_point_manager(); + QMap<uint32, gfx::TransferableFence> transferredFences; + { + QMutexLocker lock(&m_mutex); + base::MessageLoop *gpuMessageLoop = gpu_message_loop(); + content::SyncPointManager *syncPointManager = sync_point_manager(); + + Q_FOREACH (MailboxTexture *mailboxTexture, mailboxesToFetch) { + m_numPendingSyncPoints++; + AddSyncPointCallbackOnGpuThread(gpuMessageLoop, syncPointManager, mailboxTexture->resource().mailbox_holder.sync_point, base::Bind(&DelegatedFrameNode::syncPointRetired, this, &mailboxesToFetch)); + } - Q_FOREACH (MailboxTexture *mailboxTexture, mailboxesToFetch) { - m_numPendingSyncPoints++; - AddSyncPointCallbackOnGpuThread(gpuMessageLoop, syncPointManager, mailboxTexture->resource().mailbox_holder.sync_point, base::Bind(&DelegatedFrameNode::syncPointRetired, this, &mailboxesToFetch)); + m_mailboxesFetchedWaitCond.wait(&m_mutex); + m_mailboxGLFences.swap(transferredFences); } - m_mailboxesFetchedWaitCond.wait(&m_mutex); - - // Tell GL to wait until Chromium is done generating resource textures on the GPU thread. - // We can safely start referencing those textures onto geometries afterward. - waitAndDeleteChromiumSync(&m_mailboxesGLFence); + // Tell GL to wait until Chromium is done generating resource textures on the GPU thread + // for each mailbox. We can safely start referencing those textures onto geometries afterward. + Q_FOREACH (MailboxTexture *mailboxTexture, mailboxesToFetch) { + gfx::TransferableFence fence = transferredFences.take(mailboxTexture->resource().mailbox_holder.sync_point); + waitChromiumSync(&fence); + deleteChromiumSync(&fence); + } + // We transferred all sync point fences from Chromium, + // destroy all the ones not referenced by one of our mailboxes without waiting. + QMap<uint32, gfx::TransferableFence>::iterator end = transferredFences.end(); + for (QMap<uint32, gfx::TransferableFence>::iterator it = transferredFences.begin(); it != end; ++it) + deleteChromiumSync(&*it); } // Then render any intermediate RenderPass in order. @@ -602,14 +647,13 @@ void DelegatedFrameNode::fetchTexturesAndUnlockQt(DelegatedFrameNode *frameNode, Q_FOREACH (MailboxTexture *mailboxTexture, *mailboxesToFetch) mailboxTexture->fetchTexture(mailboxManager); - // Set a fence at this point in Chromium's GL command stream - // and transfer the handle to the Qt scene graph thread. - FenceSync fence = createFence(); + // Pick fences that we can ask GL to wait for before trying to sample the mailbox texture IDs. + QMap<uint32, gfx::TransferableFence> transferredFences = transferFences(); // Chromium provided everything we were waiting for, let Qt start rendering. QMutexLocker lock(&frameNode->m_mutex); - Q_ASSERT(!frameNode->m_mailboxesGLFence); - frameNode->m_mailboxesGLFence = fence; + Q_ASSERT(frameNode->m_mailboxGLFences.isEmpty()); + frameNode->m_mailboxGLFences.swap(transferredFences); frameNode->m_mailboxesFetchedWaitCond.wakeOne(); } |