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

Side by Side Diff: webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc

Issue 12908004: Lazy initialize WGC3DInProcessCommandBufferImpl (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Add comment. Created 7 years, 8 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 "webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h" 5 #include "webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h"
6 6
7 #include <GLES2/gl2.h> 7 #include <GLES2/gl2.h>
8 #ifndef GL_GLEXT_PROTOTYPES 8 #ifndef GL_GLEXT_PROTOTYPES
9 #define GL_GLEXT_PROTOTYPES 1 9 #define GL_GLEXT_PROTOTYPES 1
10 #endif 10 #endif
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
44 using gpu::gles2::GLES2CmdHelper; 44 using gpu::gles2::GLES2CmdHelper;
45 using gpu::gles2::GLES2Implementation; 45 using gpu::gles2::GLES2Implementation;
46 using gpu::GpuScheduler; 46 using gpu::GpuScheduler;
47 using gpu::TransferBuffer; 47 using gpu::TransferBuffer;
48 using gpu::TransferBufferManager; 48 using gpu::TransferBufferManager;
49 using gpu::TransferBufferManagerInterface; 49 using gpu::TransferBufferManagerInterface;
50 50
51 namespace webkit { 51 namespace webkit {
52 namespace gpu { 52 namespace gpu {
53 53
54 class GLInProcessContext : public base::SupportsWeakPtr<GLInProcessContext> { 54 class GLInProcessContext : public base::SupportsWeakPtr<GLInProcessContext> {
no sievers 2013/03/26 17:34:00 Is SupportsWeakPtr not needed here anymore now?
boliu 2013/03/26 17:58:33 Done.
55 public: 55 public:
56 // These are the same error codes as used by EGL. 56 // These are the same error codes as used by EGL.
57 enum Error { 57 enum Error {
58 SUCCESS = 0x3000, 58 SUCCESS = 0x3000,
59 NOT_INITIALIZED = 0x3001, 59 NOT_INITIALIZED = 0x3001,
60 BAD_ATTRIBUTE = 0x3004, 60 BAD_ATTRIBUTE = 0x3004,
61 BAD_GLContext = 0x3006, 61 BAD_GLContext = 0x3006,
62 CONTEXT_LOST = 0x300E 62 CONTEXT_LOST = 0x300E
63 }; 63 };
64 64
(...skipping 26 matching lines...) Expand all
91 91
92 // Create a GLInProcessContext that renders to an offscreen frame buffer. If 92 // Create a GLInProcessContext that renders to an offscreen frame buffer. If
93 // parent is not NULL, that GLInProcessContext can access a copy of the 93 // parent is not NULL, that GLInProcessContext can access a copy of the
94 // created GLInProcessContext's frame buffer that is updated every time 94 // created GLInProcessContext's frame buffer that is updated every time
95 // SwapBuffers is called. It is not as general as shared GLInProcessContexts 95 // SwapBuffers is called. It is not as general as shared GLInProcessContexts
96 // in other implementations of OpenGL. If parent is not NULL, it must be used 96 // in other implementations of OpenGL. If parent is not NULL, it must be used
97 // on the same thread as the parent. A child GLInProcessContext may not 97 // on the same thread as the parent. A child GLInProcessContext may not
98 // outlive its parent. attrib_list must be NULL or a NONE-terminated list of 98 // outlive its parent. attrib_list must be NULL or a NONE-terminated list of
99 // attribute/value pairs. 99 // attribute/value pairs.
100 static GLInProcessContext* CreateOffscreenContext( 100 static GLInProcessContext* CreateOffscreenContext(
101 GLInProcessContext* parent,
102 const gfx::Size& size, 101 const gfx::Size& size,
103 GLInProcessContext* context_group, 102 bool share_resources,
104 const char* allowed_extensions, 103 const char* allowed_extensions,
105 const int32* attrib_list, 104 const int32* attrib_list,
106 gfx::GpuPreference gpu_preference); 105 gfx::GpuPreference gpu_preference);
107 106
108 // For an offscreen frame buffer GLInProcessContext, return the texture ID 107 // For an offscreen frame buffer GLInProcessContext, return the texture ID
109 // with respect to the parent GLInProcessContext. Returns zero if 108 // with respect to the parent GLInProcessContext. Returns zero if
110 // GLInProcessContext does not have a parent. 109 // GLInProcessContext does not have a parent.
111 uint32 GetParentTextureId(); 110 uint32 GetParentTextureId();
112 111
113 // Create a new texture in the parent's GLInProcessContext. Returns zero if 112 // Create a new texture in the parent's GLInProcessContext. Returns zero if
(...skipping 23 matching lines...) Expand all
137 136
138 // Return the current error. 137 // Return the current error.
139 Error GetError(); 138 Error GetError();
140 139
141 // Return true if GPU process reported GLInProcessContext lost or there was a 140 // Return true if GPU process reported GLInProcessContext lost or there was a
142 // problem communicating with the GPU process. 141 // problem communicating with the GPU process.
143 bool IsCommandBufferContextLost(); 142 bool IsCommandBufferContextLost();
144 143
145 CommandBufferService* GetCommandBufferService(); 144 CommandBufferService* GetCommandBufferService();
146 145
146 ::gpu::gles2::GLES2Decoder* GetDecoder();
147
147 private: 148 private:
148 explicit GLInProcessContext(GLInProcessContext* parent); 149 explicit GLInProcessContext(bool share_resources);
149 150
150 bool Initialize(const gfx::Size& size, 151 bool Initialize(const gfx::Size& size,
151 GLInProcessContext* context_group,
152 const char* allowed_extensions, 152 const char* allowed_extensions,
153 const int32* attrib_list, 153 const int32* attrib_list,
154 gfx::GpuPreference gpu_preference); 154 gfx::GpuPreference gpu_preference);
155 void Destroy(); 155 void Destroy();
156 156
157 void OnContextLost(); 157 void OnContextLost();
158 158
159 base::WeakPtr<GLInProcessContext> parent_;
160 base::Closure context_lost_callback_; 159 base::Closure context_lost_callback_;
161 uint32 parent_texture_id_;
162 scoped_ptr<TransferBufferManagerInterface> transfer_buffer_manager_; 160 scoped_ptr<TransferBufferManagerInterface> transfer_buffer_manager_;
163 scoped_ptr<CommandBufferService> command_buffer_; 161 scoped_ptr<CommandBufferService> command_buffer_;
164 scoped_ptr< ::gpu::GpuScheduler> gpu_scheduler_; 162 scoped_ptr< ::gpu::GpuScheduler> gpu_scheduler_;
165 scoped_ptr< ::gpu::gles2::GLES2Decoder> decoder_; 163 scoped_ptr< ::gpu::gles2::GLES2Decoder> decoder_;
166 scoped_refptr<gfx::GLContext> context_; 164 scoped_refptr<gfx::GLContext> context_;
167 scoped_refptr<gfx::GLSurface> surface_; 165 scoped_refptr<gfx::GLSurface> surface_;
168 scoped_ptr<GLES2CmdHelper> gles2_helper_; 166 scoped_ptr<GLES2CmdHelper> gles2_helper_;
169 scoped_ptr<TransferBuffer> transfer_buffer_; 167 scoped_ptr<TransferBuffer> transfer_buffer_;
170 scoped_ptr<GLES2Implementation> gles2_implementation_; 168 scoped_ptr<GLES2Implementation> gles2_implementation_;
171 Error last_error_; 169 Error last_error_;
170 bool share_resources_;
172 bool context_lost_; 171 bool context_lost_;
173 172
174 DISALLOW_COPY_AND_ASSIGN(GLInProcessContext); 173 DISALLOW_COPY_AND_ASSIGN(GLInProcessContext);
175 }; 174 };
176 175
177 namespace { 176 namespace {
178 177
179 const int32 kCommandBufferSize = 1024 * 1024; 178 const int32 kCommandBufferSize = 1024 * 1024;
180 // TODO(kbr): make the transfer buffer size configurable via context 179 // TODO(kbr): make the transfer buffer size configurable via context
181 // creation attributes. 180 // creation attributes.
182 const size_t kStartTransferBufferSize = 4 * 1024 * 1024; 181 const size_t kStartTransferBufferSize = 4 * 1024 * 1024;
183 const size_t kMinTransferBufferSize = 1 * 256 * 1024; 182 const size_t kMinTransferBufferSize = 1 * 256 * 1024;
184 const size_t kMaxTransferBufferSize = 16 * 1024 * 1024; 183 const size_t kMaxTransferBufferSize = 16 * 1024 * 1024;
185 184
186 static base::LazyInstance<
187 std::set<WebGraphicsContext3DInProcessCommandBufferImpl*> >
188 g_all_shared_contexts = LAZY_INSTANCE_INITIALIZER;
189 static base::LazyInstance<base::Lock>::Leaky
190 g_all_shared_contexts_lock = LAZY_INSTANCE_INITIALIZER;
191
192 // Singleton used to initialize and terminate the gles2 library. 185 // Singleton used to initialize and terminate the gles2 library.
193 class GLES2Initializer { 186 class GLES2Initializer {
194 public: 187 public:
195 GLES2Initializer() { 188 GLES2Initializer() {
196 gles2::Initialize(); 189 gles2::Initialize();
197 } 190 }
198 191
199 ~GLES2Initializer() { 192 ~GLES2Initializer() {
200 gles2::Terminate(); 193 gles2::Terminate();
201 } 194 }
202 195
203 private: 196 private:
204 DISALLOW_COPY_AND_ASSIGN(GLES2Initializer); 197 DISALLOW_COPY_AND_ASSIGN(GLES2Initializer);
205 }; 198 };
206 199
207 //////////////////////////////////////////////////////////////////////////////// 200 ////////////////////////////////////////////////////////////////////////////////
208 201
209 static base::LazyInstance<GLES2Initializer> g_gles2_initializer = 202 static base::LazyInstance<GLES2Initializer> g_gles2_initializer =
210 LAZY_INSTANCE_INITIALIZER; 203 LAZY_INSTANCE_INITIALIZER;
211 204
212 } // namespace anonymous 205 } // namespace anonymous
213 206
214 GLInProcessContext::~GLInProcessContext() { 207 GLInProcessContext::~GLInProcessContext() {
215 Destroy(); 208 Destroy();
216 } 209 }
217 210
218 GLInProcessContext* GLInProcessContext::CreateOffscreenContext( 211 GLInProcessContext* GLInProcessContext::CreateOffscreenContext(
219 GLInProcessContext* parent,
220 const gfx::Size& size, 212 const gfx::Size& size,
221 GLInProcessContext* context_group, 213 bool share_resources,
222 const char* allowed_extensions, 214 const char* allowed_extensions,
223 const int32* attrib_list, 215 const int32* attrib_list,
224 gfx::GpuPreference gpu_preference) { 216 gfx::GpuPreference gpu_preference) {
225 scoped_ptr<GLInProcessContext> context(new GLInProcessContext(parent)); 217 scoped_ptr<GLInProcessContext> context(
218 new GLInProcessContext(share_resources));
226 if (!context->Initialize( 219 if (!context->Initialize(
227 size, 220 size,
228 context_group,
229 allowed_extensions, 221 allowed_extensions,
230 attrib_list, 222 attrib_list,
231 gpu_preference)) 223 gpu_preference))
232 return NULL; 224 return NULL;
233 225
234 return context.release(); 226 return context.release();
235 } 227 }
236 228
237 // In the normal command buffer implementation, all commands are passed over IPC 229 // In the normal command buffer implementation, all commands are passed over IPC
238 // to the gpu process where they are fed to the GLES2Decoder from a single 230 // to the gpu process where they are fed to the GLES2Decoder from a single
239 // thread. In layout tests, any thread could call this function. GLES2Decoder, 231 // thread. In layout tests, any thread could call this function. GLES2Decoder,
240 // and in particular the GL implementations behind it, are not generally 232 // and in particular the GL implementations behind it, are not generally
241 // threadsafe, so we guard entry points with a mutex. 233 // threadsafe, so we guard entry points with a mutex.
242 static base::LazyInstance<base::Lock> g_decoder_lock = 234 static base::LazyInstance<base::Lock> g_decoder_lock =
243 LAZY_INSTANCE_INITIALIZER; 235 LAZY_INSTANCE_INITIALIZER;
244 236
237 static base::LazyInstance<
238 std::set<GLInProcessContext*> >
239 g_all_shared_contexts = LAZY_INSTANCE_INITIALIZER;
240
241 namespace {
242
243 // Also calls DetachFromThread on all GLES2Decoders before the lock is released
244 // to maintain the invariant that all decoders are unbounded while the lock is
245 // not held. This is to workaround DumpRenderTree uses WGC3DIPCBI with shared
246 // resources on different threads.
247 class AutoLockAndDecoderDetachThread {
248 public:
249 AutoLockAndDecoderDetachThread(base::Lock& lock,
250 const std::set<GLInProcessContext*>& contexts);
251 ~AutoLockAndDecoderDetachThread();
252
253 private:
254 base::AutoLock auto_lock_;
255 const std::set<GLInProcessContext*>& contexts_;
256 };
257
258 AutoLockAndDecoderDetachThread::AutoLockAndDecoderDetachThread(
259 base::Lock& lock,
260 const std::set<GLInProcessContext*>& contexts)
261 : auto_lock_(lock),
262 contexts_(contexts) {
263 }
264
265 void DetachThread(GLInProcessContext* context) {
266 if (context->GetDecoder())
267 context->GetDecoder()->DetachFromThread();
268 }
269
270 AutoLockAndDecoderDetachThread::~AutoLockAndDecoderDetachThread() {
271 std::for_each(contexts_.begin(),
272 contexts_.end(),
273 &DetachThread);
274 }
275
276 } // namespace
277
245 void GLInProcessContext::PumpCommands() { 278 void GLInProcessContext::PumpCommands() {
246 if (!context_lost_) { 279 if (!context_lost_) {
247 base::AutoLock lock(g_decoder_lock.Get()); 280 AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(),
281 g_all_shared_contexts.Get());
248 decoder_->MakeCurrent(); 282 decoder_->MakeCurrent();
249 gpu_scheduler_->PutChanged(); 283 gpu_scheduler_->PutChanged();
250 ::gpu::CommandBuffer::State state = command_buffer_->GetState(); 284 ::gpu::CommandBuffer::State state = command_buffer_->GetState();
251 if (::gpu::error::IsError(state.error)) { 285 if (::gpu::error::IsError(state.error)) {
252 context_lost_ = true; 286 context_lost_ = true;
253 } 287 }
254 } 288 }
255 } 289 }
256 290
257 bool GLInProcessContext::GetBufferChanged(int32 transfer_buffer_id) { 291 bool GLInProcessContext::GetBufferChanged(int32 transfer_buffer_id) {
258 return gpu_scheduler_->SetGetBuffer(transfer_buffer_id); 292 return gpu_scheduler_->SetGetBuffer(transfer_buffer_id);
259 } 293 }
260 294
261 uint32 GLInProcessContext::GetParentTextureId() { 295 uint32 GLInProcessContext::GetParentTextureId() {
262 return parent_texture_id_; 296 return 0;
263 } 297 }
264 298
265 uint32 GLInProcessContext::CreateParentTexture(const gfx::Size& size) { 299 uint32 GLInProcessContext::CreateParentTexture(const gfx::Size& size) {
266 uint32 texture = 0; 300 uint32 texture = 0;
267 gles2_implementation_->GenTextures(1, &texture); 301 gles2_implementation_->GenTextures(1, &texture);
268 gles2_implementation_->Flush(); 302 gles2_implementation_->Flush();
269 return texture; 303 return texture;
270 } 304 }
271 305
272 void GLInProcessContext::DeleteParentTexture(uint32 texture) { 306 void GLInProcessContext::DeleteParentTexture(uint32 texture) {
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
325 return true; 359 return true;
326 } 360 }
327 CommandBuffer::State state = command_buffer_->GetState(); 361 CommandBuffer::State state = command_buffer_->GetState();
328 return ::gpu::error::IsError(state.error); 362 return ::gpu::error::IsError(state.error);
329 } 363 }
330 364
331 CommandBufferService* GLInProcessContext::GetCommandBufferService() { 365 CommandBufferService* GLInProcessContext::GetCommandBufferService() {
332 return command_buffer_.get(); 366 return command_buffer_.get();
333 } 367 }
334 368
369 ::gpu::gles2::GLES2Decoder* GLInProcessContext::GetDecoder() {
370 return decoder_.get();
371 }
372
335 // TODO(gman): Remove This 373 // TODO(gman): Remove This
336 void GLInProcessContext::DisableShaderTranslation() { 374 void GLInProcessContext::DisableShaderTranslation() {
337 NOTREACHED(); 375 NOTREACHED();
338 } 376 }
339 377
340 GLES2Implementation* GLInProcessContext::GetImplementation() { 378 GLES2Implementation* GLInProcessContext::GetImplementation() {
341 return gles2_implementation_.get(); 379 return gles2_implementation_.get();
342 } 380 }
343 381
344 GLInProcessContext::GLInProcessContext(GLInProcessContext* parent) 382 GLInProcessContext::GLInProcessContext(bool share_resources)
345 : parent_(parent ? 383 : last_error_(SUCCESS),
346 parent->AsWeakPtr() : base::WeakPtr<GLInProcessContext>()), 384 share_resources_(share_resources),
347 parent_texture_id_(0),
348 last_error_(SUCCESS),
349 context_lost_(false) { 385 context_lost_(false) {
350 } 386 }
351 387
352 bool GLInProcessContext::Initialize(const gfx::Size& size, 388 bool GLInProcessContext::Initialize(const gfx::Size& size,
353 GLInProcessContext* context_group,
354 const char* allowed_extensions, 389 const char* allowed_extensions,
355 const int32* attrib_list, 390 const int32* attrib_list,
356 gfx::GpuPreference gpu_preference) { 391 gfx::GpuPreference gpu_preference) {
357 // Use one share group for all contexts. 392 // Use one share group for all contexts.
358 CR_DEFINE_STATIC_LOCAL(scoped_refptr<gfx::GLShareGroup>, share_group, 393 CR_DEFINE_STATIC_LOCAL(scoped_refptr<gfx::GLShareGroup>, share_group,
359 (new gfx::GLShareGroup)); 394 (new gfx::GLShareGroup));
360 395
361 DCHECK(size.width() >= 0 && size.height() >= 0); 396 DCHECK(size.width() >= 0 && size.height() >= 0);
362 397
363 // Ensure the gles2 library is initialized first in a thread safe way. 398 // Ensure the gles2 library is initialized first in a thread safe way.
364 g_gles2_initializer.Get(); 399 g_gles2_initializer.Get();
365 400
366 // Allocate a frame buffer ID with respect to the parent.
367 if (parent_.get()) {
368 // Flush any remaining commands in the parent context to make sure the
369 // texture id accounting stays consistent.
370 int32 token = parent_->gles2_helper_->InsertToken();
371 parent_->gles2_helper_->WaitForToken(token);
372 parent_texture_id_ = parent_->gles2_implementation_->MakeTextureId();
373 }
374
375 std::vector<int32> attribs; 401 std::vector<int32> attribs;
376 while (attrib_list) { 402 while (attrib_list) {
377 int32 attrib = *attrib_list++; 403 int32 attrib = *attrib_list++;
378 switch (attrib) { 404 switch (attrib) {
379 // Known attributes 405 // Known attributes
380 case ALPHA_SIZE: 406 case ALPHA_SIZE:
381 case BLUE_SIZE: 407 case BLUE_SIZE:
382 case GREEN_SIZE: 408 case GREEN_SIZE:
383 case RED_SIZE: 409 case RED_SIZE:
384 case DEPTH_SIZE: 410 case DEPTH_SIZE:
(...skipping 22 matching lines...) Expand all
407 } 433 }
408 434
409 command_buffer_.reset( 435 command_buffer_.reset(
410 new CommandBufferService(transfer_buffer_manager_.get())); 436 new CommandBufferService(transfer_buffer_manager_.get()));
411 if (!command_buffer_->Initialize()) { 437 if (!command_buffer_->Initialize()) {
412 LOG(ERROR) << "Could not initialize command buffer."; 438 LOG(ERROR) << "Could not initialize command buffer.";
413 Destroy(); 439 Destroy();
414 return false; 440 return false;
415 } 441 }
416 442
417 // TODO(gman): This needs to be true if this is Pepper. 443 GLInProcessContext* context_group = NULL;
418 bool bind_generates_resource = false;
419 decoder_.reset(::gpu::gles2::GLES2Decoder::Create(context_group ?
420 context_group->decoder_->GetContextGroup() :
421 new ::gpu::gles2::ContextGroup(
422 NULL, NULL, NULL, bind_generates_resource)));
423 444
424 gpu_scheduler_.reset(new GpuScheduler(command_buffer_.get(), 445 {
425 decoder_.get(), 446 AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(),
426 decoder_.get())); 447 g_all_shared_contexts.Get());
448 if (share_resources_ && !g_all_shared_contexts.Get().empty())
449 context_group = *g_all_shared_contexts.Get().begin();
427 450
428 decoder_->set_engine(gpu_scheduler_.get()); 451 // TODO(gman): This needs to be true if this is Pepper.
452 bool bind_generates_resource = false;
453 decoder_.reset(::gpu::gles2::GLES2Decoder::Create(context_group ?
454 context_group->decoder_->GetContextGroup() :
455 new ::gpu::gles2::ContextGroup(
456 NULL, NULL, NULL, bind_generates_resource)));
429 457
430 surface_ = gfx::GLSurface::CreateOffscreenGLSurface(false, gfx::Size(1, 1)); 458 gpu_scheduler_.reset(new GpuScheduler(command_buffer_.get(),
459 decoder_.get(),
460 decoder_.get()));
431 461
432 if (!surface_.get()) { 462 decoder_->set_engine(gpu_scheduler_.get());
433 LOG(ERROR) << "Could not create GLSurface.";
434 Destroy();
435 return false;
436 }
437 463
438 context_ = gfx::GLContext::CreateGLContext(share_group.get(), 464 surface_ = gfx::GLSurface::CreateOffscreenGLSurface(false, gfx::Size(1, 1));
439 surface_.get(),
440 gpu_preference);
441 if (!context_.get()) {
442 LOG(ERROR) << "Could not create GLContext.";
443 Destroy();
444 return false;
445 }
446 465
447 if (!context_->MakeCurrent(surface_.get())) { 466 if (!surface_.get()) {
448 LOG(ERROR) << "Could not make context current."; 467 LOG(ERROR) << "Could not create GLSurface.";
449 Destroy(); 468 Destroy();
450 return false; 469 return false;
451 } 470 }
452 471
453 ::gpu::gles2::DisallowedFeatures disallowed_features; 472 context_ = gfx::GLContext::CreateGLContext(share_group.get(),
454 disallowed_features.swap_buffer_complete_callback = true; 473 surface_.get(),
455 disallowed_features.gpu_memory_manager = true; 474 gpu_preference);
456 if (!decoder_->Initialize(surface_, 475 if (!context_.get()) {
457 context_, 476 LOG(ERROR) << "Could not create GLContext.";
458 true, 477 Destroy();
459 size, 478 return false;
460 disallowed_features, 479 }
461 allowed_extensions,
462 attribs)) {
463 LOG(ERROR) << "Could not initialize decoder.";
464 Destroy();
465 return false;
466 }
467 480
468 if (!decoder_->SetParent( 481 if (!context_->MakeCurrent(surface_.get())) {
469 parent_.get() ? parent_->decoder_.get() : NULL, 482 LOG(ERROR) << "Could not make context current.";
470 parent_texture_id_)) { 483 Destroy();
471 LOG(ERROR) << "Could not set parent."; 484 return false;
472 Destroy(); 485 }
473 return false; 486
487 ::gpu::gles2::DisallowedFeatures disallowed_features;
488 disallowed_features.swap_buffer_complete_callback = true;
489 disallowed_features.gpu_memory_manager = true;
490 if (!decoder_->Initialize(surface_,
491 context_,
492 true,
493 size,
494 disallowed_features,
495 allowed_extensions,
496 attribs)) {
497 LOG(ERROR) << "Could not initialize decoder.";
498 Destroy();
499 return false;
500 }
474 } 501 }
475 502
476 command_buffer_->SetPutOffsetChangeCallback( 503 command_buffer_->SetPutOffsetChangeCallback(
477 base::Bind(&GLInProcessContext::PumpCommands, base::Unretained(this))); 504 base::Bind(&GLInProcessContext::PumpCommands, base::Unretained(this)));
478 command_buffer_->SetGetBufferChangeCallback( 505 command_buffer_->SetGetBufferChangeCallback(
479 base::Bind( 506 base::Bind(
480 &GLInProcessContext::GetBufferChanged, base::Unretained(this))); 507 &GLInProcessContext::GetBufferChanged, base::Unretained(this)));
481 command_buffer_->SetParseErrorCallback( 508 command_buffer_->SetParseErrorCallback(
482 base::Bind(&GLInProcessContext::OnContextLost, base::Unretained(this))); 509 base::Bind(&GLInProcessContext::OnContextLost, base::Unretained(this)));
483 510
(...skipping 15 matching lines...) Expand all
499 true, 526 true,
500 false)); 527 false));
501 528
502 if (!gles2_implementation_->Initialize( 529 if (!gles2_implementation_->Initialize(
503 kStartTransferBufferSize, 530 kStartTransferBufferSize,
504 kMinTransferBufferSize, 531 kMinTransferBufferSize,
505 kMaxTransferBufferSize)) { 532 kMaxTransferBufferSize)) {
506 return false; 533 return false;
507 } 534 }
508 535
536 if (share_resources_) {
537 AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(),
538 g_all_shared_contexts.Get());
539 g_all_shared_contexts.Pointer()->insert(this);
540 }
541
509 return true; 542 return true;
510 } 543 }
511 544
512 void GLInProcessContext::Destroy() { 545 void GLInProcessContext::Destroy() {
513 bool context_lost = IsCommandBufferContextLost(); 546 bool context_lost = IsCommandBufferContextLost();
514 547
515 if (parent_.get() && parent_texture_id_ != 0) {
516 parent_->gles2_implementation_->FreeTextureId(parent_texture_id_);
517 parent_texture_id_ = 0;
518 }
519
520 if (gles2_implementation_.get()) { 548 if (gles2_implementation_.get()) {
521 // First flush the context to ensure that any pending frees of resources 549 // First flush the context to ensure that any pending frees of resources
522 // are completed. Otherwise, if this context is part of a share group, 550 // are completed. Otherwise, if this context is part of a share group,
523 // those resources might leak. Also, any remaining side effects of commands 551 // those resources might leak. Also, any remaining side effects of commands
524 // issued on this context might not be visible to other contexts in the 552 // issued on this context might not be visible to other contexts in the
525 // share group. 553 // share group.
526 gles2_implementation_->Flush(); 554 gles2_implementation_->Flush();
527 555
528 gles2_implementation_.reset(); 556 gles2_implementation_.reset();
529 } 557 }
530 558
531 transfer_buffer_.reset(); 559 transfer_buffer_.reset();
532 gles2_helper_.reset(); 560 gles2_helper_.reset();
533 command_buffer_.reset(); 561 command_buffer_.reset();
534 562
563 AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(),
564 g_all_shared_contexts.Get());
535 if (decoder_.get()) { 565 if (decoder_.get()) {
536 decoder_->Destroy(!context_lost); 566 decoder_->Destroy(!context_lost);
537 } 567 }
568
569 g_all_shared_contexts.Pointer()->erase(this);
538 } 570 }
539 571
540 void GLInProcessContext::OnContextLost() { 572 void GLInProcessContext::OnContextLost() {
541 if (!context_lost_callback_.is_null()) 573 if (!context_lost_callback_.is_null())
542 context_lost_callback_.Run(); 574 context_lost_callback_.Run();
543 } 575 }
544 576
545 WebGraphicsContext3DInProcessCommandBufferImpl:: 577 WebGraphicsContext3DInProcessCommandBufferImpl::
546 WebGraphicsContext3DInProcessCommandBufferImpl() 578 WebGraphicsContext3DInProcessCommandBufferImpl(
547 : context_(NULL), 579 const WebKit::WebGraphicsContext3D::Attributes& attributes)
580 : initialized_(false),
581 initialize_failed_(false),
582 context_(NULL),
548 gl_(NULL), 583 gl_(NULL),
549 context_lost_callback_(NULL), 584 context_lost_callback_(NULL),
550 context_lost_reason_(GL_NO_ERROR), 585 context_lost_reason_(GL_NO_ERROR),
586 attributes_(attributes),
551 cached_width_(0), 587 cached_width_(0),
552 cached_height_(0), 588 cached_height_(0),
553 bound_fbo_(0) { 589 bound_fbo_(0) {
554 } 590 }
555 591
556 WebGraphicsContext3DInProcessCommandBufferImpl:: 592 WebGraphicsContext3DInProcessCommandBufferImpl::
557 ~WebGraphicsContext3DInProcessCommandBufferImpl() { 593 ~WebGraphicsContext3DInProcessCommandBufferImpl() {
558 base::AutoLock a(g_all_shared_contexts_lock.Get());
559 g_all_shared_contexts.Pointer()->erase(this);
560 } 594 }
561 595
562 bool WebGraphicsContext3DInProcessCommandBufferImpl::Initialize( 596 bool WebGraphicsContext3DInProcessCommandBufferImpl::MaybeInitializeGL() {
563 WebGraphicsContext3D::Attributes attributes, 597 if (initialized_)
564 WebKit::WebGraphicsContext3D* view_context) { 598 return true;
599
600 if (initialize_failed_)
601 return false;
602
565 // Convert WebGL context creation attributes into GLInProcessContext / EGL 603 // Convert WebGL context creation attributes into GLInProcessContext / EGL
566 // size requests. 604 // size requests.
567 const int alpha_size = attributes.alpha ? 8 : 0; 605 const int alpha_size = attributes_.alpha ? 8 : 0;
568 const int depth_size = attributes.depth ? 24 : 0; 606 const int depth_size = attributes_.depth ? 24 : 0;
569 const int stencil_size = attributes.stencil ? 8 : 0; 607 const int stencil_size = attributes_.stencil ? 8 : 0;
570 const int samples = attributes.antialias ? 4 : 0; 608 const int samples = attributes_.antialias ? 4 : 0;
571 const int sample_buffers = attributes.antialias ? 1 : 0; 609 const int sample_buffers = attributes_.antialias ? 1 : 0;
572 const int32 attribs[] = { 610 const int32 attribs[] = {
573 GLInProcessContext::ALPHA_SIZE, alpha_size, 611 GLInProcessContext::ALPHA_SIZE, alpha_size,
574 GLInProcessContext::DEPTH_SIZE, depth_size, 612 GLInProcessContext::DEPTH_SIZE, depth_size,
575 GLInProcessContext::STENCIL_SIZE, stencil_size, 613 GLInProcessContext::STENCIL_SIZE, stencil_size,
576 GLInProcessContext::SAMPLES, samples, 614 GLInProcessContext::SAMPLES, samples,
577 GLInProcessContext::SAMPLE_BUFFERS, sample_buffers, 615 GLInProcessContext::SAMPLE_BUFFERS, sample_buffers,
578 GLInProcessContext::NONE, 616 GLInProcessContext::NONE,
579 }; 617 };
580 618
581 const char* preferred_extensions = "*"; 619 const char* preferred_extensions = "*";
582 620
583 // TODO(kbr): More work will be needed in this implementation to 621 // TODO(kbr): More work will be needed in this implementation to
584 // properly support GPU switching. Like in the out-of-process 622 // properly support GPU switching. Like in the out-of-process
585 // command buffer implementation, all previously created contexts 623 // command buffer implementation, all previously created contexts
586 // will need to be lost either when the first context requesting the 624 // will need to be lost either when the first context requesting the
587 // discrete GPU is created, or the last one is destroyed. 625 // discrete GPU is created, or the last one is destroyed.
588 gfx::GpuPreference gpu_preference = gfx::PreferDiscreteGpu; 626 gfx::GpuPreference gpu_preference = gfx::PreferDiscreteGpu;
589 627
590 GLInProcessContext* parent_context = NULL;
591 if (view_context) {
592 WebGraphicsContext3DInProcessCommandBufferImpl* context_impl =
593 static_cast<WebGraphicsContext3DInProcessCommandBufferImpl*>(
594 view_context);
595 parent_context = context_impl->context_;
596 }
597
598 WebGraphicsContext3DInProcessCommandBufferImpl* context_group = NULL;
599 base::AutoLock lock(g_all_shared_contexts_lock.Get());
600 if (attributes.shareResources)
601 context_group = g_all_shared_contexts.Pointer()->empty() ?
602 NULL : *g_all_shared_contexts.Pointer()->begin();
603
604 context_ = GLInProcessContext::CreateOffscreenContext( 628 context_ = GLInProcessContext::CreateOffscreenContext(
605 parent_context,
606 gfx::Size(1, 1), 629 gfx::Size(1, 1),
607 context_group ? context_group->context_ : NULL, 630 attributes_.shareResources,
608 preferred_extensions, 631 preferred_extensions,
609 attribs, 632 attribs,
610 gpu_preference); 633 gpu_preference);
611 634
612 if (!context_) 635 if (!context_) {
636 initialize_failed_ = true;
613 return false; 637 return false;
638 }
614 639
615 gl_ = context_->GetImplementation(); 640 gl_ = context_->GetImplementation();
616 641
617 if (gl_ && attributes.noExtensions) 642 if (gl_ && attributes_.noExtensions)
618 gl_->EnableFeatureCHROMIUM("webgl_enable_glsl_webgl_validation"); 643 gl_->EnableFeatureCHROMIUM("webgl_enable_glsl_webgl_validation");
619 644
620 context_->SetContextLostCallback( 645 context_->SetContextLostCallback(
621 base::Bind( 646 base::Bind(
622 &WebGraphicsContext3DInProcessCommandBufferImpl::OnContextLost, 647 &WebGraphicsContext3DInProcessCommandBufferImpl::OnContextLost,
623 base::Unretained(this))); 648 base::Unretained(this)));
624 649
625 // Set attributes_ from created offscreen context. 650 // Set attributes_ from created offscreen context.
626 { 651 {
627 attributes_ = attributes;
628 GLint alpha_bits = 0; 652 GLint alpha_bits = 0;
629 getIntegerv(GL_ALPHA_BITS, &alpha_bits); 653 getIntegerv(GL_ALPHA_BITS, &alpha_bits);
630 attributes_.alpha = alpha_bits > 0; 654 attributes_.alpha = alpha_bits > 0;
631 GLint depth_bits = 0; 655 GLint depth_bits = 0;
632 getIntegerv(GL_DEPTH_BITS, &depth_bits); 656 getIntegerv(GL_DEPTH_BITS, &depth_bits);
633 attributes_.depth = depth_bits > 0; 657 attributes_.depth = depth_bits > 0;
634 GLint stencil_bits = 0; 658 GLint stencil_bits = 0;
635 getIntegerv(GL_STENCIL_BITS, &stencil_bits); 659 getIntegerv(GL_STENCIL_BITS, &stencil_bits);
636 attributes_.stencil = stencil_bits > 0; 660 attributes_.stencil = stencil_bits > 0;
637 GLint sample_buffers = 0; 661 GLint sample_buffers = 0;
638 getIntegerv(GL_SAMPLE_BUFFERS, &sample_buffers); 662 getIntegerv(GL_SAMPLE_BUFFERS, &sample_buffers);
639 attributes_.antialias = sample_buffers > 0; 663 attributes_.antialias = sample_buffers > 0;
640 } 664 }
641 makeContextCurrent();
642 665
643 if (attributes.shareResources) 666 initialized_ = true;
644 g_all_shared_contexts.Pointer()->insert(this);
645
646 return true; 667 return true;
647 } 668 }
648 669
649 bool WebGraphicsContext3DInProcessCommandBufferImpl::makeContextCurrent() { 670 bool WebGraphicsContext3DInProcessCommandBufferImpl::makeContextCurrent() {
671 if (!MaybeInitializeGL())
672 return false;
673
650 return GLInProcessContext::MakeCurrent(context_); 674 return GLInProcessContext::MakeCurrent(context_);
651 } 675 }
652 676
653 void WebGraphicsContext3DInProcessCommandBufferImpl::ClearContext() { 677 void WebGraphicsContext3DInProcessCommandBufferImpl::ClearContext() {
654 // NOTE: Comment in the line below to check for code that is not calling 678 // NOTE: Comment in the line below to check for code that is not calling
655 // eglMakeCurrent where appropriate. The issue is code using 679 // eglMakeCurrent where appropriate. The issue is code using
656 // WebGraphicsContext3D does not need to call makeContextCurrent. Code using 680 // WebGraphicsContext3D does not need to call makeContextCurrent. Code using
657 // direct OpenGL bindings needs to call the appropriate form of 681 // direct OpenGL bindings needs to call the appropriate form of
658 // eglMakeCurrent. If it doesn't it will be issuing commands on the wrong 682 // eglMakeCurrent. If it doesn't it will be issuing commands on the wrong
659 // context. Uncommenting the line below clears the current context so that 683 // context. Uncommenting the line below clears the current context so that
(...skipping 1032 matching lines...) Expand 10 before | Expand all | Expand 10 after
1692 1716
1693 DELEGATE_TO_GL_9(asyncTexSubImage2DCHROMIUM, AsyncTexSubImage2DCHROMIUM, 1717 DELEGATE_TO_GL_9(asyncTexSubImage2DCHROMIUM, AsyncTexSubImage2DCHROMIUM,
1694 WGC3Denum, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dsizei, WGC3Dsizei, 1718 WGC3Denum, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dsizei, WGC3Dsizei,
1695 WGC3Denum, WGC3Denum, const void*) 1719 WGC3Denum, WGC3Denum, const void*)
1696 1720
1697 DELEGATE_TO_GL_1(waitAsyncTexImage2DCHROMIUM, WaitAsyncTexImage2DCHROMIUM, 1721 DELEGATE_TO_GL_1(waitAsyncTexImage2DCHROMIUM, WaitAsyncTexImage2DCHROMIUM,
1698 WGC3Denum) 1722 WGC3Denum)
1699 1723
1700 } // namespace gpu 1724 } // namespace gpu
1701 } // namespace webkit 1725 } // namespace webkit
OLDNEW
« no previous file with comments | « webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h ('k') | webkit/support/test_webkit_platform_support.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698