summaryrefslogtreecommitdiffstats
path: root/webkit/gpu
diff options
context:
space:
mode:
authorkbr@google.com <kbr@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-01-11 19:50:40 +0000
committerkbr@google.com <kbr@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-01-11 19:50:40 +0000
commit49861ff21dace659d3da493b38551a07a611f4f4 (patch)
treec9d54f54ac8e3808a47730b9bc42b53d24c16e66 /webkit/gpu
parent80091c77e972d9797359388abf3baf2c46326716 (diff)
downloadchromium_src-49861ff21dace659d3da493b38551a07a611f4f4.zip
chromium_src-49861ff21dace659d3da493b38551a07a611f4f4.tar.gz
chromium_src-49861ff21dace659d3da493b38551a07a611f4f4.tar.bz2
Move the in-process WebGL implementation from the WebKit to the
Chromium repository to break circular dependencies on Chromium's OpenGL bindings in app/gfx/gl. The minimal changes to the code were made in order to break dependencies on WebCore types and to make the code fit the Google C++ style guide as closely as possible. There are many references to undesirable types like "long" in the WebGraphicsContext3D interface, which are the source of the majority of lint errors and which will be fixed in follow-on work. The upstream WebGraphicsContext3DDefaultImpl will be deleted after this lands. Tested: - Various WebGL demos in Chrome - Built and ran WebGL layout tests in DRT BUG=none TEST=none (see above) Review URL: http://codereview.chromium.org/6100009 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@71069 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/gpu')
-rw-r--r--webkit/gpu/webgraphicscontext3d_in_process_impl.cc1654
-rw-r--r--webkit/gpu/webgraphicscontext3d_in_process_impl.h471
-rw-r--r--webkit/gpu/webkit_gpu.gypi30
3 files changed, 2155 insertions, 0 deletions
diff --git a/webkit/gpu/webgraphicscontext3d_in_process_impl.cc b/webkit/gpu/webgraphicscontext3d_in_process_impl.cc
new file mode 100644
index 0000000..1a91ff1
--- /dev/null
+++ b/webkit/gpu/webgraphicscontext3d_in_process_impl.cc
@@ -0,0 +1,1654 @@
+// 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.
+
+#include "webkit/gpu/webgraphicscontext3d_in_process_impl.h"
+
+#include <string.h>
+
+#include <algorithm>
+#include <string>
+
+#include "app/gfx/gl/gl_bindings.h"
+#include "app/gfx/gl/gl_context.h"
+#include "app/gfx/gl/gl_implementation.h"
+#include "base/logging.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebView.h"
+
+using WebKit::WebGLId;
+using WebKit::WebGraphicsContext3D;
+using WebKit::WebString;
+using WebKit::WebView;
+
+namespace webkit_gpu {
+
+enum {
+ MAX_VERTEX_UNIFORM_VECTORS = 0x8DFB,
+ MAX_VARYING_VECTORS = 0x8DFC,
+ MAX_FRAGMENT_UNIFORM_VECTORS = 0x8DFD
+};
+
+WebGraphicsContext3DInProcessImpl::
+ VertexAttribPointerState::VertexAttribPointerState()
+ : enabled(false),
+ buffer(0),
+ indx(0),
+ size(0),
+ type(0),
+ normalized(false),
+ stride(0),
+ offset(0) {
+}
+
+WebGraphicsContext3DInProcessImpl::WebGraphicsContext3DInProcessImpl()
+ : initialized_(false),
+ render_directly_to_web_view_(false),
+ is_gles2_(false),
+ have_ext_framebuffer_object_(false),
+ have_ext_framebuffer_multisample_(false),
+ have_angle_framebuffer_multisample_(false),
+ texture_(0),
+ fbo_(0),
+ depth_stencil_buffer_(0),
+ cached_width_(0),
+ cached_height_(0),
+ multisample_fbo_(0),
+ multisample_depth_stencil_buffer_(0),
+ multisample_color_buffer_(0),
+ bound_fbo_(0),
+ bound_texture_(0),
+ copy_texture_to_parent_texture_fbo_(0),
+ bound_array_buffer_(0),
+#ifdef FLIP_FRAMEBUFFER_VERTICALLY
+ scanline_(0),
+#endif
+ fragment_compiler_(0),
+ vertex_compiler_(0) {
+}
+
+WebGraphicsContext3DInProcessImpl::~WebGraphicsContext3DInProcessImpl() {
+ if (!initialized_)
+ return;
+
+ makeContextCurrent();
+
+ if (attributes_.antialias) {
+ glDeleteRenderbuffersEXT(1, &multisample_color_buffer_);
+ if (attributes_.depth || attributes_.stencil)
+ glDeleteRenderbuffersEXT(1, &multisample_depth_stencil_buffer_);
+ glDeleteFramebuffersEXT(1, &multisample_fbo_);
+ } else {
+ if (attributes_.depth || attributes_.stencil)
+ glDeleteRenderbuffersEXT(1, &depth_stencil_buffer_);
+ }
+ glDeleteTextures(1, &texture_);
+ glDeleteFramebuffersEXT(1, &copy_texture_to_parent_texture_fbo_);
+#ifdef FLIP_FRAMEBUFFER_VERTICALLY
+ if (scanline_)
+ delete[] scanline_;
+#endif
+ glDeleteFramebuffersEXT(1, &fbo_);
+
+ gl_context_->Destroy();
+
+ for (ShaderSourceMap::iterator ii = shader_source_map_.begin();
+ ii != shader_source_map_.end(); ++ii) {
+ if (ii->second)
+ delete ii->second;
+ }
+ AngleDestroyCompilers();
+}
+
+bool WebGraphicsContext3DInProcessImpl::initialize(
+ WebGraphicsContext3D::Attributes attributes,
+ WebView* webView,
+ bool render_directly_to_web_view) {
+ if (!gfx::GLContext::InitializeOneOff())
+ return false;
+
+ render_directly_to_web_view_ = render_directly_to_web_view;
+ gfx::GLContext* share_context = 0;
+
+ if (!render_directly_to_web_view) {
+ // Pick up the compositor's context to share resources with.
+ WebGraphicsContext3D* view_context = webView->graphicsContext3D();
+ if (view_context) {
+ WebGraphicsContext3DInProcessImpl* contextImpl =
+ static_cast<WebGraphicsContext3DInProcessImpl*>(view_context);
+ share_context = contextImpl->gl_context_.get();
+ } else {
+ // The compositor's context didn't get created
+ // successfully, so conceptually there is no way we can
+ // render successfully to the WebView.
+ render_directly_to_web_view_ = false;
+ }
+ }
+
+ // This implementation always renders offscreen regardless of
+ // whether render_directly_to_web_view is true. Both DumpRenderTree
+ // and test_shell paint first to an intermediate offscreen buffer
+ // and from there to the window, and WebViewImpl::paint already
+ // correctly handles the case where the compositor is active but
+ // the output needs to go to a WebCanvas.
+ gl_context_.reset(gfx::GLContext::CreateOffscreenGLContext(share_context));
+ if (!gl_context_.get())
+ return false;
+
+ attributes_ = attributes;
+
+ // FIXME: for the moment we disable multisampling for the compositor.
+ // It actually works in this implementation, but there are a few
+ // considerations. First, we likely want to reduce the fuzziness in
+ // these tests as much as possible because we want to run pixel tests.
+ // Second, Mesa's multisampling doesn't seem to antialias straight
+ // edges in some CSS 3D samples. Third, we don't have multisampling
+ // support for the compositor in the normal case at the time of this
+ // writing.
+ if (render_directly_to_web_view)
+ attributes_.antialias = false;
+
+ is_gles2_ = gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2;
+ const char* extensions =
+ reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS));
+ have_ext_framebuffer_object_ =
+ strstr(extensions, "GL_EXT_framebuffer_object") != NULL;
+ have_ext_framebuffer_multisample_ =
+ strstr(extensions, "GL_EXT_framebuffer_multisample") != NULL;
+ have_angle_framebuffer_multisample_ =
+ strstr(extensions, "GL_ANGLE_framebuffer_multisample") != NULL;
+
+ ValidateAttributes();
+
+ if (!is_gles2_) {
+ glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
+ glEnable(GL_POINT_SPRITE);
+ }
+
+ if (!AngleCreateCompilers()) {
+ AngleDestroyCompilers();
+ return false;
+ }
+
+ glGenFramebuffersEXT(1, &copy_texture_to_parent_texture_fbo_);
+
+ initialized_ = true;
+ return true;
+}
+
+void WebGraphicsContext3DInProcessImpl::ValidateAttributes() {
+ const char* extensions =
+ reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS));
+
+ if (attributes_.stencil) {
+ if (strstr(extensions, "GL_OES_packed_depth_stencil") ||
+ strstr(extensions, "GL_EXT_packed_depth_stencil")) {
+ if (!attributes_.depth) {
+ attributes_.depth = true;
+ }
+ } else {
+ attributes_.stencil = false;
+ }
+ }
+ if (attributes_.antialias) {
+ bool isValidVendor = true;
+#if defined(OS_MACOSX)
+ // Currently in Mac we only turn on antialias if vendor is NVIDIA.
+ const char* vendor = reinterpret_cast<const char*>(glGetString(GL_VENDOR));
+ if (!strstr(vendor, "NVIDIA"))
+ isValidVendor = false;
+#endif
+ if (!(isValidVendor &&
+ (have_ext_framebuffer_multisample_ ||
+ (have_angle_framebuffer_multisample_ &&
+ strstr(extensions, "GL_OES_rgb8_rgba8")))))
+ attributes_.antialias = false;
+
+ // Don't antialias when using Mesa to ensure more reliable testing and
+ // because it doesn't appear to multisample straight lines correctly.
+ const char* renderer =
+ reinterpret_cast<const char*>(glGetString(GL_RENDERER));
+ if (!strncmp(renderer, "Mesa", 4)) {
+ attributes_.antialias = false;
+ }
+ }
+ // FIXME: instead of enforcing premultipliedAlpha = true, implement the
+ // correct behavior when premultipliedAlpha = false is requested.
+ attributes_.premultipliedAlpha = true;
+}
+
+void WebGraphicsContext3DInProcessImpl::ResolveMultisampledFramebuffer(
+ unsigned x, unsigned y, unsigned width, unsigned height) {
+ if (attributes_.antialias) {
+ glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, multisample_fbo_);
+ glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fbo_);
+ if (have_ext_framebuffer_multisample_) {
+ glBlitFramebufferEXT(x, y,
+ x + width, y + height,
+ x, y,
+ x + width, y + height,
+ GL_COLOR_BUFFER_BIT, GL_NEAREST);
+ } else {
+ DCHECK(have_angle_framebuffer_multisample_);
+ glBlitFramebufferANGLE(x, y,
+ x + width, y + height,
+ x, y,
+ x + width, y + height,
+ GL_COLOR_BUFFER_BIT, GL_NEAREST);
+ }
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, bound_fbo_);
+ }
+}
+
+bool WebGraphicsContext3DInProcessImpl::makeContextCurrent() {
+ return gl_context_->MakeCurrent();
+}
+
+int WebGraphicsContext3DInProcessImpl::width() {
+ return cached_width_;
+}
+
+int WebGraphicsContext3DInProcessImpl::height() {
+ return cached_height_;
+}
+
+int WebGraphicsContext3DInProcessImpl::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;
+}
+
+bool WebGraphicsContext3DInProcessImpl::isGLES2Compliant() {
+ return is_gles2_;
+}
+
+unsigned int WebGraphicsContext3DInProcessImpl::getPlatformTextureId() {
+ return texture_;
+}
+
+void WebGraphicsContext3DInProcessImpl::prepareTexture() {
+ if (!render_directly_to_web_view_) {
+ // We need to prepare our rendering results for the compositor.
+ makeContextCurrent();
+ ResolveMultisampledFramebuffer(0, 0, cached_width_, cached_height_);
+ }
+}
+
+namespace {
+
+int CreateTextureObject(GLenum target) {
+ GLuint texture = 0;
+ glGenTextures(1, &texture);
+ glBindTexture(target, texture);
+ glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ return texture;
+}
+
+} // anonymous namespace
+
+void WebGraphicsContext3DInProcessImpl::reshape(int width, int height) {
+ cached_width_ = width;
+ cached_height_ = height;
+ makeContextCurrent();
+
+ GLenum target = GL_TEXTURE_2D;
+
+ if (!texture_) {
+ // Generate the texture object
+ texture_ = CreateTextureObject(target);
+ // Generate the framebuffer object
+ glGenFramebuffersEXT(1, &fbo_);
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_);
+ bound_fbo_ = fbo_;
+ if (attributes_.depth || attributes_.stencil)
+ glGenRenderbuffersEXT(1, &depth_stencil_buffer_);
+ // Generate the multisample framebuffer object
+ if (attributes_.antialias) {
+ glGenFramebuffersEXT(1, &multisample_fbo_);
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, multisample_fbo_);
+ bound_fbo_ = multisample_fbo_;
+ glGenRenderbuffersEXT(1, &multisample_color_buffer_);
+ if (attributes_.depth || attributes_.stencil)
+ glGenRenderbuffersEXT(1, &multisample_depth_stencil_buffer_);
+ }
+ }
+
+ GLint internal_multisampled_color_format = 0;
+ GLint internal_color_format = 0;
+ GLint color_format = 0;
+ GLint internal_depth_stencil_format = 0;
+ if (attributes_.alpha) {
+ // GL_RGBA8_OES == GL_RGBA8
+ internal_multisampled_color_format = GL_RGBA8;
+ internal_color_format = is_gles2_ ? GL_RGBA : GL_RGBA8;
+ color_format = GL_RGBA;
+ } else {
+ // GL_RGB8_OES == GL_RGB8
+ internal_multisampled_color_format = GL_RGB8;
+ internal_color_format = is_gles2_ ? GL_RGB : GL_RGB8;
+ color_format = GL_RGB;
+ }
+ if (attributes_.stencil || attributes_.depth) {
+ // We don't allow the logic where stencil is required and depth is not.
+ // See GraphicsContext3DInternal constructor.
+ if (attributes_.stencil && attributes_.depth) {
+ internal_depth_stencil_format = GL_DEPTH24_STENCIL8_EXT;
+ } else {
+ if (is_gles2_)
+ internal_depth_stencil_format = GL_DEPTH_COMPONENT16;
+ else
+ internal_depth_stencil_format = GL_DEPTH_COMPONENT;
+ }
+ }
+
+ bool must_restore_fbo = false;
+
+ // Resize multisampling FBO
+ if (attributes_.antialias) {
+ GLint max_sample_count;
+ glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
+ GLint sample_count = std::min(8, max_sample_count);
+ if (bound_fbo_ != multisample_fbo_) {
+ must_restore_fbo = true;
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, multisample_fbo_);
+ }
+ glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, multisample_color_buffer_);
+ if (have_ext_framebuffer_multisample_) {
+ glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT,
+ sample_count,
+ internal_multisampled_color_format,
+ width,
+ height);
+ } else {
+ DCHECK(have_angle_framebuffer_multisample_);
+ glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER_EXT,
+ sample_count,
+ internal_multisampled_color_format,
+ width,
+ height);
+ }
+ glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
+ GL_COLOR_ATTACHMENT0_EXT,
+ GL_RENDERBUFFER_EXT,
+ multisample_color_buffer_);
+ if (attributes_.stencil || attributes_.depth) {
+ glBindRenderbufferEXT(GL_RENDERBUFFER_EXT,
+ multisample_depth_stencil_buffer_);
+ if (have_ext_framebuffer_multisample_) {
+ glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT,
+ sample_count,
+ internal_depth_stencil_format,
+ width,
+ height);
+ } else {
+ DCHECK(have_angle_framebuffer_multisample_);
+ glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER_EXT,
+ sample_count,
+ internal_depth_stencil_format,
+ width,
+ height);
+ }
+ if (attributes_.stencil)
+ glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
+ GL_STENCIL_ATTACHMENT_EXT,
+ GL_RENDERBUFFER_EXT,
+ multisample_depth_stencil_buffer_);
+ if (attributes_.depth)
+ glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
+ GL_DEPTH_ATTACHMENT_EXT,
+ GL_RENDERBUFFER_EXT,
+ multisample_depth_stencil_buffer_);
+ }
+ glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
+ GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
+ if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ LOG(ERROR) << "Multisampling framebuffer was incomplete";
+
+ // FIXME: cleanup.
+ NOTIMPLEMENTED();
+ }
+ }
+
+ // Resize regular FBO
+ if (bound_fbo_ != fbo_) {
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_);
+ must_restore_fbo = true;
+ }
+ glBindTexture(target, texture_);
+ glTexImage2D(target, 0, internal_color_format,
+ width, height,
+ 0, color_format, GL_UNSIGNED_BYTE, 0);
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
+ GL_COLOR_ATTACHMENT0_EXT,
+ target,
+ texture_,
+ 0);
+ glBindTexture(target, 0);
+ if (!attributes_.antialias && (attributes_.stencil || attributes_.depth)) {
+ glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depth_stencil_buffer_);
+ glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,
+ internal_depth_stencil_format,
+ width, height);
+ if (attributes_.stencil)
+ glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
+ GL_STENCIL_ATTACHMENT_EXT,
+ GL_RENDERBUFFER_EXT,
+ depth_stencil_buffer_);
+ if (attributes_.depth)
+ glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
+ GL_DEPTH_ATTACHMENT_EXT,
+ GL_RENDERBUFFER_EXT,
+ depth_stencil_buffer_);
+ glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
+ }
+ GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
+ if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ LOG(ERROR) << "Framebuffer was incomplete";
+
+ // FIXME: cleanup.
+ NOTIMPLEMENTED();
+ }
+
+ if (attributes_.antialias) {
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, multisample_fbo_);
+ if (bound_fbo_ == multisample_fbo_)
+ must_restore_fbo = false;
+ }
+
+ // Initialize renderbuffers to 0.
+ GLfloat clearColor[] = {0, 0, 0, 0}, clearDepth = 0;
+ GLint clearStencil = 0;
+ GLboolean colorMask[] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE};
+ GLboolean depthMask = GL_TRUE;
+ GLuint stencilMask = 0xffffffff;
+ GLboolean isScissorEnabled = GL_FALSE;
+ GLboolean isDitherEnabled = GL_FALSE;
+ GLbitfield clearMask = GL_COLOR_BUFFER_BIT;
+ glGetFloatv(GL_COLOR_CLEAR_VALUE, clearColor);
+ glClearColor(0, 0, 0, 0);
+ glGetBooleanv(GL_COLOR_WRITEMASK, colorMask);
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ if (attributes_.depth) {
+ glGetFloatv(GL_DEPTH_CLEAR_VALUE, &clearDepth);
+ glClearDepth(1);
+ glGetBooleanv(GL_DEPTH_WRITEMASK, &depthMask);
+ glDepthMask(GL_TRUE);
+ clearMask |= GL_DEPTH_BUFFER_BIT;
+ }
+ if (attributes_.stencil) {
+ glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &clearStencil);
+ glClearStencil(0);
+ glGetIntegerv(GL_STENCIL_WRITEMASK,
+ reinterpret_cast<GLint*>(&stencilMask));
+ glStencilMaskSeparate(GL_FRONT, 0xffffffff);
+ clearMask |= GL_STENCIL_BUFFER_BIT;
+ }
+ isScissorEnabled = glIsEnabled(GL_SCISSOR_TEST);
+ glDisable(GL_SCISSOR_TEST);
+ isDitherEnabled = glIsEnabled(GL_DITHER);
+ glDisable(GL_DITHER);
+
+ glClear(clearMask);
+
+ glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
+ glColorMask(colorMask[0], colorMask[1], colorMask[2], colorMask[3]);
+ if (attributes_.depth) {
+ glClearDepth(clearDepth);
+ glDepthMask(depthMask);
+ }
+ if (attributes_.stencil) {
+ glClearStencil(clearStencil);
+ glStencilMaskSeparate(GL_FRONT, stencilMask);
+ }
+ if (isScissorEnabled)
+ glEnable(GL_SCISSOR_TEST);
+ else
+ glDisable(GL_SCISSOR_TEST);
+ if (isDitherEnabled)
+ glEnable(GL_DITHER);
+ else
+ glDisable(GL_DITHER);
+
+ if (must_restore_fbo)
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, bound_fbo_);
+
+#ifdef FLIP_FRAMEBUFFER_VERTICALLY
+ if (scanline_) {
+ delete[] scanline_;
+ scanline_ = 0;
+ }
+ scanline_ = new unsigned char[width * 4];
+#endif // FLIP_FRAMEBUFFER_VERTICALLY
+}
+
+#ifdef FLIP_FRAMEBUFFER_VERTICALLY
+void WebGraphicsContext3DInProcessImpl::FlipVertically(
+ unsigned char* framebuffer, unsigned int width, unsigned int height) {
+ unsigned char* scanline = scanline_;
+ if (!scanline)
+ return;
+ unsigned int row_bytes = width * 4;
+ unsigned int count = height / 2;
+ for (unsigned int i = 0; i < count; i++) {
+ unsigned char* row_a = framebuffer + i * row_bytes;
+ unsigned char* row_b = framebuffer + (height - i - 1) * row_bytes;
+ // FIXME: 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 WebGraphicsContext3DInProcessImpl::readBackFramebuffer(
+ unsigned char* pixels, size_t bufferSize) {
+ if (bufferSize != 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.
+
+ ResolveMultisampledFramebuffer(0, 0, cached_width_, cached_height_);
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_);
+
+ GLint pack_alignment = 4;
+ bool must_restore_pack_alignment = false;
+ glGetIntegerv(GL_PACK_ALIGNMENT, &pack_alignment);
+ if (pack_alignment > 4) {
+ glPixelStorei(GL_PACK_ALIGNMENT, 4);
+ must_restore_pack_alignment = true;
+ }
+
+ if (is_gles2_) {
+ // FIXME: consider testing for presence of GL_OES_read_format
+ // and GL_EXT_read_format_bgra, and using GL_BGRA_EXT here
+ // directly.
+ glReadPixels(0, 0, cached_width_, cached_height_,
+ GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+ for (size_t i = 0; i < bufferSize; i += 4) {
+ std::swap(pixels[i], pixels[i + 2]);
+ }
+ } else {
+ glReadPixels(0, 0, cached_width_, cached_height_,
+ GL_BGRA, GL_UNSIGNED_BYTE, pixels);
+ }
+
+ if (must_restore_pack_alignment)
+ glPixelStorei(GL_PACK_ALIGNMENT, pack_alignment);
+
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, bound_fbo_);
+
+#ifdef FLIP_FRAMEBUFFER_VERTICALLY
+ if (pixels)
+ FlipVertically(pixels, cached_width_, cached_height_);
+#endif
+
+ return true;
+}
+
+void WebGraphicsContext3DInProcessImpl::synthesizeGLError(unsigned long error) {
+ if (synthetic_errors_set_.find(error) == synthetic_errors_set_.end()) {
+ synthetic_errors_set_.insert(error);
+ synthetic_errors_list_.push_back(error);
+ }
+}
+
+void* WebGraphicsContext3DInProcessImpl::mapBufferSubDataCHROMIUM(
+ unsigned target, int offset, int size, unsigned access) {
+ return 0;
+}
+
+void WebGraphicsContext3DInProcessImpl::unmapBufferSubDataCHROMIUM(
+ const void* mem) {
+}
+
+void* WebGraphicsContext3DInProcessImpl::mapTexSubImage2DCHROMIUM(
+ unsigned target, int level, int xoffset, int yoffset,
+ int width, int height, unsigned format, unsigned type, unsigned access) {
+ return 0;
+}
+
+void WebGraphicsContext3DInProcessImpl::unmapTexSubImage2DCHROMIUM(
+ const void* mem) {
+}
+
+void WebGraphicsContext3DInProcessImpl::copyTextureToParentTextureCHROMIUM(
+ unsigned id, unsigned id2) {
+ if (!glGetTexLevelParameteriv)
+ return;
+
+ makeContextCurrent();
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, copy_texture_to_parent_texture_fbo_);
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
+ GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D,
+ id,
+ 0); // level
+ glBindTexture(GL_TEXTURE_2D, id2);
+ GLsizei width, height;
+ glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
+ glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height);
+ glCopyTexImage2D(GL_TEXTURE_2D,
+ 0, // level
+ GL_RGBA,
+ 0, 0, // x, y
+ width,
+ height,
+ 0); // border
+ glBindTexture(GL_TEXTURE_2D, bound_texture_);
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, bound_fbo_);
+}
+
+WebString WebGraphicsContext3DInProcessImpl::
+ getRequestableExtensionsCHROMIUM() {
+ return WebString();
+}
+
+void WebGraphicsContext3DInProcessImpl::requestExtensionCHROMIUM(const char*) {
+}
+
+// Helper macros to reduce the amount of code.
+
+#define DELEGATE_TO_GL(name, glname) \
+void WebGraphicsContext3DInProcessImpl::name() { \
+ makeContextCurrent(); \
+ gl##glname(); \
+}
+
+#define DELEGATE_TO_GL_1(name, glname, t1) \
+void WebGraphicsContext3DInProcessImpl::name(t1 a1) { \
+ makeContextCurrent(); \
+ gl##glname(a1); \
+}
+
+#define DELEGATE_TO_GL_1_C(name, glname, t1) \
+void WebGraphicsContext3DInProcessImpl::name(t1 a1) { \
+ makeContextCurrent(); \
+ gl##glname(static_cast<GLclampf>(a1)); \
+}
+
+#define DELEGATE_TO_GL_1R(name, glname, t1, rt) \
+rt WebGraphicsContext3DInProcessImpl::name(t1 a1) { \
+ makeContextCurrent(); \
+ return gl##glname(a1); \
+}
+
+#define DELEGATE_TO_GL_1RB(name, glname, t1, rt) \
+rt WebGraphicsContext3DInProcessImpl::name(t1 a1) { \
+ makeContextCurrent(); \
+ return gl##glname(a1) ? true : false; \
+}
+
+#define DELEGATE_TO_GL_2(name, glname, t1, t2) \
+void WebGraphicsContext3DInProcessImpl::name(t1 a1, t2 a2) { \
+ makeContextCurrent(); \
+ gl##glname(a1, a2); \
+}
+
+#define DELEGATE_TO_GL_2_C1(name, glname, t1, t2) \
+void WebGraphicsContext3DInProcessImpl::name(t1 a1, t2 a2) { \
+ makeContextCurrent(); \
+ gl##glname(static_cast<GLclampf>(a1), a2); \
+}
+
+#define DELEGATE_TO_GL_2_C12(name, glname, t1, t2) \
+void WebGraphicsContext3DInProcessImpl::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 WebGraphicsContext3DInProcessImpl::name(t1 a1, t2 a2) { \
+ makeContextCurrent(); \
+ return gl##glname(a1, a2); \
+}
+
+#define DELEGATE_TO_GL_3(name, glname, t1, t2, t3) \
+void WebGraphicsContext3DInProcessImpl::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 WebGraphicsContext3DInProcessImpl::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 WebGraphicsContext3DInProcessImpl::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 WebGraphicsContext3DInProcessImpl::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 WebGraphicsContext3DInProcessImpl::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 WebGraphicsContext3DInProcessImpl::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 WebGraphicsContext3DInProcessImpl::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 WebGraphicsContext3DInProcessImpl::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); \
+}
+
+void WebGraphicsContext3DInProcessImpl::activeTexture(unsigned long texture) {
+ // FIXME: query number of textures available.
+ if (texture < GL_TEXTURE0 || texture > GL_TEXTURE0+32)
+ // FIXME: raise exception.
+ return;
+
+ makeContextCurrent();
+ glActiveTexture(texture);
+}
+
+DELEGATE_TO_GL_2(attachShader, AttachShader, WebGLId, WebGLId)
+
+DELEGATE_TO_GL_3(bindAttribLocation, BindAttribLocation,
+ WebGLId, unsigned long, const char*)
+
+void WebGraphicsContext3DInProcessImpl::bindBuffer(
+ unsigned long target, WebGLId buffer) {
+ makeContextCurrent();
+ if (target == GL_ARRAY_BUFFER)
+ bound_array_buffer_ = buffer;
+ glBindBuffer(target, buffer);
+}
+
+void WebGraphicsContext3DInProcessImpl::bindFramebuffer(
+ unsigned long target, WebGLId framebuffer) {
+ makeContextCurrent();
+ if (!framebuffer)
+ framebuffer = (attributes_.antialias ? multisample_fbo_ : fbo_);
+ if (framebuffer != bound_fbo_) {
+ glBindFramebufferEXT(target, framebuffer);
+ bound_fbo_ = framebuffer;
+ }
+}
+
+DELEGATE_TO_GL_2(bindRenderbuffer, BindRenderbufferEXT, unsigned long, WebGLId)
+
+void WebGraphicsContext3DInProcessImpl::bindTexture(
+ unsigned long target, WebGLId texture) {
+ makeContextCurrent();
+ glBindTexture(target, texture);
+ bound_texture_ = texture;
+}
+
+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, CheckFramebufferStatusEXT,
+ 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(clearDepth, ClearDepth, double)
+
+DELEGATE_TO_GL_1(clearStencil, ClearStencil, long)
+
+DELEGATE_TO_GL_4(colorMask, ColorMask, bool, bool, bool, bool)
+
+void WebGraphicsContext3DInProcessImpl::compileShader(WebGLId shader) {
+ makeContextCurrent();
+
+ ShaderSourceMap::iterator result = shader_source_map_.find(shader);
+ if (result == shader_source_map_.end()) {
+ // Passing down to gl driver to generate the correct error; or the case
+ // where the shader deletion is delayed when it's attached to a program.
+ glCompileShader(shader);
+ return;
+ }
+ ShaderSourceEntry* entry = result->second;
+ DCHECK(entry);
+
+ if (!AngleValidateShaderSource(entry)) {
+ // Shader didn't validate; don't move forward with compiling
+ // translated source.
+ return;
+ }
+
+ const char* translated_source = entry->translated_source.get();
+ int shader_length = translated_source ? strlen(translated_source) : 0;
+ glShaderSource(
+ shader, 1, const_cast<const char**>(&translated_source), &shader_length);
+ glCompileShader(shader);
+
+#ifndef NDEBUG
+ int compileStatus;
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &compileStatus);
+ // DCHECK that ANGLE generated GLSL will be accepted by OpenGL
+ DCHECK(compileStatus == GL_TRUE);
+#endif
+}
+
+void WebGraphicsContext3DInProcessImpl::copyTexImage2D(
+ unsigned long target, long level, unsigned long internalformat,
+ long x, long y, unsigned long width, unsigned long height, long border) {
+ makeContextCurrent();
+
+ bool needsResolve = (attributes_.antialias && bound_fbo_ == multisample_fbo_);
+ if (needsResolve) {
+ ResolveMultisampledFramebuffer(x, y, width, height);
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_);
+ }
+
+ glCopyTexImage2D(target, level, internalformat, x, y, width, height, border);
+
+ if (needsResolve)
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, bound_fbo_);
+}
+
+void WebGraphicsContext3DInProcessImpl::copyTexSubImage2D(
+ unsigned long target, long level, long xoffset, long yoffset,
+ long x, long y, unsigned long width, unsigned long height) {
+ makeContextCurrent();
+
+ bool needsResolve = (attributes_.antialias && bound_fbo_ == multisample_fbo_);
+ if (needsResolve) {
+ ResolveMultisampledFramebuffer(x, y, width, height);
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_);
+ }
+
+ glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
+
+ if (needsResolve)
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, bound_fbo_);
+}
+
+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(depthRange, DepthRange, double, double)
+
+DELEGATE_TO_GL_2(detachShader, DetachShader, WebGLId, WebGLId)
+
+DELEGATE_TO_GL_1(disable, Disable, unsigned long)
+
+void WebGraphicsContext3DInProcessImpl::disableVertexAttribArray(
+ unsigned long index) {
+ makeContextCurrent();
+ if (index < kNumTrackedPointerStates)
+ vertex_attrib_pointer_state_[index].enabled = false;
+ glDisableVertexAttribArray(index);
+}
+
+DELEGATE_TO_GL_3(drawArrays, DrawArrays, unsigned long, long, long)
+
+void WebGraphicsContext3DInProcessImpl::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)
+
+void WebGraphicsContext3DInProcessImpl::enableVertexAttribArray(
+ unsigned long index) {
+ makeContextCurrent();
+ if (index < kNumTrackedPointerStates)
+ vertex_attrib_pointer_state_[index].enabled = true;
+ glEnableVertexAttribArray(index);
+}
+
+DELEGATE_TO_GL(finish, Finish)
+
+DELEGATE_TO_GL(flush, Flush)
+
+DELEGATE_TO_GL_4(framebufferRenderbuffer, FramebufferRenderbufferEXT,
+ unsigned long, unsigned long, unsigned long, WebGLId)
+
+DELEGATE_TO_GL_5(framebufferTexture2D, FramebufferTexture2DEXT,
+ unsigned long, unsigned long, unsigned long, WebGLId, long)
+
+DELEGATE_TO_GL_1(frontFace, FrontFace, unsigned long)
+
+void WebGraphicsContext3DInProcessImpl::generateMipmap(unsigned long target) {
+ makeContextCurrent();
+ if (is_gles2_ || have_ext_framebuffer_object_)
+ glGenerateMipmapEXT(target);
+ // FIXME: provide alternative code path? This will be unpleasant
+ // to implement if glGenerateMipmapEXT is not available -- it will
+ // require a texture readback and re-upload.
+}
+
+bool WebGraphicsContext3DInProcessImpl::getActiveAttrib(
+ WebGLId program, unsigned long index, ActiveInfo& info) {
+ makeContextCurrent();
+ 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]);
+ 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 = WebString::fromUTF8(name.get(), length);
+ info.type = type;
+ info.size = size;
+ return true;
+}
+
+bool WebGraphicsContext3DInProcessImpl::getActiveUniform(
+ WebGLId program, unsigned long index, ActiveInfo& info) {
+ makeContextCurrent();
+ 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]);
+ 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 = WebString::fromUTF8(name.get(), length);
+ info.type = type;
+ info.size = size;
+ return true;
+}
+
+DELEGATE_TO_GL_4(getAttachedShaders, GetAttachedShaders,
+ WebGLId, int, int*, unsigned int*)
+
+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*)
+
+WebGraphicsContext3D::Attributes WebGraphicsContext3DInProcessImpl::
+ getContextAttributes() {
+ return attributes_;
+}
+
+unsigned long WebGraphicsContext3DInProcessImpl::getError() {
+ DCHECK(synthetic_errors_list_.size() == synthetic_errors_set_.size());
+ if (synthetic_errors_set_.size() > 0) {
+ unsigned long error = synthetic_errors_list_.front();
+ synthetic_errors_list_.pop_front();
+ synthetic_errors_set_.erase(error);
+ return error;
+ }
+
+ makeContextCurrent();
+ return glGetError();
+}
+
+bool WebGraphicsContext3DInProcessImpl::isContextLost() {
+ return false;
+}
+
+DELEGATE_TO_GL_2(getFloatv, GetFloatv, unsigned long, float*)
+
+void WebGraphicsContext3DInProcessImpl::getFramebufferAttachmentParameteriv(
+ unsigned long target, unsigned long attachment,
+ unsigned long pname, int* value) {
+ makeContextCurrent();
+ if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
+ attachment = GL_DEPTH_ATTACHMENT; // Or GL_STENCIL_ATTACHMENT;
+ // either works.
+ glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, value);
+}
+
+void WebGraphicsContext3DInProcessImpl::getIntegerv(
+ unsigned long pname, int* value) {
+ makeContextCurrent();
+ if (is_gles2_) {
+ glGetIntegerv(pname, value);
+ return;
+ }
+ // Need to emulate MAX_FRAGMENT/VERTEX_UNIFORM_VECTORS and
+ // MAX_VARYING_VECTORS because desktop GL's corresponding queries
+ // return the number of components whereas GLES2 return the number
+ // of vectors (each vector has 4 components). Therefore, the value
+ // returned by desktop GL needs to be divided by 4.
+ switch (pname) {
+ case MAX_FRAGMENT_UNIFORM_VECTORS:
+ glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, value);
+ *value /= 4;
+ break;
+ case MAX_VERTEX_UNIFORM_VECTORS:
+ glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS, value);
+ *value /= 4;
+ break;
+ case MAX_VARYING_VECTORS:
+ glGetIntegerv(GL_MAX_VARYING_FLOATS, value);
+ *value /= 4;
+ break;
+ default:
+ glGetIntegerv(pname, value);
+ }
+}
+
+DELEGATE_TO_GL_3(getProgramiv, GetProgramiv, WebGLId, unsigned long, int*)
+
+WebString WebGraphicsContext3DInProcessImpl::getProgramInfoLog(
+ WebGLId program) {
+ makeContextCurrent();
+ GLint log_length;
+ glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_length);
+ if (!log_length)
+ return WebString();
+ scoped_array<GLchar> log(new GLchar[log_length]);
+ GLsizei returned_log_length;
+ glGetProgramInfoLog(program, log_length, &returned_log_length, log.get());
+ DCHECK(log_length == returned_log_length + 1);
+ WebString res = WebString::fromUTF8(log.get(), returned_log_length);
+ return res;
+}
+
+DELEGATE_TO_GL_3(getRenderbufferParameteriv, GetRenderbufferParameterivEXT,
+ unsigned long, unsigned long, int*)
+
+void WebGraphicsContext3DInProcessImpl::getShaderiv(
+ WebGLId shader, unsigned long pname, int* value) {
+ makeContextCurrent();
+
+ ShaderSourceMap::iterator result = shader_source_map_.find(shader);
+ if (result != shader_source_map_.end()) {
+ ShaderSourceEntry* entry = result->second;
+ DCHECK(entry);
+ switch (pname) {
+ case GL_COMPILE_STATUS:
+ if (!entry->is_valid) {
+ *value = 0;
+ return;
+ }
+ break;
+ case GL_INFO_LOG_LENGTH:
+ if (!entry->is_valid) {
+ *value = entry->log.get() ? strlen(entry->log.get()) : 0;
+ if (*value)
+ (*value)++;
+ return;
+ }
+ break;
+ case GL_SHADER_SOURCE_LENGTH:
+ *value = entry->source.get() ? strlen(entry->source.get()) : 0;
+ if (*value)
+ (*value)++;
+ return;
+ }
+ }
+
+ glGetShaderiv(shader, pname, value);
+}
+
+WebString WebGraphicsContext3DInProcessImpl::getShaderInfoLog(WebGLId shader) {
+ makeContextCurrent();
+
+ ShaderSourceMap::iterator result = shader_source_map_.find(shader);
+ if (result != shader_source_map_.end()) {
+ ShaderSourceEntry* entry = result->second;
+ DCHECK(entry);
+ if (!entry->is_valid) {
+ if (!entry->log.get())
+ return WebString();
+ WebString res = WebString::fromUTF8(
+ entry->log.get(), strlen(entry->log.get()));
+ return res;
+ }
+ }
+
+ GLint log_length = 0;
+ glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length);
+ if (log_length <= 1)
+ return WebString();
+ scoped_array<GLchar> log(new GLchar[log_length]);
+ GLsizei returned_log_length;
+ glGetShaderInfoLog(shader, log_length, &returned_log_length, log.get());
+ DCHECK(log_length == returned_log_length + 1);
+ WebString res = WebString::fromUTF8(log.get(), returned_log_length);
+ return res;
+}
+
+WebString WebGraphicsContext3DInProcessImpl::getShaderSource(WebGLId shader) {
+ makeContextCurrent();
+
+ ShaderSourceMap::iterator result = shader_source_map_.find(shader);
+ if (result != shader_source_map_.end()) {
+ ShaderSourceEntry* entry = result->second;
+ DCHECK(entry);
+ if (!entry->source.get())
+ return WebString();
+ WebString res = WebString::fromUTF8(
+ entry->source.get(), strlen(entry->source.get()));
+ return res;
+ }
+
+ GLint log_length = 0;
+ glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &log_length);
+ if (log_length <= 1)
+ return WebString();
+ scoped_array<GLchar> log(new GLchar[log_length]);
+ GLsizei returned_log_length;
+ glGetShaderSource(shader, log_length, &returned_log_length, log.get());
+ DCHECK(log_length == returned_log_length + 1);
+ WebString res = WebString::fromUTF8(log.get(), returned_log_length);
+ return res;
+}
+
+WebString WebGraphicsContext3DInProcessImpl::getString(unsigned long name) {
+ makeContextCurrent();
+ std::string result(reinterpret_cast<const char*>(glGetString(name)));
+ if (name == GL_EXTENSIONS) {
+ // GL_CHROMIUM_copy_texture_to_parent_texture requires the
+ // desktopGL-only function glGetTexLevelParameteriv (GLES2
+ // doesn't support it).
+ if (!is_gles2_)
+ result += " GL_CHROMIUM_copy_texture_to_parent_texture";
+ }
+ return WebString::fromUTF8(result.c_str());
+}
+
+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 WebGraphicsContext3DInProcessImpl::getVertexAttribOffset(
+ unsigned long index, unsigned long pname) {
+ makeContextCurrent();
+ void* pointer;
+ glGetVertexAttribPointerv(index, pname, &pointer);
+ return reinterpret_cast<long>(pointer);
+}
+
+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, IsFramebufferEXT, WebGLId, bool)
+
+DELEGATE_TO_GL_1RB(isProgram, IsProgram, WebGLId, bool)
+
+DELEGATE_TO_GL_1RB(isRenderbuffer, IsRenderbufferEXT, 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)
+
+void WebGraphicsContext3DInProcessImpl::readPixels(
+ long x, long y, unsigned long width, unsigned long height,
+ unsigned long format, unsigned long type, void* pixels) {
+ makeContextCurrent();
+ // FIXME: remove the two glFlush calls when the driver bug is fixed, i.e.,
+ // all previous rendering calls should be done before reading pixels.
+ glFlush();
+ bool needs_resolve =
+ (attributes_.antialias && bound_fbo_ == multisample_fbo_);
+ if (needs_resolve) {
+ ResolveMultisampledFramebuffer(x, y, width, height);
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_);
+ glFlush();
+ }
+
+ glReadPixels(x, y, width, height, format, type, pixels);
+
+ if (needs_resolve)
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, bound_fbo_);
+}
+
+void WebGraphicsContext3DInProcessImpl::releaseShaderCompiler() {
+}
+
+void WebGraphicsContext3DInProcessImpl::renderbufferStorage(
+ unsigned long target,
+ unsigned long internalformat,
+ unsigned long width,
+ unsigned long height) {
+ makeContextCurrent();
+ switch (internalformat) {
+ case GL_DEPTH_STENCIL:
+ internalformat = GL_DEPTH24_STENCIL8_EXT;
+ break;
+ case GL_DEPTH_COMPONENT16:
+ internalformat = GL_DEPTH_COMPONENT;
+ break;
+ case GL_RGBA4:
+ case GL_RGB5_A1:
+ internalformat = GL_RGBA;
+ break;
+ case 0x8D62: // GL_RGB565
+ internalformat = GL_RGB;
+ break;
+ }
+ glRenderbufferStorageEXT(target, internalformat, width, height);
+}
+
+DELEGATE_TO_GL_2_C1(sampleCoverage, SampleCoverage, double, bool)
+
+DELEGATE_TO_GL_4(scissor, Scissor, long, long, unsigned long, unsigned long)
+
+void WebGraphicsContext3DInProcessImpl::texImage2D(
+ unsigned target, unsigned level, unsigned internalFormat,
+ unsigned width, unsigned height, unsigned border,
+ unsigned format, unsigned type, const void* pixels) {
+ if (width && height && !pixels) {
+ synthesizeGLError(GL_INVALID_VALUE);
+ return;
+ }
+ makeContextCurrent();
+ glTexImage2D(target, level, internalFormat,
+ width, height, border, format, type, pixels);
+}
+
+void WebGraphicsContext3DInProcessImpl::shaderSource(
+ WebGLId shader, const char* source) {
+ makeContextCurrent();
+ GLint length = source ? strlen(source) : 0;
+ ShaderSourceMap::iterator result = shader_source_map_.find(shader);
+ if (result != shader_source_map_.end()) {
+ ShaderSourceEntry* entry = result->second;
+ DCHECK(entry);
+ entry->source.reset(new char[length + 1]);
+ memcpy(entry->source.get(), source, (length + 1) * sizeof(char));
+ } else {
+ glShaderSource(shader, 1, &source, &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_3(texParameterf, TexParameterf, unsigned, unsigned, float);
+
+DELEGATE_TO_GL_3(texParameteri, TexParameteri, unsigned, unsigned, int);
+
+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 WebGraphicsContext3DInProcessImpl::vertexAttribPointer(
+ unsigned long indx, int size, int type, bool normalized,
+ unsigned long stride, unsigned long offset) {
+ makeContextCurrent();
+
+ if (bound_array_buffer_ <= 0) {
+ // FIXME: raise exception.
+ // LogMessagef(("bufferData: no buffer bound"));
+ return;
+ }
+
+ if (indx < kNumTrackedPointerStates) {
+ VertexAttribPointerState& state = vertex_attrib_pointer_state_[indx];
+ state.buffer = bound_array_buffer_;
+ state.indx = indx;
+ state.size = size;
+ state.type = type;
+ state.normalized = normalized;
+ state.stride = stride;
+ state.offset = offset;
+ }
+
+ 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 WebGraphicsContext3DInProcessImpl::createBuffer() {
+ makeContextCurrent();
+ GLuint o;
+ glGenBuffersARB(1, &o);
+ return o;
+}
+
+unsigned WebGraphicsContext3DInProcessImpl::createFramebuffer() {
+ makeContextCurrent();
+ GLuint o = 0;
+ glGenFramebuffersEXT(1, &o);
+ return o;
+}
+
+unsigned WebGraphicsContext3DInProcessImpl::createProgram() {
+ makeContextCurrent();
+ return glCreateProgram();
+}
+
+unsigned WebGraphicsContext3DInProcessImpl::createRenderbuffer() {
+ makeContextCurrent();
+ GLuint o;
+ glGenRenderbuffersEXT(1, &o);
+ return o;
+}
+
+unsigned WebGraphicsContext3DInProcessImpl::createShader(
+ unsigned long shaderType) {
+ makeContextCurrent();
+ DCHECK(shaderType == GL_VERTEX_SHADER || shaderType == GL_FRAGMENT_SHADER);
+ unsigned shader = glCreateShader(shaderType);
+ if (shader) {
+ ShaderSourceMap::iterator result = shader_source_map_.find(shader);
+ if (result != shader_source_map_.end()) {
+ delete result->second;
+ shader_source_map_.erase(result);
+ }
+ shader_source_map_.insert(
+ ShaderSourceMap::value_type(shader, new ShaderSourceEntry(shaderType)));
+ }
+
+ return shader;
+}
+
+unsigned WebGraphicsContext3DInProcessImpl::createTexture() {
+ makeContextCurrent();
+ GLuint o;
+ glGenTextures(1, &o);
+ return o;
+}
+
+void WebGraphicsContext3DInProcessImpl::deleteBuffer(unsigned buffer) {
+ makeContextCurrent();
+ glDeleteBuffersARB(1, &buffer);
+}
+
+void WebGraphicsContext3DInProcessImpl::deleteFramebuffer(
+ unsigned framebuffer) {
+ makeContextCurrent();
+ glDeleteFramebuffersEXT(1, &framebuffer);
+}
+
+void WebGraphicsContext3DInProcessImpl::deleteProgram(unsigned program) {
+ makeContextCurrent();
+ glDeleteProgram(program);
+}
+
+void WebGraphicsContext3DInProcessImpl::deleteRenderbuffer(
+ unsigned renderbuffer) {
+ makeContextCurrent();
+ glDeleteRenderbuffersEXT(1, &renderbuffer);
+}
+
+void WebGraphicsContext3DInProcessImpl::deleteShader(unsigned shader) {
+ makeContextCurrent();
+
+ ShaderSourceMap::iterator result = shader_source_map_.find(shader);
+ if (result != shader_source_map_.end()) {
+ delete result->second;
+ shader_source_map_.erase(result);
+ }
+ glDeleteShader(shader);
+}
+
+void WebGraphicsContext3DInProcessImpl::deleteTexture(unsigned texture) {
+ makeContextCurrent();
+ glDeleteTextures(1, &texture);
+}
+
+bool WebGraphicsContext3DInProcessImpl::AngleCreateCompilers() {
+ if (!ShInitialize())
+ return false;
+
+ ShBuiltInResources resources;
+ ShInitBuiltInResources(&resources);
+ getIntegerv(GL_MAX_VERTEX_ATTRIBS, &resources.MaxVertexAttribs);
+ getIntegerv(MAX_VERTEX_UNIFORM_VECTORS, &resources.MaxVertexUniformVectors);
+ getIntegerv(MAX_VARYING_VECTORS, &resources.MaxVaryingVectors);
+ getIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS,
+ &resources.MaxVertexTextureImageUnits);
+ getIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,
+ &resources.MaxCombinedTextureImageUnits);
+ getIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &resources.MaxTextureImageUnits);
+ getIntegerv(MAX_FRAGMENT_UNIFORM_VECTORS,
+ &resources.MaxFragmentUniformVectors);
+ // Always set to 1 for OpenGL ES.
+ resources.MaxDrawBuffers = 1;
+
+ fragment_compiler_ = ShConstructCompiler(
+ SH_FRAGMENT_SHADER, SH_WEBGL_SPEC, &resources);
+ vertex_compiler_ = ShConstructCompiler(
+ SH_VERTEX_SHADER, SH_WEBGL_SPEC, &resources);
+ return (fragment_compiler_ && vertex_compiler_);
+}
+
+void WebGraphicsContext3DInProcessImpl::AngleDestroyCompilers() {
+ if (fragment_compiler_) {
+ ShDestruct(fragment_compiler_);
+ fragment_compiler_ = 0;
+ }
+ if (vertex_compiler_) {
+ ShDestruct(vertex_compiler_);
+ vertex_compiler_ = 0;
+ }
+}
+
+bool WebGraphicsContext3DInProcessImpl::AngleValidateShaderSource(
+ ShaderSourceEntry* entry) {
+ entry->is_valid = false;
+ entry->translated_source.reset();
+ entry->log.reset();
+
+ ShHandle compiler = 0;
+ switch (entry->type) {
+ case GL_FRAGMENT_SHADER:
+ compiler = fragment_compiler_;
+ break;
+ case GL_VERTEX_SHADER:
+ compiler = vertex_compiler_;
+ break;
+ }
+ if (!compiler)
+ return false;
+
+ char* source = entry->source.get();
+ if (!ShCompile(compiler, &source, 1, SH_OBJECT_CODE)) {
+ int logSize = 0;
+ ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &logSize);
+ if (logSize > 1) {
+ entry->log.reset(new char[logSize]);
+ ShGetInfoLog(compiler, entry->log.get());
+ }
+ return false;
+ }
+
+ int length = 0;
+ if (is_gles2_) {
+ // ANGLE does not yet have a GLSL ES backend. Therefore if the
+ // compile succeeds we send the original source down.
+ length = strlen(entry->source.get());
+ if (length > 0)
+ ++length; // Add null terminator
+ } else {
+ ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &length);
+ }
+ if (length > 1) {
+ entry->translated_source.reset(new char[length]);
+ if (is_gles2_)
+ strncpy(entry->translated_source.get(), entry->source.get(), length);
+ else
+ ShGetObjectCode(compiler, entry->translated_source.get());
+ }
+ entry->is_valid = true;
+ return true;
+}
+
+} // namespace webkit_gpu
+
diff --git a/webkit/gpu/webgraphicscontext3d_in_process_impl.h b/webkit/gpu/webgraphicscontext3d_in_process_impl.h
new file mode 100644
index 0000000..4081995
--- /dev/null
+++ b/webkit/gpu/webgraphicscontext3d_in_process_impl.h
@@ -0,0 +1,471 @@
+// 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 WEBKIT_GPU_WEBGRAPHICSCONTEXT3D_IN_PROCESS_IMPL_H_
+#define WEBKIT_GPU_WEBGRAPHICSCONTEXT3D_IN_PROCESS_IMPL_H_
+
+#include <list>
+#include <set>
+
+#include "base/hash_tables.h"
+#include "base/scoped_ptr.h"
+#include "third_party/angle/include/GLSLANG/ShaderLang.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
+namespace gfx {
+class GLContext;
+}
+
+namespace webkit_gpu {
+
+// The default implementation of WebGL. In Chromium, using this class
+// requires the sandbox to be disabled, which is strongly discouraged.
+// It is provided for support of test_shell and any Chromium ports
+// where an in-renderer WebGL implementation would be helpful.
+
+class WebGraphicsContext3DInProcessImpl : public WebKit::WebGraphicsContext3D {
+ public:
+ WebGraphicsContext3DInProcessImpl();
+ virtual ~WebGraphicsContext3DInProcessImpl();
+
+ //----------------------------------------------------------------------
+ // WebGraphicsContext3D methods
+ virtual bool initialize(
+ WebGraphicsContext3D::Attributes attributes, WebKit::WebView*, bool);
+ virtual bool makeContextCurrent();
+
+ virtual int width();
+ virtual int height();
+
+ virtual int sizeInBytes(int type);
+
+ virtual bool isGLES2Compliant();
+
+ virtual void reshape(int width, int height);
+
+ virtual bool readBackFramebuffer(unsigned char* pixels, size_t bufferSize);
+
+ virtual unsigned int getPlatformTextureId();
+ virtual void prepareTexture();
+
+ virtual void synthesizeGLError(unsigned long error);
+ virtual void* mapBufferSubDataCHROMIUM(
+ unsigned target, int offset, int size, unsigned access);
+ virtual void unmapBufferSubDataCHROMIUM(const void*);
+ virtual void* mapTexSubImage2DCHROMIUM(
+ unsigned target,
+ int level,
+ int xoffset,
+ int yoffset,
+ int width,
+ int height,
+ unsigned format,
+ unsigned type,
+ unsigned access);
+ virtual void unmapTexSubImage2DCHROMIUM(const void*);
+ virtual void copyTextureToParentTextureCHROMIUM(
+ unsigned texture, unsigned parentTexture);
+
+ virtual WebKit::WebString getRequestableExtensionsCHROMIUM();
+ virtual void requestExtensionCHROMIUM(const char*);
+
+ virtual void activeTexture(unsigned long texture);
+ virtual void attachShader(WebKit::WebGLId program, WebKit::WebGLId shader);
+ virtual void bindAttribLocation(
+ WebKit::WebGLId program, unsigned long index, const char* name);
+ virtual void bindBuffer(unsigned long target, WebKit::WebGLId buffer);
+ virtual void bindFramebuffer(
+ unsigned long target, WebKit::WebGLId framebuffer);
+ virtual void bindRenderbuffer(
+ unsigned long target, WebKit::WebGLId renderbuffer);
+ virtual void bindTexture(unsigned long target, WebKit::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(WebKit::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(WebKit::WebGLId program, WebKit::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,
+ WebKit::WebGLId renderbuffer);
+ virtual void framebufferTexture2D(
+ unsigned long target,
+ unsigned long attachment,
+ unsigned long textarget,
+ WebKit::WebGLId texture,
+ long level);
+ virtual void frontFace(unsigned long mode);
+ virtual void generateMipmap(unsigned long target);
+
+ virtual bool getActiveAttrib(
+ WebKit::WebGLId program, unsigned long index, ActiveInfo&);
+ virtual bool getActiveUniform(
+ WebKit::WebGLId program, unsigned long index, ActiveInfo&);
+
+ virtual void getAttachedShaders(
+ WebKit::WebGLId program, int maxCount, int* count, unsigned int* shaders);
+
+ virtual int getAttribLocation(WebKit::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 bool isContextLost();
+
+ 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(
+ WebKit::WebGLId program, unsigned long pname, int* value);
+
+ virtual WebKit::WebString getProgramInfoLog(WebKit::WebGLId program);
+
+ virtual void getRenderbufferParameteriv(
+ unsigned long target, unsigned long pname, int* value);
+
+ virtual void getShaderiv(
+ WebKit::WebGLId shader, unsigned long pname, int* value);
+
+ virtual WebKit::WebString getShaderInfoLog(WebKit::WebGLId shader);
+
+ // TBD
+ // void glGetShaderPrecisionFormat(
+ // GLenum shadertype, GLenum precisiontype,
+ // GLint* range, GLint* precision);
+
+ virtual WebKit::WebString getShaderSource(WebKit::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(
+ WebKit::WebGLId program, long location, float* value);
+ virtual void getUniformiv(
+ WebKit::WebGLId program, long location, int* value);
+
+ virtual long getUniformLocation(WebKit::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(WebKit::WebGLId buffer);
+ virtual bool isEnabled(unsigned long cap);
+ virtual bool isFramebuffer(WebKit::WebGLId framebuffer);
+ virtual bool isProgram(WebKit::WebGLId program);
+ virtual bool isRenderbuffer(WebKit::WebGLId renderbuffer);
+ virtual bool isShader(WebKit::WebGLId shader);
+ virtual bool isTexture(WebKit::WebGLId texture);
+ virtual void lineWidth(double width);
+ virtual void linkProgram(WebKit::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(WebKit::WebGLId shader, const char* source);
+ 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(WebKit::WebGLId program);
+ virtual void validateProgram(WebKit::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);
+
+ private:
+ enum {
+ kNumTrackedPointerStates = 2
+ };
+
+ // Note: we aren't currently using this information, but we will
+ // need to in order to verify that all enabled vertex arrays have
+ // a valid buffer bound -- to avoid crashes on certain cards.
+ struct VertexAttribPointerState {
+ VertexAttribPointerState();
+
+ bool enabled;
+ unsigned long buffer;
+ unsigned long indx;
+ int size;
+ int type;
+ bool normalized;
+ unsigned long stride;
+ unsigned long offset;
+ };
+
+ // ANGLE related.
+ struct ShaderSourceEntry {
+ explicit ShaderSourceEntry(unsigned long shader_type)
+ : type(shader_type),
+ is_valid(false) {
+ }
+
+ unsigned long type;
+ scoped_array<char> source;
+ scoped_array<char> log;
+ scoped_array<char> translated_source;
+ bool is_valid;
+ };
+
+ typedef base::hash_map<WebKit::WebGLId, ShaderSourceEntry*> ShaderSourceMap;
+
+#ifdef FLIP_FRAMEBUFFER_VERTICALLY
+ void FlipVertically(unsigned char* framebuffer,
+ unsigned int width,
+ unsigned int height);
+#endif
+
+ // Take into account the user's requested context creation attributes, in
+ // particular stencil and antialias, and determine which could or could
+ // not be honored based on the capabilities of the OpenGL implementation.
+ void ValidateAttributes();
+
+ // Resolve the given rectangle of the multisampled framebuffer if necessary.
+ void ResolveMultisampledFramebuffer(
+ unsigned x, unsigned y, unsigned width, unsigned height);
+
+ bool AngleCreateCompilers();
+ void AngleDestroyCompilers();
+ bool AngleValidateShaderSource(ShaderSourceEntry* entry);
+
+ WebGraphicsContext3D::Attributes attributes_;
+ bool initialized_;
+ bool render_directly_to_web_view_;
+ bool is_gles2_;
+ bool have_ext_framebuffer_object_;
+ bool have_ext_framebuffer_multisample_;
+ bool have_angle_framebuffer_multisample_;
+
+ unsigned int texture_;
+ unsigned int fbo_;
+ unsigned int depth_stencil_buffer_;
+ unsigned int cached_width_, cached_height_;
+
+ // For multisampling
+ unsigned int multisample_fbo_;
+ unsigned int multisample_depth_stencil_buffer_;
+ unsigned int multisample_color_buffer_;
+
+ // For tracking which FBO is bound
+ unsigned int bound_fbo_;
+
+ // For tracking which texture is bound
+ unsigned int bound_texture_;
+
+ // FBO used for copying child texture to parent texture.
+ unsigned copy_texture_to_parent_texture_fbo_;
+
+ unsigned int bound_array_buffer_;
+
+#ifdef FLIP_FRAMEBUFFER_VERTICALLY
+ unsigned char* scanline_;
+#endif
+
+ VertexAttribPointerState vertex_attrib_pointer_state_[
+ kNumTrackedPointerStates];
+
+ // Errors raised by synthesizeGLError().
+ std::list<unsigned long> synthetic_errors_list_;
+ std::set<unsigned long> synthetic_errors_set_;
+
+ scoped_ptr<gfx::GLContext> gl_context_;
+
+ ShaderSourceMap shader_source_map_;
+
+ ShHandle fragment_compiler_;
+ ShHandle vertex_compiler_;
+};
+
+} // namespace webkit_gpu
+
+#endif // WEBKIT_GPU_WEBGRAPHICSCONTEXT3D_IN_PROCESS_IMPL_H_
+
diff --git a/webkit/gpu/webkit_gpu.gypi b/webkit/gpu/webkit_gpu.gypi
new file mode 100644
index 0000000..2ca3523
--- /dev/null
+++ b/webkit/gpu/webkit_gpu.gypi
@@ -0,0 +1,30 @@
+# 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.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'webkit_gpu',
+ 'type': '<(library)',
+ 'dependencies': [
+ '<(DEPTH)/app/app.gyp:app_base',
+ '<(DEPTH)/base/base.gyp:base',
+ '<(DEPTH)/third_party/angle/src/build_angle.gyp:translator_common',
+ ],
+ 'sources': [
+ # This list contains all .h and .cc in gpu except for test code.
+ 'webgraphicscontext3d_in_process_impl.cc',
+ 'webgraphicscontext3d_in_process_impl.h',
+ 'webkit_gpu.gypi',
+ ],
+ 'conditions': [
+ ['inside_chromium_build==0', {
+ 'dependencies': [
+ '<(DEPTH)/webkit/support/setup_third_party.gyp:third_party_headers',
+ ],
+ }],
+ ],
+ },
+ ],
+}