OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h" | |
6 | |
7 #include <GLES2/gl2.h> | |
8 #ifndef GL_GLEXT_PROTOTYPES | |
9 #define GL_GLEXT_PROTOTYPES 1 | |
10 #endif | |
11 #include <GLES2/gl2ext.h> | |
12 #include <GLES2/gl2extchromium.h> | |
13 | |
14 #include <algorithm> | |
15 #include <set> | |
16 #include <string> | |
17 | |
18 #include "base/bind.h" | |
19 #include "base/bind_helpers.h" | |
20 #include "base/callback.h" | |
21 #include "base/command_line.h" | |
22 #include "base/lazy_instance.h" | |
23 #include "base/logging.h" | |
24 #include "base/memory/singleton.h" | |
25 #include "base/message_loop.h" | |
26 #include "base/metrics/histogram.h" | |
27 #include "base/synchronization/lock.h" | |
28 #include "gpu/command_buffer/client/gles2_implementation.h" | |
29 #include "gpu/command_buffer/client/gles2_lib.h" | |
30 #include "gpu/command_buffer/client/image_factory.h" | |
31 #include "gpu/command_buffer/client/transfer_buffer.h" | |
32 #include "gpu/command_buffer/common/constants.h" | |
33 #include "gpu/command_buffer/service/command_buffer_service.h" | |
34 #include "gpu/command_buffer/service/context_group.h" | |
35 #include "gpu/command_buffer/service/gl_context_virtual.h" | |
36 #include "gpu/command_buffer/service/gpu_scheduler.h" | |
37 #include "gpu/command_buffer/service/image_manager.h" | |
38 #include "gpu/command_buffer/service/transfer_buffer_manager.h" | |
39 #include "ui/gl/gl_context.h" | |
40 #include "ui/gl/gl_image.h" | |
41 #include "ui/gl/gl_share_group.h" | |
42 #include "ui/gl/gl_surface.h" | |
43 #include "webkit/gpu/gl_bindings_skia_cmd_buffer.h" | |
44 | |
45 using gpu::Buffer; | |
46 using gpu::CommandBuffer; | |
47 using gpu::CommandBufferService; | |
48 using gpu::gles2::GLES2CmdHelper; | |
49 using gpu::gles2::GLES2Implementation; | |
50 using gpu::gles2::ImageFactory; | |
51 using gpu::gles2::ImageManager; | |
52 using gpu::GpuMemoryBuffer; | |
53 using gpu::GpuScheduler; | |
54 using gpu::TransferBuffer; | |
55 using gpu::TransferBufferManager; | |
56 using gpu::TransferBufferManagerInterface; | |
57 | |
58 namespace webkit { | |
59 namespace gpu { | |
60 namespace { | |
61 class ImageFactoryInProcess; | |
62 } | |
63 | |
64 class GLInProcessContext { | |
65 public: | |
66 // These are the same error codes as used by EGL. | |
67 enum Error { | |
68 SUCCESS = 0x3000, | |
69 NOT_INITIALIZED = 0x3001, | |
70 BAD_ATTRIBUTE = 0x3004, | |
71 BAD_GLContext = 0x3006, | |
72 CONTEXT_LOST = 0x300E | |
73 }; | |
74 | |
75 // GLInProcessContext configuration attributes. These are the same as used by | |
76 // EGL. Attributes are matched using a closest fit algorithm. | |
77 enum Attribute { | |
78 ALPHA_SIZE = 0x3021, | |
79 BLUE_SIZE = 0x3022, | |
80 GREEN_SIZE = 0x3023, | |
81 RED_SIZE = 0x3024, | |
82 DEPTH_SIZE = 0x3025, | |
83 STENCIL_SIZE = 0x3026, | |
84 SAMPLES = 0x3031, | |
85 SAMPLE_BUFFERS = 0x3032, | |
86 NONE = 0x3038 // Attrib list = terminator | |
87 }; | |
88 | |
89 // Initialize the library. This must have completed before any other | |
90 // functions are invoked. | |
91 static bool Initialize(); | |
92 | |
93 // Terminate the library. This must be called after any other functions | |
94 // have completed. | |
95 static bool Terminate(); | |
96 | |
97 ~GLInProcessContext(); | |
98 | |
99 void PumpCommands(); | |
100 bool GetBufferChanged(int32 transfer_buffer_id); | |
101 | |
102 // Create a GLInProcessContext, if |is_offscreen| is true, renders to an | |
103 // offscreen context. |attrib_list| must be NULL or a NONE-terminated list | |
104 // of attribute/value pairs. | |
105 static GLInProcessContext* CreateContext( | |
106 bool is_offscreen, | |
107 gfx::AcceleratedWidget window, | |
108 const gfx::Size& size, | |
109 bool share_resources, | |
110 const char* allowed_extensions, | |
111 const int32* attrib_list, | |
112 gfx::GpuPreference gpu_preference); | |
113 | |
114 // For an offscreen frame buffer GLInProcessContext, return the texture ID | |
115 // with respect to the parent GLInProcessContext. Returns zero if | |
116 // GLInProcessContext does not have a parent. | |
117 uint32 GetParentTextureId(); | |
118 | |
119 // Create a new texture in the parent's GLInProcessContext. Returns zero if | |
120 // GLInProcessContext does not have a parent. | |
121 uint32 CreateParentTexture(const gfx::Size& size); | |
122 | |
123 // Deletes a texture in the parent's GLInProcessContext. | |
124 void DeleteParentTexture(uint32 texture); | |
125 | |
126 void SetContextLostCallback(const base::Closure& callback); | |
127 | |
128 // Set the current GLInProcessContext for the calling thread. | |
129 static bool MakeCurrent(GLInProcessContext* context); | |
130 | |
131 // For a view GLInProcessContext, display everything that has been rendered | |
132 // since the last call. For an offscreen GLInProcessContext, resolve | |
133 // everything that has been rendered since the last call to a copy that can be | |
134 // accessed by the parent GLInProcessContext. | |
135 bool SwapBuffers(); | |
136 | |
137 // TODO(gman): Remove this | |
138 void DisableShaderTranslation(); | |
139 | |
140 // Allows direct access to the GLES2 implementation so a GLInProcessContext | |
141 // can be used without making it current. | |
142 GLES2Implementation* GetImplementation(); | |
143 | |
144 // Return the current error. | |
145 Error GetError(); | |
146 | |
147 // Return true if GPU process reported GLInProcessContext lost or there was a | |
148 // problem communicating with the GPU process. | |
149 bool IsCommandBufferContextLost(); | |
150 | |
151 void LoseContext(uint32 current, uint32 other); | |
152 | |
153 void SetSignalSyncPointCallback( | |
154 scoped_ptr< | |
155 WebKit::WebGraphicsContext3D::WebGraphicsSyncPointCallback> callback); | |
156 | |
157 CommandBufferService* GetCommandBufferService(); | |
158 | |
159 ::gpu::gles2::GLES2Decoder* GetDecoder(); | |
160 | |
161 void OnResizeView(gfx::Size size); | |
162 | |
163 private: | |
164 explicit GLInProcessContext(bool share_resources); | |
165 | |
166 bool Initialize(bool is_offscreen, | |
167 gfx::AcceleratedWidget window, | |
168 const gfx::Size& size, | |
169 const char* allowed_extensions, | |
170 const int32* attrib_list, | |
171 gfx::GpuPreference gpu_preference); | |
172 void Destroy(); | |
173 | |
174 void OnContextLost(); | |
175 | |
176 ::gpu::gles2::ImageManager* GetImageManager(); | |
177 | |
178 scoped_refptr<ImageFactoryInProcess> GetImageFactory(); | |
179 | |
180 base::Closure context_lost_callback_; | |
181 scoped_ptr<TransferBufferManagerInterface> transfer_buffer_manager_; | |
182 scoped_ptr<CommandBufferService> command_buffer_; | |
183 scoped_ptr< ::gpu::GpuScheduler> gpu_scheduler_; | |
184 scoped_ptr< ::gpu::gles2::GLES2Decoder> decoder_; | |
185 scoped_refptr<gfx::GLContext> context_; | |
186 scoped_refptr<gfx::GLSurface> surface_; | |
187 scoped_ptr<GLES2CmdHelper> gles2_helper_; | |
188 scoped_ptr<TransferBuffer> transfer_buffer_; | |
189 scoped_ptr<GLES2Implementation> gles2_implementation_; | |
190 scoped_refptr<ImageFactoryInProcess> image_factory_; | |
191 scoped_ptr<WebKit::WebGraphicsContext3D::WebGraphicsSyncPointCallback> | |
192 signal_sync_point_callback_; | |
193 Error last_error_; | |
194 bool share_resources_; | |
195 bool context_lost_; | |
196 | |
197 DISALLOW_COPY_AND_ASSIGN(GLInProcessContext); | |
198 }; | |
199 | |
200 namespace { | |
201 | |
202 const int32 kCommandBufferSize = 1024 * 1024; | |
203 // TODO(kbr): make the transfer buffer size configurable via context | |
204 // creation attributes. | |
205 const size_t kStartTransferBufferSize = 4 * 1024 * 1024; | |
206 const size_t kMinTransferBufferSize = 1 * 256 * 1024; | |
207 const size_t kMaxTransferBufferSize = 16 * 1024 * 1024; | |
208 | |
209 // Singleton used to initialize and terminate the gles2 library. | |
210 class GLES2Initializer { | |
211 public: | |
212 GLES2Initializer() { | |
213 gles2::Initialize(); | |
214 } | |
215 | |
216 ~GLES2Initializer() { | |
217 gles2::Terminate(); | |
218 } | |
219 | |
220 private: | |
221 DISALLOW_COPY_AND_ASSIGN(GLES2Initializer); | |
222 }; | |
223 | |
224 //////////////////////////////////////////////////////////////////////////////// | |
225 | |
226 static base::LazyInstance<GLES2Initializer> g_gles2_initializer = | |
227 LAZY_INSTANCE_INITIALIZER; | |
228 | |
229 } // namespace anonymous | |
230 | |
231 GLInProcessContext::~GLInProcessContext() { | |
232 Destroy(); | |
233 } | |
234 | |
235 GLInProcessContext* GLInProcessContext::CreateContext( | |
236 bool is_offscreen, | |
237 gfx::AcceleratedWidget window, | |
238 const gfx::Size& size, | |
239 bool share_resources, | |
240 const char* allowed_extensions, | |
241 const int32* attrib_list, | |
242 gfx::GpuPreference gpu_preference) { | |
243 scoped_ptr<GLInProcessContext> context( | |
244 new GLInProcessContext(share_resources)); | |
245 if (!context->Initialize( | |
246 is_offscreen, | |
247 window, | |
248 size, | |
249 allowed_extensions, | |
250 attrib_list, | |
251 gpu_preference)) | |
252 return NULL; | |
253 | |
254 return context.release(); | |
255 } | |
256 | |
257 // In the normal command buffer implementation, all commands are passed over IPC | |
258 // to the gpu process where they are fed to the GLES2Decoder from a single | |
259 // thread. In layout tests, any thread could call this function. GLES2Decoder, | |
260 // and in particular the GL implementations behind it, are not generally | |
261 // threadsafe, so we guard entry points with a mutex. | |
262 static base::LazyInstance<base::Lock> g_decoder_lock = | |
263 LAZY_INSTANCE_INITIALIZER; | |
264 | |
265 static base::LazyInstance< | |
266 std::set<GLInProcessContext*> > | |
267 g_all_shared_contexts = LAZY_INSTANCE_INITIALIZER; | |
268 | |
269 static bool g_use_virtualized_gl_context = false; | |
270 | |
271 namespace { | |
272 | |
273 // Also calls DetachFromThread on all GLES2Decoders before the lock is released | |
274 // to maintain the invariant that all decoders are unbounded while the lock is | |
275 // not held. This is to workaround DumpRenderTree uses WGC3DIPCBI with shared | |
276 // resources on different threads. | |
277 class AutoLockAndDecoderDetachThread { | |
278 public: | |
279 AutoLockAndDecoderDetachThread(base::Lock& lock, | |
280 const std::set<GLInProcessContext*>& contexts); | |
281 ~AutoLockAndDecoderDetachThread(); | |
282 | |
283 private: | |
284 base::AutoLock auto_lock_; | |
285 const std::set<GLInProcessContext*>& contexts_; | |
286 }; | |
287 | |
288 AutoLockAndDecoderDetachThread::AutoLockAndDecoderDetachThread( | |
289 base::Lock& lock, | |
290 const std::set<GLInProcessContext*>& contexts) | |
291 : auto_lock_(lock), | |
292 contexts_(contexts) { | |
293 } | |
294 | |
295 void DetachThread(GLInProcessContext* context) { | |
296 if (context->GetDecoder()) | |
297 context->GetDecoder()->DetachFromThread(); | |
298 } | |
299 | |
300 AutoLockAndDecoderDetachThread::~AutoLockAndDecoderDetachThread() { | |
301 std::for_each(contexts_.begin(), | |
302 contexts_.end(), | |
303 &DetachThread); | |
304 } | |
305 | |
306 static WebGraphicsContext3DInProcessCommandBufferImpl::GpuMemoryBufferCreator* | |
307 g_gpu_memory_buffer_creator = NULL; | |
308 | |
309 class ImageFactoryInProcess | |
310 : public ImageFactory, | |
311 public base::RefCountedThreadSafe<ImageFactoryInProcess> { | |
312 public: | |
313 explicit ImageFactoryInProcess(ImageManager* image_manager); | |
314 | |
315 // methods from ImageFactory | |
316 virtual scoped_ptr<GpuMemoryBuffer> CreateGpuMemoryBuffer( | |
317 int width, int height, GLenum internalformat, | |
318 unsigned* image_id) OVERRIDE; | |
319 virtual void DeleteGpuMemoryBuffer(unsigned image_id) OVERRIDE; | |
320 private: | |
321 friend class base::RefCountedThreadSafe<ImageFactoryInProcess>; | |
322 virtual ~ImageFactoryInProcess(); | |
323 | |
324 // ImageManager is referred by the ContextGroup and the | |
325 // ContextGroup outlives the client. | |
326 ImageManager* image_manager_; | |
327 unsigned next_id_; | |
328 | |
329 DISALLOW_COPY_AND_ASSIGN(ImageFactoryInProcess); | |
330 }; | |
331 | |
332 ImageFactoryInProcess::ImageFactoryInProcess( | |
333 ImageManager* image_manager) : image_manager_(image_manager), | |
334 next_id_(0) { | |
335 } | |
336 | |
337 ImageFactoryInProcess::~ImageFactoryInProcess() { | |
338 } | |
339 | |
340 scoped_ptr<GpuMemoryBuffer> ImageFactoryInProcess::CreateGpuMemoryBuffer( | |
341 int width, int height, GLenum internalformat, unsigned int* image_id) { | |
342 // We're taking the lock here because we're accessing the ContextGroup's | |
343 // shared ImageManager and next_id_. | |
344 AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(), | |
345 g_all_shared_contexts.Get()); | |
346 // For Android WebView we assume the |internalformat| will always be | |
347 // GL_RGBA8_OES. | |
348 DCHECK_EQ(GL_RGBA8_OES, internalformat); | |
349 scoped_ptr<GpuMemoryBuffer> buffer = | |
350 g_gpu_memory_buffer_creator(width, height); | |
351 | |
352 if (buffer.get() == NULL) | |
353 return buffer.Pass(); | |
354 | |
355 scoped_refptr<gfx::GLImage> gl_image = | |
356 gfx::GLImage::CreateGLImageForGpuMemoryBuffer(buffer->GetNativeBuffer(), | |
357 gfx::Size(width, height)); | |
358 *image_id = ++next_id_; // Valid image_ids start from 1. | |
359 image_manager_->AddImage(gl_image, *image_id); | |
360 return buffer.Pass(); | |
361 } | |
362 | |
363 void ImageFactoryInProcess::DeleteGpuMemoryBuffer(unsigned int image_id) { | |
364 // We're taking the lock here because we're accessing the ContextGroup's | |
365 // shared ImageManager. | |
366 AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(), | |
367 g_all_shared_contexts.Get()); | |
368 image_manager_->RemoveImage(image_id); | |
369 } | |
370 | |
371 } // namespace | |
372 | |
373 static void CallAndDestroy( | |
374 scoped_ptr< | |
375 WebKit::WebGraphicsContext3D::WebGraphicsSyncPointCallback> callback) { | |
376 callback->onSyncPointReached(); | |
377 } | |
378 | |
379 void GLInProcessContext::PumpCommands() { | |
380 if (!context_lost_) { | |
381 AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(), | |
382 g_all_shared_contexts.Get()); | |
383 decoder_->MakeCurrent(); | |
384 gpu_scheduler_->PutChanged(); | |
385 ::gpu::CommandBuffer::State state = command_buffer_->GetState(); | |
386 if (::gpu::error::IsError(state.error)) | |
387 context_lost_ = true; | |
388 } | |
389 | |
390 if (!context_lost_ && signal_sync_point_callback_) { | |
391 base::MessageLoop::current()->PostTask( | |
392 FROM_HERE, | |
393 base::Bind(&CallAndDestroy, | |
394 base::Passed(&signal_sync_point_callback_))); | |
395 } | |
396 } | |
397 | |
398 bool GLInProcessContext::GetBufferChanged(int32 transfer_buffer_id) { | |
399 return gpu_scheduler_->SetGetBuffer(transfer_buffer_id); | |
400 } | |
401 | |
402 uint32 GLInProcessContext::GetParentTextureId() { | |
403 return 0; | |
404 } | |
405 | |
406 uint32 GLInProcessContext::CreateParentTexture(const gfx::Size& size) { | |
407 uint32 texture = 0; | |
408 gles2_implementation_->GenTextures(1, &texture); | |
409 gles2_implementation_->Flush(); | |
410 return texture; | |
411 } | |
412 | |
413 void GLInProcessContext::DeleteParentTexture(uint32 texture) { | |
414 gles2_implementation_->DeleteTextures(1, &texture); | |
415 } | |
416 | |
417 void GLInProcessContext::SetContextLostCallback(const base::Closure& callback) { | |
418 context_lost_callback_ = callback; | |
419 } | |
420 | |
421 bool GLInProcessContext::MakeCurrent(GLInProcessContext* context) { | |
422 if (context) { | |
423 gles2::SetGLContext(context->gles2_implementation_.get()); | |
424 | |
425 // Don't request latest error status from service. Just use the locally | |
426 // cached information from the last flush. | |
427 // TODO(apatrick): I'm not sure if this should actually change the | |
428 // current context if it fails. For now it gets changed even if it fails | |
429 // because making GL calls with a NULL context crashes. | |
430 if (context->command_buffer_->GetState().error != ::gpu::error::kNoError) | |
431 return false; | |
432 } else { | |
433 gles2::SetGLContext(NULL); | |
434 } | |
435 | |
436 return true; | |
437 } | |
438 | |
439 bool GLInProcessContext::SwapBuffers() { | |
440 // Don't request latest error status from service. Just use the locally cached | |
441 // information from the last flush. | |
442 if (command_buffer_->GetState().error != ::gpu::error::kNoError) | |
443 return false; | |
444 | |
445 gles2_implementation_->SwapBuffers(); | |
446 gles2_implementation_->Finish(); | |
447 return true; | |
448 } | |
449 | |
450 GLInProcessContext::Error GLInProcessContext::GetError() { | |
451 CommandBuffer::State state = command_buffer_->GetState(); | |
452 if (state.error == ::gpu::error::kNoError) { | |
453 // TODO(gman): Figure out and document what this logic is for. | |
454 Error old_error = last_error_; | |
455 last_error_ = SUCCESS; | |
456 return old_error; | |
457 } else { | |
458 // All command buffer errors are unrecoverable. The error is treated as a | |
459 // lost context: destroy the context and create another one. | |
460 return CONTEXT_LOST; | |
461 } | |
462 } | |
463 | |
464 bool GLInProcessContext::IsCommandBufferContextLost() { | |
465 if (context_lost_ || !command_buffer_) { | |
466 return true; | |
467 } | |
468 CommandBuffer::State state = command_buffer_->GetState(); | |
469 return ::gpu::error::IsError(state.error); | |
470 } | |
471 | |
472 void GLInProcessContext::LoseContext(uint32 current, uint32 other) { | |
473 gles2_implementation_->LoseContextCHROMIUM(current, other); | |
474 gles2_implementation_->Finish(); | |
475 DCHECK(IsCommandBufferContextLost()); | |
476 } | |
477 | |
478 void GLInProcessContext::SetSignalSyncPointCallback( | |
479 scoped_ptr< | |
480 WebKit::WebGraphicsContext3D::WebGraphicsSyncPointCallback> callback) { | |
481 signal_sync_point_callback_ = callback.Pass(); | |
482 } | |
483 | |
484 CommandBufferService* GLInProcessContext::GetCommandBufferService() { | |
485 return command_buffer_.get(); | |
486 } | |
487 | |
488 ::gpu::gles2::GLES2Decoder* GLInProcessContext::GetDecoder() { | |
489 return decoder_.get(); | |
490 } | |
491 | |
492 void GLInProcessContext::OnResizeView(gfx::Size size) { | |
493 DCHECK(!surface_->IsOffscreen()); | |
494 surface_->Resize(size); | |
495 } | |
496 | |
497 // TODO(gman): Remove This | |
498 void GLInProcessContext::DisableShaderTranslation() { | |
499 NOTREACHED(); | |
500 } | |
501 | |
502 GLES2Implementation* GLInProcessContext::GetImplementation() { | |
503 return gles2_implementation_.get(); | |
504 } | |
505 | |
506 ::gpu::gles2::ImageManager* GLInProcessContext::GetImageManager() { | |
507 return decoder_->GetContextGroup()->image_manager(); | |
508 } | |
509 | |
510 scoped_refptr<ImageFactoryInProcess> GLInProcessContext::GetImageFactory() { | |
511 return image_factory_; | |
512 } | |
513 | |
514 GLInProcessContext::GLInProcessContext(bool share_resources) | |
515 : last_error_(SUCCESS), | |
516 share_resources_(share_resources), | |
517 context_lost_(false) { | |
518 } | |
519 | |
520 bool GLInProcessContext::Initialize( | |
521 bool is_offscreen, | |
522 gfx::AcceleratedWidget window, | |
523 const gfx::Size& size, | |
524 const char* allowed_extensions, | |
525 const int32* attrib_list, | |
526 gfx::GpuPreference gpu_preference) { | |
527 // Use one share group for all contexts. | |
528 CR_DEFINE_STATIC_LOCAL(scoped_refptr<gfx::GLShareGroup>, share_group, | |
529 (new gfx::GLShareGroup)); | |
530 | |
531 DCHECK(size.width() >= 0 && size.height() >= 0); | |
532 | |
533 // Ensure the gles2 library is initialized first in a thread safe way. | |
534 g_gles2_initializer.Get(); | |
535 | |
536 std::vector<int32> attribs; | |
537 while (attrib_list) { | |
538 int32 attrib = *attrib_list++; | |
539 switch (attrib) { | |
540 // Known attributes | |
541 case ALPHA_SIZE: | |
542 case BLUE_SIZE: | |
543 case GREEN_SIZE: | |
544 case RED_SIZE: | |
545 case DEPTH_SIZE: | |
546 case STENCIL_SIZE: | |
547 case SAMPLES: | |
548 case SAMPLE_BUFFERS: | |
549 attribs.push_back(attrib); | |
550 attribs.push_back(*attrib_list++); | |
551 break; | |
552 case NONE: | |
553 attribs.push_back(attrib); | |
554 attrib_list = NULL; | |
555 break; | |
556 default: | |
557 last_error_ = BAD_ATTRIBUTE; | |
558 attribs.push_back(NONE); | |
559 attrib_list = NULL; | |
560 break; | |
561 } | |
562 } | |
563 | |
564 { | |
565 TransferBufferManager* manager = new TransferBufferManager(); | |
566 transfer_buffer_manager_.reset(manager); | |
567 manager->Initialize(); | |
568 } | |
569 | |
570 command_buffer_.reset( | |
571 new CommandBufferService(transfer_buffer_manager_.get())); | |
572 if (!command_buffer_->Initialize()) { | |
573 LOG(ERROR) << "Could not initialize command buffer."; | |
574 Destroy(); | |
575 return false; | |
576 } | |
577 | |
578 GLInProcessContext* context_group = NULL; | |
579 | |
580 { | |
581 AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(), | |
582 g_all_shared_contexts.Get()); | |
583 if (share_resources_ && !g_all_shared_contexts.Get().empty()) { | |
584 for (std::set<GLInProcessContext*>::iterator it = | |
585 g_all_shared_contexts.Get().begin(); | |
586 it != g_all_shared_contexts.Get().end(); | |
587 ++it) { | |
588 if (!(*it)->IsCommandBufferContextLost()) { | |
589 context_group = *it; | |
590 break; | |
591 } | |
592 } | |
593 if (!context_group) | |
594 share_group = new gfx::GLShareGroup; | |
595 } | |
596 | |
597 // TODO(gman): This needs to be true if this is Pepper. | |
598 bool bind_generates_resource = false; | |
599 decoder_.reset(::gpu::gles2::GLES2Decoder::Create(context_group ? | |
600 context_group->decoder_->GetContextGroup() : | |
601 new ::gpu::gles2::ContextGroup( | |
602 NULL, NULL, NULL, bind_generates_resource))); | |
603 | |
604 gpu_scheduler_.reset(new GpuScheduler(command_buffer_.get(), | |
605 decoder_.get(), | |
606 decoder_.get())); | |
607 | |
608 decoder_->set_engine(gpu_scheduler_.get()); | |
609 | |
610 if (is_offscreen) | |
611 surface_ = gfx::GLSurface::CreateOffscreenGLSurface(false, size); | |
612 else | |
613 surface_ = gfx::GLSurface::CreateViewGLSurface(false, window); | |
614 | |
615 if (!surface_) { | |
616 LOG(ERROR) << "Could not create GLSurface."; | |
617 Destroy(); | |
618 return false; | |
619 } | |
620 | |
621 if (g_use_virtualized_gl_context) { | |
622 context_ = share_group->GetSharedContext(); | |
623 if (!context_) { | |
624 context_ = gfx::GLContext::CreateGLContext(share_group.get(), | |
625 surface_.get(), | |
626 gpu_preference); | |
627 share_group->SetSharedContext(context_); | |
628 } | |
629 | |
630 context_ = new ::gpu::GLContextVirtual(share_group.get(), | |
631 context_, | |
632 decoder_->AsWeakPtr()); | |
633 if (context_->Initialize(surface_, gpu_preference)) { | |
634 VLOG(1) << "Created virtual GL context."; | |
635 } else { | |
636 context_ = NULL; | |
637 } | |
638 } else { | |
639 context_ = gfx::GLContext::CreateGLContext(share_group.get(), | |
640 surface_.get(), | |
641 gpu_preference); | |
642 } | |
643 | |
644 if (!context_) { | |
645 LOG(ERROR) << "Could not create GLContext."; | |
646 Destroy(); | |
647 return false; | |
648 } | |
649 | |
650 if (!context_->MakeCurrent(surface_)) { | |
651 LOG(ERROR) << "Could not make context current."; | |
652 Destroy(); | |
653 return false; | |
654 } | |
655 | |
656 ::gpu::gles2::DisallowedFeatures disallowed_features; | |
657 disallowed_features.swap_buffer_complete_callback = true; | |
658 disallowed_features.gpu_memory_manager = true; | |
659 if (!decoder_->Initialize(surface_, | |
660 context_, | |
661 is_offscreen, | |
662 size, | |
663 disallowed_features, | |
664 allowed_extensions, | |
665 attribs)) { | |
666 LOG(ERROR) << "Could not initialize decoder."; | |
667 Destroy(); | |
668 return false; | |
669 } | |
670 | |
671 if (!is_offscreen) { | |
672 decoder_->SetResizeCallback(base::Bind(&GLInProcessContext::OnResizeView, | |
673 base::Unretained(this))); | |
674 } | |
675 } | |
676 | |
677 command_buffer_->SetPutOffsetChangeCallback( | |
678 base::Bind(&GLInProcessContext::PumpCommands, base::Unretained(this))); | |
679 command_buffer_->SetGetBufferChangeCallback( | |
680 base::Bind( | |
681 &GLInProcessContext::GetBufferChanged, base::Unretained(this))); | |
682 command_buffer_->SetParseErrorCallback( | |
683 base::Bind(&GLInProcessContext::OnContextLost, base::Unretained(this))); | |
684 | |
685 // Create the GLES2 helper, which writes the command buffer protocol. | |
686 gles2_helper_.reset(new GLES2CmdHelper(command_buffer_.get())); | |
687 if (!gles2_helper_->Initialize(kCommandBufferSize)) { | |
688 Destroy(); | |
689 return false; | |
690 } | |
691 | |
692 // Create a transfer buffer. | |
693 transfer_buffer_.reset(new TransferBuffer(gles2_helper_.get())); | |
694 | |
695 if (share_resources_) { | |
696 AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(), | |
697 g_all_shared_contexts.Get()); | |
698 if (g_all_shared_contexts.Get().empty()) { | |
699 // Create the image factory for the first context. | |
700 image_factory_ = new ImageFactoryInProcess(GetImageManager()); | |
701 } else { | |
702 // Share the image factory created by the first context. | |
703 GLInProcessContext* first_context = *g_all_shared_contexts.Get().begin(); | |
704 image_factory_ = first_context->GetImageFactory(); | |
705 } | |
706 } else { | |
707 // Create the image factory, this object retains its ownership. | |
708 image_factory_ = new ImageFactoryInProcess(GetImageManager()); | |
709 } | |
710 | |
711 // Create the object exposing the OpenGL API. | |
712 gles2_implementation_.reset(new GLES2Implementation( | |
713 gles2_helper_.get(), | |
714 context_group ? context_group->GetImplementation()->share_group() : NULL, | |
715 transfer_buffer_.get(), | |
716 true, | |
717 false, | |
718 image_factory_)); | |
719 | |
720 if (!gles2_implementation_->Initialize( | |
721 kStartTransferBufferSize, | |
722 kMinTransferBufferSize, | |
723 kMaxTransferBufferSize)) { | |
724 return false; | |
725 } | |
726 | |
727 if (share_resources_) { | |
728 AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(), | |
729 g_all_shared_contexts.Get()); | |
730 g_all_shared_contexts.Pointer()->insert(this); | |
731 } | |
732 | |
733 return true; | |
734 } | |
735 | |
736 void GLInProcessContext::Destroy() { | |
737 bool context_lost = IsCommandBufferContextLost(); | |
738 | |
739 if (gles2_implementation_) { | |
740 // First flush the context to ensure that any pending frees of resources | |
741 // are completed. Otherwise, if this context is part of a share group, | |
742 // those resources might leak. Also, any remaining side effects of commands | |
743 // issued on this context might not be visible to other contexts in the | |
744 // share group. | |
745 gles2_implementation_->Flush(); | |
746 | |
747 gles2_implementation_.reset(); | |
748 } | |
749 | |
750 transfer_buffer_.reset(); | |
751 gles2_helper_.reset(); | |
752 command_buffer_.reset(); | |
753 | |
754 AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(), | |
755 g_all_shared_contexts.Get()); | |
756 if (decoder_) { | |
757 decoder_->Destroy(!context_lost); | |
758 } | |
759 | |
760 g_all_shared_contexts.Pointer()->erase(this); | |
761 } | |
762 | |
763 void GLInProcessContext::OnContextLost() { | |
764 if (!context_lost_callback_.is_null()) | |
765 context_lost_callback_.Run(); | |
766 | |
767 context_lost_ = true; | |
768 if (share_resources_) { | |
769 for (std::set<GLInProcessContext*>::iterator it = | |
770 g_all_shared_contexts.Get().begin(); | |
771 it != g_all_shared_contexts.Get().end(); | |
772 ++it) | |
773 (*it)->context_lost_ = true; | |
774 } | |
775 } | |
776 | |
777 // static | |
778 void | |
779 WebGraphicsContext3DInProcessCommandBufferImpl::EnableVirtualizedContext() { | |
780 #if !defined(NDEBUG) | |
781 { | |
782 AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(), | |
783 g_all_shared_contexts.Get()); | |
784 DCHECK(g_all_shared_contexts.Get().empty()); | |
785 } | |
786 #endif // !defined(NDEBUG) | |
787 g_use_virtualized_gl_context = true; | |
788 } | |
789 | |
790 // static | |
791 WebGraphicsContext3DInProcessCommandBufferImpl* | |
792 WebGraphicsContext3DInProcessCommandBufferImpl::CreateViewContext( | |
793 const WebKit::WebGraphicsContext3D::Attributes& attributes, | |
794 gfx::AcceleratedWidget window) { | |
795 if (!gfx::GLSurface::InitializeOneOff()) | |
796 return NULL; | |
797 return new WebGraphicsContext3DInProcessCommandBufferImpl( | |
798 attributes, false, window); | |
799 } | |
800 | |
801 // static | |
802 WebGraphicsContext3DInProcessCommandBufferImpl* | |
803 WebGraphicsContext3DInProcessCommandBufferImpl::CreateOffscreenContext( | |
804 const WebKit::WebGraphicsContext3D::Attributes& attributes) { | |
805 return new WebGraphicsContext3DInProcessCommandBufferImpl( | |
806 attributes, true, gfx::kNullAcceleratedWidget); | |
807 } | |
808 | |
809 WebGraphicsContext3DInProcessCommandBufferImpl:: | |
810 WebGraphicsContext3DInProcessCommandBufferImpl( | |
811 const WebKit::WebGraphicsContext3D::Attributes& attributes, | |
812 bool is_offscreen, | |
813 gfx::AcceleratedWidget window) | |
814 : is_offscreen_(is_offscreen), | |
815 window_(window), | |
816 initialized_(false), | |
817 initialize_failed_(false), | |
818 context_(NULL), | |
819 gl_(NULL), | |
820 context_lost_callback_(NULL), | |
821 context_lost_reason_(GL_NO_ERROR), | |
822 attributes_(attributes), | |
823 cached_width_(0), | |
824 cached_height_(0), | |
825 bound_fbo_(0) { | |
826 } | |
827 | |
828 WebGraphicsContext3DInProcessCommandBufferImpl:: | |
829 ~WebGraphicsContext3DInProcessCommandBufferImpl() { | |
830 } | |
831 | |
832 bool WebGraphicsContext3DInProcessCommandBufferImpl::MaybeInitializeGL() { | |
833 if (initialized_) | |
834 return true; | |
835 | |
836 if (initialize_failed_) | |
837 return false; | |
838 | |
839 // Convert WebGL context creation attributes into GLInProcessContext / EGL | |
840 // size requests. | |
841 const int alpha_size = attributes_.alpha ? 8 : 0; | |
842 const int depth_size = attributes_.depth ? 24 : 0; | |
843 const int stencil_size = attributes_.stencil ? 8 : 0; | |
844 const int samples = attributes_.antialias ? 4 : 0; | |
845 const int sample_buffers = attributes_.antialias ? 1 : 0; | |
846 const int32 attribs[] = { | |
847 GLInProcessContext::ALPHA_SIZE, alpha_size, | |
848 GLInProcessContext::DEPTH_SIZE, depth_size, | |
849 GLInProcessContext::STENCIL_SIZE, stencil_size, | |
850 GLInProcessContext::SAMPLES, samples, | |
851 GLInProcessContext::SAMPLE_BUFFERS, sample_buffers, | |
852 GLInProcessContext::NONE, | |
853 }; | |
854 | |
855 const char* preferred_extensions = "*"; | |
856 | |
857 // TODO(kbr): More work will be needed in this implementation to | |
858 // properly support GPU switching. Like in the out-of-process | |
859 // command buffer implementation, all previously created contexts | |
860 // will need to be lost either when the first context requesting the | |
861 // discrete GPU is created, or the last one is destroyed. | |
862 gfx::GpuPreference gpu_preference = gfx::PreferDiscreteGpu; | |
863 | |
864 context_ = GLInProcessContext::CreateContext( | |
865 is_offscreen_, | |
866 window_, | |
867 gfx::Size(1, 1), | |
868 attributes_.shareResources, | |
869 preferred_extensions, | |
870 attribs, | |
871 gpu_preference); | |
872 | |
873 if (!context_) { | |
874 initialize_failed_ = true; | |
875 return false; | |
876 } | |
877 | |
878 gl_ = context_->GetImplementation(); | |
879 | |
880 if (gl_ && attributes_.noExtensions) | |
881 gl_->EnableFeatureCHROMIUM("webgl_enable_glsl_webgl_validation"); | |
882 | |
883 context_->SetContextLostCallback( | |
884 base::Bind( | |
885 &WebGraphicsContext3DInProcessCommandBufferImpl::OnContextLost, | |
886 base::Unretained(this))); | |
887 | |
888 // Set attributes_ from created offscreen context. | |
889 { | |
890 GLint alpha_bits = 0; | |
891 getIntegerv(GL_ALPHA_BITS, &alpha_bits); | |
892 attributes_.alpha = alpha_bits > 0; | |
893 GLint depth_bits = 0; | |
894 getIntegerv(GL_DEPTH_BITS, &depth_bits); | |
895 attributes_.depth = depth_bits > 0; | |
896 GLint stencil_bits = 0; | |
897 getIntegerv(GL_STENCIL_BITS, &stencil_bits); | |
898 attributes_.stencil = stencil_bits > 0; | |
899 GLint sample_buffers = 0; | |
900 getIntegerv(GL_SAMPLE_BUFFERS, &sample_buffers); | |
901 attributes_.antialias = sample_buffers > 0; | |
902 } | |
903 | |
904 initialized_ = true; | |
905 return true; | |
906 } | |
907 | |
908 bool WebGraphicsContext3DInProcessCommandBufferImpl::makeContextCurrent() { | |
909 if (!MaybeInitializeGL()) | |
910 return false; | |
911 | |
912 return GLInProcessContext::MakeCurrent(context_); | |
913 } | |
914 | |
915 void WebGraphicsContext3DInProcessCommandBufferImpl::ClearContext() { | |
916 // NOTE: Comment in the line below to check for code that is not calling | |
917 // eglMakeCurrent where appropriate. The issue is code using | |
918 // WebGraphicsContext3D does not need to call makeContextCurrent. Code using | |
919 // direct OpenGL bindings needs to call the appropriate form of | |
920 // eglMakeCurrent. If it doesn't it will be issuing commands on the wrong | |
921 // context. Uncommenting the line below clears the current context so that | |
922 // any code not calling eglMakeCurrent in the appropriate place should crash. | |
923 // This is not a perfect test but generally code that used the direct OpenGL | |
924 // bindings should not be mixed with code that uses WebGraphicsContext3D. | |
925 // | |
926 // GLInProcessContext::MakeCurrent(NULL); | |
927 } | |
928 | |
929 int WebGraphicsContext3DInProcessCommandBufferImpl::width() { | |
930 return cached_width_; | |
931 } | |
932 | |
933 int WebGraphicsContext3DInProcessCommandBufferImpl::height() { | |
934 return cached_height_; | |
935 } | |
936 | |
937 bool WebGraphicsContext3DInProcessCommandBufferImpl::isGLES2Compliant() { | |
938 return true; | |
939 } | |
940 | |
941 bool WebGraphicsContext3DInProcessCommandBufferImpl::setParentContext( | |
942 WebGraphicsContext3D* parent_context) { | |
943 return false; | |
944 } | |
945 | |
946 WebGLId WebGraphicsContext3DInProcessCommandBufferImpl::getPlatformTextureId() { | |
947 DCHECK(context_); | |
948 return context_->GetParentTextureId(); | |
949 } | |
950 | |
951 void WebGraphicsContext3DInProcessCommandBufferImpl::prepareTexture() { | |
952 // Copies the contents of the off-screen render target into the texture | |
953 // used by the compositor. | |
954 context_->SwapBuffers(); | |
955 } | |
956 | |
957 void WebGraphicsContext3DInProcessCommandBufferImpl::postSubBufferCHROMIUM( | |
958 int x, int y, int width, int height) { | |
959 gl_->PostSubBufferCHROMIUM(x, y, width, height); | |
960 } | |
961 | |
962 void WebGraphicsContext3DInProcessCommandBufferImpl::reshape( | |
963 int width, int height) { | |
964 reshapeWithScaleFactor(width, height, 1.0f); | |
965 } | |
966 | |
967 void WebGraphicsContext3DInProcessCommandBufferImpl::reshapeWithScaleFactor( | |
968 int width, int height, float scale_factor) { | |
969 cached_width_ = width; | |
970 cached_height_ = height; | |
971 | |
972 // TODO(gmam): See if we can comment this in. | |
973 // ClearContext(); | |
974 | |
975 gl_->ResizeCHROMIUM(width, height); | |
976 } | |
977 | |
978 WebGLId WebGraphicsContext3DInProcessCommandBufferImpl::createCompositorTexture( | |
979 WGC3Dsizei width, WGC3Dsizei height) { | |
980 // TODO(gmam): See if we can comment this in. | |
981 // ClearContext(); | |
982 return context_->CreateParentTexture(gfx::Size(width, height)); | |
983 } | |
984 | |
985 void WebGraphicsContext3DInProcessCommandBufferImpl::deleteCompositorTexture( | |
986 WebGLId parent_texture) { | |
987 // TODO(gmam): See if we can comment this in. | |
988 // ClearContext(); | |
989 context_->DeleteParentTexture(parent_texture); | |
990 } | |
991 | |
992 void WebGraphicsContext3DInProcessCommandBufferImpl::FlipVertically( | |
993 uint8* framebuffer, | |
994 unsigned int width, | |
995 unsigned int height) { | |
996 if (width == 0) | |
997 return; | |
998 scanline_.resize(width * 4); | |
999 uint8* scanline = &scanline_[0]; | |
1000 unsigned int row_bytes = width * 4; | |
1001 unsigned int count = height / 2; | |
1002 for (unsigned int i = 0; i < count; i++) { | |
1003 uint8* row_a = framebuffer + i * row_bytes; | |
1004 uint8* row_b = framebuffer + (height - i - 1) * row_bytes; | |
1005 // TODO(kbr): this is where the multiplication of the alpha | |
1006 // channel into the color buffer will need to occur if the | |
1007 // user specifies the "premultiplyAlpha" flag in the context | |
1008 // creation attributes. | |
1009 memcpy(scanline, row_b, row_bytes); | |
1010 memcpy(row_b, row_a, row_bytes); | |
1011 memcpy(row_a, scanline, row_bytes); | |
1012 } | |
1013 } | |
1014 | |
1015 bool WebGraphicsContext3DInProcessCommandBufferImpl::readBackFramebuffer( | |
1016 unsigned char* pixels, | |
1017 size_t buffer_size, | |
1018 WebGLId framebuffer, | |
1019 int width, | |
1020 int height) { | |
1021 // TODO(gmam): See if we can comment this in. | |
1022 // ClearContext(); | |
1023 if (buffer_size != static_cast<size_t>(4 * width * height)) { | |
1024 return false; | |
1025 } | |
1026 | |
1027 // Earlier versions of this code used the GPU to flip the | |
1028 // framebuffer vertically before reading it back for compositing | |
1029 // via software. This code was quite complicated, used a lot of | |
1030 // GPU memory, and didn't provide an obvious speedup. Since this | |
1031 // vertical flip is only a temporary solution anyway until Chrome | |
1032 // is fully GPU composited, it wasn't worth the complexity. | |
1033 | |
1034 bool mustRestoreFBO = (bound_fbo_ != framebuffer); | |
1035 if (mustRestoreFBO) { | |
1036 gl_->BindFramebuffer(GL_FRAMEBUFFER, framebuffer); | |
1037 } | |
1038 gl_->ReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels); | |
1039 | |
1040 // Swizzle red and blue channels | |
1041 // TODO(kbr): expose GL_BGRA as extension | |
1042 for (size_t i = 0; i < buffer_size; i += 4) { | |
1043 std::swap(pixels[i], pixels[i + 2]); | |
1044 } | |
1045 | |
1046 if (mustRestoreFBO) { | |
1047 gl_->BindFramebuffer(GL_FRAMEBUFFER, bound_fbo_); | |
1048 } | |
1049 | |
1050 if (pixels) { | |
1051 FlipVertically(pixels, width, height); | |
1052 } | |
1053 | |
1054 return true; | |
1055 } | |
1056 | |
1057 bool WebGraphicsContext3DInProcessCommandBufferImpl::readBackFramebuffer( | |
1058 unsigned char* pixels, | |
1059 size_t buffer_size) { | |
1060 return readBackFramebuffer(pixels, buffer_size, 0, width(), height()); | |
1061 } | |
1062 | |
1063 void WebGraphicsContext3DInProcessCommandBufferImpl::synthesizeGLError( | |
1064 WGC3Denum error) { | |
1065 if (std::find(synthetic_errors_.begin(), synthetic_errors_.end(), error) == | |
1066 synthetic_errors_.end()) { | |
1067 synthetic_errors_.push_back(error); | |
1068 } | |
1069 } | |
1070 | |
1071 void* WebGraphicsContext3DInProcessCommandBufferImpl::mapBufferSubDataCHROMIUM( | |
1072 WGC3Denum target, | |
1073 WGC3Dintptr offset, | |
1074 WGC3Dsizeiptr size, | |
1075 WGC3Denum access) { | |
1076 ClearContext(); | |
1077 return gl_->MapBufferSubDataCHROMIUM(target, offset, size, access); | |
1078 } | |
1079 | |
1080 void WebGraphicsContext3DInProcessCommandBufferImpl::unmapBufferSubDataCHROMIUM( | |
1081 const void* mem) { | |
1082 ClearContext(); | |
1083 return gl_->UnmapBufferSubDataCHROMIUM(mem); | |
1084 } | |
1085 | |
1086 void* WebGraphicsContext3DInProcessCommandBufferImpl::mapTexSubImage2DCHROMIUM( | |
1087 WGC3Denum target, | |
1088 WGC3Dint level, | |
1089 WGC3Dint xoffset, | |
1090 WGC3Dint yoffset, | |
1091 WGC3Dsizei width, | |
1092 WGC3Dsizei height, | |
1093 WGC3Denum format, | |
1094 WGC3Denum type, | |
1095 WGC3Denum access) { | |
1096 ClearContext(); | |
1097 return gl_->MapTexSubImage2DCHROMIUM( | |
1098 target, level, xoffset, yoffset, width, height, format, type, access); | |
1099 } | |
1100 | |
1101 void WebGraphicsContext3DInProcessCommandBufferImpl::unmapTexSubImage2DCHROMIUM( | |
1102 const void* mem) { | |
1103 ClearContext(); | |
1104 gl_->UnmapTexSubImage2DCHROMIUM(mem); | |
1105 } | |
1106 | |
1107 void WebGraphicsContext3DInProcessCommandBufferImpl::setVisibilityCHROMIUM( | |
1108 bool visible) { | |
1109 } | |
1110 | |
1111 void WebGraphicsContext3DInProcessCommandBufferImpl:: | |
1112 setMemoryAllocationChangedCallbackCHROMIUM( | |
1113 WebGraphicsMemoryAllocationChangedCallbackCHROMIUM* callback) { | |
1114 } | |
1115 | |
1116 void WebGraphicsContext3DInProcessCommandBufferImpl::discardFramebufferEXT( | |
1117 WGC3Denum target, WGC3Dsizei numAttachments, const WGC3Denum* attachments) { | |
1118 gl_->DiscardFramebufferEXT(target, numAttachments, attachments); | |
1119 } | |
1120 | |
1121 void WebGraphicsContext3DInProcessCommandBufferImpl:: | |
1122 discardBackbufferCHROMIUM() { | |
1123 } | |
1124 | |
1125 void WebGraphicsContext3DInProcessCommandBufferImpl:: | |
1126 ensureBackbufferCHROMIUM() { | |
1127 } | |
1128 | |
1129 void WebGraphicsContext3DInProcessCommandBufferImpl:: | |
1130 copyTextureToParentTextureCHROMIUM(WebGLId texture, WebGLId parentTexture) { | |
1131 NOTIMPLEMENTED(); | |
1132 } | |
1133 | |
1134 void WebGraphicsContext3DInProcessCommandBufferImpl:: | |
1135 rateLimitOffscreenContextCHROMIUM() { | |
1136 // TODO(gmam): See if we can comment this in. | |
1137 // ClearContext(); | |
1138 gl_->RateLimitOffscreenContextCHROMIUM(); | |
1139 } | |
1140 | |
1141 WebKit::WebString WebGraphicsContext3DInProcessCommandBufferImpl:: | |
1142 getRequestableExtensionsCHROMIUM() { | |
1143 // TODO(gmam): See if we can comment this in. | |
1144 // ClearContext(); | |
1145 return WebKit::WebString::fromUTF8( | |
1146 gl_->GetRequestableExtensionsCHROMIUM()); | |
1147 } | |
1148 | |
1149 void WebGraphicsContext3DInProcessCommandBufferImpl::requestExtensionCHROMIUM( | |
1150 const char* extension) { | |
1151 // TODO(gmam): See if we can comment this in. | |
1152 // ClearContext(); | |
1153 gl_->RequestExtensionCHROMIUM(extension); | |
1154 } | |
1155 | |
1156 void WebGraphicsContext3DInProcessCommandBufferImpl::blitFramebufferCHROMIUM( | |
1157 WGC3Dint srcX0, WGC3Dint srcY0, WGC3Dint srcX1, WGC3Dint srcY1, | |
1158 WGC3Dint dstX0, WGC3Dint dstY0, WGC3Dint dstX1, WGC3Dint dstY1, | |
1159 WGC3Dbitfield mask, WGC3Denum filter) { | |
1160 ClearContext(); | |
1161 gl_->BlitFramebufferEXT( | |
1162 srcX0, srcY0, srcX1, srcY1, | |
1163 dstX0, dstY0, dstX1, dstY1, | |
1164 mask, filter); | |
1165 } | |
1166 | |
1167 void WebGraphicsContext3DInProcessCommandBufferImpl:: | |
1168 renderbufferStorageMultisampleCHROMIUM( | |
1169 WGC3Denum target, WGC3Dsizei samples, WGC3Denum internalformat, | |
1170 WGC3Dsizei width, WGC3Dsizei height) { | |
1171 ClearContext(); | |
1172 gl_->RenderbufferStorageMultisampleEXT( | |
1173 target, samples, internalformat, width, height); | |
1174 } | |
1175 | |
1176 // Helper macros to reduce the amount of code. | |
1177 | |
1178 #define DELEGATE_TO_GL(name, glname) \ | |
1179 void WebGraphicsContext3DInProcessCommandBufferImpl::name() { \ | |
1180 ClearContext(); \ | |
1181 gl_->glname(); \ | |
1182 } | |
1183 | |
1184 #define DELEGATE_TO_GL_1(name, glname, t1) \ | |
1185 void WebGraphicsContext3DInProcessCommandBufferImpl::name(t1 a1) { \ | |
1186 ClearContext(); \ | |
1187 gl_->glname(a1); \ | |
1188 } | |
1189 | |
1190 #define DELEGATE_TO_GL_1R(name, glname, t1, rt) \ | |
1191 rt WebGraphicsContext3DInProcessCommandBufferImpl::name(t1 a1) { \ | |
1192 ClearContext(); \ | |
1193 return gl_->glname(a1); \ | |
1194 } | |
1195 | |
1196 #define DELEGATE_TO_GL_1RB(name, glname, t1, rt) \ | |
1197 rt WebGraphicsContext3DInProcessCommandBufferImpl::name(t1 a1) { \ | |
1198 ClearContext(); \ | |
1199 return gl_->glname(a1) ? true : false; \ | |
1200 } | |
1201 | |
1202 #define DELEGATE_TO_GL_2(name, glname, t1, t2) \ | |
1203 void WebGraphicsContext3DInProcessCommandBufferImpl::name( \ | |
1204 t1 a1, t2 a2) { \ | |
1205 ClearContext(); \ | |
1206 gl_->glname(a1, a2); \ | |
1207 } | |
1208 | |
1209 #define DELEGATE_TO_GL_2R(name, glname, t1, t2, rt) \ | |
1210 rt WebGraphicsContext3DInProcessCommandBufferImpl::name(t1 a1, t2 a2) { \ | |
1211 ClearContext(); \ | |
1212 return gl_->glname(a1, a2); \ | |
1213 } | |
1214 | |
1215 #define DELEGATE_TO_GL_3(name, glname, t1, t2, t3) \ | |
1216 void WebGraphicsContext3DInProcessCommandBufferImpl::name( \ | |
1217 t1 a1, t2 a2, t3 a3) { \ | |
1218 ClearContext(); \ | |
1219 gl_->glname(a1, a2, a3); \ | |
1220 } | |
1221 | |
1222 #define DELEGATE_TO_GL_3R(name, glname, t1, t2, t3, rt) \ | |
1223 rt WebGraphicsContext3DInProcessCommandBufferImpl::name( \ | |
1224 t1 a1, t2 a2, t3 a3) { \ | |
1225 ClearContext(); \ | |
1226 return gl_->glname(a1, a2, a3); \ | |
1227 } | |
1228 | |
1229 #define DELEGATE_TO_GL_4(name, glname, t1, t2, t3, t4) \ | |
1230 void WebGraphicsContext3DInProcessCommandBufferImpl::name( \ | |
1231 t1 a1, t2 a2, t3 a3, t4 a4) { \ | |
1232 ClearContext(); \ | |
1233 gl_->glname(a1, a2, a3, a4); \ | |
1234 } | |
1235 | |
1236 #define DELEGATE_TO_GL_5(name, glname, t1, t2, t3, t4, t5) \ | |
1237 void WebGraphicsContext3DInProcessCommandBufferImpl::name( \ | |
1238 t1 a1, t2 a2, t3 a3, t4 a4, t5 a5) { \ | |
1239 ClearContext(); \ | |
1240 gl_->glname(a1, a2, a3, a4, a5); \ | |
1241 } | |
1242 | |
1243 #define DELEGATE_TO_GL_6(name, glname, t1, t2, t3, t4, t5, t6) \ | |
1244 void WebGraphicsContext3DInProcessCommandBufferImpl::name( \ | |
1245 t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6) { \ | |
1246 ClearContext(); \ | |
1247 gl_->glname(a1, a2, a3, a4, a5, a6); \ | |
1248 } | |
1249 | |
1250 #define DELEGATE_TO_GL_7(name, glname, t1, t2, t3, t4, t5, t6, t7) \ | |
1251 void WebGraphicsContext3DInProcessCommandBufferImpl::name( \ | |
1252 t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6, t7 a7) { \ | |
1253 ClearContext(); \ | |
1254 gl_->glname(a1, a2, a3, a4, a5, a6, a7); \ | |
1255 } | |
1256 | |
1257 #define DELEGATE_TO_GL_8(name, glname, t1, t2, t3, t4, t5, t6, t7, t8) \ | |
1258 void WebGraphicsContext3DInProcessCommandBufferImpl::name( \ | |
1259 t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6, t7 a7, t8 a8) { \ | |
1260 ClearContext(); \ | |
1261 gl_->glname(a1, a2, a3, a4, a5, a6, a7, a8); \ | |
1262 } | |
1263 | |
1264 #define DELEGATE_TO_GL_9(name, glname, t1, t2, t3, t4, t5, t6, t7, t8, t9) \ | |
1265 void WebGraphicsContext3DInProcessCommandBufferImpl::name( \ | |
1266 t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6, t7 a7, t8 a8, t9 a9) { \ | |
1267 ClearContext(); \ | |
1268 gl_->glname(a1, a2, a3, a4, a5, a6, a7, a8, a9); \ | |
1269 } | |
1270 | |
1271 DELEGATE_TO_GL_1(activeTexture, ActiveTexture, WGC3Denum) | |
1272 | |
1273 DELEGATE_TO_GL_2(attachShader, AttachShader, WebGLId, WebGLId) | |
1274 | |
1275 DELEGATE_TO_GL_3(bindAttribLocation, BindAttribLocation, WebGLId, | |
1276 WGC3Duint, const WGC3Dchar*) | |
1277 | |
1278 DELEGATE_TO_GL_2(bindBuffer, BindBuffer, WGC3Denum, WebGLId) | |
1279 | |
1280 void WebGraphicsContext3DInProcessCommandBufferImpl::bindFramebuffer( | |
1281 WGC3Denum target, | |
1282 WebGLId framebuffer) { | |
1283 ClearContext(); | |
1284 gl_->BindFramebuffer(target, framebuffer); | |
1285 bound_fbo_ = framebuffer; | |
1286 } | |
1287 | |
1288 DELEGATE_TO_GL_2(bindRenderbuffer, BindRenderbuffer, WGC3Denum, WebGLId) | |
1289 | |
1290 DELEGATE_TO_GL_2(bindTexture, BindTexture, WGC3Denum, WebGLId) | |
1291 | |
1292 DELEGATE_TO_GL_4(blendColor, BlendColor, | |
1293 WGC3Dclampf, WGC3Dclampf, WGC3Dclampf, WGC3Dclampf) | |
1294 | |
1295 DELEGATE_TO_GL_1(blendEquation, BlendEquation, WGC3Denum) | |
1296 | |
1297 DELEGATE_TO_GL_2(blendEquationSeparate, BlendEquationSeparate, | |
1298 WGC3Denum, WGC3Denum) | |
1299 | |
1300 DELEGATE_TO_GL_2(blendFunc, BlendFunc, WGC3Denum, WGC3Denum) | |
1301 | |
1302 DELEGATE_TO_GL_4(blendFuncSeparate, BlendFuncSeparate, | |
1303 WGC3Denum, WGC3Denum, WGC3Denum, WGC3Denum) | |
1304 | |
1305 DELEGATE_TO_GL_4(bufferData, BufferData, | |
1306 WGC3Denum, WGC3Dsizeiptr, const void*, WGC3Denum) | |
1307 | |
1308 DELEGATE_TO_GL_4(bufferSubData, BufferSubData, | |
1309 WGC3Denum, WGC3Dintptr, WGC3Dsizeiptr, const void*) | |
1310 | |
1311 DELEGATE_TO_GL_1R(checkFramebufferStatus, CheckFramebufferStatus, | |
1312 WGC3Denum, WGC3Denum) | |
1313 | |
1314 DELEGATE_TO_GL_1(clear, Clear, WGC3Dbitfield) | |
1315 | |
1316 DELEGATE_TO_GL_4(clearColor, ClearColor, | |
1317 WGC3Dclampf, WGC3Dclampf, WGC3Dclampf, WGC3Dclampf) | |
1318 | |
1319 DELEGATE_TO_GL_1(clearDepth, ClearDepthf, WGC3Dclampf) | |
1320 | |
1321 DELEGATE_TO_GL_1(clearStencil, ClearStencil, WGC3Dint) | |
1322 | |
1323 DELEGATE_TO_GL_4(colorMask, ColorMask, | |
1324 WGC3Dboolean, WGC3Dboolean, WGC3Dboolean, WGC3Dboolean) | |
1325 | |
1326 DELEGATE_TO_GL_1(compileShader, CompileShader, WebGLId) | |
1327 | |
1328 DELEGATE_TO_GL_8(compressedTexImage2D, CompressedTexImage2D, | |
1329 WGC3Denum, WGC3Dint, WGC3Denum, WGC3Dint, WGC3Dint, | |
1330 WGC3Dsizei, WGC3Dsizei, const void*) | |
1331 | |
1332 DELEGATE_TO_GL_9(compressedTexSubImage2D, CompressedTexSubImage2D, | |
1333 WGC3Denum, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dint, | |
1334 WGC3Denum, WGC3Dsizei, const void*) | |
1335 | |
1336 DELEGATE_TO_GL_8(copyTexImage2D, CopyTexImage2D, | |
1337 WGC3Denum, WGC3Dint, WGC3Denum, WGC3Dint, WGC3Dint, | |
1338 WGC3Dsizei, WGC3Dsizei, WGC3Dint) | |
1339 | |
1340 DELEGATE_TO_GL_8(copyTexSubImage2D, CopyTexSubImage2D, | |
1341 WGC3Denum, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dint, | |
1342 WGC3Dsizei, WGC3Dsizei) | |
1343 | |
1344 DELEGATE_TO_GL_1(cullFace, CullFace, WGC3Denum) | |
1345 | |
1346 DELEGATE_TO_GL_1(depthFunc, DepthFunc, WGC3Denum) | |
1347 | |
1348 DELEGATE_TO_GL_1(depthMask, DepthMask, WGC3Dboolean) | |
1349 | |
1350 DELEGATE_TO_GL_2(depthRange, DepthRangef, WGC3Dclampf, WGC3Dclampf) | |
1351 | |
1352 DELEGATE_TO_GL_2(detachShader, DetachShader, WebGLId, WebGLId) | |
1353 | |
1354 DELEGATE_TO_GL_1(disable, Disable, WGC3Denum) | |
1355 | |
1356 DELEGATE_TO_GL_1(disableVertexAttribArray, DisableVertexAttribArray, | |
1357 WGC3Duint) | |
1358 | |
1359 DELEGATE_TO_GL_3(drawArrays, DrawArrays, WGC3Denum, WGC3Dint, WGC3Dsizei) | |
1360 | |
1361 void WebGraphicsContext3DInProcessCommandBufferImpl::drawElements( | |
1362 WGC3Denum mode, | |
1363 WGC3Dsizei count, | |
1364 WGC3Denum type, | |
1365 WGC3Dintptr offset) { | |
1366 ClearContext(); | |
1367 gl_->DrawElements( | |
1368 mode, count, type, | |
1369 reinterpret_cast<void*>(static_cast<intptr_t>(offset))); | |
1370 } | |
1371 | |
1372 DELEGATE_TO_GL_1(enable, Enable, WGC3Denum) | |
1373 | |
1374 DELEGATE_TO_GL_1(enableVertexAttribArray, EnableVertexAttribArray, | |
1375 WGC3Duint) | |
1376 | |
1377 DELEGATE_TO_GL(finish, Finish) | |
1378 | |
1379 DELEGATE_TO_GL(flush, Flush) | |
1380 | |
1381 DELEGATE_TO_GL_4(framebufferRenderbuffer, FramebufferRenderbuffer, | |
1382 WGC3Denum, WGC3Denum, WGC3Denum, WebGLId) | |
1383 | |
1384 DELEGATE_TO_GL_5(framebufferTexture2D, FramebufferTexture2D, | |
1385 WGC3Denum, WGC3Denum, WGC3Denum, WebGLId, WGC3Dint) | |
1386 | |
1387 DELEGATE_TO_GL_1(frontFace, FrontFace, WGC3Denum) | |
1388 | |
1389 DELEGATE_TO_GL_1(generateMipmap, GenerateMipmap, WGC3Denum) | |
1390 | |
1391 bool WebGraphicsContext3DInProcessCommandBufferImpl::getActiveAttrib( | |
1392 WebGLId program, WGC3Duint index, ActiveInfo& info) { | |
1393 ClearContext(); | |
1394 if (!program) { | |
1395 synthesizeGLError(GL_INVALID_VALUE); | |
1396 return false; | |
1397 } | |
1398 GLint max_name_length = -1; | |
1399 gl_->GetProgramiv( | |
1400 program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_name_length); | |
1401 if (max_name_length < 0) | |
1402 return false; | |
1403 scoped_ptr<GLchar[]> name(new GLchar[max_name_length]); | |
1404 if (!name) { | |
1405 synthesizeGLError(GL_OUT_OF_MEMORY); | |
1406 return false; | |
1407 } | |
1408 GLsizei length = 0; | |
1409 GLint size = -1; | |
1410 GLenum type = 0; | |
1411 gl_->GetActiveAttrib( | |
1412 program, index, max_name_length, &length, &size, &type, name.get()); | |
1413 if (size < 0) { | |
1414 return false; | |
1415 } | |
1416 info.name = WebKit::WebString::fromUTF8(name.get(), length); | |
1417 info.type = type; | |
1418 info.size = size; | |
1419 return true; | |
1420 } | |
1421 | |
1422 bool WebGraphicsContext3DInProcessCommandBufferImpl::getActiveUniform( | |
1423 WebGLId program, WGC3Duint index, ActiveInfo& info) { | |
1424 ClearContext(); | |
1425 GLint max_name_length = -1; | |
1426 gl_->GetProgramiv( | |
1427 program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_name_length); | |
1428 if (max_name_length < 0) | |
1429 return false; | |
1430 scoped_ptr<GLchar[]> name(new GLchar[max_name_length]); | |
1431 if (!name) { | |
1432 synthesizeGLError(GL_OUT_OF_MEMORY); | |
1433 return false; | |
1434 } | |
1435 GLsizei length = 0; | |
1436 GLint size = -1; | |
1437 GLenum type = 0; | |
1438 gl_->GetActiveUniform( | |
1439 program, index, max_name_length, &length, &size, &type, name.get()); | |
1440 if (size < 0) { | |
1441 return false; | |
1442 } | |
1443 info.name = WebKit::WebString::fromUTF8(name.get(), length); | |
1444 info.type = type; | |
1445 info.size = size; | |
1446 return true; | |
1447 } | |
1448 | |
1449 DELEGATE_TO_GL_4(getAttachedShaders, GetAttachedShaders, | |
1450 WebGLId, WGC3Dsizei, WGC3Dsizei*, WebGLId*) | |
1451 | |
1452 DELEGATE_TO_GL_2R(getAttribLocation, GetAttribLocation, | |
1453 WebGLId, const WGC3Dchar*, WGC3Dint) | |
1454 | |
1455 DELEGATE_TO_GL_2(getBooleanv, GetBooleanv, WGC3Denum, WGC3Dboolean*) | |
1456 | |
1457 DELEGATE_TO_GL_3(getBufferParameteriv, GetBufferParameteriv, | |
1458 WGC3Denum, WGC3Denum, WGC3Dint*) | |
1459 | |
1460 WebKit::WebGraphicsContext3D::Attributes | |
1461 WebGraphicsContext3DInProcessCommandBufferImpl::getContextAttributes() { | |
1462 return attributes_; | |
1463 } | |
1464 | |
1465 WGC3Denum WebGraphicsContext3DInProcessCommandBufferImpl::getError() { | |
1466 ClearContext(); | |
1467 if (!synthetic_errors_.empty()) { | |
1468 std::vector<WGC3Denum>::iterator iter = synthetic_errors_.begin(); | |
1469 WGC3Denum err = *iter; | |
1470 synthetic_errors_.erase(iter); | |
1471 return err; | |
1472 } | |
1473 | |
1474 return gl_->GetError(); | |
1475 } | |
1476 | |
1477 bool WebGraphicsContext3DInProcessCommandBufferImpl::isContextLost() { | |
1478 return context_->IsCommandBufferContextLost(); | |
1479 } | |
1480 | |
1481 DELEGATE_TO_GL_2(getFloatv, GetFloatv, WGC3Denum, WGC3Dfloat*) | |
1482 | |
1483 DELEGATE_TO_GL_4(getFramebufferAttachmentParameteriv, | |
1484 GetFramebufferAttachmentParameteriv, | |
1485 WGC3Denum, WGC3Denum, WGC3Denum, WGC3Dint*) | |
1486 | |
1487 DELEGATE_TO_GL_2(getIntegerv, GetIntegerv, WGC3Denum, WGC3Dint*) | |
1488 | |
1489 DELEGATE_TO_GL_3(getProgramiv, GetProgramiv, WebGLId, WGC3Denum, WGC3Dint*) | |
1490 | |
1491 WebKit::WebString WebGraphicsContext3DInProcessCommandBufferImpl:: | |
1492 getProgramInfoLog(WebGLId program) { | |
1493 ClearContext(); | |
1494 GLint logLength = 0; | |
1495 gl_->GetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength); | |
1496 if (!logLength) | |
1497 return WebKit::WebString(); | |
1498 scoped_ptr<GLchar[]> log(new GLchar[logLength]); | |
1499 if (!log) | |
1500 return WebKit::WebString(); | |
1501 GLsizei returnedLogLength = 0; | |
1502 gl_->GetProgramInfoLog( | |
1503 program, logLength, &returnedLogLength, log.get()); | |
1504 DCHECK_EQ(logLength, returnedLogLength + 1); | |
1505 WebKit::WebString res = | |
1506 WebKit::WebString::fromUTF8(log.get(), returnedLogLength); | |
1507 return res; | |
1508 } | |
1509 | |
1510 DELEGATE_TO_GL_3(getRenderbufferParameteriv, GetRenderbufferParameteriv, | |
1511 WGC3Denum, WGC3Denum, WGC3Dint*) | |
1512 | |
1513 DELEGATE_TO_GL_3(getShaderiv, GetShaderiv, WebGLId, WGC3Denum, WGC3Dint*) | |
1514 | |
1515 WebKit::WebString WebGraphicsContext3DInProcessCommandBufferImpl:: | |
1516 getShaderInfoLog(WebGLId shader) { | |
1517 ClearContext(); | |
1518 GLint logLength = 0; | |
1519 gl_->GetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength); | |
1520 if (!logLength) | |
1521 return WebKit::WebString(); | |
1522 scoped_ptr<GLchar[]> log(new GLchar[logLength]); | |
1523 if (!log) | |
1524 return WebKit::WebString(); | |
1525 GLsizei returnedLogLength = 0; | |
1526 gl_->GetShaderInfoLog( | |
1527 shader, logLength, &returnedLogLength, log.get()); | |
1528 DCHECK_EQ(logLength, returnedLogLength + 1); | |
1529 WebKit::WebString res = | |
1530 WebKit::WebString::fromUTF8(log.get(), returnedLogLength); | |
1531 return res; | |
1532 } | |
1533 | |
1534 DELEGATE_TO_GL_4(getShaderPrecisionFormat, GetShaderPrecisionFormat, | |
1535 WGC3Denum, WGC3Denum, WGC3Dint*, WGC3Dint*) | |
1536 | |
1537 WebKit::WebString WebGraphicsContext3DInProcessCommandBufferImpl:: | |
1538 getShaderSource(WebGLId shader) { | |
1539 ClearContext(); | |
1540 GLint logLength = 0; | |
1541 gl_->GetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &logLength); | |
1542 if (!logLength) | |
1543 return WebKit::WebString(); | |
1544 scoped_ptr<GLchar[]> log(new GLchar[logLength]); | |
1545 if (!log) | |
1546 return WebKit::WebString(); | |
1547 GLsizei returnedLogLength = 0; | |
1548 gl_->GetShaderSource( | |
1549 shader, logLength, &returnedLogLength, log.get()); | |
1550 if (!returnedLogLength) | |
1551 return WebKit::WebString(); | |
1552 DCHECK_EQ(logLength, returnedLogLength + 1); | |
1553 WebKit::WebString res = | |
1554 WebKit::WebString::fromUTF8(log.get(), returnedLogLength); | |
1555 return res; | |
1556 } | |
1557 | |
1558 WebKit::WebString WebGraphicsContext3DInProcessCommandBufferImpl:: | |
1559 getTranslatedShaderSourceANGLE(WebGLId shader) { | |
1560 ClearContext(); | |
1561 GLint logLength = 0; | |
1562 gl_->GetShaderiv( | |
1563 shader, GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE, &logLength); | |
1564 if (!logLength) | |
1565 return WebKit::WebString(); | |
1566 scoped_ptr<GLchar[]> log(new GLchar[logLength]); | |
1567 if (!log) | |
1568 return WebKit::WebString(); | |
1569 GLsizei returnedLogLength = 0; | |
1570 gl_->GetTranslatedShaderSourceANGLE( | |
1571 shader, logLength, &returnedLogLength, log.get()); | |
1572 if (!returnedLogLength) | |
1573 return WebKit::WebString(); | |
1574 DCHECK_EQ(logLength, returnedLogLength + 1); | |
1575 WebKit::WebString res = | |
1576 WebKit::WebString::fromUTF8(log.get(), returnedLogLength); | |
1577 return res; | |
1578 } | |
1579 | |
1580 WebKit::WebString WebGraphicsContext3DInProcessCommandBufferImpl::getString( | |
1581 WGC3Denum name) { | |
1582 ClearContext(); | |
1583 return WebKit::WebString::fromUTF8( | |
1584 reinterpret_cast<const char*>(gl_->GetString(name))); | |
1585 } | |
1586 | |
1587 DELEGATE_TO_GL_3(getTexParameterfv, GetTexParameterfv, | |
1588 WGC3Denum, WGC3Denum, WGC3Dfloat*) | |
1589 | |
1590 DELEGATE_TO_GL_3(getTexParameteriv, GetTexParameteriv, | |
1591 WGC3Denum, WGC3Denum, WGC3Dint*) | |
1592 | |
1593 DELEGATE_TO_GL_3(getUniformfv, GetUniformfv, WebGLId, WGC3Dint, WGC3Dfloat*) | |
1594 | |
1595 DELEGATE_TO_GL_3(getUniformiv, GetUniformiv, WebGLId, WGC3Dint, WGC3Dint*) | |
1596 | |
1597 DELEGATE_TO_GL_2R(getUniformLocation, GetUniformLocation, | |
1598 WebGLId, const WGC3Dchar*, WGC3Dint) | |
1599 | |
1600 DELEGATE_TO_GL_3(getVertexAttribfv, GetVertexAttribfv, | |
1601 WGC3Duint, WGC3Denum, WGC3Dfloat*) | |
1602 | |
1603 DELEGATE_TO_GL_3(getVertexAttribiv, GetVertexAttribiv, | |
1604 WGC3Duint, WGC3Denum, WGC3Dint*) | |
1605 | |
1606 WGC3Dsizeiptr WebGraphicsContext3DInProcessCommandBufferImpl:: | |
1607 getVertexAttribOffset(WGC3Duint index, WGC3Denum pname) { | |
1608 ClearContext(); | |
1609 GLvoid* value = NULL; | |
1610 // NOTE: If pname is ever a value that returns more then 1 element | |
1611 // this will corrupt memory. | |
1612 gl_->GetVertexAttribPointerv(index, pname, &value); | |
1613 return static_cast<WGC3Dsizeiptr>(reinterpret_cast<intptr_t>(value)); | |
1614 } | |
1615 | |
1616 DELEGATE_TO_GL_2(hint, Hint, WGC3Denum, WGC3Denum) | |
1617 | |
1618 DELEGATE_TO_GL_1RB(isBuffer, IsBuffer, WebGLId, WGC3Dboolean) | |
1619 | |
1620 DELEGATE_TO_GL_1RB(isEnabled, IsEnabled, WGC3Denum, WGC3Dboolean) | |
1621 | |
1622 DELEGATE_TO_GL_1RB(isFramebuffer, IsFramebuffer, WebGLId, WGC3Dboolean) | |
1623 | |
1624 DELEGATE_TO_GL_1RB(isProgram, IsProgram, WebGLId, WGC3Dboolean) | |
1625 | |
1626 DELEGATE_TO_GL_1RB(isRenderbuffer, IsRenderbuffer, WebGLId, WGC3Dboolean) | |
1627 | |
1628 DELEGATE_TO_GL_1RB(isShader, IsShader, WebGLId, WGC3Dboolean) | |
1629 | |
1630 DELEGATE_TO_GL_1RB(isTexture, IsTexture, WebGLId, WGC3Dboolean) | |
1631 | |
1632 DELEGATE_TO_GL_1(lineWidth, LineWidth, WGC3Dfloat) | |
1633 | |
1634 DELEGATE_TO_GL_1(linkProgram, LinkProgram, WebGLId) | |
1635 | |
1636 DELEGATE_TO_GL_2(pixelStorei, PixelStorei, WGC3Denum, WGC3Dint) | |
1637 | |
1638 DELEGATE_TO_GL_2(polygonOffset, PolygonOffset, WGC3Dfloat, WGC3Dfloat) | |
1639 | |
1640 DELEGATE_TO_GL_7(readPixels, ReadPixels, | |
1641 WGC3Dint, WGC3Dint, WGC3Dsizei, WGC3Dsizei, WGC3Denum, | |
1642 WGC3Denum, void*) | |
1643 | |
1644 void WebGraphicsContext3DInProcessCommandBufferImpl::releaseShaderCompiler() { | |
1645 ClearContext(); | |
1646 } | |
1647 | |
1648 DELEGATE_TO_GL_4(renderbufferStorage, RenderbufferStorage, | |
1649 WGC3Denum, WGC3Denum, WGC3Dsizei, WGC3Dsizei) | |
1650 | |
1651 DELEGATE_TO_GL_2(sampleCoverage, SampleCoverage, WGC3Dfloat, WGC3Dboolean) | |
1652 | |
1653 DELEGATE_TO_GL_4(scissor, Scissor, WGC3Dint, WGC3Dint, WGC3Dsizei, WGC3Dsizei) | |
1654 | |
1655 void WebGraphicsContext3DInProcessCommandBufferImpl::shaderSource( | |
1656 WebGLId shader, const WGC3Dchar* string) { | |
1657 ClearContext(); | |
1658 GLint length = strlen(string); | |
1659 gl_->ShaderSource(shader, 1, &string, &length); | |
1660 } | |
1661 | |
1662 DELEGATE_TO_GL_3(stencilFunc, StencilFunc, WGC3Denum, WGC3Dint, WGC3Duint) | |
1663 | |
1664 DELEGATE_TO_GL_4(stencilFuncSeparate, StencilFuncSeparate, | |
1665 WGC3Denum, WGC3Denum, WGC3Dint, WGC3Duint) | |
1666 | |
1667 DELEGATE_TO_GL_1(stencilMask, StencilMask, WGC3Duint) | |
1668 | |
1669 DELEGATE_TO_GL_2(stencilMaskSeparate, StencilMaskSeparate, | |
1670 WGC3Denum, WGC3Duint) | |
1671 | |
1672 DELEGATE_TO_GL_3(stencilOp, StencilOp, | |
1673 WGC3Denum, WGC3Denum, WGC3Denum) | |
1674 | |
1675 DELEGATE_TO_GL_4(stencilOpSeparate, StencilOpSeparate, | |
1676 WGC3Denum, WGC3Denum, WGC3Denum, WGC3Denum) | |
1677 | |
1678 DELEGATE_TO_GL_9(texImage2D, TexImage2D, | |
1679 WGC3Denum, WGC3Dint, WGC3Denum, WGC3Dsizei, WGC3Dsizei, | |
1680 WGC3Dint, WGC3Denum, WGC3Denum, const void*) | |
1681 | |
1682 DELEGATE_TO_GL_3(texParameterf, TexParameterf, | |
1683 WGC3Denum, WGC3Denum, WGC3Dfloat); | |
1684 | |
1685 static const unsigned int kTextureWrapR = 0x8072; | |
1686 | |
1687 void WebGraphicsContext3DInProcessCommandBufferImpl::texParameteri( | |
1688 WGC3Denum target, WGC3Denum pname, WGC3Dint param) { | |
1689 ClearContext(); | |
1690 // TODO(kbr): figure out whether the setting of TEXTURE_WRAP_R in | |
1691 // GraphicsContext3D.cpp is strictly necessary to avoid seams at the | |
1692 // edge of cube maps, and, if it is, push it into the GLES2 service | |
1693 // side code. | |
1694 if (pname == kTextureWrapR) { | |
1695 return; | |
1696 } | |
1697 gl_->TexParameteri(target, pname, param); | |
1698 } | |
1699 | |
1700 DELEGATE_TO_GL_9(texSubImage2D, TexSubImage2D, | |
1701 WGC3Denum, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dsizei, | |
1702 WGC3Dsizei, WGC3Denum, WGC3Denum, const void*) | |
1703 | |
1704 DELEGATE_TO_GL_2(uniform1f, Uniform1f, WGC3Dint, WGC3Dfloat) | |
1705 | |
1706 DELEGATE_TO_GL_3(uniform1fv, Uniform1fv, WGC3Dint, WGC3Dsizei, | |
1707 const WGC3Dfloat*) | |
1708 | |
1709 DELEGATE_TO_GL_2(uniform1i, Uniform1i, WGC3Dint, WGC3Dint) | |
1710 | |
1711 DELEGATE_TO_GL_3(uniform1iv, Uniform1iv, WGC3Dint, WGC3Dsizei, const WGC3Dint*) | |
1712 | |
1713 DELEGATE_TO_GL_3(uniform2f, Uniform2f, WGC3Dint, WGC3Dfloat, WGC3Dfloat) | |
1714 | |
1715 DELEGATE_TO_GL_3(uniform2fv, Uniform2fv, WGC3Dint, WGC3Dsizei, | |
1716 const WGC3Dfloat*) | |
1717 | |
1718 DELEGATE_TO_GL_3(uniform2i, Uniform2i, WGC3Dint, WGC3Dint, WGC3Dint) | |
1719 | |
1720 DELEGATE_TO_GL_3(uniform2iv, Uniform2iv, WGC3Dint, WGC3Dsizei, const WGC3Dint*) | |
1721 | |
1722 DELEGATE_TO_GL_4(uniform3f, Uniform3f, WGC3Dint, | |
1723 WGC3Dfloat, WGC3Dfloat, WGC3Dfloat) | |
1724 | |
1725 DELEGATE_TO_GL_3(uniform3fv, Uniform3fv, WGC3Dint, WGC3Dsizei, | |
1726 const WGC3Dfloat*) | |
1727 | |
1728 DELEGATE_TO_GL_4(uniform3i, Uniform3i, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dint) | |
1729 | |
1730 DELEGATE_TO_GL_3(uniform3iv, Uniform3iv, WGC3Dint, WGC3Dsizei, const WGC3Dint*) | |
1731 | |
1732 DELEGATE_TO_GL_5(uniform4f, Uniform4f, WGC3Dint, | |
1733 WGC3Dfloat, WGC3Dfloat, WGC3Dfloat, WGC3Dfloat) | |
1734 | |
1735 DELEGATE_TO_GL_3(uniform4fv, Uniform4fv, WGC3Dint, WGC3Dsizei, | |
1736 const WGC3Dfloat*) | |
1737 | |
1738 DELEGATE_TO_GL_5(uniform4i, Uniform4i, WGC3Dint, | |
1739 WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dint) | |
1740 | |
1741 DELEGATE_TO_GL_3(uniform4iv, Uniform4iv, WGC3Dint, WGC3Dsizei, const WGC3Dint*) | |
1742 | |
1743 DELEGATE_TO_GL_4(uniformMatrix2fv, UniformMatrix2fv, | |
1744 WGC3Dint, WGC3Dsizei, WGC3Dboolean, const WGC3Dfloat*) | |
1745 | |
1746 DELEGATE_TO_GL_4(uniformMatrix3fv, UniformMatrix3fv, | |
1747 WGC3Dint, WGC3Dsizei, WGC3Dboolean, const WGC3Dfloat*) | |
1748 | |
1749 DELEGATE_TO_GL_4(uniformMatrix4fv, UniformMatrix4fv, | |
1750 WGC3Dint, WGC3Dsizei, WGC3Dboolean, const WGC3Dfloat*) | |
1751 | |
1752 DELEGATE_TO_GL_1(useProgram, UseProgram, WebGLId) | |
1753 | |
1754 DELEGATE_TO_GL_1(validateProgram, ValidateProgram, WebGLId) | |
1755 | |
1756 DELEGATE_TO_GL_2(vertexAttrib1f, VertexAttrib1f, WGC3Duint, WGC3Dfloat) | |
1757 | |
1758 DELEGATE_TO_GL_2(vertexAttrib1fv, VertexAttrib1fv, WGC3Duint, | |
1759 const WGC3Dfloat*) | |
1760 | |
1761 DELEGATE_TO_GL_3(vertexAttrib2f, VertexAttrib2f, WGC3Duint, | |
1762 WGC3Dfloat, WGC3Dfloat) | |
1763 | |
1764 DELEGATE_TO_GL_2(vertexAttrib2fv, VertexAttrib2fv, WGC3Duint, | |
1765 const WGC3Dfloat*) | |
1766 | |
1767 DELEGATE_TO_GL_4(vertexAttrib3f, VertexAttrib3f, WGC3Duint, | |
1768 WGC3Dfloat, WGC3Dfloat, WGC3Dfloat) | |
1769 | |
1770 DELEGATE_TO_GL_2(vertexAttrib3fv, VertexAttrib3fv, WGC3Duint, | |
1771 const WGC3Dfloat*) | |
1772 | |
1773 DELEGATE_TO_GL_5(vertexAttrib4f, VertexAttrib4f, WGC3Duint, | |
1774 WGC3Dfloat, WGC3Dfloat, WGC3Dfloat, WGC3Dfloat) | |
1775 | |
1776 DELEGATE_TO_GL_2(vertexAttrib4fv, VertexAttrib4fv, WGC3Duint, | |
1777 const WGC3Dfloat*) | |
1778 | |
1779 void WebGraphicsContext3DInProcessCommandBufferImpl::vertexAttribPointer( | |
1780 WGC3Duint index, WGC3Dint size, WGC3Denum type, WGC3Dboolean normalized, | |
1781 WGC3Dsizei stride, WGC3Dintptr offset) { | |
1782 ClearContext(); | |
1783 gl_->VertexAttribPointer( | |
1784 index, size, type, normalized, stride, | |
1785 reinterpret_cast<void*>(static_cast<intptr_t>(offset))); | |
1786 } | |
1787 | |
1788 DELEGATE_TO_GL_4(viewport, Viewport, | |
1789 WGC3Dint, WGC3Dint, WGC3Dsizei, WGC3Dsizei) | |
1790 | |
1791 WebGLId WebGraphicsContext3DInProcessCommandBufferImpl::createBuffer() { | |
1792 ClearContext(); | |
1793 GLuint o; | |
1794 gl_->GenBuffers(1, &o); | |
1795 return o; | |
1796 } | |
1797 | |
1798 WebGLId WebGraphicsContext3DInProcessCommandBufferImpl::createFramebuffer() { | |
1799 ClearContext(); | |
1800 GLuint o = 0; | |
1801 gl_->GenFramebuffers(1, &o); | |
1802 return o; | |
1803 } | |
1804 | |
1805 WebGLId WebGraphicsContext3DInProcessCommandBufferImpl::createProgram() { | |
1806 ClearContext(); | |
1807 return gl_->CreateProgram(); | |
1808 } | |
1809 | |
1810 WebGLId WebGraphicsContext3DInProcessCommandBufferImpl::createRenderbuffer() { | |
1811 ClearContext(); | |
1812 GLuint o; | |
1813 gl_->GenRenderbuffers(1, &o); | |
1814 return o; | |
1815 } | |
1816 | |
1817 DELEGATE_TO_GL_1R(createShader, CreateShader, WGC3Denum, WebGLId); | |
1818 | |
1819 WebGLId WebGraphicsContext3DInProcessCommandBufferImpl::createTexture() { | |
1820 ClearContext(); | |
1821 GLuint o; | |
1822 gl_->GenTextures(1, &o); | |
1823 return o; | |
1824 } | |
1825 | |
1826 void WebGraphicsContext3DInProcessCommandBufferImpl::deleteBuffer( | |
1827 WebGLId buffer) { | |
1828 ClearContext(); | |
1829 gl_->DeleteBuffers(1, &buffer); | |
1830 } | |
1831 | |
1832 void WebGraphicsContext3DInProcessCommandBufferImpl::deleteFramebuffer( | |
1833 WebGLId framebuffer) { | |
1834 ClearContext(); | |
1835 gl_->DeleteFramebuffers(1, &framebuffer); | |
1836 } | |
1837 | |
1838 void WebGraphicsContext3DInProcessCommandBufferImpl::deleteProgram( | |
1839 WebGLId program) { | |
1840 ClearContext(); | |
1841 gl_->DeleteProgram(program); | |
1842 } | |
1843 | |
1844 void WebGraphicsContext3DInProcessCommandBufferImpl::deleteRenderbuffer( | |
1845 WebGLId renderbuffer) { | |
1846 ClearContext(); | |
1847 gl_->DeleteRenderbuffers(1, &renderbuffer); | |
1848 } | |
1849 | |
1850 void WebGraphicsContext3DInProcessCommandBufferImpl::deleteShader( | |
1851 WebGLId shader) { | |
1852 ClearContext(); | |
1853 gl_->DeleteShader(shader); | |
1854 } | |
1855 | |
1856 void WebGraphicsContext3DInProcessCommandBufferImpl::deleteTexture( | |
1857 WebGLId texture) { | |
1858 ClearContext(); | |
1859 gl_->DeleteTextures(1, &texture); | |
1860 } | |
1861 | |
1862 void WebGraphicsContext3DInProcessCommandBufferImpl::copyTextureToCompositor( | |
1863 WebGLId texture, WebGLId parentTexture) { | |
1864 NOTIMPLEMENTED(); | |
1865 } | |
1866 | |
1867 void WebGraphicsContext3DInProcessCommandBufferImpl::OnSwapBuffersComplete() { | |
1868 } | |
1869 | |
1870 void WebGraphicsContext3DInProcessCommandBufferImpl::setContextLostCallback( | |
1871 WebGraphicsContext3D::WebGraphicsContextLostCallback* cb) { | |
1872 context_lost_callback_ = cb; | |
1873 } | |
1874 | |
1875 WGC3Denum WebGraphicsContext3DInProcessCommandBufferImpl:: | |
1876 getGraphicsResetStatusARB() { | |
1877 return context_lost_reason_; | |
1878 } | |
1879 | |
1880 DELEGATE_TO_GL_5(texImageIOSurface2DCHROMIUM, TexImageIOSurface2DCHROMIUM, | |
1881 WGC3Denum, WGC3Dint, WGC3Dint, WGC3Duint, WGC3Duint) | |
1882 | |
1883 DELEGATE_TO_GL_5(texStorage2DEXT, TexStorage2DEXT, | |
1884 WGC3Denum, WGC3Dint, WGC3Duint, WGC3Dint, WGC3Dint) | |
1885 | |
1886 WebGLId WebGraphicsContext3DInProcessCommandBufferImpl::createQueryEXT() { | |
1887 GLuint o; | |
1888 gl_->GenQueriesEXT(1, &o); | |
1889 return o; | |
1890 } | |
1891 | |
1892 void WebGraphicsContext3DInProcessCommandBufferImpl:: | |
1893 deleteQueryEXT(WebGLId query) { | |
1894 gl_->DeleteQueriesEXT(1, &query); | |
1895 } | |
1896 | |
1897 DELEGATE_TO_GL_1R(isQueryEXT, IsQueryEXT, WebGLId, WGC3Dboolean) | |
1898 DELEGATE_TO_GL_2(beginQueryEXT, BeginQueryEXT, WGC3Denum, WebGLId) | |
1899 DELEGATE_TO_GL_1(endQueryEXT, EndQueryEXT, WGC3Denum) | |
1900 DELEGATE_TO_GL_3(getQueryivEXT, GetQueryivEXT, WGC3Denum, WGC3Denum, WGC3Dint*) | |
1901 DELEGATE_TO_GL_3(getQueryObjectuivEXT, GetQueryObjectuivEXT, | |
1902 WebGLId, WGC3Denum, WGC3Duint*) | |
1903 | |
1904 DELEGATE_TO_GL_6(copyTextureCHROMIUM, CopyTextureCHROMIUM, WGC3Denum, WGC3Duint, | |
1905 WGC3Duint, WGC3Dint, WGC3Denum, WGC3Denum) | |
1906 | |
1907 void WebGraphicsContext3DInProcessCommandBufferImpl::insertEventMarkerEXT( | |
1908 const WGC3Dchar* marker) { | |
1909 gl_->InsertEventMarkerEXT(0, marker); | |
1910 } | |
1911 | |
1912 void WebGraphicsContext3DInProcessCommandBufferImpl::pushGroupMarkerEXT( | |
1913 const WGC3Dchar* marker) { | |
1914 gl_->PushGroupMarkerEXT(0, marker); | |
1915 } | |
1916 | |
1917 DELEGATE_TO_GL(popGroupMarkerEXT, PopGroupMarkerEXT); | |
1918 | |
1919 DELEGATE_TO_GL_2(bindTexImage2DCHROMIUM, BindTexImage2DCHROMIUM, | |
1920 WGC3Denum, WGC3Dint) | |
1921 DELEGATE_TO_GL_2(releaseTexImage2DCHROMIUM, ReleaseTexImage2DCHROMIUM, | |
1922 WGC3Denum, WGC3Dint) | |
1923 | |
1924 void* WebGraphicsContext3DInProcessCommandBufferImpl::mapBufferCHROMIUM( | |
1925 WGC3Denum target, WGC3Denum access) { | |
1926 ClearContext(); | |
1927 return gl_->MapBufferCHROMIUM(target, access); | |
1928 } | |
1929 | |
1930 WGC3Dboolean WebGraphicsContext3DInProcessCommandBufferImpl:: | |
1931 unmapBufferCHROMIUM(WGC3Denum target) { | |
1932 ClearContext(); | |
1933 return gl_->UnmapBufferCHROMIUM(target); | |
1934 } | |
1935 | |
1936 GrGLInterface* WebGraphicsContext3DInProcessCommandBufferImpl:: | |
1937 onCreateGrGLInterface() { | |
1938 return CreateCommandBufferSkiaGLBinding(); | |
1939 } | |
1940 | |
1941 void WebGraphicsContext3DInProcessCommandBufferImpl::OnContextLost() { | |
1942 // TODO(kbr): improve the precision here. | |
1943 context_lost_reason_ = GL_UNKNOWN_CONTEXT_RESET_ARB; | |
1944 if (context_lost_callback_) { | |
1945 context_lost_callback_->onContextLost(); | |
1946 } | |
1947 } | |
1948 | |
1949 DELEGATE_TO_GL_3R(createImageCHROMIUM, CreateImageCHROMIUM, | |
1950 WGC3Dsizei, WGC3Dsizei, WGC3Denum, WGC3Duint); | |
1951 | |
1952 DELEGATE_TO_GL_1(destroyImageCHROMIUM, DestroyImageCHROMIUM, WGC3Duint); | |
1953 | |
1954 DELEGATE_TO_GL_3(getImageParameterivCHROMIUM, GetImageParameterivCHROMIUM, | |
1955 WGC3Duint, WGC3Denum, GLint*); | |
1956 | |
1957 DELEGATE_TO_GL_2R(mapImageCHROMIUM, MapImageCHROMIUM, | |
1958 WGC3Duint, WGC3Denum, void*); | |
1959 | |
1960 DELEGATE_TO_GL_1(unmapImageCHROMIUM, UnmapImageCHROMIUM, WGC3Duint); | |
1961 | |
1962 DELEGATE_TO_GL_3(bindUniformLocationCHROMIUM, BindUniformLocationCHROMIUM, | |
1963 WebGLId, WGC3Dint, const WGC3Dchar*) | |
1964 | |
1965 DELEGATE_TO_GL(shallowFlushCHROMIUM, ShallowFlushCHROMIUM) | |
1966 | |
1967 DELEGATE_TO_GL_1(genMailboxCHROMIUM, GenMailboxCHROMIUM, WGC3Dbyte*) | |
1968 DELEGATE_TO_GL_2(produceTextureCHROMIUM, ProduceTextureCHROMIUM, | |
1969 WGC3Denum, const WGC3Dbyte*) | |
1970 DELEGATE_TO_GL_2(consumeTextureCHROMIUM, ConsumeTextureCHROMIUM, | |
1971 WGC3Denum, const WGC3Dbyte*) | |
1972 | |
1973 DELEGATE_TO_GL_2(drawBuffersEXT, DrawBuffersEXT, | |
1974 WGC3Dsizei, const WGC3Denum*) | |
1975 | |
1976 unsigned WebGraphicsContext3DInProcessCommandBufferImpl::insertSyncPoint() { | |
1977 shallowFlushCHROMIUM(); | |
1978 return 0; | |
1979 } | |
1980 | |
1981 void WebGraphicsContext3DInProcessCommandBufferImpl::signalSyncPoint( | |
1982 unsigned sync_point, | |
1983 WebGraphicsSyncPointCallback* callback) { | |
1984 // Take ownership of the callback. | |
1985 context_->SetSignalSyncPointCallback(make_scoped_ptr(callback)); | |
1986 // Stick something in the command buffer. | |
1987 shallowFlushCHROMIUM(); | |
1988 } | |
1989 | |
1990 void WebGraphicsContext3DInProcessCommandBufferImpl::loseContextCHROMIUM( | |
1991 WGC3Denum current, WGC3Denum other) { | |
1992 context_->LoseContext(current, other); | |
1993 } | |
1994 | |
1995 DELEGATE_TO_GL_9(asyncTexImage2DCHROMIUM, AsyncTexImage2DCHROMIUM, | |
1996 WGC3Denum, WGC3Dint, WGC3Denum, WGC3Dsizei, WGC3Dsizei, WGC3Dint, | |
1997 WGC3Denum, WGC3Denum, const void*) | |
1998 | |
1999 DELEGATE_TO_GL_9(asyncTexSubImage2DCHROMIUM, AsyncTexSubImage2DCHROMIUM, | |
2000 WGC3Denum, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dsizei, WGC3Dsizei, | |
2001 WGC3Denum, WGC3Denum, const void*) | |
2002 | |
2003 DELEGATE_TO_GL_1(waitAsyncTexImage2DCHROMIUM, WaitAsyncTexImage2DCHROMIUM, | |
2004 WGC3Denum) | |
2005 | |
2006 void WebGraphicsContext3DInProcessCommandBufferImpl::SetGpuMemoryBufferCreator( | |
2007 GpuMemoryBufferCreator* creator) { | |
2008 g_gpu_memory_buffer_creator = creator; | |
2009 } | |
2010 | |
2011 } // namespace gpu | |
2012 } // namespace webkit | |
OLD | NEW |