1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "webkit/common/gpu/context_provider_in_process.h" 6 7 #include "base/bind.h" 8 #include "base/callback_helpers.h" 9 #include "webkit/common/gpu/grcontext_for_webgraphicscontext3d.h" 10 #include "webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h" 11 12 namespace webkit { 13 namespace gpu { 14 15 class ContextProviderInProcess::LostContextCallbackProxy 16 : public WebKit::WebGraphicsContext3D::WebGraphicsContextLostCallback { 17 public: 18 explicit LostContextCallbackProxy(ContextProviderInProcess* provider) 19 : provider_(provider) { 20 provider_->context3d_->setContextLostCallback(this); 21 } 22 23 virtual ~LostContextCallbackProxy() { 24 provider_->context3d_->setContextLostCallback(NULL); 25 } 26 27 virtual void onContextLost() { 28 provider_->OnLostContext(); 29 } 30 31 private: 32 ContextProviderInProcess* provider_; 33 }; 34 35 class ContextProviderInProcess::MemoryAllocationCallbackProxy 36 : public WebKit::WebGraphicsContext3D:: 37 WebGraphicsMemoryAllocationChangedCallbackCHROMIUM { 38 public: 39 explicit MemoryAllocationCallbackProxy(ContextProviderInProcess* provider) 40 : provider_(provider) { 41 provider_->context3d_->setMemoryAllocationChangedCallbackCHROMIUM(this); 42 } 43 44 virtual ~MemoryAllocationCallbackProxy() { 45 provider_->context3d_->setMemoryAllocationChangedCallbackCHROMIUM(NULL); 46 } 47 48 virtual void onMemoryAllocationChanged( 49 WebKit::WebGraphicsMemoryAllocation alloc) { 50 provider_->OnMemoryAllocationChanged(!!alloc.gpuResourceSizeInBytes); 51 } 52 53 private: 54 ContextProviderInProcess* provider_; 55 }; 56 57 // static 58 scoped_refptr<ContextProviderInProcess> ContextProviderInProcess::Create( 59 const CreateCallback& create_callback) { 60 scoped_refptr<ContextProviderInProcess> provider = 61 new ContextProviderInProcess; 62 if (!provider->InitializeOnMainThread(create_callback)) 63 return NULL; 64 return provider; 65 } 66 67 static scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl> 68 CreateOffscreenContext() { 69 WebKit::WebGraphicsContext3D::Attributes attributes; 70 attributes.depth = false; 71 attributes.stencil = true; 72 attributes.antialias = false; 73 attributes.shareResources = true; 74 attributes.noAutomaticFlushes = true; 75 76 return WebGraphicsContext3DInProcessCommandBufferImpl::CreateOffscreenContext( 77 attributes).Pass(); 78 } 79 80 // static 81 scoped_refptr<ContextProviderInProcess> 82 ContextProviderInProcess::CreateOffscreen() { 83 return Create(base::Bind(&CreateOffscreenContext)); 84 } 85 86 ContextProviderInProcess::ContextProviderInProcess() 87 : destroyed_(false) { 88 DCHECK(main_thread_checker_.CalledOnValidThread()); 89 context_thread_checker_.DetachFromThread(); 90 } 91 92 ContextProviderInProcess::~ContextProviderInProcess() { 93 DCHECK(main_thread_checker_.CalledOnValidThread() || 94 context_thread_checker_.CalledOnValidThread()); 95 } 96 97 bool ContextProviderInProcess::InitializeOnMainThread( 98 const CreateCallback& create_callback) { 99 DCHECK(!context3d_); 100 DCHECK(main_thread_checker_.CalledOnValidThread()); 101 DCHECK(!create_callback.is_null()); 102 103 context3d_ = create_callback.Run(); 104 return context3d_; 105 } 106 107 bool ContextProviderInProcess::BindToCurrentThread() { 108 DCHECK(context3d_); 109 110 // This is called on the thread the context will be used. 111 DCHECK(context_thread_checker_.CalledOnValidThread()); 112 113 if (lost_context_callback_proxy_) 114 return true; 115 116 if (!context3d_->makeContextCurrent()) 117 return false; 118 119 lost_context_callback_proxy_.reset(new LostContextCallbackProxy(this)); 120 return true; 121 } 122 123 WebKit::WebGraphicsContext3D* ContextProviderInProcess::Context3d() { 124 DCHECK(context3d_); 125 DCHECK(lost_context_callback_proxy_); // Is bound to thread. 126 DCHECK(context_thread_checker_.CalledOnValidThread()); 127 128 return context3d_.get(); 129 } 130 131 class GrContext* ContextProviderInProcess::GrContext() { 132 DCHECK(context3d_); 133 DCHECK(lost_context_callback_proxy_); // Is bound to thread. 134 DCHECK(context_thread_checker_.CalledOnValidThread()); 135 136 if (gr_context_) 137 return gr_context_->get(); 138 139 gr_context_.reset( 140 new webkit::gpu::GrContextForWebGraphicsContext3D(context3d_.get())); 141 memory_allocation_callback_proxy_.reset( 142 new MemoryAllocationCallbackProxy(this)); 143 return gr_context_->get(); 144 } 145 146 void ContextProviderInProcess::VerifyContexts() { 147 DCHECK(context3d_); 148 DCHECK(lost_context_callback_proxy_); // Is bound to thread. 149 DCHECK(context_thread_checker_.CalledOnValidThread()); 150 151 if (context3d_->isContextLost()) 152 OnLostContext(); 153 } 154 155 void ContextProviderInProcess::OnLostContext() { 156 DCHECK(context_thread_checker_.CalledOnValidThread()); 157 { 158 base::AutoLock lock(destroyed_lock_); 159 if (destroyed_) 160 return; 161 destroyed_ = true; 162 } 163 if (!lost_context_callback_.is_null()) 164 base::ResetAndReturn(&lost_context_callback_).Run(); 165 } 166 167 bool ContextProviderInProcess::DestroyedOnMainThread() { 168 DCHECK(main_thread_checker_.CalledOnValidThread()); 169 170 base::AutoLock lock(destroyed_lock_); 171 return destroyed_; 172 } 173 174 void ContextProviderInProcess::SetLostContextCallback( 175 const LostContextCallback& lost_context_callback) { 176 DCHECK(context_thread_checker_.CalledOnValidThread()); 177 DCHECK(lost_context_callback_.is_null()); 178 lost_context_callback_ = lost_context_callback; 179 } 180 181 void ContextProviderInProcess::OnMemoryAllocationChanged( 182 bool nonzero_allocation) { 183 DCHECK(context_thread_checker_.CalledOnValidThread()); 184 if (gr_context_) 185 gr_context_->SetMemoryLimit(nonzero_allocation); 186 } 187 188 } // namespace gpu 189 } // namespace webkit 190