diff options
author | kbr@google.com <kbr@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-27 00:23:34 +0000 |
---|---|---|
committer | kbr@google.com <kbr@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-27 00:23:34 +0000 |
commit | 3bf4d53ecb0a07e8639b4403997cddb6869ebc61 (patch) | |
tree | 5283f1b9733ecab92f0b2875110a4194c1ee41e0 /chrome/renderer/webgraphicscontext3d_command_buffer_impl.cc | |
parent | 6f4926b7834dfaf506957b02dd80e6004489824e (diff) | |
download | chromium_src-3bf4d53ecb0a07e8639b4403997cddb6869ebc61.zip chromium_src-3bf4d53ecb0a07e8639b4403997cddb6869ebc61.tar.gz chromium_src-3bf4d53ecb0a07e8639b4403997cddb6869ebc61.tar.bz2 |
Added command buffer implementation of WebGL which runs in the sandbox.
Added synchronous initialization of the channel to the GPU process, needed
to obey WebGL startup semantics. There are problems with this on the
Windows platform which will be addressed via refactoring in the
GpuProcessHost in a subsequent CL. Implemented offscreen rendering code
path in GGL / GLES2CmdDecoder for Mac OS X.
This new code path is not yet complete for all platforms and is still being
stress tested. The previous in-process WebGL implementation is currently
used when the sandbox is disabled; it will be removed in a subsequent CL.
A one-line code change in WebKit is needed after this CL lands to enable
the new code path.
BUG=29120
TEST=ran WebGL demos on command buffer implementation on Mac
Review URL: http://codereview.chromium.org/1328001
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@42879 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/renderer/webgraphicscontext3d_command_buffer_impl.cc')
-rw-r--r-- | chrome/renderer/webgraphicscontext3d_command_buffer_impl.cc | 878 |
1 files changed, 878 insertions, 0 deletions
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) + |