Update from chromium https://crrev.com/301315
This updates from chromium commit
060d7dc875cc41f46ab264181d1d622d02c3c8b7 aka commit position 301315. The
following changes from earlier rolls are included:
*) Remove gpu_media.patch, no longer needed thanks to
https://crrev.com/301048
*) Added skia_build.patch to resolve blink dependency added by
https://crrev.com/301105
*) Applied mojo changes for https://crrev.com/301165
TBR=ben@chromium.org
Review URL: https://codereview.chromium.org/681713002
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 @@
"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 @@
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/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 01d20c7..ea5fbdd 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -3580,7 +3580,7 @@
UpdateParentTextureInfo();
}
mailbox_manager()->ProduceTexture(
- GL_TEXTURE_2D, mailbox, offscreen_saved_color_texture_info_->texture());
+ mailbox, offscreen_saved_color_texture_info_->texture());
}
bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
@@ -10546,7 +10546,7 @@
return;
}
- group_->mailbox_manager()->ProduceTexture(target, mailbox, produced);
+ group_->mailbox_manager()->ProduceTexture(mailbox, produced);
}
void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target,
@@ -10574,7 +10574,7 @@
"glConsumeTextureCHROMIUM", "unknown texture for target");
return;
}
- Texture* texture = group_->mailbox_manager()->ConsumeTexture(target, mailbox);
+ Texture* texture = group_->mailbox_manager()->ConsumeTexture(mailbox);
if (!texture) {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION,
@@ -10660,7 +10660,7 @@
"glCreateAndConsumeTextureCHROMIUM", "client id already in use");
return;
}
- Texture* texture = group_->mailbox_manager()->ConsumeTexture(target, mailbox);
+ Texture* texture = group_->mailbox_manager()->ConsumeTexture(mailbox);
if (!texture) {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION,
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 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 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 @@
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.cc b/gpu/command_buffer/service/mailbox_manager.cc
deleted file mode 100644
index b4d6e79..0000000
--- a/gpu/command_buffer/service/mailbox_manager.cc
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright (c) 2012 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 <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()) {
-}
-
-MailboxManager::~MailboxManager() {
- DCHECK(mailbox_to_textures_.empty());
- DCHECK(textures_to_mailboxes_.empty());
-}
-
-Texture* MailboxManager::ConsumeTexture(unsigned target,
- const Mailbox& mailbox) {
- TargetName target_name(target, mailbox);
- MailboxToTextureMap::iterator it =
- mailbox_to_textures_.find(target_name);
- 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,
- const Mailbox& mailbox,
- Texture* texture) {
- TargetName target_name(target, mailbox);
- MailboxToTextureMap::iterator it = mailbox_to_textures_.find(target_name);
- if (it != mailbox_to_textures_.end()) {
- if (it->second->first == texture)
- return;
- TextureToMailboxMap::iterator texture_it = it->second;
- mailbox_to_textures_.erase(it);
- textures_to_mailboxes_.erase(texture_it);
- }
- InsertTexture(target_name, texture);
-}
-
-void MailboxManager::InsertTexture(TargetName target_name, Texture* texture) {
- texture->SetMailboxManager(this);
- TextureToMailboxMap::iterator texture_it =
- textures_to_mailboxes_.insert(std::make_pair(texture, target_name));
- mailbox_to_textures_.insert(std::make_pair(target_name, texture_it));
- DCHECK_EQ(mailbox_to_textures_.size(), textures_to_mailboxes_.size());
-}
-
-void MailboxManager::TextureDeleted(Texture* texture) {
- std::pair<TextureToMailboxMap::iterator,
- TextureToMailboxMap::iterator> range =
- textures_to_mailboxes_.equal_range(texture);
- for (TextureToMailboxMap::iterator it = range.first;
- it != range.second; ++it) {
- size_t count = mailbox_to_textures_.erase(it->second);
- DCHECK(count == 1);
- }
- 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
-} // namespace gpu
diff --git a/gpu/command_buffer/service/mailbox_manager.h b/gpu/command_buffer/service/mailbox_manager.h
index a00b965..8b53ce4 100644
--- a/gpu/command_buffer/service/mailbox_manager.h
+++ b/gpu/command_buffer/service/mailbox_manager.h
@@ -1,85 +1,48 @@
-// 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(const Mailbox& mailbox) = 0;
// Put the texture into the named mailbox.
- void ProduceTexture(unsigned target,
- const Mailbox& mailbox,
- Texture* texture);
+ virtual void ProduceTexture(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);
+ virtual void TextureDeleted(Texture* texture) = 0;
+
+ protected:
+ MailboxManager() {}
+ virtual ~MailboxManager() {}
private:
friend class base::RefCounted<MailboxManager>;
- friend class MailboxSynchronizer;
-
- ~MailboxManager();
-
- struct TargetName {
- TargetName(unsigned target, const Mailbox& mailbox);
- unsigned target;
- Mailbox mailbox;
- };
- void InsertTexture(TargetName target_name, Texture* texture);
-
- 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_;
DISALLOW_COPY_AND_ASSIGN(MailboxManager);
};
+
} // namespage gles2
} // namespace gpu
diff --git a/gpu/command_buffer/service/mailbox_manager_impl.cc b/gpu/command_buffer/service/mailbox_manager_impl.cc
new file mode 100644
index 0000000..db7b4c2
--- /dev/null
+++ b/gpu/command_buffer/service/mailbox_manager_impl.cc
@@ -0,0 +1,71 @@
+// 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_impl.h"
+
+#include <algorithm>
+
+#include "gpu/command_buffer/service/texture_manager.h"
+
+namespace gpu {
+namespace gles2 {
+
+MailboxManagerImpl::MailboxManagerImpl() {
+}
+
+MailboxManagerImpl::~MailboxManagerImpl() {
+ DCHECK(mailbox_to_textures_.empty());
+ DCHECK(textures_to_mailboxes_.empty());
+}
+
+bool MailboxManagerImpl::UsesSync() {
+ return false;
+}
+
+Texture* MailboxManagerImpl::ConsumeTexture(const Mailbox& mailbox) {
+ MailboxToTextureMap::iterator it =
+ mailbox_to_textures_.find(mailbox);
+ if (it != mailbox_to_textures_.end())
+ return it->second->first;
+
+ return NULL;
+}
+
+void MailboxManagerImpl::ProduceTexture(const Mailbox& mailbox,
+ Texture* texture) {
+ MailboxToTextureMap::iterator it = mailbox_to_textures_.find(mailbox);
+ if (it != mailbox_to_textures_.end()) {
+ if (it->second->first == texture)
+ return;
+ TextureToMailboxMap::iterator texture_it = it->second;
+ mailbox_to_textures_.erase(it);
+ textures_to_mailboxes_.erase(texture_it);
+ }
+ InsertTexture(mailbox, texture);
+}
+
+void MailboxManagerImpl::InsertTexture(const Mailbox& mailbox,
+ Texture* texture) {
+ texture->SetMailboxManager(this);
+ TextureToMailboxMap::iterator texture_it =
+ textures_to_mailboxes_.insert(std::make_pair(texture, mailbox));
+ mailbox_to_textures_.insert(std::make_pair(mailbox, texture_it));
+ DCHECK_EQ(mailbox_to_textures_.size(), textures_to_mailboxes_.size());
+}
+
+void MailboxManagerImpl::TextureDeleted(Texture* texture) {
+ std::pair<TextureToMailboxMap::iterator,
+ TextureToMailboxMap::iterator> range =
+ textures_to_mailboxes_.equal_range(texture);
+ for (TextureToMailboxMap::iterator it = range.first;
+ it != range.second; ++it) {
+ size_t count = mailbox_to_textures_.erase(it->second);
+ DCHECK(count == 1);
+ }
+ textures_to_mailboxes_.erase(range.first, range.second);
+ DCHECK_EQ(mailbox_to_textures_.size(), textures_to_mailboxes_.size());
+}
+
+} // namespace gles2
+} // namespace gpu
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..5ea906e
--- /dev/null
+++ b/gpu/command_buffer/service/mailbox_manager_impl.h
@@ -0,0 +1,63 @@
+// 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(const Mailbox& mailbox) override;
+ void ProduceTexture(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(const Mailbox& mailbox, 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*, Mailbox> TextureToMailboxMap;
+ typedef std::map<Mailbox, 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..65376af
--- /dev/null
+++ b/gpu/command_buffer/service/mailbox_manager_sync.cc
@@ -0,0 +1,339 @@
+// 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(const Mailbox& name,
+ MailboxManagerSync* manager,
+ Texture* texture) {
+ TextureGroup* group = new TextureGroup();
+ group->AddTexture(manager, texture);
+ group->AddName(name);
+ if (!SkipTextureWorkarounds(texture)) {
+ group->definition_ =
+ TextureDefinition(texture, kNewTextureVersion, NULL);
+ }
+ return group;
+}
+
+// static
+MailboxManagerSync::TextureGroup* MailboxManagerSync::TextureGroup::FromName(
+ const Mailbox& 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(const Mailbox& 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(const Mailbox& name) {
+ g_lock.Get().AssertAcquired();
+ std::vector<Mailbox>::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 Mailbox& name = names_[n];
+ MailboxToGroupMap::iterator mbox_it =
+ mailbox_to_group_.Get().find(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(const Mailbox& mailbox) {
+ base::AutoLock lock(g_lock.Get());
+ TextureGroup* group = TextureGroup::FromName(mailbox);
+ 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(const Mailbox& mailbox,
+ Texture* texture) {
+ base::AutoLock lock(g_lock.Get());
+
+ TextureToGroupMap::iterator tex_it = texture_to_group_.find(texture);
+ TextureGroup* group_for_mailbox = TextureGroup::FromName(mailbox);
+ 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(mailbox);
+ }
+
+ if (group_for_texture) {
+ group_for_texture->AddName(mailbox);
+ } else {
+ // This is a new texture, so create a new group.
+ texture->SetMailboxManager(this);
+ group_for_texture =
+ TextureGroup::CreateFromTexture(mailbox, 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, ++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..4727f3b
--- /dev/null
+++ b/gpu/command_buffer/service/mailbox_manager_sync.h
@@ -0,0 +1,99 @@
+// 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(const Mailbox& mailbox) override;
+ void ProduceTexture(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(const Mailbox& name,
+ MailboxManagerSync* manager,
+ Texture* texture);
+ static TextureGroup* FromName(const Mailbox& name);
+
+ void AddName(const Mailbox& name);
+ void RemoveName(const Mailbox& 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<Mailbox> names_;
+ TextureList textures_;
+ TextureDefinition definition_;
+
+ typedef std::map<Mailbox, 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..1aea4c5 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 @@
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 @@
scoped_refptr<MailboxManager> manager_;
private:
- bool initialized_synchronizer_;
scoped_refptr<FeatureInfo> feature_info_;
DISALLOW_COPY_AND_ASSIGN(MailboxManagerTest);
@@ -99,18 +95,15 @@
Texture* texture = CreateTexture();
Mailbox name = Mailbox::Generate();
- manager_->ProduceTexture(0, name, texture);
- EXPECT_EQ(texture, manager_->ConsumeTexture(0, name));
+ manager_->ProduceTexture(name, texture);
+ EXPECT_EQ(texture, manager_->ConsumeTexture(name));
// We can consume multiple times.
- EXPECT_EQ(texture, manager_->ConsumeTexture(0, name));
-
- // Wrong target should fail the consume.
- EXPECT_EQ(NULL, manager_->ConsumeTexture(1, name));
+ EXPECT_EQ(texture, manager_->ConsumeTexture(name));
// Destroy should cleanup the mailbox.
DestroyTexture(texture);
- EXPECT_EQ(NULL, manager_->ConsumeTexture(0, name));
+ EXPECT_EQ(NULL, manager_->ConsumeTexture(name));
}
// Tests behavior with multiple produce on the same texture.
@@ -119,25 +112,25 @@
Mailbox name1 = Mailbox::Generate();
- manager_->ProduceTexture(0, name1, texture);
- EXPECT_EQ(texture, manager_->ConsumeTexture(0, name1));
+ manager_->ProduceTexture(name1, texture);
+ EXPECT_EQ(texture, manager_->ConsumeTexture(name1));
// Can produce a second time with the same mailbox.
- manager_->ProduceTexture(0, name1, texture);
- EXPECT_EQ(texture, manager_->ConsumeTexture(0, name1));
+ manager_->ProduceTexture(name1, texture);
+ EXPECT_EQ(texture, manager_->ConsumeTexture(name1));
// Can produce again, with a different mailbox.
Mailbox name2 = Mailbox::Generate();
- manager_->ProduceTexture(0, name2, texture);
+ manager_->ProduceTexture(name2, texture);
// Still available under all mailboxes.
- EXPECT_EQ(texture, manager_->ConsumeTexture(0, name1));
- EXPECT_EQ(texture, manager_->ConsumeTexture(0, name2));
+ EXPECT_EQ(texture, manager_->ConsumeTexture(name1));
+ EXPECT_EQ(texture, manager_->ConsumeTexture(name2));
// Destroy should cleanup all mailboxes.
DestroyTexture(texture);
- EXPECT_EQ(NULL, manager_->ConsumeTexture(0, name1));
- EXPECT_EQ(NULL, manager_->ConsumeTexture(0, name2));
+ EXPECT_EQ(NULL, manager_->ConsumeTexture(name1));
+ EXPECT_EQ(NULL, manager_->ConsumeTexture(name2));
}
// Tests behavior with multiple produce on the same mailbox with different
@@ -148,20 +141,20 @@
Mailbox name = Mailbox::Generate();
- manager_->ProduceTexture(0, name, texture1);
- EXPECT_EQ(texture1, manager_->ConsumeTexture(0, name));
+ manager_->ProduceTexture(name, texture1);
+ EXPECT_EQ(texture1, manager_->ConsumeTexture(name));
// Can produce a second time with the same mailbox, but different texture.
- manager_->ProduceTexture(0, name, texture2);
- EXPECT_EQ(texture2, manager_->ConsumeTexture(0, name));
+ manager_->ProduceTexture(name, texture2);
+ EXPECT_EQ(texture2, manager_->ConsumeTexture(name));
// Destroying the texture that's under no mailbox shouldn't have an effect.
DestroyTexture(texture1);
- EXPECT_EQ(texture2, manager_->ConsumeTexture(0, name));
+ EXPECT_EQ(texture2, manager_->ConsumeTexture(name));
// Destroying the texture that's bound should clean up.
DestroyTexture(texture2);
- EXPECT_EQ(NULL, manager_->ConsumeTexture(0, name));
+ EXPECT_EQ(NULL, manager_->ConsumeTexture(name));
}
TEST_F(MailboxManagerTest, ProduceMultipleTextureMailbox) {
@@ -171,23 +164,23 @@
Mailbox name2 = Mailbox::Generate();
// Put texture1 on name1 and name2.
- manager_->ProduceTexture(0, name1, texture1);
- manager_->ProduceTexture(0, name2, texture1);
- EXPECT_EQ(texture1, manager_->ConsumeTexture(0, name1));
- EXPECT_EQ(texture1, manager_->ConsumeTexture(0, name2));
+ manager_->ProduceTexture(name1, texture1);
+ manager_->ProduceTexture(name2, texture1);
+ EXPECT_EQ(texture1, manager_->ConsumeTexture(name1));
+ EXPECT_EQ(texture1, manager_->ConsumeTexture(name2));
// Put texture2 on name2.
- manager_->ProduceTexture(0, name2, texture2);
- EXPECT_EQ(texture1, manager_->ConsumeTexture(0, name1));
- EXPECT_EQ(texture2, manager_->ConsumeTexture(0, name2));
+ manager_->ProduceTexture(name2, texture2);
+ EXPECT_EQ(texture1, manager_->ConsumeTexture(name1));
+ EXPECT_EQ(texture2, manager_->ConsumeTexture(name2));
// Destroy texture1, shouldn't affect name2.
DestroyTexture(texture1);
- EXPECT_EQ(NULL, manager_->ConsumeTexture(0, name1));
- EXPECT_EQ(texture2, manager_->ConsumeTexture(0, name2));
+ EXPECT_EQ(NULL, manager_->ConsumeTexture(name1));
+ EXPECT_EQ(texture2, manager_->ConsumeTexture(name2));
DestroyTexture(texture2);
- EXPECT_EQ(NULL, manager_->ConsumeTexture(0, name2));
+ EXPECT_EQ(NULL, manager_->ConsumeTexture(name2));
}
const GLsizei kMaxTextureWidth = 64;
@@ -202,7 +195,7 @@
protected:
virtual void SetUp() {
MailboxManagerTest::SetUpWithSynchronizer();
- manager2_ = new MailboxManager;
+ manager2_ = new MailboxManagerSync();
context_ = new gfx::GLContextStub();
surface_ = new gfx::GLSurfaceStub();
context_->MakeCurrent(surface_.get());
@@ -282,12 +275,12 @@
Mailbox name = Mailbox::Generate();
InSequence sequence;
- manager_->ProduceTexture(GL_TEXTURE_2D, name, texture);
- EXPECT_EQ(texture, manager_->ConsumeTexture(GL_TEXTURE_2D, name));
+ manager_->ProduceTexture(name, texture);
+ EXPECT_EQ(texture, manager_->ConsumeTexture(name));
DestroyTexture(texture);
- EXPECT_EQ(NULL, manager_->ConsumeTexture(GL_TEXTURE_2D, name));
- EXPECT_EQ(NULL, manager2_->ConsumeTexture(GL_TEXTURE_2D, name));
+ EXPECT_EQ(NULL, manager_->ConsumeTexture(name));
+ EXPECT_EQ(NULL, manager2_->ConsumeTexture(name));
}
TEST_F(MailboxManagerSyncTest, ProduceSyncDestroy) {
@@ -296,16 +289,36 @@
Texture* texture = DefineTexture();
Mailbox name = Mailbox::Generate();
- manager_->ProduceTexture(GL_TEXTURE_2D, name, texture);
- EXPECT_EQ(texture, manager_->ConsumeTexture(GL_TEXTURE_2D, name));
+ manager_->ProduceTexture(name, texture);
+ EXPECT_EQ(texture, manager_->ConsumeTexture(name));
// Synchronize
manager_->PushTextureUpdates(0);
manager2_->PullTextureUpdates(0);
DestroyTexture(texture);
- EXPECT_EQ(NULL, manager_->ConsumeTexture(GL_TEXTURE_2D, name));
- EXPECT_EQ(NULL, manager2_->ConsumeTexture(GL_TEXTURE_2D, name));
+ EXPECT_EQ(NULL, manager_->ConsumeTexture(name));
+ EXPECT_EQ(NULL, manager2_->ConsumeTexture(name));
+}
+
+TEST_F(MailboxManagerSyncTest, ProduceSyncClobberDestroy) {
+ InSequence sequence;
+
+ Texture* texture = DefineTexture();
+ Mailbox name = Mailbox::Generate();
+
+ manager_->ProduceTexture(name, texture);
+ manager_->PushTextureUpdates(0);
+
+ // Clobber
+ Texture* old_texture = texture;
+ texture = DefineTexture();
+ manager_->ProduceTexture(name, texture);
+
+ DestroyTexture(old_texture);
+ DestroyTexture(texture);
+ EXPECT_EQ(NULL, manager_->ConsumeTexture(name));
+ EXPECT_EQ(NULL, manager2_->ConsumeTexture(name));
}
// Duplicates a texture into a second manager instance, and then
@@ -317,8 +330,8 @@
Texture* texture = DefineTexture();
Mailbox name = Mailbox::Generate();
- manager_->ProduceTexture(GL_TEXTURE_2D, name, texture);
- EXPECT_EQ(texture, manager_->ConsumeTexture(GL_TEXTURE_2D, name));
+ manager_->ProduceTexture(name, texture);
+ EXPECT_EQ(texture, manager_->ConsumeTexture(name));
// Synchronize
manager_->PushTextureUpdates(0);
@@ -328,7 +341,7 @@
.WillOnce(SetArgPointee<1>(kNewTextureId));
SetupUpdateTexParamExpectations(
kNewTextureId, GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT);
- Texture* new_texture = manager2_->ConsumeTexture(GL_TEXTURE_2D, name);
+ Texture* new_texture = manager2_->ConsumeTexture(name);
EXPECT_FALSE(new_texture == NULL);
EXPECT_NE(texture, new_texture);
EXPECT_EQ(kNewTextureId, new_texture->service_id());
@@ -378,7 +391,7 @@
DestroyTexture(texture);
// Should be still around since there is a ref from manager2
- EXPECT_EQ(new_texture, manager2_->ConsumeTexture(GL_TEXTURE_2D, name));
+ EXPECT_EQ(new_texture, manager2_->ConsumeTexture(name));
// The last change to the texture should be visible without a sync point (i.e.
// push).
@@ -388,8 +401,8 @@
EXPECT_EQ(64, height);
DestroyTexture(new_texture);
- EXPECT_EQ(NULL, manager_->ConsumeTexture(GL_TEXTURE_2D, name));
- EXPECT_EQ(NULL, manager2_->ConsumeTexture(GL_TEXTURE_2D, name));
+ EXPECT_EQ(NULL, manager_->ConsumeTexture(name));
+ EXPECT_EQ(NULL, manager2_->ConsumeTexture(name));
}
// Makes sure changes are correctly published even when updates are
@@ -406,8 +419,8 @@
Texture* new_texture1 = NULL;
Texture* new_texture2 = NULL;
- manager_->ProduceTexture(GL_TEXTURE_2D, name1, texture1);
- manager2_->ProduceTexture(GL_TEXTURE_2D, name2, texture2);
+ manager_->ProduceTexture(name1, texture1);
+ manager2_->ProduceTexture(name2, texture2);
// Make visible.
manager_->PushTextureUpdates(0);
@@ -422,12 +435,12 @@
.WillOnce(SetArgPointee<1>(kNewTextureId1));
SetupUpdateTexParamExpectations(
kNewTextureId1, GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT);
- new_texture1 = manager2_->ConsumeTexture(GL_TEXTURE_2D, name1);
+ new_texture1 = manager2_->ConsumeTexture(name1);
EXPECT_CALL(*gl_, GenTextures(1, _))
.WillOnce(SetArgPointee<1>(kNewTextureId2));
SetupUpdateTexParamExpectations(
kNewTextureId2, GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT);
- new_texture2 = manager_->ConsumeTexture(GL_TEXTURE_2D, name2);
+ new_texture2 = manager_->ConsumeTexture(name2);
}
EXPECT_EQ(kNewTextureId1, new_texture1->service_id());
EXPECT_EQ(kNewTextureId2, new_texture2->service_id());
@@ -465,9 +478,148 @@
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;
-// TODO: same texture, multiple mailboxes
+ Texture* texture = DefineTexture();
+ Mailbox name = Mailbox::Generate();
+
+ manager_->ProduceTexture(name, texture);
+ EXPECT_EQ(texture, manager_->ConsumeTexture(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(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(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(name);
+ EXPECT_NE(new_texture, tmp_texture);
+ DestroyTexture(tmp_texture);
+
+ DestroyTexture(old_texture);
+ DestroyTexture(texture);
+ DestroyTexture(new_texture);
+
+ EXPECT_EQ(NULL, manager_->ConsumeTexture(name));
+ EXPECT_EQ(NULL, manager2_->ConsumeTexture(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(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(name1);
+ EXPECT_EQ(kNewTextureId, new_texture->service_id());
+
+ manager_->ProduceTexture(name2, texture);
+
+ // Synchronize
+ manager_->PushTextureUpdates(0);
+ manager2_->PullTextureUpdates(0);
+
+ // name2 should return the same texture
+ EXPECT_EQ(new_texture, manager2_->ConsumeTexture(name2));
+
+ // Even after destroying the source texture, the original mailbox should
+ // still exist.
+ DestroyTexture(texture);
+ EXPECT_EQ(new_texture, manager2_->ConsumeTexture(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(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(name);
+ EXPECT_EQ(kNewTextureId, new_texture->service_id());
+
+ // Clobber
+ manager2_->ProduceTexture(name, texture2);
+ manager_->ProduceTexture(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(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..b0cafe2 100644
--- a/gpu/command_buffer/service/texture_definition.cc
+++ b/gpu/command_buffer/service/texture_definition.cc
@@ -278,13 +278,23 @@
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,
unsigned int version,
const scoped_refptr<NativeImageBuffer>& image_buffer)
: version_(version),
- target_(target),
+ target_(texture->target()),
image_buffer_(image_buffer.get()
? image_buffer
: NativeImageBuffer::Create(texture->service_id())),
@@ -306,7 +316,7 @@
new GLImageSync(image_buffer_,
gfx::Size(first_face.level_infos[0].width,
first_face.level_infos[0].height)));
- texture->SetLevelImage(NULL, target, 0, gl_image.get());
+ texture->SetLevelImage(NULL, target_, 0, gl_image.get());
// TODO: all levels
level_infos_.clear();
diff --git a/gpu/command_buffer/service/texture_definition.h b/gpu/command_buffer/service/texture_definition.h
index cb21abd..ff891fc 100644
--- a/gpu/command_buffer/service/texture_definition.h
+++ b/gpu/command_buffer/service/texture_definition.h
@@ -40,8 +40,8 @@
// the underlying image buffer(s).
class TextureDefinition {
public:
- TextureDefinition(GLenum target,
- Texture* texture,
+ TextureDefinition();
+ TextureDefinition(Texture* texture,
unsigned int version,
const scoped_refptr<NativeImageBuffer>& image);
virtual ~TextureDefinition();
@@ -55,7 +55,7 @@
}
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 @@
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 @@
}
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/gpu/config/DEPS b/gpu/config/DEPS
index 7c0ee4b..39b325a 100644
--- a/gpu/config/DEPS
+++ b/gpu/config/DEPS
@@ -1,5 +1,4 @@
include_rules = [
"+third_party/libxml", # For parsing WinSAT results files.
"+third_party/libXNVCtrl", # For NV driver version query.
- "+media/video", # For VideoEncodeAccelerator::SupportedProfile.
]
diff --git a/gpu/config/gpu_info.cc b/gpu/config/gpu_info.cc
index f560dcb..f1f67ce 100644
--- a/gpu/config/gpu_info.cc
+++ b/gpu/config/gpu_info.cc
@@ -17,6 +17,19 @@
enumerator->EndGPUDevice();
}
+void EnumerateVideoEncodeAcceleratorSupportedProfile(
+ gpu::GPUInfo::Enumerator* enumerator,
+ const gpu::VideoEncodeAcceleratorSupportedProfile profile) {
+ enumerator->BeginVideoEncodeAcceleratorSupportedProfile();
+ enumerator->AddInt("profile", profile.profile);
+ enumerator->AddInt("maxResolutionWidth", profile.max_resolution.width());
+ enumerator->AddInt("maxResolutionHeight", profile.max_resolution.height());
+ enumerator->AddInt("maxFramerateNumerator", profile.max_framerate_numerator);
+ enumerator->AddInt("maxFramerateDenominator",
+ profile.max_framerate_denominator);
+ enumerator->EndVideoEncodeAcceleratorSupportedProfile();
+}
+
} // namespace
namespace gpu {
@@ -88,6 +101,8 @@
CollectInfoResult dx_diagnostics_info_state;
DxDiagNode dx_diagnostics;
#endif
+ std::vector<VideoEncodeAcceleratorSupportedProfile>
+ video_encode_accelerator_supported_profiles;
};
// If this assert fails then most likely something below needs to be updated.
@@ -142,6 +157,12 @@
#if defined(OS_WIN)
enumerator->AddInt("DxDiagnosticsInfoState", dx_diagnostics_info_state);
#endif
+ // TODO(kbr): add dx_diagnostics on Windows.
+ for (size_t ii = 0; ii < video_encode_accelerator_supported_profiles.size();
+ ++ii) {
+ EnumerateVideoEncodeAcceleratorSupportedProfile(
+ enumerator, video_encode_accelerator_supported_profiles[ii]);
+ }
enumerator->EndAuxAttributes();
}
diff --git a/gpu/config/gpu_info.h b/gpu/config/gpu_info.h
index 8f5479b..7c92d3a 100644
--- a/gpu/config/gpu_info.h
+++ b/gpu/config/gpu_info.h
@@ -18,6 +18,7 @@
#include "gpu/config/dx_diag_node.h"
#include "gpu/config/gpu_performance_stats.h"
#include "gpu/gpu_export.h"
+#include "ui/gfx/geometry/size.h"
namespace gpu {
@@ -34,6 +35,34 @@
kCollectInfoFatalFailure = 3
};
+// Video profile. This *must* match media::VideoCodecProfile.
+enum VideoCodecProfile {
+ VIDEO_CODEC_PROFILE_UNKNOWN = -1,
+ VIDEO_CODEC_PROFILE_MIN = VIDEO_CODEC_PROFILE_UNKNOWN,
+ H264PROFILE_BASELINE = 0,
+ H264PROFILE_MAIN = 1,
+ H264PROFILE_EXTENDED = 2,
+ H264PROFILE_HIGH = 3,
+ H264PROFILE_HIGH10PROFILE = 4,
+ H264PROFILE_HIGH422PROFILE = 5,
+ H264PROFILE_HIGH444PREDICTIVEPROFILE = 6,
+ H264PROFILE_SCALABLEBASELINE = 7,
+ H264PROFILE_SCALABLEHIGH = 8,
+ H264PROFILE_STEREOHIGH = 9,
+ H264PROFILE_MULTIVIEWHIGH = 10,
+ VP8PROFILE_ANY = 11,
+ VP9PROFILE_ANY = 12,
+ VIDEO_CODEC_PROFILE_MAX = VP9PROFILE_ANY,
+};
+
+// Specification of an encoding profile supported by a hardware encoder.
+struct GPU_EXPORT VideoEncodeAcceleratorSupportedProfile {
+ VideoCodecProfile profile;
+ gfx::Size max_resolution;
+ uint32 max_framerate_numerator;
+ uint32 max_framerate_denominator;
+};
+
struct GPU_EXPORT GPUInfo {
struct GPU_EXPORT GPUDevice {
GPUDevice();
@@ -177,6 +206,8 @@
DxDiagNode dx_diagnostics;
#endif
+ std::vector<VideoEncodeAcceleratorSupportedProfile>
+ video_encode_accelerator_supported_profiles;
// Note: when adding new members, please remember to update EnumerateFields
// in gpu_info.cc.
@@ -201,7 +232,7 @@
virtual void BeginGPUDevice() = 0;
virtual void EndGPUDevice() = 0;
- // Markers indicating that a VideoEncodeAccelerator::SupportedProfile is
+ // Markers indicating that a VideoEncodeAcceleratorSupportedProfile is
// being described.
virtual void BeginVideoEncodeAcceleratorSupportedProfile() = 0;
virtual void EndVideoEncodeAcceleratorSupportedProfile() = 0;
diff --git a/gpu/config/gpu_info_collector.cc b/gpu/config/gpu_info_collector.cc
index 78dfe22..5d25546 100644
--- a/gpu/config/gpu_info_collector.cc
+++ b/gpu/config/gpu_info_collector.cc
@@ -156,6 +156,8 @@
basic_gpu_info->direct_rendering = context_gpu_info.direct_rendering;
basic_gpu_info->context_info_state = context_gpu_info.context_info_state;
basic_gpu_info->initialization_time = context_gpu_info.initialization_time;
+ basic_gpu_info->video_encode_accelerator_supported_profiles =
+ context_gpu_info.video_encode_accelerator_supported_profiles;
}
} // namespace gpu
diff --git a/gpu/config/gpu_info_unittest.cc b/gpu/config/gpu_info_unittest.cc
index 48d476f..71d4e5c 100644
--- a/gpu/config/gpu_info_unittest.cc
+++ b/gpu/config/gpu_info_unittest.cc
@@ -32,6 +32,7 @@
#if defined(OS_WIN)
EXPECT_EQ(gpu_info.dx_diagnostics_info_state, kCollectInfoNone);
#endif
+ EXPECT_EQ(gpu_info.video_encode_accelerator_supported_profiles.size(), 0u);
}
} // namespace gpu