summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--android_webview/browser/aw_browser_main_parts.cc10
-rw-r--r--android_webview/lib/main/aw_main_delegate.cc3
-rw-r--r--content/common/gpu/gpu_channel.cc4
-rw-r--r--content/common/gpu/gpu_channel_manager.cc4
-rw-r--r--gpu/command_buffer/service/BUILD.gn7
-rw-r--r--gpu/command_buffer/service/context_group.cc4
-rw-r--r--gpu/command_buffer/service/gpu_switches.cc5
-rw-r--r--gpu/command_buffer/service/gpu_switches.h1
-rw-r--r--gpu/command_buffer/service/in_process_command_buffer.cc22
-rw-r--r--gpu/command_buffer/service/mailbox_manager.h68
-rw-r--r--gpu/command_buffer/service/mailbox_manager_impl.cc (renamed from gpu/command_buffer/service/mailbox_manager.cc)61
-rw-r--r--gpu/command_buffer/service/mailbox_manager_impl.h65
-rw-r--r--gpu/command_buffer/service/mailbox_manager_sync.cc344
-rw-r--r--gpu/command_buffer/service/mailbox_manager_sync.h101
-rw-r--r--gpu/command_buffer/service/mailbox_manager_unittest.cc183
-rw-r--r--gpu/command_buffer/service/mailbox_synchronizer.cc276
-rw-r--r--gpu/command_buffer/service/mailbox_synchronizer.h107
-rw-r--r--gpu/command_buffer/service/texture_definition.cc11
-rw-r--r--gpu/command_buffer/service/texture_definition.h3
-rw-r--r--gpu/command_buffer/service/texture_manager.h3
-rw-r--r--gpu/command_buffer/tests/gl_manager.cc4
-rw-r--r--gpu/command_buffer_service.gypi7
-rw-r--r--mojo/services/native_viewport/DEPS1
-rw-r--r--mojo/services/native_viewport/main.cc4
-rw-r--r--mojo/shell/context.cc4
25 files changed, 767 insertions, 535 deletions
diff --git a/android_webview/browser/aw_browser_main_parts.cc b/android_webview/browser/aw_browser_main_parts.cc
index 7166e00..8bbdb85 100644
--- a/android_webview/browser/aw_browser_main_parts.cc
+++ b/android_webview/browser/aw_browser_main_parts.cc
@@ -10,7 +10,6 @@
#include "base/android/build_info.h"
#include "base/android/locale_utils.h"
#include "base/android/memory_pressure_listener_android.h"
-#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/path_service.h"
#include "content/public/browser/render_process_host.h"
@@ -18,7 +17,6 @@
#include "content/public/common/content_switches.h"
#include "content/public/common/result_codes.h"
#include "content/public/common/url_utils.h"
-#include "gpu/command_buffer/service/mailbox_synchronizer.h"
#include "net/android/network_change_notifier_factory_android.h"
#include "net/base/network_change_notifier.h"
#include "ui/base/l10n/l10n_util.h"
@@ -97,14 +95,6 @@ int AwBrowserMainParts::PreCreateThreads() {
}
void AwBrowserMainParts::PreMainMessageLoopRun() {
- // TODO(boliu): Can't support accelerated 2d canvas and WebGL with ubercomp
- // yet: crbug.com/352424.
- if (!gpu::gles2::MailboxSynchronizer::Initialize()) {
- CommandLine* cl = CommandLine::ForCurrentProcess();
- cl->AppendSwitch(switches::kDisableAccelerated2dCanvas);
- cl->AppendSwitch(switches::kDisableExperimentalWebGL);
- }
-
browser_context_->PreMainMessageLoopRun();
// This is needed for WebView Classic backwards compatibility
// See crbug.com/298495
diff --git a/android_webview/lib/main/aw_main_delegate.cc b/android_webview/lib/main/aw_main_delegate.cc
index efa9454..deb5fee 100644
--- a/android_webview/lib/main/aw_main_delegate.cc
+++ b/android_webview/lib/main/aw_main_delegate.cc
@@ -25,6 +25,7 @@
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_switches.h"
#include "gpu/command_buffer/client/gl_in_process_context.h"
+#include "gpu/command_buffer/service/gpu_switches.h"
#include "media/base/media_switches.h"
#include "webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h"
@@ -80,6 +81,8 @@ bool AwMainDelegate::BasicStartupComplete(int* exit_code) {
// WebRTC hardware decoding is not supported, internal bug 15075307
cl->AppendSwitch(switches::kDisableWebRtcHWDecoding);
+ // This is needed for sharing textures across the different GL threads.
+ cl->AppendSwitch(switches::kEnableThreadedTextureMailboxes);
return false;
}
diff --git a/content/common/gpu/gpu_channel.cc b/content/common/gpu/gpu_channel.cc
index 8a327a1..369d514 100644
--- a/content/common/gpu/gpu_channel.cc
+++ b/content/common/gpu/gpu_channel.cc
@@ -25,7 +25,7 @@
#include "content/public/common/content_switches.h"
#include "gpu/command_buffer/common/mailbox.h"
#include "gpu/command_buffer/service/gpu_scheduler.h"
-#include "gpu/command_buffer/service/mailbox_manager.h"
+#include "gpu/command_buffer/service/mailbox_manager_impl.h"
#include "ipc/ipc_channel.h"
#include "ipc/message_filter.h"
#include "ui/gl/gl_context.h"
@@ -405,7 +405,7 @@ GpuChannel::GpuChannel(GpuChannelManager* gpu_channel_manager,
messages_processed_(0),
client_id_(client_id),
share_group_(share_group ? share_group : new gfx::GLShareGroup),
- mailbox_manager_(mailbox ? mailbox : new gpu::gles2::MailboxManager),
+ mailbox_manager_(mailbox ? mailbox : new gpu::gles2::MailboxManagerImpl),
watchdog_(watchdog),
software_(software),
handle_messages_scheduled_(false),
diff --git a/content/common/gpu/gpu_channel_manager.cc b/content/common/gpu/gpu_channel_manager.cc
index fd9e5f8..83530e1 100644
--- a/content/common/gpu/gpu_channel_manager.cc
+++ b/content/common/gpu/gpu_channel_manager.cc
@@ -14,7 +14,7 @@
#include "content/common/message_router.h"
#include "gpu/command_buffer/service/feature_info.h"
#include "gpu/command_buffer/service/gpu_switches.h"
-#include "gpu/command_buffer/service/mailbox_manager.h"
+#include "gpu/command_buffer/service/mailbox_manager_impl.h"
#include "gpu/command_buffer/service/memory_program_cache.h"
#include "gpu/command_buffer/service/shader_translator_cache.h"
#include "ipc/message_filter.h"
@@ -178,7 +178,7 @@ void GpuChannelManager::OnEstablishChannel(int client_id,
if (!share_group_.get()) {
share_group_ = new gfx::GLShareGroup;
DCHECK(!mailbox_manager_.get());
- mailbox_manager_ = new gpu::gles2::MailboxManager;
+ mailbox_manager_ = new gpu::gles2::MailboxManagerImpl;
}
share_group = share_group_.get();
mailbox_manager = mailbox_manager_.get();
diff --git a/gpu/command_buffer/service/BUILD.gn b/gpu/command_buffer/service/BUILD.gn
index e6c58b6..3b2b782 100644
--- a/gpu/command_buffer/service/BUILD.gn
+++ b/gpu/command_buffer/service/BUILD.gn
@@ -75,10 +75,11 @@ source_set("service") {
"in_process_command_buffer.h",
"logger.cc",
"logger.h",
- "mailbox_manager.cc",
"mailbox_manager.h",
- "mailbox_synchronizer.cc",
- "mailbox_synchronizer.h",
+ "mailbox_manager_impl.cc",
+ "mailbox_manager_impl.h",
+ "mailbox_manager_sync.cc",
+ "mailbox_manager_sync.h",
"memory_program_cache.h",
"memory_program_cache.cc",
"mocks.h",
diff --git a/gpu/command_buffer/service/context_group.cc b/gpu/command_buffer/service/context_group.cc
index fe692be..00e7ec3 100644
--- a/gpu/command_buffer/service/context_group.cc
+++ b/gpu/command_buffer/service/context_group.cc
@@ -14,7 +14,7 @@
#include "gpu/command_buffer/service/framebuffer_manager.h"
#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
#include "gpu/command_buffer/service/gpu_switches.h"
-#include "gpu/command_buffer/service/mailbox_manager.h"
+#include "gpu/command_buffer/service/mailbox_manager_impl.h"
#include "gpu/command_buffer/service/memory_tracking.h"
#include "gpu/command_buffer/service/program_manager.h"
#include "gpu/command_buffer/service/renderbuffer_manager.h"
@@ -52,7 +52,7 @@ ContextGroup::ContextGroup(
draw_buffer_(GL_BACK) {
{
if (!mailbox_manager_.get())
- mailbox_manager_ = new MailboxManager;
+ mailbox_manager_ = new MailboxManagerImpl;
if (!feature_info.get())
feature_info_ = new FeatureInfo;
TransferBufferManager* manager = new TransferBufferManager();
diff --git a/gpu/command_buffer/service/gpu_switches.cc b/gpu/command_buffer/service/gpu_switches.cc
index 0491c41..8f5bc35 100644
--- a/gpu/command_buffer/service/gpu_switches.cc
+++ b/gpu/command_buffer/service/gpu_switches.cc
@@ -56,6 +56,11 @@ const char kDisableGpuShaderDiskCache[] = "disable-gpu-shader-disk-cache";
const char kEnableShareGroupAsyncTextureUpload[] =
"enable-share-group-async-texture-upload";
+// Simulates shared textures when share groups are not available. Not available
+// everywhere.
+const char kEnableThreadedTextureMailboxes[] =
+ "enable-threaded-texture-mailboxes";
+
const char* kGpuSwitches[] = {
kCompileShaderAlwaysSucceeds,
kDisableGLErrorLimit,
diff --git a/gpu/command_buffer/service/gpu_switches.h b/gpu/command_buffer/service/gpu_switches.h
index d582b7a..2645543 100644
--- a/gpu/command_buffer/service/gpu_switches.h
+++ b/gpu/command_buffer/service/gpu_switches.h
@@ -26,6 +26,7 @@ GPU_EXPORT extern const char kGpuDriverBugWorkarounds[];
GPU_EXPORT extern const char kGpuProgramCacheSizeKb[];
GPU_EXPORT extern const char kDisableGpuShaderDiskCache[];
GPU_EXPORT extern const char kEnableShareGroupAsyncTextureUpload[];
+GPU_EXPORT extern const char kEnableThreadedTextureMailboxes[];
GPU_EXPORT extern const char* kGpuSwitches[];
GPU_EXPORT extern const int kNumGpuSwitches;
diff --git a/gpu/command_buffer/service/in_process_command_buffer.cc b/gpu/command_buffer/service/in_process_command_buffer.cc
index 1e7cc1f..3da7335 100644
--- a/gpu/command_buffer/service/in_process_command_buffer.cc
+++ b/gpu/command_buffer/service/in_process_command_buffer.cc
@@ -8,15 +8,9 @@
#include <set>
#include <utility>
-#include <GLES2/gl2.h>
-#ifndef GL_GLEXT_PROTOTYPES
-#define GL_GLEXT_PROTOTYPES 1
-#endif
-#include <GLES2/gl2ext.h>
-#include <GLES2/gl2extchromium.h>
-
#include "base/bind.h"
#include "base/bind_helpers.h"
+#include "base/command_line.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/memory/weak_ptr.h"
@@ -28,8 +22,10 @@
#include "gpu/command_buffer/service/context_group.h"
#include "gpu/command_buffer/service/gl_context_virtual.h"
#include "gpu/command_buffer/service/gpu_scheduler.h"
+#include "gpu/command_buffer/service/gpu_switches.h"
#include "gpu/command_buffer/service/image_manager.h"
-#include "gpu/command_buffer/service/mailbox_manager.h"
+#include "gpu/command_buffer/service/mailbox_manager_impl.h"
+#include "gpu/command_buffer/service/mailbox_manager_sync.h"
#include "gpu/command_buffer/service/memory_tracking.h"
#include "gpu/command_buffer/service/query_manager.h"
#include "gpu/command_buffer/service/transfer_buffer_manager.h"
@@ -185,8 +181,14 @@ InProcessCommandBuffer::Service::~Service() {}
scoped_refptr<gles2::MailboxManager>
InProcessCommandBuffer::Service::mailbox_manager() {
- if (!mailbox_manager_.get())
- mailbox_manager_ = new gles2::MailboxManager();
+ if (!mailbox_manager_.get()) {
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableThreadedTextureMailboxes)) {
+ mailbox_manager_ = new gles2::MailboxManagerSync();
+ } else {
+ mailbox_manager_ = new gles2::MailboxManagerImpl();
+ }
+ }
return mailbox_manager_;
}
diff --git a/gpu/command_buffer/service/mailbox_manager.h b/gpu/command_buffer/service/mailbox_manager.h
index a00b965..f1e23ad 100644
--- a/gpu/command_buffer/service/mailbox_manager.h
+++ b/gpu/command_buffer/service/mailbox_manager.h
@@ -1,85 +1,53 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef GPU_COMMAND_BUFFER_SERVICE_MAILBOX_MANAGER_H_
#define GPU_COMMAND_BUFFER_SERVICE_MAILBOX_MANAGER_H_
-#include <functional>
-#include <map>
-
-#include "base/memory/linked_ptr.h"
#include "base/memory/ref_counted.h"
#include "gpu/command_buffer/common/constants.h"
#include "gpu/command_buffer/common/mailbox.h"
#include "gpu/gpu_export.h"
-typedef signed char GLbyte;
-
namespace gpu {
namespace gles2 {
-class MailboxSynchronizer;
class Texture;
-class TextureManager;
// Manages resources scoped beyond the context or context group level.
class GPU_EXPORT MailboxManager : public base::RefCounted<MailboxManager> {
public:
- MailboxManager();
-
// Look up the texture definition from the named mailbox.
- Texture* ConsumeTexture(unsigned target, const Mailbox& mailbox);
+ virtual Texture* ConsumeTexture(unsigned target, const Mailbox& mailbox) = 0;
// Put the texture into the named mailbox.
- void ProduceTexture(unsigned target,
- const Mailbox& mailbox,
- Texture* texture);
+ virtual void ProduceTexture(unsigned target,
+ const Mailbox& mailbox,
+ Texture* texture) = 0;
- // Returns whether this manager synchronizes with other instances.
- bool UsesSync() { return sync_ != NULL; }
+ // If |true| then Pull/PushTextureUpdates() needs to be called.
+ virtual bool UsesSync() = 0;
- // Used with the MailboxSynchronizer to push/pull texture state to/from
- // other manager instances.
- void PushTextureUpdates(uint32 sync_point);
- void PullTextureUpdates(uint32 sync_point);
+ // Used to synchronize texture state across share groups.
+ virtual void PushTextureUpdates(uint32 sync_point) = 0;
+ virtual void PullTextureUpdates(uint32 sync_point) = 0;
// Destroy any mailbox that reference the given texture.
- void TextureDeleted(Texture* texture);
-
- private:
- friend class base::RefCounted<MailboxManager>;
- friend class MailboxSynchronizer;
+ virtual void TextureDeleted(Texture* texture) = 0;
- ~MailboxManager();
+ protected:
+ typedef std::pair<unsigned, Mailbox> TargetName;
- struct TargetName {
- TargetName(unsigned target, const Mailbox& mailbox);
- unsigned target;
- Mailbox mailbox;
- };
- void InsertTexture(TargetName target_name, Texture* texture);
+ MailboxManager() {}
+ virtual ~MailboxManager() {}
- static bool TargetNameLess(const TargetName& lhs, const TargetName& rhs);
-
- // This is a bidirectional map between mailbox and textures. We can have
- // multiple mailboxes per texture, but one texture per mailbox. We keep an
- // iterator in the MailboxToTextureMap to be able to manage changes to
- // the TextureToMailboxMap efficiently.
- typedef std::multimap<Texture*, TargetName> TextureToMailboxMap;
- typedef std::map<TargetName,
- TextureToMailboxMap::iterator,
- std::pointer_to_binary_function<const TargetName&,
- const TargetName&,
- bool> > MailboxToTextureMap;
-
- MailboxToTextureMap mailbox_to_textures_;
- TextureToMailboxMap textures_to_mailboxes_;
-
- MailboxSynchronizer* sync_;
+ private:
+ friend class base::RefCounted<MailboxManager>;
DISALLOW_COPY_AND_ASSIGN(MailboxManager);
};
+
} // namespage gles2
} // namespace gpu
diff --git a/gpu/command_buffer/service/mailbox_manager.cc b/gpu/command_buffer/service/mailbox_manager_impl.cc
index b4d6e79..a27b89b 100644
--- a/gpu/command_buffer/service/mailbox_manager.cc
+++ b/gpu/command_buffer/service/mailbox_manager_impl.cc
@@ -1,29 +1,29 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "gpu/command_buffer/service/mailbox_manager.h"
+#include "gpu/command_buffer/service/mailbox_manager_impl.h"
#include <algorithm>
-#include "crypto/random.h"
-#include "gpu/command_buffer/service/mailbox_synchronizer.h"
#include "gpu/command_buffer/service/texture_manager.h"
namespace gpu {
namespace gles2 {
-MailboxManager::MailboxManager()
- : mailbox_to_textures_(std::ptr_fun(&MailboxManager::TargetNameLess)),
- sync_(MailboxSynchronizer::GetInstance()) {
+MailboxManagerImpl::MailboxManagerImpl() {
}
-MailboxManager::~MailboxManager() {
+MailboxManagerImpl::~MailboxManagerImpl() {
DCHECK(mailbox_to_textures_.empty());
DCHECK(textures_to_mailboxes_.empty());
}
-Texture* MailboxManager::ConsumeTexture(unsigned target,
+bool MailboxManagerImpl::UsesSync() {
+ return false;
+}
+
+Texture* MailboxManagerImpl::ConsumeTexture(unsigned target,
const Mailbox& mailbox) {
TargetName target_name(target, mailbox);
MailboxToTextureMap::iterator it =
@@ -31,21 +31,10 @@ Texture* MailboxManager::ConsumeTexture(unsigned target,
if (it != mailbox_to_textures_.end())
return it->second->first;
- if (sync_) {
- // See if it's visible in another mailbox manager, and if so make it visible
- // here too.
- Texture* texture = sync_->CreateTextureFromMailbox(target, mailbox);
- if (texture) {
- InsertTexture(target_name, texture);
- DCHECK_EQ(0U, texture->refs_.size());
- }
- return texture;
- }
-
return NULL;
}
-void MailboxManager::ProduceTexture(unsigned target,
+void MailboxManagerImpl::ProduceTexture(unsigned target,
const Mailbox& mailbox,
Texture* texture) {
TargetName target_name(target, mailbox);
@@ -60,7 +49,8 @@ void MailboxManager::ProduceTexture(unsigned target,
InsertTexture(target_name, texture);
}
-void MailboxManager::InsertTexture(TargetName target_name, Texture* texture) {
+void MailboxManagerImpl::InsertTexture(TargetName target_name,
+ Texture* texture) {
texture->SetMailboxManager(this);
TextureToMailboxMap::iterator texture_it =
textures_to_mailboxes_.insert(std::make_pair(texture, target_name));
@@ -68,7 +58,7 @@ void MailboxManager::InsertTexture(TargetName target_name, Texture* texture) {
DCHECK_EQ(mailbox_to_textures_.size(), textures_to_mailboxes_.size());
}
-void MailboxManager::TextureDeleted(Texture* texture) {
+void MailboxManagerImpl::TextureDeleted(Texture* texture) {
std::pair<TextureToMailboxMap::iterator,
TextureToMailboxMap::iterator> range =
textures_to_mailboxes_.equal_range(texture);
@@ -79,31 +69,6 @@ void MailboxManager::TextureDeleted(Texture* texture) {
}
textures_to_mailboxes_.erase(range.first, range.second);
DCHECK_EQ(mailbox_to_textures_.size(), textures_to_mailboxes_.size());
-
- if (sync_)
- sync_->TextureDeleted(texture);
-}
-
-void MailboxManager::PushTextureUpdates(uint32 sync_point) {
- if (sync_)
- sync_->PushTextureUpdates(this, sync_point);
-}
-
-void MailboxManager::PullTextureUpdates(uint32 sync_point) {
- if (sync_)
- sync_->PullTextureUpdates(this, sync_point);
-}
-
-MailboxManager::TargetName::TargetName(unsigned target, const Mailbox& mailbox)
- : target(target),
- mailbox(mailbox) {
-}
-
-bool MailboxManager::TargetNameLess(const MailboxManager::TargetName& lhs,
- const MailboxManager::TargetName& rhs) {
- if (lhs.target != rhs.target)
- return lhs.target < rhs.target;
- return lhs.mailbox < rhs.mailbox;
}
} // namespace gles2
diff --git a/gpu/command_buffer/service/mailbox_manager_impl.h b/gpu/command_buffer/service/mailbox_manager_impl.h
new file mode 100644
index 0000000..9fd40b3
--- /dev/null
+++ b/gpu/command_buffer/service/mailbox_manager_impl.h
@@ -0,0 +1,65 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GPU_COMMAND_BUFFER_SERVICE_MAILBOX_MANAGER_IMPL_H_
+#define GPU_COMMAND_BUFFER_SERVICE_MAILBOX_MANAGER_IMPL_H_
+
+#include <map>
+#include <utility>
+
+#include "base/memory/linked_ptr.h"
+#include "base/memory/ref_counted.h"
+#include "gpu/command_buffer/common/constants.h"
+#include "gpu/command_buffer/common/mailbox.h"
+#include "gpu/command_buffer/service/mailbox_manager.h"
+#include "gpu/gpu_export.h"
+
+namespace gpu {
+namespace gles2 {
+
+class Texture;
+class TextureManager;
+
+// Manages resources scoped beyond the context or context group level.
+class GPU_EXPORT MailboxManagerImpl : public MailboxManager {
+ public:
+ MailboxManagerImpl();
+
+ // MailboxManager implementation:
+ Texture* ConsumeTexture(unsigned target, const Mailbox& mailbox) override;
+ void ProduceTexture(unsigned target,
+ const Mailbox& mailbox,
+ Texture* texture) override;
+ bool UsesSync() override;
+ void PushTextureUpdates(uint32 sync_point) override {}
+ void PullTextureUpdates(uint32 sync_point) override {}
+ void TextureDeleted(Texture* texture) override;
+
+ protected:
+ ~MailboxManagerImpl() override;
+
+ private:
+ friend class base::RefCounted<MailboxManager>;
+
+ void InsertTexture(TargetName target_name, Texture* texture);
+
+ // This is a bidirectional map between mailbox and textures. We can have
+ // multiple mailboxes per texture, but one texture per mailbox. We keep an
+ // iterator in the MailboxToTextureMap to be able to manage changes to
+ // the TextureToMailboxMap efficiently.
+ typedef std::multimap<Texture*, TargetName> TextureToMailboxMap;
+ typedef std::map<TargetName, TextureToMailboxMap::iterator>
+ MailboxToTextureMap;
+
+ MailboxToTextureMap mailbox_to_textures_;
+ TextureToMailboxMap textures_to_mailboxes_;
+
+ DISALLOW_COPY_AND_ASSIGN(MailboxManagerImpl);
+};
+
+} // namespage gles2
+} // namespace gpu
+
+#endif // GPU_COMMAND_BUFFER_SERVICE_MAILBOX_MANAGER_IMPL_H_
+
diff --git a/gpu/command_buffer/service/mailbox_manager_sync.cc b/gpu/command_buffer/service/mailbox_manager_sync.cc
new file mode 100644
index 0000000..0bf24c8
--- /dev/null
+++ b/gpu/command_buffer/service/mailbox_manager_sync.cc
@@ -0,0 +1,344 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu/command_buffer/service/mailbox_manager_sync.h"
+
+#include <algorithm>
+#include <queue>
+
+#include "base/memory/linked_ptr.h"
+#include "base/synchronization/lock.h"
+#include "gpu/command_buffer/service/texture_manager.h"
+#include "ui/gl/gl_fence.h"
+#include "ui/gl/gl_implementation.h"
+
+#if !defined(OS_MACOSX)
+#include "ui/gl/gl_fence_egl.h"
+#endif
+
+namespace gpu {
+namespace gles2 {
+
+namespace {
+
+bool SkipTextureWorkarounds(const Texture* texture) {
+ // TODO(sievers): crbug.com/352274
+ // Should probably only fail if it already *has* mipmaps, while allowing
+ // incomplete textures here.
+ bool needs_mips =
+ texture->min_filter() != GL_NEAREST && texture->min_filter() != GL_LINEAR;
+ if (texture->target() != GL_TEXTURE_2D || needs_mips || !texture->IsDefined())
+ return true;
+
+ // Skip compositor resources/tile textures.
+ // TODO: Remove this, see crbug.com/399226.
+ if (texture->pool() == GL_TEXTURE_POOL_MANAGED_CHROMIUM)
+ return true;
+
+ return false;
+}
+
+base::LazyInstance<base::Lock> g_lock = LAZY_INSTANCE_INITIALIZER;
+
+typedef std::map<uint32, linked_ptr<gfx::GLFence>> SyncPointToFenceMap;
+base::LazyInstance<SyncPointToFenceMap> g_sync_point_to_fence =
+ LAZY_INSTANCE_INITIALIZER;
+#if !defined(OS_MACOSX)
+base::LazyInstance<std::queue<SyncPointToFenceMap::iterator>> g_sync_points =
+ LAZY_INSTANCE_INITIALIZER;
+#endif
+
+void CreateFenceLocked(uint32 sync_point) {
+ g_lock.Get().AssertAcquired();
+ if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL)
+ return;
+
+#if !defined(OS_MACOSX)
+ std::queue<SyncPointToFenceMap::iterator>& sync_points = g_sync_points.Get();
+ SyncPointToFenceMap& sync_point_to_fence = g_sync_point_to_fence.Get();
+ if (sync_point) {
+ while (!sync_points.empty() &&
+ sync_points.front()->second->HasCompleted()) {
+ sync_point_to_fence.erase(sync_points.front());
+ sync_points.pop();
+ }
+ // Need to use EGL fences since we are likely not in a single share group.
+ linked_ptr<gfx::GLFence> fence(make_linked_ptr(new gfx::GLFenceEGL(true)));
+ if (fence.get()) {
+ std::pair<SyncPointToFenceMap::iterator, bool> result =
+ sync_point_to_fence.insert(std::make_pair(sync_point, fence));
+ DCHECK(result.second);
+ sync_points.push(result.first);
+ }
+ DCHECK(sync_points.size() == sync_point_to_fence.size());
+ }
+#endif
+}
+
+void AcquireFenceLocked(uint32 sync_point) {
+ g_lock.Get().AssertAcquired();
+ SyncPointToFenceMap::iterator fence_it =
+ g_sync_point_to_fence.Get().find(sync_point);
+ if (fence_it != g_sync_point_to_fence.Get().end()) {
+ fence_it->second->ServerWait();
+ }
+}
+
+static const unsigned kNewTextureVersion = 1;
+
+} // anonymous namespace
+
+base::LazyInstance<MailboxManagerSync::TextureGroup::MailboxToGroupMap>
+ MailboxManagerSync::TextureGroup::mailbox_to_group_ =
+ LAZY_INSTANCE_INITIALIZER;
+
+// static
+MailboxManagerSync::TextureGroup*
+MailboxManagerSync::TextureGroup::CreateFromTexture(TargetName name,
+ MailboxManagerSync* manager,
+ Texture* texture) {
+ TextureGroup* group = new TextureGroup();
+ group->AddTexture(manager, texture);
+ group->AddName(name);
+ if (!SkipTextureWorkarounds(texture)) {
+ group->definition_ =
+ TextureDefinition(name.first, texture, kNewTextureVersion, NULL);
+ }
+ return group;
+}
+
+// static
+MailboxManagerSync::TextureGroup* MailboxManagerSync::TextureGroup::FromName(
+ TargetName name) {
+ MailboxToGroupMap::iterator it = mailbox_to_group_.Get().find(name);
+ if (it == mailbox_to_group_.Get().end())
+ return NULL;
+
+ return it->second.get();
+}
+
+MailboxManagerSync::TextureGroup::TextureGroup() {
+}
+
+MailboxManagerSync::TextureGroup::~TextureGroup() {
+}
+
+void MailboxManagerSync::TextureGroup::AddName(TargetName name) {
+ g_lock.Get().AssertAcquired();
+ DCHECK(std::find(names_.begin(), names_.end(), name) == names_.end());
+ names_.push_back(name);
+ DCHECK(mailbox_to_group_.Get().find(name) == mailbox_to_group_.Get().end());
+ mailbox_to_group_.Get()[name] = this;
+}
+
+void MailboxManagerSync::TextureGroup::RemoveName(TargetName name) {
+ g_lock.Get().AssertAcquired();
+ std::vector<TargetName>::iterator names_it =
+ std::find(names_.begin(), names_.end(), name);
+ DCHECK(names_it != names_.end());
+ names_.erase(names_it);
+ MailboxToGroupMap::iterator it = mailbox_to_group_.Get().find(name);
+ DCHECK(it != mailbox_to_group_.Get().end());
+ mailbox_to_group_.Get().erase(it);
+}
+
+void MailboxManagerSync::TextureGroup::AddTexture(MailboxManagerSync* manager,
+ Texture* texture) {
+ g_lock.Get().AssertAcquired();
+ DCHECK(std::find(textures_.begin(), textures_.end(),
+ std::make_pair(manager, texture)) == textures_.end());
+ textures_.push_back(std::make_pair(manager, texture));
+}
+
+bool MailboxManagerSync::TextureGroup::RemoveTexture(
+ MailboxManagerSync* manager,
+ Texture* texture) {
+ g_lock.Get().AssertAcquired();
+ TextureGroup::TextureList::iterator tex_list_it = std::find(
+ textures_.begin(), textures_.end(), std::make_pair(manager, texture));
+ DCHECK(tex_list_it != textures_.end());
+ if (textures_.size() == 1) {
+ // This is the last texture so the group is going away.
+ for (size_t n = 0; n < names_.size(); n++) {
+ const TargetName& target_name = names_[n];
+ MailboxToGroupMap::iterator mbox_it =
+ mailbox_to_group_.Get().find(target_name);
+ DCHECK(mbox_it != mailbox_to_group_.Get().end());
+ DCHECK(mbox_it->second.get() == this);
+ mailbox_to_group_.Get().erase(mbox_it);
+ }
+ return false;
+ } else {
+ textures_.erase(tex_list_it);
+ return true;
+ }
+}
+
+Texture* MailboxManagerSync::TextureGroup::FindTexture(
+ MailboxManagerSync* manager) {
+ g_lock.Get().AssertAcquired();
+ for (TextureGroup::TextureList::iterator it = textures_.begin();
+ it != textures_.end(); it++) {
+ if (it->first == manager)
+ return it->second;
+ }
+ return NULL;
+}
+
+MailboxManagerSync::TextureGroupRef::TextureGroupRef(unsigned version,
+ TextureGroup* group)
+ : version(version), group(group) {
+}
+
+MailboxManagerSync::TextureGroupRef::~TextureGroupRef() {
+}
+
+MailboxManagerSync::MailboxManagerSync() {
+}
+
+MailboxManagerSync::~MailboxManagerSync() {
+ DCHECK_EQ(0U, texture_to_group_.size());
+}
+
+bool MailboxManagerSync::UsesSync() {
+ return true;
+}
+
+Texture* MailboxManagerSync::ConsumeTexture(unsigned target,
+ const Mailbox& mailbox) {
+ base::AutoLock lock(g_lock.Get());
+ TargetName target_name(target, mailbox);
+ TextureGroup* group = TextureGroup::FromName(target_name);
+ if (!group)
+ return NULL;
+
+ // Check if a texture already exists in this share group.
+ Texture* texture = group->FindTexture(this);
+ if (texture)
+ return texture;
+
+ // Otherwise create a new texture.
+ texture = group->GetDefinition().CreateTexture();
+ if (texture) {
+ DCHECK(!SkipTextureWorkarounds(texture));
+ texture->SetMailboxManager(this);
+ group->AddTexture(this, texture);
+
+ TextureGroupRef new_ref =
+ TextureGroupRef(group->GetDefinition().version(), group);
+ texture_to_group_.insert(std::make_pair(texture, new_ref));
+ }
+
+ return texture;
+}
+
+void MailboxManagerSync::ProduceTexture(unsigned target,
+ const Mailbox& mailbox,
+ Texture* texture) {
+ base::AutoLock lock(g_lock.Get());
+ TargetName target_name(target, mailbox);
+
+ TextureToGroupMap::iterator tex_it = texture_to_group_.find(texture);
+ TextureGroup* group_for_mailbox = TextureGroup::FromName(target_name);
+ TextureGroup* group_for_texture = NULL;
+
+ if (tex_it != texture_to_group_.end()) {
+ group_for_texture = tex_it->second.group.get();
+ DCHECK(group_for_texture);
+ if (group_for_mailbox == group_for_texture) {
+ // The texture is already known under this name.
+ return;
+ }
+ }
+
+ if (group_for_mailbox) {
+ // Unlink the mailbox from its current group.
+ group_for_mailbox->RemoveName(target_name);
+ }
+
+ if (group_for_texture) {
+ group_for_texture->AddName(target_name);
+ } else {
+ // This is a new texture, so create a new group.
+ texture->SetMailboxManager(this);
+ group_for_texture =
+ TextureGroup::CreateFromTexture(target_name, this, texture);
+ texture_to_group_.insert(std::make_pair(
+ texture, TextureGroupRef(kNewTextureVersion, group_for_texture)));
+ }
+
+ DCHECK(texture->mailbox_manager_ == this);
+}
+
+void MailboxManagerSync::TextureDeleted(Texture* texture) {
+ base::AutoLock lock(g_lock.Get());
+ TextureToGroupMap::iterator tex_it = texture_to_group_.find(texture);
+ DCHECK(tex_it != texture_to_group_.end());
+ TextureGroup* group_for_texture = tex_it->second.group.get();
+ if (group_for_texture->RemoveTexture(this, texture))
+ UpdateDefinitionLocked(texture, &tex_it->second);
+ texture_to_group_.erase(tex_it);
+}
+
+void MailboxManagerSync::UpdateDefinitionLocked(
+ Texture* texture,
+ TextureGroupRef* group_ref) {
+ g_lock.Get().AssertAcquired();
+
+ if (SkipTextureWorkarounds(texture))
+ return;
+
+ gfx::GLImage* gl_image = texture->GetLevelImage(texture->target(), 0);
+ TextureGroup* group = group_ref->group.get();
+ const TextureDefinition& definition = group->GetDefinition();
+ scoped_refptr<NativeImageBuffer> image_buffer = definition.image();
+
+ // Make sure we don't clobber with an older version
+ if (!definition.IsOlderThan(group_ref->version))
+ return;
+
+ // Also don't push redundant updates. Note that it would break the
+ // versioning.
+ if (definition.Matches(texture))
+ return;
+
+ if (gl_image && !image_buffer->IsClient(gl_image)) {
+ LOG(ERROR) << "MailboxSync: Incompatible attachment";
+ return;
+ }
+
+ group->SetDefinition(TextureDefinition(texture->target(), texture,
+ ++group_ref->version,
+ gl_image ? image_buffer : NULL));
+}
+
+void MailboxManagerSync::PushTextureUpdates(uint32 sync_point) {
+ base::AutoLock lock(g_lock.Get());
+
+ for (TextureToGroupMap::iterator it = texture_to_group_.begin();
+ it != texture_to_group_.end(); it++) {
+ UpdateDefinitionLocked(it->first, &it->second);
+ }
+ CreateFenceLocked(sync_point);
+}
+
+void MailboxManagerSync::PullTextureUpdates(uint32 sync_point) {
+ base::AutoLock lock(g_lock.Get());
+ AcquireFenceLocked(sync_point);
+
+ for (TextureToGroupMap::iterator it = texture_to_group_.begin();
+ it != texture_to_group_.end(); it++) {
+ const TextureDefinition& definition = it->second.group->GetDefinition();
+ Texture* texture = it->first;
+ unsigned& texture_version = it->second.version;
+ if (texture_version == definition.version() ||
+ definition.IsOlderThan(texture_version))
+ continue;
+ texture_version = definition.version();
+ definition.UpdateTexture(texture);
+ }
+}
+
+} // namespace gles2
+} // namespace gpu
diff --git a/gpu/command_buffer/service/mailbox_manager_sync.h b/gpu/command_buffer/service/mailbox_manager_sync.h
new file mode 100644
index 0000000..b2f6b02
--- /dev/null
+++ b/gpu/command_buffer/service/mailbox_manager_sync.h
@@ -0,0 +1,101 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GPU_COMMAND_BUFFER_SERVICE_MAILBOX_MANAGER_SYNC_H_
+#define GPU_COMMAND_BUFFER_SERVICE_MAILBOX_MANAGER_SYNC_H_
+
+#include <map>
+#include <utility>
+
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "gpu/command_buffer/common/constants.h"
+#include "gpu/command_buffer/common/mailbox.h"
+#include "gpu/command_buffer/service/mailbox_manager.h"
+#include "gpu/command_buffer/service/texture_definition.h"
+#include "gpu/gpu_export.h"
+
+namespace gpu {
+namespace gles2 {
+
+class Texture;
+class TextureManager;
+
+// Manages resources scoped beyond the context or context group level
+// and across threads and driver level share groups by synchronizing
+// texture state.
+class GPU_EXPORT MailboxManagerSync : public MailboxManager {
+ public:
+ MailboxManagerSync();
+
+ // MailboxManager implementation:
+ Texture* ConsumeTexture(unsigned target, const Mailbox& mailbox) override;
+ void ProduceTexture(unsigned target,
+ const Mailbox& mailbox,
+ Texture* texture) override;
+ bool UsesSync() override;
+ void PushTextureUpdates(uint32 sync_point) override;
+ void PullTextureUpdates(uint32 sync_point) override;
+ void TextureDeleted(Texture* texture) override;
+
+ private:
+ friend class base::RefCounted<MailboxManager>;
+
+ ~MailboxManagerSync() override;
+
+ class TextureGroup : public base::RefCounted<TextureGroup> {
+ public:
+ static TextureGroup* CreateFromTexture(TargetName name,
+ MailboxManagerSync* manager,
+ Texture* texture);
+ static TextureGroup* FromName(TargetName name);
+
+ void AddName(TargetName name);
+ void RemoveName(TargetName name);
+
+ void AddTexture(MailboxManagerSync* manager, Texture* texture);
+ // Returns true if there are other textures left in the group after removal.
+ bool RemoveTexture(MailboxManagerSync* manager, Texture* texture);
+ Texture* FindTexture(MailboxManagerSync* manager);
+
+ const TextureDefinition& GetDefinition() { return definition_; }
+ void SetDefinition(TextureDefinition definition) {
+ definition_ = definition;
+ }
+
+ private:
+ friend class base::RefCounted<TextureGroup>;
+ TextureGroup();
+ ~TextureGroup();
+
+ typedef std::vector<std::pair<MailboxManagerSync*, Texture*>> TextureList;
+ std::vector<TargetName> names_;
+ TextureList textures_;
+ TextureDefinition definition_;
+
+ typedef std::map<TargetName, scoped_refptr<TextureGroup>>
+ MailboxToGroupMap;
+ static base::LazyInstance<MailboxToGroupMap> mailbox_to_group_;
+ };
+
+ struct TextureGroupRef {
+ TextureGroupRef(unsigned version, TextureGroup* group);
+ ~TextureGroupRef();
+ unsigned version;
+ scoped_refptr<TextureGroup> group;
+ };
+ static void UpdateDefinitionLocked(Texture* texture,
+ TextureGroupRef* group_ref);
+
+ typedef std::map<Texture*, TextureGroupRef> TextureToGroupMap;
+ TextureToGroupMap texture_to_group_;
+
+ DISALLOW_COPY_AND_ASSIGN(MailboxManagerSync);
+};
+
+} // namespage gles2
+} // namespace gpu
+
+#endif // GPU_COMMAND_BUFFER_SERVICE_MAILBOX_MANAGER_SYNC_H_
+
diff --git a/gpu/command_buffer/service/mailbox_manager_unittest.cc b/gpu/command_buffer/service/mailbox_manager_unittest.cc
index 63ffc6d..4304ab3 100644
--- a/gpu/command_buffer/service/mailbox_manager_unittest.cc
+++ b/gpu/command_buffer/service/mailbox_manager_unittest.cc
@@ -2,11 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "gpu/command_buffer/service/mailbox_manager.h"
-
#include "gpu/command_buffer/service/feature_info.h"
#include "gpu/command_buffer/service/gpu_service_test.h"
-#include "gpu/command_buffer/service/mailbox_synchronizer.h"
+#include "gpu/command_buffer/service/mailbox_manager_impl.h"
+#include "gpu/command_buffer/service/mailbox_manager_sync.h"
#include "gpu/command_buffer/service/texture_manager.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gl/gl_context_stub.h"
@@ -20,27 +19,25 @@ using namespace ::testing;
class MailboxManagerTest : public GpuServiceTest {
public:
- MailboxManagerTest() : initialized_synchronizer_(false) {}
+ MailboxManagerTest() {}
virtual ~MailboxManagerTest() {}
protected:
virtual void SetUp() {
GpuServiceTest::SetUp();
feature_info_ = new FeatureInfo;
- manager_ = new MailboxManager;
+ manager_ = new MailboxManagerImpl;
+ DCHECK(!manager_->UsesSync());
}
virtual void SetUpWithSynchronizer() {
GpuServiceTest::SetUp();
- MailboxSynchronizer::Initialize();
- initialized_synchronizer_ = true;
feature_info_ = new FeatureInfo;
- manager_ = new MailboxManager;
+ manager_ = new MailboxManagerSync();
+ DCHECK(manager_->UsesSync());
}
virtual void TearDown() {
- if (initialized_synchronizer_)
- MailboxSynchronizer::Terminate();
GpuServiceTest::TearDown();
}
@@ -88,7 +85,6 @@ class MailboxManagerTest : public GpuServiceTest {
scoped_refptr<MailboxManager> manager_;
private:
- bool initialized_synchronizer_;
scoped_refptr<FeatureInfo> feature_info_;
DISALLOW_COPY_AND_ASSIGN(MailboxManagerTest);
@@ -202,7 +198,7 @@ class MailboxManagerSyncTest : public MailboxManagerTest {
protected:
virtual void SetUp() {
MailboxManagerTest::SetUpWithSynchronizer();
- manager2_ = new MailboxManager;
+ manager2_ = new MailboxManagerSync();
context_ = new gfx::GLContextStub();
surface_ = new gfx::GLSurfaceStub();
context_->MakeCurrent(surface_.get());
@@ -308,6 +304,26 @@ TEST_F(MailboxManagerSyncTest, ProduceSyncDestroy) {
EXPECT_EQ(NULL, manager2_->ConsumeTexture(GL_TEXTURE_2D, name));
}
+TEST_F(MailboxManagerSyncTest, ProduceSyncClobberDestroy) {
+ InSequence sequence;
+
+ Texture* texture = DefineTexture();
+ Mailbox name = Mailbox::Generate();
+
+ manager_->ProduceTexture(GL_TEXTURE_2D, name, texture);
+ manager_->PushTextureUpdates(0);
+
+ // Clobber
+ Texture* old_texture = texture;
+ texture = DefineTexture();
+ manager_->ProduceTexture(GL_TEXTURE_2D, name, texture);
+
+ DestroyTexture(old_texture);
+ DestroyTexture(texture);
+ EXPECT_EQ(NULL, manager_->ConsumeTexture(GL_TEXTURE_2D, name));
+ EXPECT_EQ(NULL, manager2_->ConsumeTexture(GL_TEXTURE_2D, name));
+}
+
// Duplicates a texture into a second manager instance, and then
// makes sure a redefinition becomes visible there too.
TEST_F(MailboxManagerSyncTest, ProduceConsumeResize) {
@@ -465,9 +481,148 @@ TEST_F(MailboxManagerSyncTest, ProduceConsumeBidirectional) {
DestroyTexture(new_texture2);
}
-// TODO: different texture into same mailbox
+// If a texture is shared with another manager instance, but the mailbox
+// is then clobbered with a different texture in the source context, this should
+// disconnect the earlier texture from updates.
+TEST_F(MailboxManagerSyncTest, ProduceAndClobber) {
+ const GLuint kNewTextureId = 1234;
+ InSequence sequence;
+
+ Texture* texture = DefineTexture();
+ Mailbox name = Mailbox::Generate();
+
+ manager_->ProduceTexture(GL_TEXTURE_2D, name, texture);
+ EXPECT_EQ(texture, manager_->ConsumeTexture(GL_TEXTURE_2D, name));
+
+ // Synchronize
+ manager_->PushTextureUpdates(0);
+ manager2_->PullTextureUpdates(0);
+
+ EXPECT_CALL(*gl_, GenTextures(1, _))
+ .WillOnce(SetArgPointee<1>(kNewTextureId));
+ SetupUpdateTexParamExpectations(
+ kNewTextureId, GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT);
+ Texture* new_texture = manager2_->ConsumeTexture(GL_TEXTURE_2D, name);
+ EXPECT_FALSE(new_texture == NULL);
+ EXPECT_NE(texture, new_texture);
+ EXPECT_EQ(kNewTextureId, new_texture->service_id());
+
+ Texture* old_texture = texture;
+ texture = DefineTexture();
+ manager_->ProduceTexture(GL_TEXTURE_2D, name, texture);
+
+ // Make a change to the new texture
+ DCHECK_EQ(static_cast<GLuint>(GL_LINEAR), texture->min_filter());
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR),
+ SetParameter(texture, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
+
+ // Synchronize in both directions - no changes, since it's not shared
+ manager_->PushTextureUpdates(0);
+ manager2_->PullTextureUpdates(0);
+ EXPECT_EQ(static_cast<GLuint>(GL_LINEAR), new_texture->min_filter());
+
+ // Make a change to the previously shared texture
+ DCHECK_EQ(static_cast<GLuint>(GL_LINEAR), old_texture->mag_filter());
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR),
+ SetParameter(old_texture, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
+
+ // Synchronize and expect update
+ manager_->PushTextureUpdates(0);
+ SetupUpdateTexParamExpectations(
+ new_texture->service_id(), GL_LINEAR, GL_NEAREST, GL_REPEAT, GL_REPEAT);
+ manager2_->PullTextureUpdates(0);
+
+ EXPECT_CALL(*gl_, GenTextures(1, _))
+ .WillOnce(SetArgPointee<1>(kNewTextureId));
+ SetupUpdateTexParamExpectations(
+ kNewTextureId, GL_NEAREST, GL_LINEAR, GL_REPEAT, GL_REPEAT);
+ Texture* tmp_texture = manager2_->ConsumeTexture(GL_TEXTURE_2D, name);
+ EXPECT_NE(new_texture, tmp_texture);
+ DestroyTexture(tmp_texture);
+
+ DestroyTexture(old_texture);
+ DestroyTexture(texture);
+ DestroyTexture(new_texture);
-// TODO: same texture, multiple mailboxes
+ EXPECT_EQ(NULL, manager_->ConsumeTexture(GL_TEXTURE_2D, name));
+ EXPECT_EQ(NULL, manager2_->ConsumeTexture(GL_TEXTURE_2D, name));
+}
+
+// Putting the same texture into multiple mailboxes should result in sharing
+// only a single texture also within a synchronized manager instance.
+TEST_F(MailboxManagerSyncTest, SharedThroughMultipleMailboxes) {
+ const GLuint kNewTextureId = 1234;
+ InSequence sequence;
+
+ Texture* texture = DefineTexture();
+ Mailbox name1 = Mailbox::Generate();
+ Mailbox name2 = Mailbox::Generate();
+
+ manager_->ProduceTexture(GL_TEXTURE_2D, name1, texture);
+
+ // Share
+ manager_->PushTextureUpdates(0);
+ EXPECT_CALL(*gl_, GenTextures(1, _))
+ .WillOnce(SetArgPointee<1>(kNewTextureId));
+ manager2_->PullTextureUpdates(0);
+ SetupUpdateTexParamExpectations(
+ kNewTextureId, GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT);
+ Texture* new_texture = manager2_->ConsumeTexture(GL_TEXTURE_2D, name1);
+ EXPECT_EQ(kNewTextureId, new_texture->service_id());
+
+ manager_->ProduceTexture(GL_TEXTURE_2D, name2, texture);
+
+ // Synchronize
+ manager_->PushTextureUpdates(0);
+ manager2_->PullTextureUpdates(0);
+
+ // name2 should return the same texture
+ EXPECT_EQ(new_texture, manager2_->ConsumeTexture(GL_TEXTURE_2D, name2));
+
+ // Even after destroying the source texture, the original mailbox should
+ // still exist.
+ DestroyTexture(texture);
+ EXPECT_EQ(new_texture, manager2_->ConsumeTexture(GL_TEXTURE_2D, name1));
+ DestroyTexture(new_texture);
+}
+
+// A: produce texture1 into M, B: consume into new_texture
+// B: produce texture2 into M, A: produce texture1 into M
+// B: consume M should return new_texture
+TEST_F(MailboxManagerSyncTest, ProduceBothWays) {
+ const GLuint kNewTextureId = 1234;
+ InSequence sequence;
+
+ Texture* texture1 = DefineTexture();
+ Texture* texture2 = DefineTexture();
+ Mailbox name = Mailbox::Generate();
+
+ manager_->ProduceTexture(GL_TEXTURE_2D, name, texture1);
+
+ // Share
+ manager_->PushTextureUpdates(0);
+ EXPECT_CALL(*gl_, GenTextures(1, _))
+ .WillOnce(SetArgPointee<1>(kNewTextureId));
+ SetupUpdateTexParamExpectations(
+ kNewTextureId, GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT);
+ Texture* new_texture = manager2_->ConsumeTexture(GL_TEXTURE_2D, name);
+ EXPECT_EQ(kNewTextureId, new_texture->service_id());
+
+ // Clobber
+ manager2_->ProduceTexture(GL_TEXTURE_2D, name, texture2);
+ manager_->ProduceTexture(GL_TEXTURE_2D, name, texture1);
+
+ // Synchronize manager -> manager2
+ manager_->PushTextureUpdates(0);
+ manager2_->PullTextureUpdates(0);
+
+ // name should return the original texture, and not texture2 or a new one.
+ EXPECT_EQ(new_texture, manager2_->ConsumeTexture(GL_TEXTURE_2D, name));
+
+ DestroyTexture(texture1);
+ DestroyTexture(texture2);
+ DestroyTexture(new_texture);
+}
// TODO: Produce incomplete texture
diff --git a/gpu/command_buffer/service/mailbox_synchronizer.cc b/gpu/command_buffer/service/mailbox_synchronizer.cc
deleted file mode 100644
index 81a2793..0000000
--- a/gpu/command_buffer/service/mailbox_synchronizer.cc
+++ /dev/null
@@ -1,276 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "gpu/command_buffer/service/mailbox_synchronizer.h"
-
-#include "base/bind.h"
-#include "gpu/command_buffer/service/mailbox_manager.h"
-#include "gpu/command_buffer/service/texture_manager.h"
-#include "ui/gl/gl_fence.h"
-#include "ui/gl/gl_implementation.h"
-
-#if !defined(OS_MACOSX)
-#include "ui/gl/gl_fence_egl.h"
-#endif
-
-namespace gpu {
-namespace gles2 {
-
-namespace {
-
-MailboxSynchronizer* g_instance = NULL;
-
-} // anonymous namespace
-
-// static
-bool MailboxSynchronizer::Initialize() {
- DCHECK(!g_instance);
- DCHECK(gfx::GetGLImplementation() != gfx::kGLImplementationNone)
- << "GL bindings not initialized";
- switch (gfx::GetGLImplementation()) {
- case gfx::kGLImplementationMockGL:
- break;
- case gfx::kGLImplementationEGLGLES2:
-#if !defined(OS_MACOSX)
- {
- if (!gfx::g_driver_egl.ext.b_EGL_KHR_image_base ||
- !gfx::g_driver_egl.ext.b_EGL_KHR_gl_texture_2D_image ||
- !gfx::g_driver_gl.ext.b_GL_OES_EGL_image ||
- !gfx::g_driver_egl.ext.b_EGL_KHR_fence_sync) {
- LOG(WARNING) << "MailboxSync not supported due to missing EGL "
- "image/fence support";
- return false;
- }
- }
- break;
-#endif
- default:
- NOTREACHED();
- return false;
- }
- g_instance = new MailboxSynchronizer;
- return true;
-}
-
-// static
-void MailboxSynchronizer::Terminate() {
- DCHECK(g_instance);
- delete g_instance;
- g_instance = NULL;
-}
-
-// static
-MailboxSynchronizer* MailboxSynchronizer::GetInstance() {
- return g_instance;
-}
-
-MailboxSynchronizer::TargetName::TargetName(unsigned target,
- const Mailbox& mailbox)
- : target(target), mailbox(mailbox) {}
-
-MailboxSynchronizer::TextureGroup::TextureGroup(
- const TextureDefinition& definition)
- : definition(definition) {}
-
-MailboxSynchronizer::TextureGroup::~TextureGroup() {}
-
-MailboxSynchronizer::TextureVersion::TextureVersion(
- linked_ptr<TextureGroup> group)
- : version(group->definition.version()), group(group) {}
-
-MailboxSynchronizer::TextureVersion::~TextureVersion() {}
-
-MailboxSynchronizer::MailboxSynchronizer() {}
-
-MailboxSynchronizer::~MailboxSynchronizer() {
- DCHECK_EQ(0U, textures_.size());
-}
-
-void MailboxSynchronizer::ReassociateMailboxLocked(
- const TargetName& target_name,
- TextureGroup* group) {
- lock_.AssertAcquired();
- for (TextureMap::iterator it = textures_.begin(); it != textures_.end();
- it++) {
- std::set<TargetName>::iterator mb_it =
- it->second.group->mailboxes.find(target_name);
- if (it->second.group != group &&
- mb_it != it->second.group->mailboxes.end()) {
- it->second.group->mailboxes.erase(mb_it);
- }
- }
- group->mailboxes.insert(target_name);
-}
-
-linked_ptr<MailboxSynchronizer::TextureGroup>
-MailboxSynchronizer::GetGroupForMailboxLocked(const TargetName& target_name) {
- lock_.AssertAcquired();
- for (TextureMap::iterator it = textures_.begin(); it != textures_.end();
- it++) {
- std::set<TargetName>::const_iterator mb_it =
- it->second.group->mailboxes.find(target_name);
- if (mb_it != it->second.group->mailboxes.end())
- return it->second.group;
- }
- return make_linked_ptr<MailboxSynchronizer::TextureGroup>(NULL);
-}
-
-Texture* MailboxSynchronizer::CreateTextureFromMailbox(unsigned target,
- const Mailbox& mailbox) {
- base::AutoLock lock(lock_);
- TargetName target_name(target, mailbox);
- linked_ptr<TextureGroup> group = GetGroupForMailboxLocked(target_name);
- if (group.get()) {
- Texture* new_texture = group->definition.CreateTexture();
- if (new_texture)
- textures_.insert(std::make_pair(new_texture, TextureVersion(group)));
- return new_texture;
- }
-
- return NULL;
-}
-
-void MailboxSynchronizer::TextureDeleted(Texture* texture) {
- base::AutoLock lock(lock_);
- TextureMap::iterator it = textures_.find(texture);
- if (it != textures_.end()) {
- // TODO: We could avoid the update if this was the last ref.
- UpdateTextureLocked(it->first, it->second);
- textures_.erase(it);
- }
-}
-
-void MailboxSynchronizer::PushTextureUpdates(MailboxManager* manager,
- uint32 sync_point) {
- base::AutoLock lock(lock_);
- for (MailboxManager::MailboxToTextureMap::const_iterator texture_it =
- manager->mailbox_to_textures_.begin();
- texture_it != manager->mailbox_to_textures_.end();
- texture_it++) {
- TargetName target_name(texture_it->first.target, texture_it->first.mailbox);
- Texture* texture = texture_it->second->first;
- // TODO(sievers): crbug.com/352274
- // Should probably only fail if it already *has* mipmaps, while allowing
- // incomplete textures here. Also reconsider how to fail otherwise.
- bool needs_mips = texture->min_filter() != GL_NEAREST &&
- texture->min_filter() != GL_LINEAR;
- if (target_name.target != GL_TEXTURE_2D || needs_mips)
- continue;
-
- TextureMap::iterator it = textures_.find(texture);
- if (it != textures_.end()) {
- TextureVersion& texture_version = it->second;
- TextureGroup* group = texture_version.group.get();
- std::set<TargetName>::const_iterator mb_it =
- group->mailboxes.find(target_name);
- if (mb_it == group->mailboxes.end()) {
- // We previously did not associate this texture with the given mailbox.
- // Unlink other texture groups from the mailbox.
- ReassociateMailboxLocked(target_name, group);
- }
- UpdateTextureLocked(texture, texture_version);
-
- } else {
- // Skip compositor resources/tile textures.
- // TODO: Remove this, see crbug.com/399226.
- if (texture->pool() == GL_TEXTURE_POOL_MANAGED_CHROMIUM)
- continue;
-
- linked_ptr<TextureGroup> group = make_linked_ptr(new TextureGroup(
- TextureDefinition(target_name.target, texture, 1, NULL)));
-
- // Unlink other textures from this mailbox in case the name is not new.
- ReassociateMailboxLocked(target_name, group.get());
- textures_.insert(std::make_pair(texture, TextureVersion(group)));
- }
- }
-
- CreateFenceLocked(sync_point);
-}
-
-void MailboxSynchronizer::CreateFenceLocked(uint32 sync_point) {
- lock_.AssertAcquired();
- if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL)
- return;
-
-#if !defined(OS_MACOSX)
- if (sync_point) {
- while (!sync_points_.empty() &&
- sync_points_.front()->second->HasCompleted()) {
- sync_point_to_fence_.erase(sync_points_.front());
- sync_points_.pop();
- }
- // Need to use EGL fences since we are likely not in a single share group.
- linked_ptr<gfx::GLFence> fence(make_linked_ptr(new gfx::GLFenceEGL(true)));
- if (fence.get()) {
- std::pair<SyncPointToFenceMap::iterator, bool> result =
- sync_point_to_fence_.insert(std::make_pair(sync_point, fence));
- DCHECK(result.second);
- sync_points_.push(result.first);
- }
- DCHECK(sync_points_.size() == sync_point_to_fence_.size());
- }
-#endif
-}
-
-void MailboxSynchronizer::UpdateTextureLocked(Texture* texture,
- TextureVersion& texture_version) {
- lock_.AssertAcquired();
- gfx::GLImage* gl_image = texture->GetLevelImage(texture->target(), 0);
- TextureGroup* group = texture_version.group.get();
- scoped_refptr<NativeImageBuffer> image_buffer = group->definition.image();
-
- // Make sure we don't clobber with an older version
- if (!group->definition.IsOlderThan(texture_version.version))
- return;
-
- // Also don't push redundant updates. Note that it would break the
- // versioning.
- if (group->definition.Matches(texture))
- return;
-
- if (gl_image && !image_buffer->IsClient(gl_image)) {
- LOG(ERROR) << "MailboxSync: Incompatible attachment";
- return;
- }
-
- group->definition = TextureDefinition(texture->target(),
- texture,
- ++texture_version.version,
- gl_image ? image_buffer : NULL);
-}
-
-void MailboxSynchronizer::AcquireFenceLocked(uint32 sync_point) {
- lock_.AssertAcquired();
- SyncPointToFenceMap::iterator fence_it =
- sync_point_to_fence_.find(sync_point);
- if (fence_it != sync_point_to_fence_.end()) {
- fence_it->second->ServerWait();
- }
-}
-
-void MailboxSynchronizer::PullTextureUpdates(MailboxManager* manager,
- uint32 sync_point) {
- base::AutoLock lock(lock_);
- AcquireFenceLocked(sync_point);
-
- for (MailboxManager::MailboxToTextureMap::const_iterator texture_it =
- manager->mailbox_to_textures_.begin();
- texture_it != manager->mailbox_to_textures_.end();
- texture_it++) {
- Texture* texture = texture_it->second->first;
- TextureMap::iterator it = textures_.find(texture);
- if (it != textures_.end()) {
- TextureDefinition& definition = it->second.group->definition;
- if (it->second.version == definition.version() ||
- definition.IsOlderThan(it->second.version))
- continue;
- it->second.version = definition.version();
- definition.UpdateTexture(texture);
- }
- }
-}
-
-} // namespace gles2
-} // namespace gpu
diff --git a/gpu/command_buffer/service/mailbox_synchronizer.h b/gpu/command_buffer/service/mailbox_synchronizer.h
deleted file mode 100644
index 3ddb9d0..0000000
--- a/gpu/command_buffer/service/mailbox_synchronizer.h
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef GPU_COMMAND_BUFFER_SERVICE_MAILBOX_SYNCHRONIZER_H_
-#define GPU_COMMAND_BUFFER_SERVICE_MAILBOX_SYNCHRONIZER_H_
-
-#include "gpu/command_buffer/common/mailbox.h"
-
-#include <map>
-#include <queue>
-#include <set>
-
-#include "base/memory/linked_ptr.h"
-#include "base/synchronization/lock.h"
-#include "gpu/command_buffer/service/texture_definition.h"
-#include "gpu/gpu_export.h"
-
-namespace gfx {
-class GLFence;
-}
-
-namespace gpu {
-namespace gles2 {
-
-class MailboxManager;
-class Texture;
-
-// A thread-safe proxy that can be used to emulate texture sharing across
-// share-groups.
-class MailboxSynchronizer {
- public:
- ~MailboxSynchronizer();
-
- GPU_EXPORT static bool Initialize();
- GPU_EXPORT static void Terminate();
- static MailboxSynchronizer* GetInstance();
-
- // Create a texture from a globally visible mailbox.
- Texture* CreateTextureFromMailbox(unsigned target, const Mailbox& mailbox);
-
- void PushTextureUpdates(MailboxManager* manager, uint32 sync_point);
- void PullTextureUpdates(MailboxManager* manager, uint32 sync_point);
-
- void TextureDeleted(Texture* texture);
-
- private:
- MailboxSynchronizer();
-
- struct TargetName {
- TargetName(unsigned target, const Mailbox& mailbox);
- bool operator<(const TargetName& rhs) const {
- return memcmp(this, &rhs, sizeof(rhs)) < 0;
- }
- bool operator!=(const TargetName& rhs) const {
- return memcmp(this, &rhs, sizeof(rhs)) != 0;
- }
- bool operator==(const TargetName& rhs) const {
- return !operator!=(rhs);
- }
- unsigned target;
- Mailbox mailbox;
- };
-
- base::Lock lock_;
-
- struct TextureGroup {
- explicit TextureGroup(const TextureDefinition& definition);
- ~TextureGroup();
-
- TextureDefinition definition;
- std::set<TargetName> mailboxes;
- private:
- DISALLOW_COPY_AND_ASSIGN(TextureGroup);
- };
-
- struct TextureVersion {
- explicit TextureVersion(linked_ptr<TextureGroup> group);
- ~TextureVersion();
-
- unsigned int version;
- linked_ptr<TextureGroup> group;
- };
- typedef std::map<Texture*, TextureVersion> TextureMap;
- TextureMap textures_;
-
- linked_ptr<TextureGroup> GetGroupForMailboxLocked(
- const TargetName& target_name);
- void ReassociateMailboxLocked(
- const TargetName& target_name,
- TextureGroup* group);
- void UpdateTextureLocked(Texture* texture, TextureVersion& texture_version);
- void CreateFenceLocked(uint32 sync_point);
- void AcquireFenceLocked(uint32 sync_point);
-
- typedef std::map<uint32, linked_ptr<gfx::GLFence> > SyncPointToFenceMap;
- SyncPointToFenceMap sync_point_to_fence_;
- std::queue<SyncPointToFenceMap::iterator> sync_points_;
-
- DISALLOW_COPY_AND_ASSIGN(MailboxSynchronizer);
-};
-
-} // namespage gles2
-} // namespace gpu
-
-#endif // GPU_COMMAND_BUFFER_SERVICE_MAILBOX_SYNCHRONIZER_H_
-
diff --git a/gpu/command_buffer/service/texture_definition.cc b/gpu/command_buffer/service/texture_definition.cc
index abde56a..58c8ef3 100644
--- a/gpu/command_buffer/service/texture_definition.cc
+++ b/gpu/command_buffer/service/texture_definition.cc
@@ -278,6 +278,17 @@ TextureDefinition::LevelInfo::LevelInfo(GLenum target,
TextureDefinition::LevelInfo::~LevelInfo() {}
+TextureDefinition::TextureDefinition()
+ : version_(0),
+ target_(0),
+ min_filter_(0),
+ mag_filter_(0),
+ wrap_s_(0),
+ wrap_t_(0),
+ usage_(0),
+ immutable_(true) {
+}
+
TextureDefinition::TextureDefinition(
GLenum target,
Texture* texture,
diff --git a/gpu/command_buffer/service/texture_definition.h b/gpu/command_buffer/service/texture_definition.h
index cb21abd..fff0f90 100644
--- a/gpu/command_buffer/service/texture_definition.h
+++ b/gpu/command_buffer/service/texture_definition.h
@@ -40,6 +40,7 @@ class NativeImageBuffer : public base::RefCountedThreadSafe<NativeImageBuffer> {
// the underlying image buffer(s).
class TextureDefinition {
public:
+ TextureDefinition();
TextureDefinition(GLenum target,
Texture* texture,
unsigned int version,
@@ -55,7 +56,7 @@ class TextureDefinition {
}
bool Matches(const Texture* texture) const;
- scoped_refptr<NativeImageBuffer> image() { return image_buffer_; }
+ scoped_refptr<NativeImageBuffer> image() const { return image_buffer_; }
private:
struct LevelInfo {
diff --git a/gpu/command_buffer/service/texture_manager.h b/gpu/command_buffer/service/texture_manager.h
index 25bc2ff..3ab5467 100644
--- a/gpu/command_buffer/service/texture_manager.h
+++ b/gpu/command_buffer/service/texture_manager.h
@@ -165,7 +165,8 @@ class GPU_EXPORT Texture {
void OnDidModifyPixels();
private:
- friend class MailboxManager;
+ friend class MailboxManagerImpl;
+ friend class MailboxManagerSync;
friend class MailboxManagerTest;
friend class TextureDefinition;
friend class TextureManager;
diff --git a/gpu/command_buffer/tests/gl_manager.cc b/gpu/command_buffer/tests/gl_manager.cc
index bb2acbd..ffbc573 100644
--- a/gpu/command_buffer/tests/gl_manager.cc
+++ b/gpu/command_buffer/tests/gl_manager.cc
@@ -24,7 +24,7 @@
#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
#include "gpu/command_buffer/service/gpu_scheduler.h"
#include "gpu/command_buffer/service/image_manager.h"
-#include "gpu/command_buffer/service/mailbox_manager.h"
+#include "gpu/command_buffer/service/mailbox_manager_impl.h"
#include "gpu/command_buffer/service/memory_tracking.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/gpu_memory_buffer.h"
@@ -174,7 +174,7 @@ void GLManager::Initialize(const GLManager::Options& options) {
}
mailbox_manager_ =
- mailbox_manager ? mailbox_manager : new gles2::MailboxManager;
+ mailbox_manager ? mailbox_manager : new gles2::MailboxManagerImpl;
share_group_ =
share_group ? share_group : new gfx::GLShareGroup;
diff --git a/gpu/command_buffer_service.gypi b/gpu/command_buffer_service.gypi
index 2640dad..4814cb2 100644
--- a/gpu/command_buffer_service.gypi
+++ b/gpu/command_buffer_service.gypi
@@ -93,10 +93,11 @@
'command_buffer/service/in_process_command_buffer.h',
'command_buffer/service/logger.cc',
'command_buffer/service/logger.h',
- 'command_buffer/service/mailbox_manager.cc',
'command_buffer/service/mailbox_manager.h',
- 'command_buffer/service/mailbox_synchronizer.cc',
- 'command_buffer/service/mailbox_synchronizer.h',
+ 'command_buffer/service/mailbox_manager_impl.cc',
+ 'command_buffer/service/mailbox_manager_impl.h',
+ 'command_buffer/service/mailbox_manager_sync.cc',
+ 'command_buffer/service/mailbox_manager_sync.h',
'command_buffer/service/memory_program_cache.h',
'command_buffer/service/memory_program_cache.cc',
'command_buffer/service/mocks.h',
diff --git a/mojo/services/native_viewport/DEPS b/mojo/services/native_viewport/DEPS
index 60e2518..4a4ec52 100644
--- a/mojo/services/native_viewport/DEPS
+++ b/mojo/services/native_viewport/DEPS
@@ -1,6 +1,7 @@
include_rules = [
"+cc/surfaces",
"+gpu/command_buffer/service/mailbox_manager.h",
+ "+gpu/command_buffer/service/mailbox_manager_impl.h",
"+mojo/application",
"+mojo/converters/geometry",
"+mojo/converters/input_events",
diff --git a/mojo/services/native_viewport/main.cc b/mojo/services/native_viewport/main.cc
index 1cd936f..a0de653 100644
--- a/mojo/services/native_viewport/main.cc
+++ b/mojo/services/native_viewport/main.cc
@@ -4,7 +4,7 @@
#include "base/macros.h"
#include "base/message_loop/message_loop.h"
-#include "gpu/command_buffer/service/mailbox_manager.h"
+#include "gpu/command_buffer/service/mailbox_manager_impl.h"
#include "mojo/application/application_runner_chromium.h"
#include "mojo/public/c/system/main.h"
#include "mojo/public/cpp/application/application_connection.h"
@@ -26,7 +26,7 @@ class NativeViewportAppDelegate
public:
NativeViewportAppDelegate()
: share_group_(new gfx::GLShareGroup),
- mailbox_manager_(new gpu::gles2::MailboxManager),
+ mailbox_manager_(new gpu::gles2::MailboxManagerImpl),
is_headless_(false) {}
~NativeViewportAppDelegate() override {}
diff --git a/mojo/shell/context.cc b/mojo/shell/context.cc
index 3c21980..215ed7b 100644
--- a/mojo/shell/context.cc
+++ b/mojo/shell/context.cc
@@ -15,7 +15,7 @@
#include "base/memory/scoped_vector.h"
#include "base/strings/string_split.h"
#include "build/build_config.h"
-#include "gpu/command_buffer/service/mailbox_manager.h"
+#include "gpu/command_buffer/service/mailbox_manager_impl.h"
#include "mojo/application_manager/application_loader.h"
#include "mojo/application_manager/application_manager.h"
#include "mojo/application_manager/background_shell_application_loader.h"
@@ -114,7 +114,7 @@ class Context::NativeViewportApplicationLoader
public:
NativeViewportApplicationLoader()
: share_group_(new gfx::GLShareGroup),
- mailbox_manager_(new gpu::gles2::MailboxManager) {}
+ mailbox_manager_(new gpu::gles2::MailboxManagerImpl) {}
virtual ~NativeViewportApplicationLoader() {}
private: