- add sources.
[platform/framework/web/crosswalk.git] / src / content / common / gpu / client / webgraphicscontext3d_command_buffer_impl.cc
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 "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
6
7 #include "third_party/khronos/GLES2/gl2.h"
8 #ifndef GL_GLEXT_PROTOTYPES
9 #define GL_GLEXT_PROTOTYPES 1
10 #endif
11 #include "third_party/khronos/GLES2/gl2ext.h"
12
13 #include <algorithm>
14 #include <set>
15
16 #include "base/atomicops.h"
17 #include "base/bind.h"
18 #include "base/command_line.h"
19 #include "base/debug/trace_event.h"
20 #include "base/lazy_instance.h"
21 #include "base/logging.h"
22 #include "base/message_loop/message_loop.h"
23 #include "base/metrics/field_trial.h"
24 #include "base/metrics/histogram.h"
25 #include "base/synchronization/lock.h"
26 #include "content/common/gpu/client/gpu_channel_host.h"
27 #include "content/public/common/content_constants.h"
28 #include "content/public/common/content_switches.h"
29 #include "gpu/GLES2/gl2extchromium.h"
30 #include "gpu/command_buffer/client/gles2_cmd_helper.h"
31 #include "gpu/command_buffer/client/gles2_implementation.h"
32 #include "gpu/command_buffer/client/gles2_lib.h"
33 #include "gpu/command_buffer/client/gles2_trace_implementation.h"
34 #include "gpu/command_buffer/client/transfer_buffer.h"
35 #include "gpu/command_buffer/common/constants.h"
36 #include "gpu/command_buffer/common/gpu_memory_allocation.h"
37 #include "gpu/command_buffer/common/mailbox.h"
38 #include "third_party/skia/include/core/SkTypes.h"
39 #include "webkit/common/gpu/gl_bindings_skia_cmd_buffer.h"
40
41 namespace content {
42 static base::LazyInstance<base::Lock>::Leaky
43     g_all_shared_contexts_lock = LAZY_INSTANCE_INITIALIZER;
44 static base::LazyInstance<std::set<WebGraphicsContext3DCommandBufferImpl*> >
45     g_all_shared_contexts = LAZY_INSTANCE_INITIALIZER;
46
47 static base::LazyInstance<base::Lock>::Leaky
48     g_all_shared_contexts_browser_lock = LAZY_INSTANCE_INITIALIZER;
49 static base::LazyInstance<std::set<WebGraphicsContext3DCommandBufferImpl*> >
50     g_all_shared_contexts_browser = LAZY_INSTANCE_INITIALIZER;
51
52 namespace {
53
54 void ClearSharedContextsIfInShareSet(
55     WebGraphicsContext3DCommandBufferImpl* context) {
56   // If the given context isn't in the share set, that means that it
57   // or another context it was previously sharing with already
58   // provoked a lost context. Other contexts might have since been
59   // successfully created and added to the share set, so do not clear
60   // out the share set unless we know that all the contexts in there
61   // are supposed to be lost simultaneously.
62   base::AutoLock lock(g_all_shared_contexts_lock.Get());
63   std::set<WebGraphicsContext3DCommandBufferImpl*>* share_set =
64       g_all_shared_contexts.Pointer();
65   for (std::set<WebGraphicsContext3DCommandBufferImpl*>::iterator iter =
66            share_set->begin(); iter != share_set->end(); ++iter) {
67     if (context == *iter) {
68       share_set->clear();
69       return;
70     }
71   }
72 }
73
74 void ClearSharedContextsIfInShareSetBrowser(
75     WebGraphicsContext3DCommandBufferImpl* context) {
76   // If the given context isn't in the share set, that means that it
77   // or another context it was previously sharing with already
78   // provoked a lost context. Other contexts might have since been
79   // successfully created and added to the share set, so do not clear
80   // out the share set unless we know that all the contexts in there
81   // are supposed to be lost simultaneously.
82   base::AutoLock lock(g_all_shared_contexts_browser_lock.Get());
83   std::set<WebGraphicsContext3DCommandBufferImpl*>* share_set =
84       g_all_shared_contexts_browser.Pointer();
85   for (std::set<WebGraphicsContext3DCommandBufferImpl*>::iterator iter =
86            share_set->begin(); iter != share_set->end(); ++iter) {
87     if (context == *iter) {
88       share_set->clear();
89       return;
90     }
91   }
92 }
93
94 size_t ClampUint64ToSizeT(uint64 value) {
95   value = std::min(value,
96                    static_cast<uint64>(std::numeric_limits<size_t>::max()));
97   return static_cast<size_t>(value);
98 }
99
100 uint32_t GenFlushID() {
101   static base::subtle::Atomic32 flush_id = 0;
102
103   base::subtle::Atomic32 my_id = base::subtle::Barrier_AtomicIncrement(
104       &flush_id, 1);
105   return static_cast<uint32_t>(my_id);
106 }
107
108 // Singleton used to initialize and terminate the gles2 library.
109 class GLES2Initializer {
110  public:
111   GLES2Initializer() {
112     gles2::Initialize();
113   }
114
115   ~GLES2Initializer() {
116     gles2::Terminate();
117   }
118
119  private:
120   DISALLOW_COPY_AND_ASSIGN(GLES2Initializer);
121 };
122
123 ////////////////////////////////////////////////////////////////////////////////
124
125 base::LazyInstance<GLES2Initializer> g_gles2_initializer =
126     LAZY_INSTANCE_INITIALIZER;
127
128 ////////////////////////////////////////////////////////////////////////////////
129
130 } // namespace anonymous
131
132 // Helper macros to reduce the amount of code.
133
134 #define DELEGATE_TO_GL(name, glname)                                    \
135 void WebGraphicsContext3DCommandBufferImpl::name() {                    \
136   gl_->glname();                                                        \
137 }
138
139 #define DELEGATE_TO_GL_R(name, glname, rt)                              \
140 rt WebGraphicsContext3DCommandBufferImpl::name() {                      \
141   return gl_->glname();                                                 \
142 }
143
144 #define DELEGATE_TO_GL_1(name, glname, t1)                              \
145 void WebGraphicsContext3DCommandBufferImpl::name(t1 a1) {               \
146   gl_->glname(a1);                                                      \
147 }
148
149 #define DELEGATE_TO_GL_1R(name, glname, t1, rt)                         \
150 rt WebGraphicsContext3DCommandBufferImpl::name(t1 a1) {                 \
151   return gl_->glname(a1);                                               \
152 }
153
154 #define DELEGATE_TO_GL_1RB(name, glname, t1, rt)                        \
155 rt WebGraphicsContext3DCommandBufferImpl::name(t1 a1) {                 \
156   return gl_->glname(a1) ? true : false;                                \
157 }
158
159 #define DELEGATE_TO_GL_2(name, glname, t1, t2)                          \
160 void WebGraphicsContext3DCommandBufferImpl::name(t1 a1, t2 a2) {        \
161   gl_->glname(a1, a2);                                                  \
162 }
163
164 #define DELEGATE_TO_GL_2R(name, glname, t1, t2, rt)                     \
165 rt WebGraphicsContext3DCommandBufferImpl::name(t1 a1, t2 a2) {          \
166   return gl_->glname(a1, a2);                                           \
167 }
168
169 #define DELEGATE_TO_GL_3(name, glname, t1, t2, t3)                      \
170 void WebGraphicsContext3DCommandBufferImpl::name(t1 a1, t2 a2, t3 a3) { \
171   gl_->glname(a1, a2, a3);                                              \
172 }
173
174 #define DELEGATE_TO_GL_3R(name, glname, t1, t2, t3, rt)                 \
175 rt WebGraphicsContext3DCommandBufferImpl::name(t1 a1, t2 a2, t3 a3) {   \
176   return gl_->glname(a1, a2, a3);                                       \
177 }
178
179 #define DELEGATE_TO_GL_4(name, glname, t1, t2, t3, t4)                  \
180 void WebGraphicsContext3DCommandBufferImpl::name(t1 a1, t2 a2, t3 a3,   \
181                                                  t4 a4) {               \
182   gl_->glname(a1, a2, a3, a4);                                          \
183 }
184
185 #define DELEGATE_TO_GL_4R(name, glname, t1, t2, t3, t4, rt)             \
186 rt WebGraphicsContext3DCommandBufferImpl::name(t1 a1, t2 a2, t3 a3,     \
187                                                t4 a4) {                 \
188   return gl_->glname(a1, a2, a3, a4);                                   \
189 }
190
191 #define DELEGATE_TO_GL_5(name, glname, t1, t2, t3, t4, t5)              \
192 void WebGraphicsContext3DCommandBufferImpl::name(t1 a1, t2 a2, t3 a3,   \
193                                                  t4 a4, t5 a5) {        \
194   gl_->glname(a1, a2, a3, a4, a5);                                      \
195 }
196
197 #define DELEGATE_TO_GL_6(name, glname, t1, t2, t3, t4, t5, t6)          \
198 void WebGraphicsContext3DCommandBufferImpl::name(t1 a1, t2 a2, t3 a3,   \
199                                                  t4 a4, t5 a5, t6 a6) { \
200   gl_->glname(a1, a2, a3, a4, a5, a6);                                  \
201 }
202
203 #define DELEGATE_TO_GL_7(name, glname, t1, t2, t3, t4, t5, t6, t7)      \
204 void WebGraphicsContext3DCommandBufferImpl::name(t1 a1, t2 a2, t3 a3,   \
205                                                  t4 a4, t5 a5, t6 a6,   \
206                                                  t7 a7) {               \
207   gl_->glname(a1, a2, a3, a4, a5, a6, a7);                              \
208 }
209
210 #define DELEGATE_TO_GL_8(name, glname, t1, t2, t3, t4, t5, t6, t7, t8)  \
211 void WebGraphicsContext3DCommandBufferImpl::name(t1 a1, t2 a2, t3 a3,   \
212                                                  t4 a4, t5 a5, t6 a6,   \
213                                                  t7 a7, t8 a8) {        \
214   gl_->glname(a1, a2, a3, a4, a5, a6, a7, a8);                          \
215 }
216
217 #define DELEGATE_TO_GL_9(name, glname, t1, t2, t3, t4, t5, t6, t7, t8, t9) \
218 void WebGraphicsContext3DCommandBufferImpl::name(t1 a1, t2 a2, t3 a3,   \
219                                                  t4 a4, t5 a5, t6 a6,   \
220                                                  t7 a7, t8 a8, t9 a9) { \
221   gl_->glname(a1, a2, a3, a4, a5, a6, a7, a8, a9);                      \
222 }
223
224 class WebGraphicsContext3DErrorMessageCallback
225     : public gpu::gles2::GLES2Implementation::ErrorMessageCallback {
226  public:
227   WebGraphicsContext3DErrorMessageCallback(
228       WebGraphicsContext3DCommandBufferImpl* context)
229       : graphics_context_(context) {
230   }
231
232   virtual void OnErrorMessage(const char* msg, int id) OVERRIDE;
233
234  private:
235   WebGraphicsContext3DCommandBufferImpl* graphics_context_;
236
237   DISALLOW_COPY_AND_ASSIGN(WebGraphicsContext3DErrorMessageCallback);
238 };
239
240 void WebGraphicsContext3DErrorMessageCallback::OnErrorMessage(
241     const char* msg, int id) {
242   graphics_context_->OnErrorMessage(msg, id);
243 }
244
245 WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits::SharedMemoryLimits()
246     : command_buffer_size(kDefaultCommandBufferSize),
247       start_transfer_buffer_size(kDefaultStartTransferBufferSize),
248       min_transfer_buffer_size(kDefaultMinTransferBufferSize),
249       max_transfer_buffer_size(kDefaultMaxTransferBufferSize),
250       mapped_memory_reclaim_limit(gpu::gles2::GLES2Implementation::kNoLimit) {}
251
252 WebGraphicsContext3DCommandBufferImpl::WebGraphicsContext3DCommandBufferImpl(
253     int surface_id,
254     const GURL& active_url,
255     GpuChannelHost* host,
256     const base::WeakPtr<WebGraphicsContext3DSwapBuffersClient>& swap_client,
257     const Attributes& attributes,
258     bool bind_generates_resources,
259     const SharedMemoryLimits& limits,
260     bool context_for_browser_compositor)
261     : initialize_failed_(false),
262       visible_(false),
263       free_command_buffer_when_invisible_(false),
264       host_(host),
265       surface_id_(surface_id),
266       active_url_(active_url),
267       swap_client_(swap_client),
268       context_lost_callback_(0),
269       context_lost_reason_(GL_NO_ERROR),
270       error_message_callback_(0),
271       swapbuffers_complete_callback_(0),
272       attributes_(attributes),
273       gpu_preference_(attributes.preferDiscreteGPU ? gfx::PreferDiscreteGpu
274                                                    : gfx::PreferIntegratedGpu),
275       weak_ptr_factory_(this),
276       initialized_(false),
277       gl_(NULL),
278       frame_number_(0),
279       bind_generates_resources_(bind_generates_resources),
280       use_echo_for_swap_ack_(true),
281       mem_limits_(limits),
282       context_for_browser_compositor_(context_for_browser_compositor),
283       flush_id_(0) {
284 #if (defined(OS_MACOSX) || defined(OS_WIN)) && !defined(USE_AURA)
285   // Get ViewMsg_SwapBuffers_ACK from browser for single-threaded path.
286   const CommandLine& command_line = *CommandLine::ForCurrentProcess();
287   use_echo_for_swap_ack_ =
288       command_line.HasSwitch(switches::kEnableThreadedCompositing);
289 #endif
290 }
291
292 WebGraphicsContext3DCommandBufferImpl::
293     ~WebGraphicsContext3DCommandBufferImpl() {
294   if (real_gl_) {
295     real_gl_->SetErrorMessageCallback(NULL);
296   }
297
298   if (context_for_browser_compositor_) {
299     base::AutoLock lock(g_all_shared_contexts_browser_lock.Get());
300     g_all_shared_contexts_browser.Pointer()->erase(this);
301   } else {
302     base::AutoLock lock(g_all_shared_contexts_lock.Get());
303     g_all_shared_contexts.Pointer()->erase(this);
304   }
305   Destroy();
306 }
307
308 bool WebGraphicsContext3DCommandBufferImpl::MaybeInitializeGL() {
309   if (initialized_)
310     return true;
311
312   if (initialize_failed_)
313     return false;
314
315   TRACE_EVENT0("gpu", "WebGfxCtx3DCmdBfrImpl::MaybeInitializeGL");
316
317   if (!CreateContext(surface_id_ != 0)) {
318     Destroy();
319     initialize_failed_ = true;
320     return false;
321   }
322
323   // TODO(twiz):  This code is too fragile in that it assumes that only WebGL
324   // contexts will request noExtensions.
325   if (gl_ && attributes_.noExtensions)
326     gl_->EnableFeatureCHROMIUM("webgl_enable_glsl_webgl_validation");
327
328   command_buffer_->SetChannelErrorCallback(
329       base::Bind(&WebGraphicsContext3DCommandBufferImpl::OnContextLost,
330                  weak_ptr_factory_.GetWeakPtr()));
331
332   command_buffer_->SetOnConsoleMessageCallback(
333       base::Bind(&WebGraphicsContext3DCommandBufferImpl::OnErrorMessage,
334                  weak_ptr_factory_.GetWeakPtr()));
335
336   client_error_message_callback_.reset(
337       new WebGraphicsContext3DErrorMessageCallback(this));
338   real_gl_->SetErrorMessageCallback(client_error_message_callback_.get());
339
340   const CommandLine& command_line = *CommandLine::ForCurrentProcess();
341   free_command_buffer_when_invisible_ =
342       command_line.HasSwitch(switches::kEnablePruneGpuCommandBuffers);
343
344   // Set attributes_ from created offscreen context.
345   {
346     static const int pcount = 4;
347     static const GLenum pnames[pcount] = {
348       GL_ALPHA_BITS,
349       GL_DEPTH_BITS,
350       GL_STENCIL_BITS,
351       GL_SAMPLE_BUFFERS,
352     };
353     GLint pvalues[pcount] = { 0, 0, 0, 0 };
354
355     gl_->GetMultipleIntegervCHROMIUM(pnames, pcount,
356                                      pvalues, sizeof(pvalues));
357
358     attributes_.alpha = pvalues[0] > 0;
359     attributes_.depth = pvalues[1] > 0;
360     attributes_.stencil = pvalues[2] > 0;
361     attributes_.antialias = pvalues[3] > 0;
362   }
363
364   visible_ = true;
365   initialized_ = true;
366   return true;
367 }
368
369 bool WebGraphicsContext3DCommandBufferImpl::InitializeCommandBuffer(
370     bool onscreen) {
371   if (!host_.get())
372     return false;
373   // We need to lock g_all_shared_contexts to ensure that the context we picked
374   // for our share group isn't deleted.
375   // (There's also a lock in our destructor.)
376   CommandBufferProxyImpl* share_group = NULL;
377   if (attributes_.shareResources) {
378     if (context_for_browser_compositor_) {
379       base::AutoLock lock(g_all_shared_contexts_browser_lock.Get());
380       WebGraphicsContext3DCommandBufferImpl* share_group_context =
381           g_all_shared_contexts_browser.Pointer()->empty() ?
382               NULL : *g_all_shared_contexts_browser.Pointer()->begin();
383       share_group = share_group_context ?
384           share_group_context->command_buffer_.get() : NULL;
385     } else {
386       base::AutoLock lock(g_all_shared_contexts_lock.Get());
387       WebGraphicsContext3DCommandBufferImpl* share_group_context =
388           g_all_shared_contexts.Pointer()->empty() ?
389               NULL : *g_all_shared_contexts.Pointer()->begin();
390       share_group = share_group_context ?
391           share_group_context->command_buffer_.get() : NULL;
392     }
393   }
394
395   std::vector<int32> attribs;
396   attribs.push_back(ALPHA_SIZE);
397   attribs.push_back(attributes_.alpha ? 8 : 0);
398   attribs.push_back(DEPTH_SIZE);
399   attribs.push_back(attributes_.depth ? 24 : 0);
400   attribs.push_back(STENCIL_SIZE);
401   attribs.push_back(attributes_.stencil ? 8 : 0);
402   attribs.push_back(SAMPLES);
403   attribs.push_back(attributes_.antialias ? 4 : 0);
404   attribs.push_back(SAMPLE_BUFFERS);
405   attribs.push_back(attributes_.antialias ? 1 : 0);
406   attribs.push_back(NONE);
407
408   // Create a proxy to a command buffer in the GPU process.
409   if (onscreen) {
410     command_buffer_.reset(host_->CreateViewCommandBuffer(
411         surface_id_,
412         share_group,
413         attribs,
414         active_url_,
415         gpu_preference_));
416   } else {
417     command_buffer_.reset(host_->CreateOffscreenCommandBuffer(
418         gfx::Size(1, 1),
419         share_group,
420         attribs,
421         active_url_,
422         gpu_preference_));
423   }
424
425   if (!command_buffer_)
426     return false;
427
428   // Initialize the command buffer.
429   return command_buffer_->Initialize();
430 }
431
432 bool WebGraphicsContext3DCommandBufferImpl::CreateContext(
433     bool onscreen) {
434   // Ensure the gles2 library is initialized first in a thread safe way.
435   g_gles2_initializer.Get();
436
437   if (!command_buffer_ &&
438       !InitializeCommandBuffer(onscreen)) {
439     return false;
440   }
441
442   // Create the GLES2 helper, which writes the command buffer protocol.
443   gles2_helper_.reset(new gpu::gles2::GLES2CmdHelper(command_buffer_.get()));
444   if (!gles2_helper_->Initialize(mem_limits_.command_buffer_size))
445     return false;
446
447   if (attributes_.noAutomaticFlushes)
448     gles2_helper_->SetAutomaticFlushes(false);
449
450   // Create a transfer buffer used to copy resources between the renderer
451   // process and the GPU process.
452   transfer_buffer_ .reset(new gpu::TransferBuffer(gles2_helper_.get()));
453
454   scoped_ptr<base::AutoLock> lock;
455   scoped_refptr<gpu::gles2::ShareGroup> share_group;
456   if (attributes_.shareResources) {
457     // Make sure two clients don't try to create a new ShareGroup
458     // simultaneously.
459     if (context_for_browser_compositor_) {
460       lock.reset(new base::AutoLock(g_all_shared_contexts_browser_lock.Get()));
461       if (!g_all_shared_contexts_browser.Pointer()->empty()) {
462         share_group = (*g_all_shared_contexts_browser.Pointer()->begin())
463             ->GetImplementation()->share_group();
464         DCHECK(share_group);
465       }
466     } else {
467       lock.reset(new base::AutoLock(g_all_shared_contexts_lock.Get()));
468       if (!g_all_shared_contexts.Pointer()->empty()) {
469         share_group = (*g_all_shared_contexts.Pointer()->begin())
470             ->GetImplementation()->share_group();
471         DCHECK(share_group);
472       }
473     }
474   }
475
476   // Create the object exposing the OpenGL API.
477   real_gl_.reset(new gpu::gles2::GLES2Implementation(
478       gles2_helper_.get(),
479       share_group,
480       transfer_buffer_.get(),
481       bind_generates_resources_,
482       command_buffer_.get()));
483   gl_ = real_gl_.get();
484
485   if (attributes_.shareResources) {
486     // Don't add ourselves to the list before others can get to our ShareGroup.
487     if (context_for_browser_compositor_) {
488       g_all_shared_contexts_browser.Pointer()->insert(this);
489     } else {
490       g_all_shared_contexts.Pointer()->insert(this);
491     }
492     lock.reset();
493   }
494
495   if (!real_gl_->Initialize(
496       mem_limits_.start_transfer_buffer_size,
497       mem_limits_.min_transfer_buffer_size,
498       mem_limits_.max_transfer_buffer_size,
499       mem_limits_.mapped_memory_reclaim_limit)) {
500     return false;
501   }
502
503   if (CommandLine::ForCurrentProcess()->HasSwitch(
504       switches::kEnableGpuClientTracing)) {
505     trace_gl_.reset(new gpu::gles2::GLES2TraceImplementation(gl_));
506     gl_ = trace_gl_.get();
507   }
508
509   return true;
510 }
511
512 bool WebGraphicsContext3DCommandBufferImpl::makeContextCurrent() {
513   if (!MaybeInitializeGL())
514     return false;
515   gles2::SetGLContext(gl_);
516   if (command_buffer_->GetLastError() != gpu::error::kNoError)
517     return false;
518
519   return true;
520 }
521
522 uint32_t WebGraphicsContext3DCommandBufferImpl::lastFlushID() {
523   return flush_id_;
524 }
525
526 DELEGATE_TO_GL_R(insertSyncPoint, InsertSyncPointCHROMIUM, unsigned int)
527
528 void WebGraphicsContext3DCommandBufferImpl::Destroy() {
529   if (gl_) {
530     // First flush the context to ensure that any pending frees of resources
531     // are completed. Otherwise, if this context is part of a share group,
532     // those resources might leak. Also, any remaining side effects of commands
533     // issued on this context might not be visible to other contexts in the
534     // share group.
535     gl_->Flush();
536     gl_ = NULL;
537   }
538
539   trace_gl_.reset();
540   real_gl_.reset();
541   transfer_buffer_.reset();
542   gles2_helper_.reset();
543   real_gl_.reset();
544
545   if (command_buffer_) {
546     if (host_.get())
547       host_->DestroyCommandBuffer(command_buffer_.release());
548     command_buffer_.reset();
549   }
550
551   host_ = NULL;
552 }
553
554 // TODO(apatrick,piman): This should be renamed to something clearer.
555 int WebGraphicsContext3DCommandBufferImpl::GetGPUProcessID() {
556   return host_.get() ? host_->gpu_host_id() : 0;
557 }
558
559 int WebGraphicsContext3DCommandBufferImpl::GetChannelID() {
560   return host_.get() ? host_->client_id() : 0;
561 }
562
563 int WebGraphicsContext3DCommandBufferImpl::GetContextID() {
564   return command_buffer_->GetRouteID();
565 }
566
567 gpu::ContextSupport*
568 WebGraphicsContext3DCommandBufferImpl::GetContextSupport() {
569   return real_gl_.get();
570 }
571
572 void WebGraphicsContext3DCommandBufferImpl::prepareTexture() {
573   TRACE_EVENT1("gpu",
574                 "WebGraphicsContext3DCommandBufferImpl::SwapBuffers",
575                 "frame", frame_number_);
576   frame_number_++;
577   // Copies the contents of the off-screen render target into the texture
578   // used by the compositor.
579   if (ShouldUseSwapClient())
580     swap_client_->OnViewContextSwapBuffersPosted();
581
582   if (command_buffer_->GetLastState().error == gpu::error::kNoError)
583     gl_->SwapBuffers();
584
585   if (use_echo_for_swap_ack_) {
586     command_buffer_->Echo(base::Bind(
587         &WebGraphicsContext3DCommandBufferImpl::OnSwapBuffersComplete,
588         weak_ptr_factory_.GetWeakPtr()));
589   }
590 #if defined(OS_MACOSX)
591   // It appears that making the compositor's on-screen context current on
592   // other platforms implies this flush. TODO(kbr): this means that the
593   // TOUCH build and, in the future, other platforms might need this.
594   gl_->Flush();
595 #endif
596 }
597
598 void WebGraphicsContext3DCommandBufferImpl::postSubBufferCHROMIUM(
599     int x, int y, int width, int height) {
600   // Same flow control as WebGraphicsContext3DCommandBufferImpl::prepareTexture
601   // (see above).
602   if (ShouldUseSwapClient())
603     swap_client_->OnViewContextSwapBuffersPosted();
604   gl_->PostSubBufferCHROMIUM(x, y, width, height);
605   command_buffer_->Echo(base::Bind(
606       &WebGraphicsContext3DCommandBufferImpl::OnSwapBuffersComplete,
607       weak_ptr_factory_.GetWeakPtr()));
608 }
609
610 DELEGATE_TO_GL_3(reshapeWithScaleFactor, ResizeCHROMIUM, int, int, float)
611
612 void WebGraphicsContext3DCommandBufferImpl::synthesizeGLError(
613     WGC3Denum error) {
614   if (std::find(synthetic_errors_.begin(), synthetic_errors_.end(), error) ==
615       synthetic_errors_.end()) {
616     synthetic_errors_.push_back(error);
617   }
618 }
619
620 DELEGATE_TO_GL_4R(mapBufferSubDataCHROMIUM, MapBufferSubDataCHROMIUM, WGC3Denum,
621                   WGC3Dintptr, WGC3Dsizeiptr, WGC3Denum, void*)
622
623 DELEGATE_TO_GL_1(unmapBufferSubDataCHROMIUM, UnmapBufferSubDataCHROMIUM,
624                  const void*)
625
626 void* WebGraphicsContext3DCommandBufferImpl::mapTexSubImage2DCHROMIUM(
627     WGC3Denum target,
628     WGC3Dint level,
629     WGC3Dint xoffset,
630     WGC3Dint yoffset,
631     WGC3Dsizei width,
632     WGC3Dsizei height,
633     WGC3Denum format,
634     WGC3Denum type,
635     WGC3Denum access) {
636   return gl_->MapTexSubImage2DCHROMIUM(
637       target, level, xoffset, yoffset, width, height, format, type, access);
638 }
639
640 DELEGATE_TO_GL_1(unmapTexSubImage2DCHROMIUM, UnmapTexSubImage2DCHROMIUM,
641                  const void*)
642
643 void WebGraphicsContext3DCommandBufferImpl::setVisibilityCHROMIUM(
644     bool visible) {
645   gl_->Flush();
646   visible_ = visible;
647   command_buffer_->SetSurfaceVisible(visible);
648   if (!visible)
649     real_gl_->FreeEverything();
650 }
651
652 DELEGATE_TO_GL_3(discardFramebufferEXT, DiscardFramebufferEXT, WGC3Denum,
653                  WGC3Dsizei, const WGC3Denum*)
654
655 void WebGraphicsContext3DCommandBufferImpl::discardBackbufferCHROMIUM() {
656   gl_->Flush();
657   command_buffer_->DiscardBackbuffer();
658 }
659
660 void WebGraphicsContext3DCommandBufferImpl::ensureBackbufferCHROMIUM() {
661   gl_->Flush();
662   command_buffer_->EnsureBackbuffer();
663 }
664
665 void WebGraphicsContext3DCommandBufferImpl::copyTextureToParentTextureCHROMIUM(
666     WebGLId texture, WebGLId parentTexture) {
667   NOTIMPLEMENTED();
668 }
669
670 DELEGATE_TO_GL(rateLimitOffscreenContextCHROMIUM,
671                RateLimitOffscreenContextCHROMIUM)
672
673 WebKit::WebString WebGraphicsContext3DCommandBufferImpl::
674     getRequestableExtensionsCHROMIUM() {
675   return WebKit::WebString::fromUTF8(
676       gl_->GetRequestableExtensionsCHROMIUM());
677 }
678
679 DELEGATE_TO_GL_1(requestExtensionCHROMIUM, RequestExtensionCHROMIUM,
680                  const char*)
681
682 void WebGraphicsContext3DCommandBufferImpl::blitFramebufferCHROMIUM(
683     WGC3Dint srcX0, WGC3Dint srcY0, WGC3Dint srcX1, WGC3Dint srcY1,
684     WGC3Dint dstX0, WGC3Dint dstY0, WGC3Dint dstX1, WGC3Dint dstY1,
685     WGC3Dbitfield mask, WGC3Denum filter) {
686   gl_->BlitFramebufferEXT(
687       srcX0, srcY0, srcX1, srcY1,
688       dstX0, dstY0, dstX1, dstY1,
689       mask, filter);
690 }
691
692 DELEGATE_TO_GL_5(renderbufferStorageMultisampleCHROMIUM,
693                  RenderbufferStorageMultisampleEXT, WGC3Denum, WGC3Dsizei,
694                  WGC3Denum, WGC3Dsizei, WGC3Dsizei)
695
696 DELEGATE_TO_GL_1R(createStreamTextureCHROMIUM, CreateStreamTextureCHROMIUM,
697                   WebGLId, WebGLId)
698
699 DELEGATE_TO_GL_1(destroyStreamTextureCHROMIUM, DestroyStreamTextureCHROMIUM,
700                  WebGLId)
701
702 DELEGATE_TO_GL_1(activeTexture, ActiveTexture, WGC3Denum)
703
704 DELEGATE_TO_GL_2(attachShader, AttachShader, WebGLId, WebGLId)
705
706 DELEGATE_TO_GL_3(bindAttribLocation, BindAttribLocation, WebGLId,
707                  WGC3Duint, const WGC3Dchar*)
708
709 DELEGATE_TO_GL_2(bindBuffer, BindBuffer, WGC3Denum, WebGLId)
710
711 DELEGATE_TO_GL_2(bindFramebuffer, BindFramebuffer, WGC3Denum, WebGLId)
712
713 DELEGATE_TO_GL_2(bindRenderbuffer, BindRenderbuffer, WGC3Denum, WebGLId)
714
715 DELEGATE_TO_GL_2(bindTexture, BindTexture, WGC3Denum, WebGLId)
716
717 DELEGATE_TO_GL_4(blendColor, BlendColor,
718                  WGC3Dclampf, WGC3Dclampf, WGC3Dclampf, WGC3Dclampf)
719
720 DELEGATE_TO_GL_1(blendEquation, BlendEquation, WGC3Denum)
721
722 DELEGATE_TO_GL_2(blendEquationSeparate, BlendEquationSeparate,
723                  WGC3Denum, WGC3Denum)
724
725 DELEGATE_TO_GL_2(blendFunc, BlendFunc, WGC3Denum, WGC3Denum)
726
727 DELEGATE_TO_GL_4(blendFuncSeparate, BlendFuncSeparate,
728                  WGC3Denum, WGC3Denum, WGC3Denum, WGC3Denum)
729
730 DELEGATE_TO_GL_4(bufferData, BufferData,
731                  WGC3Denum, WGC3Dsizeiptr, const void*, WGC3Denum)
732
733 DELEGATE_TO_GL_4(bufferSubData, BufferSubData,
734                  WGC3Denum, WGC3Dintptr, WGC3Dsizeiptr, const void*)
735
736 DELEGATE_TO_GL_1R(checkFramebufferStatus, CheckFramebufferStatus,
737                   WGC3Denum, WGC3Denum)
738
739 DELEGATE_TO_GL_1(clear, Clear, WGC3Dbitfield)
740
741 DELEGATE_TO_GL_4(clearColor, ClearColor,
742                  WGC3Dclampf, WGC3Dclampf, WGC3Dclampf, WGC3Dclampf)
743
744 DELEGATE_TO_GL_1(clearDepth, ClearDepthf, WGC3Dclampf)
745
746 DELEGATE_TO_GL_1(clearStencil, ClearStencil, WGC3Dint)
747
748 DELEGATE_TO_GL_4(colorMask, ColorMask,
749                  WGC3Dboolean, WGC3Dboolean, WGC3Dboolean, WGC3Dboolean)
750
751 DELEGATE_TO_GL_1(compileShader, CompileShader, WebGLId)
752
753 DELEGATE_TO_GL_8(compressedTexImage2D, CompressedTexImage2D,
754                  WGC3Denum, WGC3Dint, WGC3Denum, WGC3Dint, WGC3Dint,
755                  WGC3Dsizei, WGC3Dsizei, const void*)
756
757 DELEGATE_TO_GL_9(compressedTexSubImage2D, CompressedTexSubImage2D,
758                  WGC3Denum, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dint,
759                  WGC3Denum, WGC3Dsizei, const void*)
760
761 DELEGATE_TO_GL_8(copyTexImage2D, CopyTexImage2D,
762                  WGC3Denum, WGC3Dint, WGC3Denum, WGC3Dint, WGC3Dint,
763                  WGC3Dsizei, WGC3Dsizei, WGC3Dint)
764
765 DELEGATE_TO_GL_8(copyTexSubImage2D, CopyTexSubImage2D,
766                  WGC3Denum, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dint,
767                  WGC3Dsizei, WGC3Dsizei)
768
769 DELEGATE_TO_GL_1(cullFace, CullFace, WGC3Denum)
770
771 DELEGATE_TO_GL_1(depthFunc, DepthFunc, WGC3Denum)
772
773 DELEGATE_TO_GL_1(depthMask, DepthMask, WGC3Dboolean)
774
775 DELEGATE_TO_GL_2(depthRange, DepthRangef, WGC3Dclampf, WGC3Dclampf)
776
777 DELEGATE_TO_GL_2(detachShader, DetachShader, WebGLId, WebGLId)
778
779 DELEGATE_TO_GL_1(disable, Disable, WGC3Denum)
780
781 DELEGATE_TO_GL_1(disableVertexAttribArray, DisableVertexAttribArray,
782                  WGC3Duint)
783
784 DELEGATE_TO_GL_3(drawArrays, DrawArrays, WGC3Denum, WGC3Dint, WGC3Dsizei)
785
786 void WebGraphicsContext3DCommandBufferImpl::drawElements(WGC3Denum mode,
787                                                          WGC3Dsizei count,
788                                                          WGC3Denum type,
789                                                          WGC3Dintptr offset) {
790   gl_->DrawElements(
791       mode, count, type,
792       reinterpret_cast<void*>(static_cast<intptr_t>(offset)));
793 }
794
795 DELEGATE_TO_GL_1(enable, Enable, WGC3Denum)
796
797 DELEGATE_TO_GL_1(enableVertexAttribArray, EnableVertexAttribArray,
798                  WGC3Duint)
799
800 void WebGraphicsContext3DCommandBufferImpl::finish() {
801   flush_id_ = GenFlushID();
802   gl_->Finish();
803   if (!visible_ && free_command_buffer_when_invisible_)
804     real_gl_->FreeEverything();
805 }
806
807 void WebGraphicsContext3DCommandBufferImpl::flush() {
808   flush_id_ = GenFlushID();
809   gl_->Flush();
810   if (!visible_ && free_command_buffer_when_invisible_)
811     real_gl_->FreeEverything();
812 }
813
814 DELEGATE_TO_GL_4(framebufferRenderbuffer, FramebufferRenderbuffer,
815                  WGC3Denum, WGC3Denum, WGC3Denum, WebGLId)
816
817 DELEGATE_TO_GL_5(framebufferTexture2D, FramebufferTexture2D,
818                  WGC3Denum, WGC3Denum, WGC3Denum, WebGLId, WGC3Dint)
819
820 DELEGATE_TO_GL_1(frontFace, FrontFace, WGC3Denum)
821
822 DELEGATE_TO_GL_1(generateMipmap, GenerateMipmap, WGC3Denum)
823
824 bool WebGraphicsContext3DCommandBufferImpl::getActiveAttrib(
825     WebGLId program, WGC3Duint index, ActiveInfo& info) {
826   if (!program) {
827     synthesizeGLError(GL_INVALID_VALUE);
828     return false;
829   }
830   GLint max_name_length = -1;
831   gl_->GetProgramiv(
832       program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_name_length);
833   if (max_name_length < 0)
834     return false;
835   scoped_ptr<GLchar[]> name(new GLchar[max_name_length]);
836   if (!name) {
837     synthesizeGLError(GL_OUT_OF_MEMORY);
838     return false;
839   }
840   GLsizei length = 0;
841   GLint size = -1;
842   GLenum type = 0;
843   gl_->GetActiveAttrib(
844       program, index, max_name_length, &length, &size, &type, name.get());
845   if (size < 0) {
846     return false;
847   }
848   info.name = WebKit::WebString::fromUTF8(name.get(), length);
849   info.type = type;
850   info.size = size;
851   return true;
852 }
853
854 bool WebGraphicsContext3DCommandBufferImpl::getActiveUniform(
855     WebGLId program, WGC3Duint index, ActiveInfo& info) {
856   GLint max_name_length = -1;
857   gl_->GetProgramiv(
858       program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_name_length);
859   if (max_name_length < 0)
860     return false;
861   scoped_ptr<GLchar[]> name(new GLchar[max_name_length]);
862   if (!name) {
863     synthesizeGLError(GL_OUT_OF_MEMORY);
864     return false;
865   }
866   GLsizei length = 0;
867   GLint size = -1;
868   GLenum type = 0;
869   gl_->GetActiveUniform(
870       program, index, max_name_length, &length, &size, &type, name.get());
871   if (size < 0) {
872     return false;
873   }
874   info.name = WebKit::WebString::fromUTF8(name.get(), length);
875   info.type = type;
876   info.size = size;
877   return true;
878 }
879
880 DELEGATE_TO_GL_4(getAttachedShaders, GetAttachedShaders,
881                  WebGLId, WGC3Dsizei, WGC3Dsizei*, WebGLId*)
882
883 DELEGATE_TO_GL_2R(getAttribLocation, GetAttribLocation,
884                   WebGLId, const WGC3Dchar*, WGC3Dint)
885
886 DELEGATE_TO_GL_2(getBooleanv, GetBooleanv, WGC3Denum, WGC3Dboolean*)
887
888 DELEGATE_TO_GL_3(getBufferParameteriv, GetBufferParameteriv,
889                  WGC3Denum, WGC3Denum, WGC3Dint*)
890
891 WebKit::WebGraphicsContext3D::Attributes
892 WebGraphicsContext3DCommandBufferImpl::getContextAttributes() {
893   return attributes_;
894 }
895
896 WGC3Denum WebGraphicsContext3DCommandBufferImpl::getError() {
897   if (!synthetic_errors_.empty()) {
898     std::vector<WGC3Denum>::iterator iter = synthetic_errors_.begin();
899     WGC3Denum err = *iter;
900     synthetic_errors_.erase(iter);
901     return err;
902   }
903
904   return gl_->GetError();
905 }
906
907 bool WebGraphicsContext3DCommandBufferImpl::isContextLost() {
908   return initialize_failed_ ||
909       (command_buffer_ && IsCommandBufferContextLost()) ||
910       context_lost_reason_ != GL_NO_ERROR;
911 }
912
913 DELEGATE_TO_GL_2(getFloatv, GetFloatv, WGC3Denum, WGC3Dfloat*)
914
915 DELEGATE_TO_GL_4(getFramebufferAttachmentParameteriv,
916                  GetFramebufferAttachmentParameteriv,
917                  WGC3Denum, WGC3Denum, WGC3Denum, WGC3Dint*)
918
919 DELEGATE_TO_GL_2(getIntegerv, GetIntegerv, WGC3Denum, WGC3Dint*)
920
921 DELEGATE_TO_GL_3(getProgramiv, GetProgramiv, WebGLId, WGC3Denum, WGC3Dint*)
922
923 WebKit::WebString WebGraphicsContext3DCommandBufferImpl::getProgramInfoLog(
924     WebGLId program) {
925   GLint logLength = 0;
926   gl_->GetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
927   if (!logLength)
928     return WebKit::WebString();
929   scoped_ptr<GLchar[]> log(new GLchar[logLength]);
930   if (!log)
931     return WebKit::WebString();
932   GLsizei returnedLogLength = 0;
933   gl_->GetProgramInfoLog(
934       program, logLength, &returnedLogLength, log.get());
935   DCHECK_EQ(logLength, returnedLogLength + 1);
936   WebKit::WebString res =
937       WebKit::WebString::fromUTF8(log.get(), returnedLogLength);
938   return res;
939 }
940
941 DELEGATE_TO_GL_3(getRenderbufferParameteriv, GetRenderbufferParameteriv,
942                  WGC3Denum, WGC3Denum, WGC3Dint*)
943
944 DELEGATE_TO_GL_3(getShaderiv, GetShaderiv, WebGLId, WGC3Denum, WGC3Dint*)
945
946 WebKit::WebString WebGraphicsContext3DCommandBufferImpl::getShaderInfoLog(
947     WebGLId shader) {
948   GLint logLength = 0;
949   gl_->GetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength);
950   if (!logLength)
951     return WebKit::WebString();
952   scoped_ptr<GLchar[]> log(new GLchar[logLength]);
953   if (!log)
954     return WebKit::WebString();
955   GLsizei returnedLogLength = 0;
956   gl_->GetShaderInfoLog(
957       shader, logLength, &returnedLogLength, log.get());
958   DCHECK_EQ(logLength, returnedLogLength + 1);
959   WebKit::WebString res =
960       WebKit::WebString::fromUTF8(log.get(), returnedLogLength);
961   return res;
962 }
963
964 DELEGATE_TO_GL_4(getShaderPrecisionFormat, GetShaderPrecisionFormat,
965                  WGC3Denum, WGC3Denum, WGC3Dint*, WGC3Dint*)
966
967 WebKit::WebString WebGraphicsContext3DCommandBufferImpl::getShaderSource(
968     WebGLId shader) {
969   GLint logLength = 0;
970   gl_->GetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &logLength);
971   if (!logLength)
972     return WebKit::WebString();
973   scoped_ptr<GLchar[]> log(new GLchar[logLength]);
974   if (!log)
975     return WebKit::WebString();
976   GLsizei returnedLogLength = 0;
977   gl_->GetShaderSource(
978       shader, logLength, &returnedLogLength, log.get());
979   if (!returnedLogLength)
980     return WebKit::WebString();
981   DCHECK_EQ(logLength, returnedLogLength + 1);
982   WebKit::WebString res =
983       WebKit::WebString::fromUTF8(log.get(), returnedLogLength);
984   return res;
985 }
986
987 WebKit::WebString WebGraphicsContext3DCommandBufferImpl::
988     getTranslatedShaderSourceANGLE(WebGLId shader) {
989   GLint logLength = 0;
990   gl_->GetShaderiv(
991       shader, GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE, &logLength);
992   if (!logLength)
993     return WebKit::WebString();
994   scoped_ptr<GLchar[]> log(new GLchar[logLength]);
995   if (!log)
996     return WebKit::WebString();
997   GLsizei returnedLogLength = 0;
998   gl_->GetTranslatedShaderSourceANGLE(
999       shader, logLength, &returnedLogLength, log.get());
1000   if (!returnedLogLength)
1001     return WebKit::WebString();
1002   DCHECK_EQ(logLength, returnedLogLength + 1);
1003   WebKit::WebString res =
1004       WebKit::WebString::fromUTF8(log.get(), returnedLogLength);
1005   return res;
1006 }
1007
1008 WebKit::WebString WebGraphicsContext3DCommandBufferImpl::getString(
1009     WGC3Denum name) {
1010   return WebKit::WebString::fromUTF8(
1011       reinterpret_cast<const char*>(gl_->GetString(name)));
1012 }
1013
1014 DELEGATE_TO_GL_3(getTexParameterfv, GetTexParameterfv,
1015                  WGC3Denum, WGC3Denum, WGC3Dfloat*)
1016
1017 DELEGATE_TO_GL_3(getTexParameteriv, GetTexParameteriv,
1018                  WGC3Denum, WGC3Denum, WGC3Dint*)
1019
1020 DELEGATE_TO_GL_3(getUniformfv, GetUniformfv, WebGLId, WGC3Dint, WGC3Dfloat*)
1021
1022 DELEGATE_TO_GL_3(getUniformiv, GetUniformiv, WebGLId, WGC3Dint, WGC3Dint*)
1023
1024 DELEGATE_TO_GL_2R(getUniformLocation, GetUniformLocation,
1025                   WebGLId, const WGC3Dchar*, WGC3Dint)
1026
1027 DELEGATE_TO_GL_3(getVertexAttribfv, GetVertexAttribfv,
1028                  WGC3Duint, WGC3Denum, WGC3Dfloat*)
1029
1030 DELEGATE_TO_GL_3(getVertexAttribiv, GetVertexAttribiv,
1031                  WGC3Duint, WGC3Denum, WGC3Dint*)
1032
1033 WGC3Dsizeiptr WebGraphicsContext3DCommandBufferImpl::getVertexAttribOffset(
1034     WGC3Duint index, WGC3Denum pname) {
1035   GLvoid* value = NULL;
1036   // NOTE: If pname is ever a value that returns more then 1 element
1037   // this will corrupt memory.
1038   gl_->GetVertexAttribPointerv(index, pname, &value);
1039   return static_cast<WGC3Dsizeiptr>(reinterpret_cast<intptr_t>(value));
1040 }
1041
1042 DELEGATE_TO_GL_2(hint, Hint, WGC3Denum, WGC3Denum)
1043
1044 DELEGATE_TO_GL_1RB(isBuffer, IsBuffer, WebGLId, WGC3Dboolean)
1045
1046 DELEGATE_TO_GL_1RB(isEnabled, IsEnabled, WGC3Denum, WGC3Dboolean)
1047
1048 DELEGATE_TO_GL_1RB(isFramebuffer, IsFramebuffer, WebGLId, WGC3Dboolean)
1049
1050 DELEGATE_TO_GL_1RB(isProgram, IsProgram, WebGLId, WGC3Dboolean)
1051
1052 DELEGATE_TO_GL_1RB(isRenderbuffer, IsRenderbuffer, WebGLId, WGC3Dboolean)
1053
1054 DELEGATE_TO_GL_1RB(isShader, IsShader, WebGLId, WGC3Dboolean)
1055
1056 DELEGATE_TO_GL_1RB(isTexture, IsTexture, WebGLId, WGC3Dboolean)
1057
1058 DELEGATE_TO_GL_1(lineWidth, LineWidth, WGC3Dfloat)
1059
1060 DELEGATE_TO_GL_1(linkProgram, LinkProgram, WebGLId)
1061
1062 DELEGATE_TO_GL_2(pixelStorei, PixelStorei, WGC3Denum, WGC3Dint)
1063
1064 DELEGATE_TO_GL_2(polygonOffset, PolygonOffset, WGC3Dfloat, WGC3Dfloat)
1065
1066 DELEGATE_TO_GL_7(readPixels, ReadPixels,
1067                  WGC3Dint, WGC3Dint, WGC3Dsizei, WGC3Dsizei, WGC3Denum,
1068                  WGC3Denum, void*)
1069
1070 void WebGraphicsContext3DCommandBufferImpl::releaseShaderCompiler() {
1071 }
1072
1073 DELEGATE_TO_GL_4(renderbufferStorage, RenderbufferStorage,
1074                  WGC3Denum, WGC3Denum, WGC3Dsizei, WGC3Dsizei)
1075
1076 DELEGATE_TO_GL_2(sampleCoverage, SampleCoverage, WGC3Dfloat, WGC3Dboolean)
1077
1078 DELEGATE_TO_GL_4(scissor, Scissor, WGC3Dint, WGC3Dint, WGC3Dsizei, WGC3Dsizei)
1079
1080 void WebGraphicsContext3DCommandBufferImpl::shaderSource(
1081     WebGLId shader, const WGC3Dchar* string) {
1082   GLint length = strlen(string);
1083   gl_->ShaderSource(shader, 1, &string, &length);
1084 }
1085
1086 DELEGATE_TO_GL_3(stencilFunc, StencilFunc, WGC3Denum, WGC3Dint, WGC3Duint)
1087
1088 DELEGATE_TO_GL_4(stencilFuncSeparate, StencilFuncSeparate,
1089                  WGC3Denum, WGC3Denum, WGC3Dint, WGC3Duint)
1090
1091 DELEGATE_TO_GL_1(stencilMask, StencilMask, WGC3Duint)
1092
1093 DELEGATE_TO_GL_2(stencilMaskSeparate, StencilMaskSeparate,
1094                  WGC3Denum, WGC3Duint)
1095
1096 DELEGATE_TO_GL_3(stencilOp, StencilOp,
1097                  WGC3Denum, WGC3Denum, WGC3Denum)
1098
1099 DELEGATE_TO_GL_4(stencilOpSeparate, StencilOpSeparate,
1100                  WGC3Denum, WGC3Denum, WGC3Denum, WGC3Denum)
1101
1102 DELEGATE_TO_GL_9(texImage2D, TexImage2D,
1103                  WGC3Denum, WGC3Dint, WGC3Denum, WGC3Dsizei, WGC3Dsizei,
1104                  WGC3Dint, WGC3Denum, WGC3Denum, const void*)
1105
1106 DELEGATE_TO_GL_3(texParameterf, TexParameterf,
1107                  WGC3Denum, WGC3Denum, WGC3Dfloat);
1108
1109 static const unsigned int kTextureWrapR = 0x8072;
1110
1111 void WebGraphicsContext3DCommandBufferImpl::texParameteri(
1112     WGC3Denum target, WGC3Denum pname, WGC3Dint param) {
1113   // TODO(kbr): figure out whether the setting of TEXTURE_WRAP_R in
1114   // GraphicsContext3D.cpp is strictly necessary to avoid seams at the
1115   // edge of cube maps, and, if it is, push it into the GLES2 service
1116   // side code.
1117   if (pname == kTextureWrapR) {
1118     return;
1119   }
1120   gl_->TexParameteri(target, pname, param);
1121 }
1122
1123 DELEGATE_TO_GL_9(texSubImage2D, TexSubImage2D,
1124                  WGC3Denum, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dsizei,
1125                  WGC3Dsizei, WGC3Denum, WGC3Denum, const void*)
1126
1127 DELEGATE_TO_GL_2(uniform1f, Uniform1f, WGC3Dint, WGC3Dfloat)
1128
1129 DELEGATE_TO_GL_3(uniform1fv, Uniform1fv, WGC3Dint, WGC3Dsizei,
1130                  const WGC3Dfloat*)
1131
1132 DELEGATE_TO_GL_2(uniform1i, Uniform1i, WGC3Dint, WGC3Dint)
1133
1134 DELEGATE_TO_GL_3(uniform1iv, Uniform1iv, WGC3Dint, WGC3Dsizei, const WGC3Dint*)
1135
1136 DELEGATE_TO_GL_3(uniform2f, Uniform2f, WGC3Dint, WGC3Dfloat, WGC3Dfloat)
1137
1138 DELEGATE_TO_GL_3(uniform2fv, Uniform2fv, WGC3Dint, WGC3Dsizei,
1139                  const WGC3Dfloat*)
1140
1141 DELEGATE_TO_GL_3(uniform2i, Uniform2i, WGC3Dint, WGC3Dint, WGC3Dint)
1142
1143 DELEGATE_TO_GL_3(uniform2iv, Uniform2iv, WGC3Dint, WGC3Dsizei, const WGC3Dint*)
1144
1145 DELEGATE_TO_GL_4(uniform3f, Uniform3f, WGC3Dint,
1146                  WGC3Dfloat, WGC3Dfloat, WGC3Dfloat)
1147
1148 DELEGATE_TO_GL_3(uniform3fv, Uniform3fv, WGC3Dint, WGC3Dsizei,
1149                  const WGC3Dfloat*)
1150
1151 DELEGATE_TO_GL_4(uniform3i, Uniform3i, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dint)
1152
1153 DELEGATE_TO_GL_3(uniform3iv, Uniform3iv, WGC3Dint, WGC3Dsizei, const WGC3Dint*)
1154
1155 DELEGATE_TO_GL_5(uniform4f, Uniform4f, WGC3Dint,
1156                  WGC3Dfloat, WGC3Dfloat, WGC3Dfloat, WGC3Dfloat)
1157
1158 DELEGATE_TO_GL_3(uniform4fv, Uniform4fv, WGC3Dint, WGC3Dsizei,
1159                  const WGC3Dfloat*)
1160
1161 DELEGATE_TO_GL_5(uniform4i, Uniform4i, WGC3Dint,
1162                  WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dint)
1163
1164 DELEGATE_TO_GL_3(uniform4iv, Uniform4iv, WGC3Dint, WGC3Dsizei, const WGC3Dint*)
1165
1166 DELEGATE_TO_GL_4(uniformMatrix2fv, UniformMatrix2fv,
1167                  WGC3Dint, WGC3Dsizei, WGC3Dboolean, const WGC3Dfloat*)
1168
1169 DELEGATE_TO_GL_4(uniformMatrix3fv, UniformMatrix3fv,
1170                  WGC3Dint, WGC3Dsizei, WGC3Dboolean, const WGC3Dfloat*)
1171
1172 DELEGATE_TO_GL_4(uniformMatrix4fv, UniformMatrix4fv,
1173                  WGC3Dint, WGC3Dsizei, WGC3Dboolean, const WGC3Dfloat*)
1174
1175 DELEGATE_TO_GL_1(useProgram, UseProgram, WebGLId)
1176
1177 DELEGATE_TO_GL_1(validateProgram, ValidateProgram, WebGLId)
1178
1179 DELEGATE_TO_GL_2(vertexAttrib1f, VertexAttrib1f, WGC3Duint, WGC3Dfloat)
1180
1181 DELEGATE_TO_GL_2(vertexAttrib1fv, VertexAttrib1fv, WGC3Duint,
1182                  const WGC3Dfloat*)
1183
1184 DELEGATE_TO_GL_3(vertexAttrib2f, VertexAttrib2f, WGC3Duint,
1185                  WGC3Dfloat, WGC3Dfloat)
1186
1187 DELEGATE_TO_GL_2(vertexAttrib2fv, VertexAttrib2fv, WGC3Duint,
1188                  const WGC3Dfloat*)
1189
1190 DELEGATE_TO_GL_4(vertexAttrib3f, VertexAttrib3f, WGC3Duint,
1191                  WGC3Dfloat, WGC3Dfloat, WGC3Dfloat)
1192
1193 DELEGATE_TO_GL_2(vertexAttrib3fv, VertexAttrib3fv, WGC3Duint,
1194                  const WGC3Dfloat*)
1195
1196 DELEGATE_TO_GL_5(vertexAttrib4f, VertexAttrib4f, WGC3Duint,
1197                  WGC3Dfloat, WGC3Dfloat, WGC3Dfloat, WGC3Dfloat)
1198
1199 DELEGATE_TO_GL_2(vertexAttrib4fv, VertexAttrib4fv, WGC3Duint,
1200                  const WGC3Dfloat*)
1201
1202 void WebGraphicsContext3DCommandBufferImpl::vertexAttribPointer(
1203     WGC3Duint index, WGC3Dint size, WGC3Denum type, WGC3Dboolean normalized,
1204     WGC3Dsizei stride, WGC3Dintptr offset) {
1205   gl_->VertexAttribPointer(
1206       index, size, type, normalized, stride,
1207       reinterpret_cast<void*>(static_cast<intptr_t>(offset)));
1208 }
1209
1210 DELEGATE_TO_GL_4(viewport, Viewport,
1211                  WGC3Dint, WGC3Dint, WGC3Dsizei, WGC3Dsizei)
1212
1213 DELEGATE_TO_GL_2(genBuffers, GenBuffers, WGC3Dsizei, WebGLId*);
1214
1215 DELEGATE_TO_GL_2(genFramebuffers, GenFramebuffers, WGC3Dsizei, WebGLId*);
1216
1217 DELEGATE_TO_GL_2(genRenderbuffers, GenRenderbuffers, WGC3Dsizei, WebGLId*);
1218
1219 DELEGATE_TO_GL_2(genTextures, GenTextures, WGC3Dsizei, WebGLId*);
1220
1221 DELEGATE_TO_GL_2(deleteBuffers, DeleteBuffers, WGC3Dsizei, WebGLId*);
1222
1223 DELEGATE_TO_GL_2(deleteFramebuffers, DeleteFramebuffers, WGC3Dsizei, WebGLId*);
1224
1225 DELEGATE_TO_GL_2(deleteRenderbuffers, DeleteRenderbuffers, WGC3Dsizei,
1226                  WebGLId*);
1227
1228 DELEGATE_TO_GL_2(deleteTextures, DeleteTextures, WGC3Dsizei, WebGLId*);
1229
1230 WebGLId WebGraphicsContext3DCommandBufferImpl::createBuffer() {
1231   GLuint o;
1232   gl_->GenBuffers(1, &o);
1233   return o;
1234 }
1235
1236 WebGLId WebGraphicsContext3DCommandBufferImpl::createFramebuffer() {
1237   GLuint o = 0;
1238   gl_->GenFramebuffers(1, &o);
1239   return o;
1240 }
1241
1242 WebGLId WebGraphicsContext3DCommandBufferImpl::createRenderbuffer() {
1243   GLuint o;
1244   gl_->GenRenderbuffers(1, &o);
1245   return o;
1246 }
1247
1248 WebGLId WebGraphicsContext3DCommandBufferImpl::createTexture() {
1249   GLuint o;
1250   gl_->GenTextures(1, &o);
1251   return o;
1252 }
1253
1254 void WebGraphicsContext3DCommandBufferImpl::deleteBuffer(WebGLId buffer) {
1255   gl_->DeleteBuffers(1, &buffer);
1256 }
1257
1258 void WebGraphicsContext3DCommandBufferImpl::deleteFramebuffer(
1259     WebGLId framebuffer) {
1260   gl_->DeleteFramebuffers(1, &framebuffer);
1261 }
1262
1263 void WebGraphicsContext3DCommandBufferImpl::deleteRenderbuffer(
1264     WebGLId renderbuffer) {
1265   gl_->DeleteRenderbuffers(1, &renderbuffer);
1266 }
1267
1268 void WebGraphicsContext3DCommandBufferImpl::deleteTexture(WebGLId texture) {
1269   gl_->DeleteTextures(1, &texture);
1270 }
1271
1272 DELEGATE_TO_GL_R(createProgram, CreateProgram, WebGLId)
1273
1274 DELEGATE_TO_GL_1R(createShader, CreateShader, WGC3Denum, WebGLId)
1275
1276 DELEGATE_TO_GL_1(deleteProgram, DeleteProgram, WebGLId)
1277
1278 DELEGATE_TO_GL_1(deleteShader, DeleteShader, WebGLId)
1279
1280 bool WebGraphicsContext3DCommandBufferImpl::ShouldUseSwapClient() {
1281   return !!swap_client_.get();
1282 }
1283
1284 void WebGraphicsContext3DCommandBufferImpl::OnSwapBuffersComplete() {
1285   typedef WebGraphicsContext3DSwapBuffersClient WGC3DSwapClient;
1286   // This may be called after tear-down of the RenderView.
1287   if (ShouldUseSwapClient()) {
1288     base::MessageLoop::current()->PostTask(
1289         FROM_HERE,
1290         base::Bind(&WGC3DSwapClient::OnViewContextSwapBuffersComplete,
1291                    swap_client_));
1292   }
1293
1294   if (swapbuffers_complete_callback_)
1295     swapbuffers_complete_callback_->onSwapBuffersComplete();
1296 }
1297
1298 void WebGraphicsContext3DCommandBufferImpl::setErrorMessageCallback(
1299     WebGraphicsContext3D::WebGraphicsErrorMessageCallback* cb) {
1300   error_message_callback_ = cb;
1301 }
1302
1303 void WebGraphicsContext3DCommandBufferImpl::setContextLostCallback(
1304     WebGraphicsContext3D::WebGraphicsContextLostCallback* cb) {
1305   context_lost_callback_ = cb;
1306 }
1307
1308 WGC3Denum WebGraphicsContext3DCommandBufferImpl::getGraphicsResetStatusARB() {
1309   if (IsCommandBufferContextLost() &&
1310       context_lost_reason_ == GL_NO_ERROR) {
1311     return GL_UNKNOWN_CONTEXT_RESET_ARB;
1312   }
1313
1314   return context_lost_reason_;
1315 }
1316
1317 bool WebGraphicsContext3DCommandBufferImpl::IsCommandBufferContextLost() {
1318   // If the channel shut down unexpectedly, let that supersede the
1319   // command buffer's state.
1320   if (host_.get() && host_->IsLost())
1321     return true;
1322   gpu::CommandBuffer::State state = command_buffer_->GetLastState();
1323   return state.error == gpu::error::kLostContext;
1324 }
1325
1326 // static
1327 WebGraphicsContext3DCommandBufferImpl*
1328 WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext(
1329     GpuChannelHost* host,
1330     const WebGraphicsContext3D::Attributes& attributes,
1331     const GURL& active_url) {
1332   if (!host)
1333     return NULL;
1334   base::WeakPtr<WebGraphicsContext3DSwapBuffersClient> null_client;
1335   return new WebGraphicsContext3DCommandBufferImpl(0,
1336                                                    active_url,
1337                                                    host,
1338                                                    null_client,
1339                                                    attributes,
1340                                                    false,
1341                                                    SharedMemoryLimits());
1342 }
1343
1344 void WebGraphicsContext3DCommandBufferImpl::
1345     setSwapBuffersCompleteCallbackCHROMIUM(
1346     WebGraphicsContext3D::WebGraphicsSwapBuffersCompleteCallbackCHROMIUM* cb) {
1347   swapbuffers_complete_callback_ = cb;
1348 }
1349
1350 DELEGATE_TO_GL_5(texImageIOSurface2DCHROMIUM, TexImageIOSurface2DCHROMIUM,
1351                  WGC3Denum, WGC3Dint, WGC3Dint, WGC3Duint, WGC3Duint)
1352
1353 DELEGATE_TO_GL_5(texStorage2DEXT, TexStorage2DEXT,
1354                  WGC3Denum, WGC3Dint, WGC3Duint, WGC3Dint, WGC3Dint)
1355
1356 WebGLId WebGraphicsContext3DCommandBufferImpl::createQueryEXT() {
1357   GLuint o;
1358   gl_->GenQueriesEXT(1, &o);
1359   return o;
1360 }
1361
1362 void WebGraphicsContext3DCommandBufferImpl::deleteQueryEXT(
1363     WebGLId query) {
1364   gl_->DeleteQueriesEXT(1, &query);
1365 }
1366
1367 DELEGATE_TO_GL_1R(isQueryEXT, IsQueryEXT, WebGLId, WGC3Dboolean)
1368 DELEGATE_TO_GL_2(beginQueryEXT, BeginQueryEXT, WGC3Denum, WebGLId)
1369 DELEGATE_TO_GL_1(endQueryEXT, EndQueryEXT, WGC3Denum)
1370 DELEGATE_TO_GL_3(getQueryivEXT, GetQueryivEXT, WGC3Denum, WGC3Denum, WGC3Dint*)
1371 DELEGATE_TO_GL_3(getQueryObjectuivEXT, GetQueryObjectuivEXT,
1372                  WebGLId, WGC3Denum, WGC3Duint*)
1373
1374 DELEGATE_TO_GL_6(copyTextureCHROMIUM, CopyTextureCHROMIUM,  WGC3Denum,
1375                  WebGLId, WebGLId, WGC3Dint, WGC3Denum, WGC3Denum);
1376
1377 DELEGATE_TO_GL_3(bindUniformLocationCHROMIUM, BindUniformLocationCHROMIUM,
1378                  WebGLId, WGC3Dint, const WGC3Dchar*)
1379
1380 void WebGraphicsContext3DCommandBufferImpl::shallowFlushCHROMIUM() {
1381   flush_id_ = GenFlushID();
1382   gl_->ShallowFlushCHROMIUM();
1383 }
1384
1385 void WebGraphicsContext3DCommandBufferImpl::shallowFinishCHROMIUM() {
1386   flush_id_ = GenFlushID();
1387   gl_->ShallowFinishCHROMIUM();
1388 }
1389
1390 DELEGATE_TO_GL_1(waitSyncPoint, WaitSyncPointCHROMIUM, GLuint)
1391
1392 void WebGraphicsContext3DCommandBufferImpl::loseContextCHROMIUM(
1393     WGC3Denum current, WGC3Denum other) {
1394   gl_->LoseContextCHROMIUM(current, other);
1395   gl_->Flush();
1396 }
1397
1398 DELEGATE_TO_GL_1(genMailboxCHROMIUM, GenMailboxCHROMIUM, WGC3Dbyte*)
1399 DELEGATE_TO_GL_2(produceTextureCHROMIUM, ProduceTextureCHROMIUM,
1400                  WGC3Denum, const WGC3Dbyte*)
1401 DELEGATE_TO_GL_2(consumeTextureCHROMIUM, ConsumeTextureCHROMIUM,
1402                  WGC3Denum, const WGC3Dbyte*)
1403
1404 void WebGraphicsContext3DCommandBufferImpl::insertEventMarkerEXT(
1405     const WGC3Dchar* marker) {
1406   gl_->InsertEventMarkerEXT(0, marker);
1407 }
1408
1409 void WebGraphicsContext3DCommandBufferImpl::pushGroupMarkerEXT(
1410     const WGC3Dchar* marker) {
1411   gl_->PushGroupMarkerEXT(0, marker);
1412 }
1413
1414 DELEGATE_TO_GL(popGroupMarkerEXT, PopGroupMarkerEXT);
1415
1416 WebGLId WebGraphicsContext3DCommandBufferImpl::createVertexArrayOES() {
1417   GLuint array;
1418   gl_->GenVertexArraysOES(1, &array);
1419   return array;
1420 }
1421
1422 void WebGraphicsContext3DCommandBufferImpl::deleteVertexArrayOES(
1423     WebGLId array) {
1424   gl_->DeleteVertexArraysOES(1, &array);
1425 }
1426
1427 DELEGATE_TO_GL_1R(isVertexArrayOES, IsVertexArrayOES, WebGLId, WGC3Dboolean)
1428 DELEGATE_TO_GL_1(bindVertexArrayOES, BindVertexArrayOES, WebGLId)
1429
1430 DELEGATE_TO_GL_2(bindTexImage2DCHROMIUM, BindTexImage2DCHROMIUM,
1431                  WGC3Denum, WGC3Dint)
1432 DELEGATE_TO_GL_2(releaseTexImage2DCHROMIUM, ReleaseTexImage2DCHROMIUM,
1433                  WGC3Denum, WGC3Dint)
1434
1435 DELEGATE_TO_GL_2R(mapBufferCHROMIUM, MapBufferCHROMIUM, WGC3Denum, WGC3Denum,
1436                   void*)
1437 DELEGATE_TO_GL_1R(unmapBufferCHROMIUM, UnmapBufferCHROMIUM, WGC3Denum,
1438                   WGC3Dboolean)
1439
1440 DELEGATE_TO_GL_9(asyncTexImage2DCHROMIUM, AsyncTexImage2DCHROMIUM, WGC3Denum,
1441                  WGC3Dint, WGC3Denum, WGC3Dsizei, WGC3Dsizei, WGC3Dint,
1442                  WGC3Denum, WGC3Denum, const void*)
1443 DELEGATE_TO_GL_9(asyncTexSubImage2DCHROMIUM, AsyncTexSubImage2DCHROMIUM,
1444                  WGC3Denum, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dsizei,
1445                  WGC3Dsizei, WGC3Denum, WGC3Denum, const void*)
1446
1447 DELEGATE_TO_GL_1(waitAsyncTexImage2DCHROMIUM, WaitAsyncTexImage2DCHROMIUM,
1448                  WGC3Denum)
1449
1450 DELEGATE_TO_GL_2(drawBuffersEXT, DrawBuffersEXT, WGC3Dsizei, const WGC3Denum*)
1451
1452 DELEGATE_TO_GL_4(drawArraysInstancedANGLE, DrawArraysInstancedANGLE, WGC3Denum,
1453                  WGC3Dint, WGC3Dsizei, WGC3Dsizei)
1454
1455 void WebGraphicsContext3DCommandBufferImpl::drawElementsInstancedANGLE(
1456     WGC3Denum mode,
1457     WGC3Dsizei count,
1458     WGC3Denum type,
1459     WGC3Dintptr offset,
1460     WGC3Dsizei primcount) {
1461   gl_->DrawElementsInstancedANGLE(
1462       mode, count, type,
1463       reinterpret_cast<void*>(static_cast<intptr_t>(offset)), primcount);
1464 }
1465
1466 DELEGATE_TO_GL_2(vertexAttribDivisorANGLE, VertexAttribDivisorANGLE, WGC3Duint,
1467                  WGC3Duint)
1468
1469 DELEGATE_TO_GL_3R(createImageCHROMIUM, CreateImageCHROMIUM,
1470                   WGC3Dsizei, WGC3Dsizei, WGC3Denum,
1471                   WGC3Duint);
1472
1473 DELEGATE_TO_GL_1(destroyImageCHROMIUM, DestroyImageCHROMIUM, WGC3Duint);
1474
1475 DELEGATE_TO_GL_3(getImageParameterivCHROMIUM, GetImageParameterivCHROMIUM,
1476                  WGC3Duint, WGC3Denum, GLint*);
1477
1478 DELEGATE_TO_GL_2R(mapImageCHROMIUM, MapImageCHROMIUM,
1479                   WGC3Duint, WGC3Denum, void*);
1480
1481 DELEGATE_TO_GL_1(unmapImageCHROMIUM, UnmapImageCHROMIUM, WGC3Duint);
1482
1483 GrGLInterface* WebGraphicsContext3DCommandBufferImpl::createGrGLInterface() {
1484   return webkit::gpu::CreateCommandBufferSkiaGLBinding();
1485 }
1486
1487 namespace {
1488
1489 WGC3Denum convertReason(gpu::error::ContextLostReason reason) {
1490   switch (reason) {
1491   case gpu::error::kGuilty:
1492     return GL_GUILTY_CONTEXT_RESET_ARB;
1493   case gpu::error::kInnocent:
1494     return GL_INNOCENT_CONTEXT_RESET_ARB;
1495   case gpu::error::kUnknown:
1496     return GL_UNKNOWN_CONTEXT_RESET_ARB;
1497   }
1498
1499   NOTREACHED();
1500   return GL_UNKNOWN_CONTEXT_RESET_ARB;
1501 }
1502
1503 }  // anonymous namespace
1504
1505 void WebGraphicsContext3DCommandBufferImpl::OnContextLost() {
1506   context_lost_reason_ = convertReason(
1507       command_buffer_->GetLastState().context_lost_reason);
1508   if (context_lost_callback_) {
1509     context_lost_callback_->onContextLost();
1510   }
1511   if (attributes_.shareResources) {
1512     if (context_for_browser_compositor_) {
1513       ClearSharedContextsIfInShareSetBrowser(this);
1514     } else {
1515       ClearSharedContextsIfInShareSet(this);
1516     }
1517   }
1518   if (ShouldUseSwapClient())
1519     swap_client_->OnViewContextSwapBuffersAborted();
1520 }
1521
1522 void WebGraphicsContext3DCommandBufferImpl::OnErrorMessage(
1523     const std::string& message, int id) {
1524   if (error_message_callback_) {
1525     WebKit::WebString str = WebKit::WebString::fromUTF8(message.c_str());
1526     error_message_callback_->onErrorMessage(str, id);
1527   }
1528 }
1529
1530 }  // namespace content