summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/gpu_process_host.cc39
-rw-r--r--chrome/browser/gpu_process_host.h8
-rw-r--r--chrome/browser/renderer_host/browser_render_process_host.cc8
-rw-r--r--chrome/browser/renderer_host/browser_render_process_host.h5
-rwxr-xr-xchrome/chrome_renderer.gypi2
-rw-r--r--chrome/common/gpu_messages_internal.h13
-rw-r--r--chrome/common/render_messages_internal.h5
-rw-r--r--chrome/common/sandbox_init_wrapper_mac.cc3
-rw-r--r--chrome/gpu/gpu_thread.cc6
-rw-r--r--chrome/gpu/gpu_thread.h1
-rw-r--r--chrome/renderer/ggl/ggl.cc2
-rw-r--r--chrome/renderer/render_thread.cc8
-rw-r--r--chrome/renderer/render_thread.h6
-rw-r--r--chrome/renderer/renderer_webkitclient_impl.cc19
-rw-r--r--chrome/renderer/renderer_webkitclient_impl.h2
-rw-r--r--chrome/renderer/webgraphicscontext3d_command_buffer_impl.cc878
-rw-r--r--chrome/renderer/webgraphicscontext3d_command_buffer_impl.h352
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc73
-rw-r--r--webkit/tools/test_shell/test_shell_webkit_init.h5
19 files changed, 1426 insertions, 9 deletions
diff --git a/chrome/browser/gpu_process_host.cc b/chrome/browser/gpu_process_host.cc
index 9fa0092..9981133 100644
--- a/chrome/browser/gpu_process_host.cc
+++ b/chrome/browser/gpu_process_host.cc
@@ -62,6 +62,10 @@ GpuProcessHost::GpuProcessHost() : last_routing_id_(1) {
}
GpuProcessHost::~GpuProcessHost() {
+ while (!queued_synchronization_replies_.empty()) {
+ delete queued_synchronization_replies_.front();
+ queued_synchronization_replies_.pop();
+ }
}
// static
@@ -133,9 +137,25 @@ void GpuProcessHost::EstablishGpuChannel(int renderer_id) {
ReplyToRenderer(renderer_id, IPC::ChannelHandle());
}
+void GpuProcessHost::Synchronize(int renderer_id, IPC::Message* reply) {
+ // ************
+ // TODO(kbr): the handling of this synchronous message (which is
+ // needed for proper initialization semantics of APIs like WebGL) is
+ // currently broken on Windows because the renderer is sending a
+ // synchronous message to the browser's UI thread. To fix this, the
+ // GpuProcessHost needs to move to the IO thread, and any backing
+ // store handling needs to remain on the UI thread in a new
+ // GpuProcessHostProxy, where work is sent from the IO thread to the
+ // UI thread via PostTask.
+ // ************
+ queued_synchronization_replies_.push(reply);
+ CHECK(Send(new GpuMsg_Synchronize(renderer_id)));
+}
+
void GpuProcessHost::OnControlMessageReceived(const IPC::Message& message) {
IPC_BEGIN_MESSAGE_MAP(GpuProcessHost, message)
IPC_MESSAGE_HANDLER(GpuHostMsg_ChannelEstablished, OnChannelEstablished)
+ IPC_MESSAGE_HANDLER(GpuHostMsg_SynchronizeReply, OnSynchronizeReply)
IPC_MESSAGE_UNHANDLED_ERROR()
IPC_END_MESSAGE_MAP()
}
@@ -148,6 +168,17 @@ void GpuProcessHost::OnChannelEstablished(
sent_requests_.pop();
}
+void GpuProcessHost::OnSynchronizeReply(int renderer_id) {
+ IPC::Message* reply = queued_synchronization_replies_.front();
+ queued_synchronization_replies_.pop();
+ RenderProcessHost* process_host = RenderProcessHost::FromID(renderer_id);
+ if (!process_host) {
+ delete reply;
+ return;
+ }
+ CHECK(process_host->Send(reply));
+}
+
void GpuProcessHost::ReplyToRenderer(
int renderer_id,
const IPC::ChannelHandle& channel) {
@@ -156,7 +187,13 @@ void GpuProcessHost::ReplyToRenderer(
if (!process_host)
return;
- CHECK(process_host->Send(new ViewMsg_GpuChannelEstablished(channel)));
+ ViewMsg_GpuChannelEstablished* msg =
+ new ViewMsg_GpuChannelEstablished(channel);
+ // If the renderer process is performing synchronous initialization,
+ // it needs to handle this message before receiving the reply for
+ // the synchronous ViewHostMsg_SynchronizeGpu message.
+ msg->set_unblock(true);
+ CHECK(process_host->Send(msg));
}
void GpuProcessHost::PropagateBrowserCommandLineToGpu(
diff --git a/chrome/browser/gpu_process_host.h b/chrome/browser/gpu_process_host.h
index 4d74e00..27d3fe3 100644
--- a/chrome/browser/gpu_process_host.h
+++ b/chrome/browser/gpu_process_host.h
@@ -53,6 +53,10 @@ class GpuProcessHost : public IPC::Channel::Sender,
// on completion.
void EstablishGpuChannel(int renderer_id);
+ // Sends a reply message later when the next GpuHostMsg_SynchronizeReply comes
+ // in.
+ void Synchronize(int renderer_id, IPC::Message* reply);
+
private:
friend struct DefaultSingletonTraits<GpuProcessHost>;
@@ -74,6 +78,7 @@ class GpuProcessHost : public IPC::Channel::Sender,
// Message handlers.
void OnChannelEstablished(const IPC::ChannelHandle& channel_handle);
+ void OnSynchronizeReply(int renderer_id);
void ReplyToRenderer(int renderer_id,
const IPC::ChannelHandle& channel);
@@ -104,6 +109,9 @@ class GpuProcessHost : public IPC::Channel::Sender,
// because the queued messages may have dependencies on the init messages.
std::queue<IPC::Message*> queued_messages_;
+ // The pending synchronization requests we need to reply to.
+ std::queue<IPC::Message*> queued_synchronization_replies_;
+
DISALLOW_COPY_AND_ASSIGN(GpuProcessHost);
};
diff --git a/chrome/browser/renderer_host/browser_render_process_host.cc b/chrome/browser/renderer_host/browser_render_process_host.cc
index dccc34d..1fc8ffa 100644
--- a/chrome/browser/renderer_host/browser_render_process_host.cc
+++ b/chrome/browser/renderer_host/browser_render_process_host.cc
@@ -773,7 +773,9 @@ void BrowserRenderProcessHost::OnMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER(ViewHostMsg_ExtensionCloseChannel,
OnExtensionCloseChannel)
IPC_MESSAGE_HANDLER(ViewHostMsg_EstablishGpuChannel,
- OnMsgEstablishGpuChannel)
+ OnMsgEstablishGpuChannel)
+ IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_SynchronizeGpu,
+ OnMsgSynchronizeGpu)
IPC_MESSAGE_HANDLER(ViewHostMsg_SpellChecker_RequestDictionary,
OnSpellCheckerRequestDictionary)
IPC_MESSAGE_UNHANDLED_ERROR()
@@ -982,6 +984,10 @@ void BrowserRenderProcessHost::OnMsgEstablishGpuChannel() {
GpuProcessHost::Get()->EstablishGpuChannel(id());
}
+void BrowserRenderProcessHost::OnMsgSynchronizeGpu(IPC::Message* reply) {
+ GpuProcessHost::Get()->Synchronize(id(), reply);
+}
+
void BrowserRenderProcessHost::OnSpellCheckerRequestDictionary() {
if (profile()->GetSpellCheckHost()) {
// The spellchecker initialization already started and finished; just send
diff --git a/chrome/browser/renderer_host/browser_render_process_host.h b/chrome/browser/renderer_host/browser_render_process_host.h
index 372045a..9a9c833 100644
--- a/chrome/browser/renderer_host/browser_render_process_host.h
+++ b/chrome/browser/renderer_host/browser_render_process_host.h
@@ -110,7 +110,12 @@ class BrowserRenderProcessHost : public RenderProcessHost,
void OnExtensionAddListener(const std::string& event_name);
void OnExtensionRemoveListener(const std::string& event_name);
void OnExtensionCloseChannel(int port_id);
+ // Renderer process is requesting that the browser process establish a GPU
+ // channel.
void OnMsgEstablishGpuChannel();
+ // Renderer process is requesting that outstanding asynchronous GPU-related
+ // messages are processed.
+ void OnMsgSynchronizeGpu(IPC::Message* reply);
// Initialize support for visited links. Send the renderer process its initial
// set of visited links.
diff --git a/chrome/chrome_renderer.gypi b/chrome/chrome_renderer.gypi
index 67df617..abf5eb7 100755
--- a/chrome/chrome_renderer.gypi
+++ b/chrome/chrome_renderer.gypi
@@ -161,6 +161,8 @@
'renderer/user_script_slave.h',
'renderer/visitedlink_slave.cc',
'renderer/visitedlink_slave.h',
+ 'renderer/webgraphicscontext3d_command_buffer_impl.cc',
+ 'renderer/webgraphicscontext3d_command_buffer_impl.h',
'renderer/webplugin_delegate_proxy.cc',
'renderer/webplugin_delegate_proxy.h',
'renderer/webplugin_delegate_pepper.cc',
diff --git a/chrome/common/gpu_messages_internal.h b/chrome/common/gpu_messages_internal.h
index 9107aed..628671d 100644
--- a/chrome/common/gpu_messages_internal.h
+++ b/chrome/common/gpu_messages_internal.h
@@ -26,6 +26,14 @@ IPC_BEGIN_MESSAGES(Gpu)
IPC_MESSAGE_CONTROL1(GpuMsg_EstablishChannel,
int /* renderer_id */)
+ // Provides a synchronization point to guarantee that the processing of
+ // previous asynchronous messages (i.e., GpuMsg_EstablishChannel) has
+ // completed. (This message can't be synchronous because the
+ // GpuProcessHost uses an IPC::ChannelProxy, which sends all messages
+ // asynchronously.) Results in a GpuHostMsg_SynchronizeReply.
+ IPC_MESSAGE_CONTROL1(GpuMsg_Synchronize,
+ int /* renderer_id */)
+
IPC_MESSAGE_CONTROL2(GpuMsg_NewRenderWidgetHostView,
GpuNativeWindowHandle, /* parent window */
int32 /* view_id */)
@@ -90,6 +98,11 @@ IPC_BEGIN_MESSAGES(GpuHost)
// Response to a GpuHostMsg_EstablishChannel message.
IPC_MESSAGE_CONTROL1(GpuHostMsg_ChannelEstablished,
IPC::ChannelHandle /* channel_handle */)
+
+ // Response to a GpuMsg_Synchronize message.
+ IPC_MESSAGE_CONTROL1(GpuHostMsg_SynchronizeReply,
+ int /* renderer_id */)
+
IPC_END_MESSAGES(GpuHost)
//------------------------------------------------------------------------------
diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h
index 0372a49..c06da08 100644
--- a/chrome/common/render_messages_internal.h
+++ b/chrome/common/render_messages_internal.h
@@ -1342,6 +1342,11 @@ IPC_BEGIN_MESSAGES(ViewHost)
// a GpuChannelEstablished message.
IPC_MESSAGE_CONTROL0(ViewHostMsg_EstablishGpuChannel)
+ // A renderer sends this to the browser process to provide a synchronization
+ // point for GPU operations, in particular to make sure the GPU channel has
+ // been established.
+ IPC_SYNC_MESSAGE_CONTROL0_0(ViewHostMsg_SynchronizeGpu)
+
// A renderer sends this to the browser process when it wants to start
// a new instance of the Native Client process. The browser will launch
// the process and return a handle to an IMC channel.
diff --git a/chrome/common/sandbox_init_wrapper_mac.cc b/chrome/common/sandbox_init_wrapper_mac.cc
index a47240d..898faed 100644
--- a/chrome/common/sandbox_init_wrapper_mac.cc
+++ b/chrome/common/sandbox_init_wrapper_mac.cc
@@ -41,7 +41,8 @@ bool SandboxInitWrapper::InitializeSandbox(const CommandLine& command_line,
sandbox_process_type = sandbox::SANDBOX_TYPE_WORKER;
} else if ((process_type == switches::kNaClLoaderProcess) ||
(process_type == switches::kPluginProcess) ||
- (process_type == switches::kProfileImportProcess)) {
+ (process_type == switches::kProfileImportProcess) ||
+ (process_type == switches::kGpuProcess)) {
return true;
} else {
// Failsafe: If you hit an unreached here, is your new process type in need
diff --git a/chrome/gpu/gpu_thread.cc b/chrome/gpu/gpu_thread.cc
index 9de441c..5e096a5 100644
--- a/chrome/gpu/gpu_thread.cc
+++ b/chrome/gpu/gpu_thread.cc
@@ -40,6 +40,8 @@ void GpuThread::OnControlMessageReceived(const IPC::Message& msg) {
IPC_BEGIN_MESSAGE_MAP_EX(GpuThread, msg, msg_is_ok)
IPC_MESSAGE_HANDLER(GpuMsg_EstablishChannel,
OnEstablishChannel)
+ IPC_MESSAGE_HANDLER(GpuMsg_Synchronize,
+ OnSynchronize)
IPC_MESSAGE_HANDLER(GpuMsg_NewRenderWidgetHostView,
OnNewRenderWidgetHostView)
IPC_END_MESSAGE_MAP_EX()
@@ -79,6 +81,10 @@ void GpuThread::OnEstablishChannel(int renderer_id) {
Send(new GpuHostMsg_ChannelEstablished(channel_handle));
}
+void GpuThread::OnSynchronize(int renderer_id) {
+ Send(new GpuHostMsg_SynchronizeReply(renderer_id));
+}
+
void GpuThread::OnNewRenderWidgetHostView(GpuNativeWindowHandle parent_window,
int32 routing_id) {
// The GPUView class' lifetime is controlled by the host, which will send a
diff --git a/chrome/gpu/gpu_thread.h b/chrome/gpu/gpu_thread.h
index 23b8ba1..bc06051 100644
--- a/chrome/gpu/gpu_thread.h
+++ b/chrome/gpu/gpu_thread.h
@@ -36,6 +36,7 @@ class GpuThread : public ChildThread {
// Message handlers.
void OnEstablishChannel(int renderer_id);
+ void OnSynchronize(int renderer_id);
void OnNewRenderWidgetHostView(GpuNativeWindowHandle parent_window,
int32 routing_id);
diff --git a/chrome/renderer/ggl/ggl.cc b/chrome/renderer/ggl/ggl.cc
index 2c41126..8973dda 100644
--- a/chrome/renderer/ggl/ggl.cc
+++ b/chrome/renderer/ggl/ggl.cc
@@ -27,6 +27,8 @@ namespace ggl {
namespace {
const int32 kCommandBufferSize = 1024 * 1024;
+// TODO(kbr): make the transfer buffer size configurable via context
+// creation attributes.
const int32 kTransferBufferSize = 1024 * 1024;
base::ThreadLocalPointer<Context> g_current_context;
diff --git a/chrome/renderer/render_thread.cc b/chrome/renderer/render_thread.cc
index 4fb0971..aff8fa6 100644
--- a/chrome/renderer/render_thread.cc
+++ b/chrome/renderer/render_thread.cc
@@ -703,6 +703,14 @@ void RenderThread::EstablishGpuChannel() {
Send(new ViewHostMsg_EstablishGpuChannel());
}
+GpuChannelHost* RenderThread::EstablishGpuChannelSync() {
+ EstablishGpuChannel();
+ Send(new ViewHostMsg_SynchronizeGpu());
+ // TODO(kbr): the GPU channel is still in the unconnected state at this point.
+ // Need to figure out whether it is really safe to return it.
+ return gpu_channel_.get();
+}
+
GpuChannelHost* RenderThread::GetGpuChannel() {
if (!gpu_channel_.get())
return NULL;
diff --git a/chrome/renderer/render_thread.h b/chrome/renderer/render_thread.h
index 3caed00..b774672 100644
--- a/chrome/renderer/render_thread.h
+++ b/chrome/renderer/render_thread.h
@@ -172,6 +172,12 @@ class RenderThread : public RenderThreadBase,
// Use GetGpuChannel() to determine when the channel is ready for use.
void EstablishGpuChannel();
+ // Synchronously establish a channel to the GPU plugin if not previously
+ // established or if it has been lost (for example if the GPU plugin crashed).
+ // If there is a pending asynchronous request, it will be completed by the
+ // time this routine returns.
+ GpuChannelHost* EstablishGpuChannelSync();
+
// Get the GPU channel. Returns NULL if the channel is not established or
// has been lost.
GpuChannelHost* GetGpuChannel();
diff --git a/chrome/renderer/renderer_webkitclient_impl.cc b/chrome/renderer/renderer_webkitclient_impl.cc
index 1f6736f..33698c5 100644
--- a/chrome/renderer/renderer_webkitclient_impl.cc
+++ b/chrome/renderer/renderer_webkitclient_impl.cc
@@ -24,8 +24,10 @@
#include "chrome/renderer/render_view.h"
#include "chrome/renderer/renderer_webstoragenamespace_impl.h"
#include "chrome/renderer/visitedlink_slave.h"
+#include "chrome/renderer/webgraphicscontext3d_command_buffer_impl.h"
#include "googleurl/src/gurl.h"
#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebGraphicsContext3D.h"
#include "third_party/WebKit/WebKit/chromium/public/WebStorageEventDispatcher.h"
#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
#include "third_party/WebKit/WebKit/chromium/public/WebURL.h"
@@ -339,6 +341,23 @@ RendererWebKitClientImpl::sharedWorkerRepository() {
}
}
+WebKit::WebGraphicsContext3D*
+RendererWebKitClientImpl::createGraphicsContext3D() {
+ // TODO(kbr): remove the WebGraphicsContext3D::createDefault code path
+ // completely, and at least for a period of time, either pop up a warning
+ // dialog, or don't even start the browser, if WebGL is enabled and the
+ // sandbox isn't.
+ if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kNoSandbox)) {
+ return WebKit::WebGraphicsContext3D::createDefault();
+ } else {
+#if defined(ENABLE_GPU)
+ return new WebGraphicsContext3DCommandBufferImpl();
+#else
+ return NULL;
+#endif
+ }
+}
+
//------------------------------------------------------------------------------
WebKit::WebString RendererWebKitClientImpl::signedPublicKeyAndChallengeString(
diff --git a/chrome/renderer/renderer_webkitclient_impl.h b/chrome/renderer/renderer_webkitclient_impl.h
index f041851..b9232d2 100644
--- a/chrome/renderer/renderer_webkitclient_impl.h
+++ b/chrome/renderer/renderer_webkitclient_impl.h
@@ -66,8 +66,8 @@ class RendererWebKitClientImpl : public webkit_glue::WebKitClientImpl {
const WebKit::WebURL& url);
virtual WebKit::WebApplicationCacheHost* createApplicationCacheHost(
WebKit::WebApplicationCacheHostClient*);
-
virtual WebKit::WebSharedWorkerRepository* sharedWorkerRepository();
+ virtual WebKit::WebGraphicsContext3D* createGraphicsContext3D();
private:
class MimeRegistry : public webkit_glue::SimpleWebMimeRegistryImpl {
diff --git a/chrome/renderer/webgraphicscontext3d_command_buffer_impl.cc b/chrome/renderer/webgraphicscontext3d_command_buffer_impl.cc
new file mode 100644
index 0000000..af76cb0
--- /dev/null
+++ b/chrome/renderer/webgraphicscontext3d_command_buffer_impl.cc
@@ -0,0 +1,878 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#if defined(ENABLE_GPU)
+
+#include "chrome/renderer/webgraphicscontext3d_command_buffer_impl.h"
+
+#include <GLES2/gl2.h>
+
+#include <algorithm>
+
+#include "base/logging.h"
+#include "chrome/renderer/gpu_channel_host.h"
+#include "chrome/renderer/render_thread.h"
+
+// TODO(kbr): OpenGL may return multiple errors from sequential calls
+// to glGetError.
+static void checkGLError() {
+ GLenum error = glGetError();
+ if (error) {
+ DLOG(ERROR) << "GL Error " << error;
+ }
+}
+
+WebGraphicsContext3DCommandBufferImpl::WebGraphicsContext3DCommandBufferImpl()
+ : context_(NULL),
+ texture_(0),
+ fbo_(0),
+ depth_buffer_(0),
+ cached_width_(0),
+ cached_height_(0),
+ bound_fbo_(0) {
+}
+
+WebGraphicsContext3DCommandBufferImpl::
+ ~WebGraphicsContext3DCommandBufferImpl() {
+ if (context_) {
+ ggl::DestroyContext(context_);
+ }
+}
+
+bool WebGraphicsContext3DCommandBufferImpl::initialize(
+ WebGraphicsContext3D::Attributes attributes) {
+ RenderThread* render_thread = RenderThread::current();
+ if (!render_thread)
+ return false;
+ GpuChannelHost* host = render_thread->EstablishGpuChannelSync();
+ if (!host)
+ return false;
+ DCHECK(host->ready());
+ context_ = ggl::CreateOffscreenContext(host, NULL, gfx::Size(1, 1));
+ if (!context_)
+ return false;
+ return true;
+}
+
+bool WebGraphicsContext3DCommandBufferImpl::makeContextCurrent() {
+ return ggl::MakeCurrent(context_);
+}
+
+int WebGraphicsContext3DCommandBufferImpl::width() {
+ return cached_width_;
+}
+
+int WebGraphicsContext3DCommandBufferImpl::height() {
+ return cached_height_;
+}
+
+int WebGraphicsContext3DCommandBufferImpl::sizeInBytes(int type) {
+ switch (type) {
+ case GL_BYTE:
+ return sizeof(GLbyte);
+ case GL_UNSIGNED_BYTE:
+ return sizeof(GLubyte);
+ case GL_SHORT:
+ return sizeof(GLshort);
+ case GL_UNSIGNED_SHORT:
+ return sizeof(GLushort);
+ case GL_INT:
+ return sizeof(GLint);
+ case GL_UNSIGNED_INT:
+ return sizeof(GLuint);
+ case GL_FLOAT:
+ return sizeof(GLfloat);
+ }
+ return 0;
+}
+
+static int createTextureObject(GLenum target) {
+ GLuint texture = 0;
+ glGenTextures(1, &texture);
+ checkGLError();
+ glBindTexture(target, texture);
+ checkGLError();
+ glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ checkGLError();
+ glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ checkGLError();
+ return texture;
+}
+
+void WebGraphicsContext3DCommandBufferImpl::reshape(int width, int height) {
+ cached_width_ = width;
+ cached_height_ = height;
+ makeContextCurrent();
+
+ checkGLError();
+
+ GLenum target = GL_TEXTURE_2D;
+
+ // TODO(kbr): switch this code to use the default back buffer of
+ // GGL / the GLES2 command buffer code.
+
+ // TODO(kbr): determine whether we need to hack in
+ // GL_TEXTURE_RECTANGLE_ARB support for Mac OS X -- or resize the
+ // framebuffer objects to the next largest power of two.
+
+ if (!texture_) {
+ // Generate the texture object
+ texture_ = createTextureObject(target);
+ // Generate the framebuffer object
+ glGenFramebuffers(1, &fbo_);
+ checkGLError();
+ // Generate the depth buffer
+ glGenRenderbuffers(1, &depth_buffer_);
+ checkGLError();
+ }
+
+ // Reallocate the color and depth buffers
+ glBindTexture(target, texture_);
+ checkGLError();
+ glTexImage2D(target, 0, GL_RGBA, width, height, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, 0);
+ checkGLError();
+ glBindTexture(target, 0);
+ checkGLError();
+
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo_);
+ checkGLError();
+ bound_fbo_ = fbo_;
+ glBindRenderbuffer(GL_RENDERBUFFER, depth_buffer_);
+ checkGLError();
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16,
+ width, height);
+ checkGLError();
+ glBindRenderbuffer(GL_RENDERBUFFER, 0);
+ checkGLError();
+
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ target, texture_, 0);
+ checkGLError();
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+ GL_RENDERBUFFER, depth_buffer_);
+ checkGLError();
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ checkGLError();
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
+ DLOG(ERROR) << "WebGraphicsContext3DCommandBufferImpl: "
+ << "framebuffer was incomplete";
+
+ // TODO(kbr): cleanup.
+ NOTIMPLEMENTED();
+ }
+
+#ifdef FLIP_FRAMEBUFFER_VERTICALLY
+ scanline_.reset(new uint8[width * 4]);
+#endif // FLIP_FRAMEBUFFER_VERTICALLY
+
+ glClear(GL_COLOR_BUFFER_BIT);
+ checkGLError();
+}
+
+#ifdef FLIP_FRAMEBUFFER_VERTICALLY
+void WebGraphicsContext3DCommandBufferImpl::FlipVertically(
+ uint8* framebuffer,
+ unsigned int width,
+ unsigned int height) {
+ uint8* scanline = scanline_.get();
+ if (!scanline)
+ return;
+ unsigned int row_bytes = width * 4;
+ unsigned int count = height / 2;
+ for (unsigned int i = 0; i < count; i++) {
+ uint8* row_a = framebuffer + i * row_bytes;
+ uint8* row_b = framebuffer + (height - i - 1) * row_bytes;
+ // TODO(kbr): this is where the multiplication of the alpha
+ // channel into the color buffer will need to occur if the
+ // user specifies the "premultiplyAlpha" flag in the context
+ // creation attributes.
+ memcpy(scanline, row_b, row_bytes);
+ memcpy(row_b, row_a, row_bytes);
+ memcpy(row_a, scanline, row_bytes);
+ }
+}
+#endif
+
+bool WebGraphicsContext3DCommandBufferImpl::readBackFramebuffer(
+ unsigned char* pixels,
+ size_t buffer_size) {
+ if (buffer_size != static_cast<size_t>(4 * width() * height())) {
+ return false;
+ }
+
+ makeContextCurrent();
+
+ // Earlier versions of this code used the GPU to flip the
+ // framebuffer vertically before reading it back for compositing
+ // via software. This code was quite complicated, used a lot of
+ // GPU memory, and didn't provide an obvious speedup. Since this
+ // vertical flip is only a temporary solution anyway until Chrome
+ // is fully GPU composited, it wasn't worth the complexity.
+
+ bool mustRestoreFBO = (bound_fbo_ != fbo_);
+ if (mustRestoreFBO)
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo_);
+ glReadPixels(0, 0, cached_width_, cached_height_,
+ GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+
+ // Swizzle red and blue channels
+ // TODO(kbr): expose GL_BGRA as extension
+ for (size_t i = 0; i < buffer_size; i += 4) {
+ std::swap(pixels[i], pixels[i + 2]);
+ }
+
+ if (mustRestoreFBO) {
+ glBindFramebuffer(GL_FRAMEBUFFER, bound_fbo_);
+ }
+
+#ifdef FLIP_FRAMEBUFFER_VERTICALLY
+ if (pixels) {
+ FlipVertically(pixels, cached_width_, cached_height_);
+ }
+#endif
+
+ return true;
+}
+
+void WebGraphicsContext3DCommandBufferImpl::synthesizeGLError(
+ unsigned long error) {
+ if (find(synthetic_errors_.begin(), synthetic_errors_.end(), error) ==
+ synthetic_errors_.end()) {
+ synthetic_errors_.push_back(error);
+ }
+}
+
+// Helper macros to reduce the amount of code.
+
+#define DELEGATE_TO_GL(name, glname) \
+void WebGraphicsContext3DCommandBufferImpl::name() { \
+ makeContextCurrent(); \
+ gl##glname(); \
+}
+
+#define DELEGATE_TO_GL_1(name, glname, t1) \
+void WebGraphicsContext3DCommandBufferImpl::name(t1 a1) { \
+ makeContextCurrent(); \
+ gl##glname(a1); \
+}
+
+#define DELEGATE_TO_GL_1_C(name, glname, t1) \
+void WebGraphicsContext3DCommandBufferImpl::name(t1 a1) { \
+ makeContextCurrent(); \
+ gl##glname(static_cast<GLclampf>(a1)); \
+}
+
+#define DELEGATE_TO_GL_1R(name, glname, t1, rt) \
+rt WebGraphicsContext3DCommandBufferImpl::name(t1 a1) { \
+ makeContextCurrent(); \
+ return gl##glname(a1); \
+}
+
+#define DELEGATE_TO_GL_1RB(name, glname, t1, rt) \
+rt WebGraphicsContext3DCommandBufferImpl::name(t1 a1) { \
+ makeContextCurrent(); \
+ return gl##glname(a1) ? true : false; \
+}
+
+#define DELEGATE_TO_GL_2(name, glname, t1, t2) \
+void WebGraphicsContext3DCommandBufferImpl::name(t1 a1, t2 a2) { \
+ makeContextCurrent(); \
+ gl##glname(a1, a2); \
+}
+
+#define DELEGATE_TO_GL_2_C1(name, glname, t1, t2) \
+void WebGraphicsContext3DCommandBufferImpl::name(t1 a1, t2 a2) { \
+ makeContextCurrent(); \
+ gl##glname(static_cast<GLclampf>(a1), a2); \
+}
+
+#define DELEGATE_TO_GL_2_C12(name, glname, t1, t2) \
+void WebGraphicsContext3DCommandBufferImpl::name(t1 a1, t2 a2) { \
+ makeContextCurrent(); \
+ gl##glname(static_cast<GLclampf>(a1), static_cast<GLclampf>(a2)); \
+}
+
+#define DELEGATE_TO_GL_2R(name, glname, t1, t2, rt) \
+rt WebGraphicsContext3DCommandBufferImpl::name(t1 a1, t2 a2) { \
+ makeContextCurrent(); \
+ return gl##glname(a1, a2); \
+}
+
+#define DELEGATE_TO_GL_3(name, glname, t1, t2, t3) \
+void WebGraphicsContext3DCommandBufferImpl::name(t1 a1, t2 a2, t3 a3) { \
+ makeContextCurrent(); \
+ gl##glname(a1, a2, a3); \
+}
+
+#define DELEGATE_TO_GL_4(name, glname, t1, t2, t3, t4) \
+void WebGraphicsContext3DCommandBufferImpl::name(t1 a1, t2 a2, t3 a3, t4 a4) { \
+ makeContextCurrent(); \
+ gl##glname(a1, a2, a3, a4); \
+}
+
+#define DELEGATE_TO_GL_4_C1234(name, glname, t1, t2, t3, t4) \
+void WebGraphicsContext3DCommandBufferImpl::name(t1 a1, t2 a2, t3 a3, t4 a4) { \
+ makeContextCurrent(); \
+ gl##glname(static_cast<GLclampf>(a1), static_cast<GLclampf>(a2), \
+ static_cast<GLclampf>(a3), static_cast<GLclampf>(a4)); \
+}
+
+#define DELEGATE_TO_GL_5(name, glname, t1, t2, t3, t4, t5) \
+void WebGraphicsContext3DCommandBufferImpl::name(t1 a1, t2 a2, t3 a3, \
+ t4 a4, t5 a5) { \
+ makeContextCurrent(); \
+ gl##glname(a1, a2, a3, a4, a5); \
+}
+
+#define DELEGATE_TO_GL_6(name, glname, t1, t2, t3, t4, t5, t6) \
+void WebGraphicsContext3DCommandBufferImpl::name(t1 a1, t2 a2, t3 a3, \
+ t4 a4, t5 a5, t6 a6) { \
+ makeContextCurrent(); \
+ gl##glname(a1, a2, a3, a4, a5, a6); \
+}
+
+#define DELEGATE_TO_GL_7(name, glname, t1, t2, t3, t4, t5, t6, t7) \
+void WebGraphicsContext3DCommandBufferImpl::name(t1 a1, t2 a2, t3 a3, \
+ t4 a4, t5 a5, t6 a6, t7 a7) { \
+ makeContextCurrent(); \
+ gl##glname(a1, a2, a3, a4, a5, a6, a7); \
+}
+
+#define DELEGATE_TO_GL_8(name, glname, t1, t2, t3, t4, t5, t6, t7, t8) \
+void WebGraphicsContext3DCommandBufferImpl::name(t1 a1, t2 a2, t3 a3, \
+ t4 a4, t5 a5, t6 a6, \
+ t7 a7, t8 a8) { \
+ makeContextCurrent(); \
+ gl##glname(a1, a2, a3, a4, a5, a6, a7, a8); \
+}
+
+#define DELEGATE_TO_GL_9(name, glname, t1, t2, t3, t4, t5, t6, t7, t8, t9) \
+void WebGraphicsContext3DCommandBufferImpl::name(t1 a1, t2 a2, t3 a3, \
+ t4 a4, t5 a5, t6 a6, \
+ t7 a7, t8 a8, t9 a9) { \
+ makeContextCurrent(); \
+ gl##glname(a1, a2, a3, a4, a5, a6, a7, a8, a9); \
+}
+
+DELEGATE_TO_GL_1(activeTexture, ActiveTexture, unsigned long)
+
+DELEGATE_TO_GL_2(attachShader, AttachShader, WebGLId, WebGLId)
+
+DELEGATE_TO_GL_3(bindAttribLocation, BindAttribLocation, WebGLId,
+ unsigned long, const char*)
+
+DELEGATE_TO_GL_2(bindBuffer, BindBuffer, unsigned long, WebGLId)
+
+void WebGraphicsContext3DCommandBufferImpl::bindFramebuffer(
+ unsigned long target,
+ WebGLId framebuffer) {
+ makeContextCurrent();
+ if (!framebuffer)
+ framebuffer = fbo_;
+ glBindFramebuffer(target, framebuffer);
+ bound_fbo_ = framebuffer;
+}
+
+DELEGATE_TO_GL_2(bindRenderbuffer, BindRenderbuffer, unsigned long, WebGLId)
+
+DELEGATE_TO_GL_2(bindTexture, BindTexture, unsigned long, WebGLId)
+
+DELEGATE_TO_GL_4_C1234(blendColor, BlendColor, double, double, double, double)
+
+DELEGATE_TO_GL_1(blendEquation, BlendEquation, unsigned long)
+
+DELEGATE_TO_GL_2(blendEquationSeparate, BlendEquationSeparate,
+ unsigned long, unsigned long)
+
+DELEGATE_TO_GL_2(blendFunc, BlendFunc, unsigned long, unsigned long)
+
+DELEGATE_TO_GL_4(blendFuncSeparate, BlendFuncSeparate,
+ unsigned long, unsigned long, unsigned long, unsigned long)
+
+DELEGATE_TO_GL_4(bufferData, BufferData,
+ unsigned long, int, const void*, unsigned long)
+
+DELEGATE_TO_GL_4(bufferSubData, BufferSubData,
+ unsigned long, long, int, const void*)
+
+DELEGATE_TO_GL_1R(checkFramebufferStatus, CheckFramebufferStatus,
+ unsigned long, unsigned long)
+
+DELEGATE_TO_GL_1(clear, Clear, unsigned long)
+
+DELEGATE_TO_GL_4_C1234(clearColor, ClearColor, double, double, double, double)
+
+DELEGATE_TO_GL_1_C(clearDepth, ClearDepthf, double)
+
+DELEGATE_TO_GL_1(clearStencil, ClearStencil, long)
+
+DELEGATE_TO_GL_4(colorMask, ColorMask, bool, bool, bool, bool)
+
+DELEGATE_TO_GL_1(compileShader, CompileShader, WebGLId)
+
+DELEGATE_TO_GL_8(copyTexImage2D, CopyTexImage2D,
+ unsigned long, long, unsigned long, long, long,
+ unsigned long, unsigned long, long)
+
+DELEGATE_TO_GL_8(copyTexSubImage2D, CopyTexSubImage2D,
+ unsigned long, long, long, long, long, long,
+ unsigned long, unsigned long)
+
+DELEGATE_TO_GL_1(cullFace, CullFace, unsigned long)
+
+DELEGATE_TO_GL_1(depthFunc, DepthFunc, unsigned long)
+
+DELEGATE_TO_GL_1(depthMask, DepthMask, bool)
+
+DELEGATE_TO_GL_2_C12(depthRange, DepthRangef, double, double)
+
+DELEGATE_TO_GL_2(detachShader, DetachShader, WebGLId, WebGLId)
+
+DELEGATE_TO_GL_1(disable, Disable, unsigned long)
+
+DELEGATE_TO_GL_1(disableVertexAttribArray, DisableVertexAttribArray,
+ unsigned long)
+
+DELEGATE_TO_GL_3(drawArrays, DrawArrays, unsigned long, long, long)
+
+void WebGraphicsContext3DCommandBufferImpl::drawElements(unsigned long mode,
+ unsigned long count,
+ unsigned long type,
+ long offset) {
+ makeContextCurrent();
+ glDrawElements(mode, count, type,
+ reinterpret_cast<void*>(static_cast<intptr_t>(offset)));
+}
+
+DELEGATE_TO_GL_1(enable, Enable, unsigned long)
+
+DELEGATE_TO_GL_1(enableVertexAttribArray, EnableVertexAttribArray,
+ unsigned long)
+
+DELEGATE_TO_GL(finish, Finish)
+
+DELEGATE_TO_GL(flush, Flush)
+
+DELEGATE_TO_GL_4(framebufferRenderbuffer, FramebufferRenderbuffer,
+ unsigned long, unsigned long, unsigned long, WebGLId)
+
+DELEGATE_TO_GL_5(framebufferTexture2D, FramebufferTexture2D,
+ unsigned long, unsigned long, unsigned long, WebGLId, long)
+
+DELEGATE_TO_GL_1(frontFace, FrontFace, unsigned long)
+
+DELEGATE_TO_GL_1(generateMipmap, GenerateMipmap, unsigned long)
+
+bool WebGraphicsContext3DCommandBufferImpl::getActiveAttrib(
+ WebGLId program, unsigned long index, ActiveInfo& info) {
+ if (!program) {
+ synthesizeGLError(GL_INVALID_VALUE);
+ return false;
+ }
+ GLint max_name_length = -1;
+ glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_name_length);
+ if (max_name_length < 0)
+ return false;
+ scoped_array<GLchar> name(new GLchar[max_name_length]);
+ if (!name.get()) {
+ synthesizeGLError(GL_OUT_OF_MEMORY);
+ return false;
+ }
+ GLsizei length = 0;
+ GLint size = -1;
+ GLenum type = 0;
+ glGetActiveAttrib(program, index, max_name_length,
+ &length, &size, &type, name.get());
+ if (size < 0) {
+ return false;
+ }
+ info.name = WebKit::WebString::fromUTF8(name.get(), length);
+ info.type = type;
+ info.size = size;
+ return true;
+}
+
+bool WebGraphicsContext3DCommandBufferImpl::getActiveUniform(
+ WebGLId program, unsigned long index, ActiveInfo& info) {
+ GLint max_name_length = -1;
+ glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_name_length);
+ if (max_name_length < 0)
+ return false;
+ scoped_array<GLchar> name(new GLchar[max_name_length]);
+ if (!name.get()) {
+ synthesizeGLError(GL_OUT_OF_MEMORY);
+ return false;
+ }
+ GLsizei length = 0;
+ GLint size = -1;
+ GLenum type = 0;
+ glGetActiveUniform(program, index, max_name_length,
+ &length, &size, &type, name.get());
+ if (size < 0) {
+ return false;
+ }
+ info.name = WebKit::WebString::fromUTF8(name.get(), length);
+ info.type = type;
+ info.size = size;
+ return true;
+}
+
+DELEGATE_TO_GL_2R(getAttribLocation, GetAttribLocation,
+ WebGLId, const char*, int)
+
+DELEGATE_TO_GL_2(getBooleanv, GetBooleanv, unsigned long, unsigned char*)
+
+DELEGATE_TO_GL_3(getBufferParameteriv, GetBufferParameteriv,
+ unsigned long, unsigned long, int*)
+
+WebKit::WebGraphicsContext3D::Attributes
+WebGraphicsContext3DCommandBufferImpl::getContextAttributes() {
+ return attributes_;
+}
+
+unsigned long WebGraphicsContext3DCommandBufferImpl::getError() {
+ if (synthetic_errors_.size() > 0) {
+ std::vector<unsigned long>::iterator iter = synthetic_errors_.begin();
+ unsigned long err = *iter;
+ synthetic_errors_.erase(iter);
+ return err;
+ }
+
+ makeContextCurrent();
+ return glGetError();
+}
+
+DELEGATE_TO_GL_2(getFloatv, GetFloatv, unsigned long, float*)
+
+DELEGATE_TO_GL_4(getFramebufferAttachmentParameteriv,
+ GetFramebufferAttachmentParameteriv,
+ unsigned long, unsigned long, unsigned long, int*)
+
+DELEGATE_TO_GL_2(getIntegerv, GetIntegerv, unsigned long, int*)
+
+DELEGATE_TO_GL_3(getProgramiv, GetProgramiv, WebGLId, unsigned long, int*)
+
+WebKit::WebString WebGraphicsContext3DCommandBufferImpl::getProgramInfoLog(
+ WebGLId program) {
+ makeContextCurrent();
+ GLint logLength;
+ glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
+ if (!logLength)
+ return WebKit::WebString();
+ scoped_array<GLchar> log(new GLchar[logLength]);
+ if (!log.get())
+ return WebKit::WebString();
+ GLsizei returnedLogLength;
+ glGetProgramInfoLog(program, logLength, &returnedLogLength, log.get());
+ DCHECK_EQ(logLength, returnedLogLength + 1);
+ WebKit::WebString res =
+ WebKit::WebString::fromUTF8(log.get(), returnedLogLength);
+ return res;
+}
+
+DELEGATE_TO_GL_3(getRenderbufferParameteriv, GetRenderbufferParameteriv,
+ unsigned long, unsigned long, int*)
+
+DELEGATE_TO_GL_3(getShaderiv, GetShaderiv, WebGLId, unsigned long, int*)
+
+WebKit::WebString WebGraphicsContext3DCommandBufferImpl::getShaderInfoLog(
+ WebGLId shader) {
+ makeContextCurrent();
+ GLint logLength;
+ glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength);
+ if (!logLength)
+ return WebKit::WebString();
+ scoped_array<GLchar> log(new GLchar[logLength]);
+ if (!log.get())
+ return WebKit::WebString();
+ GLsizei returnedLogLength;
+ glGetShaderInfoLog(shader, logLength, &returnedLogLength, log.get());
+ DCHECK_EQ(logLength, returnedLogLength + 1);
+ WebKit::WebString res =
+ WebKit::WebString::fromUTF8(log.get(), returnedLogLength);
+ return res;
+}
+
+WebKit::WebString WebGraphicsContext3DCommandBufferImpl::getShaderSource(
+ WebGLId shader) {
+ makeContextCurrent();
+ GLint logLength;
+ glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &logLength);
+ if (!logLength)
+ return WebKit::WebString();
+ scoped_array<GLchar> log(new GLchar[logLength]);
+ if (!log.get())
+ return WebKit::WebString();
+ GLsizei returnedLogLength;
+ glGetShaderSource(shader, logLength, &returnedLogLength, log.get());
+ DCHECK_EQ(logLength, returnedLogLength + 1);
+ WebKit::WebString res =
+ WebKit::WebString::fromUTF8(log.get(), returnedLogLength);
+ return res;
+}
+
+WebKit::WebString WebGraphicsContext3DCommandBufferImpl::getString(
+ unsigned long name) {
+ makeContextCurrent();
+ return WebKit::WebString::fromUTF8(
+ reinterpret_cast<const char*>(glGetString(name)));
+}
+
+DELEGATE_TO_GL_3(getTexParameterfv, GetTexParameterfv,
+ unsigned long, unsigned long, float*)
+
+DELEGATE_TO_GL_3(getTexParameteriv, GetTexParameteriv,
+ unsigned long, unsigned long, int*)
+
+DELEGATE_TO_GL_3(getUniformfv, GetUniformfv, WebGLId, long, float*)
+
+DELEGATE_TO_GL_3(getUniformiv, GetUniformiv, WebGLId, long, int*)
+
+DELEGATE_TO_GL_2R(getUniformLocation, GetUniformLocation,
+ WebGLId, const char*, long)
+
+DELEGATE_TO_GL_3(getVertexAttribfv, GetVertexAttribfv,
+ unsigned long, unsigned long, float*)
+
+DELEGATE_TO_GL_3(getVertexAttribiv, GetVertexAttribiv,
+ unsigned long, unsigned long, int*)
+
+long WebGraphicsContext3DCommandBufferImpl::getVertexAttribOffset(
+ unsigned long index, unsigned long pname) {
+ // TODO(kbr): implement.
+ NOTIMPLEMENTED();
+ return 0;
+}
+
+DELEGATE_TO_GL_2(hint, Hint, unsigned long, unsigned long)
+
+DELEGATE_TO_GL_1RB(isBuffer, IsBuffer, WebGLId, bool)
+
+DELEGATE_TO_GL_1RB(isEnabled, IsEnabled, unsigned long, bool)
+
+DELEGATE_TO_GL_1RB(isFramebuffer, IsFramebuffer, WebGLId, bool)
+
+DELEGATE_TO_GL_1RB(isProgram, IsProgram, WebGLId, bool)
+
+DELEGATE_TO_GL_1RB(isRenderbuffer, IsRenderbuffer, WebGLId, bool)
+
+DELEGATE_TO_GL_1RB(isShader, IsShader, WebGLId, bool)
+
+DELEGATE_TO_GL_1RB(isTexture, IsTexture, WebGLId, bool)
+
+DELEGATE_TO_GL_1_C(lineWidth, LineWidth, double)
+
+DELEGATE_TO_GL_1(linkProgram, LinkProgram, WebGLId)
+
+DELEGATE_TO_GL_2(pixelStorei, PixelStorei, unsigned long, long)
+
+DELEGATE_TO_GL_2_C12(polygonOffset, PolygonOffset, double, double)
+
+DELEGATE_TO_GL_7(readPixels, ReadPixels,
+ long, long, unsigned long, unsigned long, unsigned long,
+ unsigned long, void*)
+
+void WebGraphicsContext3DCommandBufferImpl::releaseShaderCompiler() {
+}
+
+DELEGATE_TO_GL_4(renderbufferStorage, RenderbufferStorage,
+ unsigned long, unsigned long, unsigned long, unsigned long)
+
+DELEGATE_TO_GL_2_C1(sampleCoverage, SampleCoverage, double, bool)
+
+DELEGATE_TO_GL_4(scissor, Scissor, long, long, unsigned long, unsigned long)
+
+void WebGraphicsContext3DCommandBufferImpl::shaderSource(
+ WebGLId shader, const char* string) {
+ makeContextCurrent();
+ GLint length = strlen(string);
+ glShaderSource(shader, 1, &string, &length);
+}
+
+DELEGATE_TO_GL_3(stencilFunc, StencilFunc, unsigned long, long, unsigned long)
+
+DELEGATE_TO_GL_4(stencilFuncSeparate, StencilFuncSeparate,
+ unsigned long, unsigned long, long, unsigned long)
+
+DELEGATE_TO_GL_1(stencilMask, StencilMask, unsigned long)
+
+DELEGATE_TO_GL_2(stencilMaskSeparate, StencilMaskSeparate,
+ unsigned long, unsigned long)
+
+DELEGATE_TO_GL_3(stencilOp, StencilOp,
+ unsigned long, unsigned long, unsigned long)
+
+DELEGATE_TO_GL_4(stencilOpSeparate, StencilOpSeparate,
+ unsigned long, unsigned long, unsigned long, unsigned long)
+
+DELEGATE_TO_GL_9(texImage2D, TexImage2D,
+ unsigned, unsigned, unsigned, unsigned, unsigned, unsigned,
+ unsigned, unsigned, const void*)
+
+DELEGATE_TO_GL_3(texParameterf, TexParameterf, unsigned, unsigned, float);
+
+static const unsigned int kTextureWrapR = 0x8072;
+
+void WebGraphicsContext3DCommandBufferImpl::texParameteri(
+ unsigned target, unsigned pname, int param) {
+ // TODO(kbr): figure out whether the setting of TEXTURE_WRAP_R in
+ // GraphicsContext3D.cpp is strictly necessary to avoid seams at the
+ // edge of cube maps, and, if it is, push it into the GLES2 service
+ // side code.
+ if (pname == kTextureWrapR) {
+ return;
+ }
+ makeContextCurrent();
+ glTexParameteri(target, pname, param);
+}
+
+DELEGATE_TO_GL_9(texSubImage2D, TexSubImage2D,
+ unsigned, unsigned, unsigned, unsigned, unsigned, unsigned,
+ unsigned, unsigned, const void*)
+
+DELEGATE_TO_GL_2(uniform1f, Uniform1f, long, float)
+
+DELEGATE_TO_GL_3(uniform1fv, Uniform1fv, long, int, float*)
+
+DELEGATE_TO_GL_2(uniform1i, Uniform1i, long, int)
+
+DELEGATE_TO_GL_3(uniform1iv, Uniform1iv, long, int, int*)
+
+DELEGATE_TO_GL_3(uniform2f, Uniform2f, long, float, float)
+
+DELEGATE_TO_GL_3(uniform2fv, Uniform2fv, long, int, float*)
+
+DELEGATE_TO_GL_3(uniform2i, Uniform2i, long, int, int)
+
+DELEGATE_TO_GL_3(uniform2iv, Uniform2iv, long, int, int*)
+
+DELEGATE_TO_GL_4(uniform3f, Uniform3f, long, float, float, float)
+
+DELEGATE_TO_GL_3(uniform3fv, Uniform3fv, long, int, float*)
+
+DELEGATE_TO_GL_4(uniform3i, Uniform3i, long, int, int, int)
+
+DELEGATE_TO_GL_3(uniform3iv, Uniform3iv, long, int, int*)
+
+DELEGATE_TO_GL_5(uniform4f, Uniform4f, long, float, float, float, float)
+
+DELEGATE_TO_GL_3(uniform4fv, Uniform4fv, long, int, float*)
+
+DELEGATE_TO_GL_5(uniform4i, Uniform4i, long, int, int, int, int)
+
+DELEGATE_TO_GL_3(uniform4iv, Uniform4iv, long, int, int*)
+
+DELEGATE_TO_GL_4(uniformMatrix2fv, UniformMatrix2fv,
+ long, int, bool, const float*)
+
+DELEGATE_TO_GL_4(uniformMatrix3fv, UniformMatrix3fv,
+ long, int, bool, const float*)
+
+DELEGATE_TO_GL_4(uniformMatrix4fv, UniformMatrix4fv,
+ long, int, bool, const float*)
+
+DELEGATE_TO_GL_1(useProgram, UseProgram, WebGLId)
+
+DELEGATE_TO_GL_1(validateProgram, ValidateProgram, WebGLId)
+
+DELEGATE_TO_GL_2(vertexAttrib1f, VertexAttrib1f, unsigned long, float)
+
+DELEGATE_TO_GL_2(vertexAttrib1fv, VertexAttrib1fv, unsigned long, const float*)
+
+DELEGATE_TO_GL_3(vertexAttrib2f, VertexAttrib2f, unsigned long, float, float)
+
+DELEGATE_TO_GL_2(vertexAttrib2fv, VertexAttrib2fv, unsigned long, const float*)
+
+DELEGATE_TO_GL_4(vertexAttrib3f, VertexAttrib3f,
+ unsigned long, float, float, float)
+
+DELEGATE_TO_GL_2(vertexAttrib3fv, VertexAttrib3fv, unsigned long, const float*)
+
+DELEGATE_TO_GL_5(vertexAttrib4f, VertexAttrib4f,
+ unsigned long, float, float, float, float)
+
+DELEGATE_TO_GL_2(vertexAttrib4fv, VertexAttrib4fv, unsigned long, const float*)
+
+void WebGraphicsContext3DCommandBufferImpl::vertexAttribPointer(
+ unsigned long indx, int size, int type, bool normalized,
+ unsigned long stride, unsigned long offset) {
+ makeContextCurrent();
+
+ glVertexAttribPointer(indx, size, type, normalized, stride,
+ reinterpret_cast<void*>(
+ static_cast<intptr_t>(offset)));
+}
+
+DELEGATE_TO_GL_4(viewport, Viewport, long, long, unsigned long, unsigned long)
+
+unsigned WebGraphicsContext3DCommandBufferImpl::createBuffer() {
+ makeContextCurrent();
+ GLuint o;
+ glGenBuffers(1, &o);
+ return o;
+}
+
+unsigned WebGraphicsContext3DCommandBufferImpl::createFramebuffer() {
+ makeContextCurrent();
+ GLuint o = 0;
+ glGenFramebuffers(1, &o);
+ return o;
+}
+
+unsigned WebGraphicsContext3DCommandBufferImpl::createProgram() {
+ makeContextCurrent();
+ return glCreateProgram();
+}
+
+unsigned WebGraphicsContext3DCommandBufferImpl::createRenderbuffer() {
+ makeContextCurrent();
+ GLuint o;
+ glGenRenderbuffers(1, &o);
+ return o;
+}
+
+DELEGATE_TO_GL_1R(createShader, CreateShader, unsigned long, unsigned);
+
+unsigned WebGraphicsContext3DCommandBufferImpl::createTexture() {
+ makeContextCurrent();
+ GLuint o;
+ glGenTextures(1, &o);
+ return o;
+}
+
+void WebGraphicsContext3DCommandBufferImpl::deleteBuffer(unsigned buffer) {
+ makeContextCurrent();
+ glDeleteBuffers(1, &buffer);
+}
+
+void WebGraphicsContext3DCommandBufferImpl::deleteFramebuffer(
+ unsigned framebuffer) {
+ makeContextCurrent();
+ glDeleteFramebuffers(1, &framebuffer);
+}
+
+void WebGraphicsContext3DCommandBufferImpl::deleteProgram(unsigned program) {
+ makeContextCurrent();
+ glDeleteProgram(program);
+}
+
+void WebGraphicsContext3DCommandBufferImpl::deleteRenderbuffer(
+ unsigned renderbuffer) {
+ makeContextCurrent();
+ glDeleteRenderbuffers(1, &renderbuffer);
+}
+
+void WebGraphicsContext3DCommandBufferImpl::deleteShader(unsigned shader) {
+ makeContextCurrent();
+ glDeleteShader(shader);
+}
+
+void WebGraphicsContext3DCommandBufferImpl::deleteTexture(unsigned texture) {
+ makeContextCurrent();
+ glDeleteTextures(1, &texture);
+}
+
+#endif // defined(ENABLE_GPU)
+
diff --git a/chrome/renderer/webgraphicscontext3d_command_buffer_impl.h b/chrome/renderer/webgraphicscontext3d_command_buffer_impl.h
new file mode 100644
index 0000000..096e465
--- /dev/null
+++ b/chrome/renderer/webgraphicscontext3d_command_buffer_impl.h
@@ -0,0 +1,352 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_RENDERER_WEBGRAPHICSCONTEXT3D_COMMAND_BUFFER_IMPL_H_
+#define CHROME_RENDERER_WEBGRAPHICSCONTEXT3D_COMMAND_BUFFER_IMPL_H_
+
+#if defined(ENABLE_GPU)
+
+#include <vector>
+
+#include "base/scoped_ptr.h"
+#include "chrome/renderer/ggl/ggl.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebGraphicsContext3D.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
+
+#if !defined(OS_MACOSX)
+#define FLIP_FRAMEBUFFER_VERTICALLY
+#endif
+
+class GpuChannelHost;
+class CommandBufferProxy;
+
+namespace gpu {
+namespace gles2 {
+class GLES2Implementation;
+}
+}
+
+using WebKit::WebGLId;
+
+class WebGraphicsContext3DCommandBufferImpl
+ : public WebKit::WebGraphicsContext3D {
+ public:
+
+ WebGraphicsContext3DCommandBufferImpl();
+ virtual ~WebGraphicsContext3DCommandBufferImpl();
+
+ //----------------------------------------------------------------------
+ // WebGraphicsContext3D methods
+ virtual bool initialize(WebGraphicsContext3D::Attributes attributes);
+ virtual bool makeContextCurrent();
+
+ virtual int width();
+ virtual int height();
+
+ virtual int sizeInBytes(int type);
+
+ virtual void reshape(int width, int height);
+
+ virtual bool readBackFramebuffer(unsigned char* pixels, size_t buffer_size);
+
+ virtual void activeTexture(unsigned long texture);
+ virtual void attachShader(WebGLId program, WebGLId shader);
+ virtual void bindAttribLocation(WebGLId program, unsigned long index,
+ const char* name);
+ virtual void bindBuffer(unsigned long target, WebGLId buffer);
+ virtual void bindFramebuffer(unsigned long target, WebGLId framebuffer);
+ virtual void bindRenderbuffer(unsigned long target, WebGLId renderbuffer);
+ virtual void bindTexture(unsigned long target, WebGLId texture);
+ virtual void blendColor(double red, double green,
+ double blue, double alpha);
+ virtual void blendEquation(unsigned long mode);
+ virtual void blendEquationSeparate(unsigned long modeRGB,
+ unsigned long modeAlpha);
+ virtual void blendFunc(unsigned long sfactor, unsigned long dfactor);
+ virtual void blendFuncSeparate(unsigned long srcRGB,
+ unsigned long dstRGB,
+ unsigned long srcAlpha,
+ unsigned long dstAlpha);
+
+ virtual void bufferData(unsigned long target, int size,
+ const void* data, unsigned long usage);
+ virtual void bufferSubData(unsigned long target, long offset,
+ int size, const void* data);
+
+ virtual unsigned long checkFramebufferStatus(unsigned long target);
+ virtual void clear(unsigned long mask);
+ virtual void clearColor(double red, double green,
+ double blue, double alpha);
+ virtual void clearDepth(double depth);
+ virtual void clearStencil(long s);
+ virtual void colorMask(bool red, bool green, bool blue, bool alpha);
+ virtual void compileShader(WebGLId shader);
+
+ virtual void copyTexImage2D(unsigned long target,
+ long level,
+ unsigned long internalformat,
+ long x,
+ long y,
+ unsigned long width,
+ unsigned long height,
+ long border);
+ virtual void copyTexSubImage2D(unsigned long target,
+ long level,
+ long xoffset,
+ long yoffset,
+ long x,
+ long y,
+ unsigned long width,
+ unsigned long height);
+ virtual void cullFace(unsigned long mode);
+ virtual void depthFunc(unsigned long func);
+ virtual void depthMask(bool flag);
+ virtual void depthRange(double zNear, double zFar);
+ virtual void detachShader(WebGLId program, WebGLId shader);
+ virtual void disable(unsigned long cap);
+ virtual void disableVertexAttribArray(unsigned long index);
+ virtual void drawArrays(unsigned long mode, long first, long count);
+ virtual void drawElements(unsigned long mode,
+ unsigned long count,
+ unsigned long type,
+ long offset);
+
+ virtual void enable(unsigned long cap);
+ virtual void enableVertexAttribArray(unsigned long index);
+ virtual void finish();
+ virtual void flush();
+ virtual void framebufferRenderbuffer(unsigned long target,
+ unsigned long attachment,
+ unsigned long renderbuffertarget,
+ WebGLId renderbuffer);
+ virtual void framebufferTexture2D(unsigned long target,
+ unsigned long attachment,
+ unsigned long textarget,
+ WebGLId texture,
+ long level);
+ virtual void frontFace(unsigned long mode);
+ virtual void generateMipmap(unsigned long target);
+
+ virtual bool getActiveAttrib(WebGLId program,
+ unsigned long index,
+ ActiveInfo&);
+ virtual bool getActiveUniform(WebGLId program,
+ unsigned long index,
+ ActiveInfo&);
+
+ virtual int getAttribLocation(WebGLId program, const char* name);
+
+ virtual void getBooleanv(unsigned long pname, unsigned char* value);
+
+ virtual void getBufferParameteriv(unsigned long target,
+ unsigned long pname,
+ int* value);
+
+ virtual Attributes getContextAttributes();
+
+ virtual unsigned long getError();
+
+ virtual void getFloatv(unsigned long pname, float* value);
+
+ virtual void getFramebufferAttachmentParameteriv(unsigned long target,
+ unsigned long attachment,
+ unsigned long pname,
+ int* value);
+
+ virtual void getIntegerv(unsigned long pname, int* value);
+
+ virtual void getProgramiv(WebGLId program, unsigned long pname, int* value);
+
+ virtual WebKit::WebString getProgramInfoLog(WebGLId program);
+
+ virtual void getRenderbufferParameteriv(unsigned long target,
+ unsigned long pname,
+ int* value);
+
+ virtual void getShaderiv(WebGLId shader, unsigned long pname, int* value);
+
+ virtual WebKit::WebString getShaderInfoLog(WebGLId shader);
+
+ // TBD
+ // void glGetShaderPrecisionFormat (GLenum shadertype,
+ // GLenum precisiontype,
+ // GLint* range,
+ // GLint* precision);
+
+ virtual WebKit::WebString getShaderSource(WebGLId shader);
+ virtual WebKit::WebString getString(unsigned long name);
+
+ virtual void getTexParameterfv(unsigned long target,
+ unsigned long pname,
+ float* value);
+ virtual void getTexParameteriv(unsigned long target,
+ unsigned long pname,
+ int* value);
+
+ virtual void getUniformfv(WebGLId program, long location, float* value);
+ virtual void getUniformiv(WebGLId program, long location, int* value);
+
+ virtual long getUniformLocation(WebGLId program, const char* name);
+
+ virtual void getVertexAttribfv(unsigned long index, unsigned long pname,
+ float* value);
+ virtual void getVertexAttribiv(unsigned long index, unsigned long pname,
+ int* value);
+
+ virtual long getVertexAttribOffset(unsigned long index, unsigned long pname);
+
+ virtual void hint(unsigned long target, unsigned long mode);
+ virtual bool isBuffer(WebGLId buffer);
+ virtual bool isEnabled(unsigned long cap);
+ virtual bool isFramebuffer(WebGLId framebuffer);
+ virtual bool isProgram(WebGLId program);
+ virtual bool isRenderbuffer(WebGLId renderbuffer);
+ virtual bool isShader(WebGLId shader);
+ virtual bool isTexture(WebGLId texture);
+ virtual void lineWidth(double);
+ virtual void linkProgram(WebGLId program);
+ virtual void pixelStorei(unsigned long pname, long param);
+ virtual void polygonOffset(double factor, double units);
+
+ virtual void readPixels(long x,
+ long y,
+ unsigned long width,
+ unsigned long height,
+ unsigned long format,
+ unsigned long type,
+ void* pixels);
+
+ virtual void releaseShaderCompiler();
+ virtual void renderbufferStorage(unsigned long target,
+ unsigned long internalformat,
+ unsigned long width,
+ unsigned long height);
+ virtual void sampleCoverage(double value, bool invert);
+ virtual void scissor(long x, long y,
+ unsigned long width, unsigned long height);
+ virtual void shaderSource(WebGLId shader, const char* string);
+ virtual void stencilFunc(unsigned long func, long ref, unsigned long mask);
+ virtual void stencilFuncSeparate(unsigned long face,
+ unsigned long func,
+ long ref,
+ unsigned long mask);
+ virtual void stencilMask(unsigned long mask);
+ virtual void stencilMaskSeparate(unsigned long face, unsigned long mask);
+ virtual void stencilOp(unsigned long fail,
+ unsigned long zfail,
+ unsigned long zpass);
+ virtual void stencilOpSeparate(unsigned long face,
+ unsigned long fail,
+ unsigned long zfail,
+ unsigned long zpass);
+
+ virtual void texImage2D(unsigned target,
+ unsigned level,
+ unsigned internalformat,
+ unsigned width,
+ unsigned height,
+ unsigned border,
+ unsigned format,
+ unsigned type,
+ const void* pixels);
+
+ virtual void texParameterf(unsigned target, unsigned pname, float param);
+ virtual void texParameteri(unsigned target, unsigned pname, int param);
+
+ virtual void texSubImage2D(unsigned target,
+ unsigned level,
+ unsigned xoffset,
+ unsigned yoffset,
+ unsigned width,
+ unsigned height,
+ unsigned format,
+ unsigned type,
+ const void* pixels);
+
+ virtual void uniform1f(long location, float x);
+ virtual void uniform1fv(long location, int count, float* v);
+ virtual void uniform1i(long location, int x);
+ virtual void uniform1iv(long location, int count, int* v);
+ virtual void uniform2f(long location, float x, float y);
+ virtual void uniform2fv(long location, int count, float* v);
+ virtual void uniform2i(long location, int x, int y);
+ virtual void uniform2iv(long location, int count, int* v);
+ virtual void uniform3f(long location, float x, float y, float z);
+ virtual void uniform3fv(long location, int count, float* v);
+ virtual void uniform3i(long location, int x, int y, int z);
+ virtual void uniform3iv(long location, int count, int* v);
+ virtual void uniform4f(long location, float x, float y, float z, float w);
+ virtual void uniform4fv(long location, int count, float* v);
+ virtual void uniform4i(long location, int x, int y, int z, int w);
+ virtual void uniform4iv(long location, int count, int* v);
+ virtual void uniformMatrix2fv(long location, int count, bool transpose,
+ const float* value);
+ virtual void uniformMatrix3fv(long location, int count, bool transpose,
+ const float* value);
+ virtual void uniformMatrix4fv(long location, int count, bool transpose,
+ const float* value);
+
+ virtual void useProgram(WebGLId program);
+ virtual void validateProgram(WebGLId program);
+
+ virtual void vertexAttrib1f(unsigned long indx, float x);
+ virtual void vertexAttrib1fv(unsigned long indx, const float* values);
+ virtual void vertexAttrib2f(unsigned long indx, float x, float y);
+ virtual void vertexAttrib2fv(unsigned long indx, const float* values);
+ virtual void vertexAttrib3f(unsigned long indx, float x, float y, float z);
+ virtual void vertexAttrib3fv(unsigned long indx, const float* values);
+ virtual void vertexAttrib4f(unsigned long indx,
+ float x, float y, float z, float w);
+ virtual void vertexAttrib4fv(unsigned long indx, const float* values);
+ virtual void vertexAttribPointer(unsigned long indx, int size, int type,
+ bool normalized, unsigned long stride,
+ unsigned long offset);
+
+ virtual void viewport(long x, long y,
+ unsigned long width, unsigned long height);
+
+ // Support for buffer creation and deletion
+ virtual unsigned createBuffer();
+ virtual unsigned createFramebuffer();
+ virtual unsigned createProgram();
+ virtual unsigned createRenderbuffer();
+ virtual unsigned createShader(unsigned long);
+ virtual unsigned createTexture();
+
+ virtual void deleteBuffer(unsigned);
+ virtual void deleteFramebuffer(unsigned);
+ virtual void deleteProgram(unsigned);
+ virtual void deleteRenderbuffer(unsigned);
+ virtual void deleteShader(unsigned);
+ virtual void deleteTexture(unsigned);
+
+ virtual void synthesizeGLError(unsigned long error);
+
+ private:
+ // The GGL context we use for OpenGL rendering.
+ ggl::Context* context_;
+
+ WebKit::WebGraphicsContext3D::Attributes attributes_;
+ unsigned int texture_;
+ unsigned int fbo_;
+ unsigned int depth_buffer_;
+ int cached_width_, cached_height_;
+
+ // For tracking which FBO is bound.
+ unsigned int bound_fbo_;
+
+ // Errors raised by synthesizeGLError().
+ std::vector<unsigned long> synthetic_errors_;
+
+#ifdef FLIP_FRAMEBUFFER_VERTICALLY
+ scoped_ptr<uint8> scanline_;
+ void FlipVertically(uint8* framebuffer,
+ unsigned int width,
+ unsigned int height);
+#endif
+};
+
+#endif // defined(ENABLE_GPU)
+#endif // CHROME_RENDERER_WEBGRAPHICSCONTEXT3D_COMMAND_BUFFER_IMPL_H_
+
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 92b1312..3bfc42b 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -879,6 +879,8 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
HGLRC gl_context_;
HPBUFFERARB pbuffer_;
#elif defined(OS_MACOSX)
+ CGLContextObj gl_context_;
+ CGLPBufferObj pbuffer_;
AcceleratedSurface surface_;
#endif
@@ -1157,6 +1159,9 @@ GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
gl_device_context_(NULL),
gl_context_(NULL),
pbuffer_(NULL),
+#elif defined(OS_MAC)
+ gl_context_(NULL),
+ pbuffer_(NULL),
#endif
anti_aliased_(false) {
}
@@ -1537,9 +1542,20 @@ bool GLES2DecoderImpl::MakeCurrent() {
}
return true;
#elif defined(OS_LINUX)
+ // TODO(apatrick): offscreen rendering not yet supported on this platform.
return window()->MakeCurrent();
#elif defined(OS_MACOSX)
- return surface_.MakeCurrent();
+ if (gl_context_) {
+ if (CGLGetCurrentContext() != gl_context_) {
+ if (CGLSetCurrentContext(gl_context_) != kCGLNoError) {
+ DLOG(ERROR) << "Unable to make gl context current.";
+ return false;
+ }
+ }
+ return true;
+ } else {
+ return surface_.MakeCurrent();
+ }
#else
NOTREACHED();
return false;
@@ -1666,13 +1682,50 @@ bool GLES2DecoderImpl::InitPlatformSpecific() {
if (!window()->Initialize())
return false;
#elif defined(OS_MACOSX)
- // TODO(apatrick): offscreen rendering not yet supported on this platform.
- DCHECK(!offscreen);
-
// TODO(apatrick): parent contexts not yet supported on this platform.
DCHECK(!parent_);
- return surface_.Initialize();
+ if (offscreen) {
+ // Create a 1x1 pbuffer and associated context to bootstrap things
+ static const CGLPixelFormatAttribute attribs[] = {
+ (CGLPixelFormatAttribute) kCGLPFAPBuffer,
+ (CGLPixelFormatAttribute) 0
+ };
+ CGLPixelFormatObj pixel_format;
+ GLint num_pixel_formats;
+ if (CGLChoosePixelFormat(attribs,
+ &pixel_format,
+ &num_pixel_formats) != kCGLNoError) {
+ DLOG(ERROR) << "Error choosing pixel format.";
+ DestroyPlatformSpecific();
+ return false;
+ }
+ if (!pixel_format) {
+ return false;
+ }
+ CGLError res = CGLCreateContext(pixel_format, 0, &gl_context_);
+ CGLDestroyPixelFormat(pixel_format);
+ if (res != kCGLNoError) {
+ DLOG(ERROR) << "Error creating context.";
+ DestroyPlatformSpecific();
+ return false;
+ }
+ if (CGLCreatePBuffer(1, 1,
+ GL_TEXTURE_2D, GL_RGBA,
+ 0, &pbuffer_) != kCGLNoError) {
+ DLOG(ERROR) << "Error creating pbuffer.";
+ DestroyPlatformSpecific();
+ return false;
+ }
+ if (CGLSetPBuffer(gl_context_, pbuffer_, 0, 0, 0) != kCGLNoError) {
+ DLOG(ERROR) << "Error attaching pbuffer to context.";
+ DestroyPlatformSpecific();
+ return false;
+ }
+ return true;
+ } else {
+ return surface_.Initialize();
+ }
#endif
return true;
@@ -1755,6 +1808,16 @@ void GLES2DecoderImpl::DestroyPlatformSpecific() {
::wglDestroyPbufferARB(pbuffer_);
pbuffer_ = NULL;
}
+#elif defined(OS_MAC)
+ if (gl_context_) {
+ CGLDestroyContext(gl_context_);
+ gl_context_ = NULL;
+ }
+
+ if (pbuffer_) {
+ CGLDestroyPBuffer(pbuffer_);
+ pbuffer_ = NULL;
+ }
#endif
}
diff --git a/webkit/tools/test_shell/test_shell_webkit_init.h b/webkit/tools/test_shell/test_shell_webkit_init.h
index 65ada15..1da9f7d 100644
--- a/webkit/tools/test_shell/test_shell_webkit_init.h
+++ b/webkit/tools/test_shell/test_shell_webkit_init.h
@@ -13,6 +13,7 @@
#include "media/base/media.h"
#include "third_party/WebKit/WebKit/chromium/public/WebData.h"
#include "third_party/WebKit/WebKit/chromium/public/WebDatabase.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebGraphicsContext3D.h"
#include "third_party/WebKit/WebKit/chromium/public/WebRuntimeFeatures.h"
#include "third_party/WebKit/WebKit/chromium/public/WebKit.h"
#include "third_party/WebKit/WebKit/chromium/public/WebScriptController.h"
@@ -233,6 +234,10 @@ class TestShellWebKitInit : public webkit_glue::WebKitClientImpl {
return NULL;
}
+ virtual WebKit::WebGraphicsContext3D* createGraphicsContext3D() {
+ return WebKit::WebGraphicsContext3D::createDefault();
+ }
+
private:
TestShellWebMimeRegistryImpl mime_registry_;
MockWebClipboardImpl mock_clipboard_;