summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
m---------src/3rdparty0
-rw-r--r--src/core/chromium_gpu_helper.cpp28
-rw-r--r--src/core/chromium_gpu_helper.h30
-rw-r--r--src/core/delegated_frame_node.cpp92
-rw-r--r--src/core/delegated_frame_node.h2
5 files changed, 81 insertions, 71 deletions
diff --git a/src/3rdparty b/src/3rdparty
-Subproject 250eb95317140bf65dfd7b4dbc03ac20f45cde4
+Subproject 9005624091e3f5a9e9ff4d17d2bc5d32928ce35
diff --git a/src/core/chromium_gpu_helper.cpp b/src/core/chromium_gpu_helper.cpp
index c4cb2ec0b..6287bd7c0 100644
--- a/src/core/chromium_gpu_helper.cpp
+++ b/src/core/chromium_gpu_helper.cpp
@@ -57,27 +57,17 @@ static void addSyncPointCallbackDelegate(content::SyncPointManager *syncPointMan
syncPointManager->AddSyncPointCallback(sync_point, callback);
}
-FenceSync createFence()
+QMap<uint32, gfx::TransferableFence> transferFences()
{
- FenceSync ret;
- // Logic taken from chromium/ui/gl/gl_fence.cc
-#if !defined(OS_MACOSX)
- if (gfx::g_driver_egl.ext.b_EGL_KHR_fence_sync) {
- ret.type = FenceSync::EglSync;
- ret.egl.display = eglGetCurrentDisplay();
- ret.egl.sync = eglCreateSyncKHR(ret.egl.display, EGL_SYNC_FENCE_KHR, NULL);
- } else
-#endif
- if (gfx::g_driver_gl.ext.b_GL_ARB_sync) {
- ret.type = FenceSync::ArbSync;
- ret.arb.sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+ QMap<uint32, gfx::TransferableFence> ret;
+ content::GpuChannelManager *gpuChannelManager = content::GpuChildThread::instance()->ChannelManager();
+ content::GpuChannelManager::SyncPointGLFences::iterator it = gpuChannelManager->sync_point_gl_fences_.begin();
+ content::GpuChannelManager::SyncPointGLFences::iterator end = gpuChannelManager->sync_point_gl_fences_.end();
+ for (; it != end; ++it) {
+ ret[it->first] = it->second->Transfer();
+ delete it->second;
}
-
- // glFlush is necessary to make sure that our fence creation reaches the GL server
- // before we try waiting on it from a different context, which could deadlock.
- // In cases where no fence extension is available, this also serves as flushing
- // Chromium's GL context command stream before yielding to the SG thread.
- glFlush();
+ gpuChannelManager->sync_point_gl_fences_.clear();
return ret;
}
diff --git a/src/core/chromium_gpu_helper.h b/src/core/chromium_gpu_helper.h
index 364f82bbc..8b11c9b5f 100644
--- a/src/core/chromium_gpu_helper.h
+++ b/src/core/chromium_gpu_helper.h
@@ -38,8 +38,10 @@
#define CHROMIUM_GPU_HELPER_H
#include <QtGlobal> // We need this for the Q_OS_QNX define.
+#include <QMap>
#include "base/callback.h"
+#include "ui/gl/gl_fence.h"
namespace base {
class MessageLoop;
@@ -57,38 +59,12 @@ class Texture;
}
}
-typedef void *EGLDisplay;
-typedef void *EGLSyncKHR;
-typedef struct __GLsync *GLsync;
-
-union FenceSync {
- enum SyncType {
- NoSync,
- EglSync,
- ArbSync
- };
- SyncType type;
- struct {
- SyncType type;
- EGLDisplay display;
- EGLSyncKHR sync;
- } egl;
- struct {
- SyncType type;
- GLsync sync;
- } arb;
-
- FenceSync() : type(NoSync) { }
- operator bool() { return type != NoSync; }
- void reset() { type = NoSync; }
-};
-
// These functions wrap code that needs to include headers that are
// incompatible with Qt GL headers.
// From the outside, types from incompatible headers referenced in these
// functions should only be forward-declared and considered as opaque types.
-FenceSync createFence();
+QMap<uint32, gfx::TransferableFence> transferFences();
base::MessageLoop *gpu_message_loop();
content::SyncPointManager *sync_point_manager();
gpu::gles2::MailboxManager *mailbox_manager();
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();
}
diff --git a/src/core/delegated_frame_node.h b/src/core/delegated_frame_node.h
index 98861eefa..a031a464f 100644
--- a/src/core/delegated_frame_node.h
+++ b/src/core/delegated_frame_node.h
@@ -75,7 +75,7 @@ private:
QExplicitlySharedDataPointer<DelegatedFrameNodeData> m_data;
QList<QSharedPointer<RenderPassTexture> > m_renderPassTextures;
int m_numPendingSyncPoints;
- FenceSync m_mailboxesGLFence;
+ QMap<uint32, gfx::TransferableFence> m_mailboxGLFences;
QWaitCondition m_mailboxesFetchedWaitCond;
QMutex m_mutex;