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