Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(159)

Side by Side Diff: gpu/command_buffer/client/gl_in_process_context.cc

Issue 19522006: GLInProcessContext: support async flushes and dedicated GPU thread (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: address comments Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "gpu/command_buffer/client/gl_in_process_context.h" 5 #include "gpu/command_buffer/client/gl_in_process_context.h"
6 6
7 #include <utility> 7 #include <utility>
8 #include <vector> 8 #include <vector>
9 9
10 #include <GLES2/gl2.h> 10 #include <GLES2/gl2.h>
11 #ifndef GL_GLEXT_PROTOTYPES 11 #ifndef GL_GLEXT_PROTOTYPES
12 #define GL_GLEXT_PROTOTYPES 1 12 #define GL_GLEXT_PROTOTYPES 1
13 #endif 13 #endif
14 #include <GLES2/gl2ext.h> 14 #include <GLES2/gl2ext.h>
15 #include <GLES2/gl2extchromium.h> 15 #include <GLES2/gl2extchromium.h>
16 16
17 #include "base/bind.h" 17 #include "base/bind.h"
18 #include "base/bind_helpers.h" 18 #include "base/bind_helpers.h"
19 #include "base/callback.h"
20 #include "base/lazy_instance.h" 19 #include "base/lazy_instance.h"
21 #include "base/logging.h" 20 #include "base/logging.h"
22 #include "base/memory/scoped_ptr.h" 21 #include "base/memory/scoped_ptr.h"
23 #include "base/memory/weak_ptr.h" 22 #include "base/memory/weak_ptr.h"
24 #include "base/message_loop/message_loop.h" 23 #include "base/message_loop/message_loop.h"
25 #include "base/synchronization/lock.h"
26 #include "gpu/command_buffer/client/gles2_implementation.h" 24 #include "gpu/command_buffer/client/gles2_implementation.h"
27 #include "gpu/command_buffer/client/gpu_memory_buffer.h" 25 #include "gpu/command_buffer/client/gpu_memory_buffer.h"
28 #include "gpu/command_buffer/client/image_factory.h" 26 #include "gpu/command_buffer/client/image_factory.h"
29 #include "gpu/command_buffer/client/transfer_buffer.h" 27 #include "gpu/command_buffer/client/transfer_buffer.h"
28 #include "gpu/command_buffer/common/command_buffer.h"
30 #include "gpu/command_buffer/common/constants.h" 29 #include "gpu/command_buffer/common/constants.h"
31 #include "gpu/command_buffer/common/id_allocator.h" 30 #include "gpu/command_buffer/service/in_process_command_buffer.h"
32 #include "gpu/command_buffer/service/command_buffer_service.h"
33 #include "gpu/command_buffer/service/context_group.h"
34 #include "gpu/command_buffer/service/gl_context_virtual.h"
35 #include "gpu/command_buffer/service/gpu_scheduler.h"
36 #include "gpu/command_buffer/service/image_manager.h"
37 #include "gpu/command_buffer/service/transfer_buffer_manager.h"
38 #include "ui/gfx/size.h" 31 #include "ui/gfx/size.h"
39 #include "ui/gl/gl_context.h"
40 #include "ui/gl/gl_image.h" 32 #include "ui/gl/gl_image.h"
41 #include "ui/gl/gl_share_group.h"
42 #include "ui/gl/gl_surface.h"
43 33
44 namespace gpu { 34 namespace gpu {
45 35
46 using gles2::ImageManager;
47
48 namespace { 36 namespace {
49 37
50 const int32 kCommandBufferSize = 1024 * 1024; 38 const int32 kCommandBufferSize = 1024 * 1024;
51 // TODO(kbr): make the transfer buffer size configurable via context 39 // TODO(kbr): make the transfer buffer size configurable via context
52 // creation attributes. 40 // creation attributes.
53 const size_t kStartTransferBufferSize = 4 * 1024 * 1024; 41 const size_t kStartTransferBufferSize = 4 * 1024 * 1024;
54 const size_t kMinTransferBufferSize = 1 * 256 * 1024; 42 const size_t kMinTransferBufferSize = 1 * 256 * 1024;
55 const size_t kMaxTransferBufferSize = 16 * 1024 * 1024; 43 const size_t kMaxTransferBufferSize = 16 * 1024 * 1024;
56 44
57 // In the normal command buffer implementation, all commands are passed over IPC
58 // to the gpu process where they are fed to the GLES2Decoder from a single
59 // thread. In layout tests, any thread could call this function. GLES2Decoder,
60 // and in particular the GL implementations behind it, are not generally
61 // threadsafe, so we guard entry points with a mutex.
62 static base::LazyInstance<base::Lock> g_decoder_lock =
63 LAZY_INSTANCE_INITIALIZER;
64
65 class GLInProcessContextImpl;
66
67 static base::LazyInstance<
68 std::set<GLInProcessContextImpl*> >
69 g_all_shared_contexts = LAZY_INSTANCE_INITIALIZER;
70
71 static bool g_use_virtualized_gl_context = false;
72
73 static GLInProcessContext::GpuMemoryBufferCreator* g_gpu_memory_buffer_creator = 45 static GLInProcessContext::GpuMemoryBufferCreator* g_gpu_memory_buffer_creator =
74 NULL; 46 NULL;
75 47
76 // Also calls DetachFromThreadHack on all GLES2Decoders before the lock is
77 // released to maintain the invariant that all decoders are unbound while the
78 // lock is not held. This is to workaround DumpRenderTree using WGC3DIPCBI with
79 // shared resources on different threads.
80 // Remove this as part of crbug.com/234964.
81 class AutoLockAndDecoderDetachThread {
82 public:
83 AutoLockAndDecoderDetachThread(
84 base::Lock& lock,
85 const std::set<GLInProcessContextImpl*>& contexts);
86 ~AutoLockAndDecoderDetachThread();
87
88 private:
89 base::AutoLock auto_lock_;
90 const std::set<GLInProcessContextImpl*>& contexts_;
91 };
92
93 class GLInProcessContextImpl 48 class GLInProcessContextImpl
94 : public GLInProcessContext, 49 : public GLInProcessContext,
95 public gles2::ImageFactory, 50 public gles2::ImageFactory,
96 public base::SupportsWeakPtr<GLInProcessContextImpl> { 51 public base::SupportsWeakPtr<GLInProcessContextImpl> {
97 public: 52 public:
98 explicit GLInProcessContextImpl(bool share_resources); 53 explicit GLInProcessContextImpl();
99 virtual ~GLInProcessContextImpl(); 54 virtual ~GLInProcessContextImpl();
100 55
101 bool Initialize(bool is_offscreen, 56 bool Initialize(bool is_offscreen,
57 bool share_resources,
102 gfx::AcceleratedWidget window, 58 gfx::AcceleratedWidget window,
103 const gfx::Size& size, 59 const gfx::Size& size,
104 const char* allowed_extensions, 60 const char* allowed_extensions,
105 const int32* attrib_list, 61 const int32* attrib_list,
106 gfx::GpuPreference gpu_preference, 62 gfx::GpuPreference gpu_preference,
107 const base::Closure& context_lost_callback); 63 const base::Closure& context_lost_callback);
108 64
109 // GLInProcessContext implementation: 65 // GLInProcessContext implementation:
110 virtual void SignalSyncPoint(unsigned sync_point, 66 virtual void SignalSyncPoint(unsigned sync_point,
111 const base::Closure& callback) OVERRIDE; 67 const base::Closure& callback) OVERRIDE;
112 virtual void SignalQuery(unsigned query, const base::Closure& callback) 68 virtual void SignalQuery(unsigned query, const base::Closure& callback)
113 OVERRIDE; 69 OVERRIDE;
114 virtual gles2::GLES2Implementation* GetImplementation() OVERRIDE; 70 virtual gles2::GLES2Implementation* GetImplementation() OVERRIDE;
115 71
116 // ImageFactory implementation: 72 // ImageFactory implementation:
117 virtual scoped_ptr<GpuMemoryBuffer> CreateGpuMemoryBuffer( 73 virtual scoped_ptr<GpuMemoryBuffer> CreateGpuMemoryBuffer(
118 int width, int height, GLenum internalformat, 74 int width, int height, GLenum internalformat,
119 unsigned* image_id) OVERRIDE; 75 unsigned* image_id) OVERRIDE;
120 virtual void DeleteGpuMemoryBuffer(unsigned image_id) OVERRIDE; 76 virtual void DeleteGpuMemoryBuffer(unsigned image_id) OVERRIDE;
121 77
122 // Other methods:
123 gles2::GLES2Decoder* GetDecoder();
124 bool GetBufferChanged(int32 transfer_buffer_id);
125 void PumpCommands();
126 void OnResizeView(gfx::Size size, float scale_factor);
127 void OnContextLost();
128
129 private: 78 private:
130 void Destroy(); 79 void Destroy();
131 bool IsCommandBufferContextLost();
132 void PollQueryCallbacks(); 80 void PollQueryCallbacks();
133 void CallQueryCallback(size_t index); 81 void CallQueryCallback(size_t index);
134 bool MakeCurrent();
135 82
136 gles2::ImageManager* GetImageManager();
137
138 base::Closure context_lost_callback_;
139 scoped_ptr<TransferBufferManagerInterface> transfer_buffer_manager_;
140 scoped_ptr<CommandBuffer> command_buffer_;
141 scoped_ptr<GpuScheduler> gpu_scheduler_;
142 scoped_ptr<gles2::GLES2Decoder> decoder_;
143 scoped_refptr<gfx::GLContext> context_;
144 scoped_refptr<gfx::GLSurface> surface_;
145 scoped_ptr<gles2::GLES2CmdHelper> gles2_helper_; 83 scoped_ptr<gles2::GLES2CmdHelper> gles2_helper_;
146 scoped_ptr<TransferBuffer> transfer_buffer_; 84 scoped_ptr<TransferBuffer> transfer_buffer_;
147 scoped_ptr<gles2::GLES2Implementation> gles2_implementation_; 85 scoped_ptr<gles2::GLES2Implementation> gles2_implementation_;
148 bool share_resources_; 86 scoped_ptr<InProcessCommandBuffer> command_buffer_;
149 bool context_lost_;
150 87
151 typedef std::pair<unsigned, base::Closure> QueryCallback; 88 typedef std::pair<unsigned, base::Closure> QueryCallback;
152 std::vector<QueryCallback> query_callbacks_; 89 std::vector<QueryCallback> query_callbacks_;
153 90
154 std::vector<base::Closure> signal_sync_point_callbacks_;
155
156 DISALLOW_COPY_AND_ASSIGN(GLInProcessContextImpl); 91 DISALLOW_COPY_AND_ASSIGN(GLInProcessContextImpl);
157 }; 92 };
158 93
159 AutoLockAndDecoderDetachThread::AutoLockAndDecoderDetachThread(
160 base::Lock& lock,
161 const std::set<GLInProcessContextImpl*>& contexts)
162 : auto_lock_(lock),
163 contexts_(contexts) {
164 }
165
166 void DetachThread(GLInProcessContextImpl* context) {
167 if (context->GetDecoder())
168 context->GetDecoder()->DetachFromThreadHack();
169 }
170
171 AutoLockAndDecoderDetachThread::~AutoLockAndDecoderDetachThread() {
172 std::for_each(contexts_.begin(),
173 contexts_.end(),
174 &DetachThread);
175 }
176
177 scoped_ptr<GpuMemoryBuffer> GLInProcessContextImpl::CreateGpuMemoryBuffer( 94 scoped_ptr<GpuMemoryBuffer> GLInProcessContextImpl::CreateGpuMemoryBuffer(
178 int width, int height, GLenum internalformat, unsigned int* image_id) { 95 int width, int height, GLenum internalformat, unsigned int* image_id) {
179 // We're taking the lock here because we're accessing the ContextGroup's
180 // shared IdManager.
181 AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(),
182 g_all_shared_contexts.Get());
183 // For Android WebView we assume the |internalformat| will always be 96 // For Android WebView we assume the |internalformat| will always be
184 // GL_RGBA8_OES. 97 // GL_RGBA8_OES.
185 DCHECK_EQ(static_cast<GLenum>(GL_RGBA8_OES), internalformat); 98 DCHECK_EQ(static_cast<GLenum>(GL_RGBA8_OES), internalformat);
186 scoped_ptr<GpuMemoryBuffer> buffer = 99 scoped_ptr<GpuMemoryBuffer> buffer =
187 g_gpu_memory_buffer_creator(width, height); 100 g_gpu_memory_buffer_creator(width, height);
188 101
189 if (buffer.get() == NULL) 102 if (buffer.get() == NULL)
190 return buffer.Pass(); 103 return buffer.Pass();
191 104
192 scoped_refptr<gfx::GLImage> gl_image = 105 *image_id = command_buffer_->CreateImageForGpuMemoryBuffer(
193 gfx::GLImage::CreateGLImageForGpuMemoryBuffer(buffer->GetNativeBuffer(), 106 buffer->GetNativeBuffer(), gfx::Size(width, height));
194 gfx::Size(width, height));
195 *image_id = decoder_->GetContextGroup()
196 ->GetIdAllocator(gles2::id_namespaces::kImages)->AllocateID();
197 GetImageManager()->AddImage(gl_image.get(), *image_id);
198 return buffer.Pass(); 107 return buffer.Pass();
199 } 108 }
200 109
201 void GLInProcessContextImpl::DeleteGpuMemoryBuffer(unsigned int image_id) { 110 void GLInProcessContextImpl::DeleteGpuMemoryBuffer(unsigned int image_id) {
202 // We're taking the lock here because we're accessing the ContextGroup's 111 command_buffer_->RemoveImage(image_id);
203 // shared ImageManager.
204 AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(),
205 g_all_shared_contexts.Get());
206 GetImageManager()->RemoveImage(image_id);
207 decoder_->GetContextGroup()->GetIdAllocator(gles2::id_namespaces::kImages)
208 ->FreeID(image_id);
209 } 112 }
210 113
211 GLInProcessContextImpl::GLInProcessContextImpl(bool share_resources) 114 GLInProcessContextImpl::GLInProcessContextImpl() {}
212 : share_resources_(share_resources),
213 context_lost_(false) {
214 }
215 115
216 GLInProcessContextImpl::~GLInProcessContextImpl() { 116 GLInProcessContextImpl::~GLInProcessContextImpl() {
217 Destroy(); 117 Destroy();
218 } 118 }
219 119
220 bool GLInProcessContextImpl::MakeCurrent() {
221 if (decoder_->MakeCurrent())
222 return true;
223 DLOG(ERROR) << "Context lost because MakeCurrent failed.";
224 command_buffer_->SetContextLostReason(decoder_->GetContextLostReason());
225 command_buffer_->SetParseError(gpu::error::kLostContext);
226 return false;
227 }
228
229 void GLInProcessContextImpl::PumpCommands() {
230 {
231 AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(),
232 g_all_shared_contexts.Get());
233 if (!MakeCurrent())
234 return;
235 gpu_scheduler_->PutChanged();
236 CommandBuffer::State state = command_buffer_->GetState();
237 DCHECK((!error::IsError(state.error) && !context_lost_) ||
238 (error::IsError(state.error) && context_lost_));
239 }
240
241 if (!context_lost_ && signal_sync_point_callbacks_.size()) {
242 for (size_t n = 0; n < signal_sync_point_callbacks_.size(); n++) {
243 base::MessageLoop::current()->PostTask(FROM_HERE,
244 signal_sync_point_callbacks_[n]);
245 }
246 }
247 signal_sync_point_callbacks_.clear();
248 }
249
250 bool GLInProcessContextImpl::GetBufferChanged(int32 transfer_buffer_id) {
251 return gpu_scheduler_->SetGetBuffer(transfer_buffer_id);
252 }
253
254 void GLInProcessContextImpl::SignalSyncPoint(unsigned sync_point, 120 void GLInProcessContextImpl::SignalSyncPoint(unsigned sync_point,
255 const base::Closure& callback) { 121 const base::Closure& callback) {
256 DCHECK(!callback.is_null()); 122 DCHECK(!callback.is_null());
257 signal_sync_point_callbacks_.push_back(callback); 123 command_buffer_->SignalSyncPoint(sync_point, callback);
258 }
259
260 bool GLInProcessContextImpl::IsCommandBufferContextLost() {
261 if (context_lost_ || !command_buffer_) {
262 return true;
263 }
264 CommandBuffer::State state = command_buffer_->GetState();
265 return error::IsError(state.error);
266 }
267
268 gles2::GLES2Decoder* GLInProcessContextImpl::GetDecoder() {
269 return decoder_.get();
270 }
271
272 void GLInProcessContextImpl::OnResizeView(gfx::Size size, float scale_factor) {
273 DCHECK(!surface_->IsOffscreen());
274 surface_->Resize(size);
275 } 124 }
276 125
277 gles2::GLES2Implementation* GLInProcessContextImpl::GetImplementation() { 126 gles2::GLES2Implementation* GLInProcessContextImpl::GetImplementation() {
278 return gles2_implementation_.get(); 127 return gles2_implementation_.get();
279 } 128 }
280 129
281 gles2::ImageManager* GLInProcessContextImpl::GetImageManager() {
282 return decoder_->GetContextGroup()->image_manager();
283 }
284
285 bool GLInProcessContextImpl::Initialize( 130 bool GLInProcessContextImpl::Initialize(
286 bool is_offscreen, 131 bool is_offscreen,
132 bool share_resources,
287 gfx::AcceleratedWidget window, 133 gfx::AcceleratedWidget window,
288 const gfx::Size& size, 134 const gfx::Size& size,
289 const char* allowed_extensions, 135 const char* allowed_extensions,
290 const int32* attrib_list, 136 const int32* attrib_list,
291 gfx::GpuPreference gpu_preference, 137 gfx::GpuPreference gpu_preference,
292 const base::Closure& context_lost_callback) { 138 const base::Closure& context_lost_callback) {
293 // Use one share group for all contexts.
294 CR_DEFINE_STATIC_LOCAL(scoped_refptr<gfx::GLShareGroup>, share_group,
295 (new gfx::GLShareGroup));
296
297 DCHECK(size.width() >= 0 && size.height() >= 0); 139 DCHECK(size.width() >= 0 && size.height() >= 0);
298 140
299 std::vector<int32> attribs; 141 std::vector<int32> attribs;
300 while (attrib_list) { 142 while (attrib_list) {
301 int32 attrib = *attrib_list++; 143 int32 attrib = *attrib_list++;
302 switch (attrib) { 144 switch (attrib) {
303 // Known attributes 145 // Known attributes
304 case ALPHA_SIZE: 146 case ALPHA_SIZE:
305 case BLUE_SIZE: 147 case BLUE_SIZE:
306 case GREEN_SIZE: 148 case GREEN_SIZE:
307 case RED_SIZE: 149 case RED_SIZE:
308 case DEPTH_SIZE: 150 case DEPTH_SIZE:
309 case STENCIL_SIZE: 151 case STENCIL_SIZE:
310 case SAMPLES: 152 case SAMPLES:
311 case SAMPLE_BUFFERS: 153 case SAMPLE_BUFFERS:
312 attribs.push_back(attrib); 154 attribs.push_back(attrib);
313 attribs.push_back(*attrib_list++); 155 attribs.push_back(*attrib_list++);
314 break; 156 break;
315 case NONE: 157 case NONE:
316 attribs.push_back(attrib); 158 attribs.push_back(attrib);
317 attrib_list = NULL; 159 attrib_list = NULL;
318 break; 160 break;
319 default: 161 default:
320 attribs.push_back(NONE); 162 attribs.push_back(NONE);
321 attrib_list = NULL; 163 attrib_list = NULL;
322 break; 164 break;
323 } 165 }
324 } 166 }
325 167
326 { 168 command_buffer_.reset(new InProcessCommandBuffer());
327 TransferBufferManager* manager = new TransferBufferManager(); 169 scoped_refptr<gles2::ShareGroup> share_group;
328 transfer_buffer_manager_.reset(manager); 170 if (!command_buffer_->Initialize(is_offscreen,
329 manager->Initialize(); 171 share_resources,
330 } 172 window,
331 173 size,
332 scoped_ptr<CommandBufferService> command_buffer( 174 allowed_extensions,
333 new CommandBufferService(transfer_buffer_manager_.get())); 175 attribs,
334 command_buffer->SetPutOffsetChangeCallback(base::Bind( 176 gpu_preference,
335 &GLInProcessContextImpl::PumpCommands, base::Unretained(this))); 177 context_lost_callback,
336 command_buffer->SetGetBufferChangeCallback(base::Bind( 178 &share_group)) {
337 &GLInProcessContextImpl::GetBufferChanged, base::Unretained(this))); 179 LOG(INFO) << "Failed to initialize InProcessCommmandBuffer";
338 command_buffer->SetParseErrorCallback(base::Bind(
339 &GLInProcessContextImpl::OnContextLost, base::Unretained(this)));
340
341 command_buffer_ = command_buffer.Pass();
342 if (!command_buffer_->Initialize()) {
343 LOG(ERROR) << "Could not initialize command buffer.";
344 Destroy();
345 return false; 180 return false;
346 } 181 }
347 182 DCHECK(share_resources == !!share_group.get());
348 GLInProcessContextImpl* context_group = NULL;
349
350 {
351 AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(),
352 g_all_shared_contexts.Get());
353 if (share_resources_ && !g_all_shared_contexts.Get().empty()) {
354 for (std::set<GLInProcessContextImpl*>::iterator it =
355 g_all_shared_contexts.Get().begin();
356 it != g_all_shared_contexts.Get().end();
357 ++it) {
358 if (!(*it)->IsCommandBufferContextLost()) {
359 context_group = *it;
360 break;
361 }
362 }
363 if (!context_group)
364 share_group = new gfx::GLShareGroup;
365 }
366
367 // TODO(gman): This needs to be true if this is Pepper.
368 bool bind_generates_resource = false;
369 decoder_.reset(gles2::GLES2Decoder::Create(
370 context_group ? context_group->decoder_->GetContextGroup()
371 : new gles2::ContextGroup(
372 NULL, NULL, NULL, NULL, bind_generates_resource)));
373
374 gpu_scheduler_.reset(new GpuScheduler(command_buffer_.get(),
375 decoder_.get(),
376 decoder_.get()));
377
378 decoder_->set_engine(gpu_scheduler_.get());
379
380 if (is_offscreen)
381 surface_ = gfx::GLSurface::CreateOffscreenGLSurface(size);
382 else
383 surface_ = gfx::GLSurface::CreateViewGLSurface(window);
384
385 if (!surface_.get()) {
386 LOG(ERROR) << "Could not create GLSurface.";
387 Destroy();
388 return false;
389 }
390
391 if (g_use_virtualized_gl_context) {
392 context_ = share_group->GetSharedContext();
393 if (!context_.get()) {
394 context_ = gfx::GLContext::CreateGLContext(
395 share_group.get(), surface_.get(), gpu_preference);
396 share_group->SetSharedContext(context_.get());
397 }
398
399 context_ = new GLContextVirtual(
400 share_group.get(), context_.get(), decoder_->AsWeakPtr());
401 if (context_->Initialize(surface_.get(), gpu_preference)) {
402 VLOG(1) << "Created virtual GL context.";
403 } else {
404 context_ = NULL;
405 }
406 } else {
407 context_ = gfx::GLContext::CreateGLContext(share_group.get(),
408 surface_.get(),
409 gpu_preference);
410 }
411
412 if (!context_.get()) {
413 LOG(ERROR) << "Could not create GLContext.";
414 Destroy();
415 return false;
416 }
417
418 if (!context_->MakeCurrent(surface_.get())) {
419 LOG(ERROR) << "Could not make context current.";
420 Destroy();
421 return false;
422 }
423
424 gles2::DisallowedFeatures disallowed_features;
425 disallowed_features.swap_buffer_complete_callback = true;
426 disallowed_features.gpu_memory_manager = true;
427 if (!decoder_->Initialize(surface_,
428 context_,
429 is_offscreen,
430 size,
431 disallowed_features,
432 allowed_extensions,
433 attribs)) {
434 LOG(ERROR) << "Could not initialize decoder.";
435 Destroy();
436 return false;
437 }
438
439 if (!is_offscreen) {
440 decoder_->SetResizeCallback(base::Bind(
441 &GLInProcessContextImpl::OnResizeView, base::Unretained(this)));
442 }
443 }
444 183
445 // Create the GLES2 helper, which writes the command buffer protocol. 184 // Create the GLES2 helper, which writes the command buffer protocol.
446 gles2_helper_.reset(new gles2::GLES2CmdHelper(command_buffer_.get())); 185 gles2_helper_.reset(new gles2::GLES2CmdHelper(command_buffer_.get()));
447 if (!gles2_helper_->Initialize(kCommandBufferSize)) { 186 if (!gles2_helper_->Initialize(kCommandBufferSize)) {
187 LOG(INFO) << "Failed to initialize GLES2CmdHelper";
448 Destroy(); 188 Destroy();
449 return false; 189 return false;
450 } 190 }
451 191
452 // Create a transfer buffer. 192 // Create a transfer buffer.
453 transfer_buffer_.reset(new TransferBuffer(gles2_helper_.get())); 193 transfer_buffer_.reset(new TransferBuffer(gles2_helper_.get()));
454 194
455 // Create the object exposing the OpenGL API. 195 // Create the object exposing the OpenGL API.
456 gles2_implementation_.reset(new gles2::GLES2Implementation( 196 gles2_implementation_.reset(new gles2::GLES2Implementation(
457 gles2_helper_.get(), 197 gles2_helper_.get(),
458 context_group ? context_group->GetImplementation()->share_group() : NULL, 198 share_group,
459 transfer_buffer_.get(), 199 transfer_buffer_.get(),
460 true, 200 true,
461 false, 201 false,
462 this)); 202 this));
463 203
464 if (!gles2_implementation_->Initialize( 204 if (!gles2_implementation_->Initialize(
465 kStartTransferBufferSize, 205 kStartTransferBufferSize,
466 kMinTransferBufferSize, 206 kMinTransferBufferSize,
467 kMaxTransferBufferSize)) { 207 kMaxTransferBufferSize)) {
468 return false; 208 return false;
469 } 209 }
470 210
471 if (share_resources_) {
472 AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(),
473 g_all_shared_contexts.Get());
474 g_all_shared_contexts.Pointer()->insert(this);
475 }
476
477 context_lost_callback_ = context_lost_callback;
478 return true; 211 return true;
479 } 212 }
480 213
481 void GLInProcessContextImpl::Destroy() { 214 void GLInProcessContextImpl::Destroy() {
482 while (!query_callbacks_.empty()) { 215 while (!query_callbacks_.empty()) {
483 CallQueryCallback(0); 216 CallQueryCallback(0);
484 } 217 }
485 218
486 bool context_lost = IsCommandBufferContextLost();
487
488 if (gles2_implementation_) { 219 if (gles2_implementation_) {
489 // First flush the context to ensure that any pending frees of resources 220 // First flush the context to ensure that any pending frees of resources
490 // are completed. Otherwise, if this context is part of a share group, 221 // are completed. Otherwise, if this context is part of a share group,
491 // those resources might leak. Also, any remaining side effects of commands 222 // those resources might leak. Also, any remaining side effects of commands
492 // issued on this context might not be visible to other contexts in the 223 // issued on this context might not be visible to other contexts in the
493 // share group. 224 // share group.
494 gles2_implementation_->Flush(); 225 gles2_implementation_->Flush();
495 226
496 gles2_implementation_.reset(); 227 gles2_implementation_.reset();
497 } 228 }
498 229
499 transfer_buffer_.reset(); 230 transfer_buffer_.reset();
500 gles2_helper_.reset(); 231 gles2_helper_.reset();
501 command_buffer_.reset(); 232 command_buffer_.reset();
502
503 AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(),
504 g_all_shared_contexts.Get());
505 if (decoder_) {
506 decoder_->Destroy(!context_lost);
507 }
508
509 g_all_shared_contexts.Pointer()->erase(this);
510 }
511
512 void GLInProcessContextImpl::OnContextLost() {
513 if (!context_lost_callback_.is_null())
514 context_lost_callback_.Run();
515
516 context_lost_ = true;
517 if (share_resources_) {
518 for (std::set<GLInProcessContextImpl*>::iterator it =
519 g_all_shared_contexts.Get().begin();
520 it != g_all_shared_contexts.Get().end();
521 ++it)
522 (*it)->context_lost_ = true;
523 }
524 } 233 }
525 234
526 void GLInProcessContextImpl::CallQueryCallback(size_t index) { 235 void GLInProcessContextImpl::CallQueryCallback(size_t index) {
527 DCHECK_LT(index, query_callbacks_.size()); 236 DCHECK_LT(index, query_callbacks_.size());
528 QueryCallback query_callback = query_callbacks_[index]; 237 QueryCallback query_callback = query_callbacks_[index];
529 query_callbacks_[index] = query_callbacks_.back(); 238 query_callbacks_[index] = query_callbacks_.back();
530 query_callbacks_.pop_back(); 239 query_callbacks_.pop_back();
531 query_callback.second.Run(); 240 query_callback.second.Run();
532 } 241 }
533 242
243 // TODO(sievers): Move this to the service side
534 void GLInProcessContextImpl::PollQueryCallbacks() { 244 void GLInProcessContextImpl::PollQueryCallbacks() {
535 for (size_t i = 0; i < query_callbacks_.size();) { 245 for (size_t i = 0; i < query_callbacks_.size();) {
536 unsigned query = query_callbacks_[i].first; 246 unsigned query = query_callbacks_[i].first;
537 GLuint param = 0; 247 GLuint param = 0;
538 gles2::GLES2Implementation* gl = GetImplementation(); 248 gles2::GLES2Implementation* gl = GetImplementation();
539 if (gl->IsQueryEXT(query)) { 249 if (gl->IsQueryEXT(query)) {
540 gl->GetQueryObjectuivEXT(query, GL_QUERY_RESULT_AVAILABLE_EXT, &param); 250 gl->GetQueryObjectuivEXT(query, GL_QUERY_RESULT_AVAILABLE_EXT, &param);
541 } else { 251 } else {
542 param = 1; 252 param = 1;
543 } 253 }
(...skipping 28 matching lines...) Expand all
572 GLInProcessContext* GLInProcessContext::CreateContext( 282 GLInProcessContext* GLInProcessContext::CreateContext(
573 bool is_offscreen, 283 bool is_offscreen,
574 gfx::AcceleratedWidget window, 284 gfx::AcceleratedWidget window,
575 const gfx::Size& size, 285 const gfx::Size& size,
576 bool share_resources, 286 bool share_resources,
577 const char* allowed_extensions, 287 const char* allowed_extensions,
578 const int32* attrib_list, 288 const int32* attrib_list,
579 gfx::GpuPreference gpu_preference, 289 gfx::GpuPreference gpu_preference,
580 const base::Closure& callback) { 290 const base::Closure& callback) {
581 scoped_ptr<GLInProcessContextImpl> context( 291 scoped_ptr<GLInProcessContextImpl> context(
582 new GLInProcessContextImpl(share_resources)); 292 new GLInProcessContextImpl());
583 if (!context->Initialize( 293 if (!context->Initialize(
584 is_offscreen, 294 is_offscreen,
295 share_resources,
585 window, 296 window,
586 size, 297 size,
587 allowed_extensions, 298 allowed_extensions,
588 attrib_list, 299 attrib_list,
589 gpu_preference, 300 gpu_preference,
590 callback)) 301 callback))
591 return NULL; 302 return NULL;
592 303
593 return context.release(); 304 return context.release();
594 } 305 }
595 306
596 // static 307 // static
597 void GLInProcessContext::SetGpuMemoryBufferCreator( 308 void GLInProcessContext::SetGpuMemoryBufferCreator(
598 GpuMemoryBufferCreator* creator) { 309 GpuMemoryBufferCreator* creator) {
599 g_gpu_memory_buffer_creator = creator; 310 g_gpu_memory_buffer_creator = creator;
600 } 311 }
601 312
602 // static
603 void GLInProcessContext::EnableVirtualizedContext() {
604 #if !defined(NDEBUG)
605 {
606 AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(),
607 g_all_shared_contexts.Get());
608 DCHECK(g_all_shared_contexts.Get().empty());
609 }
610 #endif // !defined(NDEBUG)
611 g_use_virtualized_gl_context = true;
612 }
613
614 } // namespace gpu 313 } // namespace gpu
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698