Index: content/common/gpu/client/context_provider_command_buffer.cc |
diff --git a/content/common/gpu/client/context_provider_command_buffer.cc b/content/common/gpu/client/context_provider_command_buffer.cc |
deleted file mode 100644 |
index 74756be6c0076b3615da4d59aa6a234c6c6bb827..0000000000000000000000000000000000000000 |
--- a/content/common/gpu/client/context_provider_command_buffer.cc |
+++ /dev/null |
@@ -1,468 +0,0 @@ |
-// Copyright (c) 2013 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 "content/common/gpu/client/context_provider_command_buffer.h" |
- |
-#include <stddef.h> |
- |
-#include <memory> |
-#include <set> |
-#include <utility> |
-#include <vector> |
- |
-#include "base/callback_helpers.h" |
-#include "base/command_line.h" |
-#include "base/optional.h" |
-#include "base/strings/stringprintf.h" |
-#include "base/threading/thread_task_runner_handle.h" |
-#include "base/trace_event/memory_dump_manager.h" |
-#include "cc/output/context_cache_controller.h" |
-#include "cc/output/managed_memory_policy.h" |
-#include "content/common/gpu/client/command_buffer_metrics.h" |
-#include "gpu/command_buffer/client/gles2_cmd_helper.h" |
-#include "gpu/command_buffer/client/gles2_implementation.h" |
-#include "gpu/command_buffer/client/gles2_trace_implementation.h" |
-#include "gpu/command_buffer/client/gpu_switches.h" |
-#include "gpu/command_buffer/client/transfer_buffer.h" |
-#include "gpu/command_buffer/common/constants.h" |
-#include "gpu/ipc/client/command_buffer_proxy_impl.h" |
-#include "gpu/ipc/client/gpu_channel_host.h" |
-#include "gpu/skia_bindings/grcontext_for_gles2_interface.h" |
-#include "third_party/skia/include/core/SkTraceMemoryDump.h" |
-#include "third_party/skia/include/gpu/GrContext.h" |
-#include "ui/gl/trace_util.h" |
- |
-class SkDiscardableMemory; |
- |
-namespace { |
- |
-// Similar to base::AutoReset but it sets the variable to the new value |
-// when it is destroyed. Use Reset() to cancel setting the variable. |
-class AutoSet { |
- public: |
- AutoSet(bool* b, bool set) : b_(b), set_(set) {} |
- ~AutoSet() { |
- if (b_) |
- *b_ = set_; |
- } |
- // Stops us from setting b_ on destruction. |
- void Reset() { b_ = nullptr; } |
- |
- private: |
- bool* b_; |
- const bool set_; |
-}; |
- |
-// Derives from SkTraceMemoryDump and implements graphics specific memory |
-// backing functionality. |
-class SkiaGpuTraceMemoryDump : public SkTraceMemoryDump { |
- public: |
- // This should never outlive the provided ProcessMemoryDump, as it should |
- // always be scoped to a single OnMemoryDump funciton call. |
- explicit SkiaGpuTraceMemoryDump(base::trace_event::ProcessMemoryDump* pmd, |
- uint64_t share_group_tracing_guid) |
- : pmd_(pmd), share_group_tracing_guid_(share_group_tracing_guid) {} |
- |
- // Overridden from SkTraceMemoryDump: |
- void dumpNumericValue(const char* dump_name, |
- const char* value_name, |
- const char* units, |
- uint64_t value) override { |
- auto* dump = GetOrCreateAllocatorDump(dump_name); |
- dump->AddScalar(value_name, units, value); |
- } |
- |
- void setMemoryBacking(const char* dump_name, |
- const char* backing_type, |
- const char* backing_object_id) override { |
- const uint64_t tracing_process_id = |
- base::trace_event::MemoryDumpManager::GetInstance() |
- ->GetTracingProcessId(); |
- |
- // For uniformity, skia provides this value as a string. Convert back to a |
- // uint32_t. |
- uint32_t gl_id = |
- std::strtoul(backing_object_id, nullptr /* str_end */, 10 /* base */); |
- |
- // Constants used by SkiaGpuTraceMemoryDump to identify different memory |
- // types. |
- const char* kGLTextureBackingType = "gl_texture"; |
- const char* kGLBufferBackingType = "gl_buffer"; |
- const char* kGLRenderbufferBackingType = "gl_renderbuffer"; |
- |
- // Populated in if statements below. |
- base::trace_event::MemoryAllocatorDumpGuid guid; |
- |
- if (strcmp(backing_type, kGLTextureBackingType) == 0) { |
- guid = gl::GetGLTextureClientGUIDForTracing(share_group_tracing_guid_, |
- gl_id); |
- } else if (strcmp(backing_type, kGLBufferBackingType) == 0) { |
- guid = gl::GetGLBufferGUIDForTracing(tracing_process_id, gl_id); |
- } else if (strcmp(backing_type, kGLRenderbufferBackingType) == 0) { |
- guid = gl::GetGLRenderbufferGUIDForTracing(tracing_process_id, gl_id); |
- } |
- |
- if (!guid.empty()) { |
- pmd_->CreateSharedGlobalAllocatorDump(guid); |
- |
- auto* dump = GetOrCreateAllocatorDump(dump_name); |
- |
- const int kImportance = 2; |
- pmd_->AddOwnershipEdge(dump->guid(), guid, kImportance); |
- } |
- } |
- |
- void setDiscardableMemoryBacking( |
- const char* dump_name, |
- const SkDiscardableMemory& discardable_memory_object) override { |
- // We don't use this class for dumping discardable memory. |
- NOTREACHED(); |
- } |
- |
- LevelOfDetail getRequestedDetails() const override { |
- // TODO(ssid): Use MemoryDumpArgs to create light dumps when requested |
- // (crbug.com/499731). |
- return kObjectsBreakdowns_LevelOfDetail; |
- } |
- |
- private: |
- // Helper to create allocator dumps. |
- base::trace_event::MemoryAllocatorDump* GetOrCreateAllocatorDump( |
- const char* dump_name) { |
- auto* dump = pmd_->GetAllocatorDump(dump_name); |
- if (!dump) |
- dump = pmd_->CreateAllocatorDump(dump_name); |
- return dump; |
- } |
- |
- base::trace_event::ProcessMemoryDump* pmd_; |
- uint64_t share_group_tracing_guid_; |
- |
- DISALLOW_COPY_AND_ASSIGN(SkiaGpuTraceMemoryDump); |
-}; |
- |
-} // namespace |
- |
-namespace content { |
- |
-ContextProviderCommandBuffer::SharedProviders::SharedProviders() = default; |
-ContextProviderCommandBuffer::SharedProviders::~SharedProviders() = default; |
- |
-ContextProviderCommandBuffer::ContextProviderCommandBuffer( |
- scoped_refptr<gpu::GpuChannelHost> channel, |
- int32_t stream_id, |
- gpu::GpuStreamPriority stream_priority, |
- gpu::SurfaceHandle surface_handle, |
- const GURL& active_url, |
- bool automatic_flushes, |
- bool support_locking, |
- const gpu::SharedMemoryLimits& memory_limits, |
- const gpu::gles2::ContextCreationAttribHelper& attributes, |
- ContextProviderCommandBuffer* shared_context_provider, |
- command_buffer_metrics::ContextType type) |
- : stream_id_(stream_id), |
- stream_priority_(stream_priority), |
- surface_handle_(surface_handle), |
- active_url_(active_url), |
- automatic_flushes_(automatic_flushes), |
- support_locking_(support_locking), |
- memory_limits_(memory_limits), |
- attributes_(attributes), |
- context_type_(type), |
- shared_providers_(shared_context_provider |
- ? shared_context_provider->shared_providers_ |
- : new SharedProviders), |
- channel_(std::move(channel)) { |
- DCHECK(main_thread_checker_.CalledOnValidThread()); |
- DCHECK(channel_); |
- context_thread_checker_.DetachFromThread(); |
-} |
- |
-ContextProviderCommandBuffer::~ContextProviderCommandBuffer() { |
- DCHECK(main_thread_checker_.CalledOnValidThread() || |
- context_thread_checker_.CalledOnValidThread()); |
- |
- { |
- base::AutoLock hold(shared_providers_->lock); |
- auto it = std::find(shared_providers_->list.begin(), |
- shared_providers_->list.end(), this); |
- if (it != shared_providers_->list.end()) |
- shared_providers_->list.erase(it); |
- } |
- |
- if (bind_succeeded_) { |
- // Clear the lock to avoid DCHECKs that the lock is being held during |
- // shutdown. |
- command_buffer_->SetLock(nullptr); |
- // Disconnect lost callbacks during destruction. |
- gles2_impl_->SetLostContextCallback(base::Closure()); |
- // Unregister memory dump provider. |
- base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider( |
- this); |
- } |
-} |
- |
-gpu::CommandBufferProxyImpl* |
-ContextProviderCommandBuffer::GetCommandBufferProxy() { |
- return command_buffer_.get(); |
-} |
- |
-uint32_t ContextProviderCommandBuffer::GetCopyTextureInternalFormat() { |
- if (attributes_.alpha_size > 0) |
- return GL_RGBA; |
- DCHECK_NE(attributes_.red_size, 0); |
- DCHECK_NE(attributes_.green_size, 0); |
- DCHECK_NE(attributes_.blue_size, 0); |
- return GL_RGB; |
-} |
- |
-bool ContextProviderCommandBuffer::BindToCurrentThread() { |
- // This is called on the thread the context will be used. |
- DCHECK(context_thread_checker_.CalledOnValidThread()); |
- |
- if (bind_failed_) |
- return false; |
- if (bind_succeeded_) |
- return true; |
- |
- // Early outs should report failure. |
- AutoSet set_bind_failed(&bind_failed_, true); |
- |
- scoped_refptr<base::SingleThreadTaskRunner> task_runner = |
- default_task_runner_; |
- if (!task_runner) |
- task_runner = base::ThreadTaskRunnerHandle::Get(); |
- |
- // It's possible to be running BindToCurrentThread on two contexts |
- // on different threads at the same time, but which will be in the same share |
- // group. To ensure they end up in the same group, hold the lock on the |
- // shared_providers_ (which they will share) after querying the group, until |
- // this context has been added to the list. |
- { |
- ContextProviderCommandBuffer* shared_context_provider = nullptr; |
- gpu::CommandBufferProxyImpl* shared_command_buffer = nullptr; |
- scoped_refptr<gpu::gles2::ShareGroup> share_group; |
- |
- base::AutoLock hold(shared_providers_->lock); |
- |
- if (!shared_providers_->list.empty()) { |
- shared_context_provider = shared_providers_->list.front(); |
- shared_command_buffer = shared_context_provider->command_buffer_.get(); |
- share_group = shared_context_provider->gles2_impl_->share_group(); |
- DCHECK_EQ(!!shared_command_buffer, !!share_group); |
- } |
- |
- // This command buffer is a client-side proxy to the command buffer in the |
- // GPU process. |
- command_buffer_ = gpu::CommandBufferProxyImpl::Create( |
- std::move(channel_), surface_handle_, shared_command_buffer, stream_id_, |
- stream_priority_, attributes_, active_url_, task_runner); |
- if (!command_buffer_) { |
- DLOG(ERROR) << "GpuChannelHost failed to create command buffer."; |
- command_buffer_metrics::UmaRecordContextInitFailed(context_type_); |
- return false; |
- } |
- |
- // The GLES2 helper writes the command buffer protocol. |
- gles2_helper_.reset(new gpu::gles2::GLES2CmdHelper(command_buffer_.get())); |
- gles2_helper_->SetAutomaticFlushes(automatic_flushes_); |
- if (!gles2_helper_->Initialize(memory_limits_.command_buffer_size)) { |
- DLOG(ERROR) << "Failed to initialize GLES2CmdHelper."; |
- return false; |
- } |
- |
- // The transfer buffer is used to copy resources between the client |
- // process and the GPU process. |
- transfer_buffer_.reset(new gpu::TransferBuffer(gles2_helper_.get())); |
- |
- // The GLES2Implementation exposes the OpenGLES2 API, as well as the |
- // gpu::ContextSupport interface. |
- constexpr bool support_client_side_arrays = false; |
- gles2_impl_.reset(new gpu::gles2::GLES2Implementation( |
- gles2_helper_.get(), share_group, transfer_buffer_.get(), |
- attributes_.bind_generates_resource, |
- attributes_.lose_context_when_out_of_memory, support_client_side_arrays, |
- command_buffer_.get())); |
- if (!gles2_impl_->Initialize(memory_limits_.start_transfer_buffer_size, |
- memory_limits_.min_transfer_buffer_size, |
- memory_limits_.max_transfer_buffer_size, |
- memory_limits_.mapped_memory_reclaim_limit)) { |
- DLOG(ERROR) << "Failed to initialize GLES2Implementation."; |
- return false; |
- } |
- |
- if (command_buffer_->GetLastState().error != gpu::error::kNoError) { |
- DLOG(ERROR) << "Context dead on arrival. Last error: " |
- << command_buffer_->GetLastState().error; |
- return false; |
- } |
- |
- // If any context in the share group has been lost, then abort and don't |
- // continue since we need to go back to the caller of the constructor to |
- // find the correct share group. |
- // This may happen in between the share group being chosen at the |
- // constructor, and getting to run this BindToCurrentThread method which |
- // can be on some other thread. |
- // We intentionally call this *after* creating the command buffer via the |
- // GpuChannelHost. Once that has happened, the service knows we are in the |
- // share group and if a shared context is lost, our context will be informed |
- // also, and the lost context callback will occur for the owner of the |
- // context provider. If we check sooner, the shared context may be lost in |
- // between these two states and our context here would be left in an orphan |
- // share group. |
- if (share_group && share_group->IsLost()) |
- return false; |
- |
- shared_providers_->list.push_back(this); |
- |
- cache_controller_.reset( |
- new cc::ContextCacheController(gles2_impl_.get(), task_runner)); |
- } |
- set_bind_failed.Reset(); |
- bind_succeeded_ = true; |
- |
- gles2_impl_->SetLostContextCallback( |
- base::Bind(&ContextProviderCommandBuffer::OnLostContext, |
- // |this| owns the GLES2Implementation which holds the |
- // callback. |
- base::Unretained(this))); |
- |
- if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
- switches::kEnableGpuClientTracing)) { |
- // This wraps the real GLES2Implementation and we should always use this |
- // instead when it's present. |
- trace_impl_.reset( |
- new gpu::gles2::GLES2TraceImplementation(gles2_impl_.get())); |
- } |
- |
- // Do this last once the context is set up. |
- std::string type_name = |
- command_buffer_metrics::ContextTypeToString(context_type_); |
- std::string unique_context_name = |
- base::StringPrintf("%s-%p", type_name.c_str(), gles2_impl_.get()); |
- ContextGL()->TraceBeginCHROMIUM("gpu_toplevel", unique_context_name.c_str()); |
- // If support_locking_ is true, the context may be used from multiple |
- // threads, and any async callstacks will need to hold the same lock, so |
- // give it to the command buffer and cache controller. |
- // We don't hold a lock here since there's no need, so set the lock very last |
- // to prevent asserts that we're not holding it. |
- if (support_locking_) { |
- command_buffer_->SetLock(&context_lock_); |
- cache_controller_->SetLock(&context_lock_); |
- } |
- base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( |
- this, "ContextProviderCommandBuffer", std::move(task_runner)); |
- return true; |
-} |
- |
-void ContextProviderCommandBuffer::DetachFromThread() { |
- context_thread_checker_.DetachFromThread(); |
-} |
- |
-gpu::gles2::GLES2Interface* ContextProviderCommandBuffer::ContextGL() { |
- DCHECK(bind_succeeded_); |
- DCHECK(context_thread_checker_.CalledOnValidThread()); |
- |
- if (trace_impl_) |
- return trace_impl_.get(); |
- return gles2_impl_.get(); |
-} |
- |
-gpu::ContextSupport* ContextProviderCommandBuffer::ContextSupport() { |
- return gles2_impl_.get(); |
-} |
- |
-class GrContext* ContextProviderCommandBuffer::GrContext() { |
- DCHECK(bind_succeeded_); |
- DCHECK(context_thread_checker_.CalledOnValidThread()); |
- |
- if (gr_context_) |
- return gr_context_->get(); |
- |
- gr_context_.reset(new skia_bindings::GrContextForGLES2Interface(ContextGL())); |
- cache_controller_->SetGrContext(gr_context_->get()); |
- |
- // If GlContext is already lost, also abandon the new GrContext. |
- if (gr_context_->get() && |
- ContextGL()->GetGraphicsResetStatusKHR() != GL_NO_ERROR) |
- gr_context_->get()->abandonContext(); |
- |
- return gr_context_->get(); |
-} |
- |
-cc::ContextCacheController* ContextProviderCommandBuffer::CacheController() { |
- DCHECK(context_thread_checker_.CalledOnValidThread()); |
- return cache_controller_.get(); |
-} |
- |
-void ContextProviderCommandBuffer::InvalidateGrContext(uint32_t state) { |
- if (gr_context_) { |
- DCHECK(bind_succeeded_); |
- DCHECK(context_thread_checker_.CalledOnValidThread()); |
- gr_context_->ResetContext(state); |
- } |
-} |
- |
-void ContextProviderCommandBuffer::SetDefaultTaskRunner( |
- scoped_refptr<base::SingleThreadTaskRunner> default_task_runner) { |
- DCHECK(!bind_succeeded_); |
- default_task_runner_ = std::move(default_task_runner); |
-} |
- |
-base::Lock* ContextProviderCommandBuffer::GetLock() { |
- DCHECK(support_locking_); |
- return &context_lock_; |
-} |
- |
-gpu::Capabilities ContextProviderCommandBuffer::ContextCapabilities() { |
- DCHECK(bind_succeeded_); |
- DCHECK(context_thread_checker_.CalledOnValidThread()); |
- // Skips past the trace_impl_ as it doesn't have capabilities. |
- return gles2_impl_->capabilities(); |
-} |
- |
-void ContextProviderCommandBuffer::OnLostContext() { |
- DCHECK(context_thread_checker_.CalledOnValidThread()); |
- |
- if (!lost_context_callback_.is_null()) |
- lost_context_callback_.Run(); |
- if (gr_context_) |
- gr_context_->OnLostContext(); |
- |
- gpu::CommandBuffer::State state = GetCommandBufferProxy()->GetLastState(); |
- command_buffer_metrics::UmaRecordContextLost(context_type_, state.error, |
- state.context_lost_reason); |
-} |
- |
-void ContextProviderCommandBuffer::SetLostContextCallback( |
- const LostContextCallback& lost_context_callback) { |
- DCHECK(context_thread_checker_.CalledOnValidThread()); |
- DCHECK(lost_context_callback_.is_null() || |
- lost_context_callback.is_null()); |
- lost_context_callback_ = lost_context_callback; |
-} |
- |
-bool ContextProviderCommandBuffer::OnMemoryDump( |
- const base::trace_event::MemoryDumpArgs& args, |
- base::trace_event::ProcessMemoryDump* pmd) { |
- DCHECK(bind_succeeded_); |
- |
- base::Optional<base::AutoLock> hold; |
- if (support_locking_) |
- hold.emplace(context_lock_); |
- |
- gles2_impl_->OnMemoryDump(args, pmd); |
- gles2_helper_->OnMemoryDump(args, pmd); |
- |
- if (gr_context_) { |
- context_thread_checker_.DetachFromThread(); |
- SkiaGpuTraceMemoryDump trace_memory_dump( |
- pmd, gles2_impl_->ShareGroupTracingGUID()); |
- gr_context_->get()->dumpMemoryStatistics(&trace_memory_dump); |
- context_thread_checker_.DetachFromThread(); |
- } |
- return true; |
-} |
- |
-} // namespace content |