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