Index: ui/compositor/test/in_process_context_provider.cc |
diff --git a/ui/compositor/test/in_process_context_provider.cc b/ui/compositor/test/in_process_context_provider.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..9cb1a74d77945fa555fa390257821bab9680a835 |
--- /dev/null |
+++ b/ui/compositor/test/in_process_context_provider.cc |
@@ -0,0 +1,225 @@ |
+// 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 "ui/compositor/test/in_process_context_provider.h" |
+ |
+#include "base/bind.h" |
+#include "base/callback_helpers.h" |
+#include "base/debug/trace_event.h" |
+#include "base/lazy_instance.h" |
+#include "base/strings/stringprintf.h" |
+#include "cc/output/managed_memory_policy.h" |
+#include "gpu/command_buffer/client/gl_in_process_context.h" |
+#include "gpu/command_buffer/client/gles2_implementation.h" |
+#include "gpu/command_buffer/client/gles2_lib.h" |
+#include "gpu/skia_bindings/gl_bindings_skia_cmd_buffer.h" |
+#include "third_party/skia/include/gpu/GrContext.h" |
+#include "third_party/skia/include/gpu/gl/GrGLInterface.h" |
+ |
+namespace ui { |
+ |
+namespace { |
+ |
+// Singleton used to initialize and terminate the gles2 library. |
+class GLES2Initializer { |
+ public: |
+ GLES2Initializer() { gles2::Initialize(); } |
+ |
+ ~GLES2Initializer() { gles2::Terminate(); } |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(GLES2Initializer); |
+}; |
+ |
+base::LazyInstance<GLES2Initializer> g_gles2_initializer = |
+ LAZY_INSTANCE_INITIALIZER; |
+ |
+} // namespace |
+ |
+// static |
+scoped_refptr<InProcessContextProvider> InProcessContextProvider::Create( |
+ const gpu::gles2::ContextCreationAttribHelper& attribs, |
+ bool lose_context_when_out_of_memory, |
+ gfx::AcceleratedWidget window, |
+ const std::string& debug_name) { |
+ return new InProcessContextProvider( |
+ attribs, lose_context_when_out_of_memory, window, debug_name); |
+} |
+ |
+// static |
+scoped_refptr<InProcessContextProvider> |
+InProcessContextProvider::CreateOffscreen( |
+ bool lose_context_when_out_of_memory) { |
+ gpu::gles2::ContextCreationAttribHelper attribs; |
+ attribs.alpha_size = 8; |
+ attribs.blue_size = 8; |
+ attribs.green_size = 8; |
+ attribs.red_size = 8; |
+ attribs.depth_size = 0; |
+ attribs.stencil_size = 8; |
+ attribs.samples = 0; |
+ attribs.sample_buffers = 0; |
+ attribs.fail_if_major_perf_caveat = false; |
+ attribs.bind_generates_resource = false; |
+ return new InProcessContextProvider( |
+ attribs, lose_context_when_out_of_memory, gfx::kNullAcceleratedWidget, |
+ "Offscreen"); |
+} |
+ |
+InProcessContextProvider::InProcessContextProvider( |
+ const gpu::gles2::ContextCreationAttribHelper& attribs, |
+ bool lose_context_when_out_of_memory, |
+ gfx::AcceleratedWidget window, |
+ const std::string& debug_name) |
+ : attribs_(attribs), |
+ lose_context_when_out_of_memory_(lose_context_when_out_of_memory), |
+ window_(window), |
+ debug_name_(debug_name), |
+ destroyed_(false) { |
+ DCHECK(main_thread_checker_.CalledOnValidThread()); |
+ context_thread_checker_.DetachFromThread(); |
+} |
+ |
+InProcessContextProvider::~InProcessContextProvider() { |
+ DCHECK(main_thread_checker_.CalledOnValidThread() || |
+ context_thread_checker_.CalledOnValidThread()); |
+} |
+ |
+bool InProcessContextProvider::BindToCurrentThread() { |
+ // This is called on the thread the context will be used. |
+ DCHECK(context_thread_checker_.CalledOnValidThread()); |
+ |
+ if (!context_) { |
+ gfx::GpuPreference gpu_preference = gfx::PreferDiscreteGpu; |
+ scoped_ptr<gpu::GLInProcessContext> context(gpu::GLInProcessContext::Create( |
+ nullptr, /* service */ |
+ nullptr, /* surface */ |
+ true, /* is_offscreen */ |
+ window_, |
+ gfx::Size(1, 1), |
+ nullptr, /* share_context */ |
+ true, /* share_resources */ |
+ attribs_, |
+ gpu_preference, |
+ gpu::GLInProcessContextSharedMemoryLimits(), |
+ nullptr, |
+ nullptr)); |
+ |
+ if (!context) |
+ return false; |
+ |
+ context_ = context.Pass(); |
piman
2015/01/23 23:21:48
nit: you don't actually need the temporary |contex
tfarina
2015/01/24 14:57:11
Done.
|
+ context_->SetContextLostCallback(base::Bind( |
+ &InProcessContextProvider::OnLostContext, base::Unretained(this))); |
+ } |
+ |
+ capabilities_.gpu = context_->GetImplementation()->capabilities(); |
+ |
+ std::string unique_context_name = |
+ base::StringPrintf("%s-%p", debug_name_.c_str(), context_.get()); |
+ context_->GetImplementation()->TraceBeginCHROMIUM( |
+ "gpu_toplevel", unique_context_name.c_str()); |
+ |
+ return true; |
+} |
+ |
+cc::ContextProvider::Capabilities |
+InProcessContextProvider::ContextCapabilities() { |
+ DCHECK(context_thread_checker_.CalledOnValidThread()); |
+ return capabilities_; |
+} |
+ |
+gpu::gles2::GLES2Interface* InProcessContextProvider::ContextGL() { |
+ DCHECK(context_thread_checker_.CalledOnValidThread()); |
+ |
+ return context_->GetImplementation(); |
+} |
+ |
+gpu::ContextSupport* InProcessContextProvider::ContextSupport() { |
+ DCHECK(context_thread_checker_.CalledOnValidThread()); |
+ |
+ return context_->GetImplementation(); |
+} |
+ |
+static void BindGrContextCallback(const GrGLInterface* interface) { |
+ cc::ContextProvider* context_provider = |
+ reinterpret_cast<InProcessContextProvider*>(interface->fCallbackData); |
+ |
+ gles2::SetGLContext(context_provider->ContextGL()); |
+} |
+ |
+class GrContext* InProcessContextProvider::GrContext() { |
+ DCHECK(context_thread_checker_.CalledOnValidThread()); |
+ |
+ if (gr_context_) |
+ return gr_context_.get(); |
+ |
+ // The GrGLInterface factory will make GL calls using the C GLES2 interface. |
+ // Make sure the gles2 library is initialized first on exactly one thread. |
+ g_gles2_initializer.Get(); |
+ gles2::SetGLContext(ContextGL()); |
+ |
+ skia::RefPtr<GrGLInterface> interface = |
+ skia::AdoptRef(skia_bindings::CreateCommandBufferSkiaGLBinding()); |
+ interface->fCallback = BindGrContextCallback; |
+ interface->fCallbackData = reinterpret_cast<GrGLInterfaceCallbackData>(this); |
+ |
+ gr_context_ = skia::AdoptRef(GrContext::Create( |
+ kOpenGL_GrBackend, reinterpret_cast<GrBackendContext>(interface.get()))); |
+ |
+ return gr_context_.get(); |
+} |
+ |
+bool InProcessContextProvider::IsContextLost() { |
+ DCHECK(context_thread_checker_.CalledOnValidThread()); |
+ |
+ base::AutoLock lock(destroyed_lock_); |
+ return destroyed_; |
+} |
+ |
+void InProcessContextProvider::VerifyContexts() { |
+} |
+ |
+void InProcessContextProvider::DeleteCachedResources() { |
+ DCHECK(context_thread_checker_.CalledOnValidThread()); |
+ |
+ if (gr_context_) { |
+ TRACE_EVENT_INSTANT0("gpu", "GrContext::freeGpuResources", |
+ TRACE_EVENT_SCOPE_THREAD); |
+ gr_context_->freeGpuResources(); |
+ } |
+} |
+ |
+bool InProcessContextProvider::DestroyedOnMainThread() { |
+ DCHECK(main_thread_checker_.CalledOnValidThread()); |
+ |
+ base::AutoLock lock(destroyed_lock_); |
+ return destroyed_; |
+} |
+ |
+void InProcessContextProvider::SetLostContextCallback( |
+ const LostContextCallback& lost_context_callback) { |
+ lost_context_callback_ = lost_context_callback; |
+} |
+ |
+void InProcessContextProvider::SetMemoryPolicyChangedCallback( |
+ const MemoryPolicyChangedCallback& memory_policy_changed_callback) { |
+ // There's no memory manager for the in-process implementation. |
+} |
+ |
+void InProcessContextProvider::OnLostContext() { |
+ DCHECK(context_thread_checker_.CalledOnValidThread()); |
+ { |
+ base::AutoLock lock(destroyed_lock_); |
+ if (destroyed_) |
+ return; |
+ destroyed_ = true; |
+ } |
+ if (!lost_context_callback_.is_null()) |
+ base::ResetAndReturn(&lost_context_callback_).Run(); |
+ if (gr_context_) |
+ gr_context_->abandonContext(); |
+} |
+ |
+} // namespace ui |