Supervised user import: Listen for profile creation/deletion
[chromium-blink-merge.git] / gpu / command_buffer / client / gl_in_process_context.cc
blob5d8049bceee7458b2671e143537bc40d79a91d5e
1 // Copyright (c) 2012 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.
5 #include "gpu/command_buffer/client/gl_in_process_context.h"
7 #include <set>
8 #include <utility>
9 #include <vector>
11 #include <GLES2/gl2.h>
12 #ifndef GL_GLEXT_PROTOTYPES
13 #define GL_GLEXT_PROTOTYPES 1
14 #endif
15 #include <GLES2/gl2ext.h>
16 #include <GLES2/gl2extchromium.h>
18 #include "base/bind.h"
19 #include "base/bind_helpers.h"
20 #include "base/lazy_instance.h"
21 #include "base/logging.h"
22 #include "base/memory/scoped_ptr.h"
23 #include "base/memory/weak_ptr.h"
24 #include "base/message_loop/message_loop.h"
25 #include "gpu/command_buffer/client/gles2_implementation.h"
26 #include "gpu/command_buffer/client/transfer_buffer.h"
27 #include "gpu/command_buffer/common/command_buffer.h"
28 #include "gpu/command_buffer/common/constants.h"
29 #include "ui/gfx/geometry/size.h"
30 #include "ui/gl/gl_image.h"
32 #if defined(OS_ANDROID)
33 #include "ui/gl/android/surface_texture.h"
34 #endif
36 namespace gpu {
38 namespace {
40 const int32 kDefaultCommandBufferSize = 1024 * 1024;
41 const unsigned int kDefaultStartTransferBufferSize = 4 * 1024 * 1024;
42 const unsigned int kDefaultMinTransferBufferSize = 1 * 256 * 1024;
43 const unsigned int kDefaultMaxTransferBufferSize = 16 * 1024 * 1024;
45 class GLInProcessContextImpl
46 : public GLInProcessContext,
47 public base::SupportsWeakPtr<GLInProcessContextImpl> {
48 public:
49 explicit GLInProcessContextImpl(
50 const GLInProcessContextSharedMemoryLimits& mem_limits);
51 ~GLInProcessContextImpl() override;
53 bool Initialize(scoped_refptr<gfx::GLSurface> surface,
54 bool is_offscreen,
55 bool use_global_share_group,
56 GLInProcessContext* share_context,
57 gfx::AcceleratedWidget window,
58 const gfx::Size& size,
59 const gpu::gles2::ContextCreationAttribHelper& attribs,
60 gfx::GpuPreference gpu_preference,
61 const scoped_refptr<InProcessCommandBuffer::Service>& service,
62 GpuMemoryBufferManager* gpu_memory_buffer_manager,
63 ImageFactory* image_factory);
65 // GLInProcessContext implementation:
66 void SetContextLostCallback(const base::Closure& callback) override;
67 gles2::GLES2Implementation* GetImplementation() override;
68 size_t GetMappedMemoryLimit() override;
69 void SetLock(base::Lock* lock) override;
71 #if defined(OS_ANDROID)
72 scoped_refptr<gfx::SurfaceTexture> GetSurfaceTexture(
73 uint32 stream_id) override;
74 #endif
76 private:
77 void Destroy();
78 void OnContextLost();
79 void OnSignalSyncPoint(const base::Closure& callback);
81 scoped_ptr<gles2::GLES2CmdHelper> gles2_helper_;
82 scoped_ptr<TransferBuffer> transfer_buffer_;
83 scoped_ptr<gles2::GLES2Implementation> gles2_implementation_;
84 scoped_ptr<InProcessCommandBuffer> command_buffer_;
86 const GLInProcessContextSharedMemoryLimits mem_limits_;
87 bool context_lost_;
88 base::Closure context_lost_callback_;
89 base::Lock* lock_;
91 DISALLOW_COPY_AND_ASSIGN(GLInProcessContextImpl);
94 base::LazyInstance<base::Lock> g_all_shared_contexts_lock =
95 LAZY_INSTANCE_INITIALIZER;
96 base::LazyInstance<std::set<GLInProcessContextImpl*> > g_all_shared_contexts =
97 LAZY_INSTANCE_INITIALIZER;
99 GLInProcessContextImpl::GLInProcessContextImpl(
100 const GLInProcessContextSharedMemoryLimits& mem_limits)
101 : mem_limits_(mem_limits), context_lost_(false), lock_(nullptr) {
104 GLInProcessContextImpl::~GLInProcessContextImpl() {
106 base::AutoLock lock(g_all_shared_contexts_lock.Get());
107 g_all_shared_contexts.Get().erase(this);
109 Destroy();
112 gles2::GLES2Implementation* GLInProcessContextImpl::GetImplementation() {
113 return gles2_implementation_.get();
116 size_t GLInProcessContextImpl::GetMappedMemoryLimit() {
117 return mem_limits_.mapped_memory_reclaim_limit;
120 void GLInProcessContextImpl::SetLock(base::Lock* lock) {
121 command_buffer_->SetLock(lock);
122 lock_ = lock;
125 void GLInProcessContextImpl::SetContextLostCallback(
126 const base::Closure& callback) {
127 context_lost_callback_ = callback;
130 void GLInProcessContextImpl::OnContextLost() {
131 scoped_ptr<base::AutoLock> lock;
132 if (lock_)
133 lock.reset(new base::AutoLock(*lock_));
134 context_lost_ = true;
135 if (!context_lost_callback_.is_null()) {
136 context_lost_callback_.Run();
140 bool GLInProcessContextImpl::Initialize(
141 scoped_refptr<gfx::GLSurface> surface,
142 bool is_offscreen,
143 bool use_global_share_group,
144 GLInProcessContext* share_context,
145 gfx::AcceleratedWidget window,
146 const gfx::Size& size,
147 const gles2::ContextCreationAttribHelper& attribs,
148 gfx::GpuPreference gpu_preference,
149 const scoped_refptr<InProcessCommandBuffer::Service>& service,
150 GpuMemoryBufferManager* gpu_memory_buffer_manager,
151 ImageFactory* image_factory) {
152 DCHECK(!use_global_share_group || !share_context);
153 DCHECK(size.width() >= 0 && size.height() >= 0);
155 std::vector<int32> attrib_vector;
156 attribs.Serialize(&attrib_vector);
158 base::Closure wrapped_callback =
159 base::Bind(&GLInProcessContextImpl::OnContextLost, AsWeakPtr());
160 command_buffer_.reset(new InProcessCommandBuffer(service));
162 scoped_ptr<base::AutoLock> scoped_shared_context_lock;
163 scoped_refptr<gles2::ShareGroup> share_group;
164 InProcessCommandBuffer* share_command_buffer = NULL;
165 if (use_global_share_group) {
166 scoped_shared_context_lock.reset(
167 new base::AutoLock(g_all_shared_contexts_lock.Get()));
168 for (std::set<GLInProcessContextImpl*>::const_iterator it =
169 g_all_shared_contexts.Get().begin();
170 it != g_all_shared_contexts.Get().end();
171 it++) {
172 const GLInProcessContextImpl* context = *it;
173 if (!context->context_lost_) {
174 share_group = context->gles2_implementation_->share_group();
175 share_command_buffer = context->command_buffer_.get();
176 DCHECK(share_group.get());
177 DCHECK(share_command_buffer);
178 break;
181 } else if (share_context) {
182 GLInProcessContextImpl* impl =
183 static_cast<GLInProcessContextImpl*>(share_context);
184 share_group = impl->gles2_implementation_->share_group();
185 share_command_buffer = impl->command_buffer_.get();
186 DCHECK(share_group.get());
187 DCHECK(share_command_buffer);
190 if (!command_buffer_->Initialize(surface,
191 is_offscreen,
192 window,
193 size,
194 attrib_vector,
195 gpu_preference,
196 wrapped_callback,
197 share_command_buffer,
198 gpu_memory_buffer_manager,
199 image_factory)) {
200 LOG(ERROR) << "Failed to initialize InProcessCommmandBuffer";
201 return false;
204 // Create the GLES2 helper, which writes the command buffer protocol.
205 gles2_helper_.reset(new gles2::GLES2CmdHelper(command_buffer_.get()));
206 if (!gles2_helper_->Initialize(mem_limits_.command_buffer_size)) {
207 LOG(ERROR) << "Failed to initialize GLES2CmdHelper";
208 Destroy();
209 return false;
212 // Create a transfer buffer.
213 transfer_buffer_.reset(new TransferBuffer(gles2_helper_.get()));
215 // Check for consistency.
216 DCHECK(!attribs.bind_generates_resource);
217 const bool bind_generates_resource = false;
218 const bool support_client_side_arrays = false;
220 // Create the object exposing the OpenGL API.
221 gles2_implementation_.reset(
222 new gles2::GLES2Implementation(gles2_helper_.get(),
223 share_group.get(),
224 transfer_buffer_.get(),
225 bind_generates_resource,
226 attribs.lose_context_when_out_of_memory,
227 support_client_side_arrays,
228 command_buffer_.get()));
230 if (use_global_share_group) {
231 g_all_shared_contexts.Get().insert(this);
232 scoped_shared_context_lock.reset();
235 if (!gles2_implementation_->Initialize(
236 mem_limits_.start_transfer_buffer_size,
237 mem_limits_.min_transfer_buffer_size,
238 mem_limits_.max_transfer_buffer_size,
239 mem_limits_.mapped_memory_reclaim_limit)) {
240 return false;
243 return true;
246 void GLInProcessContextImpl::Destroy() {
247 if (gles2_implementation_) {
248 // First flush the context to ensure that any pending frees of resources
249 // are completed. Otherwise, if this context is part of a share group,
250 // those resources might leak. Also, any remaining side effects of commands
251 // issued on this context might not be visible to other contexts in the
252 // share group.
253 gles2_implementation_->Flush();
255 gles2_implementation_.reset();
258 transfer_buffer_.reset();
259 gles2_helper_.reset();
260 command_buffer_.reset();
263 #if defined(OS_ANDROID)
264 scoped_refptr<gfx::SurfaceTexture>
265 GLInProcessContextImpl::GetSurfaceTexture(uint32 stream_id) {
266 return command_buffer_->GetSurfaceTexture(stream_id);
268 #endif
270 } // anonymous namespace
272 GLInProcessContextSharedMemoryLimits::GLInProcessContextSharedMemoryLimits()
273 : command_buffer_size(kDefaultCommandBufferSize),
274 start_transfer_buffer_size(kDefaultStartTransferBufferSize),
275 min_transfer_buffer_size(kDefaultMinTransferBufferSize),
276 max_transfer_buffer_size(kDefaultMaxTransferBufferSize),
277 mapped_memory_reclaim_limit(gles2::GLES2Implementation::kNoLimit) {
280 // static
281 GLInProcessContext* GLInProcessContext::Create(
282 scoped_refptr<gpu::InProcessCommandBuffer::Service> service,
283 scoped_refptr<gfx::GLSurface> surface,
284 bool is_offscreen,
285 gfx::AcceleratedWidget window,
286 const gfx::Size& size,
287 GLInProcessContext* share_context,
288 bool use_global_share_group,
289 const ::gpu::gles2::ContextCreationAttribHelper& attribs,
290 gfx::GpuPreference gpu_preference,
291 const GLInProcessContextSharedMemoryLimits& memory_limits,
292 GpuMemoryBufferManager* gpu_memory_buffer_manager,
293 ImageFactory* image_factory) {
294 DCHECK(!use_global_share_group || !share_context);
295 if (surface.get()) {
296 DCHECK_EQ(surface->IsOffscreen(), is_offscreen);
297 DCHECK(surface->GetSize() == size);
298 DCHECK_EQ(gfx::kNullAcceleratedWidget, window);
301 scoped_ptr<GLInProcessContextImpl> context(
302 new GLInProcessContextImpl(memory_limits));
303 if (!context->Initialize(surface,
304 is_offscreen,
305 use_global_share_group,
306 share_context,
307 window,
308 size,
309 attribs,
310 gpu_preference,
311 service,
312 gpu_memory_buffer_manager,
313 image_factory))
314 return NULL;
316 return context.release();
319 } // namespace gpu