diff options
author | tobiasjs <tobiasjs@chromium.org> | 2015-08-21 17:39:06 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-08-22 00:39:38 +0000 |
commit | fc199b47cb5b74c9f2ccf3a6316fc9b7009c6904 (patch) | |
tree | ddebbbd1b94efa885c5e2656760911fe6460fba5 | |
parent | 926097380c61018aa2d5dfc99299f592ccfa5738 (diff) | |
download | chromium_src-fc199b47cb5b74c9f2ccf3a6316fc9b7009c6904.zip chromium_src-fc199b47cb5b74c9f2ccf3a6316fc9b7009c6904.tar.gz chromium_src-fc199b47cb5b74c9f2ccf3a6316fc9b7009c6904.tar.bz2 |
Fix crash caused by concurrent access to framebuffer_combo_complete_map_.
The current implementation of framebuffer completeness testing uses a single global hash_map as a cache. This leads to races in WebView when GPU and render threads try to access the cache concurrently.
BUG=518858
Review URL: https://codereview.chromium.org/1278333003
Cr-Commit-Position: refs/heads/master@{#344940}
23 files changed, 209 insertions, 141 deletions
diff --git a/android_webview/browser/deferred_gpu_command_service.cc b/android_webview/browser/deferred_gpu_command_service.cc index 8e0591e..ef0542c 100644 --- a/android_webview/browser/deferred_gpu_command_service.cc +++ b/android_webview/browser/deferred_gpu_command_service.cc @@ -10,6 +10,7 @@ #include "base/synchronization/lock.h" #include "base/trace_event/trace_event.h" #include "content/public/browser/android/synchronous_compositor.h" +#include "gpu/command_buffer/service/framebuffer_completeness_cache.h" #include "gpu/command_buffer/service/shader_translator_cache.h" #include "gpu/command_buffer/service/sync_point_manager.h" @@ -153,6 +154,15 @@ DeferredGpuCommandService::shader_translator_cache() { return shader_translator_cache_; } +scoped_refptr<gpu::gles2::FramebufferCompletenessCache> +DeferredGpuCommandService::framebuffer_completeness_cache() { + if (!framebuffer_completeness_cache_.get()) { + framebuffer_completeness_cache_ = + new gpu::gles2::FramebufferCompletenessCache; + } + return framebuffer_completeness_cache_; +} + gpu::SyncPointManager* DeferredGpuCommandService::sync_point_manager() { return sync_point_manager_.get(); } diff --git a/android_webview/browser/deferred_gpu_command_service.h b/android_webview/browser/deferred_gpu_command_service.h index c7f230d..395fd68 100644 --- a/android_webview/browser/deferred_gpu_command_service.h +++ b/android_webview/browser/deferred_gpu_command_service.h @@ -46,6 +46,8 @@ class DeferredGpuCommandService bool UseVirtualizedGLContexts() override; scoped_refptr<gpu::gles2::ShaderTranslatorCache> shader_translator_cache() override; + scoped_refptr<gpu::gles2::FramebufferCompletenessCache> + framebuffer_completeness_cache() override; gpu::SyncPointManager* sync_point_manager() override; void RunTasks(); @@ -76,6 +78,8 @@ class DeferredGpuCommandService scoped_ptr<gpu::SyncPointManager> sync_point_manager_; scoped_refptr<gpu::gles2::ShaderTranslatorCache> shader_translator_cache_; + scoped_refptr<gpu::gles2::FramebufferCompletenessCache> + framebuffer_completeness_cache_; DISALLOW_COPY_AND_ASSIGN(DeferredGpuCommandService); }; diff --git a/components/view_manager/gles2/command_buffer_driver.cc b/components/view_manager/gles2/command_buffer_driver.cc index 53a428a..77d2da2 100644 --- a/components/view_manager/gles2/command_buffer_driver.cc +++ b/components/view_manager/gles2/command_buffer_driver.cc @@ -96,8 +96,9 @@ bool CommandBufferDriver::DoInitialize( scoped_refptr<gpu::gles2::ContextGroup> context_group = new gpu::gles2::ContextGroup( gpu_state_->mailbox_manager(), new GpuMemoryTracker, - new gpu::gles2::ShaderTranslatorCache, nullptr, nullptr, nullptr, - bind_generates_resource); + new gpu::gles2::ShaderTranslatorCache, + new gpu::gles2::FramebufferCompletenessCache, nullptr, nullptr, + nullptr, bind_generates_resource); command_buffer_.reset( new gpu::CommandBufferService(context_group->transfer_buffer_manager())); diff --git a/components/view_manager/gles2/command_buffer_local.cc b/components/view_manager/gles2/command_buffer_local.cc index 694bc05..86ab863 100644 --- a/components/view_manager/gles2/command_buffer_local.cc +++ b/components/view_manager/gles2/command_buffer_local.cc @@ -76,8 +76,9 @@ bool CommandBufferLocal::Initialize() { scoped_refptr<gpu::gles2::ContextGroup> context_group = new gpu::gles2::ContextGroup( gpu_state_->mailbox_manager(), new gles2::GpuMemoryTracker, - new gpu::gles2::ShaderTranslatorCache, nullptr, nullptr, nullptr, - bind_generates_resource); + new gpu::gles2::ShaderTranslatorCache, + new gpu::gles2::FramebufferCompletenessCache, nullptr, nullptr, + nullptr, bind_generates_resource); command_buffer_.reset( new gpu::CommandBufferService(context_group->transfer_buffer_manager())); diff --git a/content/common/gpu/gpu_channel_manager.cc b/content/common/gpu/gpu_channel_manager.cc index 040deb9..21672e2 100644 --- a/content/common/gpu/gpu_channel_manager.cc +++ b/content/common/gpu/gpu_channel_manager.cc @@ -79,6 +79,14 @@ GpuChannelManager::shader_translator_cache() { return shader_translator_cache_.get(); } +gpu::gles2::FramebufferCompletenessCache* +GpuChannelManager::framebuffer_completeness_cache() { + if (!framebuffer_completeness_cache_.get()) + framebuffer_completeness_cache_ = + new gpu::gles2::FramebufferCompletenessCache; + return framebuffer_completeness_cache_.get(); +} + void GpuChannelManager::RemoveChannel(int client_id) { Send(new GpuHostMsg_DestroyChannel(client_id)); gpu_channels_.erase(client_id); diff --git a/content/common/gpu/gpu_channel_manager.h b/content/common/gpu/gpu_channel_manager.h index f90a76d..a611a94 100644 --- a/content/common/gpu/gpu_channel_manager.h +++ b/content/common/gpu/gpu_channel_manager.h @@ -35,6 +35,7 @@ namespace gpu { class SyncPointManager; union ValueState; namespace gles2 { +class FramebufferCompletenessCache; class MailboxManager; class ProgramCache; class ShaderTranslatorCache; @@ -92,6 +93,7 @@ class CONTENT_EXPORT GpuChannelManager : public IPC::Listener, gpu::gles2::ProgramCache* program_cache(); gpu::gles2::ShaderTranslatorCache* shader_translator_cache(); + gpu::gles2::FramebufferCompletenessCache* framebuffer_completeness_cache(); GpuMemoryManager* gpu_memory_manager() { return &gpu_memory_manager_; } @@ -157,6 +159,8 @@ class CONTENT_EXPORT GpuChannelManager : public IPC::Listener, gpu::SyncPointManager* sync_point_manager_; scoped_ptr<gpu::gles2::ProgramCache> program_cache_; scoped_refptr<gpu::gles2::ShaderTranslatorCache> shader_translator_cache_; + scoped_refptr<gpu::gles2::FramebufferCompletenessCache> + framebuffer_completeness_cache_; scoped_refptr<gfx::GLSurface> default_offscreen_surface_; GpuMemoryBufferFactory* const gpu_memory_buffer_factory_; IPC::SyncChannel* channel_; diff --git a/content/common/gpu/gpu_command_buffer_stub.cc b/content/common/gpu/gpu_command_buffer_stub.cc index c1b0127..d410eb7 100644 --- a/content/common/gpu/gpu_command_buffer_stub.cc +++ b/content/common/gpu/gpu_command_buffer_stub.cc @@ -209,12 +209,10 @@ GpuCommandBufferStub::GpuCommandBufferStub( attrib_parser.bind_generates_resource); } else { context_group_ = new gpu::gles2::ContextGroup( - mailbox_manager, - new GpuCommandBufferMemoryTracker(channel), + mailbox_manager, new GpuCommandBufferMemoryTracker(channel), channel_->gpu_channel_manager()->shader_translator_cache(), - NULL, - subscription_ref_set, - pending_valuebuffer_state, + channel_->gpu_channel_manager()->framebuffer_completeness_cache(), NULL, + subscription_ref_set, pending_valuebuffer_state, attrib_parser.bind_generates_resource); } diff --git a/gpu/command_buffer/service/BUILD.gn b/gpu/command_buffer/service/BUILD.gn index 7a2e2b2..1acdb1b 100644 --- a/gpu/command_buffer/service/BUILD.gn +++ b/gpu/command_buffer/service/BUILD.gn @@ -59,6 +59,8 @@ source_set("service_sources") { "error_state.h", "feature_info.cc", "feature_info.h", + "framebuffer_completeness_cache.cc", + "framebuffer_completeness_cache.h", "framebuffer_manager.cc", "framebuffer_manager.h", "gl_context_virtual.cc", diff --git a/gpu/command_buffer/service/context_group.cc b/gpu/command_buffer/service/context_group.cc index ca8b335..530488e 100644 --- a/gpu/command_buffer/service/context_group.cc +++ b/gpu/command_buffer/service/context_group.cc @@ -30,6 +30,8 @@ ContextGroup::ContextGroup( const scoped_refptr<MailboxManager>& mailbox_manager, const scoped_refptr<MemoryTracker>& memory_tracker, const scoped_refptr<ShaderTranslatorCache>& shader_translator_cache, + const scoped_refptr<FramebufferCompletenessCache>& + framebuffer_completeness_cache, const scoped_refptr<FeatureInfo>& feature_info, const scoped_refptr<SubscriptionRefSet>& subscription_ref_set, const scoped_refptr<ValueStateMap>& pending_valuebuffer_state, @@ -38,6 +40,17 @@ ContextGroup::ContextGroup( mailbox_manager_(mailbox_manager), memory_tracker_(memory_tracker), shader_translator_cache_(shader_translator_cache), +#if defined(OS_MACOSX) + // Framebuffer completeness is not cacheable on OS X because of dynamic + // graphics switching. + // http://crbug.com/180876 + // TODO(tobiasjs): determine whether GPU switching is possible + // programmatically, rather than just hardcoding this behaviour + // for OS X. + framebuffer_completeness_cache_(NULL), +#else + framebuffer_completeness_cache_(framebuffer_completeness_cache), +#endif subscription_ref_set_(subscription_ref_set), pending_valuebuffer_state_(pending_valuebuffer_state), enforce_gl_minimums_( @@ -154,8 +167,9 @@ bool ContextGroup::Initialize( buffer_manager_.reset( new BufferManager(memory_tracker_.get(), feature_info_.get())); - framebuffer_manager_.reset(new FramebufferManager( - max_draw_buffers_, max_color_attachments_, context_type)); + framebuffer_manager_.reset( + new FramebufferManager(max_draw_buffers_, max_color_attachments_, + context_type, framebuffer_completeness_cache_)); renderbuffer_manager_.reset(new RenderbufferManager( memory_tracker_.get(), max_renderbuffer_size, max_samples, feature_info_.get())); diff --git a/gpu/command_buffer/service/context_group.h b/gpu/command_buffer/service/context_group.h index ea62823..7625970 100644 --- a/gpu/command_buffer/service/context_group.h +++ b/gpu/command_buffer/service/context_group.h @@ -14,6 +14,7 @@ #include "gpu/command_buffer/common/constants.h" #include "gpu/command_buffer/common/gles2_cmd_format.h" #include "gpu/command_buffer/service/feature_info.h" +#include "gpu/command_buffer/service/framebuffer_completeness_cache.h" #include "gpu/command_buffer/service/shader_translator_cache.h" #include "gpu/gpu_export.h" @@ -56,6 +57,8 @@ class GPU_EXPORT ContextGroup : public base::RefCounted<ContextGroup> { const scoped_refptr<MailboxManager>& mailbox_manager, const scoped_refptr<MemoryTracker>& memory_tracker, const scoped_refptr<ShaderTranslatorCache>& shader_translator_cache, + const scoped_refptr<FramebufferCompletenessCache>& + framebuffer_completeness_cache, const scoped_refptr<FeatureInfo>& feature_info, const scoped_refptr<SubscriptionRefSet>& subscription_ref_set, const scoped_refptr<ValueStateMap>& pending_valuebuffer_state, @@ -84,6 +87,10 @@ class GPU_EXPORT ContextGroup : public base::RefCounted<ContextGroup> { return shader_translator_cache_.get(); } + FramebufferCompletenessCache* framebuffer_completeness_cache() const { + return framebuffer_completeness_cache_.get(); + } + bool bind_generates_resource() { return bind_generates_resource_; } @@ -257,6 +264,7 @@ class GPU_EXPORT ContextGroup : public base::RefCounted<ContextGroup> { scoped_refptr<MailboxManager> mailbox_manager_; scoped_refptr<MemoryTracker> memory_tracker_; scoped_refptr<ShaderTranslatorCache> shader_translator_cache_; + scoped_refptr<FramebufferCompletenessCache> framebuffer_completeness_cache_; scoped_refptr<TransferBufferManagerInterface> transfer_buffer_manager_; scoped_refptr<SubscriptionRefSet> subscription_ref_set_; scoped_refptr<ValueStateMap> pending_valuebuffer_state_; diff --git a/gpu/command_buffer/service/context_group_unittest.cc b/gpu/command_buffer/service/context_group_unittest.cc index 7c6d5c1..cbb36f5 100644 --- a/gpu/command_buffer/service/context_group_unittest.cc +++ b/gpu/command_buffer/service/context_group_unittest.cc @@ -41,7 +41,7 @@ class ContextGroupTest : public GpuServiceTest { GpuServiceTest::SetUp(); decoder_.reset(new MockGLES2Decoder()); group_ = scoped_refptr<ContextGroup>(new ContextGroup( - NULL, NULL, NULL, NULL, NULL, NULL, kBindGeneratesResource)); + NULL, NULL, NULL, NULL, NULL, NULL, NULL, kBindGeneratesResource)); } scoped_ptr<MockGLES2Decoder> decoder_; diff --git a/gpu/command_buffer/service/framebuffer_completeness_cache.cc b/gpu/command_buffer/service/framebuffer_completeness_cache.cc new file mode 100644 index 0000000..183b023 --- /dev/null +++ b/gpu/command_buffer/service/framebuffer_completeness_cache.cc @@ -0,0 +1,24 @@ +// Copyright 2015 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/framebuffer_completeness_cache.h" + +namespace gpu { +namespace gles2 { + +FramebufferCompletenessCache::FramebufferCompletenessCache() {} + +FramebufferCompletenessCache::~FramebufferCompletenessCache() {} + +bool FramebufferCompletenessCache::IsComplete( + const std::string& signature) const { + return cache_.find(signature) != cache_.end(); +} + +void FramebufferCompletenessCache::SetComplete(const std::string& signature) { + cache_.insert(signature); +} + +} // namespace gles2 +} // namespace gpu diff --git a/gpu/command_buffer/service/framebuffer_completeness_cache.h b/gpu/command_buffer/service/framebuffer_completeness_cache.h new file mode 100644 index 0000000..7200cbd --- /dev/null +++ b/gpu/command_buffer/service/framebuffer_completeness_cache.h @@ -0,0 +1,42 @@ +// Copyright 2015 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_FRAMEBUFFER_COMPLETENESS_CACHE_H_ +#define GPU_COMMAND_BUFFER_SERVICE_FRAMEBUFFER_COMPLETENESS_CACHE_H_ + +#include "base/containers/hash_tables.h" +#include "base/memory/ref_counted.h" +#include "gpu/gpu_export.h" + +namespace gpu { +namespace gles2 { + +// Refcounted wrapper for a hash_set of framebuffer format signatures +// representing framebuffer configurations that are reported by the GL +// driver as complete according to glCheckFramebufferStatusEXT. +class GPU_EXPORT FramebufferCompletenessCache + : public base::RefCounted<FramebufferCompletenessCache> { + public: + FramebufferCompletenessCache(); + + bool IsComplete(const std::string& signature) const; + void SetComplete(const std::string& signature); + + protected: + virtual ~FramebufferCompletenessCache(); + + private: + friend class base::RefCounted<FramebufferCompletenessCache>; + + typedef base::hash_set<std::string> Map; + + Map cache_; + + DISALLOW_COPY_AND_ASSIGN(FramebufferCompletenessCache); +}; + +} // namespace gles2 +} // namespace gpu + +#endif // GPU_COMMAND_BUFFER_SERVICE_FRAMEBUFFER_COMPLETENESS_CACHE_H_ diff --git a/gpu/command_buffer/service/framebuffer_manager.cc b/gpu/command_buffer/service/framebuffer_manager.cc index 9a1b77c..9c3a522 100644 --- a/gpu/command_buffer/service/framebuffer_manager.cc +++ b/gpu/command_buffer/service/framebuffer_manager.cc @@ -6,6 +6,7 @@ #include "base/logging.h" #include "base/strings/stringprintf.h" #include "gpu/command_buffer/common/gles2_cmd_utils.h" +#include "gpu/command_buffer/service/framebuffer_completeness_cache.h" #include "gpu/command_buffer/service/renderbuffer_manager.h" #include "gpu/command_buffer/service/texture_manager.h" #include "ui/gl/gl_bindings.h" @@ -22,24 +23,6 @@ DecoderFramebufferState::DecoderFramebufferState() DecoderFramebufferState::~DecoderFramebufferState() { } -Framebuffer::FramebufferComboCompleteMap* - Framebuffer::framebuffer_combo_complete_map_; - -// Framebuffer completeness is not cacheable on OS X because of dynamic -// graphics switching. -// http://crbug.com/180876 -#if defined(OS_MACOSX) -bool Framebuffer::allow_framebuffer_combo_complete_map_ = false; -#else -bool Framebuffer::allow_framebuffer_combo_complete_map_ = true; -#endif - -void Framebuffer::ClearFramebufferCompleteComboMap() { - if (framebuffer_combo_complete_map_) { - framebuffer_combo_complete_map_->clear(); - } -} - class RenderbufferAttachment : public Framebuffer::Attachment { public: @@ -260,14 +243,18 @@ FramebufferManager::TextureDetachObserver::TextureDetachObserver() {} FramebufferManager::TextureDetachObserver::~TextureDetachObserver() {} FramebufferManager::FramebufferManager( - uint32 max_draw_buffers, uint32 max_color_attachments, - ContextGroup::ContextType context_type) + uint32 max_draw_buffers, + uint32 max_color_attachments, + ContextGroup::ContextType context_type, + const scoped_refptr<FramebufferCompletenessCache>& + framebuffer_combo_complete_cache) : framebuffer_state_change_count_(1), framebuffer_count_(0), have_context_(true), max_draw_buffers_(max_draw_buffers), max_color_attachments_(max_color_attachments), - context_type_(context_type) { + context_type_(context_type), + framebuffer_combo_complete_cache_(framebuffer_combo_complete_cache) { DCHECK_GT(max_draw_buffers_, 0u); DCHECK_GT(max_color_attachments_, 0u); } @@ -503,46 +490,40 @@ GLenum Framebuffer::IsPossiblyComplete() const { GLenum Framebuffer::GetStatus( TextureManager* texture_manager, GLenum target) const { + if (!manager_->GetFramebufferComboCompleteCache()) { + return glCheckFramebufferStatusEXT(target); + } // Check if we have this combo already. std::string signature; - if (allow_framebuffer_combo_complete_map_) { - size_t signature_size = sizeof(target); - for (AttachmentMap::const_iterator it = attachments_.begin(); - it != attachments_.end(); ++it) { - Attachment* attachment = it->second.get(); - signature_size += sizeof(it->first) + - attachment->GetSignatureSize(texture_manager); - } - signature.reserve(signature_size); - signature.append(reinterpret_cast<const char*>(&target), sizeof(target)); + size_t signature_size = sizeof(target); + for (AttachmentMap::const_iterator it = attachments_.begin(); + it != attachments_.end(); ++it) { + Attachment* attachment = it->second.get(); + signature_size += + sizeof(it->first) + attachment->GetSignatureSize(texture_manager); + } - for (AttachmentMap::const_iterator it = attachments_.begin(); - it != attachments_.end(); ++it) { - Attachment* attachment = it->second.get(); - signature.append(reinterpret_cast<const char*>(&it->first), - sizeof(it->first)); - attachment->AddToSignature(texture_manager, &signature); - } - DCHECK(signature.size() == signature_size); + signature.reserve(signature_size); + signature.append(reinterpret_cast<const char*>(&target), sizeof(target)); - if (!framebuffer_combo_complete_map_) { - framebuffer_combo_complete_map_ = new FramebufferComboCompleteMap(); - } + for (AttachmentMap::const_iterator it = attachments_.begin(); + it != attachments_.end(); ++it) { + Attachment* attachment = it->second.get(); + signature.append(reinterpret_cast<const char*>(&it->first), + sizeof(it->first)); + attachment->AddToSignature(texture_manager, &signature); + } + DCHECK(signature.size() == signature_size); - FramebufferComboCompleteMap::const_iterator it = - framebuffer_combo_complete_map_->find(signature); - if (it != framebuffer_combo_complete_map_->end()) { - return GL_FRAMEBUFFER_COMPLETE; - } + if (manager_->GetFramebufferComboCompleteCache()->IsComplete(signature)) { + return GL_FRAMEBUFFER_COMPLETE; } GLenum result = glCheckFramebufferStatusEXT(target); - // Insert the new result into the combo map. - if (allow_framebuffer_combo_complete_map_ && - result == GL_FRAMEBUFFER_COMPLETE) { - framebuffer_combo_complete_map_->insert(std::make_pair(signature, true)); + if (result == GL_FRAMEBUFFER_COMPLETE) { + manager_->GetFramebufferComboCompleteCache()->SetComplete(signature); } return result; @@ -778,5 +759,3 @@ void FramebufferManager::OnTextureRefDetached(TextureRef* texture) { } // namespace gles2 } // namespace gpu - - diff --git a/gpu/command_buffer/service/framebuffer_manager.h b/gpu/command_buffer/service/framebuffer_manager.h index 9bf440a..0432584 100644 --- a/gpu/command_buffer/service/framebuffer_manager.h +++ b/gpu/command_buffer/service/framebuffer_manager.h @@ -18,6 +18,7 @@ namespace gpu { namespace gles2 { +class FramebufferCompletenessCache; class FramebufferManager; class Renderbuffer; class RenderbufferManager; @@ -156,12 +157,6 @@ class GPU_EXPORT Framebuffer : public base::RefCounted<Framebuffer> { // formats. bool HasSameInternalFormatsMRT() const; - static void ClearFramebufferCompleteComboMap(); - - static bool AllowFramebufferComboCompleteMapForTesting() { - return allow_framebuffer_combo_complete_map_; - } - void OnTextureRefDetached(TextureRef* texture); void OnWillRenderTo() const; void OnDidRenderTo() const; @@ -217,12 +212,6 @@ class GPU_EXPORT Framebuffer : public base::RefCounted<Framebuffer> { typedef base::hash_map<GLenum, scoped_refptr<Attachment> > AttachmentMap; AttachmentMap attachments_; - // A map of successful frame buffer combos. If it's in the map - // it should be FRAMEBUFFER_COMPLETE. - typedef base::hash_map<std::string, bool> FramebufferComboCompleteMap; - static FramebufferComboCompleteMap* framebuffer_combo_complete_map_; - static bool allow_framebuffer_combo_complete_map_; - scoped_ptr<GLenum[]> draw_buffers_; GLenum read_buffer_; @@ -258,8 +247,11 @@ class GPU_EXPORT FramebufferManager { DISALLOW_COPY_AND_ASSIGN(TextureDetachObserver); }; - FramebufferManager(uint32 max_draw_buffers, uint32 max_color_attachments, - ContextGroup::ContextType context_type); + FramebufferManager(uint32 max_draw_buffers, + uint32 max_color_attachments, + ContextGroup::ContextType context_type, + const scoped_refptr<FramebufferCompletenessCache>& + framebuffer_combo_complete_cache); ~FramebufferManager(); // Must call before destruction. @@ -316,6 +308,10 @@ class GPU_EXPORT FramebufferManager { void OnTextureRefDetached(TextureRef* texture); + FramebufferCompletenessCache* GetFramebufferComboCompleteCache() { + return framebuffer_combo_complete_cache_.get(); + } + // Info for each framebuffer in the system. typedef base::hash_map<GLuint, scoped_refptr<Framebuffer> > FramebufferMap; @@ -339,6 +335,8 @@ class GPU_EXPORT FramebufferManager { typedef std::vector<TextureDetachObserver*> TextureDetachObserverVector; TextureDetachObserverVector texture_detach_observers_; + scoped_refptr<FramebufferCompletenessCache> framebuffer_combo_complete_cache_; + DISALLOW_COPY_AND_ASSIGN(FramebufferManager); }; diff --git a/gpu/command_buffer/service/framebuffer_manager_unittest.cc b/gpu/command_buffer/service/framebuffer_manager_unittest.cc index c7133ac..c423764 100644 --- a/gpu/command_buffer/service/framebuffer_manager_unittest.cc +++ b/gpu/command_buffer/service/framebuffer_manager_unittest.cc @@ -34,7 +34,7 @@ const bool kUseDefaultTextures = false; class FramebufferManagerTest : public GpuServiceTest { public: FramebufferManagerTest() - : manager_(1, 1, ContextGroup::CONTEXT_TYPE_UNDEFINED), + : manager_(1, 1, ContextGroup::CONTEXT_TYPE_UNDEFINED, NULL), feature_info_(new FeatureInfo()) { texture_manager_.reset(new TextureManager(NULL, feature_info_.get(), @@ -111,7 +111,10 @@ class FramebufferInfoTestBase : public GpuServiceTest { static const GLuint kService1Id = 11; explicit FramebufferInfoTestBase(ContextGroup::ContextType context_type) - : manager_(kMaxDrawBuffers, kMaxColorAttachments, context_type), + : manager_(kMaxDrawBuffers, + kMaxColorAttachments, + context_type, + new FramebufferCompletenessCache), feature_info_(new FeatureInfo()) { texture_manager_.reset(new TextureManager(NULL, feature_info_.get(), @@ -835,11 +838,6 @@ TEST_F(FramebufferInfoTest, GetStatus) { framebuffer_->GetStatus(texture_manager_.get(), GL_FRAMEBUFFER); // Check a second call for the same type does not call anything - if (!framebuffer_->AllowFramebufferComboCompleteMapForTesting()) { - EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_FRAMEBUFFER)) - .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE)) - .RetiresOnSaturation(); - } framebuffer_->GetStatus(texture_manager_.get(), GL_FRAMEBUFFER); // Check changing the attachments calls CheckFramebufferStatus. @@ -850,11 +848,6 @@ TEST_F(FramebufferInfoTest, GetStatus) { framebuffer_->GetStatus(texture_manager_.get(), GL_FRAMEBUFFER); // Check a second call for the same type does not call anything. - if (!framebuffer_->AllowFramebufferComboCompleteMapForTesting()) { - EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_FRAMEBUFFER)) - .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE)) - .RetiresOnSaturation(); - } framebuffer_->GetStatus(texture_manager_.get(), GL_FRAMEBUFFER); // Check a second call with a different target calls CheckFramebufferStatus. @@ -864,11 +857,6 @@ TEST_F(FramebufferInfoTest, GetStatus) { framebuffer_->GetStatus(texture_manager_.get(), GL_READ_FRAMEBUFFER); // Check a second call for the same type does not call anything. - if (!framebuffer_->AllowFramebufferComboCompleteMapForTesting()) { - EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_READ_FRAMEBUFFER)) - .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE)) - .RetiresOnSaturation(); - } framebuffer_->GetStatus(texture_manager_.get(), GL_READ_FRAMEBUFFER); // Check adding another attachment calls CheckFramebufferStatus. @@ -879,11 +867,6 @@ TEST_F(FramebufferInfoTest, GetStatus) { framebuffer_->GetStatus(texture_manager_.get(), GL_READ_FRAMEBUFFER); // Check a second call for the same type does not call anything. - if (!framebuffer_->AllowFramebufferComboCompleteMapForTesting()) { - EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_READ_FRAMEBUFFER)) - .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE)) - .RetiresOnSaturation(); - } framebuffer_->GetStatus(texture_manager_.get(), GL_READ_FRAMEBUFFER); // Check changing the format calls CheckFramebuffferStatus. @@ -906,11 +889,6 @@ TEST_F(FramebufferInfoTest, GetStatus) { framebuffer_->GetStatus(texture_manager_.get(), GL_READ_FRAMEBUFFER); // Check putting it back does not call CheckFramebufferStatus. - if (!framebuffer_->AllowFramebufferComboCompleteMapForTesting()) { - EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_READ_FRAMEBUFFER)) - .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE)) - .RetiresOnSaturation(); - } TestHelper::SetTexParameteriWithExpectations(gl_.get(), error_state_.get(), texture_manager_.get(), @@ -922,11 +900,6 @@ TEST_F(FramebufferInfoTest, GetStatus) { // Check Unbinding does not call CheckFramebufferStatus framebuffer_->UnbindRenderbuffer(GL_RENDERBUFFER, renderbuffer1); - if (!framebuffer_->AllowFramebufferComboCompleteMapForTesting()) { - EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_READ_FRAMEBUFFER)) - .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE)) - .RetiresOnSaturation(); - } framebuffer_->GetStatus(texture_manager_.get(), GL_READ_FRAMEBUFFER); } diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc index d78ec98..502d076 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc @@ -174,8 +174,6 @@ void GLES2DecoderTestBase::InitDecoderWithCommandLine( // For easier substring/extension matching DCHECK(normalized_init.extensions.empty() || *normalized_init.extensions.rbegin() == ' '); - Framebuffer::ClearFramebufferCompleteComboMap(); - gfx::SetGLGetProcAddressProc(gfx::MockGLInterface::GetGLProcAddress); gfx::GLSurfaceTestSupport::InitializeOneOffWithMockBindings(); @@ -188,12 +186,9 @@ void GLES2DecoderTestBase::InitDecoderWithCommandLine( if (command_line) feature_info = new FeatureInfo(*command_line); group_ = scoped_refptr<ContextGroup>( - new ContextGroup(NULL, - memory_tracker_, - new ShaderTranslatorCache, - feature_info.get(), - new SubscriptionRefSet, - new ValueStateMap, + new ContextGroup(NULL, memory_tracker_, new ShaderTranslatorCache, + new FramebufferCompletenessCache, feature_info.get(), + new SubscriptionRefSet, new ValueStateMap, normalized_init.bind_generates_resource)); bool use_default_textures = normalized_init.bind_generates_resource; diff --git a/gpu/command_buffer/service/in_process_command_buffer.cc b/gpu/command_buffer/service/in_process_command_buffer.cc index d7810a4..fad09c8 100644 --- a/gpu/command_buffer/service/in_process_command_buffer.cc +++ b/gpu/command_buffer/service/in_process_command_buffer.cc @@ -299,11 +299,10 @@ bool InProcessCommandBuffer::InitializeOnGpuThread( decoder_.reset(gles2::GLES2Decoder::Create( params.context_group ? params.context_group->decoder_->GetContextGroup() - : new gles2::ContextGroup(service_->mailbox_manager(), - NULL, + : new gles2::ContextGroup(service_->mailbox_manager(), NULL, service_->shader_translator_cache(), - NULL, - service_->subscription_ref_set(), + service_->framebuffer_completeness_cache(), + NULL, service_->subscription_ref_set(), service_->pending_valuebuffer_state(), bind_generates_resource))); @@ -925,6 +924,14 @@ GpuInProcessThread::shader_translator_cache() { return shader_translator_cache_; } +scoped_refptr<gles2::FramebufferCompletenessCache> +GpuInProcessThread::framebuffer_completeness_cache() { + if (!framebuffer_completeness_cache_.get()) + framebuffer_completeness_cache_ = + new gpu::gles2::FramebufferCompletenessCache; + return framebuffer_completeness_cache_; +} + SyncPointManager* GpuInProcessThread::sync_point_manager() { return sync_point_manager_; } diff --git a/gpu/command_buffer/service/in_process_command_buffer.h b/gpu/command_buffer/service/in_process_command_buffer.h index 4dfee19..79c81e0 100644 --- a/gpu/command_buffer/service/in_process_command_buffer.h +++ b/gpu/command_buffer/service/in_process_command_buffer.h @@ -51,6 +51,7 @@ class SyncPointManager; class ValueStateMap; namespace gles2 { +class FramebufferCompletenessCache; class GLES2Decoder; class MailboxManager; class ShaderTranslatorCache; @@ -144,6 +145,8 @@ class GPU_EXPORT InProcessCommandBuffer : public CommandBuffer, virtual bool UseVirtualizedGLContexts() = 0; virtual scoped_refptr<gles2::ShaderTranslatorCache> shader_translator_cache() = 0; + virtual scoped_refptr<gles2::FramebufferCompletenessCache> + framebuffer_completeness_cache() = 0; virtual SyncPointManager* sync_point_manager() = 0; scoped_refptr<gfx::GLShareGroup> share_group(); scoped_refptr<gles2::MailboxManager> mailbox_manager(); @@ -279,6 +282,8 @@ class GPU_EXPORT GpuInProcessThread bool UseVirtualizedGLContexts() override; scoped_refptr<gles2::ShaderTranslatorCache> shader_translator_cache() override; + scoped_refptr<gles2::FramebufferCompletenessCache> + framebuffer_completeness_cache() override; SyncPointManager* sync_point_manager() override; private: @@ -287,6 +292,8 @@ class GPU_EXPORT GpuInProcessThread SyncPointManager* sync_point_manager_; // Non-owning. scoped_refptr<gpu::gles2::ShaderTranslatorCache> shader_translator_cache_; + scoped_refptr<gpu::gles2::FramebufferCompletenessCache> + framebuffer_completeness_cache_; DISALLOW_COPY_AND_ASSIGN(GpuInProcessThread); }; diff --git a/gpu/command_buffer/service/texture_manager_unittest.cc b/gpu/command_buffer/service/texture_manager_unittest.cc index 6cadd97..231fc04 100644 --- a/gpu/command_buffer/service/texture_manager_unittest.cc +++ b/gpu/command_buffer/service/texture_manager_unittest.cc @@ -1923,10 +1923,10 @@ TEST_F(SharedTextureTest, TextureSafetyAccounting) { TEST_F(SharedTextureTest, FBOCompletenessCheck) { const GLenum kCompleteValue = GL_FRAMEBUFFER_COMPLETE; FramebufferManager framebuffer_manager1( - 1, 1, ContextGroup::CONTEXT_TYPE_UNDEFINED); + 1, 1, ContextGroup::CONTEXT_TYPE_UNDEFINED, NULL); texture_manager1_->set_framebuffer_manager(&framebuffer_manager1); FramebufferManager framebuffer_manager2( - 1, 1, ContextGroup::CONTEXT_TYPE_UNDEFINED); + 1, 1, ContextGroup::CONTEXT_TYPE_UNDEFINED, NULL); texture_manager2_->set_framebuffer_manager(&framebuffer_manager2); scoped_refptr<TextureRef> ref1 = texture_manager1_->CreateTexture(10, 10); diff --git a/gpu/command_buffer/tests/gl_manager.cc b/gpu/command_buffer/tests/gl_manager.cc index 82930cd..539bca3 100644 --- a/gpu/command_buffer/tests/gl_manager.cc +++ b/gpu/command_buffer/tests/gl_manager.cc @@ -270,14 +270,10 @@ void GLManager::InitializeWithCommandLine(const GLManager::Options& options, scoped_refptr<gles2::FeatureInfo> feature_info; if (command_line) feature_info = new gles2::FeatureInfo(*command_line); - context_group = - new gles2::ContextGroup(mailbox_manager_.get(), - NULL, - new gpu::gles2::ShaderTranslatorCache, - feature_info, - NULL, - NULL, - options.bind_generates_resource); + context_group = new gles2::ContextGroup( + mailbox_manager_.get(), NULL, new gpu::gles2::ShaderTranslatorCache, + new gpu::gles2::FramebufferCompletenessCache, feature_info, NULL, NULL, + options.bind_generates_resource); } decoder_.reset(::gpu::gles2::GLES2Decoder::Create(context_group)); diff --git a/gpu/command_buffer_service.gypi b/gpu/command_buffer_service.gypi index b633f89..699480e 100644 --- a/gpu/command_buffer_service.gypi +++ b/gpu/command_buffer_service.gypi @@ -61,6 +61,8 @@ 'command_buffer/service/error_state.h', 'command_buffer/service/feature_info.cc', 'command_buffer/service/feature_info.h', + "command_buffer/service/framebuffer_completeness_cache.cc", + "command_buffer/service/framebuffer_completeness_cache.h", 'command_buffer/service/framebuffer_manager.cc', 'command_buffer/service/framebuffer_manager.h', 'command_buffer/service/gl_context_virtual.cc', diff --git a/gpu/gles2_conform_support/egl/display.cc b/gpu/gles2_conform_support/egl/display.cc index dce6599..59e72ea 100644 --- a/gpu/gles2_conform_support/egl/display.cc +++ b/gpu/gles2_conform_support/egl/display.cc @@ -116,14 +116,9 @@ EGLSurface Display::CreateWindowSurface(EGLConfig config, if (!command_buffer->Initialize()) return NULL; - scoped_refptr<gpu::gles2::ContextGroup> group( - new gpu::gles2::ContextGroup(NULL, - NULL, - new gpu::gles2::ShaderTranslatorCache, - NULL, - NULL, - NULL, - true)); + scoped_refptr<gpu::gles2::ContextGroup> group(new gpu::gles2::ContextGroup( + NULL, NULL, new gpu::gles2::ShaderTranslatorCache, + new gpu::gles2::FramebufferCompletenessCache, NULL, NULL, NULL, true)); decoder_.reset(gpu::gles2::GLES2Decoder::Create(group.get())); if (!decoder_.get()) |