Index: blimp/client/compositor/blimp_context_provider.cc |
diff --git a/blimp/client/compositor/blimp_context_provider.cc b/blimp/client/compositor/blimp_context_provider.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..57c46a74ef2f83d11a97572b73c4f770c3e993d1 |
--- /dev/null |
+++ b/blimp/client/compositor/blimp_context_provider.cc |
@@ -0,0 +1,188 @@ |
+// 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 "blimp/client/compositor/blimp_context_provider.h" |
+ |
+#include "base/bind.h" |
+#include "base/callback_helpers.h" |
+#include "base/lazy_instance.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 { |
+ |
+// 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; |
+ |
+static void BindGrContextCallback(const GrGLInterface* interface) { |
+ blimp::BlimpContextProvider* context_provider = |
+ reinterpret_cast<blimp::BlimpContextProvider*>(interface->fCallbackData); |
+ |
+ gles2::SetGLContext(context_provider->ContextGL()); |
+} |
+ |
+} // namespace |
+ |
+namespace blimp { |
+ |
+// static |
+scoped_refptr<BlimpContextProvider> BlimpContextProvider::Create( |
+ gfx::AcceleratedWidget widget) { |
+ return new BlimpContextProvider(widget); |
+} |
+ |
+BlimpContextProvider::BlimpContextProvider(gfx::AcceleratedWidget widget) { |
+ context_thread_checker_.DetachFromThread(); |
+ |
+ gpu::gles2::ContextCreationAttribHelper attribs_for_gles2; |
+ attribs_for_gles2.alpha_size = 8; |
+ attribs_for_gles2.depth_size = 0; |
+ attribs_for_gles2.stencil_size = 0; |
+ attribs_for_gles2.samples = 0; |
+ attribs_for_gles2.sample_buffers = 0; |
+ attribs_for_gles2.fail_if_major_perf_caveat = false; |
+ attribs_for_gles2.bind_generates_resource = false; |
+ attribs_for_gles2.webgl_version = 0; |
+ attribs_for_gles2.lose_context_when_out_of_memory = true; |
+ |
+ context_.reset(gpu::GLInProcessContext::Create( |
+ nullptr /* service */, nullptr /* surface */, false /* is_offscreen */, |
+ widget, gfx::Size(1, 1), nullptr /* share_context */, |
+ false /* share_resources */, attribs_for_gles2, gfx::PreferDiscreteGpu, |
+ gpu::GLInProcessContextSharedMemoryLimits(), |
+ nullptr /* gpu_memory_buffer_manager */, nullptr /* memory_limits */)); |
+ context_->SetContextLostCallback( |
+ base::Bind(&BlimpContextProvider::OnLostContext, base::Unretained(this))); |
+ CHECK(context_); |
danakj
2015/08/28 17:38:46
What's the point of this? You just crashed on the
David Trainor- moved to gerrit
2015/08/28 18:24:16
Gah I put it in the wrong place, I meant to put it
Wez
2015/08/31 16:27:18
Actually, if you're about to deref the variable, a
David Trainor- moved to gerrit
2015/08/31 21:25:43
Yeah that's true. I can make that change here bec
David Trainor- moved to gerrit
2015/08/31 21:27:28
scoped_ptr does have an assert, but it looks like
|
+} |
+ |
+BlimpContextProvider::~BlimpContextProvider() { |
+ DCHECK(main_thread_checker_.CalledOnValidThread() || |
+ context_thread_checker_.CalledOnValidThread()); |
+} |
+ |
+bool BlimpContextProvider::BindToCurrentThread() { |
+ DCHECK(context_thread_checker_.CalledOnValidThread()); |
+ capabilities_.gpu = context_->GetImplementation()->capabilities(); |
+ capabilities_.gpu.image = true; |
+ return true; |
+} |
+ |
+void BlimpContextProvider::DetachFromThread() { |
+ context_thread_checker_.DetachFromThread(); |
+} |
+ |
+cc::ContextProvider::Capabilities BlimpContextProvider::ContextCapabilities() { |
+ DCHECK(context_thread_checker_.CalledOnValidThread()); |
+ return capabilities_; |
+} |
+ |
+gpu::gles2::GLES2Interface* BlimpContextProvider::ContextGL() { |
+ DCHECK(context_thread_checker_.CalledOnValidThread()); |
+ return context_->GetImplementation(); |
+} |
+ |
+gpu::ContextSupport* BlimpContextProvider::ContextSupport() { |
+ DCHECK(context_thread_checker_.CalledOnValidThread()); |
+ return context_->GetImplementation(); |
+} |
+ |
+class GrContext* BlimpContextProvider::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(); |
+} |
+ |
+void BlimpContextProvider::InvalidateGrContext(uint32_t state) { |
+ DCHECK(context_thread_checker_.CalledOnValidThread()); |
+ |
+ if (gr_context_) |
+ gr_context_.get()->resetContext(state); |
+} |
+ |
+void BlimpContextProvider::SetupLock() { |
+ context_->SetLock(&context_lock_); |
+} |
+ |
+base::Lock* BlimpContextProvider::GetLock() { |
+ return &context_lock_; |
+} |
+ |
+void BlimpContextProvider::VerifyContexts() { |
+ DCHECK(context_thread_checker_.CalledOnValidThread()); |
+} |
+ |
+void BlimpContextProvider::DeleteCachedResources() { |
+ DCHECK(context_thread_checker_.CalledOnValidThread()); |
+ |
+ if (gr_context_) |
+ gr_context_->freeGpuResources(); |
+} |
+ |
+bool BlimpContextProvider::DestroyedOnMainThread() { |
+ DCHECK(main_thread_checker_.CalledOnValidThread()); |
+ |
+ base::AutoLock lock(destroyed_lock_); |
+ return destroyed_; |
+} |
+ |
+void BlimpContextProvider::SetLostContextCallback( |
+ const LostContextCallback& lost_context_callback) { |
+ DCHECK(context_thread_checker_.CalledOnValidThread()); |
+ lost_context_callback_ = lost_context_callback; |
+} |
+ |
+void BlimpContextProvider::SetMemoryPolicyChangedCallback( |
+ const MemoryPolicyChangedCallback& memory_policy_changed_callback) { |
+ // There's no memory manager for the in-process implementation. |
+} |
+ |
+void BlimpContextProvider::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 blimp |