Chromium Code Reviews

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: Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | | 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 scoped_refptr<gfx::GLImage> gl_image =
193 gfx::GLImage::CreateGLImageForGpuMemoryBuffer(buffer->GetNativeBuffer(), 106 gfx::GLImage::CreateGLImageForGpuMemoryBuffer(buffer->GetNativeBuffer(),
194 gfx::Size(width, height)); 107 gfx::Size(width, height));
195 *image_id = decoder_->GetContextGroup() 108 *image_id = command_buffer_->AddImage(gl_image);
196 ->GetIdAllocator(gles2::id_namespaces::kImages)->AllocateID();
197 GetImageManager()->AddImage(gl_image.get(), *image_id);
198 return buffer.Pass(); 109 return buffer.Pass();
199 } 110 }
200 111
201 void GLInProcessContextImpl::DeleteGpuMemoryBuffer(unsigned int image_id) { 112 void GLInProcessContextImpl::DeleteGpuMemoryBuffer(unsigned int image_id) {
202 // We're taking the lock here because we're accessing the ContextGroup's 113 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 } 114 }
210 115
211 GLInProcessContextImpl::GLInProcessContextImpl(bool share_resources) 116 GLInProcessContextImpl::GLInProcessContextImpl() {}
212 : share_resources_(share_resources),
213 context_lost_(false) {
214 }
215 117
216 GLInProcessContextImpl::~GLInProcessContextImpl() { 118 GLInProcessContextImpl::~GLInProcessContextImpl() {
217 Destroy(); 119 Destroy();
218 } 120 }
219 121
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, 122 void GLInProcessContextImpl::SignalSyncPoint(unsigned sync_point,
255 const base::Closure& callback) { 123 const base::Closure& callback) {
256 DCHECK(!callback.is_null()); 124 DCHECK(!callback.is_null());
257 signal_sync_point_callbacks_.push_back(callback); 125 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 } 126 }
276 127
277 gles2::GLES2Implementation* GLInProcessContextImpl::GetImplementation() { 128 gles2::GLES2Implementation* GLInProcessContextImpl::GetImplementation() {
278 return gles2_implementation_.get(); 129 return gles2_implementation_.get();
279 } 130 }
280 131
281 gles2::ImageManager* GLInProcessContextImpl::GetImageManager() {
282 return decoder_->GetContextGroup()->image_manager();
283 }
284
285 bool GLInProcessContextImpl::Initialize( 132 bool GLInProcessContextImpl::Initialize(
286 bool is_offscreen, 133 bool is_offscreen,
134 bool share_resources,
287 gfx::AcceleratedWidget window, 135 gfx::AcceleratedWidget window,
288 const gfx::Size& size, 136 const gfx::Size& size,
289 const char* allowed_extensions, 137 const char* allowed_extensions,
290 const int32* attrib_list, 138 const int32* attrib_list,
291 gfx::GpuPreference gpu_preference, 139 gfx::GpuPreference gpu_preference,
292 const base::Closure& context_lost_callback) { 140 const base::Closure& context_lost_callback) {
293 // Use one share group for all contexts. 141 struct ShareGroupInstance {
294 CR_DEFINE_STATIC_LOCAL(scoped_refptr<gfx::GLShareGroup>, share_group, 142 ShareGroupInstance() : share_group(new gles2::ShareGroup(true, false)) {}
295 (new gfx::GLShareGroup)); 143 scoped_refptr<gles2::ShareGroup> share_group;
144 };
piman 2013/07/23 01:57:14 nit: can you move the struct declaration out of th
no sievers 2013/07/25 00:41:23 Done.
145 static base::LazyInstance<ShareGroupInstance> share_group =
146 LAZY_INSTANCE_INITIALIZER;
piman 2013/07/23 01:57:14 So, the previous code had logic around lost contex
no sievers 2013/07/25 00:41:23 I've solved this in a cheesy way by letting the In
296 147
297 DCHECK(size.width() >= 0 && size.height() >= 0); 148 DCHECK(size.width() >= 0 && size.height() >= 0);
298 149
299 std::vector<int32> attribs; 150 std::vector<int32> attribs;
300 while (attrib_list) { 151 while (attrib_list) {
301 int32 attrib = *attrib_list++; 152 int32 attrib = *attrib_list++;
302 switch (attrib) { 153 switch (attrib) {
303 // Known attributes 154 // Known attributes
304 case ALPHA_SIZE: 155 case ALPHA_SIZE:
305 case BLUE_SIZE: 156 case BLUE_SIZE:
(...skipping 10 matching lines...)
316 attribs.push_back(attrib); 167 attribs.push_back(attrib);
317 attrib_list = NULL; 168 attrib_list = NULL;
318 break; 169 break;
319 default: 170 default:
320 attribs.push_back(NONE); 171 attribs.push_back(NONE);
321 attrib_list = NULL; 172 attrib_list = NULL;
322 break; 173 break;
323 } 174 }
324 } 175 }
325 176
326 { 177 command_buffer_.reset(new InProcessCommandBuffer());
327 TransferBufferManager* manager = new TransferBufferManager(); 178 command_buffer_->Initialize(is_offscreen,
328 transfer_buffer_manager_.reset(manager); 179 share_resources,
piman 2013/07/23 01:57:14 nit: indentation
no sievers 2013/07/25 00:41:23 Done.
329 manager->Initialize(); 180 window,
330 } 181 size,
331 182 allowed_extensions,
332 scoped_ptr<CommandBufferService> command_buffer( 183 attribs,
333 new CommandBufferService(transfer_buffer_manager_.get())); 184 gpu_preference,
334 command_buffer->SetPutOffsetChangeCallback(base::Bind( 185 context_lost_callback);
335 &GLInProcessContextImpl::PumpCommands, base::Unretained(this)));
336 command_buffer->SetGetBufferChangeCallback(base::Bind(
337 &GLInProcessContextImpl::GetBufferChanged, base::Unretained(this)));
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;
346 }
347
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 186
445 // Create the GLES2 helper, which writes the command buffer protocol. 187 // Create the GLES2 helper, which writes the command buffer protocol.
446 gles2_helper_.reset(new gles2::GLES2CmdHelper(command_buffer_.get())); 188 gles2_helper_.reset(new gles2::GLES2CmdHelper(command_buffer_.get()));
447 if (!gles2_helper_->Initialize(kCommandBufferSize)) { 189 if (!gles2_helper_->Initialize(kCommandBufferSize)) {
190 LOG(INFO) << "fail";
piman 2013/07/23 01:57:14 nit: more descriptive log?
no sievers 2013/07/25 00:41:23 Done.
448 Destroy(); 191 Destroy();
449 return false; 192 return false;
450 } 193 }
451 194
452 // Create a transfer buffer. 195 // Create a transfer buffer.
453 transfer_buffer_.reset(new TransferBuffer(gles2_helper_.get())); 196 transfer_buffer_.reset(new TransferBuffer(gles2_helper_.get()));
454 197
455 // Create the object exposing the OpenGL API. 198 // Create the object exposing the OpenGL API.
456 gles2_implementation_.reset(new gles2::GLES2Implementation( 199 gles2_implementation_.reset(new gles2::GLES2Implementation(
457 gles2_helper_.get(), 200 gles2_helper_.get(),
458 context_group ? context_group->GetImplementation()->share_group() : NULL, 201 share_resources ? share_group.Get().share_group : NULL,
459 transfer_buffer_.get(), 202 transfer_buffer_.get(),
460 true, 203 true,
461 false, 204 false,
462 this)); 205 this));
463 206
464 if (!gles2_implementation_->Initialize( 207 if (!gles2_implementation_->Initialize(
465 kStartTransferBufferSize, 208 kStartTransferBufferSize,
466 kMinTransferBufferSize, 209 kMinTransferBufferSize,
467 kMaxTransferBufferSize)) { 210 kMaxTransferBufferSize)) {
468 return false; 211 return false;
469 } 212 }
470 213
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; 214 return true;
479 } 215 }
480 216
481 void GLInProcessContextImpl::Destroy() { 217 void GLInProcessContextImpl::Destroy() {
482 while (!query_callbacks_.empty()) { 218 while (!query_callbacks_.empty()) {
483 CallQueryCallback(0); 219 CallQueryCallback(0);
484 } 220 }
485 221
486 bool context_lost = IsCommandBufferContextLost();
487
488 if (gles2_implementation_) { 222 if (gles2_implementation_) {
489 // First flush the context to ensure that any pending frees of resources 223 // 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, 224 // are completed. Otherwise, if this context is part of a share group,
491 // those resources might leak. Also, any remaining side effects of commands 225 // 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 226 // issued on this context might not be visible to other contexts in the
493 // share group. 227 // share group.
494 gles2_implementation_->Flush(); 228 gles2_implementation_->Flush();
495 229
496 gles2_implementation_.reset(); 230 gles2_implementation_.reset();
497 } 231 }
498 232
499 transfer_buffer_.reset(); 233 transfer_buffer_.reset();
500 gles2_helper_.reset(); 234 gles2_helper_.reset();
501 command_buffer_.reset(); 235 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 } 236 }
525 237
526 void GLInProcessContextImpl::CallQueryCallback(size_t index) { 238 void GLInProcessContextImpl::CallQueryCallback(size_t index) {
527 DCHECK_LT(index, query_callbacks_.size()); 239 DCHECK_LT(index, query_callbacks_.size());
528 QueryCallback query_callback = query_callbacks_[index]; 240 QueryCallback query_callback = query_callbacks_[index];
529 query_callbacks_[index] = query_callbacks_.back(); 241 query_callbacks_[index] = query_callbacks_.back();
530 query_callbacks_.pop_back(); 242 query_callbacks_.pop_back();
531 query_callback.second.Run(); 243 query_callback.second.Run();
532 } 244 }
533 245
246 // TODO(sievers): Move this to the service side
534 void GLInProcessContextImpl::PollQueryCallbacks() { 247 void GLInProcessContextImpl::PollQueryCallbacks() {
535 for (size_t i = 0; i < query_callbacks_.size();) { 248 for (size_t i = 0; i < query_callbacks_.size();) {
536 unsigned query = query_callbacks_[i].first; 249 unsigned query = query_callbacks_[i].first;
537 GLuint param = 0; 250 GLuint param = 0;
538 gles2::GLES2Implementation* gl = GetImplementation(); 251 gles2::GLES2Implementation* gl = GetImplementation();
539 if (gl->IsQueryEXT(query)) { 252 if (gl->IsQueryEXT(query)) {
540 gl->GetQueryObjectuivEXT(query, GL_QUERY_RESULT_AVAILABLE_EXT, &param); 253 gl->GetQueryObjectuivEXT(query, GL_QUERY_RESULT_AVAILABLE_EXT, &param);
541 } else { 254 } else {
542 param = 1; 255 param = 1;
543 } 256 }
(...skipping 28 matching lines...)
572 GLInProcessContext* GLInProcessContext::CreateContext( 285 GLInProcessContext* GLInProcessContext::CreateContext(
573 bool is_offscreen, 286 bool is_offscreen,
574 gfx::AcceleratedWidget window, 287 gfx::AcceleratedWidget window,
575 const gfx::Size& size, 288 const gfx::Size& size,
576 bool share_resources, 289 bool share_resources,
577 const char* allowed_extensions, 290 const char* allowed_extensions,
578 const int32* attrib_list, 291 const int32* attrib_list,
579 gfx::GpuPreference gpu_preference, 292 gfx::GpuPreference gpu_preference,
580 const base::Closure& callback) { 293 const base::Closure& callback) {
581 scoped_ptr<GLInProcessContextImpl> context( 294 scoped_ptr<GLInProcessContextImpl> context(
582 new GLInProcessContextImpl(share_resources)); 295 new GLInProcessContextImpl());
583 if (!context->Initialize( 296 if (!context->Initialize(
584 is_offscreen, 297 is_offscreen,
298 share_resources,
585 window, 299 window,
586 size, 300 size,
587 allowed_extensions, 301 allowed_extensions,
588 attrib_list, 302 attrib_list,
589 gpu_preference, 303 gpu_preference,
590 callback)) 304 callback))
591 return NULL; 305 return NULL;
592 306
593 return context.release(); 307 return context.release();
594 } 308 }
595 309
596 // static 310 // static
597 void GLInProcessContext::SetGpuMemoryBufferCreator( 311 void GLInProcessContext::SetGpuMemoryBufferCreator(
598 GpuMemoryBufferCreator* creator) { 312 GpuMemoryBufferCreator* creator) {
599 g_gpu_memory_buffer_creator = creator; 313 g_gpu_memory_buffer_creator = creator;
600 } 314 }
601 315
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 316 } // namespace gpu
OLDNEW

Powered by Google App Engine