diff options
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: |