Landing the GPU process and command buffer code again, this time with a DEPS file with the necessary include rules.
TEST=none
BUG=none


git-svn-id: svn://svn.chromium.org/chrome/trunk/src@33006 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/build/all.gyp b/build/all.gyp
index 4a61b70..3a94e7c8 100644
--- a/build/all.gyp
+++ b/build/all.gyp
@@ -54,6 +54,7 @@
         ['enable_pepper==1', {
           'dependencies': [
             '../webkit/tools/pepper_test_plugin/pepper_test_plugin.gyp:*',
+            '../gpu/gpu.gyp:*',
           ],
         }],
         ['enable_openmax==1', {
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index 4cc29cbb..7c08251 100755
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -3417,6 +3417,11 @@
         ],
       },
       'conditions': [
+        ['enable_pepper==1', {
+          'dependencies': [
+            '../gpu/gpu.gyp:gpu_plugin',
+          ],
+        }],
         ['disable_nacl!=1', {
           'dependencies': [
             'nacl',
diff --git a/gpu/DEPS b/gpu/DEPS
new file mode 100644
index 0000000..992eb71
--- /dev/null
+++ b/gpu/DEPS
@@ -0,0 +1,4 @@
+include_rules = [
+  "+webkit/glue/plugins",
+  "+third_party/npapi",
+]
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py
new file mode 100644
index 0000000..04f9a7b
--- /dev/null
+++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -0,0 +1,2577 @@
+#!/usr/bin/python
+#
+# Copyright (c) 2006-2009 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.
+
+"""code generator for GL command buffers."""
+
+import os
+import os.path
+import sys
+import re
+from optparse import OptionParser
+
+_SIZE_OF_UINT32 = 4
+_SIZE_OF_COMMAND_HEADER = 4
+_FIRST_SPECIFIC_COMMAND_ID = 1024
+
+_LICENSE = """
+// Copyright (c) 2006-2008 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.
+
+"""
+
+# This string is copied directly out of the gl2.h file from GLES2.0
+# the reasons it is copied out instead of parsed directly are
+#
+# 1) Because order is important. The command IDs need to stay constant forever
+#    so if you add a new command it needs to be added to the bottom of the list.
+#
+# 2) So we can add more commands easily that are unrelated to GLES2.0 but still
+#    needed for GLES2.0 command buffers.
+#
+# Edits:
+#
+# *) Any argument that is a resourceID has been changed to GLresourceID.
+#    (not pointer arguments)
+#
+_GL_FUNCTIONS = """
+GL_APICALL void         GL_APIENTRY glActiveTexture (GLenum texture);
+GL_APICALL void         GL_APIENTRY glAttachShader (GLResourceId program, GLResourceId shader);
+GL_APICALL void         GL_APIENTRY glBindAttribLocation (GLResourceId program, GLuint index, const char* name);
+GL_APICALL void         GL_APIENTRY glBindBuffer (GLenum target, GLResourceId buffer);
+GL_APICALL void         GL_APIENTRY glBindFramebuffer (GLenum target, GLResourceId framebuffer);
+GL_APICALL void         GL_APIENTRY glBindRenderbuffer (GLenum target, GLResourceId renderbuffer);
+GL_APICALL void         GL_APIENTRY glBindTexture (GLenum target, GLResourceId texture);
+GL_APICALL void         GL_APIENTRY glBlendColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+GL_APICALL void         GL_APIENTRY glBlendEquation ( GLenum mode );
+GL_APICALL void         GL_APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha);
+GL_APICALL void         GL_APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor);
+GL_APICALL void         GL_APIENTRY glBlendFuncSeparate (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+GL_APICALL void         GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const void* data, GLenum usage);
+GL_APICALL void         GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void* data);
+GL_APICALL GLenum       GL_APIENTRY glCheckFramebufferStatus (GLenum target);
+GL_APICALL void         GL_APIENTRY glClear (GLbitfield mask);
+GL_APICALL void         GL_APIENTRY glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+GL_APICALL void         GL_APIENTRY glClearDepthf (GLclampf depth);
+GL_APICALL void         GL_APIENTRY glClearStencil (GLint s);
+GL_APICALL void         GL_APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+GL_APICALL void         GL_APIENTRY glCompileShader (GLResourceId shader);
+GL_APICALL void         GL_APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data);
+GL_APICALL void         GL_APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data);
+GL_APICALL void         GL_APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+GL_APICALL void         GL_APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL GLuint       GL_APIENTRY glCreateProgram (void);
+GL_APICALL GLuint       GL_APIENTRY glCreateShader (GLenum type);
+GL_APICALL void         GL_APIENTRY glCullFace (GLenum mode);
+GL_APICALL void         GL_APIENTRY glDeleteBuffers (GLsizei n, const GLuint* buffers);
+GL_APICALL void         GL_APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint* framebuffers);
+GL_APICALL void         GL_APIENTRY glDeleteProgram (GLResourceId program);
+GL_APICALL void         GL_APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint* renderbuffers);
+GL_APICALL void         GL_APIENTRY glDeleteShader (GLResourceId shader);
+GL_APICALL void         GL_APIENTRY glDeleteTextures (GLsizei n, const GLuint* textures);
+GL_APICALL void         GL_APIENTRY glDepthFunc (GLenum func);
+GL_APICALL void         GL_APIENTRY glDepthMask (GLboolean flag);
+GL_APICALL void         GL_APIENTRY glDepthRangef (GLclampf zNear, GLclampf zFar);
+GL_APICALL void         GL_APIENTRY glDetachShader (GLResourceId program, GLResourceId shader);
+GL_APICALL void         GL_APIENTRY glDisable (GLenum cap);
+GL_APICALL void         GL_APIENTRY glDisableVertexAttribArray (GLuint index);
+GL_APICALL void         GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count);
+GL_APICALL void         GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const void* indices);
+GL_APICALL void         GL_APIENTRY glEnable (GLenum cap);
+GL_APICALL void         GL_APIENTRY glEnableVertexAttribArray (GLuint index);
+GL_APICALL void         GL_APIENTRY glFinish (void);
+GL_APICALL void         GL_APIENTRY glFlush (void);
+GL_APICALL void         GL_APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLResourceId renderbuffer);
+GL_APICALL void         GL_APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLResourceId texture, GLint level);
+GL_APICALL void         GL_APIENTRY glFrontFace (GLenum mode);
+GL_APICALL void         GL_APIENTRY glGenBuffers (GLsizei n, GLuint* buffers);
+GL_APICALL void         GL_APIENTRY glGenerateMipmap (GLenum target);
+GL_APICALL void         GL_APIENTRY glGenFramebuffers (GLsizei n, GLuint* framebuffers);
+GL_APICALL void         GL_APIENTRY glGenRenderbuffers (GLsizei n, GLuint* renderbuffers);
+GL_APICALL void         GL_APIENTRY glGenTextures (GLsizei n, GLuint* textures);
+GL_APICALL void         GL_APIENTRY glGetActiveAttrib (GLResourceId program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name);
+GL_APICALL void         GL_APIENTRY glGetActiveUniform (GLResourceId program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name);
+GL_APICALL void         GL_APIENTRY glGetAttachedShaders (GLResourceId program, GLsizei maxcount, GLsizei* count, GLuint* shaders);
+GL_APICALL int          GL_APIENTRY glGetAttribLocation (GLResourceId program, const char* name);
+GL_APICALL void         GL_APIENTRY glGetBooleanv (GLenum pname, GLboolean* params);
+GL_APICALL void         GL_APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint* params);
+GL_APICALL GLenum       GL_APIENTRY glGetError (void);
+GL_APICALL void         GL_APIENTRY glGetFloatv (GLenum pname, GLfloat* params);
+GL_APICALL void         GL_APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetIntegerv (GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetProgramiv (GLResourceId program, GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetProgramInfoLog (GLResourceId program, GLsizei bufsize, GLsizei* length, char* infolog);
+GL_APICALL void         GL_APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetShaderiv (GLResourceId shader, GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetShaderInfoLog (GLResourceId shader, GLsizei bufsize, GLsizei* length, char* infolog);
+GL_APICALL void         GL_APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision);
+GL_APICALL void         GL_APIENTRY glGetShaderSource (GLResourceId shader, GLsizei bufsize, GLsizei* length, char* source);
+GL_APICALL const GLubyte* GL_APIENTRY glGetString (GLenum name);
+GL_APICALL void         GL_APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat* params);
+GL_APICALL void         GL_APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetUniformfv (GLResourceId program, GLint location, GLfloat* params);
+GL_APICALL void         GL_APIENTRY glGetUniformiv (GLResourceId program, GLint location, GLint* params);
+GL_APICALL int          GL_APIENTRY glGetUniformLocation (GLResourceId program, const char* name);
+GL_APICALL void         GL_APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat* params);
+GL_APICALL void         GL_APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, void** pointer);
+GL_APICALL void         GL_APIENTRY glHint (GLenum target, GLenum mode);
+GL_APICALL GLboolean    GL_APIENTRY glIsBuffer (GLResourceId buffer);
+GL_APICALL GLboolean    GL_APIENTRY glIsEnabled (GLenum cap);
+GL_APICALL GLboolean    GL_APIENTRY glIsFramebuffer (GLResourceId framebuffer);
+GL_APICALL GLboolean    GL_APIENTRY glIsProgram (GLResourceId program);
+GL_APICALL GLboolean    GL_APIENTRY glIsRenderbuffer (GLResourceId renderbuffer);
+GL_APICALL GLboolean    GL_APIENTRY glIsShader (GLResourceId shader);
+GL_APICALL GLboolean    GL_APIENTRY glIsTexture (GLResourceId texture);
+GL_APICALL void         GL_APIENTRY glLineWidth (GLfloat width);
+GL_APICALL void         GL_APIENTRY glLinkProgram (GLResourceId program);
+GL_APICALL void         GL_APIENTRY glPixelStorei (GLenum pname, GLint param);
+GL_APICALL void         GL_APIENTRY glPolygonOffset (GLfloat factor, GLfloat units);
+GL_APICALL void         GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels);
+GL_APICALL void         GL_APIENTRY glReleaseShaderCompiler (void);
+GL_APICALL void         GL_APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void         GL_APIENTRY glSampleCoverage (GLclampf value, GLboolean invert);
+GL_APICALL void         GL_APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void         GL_APIENTRY glShaderBinary (GLsizei n, const GLResourceId* shaders, GLenum binaryformat, const void* binary, GLsizei length);
+GL_APICALL void         GL_APIENTRY glShaderSource (GLResourceId shader, GLsizei count, const char** string, const GLint* length);
+GL_APICALL void         GL_APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask);
+GL_APICALL void         GL_APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask);
+GL_APICALL void         GL_APIENTRY glStencilMask (GLuint mask);
+GL_APICALL void         GL_APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask);
+GL_APICALL void         GL_APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass);
+GL_APICALL void         GL_APIENTRY glStencilOpSeparate (GLenum face, GLenum fail, GLenum zfail, GLenum zpass);
+GL_APICALL void         GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels);
+GL_APICALL void         GL_APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param);
+GL_APICALL void         GL_APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat* params);
+GL_APICALL void         GL_APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param);
+GL_APICALL void         GL_APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint* params);
+GL_APICALL void         GL_APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels);
+GL_APICALL void         GL_APIENTRY glUniform1f (GLint location, GLfloat x);
+GL_APICALL void         GL_APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void         GL_APIENTRY glUniform1i (GLint location, GLint x);
+GL_APICALL void         GL_APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void         GL_APIENTRY glUniform2f (GLint location, GLfloat x, GLfloat y);
+GL_APICALL void         GL_APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void         GL_APIENTRY glUniform2i (GLint location, GLint x, GLint y);
+GL_APICALL void         GL_APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void         GL_APIENTRY glUniform3f (GLint location, GLfloat x, GLfloat y, GLfloat z);
+GL_APICALL void         GL_APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void         GL_APIENTRY glUniform3i (GLint location, GLint x, GLint y, GLint z);
+GL_APICALL void         GL_APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void         GL_APIENTRY glUniform4f (GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GL_APICALL void         GL_APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void         GL_APIENTRY glUniform4i (GLint location, GLint x, GLint y, GLint z, GLint w);
+GL_APICALL void         GL_APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void         GL_APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void         GL_APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void         GL_APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void         GL_APIENTRY glUseProgram (GLResourceId program);
+GL_APICALL void         GL_APIENTRY glValidateProgram (GLResourceId program);
+GL_APICALL void         GL_APIENTRY glVertexAttrib1f (GLuint indx, GLfloat x);
+GL_APICALL void         GL_APIENTRY glVertexAttrib1fv (GLuint indx, const GLfloat* values);
+GL_APICALL void         GL_APIENTRY glVertexAttrib2f (GLuint indx, GLfloat x, GLfloat y);
+GL_APICALL void         GL_APIENTRY glVertexAttrib2fv (GLuint indx, const GLfloat* values);
+GL_APICALL void         GL_APIENTRY glVertexAttrib3f (GLuint indx, GLfloat x, GLfloat y, GLfloat z);
+GL_APICALL void         GL_APIENTRY glVertexAttrib3fv (GLuint indx, const GLfloat* values);
+GL_APICALL void         GL_APIENTRY glVertexAttrib4f (GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GL_APICALL void         GL_APIENTRY glVertexAttrib4fv (GLuint indx, const GLfloat* values);
+GL_APICALL void         GL_APIENTRY glVertexAttribPointer (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr);
+GL_APICALL void         GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);
+// Non-GL commands.
+GL_APICALL void         GL_APIENTRY glSwapBuffers (void);
+"""
+
+# This table specifies types and other special data for the commands that
+# will be generated.
+#
+# type:        defines which handler will be used to generate code.
+# DecoderFunc: defines which function to call in the decoder to execute the
+#              corresponding GL command. If not specified the GL command will
+#              be called directly.
+# cmd_args:    The arguments to use for the command. This overrides generating
+#              them based on the GL function arguments.
+# immediate:   Whether or not to generate an immediate command for the GL
+#              function. The default is if there is exactly 1 pointer argument
+#              in the GL function an immediate command is generated.
+# needs_size:  If true a data_size field is added to the command.
+# data_type:   The type of data the command uses. For PUTn or PUT types.
+# count:       The number of units per element. For PUTn or PUT types.
+
+_FUNCTION_INFO = {
+  'BindAttribLocation': {'type': 'GLchar'},
+  'BindBuffer': {'DecoderFunc': 'DoBindBuffer'},
+  'BindFramebuffer': {'DecoderFunc': 'glBindFramebufferEXT'},
+  'BindRenderbuffer': {'DecoderFunc': 'glBindRenderbufferEXT'},
+  'BufferData': {'type': 'Data'},
+  'BufferSubData': {'type': 'Data'},
+  'CheckFramebufferStatus': {'DecoderFunc': 'glCheckFramebufferStatusEXT'},
+  'ClearDepthf': {'DecoderFunc': 'glClearDepth'},
+  'CompressedTexImage2D': {'type': 'Data'},
+  'CompressedTexSubImage2D': {'type': 'Data'},
+  'CreateProgram': {'type': 'Create'},
+  'CreateShader': {'type': 'Create'},
+  'DeleteBuffers': {'type': 'DELn'},
+  'DeleteFramebuffers': {'type': 'DELn'},
+  'DeleteProgram': {'DecoderFunc': 'DoDeleteProgram'},
+  'DeleteRenderbuffers': {'type': 'DELn'},
+  'DeleteShader': {'DecoderFunc': 'DoDeleteShader'},
+  'DeleteTextures': {'type': 'DELn'},
+  'DepthRangef': {'DecoderFunc': 'glDepthRange'},
+  'DrawElements': {
+    'type': 'Manual',
+    'cmd_args': 'GLenum mode, GLsizei count, GLenum type, GLuint index_offset',
+  },
+  'FramebufferRenderbuffer': {'DecoderFunc': 'glFramebufferRenderbufferEXT'},
+  'FramebufferTexture2D': {'DecoderFunc': 'glFramebufferTexture2DEXT'},
+  'GenerateMipmap': {'DecoderFunc': 'glGenerateMipmapEXT'},
+  'GenBuffers': {'type': 'GENn'},
+  'GenFramebuffers': {'type': 'GENn'},
+  'GenRenderbuffers': {'type': 'GENn'},
+  'GenTextures': {'type': 'GENn'},
+  'GetActiveAttrib': {'type': 'Custom'},
+  'GetActiveUniform': {'type': 'Custom'},
+  'GetAttachedShaders': {'type': 'Custom'},
+  'GetAttribLocation': {'type': 'GetGLchar'},
+  'GetBooleanv': {'type': 'GETn'},
+  'GetBufferParameteriv': {'type': 'GETn'},
+  'GetError': {'type': 'Is'},
+  'GetFloatv': {'type': 'GETn'},
+  'GetFramebufferAttachmentParameteriv': {
+    'type': 'GETn',
+    'DecoderFunc': 'glGetFramebufferAttachmentParameterivEXT',
+  },
+  'GetIntegerv': {'type': 'GETn'},
+  'GetProgramiv': {'type': 'GETn'},
+  'GetProgramInfoLog': {'type': 'STRn'},
+  'GetRenderbufferParameteriv': {
+    'type': 'GETn',
+    'DecoderFunc': 'glGetRenderbufferParameterivEXT',
+  },
+  'GetShaderiv': {'type': 'GETn'},
+  'GetShaderInfoLog': {'type': 'STRn'},
+  'GetShaderPrecisionFormat': {'type': 'Custom'},
+  'GetShaderSource': {'type': 'STRn'},
+  'GetTexParameterfv': {'type': 'GETn'},
+  'GetTexParameteriv': {'type': 'GETn'},
+  'GetUniformfv': {'type': 'Custom', 'immediate': False},
+  'GetUniformiv': {'type': 'Custom', 'immediate': False},
+  'GetUniformLocation': {'type': 'GetGLchar'},
+  'GetVertexAttribfv': {'type': 'GETn'},
+  'GetVertexAttribiv': {'type': 'GETn'},
+  'GetVertexAttribPointerv': {'type': 'Custom', 'immediate': False},
+  'IsBuffer': {'type': 'Is'},
+  'IsEnabled': {'type': 'Is'},
+  'IsFramebuffer': {'type': 'Is', 'DecoderFunc': 'glIsFramebufferEXT'},
+  'IsProgram': {'type': 'Is'},
+  'IsRenderbuffer': {'type': 'Is', 'DecoderFunc': 'glIsRenderbufferEXT'},
+  'IsShader': {'type': 'Is'},
+  'IsTexture': {'type': 'Is'},
+  'PixelStorei': {'type': 'Custom'},
+  'RenderbufferStorage': {'DecoderFunc': 'glRenderbufferStorageEXT'},
+  'ReadPixels': {'type': 'Custom', 'immediate': False},
+  'ReleaseShaderCompiler': {'type': 'Noop'},
+  'ShaderBinary': {'type': 'Noop'},
+  'ShaderSource': {
+    'type': 'Manual',
+    'immediate': True,
+    'needs_size': True,
+    'cmd_args':
+        'GLuint shader, GLsizei count, const char* data',
+  },
+  'TexImage2D': {'type': 'Data'},
+  'TexParameterfv': {'type': 'PUT', 'data_type': 'GLfloat', 'count': 1},
+  'TexParameteriv': {'type': 'PUT', 'data_type': 'GLint', 'count': 1},
+  'TexSubImage2D': {'type': 'Data'},
+  'Uniform1fv': {'type': 'PUTn', 'data_type': 'GLfloat', 'count': 1},
+  'Uniform1iv': {'type': 'PUTn', 'data_type': 'GLint', 'count': 1},
+  'Uniform2fv': {'type': 'PUTn', 'data_type': 'GLfloat', 'count': 2},
+  'Uniform2iv': {'type': 'PUTn', 'data_type': 'GLint', 'count': 2},
+  'Uniform3fv': {'type': 'PUTn', 'data_type': 'GLfloat', 'count': 3},
+  'Uniform3iv': {'type': 'PUTn', 'data_type': 'GLint', 'count': 3},
+  'Uniform4fv': {'type': 'PUTn', 'data_type': 'GLfloat', 'count': 4},
+  'Uniform4iv': {'type': 'PUTn', 'data_type': 'GLint', 'count': 4},
+  'UniformMatrix2fv': {'type': 'PUTn', 'data_type': 'GLfloat', 'count': 4},
+  'UniformMatrix3fv': {'type': 'PUTn', 'data_type': 'GLfloat', 'count': 9},
+  'UniformMatrix4fv': {'type': 'PUTn', 'data_type': 'GLfloat', 'count': 16},
+  'VertexAttrib1fv': {'type': 'PUT', 'data_type': 'GLfloat', 'count': 1},
+  'VertexAttrib2fv': {'type': 'PUT', 'data_type': 'GLfloat', 'count': 2},
+  'VertexAttrib3fv': {'type': 'PUT', 'data_type': 'GLfloat', 'count': 3},
+  'VertexAttrib4fv': {'type': 'PUT', 'data_type': 'GLfloat', 'count': 4},
+  'VertexAttribPointer': {
+      'type': 'Manual',
+      'cmd_args': 'GLuint indx, GLint size, GLenum type, GLboolean normalized, '
+                  'GLsizei stride, GLuint offset',
+  },
+  'SwapBuffers': {'DecoderFunc': 'DoSwapBuffers'},
+}
+
+
+class CWriter(object):
+  """Writes to a file formatting it for Google's style guidelines."""
+
+  def __init__(self, filename):
+    self.filename = filename
+    self.file = open(filename, "w")
+
+  def Write(self, string):
+    """Writes a string to a file spliting if it's > 80 characters."""
+    lines = string.splitlines()
+    num_lines = len(lines)
+    for ii in range(0, num_lines):
+      self.__WriteLine(lines[ii], ii < (num_lines - 1) or string[-1] == '\n')
+
+  def __FindSplit(self, string):
+    """Finds a place to split a string."""
+    splitter = string.find('=')
+    if splitter >= 0 and not string[splitter + 1] == '=':
+      return splitter
+    parts = string.split('(')
+    if len(parts) > 1:
+      splitter = len(parts[0])
+      for ii in range(1, len(parts)):
+        if not parts[ii - 1][-3:] == "if ":
+          return splitter
+        splitter += len(parts[ii]) + 1
+    done = False
+    end = len(string)
+    last_splitter = -1
+    while not done:
+      splitter = string[0:end].rfind(',')
+      if splitter < 0:
+        return last_splitter
+      elif splitter >= 80:
+        end = splitter
+      else:
+        return splitter
+
+  def __WriteLine(self, line, ends_with_eol):
+    """Given a signle line, writes it to a file, splitting if it's > 80 chars"""
+    if len(line) >= 80:
+      i = self.__FindSplit(line)
+      if i > 0:
+        line1 = line[0:i + 1]
+        self.file.write(line1 + '\n')
+        match = re.match("( +)", line1)
+        indent = ""
+        if match:
+          indent = match.group(1)
+        splitter = line[i]
+        if not splitter == ',':
+          indent = "    " + indent
+        self.__WriteLine(indent + line[i + 1:].lstrip(), True)
+        return
+    self.file.write(line)
+    if ends_with_eol:
+      self.file.write('\n')
+
+  def Close(self):
+    """Close the file."""
+    self.file.close()
+
+
+class TypeHandler(object):
+  """This class emits code for a particular type of function."""
+
+  def __init__(self):
+    pass
+
+  def InitFunction(self, func):
+    """Add or adjust anything type specific for this function."""
+    if func.GetInfo('needs_size'):
+      func.AddCmdArg(CmdArg('data_size', 'uint32'))
+
+  def AddImmediateFunction(self, generator, func):
+    """Adds an immediate version of a function."""
+    # Generate an immediate command if there is only 1 pointer arg.
+    immediate = func.GetInfo('immediate')  # can be True, False or None
+    if immediate == True or immediate == None:
+      if func.num_pointer_args == 1 or immediate:
+        generator.AddFunction(ImmediateFunction(func))
+
+  def WriteHandlerImplementation(self, func, file):
+    """Writes the handler implementation for this command."""
+    file.Write("  parse_error::ParseError result =\n")
+    file.Write("      Validate%s(this, arg_count%s);\n" %
+               (func.name, func.MakeOriginalArgString("", True)))
+    file.Write("  if (result != parse_error::kParseNoError) {\n")
+    file.Write("    return result;\n")
+    file.Write("  }\n")
+    file.Write("  %s(%s);\n" %
+               (func.GetGLFunctionName(), func.MakeOriginalArgString("")))
+
+  def WriteCmdSizeTest(self, func, file):
+    """Writes the size test for a command."""
+    file.Write("  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT\n")
+
+  def WriteFormatTest(self, func, file):
+    """Writes a format test for a command."""
+    file.Write("TEST(GLES2FormatTest, %s) {\n" % func.name)
+    file.Write("  %s cmd = { 0, };\n" % func.name)
+    file.Write("  void* next_cmd = cmd.Set(\n")
+    file.Write("      &cmd")
+    args = func.GetCmdArgs()
+    value = 11
+    for arg in args:
+      file.Write(",\n      static_cast<%s>(%d)" % (arg.type, value))
+      value += 1
+    file.Write(");\n")
+    value = 11
+    file.Write("  EXPECT_EQ(%s::kCmdId, cmd.header.command);\n" % func.name)
+    func.type_handler.WriteCmdSizeTest(func, file)
+    for arg in args:
+      file.Write("  EXPECT_EQ(static_cast<%s>(%d), cmd.%s);\n" %
+                 (arg.type, value, arg.name))
+      value += 1
+    file.Write("}\n")
+    file.Write("\n")
+
+  def WriteImmediateFormatTest(self, func, file):
+    """Writes a format test for an immediate version of a command."""
+    file.Write("TEST(GLES2FormatTest, %s) {\n" % func.name)
+    file.Write("  int8 buf[256] = { 0, };\n")
+    file.Write("  %s& cmd = *static_cast<%s*>(static_cast<void*>(&buf));\n" %
+               (func.name, func.name))
+    file.Write("  void* next_cmd = cmd.Set(\n")
+    file.Write("      &cmd")
+    args = func.GetCmdArgs()
+    value = 11
+    for arg in args:
+      file.Write(",\n      static_cast<%s>(%d)" % (arg.type, value))
+      value += 1
+    file.Write(");\n")
+    value = 11
+    file.Write("  EXPECT_EQ(%s::kCmdId, cmd.header.command);\n" % func.name)
+    func.type_handler.WriteImmediateCmdSizeTest(func, file)
+    for arg in args:
+      file.Write("  EXPECT_EQ(static_cast<%s>(%d), cmd.%s);\n" %
+                 (arg.type, value, arg.name))
+      value += 1
+    file.Write("}\n")
+    file.Write("\n")
+
+  def WriteImmediateCmdSizeTest(self, func, file):
+    """Writes a size test for an immediate version of a command."""
+    file.Write("  // TODO(gman): Compute correct size.\n")
+    file.Write("  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);\n")
+
+  def WriteImmediateHandlerImplementation (self, func, file):
+    """Writes the handler impl for the immediate version of a command."""
+    file.Write("  // Immediate version.\n")
+    file.Write("  parse_error::ParseError result =\n")
+    file.Write("      Validate%s(this, arg_count%s);\n" %
+               (func.name, func.MakeOriginalArgString("", True)))
+    file.Write("  if (result != parse_error::kParseNoError) {\n")
+    file.Write("    return result;\n")
+    file.Write("  }\n")
+    file.Write("  %s(%s);\n" %
+               (func.GetGLFunctionName(), func.MakeOriginalArgString("")))
+
+  def WriteServiceImplementation(self, func, file):
+    """Writes the service implementation for a command."""
+    file.Write(
+        "parse_error::ParseError GLES2DecoderImpl::Handle%s(\n" % func.name)
+    file.Write(
+        "    unsigned int arg_count, const gles2::%s& c) {\n" % func.name)
+    for arg in func.GetOriginalArgs():
+      arg.WriteGetCode(file)
+    func.WriteHandlerImplementation(file)
+    file.Write("  return parse_error::kParseNoError;\n")
+    file.Write("}\n")
+    file.Write("\n")
+
+  def WriteImmediateServiceImplementation(self, func, file):
+    """Writes the service implementation for an immediate version of command."""
+    file.Write(
+        "parse_error::ParseError GLES2DecoderImpl::Handle%s(\n" % func.name)
+    file.Write(
+        "    unsigned int arg_count, const gles2::%s& c) {\n" % func.name)
+    for arg in func.GetOriginalArgs():
+      arg.WriteGetCode(file)
+    func.WriteHandlerImplementation(file)
+    file.Write("  return parse_error::kParseNoError;\n")
+    file.Write("}\n")
+    file.Write("\n")
+
+  def WriteImmediateValidationCode(self, func, file):
+    """Writes the validation code for an immediate version of a command."""
+    pass
+
+  def WriteGLES2ImplementationHeader(self, func, file):
+    """Writes the GLES2 Implemention declaration."""
+    if func.can_auto_generate:
+      file.Write("%s %s(%s) {\n" %
+                 (func.return_type, func.original_name,
+                  func.MakeTypedOriginalArgString("")))
+      file.Write("  helper_->%s(%s);\n" %
+                 (func.name, func.MakeOriginalArgString("")))
+      file.Write("}\n")
+      file.Write("\n")
+    else:
+      file.Write("%s %s(%s);\n" %
+                 (func.return_type, func.original_name,
+                  func.MakeTypedOriginalArgString("")))
+      file.Write("\n")
+
+  def WriteGLES2ImplementationImpl(self, func, file):
+    """Writes the GLES2 Implemention definition."""
+    if not func.can_auto_generate:
+      file.Write("%s GLES2Implementation::%s(%s) {\n" %
+                 (func.return_type, func.original_name,
+                  func.MakeTypedOriginalArgString("")))
+      if not func.return_type == "void":
+        file.Write("  return 0;\n")
+      file.Write("}\n")
+      file.Write("\n")
+
+  def WriteImmediateCmdComputeSize(self, func, file):
+    """Writes the size computation code for the immediate version of a cmd."""
+    file.Write("  static uint32 ComputeSize(uint32 size_in_bytes) {\n")
+    file.Write("    return static_cast<uint32>(\n")
+    file.Write("        sizeof(ValueType) +  // NOLINT\n")
+    file.Write("        RoundSizeToMultipleOfEntries(size_in_bytes));\n")
+    file.Write("  }\n")
+    file.Write("\n")
+
+  def WriteImmediateCmdSetHeader(self, func, file):
+    """Writes the SetHeader function for the immediate version of a cmd."""
+    file.Write("  void SetHeader(uint32 size_in_bytes) {\n")
+    file.Write("    header.SetCmdByTotalSize<ValueType>(size_in_bytes);\n")
+    file.Write("  }\n")
+    file.Write("\n")
+
+  def WriteImmediateCmdInit(self, func, file):
+    """Writes the Init function for the immediate version of a command."""
+    file.Write("  void Init(%s) {\n" % func.MakeTypedCmdArgString("_"))
+    file.Write("    SetHeader(0);  // TODO(gman): pass in correct size\n")
+    args = func.GetCmdArgs()
+    for arg in args:
+      file.Write("    %s = _%s;\n" % (arg.name, arg.name))
+    file.Write("  }\n")
+    file.Write("\n")
+
+  def WriteImmediateCmdSet(self, func, file):
+    """Writes the Set function for the immediate version of a command."""
+    copy_args = func.MakeCmdArgString("_", False)
+    file.Write("  void* Set(void* cmd%s) {\n" %
+               func.MakeTypedCmdArgString("_", True))
+    file.Write("    // TODO(gman): compute correct size.\n")
+    file.Write("    const uint32 size = ComputeSize(0);\n")
+    file.Write("    static_cast<ValueType*>(cmd)->Init(%s);\n" % copy_args)
+    file.Write("    return NextImmediateCmdAddressTotalSize<ValueType>("
+               "cmd, size);\n")
+    file.Write("  }\n")
+    file.Write("\n")
+
+  def WriteImmediateCmdHelper(self, func, file):
+    """Writes the cmd helper definition for the immediate version of a cmd."""
+    args = func.MakeCmdArgString("")
+    file.Write("  void %s(%s) {\n" %
+               (func.name, func.MakeTypedCmdArgString("")))
+    file.Write("    const uint32 s = 0;  // TODO(gman): compute correct size\n")
+    file.Write("    gles2::%s& c = "
+               "GetImmediateCmdSpaceTotalSize<gles2::%s>(s);\n" %
+               (func.name, func.name))
+    file.Write("    c.Init(%s);\n" % args)
+    file.Write("  }\n\n")
+
+
+class CustomHandler(TypeHandler):
+  """Handler for commands that are auto-generated but require minor tweaks."""
+
+  def __init__(self):
+    TypeHandler.__init__(self)
+
+  def WriteServiceImplementation(self, func, file):
+    """Overrriden from TypeHandler."""
+    pass
+
+  def WriteImmediateCmdGetTotalSize(self, func, file):
+    """Overrriden from TypeHandler."""
+    file.Write("    uint32 total_size = 0;  // TODO(gman): get correct size.")
+
+  def WriteImmediateCmdInit(self, func, file):
+    """Overrriden from TypeHandler."""
+    file.Write("  void Init(%s) {\n" % func.MakeTypedCmdArgString("_"))
+    self.WriteImmediateCmdGetTotalSize(func, file)
+    file.Write("    SetHeader(total_size);\n")
+    args = func.GetCmdArgs()
+    for arg in args:
+      file.Write("    %s = _%s;\n" % (arg.name, arg.name))
+    file.Write("  }\n")
+    file.Write("\n")
+
+  def WriteImmediateCmdSet(self, func, file):
+    """Overrriden from TypeHandler."""
+    copy_args = func.MakeCmdArgString("_", False)
+    file.Write("  void* Set(void* cmd%s) {\n" %
+               func.MakeTypedCmdArgString("_", True))
+    self.WriteImmediateCmdGetTotalSize(func, file)
+    file.Write("    static_cast<ValueType*>(cmd)->Init(%s);\n" % copy_args)
+    file.Write("    return NextImmediateCmdAddressTotalSize<ValueType>("
+               "cmd, total_size);\n")
+    file.Write("  }\n")
+    file.Write("\n")
+
+
+class TodoHandler(CustomHandler):
+  """Handle for commands that are not yet implemented."""
+
+  def WriteImmediateFormatTest(self, func, file):
+    """Overrriden from TypeHandler."""
+    pass
+
+
+class ManualHandler(CustomHandler):
+  """Handler for commands that must be written by hand."""
+
+  def __init__(self):
+    CustomHandler.__init__(self)
+
+  def WriteServiceImplementation(self, func, file):
+    """Overrriden from TypeHandler."""
+    pass
+
+  def WriteImmediateServiceImplementation(self, func, file):
+    """Overrriden from TypeHandler."""
+    pass
+
+  def WriteImmediateFormatTest(self, func, file):
+    """Overrriden from TypeHandler."""
+    file.Write("// TODO(gman): Implement test for %s\n" % func.name)
+
+  def WriteGLES2ImplementationHeader(self, func, file):
+    """Overrriden from TypeHandler."""
+    file.Write("%s %s(%s);\n" %
+               (func.return_type, func.original_name,
+                func.MakeTypedOriginalArgString("")))
+    file.Write("\n")
+
+  def WriteGLES2ImplementationImpl(self, func, file):
+    """Overrriden from TypeHandler."""
+    pass
+
+  def WriteImmediateCmdGetTotalSize(self, func, file):
+    """Overrriden from TypeHandler."""
+    # TODO(gman): Move this data to _FUNCTION_INFO?
+    if func.name == 'ShaderSourceImmediate':
+      file.Write("    uint32 total_size = ComputeSize(_data_size);\n")
+    else:
+      CustomHandler.WriteImmediateCmdGetTotalSize(self, func, file)
+
+
+class DataHandler(CustomHandler):
+  """Handler for glBufferData, glBufferSubData, glTexImage2D, glTexSubImage2D,
+     glCompressedTexImage2D, glCompressedTexImageSub2D."""
+  def __init__(self):
+    CustomHandler.__init__(self)
+
+  def WriteServiceImplementation(self, func, file):
+    """Overrriden from TypeHandler."""
+    file.Write(
+        "parse_error::ParseError GLES2DecoderImpl::Handle%s(\n" % func.name)
+    file.Write(
+        "    unsigned int arg_count, const gles2::%s& c) {\n" % func.name)
+    for arg in func.GetCmdArgs():
+      arg.WriteGetCode(file)
+
+    # TODO(gman): Move this data to _FUNCTION_INFO?
+    if func.name == 'BufferData':
+      file.Write("  uint32 data_size = size;\n")
+    elif func.name == 'BufferSubData':
+      file.Write("  uint32 data_size = size;\n")
+    elif func.name == 'CompressedTexImage2D':
+      file.Write("  uint32 data_size = imageSize;\n")
+    elif func.name == 'CompressedTexSubImage2D':
+      file.Write("  uint32 data_size = imageSize;\n")
+    elif func.name == 'TexImage2D':
+      file.Write("  uint32 pixels_size = GLES2Util::ComputeImageDataSize(\n")
+      file.Write("      width, height, format, type, unpack_alignment_);\n")
+    elif func.name == 'TexSubImage2D':
+      file.Write("  uint32 pixels_size = GLES2Util::ComputeImageDataSize(\n")
+      file.Write("      width, height, format, type, unpack_alignment_);\n")
+    else:
+      file.Write("  uint32 data_size = 0;  // TODO(gman): get correct size!\n")
+
+    for arg in func.GetOriginalArgs():
+      arg.WriteGetAddress(file)
+    func.WriteHandlerImplementation(file)
+    file.Write("  return parse_error::kParseNoError;\n")
+    file.Write("}\n")
+    file.Write("\n")
+
+  def WriteImmediateCmdGetTotalSize(self, func, file):
+    """Overrriden from TypeHandler."""
+    # TODO(gman): Move this data to _FUNCTION_INFO?
+    if func.name == 'BufferDataImmediate':
+      file.Write("    uint32 total_size = ComputeSize(_size);\n")
+    elif func.name == 'BufferSubDataImmediate':
+        file.Write("    uint32 total_size = ComputeSize(_size);\n")
+    elif func.name == 'CompressedTexImage2DImmediate':
+        file.Write("    uint32 total_size = ComputeSize(_imageSize);\n")
+    elif func.name == 'CompressedTexSubImage2DImmediate':
+        file.Write("    uint32 total_size = ComputeSize(_imageSize);\n")
+    elif func.name == 'TexImage2DImmediate':
+      file.Write(
+          "    uint32 total_size = 0;  // TODO(gman): get correct size\n")
+    elif func.name == 'TexSubImage2DImmediate':
+      file.Write(
+          "    uint32 total_size = 0;  // TODO(gman): get correct size\n")
+
+  def WriteImmediateCmdSizeTest(self, func, file):
+    """Overrriden from TypeHandler."""
+    # TODO(gman): Move this data to _FUNCTION_INFO?
+    if func.name == 'BufferDataImmediate':
+      file.Write("    uint32 total_size = cmd.ComputeSize(cmd.size);\n")
+    elif func.name == 'BufferSubDataImmediate':
+        file.Write("    uint32 total_size = cmd.ComputeSize(cmd.size);\n")
+    elif func.name == 'CompressedTexImage2DImmediate':
+        file.Write("    uint32 total_size = cmd.ComputeSize(cmd.imageSize);\n")
+    elif func.name == 'CompressedTexSubImage2DImmediate':
+        file.Write("    uint32 total_size = cmd.ComputeSize(cmd.imageSize);\n")
+    elif func.name == 'TexImage2DImmediate':
+      file.Write(
+          "    uint32 total_size = 0;  // TODO(gman): get correct size\n")
+    elif func.name == 'TexSubImage2DImmediate':
+      file.Write(
+          "    uint32 total_size = 0;  // TODO(gman): get correct size\n")
+    file.Write("  EXPECT_EQ(sizeof(cmd), total_size);\n")
+
+  def WriteImmediateFormatTest(self, func, file):
+    """Overrriden from TypeHandler."""
+    # TODO(gman): Remove this exception.
+    file.Write("// TODO(gman): Implement test for %s\n" % func.name)
+    return
+
+  def WriteGLES2ImplementationImpl(self, func, file):
+    """Overrriden from TypeHandler."""
+    pass
+
+
+class GENnHandler(TypeHandler):
+  """Handler for glGen___ type functions."""
+
+  def __init__(self):
+    TypeHandler.__init__(self)
+
+  def InitFunction(self, func):
+    """Overrriden from TypeHandler."""
+    pass
+
+  def WriteHandlerImplementation (self, func, file):
+    """Overrriden from TypeHandler."""
+    file.Write("  parse_error::ParseError result =\n")
+    file.Write("      Validate%s(this, arg_count%s);\n" %
+               (func.name, func.MakeOriginalArgString("", True)))
+    file.Write("  if (result != parse_error::kParseNoError) {\n")
+    file.Write("    return result;\n")
+    file.Write("  }\n")
+    file.Write("  GenGLObjects<GL%sHelper>(n, %s);\n" %
+               (func.name, func.GetLastOriginalArg().name))
+
+  def WriteImmediateHandlerImplementation(self, func, file):
+    """Overrriden from TypeHandler."""
+    file.Write("  parse_error::ParseError result =\n")
+    file.Write("      Validate%s(this, arg_count%s);\n" %
+               (func.name, func.MakeOriginalArgString("", True)))
+    file.Write("  if (result != parse_error::kParseNoError) {\n")
+    file.Write("    return result;\n")
+    file.Write("  }\n")
+    file.Write("  GenGLObjects<GL%sHelper>(n, %s);\n" %
+               (func.original_name, func.GetLastOriginalArg().name))
+
+  def WriteGLES2ImplementationHeader(self, func, file):
+    """Overrriden from TypeHandler."""
+    file.Write("%s %s(%s) {\n" %
+               (func.return_type, func.original_name,
+                func.MakeTypedOriginalArgString("")))
+    file.Write("  MakeIds(%s);\n" % func.MakeOriginalArgString(""))
+    file.Write("  helper_->%sImmediate(%s);\n" %
+               (func.name, func.MakeOriginalArgString("")))
+    file.Write("}\n")
+    file.Write("\n")
+
+  def WriteGLES2ImplementationImpl(self, func, file):
+    """Overrriden from TypeHandler."""
+    pass
+
+  def WriteImmediateCmdComputeSize(self, func, file):
+    """Overrriden from TypeHandler."""
+    file.Write("  static uint32 ComputeDataSize(GLsizei n) {\n")
+    file.Write(
+        "    return static_cast<uint32>(sizeof(GLuint) * n);  // NOLINT\n")
+    file.Write("  }\n")
+    file.Write("\n")
+    file.Write("  static uint32 ComputeSize(GLsizei n) {\n")
+    file.Write("    return static_cast<uint32>(\n")
+    file.Write("        sizeof(ValueType) + ComputeDataSize(n));  // NOLINT\n")
+    file.Write("  }\n")
+    file.Write("\n")
+
+  def WriteImmediateCmdSetHeader(self, func, file):
+    """Overrriden from TypeHandler."""
+    file.Write("  void SetHeader(GLsizei n) {\n")
+    file.Write("    header.SetCmdByTotalSize<ValueType>(ComputeSize(n));\n")
+    file.Write("  }\n")
+    file.Write("\n")
+
+  def WriteImmediateCmdInit(self, func, file):
+    """Overrriden from TypeHandler."""
+    last_arg = func.GetLastOriginalArg()
+    file.Write("  void Init(%s, %s _%s) {\n" %
+               (func.MakeTypedCmdArgString("_"),
+                last_arg.type, last_arg.name))
+    file.Write("    SetHeader(_n);\n")
+    args = func.GetCmdArgs()
+    for arg in args:
+      file.Write("    %s = _%s;\n" % (arg.name, arg.name))
+    file.Write("    memcpy(ImmediateDataAddress(this),\n")
+    file.Write("           _%s, ComputeDataSize(_n));\n" % last_arg.name)
+    file.Write("  }\n")
+    file.Write("\n")
+
+  def WriteImmediateCmdSet(self, func, file):
+    """Overrriden from TypeHandler."""
+    last_arg = func.GetLastOriginalArg()
+    copy_args = func.MakeCmdArgString("_", False)
+    file.Write("  void* Set(void* cmd%s, %s _%s) {\n" %
+               (func.MakeTypedCmdArgString("_", True),
+                last_arg.type, last_arg.name))
+    file.Write("    static_cast<ValueType*>(cmd)->Init(%s, _%s);\n" %
+               (copy_args, last_arg.name))
+    file.Write("    const uint32 size = ComputeSize(_n);\n")
+    file.Write("    return NextImmediateCmdAddressTotalSize<ValueType>("
+               "cmd, size);\n")
+    file.Write("  }\n")
+    file.Write("\n")
+
+  def WriteImmediateCmdHelper(self, func, file):
+    """Overrriden from TypeHandler."""
+    args = func.MakeOriginalArgString("")
+    file.Write("  void %s(%s) {\n" %
+               (func.name, func.MakeTypedOriginalArgString("")))
+    file.Write("    const uint32 size = gles2::%s::ComputeSize(n);\n" %
+               func.name)
+    file.Write("    gles2::%s& c = "
+               "GetImmediateCmdSpaceTotalSize<gles2::%s>(size);\n" %
+               (func.name, func.name))
+    file.Write("    c.Init(%s);\n" % args)
+    file.Write("  }\n\n")
+
+  def WriteImmediateFormatTest(self, func, file):
+    """Overrriden from TypeHandler."""
+    file.Write("TEST(GLES2FormatTest, %s) {\n" % func.name)
+    file.Write("  static GLuint ids[] = { 12, 23, 34, };\n")
+    file.Write("  int8 buf[256] = { 0, };\n")
+    file.Write("  %s& cmd = *static_cast<%s*>(static_cast<void*>(&buf));\n" %
+               (func.name, func.name))
+    file.Write("  void* next_cmd = cmd.Set(\n")
+    file.Write("      &cmd")
+    args = func.GetCmdArgs()
+    value = 11
+    for arg in args:
+      file.Write(",\n      static_cast<%s>(%d)" % (arg.type, value))
+      value += 1
+    file.Write(",\n      ids);\n")
+    args = func.GetCmdArgs()
+    value = 11
+    file.Write("  EXPECT_EQ(%s::kCmdId, cmd.header.command);\n" % func.name)
+    file.Write("  EXPECT_EQ(sizeof(cmd) +\n")
+    file.Write("            RoundSizeToMultipleOfEntries(cmd.n * 4),\n")
+    file.Write("            cmd.header.size * 4);  // NOLINT\n")
+    for arg in args:
+      file.Write("  EXPECT_EQ(static_cast<%s>(%d), cmd.%s);\n" %
+                 (arg.type, value, arg.name))
+      value += 1
+    file.Write("  // TODO(gman): Check that ids were inserted;\n")
+    file.Write("}\n")
+    file.Write("\n")
+
+
+class CreateHandler(TypeHandler):
+  """Handler for glCreate___ type functions."""
+
+  def __init__(self):
+    TypeHandler.__init__(self)
+
+  def InitFunction(self, func):
+    """Overrriden from TypeHandler."""
+    func.AddCmdArg(CmdArg("client_id", 'uint32'))
+
+  def WriteHandlerImplementation (self, func, file):
+    """Overrriden from TypeHandler."""
+    file.Write("  uint32 client_id = c.client_id;\n")
+    file.Write("  parse_error::ParseError result =\n")
+    file.Write("      Validate%s(this, arg_count%s);\n" %
+               (func.name, func.MakeOriginalArgString("", True)))
+    file.Write("  if (result != parse_error::kParseNoError) {\n")
+    file.Write("    return result;\n")
+    file.Write("  }\n")
+    file.Write("  %sHelper(%s);\n" %
+               (func.name, func.MakeCmdArgString("")))
+
+  def WriteGLES2ImplementationHeader(self, func, file):
+    """Overrriden from TypeHandler."""
+    file.Write("%s %s(%s) {\n" %
+               (func.return_type, func.original_name,
+                func.MakeTypedOriginalArgString("")))
+    file.Write("  GLuint client_id;\n")
+    file.Write("  MakeIds(1, &client_id);\n")
+    file.Write("  helper_->%s(%s);\n" %
+               (func.name, func.MakeCmdArgString("")))
+    file.Write("  return client_id;\n")
+    file.Write("}\n")
+    file.Write("\n")
+
+  def WriteGLES2ImplementationImpl(self, func, file):
+    """Overrriden from TypeHandler."""
+    pass
+
+
+class DELnHandler(TypeHandler):
+  """Handler for glDelete___ type functions."""
+
+  def __init__(self):
+    TypeHandler.__init__(self)
+
+  def WriteHandlerImplementation (self, func, file):
+    """Overrriden from TypeHandler."""
+    file.Write("  parse_error::ParseError result =\n")
+    file.Write("      Validate%s(this, arg_count%s);\n" %
+               (func.name, func.MakeOriginalArgString("", True)))
+    file.Write("  if (result != parse_error::kParseNoError) {\n")
+    file.Write("    return result;\n")
+    file.Write("  }\n")
+    file.Write("  DeleteGLObjects<GL%sHelper>(n, %s);\n" %
+               (func.name, func.GetLastOriginalArg().name))
+
+  def WriteImmediateHandlerImplementation (self, func, file):
+    """Overrriden from TypeHandler."""
+    file.Write("  parse_error::ParseError result =\n")
+    file.Write("      Validate%s(this, arg_count%s);\n" %
+               (func.name, func.MakeOriginalArgString("", True)))
+    file.Write("  if (result != parse_error::kParseNoError) {\n")
+    file.Write("    return result;\n")
+    file.Write("  }\n")
+    file.Write("  DeleteGLObjects<GL%sHelper>(n, %s);\n" %
+               (func.original_name, func.GetLastOriginalArg().name))
+
+  def WriteGLES2ImplementationHeader(self, func, file):
+    """Overrriden from TypeHandler."""
+    file.Write("%s %s(%s) {\n" %
+               (func.return_type, func.original_name,
+                func.MakeTypedOriginalArgString("")))
+    file.Write("  FreeIds(%s);\n" % func.MakeOriginalArgString(""))
+    file.Write("  helper_->%sImmediate(%s);\n" %
+               (func.name, func.MakeOriginalArgString("")))
+    file.Write("}\n")
+    file.Write("\n")
+
+  def WriteGLES2ImplementationImpl(self, func, file):
+    """Overrriden from TypeHandler."""
+    pass
+
+  def WriteImmediateCmdComputeSize(self, func, file):
+    """Overrriden from TypeHandler."""
+    file.Write("  static uint32 ComputeDataSize(GLsizei n) {\n")
+    file.Write(
+        "    return static_cast<uint32>(sizeof(GLuint) * n);  // NOLINT\n")
+    file.Write("  }\n")
+    file.Write("\n")
+    file.Write("  static uint32 ComputeSize(GLsizei n) {\n")
+    file.Write("    return static_cast<uint32>(\n")
+    file.Write("        sizeof(ValueType) + ComputeDataSize(n));  // NOLINT\n")
+    file.Write("  }\n")
+    file.Write("\n")
+
+  def WriteImmediateCmdSetHeader(self, func, file):
+    """Overrriden from TypeHandler."""
+    file.Write("  void SetHeader(GLsizei n) {\n")
+    file.Write("    header.SetCmdByTotalSize<ValueType>(ComputeSize(n));\n")
+    file.Write("  }\n")
+    file.Write("\n")
+
+  def WriteImmediateCmdInit(self, func, file):
+    """Overrriden from TypeHandler."""
+    last_arg = func.GetLastOriginalArg()
+    file.Write("  void Init(%s, %s _%s) {\n" %
+               (func.MakeTypedCmdArgString("_"),
+                last_arg.type, last_arg.name))
+    file.Write("    SetHeader(_n);\n")
+    args = func.GetCmdArgs()
+    for arg in args:
+      file.Write("    %s = _%s;\n" % (arg.name, arg.name))
+    file.Write("    memcpy(ImmediateDataAddress(this),\n")
+    file.Write("           _%s, ComputeDataSize(_n));\n" % last_arg.name)
+    file.Write("  }\n")
+    file.Write("\n")
+
+  def WriteImmediateCmdSet(self, func, file):
+    """Overrriden from TypeHandler."""
+    last_arg = func.GetLastOriginalArg()
+    copy_args = func.MakeCmdArgString("_", False)
+    file.Write("  void* Set(void* cmd%s, %s _%s) {\n" %
+               (func.MakeTypedCmdArgString("_", True),
+                last_arg.type, last_arg.name))
+    file.Write("    static_cast<ValueType*>(cmd)->Init(%s, _%s);\n" %
+               (copy_args, last_arg.name))
+    file.Write("    const uint32 size = ComputeSize(_n);\n")
+    file.Write("    return NextImmediateCmdAddressTotalSize<ValueType>("
+               "cmd, size);\n")
+    file.Write("  }\n")
+    file.Write("\n")
+
+  def WriteImmediateCmdHelper(self, func, file):
+    """Overrriden from TypeHandler."""
+    args = func.MakeOriginalArgString("")
+    file.Write("  void %s(%s) {\n" %
+               (func.name, func.MakeTypedOriginalArgString("")))
+    file.Write("    const uint32 size = gles2::%s::ComputeSize(n);\n" %
+               func.name)
+    file.Write("    gles2::%s& c = "
+               "GetImmediateCmdSpaceTotalSize<gles2::%s>(size);\n" %
+               (func.name, func.name))
+    file.Write("    c.Init(%s);\n" % args)
+    file.Write("  }\n\n")
+
+  def WriteImmediateFormatTest(self, func, file):
+    """Overrriden from TypeHandler."""
+    file.Write("TEST(GLES2FormatTest, %s) {\n" % func.name)
+    file.Write("  static GLuint ids[] = { 12, 23, 34, };\n")
+    file.Write("  int8 buf[256] = { 0, };\n")
+    file.Write("  %s& cmd = *static_cast<%s*>(static_cast<void*>(&buf));\n" %
+               (func.name, func.name))
+    file.Write("  void* next_cmd = cmd.Set(\n")
+    file.Write("      &cmd")
+    args = func.GetCmdArgs()
+    value = 11
+    for arg in args:
+      file.Write(",\n      static_cast<%s>(%d)" % (arg.type, value))
+      value += 1
+    file.Write(",\n      ids);\n")
+    args = func.GetCmdArgs()
+    value = 11
+    file.Write("  EXPECT_EQ(%s::kCmdId, cmd.header.command);\n" % func.name)
+    file.Write("  EXPECT_EQ(sizeof(cmd) +\n")
+    file.Write("            RoundSizeToMultipleOfEntries(cmd.n * 4),\n")
+    file.Write("            cmd.header.size * 4);  // NOLINT\n")
+    for arg in args:
+      file.Write("  EXPECT_EQ(static_cast<%s>(%d), cmd.%s);\n" %
+                 (arg.type, value, arg.name))
+      value += 1
+    file.Write("  // TODO(gman): Check that ids were inserted;\n")
+    file.Write("}\n")
+    file.Write("\n")
+
+
+class GETnHandler(TypeHandler):
+  """Handler for GETn for glGetBooleanv, glGetFloatv, ... type functions."""
+
+  def __init__(self):
+    TypeHandler.__init__(self)
+
+  def AddImmediateFunction(self, generator, func):
+    """Overrriden from TypeHandler."""
+    pass
+
+  def WriteServiceImplementation(self, func, file):
+    """Overrriden from TypeHandler."""
+    file.Write(
+        "parse_error::ParseError GLES2DecoderImpl::Handle%s(\n" % func.name)
+    file.Write(
+        "    unsigned int arg_count, const gles2::%s& c) {\n" % func.name)
+    last_arg = func.GetLastOriginalArg()
+
+    all_but_last_args = func.GetOriginalArgs()[:-1]
+    for arg in all_but_last_args:
+      arg.WriteGetCode(file)
+
+    file.Write("  %s params;\n" % last_arg.type)
+    file.Write("  GLsizei num_values = util_.GLGetNumValuesReturned(pname);\n")
+    file.Write("  uint32 params_size = num_values * sizeof(*params);\n")
+    file.Write("  params = GetSharedMemoryAs<%s>(\n" % last_arg.type)
+    file.Write("      c.params_shm_id, c.params_shm_offset, params_size);\n")
+    func.WriteHandlerImplementation(file)
+    file.Write("  return parse_error::kParseNoError;\n")
+    file.Write("}\n")
+    file.Write("\n")
+
+  def WriteGLES2ImplementationHeader(self, func, file):
+    """Overrriden from TypeHandler."""
+    file.Write("%s %s(%s) {\n" %
+               (func.return_type, func.original_name,
+                func.MakeTypedOriginalArgString("")))
+    all_but_last_args = func.GetOriginalArgs()[:-1]
+    arg_string = (
+        ", ".join(["%s" % arg.name for arg in all_but_last_args]))
+    file.Write("  helper_->%s(%s, shared_memory_.GetId(), 0);\n" %
+               (func.name, arg_string))
+    file.Write("  int32 token = helper_->InsertToken();\n")
+    file.Write("  helper_->WaitForToken(token);\n")
+    file.Write("  GLsizei num_values = util_.GLGetNumValuesReturned(pname);\n")
+    file.Write("  memcpy(params, shared_memory_.GetAddress(0),\n")
+    file.Write("         num_values * sizeof(*params));\n")
+    file.Write("}\n")
+    file.Write("\n")
+
+  def WriteGLES2ImplementationImpl(self, func, file):
+    """Overrriden from TypeHandler."""
+    pass
+
+
+class PUTHandler(TypeHandler):
+  """Handler for glTexParameter_v, glVertexAttrib_v functions."""
+
+  def __init__(self):
+    TypeHandler.__init__(self)
+
+  def WriteImmediateValidationCode(self, func, file):
+    """Overrriden from TypeHandler."""
+    file.Write("  if (!CheckImmediateDataSize<%s>("
+               "arg_count, 1, sizeof(%s), %d)) {\n" %
+               (func.name, func.info.data_type, func.info.count))
+    file.Write("    return parse_error::kParseOutOfBounds;\n")
+    file.Write("  }\n")
+
+  def WriteGLES2ImplementationHeader(self, func, file):
+    """Overrriden from TypeHandler."""
+    file.Write("%s %s(%s) {\n" %
+               (func.return_type, func.original_name,
+                func.MakeTypedOriginalArgString("")))
+    file.Write("  helper_->%sImmediate(%s);\n" %
+               (func.name, func.MakeOriginalArgString("")))
+    file.Write("}\n")
+    file.Write("\n")
+
+  def WriteGLES2ImplementationImpl(self, func, file):
+    """Overrriden from TypeHandler."""
+    pass
+
+  def WriteImmediateCmdComputeSize(self, func, file):
+    """Overrriden from TypeHandler."""
+    file.Write("  static uint32 ComputeDataSize() {\n")
+    file.Write("    return static_cast<uint32>(\n")
+    file.Write("        sizeof(%s) * %d);  // NOLINT\n" %
+               (func.info.data_type, func.info.count))
+    file.Write("  }\n")
+    file.Write("\n")
+    file.Write("  static uint32 ComputeSize() {\n")
+    file.Write("    return static_cast<uint32>(\n")
+    file.Write(
+        "        sizeof(ValueType) + ComputeDataSize());  // NOLINT\n")
+    file.Write("  }\n")
+    file.Write("\n")
+
+  def WriteImmediateCmdSetHeader(self, func, file):
+    """Overrriden from TypeHandler."""
+    file.Write("  void SetHeader() {\n")
+    file.Write(
+        "    header.SetCmdByTotalSize<ValueType>(ComputeSize());\n")
+    file.Write("  }\n")
+    file.Write("\n")
+
+  def WriteImmediateCmdInit(self, func, file):
+    """Overrriden from TypeHandler."""
+    last_arg = func.GetLastOriginalArg()
+    file.Write("  void Init(%s, %s _%s) {\n" %
+               (func.MakeTypedCmdArgString("_"),
+                last_arg.type, last_arg.name))
+    file.Write("    SetHeader();\n")
+    args = func.GetCmdArgs()
+    for arg in args:
+      file.Write("    %s = _%s;\n" % (arg.name, arg.name))
+    file.Write("    memcpy(ImmediateDataAddress(this),\n")
+    file.Write("           _%s, ComputeDataSize());\n" % last_arg.name)
+    file.Write("  }\n")
+    file.Write("\n")
+
+  def WriteImmediateCmdSet(self, func, file):
+    """Overrriden from TypeHandler."""
+    last_arg = func.GetLastOriginalArg()
+    copy_args = func.MakeCmdArgString("_", False)
+    file.Write("  void* Set(void* cmd%s, %s _%s) {\n" %
+               (func.MakeTypedCmdArgString("_", True),
+                last_arg.type, last_arg.name))
+    file.Write("    static_cast<ValueType*>(cmd)->Init(%s, _%s);\n" %
+               (copy_args, last_arg.name))
+    file.Write("    const uint32 size = ComputeSize();\n")
+    file.Write("    return NextImmediateCmdAddressTotalSize<ValueType>("
+               "cmd, size);\n")
+    file.Write("  }\n")
+    file.Write("\n")
+
+  def WriteImmediateCmdHelper(self, func, file):
+    """Overrriden from TypeHandler."""
+    args = func.MakeOriginalArgString("")
+    file.Write("  void %s(%s) {\n" %
+               (func.name, func.MakeTypedOriginalArgString("")))
+    file.Write("    const uint32 size = gles2::%s::ComputeSize();\n" %
+               func.name)
+    file.Write("    gles2::%s& c = "
+               "GetImmediateCmdSpaceTotalSize<gles2::%s>(size);\n" %
+               (func.name, func.name))
+    file.Write("    c.Init(%s);\n" % args)
+    file.Write("  }\n\n")
+
+  def WriteImmediateFormatTest(self, func, file):
+    """Overrriden from TypeHandler."""
+    file.Write("TEST(GLES2FormatTest, %s) {\n" % func.name)
+    file.Write("  const int kSomeBaseValueToTestWith = 51;\n")
+    file.Write("  static %s data[] = {\n" % func.info.data_type)
+    for v in range(0, func.info.count):
+      file.Write("    static_cast<%s>(kSomeBaseValueToTestWith + %d),\n" %
+                 (func.info.data_type, v))
+    file.Write("  };\n")
+    file.Write("  int8 buf[256] = { 0, };\n")
+    file.Write("  %s& cmd = *static_cast<%s*>(static_cast<void*>(&buf));\n" %
+               (func.name, func.name))
+    file.Write("  void* next_cmd = cmd.Set(\n")
+    file.Write("      &cmd")
+    args = func.GetCmdArgs()
+    value = 11
+    for arg in args:
+      file.Write(",\n      static_cast<%s>(%d)" % (arg.type, value))
+      value += 1
+    file.Write(",\n      data);\n")
+    args = func.GetCmdArgs()
+    value = 11
+    file.Write("  EXPECT_EQ(%s::kCmdId, cmd.header.command);\n" % func.name)
+    file.Write("  EXPECT_EQ(sizeof(cmd) +\n")
+    file.Write("            RoundSizeToMultipleOfEntries(sizeof(data)),\n")
+    file.Write("            cmd.header.size * 4);  // NOLINT\n")
+    for arg in args:
+      file.Write("  EXPECT_EQ(static_cast<%s>(%d), cmd.%s);\n" %
+                 (arg.type, value, arg.name))
+      value += 1
+    file.Write("  // TODO(gman): Check that data was inserted;\n")
+    file.Write("}\n")
+    file.Write("\n")
+
+
+class PUTnHandler(TypeHandler):
+  """Handler for PUTn 'glUniform__v' type functions."""
+
+  def __init__(self):
+    TypeHandler.__init__(self)
+
+  def WriteImmediateValidationCode(self, func, file):
+    """Overrriden from TypeHandler."""
+    file.Write("  if (!CheckImmediateDataSize<%s>("
+               "arg_count, count, sizeof(%s), %d)) {\n" %
+               (func.name, func.info.data_type, func.info.count))
+    file.Write("    return parse_error::kParseOutOfBounds;\n")
+    file.Write("  }\n")
+
+  def WriteGLES2ImplementationHeader(self, func, file):
+    """Overrriden from TypeHandler."""
+    file.Write("%s %s(%s) {\n" %
+               (func.return_type, func.original_name,
+                func.MakeTypedOriginalArgString("")))
+    file.Write("  helper_->%sImmediate(%s);\n" %
+               (func.name, func.MakeOriginalArgString("")))
+    file.Write("}\n")
+    file.Write("\n")
+
+  def WriteGLES2ImplementationImpl(self, func, file):
+    """Overrriden from TypeHandler."""
+    pass
+
+  def WriteImmediateCmdComputeSize(self, func, file):
+    """Overrriden from TypeHandler."""
+    file.Write("  static uint32 ComputeDataSize(GLsizei count) {\n")
+    file.Write("    return static_cast<uint32>(\n")
+    file.Write("        sizeof(%s) * %d * count);  // NOLINT\n" %
+               (func.info.data_type, func.info.count))
+    file.Write("  }\n")
+    file.Write("\n")
+    file.Write("  static uint32 ComputeSize(GLsizei count) {\n")
+    file.Write("    return static_cast<uint32>(\n")
+    file.Write(
+        "        sizeof(ValueType) + ComputeDataSize(count));  // NOLINT\n")
+    file.Write("  }\n")
+    file.Write("\n")
+
+  def WriteImmediateCmdSetHeader(self, func, file):
+    """Overrriden from TypeHandler."""
+    file.Write("  void SetHeader(GLsizei count) {\n")
+    file.Write(
+        "    header.SetCmdByTotalSize<ValueType>(ComputeSize(count));\n")
+    file.Write("  }\n")
+    file.Write("\n")
+
+  def WriteImmediateCmdInit(self, func, file):
+    """Overrriden from TypeHandler."""
+    last_arg = func.GetLastOriginalArg()
+    file.Write("  void Init(%s, %s _%s) {\n" %
+               (func.MakeTypedCmdArgString("_"),
+                last_arg.type, last_arg.name))
+    file.Write("    SetHeader(_count);\n")
+    args = func.GetCmdArgs()
+    for arg in args:
+      file.Write("    %s = _%s;\n" % (arg.name, arg.name))
+    file.Write("    memcpy(ImmediateDataAddress(this),\n")
+    file.Write("           _%s, ComputeDataSize(_count));\n" % last_arg.name)
+    file.Write("  }\n")
+    file.Write("\n")
+
+  def WriteImmediateCmdSet(self, func, file):
+    """Overrriden from TypeHandler."""
+    last_arg = func.GetLastOriginalArg()
+    copy_args = func.MakeCmdArgString("_", False)
+    file.Write("  void* Set(void* cmd%s, %s _%s) {\n" %
+               (func.MakeTypedCmdArgString("_", True),
+                last_arg.type, last_arg.name))
+    file.Write("    static_cast<ValueType*>(cmd)->Init(%s, _%s);\n" %
+               (copy_args, last_arg.name))
+    file.Write("    const uint32 size = ComputeSize(_count);\n")
+    file.Write("    return NextImmediateCmdAddressTotalSize<ValueType>("
+               "cmd, size);\n")
+    file.Write("  }\n")
+    file.Write("\n")
+
+  def WriteImmediateCmdHelper(self, func, file):
+    """Overrriden from TypeHandler."""
+    args = func.MakeOriginalArgString("")
+    file.Write("  void %s(%s) {\n" %
+               (func.name, func.MakeTypedOriginalArgString("")))
+    file.Write("    const uint32 size = gles2::%s::ComputeSize(count);\n" %
+               func.name)
+    file.Write("    gles2::%s& c = "
+               "GetImmediateCmdSpaceTotalSize<gles2::%s>(size);\n" %
+               (func.name, func.name))
+    file.Write("    c.Init(%s);\n" % args)
+    file.Write("  }\n\n")
+
+  def WriteImmediateFormatTest(self, func, file):
+    """Overrriden from TypeHandler."""
+    file.Write("TEST(GLES2FormatTest, %s) {\n" % func.name)
+    file.Write("  const int kSomeBaseValueToTestWith = 51;\n")
+    file.Write("  static %s data[] = {\n" % func.info.data_type)
+    for v in range(0, func.info.count * 2):
+      file.Write("    static_cast<%s>(kSomeBaseValueToTestWith + %d),\n" %
+                 (func.info.data_type, v))
+    file.Write("  };\n")
+    file.Write("  int8 buf[256] = { 0, };\n")
+    file.Write("  %s& cmd = *static_cast<%s*>(static_cast<void*>(&buf));\n" %
+               (func.name, func.name))
+    file.Write("  void* next_cmd = cmd.Set(\n")
+    file.Write("      &cmd")
+    args = func.GetCmdArgs()
+    value = 1
+    for arg in args:
+      file.Write(",\n      static_cast<%s>(%d)" % (arg.type, value))
+      value += 1
+    file.Write(",\n      data);\n")
+    args = func.GetCmdArgs()
+    value = 1
+    file.Write("  EXPECT_EQ(%s::kCmdId, cmd.header.command);\n" % func.name)
+    file.Write("  EXPECT_EQ(sizeof(cmd) +\n")
+    file.Write("            RoundSizeToMultipleOfEntries(sizeof(data)),\n")
+    file.Write("            cmd.header.size * 4);  // NOLINT\n")
+    for arg in args:
+      file.Write("  EXPECT_EQ(static_cast<%s>(%d), cmd.%s);\n" %
+                 (arg.type, value, arg.name))
+      value += 1
+    file.Write("  // TODO(gman): Check that data was inserted;\n")
+    file.Write("}\n")
+    file.Write("\n")
+
+
+class GLcharHandler(TypeHandler):
+  """Handler for functions that pass a single string ."""
+
+  def __init__(self):
+    TypeHandler.__init__(self)
+
+  def InitFunction(self, func):
+    """Overrriden from TypeHandler."""
+    func.AddCmdArg(CmdArg('data_size', 'uint32'))
+
+  def WriteServiceImplementation(self, func, file):
+    """Overrriden from TypeHandler."""
+    file.Write(
+        "parse_error::ParseError GLES2DecoderImpl::Handle%s(\n" % func.name)
+    file.Write(
+        "    unsigned int arg_count, const gles2::%s& c) {\n" % func.name)
+    last_arg = func.GetLastOriginalArg()
+
+    all_but_last_arg = func.GetOriginalArgs()[:-1]
+    for arg in all_but_last_arg:
+      arg.WriteGetCode(file)
+
+    file.Write("  uint32 name_size = c.data_size;\n")
+    file.Write("  const char* name = GetSharedMemoryAs<%s>(\n" %
+               last_arg.type)
+    file.Write("      c.%s_shm_id, c.%s_shm_offset, name_size);\n" %
+               (last_arg.name, last_arg.name))
+    file.Write("  parse_error::ParseError result =\n")
+    file.Write("      Validate%s(this, arg_count%s);\n" %
+               (func.name, func.MakeOriginalArgString("", True)))
+    file.Write("  if (result != parse_error::kParseNoError) {\n")
+    file.Write("    return result;\n")
+    file.Write("  }\n")
+    arg_string = ", ".join(["%s" % arg.name for arg in all_but_last_arg])
+    file.Write("  String name_str(name, name_size);\n")
+    file.Write("  %s(%s, name_str.c_str());\n" %
+               (func.GetGLFunctionName(), arg_string))
+    file.Write("  return parse_error::kParseNoError;\n")
+    file.Write("}\n")
+    file.Write("\n")
+
+  def WriteImmediateServiceImplementation(self, func, file):
+    """Overrriden from TypeHandler."""
+    file.Write(
+        "parse_error::ParseError GLES2DecoderImpl::Handle%s(\n" % func.name)
+    file.Write(
+        "    unsigned int arg_count, const gles2::%s& c) {\n" % func.name)
+    last_arg = func.GetLastOriginalArg()
+
+    all_but_last_arg = func.GetOriginalArgs()[:-1]
+    for arg in all_but_last_arg:
+      arg.WriteGetCode(file)
+
+    file.Write("  uint32 name_size = c.data_size;\n")
+    file.Write(
+        "  const char* name = GetImmediateDataAs<const char*>(c);\n")
+    file.Write("  // TODO(gman): Make sure validate checks arg_count\n")
+    file.Write("  //     covers data_size.\n")
+    file.Write("  parse_error::ParseError result =\n")
+    file.Write("      Validate%s(this, arg_count%s);\n" %
+               (func.name, func.MakeOriginalArgString("", True)))
+    file.Write("  if (result != parse_error::kParseNoError) {\n")
+    file.Write("    return result;\n")
+    file.Write("  }\n")
+    arg_string = ", ".join(["%s" % arg.name for arg in all_but_last_arg])
+    file.Write("  String name_str(name, name_size);\n")
+    file.Write("  %s(%s, name_str.c_str());\n" %
+              (func.GetGLFunctionName(), arg_string))
+    file.Write("  return parse_error::kParseNoError;\n")
+    file.Write("}\n")
+    file.Write("\n")
+
+  def WriteGLES2ImplementationHeader(self, func, file):
+    """Overrriden from TypeHandler."""
+    file.Write("%s %s(%s) {\n" %
+               (func.return_type, func.original_name,
+                func.MakeTypedOriginalArgString("")))
+    file.Write("  // TODO(gman): This needs to change to use SendString.\n")
+    file.Write("  helper_->%sImmediate(%s);\n" %
+               (func.name, func.MakeOriginalArgString("")))
+    file.Write("}\n")
+    file.Write("\n")
+
+  def WriteGLES2ImplementationImpl(self, func, file):
+    """Overrriden from TypeHandler."""
+    pass
+
+  def WriteImmediateCmdComputeSize(self, func, file):
+    """Overrriden from TypeHandler."""
+    file.Write("  static uint32 ComputeDataSize(const char* s) {\n")
+    file.Write("    return strlen(s);\n")
+    file.Write("  }\n")
+    file.Write("\n")
+    file.Write("  static uint32 ComputeSize(const char* s) {\n")
+    file.Write("    return static_cast<uint32>(\n")
+    file.Write("        sizeof(ValueType) + ComputeDataSize(s));  // NOLINT\n")
+    file.Write("  }\n")
+    file.Write("\n")
+
+  def WriteImmediateCmdSetHeader(self, func, file):
+    """Overrriden from TypeHandler."""
+    file.Write("  void SetHeader(const char* s) {\n")
+    file.Write("    header.SetCmdByTotalSize<ValueType>(ComputeSize(s));\n")
+    file.Write("  }\n")
+    file.Write("\n")
+
+  def WriteImmediateCmdInit(self, func, file):
+    """Overrriden from TypeHandler."""
+    last_arg = func.GetLastOriginalArg()
+    file.Write("  void Init(%s) {\n" % func.MakeTypedOriginalArgString("_"))
+    file.Write("    SetHeader(_%s);\n" % last_arg.name)
+    args = func.GetCmdArgs()[:-1]
+    for arg in args:
+      file.Write("    %s = _%s;\n" % (arg.name, arg.name))
+    file.Write("    data_size = strlen(_%s);\n" % last_arg.name)
+    file.Write("    memcpy(ImmediateDataAddress(this), _%s, data_size);\n" %
+               last_arg.name)
+    file.Write("  }\n")
+    file.Write("\n")
+
+  def WriteImmediateCmdSet(self, func, file):
+    """Overrriden from TypeHandler."""
+    last_arg = func.GetLastOriginalArg()
+    file.Write("  void* Set(void* cmd%s) {\n" %
+               func.MakeTypedOriginalArgString("_", True))
+    file.Write("    static_cast<ValueType*>(cmd)->Init(%s);\n" %
+               func.MakeOriginalArgString("_"))
+    file.Write("    const uint32 size = ComputeSize(_%s);\n" % last_arg.name)
+    file.Write("    return NextImmediateCmdAddressTotalSize<ValueType>("
+               "cmd, size);\n")
+    file.Write("  }\n")
+    file.Write("\n")
+
+  def WriteImmediateCmdHelper(self, func, file):
+    """Overrriden from TypeHandler."""
+    args = func.MakeOriginalArgString("")
+    last_arg = func.GetLastOriginalArg()
+    file.Write("  void %s(%s) {\n" %
+               (func.name, func.MakeTypedOriginalArgString("")))
+    file.Write("    const uint32 size = gles2::%s::ComputeSize(%s);\n" %
+               (func.name, last_arg.name))
+    file.Write("    gles2::%s& c = GetImmediateCmdSpaceTotalSize<gles2::%s>("
+               "size);\n" %
+               (func.name, func.name))
+    file.Write("    c.Init(%s);\n" % args)
+    file.Write("  }\n\n")
+
+  def WriteImmediateFormatTest(self, func, file):
+    """Overrriden from TypeHandler."""
+    file.Write("TEST(GLES2FormatTest, %s) {\n" % func.name)
+    file.Write("  int8 buf[256] = { 0, };\n")
+    file.Write("  %s& cmd = *static_cast<%s*>(static_cast<void*>(&buf));\n" %
+               (func.name, func.name))
+    file.Write("  static const char* const test_str = \"test string\";\n")
+    file.Write("  void* next_cmd = cmd.Set(\n")
+    file.Write("      &cmd")
+    all_but_last_arg = func.GetCmdArgs()[:-1]
+    value = 11
+    for arg in all_but_last_arg:
+      file.Write(",\n      static_cast<%s>(%d)" % (arg.type, value))
+      value += 1
+    file.Write(",\n      test_str);\n")
+    value = 11
+    file.Write("  EXPECT_EQ(%s::kCmdId, cmd.header.command);\n" % func.name)
+    file.Write("  EXPECT_EQ(sizeof(cmd) +  // NOLINT\n")
+    file.Write("            RoundSizeToMultipleOfEntries(strlen(test_str)),\n")
+    file.Write("            cmd.header.size * 4);\n")
+    for arg in all_but_last_arg:
+      file.Write("  EXPECT_EQ(static_cast<%s>(%d), cmd.%s);\n" %
+                 (arg.type, value, arg.name))
+      value += 1
+    file.Write("  // TODO(gman): check that string got copied.\n")
+    file.Write("}\n")
+    file.Write("\n")
+
+class GetGLcharHandler(GLcharHandler):
+  """Handler for glGetAttibLoc, glGetUniformLoc."""
+
+  def __init__(self):
+    GLcharHandler.__init__(self)
+
+  def WriteServiceImplementation(self, func, file):
+    """Overrriden from TypeHandler."""
+    file.Write(
+        "parse_error::ParseError GLES2DecoderImpl::Handle%s(\n" % func.name)
+    file.Write(
+        "    unsigned int arg_count, const gles2::%s& c) {\n" % func.name)
+    last_arg = func.GetLastOriginalArg()
+
+    all_but_last_arg = func.GetOriginalArgs()[:-1]
+    for arg in all_but_last_arg:
+      arg.WriteGetCode(file)
+
+    file.Write("  uint32 name_size = c.data_size;\n")
+    file.Write("  const char* name = GetSharedMemoryAs<%s>(\n" %
+               last_arg.type)
+    file.Write("      c.%s_shm_id, c.%s_shm_offset, name_size);\n" %
+               (last_arg.name, last_arg.name))
+    file.Write("  parse_error::ParseError result =\n")
+    file.Write("      Validate%s(this, arg_count%s);\n" %
+               (func.name, func.MakeOriginalArgString("", True)))
+    file.Write("  if (result != parse_error::kParseNoError) {\n")
+    file.Write("    return result;\n")
+    file.Write("  }\n")
+    arg_string = ", ".join(["%s" % arg.name for arg in all_but_last_arg])
+    file.Write("  String name_str(name, name_size);\n")
+    file.Write("  GLint location = %s(%s, name_str.c_str());\n" %
+               (func.GetGLFunctionName(), arg_string))
+    file.Write("  DCHECK(false);  // TODO: return result.\n")
+    file.Write("  return parse_error::kParseNoError;\n")
+    file.Write("}\n")
+    file.Write("\n")
+
+  def WriteImmediateServiceImplementation(self, func, file):
+    """Overrriden from TypeHandler."""
+    file.Write(
+        "parse_error::ParseError GLES2DecoderImpl::Handle%s(\n" % func.name)
+    file.Write(
+        "    unsigned int arg_count, const gles2::%s& c) {\n" % func.name)
+    last_arg = func.GetLastOriginalArg()
+
+    all_but_last_arg = func.GetOriginalArgs()[:-1]
+    for arg in all_but_last_arg:
+      arg.WriteGetCode(file)
+
+    file.Write("  uint32 name_size = c.data_size;\n")
+    file.Write(
+        "  const char* name = GetImmediateDataAs<const char*>(c);\n")
+    file.Write("  // TODO(gman): Make sure validate checks arg_count\n")
+    file.Write("  //     covers data_size.\n")
+    file.Write("  parse_error::ParseError result =\n")
+    file.Write("      Validate%s(this, arg_count%s);\n" %
+               (func.name, func.MakeOriginalArgString("", True)))
+    file.Write("  if (result != parse_error::kParseNoError) {\n")
+    file.Write("    return result;\n")
+    file.Write("  }\n")
+    arg_string = ", ".join(["%s" % arg.name for arg in all_but_last_arg])
+    file.Write("  String name_str(name, name_size);\n")
+    file.Write("  GLint location = %s(%s, name_str.c_str());\n" %
+              (func.GetGLFunctionName(), arg_string))
+    file.Write("  DCHECK(false);  // TODO: return result.\n")
+    file.Write("  return parse_error::kParseNoError;\n")
+    file.Write("}\n")
+    file.Write("\n")
+
+  def WriteGLES2ImplementationHeader(self, func, file):
+    """Overrriden from TypeHandler."""
+    file.Write("%s %s(%s) {\n" %
+               (func.return_type, func.original_name,
+                func.MakeTypedOriginalArgString("")))
+    file.Write("  // TODO(gman): This needs to change to use SendString.\n")
+    file.Write("  GLint* result = shared_memory_.GetAddressAs<GLint*>(0);\n")
+    file.Write("  DCHECK(false);  // pass in shared memory\n")
+    file.Write("  helper_->%sImmediate(%s);\n" %
+               (func.name, func.MakeOriginalArgString("")))
+    file.Write("  int32 token = helper_->InsertToken();\n")
+    file.Write("  helper_->WaitForToken(token);\n")
+    file.Write("  return *result;\n")
+    file.Write("}\n")
+    file.Write("\n")
+
+  def WriteGLES2ImplementationImpl(self, func, file):
+    """Overrriden from TypeHandler."""
+    pass
+
+  def WriteImmediateCmdComputeSize(self, func, file):
+    """Overrriden from TypeHandler."""
+    file.Write("  static uint32 ComputeDataSize(const char* s) {\n")
+    file.Write("    return strlen(s);\n")
+    file.Write("  }\n")
+    file.Write("\n")
+    file.Write("  static uint32 ComputeSize(const char* s) {\n")
+    file.Write("    return static_cast<uint32>(\n")
+    file.Write("        sizeof(ValueType) + ComputeDataSize(s));  // NOLINT\n")
+    file.Write("  }\n")
+    file.Write("\n")
+
+  def WriteImmediateCmdSetHeader(self, func, file):
+    """Overrriden from TypeHandler."""
+    file.Write("  void SetHeader(const char* s) {\n")
+    file.Write("    header.SetCmdByTotalSize<ValueType>(ComputeSize(s));\n")
+    file.Write("  }\n")
+    file.Write("\n")
+
+  def WriteImmediateCmdInit(self, func, file):
+    """Overrriden from TypeHandler."""
+    last_arg = func.GetLastOriginalArg()
+    file.Write("  void Init(%s) {\n" % func.MakeTypedOriginalArgString("_"))
+    file.Write("    SetHeader(_%s);\n" % last_arg.name)
+    args = func.GetCmdArgs()[:-1]
+    for arg in args:
+      file.Write("    %s = _%s;\n" % (arg.name, arg.name))
+    file.Write("    data_size = strlen(_%s);\n" % last_arg.name)
+    file.Write("    memcpy(ImmediateDataAddress(this), _%s, data_size);\n" %
+               last_arg.name)
+    file.Write("  }\n")
+    file.Write("\n")
+
+  def WriteImmediateCmdSet(self, func, file):
+    """Overrriden from TypeHandler."""
+    last_arg = func.GetLastOriginalArg()
+    file.Write("  void* Set(void* cmd%s) {\n" %
+               func.MakeTypedOriginalArgString("_", True))
+    file.Write("    static_cast<ValueType*>(cmd)->Init(%s);\n" %
+               func.MakeOriginalArgString("_"))
+    file.Write("    const uint32 size = ComputeSize(_%s);\n" % last_arg.name)
+    file.Write("    return NextImmediateCmdAddressTotalSize<ValueType>("
+               "cmd, size);\n")
+    file.Write("  }\n")
+    file.Write("\n")
+
+  def WriteImmediateCmdHelper(self, func, file):
+    """Overrriden from TypeHandler."""
+    args = func.MakeOriginalArgString("")
+    last_arg = func.GetLastOriginalArg()
+    file.Write("  void %s(%s) {\n" %
+               (func.name, func.MakeTypedOriginalArgString("")))
+    file.Write("    const uint32 size = gles2::%s::ComputeSize(%s);\n" %
+               (func.name, last_arg.name))
+    file.Write("    gles2::%s& c = GetImmediateCmdSpaceTotalSize<gles2::%s>("
+               "size);\n" %
+               (func.name, func.name))
+    file.Write("    c.Init(%s);\n" % args)
+    file.Write("  }\n\n")
+
+  def WriteImmediateFormatTest(self, func, file):
+    """Overrriden from TypeHandler."""
+    file.Write("TEST(GLES2FormatTest, %s) {\n" % func.name)
+    file.Write("  int8 buf[256] = { 0, };\n")
+    file.Write("  %s& cmd = *static_cast<%s*>(static_cast<void*>(&buf));\n" %
+               (func.name, func.name))
+    file.Write("  static const char* const test_str = \"test string\";\n")
+    file.Write("  void* next_cmd = cmd.Set(\n")
+    file.Write("      &cmd")
+    all_but_last_arg = func.GetCmdArgs()[:-1]
+    value = 11
+    for arg in all_but_last_arg:
+      file.Write(",\n      static_cast<%s>(%d)" % (arg.type, value))
+      value += 1
+    file.Write(",\n      test_str);\n")
+    value = 11
+    file.Write("  EXPECT_EQ(%s::kCmdId, cmd.header.command);\n" % func.name)
+    file.Write("  EXPECT_EQ(sizeof(cmd) +  // NOLINT\n")
+    file.Write("            RoundSizeToMultipleOfEntries(strlen(test_str)),\n")
+    file.Write("            cmd.header.size * 4);\n")
+    for arg in all_but_last_arg:
+      file.Write("  EXPECT_EQ(static_cast<%s>(%d), cmd.%s);\n" %
+                 (arg.type, value, arg.name))
+      value += 1
+    file.Write("  // TODO(gman): check that string got copied.\n")
+    file.Write("}\n")
+    file.Write("\n")
+
+
+class IsHandler(TypeHandler):
+  """Handler for glIs____ type and glGetError functions."""
+
+  def __init__(self):
+    TypeHandler.__init__(self)
+
+  def InitFunction(self, func):
+    """Overrriden from TypeHandler."""
+    func.AddCmdArg(CmdArg("result_shm_id", 'uint32'))
+    func.AddCmdArg(CmdArg("result_shm_offset", 'uint32'))
+
+  def WriteServiceImplementation(self, func, file):
+    """Overrriden from TypeHandler."""
+    file.Write(
+        "parse_error::ParseError GLES2DecoderImpl::Handle%s(\n" % func.name)
+    file.Write(
+        "    unsigned int arg_count, const gles2::%s& c) {\n" % func.name)
+    args = func.GetOriginalArgs()
+    for arg in args:
+      arg.WriteGetCode(file)
+
+    file.Write("  %s* result_dst = GetSharedMemoryAs<%s*>(\n" %
+               (func.return_type, func.return_type))
+    file.Write(
+        "      c.result_shm_id, c.result_shm_offset, sizeof(*result_dst));\n")
+    file.Write("  parse_error::ParseError result =\n")
+    file.Write("      Validate%s(this, arg_count%s);\n" %
+               (func.name, func.MakeOriginalArgString("", True)))
+    file.Write("  if (result != parse_error::kParseNoError) {\n")
+    file.Write("    return result;\n")
+    file.Write("  }\n")
+    file.Write("  *result_dst = %s(%s);\n" %
+               (func.GetGLFunctionName(), func.MakeOriginalArgString("")))
+    file.Write("  return parse_error::kParseNoError;\n")
+    file.Write("}\n")
+    file.Write("\n")
+
+  def WriteGLES2ImplementationHeader(self, func, file):
+    """Overrriden from TypeHandler."""
+    file.Write("%s %s(%s) {\n" %
+               (func.return_type, func.original_name,
+                func.MakeTypedOriginalArgString("")))
+    arg_string = func.MakeOriginalArgString("")
+    comma = ""
+    if len(arg_string) > 0:
+      comma = ", "
+    file.Write("  helper_->%s(%s%sshared_memory_.GetId(), 0);\n" %
+               (func.name, arg_string, comma))
+    file.Write("  int32 token = helper_->InsertToken();\n")
+    file.Write("  helper_->WaitForToken(token);\n")
+    file.Write("  return *shared_memory_.GetAddressAs<%s*>(0);\n" %
+               func.return_type)
+    file.Write("}\n")
+    file.Write("\n")
+
+  def WriteGLES2ImplementationImpl(self, func, file):
+    """Overrriden from TypeHandler."""
+    pass
+
+
+class STRnHandler(TypeHandler):
+  """Handler for GetProgramInfoLog, GetShaderInfoLog and GetShaderSource."""
+
+  def __init__(self):
+    TypeHandler.__init__(self)
+
+  def WriteGLES2ImplementationHeader(self, func, file):
+    """Overrriden from TypeHandler."""
+    file.Write("// TODO(gman): Implement this\n")
+    TypeHandler.WriteGLES2ImplementationHeader(self, func, file)
+
+
+class FunctionInfo(object):
+  """Holds info about a function."""
+
+  def __init__(self, info, type_handler):
+    for key in info:
+      setattr(self, key, info[key])
+    self.type_handler = type_handler
+    if not 'type' in info:
+      self.type = ''
+
+
+class CmdArg(object):
+  """A class used to represent arguments at the command buffer level."""
+  cmd_type_map_ = {
+    'GLfloat': 'float',
+    'GLclampf': 'float',
+  }
+
+  def __init__(self, name, type):
+    self.name = name
+    self.type = type
+
+    if type in self.cmd_type_map_:
+      self.cmd_type = self.cmd_type_map_[type]
+    else:
+      self.cmd_type = 'uint32'
+
+  def WriteGetCode(self, file):
+    file.Write("  %s %s = static_cast<%s>(c.%s);\n" %
+               (self.type, self.name, self.type, self.name))
+
+
+class Argument(object):
+  """A class that represents a function argument."""
+
+  def __init__(self, name, type):
+    self.name = name
+    self.type = type
+
+  def AddCmdArgs(self, args):
+    """Adds command arguments for this argument to the given list."""
+    return args.append(CmdArg(self.name, self.type))
+
+  def WriteGetCode(self, file):
+    """Writes the code to get an argument from a command structure."""
+    file.Write("  %s %s = static_cast<%s>(c.%s);\n" %
+               (self.type, self.name, self.type, self.name))
+
+  def WriteValidationCode(self, file):
+    """Writes the validation code for an argument."""
+    pass
+
+  def WriteGetAddress(self, file):
+    """Writes the code to get the address this argument refers to."""
+    pass
+
+  def GetImmediateVersion(self):
+    """Gets the immediate version of this argument."""
+    return self
+
+
+class ImmediatePointerArgument(Argument):
+  """A class that represents an immediate argument to a function.
+
+  An immediate argument is one where the data follows the command.
+  """
+
+  def __init__(self, name, type):
+    Argument.__init__(self, name, type)
+
+  def AddCmdArgs(self, args):
+    """Overridden from Argument."""
+    pass
+
+  def WriteGetCode(self, file):
+    """Overridden from Argument."""
+    file.Write(
+      "  %s %s = GetImmediateDataAs<%s>(c);\n" %
+       (self.type, self.name, self.type))
+
+  def WriteValidationCode(self, file):
+    """Overridden from Argument."""
+    file.Write("  if (%s == NULL) {\n" % self.name)
+    file.Write("    return parse_error::kParseOutOfBounds;\n")
+    file.Write("  }\n")
+
+  def GetImmediateVersion(self):
+    """Overridden from Argument."""
+    return None
+
+
+class PointerArgument(Argument):
+  """A class that represents a pointer argument to a function."""
+
+  def __init__(self, name, type):
+    Argument.__init__(self, name, type)
+
+  def AddCmdArgs(self, args):
+    """Overridden from Argument."""
+    args.append(CmdArg("%s_shm_id" % self.name, 'uint32'))
+    args.append(CmdArg("%s_shm_offset" % self.name, 'uint32'))
+
+  def WriteGetCode(self, file):
+    """Overridden from Argument."""
+    file.Write(
+        "  %s %s = GetSharedMemoryAs<%s>(\n" %
+        (self.type, self.name, self.type))
+    file.Write(
+        "      c.%s_shm_id, c.%s_shm_offset, 0 /* TODO(gman): size */);\n" %
+        (self.name, self.name))
+
+  def WriteGetAddress(self, file):
+    """Overridden from Argument."""
+    file.Write(
+        "  %s %s = GetSharedMemoryAs<%s>(\n" %
+        (self.type, self.name, self.type))
+    file.Write(
+        "      %s_shm_id, %s_shm_offset, %s_size);\n" %
+        (self.name, self.name, self.name))
+
+  def WriteValidationCode(self, file):
+    """Overridden from Argument."""
+    file.Write("  if (%s == NULL) {\n" % self.name)
+    file.Write("    return parse_error::kParseOutOfBounds;\n")
+    file.Write("  }\n")
+
+  def GetImmediateVersion(self):
+    """Overridden from Argument."""
+    return ImmediatePointerArgument(self.name, self.type)
+
+
+class ResourceIdArgument(Argument):
+  """A class that represents a resource id argument to a function."""
+
+  def __init__(self, name, type):
+    type = type.replace("GLResourceId", "GLuint")
+    Argument.__init__(self, name, type)
+
+  def WriteGetCode(self, file):
+    """Overridden from Argument."""
+    file.Write("  %s %s;\n" % (self.type, self.name))
+    file.Write("  if (!id_map_.GetServiceId(c.%s, &%s)) {\n" %
+               (self.name, self.name))
+    file.Write("    SetGLError(GL_INVALID_VALUE);\n")
+    file.Write("    return parse_error::kParseNoError;\n")
+    file.Write("  }\n")
+
+
+class Function(object):
+  """A class that represents a function."""
+
+  def __init__(self, name, info, return_type, original_args, args_for_cmds,
+               cmd_args, num_pointer_args):
+    self.name = name
+    self.original_name = name
+    self.info = info
+    self.type_handler = info.type_handler
+    self.return_type = return_type
+    self.original_args = original_args
+    self.num_pointer_args = num_pointer_args
+    self.can_auto_generate = num_pointer_args == 0 and return_type == "void"
+    self.cmd_args = cmd_args
+    self.args_for_cmds = args_for_cmds
+    self.type_handler.InitFunction(self)
+
+  def IsType(self, type_name):
+    """Returns true if function is a certain type."""
+    return self.info.type == type_name
+
+  def GetInfo(self, name):
+    """Returns a value from the function info for this function."""
+    if hasattr(self.info, name):
+      return getattr(self.info, name)
+    return None
+
+  def GetGLFunctionName(self):
+    """Gets the function to call to execute GL for this command."""
+    if self.GetInfo('DecoderFunc'):
+      return self.GetInfo('DecoderFunc')
+    return "gl%s" % self.original_name
+
+  def AddCmdArg(self, arg):
+    """Adds a cmd argument to this function."""
+    self.cmd_args.append(arg)
+
+  def GetCmdArgs(self):
+    """Gets the command args for this function."""
+    return self.cmd_args
+
+  def GetOriginalArgs(self):
+    """Gets the original arguments to this function."""
+    return self.original_args
+
+  def GetLastOriginalArg(self):
+    """Gets the last original argument to this function."""
+    return self.original_args[len(self.original_args) - 1]
+
+  def __GetArgList(self, arg_string, add_comma):
+    """Adds a comma if arg_string is not empty and add_comma is true."""
+    comma = ""
+    if add_comma and len(arg_string):
+      comma = ", "
+    return "%s%s" % (comma, arg_string)
+
+  def MakeTypedOriginalArgString(self, prefix, add_comma = False):
+    """Gets a list of arguments as they arg in GL."""
+    args = self.GetOriginalArgs()
+    arg_string = ", ".join(
+        ["%s %s%s" % (arg.type, prefix, arg.name) for arg in args])
+    return self.__GetArgList(arg_string, add_comma)
+
+  def MakeOriginalArgString(self, prefix, add_comma = False):
+    """Gets the list of arguments as they are in GL."""
+    args = self.GetOriginalArgs()
+    arg_string = ", ".join(
+        ["%s%s" % (prefix, arg.name) for arg in args])
+    return self.__GetArgList(arg_string, add_comma)
+
+  def MakeTypedCmdArgString(self, prefix, add_comma = False):
+    """Gets a typed list of arguments as they need to be for command buffers."""
+    args = self.GetCmdArgs()
+    arg_string = ", ".join(
+        ["%s %s%s" % (arg.type, prefix, arg.name) for arg in args])
+    return self.__GetArgList(arg_string, add_comma)
+
+  def MakeCmdArgString(self, prefix, add_comma = False):
+    """Gets the list of arguments as they need to be for command buffers."""
+    args = self.GetCmdArgs()
+    arg_string = ", ".join(
+        ["%s%s" % (prefix, arg.name) for arg in args])
+    return self.__GetArgList(arg_string, add_comma)
+
+  def WriteHandlerImplementation(self, file):
+    """Writes the handler implementation for this command."""
+    self.type_handler.WriteHandlerImplementation(self, file)
+
+  def WriteValidationCode(self, file):
+    """Writes the validation code for a command."""
+    pass
+
+  def WriteCmdArgFlag(self, file):
+    """Writes the cmd kArgFlags constant."""
+    file.Write("  static const cmd::ArgFlags kArgFlags = cmd::kFixed;\n")
+
+  def WriteCmdComputeSize(self, file):
+    """Writes the ComputeSize function for the command."""
+    file.Write("  static uint32 ComputeSize() {\n")
+    file.Write(
+        "    return static_cast<uint32>(sizeof(ValueType));  // NOLINT\n")
+    file.Write("  }\n")
+    file.Write("\n")
+
+  def WriteCmdSetHeader(self, file):
+    """Writes the cmd's SetHeader function."""
+    file.Write("  void SetHeader() {\n")
+    file.Write("    header.SetCmd<ValueType>();\n")
+    file.Write("  }\n")
+    file.Write("\n")
+
+  def WriteCmdInit(self, file):
+    """Writes the cmd's Init function."""
+    file.Write("  void Init(%s) {\n" % self.MakeTypedCmdArgString("_"))
+    file.Write("    SetHeader();\n")
+    args = self.GetCmdArgs()
+    for arg in args:
+      file.Write("    %s = _%s;\n" % (arg.name, arg.name))
+    file.Write("  }\n")
+    file.Write("\n")
+
+  def WriteCmdSet(self, file):
+    """Writes the cmd's Set function."""
+    copy_args = self.MakeCmdArgString("_", False)
+    file.Write("  void* Set(void* cmd%s) {\n" %
+               self.MakeTypedCmdArgString("_", True))
+    file.Write("    static_cast<ValueType*>(cmd)->Init(%s);\n" % copy_args)
+    file.Write("    return NextCmdAddress<ValueType>(cmd);\n")
+    file.Write("  }\n")
+    file.Write("\n")
+
+  def WriteStruct(self, file):
+    """Writes a structure that matched the arguments to the function."""
+    file.Write("struct %s {\n" % self.name)
+    file.Write("  typedef %s ValueType;\n" % self.name)
+    file.Write("  static const CommandId kCmdId = k%s;\n" % self.name)
+    self.WriteCmdArgFlag(file)
+    file.Write("\n")
+
+    self.WriteCmdComputeSize(file)
+    self.WriteCmdSetHeader(file)
+    self.WriteCmdInit(file)
+    self.WriteCmdSet(file)
+
+    file.Write("  command_buffer::CommandHeader header;\n")
+    args = self.GetCmdArgs()
+    for arg in args:
+      file.Write("  %s %s;\n" % (arg.cmd_type, arg.name))
+    file.Write("};\n")
+    file.Write("\n")
+
+    size = len(args) * _SIZE_OF_UINT32 + _SIZE_OF_COMMAND_HEADER
+    file.Write("COMPILE_ASSERT(sizeof(%s) == %d,\n" % (self.name, size))
+    file.Write("               Sizeof_%s_is_not_%d);\n" % (self.name, size))
+    file.Write("COMPILE_ASSERT(offsetof(%s, header) == 0,\n" % self.name)
+    file.Write("               OffsetOf_%s_header_not_0);\n" % self.name)
+    offset = _SIZE_OF_COMMAND_HEADER
+    for arg in args:
+      file.Write("COMPILE_ASSERT(offsetof(%s, %s) == %d,\n" %
+                 (self.name, arg.name, offset))
+      file.Write("               OffsetOf_%s_%s_not_%d);\n" %
+                 (self.name, arg.name, offset))
+      offset += _SIZE_OF_UINT32
+    file.Write("\n")
+
+  def WriteCmdHelper(self, file):
+    """Writes the cmd's helper."""
+    args = self.MakeCmdArgString("")
+    file.Write("  void %s(%s) {\n" %
+               (self.name, self.MakeTypedCmdArgString("")))
+    file.Write("    gles2::%s& c = GetCmdSpace<gles2::%s>();\n" %
+               (self.name, self.name))
+    file.Write("    c.Init(%s);\n" % args)
+    file.Write("  }\n\n")
+
+  def WriteServiceImplementation(self, file):
+    """Writes the service implementation for a command."""
+    self.type_handler.WriteServiceImplementation(self, file)
+
+  def WriteGLES2ImplementationHeader(self, file):
+    """Writes the GLES2 Implemention declaration."""
+    self.type_handler.WriteGLES2ImplementationHeader(self, file)
+
+  def WriteGLES2ImplementationImpl(self, file):
+    """Writes the GLES2 Implemention definition."""
+    self.type_handler.WriteGLES2ImplementationImpl(self, file)
+
+  def WriteFormatTest(self, file):
+    """Writes the cmd's format test."""
+    self.type_handler.WriteFormatTest(self, file)
+
+
+class ImmediateFunction(Function):
+  """A class that represnets an immediate function command."""
+
+  def __init__(self, func):
+    new_args = []
+    for arg in func.GetOriginalArgs():
+      new_arg = arg.GetImmediateVersion()
+      if new_arg:
+        new_args.append(new_arg)
+
+    cmd_args = []
+    new_args_for_cmds = []
+    for arg in func.args_for_cmds:
+      new_arg = arg.GetImmediateVersion()
+      if new_arg:
+        new_args_for_cmds.append(new_arg)
+        new_arg.AddCmdArgs(cmd_args)
+
+    Function.__init__(
+        self,
+        "%sImmediate" % func.name,
+        func.info,
+        func.return_type,
+        new_args,
+        new_args_for_cmds,
+        cmd_args,
+        0)
+    self.original_name = func.name
+
+  def WriteServiceImplementation(self, file):
+    """Overridden from Function"""
+    self.type_handler.WriteImmediateServiceImplementation(self, file)
+
+  def WriteHandlerImplementation(self, file):
+    """Overridden from Function"""
+    self.type_handler.WriteImmediateHandlerImplementation(self, file)
+
+  def WriteValidationCode(self, file):
+    """Overridden from Function"""
+    self.type_handler.WriteImmediateValidationCode(self, file)
+
+  def WriteCmdArgFlag(self, file):
+    """Overridden from Function"""
+    file.Write("  static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN;\n")
+
+  def WriteCmdComputeSize(self, file):
+    """Overridden from Function"""
+    self.type_handler.WriteImmediateCmdComputeSize(self, file)
+
+  def WriteCmdSetHeader(self, file):
+    """Overridden from Function"""
+    self.type_handler.WriteImmediateCmdSetHeader(self, file)
+
+  def WriteCmdInit(self, file):
+    """Overridden from Function"""
+    self.type_handler.WriteImmediateCmdInit(self, file)
+
+  def WriteCmdSet(self, file):
+    """Overridden from Function"""
+    self.type_handler.WriteImmediateCmdSet(self, file)
+
+  def WriteCmdHelper(self, file):
+    """Overridden from Function"""
+    self.type_handler.WriteImmediateCmdHelper(self, file)
+
+  def WriteFormatTest(self, file):
+    """Overridden from Function"""
+    self.type_handler.WriteImmediateFormatTest(self, file)
+
+
+class GLGenerator(object):
+  """A class to generate GL command buffers."""
+
+  _function_re = re.compile(r'GL_APICALL(.*?)GL_APIENTRY (.*?) \((.*?)\);')
+  _non_alnum_re = re.compile(r'[^a-zA-Z0-9]')
+
+  def __init__(self, verbose):
+    self.original_functions = []
+    self.functions = []
+    self.verbose = verbose
+    self._function_info = {}
+    self._empty_type_handler = TypeHandler()
+    self._empty_function_info = FunctionInfo({}, self._empty_type_handler)
+
+    self._type_handlers = {
+      'Create': CreateHandler(),
+      'Custom': CustomHandler(),
+      'Data': DataHandler(),
+      'DELn': DELnHandler(),
+      'GENn': GENnHandler(),
+      'GETn': GETnHandler(),
+      'GetGLchar': GetGLcharHandler(),
+      'GLchar': GLcharHandler(),
+      'Is': IsHandler(),
+      'Manual': ManualHandler(),
+      'PUT': PUTHandler(),
+      'PUTn': PUTnHandler(),
+      'STRn': STRnHandler(),
+      'Todo': TodoHandler(),
+    }
+
+    for func_name in _FUNCTION_INFO:
+      info = _FUNCTION_INFO[func_name]
+      type = ''
+      if 'type' in info:
+        type = info['type']
+      self._function_info[func_name] = FunctionInfo(info,
+                                                    self.GetTypeHandler(type))
+
+  def AddFunction(self, func):
+    """Adds a function."""
+    self.functions.append(func)
+
+  def GetTypeHandler(self, name):
+    """Gets a type info for the given type."""
+    if name in self._type_handlers:
+      return self._type_handlers[name]
+    return self._empty_type_handler
+
+  def GetFunctionInfo(self, name):
+    """Gets a type info for the given function name."""
+    if name in self._function_info:
+      return self._function_info[name]
+    return self._empty_function_info
+
+  def Log(self, msg):
+    """Prints something if verbose is true."""
+    if self.verbose:
+      print msg
+
+  def WriteHeader(self, file):
+    """Writes header to file"""
+    file.Write(
+        "// This file is auto-generated. DO NOT EDIT!\n"
+        "\n")
+
+  def WriteLicense(self, file):
+    """Writes the license."""
+    file.Write(_LICENSE)
+
+  def WriteNamespaceOpen(self, file):
+    """Writes the code for the namespace."""
+    file.Write("namespace command_buffer {\n")
+    file.Write("namespace gles2 {\n")
+    file.Write("\n")
+
+  def WriteNamespaceClose(self, file):
+    """Writes the code to close the namespace."""
+    file.Write("}  // namespace gles2\n")
+    file.Write("}  // namespace command_buffer\n")
+    file.Write("\n")
+
+  def MakeGuard(self, filename):
+    """Creates a header guard id."""
+    base = os.path.dirname(os.path.dirname(os.path.dirname(
+        os.path.dirname(os.path.dirname(os.path.abspath(__file__))))))
+    hpath = os.path.abspath(filename)[len(base) + 1:]
+    return self._non_alnum_re.sub('_', hpath).upper()
+
+  def ParseArgs(self, arg_string):
+    """Parses a function arg string."""
+    args = []
+    num_pointer_args = 0
+    parts = arg_string.split(',')
+    for arg in parts:
+      arg_parts = arg.split()
+      if len(arg_parts) == 1 and arg_parts[0] == 'void':
+        pass
+      # Is this a pointer argument?
+      elif arg.find('*') >= 0:
+        num_pointer_args += 1
+        args.append(PointerArgument(
+            arg_parts[-1],
+            " ".join(arg_parts[0:-1])))
+      # Is this a resource argument? Must come after pointer check.
+      elif arg_parts[0] == 'GLResourceId':
+        args.append(ResourceIdArgument(
+            arg_parts[-1],
+            " ".join(arg_parts[0:-1])))
+      else:
+        args.append(Argument(
+            arg_parts[-1],
+            " ".join(arg_parts[0:-1])))
+    return (args, num_pointer_args)
+
+  def ParseGLH(self, filename):
+    """Parses the GL2.h file and extracts the functions"""
+    for line in _GL_FUNCTIONS.splitlines():
+      match = self._function_re.match(line)
+      if match:
+        func_name = match.group(2)[2:]
+        func_info = self.GetFunctionInfo(func_name)
+        if func_info.type != 'Noop':
+          return_type = match.group(1).strip()
+          arg_string = match.group(3)
+          (args, num_pointer_args) = self.ParseArgs(arg_string)
+          args_for_cmds = args
+          if hasattr(func_info, 'cmd_args'):
+            (args_for_cmds, num_pointer_args) = (
+                self.ParseArgs(getattr(func_info, 'cmd_args')))
+          cmd_args = []
+          for arg in args_for_cmds:
+            arg.AddCmdArgs(cmd_args)
+          f = Function(func_name, func_info, return_type, args, args_for_cmds,
+                       cmd_args, num_pointer_args)
+          self.original_functions.append(f)
+          self.AddFunction(f)
+          f.type_handler.AddImmediateFunction(self, f)
+
+    self.Log("Auto Generated Functions    : %d" %
+             len([f for f in self.functions if f.can_auto_generate or
+                  (not f.IsType('') and not f.IsType('Custom') and
+                   not f.IsType('Todo'))]))
+
+    funcs = [f for f in self.functions if not f.can_auto_generate and
+             (f.IsType('') or f.IsType('Custom') or f.IsType('Todo'))]
+    self.Log("Non Auto Generated Functions: %d" % len(funcs))
+
+    for f in funcs:
+      self.Log("  %-10s %-20s gl%s" % (f.info.type, f.return_type, f.name))
+
+  def WriteCommandIds(self, filename):
+    """Writes the command buffer format"""
+    file = CWriter(filename)
+    self.WriteHeader(file)
+    file.Write("#define GLES2_COMMAND_LIST(OP) \\\n")
+    command_id = _FIRST_SPECIFIC_COMMAND_ID
+    for func in self.functions:
+      file.Write("  %-60s /* %d */ \\\n" % ("OP(%s)" % func.name, command_id))
+      command_id += 1
+    file.Write("\n")
+
+    file.Write("enum CommandId {\n")
+    file.Write("  kStartPoint = cmd::kLastCommonId,  "
+               "// All GLES2 commands start after this.\n")
+    file.Write("#define GLES2_CMD_OP(name) k ## name,\n")
+    file.Write("  GLES2_COMMAND_LIST(GLES2_CMD_OP)\n")
+    file.Write("#undef GLES2_CMD_OP\n")
+    file.Write("  kNumCommands\n")
+    file.Write("};\n")
+    file.Write("\n")
+    file.Close()
+
+  def WriteFormat(self, filename):
+    """Writes the command buffer format"""
+    file = CWriter(filename)
+    self.WriteHeader(file)
+    file.Write("#pragma pack(push, 1)\n")
+    file.Write("\n")
+
+    for func in self.functions:
+      func.WriteStruct(file)
+
+    file.Write("#pragma pack(pop)\n")
+    file.Write("\n")
+    file.Close()
+
+  def WriteFormatTest(self, filename):
+    """Writes the command buffer format test."""
+    file = CWriter(filename)
+    self.WriteHeader(file)
+    file.Write("// This file contains unit tests for gles2 commmands\n")
+    file.Write("// It is included by gles2_cmd_format_test.cc\n")
+    file.Write("\n")
+
+    for func in self.functions:
+      func.WriteFormatTest(file)
+
+    file.Close()
+
+  def WriteCommandIdTest(self, filename):
+    """Writes the command id test."""
+    file = CWriter(filename)
+    self.WriteLicense(file)
+    file.Write("// This file contains unit tests for gles2 commmand ids\n")
+    file.Write("\n")
+    file.Write("#include \"tests/common/win/testing_common.h\"\n")
+    file.Write("#include \"gpu/command_buffer/common/gles2_cmd_format.h\"\n")
+    file.Write("\n")
+
+    self.WriteNamespaceOpen(file)
+
+    file.Write("// *** These IDs MUST NOT CHANGE!!! ***\n")
+    file.Write("// Changing them will break all client programs.\n")
+    file.Write("TEST(GLES2CommandIdTest, CommandIdsMatch) {\n")
+    command_id = 1024
+    for func in self.functions:
+      file.Write("  COMPILE_ASSERT(%s::kCmdId == %d,\n" %
+                 (func.name, command_id))
+      file.Write("                 GLES2_%s_kCmdId_mismatch);\n" % func.name)
+      command_id += 1
+
+    file.Write("}\n")
+
+    self.WriteNamespaceClose(file)
+
+    file.Close()
+
+  def WriteCmdHelperHeader(self, filename):
+    """Writes the gles2 command helper."""
+    file = CWriter(filename)
+
+    for func in self.functions:
+      func.WriteCmdHelper(file)
+
+    file.Close()
+
+  def WriteServiceImplementation(self, filename):
+    """Writes the service decorder implementation."""
+    file = CWriter(filename)
+    self.WriteHeader(file)
+    file.Write("// It is included by gles2_cmd_decoder.cc\n")
+    file.Write("\n")
+
+    for func in self.functions:
+      func.WriteServiceImplementation(file)
+
+    file.Close()
+
+  def WriteServiceValidation(self, filename):
+    file = CWriter(filename)
+    self.WriteLicense(file)
+    file.Write("\n")
+    self.WriteNamespaceOpen(file)
+    file.Write("namespace {\n")
+    file.Write("\n")
+    for func in self.functions:
+      file.Write("parse_error::ParseError Validate%s(\n" % func.name)
+      file.Write("    GLES2Decoder* decoder, unsigned int arg_count%s) {\n" %
+                 func.MakeTypedOriginalArgString("", True))
+      for arg in func.GetOriginalArgs():
+        arg.WriteValidationCode(file)
+      func.WriteValidationCode(file)
+      file.Write("  return parse_error::kParseNoError;\n")
+      file.Write("}\n")
+    file.Write("}  // anonymous namespace\n")
+    self.WriteNamespaceClose(file)
+    file.Close()
+
+  def WriteGLES2CLibImplementation(self, filename):
+    """Writes the GLES2 c lib implementation."""
+    file = CWriter(filename)
+    self.WriteHeader(file)
+    file.Write("\n")
+    file.Write("// These functions emluate GLES2 over command buffers.\n")
+    file.Write("\n")
+    file.Write("\n")
+
+    for func in self.original_functions:
+      file.Write("%s GLES2%s(%s) {\n" %
+                 (func.return_type, func.name,
+                  func.MakeTypedOriginalArgString("")))
+      return_string = "return "
+      if func.return_type == "void":
+        return_string = ""
+      file.Write("  %sgles2::GetGLContext()->%s(%s);\n" %
+                 (return_string, func.original_name,
+                  func.MakeOriginalArgString("")))
+      file.Write("}\n")
+
+    file.Write("\n")
+
+    file.Close()
+
+  def WriteGLES2ImplementationHeader(self, filename):
+    """Writes the GLES2 helper header."""
+    file = CWriter(filename)
+    self.WriteHeader(file)
+    file.Write(
+        "// This file is included by gles2_implementation.h to declare the\n")
+    file.Write("// GL api functions.\n")
+    for func in self.original_functions:
+      func.WriteGLES2ImplementationHeader(file)
+    file.Close()
+
+  def WriteGLES2ImplementationImpl(self, filename):
+    """Writes the gles2 helper implementation."""
+    file = CWriter(filename)
+    self.WriteLicense(file)
+    file.Write("\n")
+    file.Write("// A class to emluate GLES2 over command buffers.\n")
+    file.Write("\n")
+    file.Write(
+        "#include \"gpu/command_buffer/client/gles2_implementation.h\"\n")
+    file.Write("\n")
+    self.WriteNamespaceOpen(file)
+    for func in self.original_functions:
+      func.WriteGLES2ImplementationImpl(file)
+    file.Write("\n")
+
+    self.WriteNamespaceClose(file)
+    file.Close()
+
+
+def main(argv):
+  """This is the main function."""
+  parser = OptionParser()
+  parser.add_option(
+      "-g", "--generate-implementation-templates", action="store_true",
+      help="generates files that are generally hand edited..")
+  parser.add_option(
+      "--generate-command-id-tests", action="store_true",
+      help="generate tests for commands ids. Commands MUST not change ID!")
+  parser.add_option(
+      "-v", "--verbose", action="store_true",
+      help="prints more output.")
+
+  (options, args) = parser.parse_args(args=argv)
+
+  gen = GLGenerator(options.verbose)
+  gen.ParseGLH("common/GLES2/gl2.h")
+  gen.WriteCommandIds("common/gles2_cmd_ids_autogen.h")
+  gen.WriteFormat("common/gles2_cmd_format_autogen.h")
+  gen.WriteFormatTest("common/gles2_cmd_format_test_autogen.h")
+  gen.WriteGLES2ImplementationHeader("client/gles2_implementation_autogen.h")
+  gen.WriteGLES2CLibImplementation("client/gles2_c_lib_autogen.h")
+  gen.WriteCmdHelperHeader("client/gles2_cmd_helper_autogen.h")
+  gen.WriteServiceImplementation("service/gles2_cmd_decoder_autogen.h")
+
+  if options.generate_implementation_templates:
+    gen.WriteGLES2ImplementationImpl("client/gles2_implementation_gen.h")
+    gen.WriteServiceValidation("service/gles2_cmd_decoder_validate.h")
+
+  if options.generate_command_id_tests:
+    gen.WriteCommandIdTest("common/gles2_cmd_id_test.cc")
+
+
+if __name__ == '__main__':
+  main(sys.argv[1:])
+
diff --git a/gpu/command_buffer/client/cmd_buffer_helper.cc b/gpu/command_buffer/client/cmd_buffer_helper.cc
new file mode 100644
index 0000000..e8f6fef
--- /dev/null
+++ b/gpu/command_buffer/client/cmd_buffer_helper.cc
@@ -0,0 +1,195 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains the implementation of the command buffer helper class.
+
+#include "gpu/command_buffer/client/cmd_buffer_helper.h"
+#include "gpu/command_buffer/common/command_buffer.h"
+#include "gpu/np_utils/np_utils.h"
+
+namespace command_buffer {
+
+using command_buffer::CommandBuffer;
+using np_utils::NPBrowser;
+using np_utils::NPInvoke;
+using np_utils::NPObjectPointer;
+
+CommandBufferHelper::CommandBufferHelper(CommandBuffer* command_buffer)
+    : command_buffer_(command_buffer),
+      entries_(NULL),
+      entry_count_(0),
+      token_(0),
+      last_token_read_(-1),
+      get_(0),
+      put_(0) {
+}
+
+bool CommandBufferHelper::Initialize() {
+  ring_buffer_ = command_buffer_->GetRingBuffer();
+  if (!ring_buffer_)
+    return false;
+
+  // Map the ring buffer into this process.
+  if (!ring_buffer_->Map(ring_buffer_->max_size()))
+    return false;
+
+  entries_ = static_cast<CommandBufferEntry*>(ring_buffer_->memory());
+  entry_count_ = command_buffer_->GetSize();
+  get_ = command_buffer_->GetGetOffset();
+  put_ = command_buffer_->GetPutOffset();
+  last_token_read_ = command_buffer_->GetToken();
+
+  return true;
+}
+
+CommandBufferHelper::~CommandBufferHelper() {
+}
+
+bool CommandBufferHelper::Flush() {
+  get_ = command_buffer_->SyncOffsets(put_);
+  return !command_buffer_->GetErrorStatus();
+}
+
+// Calls Flush() and then waits until the buffer is empty. Break early if the
+// error is set.
+bool CommandBufferHelper::Finish() {
+  do {
+    // Do not loop forever if the flush fails, meaning the command buffer reader
+    // has shutdown).
+    if (!Flush())
+      return false;
+  } while (put_ != get_);
+
+  return true;
+}
+
+// Inserts a new token into the command stream. It uses an increasing value
+// scheme so that we don't lose tokens (a token has passed if the current token
+// value is higher than that token). Calls Finish() if the token value wraps,
+// which will be rare.
+int32 CommandBufferHelper::InsertToken() {
+  // Increment token as 31-bit integer. Negative values are used to signal an
+  // error.
+  token_ = (token_ + 1) & 0x7FFFFFFF;
+  CommandBufferEntry args;
+  args.value_uint32 = token_;
+  const uint32 kSetToken = 1;  // TODO(gman): add a common set of commands.
+  AddCommand(kSetToken, 1, &args);
+  if (token_ == 0) {
+    // we wrapped
+    Finish();
+    last_token_read_ = command_buffer_->GetToken();
+    DCHECK_EQ(token_, last_token_read_);
+  }
+  return token_;
+}
+
+// Waits until the current token value is greater or equal to the value passed
+// in argument.
+void CommandBufferHelper::WaitForToken(int32 token) {
+  // Return immediately if corresponding InsertToken failed.
+  if (token < 0)
+    return;
+  if (last_token_read_ >= token) return;  // fast path.
+  if (token > token_) return;  // we wrapped
+  Flush();
+  last_token_read_ = command_buffer_->GetToken();
+  while (last_token_read_ < token) {
+    if (get_ == put_) {
+      LOG(FATAL) << "Empty command buffer while waiting on a token.";
+      return;
+    }
+    // Do not loop forever if the flush fails, meaning the command buffer reader
+    // has shutdown.
+    if (!Flush())
+      return;
+    last_token_read_ = command_buffer_->GetToken();
+  }
+}
+
+// Waits for available entries, basically waiting until get >= put + count + 1.
+// It actually waits for contiguous entries, so it may need to wrap the buffer
+// around, adding noops. Thus this function may change the value of put_.
+// The function will return early if an error occurs, in which case the
+// available space may not be available.
+void CommandBufferHelper::WaitForAvailableEntries(int32 count) {
+  CHECK(count < entry_count_);
+  if (put_ + count > entry_count_) {
+    // There's not enough room between the current put and the end of the
+    // buffer, so we need to wrap. We will add noops all the way to the end,
+    // but we need to make sure get wraps first, actually that get is 1 or
+    // more (since put will wrap to 0 after we add the noops).
+    DCHECK_LE(1, put_);
+    Flush();
+    while (get_ > put_ || get_ == 0) {
+      // Do not loop forever if the flush fails, meaning the command buffer
+      // reader has shutdown.
+      if (!Flush())
+        return;
+    }
+    // Add the noops. By convention, a noop is a command 0 with no args.
+    // TODO(apatrick): A noop can have a size. It would be better to add a
+    //    single noop with a variable size. Watch out for size limit on
+    //    individual commands.
+    CommandHeader header;
+    header.size = 1;
+    header.command = 0;
+    while (put_ < entry_count_) {
+      entries_[put_++].value_header = header;
+    }
+    put_ = 0;
+  }
+  // If we have enough room, return immediatly.
+  if (count <= AvailableEntries()) return;
+  // Otherwise flush, and wait until we do have enough room.
+  Flush();
+  while (AvailableEntries() < count) {
+    // Do not loop forever if the flush fails, meaning the command buffer reader
+    // has shutdown.
+    if (!Flush())
+      return;
+  }
+}
+
+CommandBufferEntry* CommandBufferHelper::GetSpace(uint32 entries) {
+  WaitForAvailableEntries(entries);
+  CommandBufferEntry* space = &entries_[put_];
+  put_ += entries;
+  return space;
+}
+
+parse_error::ParseError CommandBufferHelper::GetParseError() {
+  int32 parse_error = command_buffer_->ResetParseError();
+  return static_cast<parse_error::ParseError>(parse_error);
+}
+
+}  // namespace command_buffer
diff --git a/gpu/command_buffer/client/cmd_buffer_helper.h b/gpu/command_buffer/client/cmd_buffer_helper.h
new file mode 100644
index 0000000..7cac568b
--- /dev/null
+++ b/gpu/command_buffer/client/cmd_buffer_helper.h
@@ -0,0 +1,216 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains the command buffer helper class.
+
+#ifndef GPU_COMMAND_BUFFER_CLIENT_CROSS_CMD_BUFFER_HELPER_H_
+#define GPU_COMMAND_BUFFER_CLIENT_CROSS_CMD_BUFFER_HELPER_H_
+
+#include "gpu/command_buffer/common/logging.h"
+#include "gpu/command_buffer/common/constants.h"
+#include "gpu/command_buffer/common/cmd_buffer_common.h"
+#include "gpu/command_buffer/common/command_buffer.h"
+
+namespace command_buffer {
+
+// Command buffer helper class. This class simplifies ring buffer management:
+// it will allocate the buffer, give it to the buffer interface, and let the
+// user add commands to it, while taking care of the synchronization (put and
+// get). It also provides a way to ensure commands have been executed, through
+// the token mechanism:
+//
+// helper.AddCommand(...);
+// helper.AddCommand(...);
+// int32 token = helper.InsertToken();
+// helper.AddCommand(...);
+// helper.AddCommand(...);
+// [...]
+//
+// helper.WaitForToken(token);  // this doesn't return until the first two
+//                              // commands have been executed.
+class CommandBufferHelper {
+ public:
+  explicit CommandBufferHelper(command_buffer::CommandBuffer* command_buffer);
+  virtual ~CommandBufferHelper();
+
+  bool Initialize();
+
+  // Flushes the commands, setting the put pointer to let the buffer interface
+  // know that new commands have been added. After a flush returns, the command
+  // buffer service is aware of all pending commands and it is guaranteed to
+  // have made some progress in processing them. Returns whether the flush was
+  // successful. The flush will fail if the command buffer service has
+  // disconnected.
+  bool Flush();
+
+  // Waits until all the commands have been executed. Returns whether it
+  // was successful. The function will fail if the command buffer service has
+  // disconnected.
+  bool Finish();
+
+  // Waits until a given number of available entries are available.
+  // Parameters:
+  //   count: number of entries needed. This value must be at most
+  //     the size of the buffer minus one.
+  void WaitForAvailableEntries(int32 count);
+
+  // Adds a command data to the command buffer. This may wait until sufficient
+  // space is available.
+  // Parameters:
+  //   entries: The command entries to add.
+  //   count: The number of entries.
+  void AddCommandData(const CommandBufferEntry* entries, int32 count) {
+    WaitForAvailableEntries(count);
+    for (; count > 0; --count) {
+      entries_[put_++] = *entries++;
+    }
+    DCHECK_LE(put_, entry_count_);
+    if (put_ == entry_count_) put_ = 0;
+  }
+
+  // A typed version of AddCommandData.
+  template <typename T>
+  void AddTypedCmdData(const T& cmd) {
+    AddCommandData(reinterpret_cast<const CommandBufferEntry*>(&cmd),
+                   ComputeNumEntries(sizeof(cmd)));
+  }
+
+  // Adds a command to the command buffer. This may wait until sufficient space
+  // is available.
+  // Parameters:
+  //   command: the command index.
+  //   arg_count: the number of arguments for the command.
+  //   args: the arguments for the command (these are copied before the
+  //     function returns).
+  void AddCommand(int32 command,
+                  int32 arg_count,
+                  const CommandBufferEntry *args) {
+    CommandHeader header;
+    header.size = arg_count + 1;
+    header.command = command;
+    WaitForAvailableEntries(header.size);
+    entries_[put_++].value_header = header;
+    for (int i = 0; i < arg_count; ++i) {
+      entries_[put_++] = args[i];
+    }
+    DCHECK_LE(put_, entry_count_);
+    if (put_ == entry_count_) put_ = 0;
+  }
+
+  // Inserts a new token into the command buffer. This token either has a value
+  // different from previously inserted tokens, or ensures that previously
+  // inserted tokens with that value have already passed through the command
+  // stream.
+  // Returns:
+  //   the value of the new token or -1 if the command buffer reader has
+  //   shutdown.
+  int32 InsertToken();
+
+  // Waits until the token of a particular value has passed through the command
+  // stream (i.e. commands inserted before that token have been executed).
+  // NOTE: This will call Flush if it needs to block.
+  // Parameters:
+  //   the value of the token to wait for.
+  void WaitForToken(int32 token);
+
+  // Waits for a certain amount of space to be available. Returns address
+  // of space.
+  CommandBufferEntry* GetSpace(uint32 entries);
+
+  // Typed version of GetSpace. Gets enough room for the given type and returns
+  // a reference to it.
+  template <typename T>
+  T& GetCmdSpace() {
+    COMPILE_ASSERT(T::kArgFlags == cmd::kFixed, Cmd_kArgFlags_not_kFixed);
+    uint32 space_needed = ComputeNumEntries(sizeof(T));
+    void* data = GetSpace(space_needed);
+    return *reinterpret_cast<T*>(data);
+  }
+
+  // Typed version of GetSpace for immediate commands.
+  template <typename T>
+  T& GetImmediateCmdSpace(size_t data_space) {
+    COMPILE_ASSERT(T::kArgFlags == cmd::kAtLeastN, Cmd_kArgFlags_not_kAtLeastN);
+    uint32 space_needed = ComputeNumEntries(sizeof(T) + data_space);
+    void* data = GetSpace(space_needed);
+    return *reinterpret_cast<T*>(data);
+  }
+
+  // Typed version of GetSpace for immediate commands.
+  template <typename T>
+  T& GetImmediateCmdSpaceTotalSize(size_t total_space) {
+    COMPILE_ASSERT(T::kArgFlags == cmd::kAtLeastN, Cmd_kArgFlags_not_kAtLeastN);
+    uint32 space_needed = ComputeNumEntries(total_space);
+    void* data = GetSpace(space_needed);
+    return *reinterpret_cast<T*>(data);
+  }
+
+  parse_error::ParseError GetParseError();
+
+  // Common Commands
+  void Noop(uint32 skip_count) {
+    cmd::Noop& cmd = GetImmediateCmdSpace<cmd::Noop>(
+        skip_count * sizeof(CommandBufferEntry));
+    cmd.Init(skip_count);
+  }
+
+  void SetToken(uint32 token) {
+    cmd::SetToken& cmd = GetCmdSpace<cmd::SetToken>();
+    cmd.Init(token);
+  }
+
+
+ private:
+  // Waits until get changes, updating the value of get_.
+  void WaitForGetChange();
+
+  // Returns the number of available entries (they may not be contiguous).
+  int32 AvailableEntries() {
+    return (get_ - put_ - 1 + entry_count_) % entry_count_;
+  }
+
+  command_buffer::CommandBuffer* command_buffer_;
+  ::base::SharedMemory* ring_buffer_;
+  CommandBufferEntry *entries_;
+  int32 entry_count_;
+  int32 token_;
+  int32 last_token_read_;
+  int32 get_;
+  int32 put_;
+
+  friend class CommandBufferHelperTest;
+  DISALLOW_COPY_AND_ASSIGN(CommandBufferHelper);
+};
+
+}  // namespace command_buffer
+
+#endif  // GPU_COMMAND_BUFFER_CLIENT_CROSS_CMD_BUFFER_HELPER_H_
diff --git a/gpu/command_buffer/client/cmd_buffer_helper_test.cc b/gpu/command_buffer/client/cmd_buffer_helper_test.cc
new file mode 100644
index 0000000..4e2b31b2
--- /dev/null
+++ b/gpu/command_buffer/client/cmd_buffer_helper_test.cc
@@ -0,0 +1,303 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// Tests for the Command Buffer Helper.
+
+#include "base/at_exit.h"
+#include "base/message_loop.h"
+#include "gpu/command_buffer/client/cmd_buffer_helper.h"
+#include "gpu/command_buffer/service/mocks.h"
+#include "gpu/command_buffer/service/command_buffer_service.h"
+#include "gpu/command_buffer/service/gpu_processor.h"
+#include "gpu/np_utils/np_object_pointer.h"
+#include "gpu/np_utils/np_browser_stub.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace command_buffer {
+
+using command_buffer::CommandBufferService;
+using command_buffer::GPUProcessor;
+using np_utils::NPCreateObject;
+using np_utils::NPObjectPointer;
+using testing::Return;
+using testing::Mock;
+using testing::Truly;
+using testing::Sequence;
+using testing::DoAll;
+using testing::Invoke;
+using testing::_;
+
+const int32 kNumCommandEntries = 10;
+const int32 kCommandBufferSizeBytes = kNumCommandEntries * sizeof(int32);
+
+// Test fixture for CommandBufferHelper test - Creates a CommandBufferHelper,
+// using a CommandBufferEngine with a mock AsyncAPIInterface for its interface
+// (calling it directly, not through the RPC mechanism).
+class CommandBufferHelperTest : public testing::Test {
+ protected:
+  virtual void SetUp() {
+    api_mock_.reset(new AsyncAPIMock);
+    // ignore noops in the mock - we don't want to inspect the internals of the
+    // helper.
+    EXPECT_CALL(*api_mock_, DoCommand(0, 0, _))
+        .WillRepeatedly(Return(parse_error::kParseNoError));
+
+    ::base::SharedMemory* ring_buffer = new ::base::SharedMemory;
+    ring_buffer->Create(std::wstring(), false, false, kCommandBufferSizeBytes);
+    ring_buffer->Map(1024);
+
+    command_buffer_.reset(new CommandBufferService);
+    command_buffer_->Initialize(ring_buffer);
+
+    parser_ = new command_buffer::CommandParser(ring_buffer->memory(),
+                                                kCommandBufferSizeBytes,
+                                                0,
+                                                kCommandBufferSizeBytes,
+                                                0,
+                                                api_mock_.get());
+
+    scoped_refptr<GPUProcessor> gpu_processor(new GPUProcessor(
+        command_buffer_.get(), NULL, parser_, 1));
+    command_buffer_->SetPutOffsetChangeCallback(NewCallback(
+        gpu_processor.get(), &GPUProcessor::ProcessCommands));
+
+    api_mock_->set_engine(gpu_processor.get());
+
+    helper_.reset(new CommandBufferHelper(command_buffer_.get()));
+    helper_->Initialize();
+  }
+
+  virtual void TearDown() {
+    // If the GPUProcessor posts any tasks, this forces them to run.
+    MessageLoop::current()->RunAllPending();
+    helper_.release();
+  }
+
+  // Adds a command to the buffer through the helper, while adding it as an
+  // expected call on the API mock.
+  void AddCommandWithExpect(parse_error::ParseError _return,
+                            unsigned int command,
+                            unsigned int arg_count,
+                            CommandBufferEntry *args) {
+    helper_->AddCommand(command, arg_count, args);
+    EXPECT_CALL(*api_mock_, DoCommand(command, arg_count,
+        Truly(AsyncAPIMock::IsArgs(arg_count, args))))
+        .InSequence(sequence_)
+        .WillOnce(Return(_return));
+  }
+
+  // Checks that the buffer from put to put+size is free in the parser.
+  void CheckFreeSpace(CommandBufferOffset put, unsigned int size) {
+    CommandBufferOffset parser_put = parser_->put();
+    CommandBufferOffset parser_get = parser_->get();
+    CommandBufferOffset limit = put + size;
+    if (parser_get > parser_put) {
+      // "busy" buffer wraps, so "free" buffer is between put (inclusive) and
+      // get (exclusive).
+      EXPECT_LE(parser_put, put);
+      EXPECT_GT(parser_get, limit);
+    } else {
+      // "busy" buffer does not wrap, so the "free" buffer is the top side (from
+      // put to the limit) and the bottom side (from 0 to get).
+      if (put >= parser_put) {
+        // we're on the top side, check we are below the limit.
+        EXPECT_GE(kNumCommandEntries, limit);
+      } else {
+        // we're on the bottom side, check we are below get.
+        EXPECT_GT(parser_get, limit);
+      }
+    }
+  }
+
+  CommandBufferOffset get_helper_put() { return helper_->put_; }
+
+  base::AtExitManager at_exit_manager_;
+  MessageLoop message_loop_;
+  np_utils::StubNPBrowser browser_;
+  scoped_ptr<AsyncAPIMock> api_mock_;
+  scoped_ptr<CommandBufferService> command_buffer_;
+  command_buffer::CommandParser* parser_;
+  scoped_ptr<CommandBufferHelper> helper_;
+  Sequence sequence_;
+};
+
+// Checks that commands in the buffer are properly executed, and that the
+// status/error stay valid.
+TEST_F(CommandBufferHelperTest, TestCommandProcessing) {
+  // Check initial state of the engine - it should have been configured by the
+  // helper.
+  EXPECT_TRUE(parser_ != NULL);
+  EXPECT_FALSE(command_buffer_->GetErrorStatus());
+  EXPECT_EQ(parse_error::kParseNoError, command_buffer_->ResetParseError());
+  EXPECT_EQ(0u, command_buffer_->GetGetOffset());
+
+  // Add 3 commands through the helper
+  AddCommandWithExpect(parse_error::kParseNoError, 1, 0, NULL);
+
+  CommandBufferEntry args1[2];
+  args1[0].value_uint32 = 3;
+  args1[1].value_float = 4.f;
+  AddCommandWithExpect(parse_error::kParseNoError, 2, 2, args1);
+
+  CommandBufferEntry args2[2];
+  args2[0].value_uint32 = 5;
+  args2[1].value_float = 6.f;
+  AddCommandWithExpect(parse_error::kParseNoError, 3, 2, args2);
+
+  helper_->Flush();
+  // Check that the engine has work to do now.
+  EXPECT_FALSE(parser_->IsEmpty());
+
+  // Wait until it's done.
+  helper_->Finish();
+  // Check that the engine has no more work to do.
+  EXPECT_TRUE(parser_->IsEmpty());
+
+  // Check that the commands did happen.
+  Mock::VerifyAndClearExpectations(api_mock_.get());
+
+  // Check the error status.
+  EXPECT_FALSE(command_buffer_->GetErrorStatus());
+  EXPECT_EQ(parse_error::kParseNoError, command_buffer_->ResetParseError());
+}
+
+// Checks that commands in the buffer are properly executed when wrapping the
+// buffer, and that the status/error stay valid.
+TEST_F(CommandBufferHelperTest, TestCommandWrapping) {
+  // Add 5 commands of size 3 through the helper to make sure we do wrap.
+  CommandBufferEntry args1[2];
+  args1[0].value_uint32 = 3;
+  args1[1].value_float = 4.f;
+
+  for (unsigned int i = 0; i < 5; ++i) {
+    AddCommandWithExpect(parse_error::kParseNoError, i + 1, 2, args1);
+  }
+
+  helper_->Finish();
+  // Check that the commands did happen.
+  Mock::VerifyAndClearExpectations(api_mock_.get());
+
+  // Check the error status.
+  EXPECT_FALSE(command_buffer_->GetErrorStatus());
+  EXPECT_EQ(parse_error::kParseNoError, command_buffer_->ResetParseError());
+}
+
+
+// Checks that commands in the buffer are properly executed, even if they
+// generate a recoverable error. Check that the error status is properly set,
+// and reset when queried.
+TEST_F(CommandBufferHelperTest, TestRecoverableError) {
+  CommandBufferEntry args[2];
+  args[0].value_uint32 = 3;
+  args[1].value_float = 4.f;
+
+  // Create a command buffer with 3 commands, 2 of them generating errors
+  AddCommandWithExpect(parse_error::kParseNoError, 1, 2, args);
+  AddCommandWithExpect(parse_error::kParseUnknownCommand, 2, 2, args);
+  AddCommandWithExpect(parse_error::kParseInvalidArguments, 3, 2,
+                       args);
+
+  helper_->Finish();
+  // Check that the commands did happen.
+  Mock::VerifyAndClearExpectations(api_mock_.get());
+
+  // Check that the error status was set to the first error.
+  EXPECT_EQ(parse_error::kParseUnknownCommand,
+            command_buffer_->ResetParseError());
+  // Check that the error status was reset after the query.
+  EXPECT_EQ(parse_error::kParseNoError, command_buffer_->ResetParseError());
+}
+
+// Checks that asking for available entries work, and that the parser
+// effectively won't use that space.
+TEST_F(CommandBufferHelperTest, TestAvailableEntries) {
+  CommandBufferEntry args[2];
+  args[0].value_uint32 = 3;
+  args[1].value_float = 4.f;
+
+  // Add 2 commands through the helper - 8 entries
+  AddCommandWithExpect(parse_error::kParseNoError, 1, 0, NULL);
+  AddCommandWithExpect(parse_error::kParseNoError, 2, 0, NULL);
+  AddCommandWithExpect(parse_error::kParseNoError, 3, 2, args);
+  AddCommandWithExpect(parse_error::kParseNoError, 4, 2, args);
+
+  // Ask for 5 entries.
+  helper_->WaitForAvailableEntries(5);
+
+  CommandBufferOffset put = get_helper_put();
+  CheckFreeSpace(put, 5);
+
+  // Add more commands.
+  AddCommandWithExpect(parse_error::kParseNoError, 5, 2, args);
+
+  // Wait until everything is done done.
+  helper_->Finish();
+
+  // Check that the commands did happen.
+  Mock::VerifyAndClearExpectations(api_mock_.get());
+
+  // Check the error status.
+  EXPECT_FALSE(command_buffer_->GetErrorStatus());
+  EXPECT_EQ(parse_error::kParseNoError, command_buffer_->ResetParseError());
+}
+
+// Checks that the InsertToken/WaitForToken work.
+TEST_F(CommandBufferHelperTest, TestToken) {
+  CommandBufferEntry args[2];
+  args[0].value_uint32 = 3;
+  args[1].value_float = 4.f;
+
+  // Add a first command.
+  AddCommandWithExpect(parse_error::kParseNoError, 3, 2, args);
+  // keep track of the buffer position.
+  CommandBufferOffset command1_put = get_helper_put();
+  int32 token = helper_->InsertToken();
+
+  EXPECT_CALL(*api_mock_.get(), DoCommand(cmd::kSetToken, 1, _))
+      .WillOnce(DoAll(Invoke(api_mock_.get(), &AsyncAPIMock::SetToken),
+                      Return(parse_error::kParseNoError)));
+  // Add another command.
+  AddCommandWithExpect(parse_error::kParseNoError, 4, 2, args);
+  helper_->WaitForToken(token);
+  // check that the get pointer is beyond the first command.
+  EXPECT_LE(command1_put, command_buffer_->GetGetOffset());
+  helper_->Finish();
+
+  // Check that the commands did happen.
+  Mock::VerifyAndClearExpectations(api_mock_.get());
+
+  // Check the error status.
+  EXPECT_FALSE(command_buffer_->GetErrorStatus());
+  EXPECT_EQ(parse_error::kParseNoError, command_buffer_->ResetParseError());
+}
+
+}  // namespace command_buffer
diff --git a/gpu/command_buffer/client/fenced_allocator.cc b/gpu/command_buffer/client/fenced_allocator.cc
new file mode 100644
index 0000000..810feb55
--- /dev/null
+++ b/gpu/command_buffer/client/fenced_allocator.cc
@@ -0,0 +1,214 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains the implementation of the FencedAllocator class.
+
+#include "gpu/command_buffer/client/fenced_allocator.h"
+#include <algorithm>
+#include "gpu/command_buffer/client/cmd_buffer_helper.h"
+
+namespace command_buffer {
+
+#ifndef COMPILER_MSVC
+const FencedAllocator::Offset FencedAllocator::kInvalidOffset;
+#endif
+
+FencedAllocator::~FencedAllocator() {
+  // Free blocks pending tokens.
+  for (unsigned int i = 0; i < blocks_.size(); ++i) {
+    if (blocks_[i].state == FREE_PENDING_TOKEN) {
+      i = WaitForTokenAndFreeBlock(i);
+    }
+  }
+  DCHECK_EQ(blocks_.size(), 1u);
+  DCHECK_EQ(blocks_[0].state, FREE);
+}
+
+// Looks for a non-allocated block that is big enough. Search in the FREE
+// blocks first (for direct usage), first-fit, then in the FREE_PENDING_TOKEN
+// blocks, waiting for them. The current implementation isn't smart about
+// optimizing what to wait for, just looks inside the block in order (first-fit
+// as well).
+FencedAllocator::Offset FencedAllocator::Alloc(unsigned int size) {
+  // Similarly to malloc, an allocation of 0 allocates at least 1 byte, to
+  // return different pointers every time.
+  if (size == 0) size = 1;
+
+  // Try first to allocate in a free block.
+  for (unsigned int i = 0; i < blocks_.size(); ++i) {
+    Block &block = blocks_[i];
+    if (block.state == FREE && block.size >= size) {
+      return AllocInBlock(i, size);
+    }
+  }
+
+  // No free block is available. Look for blocks pending tokens, and wait for
+  // them to be re-usable.
+  for (unsigned int i = 0; i < blocks_.size(); ++i) {
+    if (blocks_[i].state != FREE_PENDING_TOKEN)
+      continue;
+    i = WaitForTokenAndFreeBlock(i);
+    if (blocks_[i].size >= size)
+      return AllocInBlock(i, size);
+  }
+  return kInvalidOffset;
+}
+
+// Looks for the corresponding block, mark it FREE, and collapse it if
+// necessary.
+void FencedAllocator::Free(FencedAllocator::Offset offset) {
+  BlockIndex index = GetBlockByOffset(offset);
+  DCHECK_NE(blocks_[index].state, FREE);
+  blocks_[index].state = FREE;
+  CollapseFreeBlock(index);
+}
+
+// Looks for the corresponding block, mark it FREE_PENDING_TOKEN.
+void FencedAllocator::FreePendingToken(FencedAllocator::Offset offset,
+                                       unsigned int token) {
+  BlockIndex index = GetBlockByOffset(offset);
+  Block &block = blocks_[index];
+  block.state = FREE_PENDING_TOKEN;
+  block.token = token;
+}
+
+// Gets the max of the size of the blocks marked as free.
+unsigned int FencedAllocator::GetLargestFreeSize() {
+  unsigned int max_size = 0;
+  for (unsigned int i = 0; i < blocks_.size(); ++i) {
+    Block &block = blocks_[i];
+    if (block.state == FREE)
+      max_size = std::max(max_size, block.size);
+  }
+  return max_size;
+}
+
+// Gets the size of the largest segment of blocks that are either FREE or
+// FREE_PENDING_TOKEN.
+unsigned int FencedAllocator::GetLargestFreeOrPendingSize() {
+  unsigned int max_size = 0;
+  unsigned int current_size = 0;
+  for (unsigned int i = 0; i < blocks_.size(); ++i) {
+    Block &block = blocks_[i];
+    if (block.state == IN_USE) {
+      max_size = std::max(max_size, current_size);
+      current_size = 0;
+    } else {
+      DCHECK(block.state == FREE || block.state == FREE_PENDING_TOKEN);
+      current_size += block.size;
+    }
+  }
+  return std::max(max_size, current_size);
+}
+
+// Makes sure that:
+// - there is at least one block.
+// - there are no contiguous FREE blocks (they should have been collapsed).
+// - the successive offsets match the block sizes, and they are in order.
+bool FencedAllocator::CheckConsistency() {
+  if (blocks_.size() < 1) return false;
+  for (unsigned int i = 0; i < blocks_.size() - 1; ++i) {
+    Block &current = blocks_[i];
+    Block &next = blocks_[i + 1];
+    // This test is NOT included in the next one, because offset is unsigned.
+    if (next.offset <= current.offset)
+      return false;
+    if (next.offset != current.offset + current.size)
+      return false;
+    if (current.state == FREE && next.state == FREE)
+      return false;
+  }
+  return true;
+}
+
+// Collapse the block to the next one, then to the previous one. Provided the
+// structure is consistent, those are the only blocks eligible for collapse.
+FencedAllocator::BlockIndex FencedAllocator::CollapseFreeBlock(
+    BlockIndex index) {
+  if (index + 1 < blocks_.size()) {
+    Block &next = blocks_[index + 1];
+    if (next.state == FREE) {
+      blocks_[index].size += next.size;
+      blocks_.erase(blocks_.begin() + index + 1);
+    }
+  }
+  if (index > 0) {
+    Block &prev = blocks_[index - 1];
+    if (prev.state == FREE) {
+      prev.size += blocks_[index].size;
+      blocks_.erase(blocks_.begin() + index);
+      --index;
+    }
+  }
+  return index;
+}
+
+// Waits for the block's token, then mark the block as free, then collapse it.
+FencedAllocator::BlockIndex FencedAllocator::WaitForTokenAndFreeBlock(
+    BlockIndex index) {
+  Block &block = blocks_[index];
+  DCHECK_EQ(block.state, FREE_PENDING_TOKEN);
+  helper_->WaitForToken(block.token);
+  block.state = FREE;
+  return CollapseFreeBlock(index);
+}
+
+// If the block is exactly the requested size, simply mark it IN_USE, otherwise
+// split it and mark the first one (of the requested size) IN_USE.
+FencedAllocator::Offset FencedAllocator::AllocInBlock(BlockIndex index,
+                                                      unsigned int size) {
+  Block &block = blocks_[index];
+  DCHECK_GE(block.size, size);
+  DCHECK_EQ(block.state, FREE);
+  Offset offset = block.offset;
+  if (block.size == size) {
+    block.state = IN_USE;
+    return offset;
+  }
+  Block newblock = { FREE, offset + size, block.size - size, kUnusedToken};
+  block.state = IN_USE;
+  block.size = size;
+  // this is the last thing being done because it may invalidate block;
+  blocks_.insert(blocks_.begin() + index + 1, newblock);
+  return offset;
+}
+
+// The blocks are in offset order, so we can do a binary search.
+FencedAllocator::BlockIndex FencedAllocator::GetBlockByOffset(Offset offset) {
+  Block templ = { IN_USE, offset, 0, kUnusedToken };
+  Container::iterator it = std::lower_bound(blocks_.begin(), blocks_.end(),
+                                            templ, OffsetCmp());
+  DCHECK(it != blocks_.end() && it->offset == offset);
+  return it-blocks_.begin();
+}
+
+}  // namespace command_buffer
diff --git a/gpu/command_buffer/client/fenced_allocator.h b/gpu/command_buffer/client/fenced_allocator.h
new file mode 100644
index 0000000..72bba33
--- /dev/null
+++ b/gpu/command_buffer/client/fenced_allocator.h
@@ -0,0 +1,266 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains the definition of the FencedAllocator class.
+
+#ifndef GPU_COMMAND_BUFFER_CLIENT_CROSS_FENCED_ALLOCATOR_H_
+#define GPU_COMMAND_BUFFER_CLIENT_CROSS_FENCED_ALLOCATOR_H_
+
+#include <vector>
+#include "base/basictypes.h"
+#include "gpu/command_buffer/common/logging.h"
+
+namespace command_buffer {
+class CommandBufferHelper;
+
+// FencedAllocator provides a mechanism to manage allocations within a fixed
+// block of memory (storing the book-keeping externally). Furthermore this
+// class allows to free data "pending" the passage of a command buffer token,
+// that is, the memory won't be reused until the command buffer has processed
+// that token.
+//
+// NOTE: Although this class is intended to be used in the command buffer
+// environment which is multi-process, this class isn't "thread safe", because
+// it isn't meant to be shared across modules. It is thread-compatible though
+// (see http://www.corp.google.com/eng/doc/cpp_primer.html#thread_safety).
+class FencedAllocator {
+ public:
+  typedef unsigned int Offset;
+  // Invalid offset, returned by Alloc in case of failure.
+  static const Offset kInvalidOffset = 0xffffffffU;
+
+  // Creates a FencedAllocator. Note that the size of the buffer is passed, but
+  // not its base address: everything is handled as offsets into the buffer.
+  FencedAllocator(unsigned int size,
+                  CommandBufferHelper *helper)
+      : helper_(helper) {
+    Block block = { FREE, 0, size, kUnusedToken };
+    blocks_.push_back(block);
+  }
+
+  ~FencedAllocator();
+
+  // Allocates a block of memory. If the buffer is out of directly available
+  // memory, this function may wait until memory that was freed "pending a
+  // token" can be re-used.
+  //
+  // Parameters:
+  //   size: the size of the memory block to allocate.
+  //
+  // Returns:
+  //   the offset of the allocated memory block, or kInvalidOffset if out of
+  //   memory.
+  Offset Alloc(unsigned int size);
+
+  // Frees a block of memory.
+  //
+  // Parameters:
+  //   offset: the offset of the memory block to free.
+  void Free(Offset offset);
+
+  // Frees a block of memory, pending the passage of a token. That memory won't
+  // be re-allocated until the token has passed through the command stream.
+  //
+  // Parameters:
+  //   offset: the offset of the memory block to free.
+  //   token: the token value to wait for before re-using the memory.
+  void FreePendingToken(Offset offset, unsigned int token);
+
+  // Gets the size of the largest free block that is available without waiting.
+  unsigned int GetLargestFreeSize();
+
+  // Gets the size of the largest free block that can be allocated if the
+  // caller can wait. Allocating a block of this size will succeed, but may
+  // block.
+  unsigned int GetLargestFreeOrPendingSize();
+
+  // Checks for consistency inside the book-keeping structures. Used for
+  // testing.
+  bool CheckConsistency();
+
+ private:
+  // Status of a block of memory, for book-keeping.
+  enum State {
+    IN_USE,
+    FREE,
+    FREE_PENDING_TOKEN
+  };
+
+  // Book-keeping sturcture that describes a block of memory.
+  struct Block {
+    State state;
+    Offset offset;
+    unsigned int size;
+    unsigned int token;  // token to wait for in the FREE_PENDING_TOKEN case.
+  };
+
+  // Comparison functor for memory block sorting.
+  class OffsetCmp {
+   public:
+    bool operator() (const Block &left, const Block &right) {
+      return left.offset < right.offset;
+    }
+  };
+
+  typedef std::vector<Block> Container;
+  typedef unsigned int BlockIndex;
+
+  static const unsigned int kUnusedToken = 0;
+
+  // Gets the index of a memory block, given its offset.
+  BlockIndex GetBlockByOffset(Offset offset);
+
+  // Collapse a free block with its neighbours if they are free. Returns the
+  // index of the collapsed block.
+  // NOTE: this will invalidate block indices.
+  BlockIndex CollapseFreeBlock(BlockIndex index);
+
+  // Waits for a FREE_PENDING_TOKEN block to be usable, and free it. Returns
+  // the new index of that block (since it may have been collapsed).
+  // NOTE: this will invalidate block indices.
+  BlockIndex WaitForTokenAndFreeBlock(BlockIndex index);
+
+  // Allocates a block of memory inside a given block, splitting it in two
+  // (unless that block is of the exact requested size).
+  // NOTE: this will invalidate block indices.
+  // Returns the offset of the allocated block (NOTE: this is different from
+  // the other functions that return a block index).
+  Offset AllocInBlock(BlockIndex index, unsigned int size);
+
+  command_buffer::CommandBufferHelper *helper_;
+  Container blocks_;
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(FencedAllocator);
+};
+
+// This class functions just like FencedAllocator, but its API uses pointers
+// instead of offsets.
+class FencedAllocatorWrapper {
+ public:
+  FencedAllocatorWrapper(unsigned int size,
+                         CommandBufferHelper *helper,
+                         void *base)
+      : allocator_(size, helper),
+        base_(base) { }
+
+  // Allocates a block of memory. If the buffer is out of directly available
+  // memory, this function may wait until memory that was freed "pending a
+  // token" can be re-used.
+  //
+  // Parameters:
+  //   size: the size of the memory block to allocate.
+  //
+  // Returns:
+  //   the pointer to the allocated memory block, or NULL if out of
+  //   memory.
+  void *Alloc(unsigned int size) {
+    FencedAllocator::Offset offset = allocator_.Alloc(size);
+    return GetPointer(offset);
+  }
+
+  // Allocates a block of memory. If the buffer is out of directly available
+  // memory, this function may wait until memory that was freed "pending a
+  // token" can be re-used.
+  // This is a type-safe version of Alloc, returning a typed pointer.
+  //
+  // Parameters:
+  //   count: the number of elements to allocate.
+  //
+  // Returns:
+  //   the pointer to the allocated memory block, or NULL if out of
+  //   memory.
+  template <typename T> T *AllocTyped(unsigned int count) {
+    return static_cast<T *>(Alloc(count * sizeof(T)));
+  }
+
+  // Frees a block of memory.
+  //
+  // Parameters:
+  //   pointer: the pointer to the memory block to free.
+  void Free(void *pointer) {
+    DCHECK(pointer);
+    allocator_.Free(GetOffset(pointer));
+  }
+
+  // Frees a block of memory, pending the passage of a token. That memory won't
+  // be re-allocated until the token has passed through the command stream.
+  //
+  // Parameters:
+  //   pointer: the pointer to the memory block to free.
+  //   token: the token value to wait for before re-using the memory.
+  void FreePendingToken(void *pointer, unsigned int token) {
+    DCHECK(pointer);
+    allocator_.FreePendingToken(GetOffset(pointer), token);
+  }
+
+  // Gets a pointer to a memory block given the base memory and the offset.
+  // It translates FencedAllocator::kInvalidOffset to NULL.
+  void *GetPointer(FencedAllocator::Offset offset) {
+    return (offset == FencedAllocator::kInvalidOffset) ?
+        NULL : static_cast<char *>(base_) + offset;
+  }
+
+  // Gets the offset to a memory block given the base memory and the address.
+  // It translates NULL to FencedAllocator::kInvalidOffset.
+  FencedAllocator::Offset GetOffset(void *pointer) {
+    return pointer ? static_cast<char *>(pointer) - static_cast<char *>(base_) :
+        FencedAllocator::kInvalidOffset;
+  }
+
+  // Gets the size of the largest free block that is available without waiting.
+  unsigned int GetLargestFreeSize() {
+    return allocator_.GetLargestFreeSize();
+  }
+
+  // Gets the size of the largest free block that can be allocated if the
+  // caller can wait.
+  unsigned int GetLargestFreeOrPendingSize() {
+    return allocator_.GetLargestFreeOrPendingSize();
+  }
+
+  // Checks for consistency inside the book-keeping structures. Used for
+  // testing.
+  bool CheckConsistency() {
+    return allocator_.CheckConsistency();
+  }
+
+  FencedAllocator &allocator() { return allocator_; }
+
+ private:
+  FencedAllocator allocator_;
+  void *base_;
+  DISALLOW_IMPLICIT_CONSTRUCTORS(FencedAllocatorWrapper);
+};
+
+}  // namespace command_buffer
+
+#endif  // GPU_COMMAND_BUFFER_CLIENT_CROSS_FENCED_ALLOCATOR_H_
diff --git a/gpu/command_buffer/client/fenced_allocator_test.cc b/gpu/command_buffer/client/fenced_allocator_test.cc
new file mode 100644
index 0000000..dcb75bc
--- /dev/null
+++ b/gpu/command_buffer/client/fenced_allocator_test.cc
@@ -0,0 +1,501 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains the tests for the FencedAllocator class.
+
+#include "base/at_exit.h"
+#include "base/message_loop.h"
+#include "gpu/command_buffer/client/cmd_buffer_helper.h"
+#include "gpu/command_buffer/client/fenced_allocator.h"
+#include "gpu/command_buffer/service/cmd_buffer_engine.h"
+#include "gpu/command_buffer/service/mocks.h"
+#include "gpu/command_buffer/service/command_buffer_service.h"
+#include "gpu/command_buffer/service/gpu_processor.h"
+#include "gpu/np_utils/np_browser_stub.h"
+#include "gpu/np_utils/np_object_pointer.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace command_buffer {
+
+using command_buffer::CommandBufferService;
+using command_buffer::GPUProcessor;
+using np_utils::NPCreateObject;
+using np_utils::NPObjectPointer;
+using testing::Return;
+using testing::Mock;
+using testing::Truly;
+using testing::Sequence;
+using testing::DoAll;
+using testing::Invoke;
+using testing::_;
+
+class BaseFencedAllocatorTest : public testing::Test {
+ protected:
+  static const unsigned int kBufferSize = 1024;
+
+  virtual void SetUp() {
+    api_mock_.reset(new AsyncAPIMock);
+    // ignore noops in the mock - we don't want to inspect the internals of the
+    // helper.
+    EXPECT_CALL(*api_mock_, DoCommand(cmd::kNoop, 0, _))
+        .WillRepeatedly(Return(parse_error::kParseNoError));
+    // Forward the SetToken calls to the engine
+    EXPECT_CALL(*api_mock_.get(), DoCommand(cmd::kSetToken, 1, _))
+        .WillRepeatedly(DoAll(Invoke(api_mock_.get(), &AsyncAPIMock::SetToken),
+                              Return(parse_error::kParseNoError)));
+
+    ::base::SharedMemory* ring_buffer = new ::base::SharedMemory;
+    ring_buffer->Create(std::wstring(), false, false, 1024);
+    ring_buffer->Map(1024);
+
+    command_buffer_.reset(new CommandBufferService);
+    command_buffer_->Initialize(ring_buffer);
+
+    parser_ = new command_buffer::CommandParser(ring_buffer->memory(),
+                                                kBufferSize,
+                                                0,
+                                                kBufferSize,
+                                                0,
+                                                api_mock_.get());
+
+    scoped_refptr<GPUProcessor> gpu_processor(new GPUProcessor(
+        command_buffer_.get(), NULL, parser_, INT_MAX));
+    command_buffer_->SetPutOffsetChangeCallback(NewCallback(
+        gpu_processor.get(), &GPUProcessor::ProcessCommands));
+
+    api_mock_->set_engine(gpu_processor.get());
+
+    helper_.reset(new CommandBufferHelper(command_buffer_.get()));
+    helper_->Initialize();
+  }
+
+  virtual void TearDown() {
+    helper_.release();
+  }
+
+  base::AtExitManager at_exit_manager_;
+  MessageLoop message_loop_;
+  np_utils::StubNPBrowser browser_;
+  scoped_ptr<AsyncAPIMock> api_mock_;
+  scoped_ptr<CommandBufferService> command_buffer_;
+  command_buffer::CommandParser* parser_;
+  scoped_ptr<CommandBufferHelper> helper_;
+};
+
+#ifndef COMPILER_MSVC
+const unsigned int BaseFencedAllocatorTest::kBufferSize;
+#endif
+
+// Test fixture for FencedAllocator test - Creates a FencedAllocator, using a
+// CommandBufferHelper with a mock AsyncAPIInterface for its interface (calling
+// it directly, not through the RPC mechanism), making sure Noops are ignored
+// and SetToken are properly forwarded to the engine.
+class FencedAllocatorTest : public BaseFencedAllocatorTest {
+ protected:
+  virtual void SetUp() {
+    BaseFencedAllocatorTest::SetUp();
+    allocator_.reset(new FencedAllocator(kBufferSize, helper_.get()));
+  }
+
+  virtual void TearDown() {
+    // If the GPUProcessor posts any tasks, this forces them to run.
+    MessageLoop::current()->RunAllPending();
+
+    EXPECT_TRUE(allocator_->CheckConsistency());
+    allocator_.release();
+
+    BaseFencedAllocatorTest::TearDown();
+  }
+
+  scoped_ptr<FencedAllocator> allocator_;
+};
+
+// Checks basic alloc and free.
+TEST_F(FencedAllocatorTest, TestBasic) {
+  allocator_->CheckConsistency();
+
+  const unsigned int kSize = 16;
+  FencedAllocator::Offset offset = allocator_->Alloc(kSize);
+  EXPECT_NE(FencedAllocator::kInvalidOffset, offset);
+  EXPECT_GE(kBufferSize, offset+kSize);
+  EXPECT_TRUE(allocator_->CheckConsistency());
+
+  allocator_->Free(offset);
+  EXPECT_TRUE(allocator_->CheckConsistency());
+}
+
+// Checks out-of-memory condition.
+TEST_F(FencedAllocatorTest, TestOutOfMemory) {
+  EXPECT_TRUE(allocator_->CheckConsistency());
+
+  const unsigned int kSize = 16;
+  const unsigned int kAllocCount = kBufferSize / kSize;
+  CHECK(kAllocCount * kSize == kBufferSize);
+
+  // Allocate several buffers to fill in the memory.
+  FencedAllocator::Offset offsets[kAllocCount];
+  for (unsigned int i = 0; i < kAllocCount; ++i) {
+    offsets[i] = allocator_->Alloc(kSize);
+    EXPECT_NE(FencedAllocator::kInvalidOffset, offsets[i]);
+    EXPECT_GE(kBufferSize, offsets[i]+kSize);
+    EXPECT_TRUE(allocator_->CheckConsistency());
+  }
+
+  // This allocation should fail.
+  FencedAllocator::Offset offset_failed = allocator_->Alloc(kSize);
+  EXPECT_EQ(FencedAllocator::kInvalidOffset, offset_failed);
+  EXPECT_TRUE(allocator_->CheckConsistency());
+
+  // Free one successful allocation, reallocate with half the size
+  allocator_->Free(offsets[0]);
+  EXPECT_TRUE(allocator_->CheckConsistency());
+  offsets[0] = allocator_->Alloc(kSize/2);
+  EXPECT_NE(FencedAllocator::kInvalidOffset, offsets[0]);
+  EXPECT_GE(kBufferSize, offsets[0]+kSize);
+  EXPECT_TRUE(allocator_->CheckConsistency());
+
+  // This allocation should fail as well.
+  offset_failed = allocator_->Alloc(kSize);
+  EXPECT_EQ(FencedAllocator::kInvalidOffset, offset_failed);
+  EXPECT_TRUE(allocator_->CheckConsistency());
+
+  // Free up everything.
+  for (unsigned int i = 0; i < kAllocCount; ++i) {
+    allocator_->Free(offsets[i]);
+    EXPECT_TRUE(allocator_->CheckConsistency());
+  }
+}
+
+// Checks the free-pending-token mechanism.
+TEST_F(FencedAllocatorTest, TestFreePendingToken) {
+  EXPECT_TRUE(allocator_->CheckConsistency());
+
+  const unsigned int kSize = 16;
+  const unsigned int kAllocCount = kBufferSize / kSize;
+  CHECK(kAllocCount * kSize == kBufferSize);
+
+  // Allocate several buffers to fill in the memory.
+  FencedAllocator::Offset offsets[kAllocCount];
+  for (unsigned int i = 0; i < kAllocCount; ++i) {
+    offsets[i] = allocator_->Alloc(kSize);
+    EXPECT_NE(FencedAllocator::kInvalidOffset, offsets[i]);
+    EXPECT_GE(kBufferSize, offsets[i]+kSize);
+    EXPECT_TRUE(allocator_->CheckConsistency());
+  }
+
+  // This allocation should fail.
+  FencedAllocator::Offset offset_failed = allocator_->Alloc(kSize);
+  EXPECT_EQ(FencedAllocator::kInvalidOffset, offset_failed);
+  EXPECT_TRUE(allocator_->CheckConsistency());
+
+  // Free one successful allocation, pending fence.
+  int32 token = helper_.get()->InsertToken();
+  allocator_->FreePendingToken(offsets[0], token);
+  EXPECT_TRUE(allocator_->CheckConsistency());
+
+  // The way we hooked up the helper and engine, it won't process commands
+  // until it has to wait for something. Which means the token shouldn't have
+  // passed yet at this point.
+  EXPECT_GT(token, command_buffer_->GetToken());
+
+  // This allocation will need to reclaim the space freed above, so that should
+  // process the commands until the token is passed.
+  offsets[0] = allocator_->Alloc(kSize);
+  EXPECT_NE(FencedAllocator::kInvalidOffset, offsets[0]);
+  EXPECT_GE(kBufferSize, offsets[0]+kSize);
+  EXPECT_TRUE(allocator_->CheckConsistency());
+  // Check that the token has indeed passed.
+  EXPECT_LE(token, command_buffer_->GetToken());
+
+  // Free up everything.
+  for (unsigned int i = 0; i < kAllocCount; ++i) {
+    allocator_->Free(offsets[i]);
+    EXPECT_TRUE(allocator_->CheckConsistency());
+  }
+}
+
+// Tests GetLargestFreeSize
+TEST_F(FencedAllocatorTest, TestGetLargestFreeSize) {
+  EXPECT_TRUE(allocator_->CheckConsistency());
+  EXPECT_EQ(kBufferSize, allocator_->GetLargestFreeSize());
+
+  FencedAllocator::Offset offset = allocator_->Alloc(kBufferSize);
+  ASSERT_NE(FencedAllocator::kInvalidOffset, offset);
+  EXPECT_EQ(0u, allocator_->GetLargestFreeSize());
+  allocator_->Free(offset);
+  EXPECT_EQ(kBufferSize, allocator_->GetLargestFreeSize());
+
+  const unsigned int kSize = 16;
+  offset = allocator_->Alloc(kSize);
+  ASSERT_NE(FencedAllocator::kInvalidOffset, offset);
+  // The following checks that the buffer is allocated "smartly" - which is
+  // dependent on the implementation. But both first-fit or best-fit would
+  // ensure that.
+  EXPECT_EQ(kBufferSize - kSize, allocator_->GetLargestFreeSize());
+
+  // Allocate 2 more buffers (now 3), and then free the first two. This is to
+  // ensure a hole. Note that this is dependent on the first-fit current
+  // implementation.
+  FencedAllocator::Offset offset1 = allocator_->Alloc(kSize);
+  ASSERT_NE(FencedAllocator::kInvalidOffset, offset1);
+  FencedAllocator::Offset offset2 = allocator_->Alloc(kSize);
+  ASSERT_NE(FencedAllocator::kInvalidOffset, offset2);
+  allocator_->Free(offset);
+  allocator_->Free(offset1);
+  EXPECT_EQ(kBufferSize - 3 * kSize, allocator_->GetLargestFreeSize());
+
+  offset = allocator_->Alloc(kBufferSize - 3 * kSize);
+  ASSERT_NE(FencedAllocator::kInvalidOffset, offset);
+  EXPECT_EQ(2 * kSize, allocator_->GetLargestFreeSize());
+
+  offset1 = allocator_->Alloc(2 * kSize);
+  ASSERT_NE(FencedAllocator::kInvalidOffset, offset1);
+  EXPECT_EQ(0u, allocator_->GetLargestFreeSize());
+
+  allocator_->Free(offset);
+  allocator_->Free(offset1);
+  allocator_->Free(offset2);
+}
+
+// Tests GetLargestFreeOrPendingSize
+TEST_F(FencedAllocatorTest, TestGetLargestFreeOrPendingSize) {
+  EXPECT_TRUE(allocator_->CheckConsistency());
+  EXPECT_EQ(kBufferSize, allocator_->GetLargestFreeOrPendingSize());
+
+  FencedAllocator::Offset offset = allocator_->Alloc(kBufferSize);
+  ASSERT_NE(FencedAllocator::kInvalidOffset, offset);
+  EXPECT_EQ(0u, allocator_->GetLargestFreeOrPendingSize());
+  allocator_->Free(offset);
+  EXPECT_EQ(kBufferSize, allocator_->GetLargestFreeOrPendingSize());
+
+  const unsigned int kSize = 16;
+  offset = allocator_->Alloc(kSize);
+  ASSERT_NE(FencedAllocator::kInvalidOffset, offset);
+  // The following checks that the buffer is allocates "smartly" - which is
+  // dependent on the implementation. But both first-fit or best-fit would
+  // ensure that.
+  EXPECT_EQ(kBufferSize - kSize, allocator_->GetLargestFreeOrPendingSize());
+
+  // Allocate 2 more buffers (now 3), and then free the first two. This is to
+  // ensure a hole. Note that this is dependent on the first-fit current
+  // implementation.
+  FencedAllocator::Offset offset1 = allocator_->Alloc(kSize);
+  ASSERT_NE(FencedAllocator::kInvalidOffset, offset1);
+  FencedAllocator::Offset offset2 = allocator_->Alloc(kSize);
+  ASSERT_NE(FencedAllocator::kInvalidOffset, offset2);
+  allocator_->Free(offset);
+  allocator_->Free(offset1);
+  EXPECT_EQ(kBufferSize - 3 * kSize,
+            allocator_->GetLargestFreeOrPendingSize());
+
+  // Free the last one, pending a token.
+  int32 token = helper_.get()->InsertToken();
+  allocator_->FreePendingToken(offset2, token);
+
+  // Now all the buffers have been freed...
+  EXPECT_EQ(kBufferSize, allocator_->GetLargestFreeOrPendingSize());
+  // .. but one is still waiting for the token.
+  EXPECT_EQ(kBufferSize - 3 * kSize,
+            allocator_->GetLargestFreeSize());
+
+  // The way we hooked up the helper and engine, it won't process commands
+  // until it has to wait for something. Which means the token shouldn't have
+  // passed yet at this point.
+  EXPECT_GT(token, command_buffer_->GetToken());
+  // This allocation will need to reclaim the space freed above, so that should
+  // process the commands until the token is passed, but it will succeed.
+  offset = allocator_->Alloc(kBufferSize);
+  ASSERT_NE(FencedAllocator::kInvalidOffset, offset);
+  // Check that the token has indeed passed.
+  EXPECT_LE(token, command_buffer_->GetToken());
+  allocator_->Free(offset);
+
+  // Everything now has been freed...
+  EXPECT_EQ(kBufferSize, allocator_->GetLargestFreeOrPendingSize());
+  // ... for real.
+  EXPECT_EQ(kBufferSize, allocator_->GetLargestFreeSize());
+}
+
+// Test fixture for FencedAllocatorWrapper test - Creates a
+// FencedAllocatorWrapper, using a CommandBufferHelper with a mock
+// AsyncAPIInterface for its interface (calling it directly, not through the
+// RPC mechanism), making sure Noops are ignored and SetToken are properly
+// forwarded to the engine.
+class FencedAllocatorWrapperTest : public BaseFencedAllocatorTest {
+ protected:
+  virtual void SetUp() {
+    BaseFencedAllocatorTest::SetUp();
+
+    // Though allocating this buffer isn't strictly necessary, it makes
+    // allocations point to valid addresses, so they could be used for
+    // something.
+    buffer_.reset(new char[kBufferSize]);
+    allocator_.reset(new FencedAllocatorWrapper(kBufferSize, helper_.get(),
+                                                buffer_.get()));
+  }
+
+  virtual void TearDown() {
+    // If the GPUProcessor posts any tasks, this forces them to run.
+    MessageLoop::current()->RunAllPending();
+
+    EXPECT_TRUE(allocator_->CheckConsistency());
+    allocator_.release();
+    buffer_.release();
+
+    BaseFencedAllocatorTest::TearDown();
+  }
+
+  scoped_ptr<FencedAllocatorWrapper> allocator_;
+  scoped_array<char> buffer_;
+};
+
+// Checks basic alloc and free.
+TEST_F(FencedAllocatorWrapperTest, TestBasic) {
+  allocator_->CheckConsistency();
+
+  const unsigned int kSize = 16;
+  void *pointer = allocator_->Alloc(kSize);
+  ASSERT_TRUE(pointer);
+  EXPECT_LE(buffer_.get(), static_cast<char *>(pointer));
+  EXPECT_GE(kBufferSize, static_cast<char *>(pointer) - buffer_.get() + kSize);
+  EXPECT_TRUE(allocator_->CheckConsistency());
+
+  allocator_->Free(pointer);
+  EXPECT_TRUE(allocator_->CheckConsistency());
+
+  char *pointer_char = allocator_->AllocTyped<char>(kSize);
+  ASSERT_TRUE(pointer_char);
+  EXPECT_LE(buffer_.get(), pointer_char);
+  EXPECT_GE(buffer_.get() + kBufferSize, pointer_char + kSize);
+  allocator_->Free(pointer_char);
+  EXPECT_TRUE(allocator_->CheckConsistency());
+
+  unsigned int *pointer_uint = allocator_->AllocTyped<unsigned int>(kSize);
+  ASSERT_TRUE(pointer_uint);
+  EXPECT_LE(buffer_.get(), reinterpret_cast<char *>(pointer_uint));
+  EXPECT_GE(buffer_.get() + kBufferSize,
+            reinterpret_cast<char *>(pointer_uint + kSize));
+
+  // Check that it did allocate kSize * sizeof(unsigned int). We can't tell
+  // directly, except from the remaining size.
+  EXPECT_EQ(kBufferSize - kSize * sizeof(*pointer_uint),
+            allocator_->GetLargestFreeSize());
+  allocator_->Free(pointer_uint);
+}
+
+// Checks out-of-memory condition.
+TEST_F(FencedAllocatorWrapperTest, TestOutOfMemory) {
+  allocator_->CheckConsistency();
+
+  const unsigned int kSize = 16;
+  const unsigned int kAllocCount = kBufferSize / kSize;
+  CHECK(kAllocCount * kSize == kBufferSize);
+
+  // Allocate several buffers to fill in the memory.
+  void *pointers[kAllocCount];
+  for (unsigned int i = 0; i < kAllocCount; ++i) {
+    pointers[i] = allocator_->Alloc(kSize);
+    EXPECT_TRUE(pointers[i]);
+    EXPECT_TRUE(allocator_->CheckConsistency());
+  }
+
+  // This allocation should fail.
+  void *pointer_failed = allocator_->Alloc(kSize);
+  EXPECT_FALSE(pointer_failed);
+  EXPECT_TRUE(allocator_->CheckConsistency());
+
+  // Free one successful allocation, reallocate with half the size
+  allocator_->Free(pointers[0]);
+  EXPECT_TRUE(allocator_->CheckConsistency());
+  pointers[0] = allocator_->Alloc(kSize/2);
+  EXPECT_TRUE(pointers[0]);
+  EXPECT_TRUE(allocator_->CheckConsistency());
+
+  // This allocation should fail as well.
+  pointer_failed = allocator_->Alloc(kSize);
+  EXPECT_FALSE(pointer_failed);
+  EXPECT_TRUE(allocator_->CheckConsistency());
+
+  // Free up everything.
+  for (unsigned int i = 0; i < kAllocCount; ++i) {
+    allocator_->Free(pointers[i]);
+    EXPECT_TRUE(allocator_->CheckConsistency());
+  }
+}
+
+// Checks the free-pending-token mechanism.
+TEST_F(FencedAllocatorWrapperTest, TestFreePendingToken) {
+  allocator_->CheckConsistency();
+
+  const unsigned int kSize = 16;
+  const unsigned int kAllocCount = kBufferSize / kSize;
+  CHECK(kAllocCount * kSize == kBufferSize);
+
+  // Allocate several buffers to fill in the memory.
+  void *pointers[kAllocCount];
+  for (unsigned int i = 0; i < kAllocCount; ++i) {
+    pointers[i] = allocator_->Alloc(kSize);
+    EXPECT_TRUE(pointers[i]);
+    EXPECT_TRUE(allocator_->CheckConsistency());
+  }
+
+  // This allocation should fail.
+  void *pointer_failed = allocator_->Alloc(kSize);
+  EXPECT_FALSE(pointer_failed);
+  EXPECT_TRUE(allocator_->CheckConsistency());
+
+  // Free one successful allocation, pending fence.
+  int32 token = helper_.get()->InsertToken();
+  allocator_->FreePendingToken(pointers[0], token);
+  EXPECT_TRUE(allocator_->CheckConsistency());
+
+  // The way we hooked up the helper and engine, it won't process commands
+  // until it has to wait for something. Which means the token shouldn't have
+  // passed yet at this point.
+  EXPECT_GT(token, command_buffer_->GetToken());
+
+  // This allocation will need to reclaim the space freed above, so that should
+  // process the commands until the token is passed.
+  pointers[0] = allocator_->Alloc(kSize);
+  EXPECT_TRUE(pointers[0]);
+  EXPECT_TRUE(allocator_->CheckConsistency());
+  // Check that the token has indeed passed.
+  EXPECT_LE(token, command_buffer_->GetToken());
+
+  // Free up everything.
+  for (unsigned int i = 0; i < kAllocCount; ++i) {
+    allocator_->Free(pointers[i]);
+    EXPECT_TRUE(allocator_->CheckConsistency());
+  }
+}
+
+}  // namespace command_buffer
diff --git a/gpu/command_buffer/client/gles2_c_lib.cc b/gpu/command_buffer/client/gles2_c_lib.cc
new file mode 100644
index 0000000..d311a5d
--- /dev/null
+++ b/gpu/command_buffer/client/gles2_c_lib.cc
@@ -0,0 +1,16 @@
+// Copyright (c) 2006-2009 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.
+
+// These functions emluate GLES2 over command buffers for C.
+
+#include "gpu/command_buffer/client/gles2_lib.h"
+
+extern "C" {
+// Include the auto-generated part of this file. We split this because it means
+// we can easily edit the non-auto generated parts right here in this file
+// instead of having to edit some template or the code generator.
+#include "gpu/command_buffer/client/gles2_c_lib_autogen.h"
+}  // extern "C"
+
+
diff --git a/gpu/command_buffer/client/gles2_c_lib_autogen.h b/gpu/command_buffer/client/gles2_c_lib_autogen.h
new file mode 100644
index 0000000..c03a350
--- /dev/null
+++ b/gpu/command_buffer/client/gles2_c_lib_autogen.h
@@ -0,0 +1,504 @@
+// This file is auto-generated. DO NOT EDIT!
+
+
+// These functions emluate GLES2 over command buffers.
+
+
+void GLES2ActiveTexture(GLenum texture) {
+  gles2::GetGLContext()->ActiveTexture(texture);
+}
+void GLES2AttachShader(GLuint program, GLuint shader) {
+  gles2::GetGLContext()->AttachShader(program, shader);
+}
+void GLES2BindAttribLocation(GLuint program, GLuint index, const char* name) {
+  gles2::GetGLContext()->BindAttribLocation(program, index, name);
+}
+void GLES2BindBuffer(GLenum target, GLuint buffer) {
+  gles2::GetGLContext()->BindBuffer(target, buffer);
+}
+void GLES2BindFramebuffer(GLenum target, GLuint framebuffer) {
+  gles2::GetGLContext()->BindFramebuffer(target, framebuffer);
+}
+void GLES2BindRenderbuffer(GLenum target, GLuint renderbuffer) {
+  gles2::GetGLContext()->BindRenderbuffer(target, renderbuffer);
+}
+void GLES2BindTexture(GLenum target, GLuint texture) {
+  gles2::GetGLContext()->BindTexture(target, texture);
+}
+void GLES2BlendColor(
+    GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
+  gles2::GetGLContext()->BlendColor(red, green, blue, alpha);
+}
+void GLES2BlendEquation(GLenum mode) {
+  gles2::GetGLContext()->BlendEquation(mode);
+}
+void GLES2BlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) {
+  gles2::GetGLContext()->BlendEquationSeparate(modeRGB, modeAlpha);
+}
+void GLES2BlendFunc(GLenum sfactor, GLenum dfactor) {
+  gles2::GetGLContext()->BlendFunc(sfactor, dfactor);
+}
+void GLES2BlendFuncSeparate(
+    GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) {
+  gles2::GetGLContext()->BlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
+}
+void GLES2BufferData(
+    GLenum target, GLsizeiptr size, const void* data, GLenum usage) {
+  gles2::GetGLContext()->BufferData(target, size, data, usage);
+}
+void GLES2BufferSubData(
+    GLenum target, GLintptr offset, GLsizeiptr size, const void* data) {
+  gles2::GetGLContext()->BufferSubData(target, offset, size, data);
+}
+GLenum GLES2CheckFramebufferStatus(GLenum target) {
+  return gles2::GetGLContext()->CheckFramebufferStatus(target);
+}
+void GLES2Clear(GLbitfield mask) {
+  gles2::GetGLContext()->Clear(mask);
+}
+void GLES2ClearColor(
+    GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
+  gles2::GetGLContext()->ClearColor(red, green, blue, alpha);
+}
+void GLES2ClearDepthf(GLclampf depth) {
+  gles2::GetGLContext()->ClearDepthf(depth);
+}
+void GLES2ClearStencil(GLint s) {
+  gles2::GetGLContext()->ClearStencil(s);
+}
+void GLES2ColorMask(
+    GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
+  gles2::GetGLContext()->ColorMask(red, green, blue, alpha);
+}
+void GLES2CompileShader(GLuint shader) {
+  gles2::GetGLContext()->CompileShader(shader);
+}
+void GLES2CompressedTexImage2D(
+    GLenum target, GLint level, GLenum internalformat, GLsizei width,
+    GLsizei height, GLint border, GLsizei imageSize, const void* data) {
+  gles2::GetGLContext(
+      )->CompressedTexImage2D(
+          target, level, internalformat, width, height, border, imageSize,
+          data);
+}
+void GLES2CompressedTexSubImage2D(
+    GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width,
+    GLsizei height, GLenum format, GLsizei imageSize, const void* data) {
+  gles2::GetGLContext(
+      )->CompressedTexSubImage2D(
+          target, level, xoffset, yoffset, width, height, format, imageSize,
+          data);
+}
+void GLES2CopyTexImage2D(
+    GLenum target, GLint level, GLenum internalformat, GLint x, GLint y,
+    GLsizei width, GLsizei height, GLint border) {
+  gles2::GetGLContext(
+      )->CopyTexImage2D(
+          target, level, internalformat, x, y, width, height, border);
+}
+void GLES2CopyTexSubImage2D(
+    GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y,
+    GLsizei width, GLsizei height) {
+  gles2::GetGLContext(
+      )->CopyTexSubImage2D(
+          target, level, xoffset, yoffset, x, y, width, height);
+}
+GLuint GLES2CreateProgram() {
+  return gles2::GetGLContext()->CreateProgram();
+}
+GLuint GLES2CreateShader(GLenum type) {
+  return gles2::GetGLContext()->CreateShader(type);
+}
+void GLES2CullFace(GLenum mode) {
+  gles2::GetGLContext()->CullFace(mode);
+}
+void GLES2DeleteBuffers(GLsizei n, const GLuint* buffers) {
+  gles2::GetGLContext()->DeleteBuffers(n, buffers);
+}
+void GLES2DeleteFramebuffers(GLsizei n, const GLuint* framebuffers) {
+  gles2::GetGLContext()->DeleteFramebuffers(n, framebuffers);
+}
+void GLES2DeleteProgram(GLuint program) {
+  gles2::GetGLContext()->DeleteProgram(program);
+}
+void GLES2DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers) {
+  gles2::GetGLContext()->DeleteRenderbuffers(n, renderbuffers);
+}
+void GLES2DeleteShader(GLuint shader) {
+  gles2::GetGLContext()->DeleteShader(shader);
+}
+void GLES2DeleteTextures(GLsizei n, const GLuint* textures) {
+  gles2::GetGLContext()->DeleteTextures(n, textures);
+}
+void GLES2DepthFunc(GLenum func) {
+  gles2::GetGLContext()->DepthFunc(func);
+}
+void GLES2DepthMask(GLboolean flag) {
+  gles2::GetGLContext()->DepthMask(flag);
+}
+void GLES2DepthRangef(GLclampf zNear, GLclampf zFar) {
+  gles2::GetGLContext()->DepthRangef(zNear, zFar);
+}
+void GLES2DetachShader(GLuint program, GLuint shader) {
+  gles2::GetGLContext()->DetachShader(program, shader);
+}
+void GLES2Disable(GLenum cap) {
+  gles2::GetGLContext()->Disable(cap);
+}
+void GLES2DisableVertexAttribArray(GLuint index) {
+  gles2::GetGLContext()->DisableVertexAttribArray(index);
+}
+void GLES2DrawArrays(GLenum mode, GLint first, GLsizei count) {
+  gles2::GetGLContext()->DrawArrays(mode, first, count);
+}
+void GLES2DrawElements(
+    GLenum mode, GLsizei count, GLenum type, const void* indices) {
+  gles2::GetGLContext()->DrawElements(mode, count, type, indices);
+}
+void GLES2Enable(GLenum cap) {
+  gles2::GetGLContext()->Enable(cap);
+}
+void GLES2EnableVertexAttribArray(GLuint index) {
+  gles2::GetGLContext()->EnableVertexAttribArray(index);
+}
+void GLES2Finish() {
+  gles2::GetGLContext()->Finish();
+}
+void GLES2Flush() {
+  gles2::GetGLContext()->Flush();
+}
+void GLES2FramebufferRenderbuffer(
+    GLenum target, GLenum attachment, GLenum renderbuffertarget,
+    GLuint renderbuffer) {
+  gles2::GetGLContext(
+      )->FramebufferRenderbuffer(
+          target, attachment, renderbuffertarget, renderbuffer);
+}
+void GLES2FramebufferTexture2D(
+    GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
+    GLint level) {
+  gles2::GetGLContext(
+      )->FramebufferTexture2D(target, attachment, textarget, texture, level);
+}
+void GLES2FrontFace(GLenum mode) {
+  gles2::GetGLContext()->FrontFace(mode);
+}
+void GLES2GenBuffers(GLsizei n, GLuint* buffers) {
+  gles2::GetGLContext()->GenBuffers(n, buffers);
+}
+void GLES2GenerateMipmap(GLenum target) {
+  gles2::GetGLContext()->GenerateMipmap(target);
+}
+void GLES2GenFramebuffers(GLsizei n, GLuint* framebuffers) {
+  gles2::GetGLContext()->GenFramebuffers(n, framebuffers);
+}
+void GLES2GenRenderbuffers(GLsizei n, GLuint* renderbuffers) {
+  gles2::GetGLContext()->GenRenderbuffers(n, renderbuffers);
+}
+void GLES2GenTextures(GLsizei n, GLuint* textures) {
+  gles2::GetGLContext()->GenTextures(n, textures);
+}
+void GLES2GetActiveAttrib(
+    GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size,
+    GLenum* type, char* name) {
+  gles2::GetGLContext(
+      )->GetActiveAttrib(program, index, bufsize, length, size, type, name);
+}
+void GLES2GetActiveUniform(
+    GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size,
+    GLenum* type, char* name) {
+  gles2::GetGLContext(
+      )->GetActiveUniform(program, index, bufsize, length, size, type, name);
+}
+void GLES2GetAttachedShaders(
+    GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders) {
+  gles2::GetGLContext()->GetAttachedShaders(program, maxcount, count, shaders);
+}
+int GLES2GetAttribLocation(GLuint program, const char* name) {
+  return gles2::GetGLContext()->GetAttribLocation(program, name);
+}
+void GLES2GetBooleanv(GLenum pname, GLboolean* params) {
+  gles2::GetGLContext()->GetBooleanv(pname, params);
+}
+void GLES2GetBufferParameteriv(GLenum target, GLenum pname, GLint* params) {
+  gles2::GetGLContext()->GetBufferParameteriv(target, pname, params);
+}
+GLenum GLES2GetError() {
+  return gles2::GetGLContext()->GetError();
+}
+void GLES2GetFloatv(GLenum pname, GLfloat* params) {
+  gles2::GetGLContext()->GetFloatv(pname, params);
+}
+void GLES2GetFramebufferAttachmentParameteriv(
+    GLenum target, GLenum attachment, GLenum pname, GLint* params) {
+  gles2::GetGLContext(
+      )->GetFramebufferAttachmentParameteriv(
+          target, attachment, pname, params);
+}
+void GLES2GetIntegerv(GLenum pname, GLint* params) {
+  gles2::GetGLContext()->GetIntegerv(pname, params);
+}
+void GLES2GetProgramiv(GLuint program, GLenum pname, GLint* params) {
+  gles2::GetGLContext()->GetProgramiv(program, pname, params);
+}
+void GLES2GetProgramInfoLog(
+    GLuint program, GLsizei bufsize, GLsizei* length, char* infolog) {
+  gles2::GetGLContext()->GetProgramInfoLog(program, bufsize, length, infolog);
+}
+void GLES2GetRenderbufferParameteriv(
+    GLenum target, GLenum pname, GLint* params) {
+  gles2::GetGLContext()->GetRenderbufferParameteriv(target, pname, params);
+}
+void GLES2GetShaderiv(GLuint shader, GLenum pname, GLint* params) {
+  gles2::GetGLContext()->GetShaderiv(shader, pname, params);
+}
+void GLES2GetShaderInfoLog(
+    GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog) {
+  gles2::GetGLContext()->GetShaderInfoLog(shader, bufsize, length, infolog);
+}
+void GLES2GetShaderPrecisionFormat(
+    GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) {
+  gles2::GetGLContext(
+      )->GetShaderPrecisionFormat(shadertype, precisiontype, range, precision);
+}
+void GLES2GetShaderSource(
+    GLuint shader, GLsizei bufsize, GLsizei* length, char* source) {
+  gles2::GetGLContext()->GetShaderSource(shader, bufsize, length, source);
+}
+const GLubyte* GLES2GetString(GLenum name) {
+  return gles2::GetGLContext()->GetString(name);
+}
+void GLES2GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params) {
+  gles2::GetGLContext()->GetTexParameterfv(target, pname, params);
+}
+void GLES2GetTexParameteriv(GLenum target, GLenum pname, GLint* params) {
+  gles2::GetGLContext()->GetTexParameteriv(target, pname, params);
+}
+void GLES2GetUniformfv(GLuint program, GLint location, GLfloat* params) {
+  gles2::GetGLContext()->GetUniformfv(program, location, params);
+}
+void GLES2GetUniformiv(GLuint program, GLint location, GLint* params) {
+  gles2::GetGLContext()->GetUniformiv(program, location, params);
+}
+int GLES2GetUniformLocation(GLuint program, const char* name) {
+  return gles2::GetGLContext()->GetUniformLocation(program, name);
+}
+void GLES2GetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params) {
+  gles2::GetGLContext()->GetVertexAttribfv(index, pname, params);
+}
+void GLES2GetVertexAttribiv(GLuint index, GLenum pname, GLint* params) {
+  gles2::GetGLContext()->GetVertexAttribiv(index, pname, params);
+}
+void GLES2GetVertexAttribPointerv(GLuint index, GLenum pname, void** pointer) {
+  gles2::GetGLContext()->GetVertexAttribPointerv(index, pname, pointer);
+}
+void GLES2Hint(GLenum target, GLenum mode) {
+  gles2::GetGLContext()->Hint(target, mode);
+}
+GLboolean GLES2IsBuffer(GLuint buffer) {
+  return gles2::GetGLContext()->IsBuffer(buffer);
+}
+GLboolean GLES2IsEnabled(GLenum cap) {
+  return gles2::GetGLContext()->IsEnabled(cap);
+}
+GLboolean GLES2IsFramebuffer(GLuint framebuffer) {
+  return gles2::GetGLContext()->IsFramebuffer(framebuffer);
+}
+GLboolean GLES2IsProgram(GLuint program) {
+  return gles2::GetGLContext()->IsProgram(program);
+}
+GLboolean GLES2IsRenderbuffer(GLuint renderbuffer) {
+  return gles2::GetGLContext()->IsRenderbuffer(renderbuffer);
+}
+GLboolean GLES2IsShader(GLuint shader) {
+  return gles2::GetGLContext()->IsShader(shader);
+}
+GLboolean GLES2IsTexture(GLuint texture) {
+  return gles2::GetGLContext()->IsTexture(texture);
+}
+void GLES2LineWidth(GLfloat width) {
+  gles2::GetGLContext()->LineWidth(width);
+}
+void GLES2LinkProgram(GLuint program) {
+  gles2::GetGLContext()->LinkProgram(program);
+}
+void GLES2PixelStorei(GLenum pname, GLint param) {
+  gles2::GetGLContext()->PixelStorei(pname, param);
+}
+void GLES2PolygonOffset(GLfloat factor, GLfloat units) {
+  gles2::GetGLContext()->PolygonOffset(factor, units);
+}
+void GLES2ReadPixels(
+    GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type,
+    void* pixels) {
+  gles2::GetGLContext()->ReadPixels(x, y, width, height, format, type, pixels);
+}
+void GLES2RenderbufferStorage(
+    GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
+  gles2::GetGLContext(
+      )->RenderbufferStorage(target, internalformat, width, height);
+}
+void GLES2SampleCoverage(GLclampf value, GLboolean invert) {
+  gles2::GetGLContext()->SampleCoverage(value, invert);
+}
+void GLES2Scissor(GLint x, GLint y, GLsizei width, GLsizei height) {
+  gles2::GetGLContext()->Scissor(x, y, width, height);
+}
+void GLES2ShaderSource(
+    GLuint shader, GLsizei count, const char** string, const GLint* length) {
+  gles2::GetGLContext()->ShaderSource(shader, count, string, length);
+}
+void GLES2StencilFunc(GLenum func, GLint ref, GLuint mask) {
+  gles2::GetGLContext()->StencilFunc(func, ref, mask);
+}
+void GLES2StencilFuncSeparate(
+    GLenum face, GLenum func, GLint ref, GLuint mask) {
+  gles2::GetGLContext()->StencilFuncSeparate(face, func, ref, mask);
+}
+void GLES2StencilMask(GLuint mask) {
+  gles2::GetGLContext()->StencilMask(mask);
+}
+void GLES2StencilMaskSeparate(GLenum face, GLuint mask) {
+  gles2::GetGLContext()->StencilMaskSeparate(face, mask);
+}
+void GLES2StencilOp(GLenum fail, GLenum zfail, GLenum zpass) {
+  gles2::GetGLContext()->StencilOp(fail, zfail, zpass);
+}
+void GLES2StencilOpSeparate(
+    GLenum face, GLenum fail, GLenum zfail, GLenum zpass) {
+  gles2::GetGLContext()->StencilOpSeparate(face, fail, zfail, zpass);
+}
+void GLES2TexImage2D(
+    GLenum target, GLint level, GLint internalformat, GLsizei width,
+    GLsizei height, GLint border, GLenum format, GLenum type,
+    const void* pixels) {
+  gles2::GetGLContext(
+      )->TexImage2D(
+          target, level, internalformat, width, height, border, format, type,
+          pixels);
+}
+void GLES2TexParameterf(GLenum target, GLenum pname, GLfloat param) {
+  gles2::GetGLContext()->TexParameterf(target, pname, param);
+}
+void GLES2TexParameterfv(GLenum target, GLenum pname, const GLfloat* params) {
+  gles2::GetGLContext()->TexParameterfv(target, pname, params);
+}
+void GLES2TexParameteri(GLenum target, GLenum pname, GLint param) {
+  gles2::GetGLContext()->TexParameteri(target, pname, param);
+}
+void GLES2TexParameteriv(GLenum target, GLenum pname, const GLint* params) {
+  gles2::GetGLContext()->TexParameteriv(target, pname, params);
+}
+void GLES2TexSubImage2D(
+    GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width,
+    GLsizei height, GLenum format, GLenum type, const void* pixels) {
+  gles2::GetGLContext(
+      )->TexSubImage2D(
+          target, level, xoffset, yoffset, width, height, format, type,
+          pixels);
+}
+void GLES2Uniform1f(GLint location, GLfloat x) {
+  gles2::GetGLContext()->Uniform1f(location, x);
+}
+void GLES2Uniform1fv(GLint location, GLsizei count, const GLfloat* v) {
+  gles2::GetGLContext()->Uniform1fv(location, count, v);
+}
+void GLES2Uniform1i(GLint location, GLint x) {
+  gles2::GetGLContext()->Uniform1i(location, x);
+}
+void GLES2Uniform1iv(GLint location, GLsizei count, const GLint* v) {
+  gles2::GetGLContext()->Uniform1iv(location, count, v);
+}
+void GLES2Uniform2f(GLint location, GLfloat x, GLfloat y) {
+  gles2::GetGLContext()->Uniform2f(location, x, y);
+}
+void GLES2Uniform2fv(GLint location, GLsizei count, const GLfloat* v) {
+  gles2::GetGLContext()->Uniform2fv(location, count, v);
+}
+void GLES2Uniform2i(GLint location, GLint x, GLint y) {
+  gles2::GetGLContext()->Uniform2i(location, x, y);
+}
+void GLES2Uniform2iv(GLint location, GLsizei count, const GLint* v) {
+  gles2::GetGLContext()->Uniform2iv(location, count, v);
+}
+void GLES2Uniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z) {
+  gles2::GetGLContext()->Uniform3f(location, x, y, z);
+}
+void GLES2Uniform3fv(GLint location, GLsizei count, const GLfloat* v) {
+  gles2::GetGLContext()->Uniform3fv(location, count, v);
+}
+void GLES2Uniform3i(GLint location, GLint x, GLint y, GLint z) {
+  gles2::GetGLContext()->Uniform3i(location, x, y, z);
+}
+void GLES2Uniform3iv(GLint location, GLsizei count, const GLint* v) {
+  gles2::GetGLContext()->Uniform3iv(location, count, v);
+}
+void GLES2Uniform4f(
+    GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) {
+  gles2::GetGLContext()->Uniform4f(location, x, y, z, w);
+}
+void GLES2Uniform4fv(GLint location, GLsizei count, const GLfloat* v) {
+  gles2::GetGLContext()->Uniform4fv(location, count, v);
+}
+void GLES2Uniform4i(GLint location, GLint x, GLint y, GLint z, GLint w) {
+  gles2::GetGLContext()->Uniform4i(location, x, y, z, w);
+}
+void GLES2Uniform4iv(GLint location, GLsizei count, const GLint* v) {
+  gles2::GetGLContext()->Uniform4iv(location, count, v);
+}
+void GLES2UniformMatrix2fv(
+    GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
+  gles2::GetGLContext()->UniformMatrix2fv(location, count, transpose, value);
+}
+void GLES2UniformMatrix3fv(
+    GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
+  gles2::GetGLContext()->UniformMatrix3fv(location, count, transpose, value);
+}
+void GLES2UniformMatrix4fv(
+    GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
+  gles2::GetGLContext()->UniformMatrix4fv(location, count, transpose, value);
+}
+void GLES2UseProgram(GLuint program) {
+  gles2::GetGLContext()->UseProgram(program);
+}
+void GLES2ValidateProgram(GLuint program) {
+  gles2::GetGLContext()->ValidateProgram(program);
+}
+void GLES2VertexAttrib1f(GLuint indx, GLfloat x) {
+  gles2::GetGLContext()->VertexAttrib1f(indx, x);
+}
+void GLES2VertexAttrib1fv(GLuint indx, const GLfloat* values) {
+  gles2::GetGLContext()->VertexAttrib1fv(indx, values);
+}
+void GLES2VertexAttrib2f(GLuint indx, GLfloat x, GLfloat y) {
+  gles2::GetGLContext()->VertexAttrib2f(indx, x, y);
+}
+void GLES2VertexAttrib2fv(GLuint indx, const GLfloat* values) {
+  gles2::GetGLContext()->VertexAttrib2fv(indx, values);
+}
+void GLES2VertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z) {
+  gles2::GetGLContext()->VertexAttrib3f(indx, x, y, z);
+}
+void GLES2VertexAttrib3fv(GLuint indx, const GLfloat* values) {
+  gles2::GetGLContext()->VertexAttrib3fv(indx, values);
+}
+void GLES2VertexAttrib4f(
+    GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w) {
+  gles2::GetGLContext()->VertexAttrib4f(indx, x, y, z, w);
+}
+void GLES2VertexAttrib4fv(GLuint indx, const GLfloat* values) {
+  gles2::GetGLContext()->VertexAttrib4fv(indx, values);
+}
+void GLES2VertexAttribPointer(
+    GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride,
+    const void* ptr) {
+  gles2::GetGLContext(
+      )->VertexAttribPointer(indx, size, type, normalized, stride, ptr);
+}
+void GLES2Viewport(GLint x, GLint y, GLsizei width, GLsizei height) {
+  gles2::GetGLContext()->Viewport(x, y, width, height);
+}
+void GLES2SwapBuffers() {
+  gles2::GetGLContext()->SwapBuffers();
+}
+
diff --git a/gpu/command_buffer/client/gles2_cmd_helper.cc b/gpu/command_buffer/client/gles2_cmd_helper.cc
new file mode 100644
index 0000000..1dff9144
--- /dev/null
+++ b/gpu/command_buffer/client/gles2_cmd_helper.cc
@@ -0,0 +1,14 @@
+// Copyright (c) 2006-2009 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 "gpu/command_buffer/client/gles2_cmd_helper.h"
+
+namespace command_buffer {
+
+// Currently this is a place holder.
+
+}  // namespace command_buffer
+
+
+
diff --git a/gpu/command_buffer/client/gles2_cmd_helper.h b/gpu/command_buffer/client/gles2_cmd_helper.h
new file mode 100644
index 0000000..9a1a741
--- /dev/null
+++ b/gpu/command_buffer/client/gles2_cmd_helper.h
@@ -0,0 +1,36 @@
+// Copyright (c) 2006-2009 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 GPU_COMMAND_BUFFER_CLIENT_GLES2_CMD_HELPER_H
+#define GPU_COMMAND_BUFFER_CLIENT_GLES2_CMD_HELPER_H
+
+#include "gpu/command_buffer/client/cmd_buffer_helper.h"
+#include "gpu/command_buffer/common/gles2_cmd_format.h"
+
+namespace command_buffer {
+namespace gles2 {
+
+// A class that helps write GL command buffers.
+class GLES2CmdHelper : public CommandBufferHelper {
+ public:
+  explicit GLES2CmdHelper(command_buffer::CommandBuffer* command_buffer)
+      : CommandBufferHelper(command_buffer) {
+  }
+  virtual ~GLES2CmdHelper() {
+  }
+
+  // Include the auto-generated part of this class. We split this because it
+  // means we can easily edit the non-auto generated parts right here in this
+  // file instead of having to edit some template or the code generator.
+  #include "gpu/command_buffer/client/gles2_cmd_helper_autogen.h"
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(GLES2CmdHelper);
+};
+
+}  // namespace gles2
+}  // namespace command_buffer
+
+#endif  // GPU_COMMAND_BUFFER_CLIENT_GLES2_CMD_HELPER_H
+
diff --git a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
new file mode 100644
index 0000000..1cfee5b
--- /dev/null
+++ b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
@@ -0,0 +1,1143 @@
+  void ActiveTexture(GLenum texture) {
+    gles2::ActiveTexture& c = GetCmdSpace<gles2::ActiveTexture>();
+    c.Init(texture);
+  }
+
+  void AttachShader(GLuint program, GLuint shader) {
+    gles2::AttachShader& c = GetCmdSpace<gles2::AttachShader>();
+    c.Init(program, shader);
+  }
+
+  void BindAttribLocation(
+      GLuint program, GLuint index, uint32 name_shm_id, uint32 name_shm_offset,
+      uint32 data_size) {
+    gles2::BindAttribLocation& c = GetCmdSpace<gles2::BindAttribLocation>();
+    c.Init(program, index, name_shm_id, name_shm_offset, data_size);
+  }
+
+  void BindAttribLocationImmediate(
+      GLuint program, GLuint index, const char* name) {
+    const uint32 size = gles2::BindAttribLocationImmediate::ComputeSize(name);
+    gles2::BindAttribLocationImmediate& c =
+        GetImmediateCmdSpaceTotalSize<gles2::BindAttribLocationImmediate>(
+            size);
+    c.Init(program, index, name);
+  }
+
+  void BindBuffer(GLenum target, GLuint buffer) {
+    gles2::BindBuffer& c = GetCmdSpace<gles2::BindBuffer>();
+    c.Init(target, buffer);
+  }
+
+  void BindFramebuffer(GLenum target, GLuint framebuffer) {
+    gles2::BindFramebuffer& c = GetCmdSpace<gles2::BindFramebuffer>();
+    c.Init(target, framebuffer);
+  }
+
+  void BindRenderbuffer(GLenum target, GLuint renderbuffer) {
+    gles2::BindRenderbuffer& c = GetCmdSpace<gles2::BindRenderbuffer>();
+    c.Init(target, renderbuffer);
+  }
+
+  void BindTexture(GLenum target, GLuint texture) {
+    gles2::BindTexture& c = GetCmdSpace<gles2::BindTexture>();
+    c.Init(target, texture);
+  }
+
+  void BlendColor(
+      GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
+    gles2::BlendColor& c = GetCmdSpace<gles2::BlendColor>();
+    c.Init(red, green, blue, alpha);
+  }
+
+  void BlendEquation(GLenum mode) {
+    gles2::BlendEquation& c = GetCmdSpace<gles2::BlendEquation>();
+    c.Init(mode);
+  }
+
+  void BlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) {
+    gles2::BlendEquationSeparate& c =
+        GetCmdSpace<gles2::BlendEquationSeparate>();
+    c.Init(modeRGB, modeAlpha);
+  }
+
+  void BlendFunc(GLenum sfactor, GLenum dfactor) {
+    gles2::BlendFunc& c = GetCmdSpace<gles2::BlendFunc>();
+    c.Init(sfactor, dfactor);
+  }
+
+  void BlendFuncSeparate(
+      GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) {
+    gles2::BlendFuncSeparate& c = GetCmdSpace<gles2::BlendFuncSeparate>();
+    c.Init(srcRGB, dstRGB, srcAlpha, dstAlpha);
+  }
+
+  void BufferData(
+      GLenum target, GLsizeiptr size, uint32 data_shm_id,
+      uint32 data_shm_offset, GLenum usage) {
+    gles2::BufferData& c = GetCmdSpace<gles2::BufferData>();
+    c.Init(target, size, data_shm_id, data_shm_offset, usage);
+  }
+
+  void BufferDataImmediate(GLenum target, GLsizeiptr size, GLenum usage) {
+    const uint32 s = 0;  // TODO(gman): compute correct size
+    gles2::BufferDataImmediate& c =
+        GetImmediateCmdSpaceTotalSize<gles2::BufferDataImmediate>(s);
+    c.Init(target, size, usage);
+  }
+
+  void BufferSubData(
+      GLenum target, GLintptr offset, GLsizeiptr size, uint32 data_shm_id,
+      uint32 data_shm_offset) {
+    gles2::BufferSubData& c = GetCmdSpace<gles2::BufferSubData>();
+    c.Init(target, offset, size, data_shm_id, data_shm_offset);
+  }
+
+  void BufferSubDataImmediate(
+      GLenum target, GLintptr offset, GLsizeiptr size) {
+    const uint32 s = 0;  // TODO(gman): compute correct size
+    gles2::BufferSubDataImmediate& c =
+        GetImmediateCmdSpaceTotalSize<gles2::BufferSubDataImmediate>(s);
+    c.Init(target, offset, size);
+  }
+
+  void CheckFramebufferStatus(GLenum target) {
+    gles2::CheckFramebufferStatus& c =
+        GetCmdSpace<gles2::CheckFramebufferStatus>();
+    c.Init(target);
+  }
+
+  void Clear(GLbitfield mask) {
+    gles2::Clear& c = GetCmdSpace<gles2::Clear>();
+    c.Init(mask);
+  }
+
+  void ClearColor(
+      GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
+    gles2::ClearColor& c = GetCmdSpace<gles2::ClearColor>();
+    c.Init(red, green, blue, alpha);
+  }
+
+  void ClearDepthf(GLclampf depth) {
+    gles2::ClearDepthf& c = GetCmdSpace<gles2::ClearDepthf>();
+    c.Init(depth);
+  }
+
+  void ClearStencil(GLint s) {
+    gles2::ClearStencil& c = GetCmdSpace<gles2::ClearStencil>();
+    c.Init(s);
+  }
+
+  void ColorMask(
+      GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
+    gles2::ColorMask& c = GetCmdSpace<gles2::ColorMask>();
+    c.Init(red, green, blue, alpha);
+  }
+
+  void CompileShader(GLuint shader) {
+    gles2::CompileShader& c = GetCmdSpace<gles2::CompileShader>();
+    c.Init(shader);
+  }
+
+  void CompressedTexImage2D(
+      GLenum target, GLint level, GLenum internalformat, GLsizei width,
+      GLsizei height, GLint border, GLsizei imageSize, uint32 data_shm_id,
+      uint32 data_shm_offset) {
+    gles2::CompressedTexImage2D& c =
+        GetCmdSpace<gles2::CompressedTexImage2D>();
+    c.Init(
+        target, level, internalformat, width, height, border, imageSize,
+        data_shm_id, data_shm_offset);
+  }
+
+  void CompressedTexImage2DImmediate(
+      GLenum target, GLint level, GLenum internalformat, GLsizei width,
+      GLsizei height, GLint border, GLsizei imageSize) {
+    const uint32 s = 0;  // TODO(gman): compute correct size
+    gles2::CompressedTexImage2DImmediate& c =
+        GetImmediateCmdSpaceTotalSize<gles2::CompressedTexImage2DImmediate>(s);
+    c.Init(target, level, internalformat, width, height, border, imageSize);
+  }
+
+  void CompressedTexSubImage2D(
+      GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width,
+      GLsizei height, GLenum format, GLsizei imageSize, uint32 data_shm_id,
+      uint32 data_shm_offset) {
+    gles2::CompressedTexSubImage2D& c =
+        GetCmdSpace<gles2::CompressedTexSubImage2D>();
+    c.Init(
+        target, level, xoffset, yoffset, width, height, format, imageSize,
+        data_shm_id, data_shm_offset);
+  }
+
+  void CompressedTexSubImage2DImmediate(
+      GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width,
+      GLsizei height, GLenum format, GLsizei imageSize) {
+    const uint32 s = 0;  // TODO(gman): compute correct size
+    gles2::CompressedTexSubImage2DImmediate& c =
+        GetImmediateCmdSpaceTotalSize<gles2::CompressedTexSubImage2DImmediate>(
+            s);
+    c.Init(target, level, xoffset, yoffset, width, height, format, imageSize);
+  }
+
+  void CopyTexImage2D(
+      GLenum target, GLint level, GLenum internalformat, GLint x, GLint y,
+      GLsizei width, GLsizei height, GLint border) {
+    gles2::CopyTexImage2D& c = GetCmdSpace<gles2::CopyTexImage2D>();
+    c.Init(target, level, internalformat, x, y, width, height, border);
+  }
+
+  void CopyTexSubImage2D(
+      GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x,
+      GLint y, GLsizei width, GLsizei height) {
+    gles2::CopyTexSubImage2D& c = GetCmdSpace<gles2::CopyTexSubImage2D>();
+    c.Init(target, level, xoffset, yoffset, x, y, width, height);
+  }
+
+  void CreateProgram(uint32 client_id) {
+    gles2::CreateProgram& c = GetCmdSpace<gles2::CreateProgram>();
+    c.Init(client_id);
+  }
+
+  void CreateShader(GLenum type, uint32 client_id) {
+    gles2::CreateShader& c = GetCmdSpace<gles2::CreateShader>();
+    c.Init(type, client_id);
+  }
+
+  void CullFace(GLenum mode) {
+    gles2::CullFace& c = GetCmdSpace<gles2::CullFace>();
+    c.Init(mode);
+  }
+
+  void DeleteBuffers(
+      GLsizei n, uint32 buffers_shm_id, uint32 buffers_shm_offset) {
+    gles2::DeleteBuffers& c = GetCmdSpace<gles2::DeleteBuffers>();
+    c.Init(n, buffers_shm_id, buffers_shm_offset);
+  }
+
+  void DeleteBuffersImmediate(GLsizei n, const GLuint* buffers) {
+    const uint32 size = gles2::DeleteBuffersImmediate::ComputeSize(n);
+    gles2::DeleteBuffersImmediate& c =
+        GetImmediateCmdSpaceTotalSize<gles2::DeleteBuffersImmediate>(size);
+    c.Init(n, buffers);
+  }
+
+  void DeleteFramebuffers(
+      GLsizei n, uint32 framebuffers_shm_id, uint32 framebuffers_shm_offset) {
+    gles2::DeleteFramebuffers& c = GetCmdSpace<gles2::DeleteFramebuffers>();
+    c.Init(n, framebuffers_shm_id, framebuffers_shm_offset);
+  }
+
+  void DeleteFramebuffersImmediate(GLsizei n, const GLuint* framebuffers) {
+    const uint32 size = gles2::DeleteFramebuffersImmediate::ComputeSize(n);
+    gles2::DeleteFramebuffersImmediate& c =
+        GetImmediateCmdSpaceTotalSize<gles2::DeleteFramebuffersImmediate>(
+            size);
+    c.Init(n, framebuffers);
+  }
+
+  void DeleteProgram(GLuint program) {
+    gles2::DeleteProgram& c = GetCmdSpace<gles2::DeleteProgram>();
+    c.Init(program);
+  }
+
+  void DeleteRenderbuffers(
+      GLsizei n, uint32 renderbuffers_shm_id,
+      uint32 renderbuffers_shm_offset) {
+    gles2::DeleteRenderbuffers& c = GetCmdSpace<gles2::DeleteRenderbuffers>();
+    c.Init(n, renderbuffers_shm_id, renderbuffers_shm_offset);
+  }
+
+  void DeleteRenderbuffersImmediate(GLsizei n, const GLuint* renderbuffers) {
+    const uint32 size = gles2::DeleteRenderbuffersImmediate::ComputeSize(n);
+    gles2::DeleteRenderbuffersImmediate& c =
+        GetImmediateCmdSpaceTotalSize<gles2::DeleteRenderbuffersImmediate>(
+            size);
+    c.Init(n, renderbuffers);
+  }
+
+  void DeleteShader(GLuint shader) {
+    gles2::DeleteShader& c = GetCmdSpace<gles2::DeleteShader>();
+    c.Init(shader);
+  }
+
+  void DeleteTextures(
+      GLsizei n, uint32 textures_shm_id, uint32 textures_shm_offset) {
+    gles2::DeleteTextures& c = GetCmdSpace<gles2::DeleteTextures>();
+    c.Init(n, textures_shm_id, textures_shm_offset);
+  }
+
+  void DeleteTexturesImmediate(GLsizei n, const GLuint* textures) {
+    const uint32 size = gles2::DeleteTexturesImmediate::ComputeSize(n);
+    gles2::DeleteTexturesImmediate& c =
+        GetImmediateCmdSpaceTotalSize<gles2::DeleteTexturesImmediate>(size);
+    c.Init(n, textures);
+  }
+
+  void DepthFunc(GLenum func) {
+    gles2::DepthFunc& c = GetCmdSpace<gles2::DepthFunc>();
+    c.Init(func);
+  }
+
+  void DepthMask(GLboolean flag) {
+    gles2::DepthMask& c = GetCmdSpace<gles2::DepthMask>();
+    c.Init(flag);
+  }
+
+  void DepthRangef(GLclampf zNear, GLclampf zFar) {
+    gles2::DepthRangef& c = GetCmdSpace<gles2::DepthRangef>();
+    c.Init(zNear, zFar);
+  }
+
+  void DetachShader(GLuint program, GLuint shader) {
+    gles2::DetachShader& c = GetCmdSpace<gles2::DetachShader>();
+    c.Init(program, shader);
+  }
+
+  void Disable(GLenum cap) {
+    gles2::Disable& c = GetCmdSpace<gles2::Disable>();
+    c.Init(cap);
+  }
+
+  void DisableVertexAttribArray(GLuint index) {
+    gles2::DisableVertexAttribArray& c =
+        GetCmdSpace<gles2::DisableVertexAttribArray>();
+    c.Init(index);
+  }
+
+  void DrawArrays(GLenum mode, GLint first, GLsizei count) {
+    gles2::DrawArrays& c = GetCmdSpace<gles2::DrawArrays>();
+    c.Init(mode, first, count);
+  }
+
+  void DrawElements(
+      GLenum mode, GLsizei count, GLenum type, GLuint index_offset) {
+    gles2::DrawElements& c = GetCmdSpace<gles2::DrawElements>();
+    c.Init(mode, count, type, index_offset);
+  }
+
+  void Enable(GLenum cap) {
+    gles2::Enable& c = GetCmdSpace<gles2::Enable>();
+    c.Init(cap);
+  }
+
+  void EnableVertexAttribArray(GLuint index) {
+    gles2::EnableVertexAttribArray& c =
+        GetCmdSpace<gles2::EnableVertexAttribArray>();
+    c.Init(index);
+  }
+
+  void Finish() {
+    gles2::Finish& c = GetCmdSpace<gles2::Finish>();
+    c.Init();
+  }
+
+  void Flush() {
+    gles2::Flush& c = GetCmdSpace<gles2::Flush>();
+    c.Init();
+  }
+
+  void FramebufferRenderbuffer(
+      GLenum target, GLenum attachment, GLenum renderbuffertarget,
+      GLuint renderbuffer) {
+    gles2::FramebufferRenderbuffer& c =
+        GetCmdSpace<gles2::FramebufferRenderbuffer>();
+    c.Init(target, attachment, renderbuffertarget, renderbuffer);
+  }
+
+  void FramebufferTexture2D(
+      GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
+      GLint level) {
+    gles2::FramebufferTexture2D& c =
+        GetCmdSpace<gles2::FramebufferTexture2D>();
+    c.Init(target, attachment, textarget, texture, level);
+  }
+
+  void FrontFace(GLenum mode) {
+    gles2::FrontFace& c = GetCmdSpace<gles2::FrontFace>();
+    c.Init(mode);
+  }
+
+  void GenBuffers(
+      GLsizei n, uint32 buffers_shm_id, uint32 buffers_shm_offset) {
+    gles2::GenBuffers& c = GetCmdSpace<gles2::GenBuffers>();
+    c.Init(n, buffers_shm_id, buffers_shm_offset);
+  }
+
+  void GenBuffersImmediate(GLsizei n, GLuint* buffers) {
+    const uint32 size = gles2::GenBuffersImmediate::ComputeSize(n);
+    gles2::GenBuffersImmediate& c =
+        GetImmediateCmdSpaceTotalSize<gles2::GenBuffersImmediate>(size);
+    c.Init(n, buffers);
+  }
+
+  void GenerateMipmap(GLenum target) {
+    gles2::GenerateMipmap& c = GetCmdSpace<gles2::GenerateMipmap>();
+    c.Init(target);
+  }
+
+  void GenFramebuffers(
+      GLsizei n, uint32 framebuffers_shm_id, uint32 framebuffers_shm_offset) {
+    gles2::GenFramebuffers& c = GetCmdSpace<gles2::GenFramebuffers>();
+    c.Init(n, framebuffers_shm_id, framebuffers_shm_offset);
+  }
+
+  void GenFramebuffersImmediate(GLsizei n, GLuint* framebuffers) {
+    const uint32 size = gles2::GenFramebuffersImmediate::ComputeSize(n);
+    gles2::GenFramebuffersImmediate& c =
+        GetImmediateCmdSpaceTotalSize<gles2::GenFramebuffersImmediate>(size);
+    c.Init(n, framebuffers);
+  }
+
+  void GenRenderbuffers(
+      GLsizei n, uint32 renderbuffers_shm_id,
+      uint32 renderbuffers_shm_offset) {
+    gles2::GenRenderbuffers& c = GetCmdSpace<gles2::GenRenderbuffers>();
+    c.Init(n, renderbuffers_shm_id, renderbuffers_shm_offset);
+  }
+
+  void GenRenderbuffersImmediate(GLsizei n, GLuint* renderbuffers) {
+    const uint32 size = gles2::GenRenderbuffersImmediate::ComputeSize(n);
+    gles2::GenRenderbuffersImmediate& c =
+        GetImmediateCmdSpaceTotalSize<gles2::GenRenderbuffersImmediate>(size);
+    c.Init(n, renderbuffers);
+  }
+
+  void GenTextures(
+      GLsizei n, uint32 textures_shm_id, uint32 textures_shm_offset) {
+    gles2::GenTextures& c = GetCmdSpace<gles2::GenTextures>();
+    c.Init(n, textures_shm_id, textures_shm_offset);
+  }
+
+  void GenTexturesImmediate(GLsizei n, GLuint* textures) {
+    const uint32 size = gles2::GenTexturesImmediate::ComputeSize(n);
+    gles2::GenTexturesImmediate& c =
+        GetImmediateCmdSpaceTotalSize<gles2::GenTexturesImmediate>(size);
+    c.Init(n, textures);
+  }
+
+  void GetActiveAttrib(
+      GLuint program, GLuint index, GLsizei bufsize, uint32 length_shm_id,
+      uint32 length_shm_offset, uint32 size_shm_id, uint32 size_shm_offset,
+      uint32 type_shm_id, uint32 type_shm_offset, uint32 name_shm_id,
+      uint32 name_shm_offset) {
+    gles2::GetActiveAttrib& c = GetCmdSpace<gles2::GetActiveAttrib>();
+    c.Init(
+        program, index, bufsize, length_shm_id, length_shm_offset, size_shm_id,
+        size_shm_offset, type_shm_id, type_shm_offset, name_shm_id,
+        name_shm_offset);
+  }
+
+  void GetActiveUniform(
+      GLuint program, GLuint index, GLsizei bufsize, uint32 length_shm_id,
+      uint32 length_shm_offset, uint32 size_shm_id, uint32 size_shm_offset,
+      uint32 type_shm_id, uint32 type_shm_offset, uint32 name_shm_id,
+      uint32 name_shm_offset) {
+    gles2::GetActiveUniform& c = GetCmdSpace<gles2::GetActiveUniform>();
+    c.Init(
+        program, index, bufsize, length_shm_id, length_shm_offset, size_shm_id,
+        size_shm_offset, type_shm_id, type_shm_offset, name_shm_id,
+        name_shm_offset);
+  }
+
+  void GetAttachedShaders(
+      GLuint program, GLsizei maxcount, uint32 count_shm_id,
+      uint32 count_shm_offset, uint32 shaders_shm_id,
+      uint32 shaders_shm_offset) {
+    gles2::GetAttachedShaders& c = GetCmdSpace<gles2::GetAttachedShaders>();
+    c.Init(
+        program, maxcount, count_shm_id, count_shm_offset, shaders_shm_id,
+        shaders_shm_offset);
+  }
+
+  void GetAttribLocation(
+      GLuint program, uint32 name_shm_id, uint32 name_shm_offset,
+      uint32 data_size) {
+    gles2::GetAttribLocation& c = GetCmdSpace<gles2::GetAttribLocation>();
+    c.Init(program, name_shm_id, name_shm_offset, data_size);
+  }
+
+  void GetAttribLocationImmediate(GLuint program, const char* name) {
+    const uint32 size = gles2::GetAttribLocationImmediate::ComputeSize(name);
+    gles2::GetAttribLocationImmediate& c =
+        GetImmediateCmdSpaceTotalSize<gles2::GetAttribLocationImmediate>(size);
+    c.Init(program, name);
+  }
+
+  void GetBooleanv(
+      GLenum pname, uint32 params_shm_id, uint32 params_shm_offset) {
+    gles2::GetBooleanv& c = GetCmdSpace<gles2::GetBooleanv>();
+    c.Init(pname, params_shm_id, params_shm_offset);
+  }
+
+  void GetBufferParameteriv(
+      GLenum target, GLenum pname, uint32 params_shm_id,
+      uint32 params_shm_offset) {
+    gles2::GetBufferParameteriv& c =
+        GetCmdSpace<gles2::GetBufferParameteriv>();
+    c.Init(target, pname, params_shm_id, params_shm_offset);
+  }
+
+  void GetError(uint32 result_shm_id, uint32 result_shm_offset) {
+    gles2::GetError& c = GetCmdSpace<gles2::GetError>();
+    c.Init(result_shm_id, result_shm_offset);
+  }
+
+  void GetFloatv(
+      GLenum pname, uint32 params_shm_id, uint32 params_shm_offset) {
+    gles2::GetFloatv& c = GetCmdSpace<gles2::GetFloatv>();
+    c.Init(pname, params_shm_id, params_shm_offset);
+  }
+
+  void GetFramebufferAttachmentParameteriv(
+      GLenum target, GLenum attachment, GLenum pname, uint32 params_shm_id,
+      uint32 params_shm_offset) {
+    gles2::GetFramebufferAttachmentParameteriv& c =
+        GetCmdSpace<gles2::GetFramebufferAttachmentParameteriv>();
+    c.Init(target, attachment, pname, params_shm_id, params_shm_offset);
+  }
+
+  void GetIntegerv(
+      GLenum pname, uint32 params_shm_id, uint32 params_shm_offset) {
+    gles2::GetIntegerv& c = GetCmdSpace<gles2::GetIntegerv>();
+    c.Init(pname, params_shm_id, params_shm_offset);
+  }
+
+  void GetProgramiv(
+      GLuint program, GLenum pname, uint32 params_shm_id,
+      uint32 params_shm_offset) {
+    gles2::GetProgramiv& c = GetCmdSpace<gles2::GetProgramiv>();
+    c.Init(program, pname, params_shm_id, params_shm_offset);
+  }
+
+  void GetProgramInfoLog(
+      GLuint program, GLsizei bufsize, uint32 length_shm_id,
+      uint32 length_shm_offset, uint32 infolog_shm_id,
+      uint32 infolog_shm_offset) {
+    gles2::GetProgramInfoLog& c = GetCmdSpace<gles2::GetProgramInfoLog>();
+    c.Init(
+        program, bufsize, length_shm_id, length_shm_offset, infolog_shm_id,
+        infolog_shm_offset);
+  }
+
+  void GetRenderbufferParameteriv(
+      GLenum target, GLenum pname, uint32 params_shm_id,
+      uint32 params_shm_offset) {
+    gles2::GetRenderbufferParameteriv& c =
+        GetCmdSpace<gles2::GetRenderbufferParameteriv>();
+    c.Init(target, pname, params_shm_id, params_shm_offset);
+  }
+
+  void GetShaderiv(
+      GLuint shader, GLenum pname, uint32 params_shm_id,
+      uint32 params_shm_offset) {
+    gles2::GetShaderiv& c = GetCmdSpace<gles2::GetShaderiv>();
+    c.Init(shader, pname, params_shm_id, params_shm_offset);
+  }
+
+  void GetShaderInfoLog(
+      GLuint shader, GLsizei bufsize, uint32 length_shm_id,
+      uint32 length_shm_offset, uint32 infolog_shm_id,
+      uint32 infolog_shm_offset) {
+    gles2::GetShaderInfoLog& c = GetCmdSpace<gles2::GetShaderInfoLog>();
+    c.Init(
+        shader, bufsize, length_shm_id, length_shm_offset, infolog_shm_id,
+        infolog_shm_offset);
+  }
+
+  void GetShaderPrecisionFormat(
+      GLenum shadertype, GLenum precisiontype, uint32 range_shm_id,
+      uint32 range_shm_offset, uint32 precision_shm_id,
+      uint32 precision_shm_offset) {
+    gles2::GetShaderPrecisionFormat& c =
+        GetCmdSpace<gles2::GetShaderPrecisionFormat>();
+    c.Init(
+        shadertype, precisiontype, range_shm_id, range_shm_offset,
+        precision_shm_id, precision_shm_offset);
+  }
+
+  void GetShaderSource(
+      GLuint shader, GLsizei bufsize, uint32 length_shm_id,
+      uint32 length_shm_offset, uint32 source_shm_id,
+      uint32 source_shm_offset) {
+    gles2::GetShaderSource& c = GetCmdSpace<gles2::GetShaderSource>();
+    c.Init(
+        shader, bufsize, length_shm_id, length_shm_offset, source_shm_id,
+        source_shm_offset);
+  }
+
+  void GetString(GLenum name) {
+    gles2::GetString& c = GetCmdSpace<gles2::GetString>();
+    c.Init(name);
+  }
+
+  void GetTexParameterfv(
+      GLenum target, GLenum pname, uint32 params_shm_id,
+      uint32 params_shm_offset) {
+    gles2::GetTexParameterfv& c = GetCmdSpace<gles2::GetTexParameterfv>();
+    c.Init(target, pname, params_shm_id, params_shm_offset);
+  }
+
+  void GetTexParameteriv(
+      GLenum target, GLenum pname, uint32 params_shm_id,
+      uint32 params_shm_offset) {
+    gles2::GetTexParameteriv& c = GetCmdSpace<gles2::GetTexParameteriv>();
+    c.Init(target, pname, params_shm_id, params_shm_offset);
+  }
+
+  void GetUniformfv(
+      GLuint program, GLint location, uint32 params_shm_id,
+      uint32 params_shm_offset) {
+    gles2::GetUniformfv& c = GetCmdSpace<gles2::GetUniformfv>();
+    c.Init(program, location, params_shm_id, params_shm_offset);
+  }
+
+  void GetUniformiv(
+      GLuint program, GLint location, uint32 params_shm_id,
+      uint32 params_shm_offset) {
+    gles2::GetUniformiv& c = GetCmdSpace<gles2::GetUniformiv>();
+    c.Init(program, location, params_shm_id, params_shm_offset);
+  }
+
+  void GetUniformLocation(
+      GLuint program, uint32 name_shm_id, uint32 name_shm_offset,
+      uint32 data_size) {
+    gles2::GetUniformLocation& c = GetCmdSpace<gles2::GetUniformLocation>();
+    c.Init(program, name_shm_id, name_shm_offset, data_size);
+  }
+
+  void GetUniformLocationImmediate(GLuint program, const char* name) {
+    const uint32 size = gles2::GetUniformLocationImmediate::ComputeSize(name);
+    gles2::GetUniformLocationImmediate& c =
+        GetImmediateCmdSpaceTotalSize<gles2::GetUniformLocationImmediate>(
+            size);
+    c.Init(program, name);
+  }
+
+  void GetVertexAttribfv(
+      GLuint index, GLenum pname, uint32 params_shm_id,
+      uint32 params_shm_offset) {
+    gles2::GetVertexAttribfv& c = GetCmdSpace<gles2::GetVertexAttribfv>();
+    c.Init(index, pname, params_shm_id, params_shm_offset);
+  }
+
+  void GetVertexAttribiv(
+      GLuint index, GLenum pname, uint32 params_shm_id,
+      uint32 params_shm_offset) {
+    gles2::GetVertexAttribiv& c = GetCmdSpace<gles2::GetVertexAttribiv>();
+    c.Init(index, pname, params_shm_id, params_shm_offset);
+  }
+
+  void GetVertexAttribPointerv(
+      GLuint index, GLenum pname, uint32 pointer_shm_id,
+      uint32 pointer_shm_offset) {
+    gles2::GetVertexAttribPointerv& c =
+        GetCmdSpace<gles2::GetVertexAttribPointerv>();
+    c.Init(index, pname, pointer_shm_id, pointer_shm_offset);
+  }
+
+  void Hint(GLenum target, GLenum mode) {
+    gles2::Hint& c = GetCmdSpace<gles2::Hint>();
+    c.Init(target, mode);
+  }
+
+  void IsBuffer(
+      GLuint buffer, uint32 result_shm_id, uint32 result_shm_offset) {
+    gles2::IsBuffer& c = GetCmdSpace<gles2::IsBuffer>();
+    c.Init(buffer, result_shm_id, result_shm_offset);
+  }
+
+  void IsEnabled(GLenum cap, uint32 result_shm_id, uint32 result_shm_offset) {
+    gles2::IsEnabled& c = GetCmdSpace<gles2::IsEnabled>();
+    c.Init(cap, result_shm_id, result_shm_offset);
+  }
+
+  void IsFramebuffer(
+      GLuint framebuffer, uint32 result_shm_id, uint32 result_shm_offset) {
+    gles2::IsFramebuffer& c = GetCmdSpace<gles2::IsFramebuffer>();
+    c.Init(framebuffer, result_shm_id, result_shm_offset);
+  }
+
+  void IsProgram(
+      GLuint program, uint32 result_shm_id, uint32 result_shm_offset) {
+    gles2::IsProgram& c = GetCmdSpace<gles2::IsProgram>();
+    c.Init(program, result_shm_id, result_shm_offset);
+  }
+
+  void IsRenderbuffer(
+      GLuint renderbuffer, uint32 result_shm_id, uint32 result_shm_offset) {
+    gles2::IsRenderbuffer& c = GetCmdSpace<gles2::IsRenderbuffer>();
+    c.Init(renderbuffer, result_shm_id, result_shm_offset);
+  }
+
+  void IsShader(
+      GLuint shader, uint32 result_shm_id, uint32 result_shm_offset) {
+    gles2::IsShader& c = GetCmdSpace<gles2::IsShader>();
+    c.Init(shader, result_shm_id, result_shm_offset);
+  }
+
+  void IsTexture(
+      GLuint texture, uint32 result_shm_id, uint32 result_shm_offset) {
+    gles2::IsTexture& c = GetCmdSpace<gles2::IsTexture>();
+    c.Init(texture, result_shm_id, result_shm_offset);
+  }
+
+  void LineWidth(GLfloat width) {
+    gles2::LineWidth& c = GetCmdSpace<gles2::LineWidth>();
+    c.Init(width);
+  }
+
+  void LinkProgram(GLuint program) {
+    gles2::LinkProgram& c = GetCmdSpace<gles2::LinkProgram>();
+    c.Init(program);
+  }
+
+  void PixelStorei(GLenum pname, GLint param) {
+    gles2::PixelStorei& c = GetCmdSpace<gles2::PixelStorei>();
+    c.Init(pname, param);
+  }
+
+  void PolygonOffset(GLfloat factor, GLfloat units) {
+    gles2::PolygonOffset& c = GetCmdSpace<gles2::PolygonOffset>();
+    c.Init(factor, units);
+  }
+
+  void ReadPixels(
+      GLint x, GLint y, GLsizei width, GLsizei height, GLenum format,
+      GLenum type, uint32 pixels_shm_id, uint32 pixels_shm_offset) {
+    gles2::ReadPixels& c = GetCmdSpace<gles2::ReadPixels>();
+    c.Init(
+        x, y, width, height, format, type, pixels_shm_id, pixels_shm_offset);
+  }
+
+  void RenderbufferStorage(
+      GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
+    gles2::RenderbufferStorage& c = GetCmdSpace<gles2::RenderbufferStorage>();
+    c.Init(target, internalformat, width, height);
+  }
+
+  void SampleCoverage(GLclampf value, GLboolean invert) {
+    gles2::SampleCoverage& c = GetCmdSpace<gles2::SampleCoverage>();
+    c.Init(value, invert);
+  }
+
+  void Scissor(GLint x, GLint y, GLsizei width, GLsizei height) {
+    gles2::Scissor& c = GetCmdSpace<gles2::Scissor>();
+    c.Init(x, y, width, height);
+  }
+
+  void ShaderSource(
+      GLuint shader, GLsizei count, uint32 data_shm_id, uint32 data_shm_offset,
+      uint32 data_size) {
+    gles2::ShaderSource& c = GetCmdSpace<gles2::ShaderSource>();
+    c.Init(shader, count, data_shm_id, data_shm_offset, data_size);
+  }
+
+  void ShaderSourceImmediate(GLuint shader, GLsizei count, uint32 data_size) {
+    const uint32 s = 0;  // TODO(gman): compute correct size
+    gles2::ShaderSourceImmediate& c =
+        GetImmediateCmdSpaceTotalSize<gles2::ShaderSourceImmediate>(s);
+    c.Init(shader, count, data_size);
+  }
+
+  void StencilFunc(GLenum func, GLint ref, GLuint mask) {
+    gles2::StencilFunc& c = GetCmdSpace<gles2::StencilFunc>();
+    c.Init(func, ref, mask);
+  }
+
+  void StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask) {
+    gles2::StencilFuncSeparate& c = GetCmdSpace<gles2::StencilFuncSeparate>();
+    c.Init(face, func, ref, mask);
+  }
+
+  void StencilMask(GLuint mask) {
+    gles2::StencilMask& c = GetCmdSpace<gles2::StencilMask>();
+    c.Init(mask);
+  }
+
+  void StencilMaskSeparate(GLenum face, GLuint mask) {
+    gles2::StencilMaskSeparate& c = GetCmdSpace<gles2::StencilMaskSeparate>();
+    c.Init(face, mask);
+  }
+
+  void StencilOp(GLenum fail, GLenum zfail, GLenum zpass) {
+    gles2::StencilOp& c = GetCmdSpace<gles2::StencilOp>();
+    c.Init(fail, zfail, zpass);
+  }
+
+  void StencilOpSeparate(
+      GLenum face, GLenum fail, GLenum zfail, GLenum zpass) {
+    gles2::StencilOpSeparate& c = GetCmdSpace<gles2::StencilOpSeparate>();
+    c.Init(face, fail, zfail, zpass);
+  }
+
+  void TexImage2D(
+      GLenum target, GLint level, GLint internalformat, GLsizei width,
+      GLsizei height, GLint border, GLenum format, GLenum type,
+      uint32 pixels_shm_id, uint32 pixels_shm_offset) {
+    gles2::TexImage2D& c = GetCmdSpace<gles2::TexImage2D>();
+    c.Init(
+        target, level, internalformat, width, height, border, format, type,
+        pixels_shm_id, pixels_shm_offset);
+  }
+
+  void TexImage2DImmediate(
+      GLenum target, GLint level, GLint internalformat, GLsizei width,
+      GLsizei height, GLint border, GLenum format, GLenum type) {
+    const uint32 s = 0;  // TODO(gman): compute correct size
+    gles2::TexImage2DImmediate& c =
+        GetImmediateCmdSpaceTotalSize<gles2::TexImage2DImmediate>(s);
+    c.Init(target, level, internalformat, width, height, border, format, type);
+  }
+
+  void TexParameterf(GLenum target, GLenum pname, GLfloat param) {
+    gles2::TexParameterf& c = GetCmdSpace<gles2::TexParameterf>();
+    c.Init(target, pname, param);
+  }
+
+  void TexParameterfv(
+      GLenum target, GLenum pname, uint32 params_shm_id,
+      uint32 params_shm_offset) {
+    gles2::TexParameterfv& c = GetCmdSpace<gles2::TexParameterfv>();
+    c.Init(target, pname, params_shm_id, params_shm_offset);
+  }
+
+  void TexParameterfvImmediate(
+      GLenum target, GLenum pname, const GLfloat* params) {
+    const uint32 size = gles2::TexParameterfvImmediate::ComputeSize();
+    gles2::TexParameterfvImmediate& c =
+        GetImmediateCmdSpaceTotalSize<gles2::TexParameterfvImmediate>(size);
+    c.Init(target, pname, params);
+  }
+
+  void TexParameteri(GLenum target, GLenum pname, GLint param) {
+    gles2::TexParameteri& c = GetCmdSpace<gles2::TexParameteri>();
+    c.Init(target, pname, param);
+  }
+
+  void TexParameteriv(
+      GLenum target, GLenum pname, uint32 params_shm_id,
+      uint32 params_shm_offset) {
+    gles2::TexParameteriv& c = GetCmdSpace<gles2::TexParameteriv>();
+    c.Init(target, pname, params_shm_id, params_shm_offset);
+  }
+
+  void TexParameterivImmediate(
+      GLenum target, GLenum pname, const GLint* params) {
+    const uint32 size = gles2::TexParameterivImmediate::ComputeSize();
+    gles2::TexParameterivImmediate& c =
+        GetImmediateCmdSpaceTotalSize<gles2::TexParameterivImmediate>(size);
+    c.Init(target, pname, params);
+  }
+
+  void TexSubImage2D(
+      GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width,
+      GLsizei height, GLenum format, GLenum type, uint32 pixels_shm_id,
+      uint32 pixels_shm_offset) {
+    gles2::TexSubImage2D& c = GetCmdSpace<gles2::TexSubImage2D>();
+    c.Init(
+        target, level, xoffset, yoffset, width, height, format, type,
+        pixels_shm_id, pixels_shm_offset);
+  }
+
+  void TexSubImage2DImmediate(
+      GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width,
+      GLsizei height, GLenum format, GLenum type) {
+    const uint32 s = 0;  // TODO(gman): compute correct size
+    gles2::TexSubImage2DImmediate& c =
+        GetImmediateCmdSpaceTotalSize<gles2::TexSubImage2DImmediate>(s);
+    c.Init(target, level, xoffset, yoffset, width, height, format, type);
+  }
+
+  void Uniform1f(GLint location, GLfloat x) {
+    gles2::Uniform1f& c = GetCmdSpace<gles2::Uniform1f>();
+    c.Init(location, x);
+  }
+
+  void Uniform1fv(
+      GLint location, GLsizei count, uint32 v_shm_id, uint32 v_shm_offset) {
+    gles2::Uniform1fv& c = GetCmdSpace<gles2::Uniform1fv>();
+    c.Init(location, count, v_shm_id, v_shm_offset);
+  }
+
+  void Uniform1fvImmediate(GLint location, GLsizei count, const GLfloat* v) {
+    const uint32 size = gles2::Uniform1fvImmediate::ComputeSize(count);
+    gles2::Uniform1fvImmediate& c =
+        GetImmediateCmdSpaceTotalSize<gles2::Uniform1fvImmediate>(size);
+    c.Init(location, count, v);
+  }
+
+  void Uniform1i(GLint location, GLint x) {
+    gles2::Uniform1i& c = GetCmdSpace<gles2::Uniform1i>();
+    c.Init(location, x);
+  }
+
+  void Uniform1iv(
+      GLint location, GLsizei count, uint32 v_shm_id, uint32 v_shm_offset) {
+    gles2::Uniform1iv& c = GetCmdSpace<gles2::Uniform1iv>();
+    c.Init(location, count, v_shm_id, v_shm_offset);
+  }
+
+  void Uniform1ivImmediate(GLint location, GLsizei count, const GLint* v) {
+    const uint32 size = gles2::Uniform1ivImmediate::ComputeSize(count);
+    gles2::Uniform1ivImmediate& c =
+        GetImmediateCmdSpaceTotalSize<gles2::Uniform1ivImmediate>(size);
+    c.Init(location, count, v);
+  }
+
+  void Uniform2f(GLint location, GLfloat x, GLfloat y) {
+    gles2::Uniform2f& c = GetCmdSpace<gles2::Uniform2f>();
+    c.Init(location, x, y);
+  }
+
+  void Uniform2fv(
+      GLint location, GLsizei count, uint32 v_shm_id, uint32 v_shm_offset) {
+    gles2::Uniform2fv& c = GetCmdSpace<gles2::Uniform2fv>();
+    c.Init(location, count, v_shm_id, v_shm_offset);
+  }
+
+  void Uniform2fvImmediate(GLint location, GLsizei count, const GLfloat* v) {
+    const uint32 size = gles2::Uniform2fvImmediate::ComputeSize(count);
+    gles2::Uniform2fvImmediate& c =
+        GetImmediateCmdSpaceTotalSize<gles2::Uniform2fvImmediate>(size);
+    c.Init(location, count, v);
+  }
+
+  void Uniform2i(GLint location, GLint x, GLint y) {
+    gles2::Uniform2i& c = GetCmdSpace<gles2::Uniform2i>();
+    c.Init(location, x, y);
+  }
+
+  void Uniform2iv(
+      GLint location, GLsizei count, uint32 v_shm_id, uint32 v_shm_offset) {
+    gles2::Uniform2iv& c = GetCmdSpace<gles2::Uniform2iv>();
+    c.Init(location, count, v_shm_id, v_shm_offset);
+  }
+
+  void Uniform2ivImmediate(GLint location, GLsizei count, const GLint* v) {
+    const uint32 size = gles2::Uniform2ivImmediate::ComputeSize(count);
+    gles2::Uniform2ivImmediate& c =
+        GetImmediateCmdSpaceTotalSize<gles2::Uniform2ivImmediate>(size);
+    c.Init(location, count, v);
+  }
+
+  void Uniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z) {
+    gles2::Uniform3f& c = GetCmdSpace<gles2::Uniform3f>();
+    c.Init(location, x, y, z);
+  }
+
+  void Uniform3fv(
+      GLint location, GLsizei count, uint32 v_shm_id, uint32 v_shm_offset) {
+    gles2::Uniform3fv& c = GetCmdSpace<gles2::Uniform3fv>();
+    c.Init(location, count, v_shm_id, v_shm_offset);
+  }
+
+  void Uniform3fvImmediate(GLint location, GLsizei count, const GLfloat* v) {
+    const uint32 size = gles2::Uniform3fvImmediate::ComputeSize(count);
+    gles2::Uniform3fvImmediate& c =
+        GetImmediateCmdSpaceTotalSize<gles2::Uniform3fvImmediate>(size);
+    c.Init(location, count, v);
+  }
+
+  void Uniform3i(GLint location, GLint x, GLint y, GLint z) {
+    gles2::Uniform3i& c = GetCmdSpace<gles2::Uniform3i>();
+    c.Init(location, x, y, z);
+  }
+
+  void Uniform3iv(
+      GLint location, GLsizei count, uint32 v_shm_id, uint32 v_shm_offset) {
+    gles2::Uniform3iv& c = GetCmdSpace<gles2::Uniform3iv>();
+    c.Init(location, count, v_shm_id, v_shm_offset);
+  }
+
+  void Uniform3ivImmediate(GLint location, GLsizei count, const GLint* v) {
+    const uint32 size = gles2::Uniform3ivImmediate::ComputeSize(count);
+    gles2::Uniform3ivImmediate& c =
+        GetImmediateCmdSpaceTotalSize<gles2::Uniform3ivImmediate>(size);
+    c.Init(location, count, v);
+  }
+
+  void Uniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) {
+    gles2::Uniform4f& c = GetCmdSpace<gles2::Uniform4f>();
+    c.Init(location, x, y, z, w);
+  }
+
+  void Uniform4fv(
+      GLint location, GLsizei count, uint32 v_shm_id, uint32 v_shm_offset) {
+    gles2::Uniform4fv& c = GetCmdSpace<gles2::Uniform4fv>();
+    c.Init(location, count, v_shm_id, v_shm_offset);
+  }
+
+  void Uniform4fvImmediate(GLint location, GLsizei count, const GLfloat* v) {
+    const uint32 size = gles2::Uniform4fvImmediate::ComputeSize(count);
+    gles2::Uniform4fvImmediate& c =
+        GetImmediateCmdSpaceTotalSize<gles2::Uniform4fvImmediate>(size);
+    c.Init(location, count, v);
+  }
+
+  void Uniform4i(GLint location, GLint x, GLint y, GLint z, GLint w) {
+    gles2::Uniform4i& c = GetCmdSpace<gles2::Uniform4i>();
+    c.Init(location, x, y, z, w);
+  }
+
+  void Uniform4iv(
+      GLint location, GLsizei count, uint32 v_shm_id, uint32 v_shm_offset) {
+    gles2::Uniform4iv& c = GetCmdSpace<gles2::Uniform4iv>();
+    c.Init(location, count, v_shm_id, v_shm_offset);
+  }
+
+  void Uniform4ivImmediate(GLint location, GLsizei count, const GLint* v) {
+    const uint32 size = gles2::Uniform4ivImmediate::ComputeSize(count);
+    gles2::Uniform4ivImmediate& c =
+        GetImmediateCmdSpaceTotalSize<gles2::Uniform4ivImmediate>(size);
+    c.Init(location, count, v);
+  }
+
+  void UniformMatrix2fv(
+      GLint location, GLsizei count, GLboolean transpose, uint32 value_shm_id,
+      uint32 value_shm_offset) {
+    gles2::UniformMatrix2fv& c = GetCmdSpace<gles2::UniformMatrix2fv>();
+    c.Init(location, count, transpose, value_shm_id, value_shm_offset);
+  }
+
+  void UniformMatrix2fvImmediate(
+      GLint location, GLsizei count, GLboolean transpose,
+      const GLfloat* value) {
+    const uint32 size = gles2::UniformMatrix2fvImmediate::ComputeSize(count);
+    gles2::UniformMatrix2fvImmediate& c =
+        GetImmediateCmdSpaceTotalSize<gles2::UniformMatrix2fvImmediate>(size);
+    c.Init(location, count, transpose, value);
+  }
+
+  void UniformMatrix3fv(
+      GLint location, GLsizei count, GLboolean transpose, uint32 value_shm_id,
+      uint32 value_shm_offset) {
+    gles2::UniformMatrix3fv& c = GetCmdSpace<gles2::UniformMatrix3fv>();
+    c.Init(location, count, transpose, value_shm_id, value_shm_offset);
+  }
+
+  void UniformMatrix3fvImmediate(
+      GLint location, GLsizei count, GLboolean transpose,
+      const GLfloat* value) {
+    const uint32 size = gles2::UniformMatrix3fvImmediate::ComputeSize(count);
+    gles2::UniformMatrix3fvImmediate& c =
+        GetImmediateCmdSpaceTotalSize<gles2::UniformMatrix3fvImmediate>(size);
+    c.Init(location, count, transpose, value);
+  }
+
+  void UniformMatrix4fv(
+      GLint location, GLsizei count, GLboolean transpose, uint32 value_shm_id,
+      uint32 value_shm_offset) {
+    gles2::UniformMatrix4fv& c = GetCmdSpace<gles2::UniformMatrix4fv>();
+    c.Init(location, count, transpose, value_shm_id, value_shm_offset);
+  }
+
+  void UniformMatrix4fvImmediate(
+      GLint location, GLsizei count, GLboolean transpose,
+      const GLfloat* value) {
+    const uint32 size = gles2::UniformMatrix4fvImmediate::ComputeSize(count);
+    gles2::UniformMatrix4fvImmediate& c =
+        GetImmediateCmdSpaceTotalSize<gles2::UniformMatrix4fvImmediate>(size);
+    c.Init(location, count, transpose, value);
+  }
+
+  void UseProgram(GLuint program) {
+    gles2::UseProgram& c = GetCmdSpace<gles2::UseProgram>();
+    c.Init(program);
+  }
+
+  void ValidateProgram(GLuint program) {
+    gles2::ValidateProgram& c = GetCmdSpace<gles2::ValidateProgram>();
+    c.Init(program);
+  }
+
+  void VertexAttrib1f(GLuint indx, GLfloat x) {
+    gles2::VertexAttrib1f& c = GetCmdSpace<gles2::VertexAttrib1f>();
+    c.Init(indx, x);
+  }
+
+  void VertexAttrib1fv(
+      GLuint indx, uint32 values_shm_id, uint32 values_shm_offset) {
+    gles2::VertexAttrib1fv& c = GetCmdSpace<gles2::VertexAttrib1fv>();
+    c.Init(indx, values_shm_id, values_shm_offset);
+  }
+
+  void VertexAttrib1fvImmediate(GLuint indx, const GLfloat* values) {
+    const uint32 size = gles2::VertexAttrib1fvImmediate::ComputeSize();
+    gles2::VertexAttrib1fvImmediate& c =
+        GetImmediateCmdSpaceTotalSize<gles2::VertexAttrib1fvImmediate>(size);
+    c.Init(indx, values);
+  }
+
+  void VertexAttrib2f(GLuint indx, GLfloat x, GLfloat y) {
+    gles2::VertexAttrib2f& c = GetCmdSpace<gles2::VertexAttrib2f>();
+    c.Init(indx, x, y);
+  }
+
+  void VertexAttrib2fv(
+      GLuint indx, uint32 values_shm_id, uint32 values_shm_offset) {
+    gles2::VertexAttrib2fv& c = GetCmdSpace<gles2::VertexAttrib2fv>();
+    c.Init(indx, values_shm_id, values_shm_offset);
+  }
+
+  void VertexAttrib2fvImmediate(GLuint indx, const GLfloat* values) {
+    const uint32 size = gles2::VertexAttrib2fvImmediate::ComputeSize();
+    gles2::VertexAttrib2fvImmediate& c =
+        GetImmediateCmdSpaceTotalSize<gles2::VertexAttrib2fvImmediate>(size);
+    c.Init(indx, values);
+  }
+
+  void VertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z) {
+    gles2::VertexAttrib3f& c = GetCmdSpace<gles2::VertexAttrib3f>();
+    c.Init(indx, x, y, z);
+  }
+
+  void VertexAttrib3fv(
+      GLuint indx, uint32 values_shm_id, uint32 values_shm_offset) {
+    gles2::VertexAttrib3fv& c = GetCmdSpace<gles2::VertexAttrib3fv>();
+    c.Init(indx, values_shm_id, values_shm_offset);
+  }
+
+  void VertexAttrib3fvImmediate(GLuint indx, const GLfloat* values) {
+    const uint32 size = gles2::VertexAttrib3fvImmediate::ComputeSize();
+    gles2::VertexAttrib3fvImmediate& c =
+        GetImmediateCmdSpaceTotalSize<gles2::VertexAttrib3fvImmediate>(size);
+    c.Init(indx, values);
+  }
+
+  void VertexAttrib4f(
+      GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w) {
+    gles2::VertexAttrib4f& c = GetCmdSpace<gles2::VertexAttrib4f>();
+    c.Init(indx, x, y, z, w);
+  }
+
+  void VertexAttrib4fv(
+      GLuint indx, uint32 values_shm_id, uint32 values_shm_offset) {
+    gles2::VertexAttrib4fv& c = GetCmdSpace<gles2::VertexAttrib4fv>();
+    c.Init(indx, values_shm_id, values_shm_offset);
+  }
+
+  void VertexAttrib4fvImmediate(GLuint indx, const GLfloat* values) {
+    const uint32 size = gles2::VertexAttrib4fvImmediate::ComputeSize();
+    gles2::VertexAttrib4fvImmediate& c =
+        GetImmediateCmdSpaceTotalSize<gles2::VertexAttrib4fvImmediate>(size);
+    c.Init(indx, values);
+  }
+
+  void VertexAttribPointer(
+      GLuint indx, GLint size, GLenum type, GLboolean normalized,
+      GLsizei stride, GLuint offset) {
+    gles2::VertexAttribPointer& c = GetCmdSpace<gles2::VertexAttribPointer>();
+    c.Init(indx, size, type, normalized, stride, offset);
+  }
+
+  void Viewport(GLint x, GLint y, GLsizei width, GLsizei height) {
+    gles2::Viewport& c = GetCmdSpace<gles2::Viewport>();
+    c.Init(x, y, width, height);
+  }
+
+  void SwapBuffers() {
+    gles2::SwapBuffers& c = GetCmdSpace<gles2::SwapBuffers>();
+    c.Init();
+  }
+
diff --git a/gpu/command_buffer/client/gles2_demo.cc b/gpu/command_buffer/client/gles2_demo.cc
new file mode 100644
index 0000000..04419c3
--- /dev/null
+++ b/gpu/command_buffer/client/gles2_demo.cc
@@ -0,0 +1,203 @@
+// Copyright (c) 2006-2009 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.
+
+// This file is here so other GLES2 related files can have a common set of
+// includes where appropriate.
+
+#include <windows.h>
+#include <windowsx.h>
+#include <shellapi.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "base/ref_counted.h"
+#include "base/shared_memory.h"
+#include "base/scoped_ptr.h"
+#include "gpu/command_buffer/service/gpu_processor.h"
+#include "gpu/command_buffer/service/command_buffer_service.h"
+#include "gpu/np_utils/np_utils.h"
+#include "gpu/command_buffer/client/gles2_implementation.h"
+#include "gpu/command_buffer/client/gles2_lib.h"
+#include "gpu/command_buffer/client/gles2_demo_c.h"
+#include "gpu/command_buffer/client/gles2_demo_cc.h"
+
+using base::SharedMemory;
+using command_buffer::GPUProcessor;
+using command_buffer::CommandBufferService;
+using command_buffer::gles2::GLES2CmdHelper;
+using command_buffer::gles2::GLES2Implementation;
+
+class GLES2Demo {
+ public:
+  GLES2Demo();
+
+  bool GLES2Demo::Setup(NPP npp, void* hwnd, int32 size);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(GLES2Demo);
+};
+
+GLES2Demo::GLES2Demo() {
+}
+
+bool GLES2Demo::Setup(NPP npp, void* hwnd, int32 size) {
+  scoped_ptr<SharedMemory> ring_buffer(new SharedMemory);
+  if (!ring_buffer->Create(std::wstring(), false, false, size)) {
+    return NULL;
+  }
+
+  if (!ring_buffer->Map(size)) {
+    return NULL;
+  }
+
+  scoped_ptr<CommandBufferService> command_buffer(new CommandBufferService);
+  if (!command_buffer->Initialize(ring_buffer.release())) {
+    return NULL;
+  }
+
+  scoped_refptr<GPUProcessor> gpu_processor(
+      new GPUProcessor(npp, command_buffer.get()));
+  if (!gpu_processor->Initialize(reinterpret_cast<HWND>(hwnd))) {
+    return NULL;
+  }
+
+  command_buffer->SetPutOffsetChangeCallback(
+      NewCallback(gpu_processor.get(), &GPUProcessor::ProcessCommands));
+
+  GLES2CmdHelper* helper = new GLES2CmdHelper(command_buffer.get());
+  if (!helper->Initialize()) {
+    // TODO(gman): cleanup.
+    return false;
+  }
+
+  size_t transfer_buffer_size = 512 * 1024;
+  int32 transfer_buffer_id =
+      command_buffer->CreateTransferBuffer(transfer_buffer_size);
+  void* transfer_buffer =
+      command_buffer->GetTransferBuffer(transfer_buffer_id);
+
+  gles2::g_gl_impl = new GLES2Implementation(helper,
+                                             transfer_buffer,
+                                             transfer_buffer_id);
+
+  return command_buffer.release() != NULL;
+}
+
+#if defined(OS_WIN)
+LRESULT CALLBACK WindowProc(
+    HWND hwnd, UINT msg, WPARAM w_param, LPARAM l_param) {
+  switch (msg) {
+    case WM_CLOSE:
+      DestroyWindow(hwnd);
+      break;
+    case WM_DESTROY:
+      PostQuitMessage(0);
+      break;
+    case WM_PAINT: {
+      GLFromCPPTestFunction();
+      GLFromCTestFunction();
+      // TODO(gman): Not sure how SwapBuffer should be exposed.
+      gles2::GetGLContext()->SwapBuffers();
+      break;
+    }
+    default:
+      return ::DefWindowProc(hwnd, msg, w_param, l_param);
+  }
+  return 0;
+}
+
+HINSTANCE GetInstance(void) {
+  HWND hwnd = GetConsoleWindow();
+  return reinterpret_cast<HINSTANCE>(GetWindowLong(hwnd, GWL_HINSTANCE));
+}
+
+void ProcessMessages(void* in_hwnd) {
+  HWND hwnd = reinterpret_cast<HWND>(in_hwnd);
+  MSG msg;
+
+  bool done = false;
+  while (!done) {
+    while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
+      if (msg.message == WM_QUIT) {
+        done = true;
+      }
+      // dispatch the message
+      TranslateMessage(&msg);
+      DispatchMessage(&msg);
+    }
+    if (!done) {
+      InvalidateRect(hwnd, NULL, TRUE);
+    }
+  }
+}
+
+#endif
+
+void* SetupWindow() {
+#if defined(OS_WIN)
+  HINSTANCE instance = GetInstance();
+  WNDCLASSEX wc = {0};
+  wc.lpszClassName = L"MY_WINDOWS_CLASS";
+  wc.cbSize = sizeof(WNDCLASSEX);
+  wc.style = CS_HREDRAW | CS_VREDRAW;
+  wc.lpfnWndProc = ::WindowProc;
+  wc.cbClsExtra = 0;
+  wc.cbWndExtra = 0;
+  wc.hInstance = instance;
+  wc.hIcon = ::LoadIcon(instance, IDI_APPLICATION);
+  wc.hIconSm = NULL;
+  wc.hCursor = ::LoadCursor(instance, IDC_ARROW);
+  wc.hbrBackground = static_cast<HBRUSH>(::GetStockObject(BLACK_BRUSH));
+  wc.lpszMenuName = NULL;
+
+  if (!::RegisterClassEx(&wc))
+    return false;
+
+  // Leaving this window onscreen leads to a redraw error which makes it
+  // a hassle to debug tests in an IDE, so we place the window somewhere that
+  // won't happen.
+  HWND hwnd = ::CreateWindowExW(
+      NULL,
+      wc.lpszClassName,
+      L"",
+      WS_OVERLAPPEDWINDOW,
+      10,
+      0,
+      512,
+      512,
+      0,
+      0,
+      instance,
+      0);
+
+  if (hwnd == NULL) {
+    return false;
+  }
+
+  ::ShowWindow(hwnd, SW_SHOWNORMAL);
+
+
+  return hwnd;
+#else
+#error Need code.
+#endif
+}
+
+int main(int argc, const char** argv) {
+  const int32 kCommandBufferSize = 1024 * 1024;
+  GLES2Demo* demo = new GLES2Demo();
+
+  void* hwnd = SetupWindow();
+  if (!hwnd) {
+    ::fprintf(stdout, "Could not setup window.\n");
+    return EXIT_FAILURE;
+  }
+
+  demo->Setup(NULL, hwnd, kCommandBufferSize);
+
+  ProcessMessages(hwnd);
+
+  return EXIT_SUCCESS;
+}
+
+
diff --git a/gpu/command_buffer/client/gles2_demo_c.c b/gpu/command_buffer/client/gles2_demo_c.c
new file mode 100644
index 0000000..44b2c57
--- /dev/null
+++ b/gpu/command_buffer/client/gles2_demo_c.c
@@ -0,0 +1,15 @@
+// Copyright (c) 2006-2009 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.
+
+// This file is here so other GLES2 related files can have a common set of
+// includes where appropriate.
+
+#include <GLES2/gl2.h>
+#include "gpu/command_buffer/client/gles2_demo_c.h"
+
+void GLFromCTestFunction() {
+  glClear(GL_COLOR_BUFFER_BIT);
+}
+
+
diff --git a/gpu/command_buffer/client/gles2_demo_c.h b/gpu/command_buffer/client/gles2_demo_c.h
new file mode 100644
index 0000000..0cd1478
--- /dev/null
+++ b/gpu/command_buffer/client/gles2_demo_c.h
@@ -0,0 +1,22 @@
+// Copyright (c) 2006-2009 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.
+
+// A Test that we can access GL from c.
+
+#ifndef GPU_COMMAND_BUFFER_CLIENT_GLES2_DEMO_C_H
+#define GPU_COMMAND_BUFFER_CLIENT_GLES2_DEMO_C_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void GLFromCTestFunction();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // GPU_COMMAND_BUFFER_CLIENT_GLES2_DEMO_C_H
+
+
diff --git a/gpu/command_buffer/client/gles2_demo_cc.cc b/gpu/command_buffer/client/gles2_demo_cc.cc
new file mode 100644
index 0000000..d7a023c25
--- /dev/null
+++ b/gpu/command_buffer/client/gles2_demo_cc.cc
@@ -0,0 +1,21 @@
+// Copyright (c) 2006-2009 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.
+
+// This file is here so other GLES2 related files can have a common set of
+// includes where appropriate.
+
+#include <GLES2/gl2.h>
+#include "gpu/command_buffer/client/gles2_demo_cc.h"
+
+void GLFromCPPTestFunction() {
+  static bool foo = true;
+  foo = !foo;
+  glClearColor(
+      foo ? 1.0f : 0.0f,
+      foo ? 0.0f : 1.0f,
+      1.0f,
+      1.0f);
+}
+
+
diff --git a/gpu/command_buffer/client/gles2_demo_cc.h b/gpu/command_buffer/client/gles2_demo_cc.h
new file mode 100644
index 0000000..7f88d0e4
--- /dev/null
+++ b/gpu/command_buffer/client/gles2_demo_cc.h
@@ -0,0 +1,14 @@
+// Copyright (c) 2006-2009 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.
+
+// A Test that we can access GL from C++.
+
+#ifndef GPU_COMMAND_BUFFER_CLIENT_GLES2_DEMO_CC_H
+#define GPU_COMMAND_BUFFER_CLIENT_GLES2_DEMO_CC_H
+
+void GLFromCPPTestFunction();
+
+#endif  // GPU_COMMAND_BUFFER_CLIENT_GLES2_DEMO_CC_H
+
+
diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc
new file mode 100644
index 0000000..e60e68b5
--- /dev/null
+++ b/gpu/command_buffer/client/gles2_implementation.cc
@@ -0,0 +1,154 @@
+// Copyright (c) 2006-2009 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.
+
+// A class to emluate GLES2 over command buffers.
+
+#include "gpu/command_buffer/client/gles2_implementation.h"
+// TODO(gman): remove when all functions have been implemented.
+#include "gpu/command_buffer/client/gles2_implementation_gen.h"
+#include "gpu/command_buffer/common/gles2_cmd_utils.h"
+
+namespace command_buffer {
+namespace gles2 {
+
+GLES2Implementation::GLES2Implementation(
+      GLES2CmdHelper* helper,
+      void* transfer_buffer,
+      int transfer_buffer_id)
+    : util_(0),  // TODO(gman): Get real number of compressed texture formats.
+      helper_(helper),
+      shared_memory_(transfer_buffer, transfer_buffer_id),
+      pack_alignment_(4),
+      unpack_alignment_(4) {
+}
+
+void GLES2Implementation::MakeIds(GLsizei n, GLuint* ids) {
+  for (GLsizei ii = 0; ii < n; ++ii) {
+    ids[ii] = id_allocator_.AllocateID();
+  }
+}
+
+void GLES2Implementation::FreeIds(GLsizei n, const GLuint* ids) {
+  for (GLsizei ii = 0; ii < n; ++ii) {
+    id_allocator_.FreeID(ids[ii]);
+  }
+}
+
+void GLES2Implementation::DrawElements(
+    GLenum mode, GLsizei count, GLenum type, const void* indices) {
+  helper_->DrawElements(mode, count, type, reinterpret_cast<GLuint>(indices));
+}
+
+void GLES2Implementation::VertexAttribPointer(
+    GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride,
+    const void* ptr) {
+  helper_->VertexAttribPointer(index, size, type, normalized, stride,
+                               reinterpret_cast<GLuint>(ptr));
+}
+
+void GLES2Implementation::ShaderSource(
+    GLuint shader, GLsizei count, const char** string, const GLint* length) {
+  // TODO(gman): change to use buckets and check that there is enough room.
+  uint32* offsets = shared_memory_.GetAddressAs<uint32*>(0);
+  char* strings = reinterpret_cast<char*>(offsets + count);
+
+  uint32 offset = count * sizeof(*offsets);
+  for (GLsizei ii = 0; ii < count; ++ii) {
+    uint32 len = length ? length[ii] : strlen(string[ii]);
+    memcpy(strings + offset, string[ii], len);
+    offset += len;
+    offsets[ii] = offset;
+  }
+
+  helper_->ShaderSource(shader, count, shared_memory_.GetId(), 0, offset);
+  // TODO(gman): Should insert token but not wait until we need shared memory
+  //     again. Really, I should implement a shared memory manager that puts
+  //     things in the next unused part of shared memory and only blocks
+  //     when it needs more memory.
+  int32 token = helper_->InsertToken();
+  helper_->WaitForToken(token);
+}
+
+void GLES2Implementation::BufferData(
+    GLenum target, GLsizeiptr size, const void* data, GLenum usage) {
+  // TODO(gman): Switch to use buckets alwayst or at least if no room in shared
+  //    memory.
+  memcpy(shared_memory_.GetAddress(0), data, size);
+  helper_->BufferData(target, size, shared_memory_.GetId(), 0, usage);
+  int32 token = helper_->InsertToken();
+  helper_->WaitForToken(token);
+}
+
+void GLES2Implementation::BufferSubData(
+    GLenum target, GLintptr offset, GLsizeiptr size, const void* data) {
+  // TODO(gman): Switch to use buckets alwayst or at least if no room in shared
+  //    memory.
+  memcpy(shared_memory_.GetAddress(0), data, size);
+  helper_->BufferSubData(target, offset, size, shared_memory_.GetId(), 0);
+  int32 token = helper_->InsertToken();
+  helper_->WaitForToken(token);
+}
+
+void GLES2Implementation::CompressedTexImage2D(
+    GLenum target, GLint level, GLenum internalformat, GLsizei width,
+    GLsizei height, GLint border, GLsizei imageSize, const void* data) {
+  // TODO(gman): Switch to use buckets alwayst or at least if no room in shared
+  //    memory.
+  memcpy(shared_memory_.GetAddress(0), data, imageSize);
+  helper_->CompressedTexImage2D(
+      target, level, internalformat, width, height, border, imageSize,
+      shared_memory_.GetId(), 0);
+  int32 token = helper_->InsertToken();
+  helper_->WaitForToken(token);
+}
+
+void GLES2Implementation::CompressedTexSubImage2D(
+    GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width,
+    GLsizei height, GLenum format, GLsizei imageSize, const void* data) {
+  // TODO(gman): Switch to use buckets alwayst or at least if no room in shared
+  //    memory.
+  memcpy(shared_memory_.GetAddress(0), data, imageSize);
+  helper_->CompressedTexSubImage2D(
+      target, level, xoffset, yoffset, width, height, format, imageSize,
+      shared_memory_.GetId(), 0);
+  int32 token = helper_->InsertToken();
+  helper_->WaitForToken(token);
+}
+
+void GLES2Implementation::TexImage2D(
+    GLenum target, GLint level, GLint internalformat, GLsizei width,
+    GLsizei height, GLint border, GLenum format, GLenum type,
+    const void* pixels) {
+  // TODO(gman): Switch to use buckets alwayst or at least if no room in shared
+  //    memory.
+  uint32 pixels_size = GLES2Util::ComputeImageDataSize(
+      width, height, format, type, unpack_alignment_);
+  memcpy(shared_memory_.GetAddress(0), pixels, pixels_size);
+  helper_->TexImage2D(
+      target, level, internalformat, width, height, border, format, type,
+      shared_memory_.GetId(), 0);
+  int32 token = helper_->InsertToken();
+  helper_->WaitForToken(token);
+}
+
+void GLES2Implementation::TexSubImage2D(
+    GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width,
+    GLsizei height, GLenum format, GLenum type, const void* pixels) {
+  // TODO(gman): Switch to use buckets alwayst or at least if no room in shared
+  //    memory.
+  uint32 pixels_size = GLES2Util::ComputeImageDataSize(
+      width, height, format, type, unpack_alignment_);
+  memcpy(shared_memory_.GetAddress(0), pixels, pixels_size);
+  helper_->TexSubImage2D(
+      target, level, xoffset, yoffset, width, height, format, type,
+      shared_memory_.GetId(), 0);
+  int32 token = helper_->InsertToken();
+  helper_->WaitForToken(token);
+}
+
+
+}  // namespace gles2
+}  // namespace command_buffer
+
+
diff --git a/gpu/command_buffer/client/gles2_implementation.h b/gpu/command_buffer/client/gles2_implementation.h
new file mode 100644
index 0000000..2df52ca
--- /dev/null
+++ b/gpu/command_buffer/client/gles2_implementation.h
@@ -0,0 +1,93 @@
+// Copyright (c) 2006-2009 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 GPU_COMMAND_BUFFER_CLIENT_GLES2_IMPLEMENTATION_H
+#define GPU_COMMAND_BUFFER_CLIENT_GLES2_IMPLEMENTATION_H
+
+#include "base/shared_memory.h"
+#include "gpu/command_buffer/common/gles2_cmd_utils.h"
+#include "gpu/command_buffer/client/gles2_cmd_helper.h"
+#include "gpu/command_buffer/client/id_allocator.h"
+
+namespace command_buffer {
+namespace gles2 {
+
+// A class to help with shared memory.
+class SharedMemoryHelper {
+ public:
+  SharedMemoryHelper(void* address, int id)
+      : address_(address),
+        id_(id) {
+  }
+
+  unsigned int GetOffset(void* address) const {
+    return static_cast<int8*>(address) -
+           static_cast<int8*>(address_);
+  }
+
+  void* GetAddress(unsigned int offset) const {
+    return static_cast<int8*>(address_) + offset;
+  }
+
+  template <typename T>
+  T GetAddressAs(unsigned int offset) const {
+    return static_cast<T>(GetAddress(offset));
+  }
+
+  unsigned int GetId() const {
+    return id_;
+  }
+
+ private:
+  void* address_;
+  int id_;
+
+  DISALLOW_COPY_AND_ASSIGN(SharedMemoryHelper);
+};
+
+// This class emulates GLES2 over command buffers. It can be used by a client
+// program so that the program does not need deal with shared memory and command
+// buffer management. See gl2_lib.h.  Note that there is a performance gain to
+// be had by changing your code to use command buffers directly by using the
+// GLES2CmdHelper but that entails changing your code to use and deal with
+// shared memory and synchronization issues.
+class GLES2Implementation {
+ public:
+  GLES2Implementation(
+      GLES2CmdHelper* helper,
+      void* transfer_buffer,
+      int transfer_buffer_id);  // TODO: add size.
+
+  // Include the auto-generated part of this class. We split this because
+  // it means we can easily edit the non-auto generated parts right here in
+  // this file instead of having to edit some template or the code generator.
+  #include "gpu/command_buffer/client/gles2_implementation_autogen.h"
+
+ private:
+  // Makes a set of Ids for glGen___ functions.
+  void MakeIds(GLsizei n, GLuint* ids);
+
+  // Frees a set of Ids for glDelete___ functions.
+  void FreeIds(GLsizei n, const GLuint* ids);
+
+  GLES2Util util_;
+  GLES2CmdHelper* helper_;
+  IdAllocator id_allocator_;
+  SharedMemoryHelper shared_memory_;  // TODO(gman): rename transfer_buffer_.
+
+  // pack alignment as last set by glPixelStorei
+  GLint pack_alignment_;
+
+  // unpack alignment as last set by glPixelStorei
+  GLint unpack_alignment_;
+
+  DISALLOW_COPY_AND_ASSIGN(GLES2Implementation);
+};
+
+
+}  // namespace gles2
+}  // namespace command_buffer
+
+#endif  // GPU_COMMAND_BUFFER_CLIENT_GLES2_IMPLEMENTATION_H
+
diff --git a/gpu/command_buffer/client/gles2_implementation_autogen.h b/gpu/command_buffer/client/gles2_implementation_autogen.h
new file mode 100644
index 0000000..940454b
--- /dev/null
+++ b/gpu/command_buffer/client/gles2_implementation_autogen.h
@@ -0,0 +1,684 @@
+// This file is auto-generated. DO NOT EDIT!
+
+// This file is included by gles2_implementation.h to declare the
+// GL api functions.
+void ActiveTexture(GLenum texture) {
+  helper_->ActiveTexture(texture);
+}
+
+void AttachShader(GLuint program, GLuint shader) {
+  helper_->AttachShader(program, shader);
+}
+
+void BindAttribLocation(GLuint program, GLuint index, const char* name) {
+  // TODO(gman): This needs to change to use SendString.
+  helper_->BindAttribLocationImmediate(program, index, name);
+}
+
+void BindBuffer(GLenum target, GLuint buffer) {
+  helper_->BindBuffer(target, buffer);
+}
+
+void BindFramebuffer(GLenum target, GLuint framebuffer) {
+  helper_->BindFramebuffer(target, framebuffer);
+}
+
+void BindRenderbuffer(GLenum target, GLuint renderbuffer) {
+  helper_->BindRenderbuffer(target, renderbuffer);
+}
+
+void BindTexture(GLenum target, GLuint texture) {
+  helper_->BindTexture(target, texture);
+}
+
+void BlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
+  helper_->BlendColor(red, green, blue, alpha);
+}
+
+void BlendEquation(GLenum mode) {
+  helper_->BlendEquation(mode);
+}
+
+void BlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) {
+  helper_->BlendEquationSeparate(modeRGB, modeAlpha);
+}
+
+void BlendFunc(GLenum sfactor, GLenum dfactor) {
+  helper_->BlendFunc(sfactor, dfactor);
+}
+
+void BlendFuncSeparate(
+    GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) {
+  helper_->BlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
+}
+
+void BufferData(
+    GLenum target, GLsizeiptr size, const void* data, GLenum usage);
+
+void BufferSubData(
+    GLenum target, GLintptr offset, GLsizeiptr size, const void* data);
+
+GLenum CheckFramebufferStatus(GLenum target);
+
+void Clear(GLbitfield mask) {
+  helper_->Clear(mask);
+}
+
+void ClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
+  helper_->ClearColor(red, green, blue, alpha);
+}
+
+void ClearDepthf(GLclampf depth) {
+  helper_->ClearDepthf(depth);
+}
+
+void ClearStencil(GLint s) {
+  helper_->ClearStencil(s);
+}
+
+void ColorMask(
+    GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
+  helper_->ColorMask(red, green, blue, alpha);
+}
+
+void CompileShader(GLuint shader) {
+  helper_->CompileShader(shader);
+}
+
+void CompressedTexImage2D(
+    GLenum target, GLint level, GLenum internalformat, GLsizei width,
+    GLsizei height, GLint border, GLsizei imageSize, const void* data);
+
+void CompressedTexSubImage2D(
+    GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width,
+    GLsizei height, GLenum format, GLsizei imageSize, const void* data);
+
+void CopyTexImage2D(
+    GLenum target, GLint level, GLenum internalformat, GLint x, GLint y,
+    GLsizei width, GLsizei height, GLint border) {
+  helper_->CopyTexImage2D(
+      target, level, internalformat, x, y, width, height, border);
+}
+
+void CopyTexSubImage2D(
+    GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y,
+    GLsizei width, GLsizei height) {
+  helper_->CopyTexSubImage2D(
+      target, level, xoffset, yoffset, x, y, width, height);
+}
+
+GLuint CreateProgram() {
+  GLuint client_id;
+  MakeIds(1, &client_id);
+  helper_->CreateProgram(client_id);
+  return client_id;
+}
+
+GLuint CreateShader(GLenum type) {
+  GLuint client_id;
+  MakeIds(1, &client_id);
+  helper_->CreateShader(type, client_id);
+  return client_id;
+}
+
+void CullFace(GLenum mode) {
+  helper_->CullFace(mode);
+}
+
+void DeleteBuffers(GLsizei n, const GLuint* buffers) {
+  FreeIds(n, buffers);
+  helper_->DeleteBuffersImmediate(n, buffers);
+}
+
+void DeleteFramebuffers(GLsizei n, const GLuint* framebuffers) {
+  FreeIds(n, framebuffers);
+  helper_->DeleteFramebuffersImmediate(n, framebuffers);
+}
+
+void DeleteProgram(GLuint program) {
+  helper_->DeleteProgram(program);
+}
+
+void DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers) {
+  FreeIds(n, renderbuffers);
+  helper_->DeleteRenderbuffersImmediate(n, renderbuffers);
+}
+
+void DeleteShader(GLuint shader) {
+  helper_->DeleteShader(shader);
+}
+
+void DeleteTextures(GLsizei n, const GLuint* textures) {
+  FreeIds(n, textures);
+  helper_->DeleteTexturesImmediate(n, textures);
+}
+
+void DepthFunc(GLenum func) {
+  helper_->DepthFunc(func);
+}
+
+void DepthMask(GLboolean flag) {
+  helper_->DepthMask(flag);
+}
+
+void DepthRangef(GLclampf zNear, GLclampf zFar) {
+  helper_->DepthRangef(zNear, zFar);
+}
+
+void DetachShader(GLuint program, GLuint shader) {
+  helper_->DetachShader(program, shader);
+}
+
+void Disable(GLenum cap) {
+  helper_->Disable(cap);
+}
+
+void DisableVertexAttribArray(GLuint index) {
+  helper_->DisableVertexAttribArray(index);
+}
+
+void DrawArrays(GLenum mode, GLint first, GLsizei count) {
+  helper_->DrawArrays(mode, first, count);
+}
+
+void DrawElements(
+    GLenum mode, GLsizei count, GLenum type, const void* indices);
+
+void Enable(GLenum cap) {
+  helper_->Enable(cap);
+}
+
+void EnableVertexAttribArray(GLuint index) {
+  helper_->EnableVertexAttribArray(index);
+}
+
+void Finish() {
+  helper_->Finish();
+}
+
+void Flush() {
+  helper_->Flush();
+}
+
+void FramebufferRenderbuffer(
+    GLenum target, GLenum attachment, GLenum renderbuffertarget,
+    GLuint renderbuffer) {
+  helper_->FramebufferRenderbuffer(
+      target, attachment, renderbuffertarget, renderbuffer);
+}
+
+void FramebufferTexture2D(
+    GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
+    GLint level) {
+  helper_->FramebufferTexture2D(target, attachment, textarget, texture, level);
+}
+
+void FrontFace(GLenum mode) {
+  helper_->FrontFace(mode);
+}
+
+void GenBuffers(GLsizei n, GLuint* buffers) {
+  MakeIds(n, buffers);
+  helper_->GenBuffersImmediate(n, buffers);
+}
+
+void GenerateMipmap(GLenum target) {
+  helper_->GenerateMipmap(target);
+}
+
+void GenFramebuffers(GLsizei n, GLuint* framebuffers) {
+  MakeIds(n, framebuffers);
+  helper_->GenFramebuffersImmediate(n, framebuffers);
+}
+
+void GenRenderbuffers(GLsizei n, GLuint* renderbuffers) {
+  MakeIds(n, renderbuffers);
+  helper_->GenRenderbuffersImmediate(n, renderbuffers);
+}
+
+void GenTextures(GLsizei n, GLuint* textures) {
+  MakeIds(n, textures);
+  helper_->GenTexturesImmediate(n, textures);
+}
+
+void GetActiveAttrib(
+    GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size,
+    GLenum* type, char* name);
+
+void GetActiveUniform(
+    GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size,
+    GLenum* type, char* name);
+
+void GetAttachedShaders(
+    GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders);
+
+int GetAttribLocation(GLuint program, const char* name) {
+  // TODO(gman): This needs to change to use SendString.
+  GLint* result = shared_memory_.GetAddressAs<GLint*>(0);
+  DCHECK(false);  // pass in shared memory
+  helper_->GetAttribLocationImmediate(program, name);
+  int32 token = helper_->InsertToken();
+  helper_->WaitForToken(token);
+  return *result;
+}
+
+void GetBooleanv(GLenum pname, GLboolean* params) {
+  helper_->GetBooleanv(pname, shared_memory_.GetId(), 0);
+  int32 token = helper_->InsertToken();
+  helper_->WaitForToken(token);
+  GLsizei num_values = util_.GLGetNumValuesReturned(pname);
+  memcpy(params, shared_memory_.GetAddress(0),
+         num_values * sizeof(*params));
+}
+
+void GetBufferParameteriv(GLenum target, GLenum pname, GLint* params) {
+  helper_->GetBufferParameteriv(target, pname, shared_memory_.GetId(), 0);
+  int32 token = helper_->InsertToken();
+  helper_->WaitForToken(token);
+  GLsizei num_values = util_.GLGetNumValuesReturned(pname);
+  memcpy(params, shared_memory_.GetAddress(0),
+         num_values * sizeof(*params));
+}
+
+GLenum GetError() {
+  helper_->GetError(shared_memory_.GetId(), 0);
+  int32 token = helper_->InsertToken();
+  helper_->WaitForToken(token);
+  return *shared_memory_.GetAddressAs<GLenum*>(0);
+}
+
+void GetFloatv(GLenum pname, GLfloat* params) {
+  helper_->GetFloatv(pname, shared_memory_.GetId(), 0);
+  int32 token = helper_->InsertToken();
+  helper_->WaitForToken(token);
+  GLsizei num_values = util_.GLGetNumValuesReturned(pname);
+  memcpy(params, shared_memory_.GetAddress(0),
+         num_values * sizeof(*params));
+}
+
+void GetFramebufferAttachmentParameteriv(
+    GLenum target, GLenum attachment, GLenum pname, GLint* params) {
+  helper_->GetFramebufferAttachmentParameteriv(
+      target, attachment, pname, shared_memory_.GetId(), 0);
+  int32 token = helper_->InsertToken();
+  helper_->WaitForToken(token);
+  GLsizei num_values = util_.GLGetNumValuesReturned(pname);
+  memcpy(params, shared_memory_.GetAddress(0),
+         num_values * sizeof(*params));
+}
+
+void GetIntegerv(GLenum pname, GLint* params) {
+  helper_->GetIntegerv(pname, shared_memory_.GetId(), 0);
+  int32 token = helper_->InsertToken();
+  helper_->WaitForToken(token);
+  GLsizei num_values = util_.GLGetNumValuesReturned(pname);
+  memcpy(params, shared_memory_.GetAddress(0),
+         num_values * sizeof(*params));
+}
+
+void GetProgramiv(GLuint program, GLenum pname, GLint* params) {
+  helper_->GetProgramiv(program, pname, shared_memory_.GetId(), 0);
+  int32 token = helper_->InsertToken();
+  helper_->WaitForToken(token);
+  GLsizei num_values = util_.GLGetNumValuesReturned(pname);
+  memcpy(params, shared_memory_.GetAddress(0),
+         num_values * sizeof(*params));
+}
+
+// TODO(gman): Implement this
+void GetProgramInfoLog(
+    GLuint program, GLsizei bufsize, GLsizei* length, char* infolog);
+
+void GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params) {
+  helper_->GetRenderbufferParameteriv(
+      target, pname, shared_memory_.GetId(), 0);
+  int32 token = helper_->InsertToken();
+  helper_->WaitForToken(token);
+  GLsizei num_values = util_.GLGetNumValuesReturned(pname);
+  memcpy(params, shared_memory_.GetAddress(0),
+         num_values * sizeof(*params));
+}
+
+void GetShaderiv(GLuint shader, GLenum pname, GLint* params) {
+  helper_->GetShaderiv(shader, pname, shared_memory_.GetId(), 0);
+  int32 token = helper_->InsertToken();
+  helper_->WaitForToken(token);
+  GLsizei num_values = util_.GLGetNumValuesReturned(pname);
+  memcpy(params, shared_memory_.GetAddress(0),
+         num_values * sizeof(*params));
+}
+
+// TODO(gman): Implement this
+void GetShaderInfoLog(
+    GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog);
+
+void GetShaderPrecisionFormat(
+    GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision);
+
+// TODO(gman): Implement this
+void GetShaderSource(
+    GLuint shader, GLsizei bufsize, GLsizei* length, char* source);
+
+const GLubyte* GetString(GLenum name);
+
+void GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params) {
+  helper_->GetTexParameterfv(target, pname, shared_memory_.GetId(), 0);
+  int32 token = helper_->InsertToken();
+  helper_->WaitForToken(token);
+  GLsizei num_values = util_.GLGetNumValuesReturned(pname);
+  memcpy(params, shared_memory_.GetAddress(0),
+         num_values * sizeof(*params));
+}
+
+void GetTexParameteriv(GLenum target, GLenum pname, GLint* params) {
+  helper_->GetTexParameteriv(target, pname, shared_memory_.GetId(), 0);
+  int32 token = helper_->InsertToken();
+  helper_->WaitForToken(token);
+  GLsizei num_values = util_.GLGetNumValuesReturned(pname);
+  memcpy(params, shared_memory_.GetAddress(0),
+         num_values * sizeof(*params));
+}
+
+void GetUniformfv(GLuint program, GLint location, GLfloat* params);
+
+void GetUniformiv(GLuint program, GLint location, GLint* params);
+
+int GetUniformLocation(GLuint program, const char* name) {
+  // TODO(gman): This needs to change to use SendString.
+  GLint* result = shared_memory_.GetAddressAs<GLint*>(0);
+  DCHECK(false);  // pass in shared memory
+  helper_->GetUniformLocationImmediate(program, name);
+  int32 token = helper_->InsertToken();
+  helper_->WaitForToken(token);
+  return *result;
+}
+
+void GetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params) {
+  helper_->GetVertexAttribfv(index, pname, shared_memory_.GetId(), 0);
+  int32 token = helper_->InsertToken();
+  helper_->WaitForToken(token);
+  GLsizei num_values = util_.GLGetNumValuesReturned(pname);
+  memcpy(params, shared_memory_.GetAddress(0),
+         num_values * sizeof(*params));
+}
+
+void GetVertexAttribiv(GLuint index, GLenum pname, GLint* params) {
+  helper_->GetVertexAttribiv(index, pname, shared_memory_.GetId(), 0);
+  int32 token = helper_->InsertToken();
+  helper_->WaitForToken(token);
+  GLsizei num_values = util_.GLGetNumValuesReturned(pname);
+  memcpy(params, shared_memory_.GetAddress(0),
+         num_values * sizeof(*params));
+}
+
+void GetVertexAttribPointerv(GLuint index, GLenum pname, void** pointer);
+
+void Hint(GLenum target, GLenum mode) {
+  helper_->Hint(target, mode);
+}
+
+GLboolean IsBuffer(GLuint buffer) {
+  helper_->IsBuffer(buffer, shared_memory_.GetId(), 0);
+  int32 token = helper_->InsertToken();
+  helper_->WaitForToken(token);
+  return *shared_memory_.GetAddressAs<GLboolean*>(0);
+}
+
+GLboolean IsEnabled(GLenum cap) {
+  helper_->IsEnabled(cap, shared_memory_.GetId(), 0);
+  int32 token = helper_->InsertToken();
+  helper_->WaitForToken(token);
+  return *shared_memory_.GetAddressAs<GLboolean*>(0);
+}
+
+GLboolean IsFramebuffer(GLuint framebuffer) {
+  helper_->IsFramebuffer(framebuffer, shared_memory_.GetId(), 0);
+  int32 token = helper_->InsertToken();
+  helper_->WaitForToken(token);
+  return *shared_memory_.GetAddressAs<GLboolean*>(0);
+}
+
+GLboolean IsProgram(GLuint program) {
+  helper_->IsProgram(program, shared_memory_.GetId(), 0);
+  int32 token = helper_->InsertToken();
+  helper_->WaitForToken(token);
+  return *shared_memory_.GetAddressAs<GLboolean*>(0);
+}
+
+GLboolean IsRenderbuffer(GLuint renderbuffer) {
+  helper_->IsRenderbuffer(renderbuffer, shared_memory_.GetId(), 0);
+  int32 token = helper_->InsertToken();
+  helper_->WaitForToken(token);
+  return *shared_memory_.GetAddressAs<GLboolean*>(0);
+}
+
+GLboolean IsShader(GLuint shader) {
+  helper_->IsShader(shader, shared_memory_.GetId(), 0);
+  int32 token = helper_->InsertToken();
+  helper_->WaitForToken(token);
+  return *shared_memory_.GetAddressAs<GLboolean*>(0);
+}
+
+GLboolean IsTexture(GLuint texture) {
+  helper_->IsTexture(texture, shared_memory_.GetId(), 0);
+  int32 token = helper_->InsertToken();
+  helper_->WaitForToken(token);
+  return *shared_memory_.GetAddressAs<GLboolean*>(0);
+}
+
+void LineWidth(GLfloat width) {
+  helper_->LineWidth(width);
+}
+
+void LinkProgram(GLuint program) {
+  helper_->LinkProgram(program);
+}
+
+void PixelStorei(GLenum pname, GLint param) {
+  helper_->PixelStorei(pname, param);
+}
+
+void PolygonOffset(GLfloat factor, GLfloat units) {
+  helper_->PolygonOffset(factor, units);
+}
+
+void ReadPixels(
+    GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type,
+    void* pixels);
+
+void RenderbufferStorage(
+    GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
+  helper_->RenderbufferStorage(target, internalformat, width, height);
+}
+
+void SampleCoverage(GLclampf value, GLboolean invert) {
+  helper_->SampleCoverage(value, invert);
+}
+
+void Scissor(GLint x, GLint y, GLsizei width, GLsizei height) {
+  helper_->Scissor(x, y, width, height);
+}
+
+void ShaderSource(
+    GLuint shader, GLsizei count, const char** string, const GLint* length);
+
+void StencilFunc(GLenum func, GLint ref, GLuint mask) {
+  helper_->StencilFunc(func, ref, mask);
+}
+
+void StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask) {
+  helper_->StencilFuncSeparate(face, func, ref, mask);
+}
+
+void StencilMask(GLuint mask) {
+  helper_->StencilMask(mask);
+}
+
+void StencilMaskSeparate(GLenum face, GLuint mask) {
+  helper_->StencilMaskSeparate(face, mask);
+}
+
+void StencilOp(GLenum fail, GLenum zfail, GLenum zpass) {
+  helper_->StencilOp(fail, zfail, zpass);
+}
+
+void StencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass) {
+  helper_->StencilOpSeparate(face, fail, zfail, zpass);
+}
+
+void TexImage2D(
+    GLenum target, GLint level, GLint internalformat, GLsizei width,
+    GLsizei height, GLint border, GLenum format, GLenum type,
+    const void* pixels);
+
+void TexParameterf(GLenum target, GLenum pname, GLfloat param) {
+  helper_->TexParameterf(target, pname, param);
+}
+
+void TexParameterfv(GLenum target, GLenum pname, const GLfloat* params) {
+  helper_->TexParameterfvImmediate(target, pname, params);
+}
+
+void TexParameteri(GLenum target, GLenum pname, GLint param) {
+  helper_->TexParameteri(target, pname, param);
+}
+
+void TexParameteriv(GLenum target, GLenum pname, const GLint* params) {
+  helper_->TexParameterivImmediate(target, pname, params);
+}
+
+void TexSubImage2D(
+    GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width,
+    GLsizei height, GLenum format, GLenum type, const void* pixels);
+
+void Uniform1f(GLint location, GLfloat x) {
+  helper_->Uniform1f(location, x);
+}
+
+void Uniform1fv(GLint location, GLsizei count, const GLfloat* v) {
+  helper_->Uniform1fvImmediate(location, count, v);
+}
+
+void Uniform1i(GLint location, GLint x) {
+  helper_->Uniform1i(location, x);
+}
+
+void Uniform1iv(GLint location, GLsizei count, const GLint* v) {
+  helper_->Uniform1ivImmediate(location, count, v);
+}
+
+void Uniform2f(GLint location, GLfloat x, GLfloat y) {
+  helper_->Uniform2f(location, x, y);
+}
+
+void Uniform2fv(GLint location, GLsizei count, const GLfloat* v) {
+  helper_->Uniform2fvImmediate(location, count, v);
+}
+
+void Uniform2i(GLint location, GLint x, GLint y) {
+  helper_->Uniform2i(location, x, y);
+}
+
+void Uniform2iv(GLint location, GLsizei count, const GLint* v) {
+  helper_->Uniform2ivImmediate(location, count, v);
+}
+
+void Uniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z) {
+  helper_->Uniform3f(location, x, y, z);
+}
+
+void Uniform3fv(GLint location, GLsizei count, const GLfloat* v) {
+  helper_->Uniform3fvImmediate(location, count, v);
+}
+
+void Uniform3i(GLint location, GLint x, GLint y, GLint z) {
+  helper_->Uniform3i(location, x, y, z);
+}
+
+void Uniform3iv(GLint location, GLsizei count, const GLint* v) {
+  helper_->Uniform3ivImmediate(location, count, v);
+}
+
+void Uniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) {
+  helper_->Uniform4f(location, x, y, z, w);
+}
+
+void Uniform4fv(GLint location, GLsizei count, const GLfloat* v) {
+  helper_->Uniform4fvImmediate(location, count, v);
+}
+
+void Uniform4i(GLint location, GLint x, GLint y, GLint z, GLint w) {
+  helper_->Uniform4i(location, x, y, z, w);
+}
+
+void Uniform4iv(GLint location, GLsizei count, const GLint* v) {
+  helper_->Uniform4ivImmediate(location, count, v);
+}
+
+void UniformMatrix2fv(
+    GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
+  helper_->UniformMatrix2fvImmediate(location, count, transpose, value);
+}
+
+void UniformMatrix3fv(
+    GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
+  helper_->UniformMatrix3fvImmediate(location, count, transpose, value);
+}
+
+void UniformMatrix4fv(
+    GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
+  helper_->UniformMatrix4fvImmediate(location, count, transpose, value);
+}
+
+void UseProgram(GLuint program) {
+  helper_->UseProgram(program);
+}
+
+void ValidateProgram(GLuint program) {
+  helper_->ValidateProgram(program);
+}
+
+void VertexAttrib1f(GLuint indx, GLfloat x) {
+  helper_->VertexAttrib1f(indx, x);
+}
+
+void VertexAttrib1fv(GLuint indx, const GLfloat* values) {
+  helper_->VertexAttrib1fvImmediate(indx, values);
+}
+
+void VertexAttrib2f(GLuint indx, GLfloat x, GLfloat y) {
+  helper_->VertexAttrib2f(indx, x, y);
+}
+
+void VertexAttrib2fv(GLuint indx, const GLfloat* values) {
+  helper_->VertexAttrib2fvImmediate(indx, values);
+}
+
+void VertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z) {
+  helper_->VertexAttrib3f(indx, x, y, z);
+}
+
+void VertexAttrib3fv(GLuint indx, const GLfloat* values) {
+  helper_->VertexAttrib3fvImmediate(indx, values);
+}
+
+void VertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w) {
+  helper_->VertexAttrib4f(indx, x, y, z, w);
+}
+
+void VertexAttrib4fv(GLuint indx, const GLfloat* values) {
+  helper_->VertexAttrib4fvImmediate(indx, values);
+}
+
+void VertexAttribPointer(
+    GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride,
+    const void* ptr);
+
+void Viewport(GLint x, GLint y, GLsizei width, GLsizei height) {
+  helper_->Viewport(x, y, width, height);
+}
+
+void SwapBuffers() {
+  helper_->SwapBuffers();
+}
+
diff --git a/gpu/command_buffer/client/gles2_implementation_gen.h b/gpu/command_buffer/client/gles2_implementation_gen.h
new file mode 100644
index 0000000..d385f8f
--- /dev/null
+++ b/gpu/command_buffer/client/gles2_implementation_gen.h
@@ -0,0 +1,72 @@
+
+// Copyright (c) 2006-2008 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.
+
+
+// A class to emluate GLES2 over command buffers.
+
+#include "gpu/command_buffer/client/gles2_implementation.h"
+
+namespace command_buffer {
+namespace gles2 {
+
+GLenum GLES2Implementation::CheckFramebufferStatus(GLenum target) {
+  return 0;
+}
+
+void GLES2Implementation::GetActiveAttrib(
+    GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size,
+    GLenum* type, char* name) {
+}
+
+void GLES2Implementation::GetActiveUniform(
+    GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size,
+    GLenum* type, char* name) {
+}
+
+void GLES2Implementation::GetAttachedShaders(
+    GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders) {
+}
+
+void GLES2Implementation::GetProgramInfoLog(
+    GLuint program, GLsizei bufsize, GLsizei* length, char* infolog) {
+}
+
+void GLES2Implementation::GetShaderInfoLog(
+    GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog) {
+}
+
+void GLES2Implementation::GetShaderPrecisionFormat(
+    GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) {
+}
+
+void GLES2Implementation::GetShaderSource(
+    GLuint shader, GLsizei bufsize, GLsizei* length, char* source) {
+}
+
+const GLubyte* GLES2Implementation::GetString(GLenum name) {
+  return 0;
+}
+
+void GLES2Implementation::GetUniformfv(
+    GLuint program, GLint location, GLfloat* params) {
+}
+
+void GLES2Implementation::GetUniformiv(
+    GLuint program, GLint location, GLint* params) {
+}
+
+void GLES2Implementation::GetVertexAttribPointerv(
+    GLuint index, GLenum pname, void** pointer) {
+}
+
+void GLES2Implementation::ReadPixels(
+    GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type,
+    void* pixels) {
+}
+
+
+}  // namespace gles2
+}  // namespace command_buffer
+
diff --git a/gpu/command_buffer/client/gles2_lib.cc b/gpu/command_buffer/client/gles2_lib.cc
new file mode 100644
index 0000000..681f7ad6
--- /dev/null
+++ b/gpu/command_buffer/client/gles2_lib.cc
@@ -0,0 +1,20 @@
+// Copyright (c) 2006-2009 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 "gpu/command_buffer/client/gles2_lib.h"
+
+namespace gles2 {
+
+::command_buffer::gles2::GLES2Implementation* g_gl_impl;
+
+bool InitGLES2Lib() {
+  // TODO(gman): Encapulate initalizing the GLES2 library for client apps.
+  return false;
+}
+
+}  // namespace gles2
+
+
+
+
diff --git a/gpu/command_buffer/client/gles2_lib.h b/gpu/command_buffer/client/gles2_lib.h
new file mode 100644
index 0000000..589d2050
--- /dev/null
+++ b/gpu/command_buffer/client/gles2_lib.h
@@ -0,0 +1,26 @@
+// Copyright (c) 2006-2009 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.
+
+// These functions emluate GLES2 over command buffers.
+
+#ifndef GPU_COMMAND_BUFFER_CLIENT_GLES2_LIB_H
+#define GPU_COMMAND_BUFFER_CLIENT_GLES2_LIB_H
+
+#include "gpu/command_buffer/client/gles2_implementation.h"
+
+namespace gles2 {
+
+extern ::command_buffer::gles2::GLES2Implementation* g_gl_impl;
+
+inline ::command_buffer::gles2::GLES2Implementation* GetGLContext() {
+  return g_gl_impl;
+}
+
+// Initializes the GLES2 library.
+bool InitGLES2Lib();
+
+}  // namespace gles2
+
+#endif  // GPU_COMMAND_BUFFER_CLIENT_GLES2_LIB_H
+
diff --git a/gpu/command_buffer/client/id_allocator.cc b/gpu/command_buffer/client/id_allocator.cc
new file mode 100644
index 0000000..49104e5
--- /dev/null
+++ b/gpu/command_buffer/client/id_allocator.cc
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains the implementation of IdAllocator.
+
+#include "gpu/command_buffer/client/id_allocator.h"
+
+namespace command_buffer {
+
+IdAllocator::IdAllocator() : bitmap_(1) { bitmap_[0] = 0; }
+
+static const unsigned int kBitsPerUint32 = sizeof(Uint32) * 8;  // NOLINT
+
+// Looks for the first non-full entry, and return the first free bit in that
+// entry. If all the entries are full, it will return the first bit of an entry
+// that would be appended, but doesn't actually append that entry to the vector.
+unsigned int IdAllocator::FindFirstFree() const {
+  size_t size = bitmap_.size();
+  for (unsigned int i = 0; i < size; ++i) {
+    Uint32 value = bitmap_[i];
+    if (value != 0xffffffffU) {
+      for (unsigned int j = 0; j < kBitsPerUint32; ++j) {
+        if (!(value & (1 << j))) return i * kBitsPerUint32 + j;
+      }
+      DLOG(FATAL) << "Code should not reach here.";
+    }
+  }
+  return size*kBitsPerUint32;
+}
+
+// Sets the correct bit in the proper entry, resizing the vector if needed.
+void IdAllocator::SetBit(unsigned int bit, bool value) {
+  size_t size = bitmap_.size();
+  if (bit >= size * kBitsPerUint32) {
+    size_t newsize = bit / kBitsPerUint32 + 1;
+    bitmap_.resize(newsize);
+    for (size_t i = size; i < newsize; ++i) bitmap_[i] = 0;
+  }
+  Uint32 mask = 1U << (bit % kBitsPerUint32);
+  if (value) {
+    bitmap_[bit / kBitsPerUint32] |= mask;
+  } else {
+    bitmap_[bit / kBitsPerUint32] &= ~mask;
+  }
+}
+
+// Gets the bit from the proper entry. This doesn't resize the vector, just
+// returns false if the bit is beyond the last entry.
+bool IdAllocator::GetBit(unsigned int bit) const {
+  size_t size = bitmap_.size();
+  if (bit / kBitsPerUint32 >= size) return false;
+  Uint32 mask = 1U << (bit % kBitsPerUint32);
+  return (bitmap_[bit / kBitsPerUint32] & mask) != 0;
+}
+
+}  // namespace command_buffer
diff --git a/gpu/command_buffer/client/id_allocator.h b/gpu/command_buffer/client/id_allocator.h
new file mode 100644
index 0000000..b2b14b9
--- /dev/null
+++ b/gpu/command_buffer/client/id_allocator.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains the definition of the IdAllocator class.
+
+#ifndef GPU_COMMAND_BUFFER_CLIENT_CROSS_ID_ALLOCATOR_H_
+#define GPU_COMMAND_BUFFER_CLIENT_CROSS_ID_ALLOCATOR_H_
+
+#include <vector>
+#include "base/basictypes.h"
+#include "gpu/command_buffer/common/types.h"
+#include "gpu/command_buffer/common/resource.h"
+
+namespace command_buffer {
+
+// A class to manage the allocation of resource IDs. It uses a bitfield stored
+// into a vector of unsigned ints.
+class IdAllocator {
+ public:
+  IdAllocator();
+
+  // Allocates a new resource ID.
+  command_buffer::ResourceId AllocateID() {
+    unsigned int bit = FindFirstFree();
+    SetBit(bit, true);
+    return bit;
+  }
+
+  // Frees a resource ID.
+  void FreeID(command_buffer::ResourceId id) {
+    SetBit(id, false);
+  }
+
+  // Checks whether or not a resource ID is in use.
+  bool InUse(command_buffer::ResourceId id) {
+    return GetBit(id);
+  }
+ private:
+  void SetBit(unsigned int bit, bool value);
+  bool GetBit(unsigned int bit) const;
+  unsigned int FindFirstFree() const;
+
+  std::vector<Uint32> bitmap_;
+  DISALLOW_COPY_AND_ASSIGN(IdAllocator);
+};
+
+}  // namespace command_buffer
+
+#endif  // GPU_COMMAND_BUFFER_CLIENT_CROSS_ID_ALLOCATOR_H_
diff --git a/gpu/command_buffer/client/id_allocator_test.cc b/gpu/command_buffer/client/id_allocator_test.cc
new file mode 100644
index 0000000..bb8d5f9b
--- /dev/null
+++ b/gpu/command_buffer/client/id_allocator_test.cc
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file has the unit tests for the IdAllocator class.
+
+#include "gpu/command_buffer/client/id_allocator.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace command_buffer {
+
+using command_buffer::ResourceId;
+
+class IdAllocatorTest : public testing::Test {
+ protected:
+  virtual void SetUp() {}
+  virtual void TearDown() {}
+
+  IdAllocator* id_allocator() { return &id_allocator_; }
+
+ private:
+  IdAllocator id_allocator_;
+};
+
+// Checks basic functionality: AllocateID, FreeID, InUse.
+TEST_F(IdAllocatorTest, TestBasic) {
+  IdAllocator *allocator = id_allocator();
+  // Check that resource 0 is not in use
+  EXPECT_FALSE(allocator->InUse(0));
+
+  // Allocate an ID, check that it's in use.
+  ResourceId id1 = allocator->AllocateID();
+  EXPECT_TRUE(allocator->InUse(id1));
+
+  // Allocate another ID, check that it's in use, and different from the first
+  // one.
+  ResourceId id2 = allocator->AllocateID();
+  EXPECT_TRUE(allocator->InUse(id2));
+  EXPECT_NE(id1, id2);
+
+  // Free one of the IDs, check that it's not in use any more.
+  allocator->FreeID(id1);
+  EXPECT_FALSE(allocator->InUse(id1));
+
+  // Frees the other ID, check that it's not in use any more.
+  allocator->FreeID(id2);
+  EXPECT_FALSE(allocator->InUse(id2));
+}
+
+// Checks that the resource IDs are allocated conservatively, and re-used after
+// being freed.
+TEST_F(IdAllocatorTest, TestAdvanced) {
+  IdAllocator *allocator = id_allocator();
+
+  // Allocate a significant number of resources.
+  const unsigned int kNumResources = 100;
+  ResourceId ids[kNumResources];
+  for (unsigned int i = 0; i < kNumResources; ++i) {
+    ids[i] = allocator->AllocateID();
+    EXPECT_TRUE(allocator->InUse(ids[i]));
+  }
+
+  // Check that the allocation is conservative with resource IDs, that is that
+  // the resource IDs don't go over kNumResources - so that the service doesn't
+  // have to allocate too many internal structures when the resources are used.
+  for (unsigned int i = 0; i < kNumResources; ++i) {
+    EXPECT_GT(kNumResources, ids[i]);
+  }
+
+  // Check that the next resources are still free.
+  for (unsigned int i = 0; i < kNumResources; ++i) {
+    EXPECT_FALSE(allocator->InUse(kNumResources + i));
+  }
+
+  // Check that a new allocation re-uses the resource we just freed.
+  ResourceId id1 = ids[kNumResources / 2];
+  allocator->FreeID(id1);
+  EXPECT_FALSE(allocator->InUse(id1));
+  ResourceId id2 = allocator->AllocateID();
+  EXPECT_TRUE(allocator->InUse(id2));
+  EXPECT_EQ(id1, id2);
+}
+
+}  // namespace command_buffer
diff --git a/gpu/command_buffer/common/GLES2/gl2.h b/gpu/command_buffer/common/GLES2/gl2.h
new file mode 100644
index 0000000..6293ee4
--- /dev/null
+++ b/gpu/command_buffer/common/GLES2/gl2.h
@@ -0,0 +1,319 @@
+#ifndef __gl2_h_
+#define __gl2_h_
+
+/* $Revision: 8784 $ on $Date:: 2009-09-02 09:49:17 -0700 #$ */
+
+/*
+ * This document is licensed under the SGI Free Software B License Version
+ * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
+ */
+
+#include <GLES2/gl2types.h>
+
+#ifdef __cplusplus
+#include "gpu/command_buffer/client/gles2_lib.h"
+#define GLES2_GET_FUN(name) gles2::GetGLContext()->name
+#else
+#define GLES2_GET_FUN(name) GLES2 ## name
+#endif
+
+/*-------------------------------------------------------------------------
+ * GL core functions.
+ *-----------------------------------------------------------------------*/
+#undef GL_APICALL
+#define GL_APICALL
+#undef GL_APIENTRY
+#define GL_APIENTRY
+
+#define glActiveTexture GLES2_GET_FUN(ActiveTexture)
+#define glAttachShader GLES2_GET_FUN(AttachShader)
+#define glBindAttribLocation GLES2_GET_FUN(BindAttribLocation)
+#define glBindBuffer GLES2_GET_FUN(BindBuffer)
+#define glBindFramebuffer GLES2_GET_FUN(BindFramebuffer)
+#define glBindRenderbuffer GLES2_GET_FUN(BindRenderbuffer)
+#define glBindTexture GLES2_GET_FUN(BindTexture)
+#define glBlendColor GLES2_GET_FUN(BlendColor)
+#define glBlendEquation GLES2_GET_FUN(BlendEquation)
+#define glBlendEquationSeparate GLES2_GET_FUN(BlendEquationSeparate)
+#define glBlendFunc GLES2_GET_FUN(BlendFunc)
+#define glBlendFuncSeparate GLES2_GET_FUN(BlendFuncSeparate)
+#define glBufferData GLES2_GET_FUN(BufferData)
+#define glBufferSubData GLES2_GET_FUN(BufferSubData)
+#define glCheckFramebufferStatus GLES2_GET_FUN(CheckFramebufferStatus)
+#define glClear GLES2_GET_FUN(Clear)
+#define glClearColor GLES2_GET_FUN(ClearColor)
+#define glClearDepthf GLES2_GET_FUN(ClearDepthf)
+#define glClearStencil GLES2_GET_FUN(ClearStencil)
+#define glColorMask GLES2_GET_FUN(ColorMask)
+#define glCompileShader GLES2_GET_FUN(CompileShader)
+#define glCompressedTexImage2D GLES2_GET_FUN(CompressedTexImage2D)
+#define glCompressedTexSubImage2D GLES2_GET_FUN(CompressedTexSubImage2D)
+#define glCopyTexImage2D GLES2_GET_FUN(CopyTexImage2D)
+#define glCopyTexSubImage2D GLES2_GET_FUN(CopyTexSubImage2D)
+#define glCreateProgram GLES2_GET_FUN(CreateProgram)
+#define glCreateShader GLES2_GET_FUN(CreateShader)
+#define glCullFace GLES2_GET_FUN(CullFace)
+#define glDeleteBuffers GLES2_GET_FUN(DeleteBuffers)
+#define glDeleteFramebuffers GLES2_GET_FUN(DeleteFramebuffers)
+#define glDeleteProgram GLES2_GET_FUN(DeleteProgram)
+#define glDeleteRenderbuffers GLES2_GET_FUN(DeleteRenderbuffers)
+#define glDeleteShader GLES2_GET_FUN(DeleteShader)
+#define glDeleteTextures GLES2_GET_FUN(DeleteTextures)
+#define glDepthFunc GLES2_GET_FUN(DepthFunc)
+#define glDepthMask GLES2_GET_FUN(DepthMask)
+#define glDepthRangef GLES2_GET_FUN(DepthRangef)
+#define glDetachShader GLES2_GET_FUN(DetachShader)
+#define glDisable GLES2_GET_FUN(Disable)
+#define glDisableVertexAttribArray GLES2_GET_FUN(DisableVertexAttribArray)
+#define glDrawArrays GLES2_GET_FUN(DrawArrays)
+#define glDrawElements GLES2_GET_FUN(DrawElements)
+#define glEnable GLES2_GET_FUN(Enable)
+#define glEnableVertexAttribArray GLES2_GET_FUN(EnableVertexAttribArray)
+#define glFinish GLES2_GET_FUN(Finish)
+#define glFlush GLES2_GET_FUN(Flush)
+#define glFramebufferRenderbuffer GLES2_GET_FUN(FramebufferRenderbuffer)
+#define glFramebufferTexture2D GLES2_GET_FUN(FramebufferTexture2D)
+#define glFrontFace GLES2_GET_FUN(FrontFace)
+#define glGenBuffers GLES2_GET_FUN(GenBuffers)
+#define glGenerateMipmap GLES2_GET_FUN(GenerateMipmap)
+#define glGenFramebuffers GLES2_GET_FUN(GenFramebuffers)
+#define glGenRenderbuffers GLES2_GET_FUN(GenRenderbuffers)
+#define glGenTextures GLES2_GET_FUN(GenTextures)
+#define glGetActiveAttrib GLES2_GET_FUN(GetActiveAttrib)
+#define glGetActiveUniform GLES2_GET_FUN(GetActiveUniform)
+#define glGetAttachedShaders GLES2_GET_FUN(GetAttachedShaders)
+#define glGetAttribLocation GLES2_GET_FUN(GetAttribLocation)
+#define glGetBooleanv GLES2_GET_FUN(GetBooleanv)
+#define glGetBufferParameteriv GLES2_GET_FUN(GetBufferParameteriv)
+#define glGetError GLES2_GET_FUN(GetError)
+#define glGetFloatv GLES2_GET_FUN(GetFloatv)
+#define glGetFramebufferAttachmentParameteriv GLES2_GET_FUN(GetFramebufferAttachmentParameteriv)
+#define glGetIntegerv GLES2_GET_FUN(GetIntegerv)
+#define glGetProgramiv GLES2_GET_FUN(GetProgramiv)
+#define glGetProgramInfoLog GLES2_GET_FUN(GetProgramInfoLog)
+#define glGetRenderbufferParameteriv GLES2_GET_FUN(GetRenderbufferParameteriv)
+#define glGetShaderiv GLES2_GET_FUN(GetShaderiv)
+#define glGetShaderInfoLog GLES2_GET_FUN(GetShaderInfoLog)
+#define glGetShaderPrecisionFormat GLES2_GET_FUN(GetShaderPrecisionFormat)
+#define glGetShaderSource GLES2_GET_FUN(GetShaderSource)
+#define glGetString GLES2_GET_FUN(GetString)
+#define glGetTexParameterfv GLES2_GET_FUN(GetTexParameterfv)
+#define glGetTexParameteriv GLES2_GET_FUN(GetTexParameteriv)
+#define glGetUniformfv GLES2_GET_FUN(GetUniformfv)
+#define glGetUniformiv GLES2_GET_FUN(GetUniformiv)
+#define glGetUniformLocation GLES2_GET_FUN(GetUniformLocation)
+#define glGetVertexAttribfv GLES2_GET_FUN(GetVertexAttribfv)
+#define glGetVertexAttribiv GLES2_GET_FUN(GetVertexAttribiv)
+#define glGetVertexAttribPointerv GLES2_GET_FUN(GetVertexAttribPointerv)
+#define glHint GLES2_GET_FUN(Hint)
+#define glIsBuffer GLES2_GET_FUN(IsBuffer)
+#define glIsEnabled GLES2_GET_FUN(IsEnabled)
+#define glIsFramebuffer GLES2_GET_FUN(IsFramebuffer)
+#define glIsProgram GLES2_GET_FUN(IsProgram)
+#define glIsRenderbuffer GLES2_GET_FUN(IsRenderbuffer)
+#define glIsShader GLES2_GET_FUN(IsShader)
+#define glIsTexture GLES2_GET_FUN(IsTexture)
+#define glLineWidth GLES2_GET_FUN(LineWidth)
+#define glLinkProgram GLES2_GET_FUN(LinkProgram)
+#define glPixelStorei GLES2_GET_FUN(PixelStorei)
+#define glPolygonOffset GLES2_GET_FUN(PolygonOffset)
+#define glReadPixels GLES2_GET_FUN(ReadPixels)
+#define glReleaseShaderCompiler GLES2_GET_FUN(ReleaseShaderCompiler)
+#define glRenderbufferStorage GLES2_GET_FUN(RenderbufferStorage)
+#define glSampleCoverage GLES2_GET_FUN(SampleCoverage)
+#define glScissor GLES2_GET_FUN(Scissor)
+#define glShaderBinary GLES2_GET_FUN(ShaderBinary)
+#define glShaderSource GLES2_GET_FUN(ShaderSource)
+#define glStencilFunc GLES2_GET_FUN(StencilFunc)
+#define glStencilFuncSeparate GLES2_GET_FUN(StencilFuncSeparate)
+#define glStencilMask GLES2_GET_FUN(StencilMask)
+#define glStencilMaskSeparate GLES2_GET_FUN(StencilMaskSeparate)
+#define glStencilOp GLES2_GET_FUN(StencilOp)
+#define glStencilOpSeparate GLES2_GET_FUN(StencilOpSeparate)
+#define glTexImage2D GLES2_GET_FUN(TexImage2D)
+#define glTexParameterf GLES2_GET_FUN(TexParameterf)
+#define glTexParameterfv GLES2_GET_FUN(TexParameterfv)
+#define glTexParameteri GLES2_GET_FUN(TexParameteri)
+#define glTexParameteriv GLES2_GET_FUN(TexParameteriv)
+#define glTexSubImage2D GLES2_GET_FUN(TexSubImage2D)
+#define glUniform1f GLES2_GET_FUN(Uniform1f)
+#define glUniform1fv GLES2_GET_FUN(Uniform1fv)
+#define glUniform1i GLES2_GET_FUN(Uniform1i)
+#define glUniform1iv GLES2_GET_FUN(Uniform1iv)
+#define glUniform2f GLES2_GET_FUN(Uniform2f)
+#define glUniform2fv GLES2_GET_FUN(Uniform2fv)
+#define glUniform2i GLES2_GET_FUN(Uniform2i)
+#define glUniform2iv GLES2_GET_FUN(Uniform2iv)
+#define glUniform3f GLES2_GET_FUN(Uniform3f)
+#define glUniform3fv GLES2_GET_FUN(Uniform3fv)
+#define glUniform3i GLES2_GET_FUN(Uniform3i)
+#define glUniform3iv GLES2_GET_FUN(Uniform3iv)
+#define glUniform4f GLES2_GET_FUN(Uniform4f)
+#define glUniform4fv GLES2_GET_FUN(Uniform4fv)
+#define glUniform4i GLES2_GET_FUN(Uniform4i)
+#define glUniform4iv GLES2_GET_FUN(Uniform4iv)
+#define glUniformMatrix2fv GLES2_GET_FUN(UniformMatrix2fv)
+#define glUniformMatrix3fv GLES2_GET_FUN(UniformMatrix3fv)
+#define glUniformMatrix4fv GLES2_GET_FUN(UniformMatrix4fv)
+#define glUseProgram GLES2_GET_FUN(UseProgram)
+#define glValidateProgram GLES2_GET_FUN(ValidateProgram)
+#define glVertexAttrib1f GLES2_GET_FUN(VertexAttrib1f)
+#define glVertexAttrib1fv GLES2_GET_FUN(VertexAttrib1fv)
+#define glVertexAttrib2f GLES2_GET_FUN(VertexAttrib2f)
+#define glVertexAttrib2fv GLES2_GET_FUN(VertexAttrib2fv)
+#define glVertexAttrib3f GLES2_GET_FUN(VertexAttrib3f)
+#define glVertexAttrib3fv GLES2_GET_FUN(VertexAttrib3fv)
+#define glVertexAttrib4f GLES2_GET_FUN(VertexAttrib4f)
+#define glVertexAttrib4fv GLES2_GET_FUN(VertexAttrib4fv)
+#define glVertexAttribPointer GLES2_GET_FUN(VertexAttribPointer)
+#define glViewport GLES2_GET_FUN(Viewport)
+
+#ifndef __cplusplus
+
+GL_APICALL void         GL_APIENTRY glActiveTexture (GLenum texture);
+GL_APICALL void         GL_APIENTRY glAttachShader (GLuint program, GLuint shader);
+GL_APICALL void         GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const char* name);
+GL_APICALL void         GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer);
+GL_APICALL void         GL_APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer);
+GL_APICALL void         GL_APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer);
+GL_APICALL void         GL_APIENTRY glBindTexture (GLenum target, GLuint texture);
+GL_APICALL void         GL_APIENTRY glBlendColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+GL_APICALL void         GL_APIENTRY glBlendEquation ( GLenum mode );
+GL_APICALL void         GL_APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha);
+GL_APICALL void         GL_APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor);
+GL_APICALL void         GL_APIENTRY glBlendFuncSeparate (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+GL_APICALL void         GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const void* data, GLenum usage);
+GL_APICALL void         GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void* data);
+GL_APICALL GLenum       GL_APIENTRY glCheckFramebufferStatus (GLenum target);
+GL_APICALL void         GL_APIENTRY glClear (GLbitfield mask);
+GL_APICALL void         GL_APIENTRY glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+GL_APICALL void         GL_APIENTRY glClearDepthf (GLclampf depth);
+GL_APICALL void         GL_APIENTRY glClearStencil (GLint s);
+GL_APICALL void         GL_APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+GL_APICALL void         GL_APIENTRY glCompileShader (GLuint shader);
+GL_APICALL void         GL_APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data);
+GL_APICALL void         GL_APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data);
+GL_APICALL void         GL_APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+GL_APICALL void         GL_APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL GLuint       GL_APIENTRY glCreateProgram (void);
+GL_APICALL GLuint       GL_APIENTRY glCreateShader (GLenum type);
+GL_APICALL void         GL_APIENTRY glCullFace (GLenum mode);
+GL_APICALL void         GL_APIENTRY glDeleteBuffers (GLsizei n, const GLuint* buffers);
+GL_APICALL void         GL_APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint* framebuffers);
+GL_APICALL void         GL_APIENTRY glDeleteProgram (GLuint program);
+GL_APICALL void         GL_APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint* renderbuffers);
+GL_APICALL void         GL_APIENTRY glDeleteShader (GLuint shader);
+GL_APICALL void         GL_APIENTRY glDeleteTextures (GLsizei n, const GLuint* textures);
+GL_APICALL void         GL_APIENTRY glDepthFunc (GLenum func);
+GL_APICALL void         GL_APIENTRY glDepthMask (GLboolean flag);
+GL_APICALL void         GL_APIENTRY glDepthRangef (GLclampf zNear, GLclampf zFar);
+GL_APICALL void         GL_APIENTRY glDetachShader (GLuint program, GLuint shader);
+GL_APICALL void         GL_APIENTRY glDisable (GLenum cap);
+GL_APICALL void         GL_APIENTRY glDisableVertexAttribArray (GLuint index);
+GL_APICALL void         GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count);
+GL_APICALL void         GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const void* indices);
+GL_APICALL void         GL_APIENTRY glEnable (GLenum cap);
+GL_APICALL void         GL_APIENTRY glEnableVertexAttribArray (GLuint index);
+GL_APICALL void         GL_APIENTRY glFinish (void);
+GL_APICALL void         GL_APIENTRY glFlush (void);
+GL_APICALL void         GL_APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+GL_APICALL void         GL_APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GL_APICALL void         GL_APIENTRY glFrontFace (GLenum mode);
+GL_APICALL void         GL_APIENTRY glGenBuffers (GLsizei n, GLuint* buffers);
+GL_APICALL void         GL_APIENTRY glGenerateMipmap (GLenum target);
+GL_APICALL void         GL_APIENTRY glGenFramebuffers (GLsizei n, GLuint* framebuffers);
+GL_APICALL void         GL_APIENTRY glGenRenderbuffers (GLsizei n, GLuint* renderbuffers);
+GL_APICALL void         GL_APIENTRY glGenTextures (GLsizei n, GLuint* textures);
+GL_APICALL void         GL_APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name);
+GL_APICALL void         GL_APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name);
+GL_APICALL void         GL_APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders);
+GL_APICALL int          GL_APIENTRY glGetAttribLocation (GLuint program, const char* name);
+GL_APICALL void         GL_APIENTRY glGetBooleanv (GLenum pname, GLboolean* params);
+GL_APICALL void         GL_APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint* params);
+GL_APICALL GLenum       GL_APIENTRY glGetError (void);
+GL_APICALL void         GL_APIENTRY glGetFloatv (GLenum pname, GLfloat* params);
+GL_APICALL void         GL_APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetIntegerv (GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufsize, GLsizei* length, char* infolog);
+GL_APICALL void         GL_APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog);
+GL_APICALL void         GL_APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision);
+GL_APICALL void         GL_APIENTRY glGetShaderSource (GLuint shader, GLsizei bufsize, GLsizei* length, char* source);
+GL_APICALL const GLubyte* GL_APIENTRY glGetString (GLenum name);
+GL_APICALL void         GL_APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat* params);
+GL_APICALL void         GL_APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat* params);
+GL_APICALL void         GL_APIENTRY glGetUniformiv (GLuint program, GLint location, GLint* params);
+GL_APICALL int          GL_APIENTRY glGetUniformLocation (GLuint program, const char* name);
+GL_APICALL void         GL_APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat* params);
+GL_APICALL void         GL_APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, void** pointer);
+GL_APICALL void         GL_APIENTRY glHint (GLenum target, GLenum mode);
+GL_APICALL GLboolean    GL_APIENTRY glIsBuffer (GLuint buffer);
+GL_APICALL GLboolean    GL_APIENTRY glIsEnabled (GLenum cap);
+GL_APICALL GLboolean    GL_APIENTRY glIsFramebuffer (GLuint framebuffer);
+GL_APICALL GLboolean    GL_APIENTRY glIsProgram (GLuint program);
+GL_APICALL GLboolean    GL_APIENTRY glIsRenderbuffer (GLuint renderbuffer);
+GL_APICALL GLboolean    GL_APIENTRY glIsShader (GLuint shader);
+GL_APICALL GLboolean    GL_APIENTRY glIsTexture (GLuint texture);
+GL_APICALL void         GL_APIENTRY glLineWidth (GLfloat width);
+GL_APICALL void         GL_APIENTRY glLinkProgram (GLuint program);
+GL_APICALL void         GL_APIENTRY glPixelStorei (GLenum pname, GLint param);
+GL_APICALL void         GL_APIENTRY glPolygonOffset (GLfloat factor, GLfloat units);
+GL_APICALL void         GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels);
+GL_APICALL void         GL_APIENTRY glReleaseShaderCompiler (void);
+GL_APICALL void         GL_APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void         GL_APIENTRY glSampleCoverage (GLclampf value, GLboolean invert);
+GL_APICALL void         GL_APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void         GL_APIENTRY glShaderBinary (GLsizei n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLsizei length);
+GL_APICALL void         GL_APIENTRY glShaderSource (GLuint shader, GLsizei count, const char** string, const GLint* length);
+GL_APICALL void         GL_APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask);
+GL_APICALL void         GL_APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask);
+GL_APICALL void         GL_APIENTRY glStencilMask (GLuint mask);
+GL_APICALL void         GL_APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask);
+GL_APICALL void         GL_APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass);
+GL_APICALL void         GL_APIENTRY glStencilOpSeparate (GLenum face, GLenum fail, GLenum zfail, GLenum zpass);
+GL_APICALL void         GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels);
+GL_APICALL void         GL_APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param);
+GL_APICALL void         GL_APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat* params);
+GL_APICALL void         GL_APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param);
+GL_APICALL void         GL_APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint* params);
+GL_APICALL void         GL_APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels);
+GL_APICALL void         GL_APIENTRY glUniform1f (GLint location, GLfloat x);
+GL_APICALL void         GL_APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void         GL_APIENTRY glUniform1i (GLint location, GLint x);
+GL_APICALL void         GL_APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void         GL_APIENTRY glUniform2f (GLint location, GLfloat x, GLfloat y);
+GL_APICALL void         GL_APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void         GL_APIENTRY glUniform2i (GLint location, GLint x, GLint y);
+GL_APICALL void         GL_APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void         GL_APIENTRY glUniform3f (GLint location, GLfloat x, GLfloat y, GLfloat z);
+GL_APICALL void         GL_APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void         GL_APIENTRY glUniform3i (GLint location, GLint x, GLint y, GLint z);
+GL_APICALL void         GL_APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void         GL_APIENTRY glUniform4f (GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GL_APICALL void         GL_APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void         GL_APIENTRY glUniform4i (GLint location, GLint x, GLint y, GLint z, GLint w);
+GL_APICALL void         GL_APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void         GL_APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void         GL_APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void         GL_APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void         GL_APIENTRY glUseProgram (GLuint program);
+GL_APICALL void         GL_APIENTRY glValidateProgram (GLuint program);
+GL_APICALL void         GL_APIENTRY glVertexAttrib1f (GLuint indx, GLfloat x);
+GL_APICALL void         GL_APIENTRY glVertexAttrib1fv (GLuint indx, const GLfloat* values);
+GL_APICALL void         GL_APIENTRY glVertexAttrib2f (GLuint indx, GLfloat x, GLfloat y);
+GL_APICALL void         GL_APIENTRY glVertexAttrib2fv (GLuint indx, const GLfloat* values);
+GL_APICALL void         GL_APIENTRY glVertexAttrib3f (GLuint indx, GLfloat x, GLfloat y, GLfloat z);
+GL_APICALL void         GL_APIENTRY glVertexAttrib3fv (GLuint indx, const GLfloat* values);
+GL_APICALL void         GL_APIENTRY glVertexAttrib4f (GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GL_APICALL void         GL_APIENTRY glVertexAttrib4fv (GLuint indx, const GLfloat* values);
+GL_APICALL void         GL_APIENTRY glVertexAttribPointer (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr);
+GL_APICALL void         GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);
+
+#endif  // __cplusplus
+
+#endif /* __gl2_h_ */
+
diff --git a/gpu/command_buffer/common/GLES2/gl2platform.h b/gpu/command_buffer/common/GLES2/gl2platform.h
new file mode 100644
index 0000000..3e9036c1
--- /dev/null
+++ b/gpu/command_buffer/common/GLES2/gl2platform.h
@@ -0,0 +1,29 @@
+#ifndef __gl2platform_h_
+#define __gl2platform_h_
+
+/* $Revision: 7173 $ on $Date:: 2009-01-09 11:18:21 -0800 #$ */
+
+/*
+ * This document is licensed under the SGI Free Software B License Version
+ * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
+ */
+
+/* Platform-specific types and definitions for OpenGL ES 2.X  gl2.h
+ * Last modified on 2008/12/19
+ *
+ * Adopters may modify khrplatform.h and this file to suit their platform.
+ * You are encouraged to submit all modifications to the Khronos group so that
+ * they can be included in future versions of this file.  Please submit changes
+ * by sending them to the public Khronos Bugzilla (http://khronos.org/bugzilla)
+ * by filing a bug against product "OpenGL-ES" component "Registry".
+ */
+
+#include <KHR/khrplatform.h>
+
+#ifndef GL_APICALL
+#define GL_APICALL  KHRONOS_APICALL
+#endif
+
+#define GL_APIENTRY KHRONOS_APIENTRY
+
+#endif /* __gl2platform_h_ */
diff --git a/gpu/command_buffer/common/GLES2/gl2types.h b/gpu/command_buffer/common/GLES2/gl2types.h
new file mode 100644
index 0000000..85046d1
--- /dev/null
+++ b/gpu/command_buffer/common/GLES2/gl2types.h
@@ -0,0 +1,464 @@
+#ifndef __gl2types_h_
+#define __gl2types_h_
+
+#include <GLES2/gl2platform.h>
+
+/*
+ * This document is licensed under the SGI Free Software B License Version
+ * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
+ */
+
+/*-------------------------------------------------------------------------
+ * Data type definitions
+ *-----------------------------------------------------------------------*/
+
+typedef void             GLvoid;
+typedef unsigned int     GLenum;
+typedef unsigned char    GLboolean;
+typedef unsigned int     GLbitfield;
+typedef khronos_int8_t   GLbyte;
+typedef short            GLshort;
+typedef int              GLint;
+typedef int              GLsizei;
+typedef khronos_uint8_t  GLubyte;
+typedef unsigned short   GLushort;
+typedef unsigned int     GLuint;
+typedef khronos_float_t  GLfloat;
+typedef khronos_float_t  GLclampf;
+typedef khronos_int32_t  GLfixed;
+
+/* GL types for handling large vertex buffer objects */
+typedef khronos_intptr_t GLintptr;
+typedef khronos_ssize_t  GLsizeiptr;
+
+/* OpenGL ES core versions */
+#define GL_ES_VERSION_2_0                 1
+
+/* ClearBufferMask */
+#define GL_DEPTH_BUFFER_BIT               0x00000100
+#define GL_STENCIL_BUFFER_BIT             0x00000400
+#define GL_COLOR_BUFFER_BIT               0x00004000
+
+/* Boolean */
+#define GL_FALSE                          0
+#define GL_TRUE                           1
+
+/* BeginMode */
+#define GL_POINTS                         0x0000
+#define GL_LINES                          0x0001
+#define GL_LINE_LOOP                      0x0002
+#define GL_LINE_STRIP                     0x0003
+#define GL_TRIANGLES                      0x0004
+#define GL_TRIANGLE_STRIP                 0x0005
+#define GL_TRIANGLE_FAN                   0x0006
+
+/* AlphaFunction (not supported in ES20) */
+/*      GL_NEVER */
+/*      GL_LESS */
+/*      GL_EQUAL */
+/*      GL_LEQUAL */
+/*      GL_GREATER */
+/*      GL_NOTEQUAL */
+/*      GL_GEQUAL */
+/*      GL_ALWAYS */
+
+/* BlendingFactorDest */
+#define GL_ZERO                           0
+#define GL_ONE                            1
+#define GL_SRC_COLOR                      0x0300
+#define GL_ONE_MINUS_SRC_COLOR            0x0301
+#define GL_SRC_ALPHA                      0x0302
+#define GL_ONE_MINUS_SRC_ALPHA            0x0303
+#define GL_DST_ALPHA                      0x0304
+#define GL_ONE_MINUS_DST_ALPHA            0x0305
+
+/* BlendingFactorSrc */
+/*      GL_ZERO */
+/*      GL_ONE */
+#define GL_DST_COLOR                      0x0306
+#define GL_ONE_MINUS_DST_COLOR            0x0307
+#define GL_SRC_ALPHA_SATURATE             0x0308
+/*      GL_SRC_ALPHA */
+/*      GL_ONE_MINUS_SRC_ALPHA */
+/*      GL_DST_ALPHA */
+/*      GL_ONE_MINUS_DST_ALPHA */
+
+/* BlendEquationSeparate */
+#define GL_FUNC_ADD                       0x8006
+#define GL_BLEND_EQUATION                 0x8009
+#define GL_BLEND_EQUATION_RGB             0x8009    /* same as BLEND_EQUATION */
+#define GL_BLEND_EQUATION_ALPHA           0x883D
+
+/* BlendSubtract */
+#define GL_FUNC_SUBTRACT                  0x800A
+#define GL_FUNC_REVERSE_SUBTRACT          0x800B
+
+/* Separate Blend Functions */
+#define GL_BLEND_DST_RGB                  0x80C8
+#define GL_BLEND_SRC_RGB                  0x80C9
+#define GL_BLEND_DST_ALPHA                0x80CA
+#define GL_BLEND_SRC_ALPHA                0x80CB
+#define GL_CONSTANT_COLOR                 0x8001
+#define GL_ONE_MINUS_CONSTANT_COLOR       0x8002
+#define GL_CONSTANT_ALPHA                 0x8003
+#define GL_ONE_MINUS_CONSTANT_ALPHA       0x8004
+#define GL_BLEND_COLOR                    0x8005
+
+/* Buffer Objects */
+#define GL_ARRAY_BUFFER                   0x8892
+#define GL_ELEMENT_ARRAY_BUFFER           0x8893
+#define GL_ARRAY_BUFFER_BINDING           0x8894
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING   0x8895
+
+#define GL_STREAM_DRAW                    0x88E0
+#define GL_STATIC_DRAW                    0x88E4
+#define GL_DYNAMIC_DRAW                   0x88E8
+
+#define GL_BUFFER_SIZE                    0x8764
+#define GL_BUFFER_USAGE                   0x8765
+
+#define GL_CURRENT_VERTEX_ATTRIB          0x8626
+
+/* CullFaceMode */
+#define GL_FRONT                          0x0404
+#define GL_BACK                           0x0405
+#define GL_FRONT_AND_BACK                 0x0408
+
+/* DepthFunction */
+/*      GL_NEVER */
+/*      GL_LESS */
+/*      GL_EQUAL */
+/*      GL_LEQUAL */
+/*      GL_GREATER */
+/*      GL_NOTEQUAL */
+/*      GL_GEQUAL */
+/*      GL_ALWAYS */
+
+/* EnableCap */
+#define GL_TEXTURE_2D                     0x0DE1
+#define GL_CULL_FACE                      0x0B44
+#define GL_BLEND                          0x0BE2
+#define GL_DITHER                         0x0BD0
+#define GL_STENCIL_TEST                   0x0B90
+#define GL_DEPTH_TEST                     0x0B71
+#define GL_SCISSOR_TEST                   0x0C11
+#define GL_POLYGON_OFFSET_FILL            0x8037
+#define GL_SAMPLE_ALPHA_TO_COVERAGE       0x809E
+#define GL_SAMPLE_COVERAGE                0x80A0
+
+/* ErrorCode */
+#define GL_NO_ERROR                       0
+#define GL_INVALID_ENUM                   0x0500
+#define GL_INVALID_VALUE                  0x0501
+#define GL_INVALID_OPERATION              0x0502
+#define GL_OUT_OF_MEMORY                  0x0505
+
+/* FrontFaceDirection */
+#define GL_CW                             0x0900
+#define GL_CCW                            0x0901
+
+/* GetPName */
+#define GL_LINE_WIDTH                     0x0B21
+#define GL_ALIASED_POINT_SIZE_RANGE       0x846D
+#define GL_ALIASED_LINE_WIDTH_RANGE       0x846E
+#define GL_CULL_FACE_MODE                 0x0B45
+#define GL_FRONT_FACE                     0x0B46
+#define GL_DEPTH_RANGE                    0x0B70
+#define GL_DEPTH_WRITEMASK                0x0B72
+#define GL_DEPTH_CLEAR_VALUE              0x0B73
+#define GL_DEPTH_FUNC                     0x0B74
+#define GL_STENCIL_CLEAR_VALUE            0x0B91
+#define GL_STENCIL_FUNC                   0x0B92
+#define GL_STENCIL_FAIL                   0x0B94
+#define GL_STENCIL_PASS_DEPTH_FAIL        0x0B95
+#define GL_STENCIL_PASS_DEPTH_PASS        0x0B96
+#define GL_STENCIL_REF                    0x0B97
+#define GL_STENCIL_VALUE_MASK             0x0B93
+#define GL_STENCIL_WRITEMASK              0x0B98
+#define GL_STENCIL_BACK_FUNC              0x8800
+#define GL_STENCIL_BACK_FAIL              0x8801
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL   0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS   0x8803
+#define GL_STENCIL_BACK_REF               0x8CA3
+#define GL_STENCIL_BACK_VALUE_MASK        0x8CA4
+#define GL_STENCIL_BACK_WRITEMASK         0x8CA5
+#define GL_VIEWPORT                       0x0BA2
+#define GL_SCISSOR_BOX                    0x0C10
+/*      GL_SCISSOR_TEST */
+#define GL_COLOR_CLEAR_VALUE              0x0C22
+#define GL_COLOR_WRITEMASK                0x0C23
+#define GL_UNPACK_ALIGNMENT               0x0CF5
+#define GL_PACK_ALIGNMENT                 0x0D05
+#define GL_MAX_TEXTURE_SIZE               0x0D33
+#define GL_MAX_VIEWPORT_DIMS              0x0D3A
+#define GL_SUBPIXEL_BITS                  0x0D50
+#define GL_RED_BITS                       0x0D52
+#define GL_GREEN_BITS                     0x0D53
+#define GL_BLUE_BITS                      0x0D54
+#define GL_ALPHA_BITS                     0x0D55
+#define GL_DEPTH_BITS                     0x0D56
+#define GL_STENCIL_BITS                   0x0D57
+#define GL_POLYGON_OFFSET_UNITS           0x2A00
+/*      GL_POLYGON_OFFSET_FILL */
+#define GL_POLYGON_OFFSET_FACTOR          0x8038
+#define GL_TEXTURE_BINDING_2D             0x8069
+#define GL_SAMPLE_BUFFERS                 0x80A8
+#define GL_SAMPLES                        0x80A9
+#define GL_SAMPLE_COVERAGE_VALUE          0x80AA
+#define GL_SAMPLE_COVERAGE_INVERT         0x80AB
+
+/* GetTextureParameter */
+/*      GL_TEXTURE_MAG_FILTER */
+/*      GL_TEXTURE_MIN_FILTER */
+/*      GL_TEXTURE_WRAP_S */
+/*      GL_TEXTURE_WRAP_T */
+
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
+#define GL_COMPRESSED_TEXTURE_FORMATS     0x86A3
+
+/* HintMode */
+#define GL_DONT_CARE                      0x1100
+#define GL_FASTEST                        0x1101
+#define GL_NICEST                         0x1102
+
+/* HintTarget */
+#define GL_GENERATE_MIPMAP_HINT            0x8192
+
+/* DataType */
+#define GL_BYTE                           0x1400
+#define GL_UNSIGNED_BYTE                  0x1401
+#define GL_SHORT                          0x1402
+#define GL_UNSIGNED_SHORT                 0x1403
+#define GL_INT                            0x1404
+#define GL_UNSIGNED_INT                   0x1405
+#define GL_FLOAT                          0x1406
+#define GL_FIXED                          0x140C
+
+/* PixelFormat */
+#define GL_DEPTH_COMPONENT                0x1902
+#define GL_ALPHA                          0x1906
+#define GL_RGB                            0x1907
+#define GL_RGBA                           0x1908
+#define GL_LUMINANCE                      0x1909
+#define GL_LUMINANCE_ALPHA                0x190A
+
+/* PixelType */
+/*      GL_UNSIGNED_BYTE */
+#define GL_UNSIGNED_SHORT_4_4_4_4         0x8033
+#define GL_UNSIGNED_SHORT_5_5_5_1         0x8034
+#define GL_UNSIGNED_SHORT_5_6_5           0x8363
+
+/* Shaders */
+#define GL_FRAGMENT_SHADER                  0x8B30
+#define GL_VERTEX_SHADER                    0x8B31
+#define GL_MAX_VERTEX_ATTRIBS               0x8869
+#define GL_MAX_VERTEX_UNIFORM_VECTORS       0x8DFB
+#define GL_MAX_VARYING_VECTORS              0x8DFC
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS   0x8B4C
+#define GL_MAX_TEXTURE_IMAGE_UNITS          0x8872
+#define GL_MAX_FRAGMENT_UNIFORM_VECTORS     0x8DFD
+#define GL_SHADER_TYPE                      0x8B4F
+#define GL_DELETE_STATUS                    0x8B80
+#define GL_LINK_STATUS                      0x8B82
+#define GL_VALIDATE_STATUS                  0x8B83
+#define GL_ATTACHED_SHADERS                 0x8B85
+#define GL_ACTIVE_UNIFORMS                  0x8B86
+#define GL_ACTIVE_UNIFORM_MAX_LENGTH        0x8B87
+#define GL_ACTIVE_ATTRIBUTES                0x8B89
+#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH      0x8B8A
+#define GL_SHADING_LANGUAGE_VERSION         0x8B8C
+#define GL_CURRENT_PROGRAM                  0x8B8D
+
+/* StencilFunction */
+#define GL_NEVER                          0x0200
+#define GL_LESS                           0x0201
+#define GL_EQUAL                          0x0202
+#define GL_LEQUAL                         0x0203
+#define GL_GREATER                        0x0204
+#define GL_NOTEQUAL                       0x0205
+#define GL_GEQUAL                         0x0206
+#define GL_ALWAYS                         0x0207
+
+/* StencilOp */
+/*      GL_ZERO */
+#define GL_KEEP                           0x1E00
+#define GL_REPLACE                        0x1E01
+#define GL_INCR                           0x1E02
+#define GL_DECR                           0x1E03
+#define GL_INVERT                         0x150A
+#define GL_INCR_WRAP                      0x8507
+#define GL_DECR_WRAP                      0x8508
+
+/* StringName */
+#define GL_VENDOR                         0x1F00
+#define GL_RENDERER                       0x1F01
+#define GL_VERSION                        0x1F02
+#define GL_EXTENSIONS                     0x1F03
+
+/* TextureMagFilter */
+#define GL_NEAREST                        0x2600
+#define GL_LINEAR                         0x2601
+
+/* TextureMinFilter */
+/*      GL_NEAREST */
+/*      GL_LINEAR */
+#define GL_NEAREST_MIPMAP_NEAREST         0x2700
+#define GL_LINEAR_MIPMAP_NEAREST          0x2701
+#define GL_NEAREST_MIPMAP_LINEAR          0x2702
+#define GL_LINEAR_MIPMAP_LINEAR           0x2703
+
+/* TextureParameterName */
+#define GL_TEXTURE_MAG_FILTER             0x2800
+#define GL_TEXTURE_MIN_FILTER             0x2801
+#define GL_TEXTURE_WRAP_S                 0x2802
+#define GL_TEXTURE_WRAP_T                 0x2803
+
+/* TextureTarget */
+/*      GL_TEXTURE_2D */
+#define GL_TEXTURE                        0x1702
+
+#define GL_TEXTURE_CUBE_MAP               0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP       0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X    0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X    0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y    0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y    0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z    0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z    0x851A
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE      0x851C
+
+/* TextureUnit */
+#define GL_TEXTURE0                       0x84C0
+#define GL_TEXTURE1                       0x84C1
+#define GL_TEXTURE2                       0x84C2
+#define GL_TEXTURE3                       0x84C3
+#define GL_TEXTURE4                       0x84C4
+#define GL_TEXTURE5                       0x84C5
+#define GL_TEXTURE6                       0x84C6
+#define GL_TEXTURE7                       0x84C7
+#define GL_TEXTURE8                       0x84C8
+#define GL_TEXTURE9                       0x84C9
+#define GL_TEXTURE10                      0x84CA
+#define GL_TEXTURE11                      0x84CB
+#define GL_TEXTURE12                      0x84CC
+#define GL_TEXTURE13                      0x84CD
+#define GL_TEXTURE14                      0x84CE
+#define GL_TEXTURE15                      0x84CF
+#define GL_TEXTURE16                      0x84D0
+#define GL_TEXTURE17                      0x84D1
+#define GL_TEXTURE18                      0x84D2
+#define GL_TEXTURE19                      0x84D3
+#define GL_TEXTURE20                      0x84D4
+#define GL_TEXTURE21                      0x84D5
+#define GL_TEXTURE22                      0x84D6
+#define GL_TEXTURE23                      0x84D7
+#define GL_TEXTURE24                      0x84D8
+#define GL_TEXTURE25                      0x84D9
+#define GL_TEXTURE26                      0x84DA
+#define GL_TEXTURE27                      0x84DB
+#define GL_TEXTURE28                      0x84DC
+#define GL_TEXTURE29                      0x84DD
+#define GL_TEXTURE30                      0x84DE
+#define GL_TEXTURE31                      0x84DF
+#define GL_ACTIVE_TEXTURE                 0x84E0
+
+/* TextureWrapMode */
+#define GL_REPEAT                         0x2901
+#define GL_CLAMP_TO_EDGE                  0x812F
+#define GL_MIRRORED_REPEAT                0x8370
+
+/* Uniform Types */
+#define GL_FLOAT_VEC2                     0x8B50
+#define GL_FLOAT_VEC3                     0x8B51
+#define GL_FLOAT_VEC4                     0x8B52
+#define GL_INT_VEC2                       0x8B53
+#define GL_INT_VEC3                       0x8B54
+#define GL_INT_VEC4                       0x8B55
+#define GL_BOOL                           0x8B56
+#define GL_BOOL_VEC2                      0x8B57
+#define GL_BOOL_VEC3                      0x8B58
+#define GL_BOOL_VEC4                      0x8B59
+#define GL_FLOAT_MAT2                     0x8B5A
+#define GL_FLOAT_MAT3                     0x8B5B
+#define GL_FLOAT_MAT4                     0x8B5C
+#define GL_SAMPLER_2D                     0x8B5E
+#define GL_SAMPLER_CUBE                   0x8B60
+
+/* Vertex Arrays */
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED        0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE           0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE         0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE           0x8625
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED     0x886A
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER        0x8645
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
+
+/* Read Format */
+#define GL_IMPLEMENTATION_COLOR_READ_TYPE   0x8B9A
+#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B
+
+/* Shader Source */
+#define GL_COMPILE_STATUS                 0x8B81
+#define GL_INFO_LOG_LENGTH                0x8B84
+#define GL_SHADER_SOURCE_LENGTH           0x8B88
+#define GL_SHADER_COMPILER                0x8DFA
+
+/* Shader Binary */
+#define GL_SHADER_BINARY_FORMATS          0x8DF8
+#define GL_NUM_SHADER_BINARY_FORMATS      0x8DF9
+
+/* Shader Precision-Specified Types */
+#define GL_LOW_FLOAT                      0x8DF0
+#define GL_MEDIUM_FLOAT                   0x8DF1
+#define GL_HIGH_FLOAT                     0x8DF2
+#define GL_LOW_INT                        0x8DF3
+#define GL_MEDIUM_INT                     0x8DF4
+#define GL_HIGH_INT                       0x8DF5
+
+/* Framebuffer Object. */
+#define GL_FRAMEBUFFER                    0x8D40
+#define GL_RENDERBUFFER                   0x8D41
+
+#define GL_RGBA4                          0x8056
+#define GL_RGB5_A1                        0x8057
+#define GL_RGB565                         0x8D62
+#define GL_DEPTH_COMPONENT16              0x81A5
+#define GL_STENCIL_INDEX                  0x1901
+#define GL_STENCIL_INDEX8                 0x8D48
+
+#define GL_RENDERBUFFER_WIDTH             0x8D42
+#define GL_RENDERBUFFER_HEIGHT            0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT   0x8D44
+#define GL_RENDERBUFFER_RED_SIZE          0x8D50
+#define GL_RENDERBUFFER_GREEN_SIZE        0x8D51
+#define GL_RENDERBUFFER_BLUE_SIZE         0x8D52
+#define GL_RENDERBUFFER_ALPHA_SIZE        0x8D53
+#define GL_RENDERBUFFER_DEPTH_SIZE        0x8D54
+#define GL_RENDERBUFFER_STENCIL_SIZE      0x8D55
+
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE           0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME           0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL         0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
+
+#define GL_COLOR_ATTACHMENT0              0x8CE0
+#define GL_DEPTH_ATTACHMENT               0x8D00
+#define GL_STENCIL_ATTACHMENT             0x8D20
+
+#define GL_NONE                           0
+
+#define GL_FRAMEBUFFER_COMPLETE                      0x8CD5
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT         0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS         0x8CD9
+#define GL_FRAMEBUFFER_UNSUPPORTED                   0x8CDD
+
+#define GL_FRAMEBUFFER_BINDING            0x8CA6
+#define GL_RENDERBUFFER_BINDING           0x8CA7
+#define GL_MAX_RENDERBUFFER_SIZE          0x84E8
+
+#define GL_INVALID_FRAMEBUFFER_OPERATION  0x0506
+
+#endif  // __gl2types_h_
+
diff --git a/gpu/command_buffer/common/KHR/khrplatform.h b/gpu/command_buffer/common/KHR/khrplatform.h
new file mode 100644
index 0000000..8341f71b
--- /dev/null
+++ b/gpu/command_buffer/common/KHR/khrplatform.h
@@ -0,0 +1,269 @@
+#ifndef __khrplatform_h_
+#define __khrplatform_h_
+
+/*
+** Copyright (c) 2008-2009 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+/* Khronos platform-specific types and definitions.
+ *
+ * $Revision: 7820 $ on $Date: 2009-04-03 13:46:26 -0700 (Fri, 03 Apr 2009) $
+ *
+ * Adopters may modify this file to suit their platform. Adopters are
+ * encouraged to submit platform specific modifications to the Khronos
+ * group so that they can be included in future versions of this file.
+ * Please submit changes by sending them to the public Khronos Bugzilla
+ * (http://khronos.org/bugzilla) by filing a bug against product
+ * "Khronos (general)" component "Registry".
+ *
+ * A predefined template which fills in some of the bug fields can be
+ * reached using http://tinyurl.com/khrplatform-h-bugreport, but you
+ * must create a Bugzilla login first.
+ *
+ *
+ * See the Implementer's Guidelines for information about where this file
+ * should be located on your system and for more details of its use:
+ *    http://www.khronos.org/registry/implementers_guide.pdf
+ *
+ * This file should be included as
+ *        #include <KHR/khrplatform.h>
+ * by Khronos client API header files that use its types and defines.
+ *
+ * The types in khrplatform.h should only be used to define API-specific types.
+ *
+ * Types defined in khrplatform.h:
+ *    khronos_int8_t              signed   8  bit
+ *    khronos_uint8_t             unsigned 8  bit
+ *    khronos_int16_t             signed   16 bit
+ *    khronos_uint16_t            unsigned 16 bit
+ *    khronos_int32_t             signed   32 bit
+ *    khronos_uint32_t            unsigned 32 bit
+ *    khronos_int64_t             signed   64 bit
+ *    khronos_uint64_t            unsigned 64 bit
+ *    khronos_intptr_t            signed   same number of bits as a pointer
+ *    khronos_uintptr_t           unsigned same number of bits as a pointer
+ *    khronos_ssize_t             signed   size
+ *    khronos_usize_t             unsigned size
+ *    khronos_float_t             signed   32 bit floating point
+ *    khronos_time_ns_t           unsigned 64 bit time in nanoseconds
+ *    khronos_utime_nanoseconds_t unsigned time interval or absolute time in
+ *                                         nanoseconds
+ *    khronos_stime_nanoseconds_t signed time interval in nanoseconds
+ *    khronos_boolean_enum_t      enumerated boolean type. This should
+ *      only be used as a base type when a client API's boolean type is
+ *      an enum. Client APIs which use an integer or other type for
+ *      booleans cannot use this as the base type for their boolean.
+ *
+ * Tokens defined in khrplatform.h:
+ *
+ *    KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values.
+ *
+ *    KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0.
+ *    KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0.
+ *
+ * Calling convention macros defined in this file:
+ *    KHRONOS_APICALL
+ *    KHRONOS_APIENTRY
+ *    KHRONOS_APIATTRIBUTES
+ *
+ * These may be used in function prototypes as:
+ *
+ *      KHRONOS_APICALL void KHRONOS_APIENTRY funcname(
+ *                                  int arg1,
+ *                                  int arg2) KHRONOS_APIATTRIBUTES;
+ */
+
+/*-------------------------------------------------------------------------
+ * Definition of KHRONOS_APICALL
+ *-------------------------------------------------------------------------
+ * This precedes the return type of the function in the function prototype.
+ */
+#if defined(_WIN32) && !defined(__SCITECH_SNAP__)
+#   define KHRONOS_APICALL __declspec(dllimport)
+#elif defined (__SYMBIAN32__)
+#   define KHRONOS_APICALL IMPORT_C
+#else
+#   define KHRONOS_APICALL
+#endif
+
+/*-------------------------------------------------------------------------
+ * Definition of KHRONOS_APIENTRY
+ *-------------------------------------------------------------------------
+ * This follows the return type of the function  and precedes the function
+ * name in the function prototype.
+ */
+#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__)
+    /* Win32 but not WinCE */
+#   define KHRONOS_APIENTRY __stdcall
+#else
+#   define KHRONOS_APIENTRY
+#endif
+
+/*-------------------------------------------------------------------------
+ * Definition of KHRONOS_APIATTRIBUTES
+ *-------------------------------------------------------------------------
+ * This follows the closing parenthesis of the function prototype arguments.
+ */
+#if defined (__ARMCC_2__)
+#define KHRONOS_APIATTRIBUTES __softfp
+#else
+#define KHRONOS_APIATTRIBUTES
+#endif
+
+/*-------------------------------------------------------------------------
+ * basic type definitions
+ *-----------------------------------------------------------------------*/
+#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__)
+
+
+/*
+ * Using <stdint.h>
+ */
+#include <stdint.h>
+typedef int32_t                 khronos_int32_t;
+typedef uint32_t                khronos_uint32_t;
+typedef int64_t                 khronos_int64_t;
+typedef uint64_t                khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64   1
+#define KHRONOS_SUPPORT_FLOAT   1
+
+#elif defined(__VMS ) || defined(__sgi)
+
+/*
+ * Using <inttypes.h>
+ */
+#include <inttypes.h>
+typedef int32_t                 khronos_int32_t;
+typedef uint32_t                khronos_uint32_t;
+typedef int64_t                 khronos_int64_t;
+typedef uint64_t                khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64   1
+#define KHRONOS_SUPPORT_FLOAT   1
+
+#elif defined(_WIN32) && !defined(__SCITECH_SNAP__)
+
+/*
+ * Win32
+ */
+typedef __int32                 khronos_int32_t;
+typedef unsigned __int32        khronos_uint32_t;
+typedef __int64                 khronos_int64_t;
+typedef unsigned __int64        khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64   1
+#define KHRONOS_SUPPORT_FLOAT   1
+
+#elif defined(__sun__) || defined(__digital__)
+
+/*
+ * Sun or Digital
+ */
+typedef int                     khronos_int32_t;
+typedef unsigned int            khronos_uint32_t;
+#if defined(__arch64__) || defined(_LP64)
+typedef long int                khronos_int64_t;
+typedef unsigned long int       khronos_uint64_t;
+#else
+typedef long long int           khronos_int64_t;
+typedef unsigned long long int  khronos_uint64_t;
+#endif /* __arch64__ */
+#define KHRONOS_SUPPORT_INT64   1
+#define KHRONOS_SUPPORT_FLOAT   1
+
+#elif 0
+
+/*
+ * Hypothetical platform with no float or int64 support
+ */
+typedef int                     khronos_int32_t;
+typedef unsigned int            khronos_uint32_t;
+#define KHRONOS_SUPPORT_INT64   0
+#define KHRONOS_SUPPORT_FLOAT   0
+
+#else
+
+/*
+ * Generic fallback
+ */
+#include <stdint.h>
+typedef int32_t                 khronos_int32_t;
+typedef uint32_t                khronos_uint32_t;
+typedef int64_t                 khronos_int64_t;
+typedef uint64_t                khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64   1
+#define KHRONOS_SUPPORT_FLOAT   1
+
+#endif
+
+
+/*
+ * Types that are (so far) the same on all platforms
+ */
+typedef signed   char          khronos_int8_t;
+typedef unsigned char          khronos_uint8_t;
+typedef signed   short int     khronos_int16_t;
+typedef unsigned short int     khronos_uint16_t;
+typedef signed   long  int     khronos_intptr_t;
+typedef unsigned long  int     khronos_uintptr_t;
+typedef signed   long  int     khronos_ssize_t;
+typedef unsigned long  int     khronos_usize_t;
+
+#if KHRONOS_SUPPORT_FLOAT
+/*
+ * Float type
+ */
+typedef          float         khronos_float_t;
+#endif
+
+#if KHRONOS_SUPPORT_INT64
+/* Time types
+ *
+ * These types can be used to represent a time interval in nanoseconds or
+ * an absolute Unadjusted System Time.  Unadjusted System Time is the number
+ * of nanoseconds since some arbitrary system event (e.g. since the last
+ * time the system booted).  The Unadjusted System Time is an unsigned
+ * 64 bit value that wraps back to 0 every 584 years.  Time intervals
+ * may be either signed or unsigned.
+ */
+typedef khronos_uint64_t       khronos_utime_nanoseconds_t;
+typedef khronos_int64_t        khronos_stime_nanoseconds_t;
+#endif
+
+/*
+ * Dummy value used to pad enum types to 32 bits.
+ */
+#ifndef KHRONOS_MAX_ENUM
+#define KHRONOS_MAX_ENUM 0x7FFFFFFF
+#endif
+
+/*
+ * Enumerated boolean type
+ *
+ * Values other than zero should be considered to be true.  Therefore
+ * comparisons should not be made against KHRONOS_TRUE.
+ */
+typedef enum {
+    KHRONOS_FALSE = 0,
+    KHRONOS_TRUE  = 1,
+    KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM
+} khronos_boolean_enum_t;
+
+#endif /* __khrplatform_h_ */
diff --git a/gpu/command_buffer/common/bitfield_helpers.h b/gpu/command_buffer/common/bitfield_helpers.h
new file mode 100644
index 0000000..b74374da
--- /dev/null
+++ b/gpu/command_buffer/common/bitfield_helpers.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains a helper template class used to access bit fields in
+// unsigned int_ts.
+
+#ifndef GPU_COMMAND_BUFFER_COMMON_CROSS_BITFIELD_HELPERS_H_
+#define GPU_COMMAND_BUFFER_COMMON_CROSS_BITFIELD_HELPERS_H_
+
+namespace command_buffer {
+
+// Bitfield template class, used to access bit fields in unsigned int_ts.
+template<int shift, int length> class BitField {
+ public:
+  static const unsigned int kShift = shift;
+  static const unsigned int kLength = length;
+  // the following is really (1<<length)-1 but also work for length == 32
+  // without compiler warning.
+  static const unsigned int kMask = 1U + ((1U << (length-1)) - 1U) * 2U;
+
+  // Gets the value contained in this field.
+  static unsigned int Get(unsigned int container) {
+    return (container >> kShift) & kMask;
+  }
+
+  // Makes a value that can be or-ed into this field.
+  static unsigned int MakeValue(unsigned int value) {
+    return (value & kMask) << kShift;
+  }
+
+  // Changes the value of this field.
+  static void Set(unsigned int *container, unsigned int field_value) {
+    *container = (*container & ~(kMask << kShift)) | MakeValue(field_value);
+  }
+};
+
+}  // namespace command_buffer
+
+#endif  // GPU_COMMAND_BUFFER_COMMON_CROSS_BITFIELD_HELPERS_H_
diff --git a/gpu/command_buffer/common/bitfield_helpers_test.cc b/gpu/command_buffer/common/bitfield_helpers_test.cc
new file mode 100644
index 0000000..779b540
--- /dev/null
+++ b/gpu/command_buffer/common/bitfield_helpers_test.cc
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// Tests for the bitfield helper class.
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "gpu/command_buffer/common/bitfield_helpers.h"
+
+namespace command_buffer {
+
+// Tests that BitField<>::Get returns the right bits.
+TEST(BitFieldTest, TestGet) {
+  unsigned int value = 0x12345678u;
+  EXPECT_EQ(0x8u, (BitField<0, 4>::Get(value)));
+  EXPECT_EQ(0x45u, (BitField<12, 8>::Get(value)));
+  EXPECT_EQ(0x12345678u, (BitField<0, 32>::Get(value)));
+}
+
+// Tests that BitField<>::MakeValue generates the right bits.
+TEST(BitFieldTest, TestMakeValue) {
+  EXPECT_EQ(0x00000003u, (BitField<0, 4>::MakeValue(0x3)));
+  EXPECT_EQ(0x00023000u, (BitField<12, 8>::MakeValue(0x123)));
+  EXPECT_EQ(0x87654321u, (BitField<0, 32>::MakeValue(0x87654321)));
+}
+
+// Tests that BitField<>::Set modifies the right bits.
+TEST(BitFieldTest, TestSet) {
+  unsigned int value = 0x12345678u;
+  BitField<0, 4>::Set(&value, 0x9);
+  EXPECT_EQ(0x12345679u, value);
+  BitField<12, 8>::Set(&value, 0x123);
+  EXPECT_EQ(0x12323679u, value);
+  BitField<0, 32>::Set(&value, 0x87654321);
+  EXPECT_EQ(0x87654321u, value);
+}
+
+}  // namespace command_buffer
diff --git a/gpu/command_buffer/common/cmd_buffer_common.cc b/gpu/command_buffer/common/cmd_buffer_common.cc
new file mode 100644
index 0000000..e9172eb
--- /dev/null
+++ b/gpu/command_buffer/common/cmd_buffer_common.cc
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains the binary format definition of the command buffer and
+// command buffer commands.
+
+#include "gpu/command_buffer/common/cmd_buffer_common.h"
+
+namespace command_buffer {
+namespace cmd {
+
+const char* GetCommandName(CommandId command_id) {
+  static const char* const names[] = {
+  #define COMMON_COMMAND_BUFFER_CMD_OP(name) # name,
+
+  COMMON_COMMAND_BUFFER_CMDS(COMMON_COMMAND_BUFFER_CMD_OP)
+
+  #undef COMMON_COMMAND_BUFFER_CMD_OP
+  };
+
+  int id = static_cast<int>(command_id);
+  return (id >= 0 && id < kNumCommands) ? names[id] : "*unknown-command*";
+}
+
+}  // namespace cmd
+}  // namespace command_buffer
+
+
diff --git a/gpu/command_buffer/common/cmd_buffer_common.h b/gpu/command_buffer/common/cmd_buffer_common.h
new file mode 100644
index 0000000..b17b135
--- /dev/null
+++ b/gpu/command_buffer/common/cmd_buffer_common.h
@@ -0,0 +1,269 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains the common parts of command buffer formats.
+
+#ifndef GPU_COMMAND_BUFFER_COMMON_CROSS_CMD_BUFFER_COMMON_H_
+#define GPU_COMMAND_BUFFER_COMMON_CROSS_CMD_BUFFER_COMMON_H_
+
+#include "base/basictypes.h"
+#include "gpu/command_buffer/common/types.h"
+#include "gpu/command_buffer/common/bitfield_helpers.h"
+#include "gpu/command_buffer/common/logging.h"
+
+namespace command_buffer {
+
+namespace cmd {
+  enum ArgFlags {
+    kFixed = 0x0,
+    kAtLeastN = 0x1,
+  };
+}  // namespace cmd
+
+// Computes the number of command buffer entries needed for a certain size. In
+// other words it rounds up to a multiple of entries.
+inline uint32 ComputeNumEntries(size_t size_in_bytes) {
+  return static_cast<uint32>(
+      (size_in_bytes + sizeof(uint32) - 1) / sizeof(uint32));  // NOLINT
+}
+
+// Rounds up to a multiple of entries in bytes.
+inline size_t RoundSizeToMultipleOfEntries(size_t size_in_bytes) {
+  return ComputeNumEntries(size_in_bytes) * sizeof(uint32);  // NOLINT
+}
+
+// Struct that defines the command header in the command buffer.
+struct CommandHeader {
+  Uint32 size:8;
+  Uint32 command:24;
+
+  void Init(uint32 _command, uint32 _size) {
+    DCHECK_LT(_size, 256u);
+    command = _command;
+    size = _size;
+  }
+
+  // Sets the header based on the passed in command. Can not be used for
+  // variable sized commands like immediate commands or Noop.
+  template <typename T>
+  void SetCmd() {
+    COMPILE_ASSERT(T::kArgFlags == cmd::kFixed, Cmd_kArgFlags_not_kFixed);
+    Init(T::kCmdId, ComputeNumEntries(sizeof(T)));  // NOLINT
+  }
+
+  // Sets the header by a size in bytes of the immediate data after the command.
+  template <typename T>
+  void SetCmdBySize(uint32 size_of_data_in_bytes) {
+    COMPILE_ASSERT(T::kArgFlags == cmd::kAtLeastN, Cmd_kArgFlags_not_kAtLeastN);
+    Init(T::kCmdId,
+         ComputeNumEntries(sizeof(T) + size_of_data_in_bytes));  // NOLINT
+  }
+
+  // Sets the header by a size in bytes.
+  template <typename T>
+  void SetCmdByTotalSize(uint32 size_in_bytes) {
+    COMPILE_ASSERT(T::kArgFlags == cmd::kAtLeastN, Cmd_kArgFlags_not_kAtLeastN);
+    DCHECK_GE(size_in_bytes, sizeof(T));  // NOLINT
+    Init(T::kCmdId, ComputeNumEntries(size_in_bytes));
+  }
+};
+
+COMPILE_ASSERT(sizeof(CommandHeader) == 4, Sizeof_CommandHeader_is_not_4);
+
+// Union that defines possible command buffer entries.
+union CommandBufferEntry {
+  CommandHeader value_header;
+  Uint32 value_uint32;
+  Int32 value_int32;
+  float value_float;
+};
+
+COMPILE_ASSERT(sizeof(CommandBufferEntry) == 4,
+               Sizeof_CommandBufferEntry_is_not_4);
+
+
+// Make sure the compiler does not add extra padding to any of the command
+// structures.
+#pragma pack(push, 1)
+
+// Gets the address of memory just after a structure in a typesafe way. This is
+// used for IMMEDIATE commands to get the address of the place to put the data.
+// Immediate command put their data direclty in the command buffer.
+// Parameters:
+//   cmd: Address of command.
+template <typename T>
+void* ImmediateDataAddress(T* cmd) {
+  COMPILE_ASSERT(T::kArgFlags == cmd::kAtLeastN, Cmd_kArgFlags_not_kAtLeastN);
+  return reinterpret_cast<char*>(cmd) + sizeof(*cmd);
+}
+
+// Gets the address of the place to put the next command in a typesafe way.
+// This can only be used for fixed sized commands.
+template <typename T>
+// Parameters:
+//   cmd: Address of command.
+void* NextCmdAddress(void* cmd) {
+  COMPILE_ASSERT(T::kArgFlags == cmd::kFixed, Cmd_kArgFlags_not_kFixed);
+  return reinterpret_cast<char*>(cmd) + sizeof(T);
+}
+
+// Gets the address of the place to put the next command in a typesafe way.
+// This can only be used for variable sized command like IMMEDIATE commands.
+// Parameters:
+//   cmd: Address of command.
+//   size_of_data_in_bytes: Size of the data for the command.
+template <typename T>
+void* NextImmediateCmdAddress(void* cmd, uint32 size_of_data_in_bytes) {
+  COMPILE_ASSERT(T::kArgFlags == cmd::kAtLeastN, Cmd_kArgFlags_not_kAtLeastN);
+  return reinterpret_cast<char*>(cmd) + sizeof(T) +   // NOLINT
+      RoundSizeToMultipleOfEntries(size_of_data_in_bytes);
+}
+
+// Gets the address of the place to put the next command in a typesafe way.
+// This can only be used for variable sized command like IMMEDIATE commands.
+// Parameters:
+//   cmd: Address of command.
+//   size_of_cmd_in_bytes: Size of the cmd and data.
+template <typename T>
+void* NextImmediateCmdAddressTotalSize(void* cmd, uint32 total_size_in_bytes) {
+  COMPILE_ASSERT(T::kArgFlags == cmd::kAtLeastN, Cmd_kArgFlags_not_kAtLeastN);
+  DCHECK_GE(total_size_in_bytes, sizeof(T));  // NOLINT
+  return reinterpret_cast<char*>(cmd) +
+      RoundSizeToMultipleOfEntries(total_size_in_bytes);
+}
+
+struct SharedMemory {
+  void Init(uint32 _id, uint32 _offset) {
+    id = _id;
+    offset = _offset;
+  }
+
+  uint32 id;
+  uint32 offset;
+};
+
+COMPILE_ASSERT(offsetof(SharedMemory, id) == 0,
+               Offsetof_SharedMemory_id_not_0);
+COMPILE_ASSERT(offsetof(SharedMemory, offset) == 4,
+               Offsetof_SharedMemory_offset_not_4);
+
+
+namespace cmd {
+
+// This macro is used to safely and convienently expand the list of commnad
+// buffer commands in to various lists and never have them get out of sync. To
+// add a new command, add it this list, create the corresponding structure below
+// and then add a function in gapi_decoder.cc called Handle_COMMAND_NAME where
+// COMMAND_NAME is the name of your command structure.
+//
+// NOTE: THE ORDER OF THESE MUST NOT CHANGE (their id is derived by order)
+#define COMMON_COMMAND_BUFFER_CMDS(OP) \
+  OP(Noop)                          /*  0 */ \
+  OP(SetToken)                      /*  1 */ \
+
+// Common commands.
+enum CommandId {
+  #define COMMON_COMMAND_BUFFER_CMD_OP(name) k ## name,
+
+  COMMON_COMMAND_BUFFER_CMDS(COMMON_COMMAND_BUFFER_CMD_OP)
+
+  #undef COMMON_COMMAND_BUFFER_CMD_OP
+
+  kNumCommands,
+  kLastCommonId = 1023,  // reserve 1024 spaces for common commands.
+};
+
+COMPILE_ASSERT(kNumCommands - 1 <= kLastCommonId, Too_many_common_commands);
+
+const char* GetCommandName(CommandId id);
+
+struct Noop {
+  typedef Noop ValueType;
+  static const CommandId kCmdId = kNoop;
+  static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN;
+
+  void SetHeader(uint32 skip_count) {
+    header.Init(kCmdId, skip_count + 1);
+  }
+
+  void Init(uint32 skip_count) {
+    SetHeader(skip_count);
+  }
+
+  static void* Set(void* cmd, uint32 skip_count) {
+    static_cast<ValueType*>(cmd)->Init(skip_count);
+    return NextImmediateCmdAddress<ValueType>(
+        cmd, skip_count * sizeof(CommandBufferEntry));  // NOLINT
+  }
+
+  CommandHeader header;
+};
+
+COMPILE_ASSERT(sizeof(Noop) == 4, Sizeof_Noop_is_not_4);
+COMPILE_ASSERT(offsetof(Noop, header) == 0, Offsetof_Noop_header_not_0);
+
+struct SetToken {
+  typedef SetToken ValueType;
+  static const CommandId kCmdId = kSetToken;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(uint32 _token) {
+    SetHeader();
+    token = _token;
+  }
+  static void* Set(void* cmd, uint32 token) {
+    static_cast<ValueType*>(cmd)->Init(token);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  CommandHeader header;
+  uint32 token;
+};
+
+COMPILE_ASSERT(sizeof(SetToken) == 8, Sizeof_SetToken_is_not_8);
+COMPILE_ASSERT(offsetof(SetToken, header) == 0,
+               Offsetof_SetToken_header_not_0);
+COMPILE_ASSERT(offsetof(SetToken, token) == 4,
+               Offsetof_SetToken_token_not_4);
+
+}  // namespace cmd
+
+#pragma pack(pop)
+
+}  // namespace command_buffer
+
+#endif  // GPU_COMMAND_BUFFER_COMMON_CROSS_CMD_BUFFER_COMMON_H_
+
diff --git a/gpu/command_buffer/common/command_buffer.h b/gpu/command_buffer/common/command_buffer.h
new file mode 100644
index 0000000..3ce841a
--- /dev/null
+++ b/gpu/command_buffer/common/command_buffer.h
@@ -0,0 +1,97 @@
+// Copyright (c) 2006-2008 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 GPU_COMMAND_BUFFER_COMMON_COMMAND_BUFFER_H_
+#define GPU_COMMAND_BUFFER_COMMON_COMMAND_BUFFER_H_
+
+#include "base/shared_memory.h"
+#include "base/task.h"
+
+namespace command_buffer {
+
+// Common interface for CommandBuffer implementations.
+class CommandBuffer {
+ public:
+  CommandBuffer() {
+  }
+
+  virtual ~CommandBuffer() {
+  }
+
+  // Initialize the command buffer with the given ring buffer. Takes ownership
+  // of ring buffer.
+  virtual bool Initialize(::base::SharedMemory* ring_buffer) = 0;
+
+  // Gets the shared memory ring buffer object for the command buffer.
+  virtual ::base::SharedMemory* GetRingBuffer() = 0;
+
+  virtual int32 GetSize() = 0;
+
+  // The writer calls this to update its put offset. This function returns the
+  // reader's most recent get offset. Does not return until after the put offset
+  // change callback has been invoked. Returns -1 if the put offset is invalid.
+  virtual int32 SyncOffsets(int32 put_offset) = 0;
+
+  // Returns the current get offset. This can be called from any thread.
+  virtual int32 GetGetOffset() = 0;
+
+  // Sets the current get offset. This can be called from any thread.
+  virtual void SetGetOffset(int32 get_offset) = 0;
+
+  // Returns the current put offset. This can be called from any thread.
+  virtual int32 GetPutOffset() = 0;
+
+  // Sets a callback that should be posted on another thread whenever the put
+  // offset is changed. The callback must not return until some progress has
+  // been made (unless the command buffer is empty), i.e. the
+  // get offset must have changed. It need not process the entire command
+  // buffer though. This allows concurrency between the writer and the reader
+  // while giving the writer a means of waiting for the reader to make some
+  // progress before attempting to write more to the command buffer. Avoiding
+  // the use of a synchronization primitive like a condition variable to
+  // synchronize reader and writer reduces the risk of deadlock.
+  // Takes ownership of callback. The callback is invoked on the plugin thread.
+  virtual void SetPutOffsetChangeCallback(Callback0::Type* callback) = 0;
+
+  // Create a shared memory transfer buffer and return a handle that uniquely
+  // identifies it or -1 on error.
+  virtual int32 CreateTransferBuffer(size_t size) = 0;
+
+  // Destroy a shared memory transfer buffer and recycle the handle.
+  virtual void DestroyTransferBuffer(int32 id) = 0;
+
+  // Get the shared memory associated with a handle.
+  virtual ::base::SharedMemory* GetTransferBuffer(int32 handle) = 0;
+
+  // Get the current token value. This is used for by the writer to defer
+  // changes to shared memory objects until the reader has reached a certain
+  // point in the command buffer. The reader is responsible for updating the
+  // token value, for example in response to an asynchronous set token command
+  // embedded in the command buffer. The default token value is zero.
+  virtual int32 GetToken() = 0;
+
+  // Allows the reader to update the current token value.
+  virtual void SetToken(int32 token) = 0;
+
+  // Get the current parse error and reset it to zero. Zero means no error. Non-
+  // zero means error. The default error status is zero.
+  virtual int32 ResetParseError() = 0;
+
+  // Allows the reader to set the current parse error.
+  virtual void SetParseError(int32 parse_error) = 0;
+
+  // Returns whether the command buffer is in the error state.
+  virtual bool GetErrorStatus() = 0;
+
+  // Allows the reader to set the error status. Once in an error state, the
+  // command buffer cannot recover and ceases to process commands.
+  virtual void RaiseErrorStatus() = 0;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(CommandBuffer);
+};
+
+}  // namespace command_buffer
+
+#endif  // GPU_COMMAND_BUFFER_COMMON_COMMAND_BUFFER_H_
diff --git a/gpu/command_buffer/common/command_buffer_mock.h b/gpu/command_buffer/common/command_buffer_mock.h
new file mode 100644
index 0000000..faa5536
--- /dev/null
+++ b/gpu/command_buffer/common/command_buffer_mock.h
@@ -0,0 +1,48 @@
+// Copyright (c) 2006-2008 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 GPU_COMMAND_BUFFER_COMMON_COMMAND_BUFFER_MOCK_H_
+#define GPU_COMMAND_BUFFER_COMMON_COMMAND_BUFFER_MOCK_H_
+
+#include "gpu/command_buffer/common/command_buffer.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace command_buffer {
+
+// An NPObject that implements a shared memory command buffer and a synchronous
+// API to manage the put and get pointers.
+class MockCommandBuffer : public CommandBuffer {
+ public:
+  MockCommandBuffer() {
+    ON_CALL(*this, GetRingBuffer())
+      .WillByDefault(testing::Return(static_cast<::base::SharedMemory*>(NULL)));
+    ON_CALL(*this, GetTransferBuffer(testing::_))
+      .WillByDefault(testing::Return(static_cast<::base::SharedMemory*>(NULL)));
+  }
+
+  MOCK_METHOD1(Initialize, bool(::base::SharedMemory* ring_buffer));
+  MOCK_METHOD0(GetRingBuffer, ::base::SharedMemory*());
+  MOCK_METHOD0(GetSize, int32());
+  MOCK_METHOD1(SyncOffsets, int32(int32 put_offset));
+  MOCK_METHOD0(GetGetOffset, int32());
+  MOCK_METHOD1(SetGetOffset, void(int32 get_offset));
+  MOCK_METHOD0(GetPutOffset, int32());
+  MOCK_METHOD1(SetPutOffsetChangeCallback, void(Callback0::Type* callback));
+  MOCK_METHOD1(CreateTransferBuffer, int32(size_t size));
+  MOCK_METHOD1(DestroyTransferBuffer, void(int32 handle));
+  MOCK_METHOD1(GetTransferBuffer, ::base::SharedMemory*(int32 handle));
+  MOCK_METHOD0(GetToken, int32());
+  MOCK_METHOD1(SetToken, void(int32 token));
+  MOCK_METHOD0(ResetParseError, int32());
+  MOCK_METHOD1(SetParseError, void(int32 parse_erro));
+  MOCK_METHOD0(GetErrorStatus, bool());
+  MOCK_METHOD0(RaiseErrorStatus, void());
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MockCommandBuffer);
+};
+
+}  // namespace command_buffer
+
+#endif  // GPU_COMMAND_BUFFER_COMMON_COMMAND_BUFFER_MOCK_H_
diff --git a/gpu/command_buffer/common/constants.h b/gpu/command_buffer/common/constants.h
new file mode 100644
index 0000000..ee874cd
--- /dev/null
+++ b/gpu/command_buffer/common/constants.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef O3D_COMMAND_BUFFER_COMMON_CROSS_CONSTANTS_H_
+#define O3D_COMMAND_BUFFER_COMMON_CROSS_CONSTANTS_H_
+
+#include "base/basictypes.h"
+
+namespace command_buffer {
+
+typedef int32 CommandBufferOffset;
+const CommandBufferOffset kInvalidCommandBufferOffset = -1;
+
+// Status of the command buffer service. It does not process commands
+// (meaning: get will not change) unless in kParsing state.
+namespace parser_status {
+  enum ParserStatus {
+    kNotConnected,  // The service is not connected - initial state.
+    kNoBuffer,      // The service is connected but no buffer was set.
+    kParsing,       // The service is connected, and parsing commands from the
+                    // buffer.
+    kParseError,    // Parsing stopped because a parse error was found.
+  };
+}
+
+namespace parse_error {
+  enum ParseError {
+    kParseNoError,
+    kParseInvalidSize,
+    kParseOutOfBounds,
+    kParseUnknownCommand,
+    kParseInvalidArguments,
+  };
+}
+
+// Invalid shared memory Id, returned by RegisterSharedMemory in case of
+// failure.
+const int32 kInvalidSharedMemoryId = -1;
+
+}  // namespace command_buffer
+
+#endif  // O3D_COMMAND_BUFFER_COMMON_CROSS_CONSTANTS_H_
diff --git a/gpu/command_buffer/common/gles2_cmd_format.cc b/gpu/command_buffer/common/gles2_cmd_format.cc
new file mode 100644
index 0000000..62e297d
--- /dev/null
+++ b/gpu/command_buffer/common/gles2_cmd_format.cc
@@ -0,0 +1,33 @@
+// Copyright (c) 2006-2009 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.
+
+// This file contains the binary format definition of the command buffer and
+// command buffer commands.
+
+// We explicitly do NOT include gles2_cmd_format.h here because client side
+// and service side have different requirements.
+#include "gpu/command_buffer/common/cmd_buffer_common.h"
+
+namespace command_buffer {
+namespace gles2 {
+
+#include "gpu/command_buffer/common/gles2_cmd_ids_autogen.h"
+
+const char* GetCommandName(CommandId id) {
+  static const char* const names[] = {
+  #define GLES2_CMD_OP(name) "k" # name,
+
+  GLES2_COMMAND_LIST(GLES2_CMD_OP)
+
+  #undef GLES2_CMD_OP
+  };
+
+  return (static_cast<int>(id) >= 0 && static_cast<int>(id) < kNumCommands) ?
+      names[id] : "*unknown-command*";
+}
+
+}  // namespace gles2
+}  // namespace command_buffer
+
+
diff --git a/gpu/command_buffer/common/gles2_cmd_format.h b/gpu/command_buffer/common/gles2_cmd_format.h
new file mode 100644
index 0000000..729149d0
--- /dev/null
+++ b/gpu/command_buffer/common/gles2_cmd_format.h
@@ -0,0 +1,36 @@
+// Copyright (c) 2006-2009 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.
+
+// This file defines the GLES2 command buffer commands.
+
+#ifndef GPU_COMMAND_BUFFER_COMMON_GLES2_CMD_FORMAT_H
+#define GPU_COMMAND_BUFFER_COMMON_GLES2_CMD_FORMAT_H
+
+// This is here because service side code must include the system's version of
+// the GL headers where as client side code includes the Chrome version.
+#ifdef GLES2_GPU_SERVICE
+#include <GL/glew.h>
+#if defined(OS_WIN)
+#include <GL/wglew.h>
+#endif
+#else
+#include <GLES2/gl2types.h>
+#endif
+
+#include "base/basictypes.h"
+#include "gpu/command_buffer/common/types.h"
+#include "gpu/command_buffer/common/bitfield_helpers.h"
+#include "gpu/command_buffer/common/cmd_buffer_common.h"
+#include "gpu/command_buffer/common/gles2_cmd_ids.h"
+
+namespace command_buffer {
+namespace gles2 {
+
+#include "gpu/command_buffer/common/gles2_cmd_format_autogen.h"
+
+}  // namespace gles2
+}  // namespace command_buffer
+
+#endif  // GPU_COMMAND_BUFFER_COMMON_GLES2_CMD_FORMAT_H
+
diff --git a/gpu/command_buffer/common/gles2_cmd_format_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_autogen.h
new file mode 100644
index 0000000..e15713a
--- /dev/null
+++ b/gpu/command_buffer/common/gles2_cmd_format_autogen.h
@@ -0,0 +1,8278 @@
+// This file is auto-generated. DO NOT EDIT!
+
+#pragma pack(push, 1)
+
+struct ActiveTexture {
+  typedef ActiveTexture ValueType;
+  static const CommandId kCmdId = kActiveTexture;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLenum _texture) {
+    SetHeader();
+    texture = _texture;
+  }
+
+  void* Set(void* cmd, GLenum _texture) {
+    static_cast<ValueType*>(cmd)->Init(_texture);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 texture;
+};
+
+COMPILE_ASSERT(sizeof(ActiveTexture) == 8,
+               Sizeof_ActiveTexture_is_not_8);
+COMPILE_ASSERT(offsetof(ActiveTexture, header) == 0,
+               OffsetOf_ActiveTexture_header_not_0);
+COMPILE_ASSERT(offsetof(ActiveTexture, texture) == 4,
+               OffsetOf_ActiveTexture_texture_not_4);
+
+struct AttachShader {
+  typedef AttachShader ValueType;
+  static const CommandId kCmdId = kAttachShader;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLuint _program, GLuint _shader) {
+    SetHeader();
+    program = _program;
+    shader = _shader;
+  }
+
+  void* Set(void* cmd, GLuint _program, GLuint _shader) {
+    static_cast<ValueType*>(cmd)->Init(_program, _shader);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 program;
+  uint32 shader;
+};
+
+COMPILE_ASSERT(sizeof(AttachShader) == 12,
+               Sizeof_AttachShader_is_not_12);
+COMPILE_ASSERT(offsetof(AttachShader, header) == 0,
+               OffsetOf_AttachShader_header_not_0);
+COMPILE_ASSERT(offsetof(AttachShader, program) == 4,
+               OffsetOf_AttachShader_program_not_4);
+COMPILE_ASSERT(offsetof(AttachShader, shader) == 8,
+               OffsetOf_AttachShader_shader_not_8);
+
+struct BindAttribLocation {
+  typedef BindAttribLocation ValueType;
+  static const CommandId kCmdId = kBindAttribLocation;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLuint _program, GLuint _index, uint32 _name_shm_id,
+      uint32 _name_shm_offset, uint32 _data_size) {
+    SetHeader();
+    program = _program;
+    index = _index;
+    name_shm_id = _name_shm_id;
+    name_shm_offset = _name_shm_offset;
+    data_size = _data_size;
+  }
+
+  void* Set(
+      void* cmd, GLuint _program, GLuint _index, uint32 _name_shm_id,
+      uint32 _name_shm_offset, uint32 _data_size) {
+    static_cast<ValueType*>(
+        cmd)->Init(
+            _program, _index, _name_shm_id, _name_shm_offset, _data_size);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 program;
+  uint32 index;
+  uint32 name_shm_id;
+  uint32 name_shm_offset;
+  uint32 data_size;
+};
+
+COMPILE_ASSERT(sizeof(BindAttribLocation) == 24,
+               Sizeof_BindAttribLocation_is_not_24);
+COMPILE_ASSERT(offsetof(BindAttribLocation, header) == 0,
+               OffsetOf_BindAttribLocation_header_not_0);
+COMPILE_ASSERT(offsetof(BindAttribLocation, program) == 4,
+               OffsetOf_BindAttribLocation_program_not_4);
+COMPILE_ASSERT(offsetof(BindAttribLocation, index) == 8,
+               OffsetOf_BindAttribLocation_index_not_8);
+COMPILE_ASSERT(offsetof(BindAttribLocation, name_shm_id) == 12,
+               OffsetOf_BindAttribLocation_name_shm_id_not_12);
+COMPILE_ASSERT(offsetof(BindAttribLocation, name_shm_offset) == 16,
+               OffsetOf_BindAttribLocation_name_shm_offset_not_16);
+COMPILE_ASSERT(offsetof(BindAttribLocation, data_size) == 20,
+               OffsetOf_BindAttribLocation_data_size_not_20);
+
+struct BindAttribLocationImmediate {
+  typedef BindAttribLocationImmediate ValueType;
+  static const CommandId kCmdId = kBindAttribLocationImmediate;
+  static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN;
+
+  static uint32 ComputeDataSize(const char* s) {
+    return strlen(s);
+  }
+
+  static uint32 ComputeSize(const char* s) {
+    return static_cast<uint32>(
+        sizeof(ValueType) + ComputeDataSize(s));  // NOLINT
+  }
+
+  void SetHeader(const char* s) {
+    header.SetCmdByTotalSize<ValueType>(ComputeSize(s));
+  }
+
+  void Init(GLuint _program, GLuint _index, const char* _name) {
+    SetHeader(_name);
+    program = _program;
+    index = _index;
+    data_size = strlen(_name);
+    memcpy(ImmediateDataAddress(this), _name, data_size);
+  }
+
+  void* Set(void* cmd, GLuint _program, GLuint _index, const char* _name) {
+    static_cast<ValueType*>(cmd)->Init(_program, _index, _name);
+    const uint32 size = ComputeSize(_name);
+    return NextImmediateCmdAddressTotalSize<ValueType>(cmd, size);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 program;
+  uint32 index;
+  uint32 data_size;
+};
+
+COMPILE_ASSERT(sizeof(BindAttribLocationImmediate) == 16,
+               Sizeof_BindAttribLocationImmediate_is_not_16);
+COMPILE_ASSERT(offsetof(BindAttribLocationImmediate, header) == 0,
+               OffsetOf_BindAttribLocationImmediate_header_not_0);
+COMPILE_ASSERT(offsetof(BindAttribLocationImmediate, program) == 4,
+               OffsetOf_BindAttribLocationImmediate_program_not_4);
+COMPILE_ASSERT(offsetof(BindAttribLocationImmediate, index) == 8,
+               OffsetOf_BindAttribLocationImmediate_index_not_8);
+COMPILE_ASSERT(offsetof(BindAttribLocationImmediate, data_size) == 12,
+               OffsetOf_BindAttribLocationImmediate_data_size_not_12);
+
+struct BindBuffer {
+  typedef BindBuffer ValueType;
+  static const CommandId kCmdId = kBindBuffer;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLenum _target, GLuint _buffer) {
+    SetHeader();
+    target = _target;
+    buffer = _buffer;
+  }
+
+  void* Set(void* cmd, GLenum _target, GLuint _buffer) {
+    static_cast<ValueType*>(cmd)->Init(_target, _buffer);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 target;
+  uint32 buffer;
+};
+
+COMPILE_ASSERT(sizeof(BindBuffer) == 12,
+               Sizeof_BindBuffer_is_not_12);
+COMPILE_ASSERT(offsetof(BindBuffer, header) == 0,
+               OffsetOf_BindBuffer_header_not_0);
+COMPILE_ASSERT(offsetof(BindBuffer, target) == 4,
+               OffsetOf_BindBuffer_target_not_4);
+COMPILE_ASSERT(offsetof(BindBuffer, buffer) == 8,
+               OffsetOf_BindBuffer_buffer_not_8);
+
+struct BindFramebuffer {
+  typedef BindFramebuffer ValueType;
+  static const CommandId kCmdId = kBindFramebuffer;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLenum _target, GLuint _framebuffer) {
+    SetHeader();
+    target = _target;
+    framebuffer = _framebuffer;
+  }
+
+  void* Set(void* cmd, GLenum _target, GLuint _framebuffer) {
+    static_cast<ValueType*>(cmd)->Init(_target, _framebuffer);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 target;
+  uint32 framebuffer;
+};
+
+COMPILE_ASSERT(sizeof(BindFramebuffer) == 12,
+               Sizeof_BindFramebuffer_is_not_12);
+COMPILE_ASSERT(offsetof(BindFramebuffer, header) == 0,
+               OffsetOf_BindFramebuffer_header_not_0);
+COMPILE_ASSERT(offsetof(BindFramebuffer, target) == 4,
+               OffsetOf_BindFramebuffer_target_not_4);
+COMPILE_ASSERT(offsetof(BindFramebuffer, framebuffer) == 8,
+               OffsetOf_BindFramebuffer_framebuffer_not_8);
+
+struct BindRenderbuffer {
+  typedef BindRenderbuffer ValueType;
+  static const CommandId kCmdId = kBindRenderbuffer;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLenum _target, GLuint _renderbuffer) {
+    SetHeader();
+    target = _target;
+    renderbuffer = _renderbuffer;
+  }
+
+  void* Set(void* cmd, GLenum _target, GLuint _renderbuffer) {
+    static_cast<ValueType*>(cmd)->Init(_target, _renderbuffer);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 target;
+  uint32 renderbuffer;
+};
+
+COMPILE_ASSERT(sizeof(BindRenderbuffer) == 12,
+               Sizeof_BindRenderbuffer_is_not_12);
+COMPILE_ASSERT(offsetof(BindRenderbuffer, header) == 0,
+               OffsetOf_BindRenderbuffer_header_not_0);
+COMPILE_ASSERT(offsetof(BindRenderbuffer, target) == 4,
+               OffsetOf_BindRenderbuffer_target_not_4);
+COMPILE_ASSERT(offsetof(BindRenderbuffer, renderbuffer) == 8,
+               OffsetOf_BindRenderbuffer_renderbuffer_not_8);
+
+struct BindTexture {
+  typedef BindTexture ValueType;
+  static const CommandId kCmdId = kBindTexture;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLenum _target, GLuint _texture) {
+    SetHeader();
+    target = _target;
+    texture = _texture;
+  }
+
+  void* Set(void* cmd, GLenum _target, GLuint _texture) {
+    static_cast<ValueType*>(cmd)->Init(_target, _texture);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 target;
+  uint32 texture;
+};
+
+COMPILE_ASSERT(sizeof(BindTexture) == 12,
+               Sizeof_BindTexture_is_not_12);
+COMPILE_ASSERT(offsetof(BindTexture, header) == 0,
+               OffsetOf_BindTexture_header_not_0);
+COMPILE_ASSERT(offsetof(BindTexture, target) == 4,
+               OffsetOf_BindTexture_target_not_4);
+COMPILE_ASSERT(offsetof(BindTexture, texture) == 8,
+               OffsetOf_BindTexture_texture_not_8);
+
+struct BlendColor {
+  typedef BlendColor ValueType;
+  static const CommandId kCmdId = kBlendColor;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLclampf _red, GLclampf _green, GLclampf _blue, GLclampf _alpha) {
+    SetHeader();
+    red = _red;
+    green = _green;
+    blue = _blue;
+    alpha = _alpha;
+  }
+
+  void* Set(
+      void* cmd, GLclampf _red, GLclampf _green, GLclampf _blue,
+      GLclampf _alpha) {
+    static_cast<ValueType*>(cmd)->Init(_red, _green, _blue, _alpha);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  float red;
+  float green;
+  float blue;
+  float alpha;
+};
+
+COMPILE_ASSERT(sizeof(BlendColor) == 20,
+               Sizeof_BlendColor_is_not_20);
+COMPILE_ASSERT(offsetof(BlendColor, header) == 0,
+               OffsetOf_BlendColor_header_not_0);
+COMPILE_ASSERT(offsetof(BlendColor, red) == 4,
+               OffsetOf_BlendColor_red_not_4);
+COMPILE_ASSERT(offsetof(BlendColor, green) == 8,
+               OffsetOf_BlendColor_green_not_8);
+COMPILE_ASSERT(offsetof(BlendColor, blue) == 12,
+               OffsetOf_BlendColor_blue_not_12);
+COMPILE_ASSERT(offsetof(BlendColor, alpha) == 16,
+               OffsetOf_BlendColor_alpha_not_16);
+
+struct BlendEquation {
+  typedef BlendEquation ValueType;
+  static const CommandId kCmdId = kBlendEquation;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLenum _mode) {
+    SetHeader();
+    mode = _mode;
+  }
+
+  void* Set(void* cmd, GLenum _mode) {
+    static_cast<ValueType*>(cmd)->Init(_mode);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 mode;
+};
+
+COMPILE_ASSERT(sizeof(BlendEquation) == 8,
+               Sizeof_BlendEquation_is_not_8);
+COMPILE_ASSERT(offsetof(BlendEquation, header) == 0,
+               OffsetOf_BlendEquation_header_not_0);
+COMPILE_ASSERT(offsetof(BlendEquation, mode) == 4,
+               OffsetOf_BlendEquation_mode_not_4);
+
+struct BlendEquationSeparate {
+  typedef BlendEquationSeparate ValueType;
+  static const CommandId kCmdId = kBlendEquationSeparate;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLenum _modeRGB, GLenum _modeAlpha) {
+    SetHeader();
+    modeRGB = _modeRGB;
+    modeAlpha = _modeAlpha;
+  }
+
+  void* Set(void* cmd, GLenum _modeRGB, GLenum _modeAlpha) {
+    static_cast<ValueType*>(cmd)->Init(_modeRGB, _modeAlpha);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 modeRGB;
+  uint32 modeAlpha;
+};
+
+COMPILE_ASSERT(sizeof(BlendEquationSeparate) == 12,
+               Sizeof_BlendEquationSeparate_is_not_12);
+COMPILE_ASSERT(offsetof(BlendEquationSeparate, header) == 0,
+               OffsetOf_BlendEquationSeparate_header_not_0);
+COMPILE_ASSERT(offsetof(BlendEquationSeparate, modeRGB) == 4,
+               OffsetOf_BlendEquationSeparate_modeRGB_not_4);
+COMPILE_ASSERT(offsetof(BlendEquationSeparate, modeAlpha) == 8,
+               OffsetOf_BlendEquationSeparate_modeAlpha_not_8);
+
+struct BlendFunc {
+  typedef BlendFunc ValueType;
+  static const CommandId kCmdId = kBlendFunc;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLenum _sfactor, GLenum _dfactor) {
+    SetHeader();
+    sfactor = _sfactor;
+    dfactor = _dfactor;
+  }
+
+  void* Set(void* cmd, GLenum _sfactor, GLenum _dfactor) {
+    static_cast<ValueType*>(cmd)->Init(_sfactor, _dfactor);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 sfactor;
+  uint32 dfactor;
+};
+
+COMPILE_ASSERT(sizeof(BlendFunc) == 12,
+               Sizeof_BlendFunc_is_not_12);
+COMPILE_ASSERT(offsetof(BlendFunc, header) == 0,
+               OffsetOf_BlendFunc_header_not_0);
+COMPILE_ASSERT(offsetof(BlendFunc, sfactor) == 4,
+               OffsetOf_BlendFunc_sfactor_not_4);
+COMPILE_ASSERT(offsetof(BlendFunc, dfactor) == 8,
+               OffsetOf_BlendFunc_dfactor_not_8);
+
+struct BlendFuncSeparate {
+  typedef BlendFuncSeparate ValueType;
+  static const CommandId kCmdId = kBlendFuncSeparate;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLenum _srcRGB, GLenum _dstRGB, GLenum _srcAlpha, GLenum _dstAlpha) {
+    SetHeader();
+    srcRGB = _srcRGB;
+    dstRGB = _dstRGB;
+    srcAlpha = _srcAlpha;
+    dstAlpha = _dstAlpha;
+  }
+
+  void* Set(
+      void* cmd, GLenum _srcRGB, GLenum _dstRGB, GLenum _srcAlpha,
+      GLenum _dstAlpha) {
+    static_cast<ValueType*>(cmd)->Init(_srcRGB, _dstRGB, _srcAlpha, _dstAlpha);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 srcRGB;
+  uint32 dstRGB;
+  uint32 srcAlpha;
+  uint32 dstAlpha;
+};
+
+COMPILE_ASSERT(sizeof(BlendFuncSeparate) == 20,
+               Sizeof_BlendFuncSeparate_is_not_20);
+COMPILE_ASSERT(offsetof(BlendFuncSeparate, header) == 0,
+               OffsetOf_BlendFuncSeparate_header_not_0);
+COMPILE_ASSERT(offsetof(BlendFuncSeparate, srcRGB) == 4,
+               OffsetOf_BlendFuncSeparate_srcRGB_not_4);
+COMPILE_ASSERT(offsetof(BlendFuncSeparate, dstRGB) == 8,
+               OffsetOf_BlendFuncSeparate_dstRGB_not_8);
+COMPILE_ASSERT(offsetof(BlendFuncSeparate, srcAlpha) == 12,
+               OffsetOf_BlendFuncSeparate_srcAlpha_not_12);
+COMPILE_ASSERT(offsetof(BlendFuncSeparate, dstAlpha) == 16,
+               OffsetOf_BlendFuncSeparate_dstAlpha_not_16);
+
+struct BufferData {
+  typedef BufferData ValueType;
+  static const CommandId kCmdId = kBufferData;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLenum _target, GLsizeiptr _size, uint32 _data_shm_id,
+      uint32 _data_shm_offset, GLenum _usage) {
+    SetHeader();
+    target = _target;
+    size = _size;
+    data_shm_id = _data_shm_id;
+    data_shm_offset = _data_shm_offset;
+    usage = _usage;
+  }
+
+  void* Set(
+      void* cmd, GLenum _target, GLsizeiptr _size, uint32 _data_shm_id,
+      uint32 _data_shm_offset, GLenum _usage) {
+    static_cast<ValueType*>(
+        cmd)->Init(_target, _size, _data_shm_id, _data_shm_offset, _usage);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 target;
+  uint32 size;
+  uint32 data_shm_id;
+  uint32 data_shm_offset;
+  uint32 usage;
+};
+
+COMPILE_ASSERT(sizeof(BufferData) == 24,
+               Sizeof_BufferData_is_not_24);
+COMPILE_ASSERT(offsetof(BufferData, header) == 0,
+               OffsetOf_BufferData_header_not_0);
+COMPILE_ASSERT(offsetof(BufferData, target) == 4,
+               OffsetOf_BufferData_target_not_4);
+COMPILE_ASSERT(offsetof(BufferData, size) == 8,
+               OffsetOf_BufferData_size_not_8);
+COMPILE_ASSERT(offsetof(BufferData, data_shm_id) == 12,
+               OffsetOf_BufferData_data_shm_id_not_12);
+COMPILE_ASSERT(offsetof(BufferData, data_shm_offset) == 16,
+               OffsetOf_BufferData_data_shm_offset_not_16);
+COMPILE_ASSERT(offsetof(BufferData, usage) == 20,
+               OffsetOf_BufferData_usage_not_20);
+
+struct BufferDataImmediate {
+  typedef BufferDataImmediate ValueType;
+  static const CommandId kCmdId = kBufferDataImmediate;
+  static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN;
+
+  static uint32 ComputeSize(uint32 size_in_bytes) {
+    return static_cast<uint32>(
+        sizeof(ValueType) +  // NOLINT
+        RoundSizeToMultipleOfEntries(size_in_bytes));
+  }
+
+  void SetHeader(uint32 size_in_bytes) {
+    header.SetCmdByTotalSize<ValueType>(size_in_bytes);
+  }
+
+  void Init(GLenum _target, GLsizeiptr _size, GLenum _usage) {
+    uint32 total_size = ComputeSize(_size);
+    SetHeader(total_size);
+    target = _target;
+    size = _size;
+    usage = _usage;
+  }
+
+  void* Set(void* cmd, GLenum _target, GLsizeiptr _size, GLenum _usage) {
+    uint32 total_size = ComputeSize(_size);
+    static_cast<ValueType*>(cmd)->Init(_target, _size, _usage);
+    return NextImmediateCmdAddressTotalSize<ValueType>(cmd, total_size);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 target;
+  uint32 size;
+  uint32 usage;
+};
+
+COMPILE_ASSERT(sizeof(BufferDataImmediate) == 16,
+               Sizeof_BufferDataImmediate_is_not_16);
+COMPILE_ASSERT(offsetof(BufferDataImmediate, header) == 0,
+               OffsetOf_BufferDataImmediate_header_not_0);
+COMPILE_ASSERT(offsetof(BufferDataImmediate, target) == 4,
+               OffsetOf_BufferDataImmediate_target_not_4);
+COMPILE_ASSERT(offsetof(BufferDataImmediate, size) == 8,
+               OffsetOf_BufferDataImmediate_size_not_8);
+COMPILE_ASSERT(offsetof(BufferDataImmediate, usage) == 12,
+               OffsetOf_BufferDataImmediate_usage_not_12);
+
+struct BufferSubData {
+  typedef BufferSubData ValueType;
+  static const CommandId kCmdId = kBufferSubData;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLenum _target, GLintptr _offset, GLsizeiptr _size, uint32 _data_shm_id,
+      uint32 _data_shm_offset) {
+    SetHeader();
+    target = _target;
+    offset = _offset;
+    size = _size;
+    data_shm_id = _data_shm_id;
+    data_shm_offset = _data_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLenum _target, GLintptr _offset, GLsizeiptr _size,
+      uint32 _data_shm_id, uint32 _data_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(_target, _offset, _size, _data_shm_id, _data_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 target;
+  uint32 offset;
+  uint32 size;
+  uint32 data_shm_id;
+  uint32 data_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(BufferSubData) == 24,
+               Sizeof_BufferSubData_is_not_24);
+COMPILE_ASSERT(offsetof(BufferSubData, header) == 0,
+               OffsetOf_BufferSubData_header_not_0);
+COMPILE_ASSERT(offsetof(BufferSubData, target) == 4,
+               OffsetOf_BufferSubData_target_not_4);
+COMPILE_ASSERT(offsetof(BufferSubData, offset) == 8,
+               OffsetOf_BufferSubData_offset_not_8);
+COMPILE_ASSERT(offsetof(BufferSubData, size) == 12,
+               OffsetOf_BufferSubData_size_not_12);
+COMPILE_ASSERT(offsetof(BufferSubData, data_shm_id) == 16,
+               OffsetOf_BufferSubData_data_shm_id_not_16);
+COMPILE_ASSERT(offsetof(BufferSubData, data_shm_offset) == 20,
+               OffsetOf_BufferSubData_data_shm_offset_not_20);
+
+struct BufferSubDataImmediate {
+  typedef BufferSubDataImmediate ValueType;
+  static const CommandId kCmdId = kBufferSubDataImmediate;
+  static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN;
+
+  static uint32 ComputeSize(uint32 size_in_bytes) {
+    return static_cast<uint32>(
+        sizeof(ValueType) +  // NOLINT
+        RoundSizeToMultipleOfEntries(size_in_bytes));
+  }
+
+  void SetHeader(uint32 size_in_bytes) {
+    header.SetCmdByTotalSize<ValueType>(size_in_bytes);
+  }
+
+  void Init(GLenum _target, GLintptr _offset, GLsizeiptr _size) {
+    uint32 total_size = ComputeSize(_size);
+    SetHeader(total_size);
+    target = _target;
+    offset = _offset;
+    size = _size;
+  }
+
+  void* Set(void* cmd, GLenum _target, GLintptr _offset, GLsizeiptr _size) {
+    uint32 total_size = ComputeSize(_size);
+    static_cast<ValueType*>(cmd)->Init(_target, _offset, _size);
+    return NextImmediateCmdAddressTotalSize<ValueType>(cmd, total_size);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 target;
+  uint32 offset;
+  uint32 size;
+};
+
+COMPILE_ASSERT(sizeof(BufferSubDataImmediate) == 16,
+               Sizeof_BufferSubDataImmediate_is_not_16);
+COMPILE_ASSERT(offsetof(BufferSubDataImmediate, header) == 0,
+               OffsetOf_BufferSubDataImmediate_header_not_0);
+COMPILE_ASSERT(offsetof(BufferSubDataImmediate, target) == 4,
+               OffsetOf_BufferSubDataImmediate_target_not_4);
+COMPILE_ASSERT(offsetof(BufferSubDataImmediate, offset) == 8,
+               OffsetOf_BufferSubDataImmediate_offset_not_8);
+COMPILE_ASSERT(offsetof(BufferSubDataImmediate, size) == 12,
+               OffsetOf_BufferSubDataImmediate_size_not_12);
+
+struct CheckFramebufferStatus {
+  typedef CheckFramebufferStatus ValueType;
+  static const CommandId kCmdId = kCheckFramebufferStatus;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLenum _target) {
+    SetHeader();
+    target = _target;
+  }
+
+  void* Set(void* cmd, GLenum _target) {
+    static_cast<ValueType*>(cmd)->Init(_target);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 target;
+};
+
+COMPILE_ASSERT(sizeof(CheckFramebufferStatus) == 8,
+               Sizeof_CheckFramebufferStatus_is_not_8);
+COMPILE_ASSERT(offsetof(CheckFramebufferStatus, header) == 0,
+               OffsetOf_CheckFramebufferStatus_header_not_0);
+COMPILE_ASSERT(offsetof(CheckFramebufferStatus, target) == 4,
+               OffsetOf_CheckFramebufferStatus_target_not_4);
+
+struct Clear {
+  typedef Clear ValueType;
+  static const CommandId kCmdId = kClear;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLbitfield _mask) {
+    SetHeader();
+    mask = _mask;
+  }
+
+  void* Set(void* cmd, GLbitfield _mask) {
+    static_cast<ValueType*>(cmd)->Init(_mask);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 mask;
+};
+
+COMPILE_ASSERT(sizeof(Clear) == 8,
+               Sizeof_Clear_is_not_8);
+COMPILE_ASSERT(offsetof(Clear, header) == 0,
+               OffsetOf_Clear_header_not_0);
+COMPILE_ASSERT(offsetof(Clear, mask) == 4,
+               OffsetOf_Clear_mask_not_4);
+
+struct ClearColor {
+  typedef ClearColor ValueType;
+  static const CommandId kCmdId = kClearColor;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLclampf _red, GLclampf _green, GLclampf _blue, GLclampf _alpha) {
+    SetHeader();
+    red = _red;
+    green = _green;
+    blue = _blue;
+    alpha = _alpha;
+  }
+
+  void* Set(
+      void* cmd, GLclampf _red, GLclampf _green, GLclampf _blue,
+      GLclampf _alpha) {
+    static_cast<ValueType*>(cmd)->Init(_red, _green, _blue, _alpha);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  float red;
+  float green;
+  float blue;
+  float alpha;
+};
+
+COMPILE_ASSERT(sizeof(ClearColor) == 20,
+               Sizeof_ClearColor_is_not_20);
+COMPILE_ASSERT(offsetof(ClearColor, header) == 0,
+               OffsetOf_ClearColor_header_not_0);
+COMPILE_ASSERT(offsetof(ClearColor, red) == 4,
+               OffsetOf_ClearColor_red_not_4);
+COMPILE_ASSERT(offsetof(ClearColor, green) == 8,
+               OffsetOf_ClearColor_green_not_8);
+COMPILE_ASSERT(offsetof(ClearColor, blue) == 12,
+               OffsetOf_ClearColor_blue_not_12);
+COMPILE_ASSERT(offsetof(ClearColor, alpha) == 16,
+               OffsetOf_ClearColor_alpha_not_16);
+
+struct ClearDepthf {
+  typedef ClearDepthf ValueType;
+  static const CommandId kCmdId = kClearDepthf;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLclampf _depth) {
+    SetHeader();
+    depth = _depth;
+  }
+
+  void* Set(void* cmd, GLclampf _depth) {
+    static_cast<ValueType*>(cmd)->Init(_depth);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  float depth;
+};
+
+COMPILE_ASSERT(sizeof(ClearDepthf) == 8,
+               Sizeof_ClearDepthf_is_not_8);
+COMPILE_ASSERT(offsetof(ClearDepthf, header) == 0,
+               OffsetOf_ClearDepthf_header_not_0);
+COMPILE_ASSERT(offsetof(ClearDepthf, depth) == 4,
+               OffsetOf_ClearDepthf_depth_not_4);
+
+struct ClearStencil {
+  typedef ClearStencil ValueType;
+  static const CommandId kCmdId = kClearStencil;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLint _s) {
+    SetHeader();
+    s = _s;
+  }
+
+  void* Set(void* cmd, GLint _s) {
+    static_cast<ValueType*>(cmd)->Init(_s);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 s;
+};
+
+COMPILE_ASSERT(sizeof(ClearStencil) == 8,
+               Sizeof_ClearStencil_is_not_8);
+COMPILE_ASSERT(offsetof(ClearStencil, header) == 0,
+               OffsetOf_ClearStencil_header_not_0);
+COMPILE_ASSERT(offsetof(ClearStencil, s) == 4,
+               OffsetOf_ClearStencil_s_not_4);
+
+struct ColorMask {
+  typedef ColorMask ValueType;
+  static const CommandId kCmdId = kColorMask;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLboolean _red, GLboolean _green, GLboolean _blue, GLboolean _alpha) {
+    SetHeader();
+    red = _red;
+    green = _green;
+    blue = _blue;
+    alpha = _alpha;
+  }
+
+  void* Set(
+      void* cmd, GLboolean _red, GLboolean _green, GLboolean _blue,
+      GLboolean _alpha) {
+    static_cast<ValueType*>(cmd)->Init(_red, _green, _blue, _alpha);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 red;
+  uint32 green;
+  uint32 blue;
+  uint32 alpha;
+};
+
+COMPILE_ASSERT(sizeof(ColorMask) == 20,
+               Sizeof_ColorMask_is_not_20);
+COMPILE_ASSERT(offsetof(ColorMask, header) == 0,
+               OffsetOf_ColorMask_header_not_0);
+COMPILE_ASSERT(offsetof(ColorMask, red) == 4,
+               OffsetOf_ColorMask_red_not_4);
+COMPILE_ASSERT(offsetof(ColorMask, green) == 8,
+               OffsetOf_ColorMask_green_not_8);
+COMPILE_ASSERT(offsetof(ColorMask, blue) == 12,
+               OffsetOf_ColorMask_blue_not_12);
+COMPILE_ASSERT(offsetof(ColorMask, alpha) == 16,
+               OffsetOf_ColorMask_alpha_not_16);
+
+struct CompileShader {
+  typedef CompileShader ValueType;
+  static const CommandId kCmdId = kCompileShader;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLuint _shader) {
+    SetHeader();
+    shader = _shader;
+  }
+
+  void* Set(void* cmd, GLuint _shader) {
+    static_cast<ValueType*>(cmd)->Init(_shader);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 shader;
+};
+
+COMPILE_ASSERT(sizeof(CompileShader) == 8,
+               Sizeof_CompileShader_is_not_8);
+COMPILE_ASSERT(offsetof(CompileShader, header) == 0,
+               OffsetOf_CompileShader_header_not_0);
+COMPILE_ASSERT(offsetof(CompileShader, shader) == 4,
+               OffsetOf_CompileShader_shader_not_4);
+
+struct CompressedTexImage2D {
+  typedef CompressedTexImage2D ValueType;
+  static const CommandId kCmdId = kCompressedTexImage2D;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLenum _target, GLint _level, GLenum _internalformat, GLsizei _width,
+      GLsizei _height, GLint _border, GLsizei _imageSize, uint32 _data_shm_id,
+      uint32 _data_shm_offset) {
+    SetHeader();
+    target = _target;
+    level = _level;
+    internalformat = _internalformat;
+    width = _width;
+    height = _height;
+    border = _border;
+    imageSize = _imageSize;
+    data_shm_id = _data_shm_id;
+    data_shm_offset = _data_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLenum _target, GLint _level, GLenum _internalformat,
+      GLsizei _width, GLsizei _height, GLint _border, GLsizei _imageSize,
+      uint32 _data_shm_id, uint32 _data_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(
+            _target, _level, _internalformat, _width, _height, _border,
+            _imageSize, _data_shm_id, _data_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 target;
+  uint32 level;
+  uint32 internalformat;
+  uint32 width;
+  uint32 height;
+  uint32 border;
+  uint32 imageSize;
+  uint32 data_shm_id;
+  uint32 data_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(CompressedTexImage2D) == 40,
+               Sizeof_CompressedTexImage2D_is_not_40);
+COMPILE_ASSERT(offsetof(CompressedTexImage2D, header) == 0,
+               OffsetOf_CompressedTexImage2D_header_not_0);
+COMPILE_ASSERT(offsetof(CompressedTexImage2D, target) == 4,
+               OffsetOf_CompressedTexImage2D_target_not_4);
+COMPILE_ASSERT(offsetof(CompressedTexImage2D, level) == 8,
+               OffsetOf_CompressedTexImage2D_level_not_8);
+COMPILE_ASSERT(offsetof(CompressedTexImage2D, internalformat) == 12,
+               OffsetOf_CompressedTexImage2D_internalformat_not_12);
+COMPILE_ASSERT(offsetof(CompressedTexImage2D, width) == 16,
+               OffsetOf_CompressedTexImage2D_width_not_16);
+COMPILE_ASSERT(offsetof(CompressedTexImage2D, height) == 20,
+               OffsetOf_CompressedTexImage2D_height_not_20);
+COMPILE_ASSERT(offsetof(CompressedTexImage2D, border) == 24,
+               OffsetOf_CompressedTexImage2D_border_not_24);
+COMPILE_ASSERT(offsetof(CompressedTexImage2D, imageSize) == 28,
+               OffsetOf_CompressedTexImage2D_imageSize_not_28);
+COMPILE_ASSERT(offsetof(CompressedTexImage2D, data_shm_id) == 32,
+               OffsetOf_CompressedTexImage2D_data_shm_id_not_32);
+COMPILE_ASSERT(offsetof(CompressedTexImage2D, data_shm_offset) == 36,
+               OffsetOf_CompressedTexImage2D_data_shm_offset_not_36);
+
+struct CompressedTexImage2DImmediate {
+  typedef CompressedTexImage2DImmediate ValueType;
+  static const CommandId kCmdId = kCompressedTexImage2DImmediate;
+  static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN;
+
+  static uint32 ComputeSize(uint32 size_in_bytes) {
+    return static_cast<uint32>(
+        sizeof(ValueType) +  // NOLINT
+        RoundSizeToMultipleOfEntries(size_in_bytes));
+  }
+
+  void SetHeader(uint32 size_in_bytes) {
+    header.SetCmdByTotalSize<ValueType>(size_in_bytes);
+  }
+
+  void Init(
+      GLenum _target, GLint _level, GLenum _internalformat, GLsizei _width,
+      GLsizei _height, GLint _border, GLsizei _imageSize) {
+    uint32 total_size = ComputeSize(_imageSize);
+    SetHeader(total_size);
+    target = _target;
+    level = _level;
+    internalformat = _internalformat;
+    width = _width;
+    height = _height;
+    border = _border;
+    imageSize = _imageSize;
+  }
+
+  void* Set(
+      void* cmd, GLenum _target, GLint _level, GLenum _internalformat,
+      GLsizei _width, GLsizei _height, GLint _border, GLsizei _imageSize) {
+    uint32 total_size = ComputeSize(_imageSize);
+    static_cast<ValueType*>(
+        cmd)->Init(
+            _target, _level, _internalformat, _width, _height, _border,
+            _imageSize);
+    return NextImmediateCmdAddressTotalSize<ValueType>(cmd, total_size);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 target;
+  uint32 level;
+  uint32 internalformat;
+  uint32 width;
+  uint32 height;
+  uint32 border;
+  uint32 imageSize;
+};
+
+COMPILE_ASSERT(sizeof(CompressedTexImage2DImmediate) == 32,
+               Sizeof_CompressedTexImage2DImmediate_is_not_32);
+COMPILE_ASSERT(offsetof(CompressedTexImage2DImmediate, header) == 0,
+               OffsetOf_CompressedTexImage2DImmediate_header_not_0);
+COMPILE_ASSERT(offsetof(CompressedTexImage2DImmediate, target) == 4,
+               OffsetOf_CompressedTexImage2DImmediate_target_not_4);
+COMPILE_ASSERT(offsetof(CompressedTexImage2DImmediate, level) == 8,
+               OffsetOf_CompressedTexImage2DImmediate_level_not_8);
+COMPILE_ASSERT(offsetof(CompressedTexImage2DImmediate, internalformat) == 12,
+               OffsetOf_CompressedTexImage2DImmediate_internalformat_not_12);
+COMPILE_ASSERT(offsetof(CompressedTexImage2DImmediate, width) == 16,
+               OffsetOf_CompressedTexImage2DImmediate_width_not_16);
+COMPILE_ASSERT(offsetof(CompressedTexImage2DImmediate, height) == 20,
+               OffsetOf_CompressedTexImage2DImmediate_height_not_20);
+COMPILE_ASSERT(offsetof(CompressedTexImage2DImmediate, border) == 24,
+               OffsetOf_CompressedTexImage2DImmediate_border_not_24);
+COMPILE_ASSERT(offsetof(CompressedTexImage2DImmediate, imageSize) == 28,
+               OffsetOf_CompressedTexImage2DImmediate_imageSize_not_28);
+
+struct CompressedTexSubImage2D {
+  typedef CompressedTexSubImage2D ValueType;
+  static const CommandId kCmdId = kCompressedTexSubImage2D;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLenum _target, GLint _level, GLint _xoffset, GLint _yoffset,
+      GLsizei _width, GLsizei _height, GLenum _format, GLsizei _imageSize,
+      uint32 _data_shm_id, uint32 _data_shm_offset) {
+    SetHeader();
+    target = _target;
+    level = _level;
+    xoffset = _xoffset;
+    yoffset = _yoffset;
+    width = _width;
+    height = _height;
+    format = _format;
+    imageSize = _imageSize;
+    data_shm_id = _data_shm_id;
+    data_shm_offset = _data_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLenum _target, GLint _level, GLint _xoffset, GLint _yoffset,
+      GLsizei _width, GLsizei _height, GLenum _format, GLsizei _imageSize,
+      uint32 _data_shm_id, uint32 _data_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(
+            _target, _level, _xoffset, _yoffset, _width, _height, _format,
+            _imageSize, _data_shm_id, _data_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 target;
+  uint32 level;
+  uint32 xoffset;
+  uint32 yoffset;
+  uint32 width;
+  uint32 height;
+  uint32 format;
+  uint32 imageSize;
+  uint32 data_shm_id;
+  uint32 data_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(CompressedTexSubImage2D) == 44,
+               Sizeof_CompressedTexSubImage2D_is_not_44);
+COMPILE_ASSERT(offsetof(CompressedTexSubImage2D, header) == 0,
+               OffsetOf_CompressedTexSubImage2D_header_not_0);
+COMPILE_ASSERT(offsetof(CompressedTexSubImage2D, target) == 4,
+               OffsetOf_CompressedTexSubImage2D_target_not_4);
+COMPILE_ASSERT(offsetof(CompressedTexSubImage2D, level) == 8,
+               OffsetOf_CompressedTexSubImage2D_level_not_8);
+COMPILE_ASSERT(offsetof(CompressedTexSubImage2D, xoffset) == 12,
+               OffsetOf_CompressedTexSubImage2D_xoffset_not_12);
+COMPILE_ASSERT(offsetof(CompressedTexSubImage2D, yoffset) == 16,
+               OffsetOf_CompressedTexSubImage2D_yoffset_not_16);
+COMPILE_ASSERT(offsetof(CompressedTexSubImage2D, width) == 20,
+               OffsetOf_CompressedTexSubImage2D_width_not_20);
+COMPILE_ASSERT(offsetof(CompressedTexSubImage2D, height) == 24,
+               OffsetOf_CompressedTexSubImage2D_height_not_24);
+COMPILE_ASSERT(offsetof(CompressedTexSubImage2D, format) == 28,
+               OffsetOf_CompressedTexSubImage2D_format_not_28);
+COMPILE_ASSERT(offsetof(CompressedTexSubImage2D, imageSize) == 32,
+               OffsetOf_CompressedTexSubImage2D_imageSize_not_32);
+COMPILE_ASSERT(offsetof(CompressedTexSubImage2D, data_shm_id) == 36,
+               OffsetOf_CompressedTexSubImage2D_data_shm_id_not_36);
+COMPILE_ASSERT(offsetof(CompressedTexSubImage2D, data_shm_offset) == 40,
+               OffsetOf_CompressedTexSubImage2D_data_shm_offset_not_40);
+
+struct CompressedTexSubImage2DImmediate {
+  typedef CompressedTexSubImage2DImmediate ValueType;
+  static const CommandId kCmdId = kCompressedTexSubImage2DImmediate;
+  static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN;
+
+  static uint32 ComputeSize(uint32 size_in_bytes) {
+    return static_cast<uint32>(
+        sizeof(ValueType) +  // NOLINT
+        RoundSizeToMultipleOfEntries(size_in_bytes));
+  }
+
+  void SetHeader(uint32 size_in_bytes) {
+    header.SetCmdByTotalSize<ValueType>(size_in_bytes);
+  }
+
+  void Init(
+      GLenum _target, GLint _level, GLint _xoffset, GLint _yoffset,
+      GLsizei _width, GLsizei _height, GLenum _format, GLsizei _imageSize) {
+    uint32 total_size = ComputeSize(_imageSize);
+    SetHeader(total_size);
+    target = _target;
+    level = _level;
+    xoffset = _xoffset;
+    yoffset = _yoffset;
+    width = _width;
+    height = _height;
+    format = _format;
+    imageSize = _imageSize;
+  }
+
+  void* Set(
+      void* cmd, GLenum _target, GLint _level, GLint _xoffset, GLint _yoffset,
+      GLsizei _width, GLsizei _height, GLenum _format, GLsizei _imageSize) {
+    uint32 total_size = ComputeSize(_imageSize);
+    static_cast<ValueType*>(
+        cmd)->Init(
+            _target, _level, _xoffset, _yoffset, _width, _height, _format,
+            _imageSize);
+    return NextImmediateCmdAddressTotalSize<ValueType>(cmd, total_size);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 target;
+  uint32 level;
+  uint32 xoffset;
+  uint32 yoffset;
+  uint32 width;
+  uint32 height;
+  uint32 format;
+  uint32 imageSize;
+};
+
+COMPILE_ASSERT(sizeof(CompressedTexSubImage2DImmediate) == 36,
+               Sizeof_CompressedTexSubImage2DImmediate_is_not_36);
+COMPILE_ASSERT(offsetof(CompressedTexSubImage2DImmediate, header) == 0,
+               OffsetOf_CompressedTexSubImage2DImmediate_header_not_0);
+COMPILE_ASSERT(offsetof(CompressedTexSubImage2DImmediate, target) == 4,
+               OffsetOf_CompressedTexSubImage2DImmediate_target_not_4);
+COMPILE_ASSERT(offsetof(CompressedTexSubImage2DImmediate, level) == 8,
+               OffsetOf_CompressedTexSubImage2DImmediate_level_not_8);
+COMPILE_ASSERT(offsetof(CompressedTexSubImage2DImmediate, xoffset) == 12,
+               OffsetOf_CompressedTexSubImage2DImmediate_xoffset_not_12);
+COMPILE_ASSERT(offsetof(CompressedTexSubImage2DImmediate, yoffset) == 16,
+               OffsetOf_CompressedTexSubImage2DImmediate_yoffset_not_16);
+COMPILE_ASSERT(offsetof(CompressedTexSubImage2DImmediate, width) == 20,
+               OffsetOf_CompressedTexSubImage2DImmediate_width_not_20);
+COMPILE_ASSERT(offsetof(CompressedTexSubImage2DImmediate, height) == 24,
+               OffsetOf_CompressedTexSubImage2DImmediate_height_not_24);
+COMPILE_ASSERT(offsetof(CompressedTexSubImage2DImmediate, format) == 28,
+               OffsetOf_CompressedTexSubImage2DImmediate_format_not_28);
+COMPILE_ASSERT(offsetof(CompressedTexSubImage2DImmediate, imageSize) == 32,
+               OffsetOf_CompressedTexSubImage2DImmediate_imageSize_not_32);
+
+struct CopyTexImage2D {
+  typedef CopyTexImage2D ValueType;
+  static const CommandId kCmdId = kCopyTexImage2D;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLenum _target, GLint _level, GLenum _internalformat, GLint _x, GLint _y,
+      GLsizei _width, GLsizei _height, GLint _border) {
+    SetHeader();
+    target = _target;
+    level = _level;
+    internalformat = _internalformat;
+    x = _x;
+    y = _y;
+    width = _width;
+    height = _height;
+    border = _border;
+  }
+
+  void* Set(
+      void* cmd, GLenum _target, GLint _level, GLenum _internalformat, GLint _x,
+      GLint _y, GLsizei _width, GLsizei _height, GLint _border) {
+    static_cast<ValueType*>(
+        cmd)->Init(
+            _target, _level, _internalformat, _x, _y, _width, _height,
+            _border);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 target;
+  uint32 level;
+  uint32 internalformat;
+  uint32 x;
+  uint32 y;
+  uint32 width;
+  uint32 height;
+  uint32 border;
+};
+
+COMPILE_ASSERT(sizeof(CopyTexImage2D) == 36,
+               Sizeof_CopyTexImage2D_is_not_36);
+COMPILE_ASSERT(offsetof(CopyTexImage2D, header) == 0,
+               OffsetOf_CopyTexImage2D_header_not_0);
+COMPILE_ASSERT(offsetof(CopyTexImage2D, target) == 4,
+               OffsetOf_CopyTexImage2D_target_not_4);
+COMPILE_ASSERT(offsetof(CopyTexImage2D, level) == 8,
+               OffsetOf_CopyTexImage2D_level_not_8);
+COMPILE_ASSERT(offsetof(CopyTexImage2D, internalformat) == 12,
+               OffsetOf_CopyTexImage2D_internalformat_not_12);
+COMPILE_ASSERT(offsetof(CopyTexImage2D, x) == 16,
+               OffsetOf_CopyTexImage2D_x_not_16);
+COMPILE_ASSERT(offsetof(CopyTexImage2D, y) == 20,
+               OffsetOf_CopyTexImage2D_y_not_20);
+COMPILE_ASSERT(offsetof(CopyTexImage2D, width) == 24,
+               OffsetOf_CopyTexImage2D_width_not_24);
+COMPILE_ASSERT(offsetof(CopyTexImage2D, height) == 28,
+               OffsetOf_CopyTexImage2D_height_not_28);
+COMPILE_ASSERT(offsetof(CopyTexImage2D, border) == 32,
+               OffsetOf_CopyTexImage2D_border_not_32);
+
+struct CopyTexSubImage2D {
+  typedef CopyTexSubImage2D ValueType;
+  static const CommandId kCmdId = kCopyTexSubImage2D;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLenum _target, GLint _level, GLint _xoffset, GLint _yoffset, GLint _x,
+      GLint _y, GLsizei _width, GLsizei _height) {
+    SetHeader();
+    target = _target;
+    level = _level;
+    xoffset = _xoffset;
+    yoffset = _yoffset;
+    x = _x;
+    y = _y;
+    width = _width;
+    height = _height;
+  }
+
+  void* Set(
+      void* cmd, GLenum _target, GLint _level, GLint _xoffset, GLint _yoffset,
+      GLint _x, GLint _y, GLsizei _width, GLsizei _height) {
+    static_cast<ValueType*>(
+        cmd)->Init(
+            _target, _level, _xoffset, _yoffset, _x, _y, _width, _height);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 target;
+  uint32 level;
+  uint32 xoffset;
+  uint32 yoffset;
+  uint32 x;
+  uint32 y;
+  uint32 width;
+  uint32 height;
+};
+
+COMPILE_ASSERT(sizeof(CopyTexSubImage2D) == 36,
+               Sizeof_CopyTexSubImage2D_is_not_36);
+COMPILE_ASSERT(offsetof(CopyTexSubImage2D, header) == 0,
+               OffsetOf_CopyTexSubImage2D_header_not_0);
+COMPILE_ASSERT(offsetof(CopyTexSubImage2D, target) == 4,
+               OffsetOf_CopyTexSubImage2D_target_not_4);
+COMPILE_ASSERT(offsetof(CopyTexSubImage2D, level) == 8,
+               OffsetOf_CopyTexSubImage2D_level_not_8);
+COMPILE_ASSERT(offsetof(CopyTexSubImage2D, xoffset) == 12,
+               OffsetOf_CopyTexSubImage2D_xoffset_not_12);
+COMPILE_ASSERT(offsetof(CopyTexSubImage2D, yoffset) == 16,
+               OffsetOf_CopyTexSubImage2D_yoffset_not_16);
+COMPILE_ASSERT(offsetof(CopyTexSubImage2D, x) == 20,
+               OffsetOf_CopyTexSubImage2D_x_not_20);
+COMPILE_ASSERT(offsetof(CopyTexSubImage2D, y) == 24,
+               OffsetOf_CopyTexSubImage2D_y_not_24);
+COMPILE_ASSERT(offsetof(CopyTexSubImage2D, width) == 28,
+               OffsetOf_CopyTexSubImage2D_width_not_28);
+COMPILE_ASSERT(offsetof(CopyTexSubImage2D, height) == 32,
+               OffsetOf_CopyTexSubImage2D_height_not_32);
+
+struct CreateProgram {
+  typedef CreateProgram ValueType;
+  static const CommandId kCmdId = kCreateProgram;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(uint32 _client_id) {
+    SetHeader();
+    client_id = _client_id;
+  }
+
+  void* Set(void* cmd, uint32 _client_id) {
+    static_cast<ValueType*>(cmd)->Init(_client_id);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 client_id;
+};
+
+COMPILE_ASSERT(sizeof(CreateProgram) == 8,
+               Sizeof_CreateProgram_is_not_8);
+COMPILE_ASSERT(offsetof(CreateProgram, header) == 0,
+               OffsetOf_CreateProgram_header_not_0);
+COMPILE_ASSERT(offsetof(CreateProgram, client_id) == 4,
+               OffsetOf_CreateProgram_client_id_not_4);
+
+struct CreateShader {
+  typedef CreateShader ValueType;
+  static const CommandId kCmdId = kCreateShader;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLenum _type, uint32 _client_id) {
+    SetHeader();
+    type = _type;
+    client_id = _client_id;
+  }
+
+  void* Set(void* cmd, GLenum _type, uint32 _client_id) {
+    static_cast<ValueType*>(cmd)->Init(_type, _client_id);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 type;
+  uint32 client_id;
+};
+
+COMPILE_ASSERT(sizeof(CreateShader) == 12,
+               Sizeof_CreateShader_is_not_12);
+COMPILE_ASSERT(offsetof(CreateShader, header) == 0,
+               OffsetOf_CreateShader_header_not_0);
+COMPILE_ASSERT(offsetof(CreateShader, type) == 4,
+               OffsetOf_CreateShader_type_not_4);
+COMPILE_ASSERT(offsetof(CreateShader, client_id) == 8,
+               OffsetOf_CreateShader_client_id_not_8);
+
+struct CullFace {
+  typedef CullFace ValueType;
+  static const CommandId kCmdId = kCullFace;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLenum _mode) {
+    SetHeader();
+    mode = _mode;
+  }
+
+  void* Set(void* cmd, GLenum _mode) {
+    static_cast<ValueType*>(cmd)->Init(_mode);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 mode;
+};
+
+COMPILE_ASSERT(sizeof(CullFace) == 8,
+               Sizeof_CullFace_is_not_8);
+COMPILE_ASSERT(offsetof(CullFace, header) == 0,
+               OffsetOf_CullFace_header_not_0);
+COMPILE_ASSERT(offsetof(CullFace, mode) == 4,
+               OffsetOf_CullFace_mode_not_4);
+
+struct DeleteBuffers {
+  typedef DeleteBuffers ValueType;
+  static const CommandId kCmdId = kDeleteBuffers;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLsizei _n, uint32 _buffers_shm_id, uint32 _buffers_shm_offset) {
+    SetHeader();
+    n = _n;
+    buffers_shm_id = _buffers_shm_id;
+    buffers_shm_offset = _buffers_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLsizei _n, uint32 _buffers_shm_id,
+      uint32 _buffers_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(_n, _buffers_shm_id, _buffers_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 n;
+  uint32 buffers_shm_id;
+  uint32 buffers_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(DeleteBuffers) == 16,
+               Sizeof_DeleteBuffers_is_not_16);
+COMPILE_ASSERT(offsetof(DeleteBuffers, header) == 0,
+               OffsetOf_DeleteBuffers_header_not_0);
+COMPILE_ASSERT(offsetof(DeleteBuffers, n) == 4,
+               OffsetOf_DeleteBuffers_n_not_4);
+COMPILE_ASSERT(offsetof(DeleteBuffers, buffers_shm_id) == 8,
+               OffsetOf_DeleteBuffers_buffers_shm_id_not_8);
+COMPILE_ASSERT(offsetof(DeleteBuffers, buffers_shm_offset) == 12,
+               OffsetOf_DeleteBuffers_buffers_shm_offset_not_12);
+
+struct DeleteBuffersImmediate {
+  typedef DeleteBuffersImmediate ValueType;
+  static const CommandId kCmdId = kDeleteBuffersImmediate;
+  static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN;
+
+  static uint32 ComputeDataSize(GLsizei n) {
+    return static_cast<uint32>(sizeof(GLuint) * n);  // NOLINT
+  }
+
+  static uint32 ComputeSize(GLsizei n) {
+    return static_cast<uint32>(
+        sizeof(ValueType) + ComputeDataSize(n));  // NOLINT
+  }
+
+  void SetHeader(GLsizei n) {
+    header.SetCmdByTotalSize<ValueType>(ComputeSize(n));
+  }
+
+  void Init(GLsizei _n, const GLuint* _buffers) {
+    SetHeader(_n);
+    n = _n;
+    memcpy(ImmediateDataAddress(this),
+           _buffers, ComputeDataSize(_n));
+  }
+
+  void* Set(void* cmd, GLsizei _n, const GLuint* _buffers) {
+    static_cast<ValueType*>(cmd)->Init(_n, _buffers);
+    const uint32 size = ComputeSize(_n);
+    return NextImmediateCmdAddressTotalSize<ValueType>(cmd, size);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 n;
+};
+
+COMPILE_ASSERT(sizeof(DeleteBuffersImmediate) == 8,
+               Sizeof_DeleteBuffersImmediate_is_not_8);
+COMPILE_ASSERT(offsetof(DeleteBuffersImmediate, header) == 0,
+               OffsetOf_DeleteBuffersImmediate_header_not_0);
+COMPILE_ASSERT(offsetof(DeleteBuffersImmediate, n) == 4,
+               OffsetOf_DeleteBuffersImmediate_n_not_4);
+
+struct DeleteFramebuffers {
+  typedef DeleteFramebuffers ValueType;
+  static const CommandId kCmdId = kDeleteFramebuffers;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLsizei _n, uint32 _framebuffers_shm_id,
+      uint32 _framebuffers_shm_offset) {
+    SetHeader();
+    n = _n;
+    framebuffers_shm_id = _framebuffers_shm_id;
+    framebuffers_shm_offset = _framebuffers_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLsizei _n, uint32 _framebuffers_shm_id,
+      uint32 _framebuffers_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(_n, _framebuffers_shm_id, _framebuffers_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 n;
+  uint32 framebuffers_shm_id;
+  uint32 framebuffers_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(DeleteFramebuffers) == 16,
+               Sizeof_DeleteFramebuffers_is_not_16);
+COMPILE_ASSERT(offsetof(DeleteFramebuffers, header) == 0,
+               OffsetOf_DeleteFramebuffers_header_not_0);
+COMPILE_ASSERT(offsetof(DeleteFramebuffers, n) == 4,
+               OffsetOf_DeleteFramebuffers_n_not_4);
+COMPILE_ASSERT(offsetof(DeleteFramebuffers, framebuffers_shm_id) == 8,
+               OffsetOf_DeleteFramebuffers_framebuffers_shm_id_not_8);
+COMPILE_ASSERT(offsetof(DeleteFramebuffers, framebuffers_shm_offset) == 12,
+               OffsetOf_DeleteFramebuffers_framebuffers_shm_offset_not_12);
+
+struct DeleteFramebuffersImmediate {
+  typedef DeleteFramebuffersImmediate ValueType;
+  static const CommandId kCmdId = kDeleteFramebuffersImmediate;
+  static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN;
+
+  static uint32 ComputeDataSize(GLsizei n) {
+    return static_cast<uint32>(sizeof(GLuint) * n);  // NOLINT
+  }
+
+  static uint32 ComputeSize(GLsizei n) {
+    return static_cast<uint32>(
+        sizeof(ValueType) + ComputeDataSize(n));  // NOLINT
+  }
+
+  void SetHeader(GLsizei n) {
+    header.SetCmdByTotalSize<ValueType>(ComputeSize(n));
+  }
+
+  void Init(GLsizei _n, const GLuint* _framebuffers) {
+    SetHeader(_n);
+    n = _n;
+    memcpy(ImmediateDataAddress(this),
+           _framebuffers, ComputeDataSize(_n));
+  }
+
+  void* Set(void* cmd, GLsizei _n, const GLuint* _framebuffers) {
+    static_cast<ValueType*>(cmd)->Init(_n, _framebuffers);
+    const uint32 size = ComputeSize(_n);
+    return NextImmediateCmdAddressTotalSize<ValueType>(cmd, size);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 n;
+};
+
+COMPILE_ASSERT(sizeof(DeleteFramebuffersImmediate) == 8,
+               Sizeof_DeleteFramebuffersImmediate_is_not_8);
+COMPILE_ASSERT(offsetof(DeleteFramebuffersImmediate, header) == 0,
+               OffsetOf_DeleteFramebuffersImmediate_header_not_0);
+COMPILE_ASSERT(offsetof(DeleteFramebuffersImmediate, n) == 4,
+               OffsetOf_DeleteFramebuffersImmediate_n_not_4);
+
+struct DeleteProgram {
+  typedef DeleteProgram ValueType;
+  static const CommandId kCmdId = kDeleteProgram;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLuint _program) {
+    SetHeader();
+    program = _program;
+  }
+
+  void* Set(void* cmd, GLuint _program) {
+    static_cast<ValueType*>(cmd)->Init(_program);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 program;
+};
+
+COMPILE_ASSERT(sizeof(DeleteProgram) == 8,
+               Sizeof_DeleteProgram_is_not_8);
+COMPILE_ASSERT(offsetof(DeleteProgram, header) == 0,
+               OffsetOf_DeleteProgram_header_not_0);
+COMPILE_ASSERT(offsetof(DeleteProgram, program) == 4,
+               OffsetOf_DeleteProgram_program_not_4);
+
+struct DeleteRenderbuffers {
+  typedef DeleteRenderbuffers ValueType;
+  static const CommandId kCmdId = kDeleteRenderbuffers;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLsizei _n, uint32 _renderbuffers_shm_id,
+      uint32 _renderbuffers_shm_offset) {
+    SetHeader();
+    n = _n;
+    renderbuffers_shm_id = _renderbuffers_shm_id;
+    renderbuffers_shm_offset = _renderbuffers_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLsizei _n, uint32 _renderbuffers_shm_id,
+      uint32 _renderbuffers_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(_n, _renderbuffers_shm_id, _renderbuffers_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 n;
+  uint32 renderbuffers_shm_id;
+  uint32 renderbuffers_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(DeleteRenderbuffers) == 16,
+               Sizeof_DeleteRenderbuffers_is_not_16);
+COMPILE_ASSERT(offsetof(DeleteRenderbuffers, header) == 0,
+               OffsetOf_DeleteRenderbuffers_header_not_0);
+COMPILE_ASSERT(offsetof(DeleteRenderbuffers, n) == 4,
+               OffsetOf_DeleteRenderbuffers_n_not_4);
+COMPILE_ASSERT(offsetof(DeleteRenderbuffers, renderbuffers_shm_id) == 8,
+               OffsetOf_DeleteRenderbuffers_renderbuffers_shm_id_not_8);
+COMPILE_ASSERT(offsetof(DeleteRenderbuffers, renderbuffers_shm_offset) == 12,
+               OffsetOf_DeleteRenderbuffers_renderbuffers_shm_offset_not_12);
+
+struct DeleteRenderbuffersImmediate {
+  typedef DeleteRenderbuffersImmediate ValueType;
+  static const CommandId kCmdId = kDeleteRenderbuffersImmediate;
+  static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN;
+
+  static uint32 ComputeDataSize(GLsizei n) {
+    return static_cast<uint32>(sizeof(GLuint) * n);  // NOLINT
+  }
+
+  static uint32 ComputeSize(GLsizei n) {
+    return static_cast<uint32>(
+        sizeof(ValueType) + ComputeDataSize(n));  // NOLINT
+  }
+
+  void SetHeader(GLsizei n) {
+    header.SetCmdByTotalSize<ValueType>(ComputeSize(n));
+  }
+
+  void Init(GLsizei _n, const GLuint* _renderbuffers) {
+    SetHeader(_n);
+    n = _n;
+    memcpy(ImmediateDataAddress(this),
+           _renderbuffers, ComputeDataSize(_n));
+  }
+
+  void* Set(void* cmd, GLsizei _n, const GLuint* _renderbuffers) {
+    static_cast<ValueType*>(cmd)->Init(_n, _renderbuffers);
+    const uint32 size = ComputeSize(_n);
+    return NextImmediateCmdAddressTotalSize<ValueType>(cmd, size);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 n;
+};
+
+COMPILE_ASSERT(sizeof(DeleteRenderbuffersImmediate) == 8,
+               Sizeof_DeleteRenderbuffersImmediate_is_not_8);
+COMPILE_ASSERT(offsetof(DeleteRenderbuffersImmediate, header) == 0,
+               OffsetOf_DeleteRenderbuffersImmediate_header_not_0);
+COMPILE_ASSERT(offsetof(DeleteRenderbuffersImmediate, n) == 4,
+               OffsetOf_DeleteRenderbuffersImmediate_n_not_4);
+
+struct DeleteShader {
+  typedef DeleteShader ValueType;
+  static const CommandId kCmdId = kDeleteShader;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLuint _shader) {
+    SetHeader();
+    shader = _shader;
+  }
+
+  void* Set(void* cmd, GLuint _shader) {
+    static_cast<ValueType*>(cmd)->Init(_shader);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 shader;
+};
+
+COMPILE_ASSERT(sizeof(DeleteShader) == 8,
+               Sizeof_DeleteShader_is_not_8);
+COMPILE_ASSERT(offsetof(DeleteShader, header) == 0,
+               OffsetOf_DeleteShader_header_not_0);
+COMPILE_ASSERT(offsetof(DeleteShader, shader) == 4,
+               OffsetOf_DeleteShader_shader_not_4);
+
+struct DeleteTextures {
+  typedef DeleteTextures ValueType;
+  static const CommandId kCmdId = kDeleteTextures;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLsizei _n, uint32 _textures_shm_id, uint32 _textures_shm_offset) {
+    SetHeader();
+    n = _n;
+    textures_shm_id = _textures_shm_id;
+    textures_shm_offset = _textures_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLsizei _n, uint32 _textures_shm_id,
+      uint32 _textures_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(_n, _textures_shm_id, _textures_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 n;
+  uint32 textures_shm_id;
+  uint32 textures_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(DeleteTextures) == 16,
+               Sizeof_DeleteTextures_is_not_16);
+COMPILE_ASSERT(offsetof(DeleteTextures, header) == 0,
+               OffsetOf_DeleteTextures_header_not_0);
+COMPILE_ASSERT(offsetof(DeleteTextures, n) == 4,
+               OffsetOf_DeleteTextures_n_not_4);
+COMPILE_ASSERT(offsetof(DeleteTextures, textures_shm_id) == 8,
+               OffsetOf_DeleteTextures_textures_shm_id_not_8);
+COMPILE_ASSERT(offsetof(DeleteTextures, textures_shm_offset) == 12,
+               OffsetOf_DeleteTextures_textures_shm_offset_not_12);
+
+struct DeleteTexturesImmediate {
+  typedef DeleteTexturesImmediate ValueType;
+  static const CommandId kCmdId = kDeleteTexturesImmediate;
+  static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN;
+
+  static uint32 ComputeDataSize(GLsizei n) {
+    return static_cast<uint32>(sizeof(GLuint) * n);  // NOLINT
+  }
+
+  static uint32 ComputeSize(GLsizei n) {
+    return static_cast<uint32>(
+        sizeof(ValueType) + ComputeDataSize(n));  // NOLINT
+  }
+
+  void SetHeader(GLsizei n) {
+    header.SetCmdByTotalSize<ValueType>(ComputeSize(n));
+  }
+
+  void Init(GLsizei _n, const GLuint* _textures) {
+    SetHeader(_n);
+    n = _n;
+    memcpy(ImmediateDataAddress(this),
+           _textures, ComputeDataSize(_n));
+  }
+
+  void* Set(void* cmd, GLsizei _n, const GLuint* _textures) {
+    static_cast<ValueType*>(cmd)->Init(_n, _textures);
+    const uint32 size = ComputeSize(_n);
+    return NextImmediateCmdAddressTotalSize<ValueType>(cmd, size);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 n;
+};
+
+COMPILE_ASSERT(sizeof(DeleteTexturesImmediate) == 8,
+               Sizeof_DeleteTexturesImmediate_is_not_8);
+COMPILE_ASSERT(offsetof(DeleteTexturesImmediate, header) == 0,
+               OffsetOf_DeleteTexturesImmediate_header_not_0);
+COMPILE_ASSERT(offsetof(DeleteTexturesImmediate, n) == 4,
+               OffsetOf_DeleteTexturesImmediate_n_not_4);
+
+struct DepthFunc {
+  typedef DepthFunc ValueType;
+  static const CommandId kCmdId = kDepthFunc;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLenum _func) {
+    SetHeader();
+    func = _func;
+  }
+
+  void* Set(void* cmd, GLenum _func) {
+    static_cast<ValueType*>(cmd)->Init(_func);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 func;
+};
+
+COMPILE_ASSERT(sizeof(DepthFunc) == 8,
+               Sizeof_DepthFunc_is_not_8);
+COMPILE_ASSERT(offsetof(DepthFunc, header) == 0,
+               OffsetOf_DepthFunc_header_not_0);
+COMPILE_ASSERT(offsetof(DepthFunc, func) == 4,
+               OffsetOf_DepthFunc_func_not_4);
+
+struct DepthMask {
+  typedef DepthMask ValueType;
+  static const CommandId kCmdId = kDepthMask;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLboolean _flag) {
+    SetHeader();
+    flag = _flag;
+  }
+
+  void* Set(void* cmd, GLboolean _flag) {
+    static_cast<ValueType*>(cmd)->Init(_flag);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 flag;
+};
+
+COMPILE_ASSERT(sizeof(DepthMask) == 8,
+               Sizeof_DepthMask_is_not_8);
+COMPILE_ASSERT(offsetof(DepthMask, header) == 0,
+               OffsetOf_DepthMask_header_not_0);
+COMPILE_ASSERT(offsetof(DepthMask, flag) == 4,
+               OffsetOf_DepthMask_flag_not_4);
+
+struct DepthRangef {
+  typedef DepthRangef ValueType;
+  static const CommandId kCmdId = kDepthRangef;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLclampf _zNear, GLclampf _zFar) {
+    SetHeader();
+    zNear = _zNear;
+    zFar = _zFar;
+  }
+
+  void* Set(void* cmd, GLclampf _zNear, GLclampf _zFar) {
+    static_cast<ValueType*>(cmd)->Init(_zNear, _zFar);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  float zNear;
+  float zFar;
+};
+
+COMPILE_ASSERT(sizeof(DepthRangef) == 12,
+               Sizeof_DepthRangef_is_not_12);
+COMPILE_ASSERT(offsetof(DepthRangef, header) == 0,
+               OffsetOf_DepthRangef_header_not_0);
+COMPILE_ASSERT(offsetof(DepthRangef, zNear) == 4,
+               OffsetOf_DepthRangef_zNear_not_4);
+COMPILE_ASSERT(offsetof(DepthRangef, zFar) == 8,
+               OffsetOf_DepthRangef_zFar_not_8);
+
+struct DetachShader {
+  typedef DetachShader ValueType;
+  static const CommandId kCmdId = kDetachShader;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLuint _program, GLuint _shader) {
+    SetHeader();
+    program = _program;
+    shader = _shader;
+  }
+
+  void* Set(void* cmd, GLuint _program, GLuint _shader) {
+    static_cast<ValueType*>(cmd)->Init(_program, _shader);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 program;
+  uint32 shader;
+};
+
+COMPILE_ASSERT(sizeof(DetachShader) == 12,
+               Sizeof_DetachShader_is_not_12);
+COMPILE_ASSERT(offsetof(DetachShader, header) == 0,
+               OffsetOf_DetachShader_header_not_0);
+COMPILE_ASSERT(offsetof(DetachShader, program) == 4,
+               OffsetOf_DetachShader_program_not_4);
+COMPILE_ASSERT(offsetof(DetachShader, shader) == 8,
+               OffsetOf_DetachShader_shader_not_8);
+
+struct Disable {
+  typedef Disable ValueType;
+  static const CommandId kCmdId = kDisable;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLenum _cap) {
+    SetHeader();
+    cap = _cap;
+  }
+
+  void* Set(void* cmd, GLenum _cap) {
+    static_cast<ValueType*>(cmd)->Init(_cap);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 cap;
+};
+
+COMPILE_ASSERT(sizeof(Disable) == 8,
+               Sizeof_Disable_is_not_8);
+COMPILE_ASSERT(offsetof(Disable, header) == 0,
+               OffsetOf_Disable_header_not_0);
+COMPILE_ASSERT(offsetof(Disable, cap) == 4,
+               OffsetOf_Disable_cap_not_4);
+
+struct DisableVertexAttribArray {
+  typedef DisableVertexAttribArray ValueType;
+  static const CommandId kCmdId = kDisableVertexAttribArray;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLuint _index) {
+    SetHeader();
+    index = _index;
+  }
+
+  void* Set(void* cmd, GLuint _index) {
+    static_cast<ValueType*>(cmd)->Init(_index);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 index;
+};
+
+COMPILE_ASSERT(sizeof(DisableVertexAttribArray) == 8,
+               Sizeof_DisableVertexAttribArray_is_not_8);
+COMPILE_ASSERT(offsetof(DisableVertexAttribArray, header) == 0,
+               OffsetOf_DisableVertexAttribArray_header_not_0);
+COMPILE_ASSERT(offsetof(DisableVertexAttribArray, index) == 4,
+               OffsetOf_DisableVertexAttribArray_index_not_4);
+
+struct DrawArrays {
+  typedef DrawArrays ValueType;
+  static const CommandId kCmdId = kDrawArrays;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLenum _mode, GLint _first, GLsizei _count) {
+    SetHeader();
+    mode = _mode;
+    first = _first;
+    count = _count;
+  }
+
+  void* Set(void* cmd, GLenum _mode, GLint _first, GLsizei _count) {
+    static_cast<ValueType*>(cmd)->Init(_mode, _first, _count);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 mode;
+  uint32 first;
+  uint32 count;
+};
+
+COMPILE_ASSERT(sizeof(DrawArrays) == 16,
+               Sizeof_DrawArrays_is_not_16);
+COMPILE_ASSERT(offsetof(DrawArrays, header) == 0,
+               OffsetOf_DrawArrays_header_not_0);
+COMPILE_ASSERT(offsetof(DrawArrays, mode) == 4,
+               OffsetOf_DrawArrays_mode_not_4);
+COMPILE_ASSERT(offsetof(DrawArrays, first) == 8,
+               OffsetOf_DrawArrays_first_not_8);
+COMPILE_ASSERT(offsetof(DrawArrays, count) == 12,
+               OffsetOf_DrawArrays_count_not_12);
+
+struct DrawElements {
+  typedef DrawElements ValueType;
+  static const CommandId kCmdId = kDrawElements;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLenum _mode, GLsizei _count, GLenum _type, GLuint _index_offset) {
+    SetHeader();
+    mode = _mode;
+    count = _count;
+    type = _type;
+    index_offset = _index_offset;
+  }
+
+  void* Set(
+      void* cmd, GLenum _mode, GLsizei _count, GLenum _type,
+      GLuint _index_offset) {
+    static_cast<ValueType*>(cmd)->Init(_mode, _count, _type, _index_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 mode;
+  uint32 count;
+  uint32 type;
+  uint32 index_offset;
+};
+
+COMPILE_ASSERT(sizeof(DrawElements) == 20,
+               Sizeof_DrawElements_is_not_20);
+COMPILE_ASSERT(offsetof(DrawElements, header) == 0,
+               OffsetOf_DrawElements_header_not_0);
+COMPILE_ASSERT(offsetof(DrawElements, mode) == 4,
+               OffsetOf_DrawElements_mode_not_4);
+COMPILE_ASSERT(offsetof(DrawElements, count) == 8,
+               OffsetOf_DrawElements_count_not_8);
+COMPILE_ASSERT(offsetof(DrawElements, type) == 12,
+               OffsetOf_DrawElements_type_not_12);
+COMPILE_ASSERT(offsetof(DrawElements, index_offset) == 16,
+               OffsetOf_DrawElements_index_offset_not_16);
+
+struct Enable {
+  typedef Enable ValueType;
+  static const CommandId kCmdId = kEnable;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLenum _cap) {
+    SetHeader();
+    cap = _cap;
+  }
+
+  void* Set(void* cmd, GLenum _cap) {
+    static_cast<ValueType*>(cmd)->Init(_cap);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 cap;
+};
+
+COMPILE_ASSERT(sizeof(Enable) == 8,
+               Sizeof_Enable_is_not_8);
+COMPILE_ASSERT(offsetof(Enable, header) == 0,
+               OffsetOf_Enable_header_not_0);
+COMPILE_ASSERT(offsetof(Enable, cap) == 4,
+               OffsetOf_Enable_cap_not_4);
+
+struct EnableVertexAttribArray {
+  typedef EnableVertexAttribArray ValueType;
+  static const CommandId kCmdId = kEnableVertexAttribArray;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLuint _index) {
+    SetHeader();
+    index = _index;
+  }
+
+  void* Set(void* cmd, GLuint _index) {
+    static_cast<ValueType*>(cmd)->Init(_index);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 index;
+};
+
+COMPILE_ASSERT(sizeof(EnableVertexAttribArray) == 8,
+               Sizeof_EnableVertexAttribArray_is_not_8);
+COMPILE_ASSERT(offsetof(EnableVertexAttribArray, header) == 0,
+               OffsetOf_EnableVertexAttribArray_header_not_0);
+COMPILE_ASSERT(offsetof(EnableVertexAttribArray, index) == 4,
+               OffsetOf_EnableVertexAttribArray_index_not_4);
+
+struct Finish {
+  typedef Finish ValueType;
+  static const CommandId kCmdId = kFinish;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init() {
+    SetHeader();
+  }
+
+  void* Set(void* cmd) {
+    static_cast<ValueType*>(cmd)->Init();
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+};
+
+COMPILE_ASSERT(sizeof(Finish) == 4,
+               Sizeof_Finish_is_not_4);
+COMPILE_ASSERT(offsetof(Finish, header) == 0,
+               OffsetOf_Finish_header_not_0);
+
+struct Flush {
+  typedef Flush ValueType;
+  static const CommandId kCmdId = kFlush;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init() {
+    SetHeader();
+  }
+
+  void* Set(void* cmd) {
+    static_cast<ValueType*>(cmd)->Init();
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+};
+
+COMPILE_ASSERT(sizeof(Flush) == 4,
+               Sizeof_Flush_is_not_4);
+COMPILE_ASSERT(offsetof(Flush, header) == 0,
+               OffsetOf_Flush_header_not_0);
+
+struct FramebufferRenderbuffer {
+  typedef FramebufferRenderbuffer ValueType;
+  static const CommandId kCmdId = kFramebufferRenderbuffer;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLenum _target, GLenum _attachment, GLenum _renderbuffertarget,
+      GLuint _renderbuffer) {
+    SetHeader();
+    target = _target;
+    attachment = _attachment;
+    renderbuffertarget = _renderbuffertarget;
+    renderbuffer = _renderbuffer;
+  }
+
+  void* Set(
+      void* cmd, GLenum _target, GLenum _attachment, GLenum _renderbuffertarget,
+      GLuint _renderbuffer) {
+    static_cast<ValueType*>(
+        cmd)->Init(_target, _attachment, _renderbuffertarget, _renderbuffer);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 target;
+  uint32 attachment;
+  uint32 renderbuffertarget;
+  uint32 renderbuffer;
+};
+
+COMPILE_ASSERT(sizeof(FramebufferRenderbuffer) == 20,
+               Sizeof_FramebufferRenderbuffer_is_not_20);
+COMPILE_ASSERT(offsetof(FramebufferRenderbuffer, header) == 0,
+               OffsetOf_FramebufferRenderbuffer_header_not_0);
+COMPILE_ASSERT(offsetof(FramebufferRenderbuffer, target) == 4,
+               OffsetOf_FramebufferRenderbuffer_target_not_4);
+COMPILE_ASSERT(offsetof(FramebufferRenderbuffer, attachment) == 8,
+               OffsetOf_FramebufferRenderbuffer_attachment_not_8);
+COMPILE_ASSERT(offsetof(FramebufferRenderbuffer, renderbuffertarget) == 12,
+               OffsetOf_FramebufferRenderbuffer_renderbuffertarget_not_12);
+COMPILE_ASSERT(offsetof(FramebufferRenderbuffer, renderbuffer) == 16,
+               OffsetOf_FramebufferRenderbuffer_renderbuffer_not_16);
+
+struct FramebufferTexture2D {
+  typedef FramebufferTexture2D ValueType;
+  static const CommandId kCmdId = kFramebufferTexture2D;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLenum _target, GLenum _attachment, GLenum _textarget, GLuint _texture,
+      GLint _level) {
+    SetHeader();
+    target = _target;
+    attachment = _attachment;
+    textarget = _textarget;
+    texture = _texture;
+    level = _level;
+  }
+
+  void* Set(
+      void* cmd, GLenum _target, GLenum _attachment, GLenum _textarget,
+      GLuint _texture, GLint _level) {
+    static_cast<ValueType*>(
+        cmd)->Init(_target, _attachment, _textarget, _texture, _level);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 target;
+  uint32 attachment;
+  uint32 textarget;
+  uint32 texture;
+  uint32 level;
+};
+
+COMPILE_ASSERT(sizeof(FramebufferTexture2D) == 24,
+               Sizeof_FramebufferTexture2D_is_not_24);
+COMPILE_ASSERT(offsetof(FramebufferTexture2D, header) == 0,
+               OffsetOf_FramebufferTexture2D_header_not_0);
+COMPILE_ASSERT(offsetof(FramebufferTexture2D, target) == 4,
+               OffsetOf_FramebufferTexture2D_target_not_4);
+COMPILE_ASSERT(offsetof(FramebufferTexture2D, attachment) == 8,
+               OffsetOf_FramebufferTexture2D_attachment_not_8);
+COMPILE_ASSERT(offsetof(FramebufferTexture2D, textarget) == 12,
+               OffsetOf_FramebufferTexture2D_textarget_not_12);
+COMPILE_ASSERT(offsetof(FramebufferTexture2D, texture) == 16,
+               OffsetOf_FramebufferTexture2D_texture_not_16);
+COMPILE_ASSERT(offsetof(FramebufferTexture2D, level) == 20,
+               OffsetOf_FramebufferTexture2D_level_not_20);
+
+struct FrontFace {
+  typedef FrontFace ValueType;
+  static const CommandId kCmdId = kFrontFace;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLenum _mode) {
+    SetHeader();
+    mode = _mode;
+  }
+
+  void* Set(void* cmd, GLenum _mode) {
+    static_cast<ValueType*>(cmd)->Init(_mode);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 mode;
+};
+
+COMPILE_ASSERT(sizeof(FrontFace) == 8,
+               Sizeof_FrontFace_is_not_8);
+COMPILE_ASSERT(offsetof(FrontFace, header) == 0,
+               OffsetOf_FrontFace_header_not_0);
+COMPILE_ASSERT(offsetof(FrontFace, mode) == 4,
+               OffsetOf_FrontFace_mode_not_4);
+
+struct GenBuffers {
+  typedef GenBuffers ValueType;
+  static const CommandId kCmdId = kGenBuffers;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLsizei _n, uint32 _buffers_shm_id, uint32 _buffers_shm_offset) {
+    SetHeader();
+    n = _n;
+    buffers_shm_id = _buffers_shm_id;
+    buffers_shm_offset = _buffers_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLsizei _n, uint32 _buffers_shm_id,
+      uint32 _buffers_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(_n, _buffers_shm_id, _buffers_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 n;
+  uint32 buffers_shm_id;
+  uint32 buffers_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(GenBuffers) == 16,
+               Sizeof_GenBuffers_is_not_16);
+COMPILE_ASSERT(offsetof(GenBuffers, header) == 0,
+               OffsetOf_GenBuffers_header_not_0);
+COMPILE_ASSERT(offsetof(GenBuffers, n) == 4,
+               OffsetOf_GenBuffers_n_not_4);
+COMPILE_ASSERT(offsetof(GenBuffers, buffers_shm_id) == 8,
+               OffsetOf_GenBuffers_buffers_shm_id_not_8);
+COMPILE_ASSERT(offsetof(GenBuffers, buffers_shm_offset) == 12,
+               OffsetOf_GenBuffers_buffers_shm_offset_not_12);
+
+struct GenBuffersImmediate {
+  typedef GenBuffersImmediate ValueType;
+  static const CommandId kCmdId = kGenBuffersImmediate;
+  static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN;
+
+  static uint32 ComputeDataSize(GLsizei n) {
+    return static_cast<uint32>(sizeof(GLuint) * n);  // NOLINT
+  }
+
+  static uint32 ComputeSize(GLsizei n) {
+    return static_cast<uint32>(
+        sizeof(ValueType) + ComputeDataSize(n));  // NOLINT
+  }
+
+  void SetHeader(GLsizei n) {
+    header.SetCmdByTotalSize<ValueType>(ComputeSize(n));
+  }
+
+  void Init(GLsizei _n, GLuint* _buffers) {
+    SetHeader(_n);
+    n = _n;
+    memcpy(ImmediateDataAddress(this),
+           _buffers, ComputeDataSize(_n));
+  }
+
+  void* Set(void* cmd, GLsizei _n, GLuint* _buffers) {
+    static_cast<ValueType*>(cmd)->Init(_n, _buffers);
+    const uint32 size = ComputeSize(_n);
+    return NextImmediateCmdAddressTotalSize<ValueType>(cmd, size);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 n;
+};
+
+COMPILE_ASSERT(sizeof(GenBuffersImmediate) == 8,
+               Sizeof_GenBuffersImmediate_is_not_8);
+COMPILE_ASSERT(offsetof(GenBuffersImmediate, header) == 0,
+               OffsetOf_GenBuffersImmediate_header_not_0);
+COMPILE_ASSERT(offsetof(GenBuffersImmediate, n) == 4,
+               OffsetOf_GenBuffersImmediate_n_not_4);
+
+struct GenerateMipmap {
+  typedef GenerateMipmap ValueType;
+  static const CommandId kCmdId = kGenerateMipmap;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLenum _target) {
+    SetHeader();
+    target = _target;
+  }
+
+  void* Set(void* cmd, GLenum _target) {
+    static_cast<ValueType*>(cmd)->Init(_target);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 target;
+};
+
+COMPILE_ASSERT(sizeof(GenerateMipmap) == 8,
+               Sizeof_GenerateMipmap_is_not_8);
+COMPILE_ASSERT(offsetof(GenerateMipmap, header) == 0,
+               OffsetOf_GenerateMipmap_header_not_0);
+COMPILE_ASSERT(offsetof(GenerateMipmap, target) == 4,
+               OffsetOf_GenerateMipmap_target_not_4);
+
+struct GenFramebuffers {
+  typedef GenFramebuffers ValueType;
+  static const CommandId kCmdId = kGenFramebuffers;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLsizei _n, uint32 _framebuffers_shm_id,
+      uint32 _framebuffers_shm_offset) {
+    SetHeader();
+    n = _n;
+    framebuffers_shm_id = _framebuffers_shm_id;
+    framebuffers_shm_offset = _framebuffers_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLsizei _n, uint32 _framebuffers_shm_id,
+      uint32 _framebuffers_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(_n, _framebuffers_shm_id, _framebuffers_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 n;
+  uint32 framebuffers_shm_id;
+  uint32 framebuffers_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(GenFramebuffers) == 16,
+               Sizeof_GenFramebuffers_is_not_16);
+COMPILE_ASSERT(offsetof(GenFramebuffers, header) == 0,
+               OffsetOf_GenFramebuffers_header_not_0);
+COMPILE_ASSERT(offsetof(GenFramebuffers, n) == 4,
+               OffsetOf_GenFramebuffers_n_not_4);
+COMPILE_ASSERT(offsetof(GenFramebuffers, framebuffers_shm_id) == 8,
+               OffsetOf_GenFramebuffers_framebuffers_shm_id_not_8);
+COMPILE_ASSERT(offsetof(GenFramebuffers, framebuffers_shm_offset) == 12,
+               OffsetOf_GenFramebuffers_framebuffers_shm_offset_not_12);
+
+struct GenFramebuffersImmediate {
+  typedef GenFramebuffersImmediate ValueType;
+  static const CommandId kCmdId = kGenFramebuffersImmediate;
+  static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN;
+
+  static uint32 ComputeDataSize(GLsizei n) {
+    return static_cast<uint32>(sizeof(GLuint) * n);  // NOLINT
+  }
+
+  static uint32 ComputeSize(GLsizei n) {
+    return static_cast<uint32>(
+        sizeof(ValueType) + ComputeDataSize(n));  // NOLINT
+  }
+
+  void SetHeader(GLsizei n) {
+    header.SetCmdByTotalSize<ValueType>(ComputeSize(n));
+  }
+
+  void Init(GLsizei _n, GLuint* _framebuffers) {
+    SetHeader(_n);
+    n = _n;
+    memcpy(ImmediateDataAddress(this),
+           _framebuffers, ComputeDataSize(_n));
+  }
+
+  void* Set(void* cmd, GLsizei _n, GLuint* _framebuffers) {
+    static_cast<ValueType*>(cmd)->Init(_n, _framebuffers);
+    const uint32 size = ComputeSize(_n);
+    return NextImmediateCmdAddressTotalSize<ValueType>(cmd, size);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 n;
+};
+
+COMPILE_ASSERT(sizeof(GenFramebuffersImmediate) == 8,
+               Sizeof_GenFramebuffersImmediate_is_not_8);
+COMPILE_ASSERT(offsetof(GenFramebuffersImmediate, header) == 0,
+               OffsetOf_GenFramebuffersImmediate_header_not_0);
+COMPILE_ASSERT(offsetof(GenFramebuffersImmediate, n) == 4,
+               OffsetOf_GenFramebuffersImmediate_n_not_4);
+
+struct GenRenderbuffers {
+  typedef GenRenderbuffers ValueType;
+  static const CommandId kCmdId = kGenRenderbuffers;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLsizei _n, uint32 _renderbuffers_shm_id,
+      uint32 _renderbuffers_shm_offset) {
+    SetHeader();
+    n = _n;
+    renderbuffers_shm_id = _renderbuffers_shm_id;
+    renderbuffers_shm_offset = _renderbuffers_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLsizei _n, uint32 _renderbuffers_shm_id,
+      uint32 _renderbuffers_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(_n, _renderbuffers_shm_id, _renderbuffers_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 n;
+  uint32 renderbuffers_shm_id;
+  uint32 renderbuffers_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(GenRenderbuffers) == 16,
+               Sizeof_GenRenderbuffers_is_not_16);
+COMPILE_ASSERT(offsetof(GenRenderbuffers, header) == 0,
+               OffsetOf_GenRenderbuffers_header_not_0);
+COMPILE_ASSERT(offsetof(GenRenderbuffers, n) == 4,
+               OffsetOf_GenRenderbuffers_n_not_4);
+COMPILE_ASSERT(offsetof(GenRenderbuffers, renderbuffers_shm_id) == 8,
+               OffsetOf_GenRenderbuffers_renderbuffers_shm_id_not_8);
+COMPILE_ASSERT(offsetof(GenRenderbuffers, renderbuffers_shm_offset) == 12,
+               OffsetOf_GenRenderbuffers_renderbuffers_shm_offset_not_12);
+
+struct GenRenderbuffersImmediate {
+  typedef GenRenderbuffersImmediate ValueType;
+  static const CommandId kCmdId = kGenRenderbuffersImmediate;
+  static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN;
+
+  static uint32 ComputeDataSize(GLsizei n) {
+    return static_cast<uint32>(sizeof(GLuint) * n);  // NOLINT
+  }
+
+  static uint32 ComputeSize(GLsizei n) {
+    return static_cast<uint32>(
+        sizeof(ValueType) + ComputeDataSize(n));  // NOLINT
+  }
+
+  void SetHeader(GLsizei n) {
+    header.SetCmdByTotalSize<ValueType>(ComputeSize(n));
+  }
+
+  void Init(GLsizei _n, GLuint* _renderbuffers) {
+    SetHeader(_n);
+    n = _n;
+    memcpy(ImmediateDataAddress(this),
+           _renderbuffers, ComputeDataSize(_n));
+  }
+
+  void* Set(void* cmd, GLsizei _n, GLuint* _renderbuffers) {
+    static_cast<ValueType*>(cmd)->Init(_n, _renderbuffers);
+    const uint32 size = ComputeSize(_n);
+    return NextImmediateCmdAddressTotalSize<ValueType>(cmd, size);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 n;
+};
+
+COMPILE_ASSERT(sizeof(GenRenderbuffersImmediate) == 8,
+               Sizeof_GenRenderbuffersImmediate_is_not_8);
+COMPILE_ASSERT(offsetof(GenRenderbuffersImmediate, header) == 0,
+               OffsetOf_GenRenderbuffersImmediate_header_not_0);
+COMPILE_ASSERT(offsetof(GenRenderbuffersImmediate, n) == 4,
+               OffsetOf_GenRenderbuffersImmediate_n_not_4);
+
+struct GenTextures {
+  typedef GenTextures ValueType;
+  static const CommandId kCmdId = kGenTextures;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLsizei _n, uint32 _textures_shm_id, uint32 _textures_shm_offset) {
+    SetHeader();
+    n = _n;
+    textures_shm_id = _textures_shm_id;
+    textures_shm_offset = _textures_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLsizei _n, uint32 _textures_shm_id,
+      uint32 _textures_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(_n, _textures_shm_id, _textures_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 n;
+  uint32 textures_shm_id;
+  uint32 textures_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(GenTextures) == 16,
+               Sizeof_GenTextures_is_not_16);
+COMPILE_ASSERT(offsetof(GenTextures, header) == 0,
+               OffsetOf_GenTextures_header_not_0);
+COMPILE_ASSERT(offsetof(GenTextures, n) == 4,
+               OffsetOf_GenTextures_n_not_4);
+COMPILE_ASSERT(offsetof(GenTextures, textures_shm_id) == 8,
+               OffsetOf_GenTextures_textures_shm_id_not_8);
+COMPILE_ASSERT(offsetof(GenTextures, textures_shm_offset) == 12,
+               OffsetOf_GenTextures_textures_shm_offset_not_12);
+
+struct GenTexturesImmediate {
+  typedef GenTexturesImmediate ValueType;
+  static const CommandId kCmdId = kGenTexturesImmediate;
+  static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN;
+
+  static uint32 ComputeDataSize(GLsizei n) {
+    return static_cast<uint32>(sizeof(GLuint) * n);  // NOLINT
+  }
+
+  static uint32 ComputeSize(GLsizei n) {
+    return static_cast<uint32>(
+        sizeof(ValueType) + ComputeDataSize(n));  // NOLINT
+  }
+
+  void SetHeader(GLsizei n) {
+    header.SetCmdByTotalSize<ValueType>(ComputeSize(n));
+  }
+
+  void Init(GLsizei _n, GLuint* _textures) {
+    SetHeader(_n);
+    n = _n;
+    memcpy(ImmediateDataAddress(this),
+           _textures, ComputeDataSize(_n));
+  }
+
+  void* Set(void* cmd, GLsizei _n, GLuint* _textures) {
+    static_cast<ValueType*>(cmd)->Init(_n, _textures);
+    const uint32 size = ComputeSize(_n);
+    return NextImmediateCmdAddressTotalSize<ValueType>(cmd, size);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 n;
+};
+
+COMPILE_ASSERT(sizeof(GenTexturesImmediate) == 8,
+               Sizeof_GenTexturesImmediate_is_not_8);
+COMPILE_ASSERT(offsetof(GenTexturesImmediate, header) == 0,
+               OffsetOf_GenTexturesImmediate_header_not_0);
+COMPILE_ASSERT(offsetof(GenTexturesImmediate, n) == 4,
+               OffsetOf_GenTexturesImmediate_n_not_4);
+
+struct GetActiveAttrib {
+  typedef GetActiveAttrib ValueType;
+  static const CommandId kCmdId = kGetActiveAttrib;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLuint _program, GLuint _index, GLsizei _bufsize, uint32 _length_shm_id,
+      uint32 _length_shm_offset, uint32 _size_shm_id, uint32 _size_shm_offset,
+      uint32 _type_shm_id, uint32 _type_shm_offset, uint32 _name_shm_id,
+      uint32 _name_shm_offset) {
+    SetHeader();
+    program = _program;
+    index = _index;
+    bufsize = _bufsize;
+    length_shm_id = _length_shm_id;
+    length_shm_offset = _length_shm_offset;
+    size_shm_id = _size_shm_id;
+    size_shm_offset = _size_shm_offset;
+    type_shm_id = _type_shm_id;
+    type_shm_offset = _type_shm_offset;
+    name_shm_id = _name_shm_id;
+    name_shm_offset = _name_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLuint _program, GLuint _index, GLsizei _bufsize,
+      uint32 _length_shm_id, uint32 _length_shm_offset, uint32 _size_shm_id,
+      uint32 _size_shm_offset, uint32 _type_shm_id, uint32 _type_shm_offset,
+      uint32 _name_shm_id, uint32 _name_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(
+            _program, _index, _bufsize, _length_shm_id, _length_shm_offset,
+            _size_shm_id, _size_shm_offset, _type_shm_id, _type_shm_offset,
+            _name_shm_id, _name_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 program;
+  uint32 index;
+  uint32 bufsize;
+  uint32 length_shm_id;
+  uint32 length_shm_offset;
+  uint32 size_shm_id;
+  uint32 size_shm_offset;
+  uint32 type_shm_id;
+  uint32 type_shm_offset;
+  uint32 name_shm_id;
+  uint32 name_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(GetActiveAttrib) == 48,
+               Sizeof_GetActiveAttrib_is_not_48);
+COMPILE_ASSERT(offsetof(GetActiveAttrib, header) == 0,
+               OffsetOf_GetActiveAttrib_header_not_0);
+COMPILE_ASSERT(offsetof(GetActiveAttrib, program) == 4,
+               OffsetOf_GetActiveAttrib_program_not_4);
+COMPILE_ASSERT(offsetof(GetActiveAttrib, index) == 8,
+               OffsetOf_GetActiveAttrib_index_not_8);
+COMPILE_ASSERT(offsetof(GetActiveAttrib, bufsize) == 12,
+               OffsetOf_GetActiveAttrib_bufsize_not_12);
+COMPILE_ASSERT(offsetof(GetActiveAttrib, length_shm_id) == 16,
+               OffsetOf_GetActiveAttrib_length_shm_id_not_16);
+COMPILE_ASSERT(offsetof(GetActiveAttrib, length_shm_offset) == 20,
+               OffsetOf_GetActiveAttrib_length_shm_offset_not_20);
+COMPILE_ASSERT(offsetof(GetActiveAttrib, size_shm_id) == 24,
+               OffsetOf_GetActiveAttrib_size_shm_id_not_24);
+COMPILE_ASSERT(offsetof(GetActiveAttrib, size_shm_offset) == 28,
+               OffsetOf_GetActiveAttrib_size_shm_offset_not_28);
+COMPILE_ASSERT(offsetof(GetActiveAttrib, type_shm_id) == 32,
+               OffsetOf_GetActiveAttrib_type_shm_id_not_32);
+COMPILE_ASSERT(offsetof(GetActiveAttrib, type_shm_offset) == 36,
+               OffsetOf_GetActiveAttrib_type_shm_offset_not_36);
+COMPILE_ASSERT(offsetof(GetActiveAttrib, name_shm_id) == 40,
+               OffsetOf_GetActiveAttrib_name_shm_id_not_40);
+COMPILE_ASSERT(offsetof(GetActiveAttrib, name_shm_offset) == 44,
+               OffsetOf_GetActiveAttrib_name_shm_offset_not_44);
+
+struct GetActiveUniform {
+  typedef GetActiveUniform ValueType;
+  static const CommandId kCmdId = kGetActiveUniform;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLuint _program, GLuint _index, GLsizei _bufsize, uint32 _length_shm_id,
+      uint32 _length_shm_offset, uint32 _size_shm_id, uint32 _size_shm_offset,
+      uint32 _type_shm_id, uint32 _type_shm_offset, uint32 _name_shm_id,
+      uint32 _name_shm_offset) {
+    SetHeader();
+    program = _program;
+    index = _index;
+    bufsize = _bufsize;
+    length_shm_id = _length_shm_id;
+    length_shm_offset = _length_shm_offset;
+    size_shm_id = _size_shm_id;
+    size_shm_offset = _size_shm_offset;
+    type_shm_id = _type_shm_id;
+    type_shm_offset = _type_shm_offset;
+    name_shm_id = _name_shm_id;
+    name_shm_offset = _name_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLuint _program, GLuint _index, GLsizei _bufsize,
+      uint32 _length_shm_id, uint32 _length_shm_offset, uint32 _size_shm_id,
+      uint32 _size_shm_offset, uint32 _type_shm_id, uint32 _type_shm_offset,
+      uint32 _name_shm_id, uint32 _name_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(
+            _program, _index, _bufsize, _length_shm_id, _length_shm_offset,
+            _size_shm_id, _size_shm_offset, _type_shm_id, _type_shm_offset,
+            _name_shm_id, _name_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 program;
+  uint32 index;
+  uint32 bufsize;
+  uint32 length_shm_id;
+  uint32 length_shm_offset;
+  uint32 size_shm_id;
+  uint32 size_shm_offset;
+  uint32 type_shm_id;
+  uint32 type_shm_offset;
+  uint32 name_shm_id;
+  uint32 name_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(GetActiveUniform) == 48,
+               Sizeof_GetActiveUniform_is_not_48);
+COMPILE_ASSERT(offsetof(GetActiveUniform, header) == 0,
+               OffsetOf_GetActiveUniform_header_not_0);
+COMPILE_ASSERT(offsetof(GetActiveUniform, program) == 4,
+               OffsetOf_GetActiveUniform_program_not_4);
+COMPILE_ASSERT(offsetof(GetActiveUniform, index) == 8,
+               OffsetOf_GetActiveUniform_index_not_8);
+COMPILE_ASSERT(offsetof(GetActiveUniform, bufsize) == 12,
+               OffsetOf_GetActiveUniform_bufsize_not_12);
+COMPILE_ASSERT(offsetof(GetActiveUniform, length_shm_id) == 16,
+               OffsetOf_GetActiveUniform_length_shm_id_not_16);
+COMPILE_ASSERT(offsetof(GetActiveUniform, length_shm_offset) == 20,
+               OffsetOf_GetActiveUniform_length_shm_offset_not_20);
+COMPILE_ASSERT(offsetof(GetActiveUniform, size_shm_id) == 24,
+               OffsetOf_GetActiveUniform_size_shm_id_not_24);
+COMPILE_ASSERT(offsetof(GetActiveUniform, size_shm_offset) == 28,
+               OffsetOf_GetActiveUniform_size_shm_offset_not_28);
+COMPILE_ASSERT(offsetof(GetActiveUniform, type_shm_id) == 32,
+               OffsetOf_GetActiveUniform_type_shm_id_not_32);
+COMPILE_ASSERT(offsetof(GetActiveUniform, type_shm_offset) == 36,
+               OffsetOf_GetActiveUniform_type_shm_offset_not_36);
+COMPILE_ASSERT(offsetof(GetActiveUniform, name_shm_id) == 40,
+               OffsetOf_GetActiveUniform_name_shm_id_not_40);
+COMPILE_ASSERT(offsetof(GetActiveUniform, name_shm_offset) == 44,
+               OffsetOf_GetActiveUniform_name_shm_offset_not_44);
+
+struct GetAttachedShaders {
+  typedef GetAttachedShaders ValueType;
+  static const CommandId kCmdId = kGetAttachedShaders;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLuint _program, GLsizei _maxcount, uint32 _count_shm_id,
+      uint32 _count_shm_offset, uint32 _shaders_shm_id,
+      uint32 _shaders_shm_offset) {
+    SetHeader();
+    program = _program;
+    maxcount = _maxcount;
+    count_shm_id = _count_shm_id;
+    count_shm_offset = _count_shm_offset;
+    shaders_shm_id = _shaders_shm_id;
+    shaders_shm_offset = _shaders_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLuint _program, GLsizei _maxcount, uint32 _count_shm_id,
+      uint32 _count_shm_offset, uint32 _shaders_shm_id,
+      uint32 _shaders_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(
+            _program, _maxcount, _count_shm_id, _count_shm_offset,
+            _shaders_shm_id, _shaders_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 program;
+  uint32 maxcount;
+  uint32 count_shm_id;
+  uint32 count_shm_offset;
+  uint32 shaders_shm_id;
+  uint32 shaders_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(GetAttachedShaders) == 28,
+               Sizeof_GetAttachedShaders_is_not_28);
+COMPILE_ASSERT(offsetof(GetAttachedShaders, header) == 0,
+               OffsetOf_GetAttachedShaders_header_not_0);
+COMPILE_ASSERT(offsetof(GetAttachedShaders, program) == 4,
+               OffsetOf_GetAttachedShaders_program_not_4);
+COMPILE_ASSERT(offsetof(GetAttachedShaders, maxcount) == 8,
+               OffsetOf_GetAttachedShaders_maxcount_not_8);
+COMPILE_ASSERT(offsetof(GetAttachedShaders, count_shm_id) == 12,
+               OffsetOf_GetAttachedShaders_count_shm_id_not_12);
+COMPILE_ASSERT(offsetof(GetAttachedShaders, count_shm_offset) == 16,
+               OffsetOf_GetAttachedShaders_count_shm_offset_not_16);
+COMPILE_ASSERT(offsetof(GetAttachedShaders, shaders_shm_id) == 20,
+               OffsetOf_GetAttachedShaders_shaders_shm_id_not_20);
+COMPILE_ASSERT(offsetof(GetAttachedShaders, shaders_shm_offset) == 24,
+               OffsetOf_GetAttachedShaders_shaders_shm_offset_not_24);
+
+struct GetAttribLocation {
+  typedef GetAttribLocation ValueType;
+  static const CommandId kCmdId = kGetAttribLocation;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLuint _program, uint32 _name_shm_id, uint32 _name_shm_offset,
+      uint32 _data_size) {
+    SetHeader();
+    program = _program;
+    name_shm_id = _name_shm_id;
+    name_shm_offset = _name_shm_offset;
+    data_size = _data_size;
+  }
+
+  void* Set(
+      void* cmd, GLuint _program, uint32 _name_shm_id, uint32 _name_shm_offset,
+      uint32 _data_size) {
+    static_cast<ValueType*>(
+        cmd)->Init(_program, _name_shm_id, _name_shm_offset, _data_size);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 program;
+  uint32 name_shm_id;
+  uint32 name_shm_offset;
+  uint32 data_size;
+};
+
+COMPILE_ASSERT(sizeof(GetAttribLocation) == 20,
+               Sizeof_GetAttribLocation_is_not_20);
+COMPILE_ASSERT(offsetof(GetAttribLocation, header) == 0,
+               OffsetOf_GetAttribLocation_header_not_0);
+COMPILE_ASSERT(offsetof(GetAttribLocation, program) == 4,
+               OffsetOf_GetAttribLocation_program_not_4);
+COMPILE_ASSERT(offsetof(GetAttribLocation, name_shm_id) == 8,
+               OffsetOf_GetAttribLocation_name_shm_id_not_8);
+COMPILE_ASSERT(offsetof(GetAttribLocation, name_shm_offset) == 12,
+               OffsetOf_GetAttribLocation_name_shm_offset_not_12);
+COMPILE_ASSERT(offsetof(GetAttribLocation, data_size) == 16,
+               OffsetOf_GetAttribLocation_data_size_not_16);
+
+struct GetAttribLocationImmediate {
+  typedef GetAttribLocationImmediate ValueType;
+  static const CommandId kCmdId = kGetAttribLocationImmediate;
+  static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN;
+
+  static uint32 ComputeDataSize(const char* s) {
+    return strlen(s);
+  }
+
+  static uint32 ComputeSize(const char* s) {
+    return static_cast<uint32>(
+        sizeof(ValueType) + ComputeDataSize(s));  // NOLINT
+  }
+
+  void SetHeader(const char* s) {
+    header.SetCmdByTotalSize<ValueType>(ComputeSize(s));
+  }
+
+  void Init(GLuint _program, const char* _name) {
+    SetHeader(_name);
+    program = _program;
+    data_size = strlen(_name);
+    memcpy(ImmediateDataAddress(this), _name, data_size);
+  }
+
+  void* Set(void* cmd, GLuint _program, const char* _name) {
+    static_cast<ValueType*>(cmd)->Init(_program, _name);
+    const uint32 size = ComputeSize(_name);
+    return NextImmediateCmdAddressTotalSize<ValueType>(cmd, size);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 program;
+  uint32 data_size;
+};
+
+COMPILE_ASSERT(sizeof(GetAttribLocationImmediate) == 12,
+               Sizeof_GetAttribLocationImmediate_is_not_12);
+COMPILE_ASSERT(offsetof(GetAttribLocationImmediate, header) == 0,
+               OffsetOf_GetAttribLocationImmediate_header_not_0);
+COMPILE_ASSERT(offsetof(GetAttribLocationImmediate, program) == 4,
+               OffsetOf_GetAttribLocationImmediate_program_not_4);
+COMPILE_ASSERT(offsetof(GetAttribLocationImmediate, data_size) == 8,
+               OffsetOf_GetAttribLocationImmediate_data_size_not_8);
+
+struct GetBooleanv {
+  typedef GetBooleanv ValueType;
+  static const CommandId kCmdId = kGetBooleanv;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLenum _pname, uint32 _params_shm_id, uint32 _params_shm_offset) {
+    SetHeader();
+    pname = _pname;
+    params_shm_id = _params_shm_id;
+    params_shm_offset = _params_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLenum _pname, uint32 _params_shm_id,
+      uint32 _params_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(_pname, _params_shm_id, _params_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 pname;
+  uint32 params_shm_id;
+  uint32 params_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(GetBooleanv) == 16,
+               Sizeof_GetBooleanv_is_not_16);
+COMPILE_ASSERT(offsetof(GetBooleanv, header) == 0,
+               OffsetOf_GetBooleanv_header_not_0);
+COMPILE_ASSERT(offsetof(GetBooleanv, pname) == 4,
+               OffsetOf_GetBooleanv_pname_not_4);
+COMPILE_ASSERT(offsetof(GetBooleanv, params_shm_id) == 8,
+               OffsetOf_GetBooleanv_params_shm_id_not_8);
+COMPILE_ASSERT(offsetof(GetBooleanv, params_shm_offset) == 12,
+               OffsetOf_GetBooleanv_params_shm_offset_not_12);
+
+struct GetBufferParameteriv {
+  typedef GetBufferParameteriv ValueType;
+  static const CommandId kCmdId = kGetBufferParameteriv;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLenum _target, GLenum _pname, uint32 _params_shm_id,
+      uint32 _params_shm_offset) {
+    SetHeader();
+    target = _target;
+    pname = _pname;
+    params_shm_id = _params_shm_id;
+    params_shm_offset = _params_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLenum _target, GLenum _pname, uint32 _params_shm_id,
+      uint32 _params_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(_target, _pname, _params_shm_id, _params_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 target;
+  uint32 pname;
+  uint32 params_shm_id;
+  uint32 params_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(GetBufferParameteriv) == 20,
+               Sizeof_GetBufferParameteriv_is_not_20);
+COMPILE_ASSERT(offsetof(GetBufferParameteriv, header) == 0,
+               OffsetOf_GetBufferParameteriv_header_not_0);
+COMPILE_ASSERT(offsetof(GetBufferParameteriv, target) == 4,
+               OffsetOf_GetBufferParameteriv_target_not_4);
+COMPILE_ASSERT(offsetof(GetBufferParameteriv, pname) == 8,
+               OffsetOf_GetBufferParameteriv_pname_not_8);
+COMPILE_ASSERT(offsetof(GetBufferParameteriv, params_shm_id) == 12,
+               OffsetOf_GetBufferParameteriv_params_shm_id_not_12);
+COMPILE_ASSERT(offsetof(GetBufferParameteriv, params_shm_offset) == 16,
+               OffsetOf_GetBufferParameteriv_params_shm_offset_not_16);
+
+struct GetError {
+  typedef GetError ValueType;
+  static const CommandId kCmdId = kGetError;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(uint32 _result_shm_id, uint32 _result_shm_offset) {
+    SetHeader();
+    result_shm_id = _result_shm_id;
+    result_shm_offset = _result_shm_offset;
+  }
+
+  void* Set(void* cmd, uint32 _result_shm_id, uint32 _result_shm_offset) {
+    static_cast<ValueType*>(cmd)->Init(_result_shm_id, _result_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 result_shm_id;
+  uint32 result_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(GetError) == 12,
+               Sizeof_GetError_is_not_12);
+COMPILE_ASSERT(offsetof(GetError, header) == 0,
+               OffsetOf_GetError_header_not_0);
+COMPILE_ASSERT(offsetof(GetError, result_shm_id) == 4,
+               OffsetOf_GetError_result_shm_id_not_4);
+COMPILE_ASSERT(offsetof(GetError, result_shm_offset) == 8,
+               OffsetOf_GetError_result_shm_offset_not_8);
+
+struct GetFloatv {
+  typedef GetFloatv ValueType;
+  static const CommandId kCmdId = kGetFloatv;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLenum _pname, uint32 _params_shm_id, uint32 _params_shm_offset) {
+    SetHeader();
+    pname = _pname;
+    params_shm_id = _params_shm_id;
+    params_shm_offset = _params_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLenum _pname, uint32 _params_shm_id,
+      uint32 _params_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(_pname, _params_shm_id, _params_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 pname;
+  uint32 params_shm_id;
+  uint32 params_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(GetFloatv) == 16,
+               Sizeof_GetFloatv_is_not_16);
+COMPILE_ASSERT(offsetof(GetFloatv, header) == 0,
+               OffsetOf_GetFloatv_header_not_0);
+COMPILE_ASSERT(offsetof(GetFloatv, pname) == 4,
+               OffsetOf_GetFloatv_pname_not_4);
+COMPILE_ASSERT(offsetof(GetFloatv, params_shm_id) == 8,
+               OffsetOf_GetFloatv_params_shm_id_not_8);
+COMPILE_ASSERT(offsetof(GetFloatv, params_shm_offset) == 12,
+               OffsetOf_GetFloatv_params_shm_offset_not_12);
+
+struct GetFramebufferAttachmentParameteriv {
+  typedef GetFramebufferAttachmentParameteriv ValueType;
+  static const CommandId kCmdId = kGetFramebufferAttachmentParameteriv;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLenum _target, GLenum _attachment, GLenum _pname, uint32 _params_shm_id,
+      uint32 _params_shm_offset) {
+    SetHeader();
+    target = _target;
+    attachment = _attachment;
+    pname = _pname;
+    params_shm_id = _params_shm_id;
+    params_shm_offset = _params_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLenum _target, GLenum _attachment, GLenum _pname,
+      uint32 _params_shm_id, uint32 _params_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(
+            _target, _attachment, _pname, _params_shm_id, _params_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 target;
+  uint32 attachment;
+  uint32 pname;
+  uint32 params_shm_id;
+  uint32 params_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(GetFramebufferAttachmentParameteriv) == 24,
+               Sizeof_GetFramebufferAttachmentParameteriv_is_not_24);
+COMPILE_ASSERT(offsetof(GetFramebufferAttachmentParameteriv, header) == 0,
+               OffsetOf_GetFramebufferAttachmentParameteriv_header_not_0);
+COMPILE_ASSERT(offsetof(GetFramebufferAttachmentParameteriv, target) == 4,
+               OffsetOf_GetFramebufferAttachmentParameteriv_target_not_4);
+COMPILE_ASSERT(offsetof(GetFramebufferAttachmentParameteriv, attachment) == 8,
+               OffsetOf_GetFramebufferAttachmentParameteriv_attachment_not_8);
+COMPILE_ASSERT(offsetof(GetFramebufferAttachmentParameteriv, pname) == 12,
+               OffsetOf_GetFramebufferAttachmentParameteriv_pname_not_12);
+COMPILE_ASSERT(
+    offsetof(GetFramebufferAttachmentParameteriv, params_shm_id) == 16,
+               OffsetOf_GetFramebufferAttachmentParameteriv_params_shm_id_not_16);
+COMPILE_ASSERT(
+    offsetof(GetFramebufferAttachmentParameteriv, params_shm_offset) == 20,
+               OffsetOf_GetFramebufferAttachmentParameteriv_params_shm_offset_not_20);
+
+struct GetIntegerv {
+  typedef GetIntegerv ValueType;
+  static const CommandId kCmdId = kGetIntegerv;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLenum _pname, uint32 _params_shm_id, uint32 _params_shm_offset) {
+    SetHeader();
+    pname = _pname;
+    params_shm_id = _params_shm_id;
+    params_shm_offset = _params_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLenum _pname, uint32 _params_shm_id,
+      uint32 _params_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(_pname, _params_shm_id, _params_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 pname;
+  uint32 params_shm_id;
+  uint32 params_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(GetIntegerv) == 16,
+               Sizeof_GetIntegerv_is_not_16);
+COMPILE_ASSERT(offsetof(GetIntegerv, header) == 0,
+               OffsetOf_GetIntegerv_header_not_0);
+COMPILE_ASSERT(offsetof(GetIntegerv, pname) == 4,
+               OffsetOf_GetIntegerv_pname_not_4);
+COMPILE_ASSERT(offsetof(GetIntegerv, params_shm_id) == 8,
+               OffsetOf_GetIntegerv_params_shm_id_not_8);
+COMPILE_ASSERT(offsetof(GetIntegerv, params_shm_offset) == 12,
+               OffsetOf_GetIntegerv_params_shm_offset_not_12);
+
+struct GetProgramiv {
+  typedef GetProgramiv ValueType;
+  static const CommandId kCmdId = kGetProgramiv;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLuint _program, GLenum _pname, uint32 _params_shm_id,
+      uint32 _params_shm_offset) {
+    SetHeader();
+    program = _program;
+    pname = _pname;
+    params_shm_id = _params_shm_id;
+    params_shm_offset = _params_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLuint _program, GLenum _pname, uint32 _params_shm_id,
+      uint32 _params_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(_program, _pname, _params_shm_id, _params_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 program;
+  uint32 pname;
+  uint32 params_shm_id;
+  uint32 params_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(GetProgramiv) == 20,
+               Sizeof_GetProgramiv_is_not_20);
+COMPILE_ASSERT(offsetof(GetProgramiv, header) == 0,
+               OffsetOf_GetProgramiv_header_not_0);
+COMPILE_ASSERT(offsetof(GetProgramiv, program) == 4,
+               OffsetOf_GetProgramiv_program_not_4);
+COMPILE_ASSERT(offsetof(GetProgramiv, pname) == 8,
+               OffsetOf_GetProgramiv_pname_not_8);
+COMPILE_ASSERT(offsetof(GetProgramiv, params_shm_id) == 12,
+               OffsetOf_GetProgramiv_params_shm_id_not_12);
+COMPILE_ASSERT(offsetof(GetProgramiv, params_shm_offset) == 16,
+               OffsetOf_GetProgramiv_params_shm_offset_not_16);
+
+struct GetProgramInfoLog {
+  typedef GetProgramInfoLog ValueType;
+  static const CommandId kCmdId = kGetProgramInfoLog;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLuint _program, GLsizei _bufsize, uint32 _length_shm_id,
+      uint32 _length_shm_offset, uint32 _infolog_shm_id,
+      uint32 _infolog_shm_offset) {
+    SetHeader();
+    program = _program;
+    bufsize = _bufsize;
+    length_shm_id = _length_shm_id;
+    length_shm_offset = _length_shm_offset;
+    infolog_shm_id = _infolog_shm_id;
+    infolog_shm_offset = _infolog_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLuint _program, GLsizei _bufsize, uint32 _length_shm_id,
+      uint32 _length_shm_offset, uint32 _infolog_shm_id,
+      uint32 _infolog_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(
+            _program, _bufsize, _length_shm_id, _length_shm_offset,
+            _infolog_shm_id, _infolog_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 program;
+  uint32 bufsize;
+  uint32 length_shm_id;
+  uint32 length_shm_offset;
+  uint32 infolog_shm_id;
+  uint32 infolog_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(GetProgramInfoLog) == 28,
+               Sizeof_GetProgramInfoLog_is_not_28);
+COMPILE_ASSERT(offsetof(GetProgramInfoLog, header) == 0,
+               OffsetOf_GetProgramInfoLog_header_not_0);
+COMPILE_ASSERT(offsetof(GetProgramInfoLog, program) == 4,
+               OffsetOf_GetProgramInfoLog_program_not_4);
+COMPILE_ASSERT(offsetof(GetProgramInfoLog, bufsize) == 8,
+               OffsetOf_GetProgramInfoLog_bufsize_not_8);
+COMPILE_ASSERT(offsetof(GetProgramInfoLog, length_shm_id) == 12,
+               OffsetOf_GetProgramInfoLog_length_shm_id_not_12);
+COMPILE_ASSERT(offsetof(GetProgramInfoLog, length_shm_offset) == 16,
+               OffsetOf_GetProgramInfoLog_length_shm_offset_not_16);
+COMPILE_ASSERT(offsetof(GetProgramInfoLog, infolog_shm_id) == 20,
+               OffsetOf_GetProgramInfoLog_infolog_shm_id_not_20);
+COMPILE_ASSERT(offsetof(GetProgramInfoLog, infolog_shm_offset) == 24,
+               OffsetOf_GetProgramInfoLog_infolog_shm_offset_not_24);
+
+struct GetRenderbufferParameteriv {
+  typedef GetRenderbufferParameteriv ValueType;
+  static const CommandId kCmdId = kGetRenderbufferParameteriv;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLenum _target, GLenum _pname, uint32 _params_shm_id,
+      uint32 _params_shm_offset) {
+    SetHeader();
+    target = _target;
+    pname = _pname;
+    params_shm_id = _params_shm_id;
+    params_shm_offset = _params_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLenum _target, GLenum _pname, uint32 _params_shm_id,
+      uint32 _params_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(_target, _pname, _params_shm_id, _params_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 target;
+  uint32 pname;
+  uint32 params_shm_id;
+  uint32 params_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(GetRenderbufferParameteriv) == 20,
+               Sizeof_GetRenderbufferParameteriv_is_not_20);
+COMPILE_ASSERT(offsetof(GetRenderbufferParameteriv, header) == 0,
+               OffsetOf_GetRenderbufferParameteriv_header_not_0);
+COMPILE_ASSERT(offsetof(GetRenderbufferParameteriv, target) == 4,
+               OffsetOf_GetRenderbufferParameteriv_target_not_4);
+COMPILE_ASSERT(offsetof(GetRenderbufferParameteriv, pname) == 8,
+               OffsetOf_GetRenderbufferParameteriv_pname_not_8);
+COMPILE_ASSERT(offsetof(GetRenderbufferParameteriv, params_shm_id) == 12,
+               OffsetOf_GetRenderbufferParameteriv_params_shm_id_not_12);
+COMPILE_ASSERT(offsetof(GetRenderbufferParameteriv, params_shm_offset) == 16,
+               OffsetOf_GetRenderbufferParameteriv_params_shm_offset_not_16);
+
+struct GetShaderiv {
+  typedef GetShaderiv ValueType;
+  static const CommandId kCmdId = kGetShaderiv;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLuint _shader, GLenum _pname, uint32 _params_shm_id,
+      uint32 _params_shm_offset) {
+    SetHeader();
+    shader = _shader;
+    pname = _pname;
+    params_shm_id = _params_shm_id;
+    params_shm_offset = _params_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLuint _shader, GLenum _pname, uint32 _params_shm_id,
+      uint32 _params_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(_shader, _pname, _params_shm_id, _params_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 shader;
+  uint32 pname;
+  uint32 params_shm_id;
+  uint32 params_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(GetShaderiv) == 20,
+               Sizeof_GetShaderiv_is_not_20);
+COMPILE_ASSERT(offsetof(GetShaderiv, header) == 0,
+               OffsetOf_GetShaderiv_header_not_0);
+COMPILE_ASSERT(offsetof(GetShaderiv, shader) == 4,
+               OffsetOf_GetShaderiv_shader_not_4);
+COMPILE_ASSERT(offsetof(GetShaderiv, pname) == 8,
+               OffsetOf_GetShaderiv_pname_not_8);
+COMPILE_ASSERT(offsetof(GetShaderiv, params_shm_id) == 12,
+               OffsetOf_GetShaderiv_params_shm_id_not_12);
+COMPILE_ASSERT(offsetof(GetShaderiv, params_shm_offset) == 16,
+               OffsetOf_GetShaderiv_params_shm_offset_not_16);
+
+struct GetShaderInfoLog {
+  typedef GetShaderInfoLog ValueType;
+  static const CommandId kCmdId = kGetShaderInfoLog;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLuint _shader, GLsizei _bufsize, uint32 _length_shm_id,
+      uint32 _length_shm_offset, uint32 _infolog_shm_id,
+      uint32 _infolog_shm_offset) {
+    SetHeader();
+    shader = _shader;
+    bufsize = _bufsize;
+    length_shm_id = _length_shm_id;
+    length_shm_offset = _length_shm_offset;
+    infolog_shm_id = _infolog_shm_id;
+    infolog_shm_offset = _infolog_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLuint _shader, GLsizei _bufsize, uint32 _length_shm_id,
+      uint32 _length_shm_offset, uint32 _infolog_shm_id,
+      uint32 _infolog_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(
+            _shader, _bufsize, _length_shm_id, _length_shm_offset,
+            _infolog_shm_id, _infolog_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 shader;
+  uint32 bufsize;
+  uint32 length_shm_id;
+  uint32 length_shm_offset;
+  uint32 infolog_shm_id;
+  uint32 infolog_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(GetShaderInfoLog) == 28,
+               Sizeof_GetShaderInfoLog_is_not_28);
+COMPILE_ASSERT(offsetof(GetShaderInfoLog, header) == 0,
+               OffsetOf_GetShaderInfoLog_header_not_0);
+COMPILE_ASSERT(offsetof(GetShaderInfoLog, shader) == 4,
+               OffsetOf_GetShaderInfoLog_shader_not_4);
+COMPILE_ASSERT(offsetof(GetShaderInfoLog, bufsize) == 8,
+               OffsetOf_GetShaderInfoLog_bufsize_not_8);
+COMPILE_ASSERT(offsetof(GetShaderInfoLog, length_shm_id) == 12,
+               OffsetOf_GetShaderInfoLog_length_shm_id_not_12);
+COMPILE_ASSERT(offsetof(GetShaderInfoLog, length_shm_offset) == 16,
+               OffsetOf_GetShaderInfoLog_length_shm_offset_not_16);
+COMPILE_ASSERT(offsetof(GetShaderInfoLog, infolog_shm_id) == 20,
+               OffsetOf_GetShaderInfoLog_infolog_shm_id_not_20);
+COMPILE_ASSERT(offsetof(GetShaderInfoLog, infolog_shm_offset) == 24,
+               OffsetOf_GetShaderInfoLog_infolog_shm_offset_not_24);
+
+struct GetShaderPrecisionFormat {
+  typedef GetShaderPrecisionFormat ValueType;
+  static const CommandId kCmdId = kGetShaderPrecisionFormat;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLenum _shadertype, GLenum _precisiontype, uint32 _range_shm_id,
+      uint32 _range_shm_offset, uint32 _precision_shm_id,
+      uint32 _precision_shm_offset) {
+    SetHeader();
+    shadertype = _shadertype;
+    precisiontype = _precisiontype;
+    range_shm_id = _range_shm_id;
+    range_shm_offset = _range_shm_offset;
+    precision_shm_id = _precision_shm_id;
+    precision_shm_offset = _precision_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLenum _shadertype, GLenum _precisiontype,
+      uint32 _range_shm_id, uint32 _range_shm_offset, uint32 _precision_shm_id,
+      uint32 _precision_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(
+            _shadertype, _precisiontype, _range_shm_id, _range_shm_offset,
+            _precision_shm_id, _precision_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 shadertype;
+  uint32 precisiontype;
+  uint32 range_shm_id;
+  uint32 range_shm_offset;
+  uint32 precision_shm_id;
+  uint32 precision_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(GetShaderPrecisionFormat) == 28,
+               Sizeof_GetShaderPrecisionFormat_is_not_28);
+COMPILE_ASSERT(offsetof(GetShaderPrecisionFormat, header) == 0,
+               OffsetOf_GetShaderPrecisionFormat_header_not_0);
+COMPILE_ASSERT(offsetof(GetShaderPrecisionFormat, shadertype) == 4,
+               OffsetOf_GetShaderPrecisionFormat_shadertype_not_4);
+COMPILE_ASSERT(offsetof(GetShaderPrecisionFormat, precisiontype) == 8,
+               OffsetOf_GetShaderPrecisionFormat_precisiontype_not_8);
+COMPILE_ASSERT(offsetof(GetShaderPrecisionFormat, range_shm_id) == 12,
+               OffsetOf_GetShaderPrecisionFormat_range_shm_id_not_12);
+COMPILE_ASSERT(offsetof(GetShaderPrecisionFormat, range_shm_offset) == 16,
+               OffsetOf_GetShaderPrecisionFormat_range_shm_offset_not_16);
+COMPILE_ASSERT(offsetof(GetShaderPrecisionFormat, precision_shm_id) == 20,
+               OffsetOf_GetShaderPrecisionFormat_precision_shm_id_not_20);
+COMPILE_ASSERT(offsetof(GetShaderPrecisionFormat, precision_shm_offset) == 24,
+               OffsetOf_GetShaderPrecisionFormat_precision_shm_offset_not_24);
+
+struct GetShaderSource {
+  typedef GetShaderSource ValueType;
+  static const CommandId kCmdId = kGetShaderSource;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLuint _shader, GLsizei _bufsize, uint32 _length_shm_id,
+      uint32 _length_shm_offset, uint32 _source_shm_id,
+      uint32 _source_shm_offset) {
+    SetHeader();
+    shader = _shader;
+    bufsize = _bufsize;
+    length_shm_id = _length_shm_id;
+    length_shm_offset = _length_shm_offset;
+    source_shm_id = _source_shm_id;
+    source_shm_offset = _source_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLuint _shader, GLsizei _bufsize, uint32 _length_shm_id,
+      uint32 _length_shm_offset, uint32 _source_shm_id,
+      uint32 _source_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(
+            _shader, _bufsize, _length_shm_id, _length_shm_offset,
+            _source_shm_id, _source_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 shader;
+  uint32 bufsize;
+  uint32 length_shm_id;
+  uint32 length_shm_offset;
+  uint32 source_shm_id;
+  uint32 source_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(GetShaderSource) == 28,
+               Sizeof_GetShaderSource_is_not_28);
+COMPILE_ASSERT(offsetof(GetShaderSource, header) == 0,
+               OffsetOf_GetShaderSource_header_not_0);
+COMPILE_ASSERT(offsetof(GetShaderSource, shader) == 4,
+               OffsetOf_GetShaderSource_shader_not_4);
+COMPILE_ASSERT(offsetof(GetShaderSource, bufsize) == 8,
+               OffsetOf_GetShaderSource_bufsize_not_8);
+COMPILE_ASSERT(offsetof(GetShaderSource, length_shm_id) == 12,
+               OffsetOf_GetShaderSource_length_shm_id_not_12);
+COMPILE_ASSERT(offsetof(GetShaderSource, length_shm_offset) == 16,
+               OffsetOf_GetShaderSource_length_shm_offset_not_16);
+COMPILE_ASSERT(offsetof(GetShaderSource, source_shm_id) == 20,
+               OffsetOf_GetShaderSource_source_shm_id_not_20);
+COMPILE_ASSERT(offsetof(GetShaderSource, source_shm_offset) == 24,
+               OffsetOf_GetShaderSource_source_shm_offset_not_24);
+
+struct GetString {
+  typedef GetString ValueType;
+  static const CommandId kCmdId = kGetString;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLenum _name) {
+    SetHeader();
+    name = _name;
+  }
+
+  void* Set(void* cmd, GLenum _name) {
+    static_cast<ValueType*>(cmd)->Init(_name);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 name;
+};
+
+COMPILE_ASSERT(sizeof(GetString) == 8,
+               Sizeof_GetString_is_not_8);
+COMPILE_ASSERT(offsetof(GetString, header) == 0,
+               OffsetOf_GetString_header_not_0);
+COMPILE_ASSERT(offsetof(GetString, name) == 4,
+               OffsetOf_GetString_name_not_4);
+
+struct GetTexParameterfv {
+  typedef GetTexParameterfv ValueType;
+  static const CommandId kCmdId = kGetTexParameterfv;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLenum _target, GLenum _pname, uint32 _params_shm_id,
+      uint32 _params_shm_offset) {
+    SetHeader();
+    target = _target;
+    pname = _pname;
+    params_shm_id = _params_shm_id;
+    params_shm_offset = _params_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLenum _target, GLenum _pname, uint32 _params_shm_id,
+      uint32 _params_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(_target, _pname, _params_shm_id, _params_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 target;
+  uint32 pname;
+  uint32 params_shm_id;
+  uint32 params_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(GetTexParameterfv) == 20,
+               Sizeof_GetTexParameterfv_is_not_20);
+COMPILE_ASSERT(offsetof(GetTexParameterfv, header) == 0,
+               OffsetOf_GetTexParameterfv_header_not_0);
+COMPILE_ASSERT(offsetof(GetTexParameterfv, target) == 4,
+               OffsetOf_GetTexParameterfv_target_not_4);
+COMPILE_ASSERT(offsetof(GetTexParameterfv, pname) == 8,
+               OffsetOf_GetTexParameterfv_pname_not_8);
+COMPILE_ASSERT(offsetof(GetTexParameterfv, params_shm_id) == 12,
+               OffsetOf_GetTexParameterfv_params_shm_id_not_12);
+COMPILE_ASSERT(offsetof(GetTexParameterfv, params_shm_offset) == 16,
+               OffsetOf_GetTexParameterfv_params_shm_offset_not_16);
+
+struct GetTexParameteriv {
+  typedef GetTexParameteriv ValueType;
+  static const CommandId kCmdId = kGetTexParameteriv;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLenum _target, GLenum _pname, uint32 _params_shm_id,
+      uint32 _params_shm_offset) {
+    SetHeader();
+    target = _target;
+    pname = _pname;
+    params_shm_id = _params_shm_id;
+    params_shm_offset = _params_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLenum _target, GLenum _pname, uint32 _params_shm_id,
+      uint32 _params_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(_target, _pname, _params_shm_id, _params_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 target;
+  uint32 pname;
+  uint32 params_shm_id;
+  uint32 params_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(GetTexParameteriv) == 20,
+               Sizeof_GetTexParameteriv_is_not_20);
+COMPILE_ASSERT(offsetof(GetTexParameteriv, header) == 0,
+               OffsetOf_GetTexParameteriv_header_not_0);
+COMPILE_ASSERT(offsetof(GetTexParameteriv, target) == 4,
+               OffsetOf_GetTexParameteriv_target_not_4);
+COMPILE_ASSERT(offsetof(GetTexParameteriv, pname) == 8,
+               OffsetOf_GetTexParameteriv_pname_not_8);
+COMPILE_ASSERT(offsetof(GetTexParameteriv, params_shm_id) == 12,
+               OffsetOf_GetTexParameteriv_params_shm_id_not_12);
+COMPILE_ASSERT(offsetof(GetTexParameteriv, params_shm_offset) == 16,
+               OffsetOf_GetTexParameteriv_params_shm_offset_not_16);
+
+struct GetUniformfv {
+  typedef GetUniformfv ValueType;
+  static const CommandId kCmdId = kGetUniformfv;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLuint _program, GLint _location, uint32 _params_shm_id,
+      uint32 _params_shm_offset) {
+    SetHeader();
+    program = _program;
+    location = _location;
+    params_shm_id = _params_shm_id;
+    params_shm_offset = _params_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLuint _program, GLint _location, uint32 _params_shm_id,
+      uint32 _params_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(_program, _location, _params_shm_id, _params_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 program;
+  uint32 location;
+  uint32 params_shm_id;
+  uint32 params_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(GetUniformfv) == 20,
+               Sizeof_GetUniformfv_is_not_20);
+COMPILE_ASSERT(offsetof(GetUniformfv, header) == 0,
+               OffsetOf_GetUniformfv_header_not_0);
+COMPILE_ASSERT(offsetof(GetUniformfv, program) == 4,
+               OffsetOf_GetUniformfv_program_not_4);
+COMPILE_ASSERT(offsetof(GetUniformfv, location) == 8,
+               OffsetOf_GetUniformfv_location_not_8);
+COMPILE_ASSERT(offsetof(GetUniformfv, params_shm_id) == 12,
+               OffsetOf_GetUniformfv_params_shm_id_not_12);
+COMPILE_ASSERT(offsetof(GetUniformfv, params_shm_offset) == 16,
+               OffsetOf_GetUniformfv_params_shm_offset_not_16);
+
+struct GetUniformiv {
+  typedef GetUniformiv ValueType;
+  static const CommandId kCmdId = kGetUniformiv;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLuint _program, GLint _location, uint32 _params_shm_id,
+      uint32 _params_shm_offset) {
+    SetHeader();
+    program = _program;
+    location = _location;
+    params_shm_id = _params_shm_id;
+    params_shm_offset = _params_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLuint _program, GLint _location, uint32 _params_shm_id,
+      uint32 _params_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(_program, _location, _params_shm_id, _params_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 program;
+  uint32 location;
+  uint32 params_shm_id;
+  uint32 params_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(GetUniformiv) == 20,
+               Sizeof_GetUniformiv_is_not_20);
+COMPILE_ASSERT(offsetof(GetUniformiv, header) == 0,
+               OffsetOf_GetUniformiv_header_not_0);
+COMPILE_ASSERT(offsetof(GetUniformiv, program) == 4,
+               OffsetOf_GetUniformiv_program_not_4);
+COMPILE_ASSERT(offsetof(GetUniformiv, location) == 8,
+               OffsetOf_GetUniformiv_location_not_8);
+COMPILE_ASSERT(offsetof(GetUniformiv, params_shm_id) == 12,
+               OffsetOf_GetUniformiv_params_shm_id_not_12);
+COMPILE_ASSERT(offsetof(GetUniformiv, params_shm_offset) == 16,
+               OffsetOf_GetUniformiv_params_shm_offset_not_16);
+
+struct GetUniformLocation {
+  typedef GetUniformLocation ValueType;
+  static const CommandId kCmdId = kGetUniformLocation;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLuint _program, uint32 _name_shm_id, uint32 _name_shm_offset,
+      uint32 _data_size) {
+    SetHeader();
+    program = _program;
+    name_shm_id = _name_shm_id;
+    name_shm_offset = _name_shm_offset;
+    data_size = _data_size;
+  }
+
+  void* Set(
+      void* cmd, GLuint _program, uint32 _name_shm_id, uint32 _name_shm_offset,
+      uint32 _data_size) {
+    static_cast<ValueType*>(
+        cmd)->Init(_program, _name_shm_id, _name_shm_offset, _data_size);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 program;
+  uint32 name_shm_id;
+  uint32 name_shm_offset;
+  uint32 data_size;
+};
+
+COMPILE_ASSERT(sizeof(GetUniformLocation) == 20,
+               Sizeof_GetUniformLocation_is_not_20);
+COMPILE_ASSERT(offsetof(GetUniformLocation, header) == 0,
+               OffsetOf_GetUniformLocation_header_not_0);
+COMPILE_ASSERT(offsetof(GetUniformLocation, program) == 4,
+               OffsetOf_GetUniformLocation_program_not_4);
+COMPILE_ASSERT(offsetof(GetUniformLocation, name_shm_id) == 8,
+               OffsetOf_GetUniformLocation_name_shm_id_not_8);
+COMPILE_ASSERT(offsetof(GetUniformLocation, name_shm_offset) == 12,
+               OffsetOf_GetUniformLocation_name_shm_offset_not_12);
+COMPILE_ASSERT(offsetof(GetUniformLocation, data_size) == 16,
+               OffsetOf_GetUniformLocation_data_size_not_16);
+
+struct GetUniformLocationImmediate {
+  typedef GetUniformLocationImmediate ValueType;
+  static const CommandId kCmdId = kGetUniformLocationImmediate;
+  static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN;
+
+  static uint32 ComputeDataSize(const char* s) {
+    return strlen(s);
+  }
+
+  static uint32 ComputeSize(const char* s) {
+    return static_cast<uint32>(
+        sizeof(ValueType) + ComputeDataSize(s));  // NOLINT
+  }
+
+  void SetHeader(const char* s) {
+    header.SetCmdByTotalSize<ValueType>(ComputeSize(s));
+  }
+
+  void Init(GLuint _program, const char* _name) {
+    SetHeader(_name);
+    program = _program;
+    data_size = strlen(_name);
+    memcpy(ImmediateDataAddress(this), _name, data_size);
+  }
+
+  void* Set(void* cmd, GLuint _program, const char* _name) {
+    static_cast<ValueType*>(cmd)->Init(_program, _name);
+    const uint32 size = ComputeSize(_name);
+    return NextImmediateCmdAddressTotalSize<ValueType>(cmd, size);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 program;
+  uint32 data_size;
+};
+
+COMPILE_ASSERT(sizeof(GetUniformLocationImmediate) == 12,
+               Sizeof_GetUniformLocationImmediate_is_not_12);
+COMPILE_ASSERT(offsetof(GetUniformLocationImmediate, header) == 0,
+               OffsetOf_GetUniformLocationImmediate_header_not_0);
+COMPILE_ASSERT(offsetof(GetUniformLocationImmediate, program) == 4,
+               OffsetOf_GetUniformLocationImmediate_program_not_4);
+COMPILE_ASSERT(offsetof(GetUniformLocationImmediate, data_size) == 8,
+               OffsetOf_GetUniformLocationImmediate_data_size_not_8);
+
+struct GetVertexAttribfv {
+  typedef GetVertexAttribfv ValueType;
+  static const CommandId kCmdId = kGetVertexAttribfv;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLuint _index, GLenum _pname, uint32 _params_shm_id,
+      uint32 _params_shm_offset) {
+    SetHeader();
+    index = _index;
+    pname = _pname;
+    params_shm_id = _params_shm_id;
+    params_shm_offset = _params_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLuint _index, GLenum _pname, uint32 _params_shm_id,
+      uint32 _params_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(_index, _pname, _params_shm_id, _params_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 index;
+  uint32 pname;
+  uint32 params_shm_id;
+  uint32 params_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(GetVertexAttribfv) == 20,
+               Sizeof_GetVertexAttribfv_is_not_20);
+COMPILE_ASSERT(offsetof(GetVertexAttribfv, header) == 0,
+               OffsetOf_GetVertexAttribfv_header_not_0);
+COMPILE_ASSERT(offsetof(GetVertexAttribfv, index) == 4,
+               OffsetOf_GetVertexAttribfv_index_not_4);
+COMPILE_ASSERT(offsetof(GetVertexAttribfv, pname) == 8,
+               OffsetOf_GetVertexAttribfv_pname_not_8);
+COMPILE_ASSERT(offsetof(GetVertexAttribfv, params_shm_id) == 12,
+               OffsetOf_GetVertexAttribfv_params_shm_id_not_12);
+COMPILE_ASSERT(offsetof(GetVertexAttribfv, params_shm_offset) == 16,
+               OffsetOf_GetVertexAttribfv_params_shm_offset_not_16);
+
+struct GetVertexAttribiv {
+  typedef GetVertexAttribiv ValueType;
+  static const CommandId kCmdId = kGetVertexAttribiv;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLuint _index, GLenum _pname, uint32 _params_shm_id,
+      uint32 _params_shm_offset) {
+    SetHeader();
+    index = _index;
+    pname = _pname;
+    params_shm_id = _params_shm_id;
+    params_shm_offset = _params_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLuint _index, GLenum _pname, uint32 _params_shm_id,
+      uint32 _params_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(_index, _pname, _params_shm_id, _params_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 index;
+  uint32 pname;
+  uint32 params_shm_id;
+  uint32 params_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(GetVertexAttribiv) == 20,
+               Sizeof_GetVertexAttribiv_is_not_20);
+COMPILE_ASSERT(offsetof(GetVertexAttribiv, header) == 0,
+               OffsetOf_GetVertexAttribiv_header_not_0);
+COMPILE_ASSERT(offsetof(GetVertexAttribiv, index) == 4,
+               OffsetOf_GetVertexAttribiv_index_not_4);
+COMPILE_ASSERT(offsetof(GetVertexAttribiv, pname) == 8,
+               OffsetOf_GetVertexAttribiv_pname_not_8);
+COMPILE_ASSERT(offsetof(GetVertexAttribiv, params_shm_id) == 12,
+               OffsetOf_GetVertexAttribiv_params_shm_id_not_12);
+COMPILE_ASSERT(offsetof(GetVertexAttribiv, params_shm_offset) == 16,
+               OffsetOf_GetVertexAttribiv_params_shm_offset_not_16);
+
+struct GetVertexAttribPointerv {
+  typedef GetVertexAttribPointerv ValueType;
+  static const CommandId kCmdId = kGetVertexAttribPointerv;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLuint _index, GLenum _pname, uint32 _pointer_shm_id,
+      uint32 _pointer_shm_offset) {
+    SetHeader();
+    index = _index;
+    pname = _pname;
+    pointer_shm_id = _pointer_shm_id;
+    pointer_shm_offset = _pointer_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLuint _index, GLenum _pname, uint32 _pointer_shm_id,
+      uint32 _pointer_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(_index, _pname, _pointer_shm_id, _pointer_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 index;
+  uint32 pname;
+  uint32 pointer_shm_id;
+  uint32 pointer_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(GetVertexAttribPointerv) == 20,
+               Sizeof_GetVertexAttribPointerv_is_not_20);
+COMPILE_ASSERT(offsetof(GetVertexAttribPointerv, header) == 0,
+               OffsetOf_GetVertexAttribPointerv_header_not_0);
+COMPILE_ASSERT(offsetof(GetVertexAttribPointerv, index) == 4,
+               OffsetOf_GetVertexAttribPointerv_index_not_4);
+COMPILE_ASSERT(offsetof(GetVertexAttribPointerv, pname) == 8,
+               OffsetOf_GetVertexAttribPointerv_pname_not_8);
+COMPILE_ASSERT(offsetof(GetVertexAttribPointerv, pointer_shm_id) == 12,
+               OffsetOf_GetVertexAttribPointerv_pointer_shm_id_not_12);
+COMPILE_ASSERT(offsetof(GetVertexAttribPointerv, pointer_shm_offset) == 16,
+               OffsetOf_GetVertexAttribPointerv_pointer_shm_offset_not_16);
+
+struct Hint {
+  typedef Hint ValueType;
+  static const CommandId kCmdId = kHint;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLenum _target, GLenum _mode) {
+    SetHeader();
+    target = _target;
+    mode = _mode;
+  }
+
+  void* Set(void* cmd, GLenum _target, GLenum _mode) {
+    static_cast<ValueType*>(cmd)->Init(_target, _mode);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 target;
+  uint32 mode;
+};
+
+COMPILE_ASSERT(sizeof(Hint) == 12,
+               Sizeof_Hint_is_not_12);
+COMPILE_ASSERT(offsetof(Hint, header) == 0,
+               OffsetOf_Hint_header_not_0);
+COMPILE_ASSERT(offsetof(Hint, target) == 4,
+               OffsetOf_Hint_target_not_4);
+COMPILE_ASSERT(offsetof(Hint, mode) == 8,
+               OffsetOf_Hint_mode_not_8);
+
+struct IsBuffer {
+  typedef IsBuffer ValueType;
+  static const CommandId kCmdId = kIsBuffer;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLuint _buffer, uint32 _result_shm_id, uint32 _result_shm_offset) {
+    SetHeader();
+    buffer = _buffer;
+    result_shm_id = _result_shm_id;
+    result_shm_offset = _result_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLuint _buffer, uint32 _result_shm_id,
+      uint32 _result_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(_buffer, _result_shm_id, _result_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 buffer;
+  uint32 result_shm_id;
+  uint32 result_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(IsBuffer) == 16,
+               Sizeof_IsBuffer_is_not_16);
+COMPILE_ASSERT(offsetof(IsBuffer, header) == 0,
+               OffsetOf_IsBuffer_header_not_0);
+COMPILE_ASSERT(offsetof(IsBuffer, buffer) == 4,
+               OffsetOf_IsBuffer_buffer_not_4);
+COMPILE_ASSERT(offsetof(IsBuffer, result_shm_id) == 8,
+               OffsetOf_IsBuffer_result_shm_id_not_8);
+COMPILE_ASSERT(offsetof(IsBuffer, result_shm_offset) == 12,
+               OffsetOf_IsBuffer_result_shm_offset_not_12);
+
+struct IsEnabled {
+  typedef IsEnabled ValueType;
+  static const CommandId kCmdId = kIsEnabled;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLenum _cap, uint32 _result_shm_id, uint32 _result_shm_offset) {
+    SetHeader();
+    cap = _cap;
+    result_shm_id = _result_shm_id;
+    result_shm_offset = _result_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLenum _cap, uint32 _result_shm_id,
+      uint32 _result_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(_cap, _result_shm_id, _result_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 cap;
+  uint32 result_shm_id;
+  uint32 result_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(IsEnabled) == 16,
+               Sizeof_IsEnabled_is_not_16);
+COMPILE_ASSERT(offsetof(IsEnabled, header) == 0,
+               OffsetOf_IsEnabled_header_not_0);
+COMPILE_ASSERT(offsetof(IsEnabled, cap) == 4,
+               OffsetOf_IsEnabled_cap_not_4);
+COMPILE_ASSERT(offsetof(IsEnabled, result_shm_id) == 8,
+               OffsetOf_IsEnabled_result_shm_id_not_8);
+COMPILE_ASSERT(offsetof(IsEnabled, result_shm_offset) == 12,
+               OffsetOf_IsEnabled_result_shm_offset_not_12);
+
+struct IsFramebuffer {
+  typedef IsFramebuffer ValueType;
+  static const CommandId kCmdId = kIsFramebuffer;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLuint _framebuffer, uint32 _result_shm_id, uint32 _result_shm_offset) {
+    SetHeader();
+    framebuffer = _framebuffer;
+    result_shm_id = _result_shm_id;
+    result_shm_offset = _result_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLuint _framebuffer, uint32 _result_shm_id,
+      uint32 _result_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(_framebuffer, _result_shm_id, _result_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 framebuffer;
+  uint32 result_shm_id;
+  uint32 result_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(IsFramebuffer) == 16,
+               Sizeof_IsFramebuffer_is_not_16);
+COMPILE_ASSERT(offsetof(IsFramebuffer, header) == 0,
+               OffsetOf_IsFramebuffer_header_not_0);
+COMPILE_ASSERT(offsetof(IsFramebuffer, framebuffer) == 4,
+               OffsetOf_IsFramebuffer_framebuffer_not_4);
+COMPILE_ASSERT(offsetof(IsFramebuffer, result_shm_id) == 8,
+               OffsetOf_IsFramebuffer_result_shm_id_not_8);
+COMPILE_ASSERT(offsetof(IsFramebuffer, result_shm_offset) == 12,
+               OffsetOf_IsFramebuffer_result_shm_offset_not_12);
+
+struct IsProgram {
+  typedef IsProgram ValueType;
+  static const CommandId kCmdId = kIsProgram;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLuint _program, uint32 _result_shm_id, uint32 _result_shm_offset) {
+    SetHeader();
+    program = _program;
+    result_shm_id = _result_shm_id;
+    result_shm_offset = _result_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLuint _program, uint32 _result_shm_id,
+      uint32 _result_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(_program, _result_shm_id, _result_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 program;
+  uint32 result_shm_id;
+  uint32 result_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(IsProgram) == 16,
+               Sizeof_IsProgram_is_not_16);
+COMPILE_ASSERT(offsetof(IsProgram, header) == 0,
+               OffsetOf_IsProgram_header_not_0);
+COMPILE_ASSERT(offsetof(IsProgram, program) == 4,
+               OffsetOf_IsProgram_program_not_4);
+COMPILE_ASSERT(offsetof(IsProgram, result_shm_id) == 8,
+               OffsetOf_IsProgram_result_shm_id_not_8);
+COMPILE_ASSERT(offsetof(IsProgram, result_shm_offset) == 12,
+               OffsetOf_IsProgram_result_shm_offset_not_12);
+
+struct IsRenderbuffer {
+  typedef IsRenderbuffer ValueType;
+  static const CommandId kCmdId = kIsRenderbuffer;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLuint _renderbuffer, uint32 _result_shm_id, uint32 _result_shm_offset) {
+    SetHeader();
+    renderbuffer = _renderbuffer;
+    result_shm_id = _result_shm_id;
+    result_shm_offset = _result_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLuint _renderbuffer, uint32 _result_shm_id,
+      uint32 _result_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(_renderbuffer, _result_shm_id, _result_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 renderbuffer;
+  uint32 result_shm_id;
+  uint32 result_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(IsRenderbuffer) == 16,
+               Sizeof_IsRenderbuffer_is_not_16);
+COMPILE_ASSERT(offsetof(IsRenderbuffer, header) == 0,
+               OffsetOf_IsRenderbuffer_header_not_0);
+COMPILE_ASSERT(offsetof(IsRenderbuffer, renderbuffer) == 4,
+               OffsetOf_IsRenderbuffer_renderbuffer_not_4);
+COMPILE_ASSERT(offsetof(IsRenderbuffer, result_shm_id) == 8,
+               OffsetOf_IsRenderbuffer_result_shm_id_not_8);
+COMPILE_ASSERT(offsetof(IsRenderbuffer, result_shm_offset) == 12,
+               OffsetOf_IsRenderbuffer_result_shm_offset_not_12);
+
+struct IsShader {
+  typedef IsShader ValueType;
+  static const CommandId kCmdId = kIsShader;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLuint _shader, uint32 _result_shm_id, uint32 _result_shm_offset) {
+    SetHeader();
+    shader = _shader;
+    result_shm_id = _result_shm_id;
+    result_shm_offset = _result_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLuint _shader, uint32 _result_shm_id,
+      uint32 _result_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(_shader, _result_shm_id, _result_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 shader;
+  uint32 result_shm_id;
+  uint32 result_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(IsShader) == 16,
+               Sizeof_IsShader_is_not_16);
+COMPILE_ASSERT(offsetof(IsShader, header) == 0,
+               OffsetOf_IsShader_header_not_0);
+COMPILE_ASSERT(offsetof(IsShader, shader) == 4,
+               OffsetOf_IsShader_shader_not_4);
+COMPILE_ASSERT(offsetof(IsShader, result_shm_id) == 8,
+               OffsetOf_IsShader_result_shm_id_not_8);
+COMPILE_ASSERT(offsetof(IsShader, result_shm_offset) == 12,
+               OffsetOf_IsShader_result_shm_offset_not_12);
+
+struct IsTexture {
+  typedef IsTexture ValueType;
+  static const CommandId kCmdId = kIsTexture;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLuint _texture, uint32 _result_shm_id, uint32 _result_shm_offset) {
+    SetHeader();
+    texture = _texture;
+    result_shm_id = _result_shm_id;
+    result_shm_offset = _result_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLuint _texture, uint32 _result_shm_id,
+      uint32 _result_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(_texture, _result_shm_id, _result_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 texture;
+  uint32 result_shm_id;
+  uint32 result_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(IsTexture) == 16,
+               Sizeof_IsTexture_is_not_16);
+COMPILE_ASSERT(offsetof(IsTexture, header) == 0,
+               OffsetOf_IsTexture_header_not_0);
+COMPILE_ASSERT(offsetof(IsTexture, texture) == 4,
+               OffsetOf_IsTexture_texture_not_4);
+COMPILE_ASSERT(offsetof(IsTexture, result_shm_id) == 8,
+               OffsetOf_IsTexture_result_shm_id_not_8);
+COMPILE_ASSERT(offsetof(IsTexture, result_shm_offset) == 12,
+               OffsetOf_IsTexture_result_shm_offset_not_12);
+
+struct LineWidth {
+  typedef LineWidth ValueType;
+  static const CommandId kCmdId = kLineWidth;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLfloat _width) {
+    SetHeader();
+    width = _width;
+  }
+
+  void* Set(void* cmd, GLfloat _width) {
+    static_cast<ValueType*>(cmd)->Init(_width);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  float width;
+};
+
+COMPILE_ASSERT(sizeof(LineWidth) == 8,
+               Sizeof_LineWidth_is_not_8);
+COMPILE_ASSERT(offsetof(LineWidth, header) == 0,
+               OffsetOf_LineWidth_header_not_0);
+COMPILE_ASSERT(offsetof(LineWidth, width) == 4,
+               OffsetOf_LineWidth_width_not_4);
+
+struct LinkProgram {
+  typedef LinkProgram ValueType;
+  static const CommandId kCmdId = kLinkProgram;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLuint _program) {
+    SetHeader();
+    program = _program;
+  }
+
+  void* Set(void* cmd, GLuint _program) {
+    static_cast<ValueType*>(cmd)->Init(_program);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 program;
+};
+
+COMPILE_ASSERT(sizeof(LinkProgram) == 8,
+               Sizeof_LinkProgram_is_not_8);
+COMPILE_ASSERT(offsetof(LinkProgram, header) == 0,
+               OffsetOf_LinkProgram_header_not_0);
+COMPILE_ASSERT(offsetof(LinkProgram, program) == 4,
+               OffsetOf_LinkProgram_program_not_4);
+
+struct PixelStorei {
+  typedef PixelStorei ValueType;
+  static const CommandId kCmdId = kPixelStorei;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLenum _pname, GLint _param) {
+    SetHeader();
+    pname = _pname;
+    param = _param;
+  }
+
+  void* Set(void* cmd, GLenum _pname, GLint _param) {
+    static_cast<ValueType*>(cmd)->Init(_pname, _param);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 pname;
+  uint32 param;
+};
+
+COMPILE_ASSERT(sizeof(PixelStorei) == 12,
+               Sizeof_PixelStorei_is_not_12);
+COMPILE_ASSERT(offsetof(PixelStorei, header) == 0,
+               OffsetOf_PixelStorei_header_not_0);
+COMPILE_ASSERT(offsetof(PixelStorei, pname) == 4,
+               OffsetOf_PixelStorei_pname_not_4);
+COMPILE_ASSERT(offsetof(PixelStorei, param) == 8,
+               OffsetOf_PixelStorei_param_not_8);
+
+struct PolygonOffset {
+  typedef PolygonOffset ValueType;
+  static const CommandId kCmdId = kPolygonOffset;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLfloat _factor, GLfloat _units) {
+    SetHeader();
+    factor = _factor;
+    units = _units;
+  }
+
+  void* Set(void* cmd, GLfloat _factor, GLfloat _units) {
+    static_cast<ValueType*>(cmd)->Init(_factor, _units);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  float factor;
+  float units;
+};
+
+COMPILE_ASSERT(sizeof(PolygonOffset) == 12,
+               Sizeof_PolygonOffset_is_not_12);
+COMPILE_ASSERT(offsetof(PolygonOffset, header) == 0,
+               OffsetOf_PolygonOffset_header_not_0);
+COMPILE_ASSERT(offsetof(PolygonOffset, factor) == 4,
+               OffsetOf_PolygonOffset_factor_not_4);
+COMPILE_ASSERT(offsetof(PolygonOffset, units) == 8,
+               OffsetOf_PolygonOffset_units_not_8);
+
+struct ReadPixels {
+  typedef ReadPixels ValueType;
+  static const CommandId kCmdId = kReadPixels;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLint _x, GLint _y, GLsizei _width, GLsizei _height, GLenum _format,
+      GLenum _type, uint32 _pixels_shm_id, uint32 _pixels_shm_offset) {
+    SetHeader();
+    x = _x;
+    y = _y;
+    width = _width;
+    height = _height;
+    format = _format;
+    type = _type;
+    pixels_shm_id = _pixels_shm_id;
+    pixels_shm_offset = _pixels_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLint _x, GLint _y, GLsizei _width, GLsizei _height,
+      GLenum _format, GLenum _type, uint32 _pixels_shm_id,
+      uint32 _pixels_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(
+            _x, _y, _width, _height, _format, _type, _pixels_shm_id,
+            _pixels_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 x;
+  uint32 y;
+  uint32 width;
+  uint32 height;
+  uint32 format;
+  uint32 type;
+  uint32 pixels_shm_id;
+  uint32 pixels_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(ReadPixels) == 36,
+               Sizeof_ReadPixels_is_not_36);
+COMPILE_ASSERT(offsetof(ReadPixels, header) == 0,
+               OffsetOf_ReadPixels_header_not_0);
+COMPILE_ASSERT(offsetof(ReadPixels, x) == 4,
+               OffsetOf_ReadPixels_x_not_4);
+COMPILE_ASSERT(offsetof(ReadPixels, y) == 8,
+               OffsetOf_ReadPixels_y_not_8);
+COMPILE_ASSERT(offsetof(ReadPixels, width) == 12,
+               OffsetOf_ReadPixels_width_not_12);
+COMPILE_ASSERT(offsetof(ReadPixels, height) == 16,
+               OffsetOf_ReadPixels_height_not_16);
+COMPILE_ASSERT(offsetof(ReadPixels, format) == 20,
+               OffsetOf_ReadPixels_format_not_20);
+COMPILE_ASSERT(offsetof(ReadPixels, type) == 24,
+               OffsetOf_ReadPixels_type_not_24);
+COMPILE_ASSERT(offsetof(ReadPixels, pixels_shm_id) == 28,
+               OffsetOf_ReadPixels_pixels_shm_id_not_28);
+COMPILE_ASSERT(offsetof(ReadPixels, pixels_shm_offset) == 32,
+               OffsetOf_ReadPixels_pixels_shm_offset_not_32);
+
+struct RenderbufferStorage {
+  typedef RenderbufferStorage ValueType;
+  static const CommandId kCmdId = kRenderbufferStorage;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLenum _target, GLenum _internalformat, GLsizei _width,
+      GLsizei _height) {
+    SetHeader();
+    target = _target;
+    internalformat = _internalformat;
+    width = _width;
+    height = _height;
+  }
+
+  void* Set(
+      void* cmd, GLenum _target, GLenum _internalformat, GLsizei _width,
+      GLsizei _height) {
+    static_cast<ValueType*>(
+        cmd)->Init(_target, _internalformat, _width, _height);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 target;
+  uint32 internalformat;
+  uint32 width;
+  uint32 height;
+};
+
+COMPILE_ASSERT(sizeof(RenderbufferStorage) == 20,
+               Sizeof_RenderbufferStorage_is_not_20);
+COMPILE_ASSERT(offsetof(RenderbufferStorage, header) == 0,
+               OffsetOf_RenderbufferStorage_header_not_0);
+COMPILE_ASSERT(offsetof(RenderbufferStorage, target) == 4,
+               OffsetOf_RenderbufferStorage_target_not_4);
+COMPILE_ASSERT(offsetof(RenderbufferStorage, internalformat) == 8,
+               OffsetOf_RenderbufferStorage_internalformat_not_8);
+COMPILE_ASSERT(offsetof(RenderbufferStorage, width) == 12,
+               OffsetOf_RenderbufferStorage_width_not_12);
+COMPILE_ASSERT(offsetof(RenderbufferStorage, height) == 16,
+               OffsetOf_RenderbufferStorage_height_not_16);
+
+struct SampleCoverage {
+  typedef SampleCoverage ValueType;
+  static const CommandId kCmdId = kSampleCoverage;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLclampf _value, GLboolean _invert) {
+    SetHeader();
+    value = _value;
+    invert = _invert;
+  }
+
+  void* Set(void* cmd, GLclampf _value, GLboolean _invert) {
+    static_cast<ValueType*>(cmd)->Init(_value, _invert);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  float value;
+  uint32 invert;
+};
+
+COMPILE_ASSERT(sizeof(SampleCoverage) == 12,
+               Sizeof_SampleCoverage_is_not_12);
+COMPILE_ASSERT(offsetof(SampleCoverage, header) == 0,
+               OffsetOf_SampleCoverage_header_not_0);
+COMPILE_ASSERT(offsetof(SampleCoverage, value) == 4,
+               OffsetOf_SampleCoverage_value_not_4);
+COMPILE_ASSERT(offsetof(SampleCoverage, invert) == 8,
+               OffsetOf_SampleCoverage_invert_not_8);
+
+struct Scissor {
+  typedef Scissor ValueType;
+  static const CommandId kCmdId = kScissor;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLint _x, GLint _y, GLsizei _width, GLsizei _height) {
+    SetHeader();
+    x = _x;
+    y = _y;
+    width = _width;
+    height = _height;
+  }
+
+  void* Set(void* cmd, GLint _x, GLint _y, GLsizei _width, GLsizei _height) {
+    static_cast<ValueType*>(cmd)->Init(_x, _y, _width, _height);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 x;
+  uint32 y;
+  uint32 width;
+  uint32 height;
+};
+
+COMPILE_ASSERT(sizeof(Scissor) == 20,
+               Sizeof_Scissor_is_not_20);
+COMPILE_ASSERT(offsetof(Scissor, header) == 0,
+               OffsetOf_Scissor_header_not_0);
+COMPILE_ASSERT(offsetof(Scissor, x) == 4,
+               OffsetOf_Scissor_x_not_4);
+COMPILE_ASSERT(offsetof(Scissor, y) == 8,
+               OffsetOf_Scissor_y_not_8);
+COMPILE_ASSERT(offsetof(Scissor, width) == 12,
+               OffsetOf_Scissor_width_not_12);
+COMPILE_ASSERT(offsetof(Scissor, height) == 16,
+               OffsetOf_Scissor_height_not_16);
+
+struct ShaderSource {
+  typedef ShaderSource ValueType;
+  static const CommandId kCmdId = kShaderSource;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLuint _shader, GLsizei _count, uint32 _data_shm_id,
+      uint32 _data_shm_offset, uint32 _data_size) {
+    SetHeader();
+    shader = _shader;
+    count = _count;
+    data_shm_id = _data_shm_id;
+    data_shm_offset = _data_shm_offset;
+    data_size = _data_size;
+  }
+
+  void* Set(
+      void* cmd, GLuint _shader, GLsizei _count, uint32 _data_shm_id,
+      uint32 _data_shm_offset, uint32 _data_size) {
+    static_cast<ValueType*>(
+        cmd)->Init(
+            _shader, _count, _data_shm_id, _data_shm_offset, _data_size);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 shader;
+  uint32 count;
+  uint32 data_shm_id;
+  uint32 data_shm_offset;
+  uint32 data_size;
+};
+
+COMPILE_ASSERT(sizeof(ShaderSource) == 24,
+               Sizeof_ShaderSource_is_not_24);
+COMPILE_ASSERT(offsetof(ShaderSource, header) == 0,
+               OffsetOf_ShaderSource_header_not_0);
+COMPILE_ASSERT(offsetof(ShaderSource, shader) == 4,
+               OffsetOf_ShaderSource_shader_not_4);
+COMPILE_ASSERT(offsetof(ShaderSource, count) == 8,
+               OffsetOf_ShaderSource_count_not_8);
+COMPILE_ASSERT(offsetof(ShaderSource, data_shm_id) == 12,
+               OffsetOf_ShaderSource_data_shm_id_not_12);
+COMPILE_ASSERT(offsetof(ShaderSource, data_shm_offset) == 16,
+               OffsetOf_ShaderSource_data_shm_offset_not_16);
+COMPILE_ASSERT(offsetof(ShaderSource, data_size) == 20,
+               OffsetOf_ShaderSource_data_size_not_20);
+
+struct ShaderSourceImmediate {
+  typedef ShaderSourceImmediate ValueType;
+  static const CommandId kCmdId = kShaderSourceImmediate;
+  static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN;
+
+  static uint32 ComputeSize(uint32 size_in_bytes) {
+    return static_cast<uint32>(
+        sizeof(ValueType) +  // NOLINT
+        RoundSizeToMultipleOfEntries(size_in_bytes));
+  }
+
+  void SetHeader(uint32 size_in_bytes) {
+    header.SetCmdByTotalSize<ValueType>(size_in_bytes);
+  }
+
+  void Init(GLuint _shader, GLsizei _count, uint32 _data_size) {
+    uint32 total_size = ComputeSize(_data_size);
+    SetHeader(total_size);
+    shader = _shader;
+    count = _count;
+    data_size = _data_size;
+  }
+
+  void* Set(void* cmd, GLuint _shader, GLsizei _count, uint32 _data_size) {
+    uint32 total_size = ComputeSize(_data_size);
+    static_cast<ValueType*>(cmd)->Init(_shader, _count, _data_size);
+    return NextImmediateCmdAddressTotalSize<ValueType>(cmd, total_size);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 shader;
+  uint32 count;
+  uint32 data_size;
+};
+
+COMPILE_ASSERT(sizeof(ShaderSourceImmediate) == 16,
+               Sizeof_ShaderSourceImmediate_is_not_16);
+COMPILE_ASSERT(offsetof(ShaderSourceImmediate, header) == 0,
+               OffsetOf_ShaderSourceImmediate_header_not_0);
+COMPILE_ASSERT(offsetof(ShaderSourceImmediate, shader) == 4,
+               OffsetOf_ShaderSourceImmediate_shader_not_4);
+COMPILE_ASSERT(offsetof(ShaderSourceImmediate, count) == 8,
+               OffsetOf_ShaderSourceImmediate_count_not_8);
+COMPILE_ASSERT(offsetof(ShaderSourceImmediate, data_size) == 12,
+               OffsetOf_ShaderSourceImmediate_data_size_not_12);
+
+struct StencilFunc {
+  typedef StencilFunc ValueType;
+  static const CommandId kCmdId = kStencilFunc;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLenum _func, GLint _ref, GLuint _mask) {
+    SetHeader();
+    func = _func;
+    ref = _ref;
+    mask = _mask;
+  }
+
+  void* Set(void* cmd, GLenum _func, GLint _ref, GLuint _mask) {
+    static_cast<ValueType*>(cmd)->Init(_func, _ref, _mask);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 func;
+  uint32 ref;
+  uint32 mask;
+};
+
+COMPILE_ASSERT(sizeof(StencilFunc) == 16,
+               Sizeof_StencilFunc_is_not_16);
+COMPILE_ASSERT(offsetof(StencilFunc, header) == 0,
+               OffsetOf_StencilFunc_header_not_0);
+COMPILE_ASSERT(offsetof(StencilFunc, func) == 4,
+               OffsetOf_StencilFunc_func_not_4);
+COMPILE_ASSERT(offsetof(StencilFunc, ref) == 8,
+               OffsetOf_StencilFunc_ref_not_8);
+COMPILE_ASSERT(offsetof(StencilFunc, mask) == 12,
+               OffsetOf_StencilFunc_mask_not_12);
+
+struct StencilFuncSeparate {
+  typedef StencilFuncSeparate ValueType;
+  static const CommandId kCmdId = kStencilFuncSeparate;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLenum _face, GLenum _func, GLint _ref, GLuint _mask) {
+    SetHeader();
+    face = _face;
+    func = _func;
+    ref = _ref;
+    mask = _mask;
+  }
+
+  void* Set(void* cmd, GLenum _face, GLenum _func, GLint _ref, GLuint _mask) {
+    static_cast<ValueType*>(cmd)->Init(_face, _func, _ref, _mask);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 face;
+  uint32 func;
+  uint32 ref;
+  uint32 mask;
+};
+
+COMPILE_ASSERT(sizeof(StencilFuncSeparate) == 20,
+               Sizeof_StencilFuncSeparate_is_not_20);
+COMPILE_ASSERT(offsetof(StencilFuncSeparate, header) == 0,
+               OffsetOf_StencilFuncSeparate_header_not_0);
+COMPILE_ASSERT(offsetof(StencilFuncSeparate, face) == 4,
+               OffsetOf_StencilFuncSeparate_face_not_4);
+COMPILE_ASSERT(offsetof(StencilFuncSeparate, func) == 8,
+               OffsetOf_StencilFuncSeparate_func_not_8);
+COMPILE_ASSERT(offsetof(StencilFuncSeparate, ref) == 12,
+               OffsetOf_StencilFuncSeparate_ref_not_12);
+COMPILE_ASSERT(offsetof(StencilFuncSeparate, mask) == 16,
+               OffsetOf_StencilFuncSeparate_mask_not_16);
+
+struct StencilMask {
+  typedef StencilMask ValueType;
+  static const CommandId kCmdId = kStencilMask;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLuint _mask) {
+    SetHeader();
+    mask = _mask;
+  }
+
+  void* Set(void* cmd, GLuint _mask) {
+    static_cast<ValueType*>(cmd)->Init(_mask);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 mask;
+};
+
+COMPILE_ASSERT(sizeof(StencilMask) == 8,
+               Sizeof_StencilMask_is_not_8);
+COMPILE_ASSERT(offsetof(StencilMask, header) == 0,
+               OffsetOf_StencilMask_header_not_0);
+COMPILE_ASSERT(offsetof(StencilMask, mask) == 4,
+               OffsetOf_StencilMask_mask_not_4);
+
+struct StencilMaskSeparate {
+  typedef StencilMaskSeparate ValueType;
+  static const CommandId kCmdId = kStencilMaskSeparate;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLenum _face, GLuint _mask) {
+    SetHeader();
+    face = _face;
+    mask = _mask;
+  }
+
+  void* Set(void* cmd, GLenum _face, GLuint _mask) {
+    static_cast<ValueType*>(cmd)->Init(_face, _mask);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 face;
+  uint32 mask;
+};
+
+COMPILE_ASSERT(sizeof(StencilMaskSeparate) == 12,
+               Sizeof_StencilMaskSeparate_is_not_12);
+COMPILE_ASSERT(offsetof(StencilMaskSeparate, header) == 0,
+               OffsetOf_StencilMaskSeparate_header_not_0);
+COMPILE_ASSERT(offsetof(StencilMaskSeparate, face) == 4,
+               OffsetOf_StencilMaskSeparate_face_not_4);
+COMPILE_ASSERT(offsetof(StencilMaskSeparate, mask) == 8,
+               OffsetOf_StencilMaskSeparate_mask_not_8);
+
+struct StencilOp {
+  typedef StencilOp ValueType;
+  static const CommandId kCmdId = kStencilOp;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLenum _fail, GLenum _zfail, GLenum _zpass) {
+    SetHeader();
+    fail = _fail;
+    zfail = _zfail;
+    zpass = _zpass;
+  }
+
+  void* Set(void* cmd, GLenum _fail, GLenum _zfail, GLenum _zpass) {
+    static_cast<ValueType*>(cmd)->Init(_fail, _zfail, _zpass);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 fail;
+  uint32 zfail;
+  uint32 zpass;
+};
+
+COMPILE_ASSERT(sizeof(StencilOp) == 16,
+               Sizeof_StencilOp_is_not_16);
+COMPILE_ASSERT(offsetof(StencilOp, header) == 0,
+               OffsetOf_StencilOp_header_not_0);
+COMPILE_ASSERT(offsetof(StencilOp, fail) == 4,
+               OffsetOf_StencilOp_fail_not_4);
+COMPILE_ASSERT(offsetof(StencilOp, zfail) == 8,
+               OffsetOf_StencilOp_zfail_not_8);
+COMPILE_ASSERT(offsetof(StencilOp, zpass) == 12,
+               OffsetOf_StencilOp_zpass_not_12);
+
+struct StencilOpSeparate {
+  typedef StencilOpSeparate ValueType;
+  static const CommandId kCmdId = kStencilOpSeparate;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLenum _face, GLenum _fail, GLenum _zfail, GLenum _zpass) {
+    SetHeader();
+    face = _face;
+    fail = _fail;
+    zfail = _zfail;
+    zpass = _zpass;
+  }
+
+  void* Set(
+      void* cmd, GLenum _face, GLenum _fail, GLenum _zfail, GLenum _zpass) {
+    static_cast<ValueType*>(cmd)->Init(_face, _fail, _zfail, _zpass);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 face;
+  uint32 fail;
+  uint32 zfail;
+  uint32 zpass;
+};
+
+COMPILE_ASSERT(sizeof(StencilOpSeparate) == 20,
+               Sizeof_StencilOpSeparate_is_not_20);
+COMPILE_ASSERT(offsetof(StencilOpSeparate, header) == 0,
+               OffsetOf_StencilOpSeparate_header_not_0);
+COMPILE_ASSERT(offsetof(StencilOpSeparate, face) == 4,
+               OffsetOf_StencilOpSeparate_face_not_4);
+COMPILE_ASSERT(offsetof(StencilOpSeparate, fail) == 8,
+               OffsetOf_StencilOpSeparate_fail_not_8);
+COMPILE_ASSERT(offsetof(StencilOpSeparate, zfail) == 12,
+               OffsetOf_StencilOpSeparate_zfail_not_12);
+COMPILE_ASSERT(offsetof(StencilOpSeparate, zpass) == 16,
+               OffsetOf_StencilOpSeparate_zpass_not_16);
+
+struct TexImage2D {
+  typedef TexImage2D ValueType;
+  static const CommandId kCmdId = kTexImage2D;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLenum _target, GLint _level, GLint _internalformat, GLsizei _width,
+      GLsizei _height, GLint _border, GLenum _format, GLenum _type,
+      uint32 _pixels_shm_id, uint32 _pixels_shm_offset) {
+    SetHeader();
+    target = _target;
+    level = _level;
+    internalformat = _internalformat;
+    width = _width;
+    height = _height;
+    border = _border;
+    format = _format;
+    type = _type;
+    pixels_shm_id = _pixels_shm_id;
+    pixels_shm_offset = _pixels_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLenum _target, GLint _level, GLint _internalformat,
+      GLsizei _width, GLsizei _height, GLint _border, GLenum _format,
+      GLenum _type, uint32 _pixels_shm_id, uint32 _pixels_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(
+            _target, _level, _internalformat, _width, _height, _border, _format,
+            _type, _pixels_shm_id, _pixels_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 target;
+  uint32 level;
+  uint32 internalformat;
+  uint32 width;
+  uint32 height;
+  uint32 border;
+  uint32 format;
+  uint32 type;
+  uint32 pixels_shm_id;
+  uint32 pixels_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(TexImage2D) == 44,
+               Sizeof_TexImage2D_is_not_44);
+COMPILE_ASSERT(offsetof(TexImage2D, header) == 0,
+               OffsetOf_TexImage2D_header_not_0);
+COMPILE_ASSERT(offsetof(TexImage2D, target) == 4,
+               OffsetOf_TexImage2D_target_not_4);
+COMPILE_ASSERT(offsetof(TexImage2D, level) == 8,
+               OffsetOf_TexImage2D_level_not_8);
+COMPILE_ASSERT(offsetof(TexImage2D, internalformat) == 12,
+               OffsetOf_TexImage2D_internalformat_not_12);
+COMPILE_ASSERT(offsetof(TexImage2D, width) == 16,
+               OffsetOf_TexImage2D_width_not_16);
+COMPILE_ASSERT(offsetof(TexImage2D, height) == 20,
+               OffsetOf_TexImage2D_height_not_20);
+COMPILE_ASSERT(offsetof(TexImage2D, border) == 24,
+               OffsetOf_TexImage2D_border_not_24);
+COMPILE_ASSERT(offsetof(TexImage2D, format) == 28,
+               OffsetOf_TexImage2D_format_not_28);
+COMPILE_ASSERT(offsetof(TexImage2D, type) == 32,
+               OffsetOf_TexImage2D_type_not_32);
+COMPILE_ASSERT(offsetof(TexImage2D, pixels_shm_id) == 36,
+               OffsetOf_TexImage2D_pixels_shm_id_not_36);
+COMPILE_ASSERT(offsetof(TexImage2D, pixels_shm_offset) == 40,
+               OffsetOf_TexImage2D_pixels_shm_offset_not_40);
+
+struct TexImage2DImmediate {
+  typedef TexImage2DImmediate ValueType;
+  static const CommandId kCmdId = kTexImage2DImmediate;
+  static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN;
+
+  static uint32 ComputeSize(uint32 size_in_bytes) {
+    return static_cast<uint32>(
+        sizeof(ValueType) +  // NOLINT
+        RoundSizeToMultipleOfEntries(size_in_bytes));
+  }
+
+  void SetHeader(uint32 size_in_bytes) {
+    header.SetCmdByTotalSize<ValueType>(size_in_bytes);
+  }
+
+  void Init(
+      GLenum _target, GLint _level, GLint _internalformat, GLsizei _width,
+      GLsizei _height, GLint _border, GLenum _format, GLenum _type) {
+    uint32 total_size = 0;  // TODO(gman): get correct size
+    SetHeader(total_size);
+    target = _target;
+    level = _level;
+    internalformat = _internalformat;
+    width = _width;
+    height = _height;
+    border = _border;
+    format = _format;
+    type = _type;
+  }
+
+  void* Set(
+      void* cmd, GLenum _target, GLint _level, GLint _internalformat,
+      GLsizei _width, GLsizei _height, GLint _border, GLenum _format,
+      GLenum _type) {
+    uint32 total_size = 0;  // TODO(gman): get correct size
+    static_cast<ValueType*>(
+        cmd)->Init(
+            _target, _level, _internalformat, _width, _height, _border, _format,
+            _type);
+    return NextImmediateCmdAddressTotalSize<ValueType>(cmd, total_size);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 target;
+  uint32 level;
+  uint32 internalformat;
+  uint32 width;
+  uint32 height;
+  uint32 border;
+  uint32 format;
+  uint32 type;
+};
+
+COMPILE_ASSERT(sizeof(TexImage2DImmediate) == 36,
+               Sizeof_TexImage2DImmediate_is_not_36);
+COMPILE_ASSERT(offsetof(TexImage2DImmediate, header) == 0,
+               OffsetOf_TexImage2DImmediate_header_not_0);
+COMPILE_ASSERT(offsetof(TexImage2DImmediate, target) == 4,
+               OffsetOf_TexImage2DImmediate_target_not_4);
+COMPILE_ASSERT(offsetof(TexImage2DImmediate, level) == 8,
+               OffsetOf_TexImage2DImmediate_level_not_8);
+COMPILE_ASSERT(offsetof(TexImage2DImmediate, internalformat) == 12,
+               OffsetOf_TexImage2DImmediate_internalformat_not_12);
+COMPILE_ASSERT(offsetof(TexImage2DImmediate, width) == 16,
+               OffsetOf_TexImage2DImmediate_width_not_16);
+COMPILE_ASSERT(offsetof(TexImage2DImmediate, height) == 20,
+               OffsetOf_TexImage2DImmediate_height_not_20);
+COMPILE_ASSERT(offsetof(TexImage2DImmediate, border) == 24,
+               OffsetOf_TexImage2DImmediate_border_not_24);
+COMPILE_ASSERT(offsetof(TexImage2DImmediate, format) == 28,
+               OffsetOf_TexImage2DImmediate_format_not_28);
+COMPILE_ASSERT(offsetof(TexImage2DImmediate, type) == 32,
+               OffsetOf_TexImage2DImmediate_type_not_32);
+
+struct TexParameterf {
+  typedef TexParameterf ValueType;
+  static const CommandId kCmdId = kTexParameterf;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLenum _target, GLenum _pname, GLfloat _param) {
+    SetHeader();
+    target = _target;
+    pname = _pname;
+    param = _param;
+  }
+
+  void* Set(void* cmd, GLenum _target, GLenum _pname, GLfloat _param) {
+    static_cast<ValueType*>(cmd)->Init(_target, _pname, _param);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 target;
+  uint32 pname;
+  float param;
+};
+
+COMPILE_ASSERT(sizeof(TexParameterf) == 16,
+               Sizeof_TexParameterf_is_not_16);
+COMPILE_ASSERT(offsetof(TexParameterf, header) == 0,
+               OffsetOf_TexParameterf_header_not_0);
+COMPILE_ASSERT(offsetof(TexParameterf, target) == 4,
+               OffsetOf_TexParameterf_target_not_4);
+COMPILE_ASSERT(offsetof(TexParameterf, pname) == 8,
+               OffsetOf_TexParameterf_pname_not_8);
+COMPILE_ASSERT(offsetof(TexParameterf, param) == 12,
+               OffsetOf_TexParameterf_param_not_12);
+
+struct TexParameterfv {
+  typedef TexParameterfv ValueType;
+  static const CommandId kCmdId = kTexParameterfv;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLenum _target, GLenum _pname, uint32 _params_shm_id,
+      uint32 _params_shm_offset) {
+    SetHeader();
+    target = _target;
+    pname = _pname;
+    params_shm_id = _params_shm_id;
+    params_shm_offset = _params_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLenum _target, GLenum _pname, uint32 _params_shm_id,
+      uint32 _params_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(_target, _pname, _params_shm_id, _params_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 target;
+  uint32 pname;
+  uint32 params_shm_id;
+  uint32 params_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(TexParameterfv) == 20,
+               Sizeof_TexParameterfv_is_not_20);
+COMPILE_ASSERT(offsetof(TexParameterfv, header) == 0,
+               OffsetOf_TexParameterfv_header_not_0);
+COMPILE_ASSERT(offsetof(TexParameterfv, target) == 4,
+               OffsetOf_TexParameterfv_target_not_4);
+COMPILE_ASSERT(offsetof(TexParameterfv, pname) == 8,
+               OffsetOf_TexParameterfv_pname_not_8);
+COMPILE_ASSERT(offsetof(TexParameterfv, params_shm_id) == 12,
+               OffsetOf_TexParameterfv_params_shm_id_not_12);
+COMPILE_ASSERT(offsetof(TexParameterfv, params_shm_offset) == 16,
+               OffsetOf_TexParameterfv_params_shm_offset_not_16);
+
+struct TexParameterfvImmediate {
+  typedef TexParameterfvImmediate ValueType;
+  static const CommandId kCmdId = kTexParameterfvImmediate;
+  static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN;
+
+  static uint32 ComputeDataSize() {
+    return static_cast<uint32>(
+        sizeof(GLfloat) * 1);  // NOLINT
+  }
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(
+        sizeof(ValueType) + ComputeDataSize());  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmdByTotalSize<ValueType>(ComputeSize());
+  }
+
+  void Init(GLenum _target, GLenum _pname, const GLfloat* _params) {
+    SetHeader();
+    target = _target;
+    pname = _pname;
+    memcpy(ImmediateDataAddress(this),
+           _params, ComputeDataSize());
+  }
+
+  void* Set(void* cmd, GLenum _target, GLenum _pname, const GLfloat* _params) {
+    static_cast<ValueType*>(cmd)->Init(_target, _pname, _params);
+    const uint32 size = ComputeSize();
+    return NextImmediateCmdAddressTotalSize<ValueType>(cmd, size);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 target;
+  uint32 pname;
+};
+
+COMPILE_ASSERT(sizeof(TexParameterfvImmediate) == 12,
+               Sizeof_TexParameterfvImmediate_is_not_12);
+COMPILE_ASSERT(offsetof(TexParameterfvImmediate, header) == 0,
+               OffsetOf_TexParameterfvImmediate_header_not_0);
+COMPILE_ASSERT(offsetof(TexParameterfvImmediate, target) == 4,
+               OffsetOf_TexParameterfvImmediate_target_not_4);
+COMPILE_ASSERT(offsetof(TexParameterfvImmediate, pname) == 8,
+               OffsetOf_TexParameterfvImmediate_pname_not_8);
+
+struct TexParameteri {
+  typedef TexParameteri ValueType;
+  static const CommandId kCmdId = kTexParameteri;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLenum _target, GLenum _pname, GLint _param) {
+    SetHeader();
+    target = _target;
+    pname = _pname;
+    param = _param;
+  }
+
+  void* Set(void* cmd, GLenum _target, GLenum _pname, GLint _param) {
+    static_cast<ValueType*>(cmd)->Init(_target, _pname, _param);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 target;
+  uint32 pname;
+  uint32 param;
+};
+
+COMPILE_ASSERT(sizeof(TexParameteri) == 16,
+               Sizeof_TexParameteri_is_not_16);
+COMPILE_ASSERT(offsetof(TexParameteri, header) == 0,
+               OffsetOf_TexParameteri_header_not_0);
+COMPILE_ASSERT(offsetof(TexParameteri, target) == 4,
+               OffsetOf_TexParameteri_target_not_4);
+COMPILE_ASSERT(offsetof(TexParameteri, pname) == 8,
+               OffsetOf_TexParameteri_pname_not_8);
+COMPILE_ASSERT(offsetof(TexParameteri, param) == 12,
+               OffsetOf_TexParameteri_param_not_12);
+
+struct TexParameteriv {
+  typedef TexParameteriv ValueType;
+  static const CommandId kCmdId = kTexParameteriv;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLenum _target, GLenum _pname, uint32 _params_shm_id,
+      uint32 _params_shm_offset) {
+    SetHeader();
+    target = _target;
+    pname = _pname;
+    params_shm_id = _params_shm_id;
+    params_shm_offset = _params_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLenum _target, GLenum _pname, uint32 _params_shm_id,
+      uint32 _params_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(_target, _pname, _params_shm_id, _params_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 target;
+  uint32 pname;
+  uint32 params_shm_id;
+  uint32 params_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(TexParameteriv) == 20,
+               Sizeof_TexParameteriv_is_not_20);
+COMPILE_ASSERT(offsetof(TexParameteriv, header) == 0,
+               OffsetOf_TexParameteriv_header_not_0);
+COMPILE_ASSERT(offsetof(TexParameteriv, target) == 4,
+               OffsetOf_TexParameteriv_target_not_4);
+COMPILE_ASSERT(offsetof(TexParameteriv, pname) == 8,
+               OffsetOf_TexParameteriv_pname_not_8);
+COMPILE_ASSERT(offsetof(TexParameteriv, params_shm_id) == 12,
+               OffsetOf_TexParameteriv_params_shm_id_not_12);
+COMPILE_ASSERT(offsetof(TexParameteriv, params_shm_offset) == 16,
+               OffsetOf_TexParameteriv_params_shm_offset_not_16);
+
+struct TexParameterivImmediate {
+  typedef TexParameterivImmediate ValueType;
+  static const CommandId kCmdId = kTexParameterivImmediate;
+  static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN;
+
+  static uint32 ComputeDataSize() {
+    return static_cast<uint32>(
+        sizeof(GLint) * 1);  // NOLINT
+  }
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(
+        sizeof(ValueType) + ComputeDataSize());  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmdByTotalSize<ValueType>(ComputeSize());
+  }
+
+  void Init(GLenum _target, GLenum _pname, const GLint* _params) {
+    SetHeader();
+    target = _target;
+    pname = _pname;
+    memcpy(ImmediateDataAddress(this),
+           _params, ComputeDataSize());
+  }
+
+  void* Set(void* cmd, GLenum _target, GLenum _pname, const GLint* _params) {
+    static_cast<ValueType*>(cmd)->Init(_target, _pname, _params);
+    const uint32 size = ComputeSize();
+    return NextImmediateCmdAddressTotalSize<ValueType>(cmd, size);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 target;
+  uint32 pname;
+};
+
+COMPILE_ASSERT(sizeof(TexParameterivImmediate) == 12,
+               Sizeof_TexParameterivImmediate_is_not_12);
+COMPILE_ASSERT(offsetof(TexParameterivImmediate, header) == 0,
+               OffsetOf_TexParameterivImmediate_header_not_0);
+COMPILE_ASSERT(offsetof(TexParameterivImmediate, target) == 4,
+               OffsetOf_TexParameterivImmediate_target_not_4);
+COMPILE_ASSERT(offsetof(TexParameterivImmediate, pname) == 8,
+               OffsetOf_TexParameterivImmediate_pname_not_8);
+
+struct TexSubImage2D {
+  typedef TexSubImage2D ValueType;
+  static const CommandId kCmdId = kTexSubImage2D;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLenum _target, GLint _level, GLint _xoffset, GLint _yoffset,
+      GLsizei _width, GLsizei _height, GLenum _format, GLenum _type,
+      uint32 _pixels_shm_id, uint32 _pixels_shm_offset) {
+    SetHeader();
+    target = _target;
+    level = _level;
+    xoffset = _xoffset;
+    yoffset = _yoffset;
+    width = _width;
+    height = _height;
+    format = _format;
+    type = _type;
+    pixels_shm_id = _pixels_shm_id;
+    pixels_shm_offset = _pixels_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLenum _target, GLint _level, GLint _xoffset, GLint _yoffset,
+      GLsizei _width, GLsizei _height, GLenum _format, GLenum _type,
+      uint32 _pixels_shm_id, uint32 _pixels_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(
+            _target, _level, _xoffset, _yoffset, _width, _height, _format,
+            _type, _pixels_shm_id, _pixels_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 target;
+  uint32 level;
+  uint32 xoffset;
+  uint32 yoffset;
+  uint32 width;
+  uint32 height;
+  uint32 format;
+  uint32 type;
+  uint32 pixels_shm_id;
+  uint32 pixels_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(TexSubImage2D) == 44,
+               Sizeof_TexSubImage2D_is_not_44);
+COMPILE_ASSERT(offsetof(TexSubImage2D, header) == 0,
+               OffsetOf_TexSubImage2D_header_not_0);
+COMPILE_ASSERT(offsetof(TexSubImage2D, target) == 4,
+               OffsetOf_TexSubImage2D_target_not_4);
+COMPILE_ASSERT(offsetof(TexSubImage2D, level) == 8,
+               OffsetOf_TexSubImage2D_level_not_8);
+COMPILE_ASSERT(offsetof(TexSubImage2D, xoffset) == 12,
+               OffsetOf_TexSubImage2D_xoffset_not_12);
+COMPILE_ASSERT(offsetof(TexSubImage2D, yoffset) == 16,
+               OffsetOf_TexSubImage2D_yoffset_not_16);
+COMPILE_ASSERT(offsetof(TexSubImage2D, width) == 20,
+               OffsetOf_TexSubImage2D_width_not_20);
+COMPILE_ASSERT(offsetof(TexSubImage2D, height) == 24,
+               OffsetOf_TexSubImage2D_height_not_24);
+COMPILE_ASSERT(offsetof(TexSubImage2D, format) == 28,
+               OffsetOf_TexSubImage2D_format_not_28);
+COMPILE_ASSERT(offsetof(TexSubImage2D, type) == 32,
+               OffsetOf_TexSubImage2D_type_not_32);
+COMPILE_ASSERT(offsetof(TexSubImage2D, pixels_shm_id) == 36,
+               OffsetOf_TexSubImage2D_pixels_shm_id_not_36);
+COMPILE_ASSERT(offsetof(TexSubImage2D, pixels_shm_offset) == 40,
+               OffsetOf_TexSubImage2D_pixels_shm_offset_not_40);
+
+struct TexSubImage2DImmediate {
+  typedef TexSubImage2DImmediate ValueType;
+  static const CommandId kCmdId = kTexSubImage2DImmediate;
+  static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN;
+
+  static uint32 ComputeSize(uint32 size_in_bytes) {
+    return static_cast<uint32>(
+        sizeof(ValueType) +  // NOLINT
+        RoundSizeToMultipleOfEntries(size_in_bytes));
+  }
+
+  void SetHeader(uint32 size_in_bytes) {
+    header.SetCmdByTotalSize<ValueType>(size_in_bytes);
+  }
+
+  void Init(
+      GLenum _target, GLint _level, GLint _xoffset, GLint _yoffset,
+      GLsizei _width, GLsizei _height, GLenum _format, GLenum _type) {
+    uint32 total_size = 0;  // TODO(gman): get correct size
+    SetHeader(total_size);
+    target = _target;
+    level = _level;
+    xoffset = _xoffset;
+    yoffset = _yoffset;
+    width = _width;
+    height = _height;
+    format = _format;
+    type = _type;
+  }
+
+  void* Set(
+      void* cmd, GLenum _target, GLint _level, GLint _xoffset, GLint _yoffset,
+      GLsizei _width, GLsizei _height, GLenum _format, GLenum _type) {
+    uint32 total_size = 0;  // TODO(gman): get correct size
+    static_cast<ValueType*>(
+        cmd)->Init(
+            _target, _level, _xoffset, _yoffset, _width, _height, _format,
+            _type);
+    return NextImmediateCmdAddressTotalSize<ValueType>(cmd, total_size);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 target;
+  uint32 level;
+  uint32 xoffset;
+  uint32 yoffset;
+  uint32 width;
+  uint32 height;
+  uint32 format;
+  uint32 type;
+};
+
+COMPILE_ASSERT(sizeof(TexSubImage2DImmediate) == 36,
+               Sizeof_TexSubImage2DImmediate_is_not_36);
+COMPILE_ASSERT(offsetof(TexSubImage2DImmediate, header) == 0,
+               OffsetOf_TexSubImage2DImmediate_header_not_0);
+COMPILE_ASSERT(offsetof(TexSubImage2DImmediate, target) == 4,
+               OffsetOf_TexSubImage2DImmediate_target_not_4);
+COMPILE_ASSERT(offsetof(TexSubImage2DImmediate, level) == 8,
+               OffsetOf_TexSubImage2DImmediate_level_not_8);
+COMPILE_ASSERT(offsetof(TexSubImage2DImmediate, xoffset) == 12,
+               OffsetOf_TexSubImage2DImmediate_xoffset_not_12);
+COMPILE_ASSERT(offsetof(TexSubImage2DImmediate, yoffset) == 16,
+               OffsetOf_TexSubImage2DImmediate_yoffset_not_16);
+COMPILE_ASSERT(offsetof(TexSubImage2DImmediate, width) == 20,
+               OffsetOf_TexSubImage2DImmediate_width_not_20);
+COMPILE_ASSERT(offsetof(TexSubImage2DImmediate, height) == 24,
+               OffsetOf_TexSubImage2DImmediate_height_not_24);
+COMPILE_ASSERT(offsetof(TexSubImage2DImmediate, format) == 28,
+               OffsetOf_TexSubImage2DImmediate_format_not_28);
+COMPILE_ASSERT(offsetof(TexSubImage2DImmediate, type) == 32,
+               OffsetOf_TexSubImage2DImmediate_type_not_32);
+
+struct Uniform1f {
+  typedef Uniform1f ValueType;
+  static const CommandId kCmdId = kUniform1f;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLint _location, GLfloat _x) {
+    SetHeader();
+    location = _location;
+    x = _x;
+  }
+
+  void* Set(void* cmd, GLint _location, GLfloat _x) {
+    static_cast<ValueType*>(cmd)->Init(_location, _x);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 location;
+  float x;
+};
+
+COMPILE_ASSERT(sizeof(Uniform1f) == 12,
+               Sizeof_Uniform1f_is_not_12);
+COMPILE_ASSERT(offsetof(Uniform1f, header) == 0,
+               OffsetOf_Uniform1f_header_not_0);
+COMPILE_ASSERT(offsetof(Uniform1f, location) == 4,
+               OffsetOf_Uniform1f_location_not_4);
+COMPILE_ASSERT(offsetof(Uniform1f, x) == 8,
+               OffsetOf_Uniform1f_x_not_8);
+
+struct Uniform1fv {
+  typedef Uniform1fv ValueType;
+  static const CommandId kCmdId = kUniform1fv;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLint _location, GLsizei _count, uint32 _v_shm_id,
+      uint32 _v_shm_offset) {
+    SetHeader();
+    location = _location;
+    count = _count;
+    v_shm_id = _v_shm_id;
+    v_shm_offset = _v_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLint _location, GLsizei _count, uint32 _v_shm_id,
+      uint32 _v_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(_location, _count, _v_shm_id, _v_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 location;
+  uint32 count;
+  uint32 v_shm_id;
+  uint32 v_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(Uniform1fv) == 20,
+               Sizeof_Uniform1fv_is_not_20);
+COMPILE_ASSERT(offsetof(Uniform1fv, header) == 0,
+               OffsetOf_Uniform1fv_header_not_0);
+COMPILE_ASSERT(offsetof(Uniform1fv, location) == 4,
+               OffsetOf_Uniform1fv_location_not_4);
+COMPILE_ASSERT(offsetof(Uniform1fv, count) == 8,
+               OffsetOf_Uniform1fv_count_not_8);
+COMPILE_ASSERT(offsetof(Uniform1fv, v_shm_id) == 12,
+               OffsetOf_Uniform1fv_v_shm_id_not_12);
+COMPILE_ASSERT(offsetof(Uniform1fv, v_shm_offset) == 16,
+               OffsetOf_Uniform1fv_v_shm_offset_not_16);
+
+struct Uniform1fvImmediate {
+  typedef Uniform1fvImmediate ValueType;
+  static const CommandId kCmdId = kUniform1fvImmediate;
+  static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN;
+
+  static uint32 ComputeDataSize(GLsizei count) {
+    return static_cast<uint32>(
+        sizeof(GLfloat) * 1 * count);  // NOLINT
+  }
+
+  static uint32 ComputeSize(GLsizei count) {
+    return static_cast<uint32>(
+        sizeof(ValueType) + ComputeDataSize(count));  // NOLINT
+  }
+
+  void SetHeader(GLsizei count) {
+    header.SetCmdByTotalSize<ValueType>(ComputeSize(count));
+  }
+
+  void Init(GLint _location, GLsizei _count, const GLfloat* _v) {
+    SetHeader(_count);
+    location = _location;
+    count = _count;
+    memcpy(ImmediateDataAddress(this),
+           _v, ComputeDataSize(_count));
+  }
+
+  void* Set(void* cmd, GLint _location, GLsizei _count, const GLfloat* _v) {
+    static_cast<ValueType*>(cmd)->Init(_location, _count, _v);
+    const uint32 size = ComputeSize(_count);
+    return NextImmediateCmdAddressTotalSize<ValueType>(cmd, size);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 location;
+  uint32 count;
+};
+
+COMPILE_ASSERT(sizeof(Uniform1fvImmediate) == 12,
+               Sizeof_Uniform1fvImmediate_is_not_12);
+COMPILE_ASSERT(offsetof(Uniform1fvImmediate, header) == 0,
+               OffsetOf_Uniform1fvImmediate_header_not_0);
+COMPILE_ASSERT(offsetof(Uniform1fvImmediate, location) == 4,
+               OffsetOf_Uniform1fvImmediate_location_not_4);
+COMPILE_ASSERT(offsetof(Uniform1fvImmediate, count) == 8,
+               OffsetOf_Uniform1fvImmediate_count_not_8);
+
+struct Uniform1i {
+  typedef Uniform1i ValueType;
+  static const CommandId kCmdId = kUniform1i;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLint _location, GLint _x) {
+    SetHeader();
+    location = _location;
+    x = _x;
+  }
+
+  void* Set(void* cmd, GLint _location, GLint _x) {
+    static_cast<ValueType*>(cmd)->Init(_location, _x);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 location;
+  uint32 x;
+};
+
+COMPILE_ASSERT(sizeof(Uniform1i) == 12,
+               Sizeof_Uniform1i_is_not_12);
+COMPILE_ASSERT(offsetof(Uniform1i, header) == 0,
+               OffsetOf_Uniform1i_header_not_0);
+COMPILE_ASSERT(offsetof(Uniform1i, location) == 4,
+               OffsetOf_Uniform1i_location_not_4);
+COMPILE_ASSERT(offsetof(Uniform1i, x) == 8,
+               OffsetOf_Uniform1i_x_not_8);
+
+struct Uniform1iv {
+  typedef Uniform1iv ValueType;
+  static const CommandId kCmdId = kUniform1iv;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLint _location, GLsizei _count, uint32 _v_shm_id,
+      uint32 _v_shm_offset) {
+    SetHeader();
+    location = _location;
+    count = _count;
+    v_shm_id = _v_shm_id;
+    v_shm_offset = _v_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLint _location, GLsizei _count, uint32 _v_shm_id,
+      uint32 _v_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(_location, _count, _v_shm_id, _v_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 location;
+  uint32 count;
+  uint32 v_shm_id;
+  uint32 v_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(Uniform1iv) == 20,
+               Sizeof_Uniform1iv_is_not_20);
+COMPILE_ASSERT(offsetof(Uniform1iv, header) == 0,
+               OffsetOf_Uniform1iv_header_not_0);
+COMPILE_ASSERT(offsetof(Uniform1iv, location) == 4,
+               OffsetOf_Uniform1iv_location_not_4);
+COMPILE_ASSERT(offsetof(Uniform1iv, count) == 8,
+               OffsetOf_Uniform1iv_count_not_8);
+COMPILE_ASSERT(offsetof(Uniform1iv, v_shm_id) == 12,
+               OffsetOf_Uniform1iv_v_shm_id_not_12);
+COMPILE_ASSERT(offsetof(Uniform1iv, v_shm_offset) == 16,
+               OffsetOf_Uniform1iv_v_shm_offset_not_16);
+
+struct Uniform1ivImmediate {
+  typedef Uniform1ivImmediate ValueType;
+  static const CommandId kCmdId = kUniform1ivImmediate;
+  static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN;
+
+  static uint32 ComputeDataSize(GLsizei count) {
+    return static_cast<uint32>(
+        sizeof(GLint) * 1 * count);  // NOLINT
+  }
+
+  static uint32 ComputeSize(GLsizei count) {
+    return static_cast<uint32>(
+        sizeof(ValueType) + ComputeDataSize(count));  // NOLINT
+  }
+
+  void SetHeader(GLsizei count) {
+    header.SetCmdByTotalSize<ValueType>(ComputeSize(count));
+  }
+
+  void Init(GLint _location, GLsizei _count, const GLint* _v) {
+    SetHeader(_count);
+    location = _location;
+    count = _count;
+    memcpy(ImmediateDataAddress(this),
+           _v, ComputeDataSize(_count));
+  }
+
+  void* Set(void* cmd, GLint _location, GLsizei _count, const GLint* _v) {
+    static_cast<ValueType*>(cmd)->Init(_location, _count, _v);
+    const uint32 size = ComputeSize(_count);
+    return NextImmediateCmdAddressTotalSize<ValueType>(cmd, size);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 location;
+  uint32 count;
+};
+
+COMPILE_ASSERT(sizeof(Uniform1ivImmediate) == 12,
+               Sizeof_Uniform1ivImmediate_is_not_12);
+COMPILE_ASSERT(offsetof(Uniform1ivImmediate, header) == 0,
+               OffsetOf_Uniform1ivImmediate_header_not_0);
+COMPILE_ASSERT(offsetof(Uniform1ivImmediate, location) == 4,
+               OffsetOf_Uniform1ivImmediate_location_not_4);
+COMPILE_ASSERT(offsetof(Uniform1ivImmediate, count) == 8,
+               OffsetOf_Uniform1ivImmediate_count_not_8);
+
+struct Uniform2f {
+  typedef Uniform2f ValueType;
+  static const CommandId kCmdId = kUniform2f;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLint _location, GLfloat _x, GLfloat _y) {
+    SetHeader();
+    location = _location;
+    x = _x;
+    y = _y;
+  }
+
+  void* Set(void* cmd, GLint _location, GLfloat _x, GLfloat _y) {
+    static_cast<ValueType*>(cmd)->Init(_location, _x, _y);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 location;
+  float x;
+  float y;
+};
+
+COMPILE_ASSERT(sizeof(Uniform2f) == 16,
+               Sizeof_Uniform2f_is_not_16);
+COMPILE_ASSERT(offsetof(Uniform2f, header) == 0,
+               OffsetOf_Uniform2f_header_not_0);
+COMPILE_ASSERT(offsetof(Uniform2f, location) == 4,
+               OffsetOf_Uniform2f_location_not_4);
+COMPILE_ASSERT(offsetof(Uniform2f, x) == 8,
+               OffsetOf_Uniform2f_x_not_8);
+COMPILE_ASSERT(offsetof(Uniform2f, y) == 12,
+               OffsetOf_Uniform2f_y_not_12);
+
+struct Uniform2fv {
+  typedef Uniform2fv ValueType;
+  static const CommandId kCmdId = kUniform2fv;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLint _location, GLsizei _count, uint32 _v_shm_id,
+      uint32 _v_shm_offset) {
+    SetHeader();
+    location = _location;
+    count = _count;
+    v_shm_id = _v_shm_id;
+    v_shm_offset = _v_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLint _location, GLsizei _count, uint32 _v_shm_id,
+      uint32 _v_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(_location, _count, _v_shm_id, _v_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 location;
+  uint32 count;
+  uint32 v_shm_id;
+  uint32 v_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(Uniform2fv) == 20,
+               Sizeof_Uniform2fv_is_not_20);
+COMPILE_ASSERT(offsetof(Uniform2fv, header) == 0,
+               OffsetOf_Uniform2fv_header_not_0);
+COMPILE_ASSERT(offsetof(Uniform2fv, location) == 4,
+               OffsetOf_Uniform2fv_location_not_4);
+COMPILE_ASSERT(offsetof(Uniform2fv, count) == 8,
+               OffsetOf_Uniform2fv_count_not_8);
+COMPILE_ASSERT(offsetof(Uniform2fv, v_shm_id) == 12,
+               OffsetOf_Uniform2fv_v_shm_id_not_12);
+COMPILE_ASSERT(offsetof(Uniform2fv, v_shm_offset) == 16,
+               OffsetOf_Uniform2fv_v_shm_offset_not_16);
+
+struct Uniform2fvImmediate {
+  typedef Uniform2fvImmediate ValueType;
+  static const CommandId kCmdId = kUniform2fvImmediate;
+  static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN;
+
+  static uint32 ComputeDataSize(GLsizei count) {
+    return static_cast<uint32>(
+        sizeof(GLfloat) * 2 * count);  // NOLINT
+  }
+
+  static uint32 ComputeSize(GLsizei count) {
+    return static_cast<uint32>(
+        sizeof(ValueType) + ComputeDataSize(count));  // NOLINT
+  }
+
+  void SetHeader(GLsizei count) {
+    header.SetCmdByTotalSize<ValueType>(ComputeSize(count));
+  }
+
+  void Init(GLint _location, GLsizei _count, const GLfloat* _v) {
+    SetHeader(_count);
+    location = _location;
+    count = _count;
+    memcpy(ImmediateDataAddress(this),
+           _v, ComputeDataSize(_count));
+  }
+
+  void* Set(void* cmd, GLint _location, GLsizei _count, const GLfloat* _v) {
+    static_cast<ValueType*>(cmd)->Init(_location, _count, _v);
+    const uint32 size = ComputeSize(_count);
+    return NextImmediateCmdAddressTotalSize<ValueType>(cmd, size);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 location;
+  uint32 count;
+};
+
+COMPILE_ASSERT(sizeof(Uniform2fvImmediate) == 12,
+               Sizeof_Uniform2fvImmediate_is_not_12);
+COMPILE_ASSERT(offsetof(Uniform2fvImmediate, header) == 0,
+               OffsetOf_Uniform2fvImmediate_header_not_0);
+COMPILE_ASSERT(offsetof(Uniform2fvImmediate, location) == 4,
+               OffsetOf_Uniform2fvImmediate_location_not_4);
+COMPILE_ASSERT(offsetof(Uniform2fvImmediate, count) == 8,
+               OffsetOf_Uniform2fvImmediate_count_not_8);
+
+struct Uniform2i {
+  typedef Uniform2i ValueType;
+  static const CommandId kCmdId = kUniform2i;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLint _location, GLint _x, GLint _y) {
+    SetHeader();
+    location = _location;
+    x = _x;
+    y = _y;
+  }
+
+  void* Set(void* cmd, GLint _location, GLint _x, GLint _y) {
+    static_cast<ValueType*>(cmd)->Init(_location, _x, _y);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 location;
+  uint32 x;
+  uint32 y;
+};
+
+COMPILE_ASSERT(sizeof(Uniform2i) == 16,
+               Sizeof_Uniform2i_is_not_16);
+COMPILE_ASSERT(offsetof(Uniform2i, header) == 0,
+               OffsetOf_Uniform2i_header_not_0);
+COMPILE_ASSERT(offsetof(Uniform2i, location) == 4,
+               OffsetOf_Uniform2i_location_not_4);
+COMPILE_ASSERT(offsetof(Uniform2i, x) == 8,
+               OffsetOf_Uniform2i_x_not_8);
+COMPILE_ASSERT(offsetof(Uniform2i, y) == 12,
+               OffsetOf_Uniform2i_y_not_12);
+
+struct Uniform2iv {
+  typedef Uniform2iv ValueType;
+  static const CommandId kCmdId = kUniform2iv;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLint _location, GLsizei _count, uint32 _v_shm_id,
+      uint32 _v_shm_offset) {
+    SetHeader();
+    location = _location;
+    count = _count;
+    v_shm_id = _v_shm_id;
+    v_shm_offset = _v_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLint _location, GLsizei _count, uint32 _v_shm_id,
+      uint32 _v_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(_location, _count, _v_shm_id, _v_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 location;
+  uint32 count;
+  uint32 v_shm_id;
+  uint32 v_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(Uniform2iv) == 20,
+               Sizeof_Uniform2iv_is_not_20);
+COMPILE_ASSERT(offsetof(Uniform2iv, header) == 0,
+               OffsetOf_Uniform2iv_header_not_0);
+COMPILE_ASSERT(offsetof(Uniform2iv, location) == 4,
+               OffsetOf_Uniform2iv_location_not_4);
+COMPILE_ASSERT(offsetof(Uniform2iv, count) == 8,
+               OffsetOf_Uniform2iv_count_not_8);
+COMPILE_ASSERT(offsetof(Uniform2iv, v_shm_id) == 12,
+               OffsetOf_Uniform2iv_v_shm_id_not_12);
+COMPILE_ASSERT(offsetof(Uniform2iv, v_shm_offset) == 16,
+               OffsetOf_Uniform2iv_v_shm_offset_not_16);
+
+struct Uniform2ivImmediate {
+  typedef Uniform2ivImmediate ValueType;
+  static const CommandId kCmdId = kUniform2ivImmediate;
+  static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN;
+
+  static uint32 ComputeDataSize(GLsizei count) {
+    return static_cast<uint32>(
+        sizeof(GLint) * 2 * count);  // NOLINT
+  }
+
+  static uint32 ComputeSize(GLsizei count) {
+    return static_cast<uint32>(
+        sizeof(ValueType) + ComputeDataSize(count));  // NOLINT
+  }
+
+  void SetHeader(GLsizei count) {
+    header.SetCmdByTotalSize<ValueType>(ComputeSize(count));
+  }
+
+  void Init(GLint _location, GLsizei _count, const GLint* _v) {
+    SetHeader(_count);
+    location = _location;
+    count = _count;
+    memcpy(ImmediateDataAddress(this),
+           _v, ComputeDataSize(_count));
+  }
+
+  void* Set(void* cmd, GLint _location, GLsizei _count, const GLint* _v) {
+    static_cast<ValueType*>(cmd)->Init(_location, _count, _v);
+    const uint32 size = ComputeSize(_count);
+    return NextImmediateCmdAddressTotalSize<ValueType>(cmd, size);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 location;
+  uint32 count;
+};
+
+COMPILE_ASSERT(sizeof(Uniform2ivImmediate) == 12,
+               Sizeof_Uniform2ivImmediate_is_not_12);
+COMPILE_ASSERT(offsetof(Uniform2ivImmediate, header) == 0,
+               OffsetOf_Uniform2ivImmediate_header_not_0);
+COMPILE_ASSERT(offsetof(Uniform2ivImmediate, location) == 4,
+               OffsetOf_Uniform2ivImmediate_location_not_4);
+COMPILE_ASSERT(offsetof(Uniform2ivImmediate, count) == 8,
+               OffsetOf_Uniform2ivImmediate_count_not_8);
+
+struct Uniform3f {
+  typedef Uniform3f ValueType;
+  static const CommandId kCmdId = kUniform3f;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLint _location, GLfloat _x, GLfloat _y, GLfloat _z) {
+    SetHeader();
+    location = _location;
+    x = _x;
+    y = _y;
+    z = _z;
+  }
+
+  void* Set(void* cmd, GLint _location, GLfloat _x, GLfloat _y, GLfloat _z) {
+    static_cast<ValueType*>(cmd)->Init(_location, _x, _y, _z);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 location;
+  float x;
+  float y;
+  float z;
+};
+
+COMPILE_ASSERT(sizeof(Uniform3f) == 20,
+               Sizeof_Uniform3f_is_not_20);
+COMPILE_ASSERT(offsetof(Uniform3f, header) == 0,
+               OffsetOf_Uniform3f_header_not_0);
+COMPILE_ASSERT(offsetof(Uniform3f, location) == 4,
+               OffsetOf_Uniform3f_location_not_4);
+COMPILE_ASSERT(offsetof(Uniform3f, x) == 8,
+               OffsetOf_Uniform3f_x_not_8);
+COMPILE_ASSERT(offsetof(Uniform3f, y) == 12,
+               OffsetOf_Uniform3f_y_not_12);
+COMPILE_ASSERT(offsetof(Uniform3f, z) == 16,
+               OffsetOf_Uniform3f_z_not_16);
+
+struct Uniform3fv {
+  typedef Uniform3fv ValueType;
+  static const CommandId kCmdId = kUniform3fv;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLint _location, GLsizei _count, uint32 _v_shm_id,
+      uint32 _v_shm_offset) {
+    SetHeader();
+    location = _location;
+    count = _count;
+    v_shm_id = _v_shm_id;
+    v_shm_offset = _v_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLint _location, GLsizei _count, uint32 _v_shm_id,
+      uint32 _v_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(_location, _count, _v_shm_id, _v_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 location;
+  uint32 count;
+  uint32 v_shm_id;
+  uint32 v_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(Uniform3fv) == 20,
+               Sizeof_Uniform3fv_is_not_20);
+COMPILE_ASSERT(offsetof(Uniform3fv, header) == 0,
+               OffsetOf_Uniform3fv_header_not_0);
+COMPILE_ASSERT(offsetof(Uniform3fv, location) == 4,
+               OffsetOf_Uniform3fv_location_not_4);
+COMPILE_ASSERT(offsetof(Uniform3fv, count) == 8,
+               OffsetOf_Uniform3fv_count_not_8);
+COMPILE_ASSERT(offsetof(Uniform3fv, v_shm_id) == 12,
+               OffsetOf_Uniform3fv_v_shm_id_not_12);
+COMPILE_ASSERT(offsetof(Uniform3fv, v_shm_offset) == 16,
+               OffsetOf_Uniform3fv_v_shm_offset_not_16);
+
+struct Uniform3fvImmediate {
+  typedef Uniform3fvImmediate ValueType;
+  static const CommandId kCmdId = kUniform3fvImmediate;
+  static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN;
+
+  static uint32 ComputeDataSize(GLsizei count) {
+    return static_cast<uint32>(
+        sizeof(GLfloat) * 3 * count);  // NOLINT
+  }
+
+  static uint32 ComputeSize(GLsizei count) {
+    return static_cast<uint32>(
+        sizeof(ValueType) + ComputeDataSize(count));  // NOLINT
+  }
+
+  void SetHeader(GLsizei count) {
+    header.SetCmdByTotalSize<ValueType>(ComputeSize(count));
+  }
+
+  void Init(GLint _location, GLsizei _count, const GLfloat* _v) {
+    SetHeader(_count);
+    location = _location;
+    count = _count;
+    memcpy(ImmediateDataAddress(this),
+           _v, ComputeDataSize(_count));
+  }
+
+  void* Set(void* cmd, GLint _location, GLsizei _count, const GLfloat* _v) {
+    static_cast<ValueType*>(cmd)->Init(_location, _count, _v);
+    const uint32 size = ComputeSize(_count);
+    return NextImmediateCmdAddressTotalSize<ValueType>(cmd, size);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 location;
+  uint32 count;
+};
+
+COMPILE_ASSERT(sizeof(Uniform3fvImmediate) == 12,
+               Sizeof_Uniform3fvImmediate_is_not_12);
+COMPILE_ASSERT(offsetof(Uniform3fvImmediate, header) == 0,
+               OffsetOf_Uniform3fvImmediate_header_not_0);
+COMPILE_ASSERT(offsetof(Uniform3fvImmediate, location) == 4,
+               OffsetOf_Uniform3fvImmediate_location_not_4);
+COMPILE_ASSERT(offsetof(Uniform3fvImmediate, count) == 8,
+               OffsetOf_Uniform3fvImmediate_count_not_8);
+
+struct Uniform3i {
+  typedef Uniform3i ValueType;
+  static const CommandId kCmdId = kUniform3i;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLint _location, GLint _x, GLint _y, GLint _z) {
+    SetHeader();
+    location = _location;
+    x = _x;
+    y = _y;
+    z = _z;
+  }
+
+  void* Set(void* cmd, GLint _location, GLint _x, GLint _y, GLint _z) {
+    static_cast<ValueType*>(cmd)->Init(_location, _x, _y, _z);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 location;
+  uint32 x;
+  uint32 y;
+  uint32 z;
+};
+
+COMPILE_ASSERT(sizeof(Uniform3i) == 20,
+               Sizeof_Uniform3i_is_not_20);
+COMPILE_ASSERT(offsetof(Uniform3i, header) == 0,
+               OffsetOf_Uniform3i_header_not_0);
+COMPILE_ASSERT(offsetof(Uniform3i, location) == 4,
+               OffsetOf_Uniform3i_location_not_4);
+COMPILE_ASSERT(offsetof(Uniform3i, x) == 8,
+               OffsetOf_Uniform3i_x_not_8);
+COMPILE_ASSERT(offsetof(Uniform3i, y) == 12,
+               OffsetOf_Uniform3i_y_not_12);
+COMPILE_ASSERT(offsetof(Uniform3i, z) == 16,
+               OffsetOf_Uniform3i_z_not_16);
+
+struct Uniform3iv {
+  typedef Uniform3iv ValueType;
+  static const CommandId kCmdId = kUniform3iv;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLint _location, GLsizei _count, uint32 _v_shm_id,
+      uint32 _v_shm_offset) {
+    SetHeader();
+    location = _location;
+    count = _count;
+    v_shm_id = _v_shm_id;
+    v_shm_offset = _v_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLint _location, GLsizei _count, uint32 _v_shm_id,
+      uint32 _v_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(_location, _count, _v_shm_id, _v_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 location;
+  uint32 count;
+  uint32 v_shm_id;
+  uint32 v_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(Uniform3iv) == 20,
+               Sizeof_Uniform3iv_is_not_20);
+COMPILE_ASSERT(offsetof(Uniform3iv, header) == 0,
+               OffsetOf_Uniform3iv_header_not_0);
+COMPILE_ASSERT(offsetof(Uniform3iv, location) == 4,
+               OffsetOf_Uniform3iv_location_not_4);
+COMPILE_ASSERT(offsetof(Uniform3iv, count) == 8,
+               OffsetOf_Uniform3iv_count_not_8);
+COMPILE_ASSERT(offsetof(Uniform3iv, v_shm_id) == 12,
+               OffsetOf_Uniform3iv_v_shm_id_not_12);
+COMPILE_ASSERT(offsetof(Uniform3iv, v_shm_offset) == 16,
+               OffsetOf_Uniform3iv_v_shm_offset_not_16);
+
+struct Uniform3ivImmediate {
+  typedef Uniform3ivImmediate ValueType;
+  static const CommandId kCmdId = kUniform3ivImmediate;
+  static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN;
+
+  static uint32 ComputeDataSize(GLsizei count) {
+    return static_cast<uint32>(
+        sizeof(GLint) * 3 * count);  // NOLINT
+  }
+
+  static uint32 ComputeSize(GLsizei count) {
+    return static_cast<uint32>(
+        sizeof(ValueType) + ComputeDataSize(count));  // NOLINT
+  }
+
+  void SetHeader(GLsizei count) {
+    header.SetCmdByTotalSize<ValueType>(ComputeSize(count));
+  }
+
+  void Init(GLint _location, GLsizei _count, const GLint* _v) {
+    SetHeader(_count);
+    location = _location;
+    count = _count;
+    memcpy(ImmediateDataAddress(this),
+           _v, ComputeDataSize(_count));
+  }
+
+  void* Set(void* cmd, GLint _location, GLsizei _count, const GLint* _v) {
+    static_cast<ValueType*>(cmd)->Init(_location, _count, _v);
+    const uint32 size = ComputeSize(_count);
+    return NextImmediateCmdAddressTotalSize<ValueType>(cmd, size);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 location;
+  uint32 count;
+};
+
+COMPILE_ASSERT(sizeof(Uniform3ivImmediate) == 12,
+               Sizeof_Uniform3ivImmediate_is_not_12);
+COMPILE_ASSERT(offsetof(Uniform3ivImmediate, header) == 0,
+               OffsetOf_Uniform3ivImmediate_header_not_0);
+COMPILE_ASSERT(offsetof(Uniform3ivImmediate, location) == 4,
+               OffsetOf_Uniform3ivImmediate_location_not_4);
+COMPILE_ASSERT(offsetof(Uniform3ivImmediate, count) == 8,
+               OffsetOf_Uniform3ivImmediate_count_not_8);
+
+struct Uniform4f {
+  typedef Uniform4f ValueType;
+  static const CommandId kCmdId = kUniform4f;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLint _location, GLfloat _x, GLfloat _y, GLfloat _z, GLfloat _w) {
+    SetHeader();
+    location = _location;
+    x = _x;
+    y = _y;
+    z = _z;
+    w = _w;
+  }
+
+  void* Set(
+      void* cmd, GLint _location, GLfloat _x, GLfloat _y, GLfloat _z,
+      GLfloat _w) {
+    static_cast<ValueType*>(cmd)->Init(_location, _x, _y, _z, _w);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 location;
+  float x;
+  float y;
+  float z;
+  float w;
+};
+
+COMPILE_ASSERT(sizeof(Uniform4f) == 24,
+               Sizeof_Uniform4f_is_not_24);
+COMPILE_ASSERT(offsetof(Uniform4f, header) == 0,
+               OffsetOf_Uniform4f_header_not_0);
+COMPILE_ASSERT(offsetof(Uniform4f, location) == 4,
+               OffsetOf_Uniform4f_location_not_4);
+COMPILE_ASSERT(offsetof(Uniform4f, x) == 8,
+               OffsetOf_Uniform4f_x_not_8);
+COMPILE_ASSERT(offsetof(Uniform4f, y) == 12,
+               OffsetOf_Uniform4f_y_not_12);
+COMPILE_ASSERT(offsetof(Uniform4f, z) == 16,
+               OffsetOf_Uniform4f_z_not_16);
+COMPILE_ASSERT(offsetof(Uniform4f, w) == 20,
+               OffsetOf_Uniform4f_w_not_20);
+
+struct Uniform4fv {
+  typedef Uniform4fv ValueType;
+  static const CommandId kCmdId = kUniform4fv;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLint _location, GLsizei _count, uint32 _v_shm_id,
+      uint32 _v_shm_offset) {
+    SetHeader();
+    location = _location;
+    count = _count;
+    v_shm_id = _v_shm_id;
+    v_shm_offset = _v_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLint _location, GLsizei _count, uint32 _v_shm_id,
+      uint32 _v_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(_location, _count, _v_shm_id, _v_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 location;
+  uint32 count;
+  uint32 v_shm_id;
+  uint32 v_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(Uniform4fv) == 20,
+               Sizeof_Uniform4fv_is_not_20);
+COMPILE_ASSERT(offsetof(Uniform4fv, header) == 0,
+               OffsetOf_Uniform4fv_header_not_0);
+COMPILE_ASSERT(offsetof(Uniform4fv, location) == 4,
+               OffsetOf_Uniform4fv_location_not_4);
+COMPILE_ASSERT(offsetof(Uniform4fv, count) == 8,
+               OffsetOf_Uniform4fv_count_not_8);
+COMPILE_ASSERT(offsetof(Uniform4fv, v_shm_id) == 12,
+               OffsetOf_Uniform4fv_v_shm_id_not_12);
+COMPILE_ASSERT(offsetof(Uniform4fv, v_shm_offset) == 16,
+               OffsetOf_Uniform4fv_v_shm_offset_not_16);
+
+struct Uniform4fvImmediate {
+  typedef Uniform4fvImmediate ValueType;
+  static const CommandId kCmdId = kUniform4fvImmediate;
+  static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN;
+
+  static uint32 ComputeDataSize(GLsizei count) {
+    return static_cast<uint32>(
+        sizeof(GLfloat) * 4 * count);  // NOLINT
+  }
+
+  static uint32 ComputeSize(GLsizei count) {
+    return static_cast<uint32>(
+        sizeof(ValueType) + ComputeDataSize(count));  // NOLINT
+  }
+
+  void SetHeader(GLsizei count) {
+    header.SetCmdByTotalSize<ValueType>(ComputeSize(count));
+  }
+
+  void Init(GLint _location, GLsizei _count, const GLfloat* _v) {
+    SetHeader(_count);
+    location = _location;
+    count = _count;
+    memcpy(ImmediateDataAddress(this),
+           _v, ComputeDataSize(_count));
+  }
+
+  void* Set(void* cmd, GLint _location, GLsizei _count, const GLfloat* _v) {
+    static_cast<ValueType*>(cmd)->Init(_location, _count, _v);
+    const uint32 size = ComputeSize(_count);
+    return NextImmediateCmdAddressTotalSize<ValueType>(cmd, size);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 location;
+  uint32 count;
+};
+
+COMPILE_ASSERT(sizeof(Uniform4fvImmediate) == 12,
+               Sizeof_Uniform4fvImmediate_is_not_12);
+COMPILE_ASSERT(offsetof(Uniform4fvImmediate, header) == 0,
+               OffsetOf_Uniform4fvImmediate_header_not_0);
+COMPILE_ASSERT(offsetof(Uniform4fvImmediate, location) == 4,
+               OffsetOf_Uniform4fvImmediate_location_not_4);
+COMPILE_ASSERT(offsetof(Uniform4fvImmediate, count) == 8,
+               OffsetOf_Uniform4fvImmediate_count_not_8);
+
+struct Uniform4i {
+  typedef Uniform4i ValueType;
+  static const CommandId kCmdId = kUniform4i;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLint _location, GLint _x, GLint _y, GLint _z, GLint _w) {
+    SetHeader();
+    location = _location;
+    x = _x;
+    y = _y;
+    z = _z;
+    w = _w;
+  }
+
+  void* Set(
+      void* cmd, GLint _location, GLint _x, GLint _y, GLint _z, GLint _w) {
+    static_cast<ValueType*>(cmd)->Init(_location, _x, _y, _z, _w);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 location;
+  uint32 x;
+  uint32 y;
+  uint32 z;
+  uint32 w;
+};
+
+COMPILE_ASSERT(sizeof(Uniform4i) == 24,
+               Sizeof_Uniform4i_is_not_24);
+COMPILE_ASSERT(offsetof(Uniform4i, header) == 0,
+               OffsetOf_Uniform4i_header_not_0);
+COMPILE_ASSERT(offsetof(Uniform4i, location) == 4,
+               OffsetOf_Uniform4i_location_not_4);
+COMPILE_ASSERT(offsetof(Uniform4i, x) == 8,
+               OffsetOf_Uniform4i_x_not_8);
+COMPILE_ASSERT(offsetof(Uniform4i, y) == 12,
+               OffsetOf_Uniform4i_y_not_12);
+COMPILE_ASSERT(offsetof(Uniform4i, z) == 16,
+               OffsetOf_Uniform4i_z_not_16);
+COMPILE_ASSERT(offsetof(Uniform4i, w) == 20,
+               OffsetOf_Uniform4i_w_not_20);
+
+struct Uniform4iv {
+  typedef Uniform4iv ValueType;
+  static const CommandId kCmdId = kUniform4iv;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLint _location, GLsizei _count, uint32 _v_shm_id,
+      uint32 _v_shm_offset) {
+    SetHeader();
+    location = _location;
+    count = _count;
+    v_shm_id = _v_shm_id;
+    v_shm_offset = _v_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLint _location, GLsizei _count, uint32 _v_shm_id,
+      uint32 _v_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(_location, _count, _v_shm_id, _v_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 location;
+  uint32 count;
+  uint32 v_shm_id;
+  uint32 v_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(Uniform4iv) == 20,
+               Sizeof_Uniform4iv_is_not_20);
+COMPILE_ASSERT(offsetof(Uniform4iv, header) == 0,
+               OffsetOf_Uniform4iv_header_not_0);
+COMPILE_ASSERT(offsetof(Uniform4iv, location) == 4,
+               OffsetOf_Uniform4iv_location_not_4);
+COMPILE_ASSERT(offsetof(Uniform4iv, count) == 8,
+               OffsetOf_Uniform4iv_count_not_8);
+COMPILE_ASSERT(offsetof(Uniform4iv, v_shm_id) == 12,
+               OffsetOf_Uniform4iv_v_shm_id_not_12);
+COMPILE_ASSERT(offsetof(Uniform4iv, v_shm_offset) == 16,
+               OffsetOf_Uniform4iv_v_shm_offset_not_16);
+
+struct Uniform4ivImmediate {
+  typedef Uniform4ivImmediate ValueType;
+  static const CommandId kCmdId = kUniform4ivImmediate;
+  static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN;
+
+  static uint32 ComputeDataSize(GLsizei count) {
+    return static_cast<uint32>(
+        sizeof(GLint) * 4 * count);  // NOLINT
+  }
+
+  static uint32 ComputeSize(GLsizei count) {
+    return static_cast<uint32>(
+        sizeof(ValueType) + ComputeDataSize(count));  // NOLINT
+  }
+
+  void SetHeader(GLsizei count) {
+    header.SetCmdByTotalSize<ValueType>(ComputeSize(count));
+  }
+
+  void Init(GLint _location, GLsizei _count, const GLint* _v) {
+    SetHeader(_count);
+    location = _location;
+    count = _count;
+    memcpy(ImmediateDataAddress(this),
+           _v, ComputeDataSize(_count));
+  }
+
+  void* Set(void* cmd, GLint _location, GLsizei _count, const GLint* _v) {
+    static_cast<ValueType*>(cmd)->Init(_location, _count, _v);
+    const uint32 size = ComputeSize(_count);
+    return NextImmediateCmdAddressTotalSize<ValueType>(cmd, size);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 location;
+  uint32 count;
+};
+
+COMPILE_ASSERT(sizeof(Uniform4ivImmediate) == 12,
+               Sizeof_Uniform4ivImmediate_is_not_12);
+COMPILE_ASSERT(offsetof(Uniform4ivImmediate, header) == 0,
+               OffsetOf_Uniform4ivImmediate_header_not_0);
+COMPILE_ASSERT(offsetof(Uniform4ivImmediate, location) == 4,
+               OffsetOf_Uniform4ivImmediate_location_not_4);
+COMPILE_ASSERT(offsetof(Uniform4ivImmediate, count) == 8,
+               OffsetOf_Uniform4ivImmediate_count_not_8);
+
+struct UniformMatrix2fv {
+  typedef UniformMatrix2fv ValueType;
+  static const CommandId kCmdId = kUniformMatrix2fv;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLint _location, GLsizei _count, GLboolean _transpose,
+      uint32 _value_shm_id, uint32 _value_shm_offset) {
+    SetHeader();
+    location = _location;
+    count = _count;
+    transpose = _transpose;
+    value_shm_id = _value_shm_id;
+    value_shm_offset = _value_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLint _location, GLsizei _count, GLboolean _transpose,
+      uint32 _value_shm_id, uint32 _value_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(
+            _location, _count, _transpose, _value_shm_id, _value_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 location;
+  uint32 count;
+  uint32 transpose;
+  uint32 value_shm_id;
+  uint32 value_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(UniformMatrix2fv) == 24,
+               Sizeof_UniformMatrix2fv_is_not_24);
+COMPILE_ASSERT(offsetof(UniformMatrix2fv, header) == 0,
+               OffsetOf_UniformMatrix2fv_header_not_0);
+COMPILE_ASSERT(offsetof(UniformMatrix2fv, location) == 4,
+               OffsetOf_UniformMatrix2fv_location_not_4);
+COMPILE_ASSERT(offsetof(UniformMatrix2fv, count) == 8,
+               OffsetOf_UniformMatrix2fv_count_not_8);
+COMPILE_ASSERT(offsetof(UniformMatrix2fv, transpose) == 12,
+               OffsetOf_UniformMatrix2fv_transpose_not_12);
+COMPILE_ASSERT(offsetof(UniformMatrix2fv, value_shm_id) == 16,
+               OffsetOf_UniformMatrix2fv_value_shm_id_not_16);
+COMPILE_ASSERT(offsetof(UniformMatrix2fv, value_shm_offset) == 20,
+               OffsetOf_UniformMatrix2fv_value_shm_offset_not_20);
+
+struct UniformMatrix2fvImmediate {
+  typedef UniformMatrix2fvImmediate ValueType;
+  static const CommandId kCmdId = kUniformMatrix2fvImmediate;
+  static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN;
+
+  static uint32 ComputeDataSize(GLsizei count) {
+    return static_cast<uint32>(
+        sizeof(GLfloat) * 4 * count);  // NOLINT
+  }
+
+  static uint32 ComputeSize(GLsizei count) {
+    return static_cast<uint32>(
+        sizeof(ValueType) + ComputeDataSize(count));  // NOLINT
+  }
+
+  void SetHeader(GLsizei count) {
+    header.SetCmdByTotalSize<ValueType>(ComputeSize(count));
+  }
+
+  void Init(
+      GLint _location, GLsizei _count, GLboolean _transpose,
+      const GLfloat* _value) {
+    SetHeader(_count);
+    location = _location;
+    count = _count;
+    transpose = _transpose;
+    memcpy(ImmediateDataAddress(this),
+           _value, ComputeDataSize(_count));
+  }
+
+  void* Set(
+      void* cmd, GLint _location, GLsizei _count, GLboolean _transpose,
+      const GLfloat* _value) {
+    static_cast<ValueType*>(cmd)->Init(_location, _count, _transpose, _value);
+    const uint32 size = ComputeSize(_count);
+    return NextImmediateCmdAddressTotalSize<ValueType>(cmd, size);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 location;
+  uint32 count;
+  uint32 transpose;
+};
+
+COMPILE_ASSERT(sizeof(UniformMatrix2fvImmediate) == 16,
+               Sizeof_UniformMatrix2fvImmediate_is_not_16);
+COMPILE_ASSERT(offsetof(UniformMatrix2fvImmediate, header) == 0,
+               OffsetOf_UniformMatrix2fvImmediate_header_not_0);
+COMPILE_ASSERT(offsetof(UniformMatrix2fvImmediate, location) == 4,
+               OffsetOf_UniformMatrix2fvImmediate_location_not_4);
+COMPILE_ASSERT(offsetof(UniformMatrix2fvImmediate, count) == 8,
+               OffsetOf_UniformMatrix2fvImmediate_count_not_8);
+COMPILE_ASSERT(offsetof(UniformMatrix2fvImmediate, transpose) == 12,
+               OffsetOf_UniformMatrix2fvImmediate_transpose_not_12);
+
+struct UniformMatrix3fv {
+  typedef UniformMatrix3fv ValueType;
+  static const CommandId kCmdId = kUniformMatrix3fv;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLint _location, GLsizei _count, GLboolean _transpose,
+      uint32 _value_shm_id, uint32 _value_shm_offset) {
+    SetHeader();
+    location = _location;
+    count = _count;
+    transpose = _transpose;
+    value_shm_id = _value_shm_id;
+    value_shm_offset = _value_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLint _location, GLsizei _count, GLboolean _transpose,
+      uint32 _value_shm_id, uint32 _value_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(
+            _location, _count, _transpose, _value_shm_id, _value_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 location;
+  uint32 count;
+  uint32 transpose;
+  uint32 value_shm_id;
+  uint32 value_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(UniformMatrix3fv) == 24,
+               Sizeof_UniformMatrix3fv_is_not_24);
+COMPILE_ASSERT(offsetof(UniformMatrix3fv, header) == 0,
+               OffsetOf_UniformMatrix3fv_header_not_0);
+COMPILE_ASSERT(offsetof(UniformMatrix3fv, location) == 4,
+               OffsetOf_UniformMatrix3fv_location_not_4);
+COMPILE_ASSERT(offsetof(UniformMatrix3fv, count) == 8,
+               OffsetOf_UniformMatrix3fv_count_not_8);
+COMPILE_ASSERT(offsetof(UniformMatrix3fv, transpose) == 12,
+               OffsetOf_UniformMatrix3fv_transpose_not_12);
+COMPILE_ASSERT(offsetof(UniformMatrix3fv, value_shm_id) == 16,
+               OffsetOf_UniformMatrix3fv_value_shm_id_not_16);
+COMPILE_ASSERT(offsetof(UniformMatrix3fv, value_shm_offset) == 20,
+               OffsetOf_UniformMatrix3fv_value_shm_offset_not_20);
+
+struct UniformMatrix3fvImmediate {
+  typedef UniformMatrix3fvImmediate ValueType;
+  static const CommandId kCmdId = kUniformMatrix3fvImmediate;
+  static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN;
+
+  static uint32 ComputeDataSize(GLsizei count) {
+    return static_cast<uint32>(
+        sizeof(GLfloat) * 9 * count);  // NOLINT
+  }
+
+  static uint32 ComputeSize(GLsizei count) {
+    return static_cast<uint32>(
+        sizeof(ValueType) + ComputeDataSize(count));  // NOLINT
+  }
+
+  void SetHeader(GLsizei count) {
+    header.SetCmdByTotalSize<ValueType>(ComputeSize(count));
+  }
+
+  void Init(
+      GLint _location, GLsizei _count, GLboolean _transpose,
+      const GLfloat* _value) {
+    SetHeader(_count);
+    location = _location;
+    count = _count;
+    transpose = _transpose;
+    memcpy(ImmediateDataAddress(this),
+           _value, ComputeDataSize(_count));
+  }
+
+  void* Set(
+      void* cmd, GLint _location, GLsizei _count, GLboolean _transpose,
+      const GLfloat* _value) {
+    static_cast<ValueType*>(cmd)->Init(_location, _count, _transpose, _value);
+    const uint32 size = ComputeSize(_count);
+    return NextImmediateCmdAddressTotalSize<ValueType>(cmd, size);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 location;
+  uint32 count;
+  uint32 transpose;
+};
+
+COMPILE_ASSERT(sizeof(UniformMatrix3fvImmediate) == 16,
+               Sizeof_UniformMatrix3fvImmediate_is_not_16);
+COMPILE_ASSERT(offsetof(UniformMatrix3fvImmediate, header) == 0,
+               OffsetOf_UniformMatrix3fvImmediate_header_not_0);
+COMPILE_ASSERT(offsetof(UniformMatrix3fvImmediate, location) == 4,
+               OffsetOf_UniformMatrix3fvImmediate_location_not_4);
+COMPILE_ASSERT(offsetof(UniformMatrix3fvImmediate, count) == 8,
+               OffsetOf_UniformMatrix3fvImmediate_count_not_8);
+COMPILE_ASSERT(offsetof(UniformMatrix3fvImmediate, transpose) == 12,
+               OffsetOf_UniformMatrix3fvImmediate_transpose_not_12);
+
+struct UniformMatrix4fv {
+  typedef UniformMatrix4fv ValueType;
+  static const CommandId kCmdId = kUniformMatrix4fv;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLint _location, GLsizei _count, GLboolean _transpose,
+      uint32 _value_shm_id, uint32 _value_shm_offset) {
+    SetHeader();
+    location = _location;
+    count = _count;
+    transpose = _transpose;
+    value_shm_id = _value_shm_id;
+    value_shm_offset = _value_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLint _location, GLsizei _count, GLboolean _transpose,
+      uint32 _value_shm_id, uint32 _value_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(
+            _location, _count, _transpose, _value_shm_id, _value_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 location;
+  uint32 count;
+  uint32 transpose;
+  uint32 value_shm_id;
+  uint32 value_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(UniformMatrix4fv) == 24,
+               Sizeof_UniformMatrix4fv_is_not_24);
+COMPILE_ASSERT(offsetof(UniformMatrix4fv, header) == 0,
+               OffsetOf_UniformMatrix4fv_header_not_0);
+COMPILE_ASSERT(offsetof(UniformMatrix4fv, location) == 4,
+               OffsetOf_UniformMatrix4fv_location_not_4);
+COMPILE_ASSERT(offsetof(UniformMatrix4fv, count) == 8,
+               OffsetOf_UniformMatrix4fv_count_not_8);
+COMPILE_ASSERT(offsetof(UniformMatrix4fv, transpose) == 12,
+               OffsetOf_UniformMatrix4fv_transpose_not_12);
+COMPILE_ASSERT(offsetof(UniformMatrix4fv, value_shm_id) == 16,
+               OffsetOf_UniformMatrix4fv_value_shm_id_not_16);
+COMPILE_ASSERT(offsetof(UniformMatrix4fv, value_shm_offset) == 20,
+               OffsetOf_UniformMatrix4fv_value_shm_offset_not_20);
+
+struct UniformMatrix4fvImmediate {
+  typedef UniformMatrix4fvImmediate ValueType;
+  static const CommandId kCmdId = kUniformMatrix4fvImmediate;
+  static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN;
+
+  static uint32 ComputeDataSize(GLsizei count) {
+    return static_cast<uint32>(
+        sizeof(GLfloat) * 16 * count);  // NOLINT
+  }
+
+  static uint32 ComputeSize(GLsizei count) {
+    return static_cast<uint32>(
+        sizeof(ValueType) + ComputeDataSize(count));  // NOLINT
+  }
+
+  void SetHeader(GLsizei count) {
+    header.SetCmdByTotalSize<ValueType>(ComputeSize(count));
+  }
+
+  void Init(
+      GLint _location, GLsizei _count, GLboolean _transpose,
+      const GLfloat* _value) {
+    SetHeader(_count);
+    location = _location;
+    count = _count;
+    transpose = _transpose;
+    memcpy(ImmediateDataAddress(this),
+           _value, ComputeDataSize(_count));
+  }
+
+  void* Set(
+      void* cmd, GLint _location, GLsizei _count, GLboolean _transpose,
+      const GLfloat* _value) {
+    static_cast<ValueType*>(cmd)->Init(_location, _count, _transpose, _value);
+    const uint32 size = ComputeSize(_count);
+    return NextImmediateCmdAddressTotalSize<ValueType>(cmd, size);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 location;
+  uint32 count;
+  uint32 transpose;
+};
+
+COMPILE_ASSERT(sizeof(UniformMatrix4fvImmediate) == 16,
+               Sizeof_UniformMatrix4fvImmediate_is_not_16);
+COMPILE_ASSERT(offsetof(UniformMatrix4fvImmediate, header) == 0,
+               OffsetOf_UniformMatrix4fvImmediate_header_not_0);
+COMPILE_ASSERT(offsetof(UniformMatrix4fvImmediate, location) == 4,
+               OffsetOf_UniformMatrix4fvImmediate_location_not_4);
+COMPILE_ASSERT(offsetof(UniformMatrix4fvImmediate, count) == 8,
+               OffsetOf_UniformMatrix4fvImmediate_count_not_8);
+COMPILE_ASSERT(offsetof(UniformMatrix4fvImmediate, transpose) == 12,
+               OffsetOf_UniformMatrix4fvImmediate_transpose_not_12);
+
+struct UseProgram {
+  typedef UseProgram ValueType;
+  static const CommandId kCmdId = kUseProgram;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLuint _program) {
+    SetHeader();
+    program = _program;
+  }
+
+  void* Set(void* cmd, GLuint _program) {
+    static_cast<ValueType*>(cmd)->Init(_program);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 program;
+};
+
+COMPILE_ASSERT(sizeof(UseProgram) == 8,
+               Sizeof_UseProgram_is_not_8);
+COMPILE_ASSERT(offsetof(UseProgram, header) == 0,
+               OffsetOf_UseProgram_header_not_0);
+COMPILE_ASSERT(offsetof(UseProgram, program) == 4,
+               OffsetOf_UseProgram_program_not_4);
+
+struct ValidateProgram {
+  typedef ValidateProgram ValueType;
+  static const CommandId kCmdId = kValidateProgram;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLuint _program) {
+    SetHeader();
+    program = _program;
+  }
+
+  void* Set(void* cmd, GLuint _program) {
+    static_cast<ValueType*>(cmd)->Init(_program);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 program;
+};
+
+COMPILE_ASSERT(sizeof(ValidateProgram) == 8,
+               Sizeof_ValidateProgram_is_not_8);
+COMPILE_ASSERT(offsetof(ValidateProgram, header) == 0,
+               OffsetOf_ValidateProgram_header_not_0);
+COMPILE_ASSERT(offsetof(ValidateProgram, program) == 4,
+               OffsetOf_ValidateProgram_program_not_4);
+
+struct VertexAttrib1f {
+  typedef VertexAttrib1f ValueType;
+  static const CommandId kCmdId = kVertexAttrib1f;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLuint _indx, GLfloat _x) {
+    SetHeader();
+    indx = _indx;
+    x = _x;
+  }
+
+  void* Set(void* cmd, GLuint _indx, GLfloat _x) {
+    static_cast<ValueType*>(cmd)->Init(_indx, _x);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 indx;
+  float x;
+};
+
+COMPILE_ASSERT(sizeof(VertexAttrib1f) == 12,
+               Sizeof_VertexAttrib1f_is_not_12);
+COMPILE_ASSERT(offsetof(VertexAttrib1f, header) == 0,
+               OffsetOf_VertexAttrib1f_header_not_0);
+COMPILE_ASSERT(offsetof(VertexAttrib1f, indx) == 4,
+               OffsetOf_VertexAttrib1f_indx_not_4);
+COMPILE_ASSERT(offsetof(VertexAttrib1f, x) == 8,
+               OffsetOf_VertexAttrib1f_x_not_8);
+
+struct VertexAttrib1fv {
+  typedef VertexAttrib1fv ValueType;
+  static const CommandId kCmdId = kVertexAttrib1fv;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLuint _indx, uint32 _values_shm_id, uint32 _values_shm_offset) {
+    SetHeader();
+    indx = _indx;
+    values_shm_id = _values_shm_id;
+    values_shm_offset = _values_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLuint _indx, uint32 _values_shm_id,
+      uint32 _values_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(_indx, _values_shm_id, _values_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 indx;
+  uint32 values_shm_id;
+  uint32 values_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(VertexAttrib1fv) == 16,
+               Sizeof_VertexAttrib1fv_is_not_16);
+COMPILE_ASSERT(offsetof(VertexAttrib1fv, header) == 0,
+               OffsetOf_VertexAttrib1fv_header_not_0);
+COMPILE_ASSERT(offsetof(VertexAttrib1fv, indx) == 4,
+               OffsetOf_VertexAttrib1fv_indx_not_4);
+COMPILE_ASSERT(offsetof(VertexAttrib1fv, values_shm_id) == 8,
+               OffsetOf_VertexAttrib1fv_values_shm_id_not_8);
+COMPILE_ASSERT(offsetof(VertexAttrib1fv, values_shm_offset) == 12,
+               OffsetOf_VertexAttrib1fv_values_shm_offset_not_12);
+
+struct VertexAttrib1fvImmediate {
+  typedef VertexAttrib1fvImmediate ValueType;
+  static const CommandId kCmdId = kVertexAttrib1fvImmediate;
+  static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN;
+
+  static uint32 ComputeDataSize() {
+    return static_cast<uint32>(
+        sizeof(GLfloat) * 1);  // NOLINT
+  }
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(
+        sizeof(ValueType) + ComputeDataSize());  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmdByTotalSize<ValueType>(ComputeSize());
+  }
+
+  void Init(GLuint _indx, const GLfloat* _values) {
+    SetHeader();
+    indx = _indx;
+    memcpy(ImmediateDataAddress(this),
+           _values, ComputeDataSize());
+  }
+
+  void* Set(void* cmd, GLuint _indx, const GLfloat* _values) {
+    static_cast<ValueType*>(cmd)->Init(_indx, _values);
+    const uint32 size = ComputeSize();
+    return NextImmediateCmdAddressTotalSize<ValueType>(cmd, size);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 indx;
+};
+
+COMPILE_ASSERT(sizeof(VertexAttrib1fvImmediate) == 8,
+               Sizeof_VertexAttrib1fvImmediate_is_not_8);
+COMPILE_ASSERT(offsetof(VertexAttrib1fvImmediate, header) == 0,
+               OffsetOf_VertexAttrib1fvImmediate_header_not_0);
+COMPILE_ASSERT(offsetof(VertexAttrib1fvImmediate, indx) == 4,
+               OffsetOf_VertexAttrib1fvImmediate_indx_not_4);
+
+struct VertexAttrib2f {
+  typedef VertexAttrib2f ValueType;
+  static const CommandId kCmdId = kVertexAttrib2f;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLuint _indx, GLfloat _x, GLfloat _y) {
+    SetHeader();
+    indx = _indx;
+    x = _x;
+    y = _y;
+  }
+
+  void* Set(void* cmd, GLuint _indx, GLfloat _x, GLfloat _y) {
+    static_cast<ValueType*>(cmd)->Init(_indx, _x, _y);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 indx;
+  float x;
+  float y;
+};
+
+COMPILE_ASSERT(sizeof(VertexAttrib2f) == 16,
+               Sizeof_VertexAttrib2f_is_not_16);
+COMPILE_ASSERT(offsetof(VertexAttrib2f, header) == 0,
+               OffsetOf_VertexAttrib2f_header_not_0);
+COMPILE_ASSERT(offsetof(VertexAttrib2f, indx) == 4,
+               OffsetOf_VertexAttrib2f_indx_not_4);
+COMPILE_ASSERT(offsetof(VertexAttrib2f, x) == 8,
+               OffsetOf_VertexAttrib2f_x_not_8);
+COMPILE_ASSERT(offsetof(VertexAttrib2f, y) == 12,
+               OffsetOf_VertexAttrib2f_y_not_12);
+
+struct VertexAttrib2fv {
+  typedef VertexAttrib2fv ValueType;
+  static const CommandId kCmdId = kVertexAttrib2fv;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLuint _indx, uint32 _values_shm_id, uint32 _values_shm_offset) {
+    SetHeader();
+    indx = _indx;
+    values_shm_id = _values_shm_id;
+    values_shm_offset = _values_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLuint _indx, uint32 _values_shm_id,
+      uint32 _values_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(_indx, _values_shm_id, _values_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 indx;
+  uint32 values_shm_id;
+  uint32 values_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(VertexAttrib2fv) == 16,
+               Sizeof_VertexAttrib2fv_is_not_16);
+COMPILE_ASSERT(offsetof(VertexAttrib2fv, header) == 0,
+               OffsetOf_VertexAttrib2fv_header_not_0);
+COMPILE_ASSERT(offsetof(VertexAttrib2fv, indx) == 4,
+               OffsetOf_VertexAttrib2fv_indx_not_4);
+COMPILE_ASSERT(offsetof(VertexAttrib2fv, values_shm_id) == 8,
+               OffsetOf_VertexAttrib2fv_values_shm_id_not_8);
+COMPILE_ASSERT(offsetof(VertexAttrib2fv, values_shm_offset) == 12,
+               OffsetOf_VertexAttrib2fv_values_shm_offset_not_12);
+
+struct VertexAttrib2fvImmediate {
+  typedef VertexAttrib2fvImmediate ValueType;
+  static const CommandId kCmdId = kVertexAttrib2fvImmediate;
+  static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN;
+
+  static uint32 ComputeDataSize() {
+    return static_cast<uint32>(
+        sizeof(GLfloat) * 2);  // NOLINT
+  }
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(
+        sizeof(ValueType) + ComputeDataSize());  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmdByTotalSize<ValueType>(ComputeSize());
+  }
+
+  void Init(GLuint _indx, const GLfloat* _values) {
+    SetHeader();
+    indx = _indx;
+    memcpy(ImmediateDataAddress(this),
+           _values, ComputeDataSize());
+  }
+
+  void* Set(void* cmd, GLuint _indx, const GLfloat* _values) {
+    static_cast<ValueType*>(cmd)->Init(_indx, _values);
+    const uint32 size = ComputeSize();
+    return NextImmediateCmdAddressTotalSize<ValueType>(cmd, size);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 indx;
+};
+
+COMPILE_ASSERT(sizeof(VertexAttrib2fvImmediate) == 8,
+               Sizeof_VertexAttrib2fvImmediate_is_not_8);
+COMPILE_ASSERT(offsetof(VertexAttrib2fvImmediate, header) == 0,
+               OffsetOf_VertexAttrib2fvImmediate_header_not_0);
+COMPILE_ASSERT(offsetof(VertexAttrib2fvImmediate, indx) == 4,
+               OffsetOf_VertexAttrib2fvImmediate_indx_not_4);
+
+struct VertexAttrib3f {
+  typedef VertexAttrib3f ValueType;
+  static const CommandId kCmdId = kVertexAttrib3f;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLuint _indx, GLfloat _x, GLfloat _y, GLfloat _z) {
+    SetHeader();
+    indx = _indx;
+    x = _x;
+    y = _y;
+    z = _z;
+  }
+
+  void* Set(void* cmd, GLuint _indx, GLfloat _x, GLfloat _y, GLfloat _z) {
+    static_cast<ValueType*>(cmd)->Init(_indx, _x, _y, _z);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 indx;
+  float x;
+  float y;
+  float z;
+};
+
+COMPILE_ASSERT(sizeof(VertexAttrib3f) == 20,
+               Sizeof_VertexAttrib3f_is_not_20);
+COMPILE_ASSERT(offsetof(VertexAttrib3f, header) == 0,
+               OffsetOf_VertexAttrib3f_header_not_0);
+COMPILE_ASSERT(offsetof(VertexAttrib3f, indx) == 4,
+               OffsetOf_VertexAttrib3f_indx_not_4);
+COMPILE_ASSERT(offsetof(VertexAttrib3f, x) == 8,
+               OffsetOf_VertexAttrib3f_x_not_8);
+COMPILE_ASSERT(offsetof(VertexAttrib3f, y) == 12,
+               OffsetOf_VertexAttrib3f_y_not_12);
+COMPILE_ASSERT(offsetof(VertexAttrib3f, z) == 16,
+               OffsetOf_VertexAttrib3f_z_not_16);
+
+struct VertexAttrib3fv {
+  typedef VertexAttrib3fv ValueType;
+  static const CommandId kCmdId = kVertexAttrib3fv;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLuint _indx, uint32 _values_shm_id, uint32 _values_shm_offset) {
+    SetHeader();
+    indx = _indx;
+    values_shm_id = _values_shm_id;
+    values_shm_offset = _values_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLuint _indx, uint32 _values_shm_id,
+      uint32 _values_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(_indx, _values_shm_id, _values_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 indx;
+  uint32 values_shm_id;
+  uint32 values_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(VertexAttrib3fv) == 16,
+               Sizeof_VertexAttrib3fv_is_not_16);
+COMPILE_ASSERT(offsetof(VertexAttrib3fv, header) == 0,
+               OffsetOf_VertexAttrib3fv_header_not_0);
+COMPILE_ASSERT(offsetof(VertexAttrib3fv, indx) == 4,
+               OffsetOf_VertexAttrib3fv_indx_not_4);
+COMPILE_ASSERT(offsetof(VertexAttrib3fv, values_shm_id) == 8,
+               OffsetOf_VertexAttrib3fv_values_shm_id_not_8);
+COMPILE_ASSERT(offsetof(VertexAttrib3fv, values_shm_offset) == 12,
+               OffsetOf_VertexAttrib3fv_values_shm_offset_not_12);
+
+struct VertexAttrib3fvImmediate {
+  typedef VertexAttrib3fvImmediate ValueType;
+  static const CommandId kCmdId = kVertexAttrib3fvImmediate;
+  static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN;
+
+  static uint32 ComputeDataSize() {
+    return static_cast<uint32>(
+        sizeof(GLfloat) * 3);  // NOLINT
+  }
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(
+        sizeof(ValueType) + ComputeDataSize());  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmdByTotalSize<ValueType>(ComputeSize());
+  }
+
+  void Init(GLuint _indx, const GLfloat* _values) {
+    SetHeader();
+    indx = _indx;
+    memcpy(ImmediateDataAddress(this),
+           _values, ComputeDataSize());
+  }
+
+  void* Set(void* cmd, GLuint _indx, const GLfloat* _values) {
+    static_cast<ValueType*>(cmd)->Init(_indx, _values);
+    const uint32 size = ComputeSize();
+    return NextImmediateCmdAddressTotalSize<ValueType>(cmd, size);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 indx;
+};
+
+COMPILE_ASSERT(sizeof(VertexAttrib3fvImmediate) == 8,
+               Sizeof_VertexAttrib3fvImmediate_is_not_8);
+COMPILE_ASSERT(offsetof(VertexAttrib3fvImmediate, header) == 0,
+               OffsetOf_VertexAttrib3fvImmediate_header_not_0);
+COMPILE_ASSERT(offsetof(VertexAttrib3fvImmediate, indx) == 4,
+               OffsetOf_VertexAttrib3fvImmediate_indx_not_4);
+
+struct VertexAttrib4f {
+  typedef VertexAttrib4f ValueType;
+  static const CommandId kCmdId = kVertexAttrib4f;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLuint _indx, GLfloat _x, GLfloat _y, GLfloat _z, GLfloat _w) {
+    SetHeader();
+    indx = _indx;
+    x = _x;
+    y = _y;
+    z = _z;
+    w = _w;
+  }
+
+  void* Set(
+      void* cmd, GLuint _indx, GLfloat _x, GLfloat _y, GLfloat _z,
+      GLfloat _w) {
+    static_cast<ValueType*>(cmd)->Init(_indx, _x, _y, _z, _w);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 indx;
+  float x;
+  float y;
+  float z;
+  float w;
+};
+
+COMPILE_ASSERT(sizeof(VertexAttrib4f) == 24,
+               Sizeof_VertexAttrib4f_is_not_24);
+COMPILE_ASSERT(offsetof(VertexAttrib4f, header) == 0,
+               OffsetOf_VertexAttrib4f_header_not_0);
+COMPILE_ASSERT(offsetof(VertexAttrib4f, indx) == 4,
+               OffsetOf_VertexAttrib4f_indx_not_4);
+COMPILE_ASSERT(offsetof(VertexAttrib4f, x) == 8,
+               OffsetOf_VertexAttrib4f_x_not_8);
+COMPILE_ASSERT(offsetof(VertexAttrib4f, y) == 12,
+               OffsetOf_VertexAttrib4f_y_not_12);
+COMPILE_ASSERT(offsetof(VertexAttrib4f, z) == 16,
+               OffsetOf_VertexAttrib4f_z_not_16);
+COMPILE_ASSERT(offsetof(VertexAttrib4f, w) == 20,
+               OffsetOf_VertexAttrib4f_w_not_20);
+
+struct VertexAttrib4fv {
+  typedef VertexAttrib4fv ValueType;
+  static const CommandId kCmdId = kVertexAttrib4fv;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLuint _indx, uint32 _values_shm_id, uint32 _values_shm_offset) {
+    SetHeader();
+    indx = _indx;
+    values_shm_id = _values_shm_id;
+    values_shm_offset = _values_shm_offset;
+  }
+
+  void* Set(
+      void* cmd, GLuint _indx, uint32 _values_shm_id,
+      uint32 _values_shm_offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(_indx, _values_shm_id, _values_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 indx;
+  uint32 values_shm_id;
+  uint32 values_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(VertexAttrib4fv) == 16,
+               Sizeof_VertexAttrib4fv_is_not_16);
+COMPILE_ASSERT(offsetof(VertexAttrib4fv, header) == 0,
+               OffsetOf_VertexAttrib4fv_header_not_0);
+COMPILE_ASSERT(offsetof(VertexAttrib4fv, indx) == 4,
+               OffsetOf_VertexAttrib4fv_indx_not_4);
+COMPILE_ASSERT(offsetof(VertexAttrib4fv, values_shm_id) == 8,
+               OffsetOf_VertexAttrib4fv_values_shm_id_not_8);
+COMPILE_ASSERT(offsetof(VertexAttrib4fv, values_shm_offset) == 12,
+               OffsetOf_VertexAttrib4fv_values_shm_offset_not_12);
+
+struct VertexAttrib4fvImmediate {
+  typedef VertexAttrib4fvImmediate ValueType;
+  static const CommandId kCmdId = kVertexAttrib4fvImmediate;
+  static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN;
+
+  static uint32 ComputeDataSize() {
+    return static_cast<uint32>(
+        sizeof(GLfloat) * 4);  // NOLINT
+  }
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(
+        sizeof(ValueType) + ComputeDataSize());  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmdByTotalSize<ValueType>(ComputeSize());
+  }
+
+  void Init(GLuint _indx, const GLfloat* _values) {
+    SetHeader();
+    indx = _indx;
+    memcpy(ImmediateDataAddress(this),
+           _values, ComputeDataSize());
+  }
+
+  void* Set(void* cmd, GLuint _indx, const GLfloat* _values) {
+    static_cast<ValueType*>(cmd)->Init(_indx, _values);
+    const uint32 size = ComputeSize();
+    return NextImmediateCmdAddressTotalSize<ValueType>(cmd, size);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 indx;
+};
+
+COMPILE_ASSERT(sizeof(VertexAttrib4fvImmediate) == 8,
+               Sizeof_VertexAttrib4fvImmediate_is_not_8);
+COMPILE_ASSERT(offsetof(VertexAttrib4fvImmediate, header) == 0,
+               OffsetOf_VertexAttrib4fvImmediate_header_not_0);
+COMPILE_ASSERT(offsetof(VertexAttrib4fvImmediate, indx) == 4,
+               OffsetOf_VertexAttrib4fvImmediate_indx_not_4);
+
+struct VertexAttribPointer {
+  typedef VertexAttribPointer ValueType;
+  static const CommandId kCmdId = kVertexAttribPointer;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(
+      GLuint _indx, GLint _size, GLenum _type, GLboolean _normalized,
+      GLsizei _stride, GLuint _offset) {
+    SetHeader();
+    indx = _indx;
+    size = _size;
+    type = _type;
+    normalized = _normalized;
+    stride = _stride;
+    offset = _offset;
+  }
+
+  void* Set(
+      void* cmd, GLuint _indx, GLint _size, GLenum _type, GLboolean _normalized,
+      GLsizei _stride, GLuint _offset) {
+    static_cast<ValueType*>(
+        cmd)->Init(_indx, _size, _type, _normalized, _stride, _offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 indx;
+  uint32 size;
+  uint32 type;
+  uint32 normalized;
+  uint32 stride;
+  uint32 offset;
+};
+
+COMPILE_ASSERT(sizeof(VertexAttribPointer) == 28,
+               Sizeof_VertexAttribPointer_is_not_28);
+COMPILE_ASSERT(offsetof(VertexAttribPointer, header) == 0,
+               OffsetOf_VertexAttribPointer_header_not_0);
+COMPILE_ASSERT(offsetof(VertexAttribPointer, indx) == 4,
+               OffsetOf_VertexAttribPointer_indx_not_4);
+COMPILE_ASSERT(offsetof(VertexAttribPointer, size) == 8,
+               OffsetOf_VertexAttribPointer_size_not_8);
+COMPILE_ASSERT(offsetof(VertexAttribPointer, type) == 12,
+               OffsetOf_VertexAttribPointer_type_not_12);
+COMPILE_ASSERT(offsetof(VertexAttribPointer, normalized) == 16,
+               OffsetOf_VertexAttribPointer_normalized_not_16);
+COMPILE_ASSERT(offsetof(VertexAttribPointer, stride) == 20,
+               OffsetOf_VertexAttribPointer_stride_not_20);
+COMPILE_ASSERT(offsetof(VertexAttribPointer, offset) == 24,
+               OffsetOf_VertexAttribPointer_offset_not_24);
+
+struct Viewport {
+  typedef Viewport ValueType;
+  static const CommandId kCmdId = kViewport;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init(GLint _x, GLint _y, GLsizei _width, GLsizei _height) {
+    SetHeader();
+    x = _x;
+    y = _y;
+    width = _width;
+    height = _height;
+  }
+
+  void* Set(void* cmd, GLint _x, GLint _y, GLsizei _width, GLsizei _height) {
+    static_cast<ValueType*>(cmd)->Init(_x, _y, _width, _height);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+  uint32 x;
+  uint32 y;
+  uint32 width;
+  uint32 height;
+};
+
+COMPILE_ASSERT(sizeof(Viewport) == 20,
+               Sizeof_Viewport_is_not_20);
+COMPILE_ASSERT(offsetof(Viewport, header) == 0,
+               OffsetOf_Viewport_header_not_0);
+COMPILE_ASSERT(offsetof(Viewport, x) == 4,
+               OffsetOf_Viewport_x_not_4);
+COMPILE_ASSERT(offsetof(Viewport, y) == 8,
+               OffsetOf_Viewport_y_not_8);
+COMPILE_ASSERT(offsetof(Viewport, width) == 12,
+               OffsetOf_Viewport_width_not_12);
+COMPILE_ASSERT(offsetof(Viewport, height) == 16,
+               OffsetOf_Viewport_height_not_16);
+
+struct SwapBuffers {
+  typedef SwapBuffers ValueType;
+  static const CommandId kCmdId = kSwapBuffers;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+  static uint32 ComputeSize() {
+    return static_cast<uint32>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() {
+    header.SetCmd<ValueType>();
+  }
+
+  void Init() {
+    SetHeader();
+  }
+
+  void* Set(void* cmd) {
+    static_cast<ValueType*>(cmd)->Init();
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  command_buffer::CommandHeader header;
+};
+
+COMPILE_ASSERT(sizeof(SwapBuffers) == 4,
+               Sizeof_SwapBuffers_is_not_4);
+COMPILE_ASSERT(offsetof(SwapBuffers, header) == 0,
+               OffsetOf_SwapBuffers_header_not_0);
+
+#pragma pack(pop)
+
diff --git a/gpu/command_buffer/common/gles2_cmd_format_test.cc b/gpu/command_buffer/common/gles2_cmd_format_test.cc
new file mode 100644
index 0000000..c699a1d
--- /dev/null
+++ b/gpu/command_buffer/common/gles2_cmd_format_test.cc
@@ -0,0 +1,17 @@
+// Copyright (c) 2006-2009 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.
+
+// This file contains unit tests for gles2 commmands
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "gpu/command_buffer/common/gles2_cmd_format.h"
+
+namespace command_buffer {
+namespace gles2 {
+
+#include "gpu/command_buffer/common/gles2_cmd_format_test_autogen.h"
+
+}  // namespace gles2
+}  // namespace command_buffer
+
diff --git a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
new file mode 100644
index 0000000..b914e07
--- /dev/null
+++ b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
@@ -0,0 +1,2758 @@
+// This file is auto-generated. DO NOT EDIT!
+
+// This file contains unit tests for gles2 commmands
+// It is included by gles2_cmd_format_test.cc
+
+TEST(GLES2FormatTest, ActiveTexture) {
+  ActiveTexture cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11));
+  EXPECT_EQ(ActiveTexture::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.texture);
+}
+
+TEST(GLES2FormatTest, AttachShader) {
+  AttachShader cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLuint>(11),
+      static_cast<GLuint>(12));
+  EXPECT_EQ(AttachShader::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.program);
+  EXPECT_EQ(static_cast<GLuint>(12), cmd.shader);
+}
+
+TEST(GLES2FormatTest, BindAttribLocation) {
+  BindAttribLocation cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLuint>(11),
+      static_cast<GLuint>(12),
+      static_cast<uint32>(13),
+      static_cast<uint32>(14),
+      static_cast<uint32>(15));
+  EXPECT_EQ(BindAttribLocation::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.program);
+  EXPECT_EQ(static_cast<GLuint>(12), cmd.index);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.name_shm_id);
+  EXPECT_EQ(static_cast<uint32>(14), cmd.name_shm_offset);
+  EXPECT_EQ(static_cast<uint32>(15), cmd.data_size);
+}
+
+TEST(GLES2FormatTest, BindAttribLocationImmediate) {
+  int8 buf[256] = { 0, };
+  BindAttribLocationImmediate& cmd =
+      *static_cast<BindAttribLocationImmediate*>(static_cast<void*>(&buf));
+  static const char* const test_str = "test string";
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLuint>(11),
+      static_cast<GLuint>(12),
+      test_str);
+  EXPECT_EQ(BindAttribLocationImmediate::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd) +  // NOLINT
+            RoundSizeToMultipleOfEntries(strlen(test_str)),
+            cmd.header.size * 4);
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.program);
+  EXPECT_EQ(static_cast<GLuint>(12), cmd.index);
+  // TODO(gman): check that string got copied.
+}
+
+TEST(GLES2FormatTest, BindBuffer) {
+  BindBuffer cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11),
+      static_cast<GLuint>(12));
+  EXPECT_EQ(BindBuffer::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.target);
+  EXPECT_EQ(static_cast<GLuint>(12), cmd.buffer);
+}
+
+TEST(GLES2FormatTest, BindFramebuffer) {
+  BindFramebuffer cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11),
+      static_cast<GLuint>(12));
+  EXPECT_EQ(BindFramebuffer::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.target);
+  EXPECT_EQ(static_cast<GLuint>(12), cmd.framebuffer);
+}
+
+TEST(GLES2FormatTest, BindRenderbuffer) {
+  BindRenderbuffer cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11),
+      static_cast<GLuint>(12));
+  EXPECT_EQ(BindRenderbuffer::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.target);
+  EXPECT_EQ(static_cast<GLuint>(12), cmd.renderbuffer);
+}
+
+TEST(GLES2FormatTest, BindTexture) {
+  BindTexture cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11),
+      static_cast<GLuint>(12));
+  EXPECT_EQ(BindTexture::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.target);
+  EXPECT_EQ(static_cast<GLuint>(12), cmd.texture);
+}
+
+TEST(GLES2FormatTest, BlendColor) {
+  BlendColor cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLclampf>(11),
+      static_cast<GLclampf>(12),
+      static_cast<GLclampf>(13),
+      static_cast<GLclampf>(14));
+  EXPECT_EQ(BlendColor::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLclampf>(11), cmd.red);
+  EXPECT_EQ(static_cast<GLclampf>(12), cmd.green);
+  EXPECT_EQ(static_cast<GLclampf>(13), cmd.blue);
+  EXPECT_EQ(static_cast<GLclampf>(14), cmd.alpha);
+}
+
+TEST(GLES2FormatTest, BlendEquation) {
+  BlendEquation cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11));
+  EXPECT_EQ(BlendEquation::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.mode);
+}
+
+TEST(GLES2FormatTest, BlendEquationSeparate) {
+  BlendEquationSeparate cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11),
+      static_cast<GLenum>(12));
+  EXPECT_EQ(BlendEquationSeparate::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.modeRGB);
+  EXPECT_EQ(static_cast<GLenum>(12), cmd.modeAlpha);
+}
+
+TEST(GLES2FormatTest, BlendFunc) {
+  BlendFunc cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11),
+      static_cast<GLenum>(12));
+  EXPECT_EQ(BlendFunc::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.sfactor);
+  EXPECT_EQ(static_cast<GLenum>(12), cmd.dfactor);
+}
+
+TEST(GLES2FormatTest, BlendFuncSeparate) {
+  BlendFuncSeparate cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11),
+      static_cast<GLenum>(12),
+      static_cast<GLenum>(13),
+      static_cast<GLenum>(14));
+  EXPECT_EQ(BlendFuncSeparate::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.srcRGB);
+  EXPECT_EQ(static_cast<GLenum>(12), cmd.dstRGB);
+  EXPECT_EQ(static_cast<GLenum>(13), cmd.srcAlpha);
+  EXPECT_EQ(static_cast<GLenum>(14), cmd.dstAlpha);
+}
+
+TEST(GLES2FormatTest, BufferData) {
+  BufferData cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11),
+      static_cast<GLsizeiptr>(12),
+      static_cast<uint32>(13),
+      static_cast<uint32>(14),
+      static_cast<GLenum>(15));
+  EXPECT_EQ(BufferData::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.target);
+  EXPECT_EQ(static_cast<GLsizeiptr>(12), cmd.size);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.data_shm_id);
+  EXPECT_EQ(static_cast<uint32>(14), cmd.data_shm_offset);
+  EXPECT_EQ(static_cast<GLenum>(15), cmd.usage);
+}
+
+// TODO(gman): Implement test for BufferDataImmediate
+TEST(GLES2FormatTest, BufferSubData) {
+  BufferSubData cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11),
+      static_cast<GLintptr>(12),
+      static_cast<GLsizeiptr>(13),
+      static_cast<uint32>(14),
+      static_cast<uint32>(15));
+  EXPECT_EQ(BufferSubData::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.target);
+  EXPECT_EQ(static_cast<GLintptr>(12), cmd.offset);
+  EXPECT_EQ(static_cast<GLsizeiptr>(13), cmd.size);
+  EXPECT_EQ(static_cast<uint32>(14), cmd.data_shm_id);
+  EXPECT_EQ(static_cast<uint32>(15), cmd.data_shm_offset);
+}
+
+// TODO(gman): Implement test for BufferSubDataImmediate
+TEST(GLES2FormatTest, CheckFramebufferStatus) {
+  CheckFramebufferStatus cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11));
+  EXPECT_EQ(CheckFramebufferStatus::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.target);
+}
+
+TEST(GLES2FormatTest, Clear) {
+  Clear cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLbitfield>(11));
+  EXPECT_EQ(Clear::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLbitfield>(11), cmd.mask);
+}
+
+TEST(GLES2FormatTest, ClearColor) {
+  ClearColor cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLclampf>(11),
+      static_cast<GLclampf>(12),
+      static_cast<GLclampf>(13),
+      static_cast<GLclampf>(14));
+  EXPECT_EQ(ClearColor::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLclampf>(11), cmd.red);
+  EXPECT_EQ(static_cast<GLclampf>(12), cmd.green);
+  EXPECT_EQ(static_cast<GLclampf>(13), cmd.blue);
+  EXPECT_EQ(static_cast<GLclampf>(14), cmd.alpha);
+}
+
+TEST(GLES2FormatTest, ClearDepthf) {
+  ClearDepthf cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLclampf>(11));
+  EXPECT_EQ(ClearDepthf::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLclampf>(11), cmd.depth);
+}
+
+TEST(GLES2FormatTest, ClearStencil) {
+  ClearStencil cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLint>(11));
+  EXPECT_EQ(ClearStencil::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLint>(11), cmd.s);
+}
+
+TEST(GLES2FormatTest, ColorMask) {
+  ColorMask cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLboolean>(11),
+      static_cast<GLboolean>(12),
+      static_cast<GLboolean>(13),
+      static_cast<GLboolean>(14));
+  EXPECT_EQ(ColorMask::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLboolean>(11), cmd.red);
+  EXPECT_EQ(static_cast<GLboolean>(12), cmd.green);
+  EXPECT_EQ(static_cast<GLboolean>(13), cmd.blue);
+  EXPECT_EQ(static_cast<GLboolean>(14), cmd.alpha);
+}
+
+TEST(GLES2FormatTest, CompileShader) {
+  CompileShader cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLuint>(11));
+  EXPECT_EQ(CompileShader::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.shader);
+}
+
+TEST(GLES2FormatTest, CompressedTexImage2D) {
+  CompressedTexImage2D cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11),
+      static_cast<GLint>(12),
+      static_cast<GLenum>(13),
+      static_cast<GLsizei>(14),
+      static_cast<GLsizei>(15),
+      static_cast<GLint>(16),
+      static_cast<GLsizei>(17),
+      static_cast<uint32>(18),
+      static_cast<uint32>(19));
+  EXPECT_EQ(CompressedTexImage2D::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.target);
+  EXPECT_EQ(static_cast<GLint>(12), cmd.level);
+  EXPECT_EQ(static_cast<GLenum>(13), cmd.internalformat);
+  EXPECT_EQ(static_cast<GLsizei>(14), cmd.width);
+  EXPECT_EQ(static_cast<GLsizei>(15), cmd.height);
+  EXPECT_EQ(static_cast<GLint>(16), cmd.border);
+  EXPECT_EQ(static_cast<GLsizei>(17), cmd.imageSize);
+  EXPECT_EQ(static_cast<uint32>(18), cmd.data_shm_id);
+  EXPECT_EQ(static_cast<uint32>(19), cmd.data_shm_offset);
+}
+
+// TODO(gman): Implement test for CompressedTexImage2DImmediate
+TEST(GLES2FormatTest, CompressedTexSubImage2D) {
+  CompressedTexSubImage2D cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11),
+      static_cast<GLint>(12),
+      static_cast<GLint>(13),
+      static_cast<GLint>(14),
+      static_cast<GLsizei>(15),
+      static_cast<GLsizei>(16),
+      static_cast<GLenum>(17),
+      static_cast<GLsizei>(18),
+      static_cast<uint32>(19),
+      static_cast<uint32>(20));
+  EXPECT_EQ(CompressedTexSubImage2D::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.target);
+  EXPECT_EQ(static_cast<GLint>(12), cmd.level);
+  EXPECT_EQ(static_cast<GLint>(13), cmd.xoffset);
+  EXPECT_EQ(static_cast<GLint>(14), cmd.yoffset);
+  EXPECT_EQ(static_cast<GLsizei>(15), cmd.width);
+  EXPECT_EQ(static_cast<GLsizei>(16), cmd.height);
+  EXPECT_EQ(static_cast<GLenum>(17), cmd.format);
+  EXPECT_EQ(static_cast<GLsizei>(18), cmd.imageSize);
+  EXPECT_EQ(static_cast<uint32>(19), cmd.data_shm_id);
+  EXPECT_EQ(static_cast<uint32>(20), cmd.data_shm_offset);
+}
+
+// TODO(gman): Implement test for CompressedTexSubImage2DImmediate
+TEST(GLES2FormatTest, CopyTexImage2D) {
+  CopyTexImage2D cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11),
+      static_cast<GLint>(12),
+      static_cast<GLenum>(13),
+      static_cast<GLint>(14),
+      static_cast<GLint>(15),
+      static_cast<GLsizei>(16),
+      static_cast<GLsizei>(17),
+      static_cast<GLint>(18));
+  EXPECT_EQ(CopyTexImage2D::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.target);
+  EXPECT_EQ(static_cast<GLint>(12), cmd.level);
+  EXPECT_EQ(static_cast<GLenum>(13), cmd.internalformat);
+  EXPECT_EQ(static_cast<GLint>(14), cmd.x);
+  EXPECT_EQ(static_cast<GLint>(15), cmd.y);
+  EXPECT_EQ(static_cast<GLsizei>(16), cmd.width);
+  EXPECT_EQ(static_cast<GLsizei>(17), cmd.height);
+  EXPECT_EQ(static_cast<GLint>(18), cmd.border);
+}
+
+TEST(GLES2FormatTest, CopyTexSubImage2D) {
+  CopyTexSubImage2D cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11),
+      static_cast<GLint>(12),
+      static_cast<GLint>(13),
+      static_cast<GLint>(14),
+      static_cast<GLint>(15),
+      static_cast<GLint>(16),
+      static_cast<GLsizei>(17),
+      static_cast<GLsizei>(18));
+  EXPECT_EQ(CopyTexSubImage2D::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.target);
+  EXPECT_EQ(static_cast<GLint>(12), cmd.level);
+  EXPECT_EQ(static_cast<GLint>(13), cmd.xoffset);
+  EXPECT_EQ(static_cast<GLint>(14), cmd.yoffset);
+  EXPECT_EQ(static_cast<GLint>(15), cmd.x);
+  EXPECT_EQ(static_cast<GLint>(16), cmd.y);
+  EXPECT_EQ(static_cast<GLsizei>(17), cmd.width);
+  EXPECT_EQ(static_cast<GLsizei>(18), cmd.height);
+}
+
+TEST(GLES2FormatTest, CreateProgram) {
+  CreateProgram cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<uint32>(11));
+  EXPECT_EQ(CreateProgram::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<uint32>(11), cmd.client_id);
+}
+
+TEST(GLES2FormatTest, CreateShader) {
+  CreateShader cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11),
+      static_cast<uint32>(12));
+  EXPECT_EQ(CreateShader::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.type);
+  EXPECT_EQ(static_cast<uint32>(12), cmd.client_id);
+}
+
+TEST(GLES2FormatTest, CullFace) {
+  CullFace cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11));
+  EXPECT_EQ(CullFace::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.mode);
+}
+
+TEST(GLES2FormatTest, DeleteBuffers) {
+  DeleteBuffers cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLsizei>(11),
+      static_cast<uint32>(12),
+      static_cast<uint32>(13));
+  EXPECT_EQ(DeleteBuffers::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLsizei>(11), cmd.n);
+  EXPECT_EQ(static_cast<uint32>(12), cmd.buffers_shm_id);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.buffers_shm_offset);
+}
+
+TEST(GLES2FormatTest, DeleteBuffersImmediate) {
+  static GLuint ids[] = { 12, 23, 34, };
+  int8 buf[256] = { 0, };
+  DeleteBuffersImmediate& cmd =
+      *static_cast<DeleteBuffersImmediate*>(static_cast<void*>(&buf));
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLsizei>(11),
+      ids);
+  EXPECT_EQ(DeleteBuffersImmediate::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd) +
+            RoundSizeToMultipleOfEntries(cmd.n * 4),
+            cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLsizei>(11), cmd.n);
+  // TODO(gman): Check that ids were inserted;
+}
+
+TEST(GLES2FormatTest, DeleteFramebuffers) {
+  DeleteFramebuffers cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLsizei>(11),
+      static_cast<uint32>(12),
+      static_cast<uint32>(13));
+  EXPECT_EQ(DeleteFramebuffers::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLsizei>(11), cmd.n);
+  EXPECT_EQ(static_cast<uint32>(12), cmd.framebuffers_shm_id);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.framebuffers_shm_offset);
+}
+
+TEST(GLES2FormatTest, DeleteFramebuffersImmediate) {
+  static GLuint ids[] = { 12, 23, 34, };
+  int8 buf[256] = { 0, };
+  DeleteFramebuffersImmediate& cmd =
+      *static_cast<DeleteFramebuffersImmediate*>(static_cast<void*>(&buf));
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLsizei>(11),
+      ids);
+  EXPECT_EQ(DeleteFramebuffersImmediate::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd) +
+            RoundSizeToMultipleOfEntries(cmd.n * 4),
+            cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLsizei>(11), cmd.n);
+  // TODO(gman): Check that ids were inserted;
+}
+
+TEST(GLES2FormatTest, DeleteProgram) {
+  DeleteProgram cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLuint>(11));
+  EXPECT_EQ(DeleteProgram::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.program);
+}
+
+TEST(GLES2FormatTest, DeleteRenderbuffers) {
+  DeleteRenderbuffers cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLsizei>(11),
+      static_cast<uint32>(12),
+      static_cast<uint32>(13));
+  EXPECT_EQ(DeleteRenderbuffers::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLsizei>(11), cmd.n);
+  EXPECT_EQ(static_cast<uint32>(12), cmd.renderbuffers_shm_id);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.renderbuffers_shm_offset);
+}
+
+TEST(GLES2FormatTest, DeleteRenderbuffersImmediate) {
+  static GLuint ids[] = { 12, 23, 34, };
+  int8 buf[256] = { 0, };
+  DeleteRenderbuffersImmediate& cmd =
+      *static_cast<DeleteRenderbuffersImmediate*>(static_cast<void*>(&buf));
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLsizei>(11),
+      ids);
+  EXPECT_EQ(DeleteRenderbuffersImmediate::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd) +
+            RoundSizeToMultipleOfEntries(cmd.n * 4),
+            cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLsizei>(11), cmd.n);
+  // TODO(gman): Check that ids were inserted;
+}
+
+TEST(GLES2FormatTest, DeleteShader) {
+  DeleteShader cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLuint>(11));
+  EXPECT_EQ(DeleteShader::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.shader);
+}
+
+TEST(GLES2FormatTest, DeleteTextures) {
+  DeleteTextures cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLsizei>(11),
+      static_cast<uint32>(12),
+      static_cast<uint32>(13));
+  EXPECT_EQ(DeleteTextures::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLsizei>(11), cmd.n);
+  EXPECT_EQ(static_cast<uint32>(12), cmd.textures_shm_id);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.textures_shm_offset);
+}
+
+TEST(GLES2FormatTest, DeleteTexturesImmediate) {
+  static GLuint ids[] = { 12, 23, 34, };
+  int8 buf[256] = { 0, };
+  DeleteTexturesImmediate& cmd =
+      *static_cast<DeleteTexturesImmediate*>(static_cast<void*>(&buf));
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLsizei>(11),
+      ids);
+  EXPECT_EQ(DeleteTexturesImmediate::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd) +
+            RoundSizeToMultipleOfEntries(cmd.n * 4),
+            cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLsizei>(11), cmd.n);
+  // TODO(gman): Check that ids were inserted;
+}
+
+TEST(GLES2FormatTest, DepthFunc) {
+  DepthFunc cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11));
+  EXPECT_EQ(DepthFunc::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.func);
+}
+
+TEST(GLES2FormatTest, DepthMask) {
+  DepthMask cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLboolean>(11));
+  EXPECT_EQ(DepthMask::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLboolean>(11), cmd.flag);
+}
+
+TEST(GLES2FormatTest, DepthRangef) {
+  DepthRangef cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLclampf>(11),
+      static_cast<GLclampf>(12));
+  EXPECT_EQ(DepthRangef::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLclampf>(11), cmd.zNear);
+  EXPECT_EQ(static_cast<GLclampf>(12), cmd.zFar);
+}
+
+TEST(GLES2FormatTest, DetachShader) {
+  DetachShader cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLuint>(11),
+      static_cast<GLuint>(12));
+  EXPECT_EQ(DetachShader::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.program);
+  EXPECT_EQ(static_cast<GLuint>(12), cmd.shader);
+}
+
+TEST(GLES2FormatTest, Disable) {
+  Disable cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11));
+  EXPECT_EQ(Disable::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.cap);
+}
+
+TEST(GLES2FormatTest, DisableVertexAttribArray) {
+  DisableVertexAttribArray cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLuint>(11));
+  EXPECT_EQ(DisableVertexAttribArray::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.index);
+}
+
+TEST(GLES2FormatTest, DrawArrays) {
+  DrawArrays cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11),
+      static_cast<GLint>(12),
+      static_cast<GLsizei>(13));
+  EXPECT_EQ(DrawArrays::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.mode);
+  EXPECT_EQ(static_cast<GLint>(12), cmd.first);
+  EXPECT_EQ(static_cast<GLsizei>(13), cmd.count);
+}
+
+TEST(GLES2FormatTest, DrawElements) {
+  DrawElements cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11),
+      static_cast<GLsizei>(12),
+      static_cast<GLenum>(13),
+      static_cast<GLuint>(14));
+  EXPECT_EQ(DrawElements::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.mode);
+  EXPECT_EQ(static_cast<GLsizei>(12), cmd.count);
+  EXPECT_EQ(static_cast<GLenum>(13), cmd.type);
+  EXPECT_EQ(static_cast<GLuint>(14), cmd.index_offset);
+}
+
+TEST(GLES2FormatTest, Enable) {
+  Enable cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11));
+  EXPECT_EQ(Enable::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.cap);
+}
+
+TEST(GLES2FormatTest, EnableVertexAttribArray) {
+  EnableVertexAttribArray cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLuint>(11));
+  EXPECT_EQ(EnableVertexAttribArray::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.index);
+}
+
+TEST(GLES2FormatTest, Finish) {
+  Finish cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd);
+  EXPECT_EQ(Finish::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+}
+
+TEST(GLES2FormatTest, Flush) {
+  Flush cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd);
+  EXPECT_EQ(Flush::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+}
+
+TEST(GLES2FormatTest, FramebufferRenderbuffer) {
+  FramebufferRenderbuffer cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11),
+      static_cast<GLenum>(12),
+      static_cast<GLenum>(13),
+      static_cast<GLuint>(14));
+  EXPECT_EQ(FramebufferRenderbuffer::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.target);
+  EXPECT_EQ(static_cast<GLenum>(12), cmd.attachment);
+  EXPECT_EQ(static_cast<GLenum>(13), cmd.renderbuffertarget);
+  EXPECT_EQ(static_cast<GLuint>(14), cmd.renderbuffer);
+}
+
+TEST(GLES2FormatTest, FramebufferTexture2D) {
+  FramebufferTexture2D cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11),
+      static_cast<GLenum>(12),
+      static_cast<GLenum>(13),
+      static_cast<GLuint>(14),
+      static_cast<GLint>(15));
+  EXPECT_EQ(FramebufferTexture2D::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.target);
+  EXPECT_EQ(static_cast<GLenum>(12), cmd.attachment);
+  EXPECT_EQ(static_cast<GLenum>(13), cmd.textarget);
+  EXPECT_EQ(static_cast<GLuint>(14), cmd.texture);
+  EXPECT_EQ(static_cast<GLint>(15), cmd.level);
+}
+
+TEST(GLES2FormatTest, FrontFace) {
+  FrontFace cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11));
+  EXPECT_EQ(FrontFace::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.mode);
+}
+
+TEST(GLES2FormatTest, GenBuffers) {
+  GenBuffers cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLsizei>(11),
+      static_cast<uint32>(12),
+      static_cast<uint32>(13));
+  EXPECT_EQ(GenBuffers::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLsizei>(11), cmd.n);
+  EXPECT_EQ(static_cast<uint32>(12), cmd.buffers_shm_id);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.buffers_shm_offset);
+}
+
+TEST(GLES2FormatTest, GenBuffersImmediate) {
+  static GLuint ids[] = { 12, 23, 34, };
+  int8 buf[256] = { 0, };
+  GenBuffersImmediate& cmd =
+      *static_cast<GenBuffersImmediate*>(static_cast<void*>(&buf));
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLsizei>(11),
+      ids);
+  EXPECT_EQ(GenBuffersImmediate::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd) +
+            RoundSizeToMultipleOfEntries(cmd.n * 4),
+            cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLsizei>(11), cmd.n);
+  // TODO(gman): Check that ids were inserted;
+}
+
+TEST(GLES2FormatTest, GenerateMipmap) {
+  GenerateMipmap cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11));
+  EXPECT_EQ(GenerateMipmap::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.target);
+}
+
+TEST(GLES2FormatTest, GenFramebuffers) {
+  GenFramebuffers cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLsizei>(11),
+      static_cast<uint32>(12),
+      static_cast<uint32>(13));
+  EXPECT_EQ(GenFramebuffers::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLsizei>(11), cmd.n);
+  EXPECT_EQ(static_cast<uint32>(12), cmd.framebuffers_shm_id);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.framebuffers_shm_offset);
+}
+
+TEST(GLES2FormatTest, GenFramebuffersImmediate) {
+  static GLuint ids[] = { 12, 23, 34, };
+  int8 buf[256] = { 0, };
+  GenFramebuffersImmediate& cmd =
+      *static_cast<GenFramebuffersImmediate*>(static_cast<void*>(&buf));
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLsizei>(11),
+      ids);
+  EXPECT_EQ(GenFramebuffersImmediate::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd) +
+            RoundSizeToMultipleOfEntries(cmd.n * 4),
+            cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLsizei>(11), cmd.n);
+  // TODO(gman): Check that ids were inserted;
+}
+
+TEST(GLES2FormatTest, GenRenderbuffers) {
+  GenRenderbuffers cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLsizei>(11),
+      static_cast<uint32>(12),
+      static_cast<uint32>(13));
+  EXPECT_EQ(GenRenderbuffers::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLsizei>(11), cmd.n);
+  EXPECT_EQ(static_cast<uint32>(12), cmd.renderbuffers_shm_id);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.renderbuffers_shm_offset);
+}
+
+TEST(GLES2FormatTest, GenRenderbuffersImmediate) {
+  static GLuint ids[] = { 12, 23, 34, };
+  int8 buf[256] = { 0, };
+  GenRenderbuffersImmediate& cmd =
+      *static_cast<GenRenderbuffersImmediate*>(static_cast<void*>(&buf));
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLsizei>(11),
+      ids);
+  EXPECT_EQ(GenRenderbuffersImmediate::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd) +
+            RoundSizeToMultipleOfEntries(cmd.n * 4),
+            cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLsizei>(11), cmd.n);
+  // TODO(gman): Check that ids were inserted;
+}
+
+TEST(GLES2FormatTest, GenTextures) {
+  GenTextures cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLsizei>(11),
+      static_cast<uint32>(12),
+      static_cast<uint32>(13));
+  EXPECT_EQ(GenTextures::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLsizei>(11), cmd.n);
+  EXPECT_EQ(static_cast<uint32>(12), cmd.textures_shm_id);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.textures_shm_offset);
+}
+
+TEST(GLES2FormatTest, GenTexturesImmediate) {
+  static GLuint ids[] = { 12, 23, 34, };
+  int8 buf[256] = { 0, };
+  GenTexturesImmediate& cmd =
+      *static_cast<GenTexturesImmediate*>(static_cast<void*>(&buf));
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLsizei>(11),
+      ids);
+  EXPECT_EQ(GenTexturesImmediate::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd) +
+            RoundSizeToMultipleOfEntries(cmd.n * 4),
+            cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLsizei>(11), cmd.n);
+  // TODO(gman): Check that ids were inserted;
+}
+
+TEST(GLES2FormatTest, GetActiveAttrib) {
+  GetActiveAttrib cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLuint>(11),
+      static_cast<GLuint>(12),
+      static_cast<GLsizei>(13),
+      static_cast<uint32>(14),
+      static_cast<uint32>(15),
+      static_cast<uint32>(16),
+      static_cast<uint32>(17),
+      static_cast<uint32>(18),
+      static_cast<uint32>(19),
+      static_cast<uint32>(20),
+      static_cast<uint32>(21));
+  EXPECT_EQ(GetActiveAttrib::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.program);
+  EXPECT_EQ(static_cast<GLuint>(12), cmd.index);
+  EXPECT_EQ(static_cast<GLsizei>(13), cmd.bufsize);
+  EXPECT_EQ(static_cast<uint32>(14), cmd.length_shm_id);
+  EXPECT_EQ(static_cast<uint32>(15), cmd.length_shm_offset);
+  EXPECT_EQ(static_cast<uint32>(16), cmd.size_shm_id);
+  EXPECT_EQ(static_cast<uint32>(17), cmd.size_shm_offset);
+  EXPECT_EQ(static_cast<uint32>(18), cmd.type_shm_id);
+  EXPECT_EQ(static_cast<uint32>(19), cmd.type_shm_offset);
+  EXPECT_EQ(static_cast<uint32>(20), cmd.name_shm_id);
+  EXPECT_EQ(static_cast<uint32>(21), cmd.name_shm_offset);
+}
+
+TEST(GLES2FormatTest, GetActiveUniform) {
+  GetActiveUniform cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLuint>(11),
+      static_cast<GLuint>(12),
+      static_cast<GLsizei>(13),
+      static_cast<uint32>(14),
+      static_cast<uint32>(15),
+      static_cast<uint32>(16),
+      static_cast<uint32>(17),
+      static_cast<uint32>(18),
+      static_cast<uint32>(19),
+      static_cast<uint32>(20),
+      static_cast<uint32>(21));
+  EXPECT_EQ(GetActiveUniform::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.program);
+  EXPECT_EQ(static_cast<GLuint>(12), cmd.index);
+  EXPECT_EQ(static_cast<GLsizei>(13), cmd.bufsize);
+  EXPECT_EQ(static_cast<uint32>(14), cmd.length_shm_id);
+  EXPECT_EQ(static_cast<uint32>(15), cmd.length_shm_offset);
+  EXPECT_EQ(static_cast<uint32>(16), cmd.size_shm_id);
+  EXPECT_EQ(static_cast<uint32>(17), cmd.size_shm_offset);
+  EXPECT_EQ(static_cast<uint32>(18), cmd.type_shm_id);
+  EXPECT_EQ(static_cast<uint32>(19), cmd.type_shm_offset);
+  EXPECT_EQ(static_cast<uint32>(20), cmd.name_shm_id);
+  EXPECT_EQ(static_cast<uint32>(21), cmd.name_shm_offset);
+}
+
+TEST(GLES2FormatTest, GetAttachedShaders) {
+  GetAttachedShaders cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLuint>(11),
+      static_cast<GLsizei>(12),
+      static_cast<uint32>(13),
+      static_cast<uint32>(14),
+      static_cast<uint32>(15),
+      static_cast<uint32>(16));
+  EXPECT_EQ(GetAttachedShaders::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.program);
+  EXPECT_EQ(static_cast<GLsizei>(12), cmd.maxcount);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.count_shm_id);
+  EXPECT_EQ(static_cast<uint32>(14), cmd.count_shm_offset);
+  EXPECT_EQ(static_cast<uint32>(15), cmd.shaders_shm_id);
+  EXPECT_EQ(static_cast<uint32>(16), cmd.shaders_shm_offset);
+}
+
+TEST(GLES2FormatTest, GetAttribLocation) {
+  GetAttribLocation cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLuint>(11),
+      static_cast<uint32>(12),
+      static_cast<uint32>(13),
+      static_cast<uint32>(14));
+  EXPECT_EQ(GetAttribLocation::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.program);
+  EXPECT_EQ(static_cast<uint32>(12), cmd.name_shm_id);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.name_shm_offset);
+  EXPECT_EQ(static_cast<uint32>(14), cmd.data_size);
+}
+
+TEST(GLES2FormatTest, GetAttribLocationImmediate) {
+  int8 buf[256] = { 0, };
+  GetAttribLocationImmediate& cmd =
+      *static_cast<GetAttribLocationImmediate*>(static_cast<void*>(&buf));
+  static const char* const test_str = "test string";
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLuint>(11),
+      test_str);
+  EXPECT_EQ(GetAttribLocationImmediate::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd) +  // NOLINT
+            RoundSizeToMultipleOfEntries(strlen(test_str)),
+            cmd.header.size * 4);
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.program);
+  // TODO(gman): check that string got copied.
+}
+
+TEST(GLES2FormatTest, GetBooleanv) {
+  GetBooleanv cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11),
+      static_cast<uint32>(12),
+      static_cast<uint32>(13));
+  EXPECT_EQ(GetBooleanv::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.pname);
+  EXPECT_EQ(static_cast<uint32>(12), cmd.params_shm_id);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.params_shm_offset);
+}
+
+TEST(GLES2FormatTest, GetBufferParameteriv) {
+  GetBufferParameteriv cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11),
+      static_cast<GLenum>(12),
+      static_cast<uint32>(13),
+      static_cast<uint32>(14));
+  EXPECT_EQ(GetBufferParameteriv::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.target);
+  EXPECT_EQ(static_cast<GLenum>(12), cmd.pname);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.params_shm_id);
+  EXPECT_EQ(static_cast<uint32>(14), cmd.params_shm_offset);
+}
+
+TEST(GLES2FormatTest, GetError) {
+  GetError cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<uint32>(11),
+      static_cast<uint32>(12));
+  EXPECT_EQ(GetError::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<uint32>(11), cmd.result_shm_id);
+  EXPECT_EQ(static_cast<uint32>(12), cmd.result_shm_offset);
+}
+
+TEST(GLES2FormatTest, GetFloatv) {
+  GetFloatv cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11),
+      static_cast<uint32>(12),
+      static_cast<uint32>(13));
+  EXPECT_EQ(GetFloatv::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.pname);
+  EXPECT_EQ(static_cast<uint32>(12), cmd.params_shm_id);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.params_shm_offset);
+}
+
+TEST(GLES2FormatTest, GetFramebufferAttachmentParameteriv) {
+  GetFramebufferAttachmentParameteriv cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11),
+      static_cast<GLenum>(12),
+      static_cast<GLenum>(13),
+      static_cast<uint32>(14),
+      static_cast<uint32>(15));
+  EXPECT_EQ(GetFramebufferAttachmentParameteriv::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.target);
+  EXPECT_EQ(static_cast<GLenum>(12), cmd.attachment);
+  EXPECT_EQ(static_cast<GLenum>(13), cmd.pname);
+  EXPECT_EQ(static_cast<uint32>(14), cmd.params_shm_id);
+  EXPECT_EQ(static_cast<uint32>(15), cmd.params_shm_offset);
+}
+
+TEST(GLES2FormatTest, GetIntegerv) {
+  GetIntegerv cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11),
+      static_cast<uint32>(12),
+      static_cast<uint32>(13));
+  EXPECT_EQ(GetIntegerv::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.pname);
+  EXPECT_EQ(static_cast<uint32>(12), cmd.params_shm_id);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.params_shm_offset);
+}
+
+TEST(GLES2FormatTest, GetProgramiv) {
+  GetProgramiv cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLuint>(11),
+      static_cast<GLenum>(12),
+      static_cast<uint32>(13),
+      static_cast<uint32>(14));
+  EXPECT_EQ(GetProgramiv::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.program);
+  EXPECT_EQ(static_cast<GLenum>(12), cmd.pname);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.params_shm_id);
+  EXPECT_EQ(static_cast<uint32>(14), cmd.params_shm_offset);
+}
+
+TEST(GLES2FormatTest, GetProgramInfoLog) {
+  GetProgramInfoLog cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLuint>(11),
+      static_cast<GLsizei>(12),
+      static_cast<uint32>(13),
+      static_cast<uint32>(14),
+      static_cast<uint32>(15),
+      static_cast<uint32>(16));
+  EXPECT_EQ(GetProgramInfoLog::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.program);
+  EXPECT_EQ(static_cast<GLsizei>(12), cmd.bufsize);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.length_shm_id);
+  EXPECT_EQ(static_cast<uint32>(14), cmd.length_shm_offset);
+  EXPECT_EQ(static_cast<uint32>(15), cmd.infolog_shm_id);
+  EXPECT_EQ(static_cast<uint32>(16), cmd.infolog_shm_offset);
+}
+
+TEST(GLES2FormatTest, GetRenderbufferParameteriv) {
+  GetRenderbufferParameteriv cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11),
+      static_cast<GLenum>(12),
+      static_cast<uint32>(13),
+      static_cast<uint32>(14));
+  EXPECT_EQ(GetRenderbufferParameteriv::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.target);
+  EXPECT_EQ(static_cast<GLenum>(12), cmd.pname);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.params_shm_id);
+  EXPECT_EQ(static_cast<uint32>(14), cmd.params_shm_offset);
+}
+
+TEST(GLES2FormatTest, GetShaderiv) {
+  GetShaderiv cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLuint>(11),
+      static_cast<GLenum>(12),
+      static_cast<uint32>(13),
+      static_cast<uint32>(14));
+  EXPECT_EQ(GetShaderiv::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.shader);
+  EXPECT_EQ(static_cast<GLenum>(12), cmd.pname);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.params_shm_id);
+  EXPECT_EQ(static_cast<uint32>(14), cmd.params_shm_offset);
+}
+
+TEST(GLES2FormatTest, GetShaderInfoLog) {
+  GetShaderInfoLog cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLuint>(11),
+      static_cast<GLsizei>(12),
+      static_cast<uint32>(13),
+      static_cast<uint32>(14),
+      static_cast<uint32>(15),
+      static_cast<uint32>(16));
+  EXPECT_EQ(GetShaderInfoLog::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.shader);
+  EXPECT_EQ(static_cast<GLsizei>(12), cmd.bufsize);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.length_shm_id);
+  EXPECT_EQ(static_cast<uint32>(14), cmd.length_shm_offset);
+  EXPECT_EQ(static_cast<uint32>(15), cmd.infolog_shm_id);
+  EXPECT_EQ(static_cast<uint32>(16), cmd.infolog_shm_offset);
+}
+
+TEST(GLES2FormatTest, GetShaderPrecisionFormat) {
+  GetShaderPrecisionFormat cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11),
+      static_cast<GLenum>(12),
+      static_cast<uint32>(13),
+      static_cast<uint32>(14),
+      static_cast<uint32>(15),
+      static_cast<uint32>(16));
+  EXPECT_EQ(GetShaderPrecisionFormat::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.shadertype);
+  EXPECT_EQ(static_cast<GLenum>(12), cmd.precisiontype);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.range_shm_id);
+  EXPECT_EQ(static_cast<uint32>(14), cmd.range_shm_offset);
+  EXPECT_EQ(static_cast<uint32>(15), cmd.precision_shm_id);
+  EXPECT_EQ(static_cast<uint32>(16), cmd.precision_shm_offset);
+}
+
+TEST(GLES2FormatTest, GetShaderSource) {
+  GetShaderSource cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLuint>(11),
+      static_cast<GLsizei>(12),
+      static_cast<uint32>(13),
+      static_cast<uint32>(14),
+      static_cast<uint32>(15),
+      static_cast<uint32>(16));
+  EXPECT_EQ(GetShaderSource::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.shader);
+  EXPECT_EQ(static_cast<GLsizei>(12), cmd.bufsize);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.length_shm_id);
+  EXPECT_EQ(static_cast<uint32>(14), cmd.length_shm_offset);
+  EXPECT_EQ(static_cast<uint32>(15), cmd.source_shm_id);
+  EXPECT_EQ(static_cast<uint32>(16), cmd.source_shm_offset);
+}
+
+TEST(GLES2FormatTest, GetString) {
+  GetString cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11));
+  EXPECT_EQ(GetString::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.name);
+}
+
+TEST(GLES2FormatTest, GetTexParameterfv) {
+  GetTexParameterfv cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11),
+      static_cast<GLenum>(12),
+      static_cast<uint32>(13),
+      static_cast<uint32>(14));
+  EXPECT_EQ(GetTexParameterfv::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.target);
+  EXPECT_EQ(static_cast<GLenum>(12), cmd.pname);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.params_shm_id);
+  EXPECT_EQ(static_cast<uint32>(14), cmd.params_shm_offset);
+}
+
+TEST(GLES2FormatTest, GetTexParameteriv) {
+  GetTexParameteriv cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11),
+      static_cast<GLenum>(12),
+      static_cast<uint32>(13),
+      static_cast<uint32>(14));
+  EXPECT_EQ(GetTexParameteriv::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.target);
+  EXPECT_EQ(static_cast<GLenum>(12), cmd.pname);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.params_shm_id);
+  EXPECT_EQ(static_cast<uint32>(14), cmd.params_shm_offset);
+}
+
+TEST(GLES2FormatTest, GetUniformfv) {
+  GetUniformfv cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLuint>(11),
+      static_cast<GLint>(12),
+      static_cast<uint32>(13),
+      static_cast<uint32>(14));
+  EXPECT_EQ(GetUniformfv::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.program);
+  EXPECT_EQ(static_cast<GLint>(12), cmd.location);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.params_shm_id);
+  EXPECT_EQ(static_cast<uint32>(14), cmd.params_shm_offset);
+}
+
+TEST(GLES2FormatTest, GetUniformiv) {
+  GetUniformiv cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLuint>(11),
+      static_cast<GLint>(12),
+      static_cast<uint32>(13),
+      static_cast<uint32>(14));
+  EXPECT_EQ(GetUniformiv::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.program);
+  EXPECT_EQ(static_cast<GLint>(12), cmd.location);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.params_shm_id);
+  EXPECT_EQ(static_cast<uint32>(14), cmd.params_shm_offset);
+}
+
+TEST(GLES2FormatTest, GetUniformLocation) {
+  GetUniformLocation cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLuint>(11),
+      static_cast<uint32>(12),
+      static_cast<uint32>(13),
+      static_cast<uint32>(14));
+  EXPECT_EQ(GetUniformLocation::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.program);
+  EXPECT_EQ(static_cast<uint32>(12), cmd.name_shm_id);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.name_shm_offset);
+  EXPECT_EQ(static_cast<uint32>(14), cmd.data_size);
+}
+
+TEST(GLES2FormatTest, GetUniformLocationImmediate) {
+  int8 buf[256] = { 0, };
+  GetUniformLocationImmediate& cmd =
+      *static_cast<GetUniformLocationImmediate*>(static_cast<void*>(&buf));
+  static const char* const test_str = "test string";
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLuint>(11),
+      test_str);
+  EXPECT_EQ(GetUniformLocationImmediate::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd) +  // NOLINT
+            RoundSizeToMultipleOfEntries(strlen(test_str)),
+            cmd.header.size * 4);
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.program);
+  // TODO(gman): check that string got copied.
+}
+
+TEST(GLES2FormatTest, GetVertexAttribfv) {
+  GetVertexAttribfv cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLuint>(11),
+      static_cast<GLenum>(12),
+      static_cast<uint32>(13),
+      static_cast<uint32>(14));
+  EXPECT_EQ(GetVertexAttribfv::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.index);
+  EXPECT_EQ(static_cast<GLenum>(12), cmd.pname);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.params_shm_id);
+  EXPECT_EQ(static_cast<uint32>(14), cmd.params_shm_offset);
+}
+
+TEST(GLES2FormatTest, GetVertexAttribiv) {
+  GetVertexAttribiv cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLuint>(11),
+      static_cast<GLenum>(12),
+      static_cast<uint32>(13),
+      static_cast<uint32>(14));
+  EXPECT_EQ(GetVertexAttribiv::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.index);
+  EXPECT_EQ(static_cast<GLenum>(12), cmd.pname);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.params_shm_id);
+  EXPECT_EQ(static_cast<uint32>(14), cmd.params_shm_offset);
+}
+
+TEST(GLES2FormatTest, GetVertexAttribPointerv) {
+  GetVertexAttribPointerv cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLuint>(11),
+      static_cast<GLenum>(12),
+      static_cast<uint32>(13),
+      static_cast<uint32>(14));
+  EXPECT_EQ(GetVertexAttribPointerv::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.index);
+  EXPECT_EQ(static_cast<GLenum>(12), cmd.pname);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.pointer_shm_id);
+  EXPECT_EQ(static_cast<uint32>(14), cmd.pointer_shm_offset);
+}
+
+TEST(GLES2FormatTest, Hint) {
+  Hint cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11),
+      static_cast<GLenum>(12));
+  EXPECT_EQ(Hint::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.target);
+  EXPECT_EQ(static_cast<GLenum>(12), cmd.mode);
+}
+
+TEST(GLES2FormatTest, IsBuffer) {
+  IsBuffer cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLuint>(11),
+      static_cast<uint32>(12),
+      static_cast<uint32>(13));
+  EXPECT_EQ(IsBuffer::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.buffer);
+  EXPECT_EQ(static_cast<uint32>(12), cmd.result_shm_id);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.result_shm_offset);
+}
+
+TEST(GLES2FormatTest, IsEnabled) {
+  IsEnabled cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11),
+      static_cast<uint32>(12),
+      static_cast<uint32>(13));
+  EXPECT_EQ(IsEnabled::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.cap);
+  EXPECT_EQ(static_cast<uint32>(12), cmd.result_shm_id);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.result_shm_offset);
+}
+
+TEST(GLES2FormatTest, IsFramebuffer) {
+  IsFramebuffer cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLuint>(11),
+      static_cast<uint32>(12),
+      static_cast<uint32>(13));
+  EXPECT_EQ(IsFramebuffer::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.framebuffer);
+  EXPECT_EQ(static_cast<uint32>(12), cmd.result_shm_id);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.result_shm_offset);
+}
+
+TEST(GLES2FormatTest, IsProgram) {
+  IsProgram cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLuint>(11),
+      static_cast<uint32>(12),
+      static_cast<uint32>(13));
+  EXPECT_EQ(IsProgram::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.program);
+  EXPECT_EQ(static_cast<uint32>(12), cmd.result_shm_id);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.result_shm_offset);
+}
+
+TEST(GLES2FormatTest, IsRenderbuffer) {
+  IsRenderbuffer cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLuint>(11),
+      static_cast<uint32>(12),
+      static_cast<uint32>(13));
+  EXPECT_EQ(IsRenderbuffer::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.renderbuffer);
+  EXPECT_EQ(static_cast<uint32>(12), cmd.result_shm_id);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.result_shm_offset);
+}
+
+TEST(GLES2FormatTest, IsShader) {
+  IsShader cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLuint>(11),
+      static_cast<uint32>(12),
+      static_cast<uint32>(13));
+  EXPECT_EQ(IsShader::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.shader);
+  EXPECT_EQ(static_cast<uint32>(12), cmd.result_shm_id);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.result_shm_offset);
+}
+
+TEST(GLES2FormatTest, IsTexture) {
+  IsTexture cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLuint>(11),
+      static_cast<uint32>(12),
+      static_cast<uint32>(13));
+  EXPECT_EQ(IsTexture::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.texture);
+  EXPECT_EQ(static_cast<uint32>(12), cmd.result_shm_id);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.result_shm_offset);
+}
+
+TEST(GLES2FormatTest, LineWidth) {
+  LineWidth cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLfloat>(11));
+  EXPECT_EQ(LineWidth::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLfloat>(11), cmd.width);
+}
+
+TEST(GLES2FormatTest, LinkProgram) {
+  LinkProgram cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLuint>(11));
+  EXPECT_EQ(LinkProgram::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.program);
+}
+
+TEST(GLES2FormatTest, PixelStorei) {
+  PixelStorei cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11),
+      static_cast<GLint>(12));
+  EXPECT_EQ(PixelStorei::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.pname);
+  EXPECT_EQ(static_cast<GLint>(12), cmd.param);
+}
+
+TEST(GLES2FormatTest, PolygonOffset) {
+  PolygonOffset cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLfloat>(11),
+      static_cast<GLfloat>(12));
+  EXPECT_EQ(PolygonOffset::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLfloat>(11), cmd.factor);
+  EXPECT_EQ(static_cast<GLfloat>(12), cmd.units);
+}
+
+TEST(GLES2FormatTest, ReadPixels) {
+  ReadPixels cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLint>(11),
+      static_cast<GLint>(12),
+      static_cast<GLsizei>(13),
+      static_cast<GLsizei>(14),
+      static_cast<GLenum>(15),
+      static_cast<GLenum>(16),
+      static_cast<uint32>(17),
+      static_cast<uint32>(18));
+  EXPECT_EQ(ReadPixels::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLint>(11), cmd.x);
+  EXPECT_EQ(static_cast<GLint>(12), cmd.y);
+  EXPECT_EQ(static_cast<GLsizei>(13), cmd.width);
+  EXPECT_EQ(static_cast<GLsizei>(14), cmd.height);
+  EXPECT_EQ(static_cast<GLenum>(15), cmd.format);
+  EXPECT_EQ(static_cast<GLenum>(16), cmd.type);
+  EXPECT_EQ(static_cast<uint32>(17), cmd.pixels_shm_id);
+  EXPECT_EQ(static_cast<uint32>(18), cmd.pixels_shm_offset);
+}
+
+TEST(GLES2FormatTest, RenderbufferStorage) {
+  RenderbufferStorage cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11),
+      static_cast<GLenum>(12),
+      static_cast<GLsizei>(13),
+      static_cast<GLsizei>(14));
+  EXPECT_EQ(RenderbufferStorage::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.target);
+  EXPECT_EQ(static_cast<GLenum>(12), cmd.internalformat);
+  EXPECT_EQ(static_cast<GLsizei>(13), cmd.width);
+  EXPECT_EQ(static_cast<GLsizei>(14), cmd.height);
+}
+
+TEST(GLES2FormatTest, SampleCoverage) {
+  SampleCoverage cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLclampf>(11),
+      static_cast<GLboolean>(12));
+  EXPECT_EQ(SampleCoverage::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLclampf>(11), cmd.value);
+  EXPECT_EQ(static_cast<GLboolean>(12), cmd.invert);
+}
+
+TEST(GLES2FormatTest, Scissor) {
+  Scissor cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLint>(11),
+      static_cast<GLint>(12),
+      static_cast<GLsizei>(13),
+      static_cast<GLsizei>(14));
+  EXPECT_EQ(Scissor::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLint>(11), cmd.x);
+  EXPECT_EQ(static_cast<GLint>(12), cmd.y);
+  EXPECT_EQ(static_cast<GLsizei>(13), cmd.width);
+  EXPECT_EQ(static_cast<GLsizei>(14), cmd.height);
+}
+
+TEST(GLES2FormatTest, ShaderSource) {
+  ShaderSource cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLuint>(11),
+      static_cast<GLsizei>(12),
+      static_cast<uint32>(13),
+      static_cast<uint32>(14),
+      static_cast<uint32>(15));
+  EXPECT_EQ(ShaderSource::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.shader);
+  EXPECT_EQ(static_cast<GLsizei>(12), cmd.count);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.data_shm_id);
+  EXPECT_EQ(static_cast<uint32>(14), cmd.data_shm_offset);
+  EXPECT_EQ(static_cast<uint32>(15), cmd.data_size);
+}
+
+// TODO(gman): Implement test for ShaderSourceImmediate
+TEST(GLES2FormatTest, StencilFunc) {
+  StencilFunc cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11),
+      static_cast<GLint>(12),
+      static_cast<GLuint>(13));
+  EXPECT_EQ(StencilFunc::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.func);
+  EXPECT_EQ(static_cast<GLint>(12), cmd.ref);
+  EXPECT_EQ(static_cast<GLuint>(13), cmd.mask);
+}
+
+TEST(GLES2FormatTest, StencilFuncSeparate) {
+  StencilFuncSeparate cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11),
+      static_cast<GLenum>(12),
+      static_cast<GLint>(13),
+      static_cast<GLuint>(14));
+  EXPECT_EQ(StencilFuncSeparate::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.face);
+  EXPECT_EQ(static_cast<GLenum>(12), cmd.func);
+  EXPECT_EQ(static_cast<GLint>(13), cmd.ref);
+  EXPECT_EQ(static_cast<GLuint>(14), cmd.mask);
+}
+
+TEST(GLES2FormatTest, StencilMask) {
+  StencilMask cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLuint>(11));
+  EXPECT_EQ(StencilMask::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.mask);
+}
+
+TEST(GLES2FormatTest, StencilMaskSeparate) {
+  StencilMaskSeparate cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11),
+      static_cast<GLuint>(12));
+  EXPECT_EQ(StencilMaskSeparate::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.face);
+  EXPECT_EQ(static_cast<GLuint>(12), cmd.mask);
+}
+
+TEST(GLES2FormatTest, StencilOp) {
+  StencilOp cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11),
+      static_cast<GLenum>(12),
+      static_cast<GLenum>(13));
+  EXPECT_EQ(StencilOp::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.fail);
+  EXPECT_EQ(static_cast<GLenum>(12), cmd.zfail);
+  EXPECT_EQ(static_cast<GLenum>(13), cmd.zpass);
+}
+
+TEST(GLES2FormatTest, StencilOpSeparate) {
+  StencilOpSeparate cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11),
+      static_cast<GLenum>(12),
+      static_cast<GLenum>(13),
+      static_cast<GLenum>(14));
+  EXPECT_EQ(StencilOpSeparate::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.face);
+  EXPECT_EQ(static_cast<GLenum>(12), cmd.fail);
+  EXPECT_EQ(static_cast<GLenum>(13), cmd.zfail);
+  EXPECT_EQ(static_cast<GLenum>(14), cmd.zpass);
+}
+
+TEST(GLES2FormatTest, TexImage2D) {
+  TexImage2D cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11),
+      static_cast<GLint>(12),
+      static_cast<GLint>(13),
+      static_cast<GLsizei>(14),
+      static_cast<GLsizei>(15),
+      static_cast<GLint>(16),
+      static_cast<GLenum>(17),
+      static_cast<GLenum>(18),
+      static_cast<uint32>(19),
+      static_cast<uint32>(20));
+  EXPECT_EQ(TexImage2D::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.target);
+  EXPECT_EQ(static_cast<GLint>(12), cmd.level);
+  EXPECT_EQ(static_cast<GLint>(13), cmd.internalformat);
+  EXPECT_EQ(static_cast<GLsizei>(14), cmd.width);
+  EXPECT_EQ(static_cast<GLsizei>(15), cmd.height);
+  EXPECT_EQ(static_cast<GLint>(16), cmd.border);
+  EXPECT_EQ(static_cast<GLenum>(17), cmd.format);
+  EXPECT_EQ(static_cast<GLenum>(18), cmd.type);
+  EXPECT_EQ(static_cast<uint32>(19), cmd.pixels_shm_id);
+  EXPECT_EQ(static_cast<uint32>(20), cmd.pixels_shm_offset);
+}
+
+// TODO(gman): Implement test for TexImage2DImmediate
+TEST(GLES2FormatTest, TexParameterf) {
+  TexParameterf cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11),
+      static_cast<GLenum>(12),
+      static_cast<GLfloat>(13));
+  EXPECT_EQ(TexParameterf::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.target);
+  EXPECT_EQ(static_cast<GLenum>(12), cmd.pname);
+  EXPECT_EQ(static_cast<GLfloat>(13), cmd.param);
+}
+
+TEST(GLES2FormatTest, TexParameterfv) {
+  TexParameterfv cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11),
+      static_cast<GLenum>(12),
+      static_cast<uint32>(13),
+      static_cast<uint32>(14));
+  EXPECT_EQ(TexParameterfv::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.target);
+  EXPECT_EQ(static_cast<GLenum>(12), cmd.pname);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.params_shm_id);
+  EXPECT_EQ(static_cast<uint32>(14), cmd.params_shm_offset);
+}
+
+TEST(GLES2FormatTest, TexParameterfvImmediate) {
+  const int kSomeBaseValueToTestWith = 51;
+  static GLfloat data[] = {
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 0),
+  };
+  int8 buf[256] = { 0, };
+  TexParameterfvImmediate& cmd =
+      *static_cast<TexParameterfvImmediate*>(static_cast<void*>(&buf));
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11),
+      static_cast<GLenum>(12),
+      data);
+  EXPECT_EQ(TexParameterfvImmediate::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd) +
+            RoundSizeToMultipleOfEntries(sizeof(data)),
+            cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.target);
+  EXPECT_EQ(static_cast<GLenum>(12), cmd.pname);
+  // TODO(gman): Check that data was inserted;
+}
+
+TEST(GLES2FormatTest, TexParameteri) {
+  TexParameteri cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11),
+      static_cast<GLenum>(12),
+      static_cast<GLint>(13));
+  EXPECT_EQ(TexParameteri::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.target);
+  EXPECT_EQ(static_cast<GLenum>(12), cmd.pname);
+  EXPECT_EQ(static_cast<GLint>(13), cmd.param);
+}
+
+TEST(GLES2FormatTest, TexParameteriv) {
+  TexParameteriv cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11),
+      static_cast<GLenum>(12),
+      static_cast<uint32>(13),
+      static_cast<uint32>(14));
+  EXPECT_EQ(TexParameteriv::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.target);
+  EXPECT_EQ(static_cast<GLenum>(12), cmd.pname);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.params_shm_id);
+  EXPECT_EQ(static_cast<uint32>(14), cmd.params_shm_offset);
+}
+
+TEST(GLES2FormatTest, TexParameterivImmediate) {
+  const int kSomeBaseValueToTestWith = 51;
+  static GLint data[] = {
+    static_cast<GLint>(kSomeBaseValueToTestWith + 0),
+  };
+  int8 buf[256] = { 0, };
+  TexParameterivImmediate& cmd =
+      *static_cast<TexParameterivImmediate*>(static_cast<void*>(&buf));
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11),
+      static_cast<GLenum>(12),
+      data);
+  EXPECT_EQ(TexParameterivImmediate::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd) +
+            RoundSizeToMultipleOfEntries(sizeof(data)),
+            cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.target);
+  EXPECT_EQ(static_cast<GLenum>(12), cmd.pname);
+  // TODO(gman): Check that data was inserted;
+}
+
+TEST(GLES2FormatTest, TexSubImage2D) {
+  TexSubImage2D cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLenum>(11),
+      static_cast<GLint>(12),
+      static_cast<GLint>(13),
+      static_cast<GLint>(14),
+      static_cast<GLsizei>(15),
+      static_cast<GLsizei>(16),
+      static_cast<GLenum>(17),
+      static_cast<GLenum>(18),
+      static_cast<uint32>(19),
+      static_cast<uint32>(20));
+  EXPECT_EQ(TexSubImage2D::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.target);
+  EXPECT_EQ(static_cast<GLint>(12), cmd.level);
+  EXPECT_EQ(static_cast<GLint>(13), cmd.xoffset);
+  EXPECT_EQ(static_cast<GLint>(14), cmd.yoffset);
+  EXPECT_EQ(static_cast<GLsizei>(15), cmd.width);
+  EXPECT_EQ(static_cast<GLsizei>(16), cmd.height);
+  EXPECT_EQ(static_cast<GLenum>(17), cmd.format);
+  EXPECT_EQ(static_cast<GLenum>(18), cmd.type);
+  EXPECT_EQ(static_cast<uint32>(19), cmd.pixels_shm_id);
+  EXPECT_EQ(static_cast<uint32>(20), cmd.pixels_shm_offset);
+}
+
+// TODO(gman): Implement test for TexSubImage2DImmediate
+TEST(GLES2FormatTest, Uniform1f) {
+  Uniform1f cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLint>(11),
+      static_cast<GLfloat>(12));
+  EXPECT_EQ(Uniform1f::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLint>(11), cmd.location);
+  EXPECT_EQ(static_cast<GLfloat>(12), cmd.x);
+}
+
+TEST(GLES2FormatTest, Uniform1fv) {
+  Uniform1fv cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLint>(11),
+      static_cast<GLsizei>(12),
+      static_cast<uint32>(13),
+      static_cast<uint32>(14));
+  EXPECT_EQ(Uniform1fv::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLint>(11), cmd.location);
+  EXPECT_EQ(static_cast<GLsizei>(12), cmd.count);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.v_shm_id);
+  EXPECT_EQ(static_cast<uint32>(14), cmd.v_shm_offset);
+}
+
+TEST(GLES2FormatTest, Uniform1fvImmediate) {
+  const int kSomeBaseValueToTestWith = 51;
+  static GLfloat data[] = {
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 0),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 1),
+  };
+  int8 buf[256] = { 0, };
+  Uniform1fvImmediate& cmd =
+      *static_cast<Uniform1fvImmediate*>(static_cast<void*>(&buf));
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLint>(1),
+      static_cast<GLsizei>(2),
+      data);
+  EXPECT_EQ(Uniform1fvImmediate::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd) +
+            RoundSizeToMultipleOfEntries(sizeof(data)),
+            cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLint>(1), cmd.location);
+  EXPECT_EQ(static_cast<GLsizei>(2), cmd.count);
+  // TODO(gman): Check that data was inserted;
+}
+
+TEST(GLES2FormatTest, Uniform1i) {
+  Uniform1i cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLint>(11),
+      static_cast<GLint>(12));
+  EXPECT_EQ(Uniform1i::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLint>(11), cmd.location);
+  EXPECT_EQ(static_cast<GLint>(12), cmd.x);
+}
+
+TEST(GLES2FormatTest, Uniform1iv) {
+  Uniform1iv cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLint>(11),
+      static_cast<GLsizei>(12),
+      static_cast<uint32>(13),
+      static_cast<uint32>(14));
+  EXPECT_EQ(Uniform1iv::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLint>(11), cmd.location);
+  EXPECT_EQ(static_cast<GLsizei>(12), cmd.count);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.v_shm_id);
+  EXPECT_EQ(static_cast<uint32>(14), cmd.v_shm_offset);
+}
+
+TEST(GLES2FormatTest, Uniform1ivImmediate) {
+  const int kSomeBaseValueToTestWith = 51;
+  static GLint data[] = {
+    static_cast<GLint>(kSomeBaseValueToTestWith + 0),
+    static_cast<GLint>(kSomeBaseValueToTestWith + 1),
+  };
+  int8 buf[256] = { 0, };
+  Uniform1ivImmediate& cmd =
+      *static_cast<Uniform1ivImmediate*>(static_cast<void*>(&buf));
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLint>(1),
+      static_cast<GLsizei>(2),
+      data);
+  EXPECT_EQ(Uniform1ivImmediate::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd) +
+            RoundSizeToMultipleOfEntries(sizeof(data)),
+            cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLint>(1), cmd.location);
+  EXPECT_EQ(static_cast<GLsizei>(2), cmd.count);
+  // TODO(gman): Check that data was inserted;
+}
+
+TEST(GLES2FormatTest, Uniform2f) {
+  Uniform2f cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLint>(11),
+      static_cast<GLfloat>(12),
+      static_cast<GLfloat>(13));
+  EXPECT_EQ(Uniform2f::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLint>(11), cmd.location);
+  EXPECT_EQ(static_cast<GLfloat>(12), cmd.x);
+  EXPECT_EQ(static_cast<GLfloat>(13), cmd.y);
+}
+
+TEST(GLES2FormatTest, Uniform2fv) {
+  Uniform2fv cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLint>(11),
+      static_cast<GLsizei>(12),
+      static_cast<uint32>(13),
+      static_cast<uint32>(14));
+  EXPECT_EQ(Uniform2fv::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLint>(11), cmd.location);
+  EXPECT_EQ(static_cast<GLsizei>(12), cmd.count);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.v_shm_id);
+  EXPECT_EQ(static_cast<uint32>(14), cmd.v_shm_offset);
+}
+
+TEST(GLES2FormatTest, Uniform2fvImmediate) {
+  const int kSomeBaseValueToTestWith = 51;
+  static GLfloat data[] = {
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 0),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 1),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 2),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 3),
+  };
+  int8 buf[256] = { 0, };
+  Uniform2fvImmediate& cmd =
+      *static_cast<Uniform2fvImmediate*>(static_cast<void*>(&buf));
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLint>(1),
+      static_cast<GLsizei>(2),
+      data);
+  EXPECT_EQ(Uniform2fvImmediate::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd) +
+            RoundSizeToMultipleOfEntries(sizeof(data)),
+            cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLint>(1), cmd.location);
+  EXPECT_EQ(static_cast<GLsizei>(2), cmd.count);
+  // TODO(gman): Check that data was inserted;
+}
+
+TEST(GLES2FormatTest, Uniform2i) {
+  Uniform2i cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLint>(11),
+      static_cast<GLint>(12),
+      static_cast<GLint>(13));
+  EXPECT_EQ(Uniform2i::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLint>(11), cmd.location);
+  EXPECT_EQ(static_cast<GLint>(12), cmd.x);
+  EXPECT_EQ(static_cast<GLint>(13), cmd.y);
+}
+
+TEST(GLES2FormatTest, Uniform2iv) {
+  Uniform2iv cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLint>(11),
+      static_cast<GLsizei>(12),
+      static_cast<uint32>(13),
+      static_cast<uint32>(14));
+  EXPECT_EQ(Uniform2iv::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLint>(11), cmd.location);
+  EXPECT_EQ(static_cast<GLsizei>(12), cmd.count);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.v_shm_id);
+  EXPECT_EQ(static_cast<uint32>(14), cmd.v_shm_offset);
+}
+
+TEST(GLES2FormatTest, Uniform2ivImmediate) {
+  const int kSomeBaseValueToTestWith = 51;
+  static GLint data[] = {
+    static_cast<GLint>(kSomeBaseValueToTestWith + 0),
+    static_cast<GLint>(kSomeBaseValueToTestWith + 1),
+    static_cast<GLint>(kSomeBaseValueToTestWith + 2),
+    static_cast<GLint>(kSomeBaseValueToTestWith + 3),
+  };
+  int8 buf[256] = { 0, };
+  Uniform2ivImmediate& cmd =
+      *static_cast<Uniform2ivImmediate*>(static_cast<void*>(&buf));
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLint>(1),
+      static_cast<GLsizei>(2),
+      data);
+  EXPECT_EQ(Uniform2ivImmediate::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd) +
+            RoundSizeToMultipleOfEntries(sizeof(data)),
+            cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLint>(1), cmd.location);
+  EXPECT_EQ(static_cast<GLsizei>(2), cmd.count);
+  // TODO(gman): Check that data was inserted;
+}
+
+TEST(GLES2FormatTest, Uniform3f) {
+  Uniform3f cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLint>(11),
+      static_cast<GLfloat>(12),
+      static_cast<GLfloat>(13),
+      static_cast<GLfloat>(14));
+  EXPECT_EQ(Uniform3f::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLint>(11), cmd.location);
+  EXPECT_EQ(static_cast<GLfloat>(12), cmd.x);
+  EXPECT_EQ(static_cast<GLfloat>(13), cmd.y);
+  EXPECT_EQ(static_cast<GLfloat>(14), cmd.z);
+}
+
+TEST(GLES2FormatTest, Uniform3fv) {
+  Uniform3fv cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLint>(11),
+      static_cast<GLsizei>(12),
+      static_cast<uint32>(13),
+      static_cast<uint32>(14));
+  EXPECT_EQ(Uniform3fv::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLint>(11), cmd.location);
+  EXPECT_EQ(static_cast<GLsizei>(12), cmd.count);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.v_shm_id);
+  EXPECT_EQ(static_cast<uint32>(14), cmd.v_shm_offset);
+}
+
+TEST(GLES2FormatTest, Uniform3fvImmediate) {
+  const int kSomeBaseValueToTestWith = 51;
+  static GLfloat data[] = {
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 0),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 1),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 2),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 3),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 4),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 5),
+  };
+  int8 buf[256] = { 0, };
+  Uniform3fvImmediate& cmd =
+      *static_cast<Uniform3fvImmediate*>(static_cast<void*>(&buf));
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLint>(1),
+      static_cast<GLsizei>(2),
+      data);
+  EXPECT_EQ(Uniform3fvImmediate::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd) +
+            RoundSizeToMultipleOfEntries(sizeof(data)),
+            cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLint>(1), cmd.location);
+  EXPECT_EQ(static_cast<GLsizei>(2), cmd.count);
+  // TODO(gman): Check that data was inserted;
+}
+
+TEST(GLES2FormatTest, Uniform3i) {
+  Uniform3i cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLint>(11),
+      static_cast<GLint>(12),
+      static_cast<GLint>(13),
+      static_cast<GLint>(14));
+  EXPECT_EQ(Uniform3i::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLint>(11), cmd.location);
+  EXPECT_EQ(static_cast<GLint>(12), cmd.x);
+  EXPECT_EQ(static_cast<GLint>(13), cmd.y);
+  EXPECT_EQ(static_cast<GLint>(14), cmd.z);
+}
+
+TEST(GLES2FormatTest, Uniform3iv) {
+  Uniform3iv cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLint>(11),
+      static_cast<GLsizei>(12),
+      static_cast<uint32>(13),
+      static_cast<uint32>(14));
+  EXPECT_EQ(Uniform3iv::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLint>(11), cmd.location);
+  EXPECT_EQ(static_cast<GLsizei>(12), cmd.count);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.v_shm_id);
+  EXPECT_EQ(static_cast<uint32>(14), cmd.v_shm_offset);
+}
+
+TEST(GLES2FormatTest, Uniform3ivImmediate) {
+  const int kSomeBaseValueToTestWith = 51;
+  static GLint data[] = {
+    static_cast<GLint>(kSomeBaseValueToTestWith + 0),
+    static_cast<GLint>(kSomeBaseValueToTestWith + 1),
+    static_cast<GLint>(kSomeBaseValueToTestWith + 2),
+    static_cast<GLint>(kSomeBaseValueToTestWith + 3),
+    static_cast<GLint>(kSomeBaseValueToTestWith + 4),
+    static_cast<GLint>(kSomeBaseValueToTestWith + 5),
+  };
+  int8 buf[256] = { 0, };
+  Uniform3ivImmediate& cmd =
+      *static_cast<Uniform3ivImmediate*>(static_cast<void*>(&buf));
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLint>(1),
+      static_cast<GLsizei>(2),
+      data);
+  EXPECT_EQ(Uniform3ivImmediate::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd) +
+            RoundSizeToMultipleOfEntries(sizeof(data)),
+            cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLint>(1), cmd.location);
+  EXPECT_EQ(static_cast<GLsizei>(2), cmd.count);
+  // TODO(gman): Check that data was inserted;
+}
+
+TEST(GLES2FormatTest, Uniform4f) {
+  Uniform4f cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLint>(11),
+      static_cast<GLfloat>(12),
+      static_cast<GLfloat>(13),
+      static_cast<GLfloat>(14),
+      static_cast<GLfloat>(15));
+  EXPECT_EQ(Uniform4f::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLint>(11), cmd.location);
+  EXPECT_EQ(static_cast<GLfloat>(12), cmd.x);
+  EXPECT_EQ(static_cast<GLfloat>(13), cmd.y);
+  EXPECT_EQ(static_cast<GLfloat>(14), cmd.z);
+  EXPECT_EQ(static_cast<GLfloat>(15), cmd.w);
+}
+
+TEST(GLES2FormatTest, Uniform4fv) {
+  Uniform4fv cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLint>(11),
+      static_cast<GLsizei>(12),
+      static_cast<uint32>(13),
+      static_cast<uint32>(14));
+  EXPECT_EQ(Uniform4fv::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLint>(11), cmd.location);
+  EXPECT_EQ(static_cast<GLsizei>(12), cmd.count);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.v_shm_id);
+  EXPECT_EQ(static_cast<uint32>(14), cmd.v_shm_offset);
+}
+
+TEST(GLES2FormatTest, Uniform4fvImmediate) {
+  const int kSomeBaseValueToTestWith = 51;
+  static GLfloat data[] = {
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 0),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 1),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 2),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 3),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 4),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 5),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 6),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 7),
+  };
+  int8 buf[256] = { 0, };
+  Uniform4fvImmediate& cmd =
+      *static_cast<Uniform4fvImmediate*>(static_cast<void*>(&buf));
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLint>(1),
+      static_cast<GLsizei>(2),
+      data);
+  EXPECT_EQ(Uniform4fvImmediate::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd) +
+            RoundSizeToMultipleOfEntries(sizeof(data)),
+            cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLint>(1), cmd.location);
+  EXPECT_EQ(static_cast<GLsizei>(2), cmd.count);
+  // TODO(gman): Check that data was inserted;
+}
+
+TEST(GLES2FormatTest, Uniform4i) {
+  Uniform4i cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLint>(11),
+      static_cast<GLint>(12),
+      static_cast<GLint>(13),
+      static_cast<GLint>(14),
+      static_cast<GLint>(15));
+  EXPECT_EQ(Uniform4i::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLint>(11), cmd.location);
+  EXPECT_EQ(static_cast<GLint>(12), cmd.x);
+  EXPECT_EQ(static_cast<GLint>(13), cmd.y);
+  EXPECT_EQ(static_cast<GLint>(14), cmd.z);
+  EXPECT_EQ(static_cast<GLint>(15), cmd.w);
+}
+
+TEST(GLES2FormatTest, Uniform4iv) {
+  Uniform4iv cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLint>(11),
+      static_cast<GLsizei>(12),
+      static_cast<uint32>(13),
+      static_cast<uint32>(14));
+  EXPECT_EQ(Uniform4iv::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLint>(11), cmd.location);
+  EXPECT_EQ(static_cast<GLsizei>(12), cmd.count);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.v_shm_id);
+  EXPECT_EQ(static_cast<uint32>(14), cmd.v_shm_offset);
+}
+
+TEST(GLES2FormatTest, Uniform4ivImmediate) {
+  const int kSomeBaseValueToTestWith = 51;
+  static GLint data[] = {
+    static_cast<GLint>(kSomeBaseValueToTestWith + 0),
+    static_cast<GLint>(kSomeBaseValueToTestWith + 1),
+    static_cast<GLint>(kSomeBaseValueToTestWith + 2),
+    static_cast<GLint>(kSomeBaseValueToTestWith + 3),
+    static_cast<GLint>(kSomeBaseValueToTestWith + 4),
+    static_cast<GLint>(kSomeBaseValueToTestWith + 5),
+    static_cast<GLint>(kSomeBaseValueToTestWith + 6),
+    static_cast<GLint>(kSomeBaseValueToTestWith + 7),
+  };
+  int8 buf[256] = { 0, };
+  Uniform4ivImmediate& cmd =
+      *static_cast<Uniform4ivImmediate*>(static_cast<void*>(&buf));
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLint>(1),
+      static_cast<GLsizei>(2),
+      data);
+  EXPECT_EQ(Uniform4ivImmediate::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd) +
+            RoundSizeToMultipleOfEntries(sizeof(data)),
+            cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLint>(1), cmd.location);
+  EXPECT_EQ(static_cast<GLsizei>(2), cmd.count);
+  // TODO(gman): Check that data was inserted;
+}
+
+TEST(GLES2FormatTest, UniformMatrix2fv) {
+  UniformMatrix2fv cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLint>(11),
+      static_cast<GLsizei>(12),
+      static_cast<GLboolean>(13),
+      static_cast<uint32>(14),
+      static_cast<uint32>(15));
+  EXPECT_EQ(UniformMatrix2fv::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLint>(11), cmd.location);
+  EXPECT_EQ(static_cast<GLsizei>(12), cmd.count);
+  EXPECT_EQ(static_cast<GLboolean>(13), cmd.transpose);
+  EXPECT_EQ(static_cast<uint32>(14), cmd.value_shm_id);
+  EXPECT_EQ(static_cast<uint32>(15), cmd.value_shm_offset);
+}
+
+TEST(GLES2FormatTest, UniformMatrix2fvImmediate) {
+  const int kSomeBaseValueToTestWith = 51;
+  static GLfloat data[] = {
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 0),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 1),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 2),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 3),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 4),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 5),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 6),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 7),
+  };
+  int8 buf[256] = { 0, };
+  UniformMatrix2fvImmediate& cmd =
+      *static_cast<UniformMatrix2fvImmediate*>(static_cast<void*>(&buf));
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLint>(1),
+      static_cast<GLsizei>(2),
+      static_cast<GLboolean>(3),
+      data);
+  EXPECT_EQ(UniformMatrix2fvImmediate::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd) +
+            RoundSizeToMultipleOfEntries(sizeof(data)),
+            cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLint>(1), cmd.location);
+  EXPECT_EQ(static_cast<GLsizei>(2), cmd.count);
+  EXPECT_EQ(static_cast<GLboolean>(3), cmd.transpose);
+  // TODO(gman): Check that data was inserted;
+}
+
+TEST(GLES2FormatTest, UniformMatrix3fv) {
+  UniformMatrix3fv cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLint>(11),
+      static_cast<GLsizei>(12),
+      static_cast<GLboolean>(13),
+      static_cast<uint32>(14),
+      static_cast<uint32>(15));
+  EXPECT_EQ(UniformMatrix3fv::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLint>(11), cmd.location);
+  EXPECT_EQ(static_cast<GLsizei>(12), cmd.count);
+  EXPECT_EQ(static_cast<GLboolean>(13), cmd.transpose);
+  EXPECT_EQ(static_cast<uint32>(14), cmd.value_shm_id);
+  EXPECT_EQ(static_cast<uint32>(15), cmd.value_shm_offset);
+}
+
+TEST(GLES2FormatTest, UniformMatrix3fvImmediate) {
+  const int kSomeBaseValueToTestWith = 51;
+  static GLfloat data[] = {
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 0),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 1),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 2),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 3),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 4),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 5),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 6),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 7),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 8),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 9),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 10),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 11),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 12),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 13),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 14),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 15),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 16),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 17),
+  };
+  int8 buf[256] = { 0, };
+  UniformMatrix3fvImmediate& cmd =
+      *static_cast<UniformMatrix3fvImmediate*>(static_cast<void*>(&buf));
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLint>(1),
+      static_cast<GLsizei>(2),
+      static_cast<GLboolean>(3),
+      data);
+  EXPECT_EQ(UniformMatrix3fvImmediate::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd) +
+            RoundSizeToMultipleOfEntries(sizeof(data)),
+            cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLint>(1), cmd.location);
+  EXPECT_EQ(static_cast<GLsizei>(2), cmd.count);
+  EXPECT_EQ(static_cast<GLboolean>(3), cmd.transpose);
+  // TODO(gman): Check that data was inserted;
+}
+
+TEST(GLES2FormatTest, UniformMatrix4fv) {
+  UniformMatrix4fv cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLint>(11),
+      static_cast<GLsizei>(12),
+      static_cast<GLboolean>(13),
+      static_cast<uint32>(14),
+      static_cast<uint32>(15));
+  EXPECT_EQ(UniformMatrix4fv::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLint>(11), cmd.location);
+  EXPECT_EQ(static_cast<GLsizei>(12), cmd.count);
+  EXPECT_EQ(static_cast<GLboolean>(13), cmd.transpose);
+  EXPECT_EQ(static_cast<uint32>(14), cmd.value_shm_id);
+  EXPECT_EQ(static_cast<uint32>(15), cmd.value_shm_offset);
+}
+
+TEST(GLES2FormatTest, UniformMatrix4fvImmediate) {
+  const int kSomeBaseValueToTestWith = 51;
+  static GLfloat data[] = {
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 0),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 1),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 2),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 3),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 4),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 5),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 6),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 7),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 8),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 9),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 10),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 11),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 12),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 13),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 14),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 15),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 16),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 17),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 18),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 19),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 20),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 21),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 22),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 23),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 24),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 25),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 26),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 27),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 28),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 29),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 30),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 31),
+  };
+  int8 buf[256] = { 0, };
+  UniformMatrix4fvImmediate& cmd =
+      *static_cast<UniformMatrix4fvImmediate*>(static_cast<void*>(&buf));
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLint>(1),
+      static_cast<GLsizei>(2),
+      static_cast<GLboolean>(3),
+      data);
+  EXPECT_EQ(UniformMatrix4fvImmediate::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd) +
+            RoundSizeToMultipleOfEntries(sizeof(data)),
+            cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLint>(1), cmd.location);
+  EXPECT_EQ(static_cast<GLsizei>(2), cmd.count);
+  EXPECT_EQ(static_cast<GLboolean>(3), cmd.transpose);
+  // TODO(gman): Check that data was inserted;
+}
+
+TEST(GLES2FormatTest, UseProgram) {
+  UseProgram cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLuint>(11));
+  EXPECT_EQ(UseProgram::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.program);
+}
+
+TEST(GLES2FormatTest, ValidateProgram) {
+  ValidateProgram cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLuint>(11));
+  EXPECT_EQ(ValidateProgram::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.program);
+}
+
+TEST(GLES2FormatTest, VertexAttrib1f) {
+  VertexAttrib1f cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLuint>(11),
+      static_cast<GLfloat>(12));
+  EXPECT_EQ(VertexAttrib1f::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.indx);
+  EXPECT_EQ(static_cast<GLfloat>(12), cmd.x);
+}
+
+TEST(GLES2FormatTest, VertexAttrib1fv) {
+  VertexAttrib1fv cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLuint>(11),
+      static_cast<uint32>(12),
+      static_cast<uint32>(13));
+  EXPECT_EQ(VertexAttrib1fv::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.indx);
+  EXPECT_EQ(static_cast<uint32>(12), cmd.values_shm_id);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.values_shm_offset);
+}
+
+TEST(GLES2FormatTest, VertexAttrib1fvImmediate) {
+  const int kSomeBaseValueToTestWith = 51;
+  static GLfloat data[] = {
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 0),
+  };
+  int8 buf[256] = { 0, };
+  VertexAttrib1fvImmediate& cmd =
+      *static_cast<VertexAttrib1fvImmediate*>(static_cast<void*>(&buf));
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLuint>(11),
+      data);
+  EXPECT_EQ(VertexAttrib1fvImmediate::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd) +
+            RoundSizeToMultipleOfEntries(sizeof(data)),
+            cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.indx);
+  // TODO(gman): Check that data was inserted;
+}
+
+TEST(GLES2FormatTest, VertexAttrib2f) {
+  VertexAttrib2f cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLuint>(11),
+      static_cast<GLfloat>(12),
+      static_cast<GLfloat>(13));
+  EXPECT_EQ(VertexAttrib2f::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.indx);
+  EXPECT_EQ(static_cast<GLfloat>(12), cmd.x);
+  EXPECT_EQ(static_cast<GLfloat>(13), cmd.y);
+}
+
+TEST(GLES2FormatTest, VertexAttrib2fv) {
+  VertexAttrib2fv cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLuint>(11),
+      static_cast<uint32>(12),
+      static_cast<uint32>(13));
+  EXPECT_EQ(VertexAttrib2fv::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.indx);
+  EXPECT_EQ(static_cast<uint32>(12), cmd.values_shm_id);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.values_shm_offset);
+}
+
+TEST(GLES2FormatTest, VertexAttrib2fvImmediate) {
+  const int kSomeBaseValueToTestWith = 51;
+  static GLfloat data[] = {
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 0),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 1),
+  };
+  int8 buf[256] = { 0, };
+  VertexAttrib2fvImmediate& cmd =
+      *static_cast<VertexAttrib2fvImmediate*>(static_cast<void*>(&buf));
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLuint>(11),
+      data);
+  EXPECT_EQ(VertexAttrib2fvImmediate::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd) +
+            RoundSizeToMultipleOfEntries(sizeof(data)),
+            cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.indx);
+  // TODO(gman): Check that data was inserted;
+}
+
+TEST(GLES2FormatTest, VertexAttrib3f) {
+  VertexAttrib3f cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLuint>(11),
+      static_cast<GLfloat>(12),
+      static_cast<GLfloat>(13),
+      static_cast<GLfloat>(14));
+  EXPECT_EQ(VertexAttrib3f::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.indx);
+  EXPECT_EQ(static_cast<GLfloat>(12), cmd.x);
+  EXPECT_EQ(static_cast<GLfloat>(13), cmd.y);
+  EXPECT_EQ(static_cast<GLfloat>(14), cmd.z);
+}
+
+TEST(GLES2FormatTest, VertexAttrib3fv) {
+  VertexAttrib3fv cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLuint>(11),
+      static_cast<uint32>(12),
+      static_cast<uint32>(13));
+  EXPECT_EQ(VertexAttrib3fv::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.indx);
+  EXPECT_EQ(static_cast<uint32>(12), cmd.values_shm_id);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.values_shm_offset);
+}
+
+TEST(GLES2FormatTest, VertexAttrib3fvImmediate) {
+  const int kSomeBaseValueToTestWith = 51;
+  static GLfloat data[] = {
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 0),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 1),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 2),
+  };
+  int8 buf[256] = { 0, };
+  VertexAttrib3fvImmediate& cmd =
+      *static_cast<VertexAttrib3fvImmediate*>(static_cast<void*>(&buf));
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLuint>(11),
+      data);
+  EXPECT_EQ(VertexAttrib3fvImmediate::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd) +
+            RoundSizeToMultipleOfEntries(sizeof(data)),
+            cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.indx);
+  // TODO(gman): Check that data was inserted;
+}
+
+TEST(GLES2FormatTest, VertexAttrib4f) {
+  VertexAttrib4f cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLuint>(11),
+      static_cast<GLfloat>(12),
+      static_cast<GLfloat>(13),
+      static_cast<GLfloat>(14),
+      static_cast<GLfloat>(15));
+  EXPECT_EQ(VertexAttrib4f::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.indx);
+  EXPECT_EQ(static_cast<GLfloat>(12), cmd.x);
+  EXPECT_EQ(static_cast<GLfloat>(13), cmd.y);
+  EXPECT_EQ(static_cast<GLfloat>(14), cmd.z);
+  EXPECT_EQ(static_cast<GLfloat>(15), cmd.w);
+}
+
+TEST(GLES2FormatTest, VertexAttrib4fv) {
+  VertexAttrib4fv cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLuint>(11),
+      static_cast<uint32>(12),
+      static_cast<uint32>(13));
+  EXPECT_EQ(VertexAttrib4fv::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.indx);
+  EXPECT_EQ(static_cast<uint32>(12), cmd.values_shm_id);
+  EXPECT_EQ(static_cast<uint32>(13), cmd.values_shm_offset);
+}
+
+TEST(GLES2FormatTest, VertexAttrib4fvImmediate) {
+  const int kSomeBaseValueToTestWith = 51;
+  static GLfloat data[] = {
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 0),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 1),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 2),
+    static_cast<GLfloat>(kSomeBaseValueToTestWith + 3),
+  };
+  int8 buf[256] = { 0, };
+  VertexAttrib4fvImmediate& cmd =
+      *static_cast<VertexAttrib4fvImmediate*>(static_cast<void*>(&buf));
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLuint>(11),
+      data);
+  EXPECT_EQ(VertexAttrib4fvImmediate::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd) +
+            RoundSizeToMultipleOfEntries(sizeof(data)),
+            cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.indx);
+  // TODO(gman): Check that data was inserted;
+}
+
+TEST(GLES2FormatTest, VertexAttribPointer) {
+  VertexAttribPointer cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLuint>(11),
+      static_cast<GLint>(12),
+      static_cast<GLenum>(13),
+      static_cast<GLboolean>(14),
+      static_cast<GLsizei>(15),
+      static_cast<GLuint>(16));
+  EXPECT_EQ(VertexAttribPointer::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.indx);
+  EXPECT_EQ(static_cast<GLint>(12), cmd.size);
+  EXPECT_EQ(static_cast<GLenum>(13), cmd.type);
+  EXPECT_EQ(static_cast<GLboolean>(14), cmd.normalized);
+  EXPECT_EQ(static_cast<GLsizei>(15), cmd.stride);
+  EXPECT_EQ(static_cast<GLuint>(16), cmd.offset);
+}
+
+TEST(GLES2FormatTest, Viewport) {
+  Viewport cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd,
+      static_cast<GLint>(11),
+      static_cast<GLint>(12),
+      static_cast<GLsizei>(13),
+      static_cast<GLsizei>(14));
+  EXPECT_EQ(Viewport::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+  EXPECT_EQ(static_cast<GLint>(11), cmd.x);
+  EXPECT_EQ(static_cast<GLint>(12), cmd.y);
+  EXPECT_EQ(static_cast<GLsizei>(13), cmd.width);
+  EXPECT_EQ(static_cast<GLsizei>(14), cmd.height);
+}
+
+TEST(GLES2FormatTest, SwapBuffers) {
+  SwapBuffers cmd = { 0, };
+  void* next_cmd = cmd.Set(
+      &cmd);
+  EXPECT_EQ(SwapBuffers::kCmdId, cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4);  // NOLINT
+}
+
diff --git a/gpu/command_buffer/common/gles2_cmd_id_test.cc b/gpu/command_buffer/common/gles2_cmd_id_test.cc
new file mode 100644
index 0000000..4094cfb
--- /dev/null
+++ b/gpu/command_buffer/common/gles2_cmd_id_test.cc
@@ -0,0 +1,372 @@
+
+// Copyright (c) 2006-2008 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.
+
+// This file contains unit tests for gles2 commmand ids
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "gpu/command_buffer/common/gles2_cmd_format.h"
+
+namespace command_buffer {
+namespace gles2 {
+
+// *** These IDs MUST NOT CHANGE!!! ***
+// Changing them will break all client programs.
+TEST(GLES2CommandIdTest, CommandIdsMatch) {
+  COMPILE_ASSERT(ActiveTexture::kCmdId == 1024,
+                 GLES2_ActiveTexture_kCmdId_mismatch);
+  COMPILE_ASSERT(AttachShader::kCmdId == 1025,
+                 GLES2_AttachShader_kCmdId_mismatch);
+  COMPILE_ASSERT(BindAttribLocation::kCmdId == 1026,
+                 GLES2_BindAttribLocation_kCmdId_mismatch);
+  COMPILE_ASSERT(BindAttribLocationImmediate::kCmdId == 1027,
+                 GLES2_BindAttribLocationImmediate_kCmdId_mismatch);
+  COMPILE_ASSERT(BindBuffer::kCmdId == 1028,
+                 GLES2_BindBuffer_kCmdId_mismatch);
+  COMPILE_ASSERT(BindFramebuffer::kCmdId == 1029,
+                 GLES2_BindFramebuffer_kCmdId_mismatch);
+  COMPILE_ASSERT(BindRenderbuffer::kCmdId == 1030,
+                 GLES2_BindRenderbuffer_kCmdId_mismatch);
+  COMPILE_ASSERT(BindTexture::kCmdId == 1031,
+                 GLES2_BindTexture_kCmdId_mismatch);
+  COMPILE_ASSERT(BlendColor::kCmdId == 1032,
+                 GLES2_BlendColor_kCmdId_mismatch);
+  COMPILE_ASSERT(BlendEquation::kCmdId == 1033,
+                 GLES2_BlendEquation_kCmdId_mismatch);
+  COMPILE_ASSERT(BlendEquationSeparate::kCmdId == 1034,
+                 GLES2_BlendEquationSeparate_kCmdId_mismatch);
+  COMPILE_ASSERT(BlendFunc::kCmdId == 1035,
+                 GLES2_BlendFunc_kCmdId_mismatch);
+  COMPILE_ASSERT(BlendFuncSeparate::kCmdId == 1036,
+                 GLES2_BlendFuncSeparate_kCmdId_mismatch);
+  COMPILE_ASSERT(BufferData::kCmdId == 1037,
+                 GLES2_BufferData_kCmdId_mismatch);
+  COMPILE_ASSERT(BufferDataImmediate::kCmdId == 1038,
+                 GLES2_BufferDataImmediate_kCmdId_mismatch);
+  COMPILE_ASSERT(BufferSubData::kCmdId == 1039,
+                 GLES2_BufferSubData_kCmdId_mismatch);
+  COMPILE_ASSERT(BufferSubDataImmediate::kCmdId == 1040,
+                 GLES2_BufferSubDataImmediate_kCmdId_mismatch);
+  COMPILE_ASSERT(CheckFramebufferStatus::kCmdId == 1041,
+                 GLES2_CheckFramebufferStatus_kCmdId_mismatch);
+  COMPILE_ASSERT(Clear::kCmdId == 1042,
+                 GLES2_Clear_kCmdId_mismatch);
+  COMPILE_ASSERT(ClearColor::kCmdId == 1043,
+                 GLES2_ClearColor_kCmdId_mismatch);
+  COMPILE_ASSERT(ClearDepthf::kCmdId == 1044,
+                 GLES2_ClearDepthf_kCmdId_mismatch);
+  COMPILE_ASSERT(ClearStencil::kCmdId == 1045,
+                 GLES2_ClearStencil_kCmdId_mismatch);
+  COMPILE_ASSERT(ColorMask::kCmdId == 1046,
+                 GLES2_ColorMask_kCmdId_mismatch);
+  COMPILE_ASSERT(CompileShader::kCmdId == 1047,
+                 GLES2_CompileShader_kCmdId_mismatch);
+  COMPILE_ASSERT(CompressedTexImage2D::kCmdId == 1048,
+                 GLES2_CompressedTexImage2D_kCmdId_mismatch);
+  COMPILE_ASSERT(CompressedTexImage2DImmediate::kCmdId == 1049,
+                 GLES2_CompressedTexImage2DImmediate_kCmdId_mismatch);
+  COMPILE_ASSERT(CompressedTexSubImage2D::kCmdId == 1050,
+                 GLES2_CompressedTexSubImage2D_kCmdId_mismatch);
+  COMPILE_ASSERT(CompressedTexSubImage2DImmediate::kCmdId == 1051,
+                 GLES2_CompressedTexSubImage2DImmediate_kCmdId_mismatch);
+  COMPILE_ASSERT(CopyTexImage2D::kCmdId == 1052,
+                 GLES2_CopyTexImage2D_kCmdId_mismatch);
+  COMPILE_ASSERT(CopyTexSubImage2D::kCmdId == 1053,
+                 GLES2_CopyTexSubImage2D_kCmdId_mismatch);
+  COMPILE_ASSERT(CreateProgram::kCmdId == 1054,
+                 GLES2_CreateProgram_kCmdId_mismatch);
+  COMPILE_ASSERT(CreateShader::kCmdId == 1055,
+                 GLES2_CreateShader_kCmdId_mismatch);
+  COMPILE_ASSERT(CullFace::kCmdId == 1056,
+                 GLES2_CullFace_kCmdId_mismatch);
+  COMPILE_ASSERT(DeleteBuffers::kCmdId == 1057,
+                 GLES2_DeleteBuffers_kCmdId_mismatch);
+  COMPILE_ASSERT(DeleteBuffersImmediate::kCmdId == 1058,
+                 GLES2_DeleteBuffersImmediate_kCmdId_mismatch);
+  COMPILE_ASSERT(DeleteFramebuffers::kCmdId == 1059,
+                 GLES2_DeleteFramebuffers_kCmdId_mismatch);
+  COMPILE_ASSERT(DeleteFramebuffersImmediate::kCmdId == 1060,
+                 GLES2_DeleteFramebuffersImmediate_kCmdId_mismatch);
+  COMPILE_ASSERT(DeleteProgram::kCmdId == 1061,
+                 GLES2_DeleteProgram_kCmdId_mismatch);
+  COMPILE_ASSERT(DeleteRenderbuffers::kCmdId == 1062,
+                 GLES2_DeleteRenderbuffers_kCmdId_mismatch);
+  COMPILE_ASSERT(DeleteRenderbuffersImmediate::kCmdId == 1063,
+                 GLES2_DeleteRenderbuffersImmediate_kCmdId_mismatch);
+  COMPILE_ASSERT(DeleteShader::kCmdId == 1064,
+                 GLES2_DeleteShader_kCmdId_mismatch);
+  COMPILE_ASSERT(DeleteTextures::kCmdId == 1065,
+                 GLES2_DeleteTextures_kCmdId_mismatch);
+  COMPILE_ASSERT(DeleteTexturesImmediate::kCmdId == 1066,
+                 GLES2_DeleteTexturesImmediate_kCmdId_mismatch);
+  COMPILE_ASSERT(DepthFunc::kCmdId == 1067,
+                 GLES2_DepthFunc_kCmdId_mismatch);
+  COMPILE_ASSERT(DepthMask::kCmdId == 1068,
+                 GLES2_DepthMask_kCmdId_mismatch);
+  COMPILE_ASSERT(DepthRangef::kCmdId == 1069,
+                 GLES2_DepthRangef_kCmdId_mismatch);
+  COMPILE_ASSERT(DetachShader::kCmdId == 1070,
+                 GLES2_DetachShader_kCmdId_mismatch);
+  COMPILE_ASSERT(Disable::kCmdId == 1071,
+                 GLES2_Disable_kCmdId_mismatch);
+  COMPILE_ASSERT(DisableVertexAttribArray::kCmdId == 1072,
+                 GLES2_DisableVertexAttribArray_kCmdId_mismatch);
+  COMPILE_ASSERT(DrawArrays::kCmdId == 1073,
+                 GLES2_DrawArrays_kCmdId_mismatch);
+  COMPILE_ASSERT(DrawElements::kCmdId == 1074,
+                 GLES2_DrawElements_kCmdId_mismatch);
+  COMPILE_ASSERT(Enable::kCmdId == 1075,
+                 GLES2_Enable_kCmdId_mismatch);
+  COMPILE_ASSERT(EnableVertexAttribArray::kCmdId == 1076,
+                 GLES2_EnableVertexAttribArray_kCmdId_mismatch);
+  COMPILE_ASSERT(Finish::kCmdId == 1077,
+                 GLES2_Finish_kCmdId_mismatch);
+  COMPILE_ASSERT(Flush::kCmdId == 1078,
+                 GLES2_Flush_kCmdId_mismatch);
+  COMPILE_ASSERT(FramebufferRenderbuffer::kCmdId == 1079,
+                 GLES2_FramebufferRenderbuffer_kCmdId_mismatch);
+  COMPILE_ASSERT(FramebufferTexture2D::kCmdId == 1080,
+                 GLES2_FramebufferTexture2D_kCmdId_mismatch);
+  COMPILE_ASSERT(FrontFace::kCmdId == 1081,
+                 GLES2_FrontFace_kCmdId_mismatch);
+  COMPILE_ASSERT(GenBuffers::kCmdId == 1082,
+                 GLES2_GenBuffers_kCmdId_mismatch);
+  COMPILE_ASSERT(GenBuffersImmediate::kCmdId == 1083,
+                 GLES2_GenBuffersImmediate_kCmdId_mismatch);
+  COMPILE_ASSERT(GenerateMipmap::kCmdId == 1084,
+                 GLES2_GenerateMipmap_kCmdId_mismatch);
+  COMPILE_ASSERT(GenFramebuffers::kCmdId == 1085,
+                 GLES2_GenFramebuffers_kCmdId_mismatch);
+  COMPILE_ASSERT(GenFramebuffersImmediate::kCmdId == 1086,
+                 GLES2_GenFramebuffersImmediate_kCmdId_mismatch);
+  COMPILE_ASSERT(GenRenderbuffers::kCmdId == 1087,
+                 GLES2_GenRenderbuffers_kCmdId_mismatch);
+  COMPILE_ASSERT(GenRenderbuffersImmediate::kCmdId == 1088,
+                 GLES2_GenRenderbuffersImmediate_kCmdId_mismatch);
+  COMPILE_ASSERT(GenTextures::kCmdId == 1089,
+                 GLES2_GenTextures_kCmdId_mismatch);
+  COMPILE_ASSERT(GenTexturesImmediate::kCmdId == 1090,
+                 GLES2_GenTexturesImmediate_kCmdId_mismatch);
+  COMPILE_ASSERT(GetActiveAttrib::kCmdId == 1091,
+                 GLES2_GetActiveAttrib_kCmdId_mismatch);
+  COMPILE_ASSERT(GetActiveUniform::kCmdId == 1092,
+                 GLES2_GetActiveUniform_kCmdId_mismatch);
+  COMPILE_ASSERT(GetAttachedShaders::kCmdId == 1093,
+                 GLES2_GetAttachedShaders_kCmdId_mismatch);
+  COMPILE_ASSERT(GetAttribLocation::kCmdId == 1094,
+                 GLES2_GetAttribLocation_kCmdId_mismatch);
+  COMPILE_ASSERT(GetAttribLocationImmediate::kCmdId == 1095,
+                 GLES2_GetAttribLocationImmediate_kCmdId_mismatch);
+  COMPILE_ASSERT(GetBooleanv::kCmdId == 1096,
+                 GLES2_GetBooleanv_kCmdId_mismatch);
+  COMPILE_ASSERT(GetBufferParameteriv::kCmdId == 1097,
+                 GLES2_GetBufferParameteriv_kCmdId_mismatch);
+  COMPILE_ASSERT(GetError::kCmdId == 1098,
+                 GLES2_GetError_kCmdId_mismatch);
+  COMPILE_ASSERT(GetFloatv::kCmdId == 1099,
+                 GLES2_GetFloatv_kCmdId_mismatch);
+  COMPILE_ASSERT(GetFramebufferAttachmentParameteriv::kCmdId == 1100,
+                 GLES2_GetFramebufferAttachmentParameteriv_kCmdId_mismatch);
+  COMPILE_ASSERT(GetIntegerv::kCmdId == 1101,
+                 GLES2_GetIntegerv_kCmdId_mismatch);
+  COMPILE_ASSERT(GetProgramiv::kCmdId == 1102,
+                 GLES2_GetProgramiv_kCmdId_mismatch);
+  COMPILE_ASSERT(GetProgramInfoLog::kCmdId == 1103,
+                 GLES2_GetProgramInfoLog_kCmdId_mismatch);
+  COMPILE_ASSERT(GetRenderbufferParameteriv::kCmdId == 1104,
+                 GLES2_GetRenderbufferParameteriv_kCmdId_mismatch);
+  COMPILE_ASSERT(GetShaderiv::kCmdId == 1105,
+                 GLES2_GetShaderiv_kCmdId_mismatch);
+  COMPILE_ASSERT(GetShaderInfoLog::kCmdId == 1106,
+                 GLES2_GetShaderInfoLog_kCmdId_mismatch);
+  COMPILE_ASSERT(GetShaderPrecisionFormat::kCmdId == 1107,
+                 GLES2_GetShaderPrecisionFormat_kCmdId_mismatch);
+  COMPILE_ASSERT(GetShaderSource::kCmdId == 1108,
+                 GLES2_GetShaderSource_kCmdId_mismatch);
+  COMPILE_ASSERT(GetString::kCmdId == 1109,
+                 GLES2_GetString_kCmdId_mismatch);
+  COMPILE_ASSERT(GetTexParameterfv::kCmdId == 1110,
+                 GLES2_GetTexParameterfv_kCmdId_mismatch);
+  COMPILE_ASSERT(GetTexParameteriv::kCmdId == 1111,
+                 GLES2_GetTexParameteriv_kCmdId_mismatch);
+  COMPILE_ASSERT(GetUniformfv::kCmdId == 1112,
+                 GLES2_GetUniformfv_kCmdId_mismatch);
+  COMPILE_ASSERT(GetUniformiv::kCmdId == 1113,
+                 GLES2_GetUniformiv_kCmdId_mismatch);
+  COMPILE_ASSERT(GetUniformLocation::kCmdId == 1114,
+                 GLES2_GetUniformLocation_kCmdId_mismatch);
+  COMPILE_ASSERT(GetUniformLocationImmediate::kCmdId == 1115,
+                 GLES2_GetUniformLocationImmediate_kCmdId_mismatch);
+  COMPILE_ASSERT(GetVertexAttribfv::kCmdId == 1116,
+                 GLES2_GetVertexAttribfv_kCmdId_mismatch);
+  COMPILE_ASSERT(GetVertexAttribiv::kCmdId == 1117,
+                 GLES2_GetVertexAttribiv_kCmdId_mismatch);
+  COMPILE_ASSERT(GetVertexAttribPointerv::kCmdId == 1118,
+                 GLES2_GetVertexAttribPointerv_kCmdId_mismatch);
+  COMPILE_ASSERT(Hint::kCmdId == 1119,
+                 GLES2_Hint_kCmdId_mismatch);
+  COMPILE_ASSERT(IsBuffer::kCmdId == 1120,
+                 GLES2_IsBuffer_kCmdId_mismatch);
+  COMPILE_ASSERT(IsEnabled::kCmdId == 1121,
+                 GLES2_IsEnabled_kCmdId_mismatch);
+  COMPILE_ASSERT(IsFramebuffer::kCmdId == 1122,
+                 GLES2_IsFramebuffer_kCmdId_mismatch);
+  COMPILE_ASSERT(IsProgram::kCmdId == 1123,
+                 GLES2_IsProgram_kCmdId_mismatch);
+  COMPILE_ASSERT(IsRenderbuffer::kCmdId == 1124,
+                 GLES2_IsRenderbuffer_kCmdId_mismatch);
+  COMPILE_ASSERT(IsShader::kCmdId == 1125,
+                 GLES2_IsShader_kCmdId_mismatch);
+  COMPILE_ASSERT(IsTexture::kCmdId == 1126,
+                 GLES2_IsTexture_kCmdId_mismatch);
+  COMPILE_ASSERT(LineWidth::kCmdId == 1127,
+                 GLES2_LineWidth_kCmdId_mismatch);
+  COMPILE_ASSERT(LinkProgram::kCmdId == 1128,
+                 GLES2_LinkProgram_kCmdId_mismatch);
+  COMPILE_ASSERT(PixelStorei::kCmdId == 1129,
+                 GLES2_PixelStorei_kCmdId_mismatch);
+  COMPILE_ASSERT(PolygonOffset::kCmdId == 1130,
+                 GLES2_PolygonOffset_kCmdId_mismatch);
+  COMPILE_ASSERT(ReadPixels::kCmdId == 1131,
+                 GLES2_ReadPixels_kCmdId_mismatch);
+  COMPILE_ASSERT(RenderbufferStorage::kCmdId == 1132,
+                 GLES2_RenderbufferStorage_kCmdId_mismatch);
+  COMPILE_ASSERT(SampleCoverage::kCmdId == 1133,
+                 GLES2_SampleCoverage_kCmdId_mismatch);
+  COMPILE_ASSERT(Scissor::kCmdId == 1134,
+                 GLES2_Scissor_kCmdId_mismatch);
+  COMPILE_ASSERT(ShaderSource::kCmdId == 1135,
+                 GLES2_ShaderSource_kCmdId_mismatch);
+  COMPILE_ASSERT(ShaderSourceImmediate::kCmdId == 1136,
+                 GLES2_ShaderSourceImmediate_kCmdId_mismatch);
+  COMPILE_ASSERT(StencilFunc::kCmdId == 1137,
+                 GLES2_StencilFunc_kCmdId_mismatch);
+  COMPILE_ASSERT(StencilFuncSeparate::kCmdId == 1138,
+                 GLES2_StencilFuncSeparate_kCmdId_mismatch);
+  COMPILE_ASSERT(StencilMask::kCmdId == 1139,
+                 GLES2_StencilMask_kCmdId_mismatch);
+  COMPILE_ASSERT(StencilMaskSeparate::kCmdId == 1140,
+                 GLES2_StencilMaskSeparate_kCmdId_mismatch);
+  COMPILE_ASSERT(StencilOp::kCmdId == 1141,
+                 GLES2_StencilOp_kCmdId_mismatch);
+  COMPILE_ASSERT(StencilOpSeparate::kCmdId == 1142,
+                 GLES2_StencilOpSeparate_kCmdId_mismatch);
+  COMPILE_ASSERT(TexImage2D::kCmdId == 1143,
+                 GLES2_TexImage2D_kCmdId_mismatch);
+  COMPILE_ASSERT(TexImage2DImmediate::kCmdId == 1144,
+                 GLES2_TexImage2DImmediate_kCmdId_mismatch);
+  COMPILE_ASSERT(TexParameterf::kCmdId == 1145,
+                 GLES2_TexParameterf_kCmdId_mismatch);
+  COMPILE_ASSERT(TexParameterfv::kCmdId == 1146,
+                 GLES2_TexParameterfv_kCmdId_mismatch);
+  COMPILE_ASSERT(TexParameterfvImmediate::kCmdId == 1147,
+                 GLES2_TexParameterfvImmediate_kCmdId_mismatch);
+  COMPILE_ASSERT(TexParameteri::kCmdId == 1148,
+                 GLES2_TexParameteri_kCmdId_mismatch);
+  COMPILE_ASSERT(TexParameteriv::kCmdId == 1149,
+                 GLES2_TexParameteriv_kCmdId_mismatch);
+  COMPILE_ASSERT(TexParameterivImmediate::kCmdId == 1150,
+                 GLES2_TexParameterivImmediate_kCmdId_mismatch);
+  COMPILE_ASSERT(TexSubImage2D::kCmdId == 1151,
+                 GLES2_TexSubImage2D_kCmdId_mismatch);
+  COMPILE_ASSERT(TexSubImage2DImmediate::kCmdId == 1152,
+                 GLES2_TexSubImage2DImmediate_kCmdId_mismatch);
+  COMPILE_ASSERT(Uniform1f::kCmdId == 1153,
+                 GLES2_Uniform1f_kCmdId_mismatch);
+  COMPILE_ASSERT(Uniform1fv::kCmdId == 1154,
+                 GLES2_Uniform1fv_kCmdId_mismatch);
+  COMPILE_ASSERT(Uniform1fvImmediate::kCmdId == 1155,
+                 GLES2_Uniform1fvImmediate_kCmdId_mismatch);
+  COMPILE_ASSERT(Uniform1i::kCmdId == 1156,
+                 GLES2_Uniform1i_kCmdId_mismatch);
+  COMPILE_ASSERT(Uniform1iv::kCmdId == 1157,
+                 GLES2_Uniform1iv_kCmdId_mismatch);
+  COMPILE_ASSERT(Uniform1ivImmediate::kCmdId == 1158,
+                 GLES2_Uniform1ivImmediate_kCmdId_mismatch);
+  COMPILE_ASSERT(Uniform2f::kCmdId == 1159,
+                 GLES2_Uniform2f_kCmdId_mismatch);
+  COMPILE_ASSERT(Uniform2fv::kCmdId == 1160,
+                 GLES2_Uniform2fv_kCmdId_mismatch);
+  COMPILE_ASSERT(Uniform2fvImmediate::kCmdId == 1161,
+                 GLES2_Uniform2fvImmediate_kCmdId_mismatch);
+  COMPILE_ASSERT(Uniform2i::kCmdId == 1162,
+                 GLES2_Uniform2i_kCmdId_mismatch);
+  COMPILE_ASSERT(Uniform2iv::kCmdId == 1163,
+                 GLES2_Uniform2iv_kCmdId_mismatch);
+  COMPILE_ASSERT(Uniform2ivImmediate::kCmdId == 1164,
+                 GLES2_Uniform2ivImmediate_kCmdId_mismatch);
+  COMPILE_ASSERT(Uniform3f::kCmdId == 1165,
+                 GLES2_Uniform3f_kCmdId_mismatch);
+  COMPILE_ASSERT(Uniform3fv::kCmdId == 1166,
+                 GLES2_Uniform3fv_kCmdId_mismatch);
+  COMPILE_ASSERT(Uniform3fvImmediate::kCmdId == 1167,
+                 GLES2_Uniform3fvImmediate_kCmdId_mismatch);
+  COMPILE_ASSERT(Uniform3i::kCmdId == 1168,
+                 GLES2_Uniform3i_kCmdId_mismatch);
+  COMPILE_ASSERT(Uniform3iv::kCmdId == 1169,
+                 GLES2_Uniform3iv_kCmdId_mismatch);
+  COMPILE_ASSERT(Uniform3ivImmediate::kCmdId == 1170,
+                 GLES2_Uniform3ivImmediate_kCmdId_mismatch);
+  COMPILE_ASSERT(Uniform4f::kCmdId == 1171,
+                 GLES2_Uniform4f_kCmdId_mismatch);
+  COMPILE_ASSERT(Uniform4fv::kCmdId == 1172,
+                 GLES2_Uniform4fv_kCmdId_mismatch);
+  COMPILE_ASSERT(Uniform4fvImmediate::kCmdId == 1173,
+                 GLES2_Uniform4fvImmediate_kCmdId_mismatch);
+  COMPILE_ASSERT(Uniform4i::kCmdId == 1174,
+                 GLES2_Uniform4i_kCmdId_mismatch);
+  COMPILE_ASSERT(Uniform4iv::kCmdId == 1175,
+                 GLES2_Uniform4iv_kCmdId_mismatch);
+  COMPILE_ASSERT(Uniform4ivImmediate::kCmdId == 1176,
+                 GLES2_Uniform4ivImmediate_kCmdId_mismatch);
+  COMPILE_ASSERT(UniformMatrix2fv::kCmdId == 1177,
+                 GLES2_UniformMatrix2fv_kCmdId_mismatch);
+  COMPILE_ASSERT(UniformMatrix2fvImmediate::kCmdId == 1178,
+                 GLES2_UniformMatrix2fvImmediate_kCmdId_mismatch);
+  COMPILE_ASSERT(UniformMatrix3fv::kCmdId == 1179,
+                 GLES2_UniformMatrix3fv_kCmdId_mismatch);
+  COMPILE_ASSERT(UniformMatrix3fvImmediate::kCmdId == 1180,
+                 GLES2_UniformMatrix3fvImmediate_kCmdId_mismatch);
+  COMPILE_ASSERT(UniformMatrix4fv::kCmdId == 1181,
+                 GLES2_UniformMatrix4fv_kCmdId_mismatch);
+  COMPILE_ASSERT(UniformMatrix4fvImmediate::kCmdId == 1182,
+                 GLES2_UniformMatrix4fvImmediate_kCmdId_mismatch);
+  COMPILE_ASSERT(UseProgram::kCmdId == 1183,
+                 GLES2_UseProgram_kCmdId_mismatch);
+  COMPILE_ASSERT(ValidateProgram::kCmdId == 1184,
+                 GLES2_ValidateProgram_kCmdId_mismatch);
+  COMPILE_ASSERT(VertexAttrib1f::kCmdId == 1185,
+                 GLES2_VertexAttrib1f_kCmdId_mismatch);
+  COMPILE_ASSERT(VertexAttrib1fv::kCmdId == 1186,
+                 GLES2_VertexAttrib1fv_kCmdId_mismatch);
+  COMPILE_ASSERT(VertexAttrib1fvImmediate::kCmdId == 1187,
+                 GLES2_VertexAttrib1fvImmediate_kCmdId_mismatch);
+  COMPILE_ASSERT(VertexAttrib2f::kCmdId == 1188,
+                 GLES2_VertexAttrib2f_kCmdId_mismatch);
+  COMPILE_ASSERT(VertexAttrib2fv::kCmdId == 1189,
+                 GLES2_VertexAttrib2fv_kCmdId_mismatch);
+  COMPILE_ASSERT(VertexAttrib2fvImmediate::kCmdId == 1190,
+                 GLES2_VertexAttrib2fvImmediate_kCmdId_mismatch);
+  COMPILE_ASSERT(VertexAttrib3f::kCmdId == 1191,
+                 GLES2_VertexAttrib3f_kCmdId_mismatch);
+  COMPILE_ASSERT(VertexAttrib3fv::kCmdId == 1192,
+                 GLES2_VertexAttrib3fv_kCmdId_mismatch);
+  COMPILE_ASSERT(VertexAttrib3fvImmediate::kCmdId == 1193,
+                 GLES2_VertexAttrib3fvImmediate_kCmdId_mismatch);
+  COMPILE_ASSERT(VertexAttrib4f::kCmdId == 1194,
+                 GLES2_VertexAttrib4f_kCmdId_mismatch);
+  COMPILE_ASSERT(VertexAttrib4fv::kCmdId == 1195,
+                 GLES2_VertexAttrib4fv_kCmdId_mismatch);
+  COMPILE_ASSERT(VertexAttrib4fvImmediate::kCmdId == 1196,
+                 GLES2_VertexAttrib4fvImmediate_kCmdId_mismatch);
+  COMPILE_ASSERT(VertexAttribPointer::kCmdId == 1197,
+                 GLES2_VertexAttribPointer_kCmdId_mismatch);
+  COMPILE_ASSERT(Viewport::kCmdId == 1198,
+                 GLES2_Viewport_kCmdId_mismatch);
+  COMPILE_ASSERT(SwapBuffers::kCmdId == 1199,
+                 GLES2_SwapBuffers_kCmdId_mismatch);
+}
+}  // namespace gles2
+}  // namespace command_buffer
+
diff --git a/gpu/command_buffer/common/gles2_cmd_ids.h b/gpu/command_buffer/common/gles2_cmd_ids.h
new file mode 100644
index 0000000..130fce9
--- /dev/null
+++ b/gpu/command_buffer/common/gles2_cmd_ids.h
@@ -0,0 +1,23 @@
+// Copyright (c) 2006-2009 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.
+
+// This file defines the GLES2 command buffer commands.
+
+#ifndef GPU_COMMAND_BUFFER_COMMON_GLES2_CMD_IDS_H
+#define GPU_COMMAND_BUFFER_COMMON_GLES2_CMD_IDS_H
+
+#include "gpu/command_buffer/common/cmd_buffer_common.h"
+
+namespace command_buffer {
+namespace gles2 {
+
+#include "gpu/command_buffer/common/gles2_cmd_ids_autogen.h"
+
+const char* GetCommandName(CommandId command_id);
+
+}  // namespace gles2
+}  // namespace command_buffer
+
+#endif  // GPU_COMMAND_BUFFER_COMMON_GLES2_CMD_IDS_H
+
diff --git a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
new file mode 100644
index 0000000..9e9d5c6
--- /dev/null
+++ b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
@@ -0,0 +1,188 @@
+// This file is auto-generated. DO NOT EDIT!
+
+#define GLES2_COMMAND_LIST(OP) \
+  OP(ActiveTexture)                                            /* 1024 */ \
+  OP(AttachShader)                                             /* 1025 */ \
+  OP(BindAttribLocation)                                       /* 1026 */ \
+  OP(BindAttribLocationImmediate)                              /* 1027 */ \
+  OP(BindBuffer)                                               /* 1028 */ \
+  OP(BindFramebuffer)                                          /* 1029 */ \
+  OP(BindRenderbuffer)                                         /* 1030 */ \
+  OP(BindTexture)                                              /* 1031 */ \
+  OP(BlendColor)                                               /* 1032 */ \
+  OP(BlendEquation)                                            /* 1033 */ \
+  OP(BlendEquationSeparate)                                    /* 1034 */ \
+  OP(BlendFunc)                                                /* 1035 */ \
+  OP(BlendFuncSeparate)                                        /* 1036 */ \
+  OP(BufferData)                                               /* 1037 */ \
+  OP(BufferDataImmediate)                                      /* 1038 */ \
+  OP(BufferSubData)                                            /* 1039 */ \
+  OP(BufferSubDataImmediate)                                   /* 1040 */ \
+  OP(CheckFramebufferStatus)                                   /* 1041 */ \
+  OP(Clear)                                                    /* 1042 */ \
+  OP(ClearColor)                                               /* 1043 */ \
+  OP(ClearDepthf)                                              /* 1044 */ \
+  OP(ClearStencil)                                             /* 1045 */ \
+  OP(ColorMask)                                                /* 1046 */ \
+  OP(CompileShader)                                            /* 1047 */ \
+  OP(CompressedTexImage2D)                                     /* 1048 */ \
+  OP(CompressedTexImage2DImmediate)                            /* 1049 */ \
+  OP(CompressedTexSubImage2D)                                  /* 1050 */ \
+  OP(CompressedTexSubImage2DImmediate)                         /* 1051 */ \
+  OP(CopyTexImage2D)                                           /* 1052 */ \
+  OP(CopyTexSubImage2D)                                        /* 1053 */ \
+  OP(CreateProgram)                                            /* 1054 */ \
+  OP(CreateShader)                                             /* 1055 */ \
+  OP(CullFace)                                                 /* 1056 */ \
+  OP(DeleteBuffers)                                            /* 1057 */ \
+  OP(DeleteBuffersImmediate)                                   /* 1058 */ \
+  OP(DeleteFramebuffers)                                       /* 1059 */ \
+  OP(DeleteFramebuffersImmediate)                              /* 1060 */ \
+  OP(DeleteProgram)                                            /* 1061 */ \
+  OP(DeleteRenderbuffers)                                      /* 1062 */ \
+  OP(DeleteRenderbuffersImmediate)                             /* 1063 */ \
+  OP(DeleteShader)                                             /* 1064 */ \
+  OP(DeleteTextures)                                           /* 1065 */ \
+  OP(DeleteTexturesImmediate)                                  /* 1066 */ \
+  OP(DepthFunc)                                                /* 1067 */ \
+  OP(DepthMask)                                                /* 1068 */ \
+  OP(DepthRangef)                                              /* 1069 */ \
+  OP(DetachShader)                                             /* 1070 */ \
+  OP(Disable)                                                  /* 1071 */ \
+  OP(DisableVertexAttribArray)                                 /* 1072 */ \
+  OP(DrawArrays)                                               /* 1073 */ \
+  OP(DrawElements)                                             /* 1074 */ \
+  OP(Enable)                                                   /* 1075 */ \
+  OP(EnableVertexAttribArray)                                  /* 1076 */ \
+  OP(Finish)                                                   /* 1077 */ \
+  OP(Flush)                                                    /* 1078 */ \
+  OP(FramebufferRenderbuffer)                                  /* 1079 */ \
+  OP(FramebufferTexture2D)                                     /* 1080 */ \
+  OP(FrontFace)                                                /* 1081 */ \
+  OP(GenBuffers)                                               /* 1082 */ \
+  OP(GenBuffersImmediate)                                      /* 1083 */ \
+  OP(GenerateMipmap)                                           /* 1084 */ \
+  OP(GenFramebuffers)                                          /* 1085 */ \
+  OP(GenFramebuffersImmediate)                                 /* 1086 */ \
+  OP(GenRenderbuffers)                                         /* 1087 */ \
+  OP(GenRenderbuffersImmediate)                                /* 1088 */ \
+  OP(GenTextures)                                              /* 1089 */ \
+  OP(GenTexturesImmediate)                                     /* 1090 */ \
+  OP(GetActiveAttrib)                                          /* 1091 */ \
+  OP(GetActiveUniform)                                         /* 1092 */ \
+  OP(GetAttachedShaders)                                       /* 1093 */ \
+  OP(GetAttribLocation)                                        /* 1094 */ \
+  OP(GetAttribLocationImmediate)                               /* 1095 */ \
+  OP(GetBooleanv)                                              /* 1096 */ \
+  OP(GetBufferParameteriv)                                     /* 1097 */ \
+  OP(GetError)                                                 /* 1098 */ \
+  OP(GetFloatv)                                                /* 1099 */ \
+  OP(GetFramebufferAttachmentParameteriv)                      /* 1100 */ \
+  OP(GetIntegerv)                                              /* 1101 */ \
+  OP(GetProgramiv)                                             /* 1102 */ \
+  OP(GetProgramInfoLog)                                        /* 1103 */ \
+  OP(GetRenderbufferParameteriv)                               /* 1104 */ \
+  OP(GetShaderiv)                                              /* 1105 */ \
+  OP(GetShaderInfoLog)                                         /* 1106 */ \
+  OP(GetShaderPrecisionFormat)                                 /* 1107 */ \
+  OP(GetShaderSource)                                          /* 1108 */ \
+  OP(GetString)                                                /* 1109 */ \
+  OP(GetTexParameterfv)                                        /* 1110 */ \
+  OP(GetTexParameteriv)                                        /* 1111 */ \
+  OP(GetUniformfv)                                             /* 1112 */ \
+  OP(GetUniformiv)                                             /* 1113 */ \
+  OP(GetUniformLocation)                                       /* 1114 */ \
+  OP(GetUniformLocationImmediate)                              /* 1115 */ \
+  OP(GetVertexAttribfv)                                        /* 1116 */ \
+  OP(GetVertexAttribiv)                                        /* 1117 */ \
+  OP(GetVertexAttribPointerv)                                  /* 1118 */ \
+  OP(Hint)                                                     /* 1119 */ \
+  OP(IsBuffer)                                                 /* 1120 */ \
+  OP(IsEnabled)                                                /* 1121 */ \
+  OP(IsFramebuffer)                                            /* 1122 */ \
+  OP(IsProgram)                                                /* 1123 */ \
+  OP(IsRenderbuffer)                                           /* 1124 */ \
+  OP(IsShader)                                                 /* 1125 */ \
+  OP(IsTexture)                                                /* 1126 */ \
+  OP(LineWidth)                                                /* 1127 */ \
+  OP(LinkProgram)                                              /* 1128 */ \
+  OP(PixelStorei)                                              /* 1129 */ \
+  OP(PolygonOffset)                                            /* 1130 */ \
+  OP(ReadPixels)                                               /* 1131 */ \
+  OP(RenderbufferStorage)                                      /* 1132 */ \
+  OP(SampleCoverage)                                           /* 1133 */ \
+  OP(Scissor)                                                  /* 1134 */ \
+  OP(ShaderSource)                                             /* 1135 */ \
+  OP(ShaderSourceImmediate)                                    /* 1136 */ \
+  OP(StencilFunc)                                              /* 1137 */ \
+  OP(StencilFuncSeparate)                                      /* 1138 */ \
+  OP(StencilMask)                                              /* 1139 */ \
+  OP(StencilMaskSeparate)                                      /* 1140 */ \
+  OP(StencilOp)                                                /* 1141 */ \
+  OP(StencilOpSeparate)                                        /* 1142 */ \
+  OP(TexImage2D)                                               /* 1143 */ \
+  OP(TexImage2DImmediate)                                      /* 1144 */ \
+  OP(TexParameterf)                                            /* 1145 */ \
+  OP(TexParameterfv)                                           /* 1146 */ \
+  OP(TexParameterfvImmediate)                                  /* 1147 */ \
+  OP(TexParameteri)                                            /* 1148 */ \
+  OP(TexParameteriv)                                           /* 1149 */ \
+  OP(TexParameterivImmediate)                                  /* 1150 */ \
+  OP(TexSubImage2D)                                            /* 1151 */ \
+  OP(TexSubImage2DImmediate)                                   /* 1152 */ \
+  OP(Uniform1f)                                                /* 1153 */ \
+  OP(Uniform1fv)                                               /* 1154 */ \
+  OP(Uniform1fvImmediate)                                      /* 1155 */ \
+  OP(Uniform1i)                                                /* 1156 */ \
+  OP(Uniform1iv)                                               /* 1157 */ \
+  OP(Uniform1ivImmediate)                                      /* 1158 */ \
+  OP(Uniform2f)                                                /* 1159 */ \
+  OP(Uniform2fv)                                               /* 1160 */ \
+  OP(Uniform2fvImmediate)                                      /* 1161 */ \
+  OP(Uniform2i)                                                /* 1162 */ \
+  OP(Uniform2iv)                                               /* 1163 */ \
+  OP(Uniform2ivImmediate)                                      /* 1164 */ \
+  OP(Uniform3f)                                                /* 1165 */ \
+  OP(Uniform3fv)                                               /* 1166 */ \
+  OP(Uniform3fvImmediate)                                      /* 1167 */ \
+  OP(Uniform3i)                                                /* 1168 */ \
+  OP(Uniform3iv)                                               /* 1169 */ \
+  OP(Uniform3ivImmediate)                                      /* 1170 */ \
+  OP(Uniform4f)                                                /* 1171 */ \
+  OP(Uniform4fv)                                               /* 1172 */ \
+  OP(Uniform4fvImmediate)                                      /* 1173 */ \
+  OP(Uniform4i)                                                /* 1174 */ \
+  OP(Uniform4iv)                                               /* 1175 */ \
+  OP(Uniform4ivImmediate)                                      /* 1176 */ \
+  OP(UniformMatrix2fv)                                         /* 1177 */ \
+  OP(UniformMatrix2fvImmediate)                                /* 1178 */ \
+  OP(UniformMatrix3fv)                                         /* 1179 */ \
+  OP(UniformMatrix3fvImmediate)                                /* 1180 */ \
+  OP(UniformMatrix4fv)                                         /* 1181 */ \
+  OP(UniformMatrix4fvImmediate)                                /* 1182 */ \
+  OP(UseProgram)                                               /* 1183 */ \
+  OP(ValidateProgram)                                          /* 1184 */ \
+  OP(VertexAttrib1f)                                           /* 1185 */ \
+  OP(VertexAttrib1fv)                                          /* 1186 */ \
+  OP(VertexAttrib1fvImmediate)                                 /* 1187 */ \
+  OP(VertexAttrib2f)                                           /* 1188 */ \
+  OP(VertexAttrib2fv)                                          /* 1189 */ \
+  OP(VertexAttrib2fvImmediate)                                 /* 1190 */ \
+  OP(VertexAttrib3f)                                           /* 1191 */ \
+  OP(VertexAttrib3fv)                                          /* 1192 */ \
+  OP(VertexAttrib3fvImmediate)                                 /* 1193 */ \
+  OP(VertexAttrib4f)                                           /* 1194 */ \
+  OP(VertexAttrib4fv)                                          /* 1195 */ \
+  OP(VertexAttrib4fvImmediate)                                 /* 1196 */ \
+  OP(VertexAttribPointer)                                      /* 1197 */ \
+  OP(Viewport)                                                 /* 1198 */ \
+  OP(SwapBuffers)                                              /* 1199 */ \
+
+enum CommandId {
+  kStartPoint = cmd::kLastCommonId,  // All GLES2 commands start after this.
+#define GLES2_CMD_OP(name) k ## name,
+  GLES2_COMMAND_LIST(GLES2_CMD_OP)
+#undef GLES2_CMD_OP
+  kNumCommands
+};
+
diff --git a/gpu/command_buffer/common/gles2_cmd_utils.cc b/gpu/command_buffer/common/gles2_cmd_utils.cc
new file mode 100644
index 0000000..9b0c20b
--- /dev/null
+++ b/gpu/command_buffer/common/gles2_cmd_utils.cc
@@ -0,0 +1,347 @@
+// Copyright (c) 2006-2009 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.
+
+// This file is here so other GLES2 related files can have a common set of
+// includes where appropriate.
+
+#include "gpu/command_buffer/common/gles2_cmd_utils.h"
+#include "gpu/command_buffer/common/gles2_cmd_format.h"
+
+namespace command_buffer {
+namespace gles2 {
+
+int GLES2Util::GLGetNumValuesReturned(int id) const {
+  switch (id) {
+    // -- glGetBooleanv, glGetFloatv, glGetIntergerv
+    case GL_ACTIVE_TEXTURE:
+      return 1;
+    case GL_ALIASED_LINE_WIDTH_RANGE:
+      return 2;
+    case GL_ALIASED_POINT_SIZE_RANGE:
+      return 1;
+    case GL_ALPHA_BITS:
+      return 1;
+    case GL_ARRAY_BUFFER_BINDING:
+      return 1;
+    case GL_BLEND:
+      return 1;
+    case GL_BLEND_COLOR:
+      return 4;
+    case GL_BLEND_DST_ALPHA:
+      return 1;
+    case GL_BLEND_DST_RGB:
+      return 1;
+    case GL_BLEND_EQUATION_ALPHA:
+      return 1;
+    case GL_BLEND_EQUATION_RGB:
+      return 1;
+    case GL_BLEND_SRC_ALPHA:
+      return 1;
+    case GL_BLEND_SRC_RGB:
+      return 1;
+    case GL_BLUE_BITS:
+      return 1;
+    case GL_COLOR_CLEAR_VALUE:
+      return 4;
+    case GL_COLOR_WRITEMASK:
+      return 4;
+    case GL_COMPRESSED_TEXTURE_FORMATS:
+      return num_compressed_texture_formats_;
+    case GL_CULL_FACE:
+      return 1;
+    case GL_CULL_FACE_MODE:
+      return 1;
+    case GL_CURRENT_PROGRAM:
+      return 1;
+    case GL_DEPTH_BITS:
+      return 1;
+    case GL_DEPTH_CLEAR_VALUE:
+      return 1;
+    case GL_DEPTH_FUNC:
+      return 1;
+    case GL_DEPTH_RANGE:
+      return 2;
+    case GL_DEPTH_TEST:
+      return 1;
+    case GL_DEPTH_WRITEMASK:
+      return 1;
+    case GL_DITHER:
+      return 1;
+    case GL_ELEMENT_ARRAY_BUFFER_BINDING:
+      return 1;
+    case GL_FRAMEBUFFER_BINDING:
+      return 1;
+    case GL_FRONT_FACE:
+      return 1;
+    case GL_GENERATE_MIPMAP_HINT:
+      return 1;
+    case GL_GREEN_BITS:
+      return 1;
+    case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
+      return 1;
+    case GL_IMPLEMENTATION_COLOR_READ_TYPE:
+      return 1;
+    case GL_LINE_WIDTH:
+      return 1;
+    case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
+      return 1;
+    case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
+      return 1;
+    case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
+      return 1;
+    case GL_MAX_RENDERBUFFER_SIZE:
+      return 1;
+    case GL_MAX_TEXTURE_IMAGE_UNITS:
+      return 1;
+    case GL_MAX_TEXTURE_SIZE:
+      return 1;
+    case GL_MAX_VARYING_VECTORS:
+      return 1;
+    case GL_MAX_VERTEX_ATTRIBS:
+      return 1;
+    case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
+      return 1;
+    case GL_MAX_VERTEX_UNIFORM_VECTORS:
+      return 1;
+    case GL_MAX_VIEWPORT_DIMS:
+      return 2;
+    case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
+      return 1;
+    case GL_PACK_ALIGNMENT:
+      return 1;
+    case GL_POLYGON_OFFSET_FACTOR:
+      return 1;
+    case GL_POLYGON_OFFSET_FILL:
+      return 1;
+    case GL_POLYGON_OFFSET_UNITS:
+      return 1;
+    case GL_RED_BITS:
+      return 1;
+    case GL_RENDERBUFFER_BINDING:
+      return 1;
+    case GL_SAMPLE_BUFFERS:
+      return 1;
+    case GL_SAMPLE_COVERAGE_INVERT:
+      return 1;
+    case GL_SAMPLE_COVERAGE_VALUE:
+      return 1;
+    case GL_SAMPLES:
+      return 1;
+    case GL_SCISSOR_BOX:
+      return 4;
+    case GL_SCISSOR_TEST:
+      return 1;
+    case GL_SHADER_COMPILER:
+      return 1;
+    case GL_STENCIL_BACK_FAIL:
+      return 1;
+    case GL_STENCIL_BACK_FUNC:
+      return 1;
+    case GL_STENCIL_BACK_PASS_DEPTH_FAIL:
+      return 1;
+    case GL_STENCIL_BACK_PASS_DEPTH_PASS:
+      return 1;
+    case GL_STENCIL_BACK_REF:
+      return 1;
+    case GL_STENCIL_BACK_VALUE_MASK:
+      return 1;
+    case GL_STENCIL_BACK_WRITEMASK:
+      return 1;
+    case GL_STENCIL_BITS:
+      return 1;
+    case GL_STENCIL_CLEAR_VALUE:
+      return 1;
+    case GL_STENCIL_FAIL:
+      return 1;
+    case GL_STENCIL_FUNC:
+      return 1;
+    case GL_STENCIL_PASS_DEPTH_FAIL:
+      return 1;
+    case GL_STENCIL_PASS_DEPTH_PASS:
+      return 1;
+    case GL_STENCIL_REF:
+      return 1;
+    case GL_STENCIL_TEST:
+      return 1;
+    case GL_STENCIL_VALUE_MASK:
+      return 1;
+    case GL_STENCIL_WRITEMASK:
+      return 1;
+    case GL_SUBPIXEL_BITS:
+      return 1;
+    case GL_TEXTURE_BINDING_2D:
+      return 1;
+    case GL_TEXTURE_BINDING_CUBE_MAP:
+      return 1;
+    case GL_UNPACK_ALIGNMENT:
+      return 1;
+    case GL_VIEWPORT:
+      return 4;
+
+    // -- glGetBufferParameteriv
+    case GL_BUFFER_SIZE:
+      return 1;
+    case GL_BUFFER_USAGE:
+      return 1;
+
+    // -- glGetFramebufferAttachmentParameteriv
+    case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
+      return 1;
+    case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
+      return 1;
+    case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
+      return 1;
+    case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
+      return 1;
+
+    // -- glGetFramebufferAttachmentParameteriv
+    case GL_DELETE_STATUS:
+      return 1;
+    case GL_LINK_STATUS:
+      return 1;
+    case GL_VALIDATE_STATUS:
+      return 1;
+    case GL_INFO_LOG_LENGTH:
+      return 1;
+    case GL_ATTACHED_SHADERS:
+      return 1;
+    case GL_ACTIVE_ATTRIBUTES:
+      return 1;
+    case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
+      return 1;
+    case GL_ACTIVE_UNIFORMS:
+      return 1;
+    case GL_ACTIVE_UNIFORM_MAX_LENGTH:
+      return 1;
+
+
+    // -- glGetRenderbufferAttachmentParameteriv
+    case GL_RENDERBUFFER_WIDTH:
+      return 1;
+    case GL_RENDERBUFFER_HEIGHT:
+      return 1;
+    case GL_RENDERBUFFER_INTERNAL_FORMAT:
+      return 1;
+    case GL_RENDERBUFFER_RED_SIZE:
+      return 1;
+    case GL_RENDERBUFFER_GREEN_SIZE:
+      return 1;
+    case GL_RENDERBUFFER_BLUE_SIZE:
+      return 1;
+    case GL_RENDERBUFFER_ALPHA_SIZE:
+      return 1;
+    case GL_RENDERBUFFER_DEPTH_SIZE:
+      return 1;
+    case GL_RENDERBUFFER_STENCIL_SIZE:
+      return 1;
+
+    // -- glGetShaderiv
+    case GL_SHADER_TYPE:
+      return 1;
+    // Already defined under glGetFramebufferAttachemntParameteriv.
+    // case GL_DELETE_STATUS:
+    //   return 1;
+    case GL_COMPILE_STATUS:
+      return 1;
+    // Already defined under glGetFramebufferAttachemntParameteriv.
+    // case GL_INFO_LOG_LENGTH:
+    //   return 1;
+    case GL_SHADER_SOURCE_LENGTH:
+      return 1;
+
+    // -- glGetTexParameterfv, glGetTexParameteriv
+    case GL_TEXTURE_MAG_FILTER:
+      return 1;
+    case GL_TEXTURE_MIN_FILTER:
+      return 1;
+    case GL_TEXTURE_WRAP_S:
+      return 1;
+    case GL_TEXTURE_WRAP_T:
+      return 1;
+
+    // -- glGetVertexAttribfv, glGetVertexAttribiv
+    case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
+      return 1;
+    case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
+      return 1;
+    case GL_VERTEX_ATTRIB_ARRAY_SIZE:
+      return 1;
+    case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
+      return 1;
+    case GL_VERTEX_ATTRIB_ARRAY_TYPE:
+      return 1;
+    case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
+      return 1;
+    case GL_CURRENT_VERTEX_ATTRIB:
+      return 4;
+
+    // bad enum
+    default:
+      return 0;
+  }
+}
+
+namespace {
+
+// Return the number of elements per group of a specified format.
+int ElementsPerGroup(int format, int type) {
+  switch (type) {
+    case GL_UNSIGNED_SHORT_5_6_5:
+    case GL_UNSIGNED_SHORT_4_4_4_4:
+    case GL_UNSIGNED_SHORT_5_5_5_1:
+       return 1;
+    default:
+       break;
+    }
+
+    switch (format) {
+    case GL_RGB:
+       return 3;
+    case GL_LUMINANCE_ALPHA:
+       return 2;
+    case GL_RGBA:
+       return 4;
+    case GL_ALPHA:
+    case GL_LUMINANCE:
+       return 1;
+    default:
+       return 0;
+  }
+}
+
+// Return the number of bytes per element, based on the element type.
+int BytesPerElement(int type) {
+  switch (type) {
+    case GL_UNSIGNED_SHORT:
+    case GL_SHORT:
+    case GL_UNSIGNED_SHORT_5_6_5:
+    case GL_UNSIGNED_SHORT_4_4_4_4:
+    case GL_UNSIGNED_SHORT_5_5_5_1:
+       return 2;
+    case GL_UNSIGNED_BYTE:
+    case GL_BYTE:
+       return 1;
+    default:
+       return 0;
+  }
+}
+
+}  // anonymous namespace
+
+// Returns the amount of data glTexImage2D or glTexSubImage2D will access.
+uint32 GLES2Util::ComputeImageDataSize(
+    int width, int height, int format, int type, int unpack_alignment) {
+  uint32 bytes_per_group = BytesPerElement(ElementsPerGroup(format, type));
+  uint32 row_size = width * bytes_per_group;
+  if (height > 1) {
+    uint32 padded_row_size = ((row_size + unpack_alignment - 1) /
+                              unpack_alignment) * unpack_alignment;
+    return height - 1 * padded_row_size + row_size;
+  }
+  return height * row_size;
+}
+
+}  // namespace gles2
+}  // namespace command_buffer
+
diff --git a/gpu/command_buffer/common/gles2_cmd_utils.h b/gpu/command_buffer/common/gles2_cmd_utils.h
new file mode 100644
index 0000000..9674a30
--- /dev/null
+++ b/gpu/command_buffer/common/gles2_cmd_utils.h
@@ -0,0 +1,41 @@
+// Copyright (c) 2006-2009 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.
+
+// This file is here so other GLES2 related files can have a common set of
+// includes where appropriate.
+
+#ifndef GPU_COMMAND_BUFFER_COMMON_GLES2_CMD_UTILS_H
+#define GPU_COMMAND_BUFFER_COMMON_GLES2_CMD_UTILS_H
+
+#include "base/basictypes.h"
+#include "gpu/command_buffer/common/types.h"
+
+namespace command_buffer {
+namespace gles2 {
+
+// Utilties for GLES2 support.
+class GLES2Util {
+ public:
+  explicit GLES2Util(
+      int num_compressed_texture_formats)
+      : num_compressed_texture_formats_(num_compressed_texture_formats) {
+  }
+
+  // Gets the number of values a particular id will return when a glGet
+  // function is called. If 0 is returned the id is invalid.
+  int GLGetNumValuesReturned(int id) const;
+
+  // Computes the size of image data for TexImage2D and TexSubImage2D.
+  static uint32 ComputeImageDataSize(
+    int width, int height, int format, int type, int unpack_alignment);
+
+ private:
+  int num_compressed_texture_formats_;
+};
+
+}  // namespace gles2
+}  // namespace command_buffer
+
+#endif  // GPU_COMMAND_BUFFER_COMMON_GLES2_CMD_UTILS_H
+
diff --git a/gpu/command_buffer/common/logging.h b/gpu/command_buffer/common/logging.h
new file mode 100644
index 0000000..a9bbad8
--- /dev/null
+++ b/gpu/command_buffer/common/logging.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file abstracts differences in logging between NaCl and host
+// environment.
+
+#ifndef GPU_COMMAND_BUFFER_COMMON_CROSS_LOGGING_H_
+#define GPU_COMMAND_BUFFER_COMMON_CROSS_LOGGING_H_
+
+#ifndef __native_client__
+#include "base/logging.h"
+#else
+#include <sstream>
+
+// TODO: implement logging through nacl's debug service runtime if
+// available.
+#define CHECK(X) do {} while (0)
+#define CHECK_EQ(X, Y) do {} while (0)
+#define CHECK_NE(X, Y) do {} while (0)
+#define CHECK_GT(X, Y) do {} while (0)
+#define CHECK_GE(X, Y) do {} while (0)
+#define CHECK_LT(X, Y) do {} while (0)
+#define CHECK_LE(X, Y) do {} while (0)
+
+#define DCHECK(X) do {} while (0)
+#define DCHECK_EQ(X, Y) do {} while (0)
+#define DCHECK_NE(X, Y) do {} while (0)
+#define DCHECK_GT(X, Y) do {} while (0)
+#define DCHECK_GE(X, Y) do {} while (0)
+#define DCHECK_LT(X, Y) do {} while (0)
+#define DCHECK_LE(X, Y) do {} while (0)
+
+#define LOG(LEVEL) if (0) std::ostringstream()
+#define DLOG(LEVEL) if (0) std::ostringstream()
+
+#endif
+
+#endif  // GPU_COMMAND_BUFFER_COMMON_CROSS_LOGGING_H_
diff --git a/gpu/command_buffer/common/resource.cc b/gpu/command_buffer/common/resource.cc
new file mode 100644
index 0000000..f3b75ec
--- /dev/null
+++ b/gpu/command_buffer/common/resource.cc
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains the implementation of the helper functions for resources.
+
+#include "gpu/command_buffer/common/resource.h"
+
+namespace command_buffer {
+
+namespace texture {
+
+// Gets the number of bytes per block for a given format.
+unsigned int GetBytesPerBlock(Format format) {
+  switch (format) {
+    case kXRGB8:
+    case kARGB8:
+    case kR32F:
+      return 4;
+    case kABGR16F:
+      return 8;
+    case kABGR32F:
+      return 16;
+    case kDXT1:
+      return 8;
+    default:
+      // TODO(petersont): Add DXT3/5 support.
+      LOG(FATAL) << "Invalid format";
+      return 1;
+  }
+}
+
+// Gets the width of a block for a given format.
+unsigned int GetBlockSizeX(Format format) {
+  switch (format) {
+    case kXRGB8:
+    case kARGB8:
+    case kABGR16F:
+    case kR32F:
+    case kABGR32F:
+      return 1;
+    case kDXT1:
+      return 4;
+    default:
+      // TODO(petersont): Add DXT3/5 support.
+      LOG(FATAL) << "Invalid format";
+      return 1;
+  }
+}
+
+// Gets the height of a block for a given format.
+unsigned int GetBlockSizeY(Format format) {
+  // NOTE: currently only supported formats use square blocks.
+  return GetBlockSizeX(format);
+}
+
+}  // namespace texture
+
+namespace effect_param {
+
+// Gets the size of the data of a given parameter type.
+unsigned int GetDataSize(DataType type) {
+  switch (type) {
+    case kUnknown:
+      return 0;
+    case kFloat1:
+      return sizeof(float);  // NOLINT
+    case kFloat2:
+      return sizeof(float) * 2;  // NOLINT
+    case kFloat3:
+      return sizeof(float) * 3;  // NOLINT
+    case kFloat4:
+      return sizeof(float) * 4;  // NOLINT
+    case kMatrix4:
+      return sizeof(float) * 16;  // NOLINT
+    case kInt:
+      return sizeof(int);  // NOLINT
+    case kBool:
+      return sizeof(bool);  // NOLINT
+    case kSampler:
+      return sizeof(ResourceId);  // NOLINT
+    case kTexture:
+      return sizeof(ResourceId);  // NOLINT
+    default:
+      LOG(FATAL) << "Invalid type.";
+      return 0;
+  }
+}
+
+}  // namespace effect_param
+
+}  // namespace command_buffer
diff --git a/gpu/command_buffer/common/resource.h b/gpu/command_buffer/common/resource.h
new file mode 100644
index 0000000..01de6a1
--- /dev/null
+++ b/gpu/command_buffer/common/resource.h
@@ -0,0 +1,229 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains definitions for resource flags, enums, and helper
+// functions.
+
+#ifndef GPU_COMMAND_BUFFER_COMMON_CROSS_RESOURCE_H_
+#define GPU_COMMAND_BUFFER_COMMON_CROSS_RESOURCE_H_
+
+#include <algorithm>
+#include "base/basictypes.h"
+#include "base/scoped_ptr.h"
+#include "gpu/command_buffer/common/types.h"
+#include "gpu/command_buffer/common/logging.h"
+
+namespace command_buffer {
+
+// A resource ID, key to the resource maps.
+typedef uint32 ResourceId;
+// Invalid resource ID.
+static const ResourceId kInvalidResource = 0xffffffffU;
+
+namespace vertex_buffer {
+// Vertex buffer flags.
+enum Flags {
+  kNone = 0x00,
+  kDynamic = 0x01,  // This vertex buffer is dynamic and is expected to have
+                    // its data updated often.
+};
+}  // namespace vertex_buffer
+
+namespace index_buffer {
+// Index buffer flags.
+enum Flags {
+  kNone = 0x00,
+  kDynamic = 0x01,  // This index buffer is dynamic and is expected to have
+                    // its data updated often.
+  kIndex32Bit = 0x02,  // Indices contained in this index buffer are 32 bits
+                       // (unsigned int) instead of 16 bit (unsigned short).
+};
+}  // namespace index_buffer
+
+namespace vertex_struct {
+// Semantics for input data.
+enum Semantic {
+  kUnknownSemantic = -1,
+  kPosition = 0,
+  kNormal,
+  kColor,
+  kTexCoord,
+  kNumSemantics
+};
+
+// Input data types.
+enum Type {
+  kFloat1,
+  kFloat2,
+  kFloat3,
+  kFloat4,
+  kUChar4N,
+  kNumTypes
+};
+}  // namespace vertex_struct
+
+namespace effect_param {
+enum DataType {
+  kUnknown,  // A parameter exists in the effect, but the type is not
+  // representable (e.g. MATRIX3x4).
+  kFloat1,
+  kFloat2,
+  kFloat3,
+  kFloat4,
+  kMatrix4,
+  kInt,
+  kBool,
+  kSampler,
+  kTexture,
+  kNumTypes,
+  kMake32Bit = 0x7fffffff,
+};
+COMPILE_ASSERT(sizeof(DataType) == 4, DataType_should_be_32_bits);
+
+// Gets the size of the data of a particular type.
+unsigned int GetDataSize(DataType type);
+
+// Structure describing a parameter, filled in by the
+// GAPIInterface::GetParamDesc call.
+struct Desc {
+  Uint32 size;             // the total memory size needed for the complete
+                           // description.
+  Uint32 name_offset;      // the offset of the parameter name, relative to
+                           // the beginning of the structure. May be 0 if the
+                           // name doesn't fit into the memory buffer.
+  Uint32 name_size;        // the size of the parameter name, including the
+                           // terminating nul character. Will always be set
+                           // even if the name doesn't fit into the buffer.
+  Uint32 semantic_offset;  // the offset of the parameter semantic, relative
+                           // to the beginning of the structure. May be 0 if
+                           // the semantic doesn't fit into the memory
+                           // buffer.
+  Uint32 semantic_size;    // the size of the parameter semantic, including
+                           // the terminating nul character. Will always be
+                           // set even if the semantic doesn't fit into the
+                           // buffer.
+  Uint32 num_elements;     // the number of entries if the parameter is an array
+                           // 0 otherwise.
+  DataType data_type;      // the data type of the parameter.
+  Uint32 data_size;        // the size of the parameter data, in bytes.
+};
+}  // namespace effect_param
+
+namespace effect_stream {
+struct Desc {
+  Desc()
+    : semantic(vertex_struct::kUnknownSemantic),
+      semantic_index(0) {}
+  Desc(Uint32 semantic, Uint32 semantic_index)
+    : semantic(semantic),
+      semantic_index(semantic_index) {}
+  Uint32 semantic;         // the semantic type
+  Uint32 semantic_index;
+};
+}  // namespace effect_stream
+
+namespace texture {
+// Texture flags.
+enum Flags {
+  kNone = 0x00,
+  kDynamic = 0x01,  // This texture is dynamic and is expected to have
+                    // its data updated often.
+};
+
+// Texel formats.
+enum Format {
+  kUnknown,
+  kXRGB8,
+  kARGB8,
+  kABGR16F,
+  kR32F,
+  kABGR32F,
+  kDXT1
+};
+
+// Texture type.
+enum Type {
+  kTexture2d,
+  kTexture3d,
+  kTextureCube,
+};
+
+// Cube map face.
+enum Face {
+  kFacePositiveX,
+  kFaceNegativeX,
+  kFacePositiveY,
+  kFaceNegativeY,
+  kFacePositiveZ,
+  kFaceNegativeZ,
+  kFaceNone = kFacePositiveX,  // For non-cube maps.
+};
+
+// Gets the number of bytes per block for a given texture format. For most
+// texture formats, a block is 1x1 texels, but DXT* formats have 4x4 blocks.
+unsigned int GetBytesPerBlock(Format format);
+// Gets the x dimension of a texel block for a given texture format. For most
+// texture formats, a block is 1x1 texels, but DXT* formats have 4x4 blocks.
+unsigned int GetBlockSizeX(Format format);
+// Gets the y dimension of a texel block for a given texture format. For most
+// texture formats, a block is 1x1 texels, but DXT* formats have 4x4 blocks.
+unsigned int GetBlockSizeY(Format format);
+// Gets the dimension of a mipmap level given the dimension of the base
+// level. Every mipmap level is half the size of the previous level, rounding
+// down.
+inline unsigned int GetMipMapDimension(unsigned int base,
+                                       unsigned int level) {
+  DCHECK_GT(base, 0U);
+  return std::max(1U, base >> level);
+}
+}  // namespace texture
+
+namespace sampler {
+enum AddressingMode {
+  kWrap,
+  kMirrorRepeat,
+  kClampToEdge,
+  kClampToBorder,
+  kNumAddressingMode
+};
+
+enum FilteringMode {
+  kNone,
+  kPoint,
+  kLinear,
+  kNumFilteringMode
+};
+}  // namespace sampler
+
+}  // namespace command_buffer
+
+#endif  // GPU_COMMAND_BUFFER_COMMON_CROSS_RESOURCE_H_
diff --git a/gpu/command_buffer/common/types.h b/gpu/command_buffer/common/types.h
new file mode 100644
index 0000000..daa01cb
--- /dev/null
+++ b/gpu/command_buffer/common/types.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains cross-platform basic type definitions
+
+#ifndef GPU_COMMAND_BUFFER_COMMON_CROSS_TYPES_H_
+#define GPU_COMMAND_BUFFER_COMMON_CROSS_TYPES_H_
+
+#include <build/build_config.h>
+#if !defined(COMPILER_MSVC)
+#include <stdint.h>
+#endif
+#include <string>
+
+namespace command_buffer {
+#if defined(COMPILER_MSVC)
+typedef short Int16;
+typedef unsigned short Uint16;
+typedef int Int32;
+typedef unsigned int Uint32;
+#else
+typedef int16_t Int16;
+typedef uint16_t Uint16;
+typedef int32_t Int32;
+typedef uint32_t Uint32;
+#endif
+
+typedef std::string String;
+}  // namespace command_buffer
+
+#endif  // GPU_COMMAND_BUFFER_COMMON_CROSS_TYPES_H_
diff --git a/gpu/command_buffer/service/cmd_buffer_engine.h b/gpu/command_buffer/service/cmd_buffer_engine.h
new file mode 100644
index 0000000..74ad649
--- /dev/null
+++ b/gpu/command_buffer/service/cmd_buffer_engine.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file defines the CommandBufferEngine class, providing the main loop for
+// the service, exposing the RPC API, managing the command parser.
+
+#ifndef GPU_COMMAND_BUFFER_SERVICE_CROSS_CMD_BUFFER_ENGINE_H_
+#define GPU_COMMAND_BUFFER_SERVICE_CROSS_CMD_BUFFER_ENGINE_H_
+
+#include "base/basictypes.h"
+
+namespace command_buffer {
+
+class CommandBufferEngine {
+ public:
+  CommandBufferEngine() {
+  }
+
+  virtual ~CommandBufferEngine() {
+  }
+
+  // Gets the base address of a registered shared memory buffer.
+  // Parameters:
+  //   shm_id: the identifier for the shared memory buffer.
+  virtual void *GetSharedMemoryAddress(int32 shm_id) = 0;
+
+  // Gets the size of a registered shared memory buffer.
+  // Parameters:
+  //   shm_id: the identifier for the shared memory buffer.
+  virtual size_t GetSharedMemorySize(int32 shm_id) = 0;
+
+  // Sets the token value.
+  virtual void set_token(int32 token) = 0;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(CommandBufferEngine);
+};
+
+}  // namespace command_buffer
+
+#endif  // GPU_COMMAND_BUFFER_SERVICE_CROSS_CMD_BUFFER_ENGINE_H_
diff --git a/gpu/command_buffer/service/cmd_parser.cc b/gpu/command_buffer/service/cmd_parser.cc
new file mode 100644
index 0000000..019e7b2
--- /dev/null
+++ b/gpu/command_buffer/service/cmd_parser.cc
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains the implementation of the command parser.
+
+#include "gpu/command_buffer/service/precompile.h"
+#include "gpu/command_buffer/service/cmd_parser.h"
+
+namespace command_buffer {
+
+CommandParser::CommandParser(void *shm_address,
+                             size_t shm_size,
+                             ptrdiff_t offset,
+                             size_t size,
+                             CommandBufferOffset start_get,
+                             AsyncAPIInterface *handler)
+    : get_(start_get),
+      put_(start_get),
+      handler_(handler) {
+  // check proper alignments.
+  DCHECK_EQ(0, (reinterpret_cast<intptr_t>(shm_address)) % 4);
+  DCHECK_EQ(0, offset % 4);
+  DCHECK_EQ(0u, size % 4);
+  // check that the command buffer fits into the memory buffer.
+  DCHECK_GE(shm_size, offset + size);
+  char * buffer_begin = static_cast<char *>(shm_address) + offset;
+  buffer_ = reinterpret_cast<CommandBufferEntry *>(buffer_begin);
+  entry_count_ = size / 4;
+}
+
+// Process one command, reading the header from the command buffer, and
+// forwarding the command index and the arguments to the handler.
+// Note that:
+// - validation needs to happen on a copy of the data (to avoid race
+// conditions). This function only validates the header, leaving the arguments
+// validation to the handler, so it can pass a reference to them.
+// - get_ is modified *after* the command has been executed.
+parse_error::ParseError CommandParser::ProcessCommand() {
+  CommandBufferOffset get = get_;
+  if (get == put_) return parse_error::kParseNoError;
+
+  CommandHeader header = buffer_[get].value_header;
+  if (header.size == 0) {
+    DLOG(INFO) << "Error: zero sized command in command buffer";
+    return parse_error::kParseInvalidSize;
+  }
+
+  if (header.size + get > entry_count_) {
+    DLOG(INFO) << "Error: get offset out of bounds";
+    return parse_error::kParseOutOfBounds;
+  }
+
+  parse_error::ParseError result = handler_->DoCommand(
+      header.command, header.size - 1, buffer_ + get);
+  // TODO(gman): If you want to log errors this is the best place to catch them.
+  //     It seems like we need an official way to turn on a debug mode and
+  //     get these errors.
+  if (result != parse_error::kParseNoError) {
+    ReportError(header.command, result);
+  }
+  get_ = (get + header.size) % entry_count_;
+  return result;
+}
+
+void CommandParser::ReportError(unsigned int command_id,
+                                parse_error::ParseError result) {
+  DLOG(INFO) << "Error: " << result << " for Command "
+             << handler_->GetCommandName(command_id);
+}
+
+// Processes all the commands, while the buffer is not empty. Stop if an error
+// is encountered.
+parse_error::ParseError CommandParser::ProcessAllCommands() {
+  while (!IsEmpty()) {
+    parse_error::ParseError error = ProcessCommand();
+    if (error) return error;
+  }
+  return parse_error::kParseNoError;
+}
+
+}  // namespace command_buffer
diff --git a/gpu/command_buffer/service/cmd_parser.h b/gpu/command_buffer/service/cmd_parser.h
new file mode 100644
index 0000000..2209cf8
--- /dev/null
+++ b/gpu/command_buffer/service/cmd_parser.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains the command parser class.
+
+#ifndef GPU_COMMAND_BUFFER_SERVICE_CROSS_CMD_PARSER_H_
+#define GPU_COMMAND_BUFFER_SERVICE_CROSS_CMD_PARSER_H_
+
+#include "gpu/command_buffer/common/constants.h"
+#include "gpu/command_buffer/common/cmd_buffer_common.h"
+
+namespace command_buffer {
+
+class AsyncAPIInterface;
+
+// Command parser class. This class parses commands from a shared memory
+// buffer, to implement some asynchronous RPC mechanism.
+class CommandParser {
+ public:
+  CommandParser(void *shm_address,
+                size_t shm_size,
+                ptrdiff_t offset,
+                size_t size,
+                CommandBufferOffset start_get,
+                AsyncAPIInterface *handler);
+
+  // Gets the "get" pointer. The get pointer is an index into the command
+  // buffer considered as an array of CommandBufferEntry.
+  CommandBufferOffset get() const { return get_; }
+
+  // Sets the "put" pointer. The put pointer is an index into the command
+  // buffer considered as an array of CommandBufferEntry.
+  void set_put(CommandBufferOffset put) { put_ = put; }
+
+  // Gets the "put" pointer. The put pointer is an index into the command
+  // buffer considered as an array of CommandBufferEntry.
+  CommandBufferOffset put() const { return put_; }
+
+  // Checks whether there are commands to process.
+  bool IsEmpty() const { return put_ == get_; }
+
+  // Processes one command, updating the get pointer. This will return an error
+  // if there are no commands in the buffer.
+  parse_error::ParseError ProcessCommand();
+
+  // Processes all commands until get == put.
+  parse_error::ParseError ProcessAllCommands();
+
+  // Reports an error.
+  void ReportError(unsigned int command_id, parse_error::ParseError result);
+
+ private:
+  CommandBufferOffset get_;
+  CommandBufferOffset put_;
+  CommandBufferEntry *buffer_;
+  size_t entry_count_;
+  AsyncAPIInterface *handler_;
+};
+
+// This class defines the interface for an asynchronous API handler, that
+// is responsible for de-multiplexing commands and their arguments.
+class AsyncAPIInterface {
+ public:
+  AsyncAPIInterface() {}
+  virtual ~AsyncAPIInterface() {}
+
+  // Executes a command.
+  // Parameters:
+  //    command: the command index.
+  //    arg_count: the number of CommandBufferEntry arguments.
+  //    cmd_data: the command data.
+  // Returns:
+  //   parse_error::NO_ERROR if no error was found, one of
+  //   parse_error::ParseError otherwise.
+  virtual parse_error::ParseError DoCommand(
+      unsigned int command,
+      unsigned int arg_count,
+      const void* cmd_data) = 0;
+
+  // Returns a name for a command. Useful for logging / debuging.
+  virtual const char* GetCommandName(unsigned int command_id) const = 0;
+};
+
+}  // namespace command_buffer
+
+#endif  // GPU_COMMAND_BUFFER_SERVICE_CROSS_CMD_PARSER_H_
diff --git a/gpu/command_buffer/service/cmd_parser_test.cc b/gpu/command_buffer/service/cmd_parser_test.cc
new file mode 100644
index 0000000..347eef2
--- /dev/null
+++ b/gpu/command_buffer/service/cmd_parser_test.cc
@@ -0,0 +1,316 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// Tests for the command parser.
+
+#include "gpu/command_buffer/service/precompile.h"
+
+#include "base/scoped_ptr.h"
+#include "gpu/command_buffer/service/cmd_parser.h"
+#include "gpu/command_buffer/service/mocks.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace command_buffer {
+
+using testing::Return;
+using testing::Mock;
+using testing::Truly;
+using testing::Sequence;
+using testing::_;
+
+// Test fixture for CommandParser test - Creates a mock AsyncAPIInterface, and
+// a fixed size memory buffer. Also provides a simple API to create a
+// CommandParser.
+class CommandParserTest : public testing::Test {
+ protected:
+  virtual void SetUp() {
+    api_mock_.reset(new AsyncAPIMock);
+    buffer_entry_count_ = 20;
+    buffer_.reset(new CommandBufferEntry[buffer_entry_count_]);
+  }
+  virtual void TearDown() {}
+
+  // Adds a DoCommand expectation in the mock.
+  void AddDoCommandExpect(parse_error::ParseError _return,
+                          unsigned int command,
+                          unsigned int arg_count,
+                          CommandBufferEntry *args) {
+    EXPECT_CALL(*api_mock(), DoCommand(command, arg_count,
+        Truly(AsyncAPIMock::IsArgs(arg_count, args))))
+        .InSequence(sequence_)
+        .WillOnce(Return(_return));
+  }
+
+  // Creates a parser, with a buffer of the specified size (in entries).
+  CommandParser *MakeParser(unsigned int entry_count) {
+    size_t shm_size = buffer_entry_count_ *
+                      sizeof(CommandBufferEntry);  // NOLINT
+    size_t command_buffer_size = entry_count *
+                                 sizeof(CommandBufferEntry);  // NOLINT
+    DCHECK_LE(command_buffer_size, shm_size);
+    return new CommandParser(buffer(),
+                             shm_size,
+                             0,
+                             command_buffer_size,
+                             0,
+                             api_mock());
+  }
+
+  unsigned int buffer_entry_count() { return 20; }
+  AsyncAPIMock *api_mock() { return api_mock_.get(); }
+  CommandBufferEntry *buffer() { return buffer_.get(); }
+ private:
+  unsigned int buffer_entry_count_;
+  scoped_ptr<AsyncAPIMock> api_mock_;
+  scoped_array<CommandBufferEntry> buffer_;
+  Sequence sequence_;
+};
+
+// Tests initialization conditions.
+TEST_F(CommandParserTest, TestInit) {
+  scoped_ptr<CommandParser> parser(MakeParser(10));
+  EXPECT_EQ(0u, parser->get());
+  EXPECT_EQ(0u, parser->put());
+  EXPECT_TRUE(parser->IsEmpty());
+}
+
+// Tests simple commands.
+TEST_F(CommandParserTest, TestSimple) {
+  scoped_ptr<CommandParser> parser(MakeParser(10));
+  CommandBufferOffset put = parser->put();
+  CommandHeader header;
+
+  // add a single command, no args
+  header.size = 1;
+  header.command = 123;
+  buffer()[put++].value_header = header;
+
+  parser->set_put(put);
+  EXPECT_EQ(put, parser->put());
+
+  AddDoCommandExpect(parse_error::kParseNoError, 123, 0, NULL);
+  EXPECT_EQ(parse_error::kParseNoError, parser->ProcessCommand());
+  EXPECT_EQ(put, parser->get());
+  Mock::VerifyAndClearExpectations(api_mock());
+
+  // add a single command, 2 args
+  header.size = 3;
+  header.command = 456;
+  buffer()[put++].value_header = header;
+  buffer()[put++].value_int32 = 2134;
+  buffer()[put++].value_float = 1.f;
+
+  parser->set_put(put);
+  EXPECT_EQ(put, parser->put());
+
+  CommandBufferEntry param_array[2];
+  param_array[0].value_int32 = 2134;
+  param_array[1].value_float = 1.f;
+  AddDoCommandExpect(parse_error::kParseNoError, 456, 2, param_array);
+  EXPECT_EQ(parse_error::kParseNoError, parser->ProcessCommand());
+  EXPECT_EQ(put, parser->get());
+  Mock::VerifyAndClearExpectations(api_mock());
+}
+
+// Tests having multiple commands in the buffer.
+TEST_F(CommandParserTest, TestMultipleCommands) {
+  scoped_ptr<CommandParser> parser(MakeParser(10));
+  CommandBufferOffset put = parser->put();
+  CommandHeader header;
+
+  // add 2 commands, test with single ProcessCommand()
+  header.size = 2;
+  header.command = 789;
+  buffer()[put++].value_header = header;
+  buffer()[put++].value_int32 = 5151;
+
+  CommandBufferOffset put_cmd2 = put;
+  header.size = 2;
+  header.command = 2121;
+  buffer()[put++].value_header = header;
+  buffer()[put++].value_int32 = 3434;
+
+  parser->set_put(put);
+  EXPECT_EQ(put, parser->put());
+
+  CommandBufferEntry param_array[2];
+  param_array[0].value_int32 = 5151;
+  AddDoCommandExpect(parse_error::kParseNoError, 789, 1, param_array);
+  param_array[1].value_int32 = 3434;
+  AddDoCommandExpect(parse_error::kParseNoError, 2121, 1,
+                     param_array+1);
+
+  EXPECT_EQ(parse_error::kParseNoError, parser->ProcessCommand());
+  EXPECT_EQ(put_cmd2, parser->get());
+  EXPECT_EQ(parse_error::kParseNoError, parser->ProcessCommand());
+  EXPECT_EQ(put, parser->get());
+  Mock::VerifyAndClearExpectations(api_mock());
+
+  // add 2 commands again, test with ProcessAllCommands()
+  header.size = 2;
+  header.command = 4545;
+  buffer()[put++].value_header = header;
+  buffer()[put++].value_int32 = 5656;
+
+  header.size = 2;
+  header.command = 6767;
+  buffer()[put++].value_header = header;
+  buffer()[put++].value_int32 = 7878;
+
+  parser->set_put(put);
+  EXPECT_EQ(put, parser->put());
+
+  param_array[0].value_int32 = 5656;
+  AddDoCommandExpect(parse_error::kParseNoError, 4545, 1, param_array);
+  param_array[1].value_int32 = 7878;
+  AddDoCommandExpect(parse_error::kParseNoError, 6767, 1,
+                     param_array+1);
+
+  EXPECT_EQ(parse_error::kParseNoError, parser->ProcessAllCommands());
+  EXPECT_EQ(put, parser->get());
+  Mock::VerifyAndClearExpectations(api_mock());
+}
+
+// Tests that the parser will wrap correctly at the end of the buffer.
+TEST_F(CommandParserTest, TestWrap) {
+  scoped_ptr<CommandParser> parser(MakeParser(5));
+  CommandBufferOffset put = parser->put();
+  CommandHeader header;
+
+  // add 3 commands with no args (1 word each)
+  for (unsigned int i = 0; i < 3; ++i) {
+    header.size = 1;
+    header.command = i;
+    buffer()[put++].value_header = header;
+    AddDoCommandExpect(parse_error::kParseNoError, i, 0, NULL);
+  }
+  parser->set_put(put);
+  EXPECT_EQ(put, parser->put());
+  EXPECT_EQ(parse_error::kParseNoError, parser->ProcessAllCommands());
+  EXPECT_EQ(put, parser->get());
+  Mock::VerifyAndClearExpectations(api_mock());
+
+  // add 1 command with 1 arg (2 words). That should put us at the end of the
+  // buffer.
+  header.size = 2;
+  header.command = 3;
+  buffer()[put++].value_header = header;
+  buffer()[put++].value_int32 = 5;
+  CommandBufferEntry param;
+  param.value_int32 = 5;
+  AddDoCommandExpect(parse_error::kParseNoError, 3, 1, &param);
+
+  DCHECK_EQ(5u, put);
+  put = 0;
+  parser->set_put(put);
+  EXPECT_EQ(put, parser->put());
+  EXPECT_EQ(parse_error::kParseNoError, parser->ProcessAllCommands());
+  EXPECT_EQ(put, parser->get());
+  Mock::VerifyAndClearExpectations(api_mock());
+
+  // add 1 command with 1 arg (2 words).
+  header.size = 2;
+  header.command = 4;
+  buffer()[put++].value_header = header;
+  buffer()[put++].value_int32 = 6;
+  param.value_int32 = 6;
+  AddDoCommandExpect(parse_error::kParseNoError, 4, 1, &param);
+  parser->set_put(put);
+  EXPECT_EQ(put, parser->put());
+  EXPECT_EQ(parse_error::kParseNoError, parser->ProcessAllCommands());
+  EXPECT_EQ(put, parser->get());
+  Mock::VerifyAndClearExpectations(api_mock());
+}
+
+// Tests error conditions.
+TEST_F(CommandParserTest, TestError) {
+  scoped_ptr<CommandParser> parser(MakeParser(5));
+  CommandBufferOffset put = parser->put();
+  CommandHeader header;
+
+  // Generate a command with size 0.
+  header.size = 0;
+  header.command = 3;
+  buffer()[put++].value_header = header;
+
+  parser->set_put(put);
+  EXPECT_EQ(put, parser->put());
+  EXPECT_EQ(parse_error::kParseInvalidSize,
+            parser->ProcessAllCommands());
+  // check that no DoCommand call was made.
+  Mock::VerifyAndClearExpectations(api_mock());
+
+  parser.reset(MakeParser(5));
+  put = parser->put();
+
+  // Generate a command with size 6, extends beyond the end of the buffer.
+  header.size = 6;
+  header.command = 3;
+  buffer()[put++].value_header = header;
+
+  parser->set_put(put);
+  EXPECT_EQ(put, parser->put());
+  EXPECT_EQ(parse_error::kParseOutOfBounds,
+            parser->ProcessAllCommands());
+  // check that no DoCommand call was made.
+  Mock::VerifyAndClearExpectations(api_mock());
+
+  parser.reset(MakeParser(5));
+  put = parser->put();
+
+  // Generates 2 commands.
+  header.size = 1;
+  header.command = 3;
+  buffer()[put++].value_header = header;
+  CommandBufferOffset put_post_fail = put;
+  header.size = 1;
+  header.command = 4;
+  buffer()[put++].value_header = header;
+
+  parser->set_put(put);
+  EXPECT_EQ(put, parser->put());
+  // have the first command fail to parse.
+  AddDoCommandExpect(parse_error::kParseUnknownCommand, 3, 0, NULL);
+  EXPECT_EQ(parse_error::kParseUnknownCommand,
+            parser->ProcessAllCommands());
+  // check that only one command was executed, and that get reflects that
+  // correctly.
+  EXPECT_EQ(put_post_fail, parser->get());
+  Mock::VerifyAndClearExpectations(api_mock());
+  // make the second one succeed, and check that the parser recovered fine.
+  AddDoCommandExpect(parse_error::kParseNoError, 4, 0, NULL);
+  EXPECT_EQ(parse_error::kParseNoError, parser->ProcessAllCommands());
+  EXPECT_EQ(put, parser->get());
+  Mock::VerifyAndClearExpectations(api_mock());
+}
+
+}  // namespace command_buffer
diff --git a/gpu/command_buffer/service/command_buffer_service.cc b/gpu/command_buffer/service/command_buffer_service.cc
new file mode 100644
index 0000000..1ab2a9b
--- /dev/null
+++ b/gpu/command_buffer/service/command_buffer_service.cc
@@ -0,0 +1,159 @@
+// Copyright (c) 2006-2008 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 "gpu/command_buffer/service/command_buffer_service.h"
+
+using ::base::SharedMemory;
+
+namespace command_buffer {
+
+CommandBufferService::CommandBufferService()
+    : size_(0),
+      get_offset_(0),
+      put_offset_(0),
+      token_(0),
+      parse_error_(0),
+      error_status_(false) {
+  // Element zero is always NULL.
+  registered_objects_.push_back(linked_ptr<SharedMemory>());
+}
+
+CommandBufferService::~CommandBufferService() {
+}
+
+bool CommandBufferService::Initialize(::base::SharedMemory* ring_buffer) {
+  DCHECK(ring_buffer);
+
+  // Fail if already initialized.
+  if (ring_buffer_.get())
+    return false;
+
+  size_t size_in_bytes = ring_buffer->max_size();
+  size_ = size_in_bytes / sizeof(int32);
+  ring_buffer_.reset(ring_buffer);
+
+  return true;
+}
+
+SharedMemory* CommandBufferService::GetRingBuffer() {
+  return ring_buffer_.get();
+}
+
+int32 CommandBufferService::GetSize() {
+  return size_;
+}
+
+int32 CommandBufferService::SyncOffsets(int32 put_offset) {
+  if (put_offset < 0 || put_offset >= size_)
+    return -1;
+
+  put_offset_ = put_offset;
+
+  if (put_offset_change_callback_.get()) {
+    put_offset_change_callback_->Run();
+  }
+
+  return get_offset_;
+}
+
+int32 CommandBufferService::GetGetOffset() {
+  return get_offset_;
+}
+
+void CommandBufferService::SetGetOffset(int32 get_offset) {
+  DCHECK(get_offset >= 0 && get_offset < size_);
+  get_offset_ = get_offset;
+}
+
+int32 CommandBufferService::GetPutOffset() {
+  return put_offset_;
+}
+
+void CommandBufferService::SetPutOffsetChangeCallback(
+    Callback0::Type* callback) {
+  put_offset_change_callback_.reset(callback);
+}
+
+int32 CommandBufferService::CreateTransferBuffer(size_t size) {
+  linked_ptr<SharedMemory> buffer(new SharedMemory);
+  if (!buffer->Create(std::wstring(), false, false, size))
+    return -1;
+
+  if (unused_registered_object_elements_.empty()) {
+    // Check we haven't exceeded the range that fits in a 32-bit integer.
+    int32 handle = static_cast<int32>(registered_objects_.size());
+    if (handle != registered_objects_.size())
+      return -1;
+
+    registered_objects_.push_back(buffer);
+    return handle;
+  }
+
+  int32 handle = *unused_registered_object_elements_.begin();
+  unused_registered_object_elements_.erase(
+      unused_registered_object_elements_.begin());
+  DCHECK(!registered_objects_[handle].get());
+  registered_objects_[handle] = buffer;
+  return handle;
+}
+
+void CommandBufferService::DestroyTransferBuffer(int32 handle) {
+  if (handle <= 0)
+    return;
+
+  if (static_cast<size_t>(handle) >= registered_objects_.size())
+    return;
+
+  registered_objects_[handle].reset();
+  unused_registered_object_elements_.insert(handle);
+
+  // Remove all null objects from the end of the vector. This allows the vector
+  // to shrink when, for example, all objects are unregistered. Note that this
+  // loop never removes element zero, which is always NULL.
+  while (registered_objects_.size() > 1 && !registered_objects_.back().get()) {
+    registered_objects_.pop_back();
+    unused_registered_object_elements_.erase(
+        static_cast<int32>(registered_objects_.size()));
+  }
+}
+
+::base::SharedMemory* CommandBufferService::GetTransferBuffer(int32 handle) {
+  if (handle < 0)
+    return NULL;
+
+  if (static_cast<size_t>(handle) >= registered_objects_.size())
+    return NULL;
+
+  return registered_objects_[handle].get();
+}
+
+int32 CommandBufferService::GetToken() {
+  return token_;
+}
+
+void CommandBufferService::SetToken(int32 token) {
+  token_ = token;
+}
+
+int32 CommandBufferService::ResetParseError() {
+  int32 last_error = parse_error_;
+  parse_error_ = 0;
+  return last_error;
+}
+
+void CommandBufferService::SetParseError(int32 parse_error) {
+  if (parse_error_ == 0) {
+    parse_error_ = parse_error;
+  }
+}
+
+bool CommandBufferService::GetErrorStatus() {
+  return error_status_;
+}
+
+void CommandBufferService::RaiseErrorStatus() {
+  error_status_ = true;
+}
+
+}  // namespace command_buffer
diff --git a/gpu/command_buffer/service/command_buffer_service.h b/gpu/command_buffer/service/command_buffer_service.h
new file mode 100644
index 0000000..d6da953
--- /dev/null
+++ b/gpu/command_buffer/service/command_buffer_service.h
@@ -0,0 +1,93 @@
+// Copyright (c) 2006-2008 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 GPU_COMMAND_BUFFER_SERVICE_COMMAND_BUFFER_H_
+#define GPU_COMMAND_BUFFER_SERVICE_COMMAND_BUFFER_H_
+
+#include <set>
+#include <vector>
+
+#include "base/linked_ptr.h"
+#include "base/scoped_ptr.h"
+#include "base/shared_memory.h"
+#include "base/task.h"
+#include "gpu/command_buffer/common/command_buffer.h"
+#include "gpu/np_utils/default_np_object.h"
+#include "gpu/np_utils/np_dispatcher.h"
+
+namespace command_buffer {
+
+// An NPObject that implements a shared memory command buffer and a synchronous
+// API to manage the put and get pointers.
+class CommandBufferService : public CommandBuffer {
+ public:
+  CommandBufferService();
+  virtual ~CommandBufferService();
+
+  // Overrides CommandBuffer.
+  virtual bool Initialize(::base::SharedMemory* ring_buffer);
+
+  // Overrides CommandBuffer.
+  virtual ::base::SharedMemory* GetRingBuffer();
+
+  virtual int32 GetSize();
+
+  // Overrides CommandBuffer.
+  virtual int32 SyncOffsets(int32 put_offset);
+
+  // Overrides CommandBuffer.
+  virtual int32 GetGetOffset();
+
+  // Overrides CommandBuffer.
+  virtual void SetGetOffset(int32 get_offset);
+
+  // Overrides CommandBuffer.
+  virtual int32 GetPutOffset();
+
+  // Overrides CommandBuffer.
+  virtual void SetPutOffsetChangeCallback(Callback0::Type* callback);
+
+  // Overrides CommandBuffer.
+  virtual int32 CreateTransferBuffer(size_t size);
+
+  // Overrides CommandBuffer.
+  virtual void DestroyTransferBuffer(int32 id);
+
+  // Overrides CommandBuffer.
+  virtual ::base::SharedMemory* GetTransferBuffer(int32 handle);
+
+  // Overrides CommandBuffer.
+  virtual int32 GetToken();
+
+  // Overrides CommandBuffer.
+  virtual void SetToken(int32 token);
+
+  // Overrides CommandBuffer.
+  virtual int32 ResetParseError();
+
+  // Overrides CommandBuffer.
+  virtual void SetParseError(int32 parse_error);
+
+  // Overrides CommandBuffer.
+  virtual bool GetErrorStatus();
+
+  // Overrides CommandBuffer.
+  virtual void RaiseErrorStatus();
+
+ private:
+  scoped_ptr< ::base::SharedMemory> ring_buffer_;
+  int32 size_;
+  int32 get_offset_;
+  int32 put_offset_;
+  scoped_ptr<Callback0::Type> put_offset_change_callback_;
+  std::vector<linked_ptr< ::base::SharedMemory> > registered_objects_;
+  std::set<int32> unused_registered_object_elements_;
+  int32 token_;
+  int32 parse_error_;
+  bool error_status_;
+};
+
+}  // namespace command_buffer
+
+#endif  // GPU_COMMAND_BUFFER_SERVICE_COMMAND_BUFFER_H_
diff --git a/gpu/command_buffer/service/command_buffer_service_unittest.cc b/gpu/command_buffer/service/command_buffer_service_unittest.cc
new file mode 100644
index 0000000..2f9c1fb
--- /dev/null
+++ b/gpu/command_buffer/service/command_buffer_service_unittest.cc
@@ -0,0 +1,185 @@
+// Copyright (c) 2006-2008 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 "base/thread.h"
+#include "gpu/command_buffer/service/command_buffer_service.h"
+#include "gpu/np_utils/np_browser_mock.h"
+#include "gpu/np_utils/dynamic_np_object.h"
+#include "gpu/np_utils/np_object_mock.h"
+#include "gpu/np_utils/np_object_pointer.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+using base::SharedMemory;
+using np_utils::NPCreateObject;
+using np_utils::NPObjectPointer;
+using testing::_;
+using testing::DoAll;
+using testing::Return;
+using testing::SetArgumentPointee;
+using testing::StrictMock;
+
+namespace command_buffer {
+
+class CommandBufferServiceTest : public testing::Test {
+ protected:
+  virtual void SetUp() {
+    command_buffer_.reset(new CommandBufferService);
+  }
+
+  np_utils::MockNPBrowser mock_browser_;
+  scoped_ptr<CommandBufferService> command_buffer_;
+};
+
+TEST_F(CommandBufferServiceTest, NullRingBufferByDefault) {
+  EXPECT_TRUE(NULL == command_buffer_->GetRingBuffer());
+}
+
+TEST_F(CommandBufferServiceTest, InitializesCommandBuffer) {
+  SharedMemory* ring_buffer = new SharedMemory;
+  EXPECT_TRUE(ring_buffer->Create(std::wstring(), false, false, 1024));
+  EXPECT_TRUE(command_buffer_->Initialize(ring_buffer));
+  EXPECT_TRUE(ring_buffer == command_buffer_->GetRingBuffer());
+  EXPECT_EQ(256, command_buffer_->GetSize());
+}
+
+TEST_F(CommandBufferServiceTest, InitializeFailsSecondTime) {
+  SharedMemory* ring_buffer = new SharedMemory;
+  EXPECT_TRUE(command_buffer_->Initialize(ring_buffer));
+  EXPECT_FALSE(command_buffer_->Initialize(ring_buffer));
+}
+
+TEST_F(CommandBufferServiceTest, GetAndPutOffsetsDefaultToZero) {
+  EXPECT_EQ(0, command_buffer_->GetGetOffset());
+  EXPECT_EQ(0, command_buffer_->GetPutOffset());
+}
+
+class MockCallback : public CallbackRunner<Tuple0> {
+ public:
+  MOCK_METHOD1(RunWithParams, void(const Tuple0&));
+};
+
+TEST_F(CommandBufferServiceTest, CanSyncGetAndPutOffset) {
+  SharedMemory* ring_buffer = new SharedMemory;
+  ring_buffer->Create(std::wstring(), false, false, 1024);
+
+  EXPECT_TRUE(command_buffer_->Initialize(ring_buffer));
+
+  StrictMock<MockCallback>* put_offset_change_callback =
+      new StrictMock<MockCallback>;
+  command_buffer_->SetPutOffsetChangeCallback(put_offset_change_callback);
+
+  EXPECT_CALL(*put_offset_change_callback, RunWithParams(_));
+  EXPECT_EQ(0, command_buffer_->SyncOffsets(2));
+  EXPECT_EQ(2, command_buffer_->GetPutOffset());
+
+  EXPECT_CALL(*put_offset_change_callback, RunWithParams(_));
+  EXPECT_EQ(0, command_buffer_->SyncOffsets(4));
+  EXPECT_EQ(4, command_buffer_->GetPutOffset());
+
+  command_buffer_->SetGetOffset(2);
+  EXPECT_EQ(2, command_buffer_->GetGetOffset());
+  EXPECT_CALL(*put_offset_change_callback, RunWithParams(_));
+  EXPECT_EQ(2, command_buffer_->SyncOffsets(6));
+
+  EXPECT_EQ(-1, command_buffer_->SyncOffsets(-1));
+  EXPECT_EQ(-1, command_buffer_->SyncOffsets(1024));
+}
+
+TEST_F(CommandBufferServiceTest, ZeroHandleMapsToNull) {
+  EXPECT_TRUE(NULL == command_buffer_->GetTransferBuffer(0));
+}
+
+TEST_F(CommandBufferServiceTest, NegativeHandleMapsToNull) {
+  EXPECT_TRUE(NULL == command_buffer_->GetTransferBuffer(-1));
+}
+
+TEST_F(CommandBufferServiceTest, OutOfRangeHandleMapsToNull) {
+  EXPECT_TRUE(NULL == command_buffer_->GetTransferBuffer(1));
+}
+
+TEST_F(CommandBufferServiceTest, CanCreateTransferBuffers) {
+  int32 handle = command_buffer_->CreateTransferBuffer(1024);
+  EXPECT_EQ(1, handle);
+  SharedMemory* buffer = command_buffer_->GetTransferBuffer(handle);
+  ASSERT_TRUE(NULL != buffer);
+  EXPECT_EQ(1024, buffer->max_size());
+}
+
+TEST_F(CommandBufferServiceTest, CreateTransferBufferReturnsDistinctHandles) {
+  EXPECT_EQ(1, command_buffer_->CreateTransferBuffer(1024));
+}
+
+TEST_F(CommandBufferServiceTest,
+    CreateTransferBufferReusesUnregisteredHandles) {
+  EXPECT_EQ(1, command_buffer_->CreateTransferBuffer(1024));
+  EXPECT_EQ(2, command_buffer_->CreateTransferBuffer(1024));
+  command_buffer_->DestroyTransferBuffer(1);
+  EXPECT_EQ(1, command_buffer_->CreateTransferBuffer(1024));
+  EXPECT_EQ(3, command_buffer_->CreateTransferBuffer(1024));
+}
+
+TEST_F(CommandBufferServiceTest, CannotUnregisterHandleZero) {
+  command_buffer_->DestroyTransferBuffer(0);
+  EXPECT_TRUE(NULL == command_buffer_->GetTransferBuffer(0));
+  EXPECT_EQ(1, command_buffer_->CreateTransferBuffer(1024));
+}
+
+TEST_F(CommandBufferServiceTest, CannotUnregisterNegativeHandles) {
+  command_buffer_->DestroyTransferBuffer(-1);
+  EXPECT_EQ(1, command_buffer_->CreateTransferBuffer(1024));
+}
+
+TEST_F(CommandBufferServiceTest, CannotUnregisterUnregisteredHandles) {
+  command_buffer_->DestroyTransferBuffer(1);
+  EXPECT_EQ(1, command_buffer_->CreateTransferBuffer(1024));
+}
+
+// Testing this case specifically because there is an optimization that takes
+// a different code path in this case.
+TEST_F(CommandBufferServiceTest, UnregistersLastRegisteredHandle) {
+  EXPECT_EQ(1, command_buffer_->CreateTransferBuffer(1024));
+  command_buffer_->DestroyTransferBuffer(1);
+  EXPECT_EQ(1, command_buffer_->CreateTransferBuffer(1024));
+}
+
+// Testing this case specifically because there is an optimization that takes
+// a different code path in this case.
+TEST_F(CommandBufferServiceTest, UnregistersTwoLastRegisteredHandles) {
+  EXPECT_EQ(1, command_buffer_->CreateTransferBuffer(1024));
+  EXPECT_EQ(2, command_buffer_->CreateTransferBuffer(1024));
+  command_buffer_->DestroyTransferBuffer(2);
+  command_buffer_->DestroyTransferBuffer(1);
+  EXPECT_EQ(1, command_buffer_->CreateTransferBuffer(1024));
+}
+
+TEST_F(CommandBufferServiceTest, DefaultTokenIsZero) {
+  EXPECT_EQ(0, command_buffer_->GetToken());
+}
+
+TEST_F(CommandBufferServiceTest, CanSetToken) {
+  command_buffer_->SetToken(7);
+  EXPECT_EQ(7, command_buffer_->GetToken());
+}
+
+TEST_F(CommandBufferServiceTest, DefaultParseErrorIsNoError) {
+  EXPECT_EQ(0, command_buffer_->ResetParseError());
+}
+
+TEST_F(CommandBufferServiceTest, CanSetAndResetParseError) {
+  command_buffer_->SetParseError(1);
+  EXPECT_EQ(1, command_buffer_->ResetParseError());
+  EXPECT_EQ(0, command_buffer_->ResetParseError());
+}
+
+TEST_F(CommandBufferServiceTest, DefaultErrorStatusIsFalse) {
+  EXPECT_FALSE(command_buffer_->GetErrorStatus());
+}
+
+TEST_F(CommandBufferServiceTest, CanRaiseErrorStatus) {
+  command_buffer_->RaiseErrorStatus();
+  EXPECT_TRUE(command_buffer_->GetErrorStatus());
+}
+
+}  // namespace command_buffer
diff --git a/gpu/command_buffer/service/common_decoder.cc b/gpu/command_buffer/service/common_decoder.cc
new file mode 100644
index 0000000..22bf445
--- /dev/null
+++ b/gpu/command_buffer/service/common_decoder.cc
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "gpu/command_buffer/service/precompile.h"
+#include "gpu/command_buffer/service/common_decoder.h"
+#include "gpu/command_buffer/service/cmd_buffer_engine.h"
+
+namespace command_buffer {
+
+void* CommonDecoder::GetAddressAndCheckSize(unsigned int shm_id,
+                                            unsigned int offset,
+                                            unsigned int size) {
+  void* shm_addr = engine_->GetSharedMemoryAddress(shm_id);
+  if (!shm_addr) return NULL;
+  size_t shm_size = engine_->GetSharedMemorySize(shm_id);
+  unsigned int end = offset + size;
+  if (end > shm_size || end < offset) {
+    return NULL;
+  }
+  return static_cast<int8 *>(shm_addr) + offset;
+}
+
+const char* CommonDecoder::GetCommonCommandName(
+    cmd::CommandId command_id) const {
+  return cmd::GetCommandName(command_id);
+}
+
+namespace {
+
+// A struct to hold info about each command.
+struct CommandInfo {
+  int arg_flags;  // How to handle the arguments for this command
+  int arg_count;  // How many arguments are expected for this command.
+};
+
+// A table of CommandInfo for all the commands.
+const CommandInfo g_command_info[] = {
+  #define COMMON_COMMAND_BUFFER_CMD_OP(name) {                           \
+    cmd::name::kArgFlags,                                                \
+    sizeof(cmd::name) / sizeof(CommandBufferEntry) - 1, },  /* NOLINT */ \
+
+  COMMON_COMMAND_BUFFER_CMDS(COMMON_COMMAND_BUFFER_CMD_OP)
+
+  #undef COMMON_COMMAND_BUFFER_CMD_OP
+};
+
+}  // anonymous namespace.
+
+// Decode command with its arguments, and call the corresponding method.
+// Note: args is a pointer to the command buffer. As such, it could be changed
+// by a (malicious) client at any time, so if validation has to happen, it
+// should operate on a copy of them.
+parse_error::ParseError CommonDecoder::DoCommonCommand(
+    unsigned int command,
+    unsigned int arg_count,
+    const void* cmd_data) {
+  if (command < arraysize(g_command_info)) {
+    const CommandInfo& info = g_command_info[command];
+    unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
+    if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
+        (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
+      switch (command) {
+        #define COMMON_COMMAND_BUFFER_CMD_OP(name)                      \
+          case cmd::name::kCmdId:                                       \
+            return Handle ## name(                                      \
+                arg_count,                                              \
+                *static_cast<const cmd::name*>(cmd_data));              \
+
+        COMMON_COMMAND_BUFFER_CMDS(COMMON_COMMAND_BUFFER_CMD_OP)
+
+        #undef COMMON_COMMAND_BUFFER_CMD_OP
+      }
+    } else {
+      return parse_error::kParseInvalidArguments;
+    }
+  }
+  return DoCommonCommand(command, arg_count, cmd_data);
+  return parse_error::kParseUnknownCommand;
+}
+
+parse_error::ParseError CommonDecoder::HandleNoop(
+    uint32 arg_count,
+    const cmd::Noop& args) {
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError CommonDecoder::HandleSetToken(
+    uint32 arg_count,
+    const cmd::SetToken& args) {
+  engine_->set_token(args.token);
+  return parse_error::kParseNoError;
+}
+
+}  // namespace command_buffer
diff --git a/gpu/command_buffer/service/common_decoder.h b/gpu/command_buffer/service/common_decoder.h
new file mode 100644
index 0000000..25d1dbe
--- /dev/null
+++ b/gpu/command_buffer/service/common_decoder.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef GPU_COMMAND_BUFFER_SERVICE_CROSS_COMMON_DECODER_H_
+#define GPU_COMMAND_BUFFER_SERVICE_CROSS_COMMON_DECODER_H_
+
+#include "gpu/command_buffer/service/cmd_parser.h"
+
+namespace command_buffer {
+
+class CommandBufferEngine;
+
+// This class is a helper base class for implementing the common parts of the
+// o3d/gl2 command buffer decoder.
+class CommonDecoder : public AsyncAPIInterface {
+ public:
+  typedef parse_error::ParseError ParseError;
+
+  CommonDecoder() : engine_(NULL) {
+  }
+  virtual ~CommonDecoder() {
+  }
+
+  // Sets the engine, to get shared memory buffers from, and to set the token
+  // to.
+  void set_engine(CommandBufferEngine* engine) {
+    engine_ = engine;
+  }
+
+ protected:
+  // Executes a common command.
+  // Parameters:
+  //    command: the command index.
+  //    arg_count: the number of CommandBufferEntry arguments.
+  //    cmd_data: the command data.
+  // Returns:
+  //   parse_error::NO_ERROR if no error was found, one of
+  //   parse_error::ParseError otherwise.
+  parse_error::ParseError DoCommonCommand(
+      unsigned int command,
+      unsigned int arg_count,
+      const void* cmd_data);
+
+  // Gets the address of shared memory data, given a shared memory ID and an
+  // offset. Also checks that the size is consistent with the shared memory
+  // size.
+  // Parameters:
+  //   shm_id: the id of the shared memory buffer.
+  //   offset: the offset of the data in the shared memory buffer.
+  //   size: the size of the data.
+  // Returns:
+  //   NULL if shm_id isn't a valid shared memory buffer ID or if the size
+  //   check fails. Return a pointer to the data otherwise.
+  void* GetAddressAndCheckSize(unsigned int shm_id,
+                               unsigned int offset,
+                               unsigned int size);
+
+  // Gets an name for a common command.
+  const char* GetCommonCommandName(cmd::CommandId command_id) const;
+
+ private:
+  // Generate a member function prototype for each command in an automated and
+  // typesafe way.
+  #define COMMON_COMMAND_BUFFER_CMD_OP(name)             \
+     parse_error::ParseError Handle ## name(             \
+       unsigned int arg_count,                           \
+       const cmd::name& args);                           \
+
+  COMMON_COMMAND_BUFFER_CMDS(COMMON_COMMAND_BUFFER_CMD_OP)
+
+  #undef COMMON_COMMAND_BUFFER_CMD_OP
+
+  CommandBufferEngine* engine_;
+};
+
+}  // namespace command_buffer
+
+#endif  // GPU_COMMAND_BUFFER_SERVICE_CROSS_COMMON_DECODER_H_
+
diff --git a/gpu/command_buffer/service/gl_utils.h b/gpu/command_buffer/service/gl_utils.h
new file mode 100644
index 0000000..b9c10f5
--- /dev/null
+++ b/gpu/command_buffer/service/gl_utils.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file includes all the necessary GL headers and implements some useful
+// utilities.
+
+#ifndef GPU_COMMAND_BUFFER_SERVICE_GL_UTILS_H_
+#define GPU_COMMAND_BUFFER_SERVICE_GL_UTILS_H_
+
+#include <GL/glew.h>
+#if defined(OS_WIN)
+#include <GL/wglew.h>
+#endif
+#include <build/build_config.h>
+
+#define GL_GLEXT_PROTOTYPES
+
+// Define this for extra GL error debugging (slower).
+// #define GL_ERROR_DEBUGGING
+#ifdef GL_ERROR_DEBUGGING
+#define CHECK_GL_ERROR() do {                                           \
+    GLenum gl_error = glGetError();                                     \
+    LOG_IF(ERROR, gl_error != GL_NO_ERROR) << "GL Error :" << gl_error; \
+  } while (0)
+#else  // GL_ERROR_DEBUGGING
+#define CHECK_GL_ERROR() void(0)
+#endif  // GL_ERROR_DEBUGGING
+
+#endif  // GPU_COMMAND_BUFFER_SERVICE_GL_UTILS_H_
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
new file mode 100644
index 0000000..159c5c5
--- /dev/null
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -0,0 +1,950 @@
+// Copyright (c) 2006-2009 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 <vector>
+#include <string>
+#include <map>
+#include <build/build_config.h>
+#include "base/scoped_ptr.h"
+#define GLES2_GPU_SERVICE 1
+#include "gpu/command_buffer/common/gles2_cmd_format.h"
+#include "gpu/command_buffer/common/gles2_cmd_utils.h"
+#include "gpu/command_buffer/service/cmd_buffer_engine.h"
+#include "gpu/command_buffer/service/gl_utils.h"
+#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
+
+namespace command_buffer {
+namespace gles2 {
+
+namespace {
+
+// Returns the address of the first byte after a struct.
+template <typename T>
+const void* AddressAfterStruct(const T& pod) {
+  return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
+}
+
+// Returns the address of the frst byte after the struct.
+template <typename RETURN_TYPE, typename COMMAND_TYPE>
+RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod) {
+  return static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod)));
+}
+
+// Returns the size in bytes of the data of an Immediate command, a command with
+// its data inline in the command buffer.
+template <typename T>
+unsigned int ImmediateDataSize(uint32 arg_count) {
+  return static_cast<unsigned int>(
+      (arg_count + 1 - ComputeNumEntries(sizeof(T))) *
+      sizeof(CommandBufferEntry));  // NOLINT
+}
+
+// Checks if there is enough immediate data.
+template<typename T>
+bool CheckImmediateDataSize(
+    unsigned int arg_count,
+    GLuint count,
+    size_t size,
+    unsigned int elements_per_unit) {
+  return ImmediateDataSize<T>(arg_count) == count * size * elements_per_unit;
+}
+
+// A struct to hold info about each command.
+struct CommandInfo {
+  int arg_flags;  // How to handle the arguments for this command
+  int arg_count;  // How many arguments are expected for this command.
+};
+
+// A table of CommandInfo for all the commands.
+const CommandInfo g_command_info[] = {
+  #define GLES2_CMD_OP(name) {                                            \
+    name::kArgFlags,                                                      \
+    sizeof(name) / sizeof(CommandBufferEntry) - 1, },  /* NOLINT */       \
+
+  GLES2_COMMAND_LIST(GLES2_CMD_OP)
+
+  #undef GLES2_CMD_OP
+};
+
+// These commands convert from c calls to local os calls.
+void GLGenBuffersHelper(GLsizei n, GLuint* ids) {
+  glGenBuffersARB(n, ids);
+}
+
+void GLGenFramebuffersHelper(GLsizei n, GLuint* ids) {
+  glGenFramebuffersEXT(n, ids);
+}
+
+void GLGenRenderbuffersHelper(GLsizei n, GLuint* ids) {
+  glGenRenderbuffersEXT(n, ids);
+}
+
+void GLGenTexturesHelper(GLsizei n, GLuint* ids) {
+  glGenTextures(n, ids);
+}
+
+void GLDeleteBuffersHelper(GLsizei n, GLuint* ids) {
+  glDeleteBuffersARB(n, ids);
+}
+
+void GLDeleteFramebuffersHelper(GLsizei n, GLuint* ids) {
+  glDeleteFramebuffersEXT(n, ids);
+}
+
+void GLDeleteRenderbuffersHelper(GLsizei n, GLuint* ids) {
+  glDeleteRenderbuffersEXT(n, ids);
+}
+
+void GLDeleteTexturesHelper(GLsizei n, GLuint* ids) {
+  glDeleteTextures(n, ids);
+}
+
+namespace GLErrorBit {
+enum GLErrorBit {
+  kNoError = 0,
+  kInvalidEnum,
+  kInvalidValue,
+  kInvalidOperation,
+  kOutOfMemory,
+  kInvalidFrameBufferOperation,
+};
+}
+
+uint32 GLErrorToErrorBit(GLenum error) {
+  switch(error) {
+    case GL_INVALID_ENUM:
+      return GLErrorBit::kInvalidEnum;
+    case GL_INVALID_VALUE:
+      return GLErrorBit::kInvalidValue;
+    case GL_INVALID_OPERATION:
+      return GLErrorBit::kInvalidOperation;
+    case GL_OUT_OF_MEMORY:
+      return GLErrorBit::kOutOfMemory;
+    case GL_INVALID_FRAMEBUFFER_OPERATION:
+      return GLErrorBit::kInvalidFrameBufferOperation;
+    default:
+      DCHECK(false);
+      return GLErrorBit::kNoError;
+  }
+}
+
+GLenum GLErrorBitToGLError(uint32 error_bit) {
+  switch(error_bit) {
+    case GLErrorBit::kInvalidEnum:
+      return GL_INVALID_ENUM;
+    case GLErrorBit::kInvalidValue:
+      return GL_INVALID_VALUE;
+    case GLErrorBit::kInvalidOperation:
+      return GL_INVALID_OPERATION;
+    case GLErrorBit::kOutOfMemory:
+      return GL_OUT_OF_MEMORY;
+    case GLErrorBit::kInvalidFrameBufferOperation:
+      return GL_INVALID_FRAMEBUFFER_OPERATION;
+    default:
+      DCHECK(false);
+      return GL_NO_ERROR;
+  }
+}
+
+}  // anonymous namespace.
+
+GLES2Decoder::GLES2Decoder()
+#ifdef OS_LINUX
+    : window_(NULL) {
+#endif
+#ifdef OS_WIN
+    : hwnd_(NULL) {
+#endif
+}
+
+// This class maps one set of ids to another.
+class IdMap {
+ public:
+  // Maps a client_id to a service_id. Return false if the client_id or
+  // service_id are already mapped to something else.
+  bool AddMapping(GLuint client_id, GLuint service_id);
+
+  // Unmaps a pair of ids. Returns false if the pair were not previously mapped.
+  bool RemoveMapping(GLuint client_id, GLuint service_id);
+
+  // Gets the corresponding service_id for the given client_id.
+  // Returns false if there is no corresponding service_id.
+  bool GetServiceId(GLuint client_id, GLuint* service_id);
+
+  // Gets the corresponding client_id for the given service_id.
+  // Returns false if there is no corresponding client_id.
+  bool GetClientId(GLuint service_id, GLuint* client_id);
+
+ private:
+  // TODO(gman): Replace with faster implementation.
+  typedef std::map<GLuint, GLuint> MapType;
+  MapType id_map_;
+};
+
+bool IdMap::AddMapping(GLuint client_id, GLuint service_id) {
+  std::pair<MapType::iterator, bool> result = id_map_.insert(
+      std::make_pair(client_id, service_id));
+  return result.second;
+}
+
+bool IdMap::RemoveMapping(GLuint client_id, GLuint service_id) {
+  MapType::iterator iter = id_map_.find(client_id);
+  if (iter != id_map_.end() && iter->second == service_id) {
+    id_map_.erase(iter);
+    return true;
+  }
+  return false;
+}
+
+bool IdMap::GetServiceId(GLuint client_id, GLuint* service_id) {
+  DCHECK(service_id);
+  MapType::iterator iter = id_map_.find(client_id);
+  if (iter != id_map_.end()) {
+    *service_id = iter->second;
+    return true;
+  }
+  return false;
+}
+
+bool IdMap::GetClientId(GLuint service_id, GLuint* client_id) {
+  DCHECK(client_id);
+  MapType::iterator end(id_map_.end());
+  for (MapType::iterator iter(id_map_.begin());
+       iter != end;
+       ++iter) {
+    if (iter->second == service_id) {
+      *client_id = iter->first;
+      return true;
+    }
+  }
+  return false;
+}
+
+// This class implements GLES2Decoder so we don't have to expose all the GLES2
+// cmd stuff to outside this class.
+class GLES2DecoderImpl : public GLES2Decoder {
+ public:
+  GLES2DecoderImpl();
+
+  // Overridden from AsyncAPIInterface.
+  virtual ParseError DoCommand(unsigned int command,
+                               unsigned int arg_count,
+                               const void* args);
+
+  // Overridden from AsyncAPIInterface.
+  virtual const char* GetCommandName(unsigned int command_id) const;
+
+  // Overridden from GLES2Decoder.
+  virtual bool Initialize();
+
+  // Overridden from GLES2Decoder.
+  virtual void Destroy();
+
+ private:
+  bool InitPlatformSpecific();
+  bool InitGlew();
+
+  // Typed version of GetAddressAndCheckSize.
+  template <typename T>
+  T GetSharedMemoryAs(unsigned int shm_id, unsigned int offset,
+                      unsigned int size) {
+    return static_cast<T>(GetAddressAndCheckSize(shm_id, offset, size));
+  }
+
+  // Template to help call glGenXXX functions.
+  template <void gl_gen_function(GLsizei, GLuint*)>
+  bool GenGLObjects(GLsizei n, const GLuint* client_ids) {
+    // TODO(gman): Verify client ids are unused.
+    scoped_array<GLuint>temp(new GLuint[n]);
+    gl_gen_function(n, temp.get());
+    // TODO(gman): check for success before copying results.
+    for (GLsizei ii = 0; ii < n; ++ii) {
+      if (!id_map_.AddMapping(client_ids[ii], temp[ii])) {
+        // TODO(gman): fail.
+      }
+    }
+    return true;
+  }
+
+  // Template to help call glDeleteXXX functions.
+  template <void gl_delete_function(GLsizei, GLuint*)>
+  bool DeleteGLObjects(GLsizei n, const GLuint* client_ids) {
+    scoped_array<GLuint>temp(new GLuint[n]);
+    // TODO(gman): check for success before copying results.
+    for (GLsizei ii = 0; ii < n; ++ii) {
+      if (id_map_.GetServiceId(client_ids[ii], &temp[ii])) {
+        id_map_.RemoveMapping(client_ids[ii], temp[ii]);
+      } else {
+        temp[ii] = 0;
+      }
+    }
+    gl_delete_function(n, temp.get());
+    return true;
+  }
+
+  // Wrapper for glCreateProgram
+  void CreateProgramHelper(GLuint client_id);
+
+  // Wrapper for glCreateShader
+  void CreateShaderHelper(GLenum type, GLuint client_id);
+
+  // Wrapper for glBindBuffer since we need to track the current targets.
+  void DoBindBuffer(GLenum target, GLuint buffer);
+
+  // Wrapper for glDeleteProgram.
+  void DoDeleteProgram(GLuint program);
+
+  // Wrapper for glDeleteShader.
+  void DoDeleteShader(GLuint shader);
+
+  // Swaps the buffers (copies/renders to the current window).
+  void DoSwapBuffers();
+
+  // Gets the GLError through our wrapper.
+  GLenum GetGLError();
+
+  // Sets our wrapper for the GLError.
+  void SetGLError(GLenum error);
+
+  // Generate a member function prototype for each command in an automated and
+  // typesafe way.
+  #define GLES2_CMD_OP(name) \
+     ParseError Handle ## name(             \
+       unsigned int arg_count,              \
+       const gles2::name& args);            \
+
+  GLES2_COMMAND_LIST(GLES2_CMD_OP)
+
+  #undef GLES2_CMD_OP
+
+  // Current GL error bits.
+  uint32 error_bits_;
+
+  // Map of client ids to GL ids.
+  IdMap id_map_;
+
+  // Util to help with GL.
+  GLES2Util util_;
+
+  // pack alignment as last set by glPixelStorei
+  GLint pack_alignment_;
+
+  // unpack alignment as last set by glPixelStorei
+  GLint unpack_alignment_;
+
+  // The currently bound array buffer. If this is 0 it is illegal to call
+  // glVertexAttribPointer.
+  GLuint bound_array_buffer_;
+
+  // The currently bound element array buffer. If this is 0 it is illegal
+  // to call glDrawElements.
+  GLuint bound_element_array_buffer_;
+
+#if defined(OS_WIN)
+  HDC device_context_;
+  HGLRC gl_context_;
+#endif
+
+  bool anti_aliased_;
+
+  DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
+};
+
+GLES2Decoder* GLES2Decoder::Create() {
+  return new GLES2DecoderImpl();
+}
+
+GLES2DecoderImpl::GLES2DecoderImpl()
+    : GLES2Decoder(),
+      error_bits_(0),
+      util_(0),  // TODO(gman): Set to actual num compress texture formats.
+      pack_alignment_(4),
+      unpack_alignment_(4),
+      bound_array_buffer_(0),
+      bound_element_array_buffer_(0),
+#ifdef OS_WIN
+      device_context_(NULL),
+      gl_context_(NULL),
+#endif
+      anti_aliased_(false) {
+}
+
+bool GLES2DecoderImpl::Initialize() {
+  if (!InitPlatformSpecific())
+    return false;
+  if (!InitGlew())
+    return false;
+  CHECK_GL_ERROR();
+
+  //glBindFramebuffer(0, 0);
+  return true;
+}
+
+#if defined(OS_WIN)
+namespace {
+
+const PIXELFORMATDESCRIPTOR kPixelFormatDescriptor = {
+  sizeof(kPixelFormatDescriptor),    // Size of structure.
+  1,                       // Default version.
+  PFD_DRAW_TO_WINDOW |     // Window drawing support.
+  PFD_SUPPORT_OPENGL |     // OpenGL support.
+  PFD_DOUBLEBUFFER,        // Double buffering support (not stereo).
+  PFD_TYPE_RGBA,           // RGBA color mode (not indexed).
+  24,                      // 24 bit color mode.
+  0, 0, 0, 0, 0, 0,        // Don't set RGB bits & shifts.
+  8, 0,                    // 8 bit alpha
+  0,                       // No accumulation buffer.
+  0, 0, 0, 0,              // Ignore accumulation bits.
+  24,                      // 24 bit z-buffer size.
+  8,                       // 8-bit stencil buffer.
+  0,                       // No aux buffer.
+  PFD_MAIN_PLANE,          // Main drawing plane (not overlay).
+  0,                       // Reserved.
+  0, 0, 0,                 // Layer masks ignored.
+};
+
+LRESULT CALLBACK IntermediateWindowProc(HWND window,
+                                        UINT message,
+                                        WPARAM w_param,
+                                        LPARAM l_param) {
+  return ::DefWindowProc(window, message, w_param, l_param);
+}
+
+// Helper routine that returns the highest quality pixel format supported on
+// the current platform.  Returns true upon success.
+bool GetWindowsPixelFormat(HWND window,
+                           bool anti_aliased,
+                           int* pixel_format) {
+  // We must initialize a GL context before we can determine the multi-sampling
+  // supported on the current hardware, so we create an intermediate window
+  // and context here.
+  HINSTANCE module_handle;
+  if (!::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT |
+                           GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
+                           reinterpret_cast<wchar_t*>(IntermediateWindowProc),
+                           &module_handle)) {
+    return false;
+  }
+
+  WNDCLASS intermediate_class;
+  intermediate_class.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
+  intermediate_class.lpfnWndProc = IntermediateWindowProc;
+  intermediate_class.cbClsExtra = 0;
+  intermediate_class.cbWndExtra = 0;
+  intermediate_class.hInstance = module_handle;
+  intermediate_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
+  intermediate_class.hCursor = LoadCursor(NULL, IDC_ARROW);
+  intermediate_class.hbrBackground = NULL;
+  intermediate_class.lpszMenuName = NULL;
+  intermediate_class.lpszClassName = L"Intermediate GL Window";
+
+  ATOM class_registration = ::RegisterClass(&intermediate_class);
+  if (!class_registration) {
+    return false;
+  }
+
+  HWND intermediate_window = ::CreateWindow(
+      reinterpret_cast<wchar_t*>(class_registration),
+      L"",
+      WS_OVERLAPPEDWINDOW,
+      0, 0,
+      CW_USEDEFAULT, CW_USEDEFAULT,
+      NULL,
+      NULL,
+      NULL,
+      NULL);
+
+  if (!intermediate_window) {
+    ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration),
+                      module_handle);
+    return false;
+  }
+
+  HDC intermediate_dc = ::GetDC(intermediate_window);
+  int format_index = ::ChoosePixelFormat(intermediate_dc,
+                                         &kPixelFormatDescriptor);
+  if (format_index == 0) {
+    DLOG(ERROR) << "Unable to get the pixel format for GL context.";
+    ::ReleaseDC(intermediate_window, intermediate_dc);
+    ::DestroyWindow(intermediate_window);
+    ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration),
+                      module_handle);
+    return false;
+  }
+  if (!::SetPixelFormat(intermediate_dc, format_index,
+                        &kPixelFormatDescriptor)) {
+    DLOG(ERROR) << "Unable to set the pixel format for GL context.";
+    ::ReleaseDC(intermediate_window, intermediate_dc);
+    ::DestroyWindow(intermediate_window);
+    ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration),
+                      module_handle);
+    return false;
+  }
+
+  // Store the pixel format without multisampling.
+  *pixel_format = format_index;
+  HGLRC gl_context = ::wglCreateContext(intermediate_dc);
+  if (::wglMakeCurrent(intermediate_dc, gl_context)) {
+    // GL context was successfully created and applied to the window's DC.
+    // Startup GLEW, the GL extensions wrangler.
+    GLenum glew_error = ::glewInit();
+    if (glew_error == GLEW_OK) {
+      DLOG(INFO) << "Initialized GLEW " << ::glewGetString(GLEW_VERSION);
+    } else {
+      DLOG(ERROR) << "Unable to initialise GLEW : "
+                  << ::glewGetErrorString(glew_error);
+      ::wglMakeCurrent(intermediate_dc, NULL);
+      ::wglDeleteContext(gl_context);
+      ::ReleaseDC(intermediate_window, intermediate_dc);
+      ::DestroyWindow(intermediate_window);
+      ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration),
+                        module_handle);
+      return false;
+    }
+
+    // If the multi-sample extensions are present, query the api to determine
+    // the pixel format.
+    if (anti_aliased && WGLEW_ARB_pixel_format && WGLEW_ARB_multisample) {
+      int pixel_attributes[] = {
+        WGL_SAMPLES_ARB, 4,
+        WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
+        WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
+        WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
+        WGL_COLOR_BITS_ARB, 24,
+        WGL_ALPHA_BITS_ARB, 8,
+        WGL_DEPTH_BITS_ARB, 24,
+        WGL_STENCIL_BITS_ARB, 8,
+        WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
+        WGL_SAMPLE_BUFFERS_ARB, GL_TRUE,
+        0, 0};
+
+      float pixel_attributes_f[] = {0, 0};
+      int msaa_pixel_format;
+      unsigned int num_formats;
+
+      // Query for the highest sampling rate supported, starting at 4x.
+      static const int kSampleCount[] = {4, 2};
+      static const int kNumSamples = 2;
+      for (int sample = 0; sample < kNumSamples; ++sample) {
+        pixel_attributes[1] = kSampleCount[sample];
+        if (GL_TRUE == ::wglChoosePixelFormatARB(intermediate_dc,
+                                                 pixel_attributes,
+                                                 pixel_attributes_f,
+                                                 1,
+                                                 &msaa_pixel_format,
+                                                 &num_formats)) {
+          *pixel_format = msaa_pixel_format;
+          break;
+        }
+      }
+    }
+  }
+
+  ::wglMakeCurrent(intermediate_dc, NULL);
+  ::wglDeleteContext(gl_context);
+  ::ReleaseDC(intermediate_window, intermediate_dc);
+  ::DestroyWindow(intermediate_window);
+  ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration),
+                    module_handle);
+  return true;
+}
+
+}  // anonymous namespace
+#endif
+
+bool GLES2DecoderImpl::InitPlatformSpecific() {
+#if defined(OS_WIN)
+  device_context_ = ::GetDC(hwnd());
+
+  int pixel_format;
+
+  if (!GetWindowsPixelFormat(hwnd(),
+                             anti_aliased_,
+                             &pixel_format)) {
+      DLOG(ERROR) << "Unable to determine optimal pixel format for GL context.";
+      return false;
+  }
+
+  if (!::SetPixelFormat(device_context_, pixel_format,
+                        &kPixelFormatDescriptor)) {
+    DLOG(ERROR) << "Unable to set the pixel format for GL context.";
+    return false;
+  }
+
+  gl_context_ = ::wglCreateContext(device_context_);
+  if (!gl_context_) {
+    DLOG(ERROR) << "Failed to create GL context.";
+    return false;
+  }
+
+  if (!::wglMakeCurrent(device_context_, gl_context_)) {
+    DLOG(ERROR) << "Unable to make gl context current.";
+    return false;
+  }
+#elif defined(OS_LINUX)
+  DCHECK(window());
+  if (!window()->Initialize())
+    return false;
+  if (!window()->MakeCurrent())
+    return false;
+#endif
+
+  return true;
+}
+
+bool GLES2DecoderImpl::InitGlew() {
+  DLOG(INFO) << "Initializing GL and GLEW for GLES2Decoder.";
+
+  GLenum glew_error = glewInit();
+  if (glew_error != GLEW_OK) {
+    DLOG(ERROR) << "Unable to initialise GLEW : "
+                << ::glewGetErrorString(glew_error);
+    return false;
+  }
+
+  // Check to see that we can use the OpenGL vertex attribute APIs
+  // TODO(petersont):  Return false if this check fails, but because some
+  // Intel hardware does not support OpenGL 2.0, yet does support all of the
+  // extensions we require, we only log an error.  A future CL should change
+  // this check to ensure that all of the extension strings we require are
+  // present.
+  if (!GLEW_VERSION_2_0) {
+    DLOG(ERROR) << "GL drivers do not have OpenGL 2.0 functionality.";
+  }
+
+  bool extensions_found = true;
+  if (!GLEW_ARB_vertex_buffer_object) {
+    // NOTE: Linux NVidia drivers claim to support OpenGL 2.0 when using
+    // indirect rendering (e.g. remote X), but it is actually lying. The
+    // ARB_vertex_buffer_object functions silently no-op (!) when using
+    // indirect rendering, leading to crashes. Fortunately, in that case, the
+    // driver claims to not support ARB_vertex_buffer_object, so fail in that
+    // case.
+    DLOG(ERROR) << "GL drivers do not support vertex buffer objects.";
+    extensions_found = false;
+  }
+  if (!GLEW_EXT_framebuffer_object) {
+    DLOG(ERROR) << "GL drivers do not support framebuffer objects.";
+    extensions_found = false;
+  }
+  // Check for necessary extensions
+  if (!GLEW_VERSION_2_0 && !GLEW_EXT_stencil_two_side) {
+    DLOG(ERROR) << "Two sided stencil extension missing.";
+    extensions_found = false;
+  }
+  if (!GLEW_VERSION_1_4 && !GLEW_EXT_blend_func_separate) {
+    DLOG(ERROR) <<"Separate blend func extension missing.";
+    extensions_found = false;
+  }
+  if (!GLEW_VERSION_2_0 && !GLEW_EXT_blend_equation_separate) {
+    DLOG(ERROR) << "Separate blend function extension missing.";
+    extensions_found = false;
+  }
+  if (!extensions_found)
+    return false;
+
+  return true;
+}
+
+void GLES2DecoderImpl::Destroy() {
+#ifdef OS_LINUX
+  DCHECK(window());
+  window()->Destroy();
+#endif
+}
+
+const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
+  if (command_id > kStartPoint && command_id < kNumCommands) {
+    return gles2::GetCommandName(static_cast<CommandId>(command_id));
+  }
+  return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
+}
+
+// Decode command with its arguments, and call the corresponding GL function.
+// Note: args is a pointer to the command buffer. As such, it could be changed
+// by a (malicious) client at any time, so if validation has to happen, it
+// should operate on a copy of them.
+parse_error::ParseError GLES2DecoderImpl::DoCommand(
+    unsigned int command,
+    unsigned int arg_count,
+    const void* cmd_data) {
+  unsigned int command_index = command - kStartPoint - 1;
+  if (command_index < arraysize(g_command_info)) {
+    const CommandInfo& info = g_command_info[command_index];
+    unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
+    if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
+        (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
+      switch (command) {
+        #define GLES2_CMD_OP(name)                                 \
+          case name::kCmdId:                                       \
+            return Handle ## name(                                 \
+                arg_count,                                         \
+                *static_cast<const name*>(cmd_data));              \
+
+        GLES2_COMMAND_LIST(GLES2_CMD_OP)
+
+        #undef GLES2_CMD_OP
+      }
+    } else {
+      return parse_error::kParseInvalidArguments;
+    }
+  }
+  return DoCommonCommand(command, arg_count, cmd_data);
+}
+
+}  // namespace gles2
+}  // namespace command_buffer
+
+// This is included so the compiler will make these inline.
+#include "gpu/command_buffer/service/gles2_cmd_decoder_validate.h"
+
+namespace command_buffer {
+namespace gles2 {
+
+void GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
+  // TODO(gman): verify client_id is unused.
+  GLuint service_id = glCreateProgram();
+  if (service_id) {
+    id_map_.AddMapping(client_id, service_id);
+  }
+}
+
+void GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
+  // TODO(gman): verify client_id is unused.
+  GLuint service_id = glCreateShader(type);
+  if (service_id) {
+    id_map_.AddMapping(client_id, service_id);
+  }
+}
+
+void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint buffer) {
+  switch (target) {
+    case GL_ARRAY_BUFFER:
+      bound_array_buffer_ = buffer;
+      break;
+    case GL_ELEMENT_ARRAY_BUFFER:
+      bound_element_array_buffer_ = buffer;
+      break;
+    default:
+      break;
+  }
+  glBindBuffer(target, buffer);
+}
+
+void GLES2DecoderImpl::DoDeleteProgram(GLuint program) {
+  GLuint service_id;
+  if (id_map_.GetServiceId(program, &service_id)) {
+    glDeleteProgram(service_id);
+    id_map_.RemoveMapping(program, service_id);
+  }
+}
+
+void GLES2DecoderImpl::DoDeleteShader(GLuint shader) {
+  GLuint service_id;
+  if (id_map_.GetServiceId(shader, &service_id)) {
+    glDeleteProgram(service_id);
+    id_map_.RemoveMapping(shader, service_id);
+  }
+}
+
+// NOTE: If you need to know the results of SwapBuffers (like losing
+//    the context) then add a new command. Do NOT make SwapBuffers synchronous.
+void GLES2DecoderImpl::DoSwapBuffers() {
+#ifdef OS_WIN
+  ::SwapBuffers(device_context_);
+#endif
+
+#ifdef OS_LINUX
+  DCHECK(window());
+  window()->SwapBuffers();
+#endif
+}
+
+GLenum GLES2DecoderImpl::GetGLError() {
+  // Check the GL error first, then our wrapped error.
+  GLenum error = glGetError();
+  if (error == GL_NO_ERROR && error_bits_ != 0) {
+    uint32 mask = 1;
+    while (mask) {
+      if ((error_bits_ & mask) != 0) {
+        error = GLErrorBitToGLError(mask);
+        break;
+      }
+    }
+  }
+
+  if (error != GL_NO_ERROR) {
+    // There was an error, clear the corresponding wrapped error.
+    error_bits_ &= ~GLErrorToErrorBit(error);
+  }
+  return error;
+}
+
+void GLES2DecoderImpl::SetGLError(GLenum error) {
+  error_bits_ |= GLErrorToErrorBit(error);
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleDrawElements(
+    unsigned int arg_count, const gles2::DrawElements& c) {
+  if (bound_element_array_buffer_ != 0) {
+    GLenum mode = c.mode;
+    GLsizei count = c.count;
+    GLenum type = c.type;
+    const GLvoid* indices = reinterpret_cast<const GLvoid*>(c.index_offset);
+    glDrawElements(mode, count, type, indices);
+  } else {
+    SetGLError(GL_INVALID_VALUE);
+  }
+  return parse_error::kParseNoError;
+}
+
+namespace {
+
+// Calls glShaderSource for the various versions of the ShaderSource command.
+// Assumes that data / data_size points to a piece of memory that is in range
+// of whatever context it came from (shared memory, immediate memory, bucket
+// memory.)
+parse_error::ParseError ShaderSourceHelper(
+    GLuint shader, GLsizei count, const char* data, uint32 data_size) {
+  std::vector<std::string> strings(count);
+  scoped_array<const char*> string_pointers(new const char* [count]);
+
+  const uint32* ends = reinterpret_cast<const uint32*>(data);
+  uint32 start_offset = count * sizeof(*ends);
+  if (start_offset > data_size) {
+    return parse_error::kParseOutOfBounds;
+  }
+  for (GLsizei ii = 0; ii < count; ++ii) {
+    uint32 end_offset = ends[ii];
+    if (end_offset > data_size || end_offset < start_offset) {
+      return parse_error::kParseOutOfBounds;
+    }
+    strings[ii] = std::string(data + start_offset, end_offset - start_offset);
+    string_pointers[ii] = strings[ii].c_str();
+  }
+
+  glShaderSource(shader, count, string_pointers.get(), NULL);
+  return parse_error::kParseNoError;
+}
+
+}  // anonymous namespace.
+
+parse_error::ParseError GLES2DecoderImpl::HandleShaderSource(
+    unsigned int arg_count, const gles2::ShaderSource& c) {
+  GLuint shader = c.shader;
+  GLsizei count = c.count;
+  uint32 data_size = c.data_size;
+  const char** data = GetSharedMemoryAs<const char**>(
+      c.data_shm_id, c.data_shm_offset, data_size);
+  parse_error::ParseError result =
+      ValidateShaderSource(this, arg_count, shader, count, data, NULL);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  return ShaderSourceHelper(
+      shader, count, reinterpret_cast<const char*>(data), data_size);
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleShaderSourceImmediate(
+  unsigned int arg_count, const gles2::ShaderSourceImmediate& c) {
+  GLuint shader = c.shader;
+  GLsizei count = c.count;
+  uint32 data_size = c.data_size;
+  // TODO(gman): need to check that data_size is in range for arg_count.
+  const char** data = GetImmediateDataAs<const char**>(c);
+  parse_error::ParseError result =
+      ValidateShaderSourceImmediate(
+          this, arg_count, shader, count, data, NULL);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  return ShaderSourceHelper(
+      shader, count, reinterpret_cast<const char*>(data), data_size);
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleVertexAttribPointer(
+    unsigned int arg_count, const gles2::VertexAttribPointer& c) {
+  if (bound_array_buffer_ != 0) {
+    GLuint indx = c.indx;
+    GLint size = c.size;
+    GLenum type = c.type;
+    GLboolean normalized = c.normalized;
+    GLsizei stride = c.stride;
+    GLuint offset = c.offset;
+    const void* ptr = reinterpret_cast<const void*>(c.offset);
+    parse_error::ParseError result =
+        ValidateVertexAttribPointer(
+            this, arg_count, indx, size, type, normalized, stride, ptr);
+    if (result != parse_error::kParseNoError) {
+      return result;
+    }
+    glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
+  } else {
+    SetGLError(GL_INVALID_VALUE);
+  }
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleReadPixels(
+    unsigned int arg_count, const gles2::ReadPixels& c) {
+  // TODO(gman): Implement.
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandlePixelStorei(
+    unsigned int arg_count, const gles2::PixelStorei& c) {
+  // TODO(gman): Implement.
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetVertexAttribPointerv(
+    unsigned int arg_count, const gles2::GetVertexAttribPointerv& c) {
+  // TODO(gman): Implement.
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetUniformiv(
+    unsigned int arg_count, const gles2::GetUniformiv& c) {
+  // TODO(gman): Implement.
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetUniformfv(
+    unsigned int arg_count, const gles2::GetUniformfv& c) {
+  // TODO(gman): Implement.
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
+    unsigned int arg_count, const gles2::GetShaderPrecisionFormat& c) {
+  // TODO(gman): Implement.
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetAttachedShaders(
+    unsigned int arg_count, const gles2::GetAttachedShaders& c) {
+  // TODO(gman): Implement.
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetActiveUniform(
+    unsigned int arg_count, const gles2::GetActiveUniform& c) {
+  // TODO(gman): Implement.
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetActiveAttrib(
+    unsigned int arg_count, const gles2::GetActiveAttrib& c) {
+  // TODO(gman): Implement.
+  return parse_error::kParseNoError;
+}
+
+// Include the auto-generated part of this file. We split this because it means
+// we can easily edit the non-auto generated parts right here in this file
+// instead of having to edit some template or the code generator.
+#include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
+
+}  // namespace gles2
+}  // namespace command_buffer
+
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.h b/gpu/command_buffer/service/gles2_cmd_decoder.h
new file mode 100644
index 0000000..10387c6b
--- /dev/null
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.h
@@ -0,0 +1,74 @@
+// Copyright (c) 2006-2009 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.
+
+// This file contains the GLES2Decoder class.
+
+#ifndef O3D_COMMAND_BUFFER_SERVICE_CROSS_GLES2_CMD_DECODER_H
+#define O3D_COMMAND_BUFFER_SERVICE_CROSS_GLES2_CMD_DECODER_H
+
+#include <build/build_config.h>
+#ifdef OS_WIN
+#include <windows.h>
+#endif
+#include "gpu/command_buffer/service/common_decoder.h"
+
+namespace command_buffer {
+namespace gles2 {
+
+// This class implements the AsyncAPIInterface interface, decoding GLES2
+// commands and calling GL.
+class GLES2Decoder : public CommonDecoder {
+ public:
+  typedef parse_error::ParseError ParseError;
+
+  // Creates a decoder.
+  static GLES2Decoder* Create();
+
+  virtual ~GLES2Decoder() {
+  }
+
+#if defined(OS_LINUX)
+  void set_window_wrapper(XWindowWrapper *window) {
+    window_ = window;
+  }
+  XWindowWrapper* window() const {
+    return window_;
+  }
+#elif defined(OS_WIN)
+  void set_hwnd(HWND hwnd) {
+    hwnd_ = hwnd;
+  }
+
+  HWND hwnd() const {
+    return hwnd_;
+  }
+#endif
+
+  // Initializes the graphics context.
+  // Returns:
+  //   true if successful.
+  virtual bool Initialize() = 0;
+
+  // Destroys the graphics context.
+  virtual void Destroy() = 0;
+
+ protected:
+  GLES2Decoder();
+
+ private:
+#if defined(OS_LINUX)
+  XWindowWrapper *window_;
+#elif defined(OS_WIN)
+  // Handle to the GL device.
+  HWND hwnd_;
+#endif
+
+  DISALLOW_COPY_AND_ASSIGN(GLES2Decoder);
+};
+
+}  // namespace gles2
+}  // namespace command_buffer
+
+#endif  // O3D_COMMAND_BUFFER_SERVICE_CROSS_GLES2_CMD_DECODER_H
+
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
new file mode 100644
index 0000000..1a247fd
--- /dev/null
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
@@ -0,0 +1,2610 @@
+// This file is auto-generated. DO NOT EDIT!
+
+// It is included by gles2_cmd_decoder.cc
+
+parse_error::ParseError GLES2DecoderImpl::HandleActiveTexture(
+    unsigned int arg_count, const gles2::ActiveTexture& c) {
+  GLenum texture = static_cast<GLenum>(c.texture);
+  parse_error::ParseError result =
+      ValidateActiveTexture(this, arg_count, texture);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glActiveTexture(texture);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleAttachShader(
+    unsigned int arg_count, const gles2::AttachShader& c) {
+  GLuint program;
+  if (!id_map_.GetServiceId(c.program, &program)) {
+    SetGLError(GL_INVALID_VALUE);
+    return parse_error::kParseNoError;
+  }
+  GLuint shader;
+  if (!id_map_.GetServiceId(c.shader, &shader)) {
+    SetGLError(GL_INVALID_VALUE);
+    return parse_error::kParseNoError;
+  }
+  parse_error::ParseError result =
+      ValidateAttachShader(this, arg_count, program, shader);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glAttachShader(program, shader);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleBindAttribLocation(
+    unsigned int arg_count, const gles2::BindAttribLocation& c) {
+  GLuint program;
+  if (!id_map_.GetServiceId(c.program, &program)) {
+    SetGLError(GL_INVALID_VALUE);
+    return parse_error::kParseNoError;
+  }
+  GLuint index = static_cast<GLuint>(c.index);
+  uint32 name_size = c.data_size;
+  const char* name = GetSharedMemoryAs<const char*>(
+      c.name_shm_id, c.name_shm_offset, name_size);
+  parse_error::ParseError result =
+      ValidateBindAttribLocation(this, arg_count, program, index, name);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  String name_str(name, name_size);
+  glBindAttribLocation(program, index, name_str.c_str());
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleBindAttribLocationImmediate(
+    unsigned int arg_count, const gles2::BindAttribLocationImmediate& c) {
+  GLuint program;
+  if (!id_map_.GetServiceId(c.program, &program)) {
+    SetGLError(GL_INVALID_VALUE);
+    return parse_error::kParseNoError;
+  }
+  GLuint index = static_cast<GLuint>(c.index);
+  uint32 name_size = c.data_size;
+  const char* name = GetImmediateDataAs<const char*>(c);
+  // TODO(gman): Make sure validate checks arg_count
+  //     covers data_size.
+  parse_error::ParseError result =
+      ValidateBindAttribLocationImmediate(
+          this, arg_count, program, index, name);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  String name_str(name, name_size);
+  glBindAttribLocation(program, index, name_str.c_str());
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleBindBuffer(
+    unsigned int arg_count, const gles2::BindBuffer& c) {
+  GLenum target = static_cast<GLenum>(c.target);
+  GLuint buffer;
+  if (!id_map_.GetServiceId(c.buffer, &buffer)) {
+    SetGLError(GL_INVALID_VALUE);
+    return parse_error::kParseNoError;
+  }
+  parse_error::ParseError result =
+      ValidateBindBuffer(this, arg_count, target, buffer);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  DoBindBuffer(target, buffer);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleBindFramebuffer(
+    unsigned int arg_count, const gles2::BindFramebuffer& c) {
+  GLenum target = static_cast<GLenum>(c.target);
+  GLuint framebuffer;
+  if (!id_map_.GetServiceId(c.framebuffer, &framebuffer)) {
+    SetGLError(GL_INVALID_VALUE);
+    return parse_error::kParseNoError;
+  }
+  parse_error::ParseError result =
+      ValidateBindFramebuffer(this, arg_count, target, framebuffer);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glBindFramebufferEXT(target, framebuffer);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleBindRenderbuffer(
+    unsigned int arg_count, const gles2::BindRenderbuffer& c) {
+  GLenum target = static_cast<GLenum>(c.target);
+  GLuint renderbuffer;
+  if (!id_map_.GetServiceId(c.renderbuffer, &renderbuffer)) {
+    SetGLError(GL_INVALID_VALUE);
+    return parse_error::kParseNoError;
+  }
+  parse_error::ParseError result =
+      ValidateBindRenderbuffer(this, arg_count, target, renderbuffer);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glBindRenderbufferEXT(target, renderbuffer);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleBindTexture(
+    unsigned int arg_count, const gles2::BindTexture& c) {
+  GLenum target = static_cast<GLenum>(c.target);
+  GLuint texture;
+  if (!id_map_.GetServiceId(c.texture, &texture)) {
+    SetGLError(GL_INVALID_VALUE);
+    return parse_error::kParseNoError;
+  }
+  parse_error::ParseError result =
+      ValidateBindTexture(this, arg_count, target, texture);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glBindTexture(target, texture);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleBlendColor(
+    unsigned int arg_count, const gles2::BlendColor& c) {
+  GLclampf red = static_cast<GLclampf>(c.red);
+  GLclampf green = static_cast<GLclampf>(c.green);
+  GLclampf blue = static_cast<GLclampf>(c.blue);
+  GLclampf alpha = static_cast<GLclampf>(c.alpha);
+  parse_error::ParseError result =
+      ValidateBlendColor(this, arg_count, red, green, blue, alpha);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glBlendColor(red, green, blue, alpha);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleBlendEquation(
+    unsigned int arg_count, const gles2::BlendEquation& c) {
+  GLenum mode = static_cast<GLenum>(c.mode);
+  parse_error::ParseError result =
+      ValidateBlendEquation(this, arg_count, mode);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glBlendEquation(mode);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleBlendEquationSeparate(
+    unsigned int arg_count, const gles2::BlendEquationSeparate& c) {
+  GLenum modeRGB = static_cast<GLenum>(c.modeRGB);
+  GLenum modeAlpha = static_cast<GLenum>(c.modeAlpha);
+  parse_error::ParseError result =
+      ValidateBlendEquationSeparate(this, arg_count, modeRGB, modeAlpha);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glBlendEquationSeparate(modeRGB, modeAlpha);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleBlendFunc(
+    unsigned int arg_count, const gles2::BlendFunc& c) {
+  GLenum sfactor = static_cast<GLenum>(c.sfactor);
+  GLenum dfactor = static_cast<GLenum>(c.dfactor);
+  parse_error::ParseError result =
+      ValidateBlendFunc(this, arg_count, sfactor, dfactor);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glBlendFunc(sfactor, dfactor);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleBlendFuncSeparate(
+    unsigned int arg_count, const gles2::BlendFuncSeparate& c) {
+  GLenum srcRGB = static_cast<GLenum>(c.srcRGB);
+  GLenum dstRGB = static_cast<GLenum>(c.dstRGB);
+  GLenum srcAlpha = static_cast<GLenum>(c.srcAlpha);
+  GLenum dstAlpha = static_cast<GLenum>(c.dstAlpha);
+  parse_error::ParseError result =
+      ValidateBlendFuncSeparate(
+          this, arg_count, srcRGB, dstRGB, srcAlpha, dstAlpha);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleBufferData(
+    unsigned int arg_count, const gles2::BufferData& c) {
+  GLenum target = static_cast<GLenum>(c.target);
+  GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
+  uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
+  uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
+  GLenum usage = static_cast<GLenum>(c.usage);
+  uint32 data_size = size;
+  const void* data = GetSharedMemoryAs<const void*>(
+      data_shm_id, data_shm_offset, data_size);
+  parse_error::ParseError result =
+      ValidateBufferData(this, arg_count, target, size, data, usage);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glBufferData(target, size, data, usage);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleBufferDataImmediate(
+    unsigned int arg_count, const gles2::BufferDataImmediate& c) {
+  GLenum target = static_cast<GLenum>(c.target);
+  GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
+  const void* data = GetImmediateDataAs<const void*>(c);
+  GLenum usage = static_cast<GLenum>(c.usage);
+  // Immediate version.
+  parse_error::ParseError result =
+      ValidateBufferDataImmediate(this, arg_count, target, size, data, usage);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glBufferData(target, size, data, usage);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleBufferSubData(
+    unsigned int arg_count, const gles2::BufferSubData& c) {
+  GLenum target = static_cast<GLenum>(c.target);
+  GLintptr offset = static_cast<GLintptr>(c.offset);
+  GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
+  uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
+  uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
+  uint32 data_size = size;
+  const void* data = GetSharedMemoryAs<const void*>(
+      data_shm_id, data_shm_offset, data_size);
+  parse_error::ParseError result =
+      ValidateBufferSubData(this, arg_count, target, offset, size, data);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glBufferSubData(target, offset, size, data);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleBufferSubDataImmediate(
+    unsigned int arg_count, const gles2::BufferSubDataImmediate& c) {
+  GLenum target = static_cast<GLenum>(c.target);
+  GLintptr offset = static_cast<GLintptr>(c.offset);
+  GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
+  const void* data = GetImmediateDataAs<const void*>(c);
+  // Immediate version.
+  parse_error::ParseError result =
+      ValidateBufferSubDataImmediate(
+          this, arg_count, target, offset, size, data);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glBufferSubData(target, offset, size, data);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleCheckFramebufferStatus(
+    unsigned int arg_count, const gles2::CheckFramebufferStatus& c) {
+  GLenum target = static_cast<GLenum>(c.target);
+  parse_error::ParseError result =
+      ValidateCheckFramebufferStatus(this, arg_count, target);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glCheckFramebufferStatusEXT(target);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleClear(
+    unsigned int arg_count, const gles2::Clear& c) {
+  GLbitfield mask = static_cast<GLbitfield>(c.mask);
+  parse_error::ParseError result =
+      ValidateClear(this, arg_count, mask);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glClear(mask);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleClearColor(
+    unsigned int arg_count, const gles2::ClearColor& c) {
+  GLclampf red = static_cast<GLclampf>(c.red);
+  GLclampf green = static_cast<GLclampf>(c.green);
+  GLclampf blue = static_cast<GLclampf>(c.blue);
+  GLclampf alpha = static_cast<GLclampf>(c.alpha);
+  parse_error::ParseError result =
+      ValidateClearColor(this, arg_count, red, green, blue, alpha);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glClearColor(red, green, blue, alpha);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleClearDepthf(
+    unsigned int arg_count, const gles2::ClearDepthf& c) {
+  GLclampf depth = static_cast<GLclampf>(c.depth);
+  parse_error::ParseError result =
+      ValidateClearDepthf(this, arg_count, depth);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glClearDepth(depth);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleClearStencil(
+    unsigned int arg_count, const gles2::ClearStencil& c) {
+  GLint s = static_cast<GLint>(c.s);
+  parse_error::ParseError result =
+      ValidateClearStencil(this, arg_count, s);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glClearStencil(s);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleColorMask(
+    unsigned int arg_count, const gles2::ColorMask& c) {
+  GLboolean red = static_cast<GLboolean>(c.red);
+  GLboolean green = static_cast<GLboolean>(c.green);
+  GLboolean blue = static_cast<GLboolean>(c.blue);
+  GLboolean alpha = static_cast<GLboolean>(c.alpha);
+  parse_error::ParseError result =
+      ValidateColorMask(this, arg_count, red, green, blue, alpha);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glColorMask(red, green, blue, alpha);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleCompileShader(
+    unsigned int arg_count, const gles2::CompileShader& c) {
+  GLuint shader;
+  if (!id_map_.GetServiceId(c.shader, &shader)) {
+    SetGLError(GL_INVALID_VALUE);
+    return parse_error::kParseNoError;
+  }
+  parse_error::ParseError result =
+      ValidateCompileShader(this, arg_count, shader);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glCompileShader(shader);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleCompressedTexImage2D(
+    unsigned int arg_count, const gles2::CompressedTexImage2D& c) {
+  GLenum target = static_cast<GLenum>(c.target);
+  GLint level = static_cast<GLint>(c.level);
+  GLenum internalformat = static_cast<GLenum>(c.internalformat);
+  GLsizei width = static_cast<GLsizei>(c.width);
+  GLsizei height = static_cast<GLsizei>(c.height);
+  GLint border = static_cast<GLint>(c.border);
+  GLsizei imageSize = static_cast<GLsizei>(c.imageSize);
+  uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
+  uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
+  uint32 data_size = imageSize;
+  const void* data = GetSharedMemoryAs<const void*>(
+      data_shm_id, data_shm_offset, data_size);
+  parse_error::ParseError result =
+      ValidateCompressedTexImage2D(
+          this, arg_count, target, level, internalformat, width, height, border,
+          imageSize, data);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glCompressedTexImage2D(
+      target, level, internalformat, width, height, border, imageSize, data);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleCompressedTexImage2DImmediate(
+    unsigned int arg_count, const gles2::CompressedTexImage2DImmediate& c) {
+  GLenum target = static_cast<GLenum>(c.target);
+  GLint level = static_cast<GLint>(c.level);
+  GLenum internalformat = static_cast<GLenum>(c.internalformat);
+  GLsizei width = static_cast<GLsizei>(c.width);
+  GLsizei height = static_cast<GLsizei>(c.height);
+  GLint border = static_cast<GLint>(c.border);
+  GLsizei imageSize = static_cast<GLsizei>(c.imageSize);
+  const void* data = GetImmediateDataAs<const void*>(c);
+  // Immediate version.
+  parse_error::ParseError result =
+      ValidateCompressedTexImage2DImmediate(
+          this, arg_count, target, level, internalformat, width, height, border,
+          imageSize, data);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glCompressedTexImage2D(
+      target, level, internalformat, width, height, border, imageSize, data);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleCompressedTexSubImage2D(
+    unsigned int arg_count, const gles2::CompressedTexSubImage2D& c) {
+  GLenum target = static_cast<GLenum>(c.target);
+  GLint level = static_cast<GLint>(c.level);
+  GLint xoffset = static_cast<GLint>(c.xoffset);
+  GLint yoffset = static_cast<GLint>(c.yoffset);
+  GLsizei width = static_cast<GLsizei>(c.width);
+  GLsizei height = static_cast<GLsizei>(c.height);
+  GLenum format = static_cast<GLenum>(c.format);
+  GLsizei imageSize = static_cast<GLsizei>(c.imageSize);
+  uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
+  uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
+  uint32 data_size = imageSize;
+  const void* data = GetSharedMemoryAs<const void*>(
+      data_shm_id, data_shm_offset, data_size);
+  parse_error::ParseError result =
+      ValidateCompressedTexSubImage2D(
+          this, arg_count, target, level, xoffset, yoffset, width, height,
+          format, imageSize, data);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glCompressedTexSubImage2D(
+      target, level, xoffset, yoffset, width, height, format, imageSize, data);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleCompressedTexSubImage2DImmediate(
+    
+    unsigned int arg_count, const gles2::CompressedTexSubImage2DImmediate& c) {
+  GLenum target = static_cast<GLenum>(c.target);
+  GLint level = static_cast<GLint>(c.level);
+  GLint xoffset = static_cast<GLint>(c.xoffset);
+  GLint yoffset = static_cast<GLint>(c.yoffset);
+  GLsizei width = static_cast<GLsizei>(c.width);
+  GLsizei height = static_cast<GLsizei>(c.height);
+  GLenum format = static_cast<GLenum>(c.format);
+  GLsizei imageSize = static_cast<GLsizei>(c.imageSize);
+  const void* data = GetImmediateDataAs<const void*>(c);
+  // Immediate version.
+  parse_error::ParseError result =
+      ValidateCompressedTexSubImage2DImmediate(
+          this, arg_count, target, level, xoffset, yoffset, width, height,
+          format, imageSize, data);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glCompressedTexSubImage2D(
+      target, level, xoffset, yoffset, width, height, format, imageSize, data);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleCopyTexImage2D(
+    unsigned int arg_count, const gles2::CopyTexImage2D& c) {
+  GLenum target = static_cast<GLenum>(c.target);
+  GLint level = static_cast<GLint>(c.level);
+  GLenum internalformat = static_cast<GLenum>(c.internalformat);
+  GLint x = static_cast<GLint>(c.x);
+  GLint y = static_cast<GLint>(c.y);
+  GLsizei width = static_cast<GLsizei>(c.width);
+  GLsizei height = static_cast<GLsizei>(c.height);
+  GLint border = static_cast<GLint>(c.border);
+  parse_error::ParseError result =
+      ValidateCopyTexImage2D(
+          this, arg_count, target, level, internalformat, x, y, width, height,
+          border);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glCopyTexImage2D(target, level, internalformat, x, y, width, height, border);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleCopyTexSubImage2D(
+    unsigned int arg_count, const gles2::CopyTexSubImage2D& c) {
+  GLenum target = static_cast<GLenum>(c.target);
+  GLint level = static_cast<GLint>(c.level);
+  GLint xoffset = static_cast<GLint>(c.xoffset);
+  GLint yoffset = static_cast<GLint>(c.yoffset);
+  GLint x = static_cast<GLint>(c.x);
+  GLint y = static_cast<GLint>(c.y);
+  GLsizei width = static_cast<GLsizei>(c.width);
+  GLsizei height = static_cast<GLsizei>(c.height);
+  parse_error::ParseError result =
+      ValidateCopyTexSubImage2D(
+          this, arg_count, target, level, xoffset, yoffset, x, y, width,
+          height);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleCreateProgram(
+    unsigned int arg_count, const gles2::CreateProgram& c) {
+  uint32 client_id = c.client_id;
+  parse_error::ParseError result =
+      ValidateCreateProgram(this, arg_count);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  CreateProgramHelper(client_id);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleCreateShader(
+    unsigned int arg_count, const gles2::CreateShader& c) {
+  GLenum type = static_cast<GLenum>(c.type);
+  uint32 client_id = c.client_id;
+  parse_error::ParseError result =
+      ValidateCreateShader(this, arg_count, type);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  CreateShaderHelper(type, client_id);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleCullFace(
+    unsigned int arg_count, const gles2::CullFace& c) {
+  GLenum mode = static_cast<GLenum>(c.mode);
+  parse_error::ParseError result =
+      ValidateCullFace(this, arg_count, mode);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glCullFace(mode);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleDeleteBuffers(
+    unsigned int arg_count, const gles2::DeleteBuffers& c) {
+  GLsizei n = static_cast<GLsizei>(c.n);
+  const GLuint* buffers = GetSharedMemoryAs<const GLuint*>(
+      c.buffers_shm_id, c.buffers_shm_offset, 0 /* TODO(gman): size */);
+  parse_error::ParseError result =
+      ValidateDeleteBuffers(this, arg_count, n, buffers);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  DeleteGLObjects<GLDeleteBuffersHelper>(n, buffers);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleDeleteBuffersImmediate(
+    unsigned int arg_count, const gles2::DeleteBuffersImmediate& c) {
+  GLsizei n = static_cast<GLsizei>(c.n);
+  const GLuint* buffers = GetImmediateDataAs<const GLuint*>(c);
+  parse_error::ParseError result =
+      ValidateDeleteBuffersImmediate(this, arg_count, n, buffers);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  DeleteGLObjects<GLDeleteBuffersHelper>(n, buffers);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleDeleteFramebuffers(
+    unsigned int arg_count, const gles2::DeleteFramebuffers& c) {
+  GLsizei n = static_cast<GLsizei>(c.n);
+  const GLuint* framebuffers = GetSharedMemoryAs<const GLuint*>(
+      c.framebuffers_shm_id, c.framebuffers_shm_offset, 0 /* TODO(
+          gman): size */);
+  parse_error::ParseError result =
+      ValidateDeleteFramebuffers(this, arg_count, n, framebuffers);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  DeleteGLObjects<GLDeleteFramebuffersHelper>(n, framebuffers);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleDeleteFramebuffersImmediate(
+    unsigned int arg_count, const gles2::DeleteFramebuffersImmediate& c) {
+  GLsizei n = static_cast<GLsizei>(c.n);
+  const GLuint* framebuffers = GetImmediateDataAs<const GLuint*>(c);
+  parse_error::ParseError result =
+      ValidateDeleteFramebuffersImmediate(this, arg_count, n, framebuffers);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  DeleteGLObjects<GLDeleteFramebuffersHelper>(n, framebuffers);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleDeleteProgram(
+    unsigned int arg_count, const gles2::DeleteProgram& c) {
+  GLuint program;
+  if (!id_map_.GetServiceId(c.program, &program)) {
+    SetGLError(GL_INVALID_VALUE);
+    return parse_error::kParseNoError;
+  }
+  parse_error::ParseError result =
+      ValidateDeleteProgram(this, arg_count, program);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  DoDeleteProgram(program);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleDeleteRenderbuffers(
+    unsigned int arg_count, const gles2::DeleteRenderbuffers& c) {
+  GLsizei n = static_cast<GLsizei>(c.n);
+  const GLuint* renderbuffers = GetSharedMemoryAs<const GLuint*>(
+      c.renderbuffers_shm_id, c.renderbuffers_shm_offset, 0 /* TODO(
+          gman): size */);
+  parse_error::ParseError result =
+      ValidateDeleteRenderbuffers(this, arg_count, n, renderbuffers);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  DeleteGLObjects<GLDeleteRenderbuffersHelper>(n, renderbuffers);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleDeleteRenderbuffersImmediate(
+    unsigned int arg_count, const gles2::DeleteRenderbuffersImmediate& c) {
+  GLsizei n = static_cast<GLsizei>(c.n);
+  const GLuint* renderbuffers = GetImmediateDataAs<const GLuint*>(c);
+  parse_error::ParseError result =
+      ValidateDeleteRenderbuffersImmediate(this, arg_count, n, renderbuffers);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  DeleteGLObjects<GLDeleteRenderbuffersHelper>(n, renderbuffers);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleDeleteShader(
+    unsigned int arg_count, const gles2::DeleteShader& c) {
+  GLuint shader;
+  if (!id_map_.GetServiceId(c.shader, &shader)) {
+    SetGLError(GL_INVALID_VALUE);
+    return parse_error::kParseNoError;
+  }
+  parse_error::ParseError result =
+      ValidateDeleteShader(this, arg_count, shader);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  DoDeleteShader(shader);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleDeleteTextures(
+    unsigned int arg_count, const gles2::DeleteTextures& c) {
+  GLsizei n = static_cast<GLsizei>(c.n);
+  const GLuint* textures = GetSharedMemoryAs<const GLuint*>(
+      c.textures_shm_id, c.textures_shm_offset, 0 /* TODO(gman): size */);
+  parse_error::ParseError result =
+      ValidateDeleteTextures(this, arg_count, n, textures);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  DeleteGLObjects<GLDeleteTexturesHelper>(n, textures);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleDeleteTexturesImmediate(
+    unsigned int arg_count, const gles2::DeleteTexturesImmediate& c) {
+  GLsizei n = static_cast<GLsizei>(c.n);
+  const GLuint* textures = GetImmediateDataAs<const GLuint*>(c);
+  parse_error::ParseError result =
+      ValidateDeleteTexturesImmediate(this, arg_count, n, textures);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  DeleteGLObjects<GLDeleteTexturesHelper>(n, textures);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleDepthFunc(
+    unsigned int arg_count, const gles2::DepthFunc& c) {
+  GLenum func = static_cast<GLenum>(c.func);
+  parse_error::ParseError result =
+      ValidateDepthFunc(this, arg_count, func);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glDepthFunc(func);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleDepthMask(
+    unsigned int arg_count, const gles2::DepthMask& c) {
+  GLboolean flag = static_cast<GLboolean>(c.flag);
+  parse_error::ParseError result =
+      ValidateDepthMask(this, arg_count, flag);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glDepthMask(flag);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleDepthRangef(
+    unsigned int arg_count, const gles2::DepthRangef& c) {
+  GLclampf zNear = static_cast<GLclampf>(c.zNear);
+  GLclampf zFar = static_cast<GLclampf>(c.zFar);
+  parse_error::ParseError result =
+      ValidateDepthRangef(this, arg_count, zNear, zFar);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glDepthRange(zNear, zFar);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleDetachShader(
+    unsigned int arg_count, const gles2::DetachShader& c) {
+  GLuint program;
+  if (!id_map_.GetServiceId(c.program, &program)) {
+    SetGLError(GL_INVALID_VALUE);
+    return parse_error::kParseNoError;
+  }
+  GLuint shader;
+  if (!id_map_.GetServiceId(c.shader, &shader)) {
+    SetGLError(GL_INVALID_VALUE);
+    return parse_error::kParseNoError;
+  }
+  parse_error::ParseError result =
+      ValidateDetachShader(this, arg_count, program, shader);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glDetachShader(program, shader);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleDisable(
+    unsigned int arg_count, const gles2::Disable& c) {
+  GLenum cap = static_cast<GLenum>(c.cap);
+  parse_error::ParseError result =
+      ValidateDisable(this, arg_count, cap);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glDisable(cap);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleDisableVertexAttribArray(
+    unsigned int arg_count, const gles2::DisableVertexAttribArray& c) {
+  GLuint index = static_cast<GLuint>(c.index);
+  parse_error::ParseError result =
+      ValidateDisableVertexAttribArray(this, arg_count, index);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glDisableVertexAttribArray(index);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleDrawArrays(
+    unsigned int arg_count, const gles2::DrawArrays& c) {
+  GLenum mode = static_cast<GLenum>(c.mode);
+  GLint first = static_cast<GLint>(c.first);
+  GLsizei count = static_cast<GLsizei>(c.count);
+  parse_error::ParseError result =
+      ValidateDrawArrays(this, arg_count, mode, first, count);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glDrawArrays(mode, first, count);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleEnable(
+    unsigned int arg_count, const gles2::Enable& c) {
+  GLenum cap = static_cast<GLenum>(c.cap);
+  parse_error::ParseError result =
+      ValidateEnable(this, arg_count, cap);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glEnable(cap);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleEnableVertexAttribArray(
+    unsigned int arg_count, const gles2::EnableVertexAttribArray& c) {
+  GLuint index = static_cast<GLuint>(c.index);
+  parse_error::ParseError result =
+      ValidateEnableVertexAttribArray(this, arg_count, index);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glEnableVertexAttribArray(index);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleFinish(
+    unsigned int arg_count, const gles2::Finish& c) {
+  parse_error::ParseError result =
+      ValidateFinish(this, arg_count);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glFinish();
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleFlush(
+    unsigned int arg_count, const gles2::Flush& c) {
+  parse_error::ParseError result =
+      ValidateFlush(this, arg_count);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glFlush();
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleFramebufferRenderbuffer(
+    unsigned int arg_count, const gles2::FramebufferRenderbuffer& c) {
+  GLenum target = static_cast<GLenum>(c.target);
+  GLenum attachment = static_cast<GLenum>(c.attachment);
+  GLenum renderbuffertarget = static_cast<GLenum>(c.renderbuffertarget);
+  GLuint renderbuffer;
+  if (!id_map_.GetServiceId(c.renderbuffer, &renderbuffer)) {
+    SetGLError(GL_INVALID_VALUE);
+    return parse_error::kParseNoError;
+  }
+  parse_error::ParseError result =
+      ValidateFramebufferRenderbuffer(
+          this, arg_count, target, attachment, renderbuffertarget,
+          renderbuffer);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glFramebufferRenderbufferEXT(
+      target, attachment, renderbuffertarget, renderbuffer);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleFramebufferTexture2D(
+    unsigned int arg_count, const gles2::FramebufferTexture2D& c) {
+  GLenum target = static_cast<GLenum>(c.target);
+  GLenum attachment = static_cast<GLenum>(c.attachment);
+  GLenum textarget = static_cast<GLenum>(c.textarget);
+  GLuint texture;
+  if (!id_map_.GetServiceId(c.texture, &texture)) {
+    SetGLError(GL_INVALID_VALUE);
+    return parse_error::kParseNoError;
+  }
+  GLint level = static_cast<GLint>(c.level);
+  parse_error::ParseError result =
+      ValidateFramebufferTexture2D(
+          this, arg_count, target, attachment, textarget, texture, level);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glFramebufferTexture2DEXT(target, attachment, textarget, texture, level);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleFrontFace(
+    unsigned int arg_count, const gles2::FrontFace& c) {
+  GLenum mode = static_cast<GLenum>(c.mode);
+  parse_error::ParseError result =
+      ValidateFrontFace(this, arg_count, mode);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glFrontFace(mode);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGenBuffers(
+    unsigned int arg_count, const gles2::GenBuffers& c) {
+  GLsizei n = static_cast<GLsizei>(c.n);
+  GLuint* buffers = GetSharedMemoryAs<GLuint*>(
+      c.buffers_shm_id, c.buffers_shm_offset, 0 /* TODO(gman): size */);
+  parse_error::ParseError result =
+      ValidateGenBuffers(this, arg_count, n, buffers);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  GenGLObjects<GLGenBuffersHelper>(n, buffers);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGenBuffersImmediate(
+    unsigned int arg_count, const gles2::GenBuffersImmediate& c) {
+  GLsizei n = static_cast<GLsizei>(c.n);
+  GLuint* buffers = GetImmediateDataAs<GLuint*>(c);
+  parse_error::ParseError result =
+      ValidateGenBuffersImmediate(this, arg_count, n, buffers);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  GenGLObjects<GLGenBuffersHelper>(n, buffers);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGenerateMipmap(
+    unsigned int arg_count, const gles2::GenerateMipmap& c) {
+  GLenum target = static_cast<GLenum>(c.target);
+  parse_error::ParseError result =
+      ValidateGenerateMipmap(this, arg_count, target);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glGenerateMipmapEXT(target);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGenFramebuffers(
+    unsigned int arg_count, const gles2::GenFramebuffers& c) {
+  GLsizei n = static_cast<GLsizei>(c.n);
+  GLuint* framebuffers = GetSharedMemoryAs<GLuint*>(
+      c.framebuffers_shm_id, c.framebuffers_shm_offset, 0 /* TODO(
+          gman): size */);
+  parse_error::ParseError result =
+      ValidateGenFramebuffers(this, arg_count, n, framebuffers);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  GenGLObjects<GLGenFramebuffersHelper>(n, framebuffers);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGenFramebuffersImmediate(
+    unsigned int arg_count, const gles2::GenFramebuffersImmediate& c) {
+  GLsizei n = static_cast<GLsizei>(c.n);
+  GLuint* framebuffers = GetImmediateDataAs<GLuint*>(c);
+  parse_error::ParseError result =
+      ValidateGenFramebuffersImmediate(this, arg_count, n, framebuffers);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  GenGLObjects<GLGenFramebuffersHelper>(n, framebuffers);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGenRenderbuffers(
+    unsigned int arg_count, const gles2::GenRenderbuffers& c) {
+  GLsizei n = static_cast<GLsizei>(c.n);
+  GLuint* renderbuffers = GetSharedMemoryAs<GLuint*>(
+      c.renderbuffers_shm_id, c.renderbuffers_shm_offset, 0 /* TODO(
+          gman): size */);
+  parse_error::ParseError result =
+      ValidateGenRenderbuffers(this, arg_count, n, renderbuffers);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  GenGLObjects<GLGenRenderbuffersHelper>(n, renderbuffers);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGenRenderbuffersImmediate(
+    unsigned int arg_count, const gles2::GenRenderbuffersImmediate& c) {
+  GLsizei n = static_cast<GLsizei>(c.n);
+  GLuint* renderbuffers = GetImmediateDataAs<GLuint*>(c);
+  parse_error::ParseError result =
+      ValidateGenRenderbuffersImmediate(this, arg_count, n, renderbuffers);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  GenGLObjects<GLGenRenderbuffersHelper>(n, renderbuffers);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGenTextures(
+    unsigned int arg_count, const gles2::GenTextures& c) {
+  GLsizei n = static_cast<GLsizei>(c.n);
+  GLuint* textures = GetSharedMemoryAs<GLuint*>(
+      c.textures_shm_id, c.textures_shm_offset, 0 /* TODO(gman): size */);
+  parse_error::ParseError result =
+      ValidateGenTextures(this, arg_count, n, textures);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  GenGLObjects<GLGenTexturesHelper>(n, textures);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGenTexturesImmediate(
+    unsigned int arg_count, const gles2::GenTexturesImmediate& c) {
+  GLsizei n = static_cast<GLsizei>(c.n);
+  GLuint* textures = GetImmediateDataAs<GLuint*>(c);
+  parse_error::ParseError result =
+      ValidateGenTexturesImmediate(this, arg_count, n, textures);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  GenGLObjects<GLGenTexturesHelper>(n, textures);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetAttribLocation(
+    unsigned int arg_count, const gles2::GetAttribLocation& c) {
+  GLuint program;
+  if (!id_map_.GetServiceId(c.program, &program)) {
+    SetGLError(GL_INVALID_VALUE);
+    return parse_error::kParseNoError;
+  }
+  uint32 name_size = c.data_size;
+  const char* name = GetSharedMemoryAs<const char*>(
+      c.name_shm_id, c.name_shm_offset, name_size);
+  parse_error::ParseError result =
+      ValidateGetAttribLocation(this, arg_count, program, name);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  String name_str(name, name_size);
+  GLint location = glGetAttribLocation(program, name_str.c_str());
+  DCHECK(false);  // TODO: return result.
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetAttribLocationImmediate(
+    unsigned int arg_count, const gles2::GetAttribLocationImmediate& c) {
+  GLuint program;
+  if (!id_map_.GetServiceId(c.program, &program)) {
+    SetGLError(GL_INVALID_VALUE);
+    return parse_error::kParseNoError;
+  }
+  uint32 name_size = c.data_size;
+  const char* name = GetImmediateDataAs<const char*>(c);
+  // TODO(gman): Make sure validate checks arg_count
+  //     covers data_size.
+  parse_error::ParseError result =
+      ValidateGetAttribLocationImmediate(this, arg_count, program, name);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  String name_str(name, name_size);
+  GLint location = glGetAttribLocation(program, name_str.c_str());
+  DCHECK(false);  // TODO: return result.
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetBooleanv(
+    unsigned int arg_count, const gles2::GetBooleanv& c) {
+  GLenum pname = static_cast<GLenum>(c.pname);
+  GLboolean* params;
+  GLsizei num_values = util_.GLGetNumValuesReturned(pname);
+  uint32 params_size = num_values * sizeof(*params);
+  params = GetSharedMemoryAs<GLboolean*>(
+      c.params_shm_id, c.params_shm_offset, params_size);
+  parse_error::ParseError result =
+      ValidateGetBooleanv(this, arg_count, pname, params);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glGetBooleanv(pname, params);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetBufferParameteriv(
+    unsigned int arg_count, const gles2::GetBufferParameteriv& c) {
+  GLenum target = static_cast<GLenum>(c.target);
+  GLenum pname = static_cast<GLenum>(c.pname);
+  GLint* params;
+  GLsizei num_values = util_.GLGetNumValuesReturned(pname);
+  uint32 params_size = num_values * sizeof(*params);
+  params = GetSharedMemoryAs<GLint*>(
+      c.params_shm_id, c.params_shm_offset, params_size);
+  parse_error::ParseError result =
+      ValidateGetBufferParameteriv(this, arg_count, target, pname, params);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glGetBufferParameteriv(target, pname, params);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetError(
+    unsigned int arg_count, const gles2::GetError& c) {
+  GLenum* result_dst = GetSharedMemoryAs<GLenum*>(
+      c.result_shm_id, c.result_shm_offset, sizeof(*result_dst));
+  parse_error::ParseError result =
+      ValidateGetError(this, arg_count);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  *result_dst = glGetError();
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetFloatv(
+    unsigned int arg_count, const gles2::GetFloatv& c) {
+  GLenum pname = static_cast<GLenum>(c.pname);
+  GLfloat* params;
+  GLsizei num_values = util_.GLGetNumValuesReturned(pname);
+  uint32 params_size = num_values * sizeof(*params);
+  params = GetSharedMemoryAs<GLfloat*>(
+      c.params_shm_id, c.params_shm_offset, params_size);
+  parse_error::ParseError result =
+      ValidateGetFloatv(this, arg_count, pname, params);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glGetFloatv(pname, params);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetFramebufferAttachmentParameteriv(
+    
+    unsigned int arg_count,
+    const gles2::GetFramebufferAttachmentParameteriv& c) {
+  GLenum target = static_cast<GLenum>(c.target);
+  GLenum attachment = static_cast<GLenum>(c.attachment);
+  GLenum pname = static_cast<GLenum>(c.pname);
+  GLint* params;
+  GLsizei num_values = util_.GLGetNumValuesReturned(pname);
+  uint32 params_size = num_values * sizeof(*params);
+  params = GetSharedMemoryAs<GLint*>(
+      c.params_shm_id, c.params_shm_offset, params_size);
+  parse_error::ParseError result =
+      ValidateGetFramebufferAttachmentParameteriv(
+          this, arg_count, target, attachment, pname, params);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetIntegerv(
+    unsigned int arg_count, const gles2::GetIntegerv& c) {
+  GLenum pname = static_cast<GLenum>(c.pname);
+  GLint* params;
+  GLsizei num_values = util_.GLGetNumValuesReturned(pname);
+  uint32 params_size = num_values * sizeof(*params);
+  params = GetSharedMemoryAs<GLint*>(
+      c.params_shm_id, c.params_shm_offset, params_size);
+  parse_error::ParseError result =
+      ValidateGetIntegerv(this, arg_count, pname, params);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glGetIntegerv(pname, params);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetProgramiv(
+    unsigned int arg_count, const gles2::GetProgramiv& c) {
+  GLuint program;
+  if (!id_map_.GetServiceId(c.program, &program)) {
+    SetGLError(GL_INVALID_VALUE);
+    return parse_error::kParseNoError;
+  }
+  GLenum pname = static_cast<GLenum>(c.pname);
+  GLint* params;
+  GLsizei num_values = util_.GLGetNumValuesReturned(pname);
+  uint32 params_size = num_values * sizeof(*params);
+  params = GetSharedMemoryAs<GLint*>(
+      c.params_shm_id, c.params_shm_offset, params_size);
+  parse_error::ParseError result =
+      ValidateGetProgramiv(this, arg_count, program, pname, params);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glGetProgramiv(program, pname, params);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetProgramInfoLog(
+    unsigned int arg_count, const gles2::GetProgramInfoLog& c) {
+  GLuint program;
+  if (!id_map_.GetServiceId(c.program, &program)) {
+    SetGLError(GL_INVALID_VALUE);
+    return parse_error::kParseNoError;
+  }
+  GLsizei bufsize = static_cast<GLsizei>(c.bufsize);
+  GLsizei* length = GetSharedMemoryAs<GLsizei*>(
+      c.length_shm_id, c.length_shm_offset, 0 /* TODO(gman): size */);
+  char* infolog = GetSharedMemoryAs<char*>(
+      c.infolog_shm_id, c.infolog_shm_offset, 0 /* TODO(gman): size */);
+  parse_error::ParseError result =
+      ValidateGetProgramInfoLog(
+          this, arg_count, program, bufsize, length, infolog);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glGetProgramInfoLog(program, bufsize, length, infolog);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetRenderbufferParameteriv(
+    unsigned int arg_count, const gles2::GetRenderbufferParameteriv& c) {
+  GLenum target = static_cast<GLenum>(c.target);
+  GLenum pname = static_cast<GLenum>(c.pname);
+  GLint* params;
+  GLsizei num_values = util_.GLGetNumValuesReturned(pname);
+  uint32 params_size = num_values * sizeof(*params);
+  params = GetSharedMemoryAs<GLint*>(
+      c.params_shm_id, c.params_shm_offset, params_size);
+  parse_error::ParseError result =
+      ValidateGetRenderbufferParameteriv(
+          this, arg_count, target, pname, params);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glGetRenderbufferParameterivEXT(target, pname, params);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetShaderiv(
+    unsigned int arg_count, const gles2::GetShaderiv& c) {
+  GLuint shader;
+  if (!id_map_.GetServiceId(c.shader, &shader)) {
+    SetGLError(GL_INVALID_VALUE);
+    return parse_error::kParseNoError;
+  }
+  GLenum pname = static_cast<GLenum>(c.pname);
+  GLint* params;
+  GLsizei num_values = util_.GLGetNumValuesReturned(pname);
+  uint32 params_size = num_values * sizeof(*params);
+  params = GetSharedMemoryAs<GLint*>(
+      c.params_shm_id, c.params_shm_offset, params_size);
+  parse_error::ParseError result =
+      ValidateGetShaderiv(this, arg_count, shader, pname, params);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glGetShaderiv(shader, pname, params);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetShaderInfoLog(
+    unsigned int arg_count, const gles2::GetShaderInfoLog& c) {
+  GLuint shader;
+  if (!id_map_.GetServiceId(c.shader, &shader)) {
+    SetGLError(GL_INVALID_VALUE);
+    return parse_error::kParseNoError;
+  }
+  GLsizei bufsize = static_cast<GLsizei>(c.bufsize);
+  GLsizei* length = GetSharedMemoryAs<GLsizei*>(
+      c.length_shm_id, c.length_shm_offset, 0 /* TODO(gman): size */);
+  char* infolog = GetSharedMemoryAs<char*>(
+      c.infolog_shm_id, c.infolog_shm_offset, 0 /* TODO(gman): size */);
+  parse_error::ParseError result =
+      ValidateGetShaderInfoLog(
+          this, arg_count, shader, bufsize, length, infolog);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glGetShaderInfoLog(shader, bufsize, length, infolog);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetShaderSource(
+    unsigned int arg_count, const gles2::GetShaderSource& c) {
+  GLuint shader;
+  if (!id_map_.GetServiceId(c.shader, &shader)) {
+    SetGLError(GL_INVALID_VALUE);
+    return parse_error::kParseNoError;
+  }
+  GLsizei bufsize = static_cast<GLsizei>(c.bufsize);
+  GLsizei* length = GetSharedMemoryAs<GLsizei*>(
+      c.length_shm_id, c.length_shm_offset, 0 /* TODO(gman): size */);
+  char* source = GetSharedMemoryAs<char*>(
+      c.source_shm_id, c.source_shm_offset, 0 /* TODO(gman): size */);
+  parse_error::ParseError result =
+      ValidateGetShaderSource(
+          this, arg_count, shader, bufsize, length, source);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glGetShaderSource(shader, bufsize, length, source);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetString(
+    unsigned int arg_count, const gles2::GetString& c) {
+  GLenum name = static_cast<GLenum>(c.name);
+  parse_error::ParseError result =
+      ValidateGetString(this, arg_count, name);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glGetString(name);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetTexParameterfv(
+    unsigned int arg_count, const gles2::GetTexParameterfv& c) {
+  GLenum target = static_cast<GLenum>(c.target);
+  GLenum pname = static_cast<GLenum>(c.pname);
+  GLfloat* params;
+  GLsizei num_values = util_.GLGetNumValuesReturned(pname);
+  uint32 params_size = num_values * sizeof(*params);
+  params = GetSharedMemoryAs<GLfloat*>(
+      c.params_shm_id, c.params_shm_offset, params_size);
+  parse_error::ParseError result =
+      ValidateGetTexParameterfv(this, arg_count, target, pname, params);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glGetTexParameterfv(target, pname, params);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetTexParameteriv(
+    unsigned int arg_count, const gles2::GetTexParameteriv& c) {
+  GLenum target = static_cast<GLenum>(c.target);
+  GLenum pname = static_cast<GLenum>(c.pname);
+  GLint* params;
+  GLsizei num_values = util_.GLGetNumValuesReturned(pname);
+  uint32 params_size = num_values * sizeof(*params);
+  params = GetSharedMemoryAs<GLint*>(
+      c.params_shm_id, c.params_shm_offset, params_size);
+  parse_error::ParseError result =
+      ValidateGetTexParameteriv(this, arg_count, target, pname, params);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glGetTexParameteriv(target, pname, params);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetUniformLocation(
+    unsigned int arg_count, const gles2::GetUniformLocation& c) {
+  GLuint program;
+  if (!id_map_.GetServiceId(c.program, &program)) {
+    SetGLError(GL_INVALID_VALUE);
+    return parse_error::kParseNoError;
+  }
+  uint32 name_size = c.data_size;
+  const char* name = GetSharedMemoryAs<const char*>(
+      c.name_shm_id, c.name_shm_offset, name_size);
+  parse_error::ParseError result =
+      ValidateGetUniformLocation(this, arg_count, program, name);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  String name_str(name, name_size);
+  GLint location = glGetUniformLocation(program, name_str.c_str());
+  DCHECK(false);  // TODO: return result.
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetUniformLocationImmediate(
+    unsigned int arg_count, const gles2::GetUniformLocationImmediate& c) {
+  GLuint program;
+  if (!id_map_.GetServiceId(c.program, &program)) {
+    SetGLError(GL_INVALID_VALUE);
+    return parse_error::kParseNoError;
+  }
+  uint32 name_size = c.data_size;
+  const char* name = GetImmediateDataAs<const char*>(c);
+  // TODO(gman): Make sure validate checks arg_count
+  //     covers data_size.
+  parse_error::ParseError result =
+      ValidateGetUniformLocationImmediate(this, arg_count, program, name);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  String name_str(name, name_size);
+  GLint location = glGetUniformLocation(program, name_str.c_str());
+  DCHECK(false);  // TODO: return result.
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetVertexAttribfv(
+    unsigned int arg_count, const gles2::GetVertexAttribfv& c) {
+  GLuint index = static_cast<GLuint>(c.index);
+  GLenum pname = static_cast<GLenum>(c.pname);
+  GLfloat* params;
+  GLsizei num_values = util_.GLGetNumValuesReturned(pname);
+  uint32 params_size = num_values * sizeof(*params);
+  params = GetSharedMemoryAs<GLfloat*>(
+      c.params_shm_id, c.params_shm_offset, params_size);
+  parse_error::ParseError result =
+      ValidateGetVertexAttribfv(this, arg_count, index, pname, params);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glGetVertexAttribfv(index, pname, params);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetVertexAttribiv(
+    unsigned int arg_count, const gles2::GetVertexAttribiv& c) {
+  GLuint index = static_cast<GLuint>(c.index);
+  GLenum pname = static_cast<GLenum>(c.pname);
+  GLint* params;
+  GLsizei num_values = util_.GLGetNumValuesReturned(pname);
+  uint32 params_size = num_values * sizeof(*params);
+  params = GetSharedMemoryAs<GLint*>(
+      c.params_shm_id, c.params_shm_offset, params_size);
+  parse_error::ParseError result =
+      ValidateGetVertexAttribiv(this, arg_count, index, pname, params);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glGetVertexAttribiv(index, pname, params);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleHint(
+    unsigned int arg_count, const gles2::Hint& c) {
+  GLenum target = static_cast<GLenum>(c.target);
+  GLenum mode = static_cast<GLenum>(c.mode);
+  parse_error::ParseError result =
+      ValidateHint(this, arg_count, target, mode);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glHint(target, mode);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleIsBuffer(
+    unsigned int arg_count, const gles2::IsBuffer& c) {
+  GLuint buffer;
+  if (!id_map_.GetServiceId(c.buffer, &buffer)) {
+    SetGLError(GL_INVALID_VALUE);
+    return parse_error::kParseNoError;
+  }
+  GLboolean* result_dst = GetSharedMemoryAs<GLboolean*>(
+      c.result_shm_id, c.result_shm_offset, sizeof(*result_dst));
+  parse_error::ParseError result =
+      ValidateIsBuffer(this, arg_count, buffer);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  *result_dst = glIsBuffer(buffer);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleIsEnabled(
+    unsigned int arg_count, const gles2::IsEnabled& c) {
+  GLenum cap = static_cast<GLenum>(c.cap);
+  GLboolean* result_dst = GetSharedMemoryAs<GLboolean*>(
+      c.result_shm_id, c.result_shm_offset, sizeof(*result_dst));
+  parse_error::ParseError result =
+      ValidateIsEnabled(this, arg_count, cap);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  *result_dst = glIsEnabled(cap);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleIsFramebuffer(
+    unsigned int arg_count, const gles2::IsFramebuffer& c) {
+  GLuint framebuffer;
+  if (!id_map_.GetServiceId(c.framebuffer, &framebuffer)) {
+    SetGLError(GL_INVALID_VALUE);
+    return parse_error::kParseNoError;
+  }
+  GLboolean* result_dst = GetSharedMemoryAs<GLboolean*>(
+      c.result_shm_id, c.result_shm_offset, sizeof(*result_dst));
+  parse_error::ParseError result =
+      ValidateIsFramebuffer(this, arg_count, framebuffer);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  *result_dst = glIsFramebufferEXT(framebuffer);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleIsProgram(
+    unsigned int arg_count, const gles2::IsProgram& c) {
+  GLuint program;
+  if (!id_map_.GetServiceId(c.program, &program)) {
+    SetGLError(GL_INVALID_VALUE);
+    return parse_error::kParseNoError;
+  }
+  GLboolean* result_dst = GetSharedMemoryAs<GLboolean*>(
+      c.result_shm_id, c.result_shm_offset, sizeof(*result_dst));
+  parse_error::ParseError result =
+      ValidateIsProgram(this, arg_count, program);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  *result_dst = glIsProgram(program);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleIsRenderbuffer(
+    unsigned int arg_count, const gles2::IsRenderbuffer& c) {
+  GLuint renderbuffer;
+  if (!id_map_.GetServiceId(c.renderbuffer, &renderbuffer)) {
+    SetGLError(GL_INVALID_VALUE);
+    return parse_error::kParseNoError;
+  }
+  GLboolean* result_dst = GetSharedMemoryAs<GLboolean*>(
+      c.result_shm_id, c.result_shm_offset, sizeof(*result_dst));
+  parse_error::ParseError result =
+      ValidateIsRenderbuffer(this, arg_count, renderbuffer);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  *result_dst = glIsRenderbufferEXT(renderbuffer);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleIsShader(
+    unsigned int arg_count, const gles2::IsShader& c) {
+  GLuint shader;
+  if (!id_map_.GetServiceId(c.shader, &shader)) {
+    SetGLError(GL_INVALID_VALUE);
+    return parse_error::kParseNoError;
+  }
+  GLboolean* result_dst = GetSharedMemoryAs<GLboolean*>(
+      c.result_shm_id, c.result_shm_offset, sizeof(*result_dst));
+  parse_error::ParseError result =
+      ValidateIsShader(this, arg_count, shader);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  *result_dst = glIsShader(shader);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleIsTexture(
+    unsigned int arg_count, const gles2::IsTexture& c) {
+  GLuint texture;
+  if (!id_map_.GetServiceId(c.texture, &texture)) {
+    SetGLError(GL_INVALID_VALUE);
+    return parse_error::kParseNoError;
+  }
+  GLboolean* result_dst = GetSharedMemoryAs<GLboolean*>(
+      c.result_shm_id, c.result_shm_offset, sizeof(*result_dst));
+  parse_error::ParseError result =
+      ValidateIsTexture(this, arg_count, texture);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  *result_dst = glIsTexture(texture);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleLineWidth(
+    unsigned int arg_count, const gles2::LineWidth& c) {
+  GLfloat width = static_cast<GLfloat>(c.width);
+  parse_error::ParseError result =
+      ValidateLineWidth(this, arg_count, width);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glLineWidth(width);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleLinkProgram(
+    unsigned int arg_count, const gles2::LinkProgram& c) {
+  GLuint program;
+  if (!id_map_.GetServiceId(c.program, &program)) {
+    SetGLError(GL_INVALID_VALUE);
+    return parse_error::kParseNoError;
+  }
+  parse_error::ParseError result =
+      ValidateLinkProgram(this, arg_count, program);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glLinkProgram(program);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandlePolygonOffset(
+    unsigned int arg_count, const gles2::PolygonOffset& c) {
+  GLfloat factor = static_cast<GLfloat>(c.factor);
+  GLfloat units = static_cast<GLfloat>(c.units);
+  parse_error::ParseError result =
+      ValidatePolygonOffset(this, arg_count, factor, units);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glPolygonOffset(factor, units);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleRenderbufferStorage(
+    unsigned int arg_count, const gles2::RenderbufferStorage& c) {
+  GLenum target = static_cast<GLenum>(c.target);
+  GLenum internalformat = static_cast<GLenum>(c.internalformat);
+  GLsizei width = static_cast<GLsizei>(c.width);
+  GLsizei height = static_cast<GLsizei>(c.height);
+  parse_error::ParseError result =
+      ValidateRenderbufferStorage(
+          this, arg_count, target, internalformat, width, height);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glRenderbufferStorageEXT(target, internalformat, width, height);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleSampleCoverage(
+    unsigned int arg_count, const gles2::SampleCoverage& c) {
+  GLclampf value = static_cast<GLclampf>(c.value);
+  GLboolean invert = static_cast<GLboolean>(c.invert);
+  parse_error::ParseError result =
+      ValidateSampleCoverage(this, arg_count, value, invert);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glSampleCoverage(value, invert);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleScissor(
+    unsigned int arg_count, const gles2::Scissor& c) {
+  GLint x = static_cast<GLint>(c.x);
+  GLint y = static_cast<GLint>(c.y);
+  GLsizei width = static_cast<GLsizei>(c.width);
+  GLsizei height = static_cast<GLsizei>(c.height);
+  parse_error::ParseError result =
+      ValidateScissor(this, arg_count, x, y, width, height);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glScissor(x, y, width, height);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleStencilFunc(
+    unsigned int arg_count, const gles2::StencilFunc& c) {
+  GLenum func = static_cast<GLenum>(c.func);
+  GLint ref = static_cast<GLint>(c.ref);
+  GLuint mask = static_cast<GLuint>(c.mask);
+  parse_error::ParseError result =
+      ValidateStencilFunc(this, arg_count, func, ref, mask);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glStencilFunc(func, ref, mask);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleStencilFuncSeparate(
+    unsigned int arg_count, const gles2::StencilFuncSeparate& c) {
+  GLenum face = static_cast<GLenum>(c.face);
+  GLenum func = static_cast<GLenum>(c.func);
+  GLint ref = static_cast<GLint>(c.ref);
+  GLuint mask = static_cast<GLuint>(c.mask);
+  parse_error::ParseError result =
+      ValidateStencilFuncSeparate(this, arg_count, face, func, ref, mask);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glStencilFuncSeparate(face, func, ref, mask);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleStencilMask(
+    unsigned int arg_count, const gles2::StencilMask& c) {
+  GLuint mask = static_cast<GLuint>(c.mask);
+  parse_error::ParseError result =
+      ValidateStencilMask(this, arg_count, mask);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glStencilMask(mask);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleStencilMaskSeparate(
+    unsigned int arg_count, const gles2::StencilMaskSeparate& c) {
+  GLenum face = static_cast<GLenum>(c.face);
+  GLuint mask = static_cast<GLuint>(c.mask);
+  parse_error::ParseError result =
+      ValidateStencilMaskSeparate(this, arg_count, face, mask);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glStencilMaskSeparate(face, mask);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleStencilOp(
+    unsigned int arg_count, const gles2::StencilOp& c) {
+  GLenum fail = static_cast<GLenum>(c.fail);
+  GLenum zfail = static_cast<GLenum>(c.zfail);
+  GLenum zpass = static_cast<GLenum>(c.zpass);
+  parse_error::ParseError result =
+      ValidateStencilOp(this, arg_count, fail, zfail, zpass);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glStencilOp(fail, zfail, zpass);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleStencilOpSeparate(
+    unsigned int arg_count, const gles2::StencilOpSeparate& c) {
+  GLenum face = static_cast<GLenum>(c.face);
+  GLenum fail = static_cast<GLenum>(c.fail);
+  GLenum zfail = static_cast<GLenum>(c.zfail);
+  GLenum zpass = static_cast<GLenum>(c.zpass);
+  parse_error::ParseError result =
+      ValidateStencilOpSeparate(this, arg_count, face, fail, zfail, zpass);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glStencilOpSeparate(face, fail, zfail, zpass);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleTexImage2D(
+    unsigned int arg_count, const gles2::TexImage2D& c) {
+  GLenum target = static_cast<GLenum>(c.target);
+  GLint level = static_cast<GLint>(c.level);
+  GLint internalformat = static_cast<GLint>(c.internalformat);
+  GLsizei width = static_cast<GLsizei>(c.width);
+  GLsizei height = static_cast<GLsizei>(c.height);
+  GLint border = static_cast<GLint>(c.border);
+  GLenum format = static_cast<GLenum>(c.format);
+  GLenum type = static_cast<GLenum>(c.type);
+  uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
+  uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
+  uint32 pixels_size = GLES2Util::ComputeImageDataSize(
+      width, height, format, type, unpack_alignment_);
+  const void* pixels = GetSharedMemoryAs<const void*>(
+      pixels_shm_id, pixels_shm_offset, pixels_size);
+  parse_error::ParseError result =
+      ValidateTexImage2D(
+          this, arg_count, target, level, internalformat, width, height, border,
+          format, type, pixels);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glTexImage2D(
+      target, level, internalformat, width, height, border, format, type,
+      pixels);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleTexImage2DImmediate(
+    unsigned int arg_count, const gles2::TexImage2DImmediate& c) {
+  GLenum target = static_cast<GLenum>(c.target);
+  GLint level = static_cast<GLint>(c.level);
+  GLint internalformat = static_cast<GLint>(c.internalformat);
+  GLsizei width = static_cast<GLsizei>(c.width);
+  GLsizei height = static_cast<GLsizei>(c.height);
+  GLint border = static_cast<GLint>(c.border);
+  GLenum format = static_cast<GLenum>(c.format);
+  GLenum type = static_cast<GLenum>(c.type);
+  const void* pixels = GetImmediateDataAs<const void*>(c);
+  // Immediate version.
+  parse_error::ParseError result =
+      ValidateTexImage2DImmediate(
+          this, arg_count, target, level, internalformat, width, height, border,
+          format, type, pixels);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glTexImage2D(
+      target, level, internalformat, width, height, border, format, type,
+      pixels);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleTexParameterf(
+    unsigned int arg_count, const gles2::TexParameterf& c) {
+  GLenum target = static_cast<GLenum>(c.target);
+  GLenum pname = static_cast<GLenum>(c.pname);
+  GLfloat param = static_cast<GLfloat>(c.param);
+  parse_error::ParseError result =
+      ValidateTexParameterf(this, arg_count, target, pname, param);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glTexParameterf(target, pname, param);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleTexParameterfv(
+    unsigned int arg_count, const gles2::TexParameterfv& c) {
+  GLenum target = static_cast<GLenum>(c.target);
+  GLenum pname = static_cast<GLenum>(c.pname);
+  const GLfloat* params = GetSharedMemoryAs<const GLfloat*>(
+      c.params_shm_id, c.params_shm_offset, 0 /* TODO(gman): size */);
+  parse_error::ParseError result =
+      ValidateTexParameterfv(this, arg_count, target, pname, params);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glTexParameterfv(target, pname, params);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleTexParameterfvImmediate(
+    unsigned int arg_count, const gles2::TexParameterfvImmediate& c) {
+  GLenum target = static_cast<GLenum>(c.target);
+  GLenum pname = static_cast<GLenum>(c.pname);
+  const GLfloat* params = GetImmediateDataAs<const GLfloat*>(c);
+  // Immediate version.
+  parse_error::ParseError result =
+      ValidateTexParameterfvImmediate(this, arg_count, target, pname, params);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glTexParameterfv(target, pname, params);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleTexParameteri(
+    unsigned int arg_count, const gles2::TexParameteri& c) {
+  GLenum target = static_cast<GLenum>(c.target);
+  GLenum pname = static_cast<GLenum>(c.pname);
+  GLint param = static_cast<GLint>(c.param);
+  parse_error::ParseError result =
+      ValidateTexParameteri(this, arg_count, target, pname, param);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glTexParameteri(target, pname, param);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleTexParameteriv(
+    unsigned int arg_count, const gles2::TexParameteriv& c) {
+  GLenum target = static_cast<GLenum>(c.target);
+  GLenum pname = static_cast<GLenum>(c.pname);
+  const GLint* params = GetSharedMemoryAs<const GLint*>(
+      c.params_shm_id, c.params_shm_offset, 0 /* TODO(gman): size */);
+  parse_error::ParseError result =
+      ValidateTexParameteriv(this, arg_count, target, pname, params);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glTexParameteriv(target, pname, params);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleTexParameterivImmediate(
+    unsigned int arg_count, const gles2::TexParameterivImmediate& c) {
+  GLenum target = static_cast<GLenum>(c.target);
+  GLenum pname = static_cast<GLenum>(c.pname);
+  const GLint* params = GetImmediateDataAs<const GLint*>(c);
+  // Immediate version.
+  parse_error::ParseError result =
+      ValidateTexParameterivImmediate(this, arg_count, target, pname, params);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glTexParameteriv(target, pname, params);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleTexSubImage2D(
+    unsigned int arg_count, const gles2::TexSubImage2D& c) {
+  GLenum target = static_cast<GLenum>(c.target);
+  GLint level = static_cast<GLint>(c.level);
+  GLint xoffset = static_cast<GLint>(c.xoffset);
+  GLint yoffset = static_cast<GLint>(c.yoffset);
+  GLsizei width = static_cast<GLsizei>(c.width);
+  GLsizei height = static_cast<GLsizei>(c.height);
+  GLenum format = static_cast<GLenum>(c.format);
+  GLenum type = static_cast<GLenum>(c.type);
+  uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
+  uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
+  uint32 pixels_size = GLES2Util::ComputeImageDataSize(
+      width, height, format, type, unpack_alignment_);
+  const void* pixels = GetSharedMemoryAs<const void*>(
+      pixels_shm_id, pixels_shm_offset, pixels_size);
+  parse_error::ParseError result =
+      ValidateTexSubImage2D(
+          this, arg_count, target, level, xoffset, yoffset, width, height,
+          format, type, pixels);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glTexSubImage2D(
+      target, level, xoffset, yoffset, width, height, format, type, pixels);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleTexSubImage2DImmediate(
+    unsigned int arg_count, const gles2::TexSubImage2DImmediate& c) {
+  GLenum target = static_cast<GLenum>(c.target);
+  GLint level = static_cast<GLint>(c.level);
+  GLint xoffset = static_cast<GLint>(c.xoffset);
+  GLint yoffset = static_cast<GLint>(c.yoffset);
+  GLsizei width = static_cast<GLsizei>(c.width);
+  GLsizei height = static_cast<GLsizei>(c.height);
+  GLenum format = static_cast<GLenum>(c.format);
+  GLenum type = static_cast<GLenum>(c.type);
+  const void* pixels = GetImmediateDataAs<const void*>(c);
+  // Immediate version.
+  parse_error::ParseError result =
+      ValidateTexSubImage2DImmediate(
+          this, arg_count, target, level, xoffset, yoffset, width, height,
+          format, type, pixels);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glTexSubImage2D(
+      target, level, xoffset, yoffset, width, height, format, type, pixels);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniform1f(
+    unsigned int arg_count, const gles2::Uniform1f& c) {
+  GLint location = static_cast<GLint>(c.location);
+  GLfloat x = static_cast<GLfloat>(c.x);
+  parse_error::ParseError result =
+      ValidateUniform1f(this, arg_count, location, x);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glUniform1f(location, x);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniform1fv(
+    unsigned int arg_count, const gles2::Uniform1fv& c) {
+  GLint location = static_cast<GLint>(c.location);
+  GLsizei count = static_cast<GLsizei>(c.count);
+  const GLfloat* v = GetSharedMemoryAs<const GLfloat*>(
+      c.v_shm_id, c.v_shm_offset, 0 /* TODO(gman): size */);
+  parse_error::ParseError result =
+      ValidateUniform1fv(this, arg_count, location, count, v);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glUniform1fv(location, count, v);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniform1fvImmediate(
+    unsigned int arg_count, const gles2::Uniform1fvImmediate& c) {
+  GLint location = static_cast<GLint>(c.location);
+  GLsizei count = static_cast<GLsizei>(c.count);
+  const GLfloat* v = GetImmediateDataAs<const GLfloat*>(c);
+  // Immediate version.
+  parse_error::ParseError result =
+      ValidateUniform1fvImmediate(this, arg_count, location, count, v);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glUniform1fv(location, count, v);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniform1i(
+    unsigned int arg_count, const gles2::Uniform1i& c) {
+  GLint location = static_cast<GLint>(c.location);
+  GLint x = static_cast<GLint>(c.x);
+  parse_error::ParseError result =
+      ValidateUniform1i(this, arg_count, location, x);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glUniform1i(location, x);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniform1iv(
+    unsigned int arg_count, const gles2::Uniform1iv& c) {
+  GLint location = static_cast<GLint>(c.location);
+  GLsizei count = static_cast<GLsizei>(c.count);
+  const GLint* v = GetSharedMemoryAs<const GLint*>(
+      c.v_shm_id, c.v_shm_offset, 0 /* TODO(gman): size */);
+  parse_error::ParseError result =
+      ValidateUniform1iv(this, arg_count, location, count, v);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glUniform1iv(location, count, v);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniform1ivImmediate(
+    unsigned int arg_count, const gles2::Uniform1ivImmediate& c) {
+  GLint location = static_cast<GLint>(c.location);
+  GLsizei count = static_cast<GLsizei>(c.count);
+  const GLint* v = GetImmediateDataAs<const GLint*>(c);
+  // Immediate version.
+  parse_error::ParseError result =
+      ValidateUniform1ivImmediate(this, arg_count, location, count, v);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glUniform1iv(location, count, v);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniform2f(
+    unsigned int arg_count, const gles2::Uniform2f& c) {
+  GLint location = static_cast<GLint>(c.location);
+  GLfloat x = static_cast<GLfloat>(c.x);
+  GLfloat y = static_cast<GLfloat>(c.y);
+  parse_error::ParseError result =
+      ValidateUniform2f(this, arg_count, location, x, y);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glUniform2f(location, x, y);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniform2fv(
+    unsigned int arg_count, const gles2::Uniform2fv& c) {
+  GLint location = static_cast<GLint>(c.location);
+  GLsizei count = static_cast<GLsizei>(c.count);
+  const GLfloat* v = GetSharedMemoryAs<const GLfloat*>(
+      c.v_shm_id, c.v_shm_offset, 0 /* TODO(gman): size */);
+  parse_error::ParseError result =
+      ValidateUniform2fv(this, arg_count, location, count, v);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glUniform2fv(location, count, v);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniform2fvImmediate(
+    unsigned int arg_count, const gles2::Uniform2fvImmediate& c) {
+  GLint location = static_cast<GLint>(c.location);
+  GLsizei count = static_cast<GLsizei>(c.count);
+  const GLfloat* v = GetImmediateDataAs<const GLfloat*>(c);
+  // Immediate version.
+  parse_error::ParseError result =
+      ValidateUniform2fvImmediate(this, arg_count, location, count, v);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glUniform2fv(location, count, v);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniform2i(
+    unsigned int arg_count, const gles2::Uniform2i& c) {
+  GLint location = static_cast<GLint>(c.location);
+  GLint x = static_cast<GLint>(c.x);
+  GLint y = static_cast<GLint>(c.y);
+  parse_error::ParseError result =
+      ValidateUniform2i(this, arg_count, location, x, y);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glUniform2i(location, x, y);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniform2iv(
+    unsigned int arg_count, const gles2::Uniform2iv& c) {
+  GLint location = static_cast<GLint>(c.location);
+  GLsizei count = static_cast<GLsizei>(c.count);
+  const GLint* v = GetSharedMemoryAs<const GLint*>(
+      c.v_shm_id, c.v_shm_offset, 0 /* TODO(gman): size */);
+  parse_error::ParseError result =
+      ValidateUniform2iv(this, arg_count, location, count, v);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glUniform2iv(location, count, v);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniform2ivImmediate(
+    unsigned int arg_count, const gles2::Uniform2ivImmediate& c) {
+  GLint location = static_cast<GLint>(c.location);
+  GLsizei count = static_cast<GLsizei>(c.count);
+  const GLint* v = GetImmediateDataAs<const GLint*>(c);
+  // Immediate version.
+  parse_error::ParseError result =
+      ValidateUniform2ivImmediate(this, arg_count, location, count, v);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glUniform2iv(location, count, v);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniform3f(
+    unsigned int arg_count, const gles2::Uniform3f& c) {
+  GLint location = static_cast<GLint>(c.location);
+  GLfloat x = static_cast<GLfloat>(c.x);
+  GLfloat y = static_cast<GLfloat>(c.y);
+  GLfloat z = static_cast<GLfloat>(c.z);
+  parse_error::ParseError result =
+      ValidateUniform3f(this, arg_count, location, x, y, z);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glUniform3f(location, x, y, z);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniform3fv(
+    unsigned int arg_count, const gles2::Uniform3fv& c) {
+  GLint location = static_cast<GLint>(c.location);
+  GLsizei count = static_cast<GLsizei>(c.count);
+  const GLfloat* v = GetSharedMemoryAs<const GLfloat*>(
+      c.v_shm_id, c.v_shm_offset, 0 /* TODO(gman): size */);
+  parse_error::ParseError result =
+      ValidateUniform3fv(this, arg_count, location, count, v);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glUniform3fv(location, count, v);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniform3fvImmediate(
+    unsigned int arg_count, const gles2::Uniform3fvImmediate& c) {
+  GLint location = static_cast<GLint>(c.location);
+  GLsizei count = static_cast<GLsizei>(c.count);
+  const GLfloat* v = GetImmediateDataAs<const GLfloat*>(c);
+  // Immediate version.
+  parse_error::ParseError result =
+      ValidateUniform3fvImmediate(this, arg_count, location, count, v);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glUniform3fv(location, count, v);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniform3i(
+    unsigned int arg_count, const gles2::Uniform3i& c) {
+  GLint location = static_cast<GLint>(c.location);
+  GLint x = static_cast<GLint>(c.x);
+  GLint y = static_cast<GLint>(c.y);
+  GLint z = static_cast<GLint>(c.z);
+  parse_error::ParseError result =
+      ValidateUniform3i(this, arg_count, location, x, y, z);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glUniform3i(location, x, y, z);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniform3iv(
+    unsigned int arg_count, const gles2::Uniform3iv& c) {
+  GLint location = static_cast<GLint>(c.location);
+  GLsizei count = static_cast<GLsizei>(c.count);
+  const GLint* v = GetSharedMemoryAs<const GLint*>(
+      c.v_shm_id, c.v_shm_offset, 0 /* TODO(gman): size */);
+  parse_error::ParseError result =
+      ValidateUniform3iv(this, arg_count, location, count, v);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glUniform3iv(location, count, v);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniform3ivImmediate(
+    unsigned int arg_count, const gles2::Uniform3ivImmediate& c) {
+  GLint location = static_cast<GLint>(c.location);
+  GLsizei count = static_cast<GLsizei>(c.count);
+  const GLint* v = GetImmediateDataAs<const GLint*>(c);
+  // Immediate version.
+  parse_error::ParseError result =
+      ValidateUniform3ivImmediate(this, arg_count, location, count, v);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glUniform3iv(location, count, v);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniform4f(
+    unsigned int arg_count, const gles2::Uniform4f& c) {
+  GLint location = static_cast<GLint>(c.location);
+  GLfloat x = static_cast<GLfloat>(c.x);
+  GLfloat y = static_cast<GLfloat>(c.y);
+  GLfloat z = static_cast<GLfloat>(c.z);
+  GLfloat w = static_cast<GLfloat>(c.w);
+  parse_error::ParseError result =
+      ValidateUniform4f(this, arg_count, location, x, y, z, w);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glUniform4f(location, x, y, z, w);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniform4fv(
+    unsigned int arg_count, const gles2::Uniform4fv& c) {
+  GLint location = static_cast<GLint>(c.location);
+  GLsizei count = static_cast<GLsizei>(c.count);
+  const GLfloat* v = GetSharedMemoryAs<const GLfloat*>(
+      c.v_shm_id, c.v_shm_offset, 0 /* TODO(gman): size */);
+  parse_error::ParseError result =
+      ValidateUniform4fv(this, arg_count, location, count, v);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glUniform4fv(location, count, v);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniform4fvImmediate(
+    unsigned int arg_count, const gles2::Uniform4fvImmediate& c) {
+  GLint location = static_cast<GLint>(c.location);
+  GLsizei count = static_cast<GLsizei>(c.count);
+  const GLfloat* v = GetImmediateDataAs<const GLfloat*>(c);
+  // Immediate version.
+  parse_error::ParseError result =
+      ValidateUniform4fvImmediate(this, arg_count, location, count, v);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glUniform4fv(location, count, v);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniform4i(
+    unsigned int arg_count, const gles2::Uniform4i& c) {
+  GLint location = static_cast<GLint>(c.location);
+  GLint x = static_cast<GLint>(c.x);
+  GLint y = static_cast<GLint>(c.y);
+  GLint z = static_cast<GLint>(c.z);
+  GLint w = static_cast<GLint>(c.w);
+  parse_error::ParseError result =
+      ValidateUniform4i(this, arg_count, location, x, y, z, w);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glUniform4i(location, x, y, z, w);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniform4iv(
+    unsigned int arg_count, const gles2::Uniform4iv& c) {
+  GLint location = static_cast<GLint>(c.location);
+  GLsizei count = static_cast<GLsizei>(c.count);
+  const GLint* v = GetSharedMemoryAs<const GLint*>(
+      c.v_shm_id, c.v_shm_offset, 0 /* TODO(gman): size */);
+  parse_error::ParseError result =
+      ValidateUniform4iv(this, arg_count, location, count, v);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glUniform4iv(location, count, v);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniform4ivImmediate(
+    unsigned int arg_count, const gles2::Uniform4ivImmediate& c) {
+  GLint location = static_cast<GLint>(c.location);
+  GLsizei count = static_cast<GLsizei>(c.count);
+  const GLint* v = GetImmediateDataAs<const GLint*>(c);
+  // Immediate version.
+  parse_error::ParseError result =
+      ValidateUniform4ivImmediate(this, arg_count, location, count, v);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glUniform4iv(location, count, v);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniformMatrix2fv(
+    unsigned int arg_count, const gles2::UniformMatrix2fv& c) {
+  GLint location = static_cast<GLint>(c.location);
+  GLsizei count = static_cast<GLsizei>(c.count);
+  GLboolean transpose = static_cast<GLboolean>(c.transpose);
+  const GLfloat* value = GetSharedMemoryAs<const GLfloat*>(
+      c.value_shm_id, c.value_shm_offset, 0 /* TODO(gman): size */);
+  parse_error::ParseError result =
+      ValidateUniformMatrix2fv(
+          this, arg_count, location, count, transpose, value);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glUniformMatrix2fv(location, count, transpose, value);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniformMatrix2fvImmediate(
+    unsigned int arg_count, const gles2::UniformMatrix2fvImmediate& c) {
+  GLint location = static_cast<GLint>(c.location);
+  GLsizei count = static_cast<GLsizei>(c.count);
+  GLboolean transpose = static_cast<GLboolean>(c.transpose);
+  const GLfloat* value = GetImmediateDataAs<const GLfloat*>(c);
+  // Immediate version.
+  parse_error::ParseError result =
+      ValidateUniformMatrix2fvImmediate(
+          this, arg_count, location, count, transpose, value);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glUniformMatrix2fv(location, count, transpose, value);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniformMatrix3fv(
+    unsigned int arg_count, const gles2::UniformMatrix3fv& c) {
+  GLint location = static_cast<GLint>(c.location);
+  GLsizei count = static_cast<GLsizei>(c.count);
+  GLboolean transpose = static_cast<GLboolean>(c.transpose);
+  const GLfloat* value = GetSharedMemoryAs<const GLfloat*>(
+      c.value_shm_id, c.value_shm_offset, 0 /* TODO(gman): size */);
+  parse_error::ParseError result =
+      ValidateUniformMatrix3fv(
+          this, arg_count, location, count, transpose, value);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glUniformMatrix3fv(location, count, transpose, value);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniformMatrix3fvImmediate(
+    unsigned int arg_count, const gles2::UniformMatrix3fvImmediate& c) {
+  GLint location = static_cast<GLint>(c.location);
+  GLsizei count = static_cast<GLsizei>(c.count);
+  GLboolean transpose = static_cast<GLboolean>(c.transpose);
+  const GLfloat* value = GetImmediateDataAs<const GLfloat*>(c);
+  // Immediate version.
+  parse_error::ParseError result =
+      ValidateUniformMatrix3fvImmediate(
+          this, arg_count, location, count, transpose, value);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glUniformMatrix3fv(location, count, transpose, value);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniformMatrix4fv(
+    unsigned int arg_count, const gles2::UniformMatrix4fv& c) {
+  GLint location = static_cast<GLint>(c.location);
+  GLsizei count = static_cast<GLsizei>(c.count);
+  GLboolean transpose = static_cast<GLboolean>(c.transpose);
+  const GLfloat* value = GetSharedMemoryAs<const GLfloat*>(
+      c.value_shm_id, c.value_shm_offset, 0 /* TODO(gman): size */);
+  parse_error::ParseError result =
+      ValidateUniformMatrix4fv(
+          this, arg_count, location, count, transpose, value);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glUniformMatrix4fv(location, count, transpose, value);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniformMatrix4fvImmediate(
+    unsigned int arg_count, const gles2::UniformMatrix4fvImmediate& c) {
+  GLint location = static_cast<GLint>(c.location);
+  GLsizei count = static_cast<GLsizei>(c.count);
+  GLboolean transpose = static_cast<GLboolean>(c.transpose);
+  const GLfloat* value = GetImmediateDataAs<const GLfloat*>(c);
+  // Immediate version.
+  parse_error::ParseError result =
+      ValidateUniformMatrix4fvImmediate(
+          this, arg_count, location, count, transpose, value);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glUniformMatrix4fv(location, count, transpose, value);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUseProgram(
+    unsigned int arg_count, const gles2::UseProgram& c) {
+  GLuint program;
+  if (!id_map_.GetServiceId(c.program, &program)) {
+    SetGLError(GL_INVALID_VALUE);
+    return parse_error::kParseNoError;
+  }
+  parse_error::ParseError result =
+      ValidateUseProgram(this, arg_count, program);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glUseProgram(program);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleValidateProgram(
+    unsigned int arg_count, const gles2::ValidateProgram& c) {
+  GLuint program;
+  if (!id_map_.GetServiceId(c.program, &program)) {
+    SetGLError(GL_INVALID_VALUE);
+    return parse_error::kParseNoError;
+  }
+  parse_error::ParseError result =
+      ValidateValidateProgram(this, arg_count, program);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glValidateProgram(program);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleVertexAttrib1f(
+    unsigned int arg_count, const gles2::VertexAttrib1f& c) {
+  GLuint indx = static_cast<GLuint>(c.indx);
+  GLfloat x = static_cast<GLfloat>(c.x);
+  parse_error::ParseError result =
+      ValidateVertexAttrib1f(this, arg_count, indx, x);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glVertexAttrib1f(indx, x);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleVertexAttrib1fv(
+    unsigned int arg_count, const gles2::VertexAttrib1fv& c) {
+  GLuint indx = static_cast<GLuint>(c.indx);
+  const GLfloat* values = GetSharedMemoryAs<const GLfloat*>(
+      c.values_shm_id, c.values_shm_offset, 0 /* TODO(gman): size */);
+  parse_error::ParseError result =
+      ValidateVertexAttrib1fv(this, arg_count, indx, values);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glVertexAttrib1fv(indx, values);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleVertexAttrib1fvImmediate(
+    unsigned int arg_count, const gles2::VertexAttrib1fvImmediate& c) {
+  GLuint indx = static_cast<GLuint>(c.indx);
+  const GLfloat* values = GetImmediateDataAs<const GLfloat*>(c);
+  // Immediate version.
+  parse_error::ParseError result =
+      ValidateVertexAttrib1fvImmediate(this, arg_count, indx, values);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glVertexAttrib1fv(indx, values);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleVertexAttrib2f(
+    unsigned int arg_count, const gles2::VertexAttrib2f& c) {
+  GLuint indx = static_cast<GLuint>(c.indx);
+  GLfloat x = static_cast<GLfloat>(c.x);
+  GLfloat y = static_cast<GLfloat>(c.y);
+  parse_error::ParseError result =
+      ValidateVertexAttrib2f(this, arg_count, indx, x, y);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glVertexAttrib2f(indx, x, y);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleVertexAttrib2fv(
+    unsigned int arg_count, const gles2::VertexAttrib2fv& c) {
+  GLuint indx = static_cast<GLuint>(c.indx);
+  const GLfloat* values = GetSharedMemoryAs<const GLfloat*>(
+      c.values_shm_id, c.values_shm_offset, 0 /* TODO(gman): size */);
+  parse_error::ParseError result =
+      ValidateVertexAttrib2fv(this, arg_count, indx, values);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glVertexAttrib2fv(indx, values);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleVertexAttrib2fvImmediate(
+    unsigned int arg_count, const gles2::VertexAttrib2fvImmediate& c) {
+  GLuint indx = static_cast<GLuint>(c.indx);
+  const GLfloat* values = GetImmediateDataAs<const GLfloat*>(c);
+  // Immediate version.
+  parse_error::ParseError result =
+      ValidateVertexAttrib2fvImmediate(this, arg_count, indx, values);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glVertexAttrib2fv(indx, values);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleVertexAttrib3f(
+    unsigned int arg_count, const gles2::VertexAttrib3f& c) {
+  GLuint indx = static_cast<GLuint>(c.indx);
+  GLfloat x = static_cast<GLfloat>(c.x);
+  GLfloat y = static_cast<GLfloat>(c.y);
+  GLfloat z = static_cast<GLfloat>(c.z);
+  parse_error::ParseError result =
+      ValidateVertexAttrib3f(this, arg_count, indx, x, y, z);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glVertexAttrib3f(indx, x, y, z);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleVertexAttrib3fv(
+    unsigned int arg_count, const gles2::VertexAttrib3fv& c) {
+  GLuint indx = static_cast<GLuint>(c.indx);
+  const GLfloat* values = GetSharedMemoryAs<const GLfloat*>(
+      c.values_shm_id, c.values_shm_offset, 0 /* TODO(gman): size */);
+  parse_error::ParseError result =
+      ValidateVertexAttrib3fv(this, arg_count, indx, values);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glVertexAttrib3fv(indx, values);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleVertexAttrib3fvImmediate(
+    unsigned int arg_count, const gles2::VertexAttrib3fvImmediate& c) {
+  GLuint indx = static_cast<GLuint>(c.indx);
+  const GLfloat* values = GetImmediateDataAs<const GLfloat*>(c);
+  // Immediate version.
+  parse_error::ParseError result =
+      ValidateVertexAttrib3fvImmediate(this, arg_count, indx, values);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glVertexAttrib3fv(indx, values);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleVertexAttrib4f(
+    unsigned int arg_count, const gles2::VertexAttrib4f& c) {
+  GLuint indx = static_cast<GLuint>(c.indx);
+  GLfloat x = static_cast<GLfloat>(c.x);
+  GLfloat y = static_cast<GLfloat>(c.y);
+  GLfloat z = static_cast<GLfloat>(c.z);
+  GLfloat w = static_cast<GLfloat>(c.w);
+  parse_error::ParseError result =
+      ValidateVertexAttrib4f(this, arg_count, indx, x, y, z, w);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glVertexAttrib4f(indx, x, y, z, w);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleVertexAttrib4fv(
+    unsigned int arg_count, const gles2::VertexAttrib4fv& c) {
+  GLuint indx = static_cast<GLuint>(c.indx);
+  const GLfloat* values = GetSharedMemoryAs<const GLfloat*>(
+      c.values_shm_id, c.values_shm_offset, 0 /* TODO(gman): size */);
+  parse_error::ParseError result =
+      ValidateVertexAttrib4fv(this, arg_count, indx, values);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glVertexAttrib4fv(indx, values);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleVertexAttrib4fvImmediate(
+    unsigned int arg_count, const gles2::VertexAttrib4fvImmediate& c) {
+  GLuint indx = static_cast<GLuint>(c.indx);
+  const GLfloat* values = GetImmediateDataAs<const GLfloat*>(c);
+  // Immediate version.
+  parse_error::ParseError result =
+      ValidateVertexAttrib4fvImmediate(this, arg_count, indx, values);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glVertexAttrib4fv(indx, values);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleViewport(
+    unsigned int arg_count, const gles2::Viewport& c) {
+  GLint x = static_cast<GLint>(c.x);
+  GLint y = static_cast<GLint>(c.y);
+  GLsizei width = static_cast<GLsizei>(c.width);
+  GLsizei height = static_cast<GLsizei>(c.height);
+  parse_error::ParseError result =
+      ValidateViewport(this, arg_count, x, y, width, height);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glViewport(x, y, width, height);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleSwapBuffers(
+    unsigned int arg_count, const gles2::SwapBuffers& c) {
+  parse_error::ParseError result =
+      ValidateSwapBuffers(this, arg_count);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  DoSwapBuffers();
+  return parse_error::kParseNoError;
+}
+
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_validate.h b/gpu/command_buffer/service/gles2_cmd_decoder_validate.h
new file mode 100644
index 0000000..616d3fc
--- /dev/null
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_validate.h
@@ -0,0 +1,1255 @@
+
+// Copyright (c) 2006-2008 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.
+
+
+namespace command_buffer {
+namespace gles2 {
+
+namespace {
+
+parse_error::ParseError ValidateActiveTexture(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum texture) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateAttachShader(
+    GLES2Decoder* decoder, unsigned int arg_count, GLuint program,
+    GLuint shader) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateBindAttribLocation(
+    GLES2Decoder* decoder, unsigned int arg_count, GLuint program, GLuint index,
+    const char* name) {
+  if (name == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateBindAttribLocationImmediate(
+    GLES2Decoder* decoder, unsigned int arg_count, GLuint program, GLuint index,
+    const char* name) {
+  if (name == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateBindBuffer(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum target,
+    GLuint buffer) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateBindFramebuffer(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum target,
+    GLuint framebuffer) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateBindRenderbuffer(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum target,
+    GLuint renderbuffer) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateBindTexture(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum target,
+    GLuint texture) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateBlendColor(
+    GLES2Decoder* decoder, unsigned int arg_count, GLclampf red, GLclampf green,
+    GLclampf blue, GLclampf alpha) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateBlendEquation(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum mode) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateBlendEquationSeparate(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum modeRGB,
+    GLenum modeAlpha) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateBlendFunc(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum sfactor,
+    GLenum dfactor) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateBlendFuncSeparate(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum srcRGB, GLenum dstRGB,
+    GLenum srcAlpha, GLenum dstAlpha) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateBufferData(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum target,
+    GLsizeiptr size, const void* data, GLenum usage) {
+  if (data == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateBufferDataImmediate(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum target,
+    GLsizeiptr size, const void* data, GLenum usage) {
+  if (data == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateBufferSubData(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum target,
+    GLintptr offset, GLsizeiptr size, const void* data) {
+  if (data == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateBufferSubDataImmediate(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum target,
+    GLintptr offset, GLsizeiptr size, const void* data) {
+  if (data == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateCheckFramebufferStatus(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum target) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateClear(
+    GLES2Decoder* decoder, unsigned int arg_count, GLbitfield mask) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateClearColor(
+    GLES2Decoder* decoder, unsigned int arg_count, GLclampf red, GLclampf green,
+    GLclampf blue, GLclampf alpha) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateClearDepthf(
+    GLES2Decoder* decoder, unsigned int arg_count, GLclampf depth) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateClearStencil(
+    GLES2Decoder* decoder, unsigned int arg_count, GLint s) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateColorMask(
+    GLES2Decoder* decoder, unsigned int arg_count, GLboolean red,
+    GLboolean green, GLboolean blue, GLboolean alpha) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateCompileShader(
+    GLES2Decoder* decoder, unsigned int arg_count, GLuint shader) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateCompressedTexImage2D(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum target, GLint level,
+    GLenum internalformat, GLsizei width, GLsizei height, GLint border,
+    GLsizei imageSize, const void* data) {
+  if (data == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateCompressedTexImage2DImmediate(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum target, GLint level,
+    GLenum internalformat, GLsizei width, GLsizei height, GLint border,
+    GLsizei imageSize, const void* data) {
+  if (data == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateCompressedTexSubImage2D(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum target, GLint level,
+    GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format,
+    GLsizei imageSize, const void* data) {
+  if (data == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateCompressedTexSubImage2DImmediate(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum target, GLint level,
+    GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format,
+    GLsizei imageSize, const void* data) {
+  if (data == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateCopyTexImage2D(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum target, GLint level,
+    GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height,
+    GLint border) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateCopyTexSubImage2D(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum target, GLint level,
+    GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width,
+    GLsizei height) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateCreateProgram(
+    GLES2Decoder* decoder, unsigned int arg_count) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateCreateShader(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum type) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateCullFace(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum mode) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateDeleteBuffers(
+    GLES2Decoder* decoder, unsigned int arg_count, GLsizei n,
+    const GLuint* buffers) {
+  if (buffers == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateDeleteBuffersImmediate(
+    GLES2Decoder* decoder, unsigned int arg_count, GLsizei n,
+    const GLuint* buffers) {
+  if (buffers == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateDeleteFramebuffers(
+    GLES2Decoder* decoder, unsigned int arg_count, GLsizei n,
+    const GLuint* framebuffers) {
+  if (framebuffers == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateDeleteFramebuffersImmediate(
+    GLES2Decoder* decoder, unsigned int arg_count, GLsizei n,
+    const GLuint* framebuffers) {
+  if (framebuffers == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateDeleteProgram(
+    GLES2Decoder* decoder, unsigned int arg_count, GLuint program) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateDeleteRenderbuffers(
+    GLES2Decoder* decoder, unsigned int arg_count, GLsizei n,
+    const GLuint* renderbuffers) {
+  if (renderbuffers == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateDeleteRenderbuffersImmediate(
+    GLES2Decoder* decoder, unsigned int arg_count, GLsizei n,
+    const GLuint* renderbuffers) {
+  if (renderbuffers == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateDeleteShader(
+    GLES2Decoder* decoder, unsigned int arg_count, GLuint shader) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateDeleteTextures(
+    GLES2Decoder* decoder, unsigned int arg_count, GLsizei n,
+    const GLuint* textures) {
+  if (textures == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateDeleteTexturesImmediate(
+    GLES2Decoder* decoder, unsigned int arg_count, GLsizei n,
+    const GLuint* textures) {
+  if (textures == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateDepthFunc(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum func) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateDepthMask(
+    GLES2Decoder* decoder, unsigned int arg_count, GLboolean flag) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateDepthRangef(
+    GLES2Decoder* decoder, unsigned int arg_count, GLclampf zNear,
+    GLclampf zFar) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateDetachShader(
+    GLES2Decoder* decoder, unsigned int arg_count, GLuint program,
+    GLuint shader) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateDisable(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum cap) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateDisableVertexAttribArray(
+    GLES2Decoder* decoder, unsigned int arg_count, GLuint index) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateDrawArrays(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum mode, GLint first,
+    GLsizei count) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateDrawElements(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum mode, GLsizei count,
+    GLenum type, const void* indices) {
+  if (indices == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateEnable(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum cap) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateEnableVertexAttribArray(
+    GLES2Decoder* decoder, unsigned int arg_count, GLuint index) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateFinish(
+    GLES2Decoder* decoder, unsigned int arg_count) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateFlush(
+    GLES2Decoder* decoder, unsigned int arg_count) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateFramebufferRenderbuffer(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum target,
+    GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateFramebufferTexture2D(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum target,
+    GLenum attachment, GLenum textarget, GLuint texture, GLint level) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateFrontFace(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum mode) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGenBuffers(
+    GLES2Decoder* decoder, unsigned int arg_count, GLsizei n,
+    GLuint* buffers) {
+  if (buffers == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGenBuffersImmediate(
+    GLES2Decoder* decoder, unsigned int arg_count, GLsizei n,
+    GLuint* buffers) {
+  if (buffers == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGenerateMipmap(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum target) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGenFramebuffers(
+    GLES2Decoder* decoder, unsigned int arg_count, GLsizei n,
+    GLuint* framebuffers) {
+  if (framebuffers == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGenFramebuffersImmediate(
+    GLES2Decoder* decoder, unsigned int arg_count, GLsizei n,
+    GLuint* framebuffers) {
+  if (framebuffers == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGenRenderbuffers(
+    GLES2Decoder* decoder, unsigned int arg_count, GLsizei n,
+    GLuint* renderbuffers) {
+  if (renderbuffers == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGenRenderbuffersImmediate(
+    GLES2Decoder* decoder, unsigned int arg_count, GLsizei n,
+    GLuint* renderbuffers) {
+  if (renderbuffers == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGenTextures(
+    GLES2Decoder* decoder, unsigned int arg_count, GLsizei n,
+    GLuint* textures) {
+  if (textures == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGenTexturesImmediate(
+    GLES2Decoder* decoder, unsigned int arg_count, GLsizei n,
+    GLuint* textures) {
+  if (textures == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetActiveAttrib(
+    GLES2Decoder* decoder, unsigned int arg_count, GLuint program, GLuint index,
+    GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name) {
+  if (length == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  if (size == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  if (type == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  if (name == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetActiveUniform(
+    GLES2Decoder* decoder, unsigned int arg_count, GLuint program, GLuint index,
+    GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name) {
+  if (length == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  if (size == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  if (type == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  if (name == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetAttachedShaders(
+    GLES2Decoder* decoder, unsigned int arg_count, GLuint program,
+    GLsizei maxcount, GLsizei* count, GLuint* shaders) {
+  if (count == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  if (shaders == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetAttribLocation(
+    GLES2Decoder* decoder, unsigned int arg_count, GLuint program,
+    const char* name) {
+  if (name == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetAttribLocationImmediate(
+    GLES2Decoder* decoder, unsigned int arg_count, GLuint program,
+    const char* name) {
+  if (name == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetBooleanv(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum pname,
+    GLboolean* params) {
+  if (params == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetBufferParameteriv(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum target, GLenum pname,
+    GLint* params) {
+  if (params == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetError(
+    GLES2Decoder* decoder, unsigned int arg_count) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetFloatv(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum pname,
+    GLfloat* params) {
+  if (params == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetFramebufferAttachmentParameteriv(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum target,
+    GLenum attachment, GLenum pname, GLint* params) {
+  if (params == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetIntegerv(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum pname,
+    GLint* params) {
+  if (params == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetProgramiv(
+    GLES2Decoder* decoder, unsigned int arg_count, GLuint program, GLenum pname,
+    GLint* params) {
+  if (params == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetProgramInfoLog(
+    GLES2Decoder* decoder, unsigned int arg_count, GLuint program,
+    GLsizei bufsize, GLsizei* length, char* infolog) {
+  if (length == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  if (infolog == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetRenderbufferParameteriv(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum target, GLenum pname,
+    GLint* params) {
+  if (params == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetShaderiv(
+    GLES2Decoder* decoder, unsigned int arg_count, GLuint shader, GLenum pname,
+    GLint* params) {
+  if (params == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetShaderInfoLog(
+    GLES2Decoder* decoder, unsigned int arg_count, GLuint shader,
+    GLsizei bufsize, GLsizei* length, char* infolog) {
+  if (length == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  if (infolog == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetShaderPrecisionFormat(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum shadertype,
+    GLenum precisiontype, GLint* range, GLint* precision) {
+  if (range == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  if (precision == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetShaderSource(
+    GLES2Decoder* decoder, unsigned int arg_count, GLuint shader,
+    GLsizei bufsize, GLsizei* length, char* source) {
+  if (length == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  if (source == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetString(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum name) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetTexParameterfv(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum target, GLenum pname,
+    GLfloat* params) {
+  if (params == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetTexParameteriv(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum target, GLenum pname,
+    GLint* params) {
+  if (params == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetUniformfv(
+    GLES2Decoder* decoder, unsigned int arg_count, GLuint program,
+    GLint location, GLfloat* params) {
+  if (params == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetUniformiv(
+    GLES2Decoder* decoder, unsigned int arg_count, GLuint program,
+    GLint location, GLint* params) {
+  if (params == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetUniformLocation(
+    GLES2Decoder* decoder, unsigned int arg_count, GLuint program,
+    const char* name) {
+  if (name == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetUniformLocationImmediate(
+    GLES2Decoder* decoder, unsigned int arg_count, GLuint program,
+    const char* name) {
+  if (name == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetVertexAttribfv(
+    GLES2Decoder* decoder, unsigned int arg_count, GLuint index, GLenum pname,
+    GLfloat* params) {
+  if (params == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetVertexAttribiv(
+    GLES2Decoder* decoder, unsigned int arg_count, GLuint index, GLenum pname,
+    GLint* params) {
+  if (params == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetVertexAttribPointerv(
+    GLES2Decoder* decoder, unsigned int arg_count, GLuint index, GLenum pname,
+    void** pointer) {
+  if (pointer == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateHint(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum target,
+    GLenum mode) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateIsBuffer(
+    GLES2Decoder* decoder, unsigned int arg_count, GLuint buffer) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateIsEnabled(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum cap) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateIsFramebuffer(
+    GLES2Decoder* decoder, unsigned int arg_count, GLuint framebuffer) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateIsProgram(
+    GLES2Decoder* decoder, unsigned int arg_count, GLuint program) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateIsRenderbuffer(
+    GLES2Decoder* decoder, unsigned int arg_count, GLuint renderbuffer) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateIsShader(
+    GLES2Decoder* decoder, unsigned int arg_count, GLuint shader) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateIsTexture(
+    GLES2Decoder* decoder, unsigned int arg_count, GLuint texture) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateLineWidth(
+    GLES2Decoder* decoder, unsigned int arg_count, GLfloat width) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateLinkProgram(
+    GLES2Decoder* decoder, unsigned int arg_count, GLuint program) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidatePixelStorei(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum pname, GLint param) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidatePolygonOffset(
+    GLES2Decoder* decoder, unsigned int arg_count, GLfloat factor,
+    GLfloat units) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateReadPixels(
+    GLES2Decoder* decoder, unsigned int arg_count, GLint x, GLint y,
+    GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels) {
+  if (pixels == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateRenderbufferStorage(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum target,
+    GLenum internalformat, GLsizei width, GLsizei height) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateSampleCoverage(
+    GLES2Decoder* decoder, unsigned int arg_count, GLclampf value,
+    GLboolean invert) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateScissor(
+    GLES2Decoder* decoder, unsigned int arg_count, GLint x, GLint y,
+    GLsizei width, GLsizei height) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateShaderSource(
+    GLES2Decoder* decoder, unsigned int arg_count, GLuint shader, GLsizei count,
+    const char** string, const GLint* length) {
+  if (string == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  if (length == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateShaderSourceImmediate(
+    GLES2Decoder* decoder, unsigned int arg_count, GLuint shader, GLsizei count,
+    const char** string, const GLint* length) {
+  if (string == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  if (length == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateStencilFunc(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum func, GLint ref,
+    GLuint mask) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateStencilFuncSeparate(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum face, GLenum func,
+    GLint ref, GLuint mask) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateStencilMask(
+    GLES2Decoder* decoder, unsigned int arg_count, GLuint mask) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateStencilMaskSeparate(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum face, GLuint mask) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateStencilOp(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum fail, GLenum zfail,
+    GLenum zpass) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateStencilOpSeparate(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum face, GLenum fail,
+    GLenum zfail, GLenum zpass) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateTexImage2D(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum target, GLint level,
+    GLint internalformat, GLsizei width, GLsizei height, GLint border,
+    GLenum format, GLenum type, const void* pixels) {
+  if (pixels == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateTexImage2DImmediate(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum target, GLint level,
+    GLint internalformat, GLsizei width, GLsizei height, GLint border,
+    GLenum format, GLenum type, const void* pixels) {
+  if (pixels == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateTexParameterf(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum target, GLenum pname,
+    GLfloat param) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateTexParameterfv(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum target, GLenum pname,
+    const GLfloat* params) {
+  if (params == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateTexParameterfvImmediate(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum target, GLenum pname,
+    const GLfloat* params) {
+  if (params == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  if (!CheckImmediateDataSize<TexParameterfvImmediate>(
+      arg_count, 1, sizeof(GLfloat), 1)) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateTexParameteri(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum target, GLenum pname,
+    GLint param) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateTexParameteriv(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum target, GLenum pname,
+    const GLint* params) {
+  if (params == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateTexParameterivImmediate(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum target, GLenum pname,
+    const GLint* params) {
+  if (params == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  if (!CheckImmediateDataSize<TexParameterivImmediate>(
+      arg_count, 1, sizeof(GLint), 1)) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateTexSubImage2D(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum target, GLint level,
+    GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format,
+    GLenum type, const void* pixels) {
+  if (pixels == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateTexSubImage2DImmediate(
+    GLES2Decoder* decoder, unsigned int arg_count, GLenum target, GLint level,
+    GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format,
+    GLenum type, const void* pixels) {
+  if (pixels == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniform1f(
+    GLES2Decoder* decoder, unsigned int arg_count, GLint location, GLfloat x) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniform1fv(
+    GLES2Decoder* decoder, unsigned int arg_count, GLint location,
+    GLsizei count, const GLfloat* v) {
+  if (v == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniform1fvImmediate(
+    GLES2Decoder* decoder, unsigned int arg_count, GLint location,
+    GLsizei count, const GLfloat* v) {
+  if (v == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  if (!CheckImmediateDataSize<Uniform1fvImmediate>(
+      arg_count, count, sizeof(GLfloat), 1)) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniform1i(
+    GLES2Decoder* decoder, unsigned int arg_count, GLint location, GLint x) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniform1iv(
+    GLES2Decoder* decoder, unsigned int arg_count, GLint location,
+    GLsizei count, const GLint* v) {
+  if (v == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniform1ivImmediate(
+    GLES2Decoder* decoder, unsigned int arg_count, GLint location,
+    GLsizei count, const GLint* v) {
+  if (v == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  if (!CheckImmediateDataSize<Uniform1ivImmediate>(
+      arg_count, count, sizeof(GLint), 1)) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniform2f(
+    GLES2Decoder* decoder, unsigned int arg_count, GLint location, GLfloat x,
+    GLfloat y) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniform2fv(
+    GLES2Decoder* decoder, unsigned int arg_count, GLint location,
+    GLsizei count, const GLfloat* v) {
+  if (v == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniform2fvImmediate(
+    GLES2Decoder* decoder, unsigned int arg_count, GLint location,
+    GLsizei count, const GLfloat* v) {
+  if (v == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  if (!CheckImmediateDataSize<Uniform2fvImmediate>(
+      arg_count, count, sizeof(GLfloat), 2)) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniform2i(
+    GLES2Decoder* decoder, unsigned int arg_count, GLint location, GLint x,
+    GLint y) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniform2iv(
+    GLES2Decoder* decoder, unsigned int arg_count, GLint location,
+    GLsizei count, const GLint* v) {
+  if (v == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniform2ivImmediate(
+    GLES2Decoder* decoder, unsigned int arg_count, GLint location,
+    GLsizei count, const GLint* v) {
+  if (v == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  if (!CheckImmediateDataSize<Uniform2ivImmediate>(
+      arg_count, count, sizeof(GLint), 2)) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniform3f(
+    GLES2Decoder* decoder, unsigned int arg_count, GLint location, GLfloat x,
+    GLfloat y, GLfloat z) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniform3fv(
+    GLES2Decoder* decoder, unsigned int arg_count, GLint location,
+    GLsizei count, const GLfloat* v) {
+  if (v == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniform3fvImmediate(
+    GLES2Decoder* decoder, unsigned int arg_count, GLint location,
+    GLsizei count, const GLfloat* v) {
+  if (v == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  if (!CheckImmediateDataSize<Uniform3fvImmediate>(
+      arg_count, count, sizeof(GLfloat), 3)) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniform3i(
+    GLES2Decoder* decoder, unsigned int arg_count, GLint location, GLint x,
+    GLint y, GLint z) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniform3iv(
+    GLES2Decoder* decoder, unsigned int arg_count, GLint location,
+    GLsizei count, const GLint* v) {
+  if (v == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniform3ivImmediate(
+    GLES2Decoder* decoder, unsigned int arg_count, GLint location,
+    GLsizei count, const GLint* v) {
+  if (v == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  if (!CheckImmediateDataSize<Uniform3ivImmediate>(
+      arg_count, count, sizeof(GLint), 3)) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniform4f(
+    GLES2Decoder* decoder, unsigned int arg_count, GLint location, GLfloat x,
+    GLfloat y, GLfloat z, GLfloat w) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniform4fv(
+    GLES2Decoder* decoder, unsigned int arg_count, GLint location,
+    GLsizei count, const GLfloat* v) {
+  if (v == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniform4fvImmediate(
+    GLES2Decoder* decoder, unsigned int arg_count, GLint location,
+    GLsizei count, const GLfloat* v) {
+  if (v == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  if (!CheckImmediateDataSize<Uniform4fvImmediate>(
+      arg_count, count, sizeof(GLfloat), 4)) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniform4i(
+    GLES2Decoder* decoder, unsigned int arg_count, GLint location, GLint x,
+    GLint y, GLint z, GLint w) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniform4iv(
+    GLES2Decoder* decoder, unsigned int arg_count, GLint location,
+    GLsizei count, const GLint* v) {
+  if (v == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniform4ivImmediate(
+    GLES2Decoder* decoder, unsigned int arg_count, GLint location,
+    GLsizei count, const GLint* v) {
+  if (v == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  if (!CheckImmediateDataSize<Uniform4ivImmediate>(
+      arg_count, count, sizeof(GLint), 4)) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniformMatrix2fv(
+    GLES2Decoder* decoder, unsigned int arg_count, GLint location,
+    GLsizei count, GLboolean transpose, const GLfloat* value) {
+  if (value == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniformMatrix2fvImmediate(
+    GLES2Decoder* decoder, unsigned int arg_count, GLint location,
+    GLsizei count, GLboolean transpose, const GLfloat* value) {
+  if (value == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  if (!CheckImmediateDataSize<UniformMatrix2fvImmediate>(
+      arg_count, count, sizeof(GLfloat), 4)) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniformMatrix3fv(
+    GLES2Decoder* decoder, unsigned int arg_count, GLint location,
+    GLsizei count, GLboolean transpose, const GLfloat* value) {
+  if (value == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniformMatrix3fvImmediate(
+    GLES2Decoder* decoder, unsigned int arg_count, GLint location,
+    GLsizei count, GLboolean transpose, const GLfloat* value) {
+  if (value == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  if (!CheckImmediateDataSize<UniformMatrix3fvImmediate>(
+      arg_count, count, sizeof(GLfloat), 9)) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniformMatrix4fv(
+    GLES2Decoder* decoder, unsigned int arg_count, GLint location,
+    GLsizei count, GLboolean transpose, const GLfloat* value) {
+  if (value == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniformMatrix4fvImmediate(
+    GLES2Decoder* decoder, unsigned int arg_count, GLint location,
+    GLsizei count, GLboolean transpose, const GLfloat* value) {
+  if (value == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  if (!CheckImmediateDataSize<UniformMatrix4fvImmediate>(
+      arg_count, count, sizeof(GLfloat), 16)) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUseProgram(
+    GLES2Decoder* decoder, unsigned int arg_count, GLuint program) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateValidateProgram(
+    GLES2Decoder* decoder, unsigned int arg_count, GLuint program) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateVertexAttrib1f(
+    GLES2Decoder* decoder, unsigned int arg_count, GLuint indx, GLfloat x) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateVertexAttrib1fv(
+    GLES2Decoder* decoder, unsigned int arg_count, GLuint indx,
+    const GLfloat* values) {
+  if (values == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateVertexAttrib1fvImmediate(
+    GLES2Decoder* decoder, unsigned int arg_count, GLuint indx,
+    const GLfloat* values) {
+  if (values == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  if (!CheckImmediateDataSize<VertexAttrib1fvImmediate>(
+      arg_count, 1, sizeof(GLfloat), 1)) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateVertexAttrib2f(
+    GLES2Decoder* decoder, unsigned int arg_count, GLuint indx, GLfloat x,
+    GLfloat y) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateVertexAttrib2fv(
+    GLES2Decoder* decoder, unsigned int arg_count, GLuint indx,
+    const GLfloat* values) {
+  if (values == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateVertexAttrib2fvImmediate(
+    GLES2Decoder* decoder, unsigned int arg_count, GLuint indx,
+    const GLfloat* values) {
+  if (values == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  if (!CheckImmediateDataSize<VertexAttrib2fvImmediate>(
+      arg_count, 1, sizeof(GLfloat), 2)) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateVertexAttrib3f(
+    GLES2Decoder* decoder, unsigned int arg_count, GLuint indx, GLfloat x,
+    GLfloat y, GLfloat z) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateVertexAttrib3fv(
+    GLES2Decoder* decoder, unsigned int arg_count, GLuint indx,
+    const GLfloat* values) {
+  if (values == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateVertexAttrib3fvImmediate(
+    GLES2Decoder* decoder, unsigned int arg_count, GLuint indx,
+    const GLfloat* values) {
+  if (values == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  if (!CheckImmediateDataSize<VertexAttrib3fvImmediate>(
+      arg_count, 1, sizeof(GLfloat), 3)) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateVertexAttrib4f(
+    GLES2Decoder* decoder, unsigned int arg_count, GLuint indx, GLfloat x,
+    GLfloat y, GLfloat z, GLfloat w) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateVertexAttrib4fv(
+    GLES2Decoder* decoder, unsigned int arg_count, GLuint indx,
+    const GLfloat* values) {
+  if (values == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateVertexAttrib4fvImmediate(
+    GLES2Decoder* decoder, unsigned int arg_count, GLuint indx,
+    const GLfloat* values) {
+  if (values == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  if (!CheckImmediateDataSize<VertexAttrib4fvImmediate>(
+      arg_count, 1, sizeof(GLfloat), 4)) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateVertexAttribPointer(
+    GLES2Decoder* decoder, unsigned int arg_count, GLuint indx, GLint size,
+    GLenum type, GLboolean normalized, GLsizei stride, const void* ptr) {
+  if (ptr == NULL) {
+    return parse_error::kParseOutOfBounds;
+  }
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateViewport(
+    GLES2Decoder* decoder, unsigned int arg_count, GLint x, GLint y,
+    GLsizei width, GLsizei height) {
+  return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateSwapBuffers(
+    GLES2Decoder* decoder, unsigned int arg_count) {
+  return parse_error::kParseNoError;
+}
+}  // anonymous namespace
+}  // namespace gles2
+}  // namespace command_buffer
+
diff --git a/gpu/command_buffer/service/gpu_processor.cc b/gpu/command_buffer/service/gpu_processor.cc
new file mode 100644
index 0000000..845d5b6dc
--- /dev/null
+++ b/gpu/command_buffer/service/gpu_processor.cc
@@ -0,0 +1,84 @@
+// Copyright (c) 2006-2008 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 "gpu/command_buffer/service/gpu_processor.h"
+#include "gpu/np_utils/np_browser.h"
+
+using ::base::SharedMemory;
+using np_utils::NPBrowser;
+
+namespace command_buffer {
+
+GPUProcessor::~GPUProcessor() {
+}
+
+namespace {
+void InvokeProcessCommands(void* data) {
+  static_cast<GPUProcessor*>(data)->ProcessCommands();
+}
+}  // namespace anonymous
+
+void GPUProcessor::ProcessCommands() {
+  if (command_buffer_->GetErrorStatus())
+    return;
+
+  parser_->set_put(command_buffer_->GetPutOffset());
+
+  int commands_processed = 0;
+  while (commands_processed < commands_per_update_ && !parser_->IsEmpty()) {
+    command_buffer::parse_error::ParseError parse_error =
+        parser_->ProcessCommand();
+    switch (parse_error) {
+      case command_buffer::parse_error::kParseUnknownCommand:
+      case command_buffer::parse_error::kParseInvalidArguments:
+        command_buffer_->SetParseError(parse_error);
+        break;
+
+      case command_buffer::parse_error::kParseInvalidSize:
+      case command_buffer::parse_error::kParseOutOfBounds:
+        command_buffer_->SetParseError(parse_error);
+        command_buffer_->RaiseErrorStatus();
+        return;
+    }
+
+    ++commands_processed;
+  }
+
+  command_buffer_->SetGetOffset(static_cast<int32>(parser_->get()));
+
+  if (!parser_->IsEmpty()) {
+    NPBrowser::get()->PluginThreadAsyncCall(npp_, InvokeProcessCommands, this);
+  }
+}
+
+void *GPUProcessor::GetSharedMemoryAddress(int32 shm_id) {
+  ::base::SharedMemory* shared_memory =
+      command_buffer_->GetTransferBuffer(shm_id);
+  if (!shared_memory)
+    return NULL;
+
+  if (!shared_memory->memory()) {
+    if (!shared_memory->Map(shared_memory->max_size()))
+      return NULL;
+  }
+
+  return shared_memory->memory();
+}
+
+// TODO(apatrick): Consolidate this with the above and return both the address
+// and size.
+size_t GPUProcessor::GetSharedMemorySize(int32 shm_id) {
+  ::base::SharedMemory* shared_memory =
+      command_buffer_->GetTransferBuffer(shm_id);
+  if (!shared_memory)
+    return 0;
+
+  return shared_memory->max_size();
+}
+
+void GPUProcessor::set_token(int32 token) {
+  command_buffer_->SetToken(token);
+}
+
+}  // namespace command_buffer
diff --git a/gpu/command_buffer/service/gpu_processor.h b/gpu/command_buffer/service/gpu_processor.h
new file mode 100644
index 0000000..786e504
--- /dev/null
+++ b/gpu/command_buffer/service/gpu_processor.h
@@ -0,0 +1,99 @@
+// Copyright (c) 2006-2008 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 GPU_COMMAND_BUFFER_SERVICE_GPU_PROCESSOR_H_
+#define GPU_COMMAND_BUFFER_SERVICE_GPU_PROCESSOR_H_
+
+#include "base/ref_counted.h"
+#include "base/scoped_ptr.h"
+#include "base/shared_memory.h"
+#include "gpu/command_buffer/common/command_buffer.h"
+#include "gpu/command_buffer/service/cmd_buffer_engine.h"
+#include "gpu/command_buffer/service/cmd_parser.h"
+#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
+#include "gpu/np_utils/np_object_pointer.h"
+
+namespace command_buffer {
+
+// This class processes commands in a command buffer. It is event driven and
+// posts tasks to the current message loop to do additional work.
+class GPUProcessor : public ::base::RefCounted<GPUProcessor>,
+                     public command_buffer::CommandBufferEngine {
+ public:
+  GPUProcessor(NPP npp, CommandBuffer* command_buffer);
+
+  // This constructor is for unit tests.
+  GPUProcessor(CommandBuffer* command_buffer,
+               gles2::GLES2Decoder* decoder,
+               CommandParser* parser,
+               int commands_per_update);
+
+  virtual bool Initialize(HWND hwnd);
+
+  virtual ~GPUProcessor();
+
+  virtual void Destroy();
+
+  virtual void ProcessCommands();
+
+#if defined(OS_WIN)
+  virtual bool SetWindow(HWND handle, int width, int height);
+#endif
+
+  // Implementation of CommandBufferEngine.
+
+  // Gets the base address of a registered shared memory buffer.
+  // Parameters:
+  //   shm_id: the identifier for the shared memory buffer.
+  virtual void *GetSharedMemoryAddress(int32 shm_id);
+
+  // Gets the size of a registered shared memory buffer.
+  // Parameters:
+  //   shm_id: the identifier for the shared memory buffer.
+  virtual size_t GetSharedMemorySize(int32 shm_id);
+
+  // Sets the token value.
+  virtual void set_token(int32 token);
+
+ private:
+  NPP npp_;
+
+  // The GPUProcessor holds a weak reference to the CommandBuffer. The
+  // CommandBuffer owns the GPUProcessor and holds a strong reference to it
+  // through the ProcessCommands callback.
+  CommandBuffer* command_buffer_;
+
+  scoped_ptr< ::base::SharedMemory> mapped_ring_buffer_;
+  int commands_per_update_;
+
+  scoped_ptr<gles2::GLES2Decoder> decoder_;
+  scoped_ptr<CommandParser> parser_;
+};
+
+}  // namespace command_buffer
+
+// Callbacks to the GPUProcessor hold a reference count.
+template <typename Method>
+class CallbackStorage<command_buffer::GPUProcessor, Method> {
+ public:
+  CallbackStorage(command_buffer::GPUProcessor* obj, Method method)
+      : obj_(obj),
+        meth_(method) {
+    DCHECK(obj_);
+    obj_->AddRef();
+  }
+
+  ~CallbackStorage() {
+    obj_->Release();
+  }
+
+ protected:
+  command_buffer::GPUProcessor* obj_;
+  Method meth_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(CallbackStorage);
+};
+
+#endif  // GPU_COMMAND_BUFFER_SERVICE_GPU_PROCESSOR_H_
diff --git a/gpu/command_buffer/service/gpu_processor_mock.h b/gpu/command_buffer/service/gpu_processor_mock.h
new file mode 100644
index 0000000..d65965f
--- /dev/null
+++ b/gpu/command_buffer/service/gpu_processor_mock.h
@@ -0,0 +1,40 @@
+// Copyright (c) 2006-2008 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 GPU_COMMAND_BUFFER_SERVICE_GPU_PROCESSOR_MOCK_H_
+#define GPU_COMMAND_BUFFER_SERVICE_GPU_PROCESSOR_MOCK_H_
+
+#include "gpu/command_buffer/service/gpu_processor.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace command_buffer {
+
+class MockGPUProcessor : public GPUProcessor {
+ public:
+  explicit MockGPUProcessor(CommandBuffer* command_buffer)
+      : GPUProcessor(NULL, command_buffer) {
+  }
+
+#if defined(OS_WIN)
+  MOCK_METHOD1(Initialize, bool(HWND handle));
+#endif
+
+  MOCK_METHOD0(Destroy, void());
+  MOCK_METHOD0(ProcessCommands, void());
+
+#if defined(OS_WIN)
+  MOCK_METHOD3(SetWindow, bool(HWND handle, int width, int height));
+#endif
+
+  MOCK_METHOD1(GetSharedMemoryAddress, void*(int32 shm_id));
+  MOCK_METHOD1(GetSharedMemorySize, size_t(int32 shm_id));
+  MOCK_METHOD1(set_token, void(int32 token));
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MockGPUProcessor);
+};
+
+}  // namespace command_buffer
+
+#endif  // GPU_COMMAND_BUFFER_SERVICE_GPU_PROCESSOR_MOCK_H_
diff --git a/gpu/command_buffer/service/gpu_processor_unittest.cc b/gpu/command_buffer/service/gpu_processor_unittest.cc
new file mode 100644
index 0000000..89a9392
--- /dev/null
+++ b/gpu/command_buffer/service/gpu_processor_unittest.cc
@@ -0,0 +1,285 @@
+// Copyright (c) 2006-2008 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 "base/at_exit.h"
+#include "base/message_loop.h"
+#include "gpu/command_buffer/common/command_buffer_mock.h"
+#include "gpu/command_buffer/service/mocks.h"
+#include "gpu/command_buffer/service/gpu_processor.h"
+#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
+#include "gpu/np_utils/np_browser_mock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+using testing::_;
+using testing::DoAll;
+using testing::Invoke;
+using testing::NiceMock;
+using testing::Return;
+using testing::SetArgumentPointee;
+using testing::StrictMock;
+
+namespace command_buffer {
+
+const size_t kRingBufferSize = 1024;
+const size_t kRingBufferEntries = kRingBufferSize / sizeof(int32);
+
+class GPUProcessorTest : public testing::Test {
+ protected:
+  virtual void SetUp() {
+    shared_memory_.reset(new ::base::SharedMemory);
+    shared_memory_->Create(std::wstring(), false, false, kRingBufferSize);
+    shared_memory_->Map(kRingBufferSize);
+    buffer_ = static_cast<int32*>(shared_memory_->memory());
+
+    memset(buffer_, 0, kRingBufferSize);
+
+    // Don't mock PluginThreadAsyncCall. Have it schedule the task.
+    ON_CALL(mock_browser_, PluginThreadAsyncCall(_, _, _))
+      .WillByDefault(
+          Invoke(&mock_browser_,
+                 &np_utils::MockNPBrowser::ConcretePluginThreadAsyncCall));
+
+    command_buffer_.reset(new MockCommandBuffer);
+    ON_CALL(*command_buffer_.get(), GetRingBuffer())
+      .WillByDefault(Return(shared_memory_.get()));
+    ON_CALL(*command_buffer_.get(), GetSize())
+      .WillByDefault(Return(kRingBufferEntries));
+
+    async_api_.reset(new StrictMock<command_buffer::AsyncAPIMock>);
+
+    decoder_ = gles2::GLES2Decoder::Create();
+
+    parser_ = new command_buffer::CommandParser(buffer_,
+                                                kRingBufferEntries,
+                                                0,
+                                                kRingBufferEntries,
+                                                0,
+                                                async_api_.get());
+
+    processor_ = new GPUProcessor(command_buffer_.get(),
+                                  decoder_,
+                                  parser_,
+                                  2);
+  }
+
+  virtual void TearDown() {
+    // Ensure that any unexpected tasks posted by the GPU processor are executed
+    // in order to fail the test.
+    MessageLoop::current()->RunAllPending();
+  }
+
+  base::AtExitManager at_exit_manager;
+  MessageLoop message_loop;
+  np_utils::MockNPBrowser mock_browser_;
+  scoped_ptr<MockCommandBuffer> command_buffer_;
+  scoped_ptr<::base::SharedMemory> shared_memory_;
+  int32* buffer_;
+  command_buffer::gles2::GLES2Decoder* decoder_;
+  command_buffer::CommandParser* parser_;
+  scoped_ptr<command_buffer::AsyncAPIMock> async_api_;
+  scoped_refptr<GPUProcessor> processor_;
+};
+
+TEST_F(GPUProcessorTest, ProcessorDoesNothingIfRingBufferIsEmpty) {
+  EXPECT_CALL(*command_buffer_, GetPutOffset())
+    .WillOnce(Return(0));
+  EXPECT_CALL(*command_buffer_, SetGetOffset(0));
+
+  processor_->ProcessCommands();
+
+  EXPECT_EQ(command_buffer::parse_error::kParseNoError,
+            command_buffer_->ResetParseError());
+  EXPECT_FALSE(command_buffer_->GetErrorStatus());
+}
+
+TEST_F(GPUProcessorTest, ProcessesOneCommand) {
+  command_buffer::CommandHeader* header =
+      reinterpret_cast<command_buffer::CommandHeader*>(&buffer_[0]);
+  header[0].command = 7;
+  header[0].size = 2;
+  buffer_[1] = 123;
+
+  EXPECT_CALL(*command_buffer_, GetPutOffset())
+    .WillOnce(Return(2));
+  EXPECT_CALL(*command_buffer_, SetGetOffset(2));
+
+  EXPECT_CALL(*async_api_, DoCommand(7, 1, &buffer_[0]))
+    .WillOnce(Return(command_buffer::parse_error::kParseNoError));
+
+  processor_->ProcessCommands();
+
+  EXPECT_EQ(command_buffer::parse_error::kParseNoError,
+            command_buffer_->ResetParseError());
+  EXPECT_FALSE(command_buffer_->GetErrorStatus());
+}
+
+TEST_F(GPUProcessorTest, ProcessesTwoCommands) {
+  command_buffer::CommandHeader* header =
+      reinterpret_cast<command_buffer::CommandHeader*>(&buffer_[0]);
+  header[0].command = 7;
+  header[0].size = 2;
+  buffer_[1] = 123;
+  header[2].command = 8;
+  header[2].size = 1;
+
+  EXPECT_CALL(*command_buffer_, GetPutOffset())
+    .WillOnce(Return(3));
+  EXPECT_CALL(*command_buffer_, SetGetOffset(3));
+
+  EXPECT_CALL(*async_api_, DoCommand(7, 1, &buffer_[0]))
+    .WillOnce(Return(command_buffer::parse_error::kParseNoError));
+
+  EXPECT_CALL(*async_api_, DoCommand(8, 0, &buffer_[2]))
+    .WillOnce(Return(command_buffer::parse_error::kParseNoError));
+
+  processor_->ProcessCommands();
+}
+
+TEST_F(GPUProcessorTest, PostsTaskToFinishRemainingCommands) {
+  command_buffer::CommandHeader* header =
+      reinterpret_cast<command_buffer::CommandHeader*>(&buffer_[0]);
+  header[0].command = 7;
+  header[0].size = 2;
+  buffer_[1] = 123;
+  header[2].command = 8;
+  header[2].size = 1;
+  header[3].command = 9;
+  header[3].size = 1;
+
+  EXPECT_CALL(*command_buffer_, GetPutOffset())
+    .WillOnce(Return(4));
+
+  EXPECT_CALL(*async_api_, DoCommand(7, 1, &buffer_[0]))
+    .WillOnce(Return(command_buffer::parse_error::kParseNoError));
+
+  EXPECT_CALL(*async_api_, DoCommand(8, 0, &buffer_[2]))
+    .WillOnce(Return(command_buffer::parse_error::kParseNoError));
+
+  EXPECT_CALL(*command_buffer_, SetGetOffset(3));
+
+  processor_->ProcessCommands();
+
+  // ProcessCommands is called a second time when the pending task is run.
+
+  EXPECT_CALL(*command_buffer_, GetPutOffset())
+    .WillOnce(Return(4));
+
+  EXPECT_CALL(*async_api_, DoCommand(9, 0, &buffer_[3]))
+    .WillOnce(Return(command_buffer::parse_error::kParseNoError));
+
+  EXPECT_CALL(*command_buffer_, SetGetOffset(4));
+
+  MessageLoop::current()->RunAllPending();
+}
+
+TEST_F(GPUProcessorTest, SetsErrorCodeOnCommandBuffer) {
+  command_buffer::CommandHeader* header =
+      reinterpret_cast<command_buffer::CommandHeader*>(&buffer_[0]);
+  header[0].command = 7;
+  header[0].size = 1;
+
+  EXPECT_CALL(*command_buffer_, GetPutOffset())
+    .WillOnce(Return(1));
+  EXPECT_CALL(*command_buffer_, SetGetOffset(1));
+
+  EXPECT_CALL(*async_api_, DoCommand(7, 0, &buffer_[0]))
+    .WillOnce(Return(
+        command_buffer::parse_error::kParseUnknownCommand));
+
+  EXPECT_CALL(*command_buffer_,
+      SetParseError(command_buffer::parse_error::kParseUnknownCommand));
+
+  processor_->ProcessCommands();
+}
+
+TEST_F(GPUProcessorTest,
+       RecoverableParseErrorsAreNotClearedByFollowingSuccessfulCommands) {
+  command_buffer::CommandHeader* header =
+      reinterpret_cast<command_buffer::CommandHeader*>(&buffer_[0]);
+  header[0].command = 7;
+  header[0].size = 1;
+  header[1].command = 8;
+  header[1].size = 1;
+
+  EXPECT_CALL(*command_buffer_, GetPutOffset())
+    .WillOnce(Return(2));
+  EXPECT_CALL(*command_buffer_, SetGetOffset(2));
+
+  EXPECT_CALL(*async_api_, DoCommand(7, 0, &buffer_[0]))
+    .WillOnce(Return(
+        command_buffer::parse_error::kParseUnknownCommand));
+
+  EXPECT_CALL(*async_api_, DoCommand(8, 0, &buffer_[1]))
+    .WillOnce(Return(command_buffer::parse_error::kParseNoError));
+
+  EXPECT_CALL(*command_buffer_,
+      SetParseError(command_buffer::parse_error::kParseUnknownCommand));
+
+  processor_->ProcessCommands();
+}
+
+TEST_F(GPUProcessorTest, UnrecoverableParseErrorsRaiseTheErrorStatus) {
+  command_buffer::CommandHeader* header =
+      reinterpret_cast<command_buffer::CommandHeader*>(&buffer_[0]);
+  header[0].command = 7;
+  header[0].size = 1;
+  header[1].command = 8;
+  header[1].size = 1;
+
+  EXPECT_CALL(*command_buffer_, GetPutOffset())
+    .WillOnce(Return(2));
+
+  EXPECT_CALL(*async_api_, DoCommand(7, 0, &buffer_[0]))
+    .WillOnce(Return(command_buffer::parse_error::kParseInvalidSize));
+
+  EXPECT_CALL(*command_buffer_,
+      SetParseError(command_buffer::parse_error::kParseInvalidSize));
+
+  EXPECT_CALL(*command_buffer_, RaiseErrorStatus());
+
+  processor_->ProcessCommands();
+}
+
+TEST_F(GPUProcessorTest, ProcessCommandsDoesNothingAfterUnrecoverableError) {
+  EXPECT_CALL(*command_buffer_, GetErrorStatus())
+    .WillOnce(Return(true));
+
+  EXPECT_CALL(*command_buffer_, GetPutOffset())
+    .Times(0);
+
+  processor_->ProcessCommands();
+}
+
+TEST_F(GPUProcessorTest, CanGetAddressOfSharedMemory) {
+  EXPECT_CALL(*command_buffer_.get(), GetTransferBuffer(7))
+    .WillOnce(Return(shared_memory_.get()));
+
+  EXPECT_EQ(&buffer_[0], processor_->GetSharedMemoryAddress(7));
+}
+
+ACTION_P2(SetPointee, address, value) {
+  *address = value;
+}
+
+TEST_F(GPUProcessorTest, GetAddressOfSharedMemoryMapsMemoryIfUnmapped) {
+  EXPECT_CALL(*command_buffer_.get(), GetTransferBuffer(7))
+    .WillOnce(Return(shared_memory_.get()));
+
+  EXPECT_EQ(&buffer_[0], processor_->GetSharedMemoryAddress(7));
+}
+
+TEST_F(GPUProcessorTest, CanGetSizeOfSharedMemory) {
+  EXPECT_CALL(*command_buffer_.get(), GetTransferBuffer(7))
+    .WillOnce(Return(shared_memory_.get()));
+
+  EXPECT_EQ(kRingBufferSize, processor_->GetSharedMemorySize(7));
+}
+
+TEST_F(GPUProcessorTest, SetTokenForwardsToCommandBuffer) {
+  EXPECT_CALL(*command_buffer_, SetToken(7));
+  processor_->set_token(7);
+}
+
+}  // namespace command_buffer
diff --git a/gpu/command_buffer/service/gpu_processor_win.cc b/gpu/command_buffer/service/gpu_processor_win.cc
new file mode 100644
index 0000000..d672c12
--- /dev/null
+++ b/gpu/command_buffer/service/gpu_processor_win.cc
@@ -0,0 +1,80 @@
+// Copyright (c) 2006-2008 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 <windows.h>
+
+#include "gpu/command_buffer/service/gpu_processor.h"
+
+using ::base::SharedMemory;
+
+namespace command_buffer {
+
+GPUProcessor::GPUProcessor(NPP npp, CommandBuffer* command_buffer)
+    : npp_(npp),
+      command_buffer_(command_buffer),
+      commands_per_update_(100) {
+  DCHECK(command_buffer);
+  decoder_.reset(gles2::GLES2Decoder::Create());
+  decoder_->set_engine(this);
+}
+
+GPUProcessor::GPUProcessor(CommandBuffer* command_buffer,
+                           gles2::GLES2Decoder* decoder,
+                           CommandParser* parser,
+                           int commands_per_update)
+    : npp_(NULL),
+      command_buffer_(command_buffer),
+      commands_per_update_(commands_per_update) {
+  DCHECK(command_buffer);
+  decoder_.reset(decoder);
+  parser_.reset(parser);
+}
+
+bool GPUProcessor::Initialize(HWND handle) {
+  DCHECK(handle);
+
+  // Cannot reinitialize.
+  if (decoder_->hwnd() != NULL)
+    return false;
+
+  // Map the ring buffer and create the parser.
+  ::base::SharedMemory* ring_buffer = command_buffer_->GetRingBuffer();
+  if (ring_buffer) {
+    size_t size = ring_buffer->max_size();
+    if (!ring_buffer->Map(size)) {
+      return false;
+    }
+
+    void* ptr = ring_buffer->memory();
+    parser_.reset(new command_buffer::CommandParser(ptr, size, 0, size, 0,
+                                                    decoder_.get()));
+  } else {
+    parser_.reset(new command_buffer::CommandParser(NULL, 0, 0, 0, 0,
+                                                    decoder_.get()));
+  }
+
+  // Initialize GAPI immediately if the window handle is valid.
+  decoder_->set_hwnd(handle);
+  return decoder_->Initialize();
+}
+
+void GPUProcessor::Destroy() {
+  // Destroy GAPI if window handle has not already become invalid.
+  if (decoder_->hwnd()) {
+    decoder_->Destroy();
+    decoder_->set_hwnd(NULL);
+  }
+}
+
+bool GPUProcessor::SetWindow(HWND handle, int width, int height) {
+  if (handle == NULL) {
+    // Destroy GAPI when the window handle becomes invalid.
+    Destroy();
+    return true;
+  } else {
+    return Initialize(handle);
+  }
+}
+
+}  // namespace command_buffer
diff --git a/gpu/command_buffer/service/mocks.h b/gpu/command_buffer/service/mocks.h
new file mode 100644
index 0000000..3d85e32
--- /dev/null
+++ b/gpu/command_buffer/service/mocks.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains definitions for mock objects, used for testing.
+
+// TODO: This file "manually" defines some mock objects. Using gMock
+// would be definitely preferable, unfortunately it doesn't work on Windows
+// yet.
+
+#ifndef GPU_COMMAND_BUFFER_SERVICE_CROSS_MOCKS_H_
+#define GPU_COMMAND_BUFFER_SERVICE_CROSS_MOCKS_H_
+
+#include <vector>
+#include "testing/gmock/include/gmock/gmock.h"
+#include "gpu/command_buffer/service/cmd_parser.h"
+#include "gpu/command_buffer/service/cmd_buffer_engine.h"
+
+namespace command_buffer {
+
+// Mocks an AsyncAPIInterface, using GMock.
+class AsyncAPIMock : public AsyncAPIInterface {
+ public:
+  AsyncAPIMock() {
+    testing::DefaultValue<parse_error::ParseError>::Set(
+        parse_error::kParseNoError);
+  }
+
+  // Predicate that matches args passed to DoCommand, by looking at the values.
+  class IsArgs {
+   public:
+    IsArgs(unsigned int arg_count, const void* args)
+        : arg_count_(arg_count),
+          args_(static_cast<CommandBufferEntry*>(const_cast<void*>(args))) {
+    }
+
+    bool operator() (const void* _args) const {
+      const CommandBufferEntry* args =
+          static_cast<const CommandBufferEntry*>(_args) + 1;
+      for (unsigned int i = 0; i < arg_count_; ++i) {
+        if (args[i].value_uint32 != args_[i].value_uint32) return false;
+      }
+      return true;
+    }
+
+   private:
+    unsigned int arg_count_;
+    CommandBufferEntry *args_;
+  };
+
+  MOCK_METHOD3(DoCommand, parse_error::ParseError(
+      unsigned int command,
+      unsigned int arg_count,
+      const void* cmd_data));
+
+  const char* GetCommandName(unsigned int command_id) const {
+    return "";
+  };
+
+  // Sets the engine, to forward SetToken commands to it.
+  void set_engine(CommandBufferEngine *engine) { engine_ = engine; }
+
+  // Forwards the SetToken commands to the engine.
+  void SetToken(unsigned int command,
+                unsigned int arg_count,
+                const void* _args) {
+    DCHECK(engine_);
+    DCHECK_EQ(1u, command);
+    DCHECK_EQ(1u, arg_count);
+    const CommandBufferEntry* args =
+        static_cast<const CommandBufferEntry*>(_args);
+    engine_->set_token(args[0].value_uint32);
+  }
+ private:
+  CommandBufferEngine *engine_;
+};
+
+}  // namespace command_buffer
+
+#endif  // GPU_COMMAND_BUFFER_SERVICE_CROSS_MOCKS_H_
diff --git a/gpu/command_buffer/service/precompile.cc b/gpu/command_buffer/service/precompile.cc
new file mode 100644
index 0000000..3e219b0
--- /dev/null
+++ b/gpu/command_buffer/service/precompile.cc
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "gpu/command_buffer/service/precompile.h"
diff --git a/gpu/command_buffer/service/precompile.h b/gpu/command_buffer/service/precompile.h
new file mode 100644
index 0000000..55d2b21
--- /dev/null
+++ b/gpu/command_buffer/service/precompile.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains includes for common headers used by command buffer server
+// files.  It is used for pre-compiled header support.
+
+#ifndef GPU_COMMAND_BUFFER_SERVICE_CROSS_PRECOMPILE_H_
+#define GPU_COMMAND_BUFFER_SERVICE_CROSS_PRECOMPILE_H_
+
+#include <build/build_config.h>
+
+#if defined(OS_WIN)
+#include <windows.h>
+#endif
+
+#include <assert.h>
+#include <algorithm>
+#include <map>
+#include <vector>
+
+#endif  // O3D_CORE_CROSS_PRECOMPILE_H_
diff --git a/gpu/command_buffer/service/resource.cc b/gpu/command_buffer/service/resource.cc
new file mode 100644
index 0000000..1208d30
--- /dev/null
+++ b/gpu/command_buffer/service/resource.cc
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains the implementation of ResourceMapBase.
+
+#include "gpu/command_buffer/service/precompile.h"
+#include "gpu/command_buffer/service/resource.h"
+
+namespace command_buffer {
+
+// Assigns a resource to a resource ID, by setting it at the right location
+// into the list, resizing the list if necessary, and destroying an existing
+// resource if one existed already.
+void ResourceMapBase::Assign(ResourceId id, Resource *resource) {
+  if (id >= resources_.size()) {
+    resources_.resize(id + 1, NULL);
+  } else {
+    Resource *&entry = resources_[id];
+    if (entry) {
+      delete entry;
+      entry = NULL;
+    }
+  }
+  DCHECK(resources_[id] == NULL);
+  resources_[id] = resource;
+}
+
+// Destroys a resource contained in the map, setting its entry to NULL. If
+// necessary, this will trim the list.
+bool ResourceMapBase::Destroy(ResourceId id) {
+  if (id >= resources_.size()) {
+    return false;
+  }
+  Resource *&entry = resources_[id];
+  if (entry) {
+    delete entry;
+    entry = NULL;
+
+    // Removing the last element, we can trim the list.
+    // TODO: this may not be optimal to do every time. Investigate if it
+    // becomes an issue, and add a threshold before we resize.
+    if (id == resources_.size() - 1) {
+      size_t last_valid = resources_.max_size();
+      for (unsigned int i = id; i < resources_.size(); --i) {
+        if (resources_[i]) {
+          last_valid = i;
+          break;
+        }
+      }
+      if (last_valid == resources_.max_size()) {
+        resources_.clear();
+      } else {
+        resources_.resize(last_valid + 1);
+      }
+    }
+    return true;
+  }
+  return false;
+}
+
+// Goes over all non-NULL entries in the list, destroying them, then clears the
+// list.
+void ResourceMapBase::DestroyAllResources() {
+  for (Container::iterator i = resources_.begin(); i != resources_.end(); ++i) {
+    if (*i) {
+      delete *i;
+    }
+  }
+  resources_.clear();
+}
+
+}  // namespace command_buffer
diff --git a/gpu/command_buffer/service/resource.h b/gpu/command_buffer/service/resource.h
new file mode 100644
index 0000000..20e30389
--- /dev/null
+++ b/gpu/command_buffer/service/resource.h
@@ -0,0 +1,268 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains the definition for resource classes and the resource map.
+
+#ifndef GPU_COMMAND_BUFFER_SERVICE_CROSS_RESOURCE_H_
+#define GPU_COMMAND_BUFFER_SERVICE_CROSS_RESOURCE_H_
+
+#include <vector>
+#include "base/scoped_ptr.h"
+#include "gpu/command_buffer/common/resource.h"
+
+namespace command_buffer {
+
+// Base class for resources, just providing a common Destroy function.
+class Resource {
+ public:
+  Resource() {}
+  virtual ~Resource() {}
+ private:
+  DISALLOW_COPY_AND_ASSIGN(Resource);
+};
+
+// VertexBuffer class, representing a vertex buffer resource.
+class VertexBuffer: public Resource {
+ public:
+  VertexBuffer(unsigned int size, unsigned int flags)
+      : size_(size),
+        flags_(flags) {}
+  virtual ~VertexBuffer() {}
+
+  // Returns the vertex buffer flags.
+  unsigned int flags() const { return flags_; }
+  // Sets the vertex buffer flags.
+  void set_flags(unsigned int flags) { flags_ = flags; }
+  // Returns the vertex buffer size.
+  unsigned int size() const { return size_; }
+  // Sets the vertex buffer size.
+  void set_size(unsigned int size) { size_ = size; }
+ protected:
+  unsigned int size_;
+  unsigned int flags_;
+ private:
+  DISALLOW_COPY_AND_ASSIGN(VertexBuffer);
+};
+
+// IndexBuffer class, representing an index buffer resource.
+class IndexBuffer: public Resource {
+ public:
+  IndexBuffer(unsigned int size, unsigned int flags)
+      : size_(size),
+        flags_(flags) {}
+  virtual ~IndexBuffer() {}
+
+  // Returns the index buffer flags.
+  unsigned int flags() const { return flags_; }
+  // Sets the index buffer flags.
+  void set_flags(unsigned int flags) { flags_ = flags; }
+  // Returns the index buffer size.
+  unsigned int size() const { return size_; }
+  // Sets the index buffer size.
+  void set_size(unsigned int size) { size_ = size; }
+ protected:
+  unsigned int size_;
+  unsigned int flags_;
+ private:
+  DISALLOW_COPY_AND_ASSIGN(IndexBuffer);
+};
+
+// VertexStruct class, representing a vertex struct resource.
+class VertexStruct: public Resource {
+ public:
+  // The representation of an input data stream.
+  struct Element {
+    ResourceId vertex_buffer;
+    unsigned int offset;
+    unsigned int stride;
+    vertex_struct::Type type;
+    vertex_struct::Semantic semantic;
+    unsigned int semantic_index;
+  };
+
+  explicit VertexStruct(unsigned int count)
+      : count_(count),
+        elements_(new Element[count]) {
+    memset(elements_.get(), 0, count * sizeof(Element));  // NOLINT
+  }
+
+  // Returns the number of inputs in this struct.
+  unsigned int count() const { return count_; }
+  // Returns an element by index.
+  Element &GetElement(unsigned int i) {
+    DCHECK_GT(count_, i);
+    return elements_[i];
+  }
+ protected:
+  unsigned int count_;
+  scoped_array<Element> elements_;
+ private:
+  DISALLOW_COPY_AND_ASSIGN(VertexStruct);
+};
+
+// Effect class, representing an effect.
+class Effect: public Resource {
+ public:
+  Effect() {}
+ private:
+  DISALLOW_COPY_AND_ASSIGN(Effect);
+};
+
+// EffectParam class, representing an effect parameter.
+class EffectParam: public Resource {
+ public:
+  explicit EffectParam(effect_param::DataType data_type)
+      : data_type_(data_type) {
+  }
+
+  // Gets the data type of this parameter.
+  effect_param::DataType data_type() const { return data_type_; }
+ private:
+  effect_param::DataType data_type_;
+  DISALLOW_COPY_AND_ASSIGN(EffectParam);
+};
+
+// Texture class, representing a texture resource.
+class Texture: public Resource {
+ public:
+  Texture(texture::Type type,
+          unsigned int levels,
+          texture::Format format,
+          bool enable_render_surfaces,
+          unsigned int flags)
+      : type_(type),
+        levels_(levels),
+        format_(format),
+        render_surfaces_enabled_(enable_render_surfaces),
+        flags_(flags) {}
+  virtual ~Texture() {}
+
+  // Returns the type of the texture.
+  texture::Type type() const { return type_; }
+  // Returns the texture flags.
+  unsigned int flags() const { return flags_; }
+  // Returns the texture format.
+  texture::Format format() const { return format_; }
+  // Returns whether the texture supports render surfaces
+  bool render_surfaces_enabled() const { return render_surfaces_enabled_; }
+  // Returns the number of mipmap levels in the texture.
+  unsigned int levels() const { return levels_; }
+ private:
+  texture::Type type_;
+  unsigned int levels_;
+  texture::Format format_;
+  bool render_surfaces_enabled_;
+  unsigned int flags_;
+  DISALLOW_COPY_AND_ASSIGN(Texture);
+};
+
+// RenderSurface class, representing a render surface/target
+class RenderSurface: public Resource {
+ public:
+  RenderSurface() {}
+ private:
+  DISALLOW_COPY_AND_ASSIGN(RenderSurface);
+};
+
+// RenderSurface class, representing a render surface/target
+class RenderDepthStencilSurface: public Resource {
+ public:
+  RenderDepthStencilSurface() {}
+ private:
+  DISALLOW_COPY_AND_ASSIGN(RenderDepthStencilSurface);
+};
+
+
+// Texture class, representing a sampler resource.
+class Sampler: public Resource {
+ public:
+  Sampler() {}
+ private:
+  DISALLOW_COPY_AND_ASSIGN(Sampler);
+};
+
+// Base of ResourceMap. Contains most of the implementation of ResourceMap, to
+// avoid template bloat.
+class ResourceMapBase {
+ public:
+  ResourceMapBase() : resources_() {}
+  ~ResourceMapBase() {}
+
+  // Assigns a resource to a resource ID. Assigning a resource to an ID that
+  // already has an existing resource will destroy that existing resource. The
+  // map takes ownership of the resource.
+  void Assign(ResourceId id, Resource* resource);
+  // Destroys a resource.
+  bool Destroy(ResourceId id);
+  // Destroy all resources.
+  void DestroyAllResources();
+  // Gets a resource by ID.
+  Resource *Get(ResourceId id) {
+    return (id < resources_.size()) ? resources_[id] : NULL;
+  }
+ private:
+  typedef std::vector<Resource *> Container;
+  Container resources_;
+};
+
+// Resource Map class, allowing resource ID <-> Resource association. This is a
+// dense map, optimized for retrieval (O(1)).
+template<class T> class ResourceMap {
+ public:
+  ResourceMap() : container_() {}
+  ~ResourceMap() {}
+
+  // Assigns a resource to a resource ID. Assigning a resource to an ID that
+  // already has an existing resource will destroy that existing resource. The
+  // map takes ownership of the resource.
+  void Assign(ResourceId id, T* resource) {
+    container_.Assign(id, resource);
+  }
+  // Destroys a resource.
+  bool Destroy(ResourceId id) {
+    return container_.Destroy(id);
+  }
+  // Destroy all resources.
+  void DestroyAllResources() {
+    return container_.DestroyAllResources();
+  }
+  // Gets a resource by ID.
+  T *Get(ResourceId id) {
+    return static_cast<T*>(container_.Get(id));
+  }
+ private:
+  ResourceMapBase container_;
+};
+
+}  // namespace command_buffer
+
+#endif  // GPU_COMMAND_BUFFER_SERVICE_CROSS_RESOURCE_H_
diff --git a/gpu/command_buffer/service/resource_test.cc b/gpu/command_buffer/service/resource_test.cc
new file mode 100644
index 0000000..7a9438b
--- /dev/null
+++ b/gpu/command_buffer/service/resource_test.cc
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// Tests for the ResourceMap.
+
+#include "gpu/command_buffer/service/precompile.h"
+#include "gpu/command_buffer/service/resource.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace command_buffer {
+
+// Mock resource implementation that checks for leaks.
+class ResourceMock : public Resource {
+ public:
+  ResourceMock() : Resource() {
+    ++instance_count_;
+  }
+  virtual ~ResourceMock() {
+    --instance_count_;
+  }
+
+  // Returns the instance count. The instance count is increased in the
+  // constructor and decreased in the destructor, to track leaks. The reason is
+  // that we can't mock the destructor, though we want to make sure the mock is
+  // destroyed.
+  static int instance_count() { return instance_count_; }
+ private:
+  static int instance_count_;
+  DISALLOW_COPY_AND_ASSIGN(ResourceMock);
+};
+int ResourceMock::instance_count_ = 0;
+
+// Test fixture for ResourceMap test. Creates a ResourceMap using a mock
+// Resource, and checks for ResourceMock leaks.
+class ResourceMapTest : public testing::Test {
+ protected:
+  typedef ResourceMap<ResourceMock> Map;
+  virtual void SetUp() {
+    instance_count_ = ResourceMock::instance_count();
+    map_.reset(new Map());
+  }
+  virtual void TearDown() {
+    CheckLeaks();
+  }
+
+  // Makes sure we didn't leak any ResourceMock object.
+  void CheckLeaks() {
+    EXPECT_EQ(instance_count_, ResourceMock::instance_count());
+  }
+
+  Map *map() const { return map_.get(); }
+ private:
+  int instance_count_;
+  scoped_ptr<Map> map_;
+};
+
+TEST_F(ResourceMapTest, TestMap) {
+  // check that initial mapping is empty.
+  EXPECT_EQ(NULL, map()->Get(0));
+  EXPECT_EQ(NULL, map()->Get(1));
+  EXPECT_EQ(NULL, map()->Get(392));
+
+  // create a new resource, assign it to an ID.
+  ResourceMock *resource = new ResourceMock();
+  map()->Assign(123, resource);
+  EXPECT_EQ(resource, map()->Get(123));
+
+  // Destroy the resource, making sure the object is deleted.
+  EXPECT_EQ(true, map()->Destroy(123));
+  EXPECT_EQ(false, map()->Destroy(123));  // destroying again should fail.
+  resource = NULL;
+  CheckLeaks();
+
+  // create a new resource, add it to the map, and make sure it gets deleted
+  // when we assign a new resource to that ID.
+  resource = new ResourceMock();
+  map()->Assign(1, resource);
+  resource = new ResourceMock();
+  map()->Assign(1, resource);
+  EXPECT_EQ(resource, map()->Get(1));  // check that we have the new resource.
+  EXPECT_EQ(true, map()->Destroy(1));
+  CheckLeaks();
+
+  // Adds 3 resources, then call DestroyAllResources().
+  resource = new ResourceMock();
+  map()->Assign(1, resource);
+  resource = new ResourceMock();
+  map()->Assign(2, resource);
+  resource = new ResourceMock();
+  map()->Assign(3, resource);
+  map()->DestroyAllResources();
+  EXPECT_EQ(NULL, map()->Get(1));
+  EXPECT_EQ(NULL, map()->Get(2));
+  EXPECT_EQ(NULL, map()->Get(3));
+  CheckLeaks();
+}
+
+}  // namespace command_buffer
diff --git a/gpu/command_buffer/service/x_utils.cc b/gpu/command_buffer/service/x_utils.cc
new file mode 100644
index 0000000..b9eb9d9
--- /dev/null
+++ b/gpu/command_buffer/service/x_utils.cc
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This class implements the XWindowWrapper class.
+
+#include "gpu/command_buffer/service/precompile.h"
+#include "gpu/command_buffer/common/cross/logging.h"
+#include "gpu/command_buffer/service/linux/x_utils.h"
+
+namespace command_buffer {
+
+bool XWindowWrapper::Initialize() {
+  XWindowAttributes attributes;
+  XGetWindowAttributes(display_, window_, &attributes);
+  XVisualInfo visual_info_template;
+  visual_info_template.visualid = XVisualIDFromVisual(attributes.visual);
+  int visual_info_count = 0;
+  XVisualInfo *visual_info_list = XGetVisualInfo(display_, VisualIDMask,
+                                                 &visual_info_template,
+                                                 &visual_info_count);
+  DCHECK(visual_info_list);
+  DCHECK_GT(visual_info_count, 0);
+  context_ = 0;
+  for (int i = 0; i < visual_info_count; ++i) {
+    context_ = glXCreateContext(display_, visual_info_list + i, 0,
+                                True);
+    if (context_) break;
+  }
+  XFree(visual_info_list);
+  if (!context_) {
+    DLOG(ERROR) << "Couldn't create GL context.";
+    return false;
+  }
+  return true;
+}
+
+bool XWindowWrapper::MakeCurrent() {
+  if (glXMakeCurrent(display_, window_, context_) != True) {
+    glXDestroyContext(display_, context_);
+    context_ = 0;
+    DLOG(ERROR) << "Couldn't make context current.";
+    return false;
+  }
+  return true;
+}
+
+void XWindowWrapper::Destroy() {
+  Bool result = glXMakeCurrent(display_, 0, 0);
+  // glXMakeCurrent isn't supposed to fail when unsetting the context, unless
+  // we have pending draws on an invalid window - which shouldn't be the case
+  // here.
+  DCHECK(result);
+  if (context_) {
+    glXDestroyContext(display_, context_);
+    context_ = 0;
+  }
+}
+
+void XWindowWrapper::SwapBuffers() {
+  glXSwapBuffers(display_, window_);
+}
+
+}  // namespace command_buffer
diff --git a/gpu/command_buffer/service/x_utils.h b/gpu/command_buffer/service/x_utils.h
new file mode 100644
index 0000000..0d8c26a
--- /dev/null
+++ b/gpu/command_buffer/service/x_utils.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file declares the XWindowWrapper class.
+
+#ifndef GPU_COMMAND_BUFFER_SERVICE_X_UTILS_H_
+#define GPU_COMMAND_BUFFER_SERVICE_X_UTILS_H_
+
+#include <GL/glx.h>
+#include "base/basictypes.h"
+#include "gpu/command_buffer/common/cross/logging.h"
+
+namespace command_buffer {
+
+// This class is a wrapper around an X Window and associated GL context. It is
+// useful to isolate intrusive X headers, since it can be forward declared
+// (Window and GLXContext can't).
+class XWindowWrapper {
+ public:
+  XWindowWrapper(Display *display, Window window)
+      : display_(display),
+        window_(window) {
+    DCHECK(display_);
+    DCHECK(window_);
+  }
+  // Initializes the GL context.
+  bool Initialize();
+
+  // Destroys the GL context.
+  void Destroy();
+
+  // Makes the GL context current on the current thread.
+  bool MakeCurrent();
+
+  // Swaps front and back buffers.
+  void SwapBuffers();
+
+ private:
+  Display *display_;
+  Window window_;
+  GLXContext context_;
+  DISALLOW_COPY_AND_ASSIGN(XWindowWrapper);
+};
+
+}  // namespace command_buffer
+
+#endif  // GPU_COMMAND_BUFFER_SERVICE_X_UTILS_H_
diff --git a/gpu/gpu.gyp b/gpu/gpu.gyp
new file mode 100644
index 0000000..aa89b51
--- /dev/null
+++ b/gpu/gpu.gyp
@@ -0,0 +1,412 @@
+# Copyright (c) 2009 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.
+
+{
+  'variables': {
+    'chromium_code': 1,
+  },
+  'includes': [
+    '../build/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'gl_libs',
+      'type': 'static_library',
+        'include_dirs': [
+          '../third_party/glew/include',
+        ],
+        'defines': [
+          'GLEW_STATIC',
+        ],
+      'all_dependent_settings': {
+        'include_dirs': [
+          '../third_party/glew/include',
+        ],
+        'defines': [
+          'GLEW_STATIC',
+        ],
+      },
+      'sources': [
+        '../third_party/glew/src/glew.c',
+      ],
+      'conditions': [
+        [ 'OS=="linux"',
+          {
+            'all_dependent_settings': {
+              'defines': [
+                'GL_GLEXT_PROTOTYPES',
+              ],
+              'ldflags': [
+                '-L<(PRODUCT_DIR)',
+              ],
+              'libraries': [
+                '-lGL',
+                '-lX11',
+              ],
+            },
+          },
+        ],
+        [ 'OS=="mac"',
+          {
+            'direct_dependent_settings': {
+              'libraries': [
+                '$(SDKROOT)/System/Library/Frameworks/OpenGL.framework',
+              ],
+            },
+          },
+        ],
+        [ 'OS=="win"',
+          {
+            'all_dependent_settings': {
+              'libraries': [
+                '-lOpenGL32.lib',
+              ],
+            },
+          },
+        ],
+      ],
+    },
+    {
+      'target_name': 'command_buffer_common',
+      'type': 'static_library',
+      'include_dirs': [
+        'command_buffer/common',
+        '..',
+      ],
+      'all_dependent_settings': {
+        'include_dirs': [
+          'command_buffer/common',
+          '..',
+        ],
+      },
+      'sources': [
+        'command_buffer/common/bitfield_helpers.h',
+        'command_buffer/common/cmd_buffer_common.h',
+        'command_buffer/common/cmd_buffer_common.cc',
+        'command_buffer/common/command_buffer.h',
+        'command_buffer/common/command_buffer_mock.h',
+        'command_buffer/common/gles2_cmd_ids_autogen.h',
+        'command_buffer/common/gles2_cmd_ids.h',
+        'command_buffer/common/gles2_cmd_format_autogen.h',
+        'command_buffer/common/gles2_cmd_format.cc',
+        'command_buffer/common/gles2_cmd_format.h',
+        'command_buffer/common/gles2_cmd_utils.cc',
+        'command_buffer/common/gles2_cmd_utils.h',
+        'command_buffer/common/logging.h',
+        'command_buffer/common/mocks.h',
+        'command_buffer/common/resource.cc',
+        'command_buffer/common/resource.h',
+        'command_buffer/common/types.h',
+      ],
+    },
+    {
+      # Library helps make GLES2 command buffers.
+      'target_name': 'gles2_cmd_helper',
+      'type': 'static_library',
+      'dependencies': [
+        'command_buffer_common',
+        'np_utils',
+      ],
+      'sources': [
+        'command_buffer/client/gles2_cmd_helper.cc',
+        'command_buffer/client/gles2_cmd_helper.h',
+        'command_buffer/client/gles2_cmd_helper_autogen.h',
+      ],
+    },
+    {
+      # Library emulates GLES2 using command_buffers.
+      'target_name': 'gles2_implementation',
+      'type': 'static_library',
+      'dependencies': [
+        'gles2_cmd_helper',
+      ],
+      'sources': [
+        'command_buffer/client/gles2_implementation_autogen.h',
+        'command_buffer/client/gles2_implementation.cc',
+        'command_buffer/client/gles2_implementation_gen.h',
+        'command_buffer/client/gles2_implementation.h',
+      ],
+    },
+    {
+      # Stub to expose gles2_implementation as a namespace rather than a class
+      # so GLES2 C++ programs can work with no changes.
+      'target_name': 'gles2_lib',
+      'type': 'static_library',
+      'dependencies': [
+        'gles2_implementation',
+      ],
+      'sources': [
+        'command_buffer/client/gles2_lib.cc',
+        'command_buffer/client/gles2_lib.h',
+      ],
+    },
+    {
+      # Stub to expose gles2_implemenation in C instead of C++.
+      # so GLES2 C programs can work with no changes.
+      'target_name': 'gles2_c_lib',
+      'type': 'static_library',
+      'dependencies': [
+        'gles2_lib',
+      ],
+      'sources': [
+        'command_buffer/client/gles2_c_lib.h',
+        'command_buffer/client/gles2_c_lib.cc',
+        'command_buffer/client/gles2_c_lib_autogen.h',
+      ],
+    },
+    {
+      'target_name': 'command_buffer_common_unittests',
+      'type': 'none',
+      'include_dirs': [
+        'command_buffer/common',
+      ],
+      'dependencies': [
+        'gles2_lib',
+        'gles2_implementation',
+        'gles2_cmd_helper',
+      ],
+      'direct_dependent_settings': {
+        'sources': [
+          'command_buffer/common/bitfield_helpers_test.cc',
+          'command_buffer/common/gles2_cmd_format_test.cc',
+          'command_buffer/common/gles2_cmd_format_test_autogen.h',
+          'command_buffer/common/gles2_cmd_id_test.cc',
+        ],
+      },
+    },
+    {
+      'target_name': 'command_buffer_client',
+      'type': 'static_library',
+      'dependencies': [
+        'command_buffer_common',
+      ],
+      'sources': [
+        'command_buffer/client/cmd_buffer_helper.cc',
+        'command_buffer/client/cmd_buffer_helper.h',
+        'command_buffer/client/fenced_allocator.cc',
+        'command_buffer/client/fenced_allocator.h',
+        'command_buffer/client/id_allocator.cc',
+        'command_buffer/client/id_allocator.h',
+      ],
+    },
+    {
+      'target_name': 'command_buffer_client_unittests',
+      'type': 'none',
+      'direct_dependent_settings': {
+        'sources': [
+          'command_buffer/client/cmd_buffer_helper_test.cc',
+          'command_buffer/client/fenced_allocator_test.cc',
+          'command_buffer/client/id_allocator_test.cc',
+        ],
+      },
+    },
+    {
+      'target_name': 'command_buffer_service',
+      'type': 'static_library',
+      'include_dirs': [
+        '..',
+      ],
+      'all_dependent_settings': {
+        'include_dirs': [
+          '..',
+        ],
+      },
+      'dependencies': [
+        'command_buffer_common',
+        'gl_libs',
+      ],
+      'sources': [
+        'command_buffer/service/common_decoder.cc',
+        'command_buffer/service/common_decoder.h',
+        'command_buffer/service/cmd_buffer_engine.h',
+        'command_buffer/service/command_buffer_service.cc',
+        'command_buffer/service/command_buffer_service.h',
+        'command_buffer/service/cmd_parser.cc',
+        'command_buffer/service/cmd_parser.h',
+        'command_buffer/service/gles2_cmd_decoder.h',
+        'command_buffer/service/gles2_cmd_decoder_validate.h',
+        'command_buffer/service/gles2_cmd_decoder_autogen.h',
+        'command_buffer/service/gles2_cmd_decoder.cc',
+        'command_buffer/service/gl_utils.h',
+        'command_buffer/service/gpu_processor.h',
+        'command_buffer/service/gpu_processor.cc',
+        'command_buffer/service/gpu_processor_mock.h',
+        'command_buffer/service/mocks.h',
+        'command_buffer/service/precompile.cc',
+        'command_buffer/service/precompile.h',
+        'command_buffer/service/resource.cc',
+        'command_buffer/service/resource.h',
+      ],
+      'conditions': [
+        ['OS == "linux"',
+          {
+            'sources': [
+              'command_buffer/service/linux/x_utils.cc',
+              'command_buffer/service/linux/x_utils.h',
+            ],
+          },
+        ],
+        ['OS == "win"',
+          {
+            'sources': [
+              'command_buffer/service/gpu_processor_win.cc',
+            ],
+          },
+        ],
+      ],
+    },
+    {
+      'target_name': 'command_buffer_service_unittests',
+      'type': 'none',
+      'direct_dependent_settings': {
+        'sources': [
+          'command_buffer/service/cmd_parser_test.cc',
+          'command_buffer/service/command_buffer_service_unittest.cc',
+          'command_buffer/service/gpu_processor_unittest.cc',
+          'command_buffer/service/resource_test.cc',
+        ],
+      },
+    },
+    {
+      'target_name': 'np_utils',
+      'type': '<(library)',
+      'dependencies': [
+        '../base/base.gyp:base',
+      ],
+      'include_dirs': [
+        '..',
+      ],
+      'all_dependent_settings': {
+        'include_dirs': [
+          '..',
+        ],
+      },
+      'sources': [
+        'np_utils/default_np_object.h',
+        'np_utils/dynamic_np_object.cc',
+        'np_utils/dynamic_np_object.h',
+        'np_utils/np_browser.cc',
+        'np_utils/np_browser.h',
+        'np_utils/np_browser_mock.h',
+        'np_utils/np_browser_stub.cc',
+        'np_utils/np_browser_stub.h',
+        'np_utils/np_class.h',
+        'np_utils/np_dispatcher.cc',
+        'np_utils/np_dispatcher.h',
+        'np_utils/np_dispatcher_specializations.h',
+        'np_utils/np_headers.h',
+        'np_utils/np_object_mock.h',
+        'np_utils/np_object_pointer.h',
+        'np_utils/np_plugin_object.h',
+        'np_utils/np_plugin_object_mock.h',
+        'np_utils/np_plugin_object_factory.cc',
+        'np_utils/np_plugin_object_factory.h',
+        'np_utils/np_plugin_object_factory_mock.h',
+        'np_utils/np_utils.cc',
+        'np_utils/np_utils.h',
+        'np_utils/webkit_browser.h',
+      ],
+    },
+    {
+      'target_name': 'np_utils_unittests',
+      'type': 'none',
+      'direct_dependent_settings': {
+        'include_dirs': [
+          '..',
+        ],
+        'sources': [
+          'np_utils/dispatched_np_object_unittest.cc',
+          'np_utils/dynamic_np_object_unittest.cc',
+          'np_utils/np_class_unittest.cc',
+          'np_utils/np_object_pointer_unittest.cc',
+          'np_utils/np_utils_unittest.cc',
+        ],
+      },
+    },
+    {
+      'target_name': 'gpu_plugin',
+      'type': '<(library)',
+      'dependencies': [
+        '../base/base.gyp:base',
+        'command_buffer_service',
+        'np_utils',
+      ],
+      'include_dirs': [
+        '..',
+      ],
+      'all_dependent_settings': {
+        'include_dirs': [
+          '..',
+        ],
+      },
+      'sources': [
+        'gpu_plugin/gpu_plugin.cc',
+        'gpu_plugin/gpu_plugin.h',
+        'gpu_plugin/gpu_plugin_object.cc',
+        'gpu_plugin/gpu_plugin_object.h',
+        'gpu_plugin/gpu_plugin_object_win.cc',
+        'gpu_plugin/gpu_plugin_object_factory.cc',
+        'gpu_plugin/gpu_plugin_object_factory.h',
+      ],
+    },
+    {
+      'target_name': 'gpu_plugin_unittests',
+      'type': 'none',
+      'direct_dependent_settings': {
+        'include_dirs': [
+          '..',
+        ],
+        'sources': [
+          'gpu_plugin/gpu_plugin_unittest.cc',
+          'gpu_plugin/gpu_plugin_object_unittest.cc',
+          'gpu_plugin/gpu_plugin_object_factory_unittest.cc',
+        ],
+      },
+    },
+    {
+      'target_name': 'gpu_all_unittests',
+      'type': 'executable',
+      'dependencies': [
+        '../testing/gmock.gyp:gmock',
+        '../testing/gmock.gyp:gmockmain',
+        '../testing/gtest.gyp:gtest',
+        'command_buffer_client',
+        'command_buffer_client_unittests',
+        'command_buffer_common',
+        'command_buffer_common_unittests',
+        'command_buffer_service',
+        'command_buffer_service_unittests',
+        'gpu_plugin',
+        'gpu_plugin_unittests',
+        'np_utils',
+        'np_utils_unittests',
+      ],
+    },
+    {
+      'target_name': 'gles2_demo',
+      'type': 'executable',
+      'dependencies': [
+        'command_buffer_client',
+        'command_buffer_service',
+        'gles2_lib',
+        'gles2_c_lib',
+        'gpu_plugin',
+        'np_utils',
+      ],
+      'sources': [
+        'command_buffer/client/gles2_demo.cc',
+        'command_buffer/client/gles2_demo_c.h',
+        'command_buffer/client/gles2_demo_c.c',
+        'command_buffer/client/gles2_demo_cc.h',
+        'command_buffer/client/gles2_demo_cc.cc',
+      ],
+    },
+  ]
+}
+
+# Local Variables:
+# tab-width:2
+# indent-tabs-mode:nil
+# End:
+# vim: set expandtab tabstop=2 shiftwidth=2:
diff --git a/gpu/gpu_plugin/gpu_plugin.cc b/gpu/gpu_plugin/gpu_plugin.cc
new file mode 100644
index 0000000..35771fd
--- /dev/null
+++ b/gpu/gpu_plugin/gpu_plugin.cc
@@ -0,0 +1,135 @@
+// Copyright (c) 2006-2008 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 "gpu/gpu_plugin/gpu_plugin.h"
+#include "gpu/gpu_plugin/gpu_plugin_object_factory.h"
+#include "gpu/np_utils/np_browser.h"
+#include "gpu/np_utils/np_plugin_object.h"
+#include "gpu/np_utils/np_plugin_object_factory.h"
+#include "webkit/glue/plugins/nphostapi.h"
+
+using np_utils::NPBrowser;
+using np_utils::NPPluginObjectFactory;
+using np_utils::PluginObject;
+
+namespace gpu_plugin {
+
+// Definitions of NPAPI plugin entry points.
+
+namespace {
+NPBrowser* g_browser;
+GPUPluginObjectFactory g_plugin_object_factory;
+
+NPError NPP_New(NPMIMEType plugin_type, NPP instance,
+                uint16 mode, int16 argc, char* argn[],
+                char* argv[], NPSavedData* saved) {
+  if (!instance)
+    return NPERR_INVALID_INSTANCE_ERROR;
+
+  PluginObject* plugin_object =
+      NPPluginObjectFactory::get()->CreatePluginObject(instance, plugin_type);
+  if (!plugin_object)
+    return NPERR_GENERIC_ERROR;
+
+  instance->pdata = plugin_object;
+
+  NPError error = plugin_object->New(plugin_type, argc, argn, argv, saved);
+  if (error != NPERR_NO_ERROR) {
+    plugin_object->Release();
+  }
+
+  return error;
+}
+
+NPError NPP_Destroy(NPP instance, NPSavedData** saved) {
+  if (!instance)
+    return NPERR_INVALID_INSTANCE_ERROR;
+
+  PluginObject* plugin_object = static_cast<PluginObject*>(instance->pdata);
+  NPError error = plugin_object->Destroy(saved);
+
+  if (error == NPERR_NO_ERROR) {
+    plugin_object->Release();
+  }
+
+  return error;
+}
+
+NPError NPP_SetWindow(NPP instance, NPWindow* window) {
+  if (!instance)
+    return NPERR_INVALID_INSTANCE_ERROR;
+
+  PluginObject* plugin_object = static_cast<PluginObject*>(instance->pdata);
+  return plugin_object->SetWindow(window);
+}
+
+int16 NPP_HandleEvent(NPP instance, void* event) {
+  if (!instance)
+    return 0;
+
+  PluginObject* plugin_object = static_cast<PluginObject*>(instance->pdata);
+  return plugin_object->HandleEvent(static_cast<NPEvent*>(event));
+}
+
+NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value) {
+  if (!instance)
+    return NPERR_INVALID_INSTANCE_ERROR;
+
+  PluginObject* plugin_object = static_cast<PluginObject*>(instance->pdata);
+  switch (variable) {
+    case NPPVpluginScriptableNPObject:
+      *reinterpret_cast<NPObject**>(value) =
+          plugin_object->GetScriptableNPObject();
+      return NPERR_NO_ERROR;
+    default:
+      return NPERR_GENERIC_ERROR;
+  }
+}
+
+NPError NPP_SetValue(NPP instance, NPNVariable variable, void *value) {
+  return NPERR_NO_ERROR;
+}
+}
+
+NPError NP_GetEntryPoints(NPPluginFuncs* funcs) {
+  funcs->newp = NPP_New;
+  funcs->destroy = NPP_Destroy;
+  funcs->setwindow = NPP_SetWindow;
+  funcs->event = NPP_HandleEvent;
+  funcs->getvalue = NPP_GetValue;
+  funcs->setvalue = NPP_SetValue;
+  return NPERR_NO_ERROR;
+}
+
+#if defined(OS_LINUX)
+NPError API_CALL NP_Initialize(NPNetscapeFuncs *browser_funcs,
+                               NPPluginFuncs* plugin_funcs) {
+#else
+NPError NP_Initialize(NPNetscapeFuncs *browser_funcs) {
+#endif
+  if (!browser_funcs)
+    return NPERR_INVALID_FUNCTABLE_ERROR;
+
+  if (g_browser)
+    return NPERR_GENERIC_ERROR;
+
+#if defined(OS_LINUX)
+  NP_GetEntryPoints(plugin_funcs);
+#endif
+
+  g_browser = new NPBrowser(browser_funcs);
+
+  return NPERR_NO_ERROR;
+}
+
+NPError NP_Shutdown() {
+  if (!g_browser)
+    return NPERR_GENERIC_ERROR;
+
+  delete g_browser;
+  g_browser = NULL;
+
+  return NPERR_NO_ERROR;
+}
+}  // namespace gpu_plugin
diff --git a/gpu/gpu_plugin/gpu_plugin.h b/gpu/gpu_plugin/gpu_plugin.h
new file mode 100644
index 0000000..0f90f77
--- /dev/null
+++ b/gpu/gpu_plugin/gpu_plugin.h
@@ -0,0 +1,30 @@
+// Copyright (c) 2006-2008 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 GPU_GPU_PLUGIN_GPU_PLUGIN_H_
+#define GPU_GPU_PLUGIN_GPU_PLUGIN_H_
+
+#include "gpu/np_utils/np_headers.h"
+
+typedef struct _NPPluginFuncs NPPluginFuncs;
+typedef struct _NPNetscapeFuncs NPNetscapeFuncs;
+
+namespace gpu_plugin {
+
+// Declarations of NPAPI plugin entry points.
+
+NPError NP_GetEntryPoints(NPPluginFuncs* funcs);
+
+#if defined(OS_LINUX)
+NPError NP_Initialize(NPNetscapeFuncs *browser_funcs,
+                               NPPluginFuncs* plugin_funcs);
+#else
+NPError NP_Initialize(NPNetscapeFuncs* browser_funcs);
+#endif
+
+NPError NP_Shutdown();
+
+}  // namespace gpu_plugin
+
+#endif  // GPU_GPU_PLUGIN_GPU_PLUGIN_H_
diff --git a/gpu/gpu_plugin/gpu_plugin_object.cc b/gpu/gpu_plugin/gpu_plugin_object.cc
new file mode 100644
index 0000000..d4ea9150
--- /dev/null
+++ b/gpu/gpu_plugin/gpu_plugin_object.cc
@@ -0,0 +1,123 @@
+// Copyright (c) 2006-2008 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 <stdlib.h>
+
+#include "base/logging.h"
+#include "gpu/command_buffer/service/command_buffer_service.h"
+#include "gpu/command_buffer/service/gpu_processor.h"
+#include "gpu/np_utils/np_utils.h"
+#include "gpu/gpu_plugin/gpu_plugin_object.h"
+
+using ::base::SharedMemory;
+using command_buffer::CommandBuffer;
+using command_buffer::CommandBufferService;
+using command_buffer::GPUProcessor;
+using np_utils::NPBrowser;
+using np_utils::NPObjectPointer;
+
+namespace gpu_plugin {
+
+const NPUTF8 GPUPluginObject::kPluginType[] =
+    "application/vnd.google.chrome.gpu-plugin";
+
+GPUPluginObject::GPUPluginObject(NPP npp)
+    : npp_(npp),
+      status_(kWaitingForNew),
+      command_buffer_(new CommandBufferService),
+      processor_(new GPUProcessor(npp, command_buffer_.get())) {
+  memset(&window_, 0, sizeof(window_));
+}
+
+NPError GPUPluginObject::New(NPMIMEType plugin_type,
+                             int16 argc,
+                             char* argn[],
+                             char* argv[],
+                             NPSavedData* saved) {
+  if (status_ != kWaitingForNew)
+    return NPERR_GENERIC_ERROR;
+
+  status_ = kWaitingForSetWindow;
+
+  return NPERR_NO_ERROR;
+}
+
+NPError GPUPluginObject::SetWindow(NPWindow* new_window) {
+  if (status_ == kWaitingForNew || status_ == kDestroyed)
+    return NPERR_GENERIC_ERROR;
+
+  // PlatformSpecificSetWindow advances the status depending on what happens.
+  NPError error = PlatformSpecificSetWindow(new_window);
+  if (error == NPERR_NO_ERROR) {
+    window_ = *new_window;
+
+    if (event_sync_.Get()) {
+      NPInvokeVoid(npp_,
+                   event_sync_,
+                   "resize",
+                   static_cast<int32>(window_.width),
+                   static_cast<int32>(window_.height));
+    }
+  } else {
+    memset(&window_, 0, sizeof(window_));
+  }
+
+  return error;
+}
+
+int16 GPUPluginObject::HandleEvent(NPEvent* event) {
+  return 0;
+}
+
+NPError GPUPluginObject::Destroy(NPSavedData** saved) {
+  if (status_ == kWaitingForNew || status_ == kDestroyed)
+    return NPERR_GENERIC_ERROR;
+
+  if (command_buffer_.get()) {
+    command_buffer_->SetPutOffsetChangeCallback(NULL);
+  }
+
+  status_ = kDestroyed;
+
+  return NPERR_NO_ERROR;
+}
+
+void GPUPluginObject::Release() {
+  DCHECK(status_ == kWaitingForNew || status_ == kDestroyed);
+  NPBrowser::get()->ReleaseObject(this);
+}
+
+NPObject*GPUPluginObject::GetScriptableNPObject() {
+  NPBrowser::get()->RetainObject(this);
+  return this;
+}
+
+CommandBuffer* GPUPluginObject::OpenCommandBuffer() {
+  if (status_ == kInitializationSuccessful)
+    return command_buffer_.get();
+
+  // SetWindow must have been called before OpenCommandBuffer.
+  // PlatformSpecificSetWindow advances the status to
+  // kWaitingForOpenCommandBuffer.
+  if (status_ != kWaitingForOpenCommandBuffer)
+    return NULL;
+
+  scoped_ptr<SharedMemory> ring_buffer(new SharedMemory);
+  if (!ring_buffer->Create(std::wstring(), false, false, kCommandBufferSize))
+    return NULL;
+
+  if (command_buffer_->Initialize(ring_buffer.release())) {
+    if (processor_->Initialize(static_cast<HWND>(window_.window))) {
+      command_buffer_->SetPutOffsetChangeCallback(
+          NewCallback(processor_.get(),
+                      &GPUProcessor::ProcessCommands));
+      status_ = kInitializationSuccessful;
+      return command_buffer_.get();
+    }
+  }
+
+  return NULL;
+}
+
+}  // namespace gpu_plugin
diff --git a/gpu/gpu_plugin/gpu_plugin_object.h b/gpu/gpu_plugin/gpu_plugin_object.h
new file mode 100644
index 0000000..0602aa92
--- /dev/null
+++ b/gpu/gpu_plugin/gpu_plugin_object.h
@@ -0,0 +1,133 @@
+// Copyright (c) 2006-2008 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 GPU_GPU_PLUGIN_GPU_PLUGIN_OBJECT_H_
+#define GPU_GPU_PLUGIN_GPU_PLUGIN_OBJECT_H_
+
+#include <string>
+
+#include "base/ref_counted.h"
+#include "base/thread.h"
+#include "gpu/command_buffer/common/command_buffer.h"
+#include "gpu/command_buffer/service/gpu_processor.h"
+#include "gpu/np_utils/default_np_object.h"
+#include "gpu/np_utils/np_dispatcher.h"
+#include "gpu/np_utils/np_headers.h"
+#include "gpu/np_utils/np_plugin_object.h"
+#include "gpu/np_utils/np_utils.h"
+
+namespace gpu_plugin {
+
+// The scriptable object for the GPU plugin.
+class GPUPluginObject : public np_utils::DefaultNPObject<NPObject>,
+                        public np_utils::PluginObject {
+ public:
+  static const int32 kCommandBufferSize = 1024 * 1024;
+
+  enum Status {
+    // In the state of waiting for the named function to be called to continue
+    // the initialization sequence.
+    kWaitingForNew,
+    kWaitingForSetWindow,
+    kWaitingForOpenCommandBuffer,
+
+    // Initialization either succeeded or failed.
+    kInitializationSuccessful,
+    kInitializationFailed,
+
+    // Destroy has now been called and the plugin object cannot be used.
+    kDestroyed,
+  };
+
+  static const NPUTF8 kPluginType[];
+
+  explicit GPUPluginObject(NPP npp);
+
+  virtual NPError New(NPMIMEType plugin_type,
+                      int16 argc,
+                      char* argn[],
+                      char* argv[],
+                      NPSavedData* saved);
+
+  virtual NPError SetWindow(NPWindow* new_window);
+  const NPWindow& GetWindow() { return window_; }
+
+  virtual int16 HandleEvent(NPEvent* event);
+
+  virtual NPError Destroy(NPSavedData** saved);
+
+  virtual void Release();
+
+  virtual NPObject* GetScriptableNPObject();
+
+  // Returns the current initialization status. See Status enum.
+  int32 GetStatus() {
+    return status_;
+  }
+
+  // Get the width of the plugin window.
+  int32 GetWidth() {
+    return window_.width;
+  }
+
+  // Get the height of the plugin window.
+  int32 GetHeight() {
+    return window_.height;
+  }
+
+  // Set the object that receives notifications of GPU plugin object events
+  // such as resize and keyboard and mouse input.
+  void SetEventSync(np_utils::NPObjectPointer<NPObject> event_sync) {
+    event_sync_ = event_sync;
+  }
+
+  np_utils::NPObjectPointer<NPObject> GetEventSync() {
+    return event_sync_;
+  }
+
+  // Initializes and returns the command buffer object. Returns NULL if the
+  // command buffer cannot be initialized, for example if the plugin does not
+  // yet have a window handle.
+  command_buffer::CommandBuffer* OpenCommandBuffer();
+
+  // Set the status for testing.
+  void set_status(Status status) {
+    status_ = status;
+  }
+
+  // Replace the default command buffer for testing. Takes ownership.
+  void set_command_buffer(command_buffer::CommandBuffer*
+      command_buffer) {
+    command_buffer_.reset(command_buffer);
+  }
+
+  // Replace the default GPU processor for testing.
+  void set_gpu_processor(
+      const scoped_refptr<command_buffer::GPUProcessor>& processor) {
+    processor_ = processor;
+  }
+
+  NP_UTILS_BEGIN_DISPATCHER_CHAIN(GPUPluginObject, DefaultNPObject<NPObject>)
+    NP_UTILS_DISPATCHER(GetStatus, int32())
+    NP_UTILS_DISPATCHER(GetWidth, int32())
+    NP_UTILS_DISPATCHER(GetHeight, int32())
+    NP_UTILS_DISPATCHER(SetEventSync,
+        void(np_utils::NPObjectPointer<NPObject> sync))
+    NP_UTILS_DISPATCHER(GetEventSync, np_utils::NPObjectPointer<NPObject>())
+  NP_UTILS_END_DISPATCHER_CHAIN
+
+ private:
+  NPError PlatformSpecificSetWindow(NPWindow* new_window);
+
+  NPP npp_;
+  Status status_;
+  NPWindow window_;
+  scoped_ptr<command_buffer::CommandBuffer> command_buffer_;
+  scoped_refptr<command_buffer::GPUProcessor> processor_;
+  np_utils::NPObjectPointer<NPObject> event_sync_;
+};
+
+}  // namespace gpu_plugin
+
+#endif  // GPU_GPU_PLUGIN_GPU_PLUGIN_OBJECT_H_
diff --git a/gpu/gpu_plugin/gpu_plugin_object_factory.cc b/gpu/gpu_plugin/gpu_plugin_object_factory.cc
new file mode 100644
index 0000000..da9e17ac
--- /dev/null
+++ b/gpu/gpu_plugin/gpu_plugin_object_factory.cc
@@ -0,0 +1,27 @@
+// Copyright (c) 2006-2008 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 "gpu/gpu_plugin/gpu_plugin_object.h"
+#include "gpu/gpu_plugin/gpu_plugin_object_factory.h"
+#include "gpu/np_utils/np_utils.h"
+
+namespace gpu_plugin {
+
+GPUPluginObjectFactory::GPUPluginObjectFactory() {
+}
+
+GPUPluginObjectFactory::~GPUPluginObjectFactory() {
+}
+
+np_utils::PluginObject* GPUPluginObjectFactory::CreatePluginObject(
+    NPP npp,
+    NPMIMEType plugin_type) {
+  if (strcmp(plugin_type, GPUPluginObject::kPluginType) == 0) {
+    return np_utils::NPCreateObject<GPUPluginObject>(npp).ToReturned();
+  }
+
+  return NULL;
+}
+
+}  // namespace gpu_plugin
diff --git a/gpu/gpu_plugin/gpu_plugin_object_factory.h b/gpu/gpu_plugin/gpu_plugin_object_factory.h
new file mode 100644
index 0000000..0d1d80ed
--- /dev/null
+++ b/gpu/gpu_plugin/gpu_plugin_object_factory.h
@@ -0,0 +1,27 @@
+// Copyright (c) 2006-2008 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 GPU_GPU_PLUGIN_GPU_PLUGIN_OBJECT_FACTORY_H_
+#define GPU_GPU_PLUGIN_GPU_PLUGIN_OBJECT_FACTORY_H_
+
+#include "gpu/np_utils/np_plugin_object_factory.h"
+
+namespace gpu_plugin {
+
+// Plugin object factory for creating the GPUPluginObject.
+class GPUPluginObjectFactory : public np_utils::NPPluginObjectFactory {
+ public:
+  GPUPluginObjectFactory();
+  virtual ~GPUPluginObjectFactory();
+
+  virtual np_utils::PluginObject* CreatePluginObject(NPP npp,
+                                                     NPMIMEType plugin_type);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(GPUPluginObjectFactory);
+};
+
+}  // namespace gpu_plugin
+
+#endif  // GPU_GPU_PLUGIN_GPU_PLUGIN_OBJECT_FACTORY_H_
diff --git a/gpu/gpu_plugin/gpu_plugin_object_factory_unittest.cc b/gpu/gpu_plugin/gpu_plugin_object_factory_unittest.cc
new file mode 100644
index 0000000..298a8c5
--- /dev/null
+++ b/gpu/gpu_plugin/gpu_plugin_object_factory_unittest.cc
@@ -0,0 +1,41 @@
+// Copyright (c) 2006-2008 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 "gpu/gpu_plugin/gpu_plugin_object.h"
+#include "gpu/gpu_plugin/gpu_plugin_object_factory.h"
+#include "gpu/np_utils/np_browser_stub.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using np_utils::PluginObject;
+
+namespace gpu_plugin {
+
+class PluginObjectFactoryTest : public testing::Test {
+ protected:
+  virtual void SetUp() {
+    factory_ = new GPUPluginObjectFactory;
+  }
+
+  virtual void TearDown() {
+    delete factory_;
+  }
+
+  np_utils::StubNPBrowser stub_browser_;
+  GPUPluginObjectFactory* factory_;
+};
+
+TEST_F(PluginObjectFactoryTest, ReturnsNullForUnknownMimeType) {
+  PluginObject* plugin_object = factory_->CreatePluginObject(
+      NULL, "application/unknown");
+  EXPECT_TRUE(NULL == plugin_object);
+}
+
+TEST_F(PluginObjectFactoryTest, CreatesGPUPlugin) {
+  PluginObject* plugin_object = factory_->CreatePluginObject(
+      NULL, const_cast<NPMIMEType>(GPUPluginObject::kPluginType));
+  EXPECT_TRUE(NULL != plugin_object);
+}
+
+}  // namespace gpu_plugin
diff --git a/gpu/gpu_plugin/gpu_plugin_object_unittest.cc b/gpu/gpu_plugin/gpu_plugin_object_unittest.cc
new file mode 100644
index 0000000..b032aa0
--- /dev/null
+++ b/gpu/gpu_plugin/gpu_plugin_object_unittest.cc
@@ -0,0 +1,319 @@
+// Copyright (c) 2006-2008 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 "gpu/command_buffer/common/command_buffer_mock.h"
+#include "gpu/gpu_plugin/gpu_plugin_object.h"
+#include "gpu/command_buffer/service/gpu_processor_mock.h"
+#include "gpu/np_utils/np_browser_mock.h"
+#include "gpu/np_utils/dynamic_np_object.h"
+#include "gpu/np_utils/np_object_mock.h"
+#include "gpu/np_utils/np_object_pointer.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "webkit/glue/plugins/nphostapi.h"
+
+using ::base::SharedMemory;
+using command_buffer::GPUProcessor;
+using command_buffer::MockCommandBuffer;
+using command_buffer::MockGPUProcessor;
+using np_utils::MockNPBrowser;
+using np_utils::NPBrowser;
+using np_utils::NPObjectPointer;
+using testing::_;
+using testing::DoAll;
+using testing::Invoke;
+using testing::NotNull;
+using testing::Return;
+using testing::SetArgumentPointee;
+using testing::StrictMock;
+
+namespace gpu_plugin {
+
+class GPUPluginObjectTest : public testing::Test {
+ protected:
+  virtual void SetUp() {
+    plugin_object_ = np_utils::NPCreateObject<GPUPluginObject>(NULL);
+
+    command_buffer_ = new MockCommandBuffer;
+
+    // Takes ownership.
+    plugin_object_->set_command_buffer(command_buffer_);
+
+    processor_ = new MockGPUProcessor(command_buffer_);
+    plugin_object_->set_gpu_processor(processor_.get());
+  }
+
+  MockNPBrowser mock_browser_;
+  NPObjectPointer<GPUPluginObject> plugin_object_;
+  MockCommandBuffer* command_buffer_;
+  scoped_refptr<MockGPUProcessor> processor_;
+};
+
+namespace {
+template <typename T>
+void DeleteObject(T* object) {
+  delete object;
+}
+}  // namespace anonymous
+
+
+TEST_F(GPUPluginObjectTest, CanInstantiateAndDestroyPluginObject) {
+  EXPECT_EQ(GPUPluginObject::kWaitingForNew, plugin_object_->GetStatus());
+
+  EXPECT_EQ(NPERR_NO_ERROR, plugin_object_->New("application/foo",
+                                                0,
+                                                NULL,
+                                                NULL,
+                                                NULL));
+
+  EXPECT_EQ(GPUPluginObject::kWaitingForSetWindow, plugin_object_->GetStatus());
+
+  EXPECT_EQ(NPERR_NO_ERROR, plugin_object_->Destroy(NULL));
+
+  EXPECT_EQ(GPUPluginObject::kDestroyed, plugin_object_->GetStatus());
+}
+
+TEST_F(GPUPluginObjectTest, DestroyFailsIfNotInitialized) {
+  EXPECT_EQ(NPERR_GENERIC_ERROR, plugin_object_->Destroy(NULL));
+}
+
+TEST_F(GPUPluginObjectTest, NewFailsIfAlreadyInitialized) {
+  EXPECT_EQ(NPERR_NO_ERROR, plugin_object_->New("application/foo",
+                                                0,
+                                                NULL,
+                                                NULL,
+                                                NULL));
+
+  EXPECT_EQ(NPERR_GENERIC_ERROR, plugin_object_->New("application/foo",
+                                                0,
+                                                NULL,
+                                                NULL,
+                                                NULL));
+
+  EXPECT_EQ(GPUPluginObject::kWaitingForSetWindow, plugin_object_->GetStatus());
+
+  EXPECT_EQ(NPERR_NO_ERROR, plugin_object_->Destroy(NULL));
+
+  EXPECT_EQ(GPUPluginObject::kDestroyed, plugin_object_->GetStatus());
+}
+
+TEST_F(GPUPluginObjectTest, NewFailsIfObjectHasPreviouslyBeenDestroyed) {
+  EXPECT_EQ(NPERR_NO_ERROR, plugin_object_->New("application/foo",
+                                                0,
+                                                NULL,
+                                                NULL,
+                                                NULL));
+
+  EXPECT_EQ(NPERR_NO_ERROR, plugin_object_->Destroy(NULL));
+
+  EXPECT_EQ(NPERR_GENERIC_ERROR, plugin_object_->New("application/foo",
+                                                     0,
+                                                     NULL,
+                                                     NULL,
+                                                     NULL));
+
+  EXPECT_EQ(GPUPluginObject::kDestroyed, plugin_object_->GetStatus());
+}
+
+TEST_F(GPUPluginObjectTest, WindowIsNullBeforeSetWindowCalled) {
+  NPWindow window = plugin_object_->GetWindow();
+  EXPECT_EQ(NULL, window.window);
+}
+
+TEST_F(GPUPluginObjectTest, CanSetWindow) {
+  EXPECT_EQ(NPERR_NO_ERROR, plugin_object_->New("application/foo",
+                                                0,
+                                                NULL,
+                                                NULL,
+                                                NULL));
+
+  NPWindow window = {0};
+  window.window = &window;
+  window.x = 7;
+
+  EXPECT_EQ(NPERR_NO_ERROR, plugin_object_->SetWindow(&window));
+  EXPECT_EQ(0, memcmp(&window, &plugin_object_->GetWindow(), sizeof(window)));
+  EXPECT_EQ(GPUPluginObject::kWaitingForOpenCommandBuffer,
+            plugin_object_->GetStatus());
+
+  EXPECT_EQ(NPERR_NO_ERROR, plugin_object_->Destroy(NULL));
+}
+
+TEST_F(GPUPluginObjectTest, CanGetWindowSize) {
+  EXPECT_EQ(NPERR_NO_ERROR, plugin_object_->New("application/foo",
+                                                0,
+                                                NULL,
+                                                NULL,
+                                                NULL));
+
+  NPWindow window = {0};
+  window.window = &window;
+  window.x = 10;
+  window.y = 10;
+  window.width = 100;
+  window.height = 200;
+
+  EXPECT_EQ(0, plugin_object_->GetWidth());
+  EXPECT_EQ(0, plugin_object_->GetHeight());
+  EXPECT_EQ(NPERR_NO_ERROR, plugin_object_->SetWindow(&window));
+  EXPECT_EQ(100, plugin_object_->GetWidth());
+  EXPECT_EQ(200, plugin_object_->GetHeight());
+
+  EXPECT_EQ(NPERR_NO_ERROR, plugin_object_->Destroy(NULL));
+}
+
+TEST_F(GPUPluginObjectTest, SetWindowFailsIfNotInitialized) {
+  NPWindow window = {0};
+  EXPECT_EQ(NPERR_GENERIC_ERROR, plugin_object_->SetWindow(&window));
+  EXPECT_EQ(GPUPluginObject::kWaitingForNew, plugin_object_->GetStatus());
+}
+
+TEST_F(GPUPluginObjectTest, CanGetScriptableNPObject) {
+  NPObject* scriptable_object = plugin_object_->GetScriptableNPObject();
+  EXPECT_EQ(plugin_object_.Get(), scriptable_object);
+  NPBrowser::get()->ReleaseObject(scriptable_object);
+}
+
+TEST_F(GPUPluginObjectTest, OpenCommandBufferReturnsInitializedCommandBuffer) {
+  EXPECT_CALL(*command_buffer_, Initialize(NotNull()))
+    .WillOnce(DoAll(Invoke(DeleteObject<SharedMemory>),
+                    Return(true)));
+
+  EXPECT_CALL(*processor_.get(), Initialize(NULL))
+    .WillOnce(Return(true));
+
+  EXPECT_CALL(*command_buffer_, SetPutOffsetChangeCallback(NotNull()))
+    .WillOnce(Invoke(DeleteObject<Callback0::Type>));
+
+  EXPECT_EQ(NPERR_NO_ERROR, plugin_object_->New("application/foo",
+                                                0,
+                                                NULL,
+                                                NULL,
+                                                NULL));
+
+  // Set status as though SetWindow has been called. Avoids having to create a
+  // valid window handle to pass to SetWindow in tests.
+  plugin_object_->set_status(GPUPluginObject::kWaitingForOpenCommandBuffer);
+
+  EXPECT_EQ(command_buffer_, plugin_object_->OpenCommandBuffer());
+
+  // Calling OpenCommandBuffer again just returns the existing command buffer.
+  EXPECT_EQ(command_buffer_, plugin_object_->OpenCommandBuffer());
+
+  EXPECT_EQ(GPUPluginObject::kInitializationSuccessful,
+            plugin_object_->GetStatus());
+
+  EXPECT_CALL(*command_buffer_, SetPutOffsetChangeCallback(NULL));
+
+  EXPECT_EQ(NPERR_NO_ERROR, plugin_object_->Destroy(NULL));
+}
+
+TEST_F(GPUPluginObjectTest, OpenCommandBufferReturnsNullIfWindowNotReady) {
+  EXPECT_EQ(NPERR_NO_ERROR, plugin_object_->New("application/foo",
+                                                0,
+                                                NULL,
+                                                NULL,
+                                                NULL));
+
+  // Set status as though SetWindow has not been called.
+  plugin_object_->set_status(GPUPluginObject::kWaitingForSetWindow);
+
+  EXPECT_TRUE(NULL == plugin_object_->OpenCommandBuffer());
+
+  EXPECT_EQ(GPUPluginObject::kWaitingForSetWindow, plugin_object_->GetStatus());
+}
+
+
+TEST_F(GPUPluginObjectTest,
+    OpenCommandBufferReturnsNullIfCommandBufferCannotInitialize) {
+  EXPECT_CALL(*command_buffer_, Initialize(NotNull()))
+    .WillOnce(DoAll(Invoke(DeleteObject<SharedMemory>),
+                    Return(false)));
+
+  EXPECT_EQ(NPERR_NO_ERROR, plugin_object_->New("application/foo",
+                                                0,
+                                                NULL,
+                                                NULL,
+                                                NULL));
+
+  // Set status as though SetWindow has been called. Avoids having to create a
+  // valid window handle to pass to SetWindow in tests.
+  plugin_object_->set_status(GPUPluginObject::kWaitingForOpenCommandBuffer);
+
+  EXPECT_TRUE(NULL == plugin_object_->OpenCommandBuffer());
+
+  EXPECT_EQ(GPUPluginObject::kWaitingForOpenCommandBuffer,
+            plugin_object_->GetStatus());
+
+  EXPECT_EQ(NPERR_NO_ERROR, plugin_object_->Destroy(NULL));
+}
+
+TEST_F(GPUPluginObjectTest,
+    OpenCommandBufferReturnsNullIGPUProcessorCannotInitialize) {
+  EXPECT_CALL(*command_buffer_, Initialize(NotNull()))
+    .WillOnce(DoAll(Invoke(DeleteObject<SharedMemory>),
+                    Return(true)));
+
+  EXPECT_CALL(*processor_.get(), Initialize(NULL))
+    .WillOnce(Return(false));
+
+  EXPECT_EQ(NPERR_NO_ERROR, plugin_object_->New("application/foo",
+                                                0,
+                                                NULL,
+                                                NULL,
+                                                NULL));
+
+  // Set status as though SetWindow has been called. Avoids having to create a
+  // valid window handle to pass to SetWindow in tests.
+  plugin_object_->set_status(GPUPluginObject::kWaitingForOpenCommandBuffer);
+
+  EXPECT_TRUE(NULL == plugin_object_->OpenCommandBuffer());
+
+  EXPECT_EQ(GPUPluginObject::kWaitingForOpenCommandBuffer,
+            plugin_object_->GetStatus());
+
+  EXPECT_EQ(NPERR_NO_ERROR, plugin_object_->Destroy(NULL));
+}
+
+class MockEventSync : public np_utils::DefaultNPObject<NPObject> {
+ public:
+  explicit MockEventSync(NPP npp) {
+  }
+
+  MOCK_METHOD2(Resize, void(int32 width, int32 height));
+
+  NP_UTILS_BEGIN_DISPATCHER_CHAIN(MockEventSync, DefaultNPObject<NPObject>)
+    NP_UTILS_DISPATCHER(Resize, void(int32 width, int32 height))
+  NP_UTILS_END_DISPATCHER_CHAIN
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MockEventSync);
+};
+
+TEST_F(GPUPluginObjectTest, SendsResizeEventOnSetWindow) {
+  EXPECT_EQ(NPERR_NO_ERROR, plugin_object_->New("application/foo",
+                                                0,
+                                                NULL,
+                                                NULL,
+                                                NULL));
+
+  NPObjectPointer<MockEventSync> event_sync =
+      np_utils::NPCreateObject<MockEventSync>(NULL);
+  plugin_object_->SetEventSync(event_sync);
+
+  EXPECT_CALL(*event_sync.Get(), Resize(100, 200));
+
+  NPWindow window = {0};
+  window.window = &window;
+  window.x = 10;
+  window.y = 10;
+  window.width = 100;
+  window.height = 200;
+
+  plugin_object_->SetWindow(&window);
+
+  EXPECT_EQ(NPERR_NO_ERROR, plugin_object_->Destroy(NULL));
+}
+
+}  // namespace gpu_plugin
diff --git a/gpu/gpu_plugin/gpu_plugin_object_win.cc b/gpu/gpu_plugin/gpu_plugin_object_win.cc
new file mode 100644
index 0000000..31c6393e
--- /dev/null
+++ b/gpu/gpu_plugin/gpu_plugin_object_win.cc
@@ -0,0 +1,62 @@
+// Copyright (c) 2006-2008 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 <windows.h>
+
+#include "gpu/command_buffer/service/gpu_processor.h"
+#include "gpu/gpu_plugin/gpu_plugin_object.h"
+
+namespace gpu_plugin {
+
+namespace {
+const LPCTSTR kPluginObjectProperty = TEXT("GPUPluginObject");
+const LPCTSTR kOriginalWindowProc = TEXT("GPUPluginObjectOriginalWindowProc");
+
+LRESULT CALLBACK WindowProc(HWND handle,
+                            UINT message,
+                            WPARAM w_param,
+                            LPARAM l_param) {
+  return ::DefWindowProc(handle, message, w_param, l_param);
+}
+}  // namespace anonymous
+
+NPError GPUPluginObject::PlatformSpecificSetWindow(NPWindow* new_window) {
+  // Detach properties from old window and restore the original window proc.
+  if (window_.window) {
+    HWND handle = reinterpret_cast<HWND>(window_.window);
+    ::RemoveProp(handle, kPluginObjectProperty);
+
+    LONG original_window_proc = reinterpret_cast<LONG>(
+        ::GetProp(handle, kOriginalWindowProc));
+    ::SetWindowLong(handle, GWL_WNDPROC,
+                    original_window_proc);
+    ::RemoveProp(handle, kOriginalWindowProc);
+  }
+
+  // Attach properties to new window and set a new window proc.
+  if (new_window->window) {
+    HWND handle = reinterpret_cast<HWND>(new_window->window);
+    ::SetProp(handle,
+              kPluginObjectProperty,
+              reinterpret_cast<HANDLE>(this));
+
+    LONG original_window_proc = ::GetWindowLong(handle, GWL_WNDPROC);
+    ::SetProp(handle,
+              kOriginalWindowProc,
+              reinterpret_cast<HANDLE>(original_window_proc));
+    ::SetWindowLong(handle, GWL_WNDPROC,
+                    reinterpret_cast<LONG>(WindowProc));
+
+    status_ = kWaitingForOpenCommandBuffer;
+  } else {
+    status_ = kWaitingForSetWindow;
+    if (processor_) {
+      processor_->Destroy();
+    }
+  }
+
+  return NPERR_NO_ERROR;
+}
+
+}  // namespace gpu_plugin
diff --git a/gpu/gpu_plugin/gpu_plugin_unittest.cc b/gpu/gpu_plugin/gpu_plugin_unittest.cc
new file mode 100644
index 0000000..ea1bb5f9
--- /dev/null
+++ b/gpu/gpu_plugin/gpu_plugin_unittest.cc
@@ -0,0 +1,302 @@
+// Copyright (c) 2006-2008 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 "gpu/gpu_plugin/gpu_plugin.h"
+#include "gpu/gpu_plugin/gpu_plugin_object.h"
+#include "gpu/np_utils/np_object_mock.h"
+#include "gpu/np_utils/np_plugin_object_factory_mock.h"
+#include "gpu/np_utils/np_plugin_object_mock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/glue/plugins/nphostapi.h"
+
+#if defined(OS_LINUX)
+#define INITIALIZE_PLUGIN_FUNCS , &plugin_funcs_
+#else
+#define INITIALIZE_PLUGIN_FUNCS
+#endif
+
+using np_utils::MockPluginObject;
+using np_utils::PluginObject;
+using testing::_;
+using testing::DoAll;
+using testing::NiceMock;
+using testing::Return;
+using testing::SetArgumentPointee;
+using testing::StrictMock;
+
+namespace gpu_plugin {
+
+class GPUPluginTest : public testing::Test {
+ protected:
+  virtual void SetUp() {
+    memset(&npp_, 0, sizeof(npp_));
+    memset(&browser_funcs_, 0, sizeof(browser_funcs_));
+    memset(&plugin_funcs_, 0, sizeof(plugin_funcs_));
+
+    plugin_object_factory_ = new StrictMock<np_utils::MockPluginObjectFactory>;
+
+    np_class_ = np_utils::NPGetClass<StrictMock<np_utils::MockNPObject> >();
+  }
+
+  virtual void TearDown() {
+    delete plugin_object_factory_;
+  }
+
+  NPP_t npp_;
+  NPNetscapeFuncs browser_funcs_;
+  NPPluginFuncs plugin_funcs_;
+  np_utils::MockPluginObjectFactory* plugin_object_factory_;
+  const NPClass* np_class_;
+};
+
+TEST_F(GPUPluginTest, GetEntryPointsSetsNeededFunctionPointers) {
+#if defined(OS_LINUX)
+  NPError error = gpu_plugin::NP_Initialize(&browser_funcs_,
+                                                 &plugin_funcs_);
+  gpu_plugin::NP_Shutdown();
+#else
+  NPError error = gpu_plugin::NP_GetEntryPoints(&plugin_funcs_);
+#endif
+
+  EXPECT_EQ(NPERR_NO_ERROR, error);
+  EXPECT_TRUE(NULL != plugin_funcs_.newp);
+  EXPECT_TRUE(NULL != plugin_funcs_.destroy);
+  EXPECT_TRUE(NULL != plugin_funcs_.setwindow);
+  EXPECT_TRUE(NULL != plugin_funcs_.event);
+  EXPECT_TRUE(NULL != plugin_funcs_.getvalue);
+  EXPECT_TRUE(NULL != plugin_funcs_.setvalue);
+}
+
+TEST_F(GPUPluginTest, CanInitializeAndShutdownPlugin) {
+  EXPECT_EQ(NPERR_NO_ERROR,
+      gpu_plugin::NP_Initialize(&browser_funcs_ INITIALIZE_PLUGIN_FUNCS));
+  EXPECT_EQ(NPERR_NO_ERROR, gpu_plugin::NP_Shutdown());
+}
+
+TEST_F(GPUPluginTest, InitializeFailsIfBrowserFuncsIsNull) {
+  EXPECT_EQ(NPERR_INVALID_FUNCTABLE_ERROR,
+      gpu_plugin::NP_Initialize(NULL INITIALIZE_PLUGIN_FUNCS));
+}
+
+TEST_F(GPUPluginTest, InitializeFailsIfAlreadyInitialized) {
+  EXPECT_EQ(NPERR_NO_ERROR,
+      gpu_plugin::NP_Initialize(&browser_funcs_ INITIALIZE_PLUGIN_FUNCS));
+  EXPECT_EQ(NPERR_GENERIC_ERROR,
+      gpu_plugin::NP_Initialize(&browser_funcs_ INITIALIZE_PLUGIN_FUNCS));
+  EXPECT_EQ(NPERR_NO_ERROR, gpu_plugin::NP_Shutdown());
+}
+
+TEST_F(GPUPluginTest, ShutdownFailsIfNotInitialized) {
+  EXPECT_EQ(NPERR_GENERIC_ERROR, gpu_plugin::NP_Shutdown());
+}
+
+TEST_F(GPUPluginTest, NewReturnsErrorForInvalidInstance) {
+  gpu_plugin::NP_GetEntryPoints(&plugin_funcs_);
+  gpu_plugin::NP_Initialize(&browser_funcs_ INITIALIZE_PLUGIN_FUNCS);
+
+  EXPECT_EQ(NPERR_INVALID_INSTANCE_ERROR, plugin_funcs_.newp(
+      const_cast<NPMIMEType>(GPUPluginObject::kPluginType),
+      NULL, 0, 0, NULL, NULL, NULL));
+
+  gpu_plugin::NP_Shutdown();
+}
+
+TEST_F(GPUPluginTest, GetValueReturnsErrorForInvalidInstance) {
+  gpu_plugin::NP_GetEntryPoints(&plugin_funcs_);
+  gpu_plugin::NP_Initialize(&browser_funcs_ INITIALIZE_PLUGIN_FUNCS);
+
+  int* result = NULL;
+  EXPECT_EQ(NPERR_INVALID_INSTANCE_ERROR, plugin_funcs_.getvalue(
+      NULL, NPPVjavaClass, &result));
+
+  gpu_plugin::NP_Shutdown();
+}
+
+TEST_F(GPUPluginTest, DestroyReturnsErrorForInvalidInstance) {
+  gpu_plugin::NP_GetEntryPoints(&plugin_funcs_);
+  gpu_plugin::NP_Initialize(&browser_funcs_ INITIALIZE_PLUGIN_FUNCS);
+
+  EXPECT_EQ(NPERR_INVALID_INSTANCE_ERROR, plugin_funcs_.destroy(NULL, NULL));
+
+  gpu_plugin::NP_Shutdown();
+}
+
+TEST_F(GPUPluginTest, SetWindowReturnsErrorForInvalidInstance) {
+  gpu_plugin::NP_GetEntryPoints(&plugin_funcs_);
+  gpu_plugin::NP_Initialize(&browser_funcs_ INITIALIZE_PLUGIN_FUNCS);
+
+  EXPECT_EQ(NPERR_INVALID_INSTANCE_ERROR, plugin_funcs_.setwindow(NULL, NULL));
+
+  gpu_plugin::NP_Shutdown();
+}
+
+TEST_F(GPUPluginTest, HandleEventReturnsFalseForInvalidInstance) {
+  gpu_plugin::NP_GetEntryPoints(&plugin_funcs_);
+  gpu_plugin::NP_Initialize(&browser_funcs_ INITIALIZE_PLUGIN_FUNCS);
+
+  EXPECT_EQ(0, plugin_funcs_.event(NULL, NULL));
+
+  gpu_plugin::NP_Shutdown();
+}
+
+TEST_F(GPUPluginTest, NewCreatesAPluginObjectAndInitializesIt) {
+  StrictMock<np_utils::MockPluginObject> plugin_object;
+
+  EXPECT_CALL(*plugin_object_factory_, CreatePluginObject(
+      &npp_, const_cast<NPMIMEType>(GPUPluginObject::kPluginType)))
+    .WillOnce(Return(&plugin_object));
+
+  NPObject scriptable_object;
+
+  EXPECT_CALL(plugin_object, New(
+      const_cast<NPMIMEType>(GPUPluginObject::kPluginType),
+      0, NULL, NULL, NULL))
+    .WillOnce(Return(NPERR_NO_ERROR));
+
+  EXPECT_CALL(plugin_object, GetScriptableNPObject())
+    .WillOnce(Return(&scriptable_object));
+
+  EXPECT_CALL(plugin_object, Destroy(static_cast<NPSavedData**>(NULL)))
+    .WillOnce(Return(NPERR_NO_ERROR));
+
+  EXPECT_CALL(plugin_object, Release());
+
+  gpu_plugin::NP_GetEntryPoints(&plugin_funcs_);
+  gpu_plugin::NP_Initialize(&browser_funcs_ INITIALIZE_PLUGIN_FUNCS);
+
+  EXPECT_EQ(NPERR_NO_ERROR, plugin_funcs_.newp(
+      const_cast<NPMIMEType>(GPUPluginObject::kPluginType),
+      &npp_, 0, 0, NULL, NULL, NULL));
+
+  NPObject* result;
+  EXPECT_EQ(NPERR_NO_ERROR, plugin_funcs_.getvalue(
+      &npp_, NPPVpluginScriptableNPObject, &result));
+  EXPECT_EQ(&scriptable_object, result);
+
+  EXPECT_EQ(NPERR_NO_ERROR, plugin_funcs_.destroy(&npp_, NULL));
+
+  gpu_plugin::NP_Shutdown();
+}
+
+TEST_F(GPUPluginTest, NewFailsIfPluginObjectFactoryFails) {
+  EXPECT_CALL(*plugin_object_factory_, CreatePluginObject(
+      &npp_, const_cast<NPMIMEType>(GPUPluginObject::kPluginType)))
+    .WillOnce(Return(static_cast<PluginObject*>(NULL)));
+
+  gpu_plugin::NP_GetEntryPoints(&plugin_funcs_);
+  gpu_plugin::NP_Initialize(&browser_funcs_ INITIALIZE_PLUGIN_FUNCS);
+
+  EXPECT_EQ(NPERR_GENERIC_ERROR, plugin_funcs_.newp(
+      const_cast<NPMIMEType>(GPUPluginObject::kPluginType),
+      &npp_, 0, 0, NULL, NULL, NULL));
+
+  gpu_plugin::NP_Shutdown();
+}
+
+TEST_F(GPUPluginTest, SetWindowForwardsToPluginObject) {
+  StrictMock<MockPluginObject> plugin_object;
+
+  EXPECT_CALL(*plugin_object_factory_, CreatePluginObject(
+      &npp_, const_cast<NPMIMEType>(GPUPluginObject::kPluginType)))
+    .WillOnce(Return(&plugin_object));
+
+  EXPECT_CALL(plugin_object, New(
+      const_cast<NPMIMEType>(GPUPluginObject::kPluginType),
+      0, NULL, NULL, NULL))
+    .WillOnce(Return(NPERR_NO_ERROR));
+
+  NPWindow window = {0};
+
+  EXPECT_CALL(plugin_object, SetWindow(&window))
+    .WillOnce(Return(NPERR_NO_ERROR));
+
+  EXPECT_CALL(plugin_object, Destroy(static_cast<NPSavedData**>(NULL)))
+    .WillOnce(Return(NPERR_NO_ERROR));
+
+  EXPECT_CALL(plugin_object, Release());
+
+  gpu_plugin::NP_GetEntryPoints(&plugin_funcs_);
+  gpu_plugin::NP_Initialize(&browser_funcs_ INITIALIZE_PLUGIN_FUNCS);
+
+  EXPECT_EQ(NPERR_NO_ERROR, plugin_funcs_.newp(
+      const_cast<NPMIMEType>(GPUPluginObject::kPluginType),
+      &npp_, 0, 0, NULL, NULL, NULL));
+
+  EXPECT_EQ(NPERR_NO_ERROR, plugin_funcs_.setwindow(&npp_, &window));
+
+  EXPECT_EQ(NPERR_NO_ERROR, plugin_funcs_.destroy(&npp_, NULL));
+
+  gpu_plugin::NP_Shutdown();
+}
+
+TEST_F(GPUPluginTest, HandleEventForwardsToPluginObject) {
+  StrictMock<MockPluginObject> plugin_object;
+
+  EXPECT_CALL(*plugin_object_factory_, CreatePluginObject(
+      &npp_, const_cast<NPMIMEType>(GPUPluginObject::kPluginType)))
+    .WillOnce(Return(&plugin_object));
+
+  EXPECT_CALL(plugin_object, New(
+      const_cast<NPMIMEType>(GPUPluginObject::kPluginType),
+      0, NULL, NULL, NULL))
+    .WillOnce(Return(NPERR_NO_ERROR));
+
+  NPEvent event = {0};
+
+  EXPECT_CALL(plugin_object, HandleEvent(&event))
+    .WillOnce(Return(7));
+
+  EXPECT_CALL(plugin_object, Destroy(static_cast<NPSavedData**>(NULL)))
+    .WillOnce(Return(NPERR_NO_ERROR));
+
+  EXPECT_CALL(plugin_object, Release());
+
+  gpu_plugin::NP_GetEntryPoints(&plugin_funcs_);
+  gpu_plugin::NP_Initialize(&browser_funcs_ INITIALIZE_PLUGIN_FUNCS);
+
+  EXPECT_EQ(NPERR_NO_ERROR, plugin_funcs_.newp(
+      const_cast<NPMIMEType>(GPUPluginObject::kPluginType),
+      &npp_, 0, 0, NULL, NULL, NULL));
+
+  EXPECT_EQ(7, plugin_funcs_.event(&npp_, &event));
+
+  EXPECT_EQ(NPERR_NO_ERROR, plugin_funcs_.destroy(&npp_, NULL));
+
+  gpu_plugin::NP_Shutdown();
+}
+
+TEST_F(GPUPluginTest, GetValueReturnsErrorForUnknownVariable) {
+  StrictMock<MockPluginObject> plugin_object;
+
+  EXPECT_CALL(*plugin_object_factory_, CreatePluginObject(
+      &npp_, const_cast<NPMIMEType>(GPUPluginObject::kPluginType)))
+    .WillOnce(Return(&plugin_object));
+
+  EXPECT_CALL(plugin_object, New(
+      const_cast<NPMIMEType>(GPUPluginObject::kPluginType),
+      0, NULL, NULL, NULL))
+    .WillOnce(Return(NPERR_NO_ERROR));
+
+  EXPECT_CALL(plugin_object, Destroy(static_cast<NPSavedData**>(NULL)))
+    .WillOnce(Return(NPERR_NO_ERROR));
+
+  EXPECT_CALL(plugin_object, Release());
+
+  gpu_plugin::NP_GetEntryPoints(&plugin_funcs_);
+  gpu_plugin::NP_Initialize(&browser_funcs_ INITIALIZE_PLUGIN_FUNCS);
+
+  EXPECT_EQ(NPERR_NO_ERROR, plugin_funcs_.newp(
+      const_cast<NPMIMEType>(GPUPluginObject::kPluginType),
+      &npp_, 0, 0, NULL, NULL, NULL));
+
+  int* result = NULL;
+  EXPECT_EQ(NPERR_GENERIC_ERROR, plugin_funcs_.getvalue(
+      &npp_, NPPVjavaClass, &result));
+
+  EXPECT_EQ(NPERR_NO_ERROR, plugin_funcs_.destroy(&npp_, NULL));
+
+  gpu_plugin::NP_Shutdown();
+}
+
+}  // namespace gpu_plugin
diff --git a/gpu/np_utils/default_np_object.h b/gpu/np_utils/default_np_object.h
new file mode 100644
index 0000000..b3b5fc0
--- /dev/null
+++ b/gpu/np_utils/default_np_object.h
@@ -0,0 +1,84 @@
+// Copyright (c) 2006-2008 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 GPU_NP_UTILS_DEFAULT_NP_OBJECT_H_
+#define GPU_NP_UTILS_DEFAULT_NP_OBJECT_H_
+
+#include "base/basictypes.h"
+#include "gpu/np_utils/np_headers.h"
+
+namespace np_utils {
+
+class BaseNPDispatcher;
+
+// This class implements each of the functions in the NPClass interface. They
+// all return error by default. Note that these are not virtual functions and
+// this is not an interface. This class can be used as a mixin so that an
+// NPObject class does not need to implement every NPClass function but rather
+// inherits a default from DefaultNPObject.
+template <typename RootClass>
+class DefaultNPObject : public RootClass {
+ public:
+  void Invalidate() {}
+
+  bool HasMethod(NPIdentifier name) {
+    return false;
+  }
+
+  bool Invoke(NPIdentifier name,
+              const NPVariant* args,
+              uint32_t num_args,
+              NPVariant* result) {
+    return false;
+  }
+
+  bool InvokeDefault(const NPVariant* args,
+                     uint32_t num_args,
+                     NPVariant* result) {
+    return false;
+  }
+
+  bool HasProperty(NPIdentifier name) {
+    return false;
+  }
+
+  bool GetProperty(NPIdentifier name, NPVariant* result) {
+    return false;
+  }
+
+  bool SetProperty(NPIdentifier name, const NPVariant* value) {
+    return false;
+  }
+
+  bool RemoveProperty(NPIdentifier name) {
+    return false;
+  }
+
+  bool Enumerate(NPIdentifier** names,
+                 uint32_t* count) {
+    *names = NULL;
+    *count = 0;
+    return true;
+  }
+
+  bool Construct(const NPVariant* args,
+                 uint32_t num_args,
+                 NPVariant* result) {
+    return false;
+  }
+
+  static BaseNPDispatcher* GetDispatcherChain() {
+    return NULL;
+  }
+
+ protected:
+  DefaultNPObject() {}
+  virtual ~DefaultNPObject() {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(DefaultNPObject);
+};
+}  // namespace np_utils
+
+#endif  // GPU_NP_UTILS_DEFAULT_NP_OBJECT_H_
diff --git a/gpu/np_utils/dispatched_np_object_unittest.cc b/gpu/np_utils/dispatched_np_object_unittest.cc
new file mode 100644
index 0000000..19d5a2b2
--- /dev/null
+++ b/gpu/np_utils/dispatched_np_object_unittest.cc
@@ -0,0 +1,403 @@
+// Copyright (c) 2006-2008 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 <string>
+
+#include "gpu/np_utils/default_np_object.h"
+#include "gpu/np_utils/np_browser_stub.h"
+#include "gpu/np_utils/np_dispatcher.h"
+#include "gpu/np_utils/np_object_mock.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using testing::Return;
+using testing::StrictMock;
+
+namespace np_utils {
+
+// This mock class has a dispatcher chain with an entry for each mocked
+// function. The tests that follow that invoking an NPAPI method calls the
+// corresponding mocked member function.
+class MockDispatchedNPObject : public DefaultNPObject<NPObject> {
+ public:
+  explicit MockDispatchedNPObject(NPP npp) {
+  }
+
+  MOCK_METHOD0(VoidReturnNoParams, void());
+  MOCK_METHOD1(VoidReturnBoolParam, void(bool));
+  MOCK_METHOD1(VoidReturnIntParam, void(int));
+  MOCK_METHOD1(VoidReturnFloatParam, void(float));
+  MOCK_METHOD1(VoidReturnDoubleParam, void(double));
+  MOCK_METHOD1(VoidReturnStringParam, void(std::string));
+  MOCK_METHOD1(VoidReturnObjectParam, void(NPObjectPointer<NPObject>));
+  MOCK_METHOD2(VoidReturnTwoParams, void(bool, int));
+  MOCK_METHOD0(Overloaded, void());
+  MOCK_METHOD1(Overloaded, void(bool));
+  MOCK_METHOD1(Overloaded, void(std::string));
+  MOCK_METHOD0(BoolReturn, bool());
+  MOCK_METHOD0(IntReturn, int());
+  MOCK_METHOD0(FloatReturn, float());
+  MOCK_METHOD0(DoubleReturn, double());
+  MOCK_METHOD0(StringReturn, std::string());
+  MOCK_METHOD0(ObjectReturn, NPObjectPointer<NPObject>());
+
+  NP_UTILS_BEGIN_DISPATCHER_CHAIN(MockDispatchedNPObject, DefaultNPObject<NPObject>)
+    NP_UTILS_DISPATCHER(VoidReturnNoParams, void())
+    NP_UTILS_DISPATCHER(VoidReturnBoolParam, void(bool))
+    NP_UTILS_DISPATCHER(VoidReturnIntParam, void(int))
+    NP_UTILS_DISPATCHER(VoidReturnFloatParam, void(float))
+    NP_UTILS_DISPATCHER(VoidReturnDoubleParam, void(double))
+    NP_UTILS_DISPATCHER(VoidReturnStringParam, void(std::string))
+    NP_UTILS_DISPATCHER(VoidReturnObjectParam, void(NPObjectPointer<NPObject>))
+    NP_UTILS_DISPATCHER(VoidReturnTwoParams, void(bool, int))
+    NP_UTILS_DISPATCHER(Overloaded, void())
+    NP_UTILS_DISPATCHER(Overloaded, void(bool))
+    NP_UTILS_DISPATCHER(Overloaded, void(std::string))
+    NP_UTILS_DISPATCHER(BoolReturn, bool())
+    NP_UTILS_DISPATCHER(IntReturn, int())
+    NP_UTILS_DISPATCHER(FloatReturn, float())
+    NP_UTILS_DISPATCHER(DoubleReturn, double())
+    NP_UTILS_DISPATCHER(StringReturn, std::string())
+    NP_UTILS_DISPATCHER(ObjectReturn, NPObjectPointer<NPObject>());
+  NP_UTILS_END_DISPATCHER_CHAIN
+};
+
+class DispatchedNPObjectTest : public testing::Test {
+ protected:
+  virtual void SetUp() {
+    object_ = NPCreateObject<StrictMock<MockDispatchedNPObject> >(NULL);
+    passed_object_ = NPCreateObject<MockNPObject>(NULL);
+
+    for (int i = 0; i != arraysize(args_); ++i) {
+      NULL_TO_NPVARIANT(args_[i]);
+    }
+    NULL_TO_NPVARIANT(result_);
+  }
+
+  StubNPBrowser stub_browser_;
+  NPVariant args_[3];
+  NPVariant result_;
+  NPObjectPointer<MockDispatchedNPObject> object_;
+  NPObjectPointer<NPObject> passed_object_;
+};
+
+TEST_F(DispatchedNPObjectTest, CannotInvokeMissingFunction) {
+  EXPECT_FALSE(object_->Invoke(
+      NPBrowser::get()->GetStringIdentifier("missing"),
+      NULL,
+      0,
+      &result_));
+  EXPECT_TRUE(NPVARIANT_IS_VOID(result_));
+}
+
+TEST_F(DispatchedNPObjectTest, CanInvokeVoidReturnNoParams) {
+  EXPECT_CALL(*object_, VoidReturnNoParams());
+
+  EXPECT_TRUE(object_->Invoke(
+      NPBrowser::get()->GetStringIdentifier("voidReturnNoParams"),
+      NULL,
+      0,
+      &result_));
+  EXPECT_TRUE(NPVARIANT_IS_VOID(result_));
+}
+
+TEST_F(DispatchedNPObjectTest,
+       CannotInvokeVoidReturnNoParamsWithTooManyParams) {
+  EXPECT_FALSE(object_->Invoke(
+      NPBrowser::get()->GetStringIdentifier("voidReturnNoParams"),
+      args_,
+      1,
+      &result_));
+  EXPECT_TRUE(NPVARIANT_IS_VOID(result_));
+}
+
+TEST_F(DispatchedNPObjectTest, CanInvokeVoidReturnIntParam) {
+  EXPECT_CALL(*object_, VoidReturnIntParam(7));
+
+  INT32_TO_NPVARIANT(7, args_[0]);
+
+  EXPECT_TRUE(object_->Invoke(
+      NPBrowser::get()->GetStringIdentifier("voidReturnIntParam"),
+      args_,
+      1,
+      &result_));
+  EXPECT_TRUE(NPVARIANT_IS_VOID(result_));
+}
+
+TEST_F(DispatchedNPObjectTest, CanInvokeVoidReturnBoolParam) {
+  EXPECT_CALL(*object_, VoidReturnBoolParam(true));
+
+  BOOLEAN_TO_NPVARIANT(true, args_[0]);
+
+  EXPECT_TRUE(object_->Invoke(
+      NPBrowser::get()->GetStringIdentifier("voidReturnBoolParam"),
+      args_,
+      1,
+      &result_));
+  EXPECT_TRUE(NPVARIANT_IS_VOID(result_));
+}
+
+TEST_F(DispatchedNPObjectTest, CanInvokeVoidReturnFloatParamWithDoubleParam) {
+  EXPECT_CALL(*object_, VoidReturnFloatParam(7.0f));
+
+  DOUBLE_TO_NPVARIANT(7.0, args_[0]);
+
+  EXPECT_TRUE(object_->Invoke(
+      NPBrowser::get()->GetStringIdentifier("voidReturnFloatParam"),
+      args_,
+      1,
+      &result_));
+  EXPECT_TRUE(NPVARIANT_IS_VOID(result_));
+}
+
+TEST_F(DispatchedNPObjectTest, CanInvokeVoidReturnFloatParamWithIntParam) {
+  EXPECT_CALL(*object_, VoidReturnFloatParam(7.0f));
+
+  INT32_TO_NPVARIANT(7, args_[0]);
+
+  EXPECT_TRUE(object_->Invoke(
+      NPBrowser::get()->GetStringIdentifier("voidReturnFloatParam"),
+      args_,
+      1,
+      &result_));
+  EXPECT_TRUE(NPVARIANT_IS_VOID(result_));
+}
+
+TEST_F(DispatchedNPObjectTest, CanInvokeVoidReturnDoubleParamWithDoubleParam) {
+  EXPECT_CALL(*object_, VoidReturnDoubleParam(7.0));
+
+  DOUBLE_TO_NPVARIANT(7.0, args_[0]);
+
+  EXPECT_TRUE(object_->Invoke(
+      NPBrowser::get()->GetStringIdentifier("voidReturnDoubleParam"),
+      args_,
+      1,
+      &result_));
+  EXPECT_TRUE(NPVARIANT_IS_VOID(result_));
+}
+
+TEST_F(DispatchedNPObjectTest, CanInvokeVoidReturnDoubleParamWithIntParam) {
+  EXPECT_CALL(*object_, VoidReturnDoubleParam(7.0f));
+
+  INT32_TO_NPVARIANT(7, args_[0]);
+
+  EXPECT_TRUE(object_->Invoke(
+      NPBrowser::get()->GetStringIdentifier("voidReturnDoubleParam"),
+      args_,
+      1,
+      &result_));
+  EXPECT_TRUE(NPVARIANT_IS_VOID(result_));
+}
+
+TEST_F(DispatchedNPObjectTest, CanInvokeVoidReturnStringParam) {
+  EXPECT_CALL(*object_, VoidReturnStringParam(std::string("hello")));
+
+  STRINGZ_TO_NPVARIANT("hello", args_[0]);
+
+  EXPECT_TRUE(object_->Invoke(
+      NPBrowser::get()->GetStringIdentifier("voidReturnStringParam"),
+      args_,
+      1,
+      &result_));
+  EXPECT_TRUE(NPVARIANT_IS_VOID(result_));
+}
+
+TEST_F(DispatchedNPObjectTest, CanInvokeVoidReturnObjectParamWithObject) {
+  EXPECT_CALL(*object_, VoidReturnObjectParam(passed_object_));
+
+  OBJECT_TO_NPVARIANT(passed_object_.Get(), args_[0]);
+
+  EXPECT_TRUE(object_->Invoke(
+      NPBrowser::get()->GetStringIdentifier("voidReturnObjectParam"),
+      args_,
+      1,
+      &result_));
+  EXPECT_TRUE(NPVARIANT_IS_VOID(result_));
+}
+
+TEST_F(DispatchedNPObjectTest, CanInvokeVoidReturnObjectParamWithNull) {
+  EXPECT_CALL(
+      *object_,
+      VoidReturnObjectParam(NPObjectPointer<NPObject>()));
+
+  NULL_TO_NPVARIANT(args_[0]);
+
+  EXPECT_TRUE(object_->Invoke(
+      NPBrowser::get()->GetStringIdentifier("voidReturnObjectParam"),
+      args_,
+      1,
+      &result_));
+  EXPECT_TRUE(NPVARIANT_IS_VOID(result_));
+}
+
+TEST_F(DispatchedNPObjectTest, CanInvokeVoidReturnTwoParams) {
+  EXPECT_CALL(*object_, VoidReturnTwoParams(false, 7));
+
+  BOOLEAN_TO_NPVARIANT(false, args_[0]);
+  INT32_TO_NPVARIANT(7, args_[1]);
+
+  EXPECT_TRUE(object_->Invoke(
+      NPBrowser::get()->GetStringIdentifier("voidReturnTwoParams"),
+      args_,
+      2,
+      &result_));
+  EXPECT_TRUE(NPVARIANT_IS_VOID(result_));
+}
+
+TEST_F(DispatchedNPObjectTest, CanInvokeOverloadedWithNoParams) {
+  EXPECT_CALL(*object_, Overloaded());
+
+  EXPECT_TRUE(object_->Invoke(
+      NPBrowser::get()->GetStringIdentifier("overloaded"),
+      NULL,
+      0,
+      &result_));
+  EXPECT_TRUE(NPVARIANT_IS_VOID(result_));
+}
+
+TEST_F(DispatchedNPObjectTest, CanInvokeOverloadedWithOneStringParam) {
+  EXPECT_CALL(*object_, Overloaded(std::string("hello")));
+
+  STRINGZ_TO_NPVARIANT("hello", args_[0]);
+
+  EXPECT_TRUE(object_->Invoke(
+      NPBrowser::get()->GetStringIdentifier("overloaded"),
+      args_,
+      1,
+      &result_));
+  EXPECT_TRUE(NPVARIANT_IS_VOID(result_));
+}
+
+TEST_F(DispatchedNPObjectTest, CanInvokeOverloadedWithOneBoolParam) {
+  EXPECT_CALL(*object_, Overloaded(true));
+
+  BOOLEAN_TO_NPVARIANT(true, args_[0]);
+
+  EXPECT_TRUE(object_->Invoke(
+      NPBrowser::get()->GetStringIdentifier("overloaded"),
+      args_,
+      1,
+      &result_));
+  EXPECT_TRUE(NPVARIANT_IS_VOID(result_));
+}
+
+TEST_F(DispatchedNPObjectTest, CanInvokeBoolReturn) {
+  EXPECT_CALL(*object_, BoolReturn()).WillOnce(Return(true));
+
+  EXPECT_TRUE(object_->Invoke(
+      NPBrowser::get()->GetStringIdentifier("boolReturn"),
+      NULL,
+      0,
+      &result_));
+  EXPECT_TRUE(NPVARIANT_IS_BOOLEAN(result_));
+  EXPECT_TRUE(NPVARIANT_TO_BOOLEAN(result_));
+}
+
+TEST_F(DispatchedNPObjectTest, CanInvokeIntReturn) {
+  EXPECT_CALL(*object_, IntReturn()).WillOnce(Return(7));
+
+  EXPECT_TRUE(object_->Invoke(
+      NPBrowser::get()->GetStringIdentifier("intReturn"),
+      NULL,
+      0,
+      &result_));
+  EXPECT_TRUE(NPVARIANT_IS_INT32(result_));
+  EXPECT_EQ(7, NPVARIANT_TO_INT32(result_));
+}
+
+TEST_F(DispatchedNPObjectTest, CanInvokeFloatReturn) {
+  EXPECT_CALL(*object_, FloatReturn()).WillOnce(Return(7.0f));
+
+  EXPECT_TRUE(object_->Invoke(
+      NPBrowser::get()->GetStringIdentifier("floatReturn"),
+      NULL,
+      0,
+      &result_));
+  EXPECT_TRUE(NPVARIANT_IS_DOUBLE(result_));
+  EXPECT_EQ(7.0, NPVARIANT_TO_DOUBLE(result_));
+}
+
+TEST_F(DispatchedNPObjectTest, CanInvokeDoubleReturn) {
+  EXPECT_CALL(*object_, DoubleReturn()).WillOnce(Return(7.0));
+
+  EXPECT_TRUE(object_->Invoke(
+      NPBrowser::get()->GetStringIdentifier("doubleReturn"),
+      NULL,
+      0,
+      &result_));
+  EXPECT_TRUE(NPVARIANT_IS_DOUBLE(result_));
+  EXPECT_EQ(7.0, NPVARIANT_TO_DOUBLE(result_));
+}
+
+TEST_F(DispatchedNPObjectTest, CanInvokeStringReturn) {
+  EXPECT_CALL(*object_, StringReturn()).WillOnce(Return(std::string("hello")));
+
+  EXPECT_TRUE(object_->Invoke(
+      NPBrowser::get()->GetStringIdentifier("stringReturn"),
+      NULL,
+      0,
+      &result_));
+  EXPECT_TRUE(NPVARIANT_IS_STRING(result_));
+
+  NPString& str = NPVARIANT_TO_STRING(result_);
+  EXPECT_EQ(std::string("hello"),
+            std::string(str.UTF8Characters, str.UTF8Length));
+
+  // Callee is responsible for releasing string.
+  NPBrowser::get()->ReleaseVariantValue(&result_);
+}
+
+TEST_F(DispatchedNPObjectTest, CanInvokeObjectReturnWithObject) {
+  EXPECT_CALL(*object_, ObjectReturn()).WillOnce(Return(passed_object_));
+
+  EXPECT_TRUE(object_->Invoke(
+      NPBrowser::get()->GetStringIdentifier("objectReturn"),
+      NULL,
+      0,
+      &result_));
+  EXPECT_TRUE(NPVARIANT_IS_OBJECT(result_));
+  EXPECT_EQ(passed_object_.Get(), NPVARIANT_TO_OBJECT(result_));
+
+  NPBrowser::get()->ReleaseVariantValue(&result_);
+}
+
+TEST_F(DispatchedNPObjectTest, CanInvokeObjectReturnWithNull) {
+  EXPECT_CALL(*object_, ObjectReturn())
+      .WillOnce(Return(NPObjectPointer<NPObject>()));
+
+  EXPECT_TRUE(object_->Invoke(
+      NPBrowser::get()->GetStringIdentifier("objectReturn"),
+      NULL,
+      0,
+      &result_));
+  EXPECT_TRUE(NPVARIANT_IS_NULL(result_));
+}
+
+TEST_F(DispatchedNPObjectTest, HasMethodReturnsTrueIfMatchingMemberVariable) {
+  EXPECT_TRUE(object_->HasMethod(
+      NPBrowser::get()->GetStringIdentifier("objectReturn")));
+}
+
+TEST_F(DispatchedNPObjectTest, HasMethodReturnsTrueIfNoMatchingMemberVariable) {
+  EXPECT_FALSE(object_->HasMethod(
+      NPBrowser::get()->GetStringIdentifier("missing")));
+}
+
+TEST_F(DispatchedNPObjectTest, EnumeratesAllAvailableMethods) {
+  NPIdentifier* names;
+  uint32_t num_names;
+  ASSERT_TRUE(object_->Enumerate(&names, &num_names));
+
+  // Don't compare all of them; this test would need to change every time new
+  // dispatchers were added to the test NPObject class. Just compare the first
+  // registered (last in the dispatcher chain) and that more than one is
+  // returned.
+  EXPECT_GT(num_names, 1u);
+  EXPECT_EQ(NPBrowser::get()->GetStringIdentifier("voidReturnNoParams"),
+            names[num_names - 1]);
+
+  NPBrowser::get()->MemFree(names);
+}
+
+}  // namespace np_utils
diff --git a/gpu/np_utils/dynamic_np_object.cc b/gpu/np_utils/dynamic_np_object.cc
new file mode 100644
index 0000000..e037fdc
--- /dev/null
+++ b/gpu/np_utils/dynamic_np_object.cc
@@ -0,0 +1,59 @@
+// Copyright (c) 2006-2008 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 "gpu/np_utils/dynamic_np_object.h"
+
+namespace np_utils {
+
+DynamicNPObject::DynamicNPObject(NPP npp) {
+}
+
+void DynamicNPObject::Invalidate() {
+  for (PropertyMap::iterator it = properties_.begin();
+       it != properties_.end();
+       ++it) {
+    it->second.Invalidate();
+  }
+}
+
+bool DynamicNPObject::HasProperty(NPIdentifier name) {
+  PropertyMap::iterator it = properties_.find(name);
+  return it != properties_.end();
+}
+
+bool DynamicNPObject::GetProperty(NPIdentifier name, NPVariant* result) {
+  PropertyMap::iterator it = properties_.find(name);
+  if (it == properties_.end())
+    return false;
+
+  it->second.CopyTo(result);
+  return true;
+}
+
+bool DynamicNPObject::SetProperty(NPIdentifier name, const NPVariant* value) {
+  properties_[name] = *value;
+  return true;
+}
+
+bool DynamicNPObject::RemoveProperty(NPIdentifier name) {
+  properties_.erase(name);
+  return false;
+}
+
+bool DynamicNPObject::Enumerate(NPIdentifier** names, uint32_t* count) {
+  *names = static_cast<NPIdentifier*>(
+      NPBrowser::get()->MemAlloc(properties_.size() * sizeof(*names)));
+  *count = properties_.size();
+
+  int i = 0;
+  for (PropertyMap::iterator it = properties_.begin();
+       it != properties_.end();
+       ++it) {
+    (*names)[i] = it->first;
+    ++i;
+  }
+
+  return true;
+}
+}  // namespace np_utils
diff --git a/gpu/np_utils/dynamic_np_object.h b/gpu/np_utils/dynamic_np_object.h
new file mode 100644
index 0000000..2b63e78
--- /dev/null
+++ b/gpu/np_utils/dynamic_np_object.h
@@ -0,0 +1,35 @@
+// Copyright (c) 2006-2008 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 GPU_NP_UTILS_DYNAMIC_NP_OBJECT_H_
+#define GPU_NP_UTILS_DYNAMIC_NP_OBJECT_H_
+
+#include <map>
+
+#include "gpu/np_utils/default_np_object.h"
+#include "gpu/np_utils/np_utils.h"
+
+namespace np_utils {
+
+// NPObjects of this type have a dictionary of property name / variant pairs
+// that can be changed at runtime through NPAPI.
+class DynamicNPObject : public DefaultNPObject<NPObject> {
+ public:
+  explicit DynamicNPObject(NPP npp);
+
+  void Invalidate();
+  bool HasProperty(NPIdentifier name);
+  bool GetProperty(NPIdentifier name, NPVariant* result);
+  bool SetProperty(NPIdentifier name, const NPVariant* value);
+  bool RemoveProperty(NPIdentifier name);
+  bool Enumerate(NPIdentifier** names, uint32_t* count);
+
+ private:
+  typedef std::map<NPIdentifier, SmartNPVariant> PropertyMap;
+  PropertyMap properties_;
+  DISALLOW_COPY_AND_ASSIGN(DynamicNPObject);
+};
+}  // namespace np_utils
+
+#endif  // GPU_NP_UTILS_DYNAMIC_NP_OBJECT_H_
diff --git a/gpu/np_utils/dynamic_np_object_unittest.cc b/gpu/np_utils/dynamic_np_object_unittest.cc
new file mode 100644
index 0000000..d58e963
--- /dev/null
+++ b/gpu/np_utils/dynamic_np_object_unittest.cc
@@ -0,0 +1,83 @@
+// Copyright (c) 2006-2008 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 <string>
+
+#include "gpu/np_utils/dynamic_np_object.h"
+#include "gpu/np_utils/np_browser_stub.h"
+#include "gpu/np_utils/np_utils.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using testing::Return;
+using testing::StrictMock;
+
+namespace np_utils {
+
+class NPDynamicNPObjectTest : public testing::Test {
+ protected:
+  virtual void SetUp() {
+    object_ = NPCreateObject<DynamicNPObject>(NULL);
+  }
+
+  StubNPBrowser stub_browser_;
+  NPObjectPointer<DynamicNPObject> object_;
+};
+
+TEST_F(NPDynamicNPObjectTest, HasPropertyReturnsFalseForMissingProperty) {
+  EXPECT_FALSE(NPHasProperty(NULL, object_, "missing"));
+}
+
+TEST_F(NPDynamicNPObjectTest, GetPropertyReturnsFalseForMissingProperty) {
+  int32 r;
+  EXPECT_FALSE(NPGetProperty(NULL, object_, "missing", &r));
+}
+
+TEST_F(NPDynamicNPObjectTest, CanSetProperty) {
+  EXPECT_TRUE(NPSetProperty(NULL, object_, "foo", 7));
+  int32 r;
+  EXPECT_TRUE(NPHasProperty(NULL, object_, "foo"));
+  EXPECT_TRUE(NPGetProperty(NULL, object_, "foo", &r));
+  EXPECT_EQ(7, r);
+}
+
+TEST_F(NPDynamicNPObjectTest, CanRemoveProperty) {
+  EXPECT_TRUE(NPSetProperty(NULL, object_, "foo", 7));
+  EXPECT_TRUE(NPHasProperty(NULL, object_, "foo"));
+  EXPECT_FALSE(NPRemoveProperty(NULL, object_, "foo"));
+  EXPECT_FALSE(NPHasProperty(NULL, object_, "foo"));
+  int32 r;
+  EXPECT_FALSE(NPGetProperty(NULL, object_, "foo", &r));
+}
+
+TEST_F(NPDynamicNPObjectTest, CanEnumerateProperties) {
+  EXPECT_TRUE(NPSetProperty(NULL, object_, "foo", 7));
+
+  NPIdentifier* names;
+  uint32 num_names;
+  EXPECT_TRUE(object_->_class->enumerate(object_.Get(), &names, &num_names));
+
+  EXPECT_EQ(1, num_names);
+  EXPECT_EQ(NPBrowser::get()->GetStringIdentifier("foo"), names[0]);
+
+  NPBrowser::get()->MemFree(names);
+}
+
+// Properties should not be
+TEST_F(NPDynamicNPObjectTest, InvalidateNullsObjectProperties) {
+  EXPECT_EQ(1, object_->referenceCount);
+  {
+    EXPECT_TRUE(NPSetProperty(NULL, object_, "foo", object_));
+    EXPECT_TRUE(NPHasProperty(NULL, object_, "foo"));
+    object_->_class->invalidate(object_.Get());
+    EXPECT_TRUE(NPHasProperty(NULL, object_, "foo"));
+    NPObjectPointer<DynamicNPObject> r;
+    EXPECT_TRUE(NPGetProperty(NULL, object_, "foo", &r));
+    EXPECT_TRUE(NULL == r.Get());
+  }
+  // Invalidate did not release object
+  EXPECT_EQ(2, object_->referenceCount);
+  NPBrowser::get()->ReleaseObject(object_.Get());
+}
+}  // namespace np_utils
diff --git a/gpu/np_utils/np_browser.cc b/gpu/np_utils/np_browser.cc
new file mode 100644
index 0000000..d0d703c7
--- /dev/null
+++ b/gpu/np_utils/np_browser.cc
@@ -0,0 +1,123 @@
+// Copyright (c) 2006-2008 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 "gpu/np_utils/np_browser.h"
+#include "base/logging.h"
+#include "webkit/glue/plugins/nphostapi.h"
+
+namespace np_utils {
+
+NPBrowser* NPBrowser::browser_;
+
+NPBrowser::NPBrowser(NPNetscapeFuncs* funcs)
+    : netscape_funcs_(funcs) {
+  // Make this the first browser in the linked list.
+  previous_browser_ = browser_;
+  browser_ = this;
+}
+
+NPBrowser::~NPBrowser() {
+  // Remove this browser from the linked list.
+  DCHECK(browser_ == this);
+  browser_ = previous_browser_;
+}
+
+NPIdentifier NPBrowser::GetStringIdentifier(const NPUTF8* name) {
+  return netscape_funcs_->getstringidentifier(name);
+}
+
+void* NPBrowser::MemAlloc(size_t size) {
+  return netscape_funcs_->memalloc(size);
+}
+
+void NPBrowser::MemFree(void* p) {
+  netscape_funcs_->memfree(p);
+}
+
+NPObject* NPBrowser::CreateObject(NPP npp, const NPClass* cl) {
+  return netscape_funcs_->createobject(npp, const_cast<NPClass*>(cl));
+}
+
+NPObject* NPBrowser::RetainObject(NPObject* object) {
+  return netscape_funcs_->retainobject(object);
+}
+
+void NPBrowser::ReleaseObject(NPObject* object) {
+  netscape_funcs_->releaseobject(object);
+}
+
+void NPBrowser::ReleaseVariantValue(NPVariant* variant) {
+  netscape_funcs_->releasevariantvalue(variant);
+}
+
+bool NPBrowser::HasProperty(NPP npp,
+                            NPObject* object,
+                            NPIdentifier name) {
+  return netscape_funcs_->hasproperty(npp, object, name);
+}
+
+bool NPBrowser::GetProperty(NPP npp,
+                            NPObject* object,
+                            NPIdentifier name,
+                            NPVariant* result) {
+  return netscape_funcs_->getproperty(npp, object, name, result);
+}
+
+bool NPBrowser::SetProperty(NPP npp,
+                            NPObject* object,
+                            NPIdentifier name,
+                            const NPVariant* result) {
+  return netscape_funcs_->setproperty(npp, object, name, result);
+}
+
+bool NPBrowser::RemoveProperty(NPP npp,
+                               NPObject* object,
+                               NPIdentifier name) {
+  return netscape_funcs_->removeproperty(npp, object, name);
+}
+
+bool NPBrowser::HasMethod(NPP npp,
+                          NPObject* object,
+                          NPIdentifier name) {
+  return netscape_funcs_->hasmethod(npp, object, name);
+}
+
+bool NPBrowser::Invoke(NPP npp,
+                       NPObject* object,
+                       NPIdentifier name,
+                       const NPVariant* args,
+                       uint32_t num_args,
+                       NPVariant* result) {
+  return netscape_funcs_->invoke(npp, object, name, args, num_args, result);
+}
+
+NPObject* NPBrowser::GetWindowNPObject(NPP npp) {
+  NPObject* window;
+  if (NPERR_NO_ERROR == netscape_funcs_->getvalue(npp,
+                                                  NPNVWindowNPObject,
+                                                  &window)) {
+    return window;
+  } else {
+    return NULL;
+  }
+}
+
+void NPBrowser::PluginThreadAsyncCall(NPP npp,
+                                      PluginThreadAsyncCallProc callback,
+                                      void* data) {
+  netscape_funcs_->pluginthreadasynccall(npp, callback, data);
+}
+
+uint32 NPBrowser::ScheduleTimer(NPP npp,
+                                uint32 interval,
+                                bool repeat,
+                                TimerProc callback) {
+  return netscape_funcs_->scheduletimer(npp, interval, repeat, callback);
+}
+
+void NPBrowser::UnscheduleTimer(NPP npp, uint32 timer_id) {
+  netscape_funcs_->unscheduletimer(npp, timer_id);
+}
+
+}  // namespace np_utils
diff --git a/gpu/np_utils/np_browser.h b/gpu/np_utils/np_browser.h
new file mode 100644
index 0000000..e46bf38f
--- /dev/null
+++ b/gpu/np_utils/np_browser.h
@@ -0,0 +1,95 @@
+// Copyright (c) 2006-2008 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 GPU_NP_UTILS_NP_BROWSER_H_
+#define GPU_NP_UTILS_NP_BROWSER_H_
+
+#include "base/basictypes.h"
+#include "gpu/np_utils/np_headers.h"
+
+typedef struct _NPNetscapeFuncs NPNetscapeFuncs;
+
+namespace np_utils {
+
+// This class exposes the functions provided by the browser to a plugin (the
+// ones prefixed NPN_).
+class NPBrowser {
+ public:
+  explicit NPBrowser(NPNetscapeFuncs* funcs);
+  virtual ~NPBrowser();
+
+  static NPBrowser* get() {
+    return browser_;
+  }
+
+  // Standard functions from NPNetscapeFuncs.
+
+  virtual NPIdentifier GetStringIdentifier(const NPUTF8* name);
+
+  virtual void* MemAlloc(size_t size);
+
+  virtual void MemFree(void* p);
+
+  virtual NPObject* CreateObject(NPP npp, const NPClass* cl);
+
+  virtual NPObject* RetainObject(NPObject* object);
+
+  virtual void ReleaseObject(NPObject* object);
+
+  virtual void ReleaseVariantValue(NPVariant* variant);
+
+  virtual bool HasProperty(NPP npp,
+                           NPObject* object,
+                           NPIdentifier name);
+
+  virtual bool GetProperty(NPP npp,
+                           NPObject* object,
+                           NPIdentifier name,
+                           NPVariant* result);
+
+  virtual bool SetProperty(NPP npp,
+                           NPObject* object,
+                           NPIdentifier name,
+                           const NPVariant* result);
+
+  virtual bool RemoveProperty(NPP npp,
+                              NPObject* object,
+                              NPIdentifier name);
+
+  virtual bool HasMethod(NPP npp,
+                           NPObject* object,
+                           NPIdentifier name);
+
+  virtual bool Invoke(NPP npp,
+                      NPObject* object,
+                      NPIdentifier name,
+                      const NPVariant* args,
+                      uint32_t num_args,
+                      NPVariant* result);
+
+  virtual NPObject* GetWindowNPObject(NPP npp);
+
+  typedef void (*PluginThreadAsyncCallProc)(void* data);
+  virtual void PluginThreadAsyncCall(NPP npp,
+                                     PluginThreadAsyncCallProc callback,
+                                     void* data);
+
+  typedef void (*TimerProc)(NPP npp, uint32 timer_id);
+  virtual uint32 ScheduleTimer(NPP npp,
+                               uint32 interval,
+                               bool repeat,
+                               TimerProc callback);
+
+  virtual void UnscheduleTimer(NPP npp, uint32 timer_id);
+
+ private:
+  static NPBrowser* browser_;
+  NPBrowser* previous_browser_;
+  NPNetscapeFuncs* netscape_funcs_;
+  DISALLOW_COPY_AND_ASSIGN(NPBrowser);
+};
+
+}  // namespace np_utils
+
+#endif  // GPU_NP_UTILS_NP_BROWSER_H_
diff --git a/gpu/np_utils/np_browser_mock.h b/gpu/np_utils/np_browser_mock.h
new file mode 100644
index 0000000..c5361c71
--- /dev/null
+++ b/gpu/np_utils/np_browser_mock.h
@@ -0,0 +1,50 @@
+// Copyright (c) 2006-2008 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 GPU_NP_UTILS_NP_BROWSER_MOCK_H_
+#define GPU_NP_UTILS_NP_BROWSER_MOCK_H_
+
+#include "gpu/np_utils/np_browser_stub.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace np_utils {
+
+// This mocks certain member functions of the stub browser. Those relating
+// to identifiers, memory management, reference counting and forwarding to
+// NPObjects are deliberately not mocked so the mock browser can be used as
+// normal for these calls.
+class MockNPBrowser : public StubNPBrowser {
+ public:
+  NPObject* ConcreteCreateObject(NPP npp, const NPClass* cl) {
+    return StubNPBrowser::CreateObject(npp, cl);
+  }
+
+  MockNPBrowser() {
+    // Do not mock CreateObject by default but allow it to be mocked so object
+    // creation can be intercepted.
+    ON_CALL(*this, CreateObject(testing::_, testing::_))
+      .WillByDefault(testing::Invoke(this,
+                                     &MockNPBrowser::ConcreteCreateObject));
+  }
+
+  void ConcretePluginThreadAsyncCall(NPP npp,
+                                     PluginThreadAsyncCallProc callback,
+                                     void* data) {
+    return StubNPBrowser::PluginThreadAsyncCall(npp, callback, data);
+  }
+
+  MOCK_METHOD2(CreateObject, NPObject*(NPP npp, const NPClass* cl));
+  MOCK_METHOD1(GetWindowNPObject, NPObject*(NPP cpp));
+  MOCK_METHOD3(PluginThreadAsyncCall,
+               void(NPP npp, PluginThreadAsyncCallProc callback, void* data));
+  MOCK_METHOD4(ScheduleTimer, uint32(NPP npp,
+                                     uint32 interval,
+                                     bool repeat,
+                                     TimerProc callback));
+  MOCK_METHOD2(UnscheduleTimer, void(NPP npp, uint32 timer_id));
+};
+
+}  // namespace np_utils
+
+#endif  // GPU_NP_UTILS_NP_BROWSER_MOCK_H_
diff --git a/gpu/np_utils/np_browser_stub.cc b/gpu/np_utils/np_browser_stub.cc
new file mode 100644
index 0000000..2e1c757
--- /dev/null
+++ b/gpu/np_utils/np_browser_stub.cc
@@ -0,0 +1,125 @@
+// Copyright (c) 2006-2008 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 "gpu/np_utils/np_browser_stub.h"
+#include "base/logging.h"
+#include "base/message_loop.h"
+
+namespace np_utils {
+
+StubNPBrowser::StubNPBrowser() : NPBrowser(NULL) {
+}
+
+StubNPBrowser::~StubNPBrowser() {
+}
+
+NPIdentifier StubNPBrowser::GetStringIdentifier(const NPUTF8* name) {
+  static std::set<std::string> names;
+  std::set<std::string>::iterator it = names.find(name);
+  if (it == names.end()) {
+    it = names.insert(name).first;
+  }
+  return const_cast<NPUTF8*>((*it).c_str());
+}
+
+void* StubNPBrowser::MemAlloc(size_t size) {
+  return malloc(size);
+}
+
+void StubNPBrowser::MemFree(void* p) {
+  free(p);
+}
+
+NPObject* StubNPBrowser::CreateObject(NPP npp, const NPClass* cl) {
+  NPObject* object = cl->allocate(npp, const_cast<NPClass*>(cl));
+  object->referenceCount = 1;
+  object->_class = const_cast<NPClass*>(cl);
+  return object;
+}
+
+NPObject* StubNPBrowser::RetainObject(NPObject* object) {
+  ++object->referenceCount;
+  return object;
+}
+
+void StubNPBrowser::ReleaseObject(NPObject* object) {
+  DCHECK_GE(object->referenceCount, 0u);
+  --object->referenceCount;
+  if (object->referenceCount == 0) {
+    object->_class->deallocate(object);
+  }
+}
+
+void StubNPBrowser::ReleaseVariantValue(NPVariant* variant) {
+  if (NPVARIANT_IS_STRING(*variant)) {
+    MemFree(const_cast<NPUTF8*>(variant->value.stringValue.UTF8Characters));
+  } else if (NPVARIANT_IS_OBJECT(*variant)) {
+    ReleaseObject(NPVARIANT_TO_OBJECT(*variant));
+  }
+}
+
+bool StubNPBrowser::HasProperty(NPP npp,
+                                NPObject* object,
+                                NPIdentifier name) {
+  return object->_class->hasProperty(object, name);
+}
+
+bool StubNPBrowser::GetProperty(NPP npp,
+                         NPObject* object,
+                         NPIdentifier name,
+                         NPVariant* result) {
+  return object->_class->getProperty(object, name, result);
+}
+
+bool StubNPBrowser::SetProperty(NPP npp,
+                            NPObject* object,
+                            NPIdentifier name,
+                            const NPVariant* result) {
+  return object->_class->setProperty(object, name, result);
+}
+
+bool StubNPBrowser::RemoveProperty(NPP npp,
+                                   NPObject* object,
+                                   NPIdentifier name) {
+  return object->_class->removeProperty(object, name);
+}
+
+bool StubNPBrowser::HasMethod(NPP npp,
+                              NPObject* object,
+                              NPIdentifier name) {
+  return object->_class->hasMethod(object, name);
+}
+
+bool StubNPBrowser::Invoke(NPP npp,
+                    NPObject* object,
+                    NPIdentifier name,
+                    const NPVariant* args,
+                    uint32_t num_args,
+                    NPVariant* result) {
+  return object->_class->invoke(object, name, args, num_args, result);
+}
+
+NPObject* StubNPBrowser::GetWindowNPObject(NPP npp) {
+  return NULL;
+}
+
+void StubNPBrowser::PluginThreadAsyncCall(
+    NPP npp,
+    PluginThreadAsyncCallProc callback,
+    void* data) {
+  MessageLoop::current()->PostTask(FROM_HERE,
+                                   NewRunnableFunction(callback, data));
+}
+
+uint32 StubNPBrowser::ScheduleTimer(NPP npp,
+                                    uint32 interval,
+                                    bool repeat,
+                                    TimerProc callback) {
+  return 0;
+}
+
+void StubNPBrowser::UnscheduleTimer(NPP npp, uint32 timer_id) {
+}
+
+}  // namespace np_utils
diff --git a/gpu/np_utils/np_browser_stub.h b/gpu/np_utils/np_browser_stub.h
new file mode 100644
index 0000000..f208b7b7
--- /dev/null
+++ b/gpu/np_utils/np_browser_stub.h
@@ -0,0 +1,84 @@
+// Copyright (c) 2006-2008 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 GPU_NP_UTILS_NP_BROWSER_STUB_H_
+#define GPU_NP_UTILS_NP_BROWSER_STUB_H_
+
+#include <set>
+#include <string>
+
+#include "gpu/np_utils/np_browser.h"
+
+namespace np_utils {
+
+// Simple implementation of subset of the NPN functions for testing.
+class StubNPBrowser : public NPBrowser {
+ public:
+  StubNPBrowser();
+  virtual ~StubNPBrowser();
+
+  // Standard functions from NPNetscapeFuncs.
+
+  virtual NPIdentifier GetStringIdentifier(const NPUTF8* name);
+
+  virtual void* MemAlloc(size_t size);
+
+  virtual void MemFree(void* p);
+
+  virtual NPObject* CreateObject(NPP npp, const NPClass* cl);
+
+  virtual NPObject* RetainObject(NPObject* object);
+
+  virtual void ReleaseObject(NPObject* object);
+
+  virtual void ReleaseVariantValue(NPVariant* variant);
+
+  virtual bool HasProperty(NPP npp,
+                           NPObject* object,
+                           NPIdentifier name);
+
+  virtual bool GetProperty(NPP npp,
+                           NPObject* object,
+                           NPIdentifier name,
+                           NPVariant* result);
+
+  virtual bool SetProperty(NPP npp,
+                           NPObject* object,
+                           NPIdentifier name,
+                           const NPVariant* result);
+
+  virtual bool RemoveProperty(NPP npp,
+                              NPObject* object,
+                              NPIdentifier name);
+
+  virtual bool HasMethod(NPP npp,
+                           NPObject* object,
+                           NPIdentifier name);
+  virtual bool Invoke(NPP npp,
+                      NPObject* object,
+                      NPIdentifier name,
+                      const NPVariant* args,
+                      uint32_t num_args,
+                      NPVariant* result);
+
+  virtual NPObject* GetWindowNPObject(NPP npp);
+
+  virtual void PluginThreadAsyncCall(NPP npp,
+                                     PluginThreadAsyncCallProc callback,
+                                     void* data);
+
+  virtual uint32 ScheduleTimer(NPP npp,
+                               uint32 interval,
+                               bool repeat,
+                               TimerProc callback);
+
+  virtual void UnscheduleTimer(NPP npp, uint32 timer_id);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(StubNPBrowser);
+};
+
+}  // namespace np_utils
+
+#endif  // GPU_NP_UTILS_NP_BROWSER_STUB_H_
diff --git a/gpu/np_utils/np_class.h b/gpu/np_utils/np_class.h
new file mode 100644
index 0000000..21d1d4b7
--- /dev/null
+++ b/gpu/np_utils/np_class.h
@@ -0,0 +1,125 @@
+// Copyright (c) 2006-2008 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 GPU_NP_UTILS_NP_CLASS_H_
+#define GPU_NP_UTILS_NP_CLASS_H_
+
+#include "gpu/np_utils/np_object_pointer.h"
+#include "gpu/np_utils/np_headers.h"
+
+// This file implements NPGetClass<T>. This function returns an NPClass
+// that can be used to instantiate an NPObject subclass T. The NPClass
+// function pointers will invoke the most derived corresponding member
+// functions in T.
+
+namespace np_utils {
+
+namespace np_class_impl {
+  // This template version of the NPClass allocate function creates a subclass
+  // of BaseNPObject.
+  template <typename NPObjectType>
+  static NPObject* Allocate(NPP npp, NPClass*) {
+    return new NPObjectType(npp);
+  }
+
+  // These implementations of the NPClass functions forward to the virtual
+  // functions in DefaultNPObject.
+  template <typename NPObjectType>
+  static void Deallocate(NPObject* object) {
+    delete static_cast<NPObjectType*>(object);
+  }
+
+  template <typename NPObjectType>
+  static void Invalidate(NPObject* object) {
+    return static_cast<NPObjectType*>(object)->Invalidate();
+  }
+
+  template <typename NPObjectType>
+  static bool HasMethod(NPObject* object, NPIdentifier name) {
+    return static_cast<NPObjectType*>(object)->HasMethod(name);
+  }
+
+  template <typename NPObjectType>
+  static bool Invoke(NPObject* object,
+                     NPIdentifier name,
+                     const NPVariant* args,
+                     uint32_t num_args,
+                     NPVariant* result) {
+    return static_cast<NPObjectType*>(object)->Invoke(
+        name, args, num_args, result);
+  }
+
+  template <typename NPObjectType>
+  static bool InvokeDefault(NPObject* object,
+                            const NPVariant* args,
+                            uint32_t num_args,
+                            NPVariant* result) {
+    return static_cast<NPObjectType*>(object)->InvokeDefault(
+        args, num_args, result);
+  }
+
+  template <typename NPObjectType>
+  static bool HasProperty(NPObject* object, NPIdentifier name) {
+    return static_cast<NPObjectType*>(object)->HasProperty(name);
+  }
+
+  template <typename NPObjectType>
+  static bool GetProperty(NPObject* object,
+                          NPIdentifier name,
+                          NPVariant* result) {
+    return static_cast<NPObjectType*>(object)->GetProperty(name, result);
+  }
+
+  template <typename NPObjectType>
+  static bool SetProperty(NPObject* object,
+                              NPIdentifier name,
+                              const NPVariant* value) {
+    return static_cast<NPObjectType*>(object)->SetProperty(name, value);
+  }
+
+  template <typename NPObjectType>
+  static bool RemoveProperty(NPObject* object, NPIdentifier name) {
+    return static_cast<NPObjectType*>(object)->RemoveProperty(name);
+  }
+
+  template <typename NPObjectType>
+  static bool Enumerate(NPObject* object,
+                            NPIdentifier** names,
+                            uint32_t* count) {
+    return static_cast<NPObjectType*>(object)->Enumerate(names, count);
+  };
+
+  template <typename NPObjectType>
+  static bool Construct(NPObject* object,
+                            const NPVariant* args,
+                            uint32_t num_args,
+                            NPVariant* result) {
+    return static_cast<NPObjectType*>(object)->Construct(
+        args, num_args, result);
+  }
+}  // namespace np_class_impl;
+
+template <typename NPObjectType>
+const NPClass* NPGetClass() {
+  static const NPClass np_class = {
+    NP_CLASS_STRUCT_VERSION,
+    np_class_impl::Allocate<NPObjectType>,
+    np_class_impl::Deallocate<NPObjectType>,
+    np_class_impl::Invalidate<NPObjectType>,
+    np_class_impl::HasMethod<NPObjectType>,
+    np_class_impl::Invoke<NPObjectType>,
+    np_class_impl::InvokeDefault<NPObjectType>,
+    np_class_impl::HasProperty<NPObjectType>,
+    np_class_impl::GetProperty<NPObjectType>,
+    np_class_impl::SetProperty<NPObjectType>,
+    np_class_impl::RemoveProperty<NPObjectType>,
+    np_class_impl::Enumerate<NPObjectType>,
+    np_class_impl::Construct<NPObjectType>,
+  };
+  return &np_class;
+};
+
+}  // namespace np_utils
+
+#endif  // GPU_NP_UTILS_NP_CLASS_H_
diff --git a/gpu/np_utils/np_class_unittest.cc b/gpu/np_utils/np_class_unittest.cc
new file mode 100644
index 0000000..0e7807f
--- /dev/null
+++ b/gpu/np_utils/np_class_unittest.cc
@@ -0,0 +1,143 @@
+// Copyright (c) 2006-2008 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 "gpu/np_utils/np_class.h"
+#include "gpu/np_utils/np_object_mock.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using testing::StrictMock;
+
+namespace np_utils {
+
+class NPClassTest : public testing::Test {
+ protected:
+  virtual void SetUp() {
+    np_class = NPGetClass<StrictMock<MockNPObject> >();
+
+    // Dummy identifier is never used with real NPAPI so it can point to
+    // anything.
+    identifier = this;
+  }
+
+  virtual void TearDown() {
+  }
+
+  NPP_t npp_;
+  const NPClass* np_class;
+  NPIdentifier identifier;
+  NPVariant args[3];
+  NPVariant result;
+};
+
+TEST_F(NPClassTest, AllocateAndDeallocateObject) {
+  MockNPObject* object = static_cast<MockNPObject*>(
+      np_class->allocate(&npp_, const_cast<NPClass*>(np_class)));
+  EXPECT_TRUE(NULL != object);
+
+  np_class->deallocate(object);
+}
+
+TEST_F(NPClassTest, InvalidateForwards) {
+  MockNPObject* object = static_cast<MockNPObject*>(
+      np_class->allocate(&npp_, const_cast<NPClass*>(np_class)));
+
+  EXPECT_CALL(*object, Invalidate());
+  np_class->invalidate(object);
+
+  np_class->deallocate(object);
+}
+
+TEST_F(NPClassTest, HasMethodForwards) {
+  MockNPObject* object = static_cast<MockNPObject*>(
+      np_class->allocate(&npp_, const_cast<NPClass*>(np_class)));
+
+  EXPECT_CALL(*object, HasMethod(identifier));
+  np_class->hasMethod(object, identifier);
+
+  np_class->deallocate(object);
+}
+
+TEST_F(NPClassTest, InvokeForwards) {
+  MockNPObject* object = static_cast<MockNPObject*>(
+      np_class->allocate(&npp_, const_cast<NPClass*>(np_class)));
+
+  EXPECT_CALL(*object, Invoke(identifier, args, 3, &result));
+  np_class->invoke(object, identifier, args, 3, &result);
+
+  np_class->deallocate(object);
+}
+
+TEST_F(NPClassTest, InvokeDefaultForwards) {
+  MockNPObject* object = static_cast<MockNPObject*>(
+      np_class->allocate(&npp_, const_cast<NPClass*>(np_class)));
+
+  EXPECT_CALL(*object, InvokeDefault(args, 3, &result));
+  np_class->invokeDefault(object, args, 3, &result);
+
+  np_class->deallocate(object);
+}
+
+TEST_F(NPClassTest, HasPropertyForwards) {
+  MockNPObject* object = static_cast<MockNPObject*>(
+      np_class->allocate(&npp_, const_cast<NPClass*>(np_class)));
+
+  EXPECT_CALL(*object, HasProperty(identifier));
+  np_class->hasProperty(object, identifier);
+
+  np_class->deallocate(object);
+}
+
+TEST_F(NPClassTest, GetPropertyForwards) {
+  MockNPObject* object = static_cast<MockNPObject*>(
+      np_class->allocate(&npp_, const_cast<NPClass*>(np_class)));
+
+  EXPECT_CALL(*object, GetProperty(identifier, &result));
+  np_class->getProperty(object, identifier, &result);
+
+  np_class->deallocate(object);
+}
+
+TEST_F(NPClassTest, SetPropertyForwards) {
+  MockNPObject* object = static_cast<MockNPObject*>(
+      np_class->allocate(&npp_, const_cast<NPClass*>(np_class)));
+
+  EXPECT_CALL(*object, SetProperty(identifier, &result));
+  np_class->setProperty(object, identifier, &result);
+
+  np_class->deallocate(object);
+}
+
+TEST_F(NPClassTest, RemovePropertyForwards) {
+  MockNPObject* object = static_cast<MockNPObject*>(
+      np_class->allocate(&npp_, const_cast<NPClass*>(np_class)));
+
+  EXPECT_CALL(*object, RemoveProperty(identifier));
+  np_class->removeProperty(object, identifier);
+
+  np_class->deallocate(object);
+}
+
+TEST_F(NPClassTest, EnumerateForwards) {
+  MockNPObject* object = static_cast<MockNPObject*>(
+      np_class->allocate(&npp_, const_cast<NPClass*>(np_class)));
+
+  NPIdentifier* identifier = NULL;
+  uint32_t count;
+  EXPECT_CALL(*object, Enumerate(&identifier, &count));
+  np_class->enumerate(object, &identifier, &count);
+
+  np_class->deallocate(object);
+}
+
+TEST_F(NPClassTest, ConstructForwards) {
+  MockNPObject* object = static_cast<MockNPObject*>(
+      np_class->allocate(&npp_, const_cast<NPClass*>(np_class)));
+
+  EXPECT_CALL(*object, Construct(args, 3, &result));
+  np_class->construct(object, args, 3, &result);
+
+  np_class->deallocate(object);
+}
+}  // namespace np_utils
diff --git a/gpu/np_utils/np_dispatcher.cc b/gpu/np_utils/np_dispatcher.cc
new file mode 100644
index 0000000..63293c0e
--- /dev/null
+++ b/gpu/np_utils/np_dispatcher.cc
@@ -0,0 +1,86 @@
+// Copyright (c) 2006-2008 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 "gpu/np_utils/np_dispatcher.h"
+
+namespace np_utils {
+
+bool DispatcherHasMethodHelper(BaseNPDispatcher* chain,
+                               NPObject* object,
+                               NPIdentifier name) {
+  for (BaseNPDispatcher* dispatcher = chain;
+       dispatcher;
+       dispatcher = dispatcher->next()) {
+    if (dispatcher->name() == name) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
+bool DispatcherInvokeHelper(BaseNPDispatcher* chain,
+                            NPObject* object,
+                            NPIdentifier name,
+                            const NPVariant* args,
+                            uint32_t num_args,
+                            NPVariant* result) {
+  VOID_TO_NPVARIANT(*result);
+
+  for (BaseNPDispatcher* dispatcher = chain;
+       dispatcher;
+       dispatcher = dispatcher->next()) {
+    if (dispatcher->name() == name &&
+        dispatcher->num_args() == static_cast<int>(num_args)) {
+      if (dispatcher->Invoke(object, args, num_args, result))
+        return true;
+    }
+  }
+
+  return false;
+}
+
+bool DispatcherEnumerateHelper(BaseNPDispatcher* chain,
+                               NPObject* object,
+                               NPIdentifier** names,
+                               uint32_t* num_names) {
+  // Count the number of names.
+  *num_names = 0;
+  for (BaseNPDispatcher* dispatcher = chain;
+       dispatcher;
+       dispatcher = dispatcher->next()) {
+    ++(*num_names);
+  }
+
+  // Copy names into the array.
+  *names = static_cast<NPIdentifier*>(
+      NPBrowser::get()->MemAlloc((*num_names) * sizeof(**names)));
+  int i = 0;
+  for (BaseNPDispatcher* dispatcher = chain;
+       dispatcher;
+       dispatcher = dispatcher->next()) {
+    (*names)[i] = dispatcher->name();
+    ++i;
+  }
+
+  return true;
+}
+
+BaseNPDispatcher::BaseNPDispatcher(BaseNPDispatcher* next, const NPUTF8* name)
+    : next_(next) {
+  // Convert first character to lower case if it is the ASCII range.
+  // TODO(apatrick): do this correctly for non-ASCII characters.
+  std::string java_script_style_name(name);
+  if (isupper(java_script_style_name[0])) {
+    java_script_style_name[0] = tolower(java_script_style_name[0]);
+  }
+
+  name_ = NPBrowser::get()->GetStringIdentifier(
+      java_script_style_name.c_str());
+}
+
+BaseNPDispatcher::~BaseNPDispatcher() {
+}
+
+}  // namespace np_utils
diff --git a/gpu/np_utils/np_dispatcher.h b/gpu/np_utils/np_dispatcher.h
new file mode 100644
index 0000000..ff6bed59
--- /dev/null
+++ b/gpu/np_utils/np_dispatcher.h
@@ -0,0 +1,224 @@
+// Copyright (c) 2006-2008 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 GPU_NP_UTILS_NP_DISPATCHER_H_
+#define GPU_NP_UTILS_NP_DISPATCHER_H_
+
+#include <string>
+
+#include "gpu/np_utils/np_utils.h"
+#include "gpu/np_utils/np_headers.h"
+
+// Dispatchers make regular member functions available as NPObject methods.
+// Usage:
+//
+// class MyNPObject : public DefaultNPObject<NPObject> {
+//  public:
+//   int MyMethod(bool a, float b);
+//   NP_UTILS_BEGIN_DISPATCHER_CHAIN(MyNPObject, DispatchedNPObject)
+//     NP_UTILS_DISPATCHER(MyMethod, int(bool, float))
+//   NP_UTILS_END_DISPATCHER_CHAIN
+// };
+//
+// Multiple member functions may be listed in the dispatcher chain. Inheritance
+// is supported. The following types are supported as return types and parameter
+// types:
+//   * bool
+//   * int
+//   * float
+//   * double
+//   * std::string
+//   * NPObject*
+//
+
+// These macros are used to make dispatcher chains.
+#define NP_UTILS_NP_UTILS_DISPATCHER_JOIN2(a, b) a ## b
+#define NP_UTILS_DISPATCHER_JOIN(a, b) NP_UTILS_NP_UTILS_DISPATCHER_JOIN2(a, b)
+#define NP_UTILS_DISPATCHER_UNIQUE                                             \
+  NP_UTILS_DISPATCHER_JOIN(dispatcher, __LINE__)
+
+#define NP_UTILS_BEGIN_DISPATCHER_CHAIN(Class, BaseClass)                      \
+  static ::np_utils::BaseNPDispatcher* GetDispatcherChain() {                  \
+    typedef Class ThisClass;                                                   \
+    ::np_utils::BaseNPDispatcher* top_dispatcher =                             \
+        BaseClass::GetDispatcherChain();                                       \
+
+#define NP_UTILS_DISPATCHER(name, Signature)                                   \
+    static ::np_utils::NPDispatcher<ThisClass, Signature>                      \
+        NP_UTILS_DISPATCHER_UNIQUE(                                            \
+            top_dispatcher,                                                    \
+            #name,                                                             \
+            &ThisClass::name);                                                 \
+    top_dispatcher = &NP_UTILS_DISPATCHER_UNIQUE;                              \
+
+#define NP_UTILS_END_DISPATCHER_CHAIN                                          \
+    return top_dispatcher;                                                     \
+  }                                                                            \
+  bool HasMethod(NPIdentifier name) {                                          \
+    return ::np_utils::DispatcherHasMethodHelper(                              \
+        GetDispatcherChain(), this, name);                                     \
+  }                                                                            \
+  bool Invoke(NPIdentifier name,                                               \
+              const NPVariant* args,                                           \
+              uint32_t num_args,                                               \
+              NPVariant* result) {                                             \
+    return ::np_utils::DispatcherInvokeHelper(GetDispatcherChain(),            \
+                                              this,                            \
+                                              name,                            \
+                                              args,                            \
+                                              num_args,                        \
+                                              result);                         \
+  }                                                                            \
+  bool Enumerate(NPIdentifier** names, uint32_t* num_names) {                  \
+    return ::np_utils::DispatcherEnumerateHelper(GetDispatcherChain(),         \
+                                                 this,                         \
+                                                 names,                        \
+                                                 num_names);                   \
+  }                                                                            \
+
+namespace np_utils {
+
+class BaseNPDispatcher {
+ public:
+  BaseNPDispatcher(BaseNPDispatcher* next, const NPUTF8* name);
+
+  virtual ~BaseNPDispatcher();
+
+  BaseNPDispatcher* next() const {
+    return next_;
+  }
+
+  NPIdentifier name() const {
+    return name_;
+  }
+
+  virtual int num_args() const = 0;
+
+  virtual bool Invoke(NPObject* object,
+                      const NPVariant* args,
+                      uint32_t num_args,
+                      NPVariant* result) = 0;
+
+ private:
+  BaseNPDispatcher* next_;
+  NPIdentifier name_;
+  DISALLOW_COPY_AND_ASSIGN(BaseNPDispatcher);
+};
+
+bool DispatcherHasMethodHelper(BaseNPDispatcher* chain,
+                               NPObject* object,
+                               NPIdentifier name);
+
+bool DispatcherInvokeHelper(BaseNPDispatcher* chain,
+                            NPObject* object,
+                            NPIdentifier name,
+                            const NPVariant* args,
+                            uint32_t num_args,
+                            NPVariant* result);
+
+bool DispatcherEnumerateHelper(BaseNPDispatcher* chain,
+                               NPObject* object,
+                               NPIdentifier** names,
+                               uint32_t* num_names);
+
+// This class should never be instantiated. It is always specialized. Attempting
+// to instantiate it results in a compilation error. This might mean an
+// attempt to instantiate a dispatcher with more parameters than have been
+// specialized for. See the specialization code below.
+template <typename NPObjectType, typename FunctionType>
+struct NPDispatcher {
+};
+
+#define TO_NPVARIANT(index)                                                    \
+  T##index n##index;                                                           \
+  if (!NPVariantToValue(&n##index, args[index]))                               \
+    return false;                                                              \
+
+#define NUM_PARAMS 0
+#define PARAM_TYPENAMES
+#define PARAM_TYPES
+#define PARAM_NAMES
+#define PARAM_DECLS  // NOLINT
+
+#define PARAM_TO_NVPARIANT_CONVERSIONS                                         \
+
+#include "gpu/np_utils/np_dispatcher_specializations.h"  // NOLINT
+
+
+#define NUM_PARAMS 1
+#define PARAM_TYPENAMES , typename T0
+#define PARAM_TYPES T0
+#define PARAM_NAMES n0
+#define PARAM_DECLS T0 n0;  // NOLINT
+
+#define PARAM_TO_NVPARIANT_CONVERSIONS                                         \
+  TO_NPVARIANT(0);                                                             \
+
+#include "gpu/np_utils/np_dispatcher_specializations.h"  // NOLINT
+
+
+#define NUM_PARAMS 2
+#define PARAM_TYPENAMES , typename T0, typename T1
+#define PARAM_TYPES T0, T1
+#define PARAM_NAMES n0, n1
+#define PARAM_DECLS T0 n0; T1 n1;  // NOLINT
+
+#define PARAM_TO_NVPARIANT_CONVERSIONS                                         \
+  TO_NPVARIANT(0);                                                             \
+  TO_NPVARIANT(1);                                                             \
+
+#include "gpu/np_utils/np_dispatcher_specializations.h"  // NOLINT
+
+
+#define NUM_PARAMS 3
+#define PARAM_TYPENAMES , typename T0, typename T1, typename T2
+#define PARAM_TYPES T0, T1, T2
+#define PARAM_NAMES n0, n1, n2
+#define PARAM_DECLS T0 n0; T1 n1; T2 n2;  // NOLINT
+
+#define PARAM_TO_NVPARIANT_CONVERSIONS                                         \
+  TO_NPVARIANT(0);                                                             \
+  TO_NPVARIANT(1);                                                             \
+  TO_NPVARIANT(2);                                                             \
+
+#include "gpu/np_utils/np_dispatcher_specializations.h"  // NOLINT
+
+
+#define NUM_PARAMS 4
+#define PARAM_TYPENAMES , typename T0, typename T1, typename T2, typename T3
+#define PARAM_TYPES T0, T1, T2, T3
+#define PARAM_NAMES n0, n1, n2, n3
+#define PARAM_DECLS T0 n0; T1 n1; T2 n2; T3 n3;  // NOLINT
+
+#define PARAM_TO_NVPARIANT_CONVERSIONS                                         \
+  TO_NPVARIANT(0);                                                             \
+  TO_NPVARIANT(1);                                                             \
+  TO_NPVARIANT(2);                                                             \
+  TO_NPVARIANT(3);                                                             \
+
+#include "gpu/np_utils/np_dispatcher_specializations.h"  // NOLINT
+
+
+#define NUM_PARAMS 5
+#define PARAM_TYPENAMES , typename T0, typename T1, typename T2, typename T3,  \
+    typename T4
+#define PARAM_TYPES T0, T1, T2, T3, T4
+#define PARAM_NAMES n0, n1, n2, n3, n4
+#define PARAM_DECLS T0 n0; T1 n1; T2 n2; T3 n3; T4 n4;  // NOLINT
+
+#define PARAM_TO_NVPARIANT_CONVERSIONS                                         \
+  TO_NPVARIANT(0);                                                             \
+  TO_NPVARIANT(1);                                                             \
+  TO_NPVARIANT(2);                                                             \
+  TO_NPVARIANT(3);                                                             \
+  TO_NPVARIANT(4);                                                             \
+
+#include "gpu/np_utils/np_dispatcher_specializations.h"  // NOLINT
+
+
+#undef TO_NPVARIANT
+
+}  // namespace np_utils
+
+#endif  // GPU_NP_UTILS_NP_DISPATCHER_H_
diff --git a/gpu/np_utils/np_dispatcher_specializations.h b/gpu/np_utils/np_dispatcher_specializations.h
new file mode 100644
index 0000000..62fb8c4
--- /dev/null
+++ b/gpu/np_utils/np_dispatcher_specializations.h
@@ -0,0 +1,85 @@
+// Copyright (c) 2006-2008 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.
+
+// There is deliberately no header guard here. This file is included multiple
+// times, once for each dispatcher specialiation arity. Do not include this
+// file directly. Include np_dispatcher.h instead.
+
+template <typename NPObjectType PARAM_TYPENAMES>
+class NPDispatcher<NPObjectType, void(PARAM_TYPES)>
+    : public BaseNPDispatcher {
+  typedef void (NPObjectType::*FunctionType)(PARAM_TYPES);
+ public:
+  NPDispatcher(BaseNPDispatcher* next,
+               const NPUTF8* name,
+               FunctionType function)
+      : BaseNPDispatcher(next, name),
+        function_(function) {
+  }
+
+  virtual bool Invoke(NPObject* object,
+                      const NPVariant* args,
+                      uint32_t num_args,
+                      NPVariant* result) {
+    VOID_TO_NPVARIANT(*result);
+
+    if (num_args != NUM_PARAMS)
+      return false;
+
+    PARAM_TO_NVPARIANT_CONVERSIONS
+
+    (static_cast<NPObjectType*>(object)->*function_)(PARAM_NAMES);
+    return true;
+  }
+
+  virtual int num_args() const {
+    return NUM_PARAMS;
+  }
+
+ private:
+  FunctionType function_;
+};
+
+template <typename NPObjectType, typename R PARAM_TYPENAMES>
+class NPDispatcher<NPObjectType, R(PARAM_TYPES)>
+    : public BaseNPDispatcher {
+  typedef R (NPObjectType::*FunctionType)(PARAM_TYPES);
+ public:
+  NPDispatcher(BaseNPDispatcher* next,
+               const NPUTF8* name,
+               FunctionType function)
+      : BaseNPDispatcher(next, name),
+        function_(function) {
+  }
+
+  virtual bool Invoke(NPObject* object,
+                      const NPVariant* args,
+                      uint32_t num_args,
+                      NPVariant* result) {
+    VOID_TO_NPVARIANT(*result);
+
+    if (num_args != NUM_PARAMS)
+      return false;
+
+    PARAM_TO_NVPARIANT_CONVERSIONS
+
+    ValueToNPVariant(
+        (static_cast<NPObjectType*>(object)->*function_)(PARAM_NAMES), result);
+    return true;
+  }
+
+  virtual int num_args() const {
+    return NUM_PARAMS;
+  }
+
+ private:
+  FunctionType function_;
+};
+
+#undef NUM_PARAMS
+#undef PARAM_TYPENAMES
+#undef PARAM_TYPES
+#undef PARAM_NAMES
+#undef PARAM_DECLS
+#undef PARAM_TO_NVPARIANT_CONVERSIONS
diff --git a/gpu/np_utils/np_headers.h b/gpu/np_utils/np_headers.h
new file mode 100644
index 0000000..cd4d8f9c
--- /dev/null
+++ b/gpu/np_utils/np_headers.h
@@ -0,0 +1,11 @@
+// Copyright (c) 2006-2008 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 GPU_NP_UTILS_NP_HEADERS_H_
+#define GPU_NP_UTILS_NP_HEADERS_H_
+
+#include "third_party/npapi/bindings/npapi.h"
+#include "third_party/npapi/bindings/npruntime.h"
+
+#endif  // GPU_NP_UTILS_NP_HEADERS_H_
diff --git a/gpu/np_utils/np_object_mock.h b/gpu/np_utils/np_object_mock.h
new file mode 100644
index 0000000..99d1ff62
--- /dev/null
+++ b/gpu/np_utils/np_object_mock.h
@@ -0,0 +1,36 @@
+// Copyright (c) 2006-2008 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 GPU_NP_UTILS_NP_OBJECT_MOCK_H_
+#define GPU_NP_UTILS_NP_OBJECT_MOCK_H_
+
+#include "gpu/np_utils/np_browser.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace np_utils {
+
+class MockNPObject : public NPObject {
+ public:
+  explicit MockNPObject(NPP npp) {
+  }
+
+  MOCK_METHOD0(Invalidate, void());
+  MOCK_METHOD1(HasMethod, bool(NPIdentifier));
+  MOCK_METHOD4(Invoke,
+               bool(NPIdentifier, const NPVariant*, uint32_t, NPVariant*));
+  MOCK_METHOD3(InvokeDefault, bool(const NPVariant*, uint32_t, NPVariant*));
+  MOCK_METHOD1(HasProperty, bool(NPIdentifier));
+  MOCK_METHOD2(GetProperty, bool(NPIdentifier, NPVariant*));
+  MOCK_METHOD2(SetProperty, bool(NPIdentifier, const NPVariant*));
+  MOCK_METHOD1(RemoveProperty, bool(NPIdentifier));
+  MOCK_METHOD2(Enumerate, bool(NPIdentifier**, uint32_t*));
+  MOCK_METHOD3(Construct, bool(const NPVariant*, uint32_t, NPVariant*));
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MockNPObject);
+};
+
+}  // namespace np_utils
+
+#endif  // GPU_NP_UTILS_NP_OBJECT_MOCK_H_
diff --git a/gpu/np_utils/np_object_pointer.h b/gpu/np_utils/np_object_pointer.h
new file mode 100644
index 0000000..44286a7
--- /dev/null
+++ b/gpu/np_utils/np_object_pointer.h
@@ -0,0 +1,119 @@
+// Copyright (c) 2006-2008 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 GPU_NP_UTILS_NP_OBJECT_POINTER_H_
+#define GPU_NP_UTILS_NP_OBJECT_POINTER_H_
+
+#include "base/logging.h"
+#include "gpu/np_utils/np_browser.h"
+#include "gpu/np_utils/np_headers.h"
+
+namespace np_utils {
+
+// Smart pointer for NPObjects that automatically handles reference counting.
+template <typename NPObjectType>
+class NPObjectPointer {
+ public:
+  NPObjectPointer() : object_(NULL) {}
+
+  NPObjectPointer(const NPObjectPointer& rhs) : object_(rhs.object_) {
+    Retain();
+  }
+
+  explicit NPObjectPointer(NPObjectType* p) : object_(p) {
+    Retain();
+  }
+
+  template <typename RHS>
+  NPObjectPointer(const NPObjectPointer<RHS>& rhs) : object_(rhs.Get()) {
+    Retain();
+  }
+
+  ~NPObjectPointer() {
+    Release();
+  }
+
+  NPObjectPointer& operator=(const NPObjectPointer& rhs) {
+    if (object_ == rhs.Get())
+      return *this;
+
+    Release();
+    object_ = rhs.object_;
+    Retain();
+    return *this;
+  }
+
+  template <typename RHS>
+  NPObjectPointer& operator=(const NPObjectPointer<RHS>& rhs) {
+    if (object_ == rhs.Get())
+      return *this;
+
+    Release();
+    object_ = rhs.Get();
+    Retain();
+    return *this;
+  }
+
+  template <class RHS>
+  bool operator==(const NPObjectPointer<RHS>& rhs) const {
+    return object_ == rhs.Get();
+  }
+
+  template <class RHS>
+  bool operator!=(const NPObjectPointer<RHS>& rhs) const {
+    return object_ != rhs.Get();
+  }
+
+  // The NPObject convention for returning an NPObject pointer from a function
+  // is that the caller is responsible for releasing the reference count.
+  static NPObjectPointer FromReturned(NPObjectType* p) {
+    NPObjectPointer pointer(p);
+    pointer.Release();
+    return pointer;
+  }
+
+  // The NPObject convention for returning an NPObject pointer from a function
+  // is that the caller is responsible for releasing the reference count.
+  NPObjectType* ToReturned() const {
+    Retain();
+    return object_;
+  }
+
+  NPObjectType* Get() const {
+    return object_;
+  }
+
+  NPObjectType* operator->() const {
+    return object_;
+  }
+
+  NPObjectType& operator*() const {
+    return *object_;
+  }
+
+ private:
+  void Retain() const {
+    if (object_) {
+      NPBrowser::get()->RetainObject(object_);
+    }
+  }
+
+  void Release() const {
+    if (object_) {
+      NPBrowser::get()->ReleaseObject(object_);
+    }
+  }
+
+  NPObjectType* object_;
+};
+
+// For test diagnostics.
+template <typename NPObjectType>
+std::ostream& operator<<(std::ostream& stream,
+                         const NPObjectPointer<NPObjectType>& pointer) {
+  return stream << pointer.Get();
+}
+}  // namespace np_utils
+
+#endif  // GPU_NP_UTILS_NP_OBJECT_POINTER_H_
diff --git a/gpu/np_utils/np_object_pointer_unittest.cc b/gpu/np_utils/np_object_pointer_unittest.cc
new file mode 100644
index 0000000..1e48453
--- /dev/null
+++ b/gpu/np_utils/np_object_pointer_unittest.cc
@@ -0,0 +1,220 @@
+// Copyright (c) 2006-2008 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 "gpu/np_utils/np_class.h"
+#include "gpu/np_utils/np_object_mock.h"
+#include "gpu/np_utils/np_browser_stub.h"
+#include "gpu/np_utils/np_object_pointer.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using testing::Return;
+using testing::StrictMock;
+
+namespace np_utils {
+
+class DerivedNPObject : public MockNPObject {
+ public:
+  explicit DerivedNPObject(NPP npp) : MockNPObject(npp) {
+  }
+};
+
+class NPObjectPointerTest : public testing::Test {
+ protected:
+  virtual void SetUp() {
+    np_class_ = NPGetClass<StrictMock<MockNPObject> >();
+
+    raw_pointer_ = static_cast<MockNPObject*>(
+      NPBrowser::get()->CreateObject(NULL, np_class_));
+
+    raw_derived_pointer_ = static_cast<DerivedNPObject*>(
+      NPBrowser::get()->CreateObject(NULL, np_class_));
+  }
+
+  virtual void TearDown() {
+    NPBrowser::get()->ReleaseObject(raw_pointer_);
+    NPBrowser::get()->ReleaseObject(raw_derived_pointer_);
+  }
+
+  StubNPBrowser stub_browser_;
+  const NPClass* np_class_;
+  MockNPObject* raw_pointer_;
+  DerivedNPObject* raw_derived_pointer_;
+};
+
+TEST_F(NPObjectPointerTest, PointerIsNullByDefault) {
+  NPObjectPointer<MockNPObject> p;
+  ASSERT_TRUE(NULL == p.Get());
+}
+
+TEST_F(NPObjectPointerTest, PointerCanBeExplicitlyConstructedFromRawPointer) {
+  EXPECT_EQ(1, raw_pointer_->referenceCount);
+  {
+    NPObjectPointer<MockNPObject> p(raw_pointer_);
+    ASSERT_TRUE(raw_pointer_ == p.Get());
+    EXPECT_EQ(2, raw_pointer_->referenceCount);
+  }
+  EXPECT_EQ(1, raw_pointer_->referenceCount);
+}
+
+TEST_F(NPObjectPointerTest,
+    PointerCanBeExplicitlyConstructedFromNullRawPointer) {
+  NPObjectPointer<MockNPObject> p(NULL);
+  ASSERT_TRUE(NULL == p.Get());
+}
+
+TEST_F(NPObjectPointerTest, PointerCanBeCopyConstructed) {
+  NPObjectPointer<MockNPObject> p1(raw_pointer_);
+  EXPECT_EQ(2, raw_pointer_->referenceCount);
+  {
+    NPObjectPointer<MockNPObject> p2(p1);
+    ASSERT_TRUE(raw_pointer_ == p2.Get());
+    EXPECT_EQ(3, raw_pointer_->referenceCount);
+  }
+  EXPECT_EQ(2, raw_pointer_->referenceCount);
+}
+
+TEST_F(NPObjectPointerTest, PointerCanBeConstructedFromDerived) {
+  NPObjectPointer<DerivedNPObject> p1(raw_derived_pointer_);
+  EXPECT_EQ(2, raw_derived_pointer_->referenceCount);
+  {
+    NPObjectPointer<MockNPObject> p2(p1);
+    ASSERT_TRUE(raw_derived_pointer_ == p2.Get());
+    EXPECT_EQ(3, raw_derived_pointer_->referenceCount);
+  }
+  EXPECT_EQ(2, raw_derived_pointer_->referenceCount);
+}
+
+TEST_F(NPObjectPointerTest,
+    PointerCanBeCopyConstructedFromNull) {
+  NPObjectPointer<MockNPObject> p(NULL);
+  ASSERT_TRUE(NULL == p.Get());
+}
+
+TEST_F(NPObjectPointerTest, PointerCanBeAssigned) {
+  NPObjectPointer<MockNPObject> p1(raw_pointer_);
+  EXPECT_EQ(2, raw_pointer_->referenceCount);
+  {
+    NPObjectPointer<MockNPObject> p2;
+    p2 = p1;
+    ASSERT_TRUE(raw_pointer_ == p2.Get());
+    EXPECT_EQ(3, raw_pointer_->referenceCount);
+
+    p2 = NPObjectPointer<MockNPObject>();
+    ASSERT_TRUE(NULL == p2.Get());
+    EXPECT_EQ(2, raw_pointer_->referenceCount);
+
+    p2 = p1;
+    ASSERT_TRUE(raw_pointer_ == p2.Get());
+    EXPECT_EQ(3, raw_pointer_->referenceCount);
+  }
+  EXPECT_EQ(2, raw_pointer_->referenceCount);
+}
+
+TEST_F(NPObjectPointerTest, PointerCanBeAssignedToSelf) {
+  NPObjectPointer<MockNPObject> p(raw_pointer_);
+  NPBrowser::get()->ReleaseObject(raw_pointer_);
+  EXPECT_EQ(1, raw_pointer_->referenceCount);
+  p = p;
+  EXPECT_EQ(1, raw_pointer_->referenceCount);
+  NPBrowser::get()->RetainObject(raw_pointer_);
+}
+
+TEST_F(NPObjectPointerTest, PointerCanBeAssignedDerived) {
+  NPObjectPointer<DerivedNPObject> p1(raw_derived_pointer_);
+  EXPECT_EQ(2, raw_derived_pointer_->referenceCount);
+  {
+    NPObjectPointer<MockNPObject> p2;
+    p2 = p1;
+    ASSERT_TRUE(raw_derived_pointer_ == p2.Get());
+    EXPECT_EQ(3, raw_derived_pointer_->referenceCount);
+
+    p2 = NPObjectPointer<MockNPObject>();
+    ASSERT_TRUE(NULL == p2.Get());
+    EXPECT_EQ(2, raw_derived_pointer_->referenceCount);
+
+    p2 = p1;
+    ASSERT_TRUE(raw_derived_pointer_ == p2.Get());
+    EXPECT_EQ(3, raw_derived_pointer_->referenceCount);
+  }
+  EXPECT_EQ(2, raw_derived_pointer_->referenceCount);
+}
+
+TEST_F(NPObjectPointerTest, DerivedPointerCanBeAssignedToSelf) {
+  NPObjectPointer<MockNPObject> p1(raw_derived_pointer_);
+  NPObjectPointer<DerivedNPObject> p2(raw_derived_pointer_);
+  NPBrowser::get()->ReleaseObject(raw_derived_pointer_);
+  NPBrowser::get()->ReleaseObject(raw_derived_pointer_);
+  EXPECT_EQ(1, raw_derived_pointer_->referenceCount);
+  p1 = p2;
+  EXPECT_EQ(1, raw_derived_pointer_->referenceCount);
+  NPBrowser::get()->RetainObject(raw_derived_pointer_);
+  NPBrowser::get()->RetainObject(raw_derived_pointer_);
+}
+
+TEST_F(NPObjectPointerTest, CanComparePointersForEqual) {
+  NPObjectPointer<MockNPObject> p1(raw_pointer_);
+  NPObjectPointer<DerivedNPObject> p2(raw_derived_pointer_);
+  EXPECT_TRUE(p1 == p1);
+  EXPECT_FALSE(p1 == p2);
+  EXPECT_FALSE(p2 == p1);
+  EXPECT_FALSE(p1 == NPObjectPointer<MockNPObject>());
+}
+
+TEST_F(NPObjectPointerTest, CanComparePointersForNotEqual) {
+  NPObjectPointer<MockNPObject> p1(raw_pointer_);
+  NPObjectPointer<DerivedNPObject> p2(raw_derived_pointer_);
+  EXPECT_FALSE(p1 != p1);
+  EXPECT_TRUE(p1 != p2);
+  EXPECT_TRUE(p2 != p1);
+  EXPECT_TRUE(p1 != NPObjectPointer<MockNPObject>());
+}
+
+TEST_F(NPObjectPointerTest, ArrowOperatorCanBeUsedToAccessNPObjectMembers) {
+  NPIdentifier name = NPBrowser::get()->GetStringIdentifier("hello");
+
+  EXPECT_CALL(*raw_pointer_, HasProperty(name)).WillOnce(Return(true));
+
+  NPObjectPointer<MockNPObject> p(raw_pointer_);
+  EXPECT_TRUE(p->HasProperty(name));
+}
+
+TEST_F(NPObjectPointerTest, StarOperatorReturnsNPObjectReference) {
+  NPObjectPointer<MockNPObject> p(raw_pointer_);
+  EXPECT_EQ(raw_pointer_, &*p);
+}
+
+TEST_F(NPObjectPointerTest, PointerCanBeConstructedFromReturnedNPObject) {
+  NPBrowser::get()->RetainObject(raw_pointer_);
+  EXPECT_EQ(2, raw_pointer_->referenceCount);
+  {
+    NPObjectPointer<MockNPObject> p(
+      NPObjectPointer<MockNPObject>::FromReturned(raw_pointer_));
+    EXPECT_EQ(2, raw_pointer_->referenceCount);
+  }
+  EXPECT_EQ(1, raw_pointer_->referenceCount);
+}
+
+TEST_F(NPObjectPointerTest, PointerCanBeConstructedFromReturnedNullNPObject) {
+  NPObjectPointer<MockNPObject> p(
+    NPObjectPointer<MockNPObject>::FromReturned(NULL));
+  EXPECT_TRUE(NULL == p.Get());
+}
+
+TEST_F(NPObjectPointerTest, PointerCanBeReturnedAsARawNPObject) {
+  NPObjectPointer<MockNPObject> p(raw_pointer_);
+  EXPECT_EQ(raw_pointer_, p.ToReturned());
+
+  // Check reference count is incremented before return for caller.
+  EXPECT_EQ(3, raw_pointer_->referenceCount);
+
+  NPBrowser::get()->ReleaseObject(raw_pointer_);
+}
+
+TEST_F(NPObjectPointerTest, NULLPointerCanBeReturnedAsARawNPObject) {
+  NPObjectPointer<MockNPObject> p;
+  EXPECT_TRUE(NULL == p.ToReturned());
+}
+
+}  // namespace np_utils
diff --git a/gpu/np_utils/np_plugin_object.h b/gpu/np_utils/np_plugin_object.h
new file mode 100644
index 0000000..ad578e45
--- /dev/null
+++ b/gpu/np_utils/np_plugin_object.h
@@ -0,0 +1,50 @@
+// Copyright (c) 2006-2008 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 GPU_NP_UTILS_NP_PLUGIN_OBJECT_H_
+#define GPU_NP_UTILS_NP_PLUGIN_OBJECT_H_
+
+#include "gpu/np_utils/np_object_pointer.h"
+#include "gpu/np_utils/np_headers.h"
+
+namespace np_utils {
+
+// Interface for a plugin instance. The NPP plugin calls forwards to an instance
+// of this interface.
+class PluginObject {
+ public:
+  // Initialize this object.
+  virtual NPError New(NPMIMEType plugin_type,
+                      int16 argc,
+                      char* argn[],
+                      char* argv[],
+                      NPSavedData* saved) = 0;
+
+  virtual NPError SetWindow(NPWindow* new_window) = 0;
+
+  virtual int16 HandleEvent(NPEvent* event) = 0;
+
+  // Uninitialize but do not deallocate the object. Release will be called to
+  // deallocate if Destroy succeeds.
+  virtual NPError Destroy(NPSavedData** saved) = 0;
+
+  // Deallocate this object. This object is invalid after this returns.
+  virtual void Release() = 0;
+
+  virtual NPObject* GetScriptableNPObject() = 0;
+
+ protected:
+  PluginObject() {
+  }
+
+  virtual ~PluginObject() {
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(PluginObject);
+};
+
+}  // namespace np_utils
+
+#endif  // GPU_NP_UTILS_NP_PLUGIN_OBJECT_H_
diff --git a/gpu/np_utils/np_plugin_object_factory.cc b/gpu/np_utils/np_plugin_object_factory.cc
new file mode 100644
index 0000000..7eedcc8
--- /dev/null
+++ b/gpu/np_utils/np_plugin_object_factory.cc
@@ -0,0 +1,30 @@
+// Copyright (c) 2006-2008 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 "gpu/gpu_plugin/gpu_plugin_object_factory.h"
+#include "base/logging.h"
+
+namespace np_utils {
+
+NPPluginObjectFactory* NPPluginObjectFactory::factory_;
+
+PluginObject* NPPluginObjectFactory::CreatePluginObject(
+    NPP npp,
+    NPMIMEType plugin_type) {
+  return NULL;
+}
+
+NPPluginObjectFactory::NPPluginObjectFactory() {
+  // Make this the first factory in the linked list.
+  previous_factory_ = factory_;
+  factory_ = this;
+}
+
+NPPluginObjectFactory::~NPPluginObjectFactory() {
+  // Remove this factory from the linked list.
+  DCHECK(factory_ == this);
+  factory_ = previous_factory_;
+}
+
+}  // namespace np_utils
diff --git a/gpu/np_utils/np_plugin_object_factory.h b/gpu/np_utils/np_plugin_object_factory.h
new file mode 100644
index 0000000..969f5a3
--- /dev/null
+++ b/gpu/np_utils/np_plugin_object_factory.h
@@ -0,0 +1,37 @@
+// Copyright (c) 2006-2008 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 GPU_NP_UTILS_NP_PLUGIN_OBJECT_FACTORY_H_
+#define GPU_NP_UTILS_NP_PLUGIN_OBJECT_FACTORY_H_
+
+#include "base/basictypes.h"
+#include "gpu/np_utils/np_headers.h"
+
+namespace np_utils {
+
+class PluginObject;
+
+// Mockable factory base class used to create instances of PluginObject based on
+// plugin mime type.
+class NPPluginObjectFactory {
+ public:
+  virtual PluginObject* CreatePluginObject(NPP npp, NPMIMEType plugin_type);
+
+  static NPPluginObjectFactory* get() {
+    return factory_;
+  }
+
+ protected:
+  NPPluginObjectFactory();
+  virtual ~NPPluginObjectFactory();
+
+ private:
+  static NPPluginObjectFactory* factory_;
+  NPPluginObjectFactory* previous_factory_;
+  DISALLOW_COPY_AND_ASSIGN(NPPluginObjectFactory);
+};
+
+}  // namespace np_utils
+
+#endif  // GPU_NP_UTILS_NP_PLUGIN_OBJECT_FACTORY_H_
diff --git a/gpu/np_utils/np_plugin_object_factory_mock.h b/gpu/np_utils/np_plugin_object_factory_mock.h
new file mode 100644
index 0000000..a09205c
--- /dev/null
+++ b/gpu/np_utils/np_plugin_object_factory_mock.h
@@ -0,0 +1,23 @@
+// Copyright (c) 2006-2008 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 GPU_NP_UTILS_NP_PLUGIN_OBJECT_FACTORY_MOCK_H_
+#define GPU_NP_UTILS_NP_PLUGIN_OBJECT_FACTORY_MOCK_H_
+
+#include "gpu/np_utils/np_plugin_object_factory.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace np_utils {
+
+// Mockable factory used to create instances of PluginObject based on plugin
+// mime type.
+class MockPluginObjectFactory : public NPPluginObjectFactory {
+ public:
+  MOCK_METHOD2(CreatePluginObject, PluginObject*(NPP, NPMIMEType));
+};
+
+}  // namespace np_utils
+
+#endif  // GPU_NP_UTILS_NP_PLUGIN_OBJECT_FACTORY_MOCK_H_
diff --git a/gpu/np_utils/np_plugin_object_mock.h b/gpu/np_utils/np_plugin_object_mock.h
new file mode 100644
index 0000000..342b22cd
--- /dev/null
+++ b/gpu/np_utils/np_plugin_object_mock.h
@@ -0,0 +1,26 @@
+// Copyright (c) 2006-2008 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 GPU_NP_UTILS_NP_PLUGIN_OBJECT_MOCK_H_
+#define GPU_NP_UTILS_NP_PLUGIN_OBJECT_MOCK_H_
+
+#include "gpu/np_utils/np_plugin_object.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace np_utils {
+
+class MockPluginObject : public PluginObject {
+ public:
+  MOCK_METHOD5(New, NPError(NPMIMEType, int16, char*[], char*[], NPSavedData*));
+  MOCK_METHOD1(SetWindow, NPError(NPWindow*));
+  MOCK_METHOD1(HandleEvent, int16(NPEvent*));
+  MOCK_METHOD1(Destroy, NPError(NPSavedData**));
+  MOCK_METHOD0(Release, void());
+  MOCK_METHOD0(GetScriptableNPObject, NPObject*());
+};
+
+}  // namespace np_utils
+
+#endif  // GPU_NP_UTILS_NP_PLUGIN_OBJECT_MOCK_H_
diff --git a/gpu/np_utils/np_utils.cc b/gpu/np_utils/np_utils.cc
new file mode 100644
index 0000000..d6a15a4
--- /dev/null
+++ b/gpu/np_utils/np_utils.cc
@@ -0,0 +1,170 @@
+// Copyright (c) 2006-2008 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 "gpu/np_utils/np_utils.h"
+
+namespace np_utils {
+
+bool NPVariantToValue(bool* value, const NPVariant& variant) {
+  if (NPVARIANT_IS_BOOLEAN(variant)) {
+    *value = NPVARIANT_TO_BOOLEAN(variant);
+    return true;
+  }
+
+  return false;
+}
+
+bool NPVariantToValue(int32* value, const NPVariant& variant) {
+  if (NPVARIANT_IS_INT32(variant)) {
+    *value = NPVARIANT_TO_INT32(variant);
+    return true;
+  }
+
+  return false;
+}
+
+bool NPVariantToValue(float* value, const NPVariant& variant) {
+  if (NPVARIANT_IS_DOUBLE(variant)) {
+    *value = static_cast<float>(NPVARIANT_TO_DOUBLE(variant));
+    return true;
+  } else if (NPVARIANT_IS_INT32(variant)) {
+    *value = static_cast<float>(NPVARIANT_TO_INT32(variant));
+    return true;
+  }
+
+  return false;
+}
+
+bool NPVariantToValue(double* value, const NPVariant& variant) {
+  if (NPVARIANT_IS_DOUBLE(variant)) {
+    *value = NPVARIANT_TO_DOUBLE(variant);
+    return true;
+  } else if (NPVARIANT_IS_INT32(variant)) {
+    *value = NPVARIANT_TO_INT32(variant);
+    return true;
+  }
+
+  return false;
+}
+
+bool NPVariantToValue(std::string* value, const NPVariant& variant) {
+  if (NPVARIANT_IS_STRING(variant)) {
+    const NPString& str = NPVARIANT_TO_STRING(variant);
+    *value = std::string(str.UTF8Characters, str.UTF8Length);
+    return true;
+  }
+
+  return false;
+}
+
+void ValueToNPVariant(bool value, NPVariant* variant) {
+  BOOLEAN_TO_NPVARIANT(value, *variant);
+}
+
+void ValueToNPVariant(int32 value, NPVariant* variant) {
+  INT32_TO_NPVARIANT(value, *variant);
+}
+
+void ValueToNPVariant(float value, NPVariant* variant) {
+  DOUBLE_TO_NPVARIANT(value, *variant);
+}
+
+void ValueToNPVariant(double value, NPVariant* variant) {
+  DOUBLE_TO_NPVARIANT(value, *variant);
+}
+
+void ValueToNPVariant(const std::string& value, NPVariant* variant) {
+  NPUTF8* p = static_cast<NPUTF8*>(NPBrowser::get()->MemAlloc(value.length()));
+  memcpy(p, value.c_str(), value.length());
+  STRINGN_TO_NPVARIANT(p, value.length(), *variant);
+}
+
+SmartNPVariant::SmartNPVariant() {
+  VOID_TO_NPVARIANT(*this);
+}
+
+SmartNPVariant::SmartNPVariant(const SmartNPVariant& rhs) {
+  rhs.CopyTo(this);
+}
+
+SmartNPVariant::SmartNPVariant(const NPVariant& rhs) {
+  static_cast<const SmartNPVariant&>(rhs).CopyTo(this);
+}
+
+SmartNPVariant::~SmartNPVariant() {
+  Release();
+}
+
+SmartNPVariant& SmartNPVariant::operator=(const SmartNPVariant& rhs) {
+  Release();
+  rhs.CopyTo(this);
+  return *this;
+}
+
+SmartNPVariant& SmartNPVariant::operator=(const NPVariant& rhs) {
+  Release();
+  static_cast<const SmartNPVariant&>(rhs).CopyTo(this);
+  return *this;
+}
+
+bool SmartNPVariant::IsVoid() const {
+  return NPVARIANT_IS_VOID(*this);
+}
+
+void SmartNPVariant::Release() {
+  NPBrowser::get()->ReleaseVariantValue(this);
+  VOID_TO_NPVARIANT(*this);
+}
+
+void SmartNPVariant::Invalidate() {
+  if (NPVARIANT_IS_OBJECT(*this)) {
+    NULL_TO_NPVARIANT(*this);
+  }
+}
+
+void SmartNPVariant::CopyTo(NPVariant* rhs) const {
+  if (NPVARIANT_IS_OBJECT(*this)) {
+    NPObject* object = NPVARIANT_TO_OBJECT(*this);
+    OBJECT_TO_NPVARIANT(object, *rhs);
+    NPBrowser::get()->RetainObject(object);
+  } else if (NPVARIANT_IS_STRING(*this)) {
+    NPUTF8* copy = static_cast<NPUTF8*>(NPBrowser::get()->MemAlloc(
+        value.stringValue.UTF8Length));
+    memcpy(copy,
+           value.stringValue.UTF8Characters,
+           value.stringValue.UTF8Length);
+    STRINGN_TO_NPVARIANT(copy, value.stringValue.UTF8Length, *rhs);
+  } else {
+    memcpy(rhs, this, sizeof(*rhs));
+  }
+}
+
+bool NPHasMethod(NPP npp,
+                 const NPObjectPointer<NPObject>& object,
+                 const NPUTF8* name) {
+  return NPBrowser::get()->HasMethod(
+      npp,
+      object.Get(),
+      NPBrowser::get()->GetStringIdentifier(name));
+}
+
+bool NPHasProperty(NPP npp,
+                   const NPObjectPointer<NPObject>& object,
+                   const NPUTF8* name) {
+  return NPBrowser::get()->HasProperty(
+      npp,
+      object.Get(),
+      NPBrowser::get()->GetStringIdentifier(name));
+}
+
+bool NPRemoveProperty(NPP npp,
+                      const NPObjectPointer<NPObject>& object,
+                      const NPUTF8* name) {
+  return NPBrowser::get()->RemoveProperty(
+      npp,
+      object.Get(),
+      NPBrowser::get()->GetStringIdentifier(name));
+}
+
+}  // namespace np_utils
diff --git a/gpu/np_utils/np_utils.h b/gpu/np_utils/np_utils.h
new file mode 100644
index 0000000..5c7e3b7
--- /dev/null
+++ b/gpu/np_utils/np_utils.h
@@ -0,0 +1,271 @@
+// Copyright (c) 2006-2008 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 GPU_NP_UTILS_NP_UTILS_H_
+#define GPU_NP_UTILS_NP_UTILS_H_
+
+#include <string>
+
+#include "gpu/np_utils/np_browser.h"
+#include "gpu/np_utils/np_class.h"
+#include "gpu/np_utils/np_object_pointer.h"
+#include "gpu/np_utils/np_headers.h"
+
+namespace np_utils {
+
+// Convert NPVariant to C++ type. Returns whether the conversion was successful.
+bool NPVariantToValue(bool* value, const NPVariant& variant);
+bool NPVariantToValue(int32* value, const NPVariant& variant);
+bool NPVariantToValue(float* value, const NPVariant& variant);
+bool NPVariantToValue(double* value, const NPVariant& variant);
+bool NPVariantToValue(std::string* value, const NPVariant& variant);
+
+template <typename T>
+bool NPVariantToValue(NPObjectPointer<T>* value,
+                      const NPVariant& variant) {
+  if (NPVARIANT_IS_NULL(variant)) {
+    *value = NPObjectPointer<T>();
+    return true;
+  } else if (NPVARIANT_IS_OBJECT(variant)) {
+    NPObject* object = NPVARIANT_TO_OBJECT(variant);
+    if (object->_class == NPGetClass<T>()) {
+      *value = NPObjectPointer<T>(static_cast<T*>(
+          NPVARIANT_TO_OBJECT(variant)));
+      return true;
+    }
+  }
+
+  return false;
+}
+
+// Specialization for NPObject does not check for mismatched NPClass.
+template <>
+inline bool NPVariantToValue(NPObjectPointer<NPObject>* value,
+                             const NPVariant& variant) {
+  if (NPVARIANT_IS_NULL(variant)) {
+    *value = NPObjectPointer<NPObject>();
+    return true;
+  } else if (NPVARIANT_IS_OBJECT(variant)) {
+    *value = NPObjectPointer<NPObject>(NPVARIANT_TO_OBJECT(variant));
+    return true;
+  }
+
+  return false;
+}
+
+// Convert C++ type to NPVariant.
+void ValueToNPVariant(bool value, NPVariant* variant);
+void ValueToNPVariant(int32 value, NPVariant* variant);
+void ValueToNPVariant(float value, NPVariant* variant);
+void ValueToNPVariant(double value, NPVariant* variant);
+void ValueToNPVariant(const std::string& value, NPVariant* variant);
+
+template <typename T>
+void ValueToNPVariant(const NPObjectPointer<T>& value,
+                      NPVariant* variant) {
+  if (value.Get()) {
+    NPBrowser::get()->RetainObject(value.Get());
+    OBJECT_TO_NPVARIANT(value.Get(), *variant);
+  } else {
+    NULL_TO_NPVARIANT(*variant);
+  }
+}
+
+// NPVariant that automatically manages lifetime of string and object variants.
+class SmartNPVariant : public NPVariant {
+ public:
+  SmartNPVariant();
+  SmartNPVariant(const SmartNPVariant& rhs);
+  explicit SmartNPVariant(const NPVariant& rhs);
+
+  template <typename T>
+  explicit SmartNPVariant(const T& v) {
+    ValueToNPVariant(v, this);
+  }
+
+  ~SmartNPVariant();
+
+  SmartNPVariant& operator=(const SmartNPVariant& rhs);
+  SmartNPVariant& operator=(const NPVariant& rhs);
+
+  template <typename T>
+  bool GetValue(T* v) const {
+    return NPVariantToValue(v, *this);
+  }
+
+  bool IsVoid() const;
+
+  template <typename T>
+  void SetValue(const T& v) {
+    Release();
+    ValueToNPVariant(v, this);
+  }
+
+  void CopyTo(NPVariant* target) const;
+
+  // Sets the variant to void.
+  void Release();
+
+  // Called when an NPObject is invalidated to clear any references to other
+  // NPObjects. Does not release the object as it might no longer be valid.
+  void Invalidate();
+};
+
+// These allow a method to be invoked with automatic conversion of C++
+// types to variants for arguments and return values.
+
+bool NPHasMethod(NPP npp,
+                 const NPObjectPointer<NPObject>& object,
+                 const NPUTF8* name);
+
+inline bool NPInvokeVoid(NPP npp,
+                         const NPObjectPointer<NPObject>& object,
+                         const NPUTF8* name) {
+  SmartNPVariant result;
+  return NPBrowser::get()->Invoke(
+      npp,
+      object.Get(),
+      NPBrowser::get()->GetStringIdentifier(name),
+      NULL, 0,
+      &result);
+}
+
+template<typename R>
+bool NPInvoke(NPP npp,
+              const NPObjectPointer<NPObject>& object,
+              const NPUTF8* name,
+              R* r) {
+  SmartNPVariant result;
+  if (NPBrowser::get()->Invoke(
+      npp,
+      object.Get(),
+      NPBrowser::get()->GetStringIdentifier(name),
+      NULL, 0,
+      &result)) {
+    return result.GetValue(r);
+  }
+  return false;
+}
+
+template<typename P0>
+bool NPInvokeVoid(NPP npp,
+                  const NPObjectPointer<NPObject>& object,
+                  const NPUTF8* name,
+                  P0 p0) {
+  SmartNPVariant args[1];
+  args[0].SetValue(p0);
+  SmartNPVariant result;
+  return NPBrowser::get()->Invoke(
+      npp,
+      object.Get(),
+      NPBrowser::get()->GetStringIdentifier(name),
+      &args[0], 1,
+      &result);
+}
+
+template<typename R, typename P0>
+bool NPInvoke(NPP npp,
+              const NPObjectPointer<NPObject>& object,
+              const NPUTF8* name,
+              P0 p0,
+              R* r) {
+  SmartNPVariant args[1];
+  args[0].SetValue(p0);
+  SmartNPVariant result;
+  if (NPBrowser::get()->Invoke(
+      npp,
+      object.Get(),
+      NPBrowser::get()->GetStringIdentifier(name),
+      &args[0], 1,
+      &result)) {
+    return result.GetValue(r);
+  }
+  return false;
+}
+
+template<typename P0, typename P1>
+bool NPInvokeVoid(NPP npp,
+                  const NPObjectPointer<NPObject>& object,
+                  const NPUTF8* name,
+                  P0 p0, P1 p1) {
+  SmartNPVariant args[2];
+  args[0].SetValue(p0);
+  args[1].SetValue(p1);
+  SmartNPVariant result;
+  return NPBrowser::get()->Invoke(
+      npp,
+      object.Get(),
+      NPBrowser::get()->GetStringIdentifier(name),
+      &args[0], 2,
+      &result);
+}
+
+template<typename R, typename P0, typename P1>
+bool NPInvoke(NPP npp,
+              const NPObjectPointer<NPObject>& object,
+              const NPUTF8* name,
+              P0 p0, P1 p1,
+              R* r) {
+  SmartNPVariant args[2];
+  args[0].SetValue(p0);
+  args[1].SetValue(p1);
+  SmartNPVariant result;
+  if (NPBrowser::get()->Invoke(
+      npp,
+      object.Get(),
+      NPBrowser::get()->GetStringIdentifier(name),
+      &args[0], 2,
+      &result)) {
+    return result.GetValue(r);
+  }
+  return false;
+}
+
+bool NPHasProperty(NPP npp,
+                   const NPObjectPointer<NPObject>& object,
+                   const NPUTF8* name);
+
+template <typename T>
+bool NPGetProperty(NPP npp,
+                   const NPObjectPointer<NPObject>& object,
+                   const NPUTF8* name,
+                   T* value) {
+  SmartNPVariant result;
+  if (NPBrowser::get()->GetProperty(npp,
+                                    object.Get(),
+                                    NPBrowser::get()->GetStringIdentifier(name),
+                                    &result)) {
+    return result.GetValue(value);
+  }
+  return false;
+}
+
+template <typename T>
+bool NPSetProperty(NPP npp,
+                   const NPObjectPointer<NPObject>& object,
+                   const NPUTF8* name,
+                   const T& value) {
+  SmartNPVariant variant(value);
+  return NPBrowser::get()->SetProperty(
+      npp,
+      object.Get(),
+      NPBrowser::get()->GetStringIdentifier(name),
+      &variant);
+}
+
+bool NPRemoveProperty(NPP npp,
+                      const NPObjectPointer<NPObject>& object,
+                      const NPUTF8* name);
+
+template <typename NPObjectType>
+NPObjectPointer<NPObjectType> NPCreateObject(NPP npp) {
+  const NPClass* np_class = NPGetClass<NPObjectType>();
+  NPObjectType* object = static_cast<NPObjectType*>(
+      NPBrowser::get()->CreateObject(npp, np_class));
+  return NPObjectPointer<NPObjectType>::FromReturned(object);
+}
+
+}  // namespace np_utils
+
+#endif  // GPU_NP_UTILS_NP_UTILS_H_
diff --git a/gpu/np_utils/np_utils_unittest.cc b/gpu/np_utils/np_utils_unittest.cc
new file mode 100644
index 0000000..ceb87ad
--- /dev/null
+++ b/gpu/np_utils/np_utils_unittest.cc
@@ -0,0 +1,424 @@
+// Copyright (c) 2006-2008 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 "gpu/np_utils/np_object_mock.h"
+#include "gpu/np_utils/np_browser_stub.h"
+#include "gpu/np_utils/np_utils.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using testing::_;
+using testing::DoAll;
+using testing::MakeMatcher;
+using testing::Matcher;
+using testing::Pointee;
+using testing::Return;
+using testing::SetArgumentPointee;
+using testing::StrictMock;
+
+namespace np_utils {
+
+class NPUtilsTest : public testing::Test {
+ protected:
+  StubNPBrowser stub_browser_;
+  NPP_t npp_;
+  NPVariant variant_;
+};
+
+TEST_F(NPUtilsTest, TestBoolNPVariantToValue) {
+  bool v;
+
+  BOOLEAN_TO_NPVARIANT(false, variant_);
+  EXPECT_TRUE(NPVariantToValue(&v, variant_));
+  EXPECT_FALSE(v);
+
+  BOOLEAN_TO_NPVARIANT(true, variant_);
+  EXPECT_TRUE(NPVariantToValue(&v, variant_));
+  EXPECT_TRUE(v);
+
+  INT32_TO_NPVARIANT(7, variant_);
+  EXPECT_FALSE(NPVariantToValue(&v, variant_));
+}
+
+TEST_F(NPUtilsTest, TestIntNPVariantToValue) {
+  INT32_TO_NPVARIANT(7, variant_);
+
+  int v1;
+  EXPECT_TRUE(NPVariantToValue(&v1, variant_));
+  EXPECT_EQ(7, v1);
+
+  float v2;
+  EXPECT_TRUE(NPVariantToValue(&v2, variant_));
+  EXPECT_EQ(7.0f, v2);
+
+  double v3;
+  EXPECT_TRUE(NPVariantToValue(&v3, variant_));
+  EXPECT_EQ(7.0, v3);
+
+  BOOLEAN_TO_NPVARIANT(false, variant_);
+  EXPECT_FALSE(NPVariantToValue(&v1, variant_));
+}
+
+TEST_F(NPUtilsTest, TestFloatNPVariantToValue) {
+  float v;
+
+  DOUBLE_TO_NPVARIANT(7.0, variant_);
+  EXPECT_TRUE(NPVariantToValue(&v, variant_));
+  EXPECT_EQ(7.0f, v);
+
+  BOOLEAN_TO_NPVARIANT(false, variant_);
+  EXPECT_FALSE(NPVariantToValue(&v, variant_));
+}
+
+TEST_F(NPUtilsTest, TestDoubleNPVariantToValue) {
+  double v;
+
+  DOUBLE_TO_NPVARIANT(7.0, variant_);
+  EXPECT_TRUE(NPVariantToValue(&v, variant_));
+  EXPECT_EQ(7.0, v);
+
+  BOOLEAN_TO_NPVARIANT(false, variant_);
+  EXPECT_FALSE(NPVariantToValue(&v, variant_));
+}
+
+TEST_F(NPUtilsTest, TestStringNPVariantToValue) {
+  std::string v;
+
+  STRINGZ_TO_NPVARIANT("hello", variant_);
+  EXPECT_TRUE(NPVariantToValue(&v, variant_));
+  EXPECT_EQ(std::string("hello"), v);
+
+  BOOLEAN_TO_NPVARIANT(false, variant_);
+  EXPECT_FALSE(NPVariantToValue(&v, variant_));
+}
+
+TEST_F(NPUtilsTest, TestObjectNPVariantToValue) {
+  NPObjectPointer<NPObject> object =
+      NPCreateObject<StrictMock<MockNPObject> >(NULL);
+  NPObjectPointer<NPObject> v;
+
+  OBJECT_TO_NPVARIANT(object.Get(), variant_);
+  EXPECT_TRUE(NPVariantToValue(&v, variant_));
+  EXPECT_EQ(object, v);
+
+  BOOLEAN_TO_NPVARIANT(false, variant_);
+  EXPECT_FALSE(NPVariantToValue(&v, variant_));
+}
+
+TEST_F(NPUtilsTest, TestNullNPVariantToValue) {
+  NPObjectPointer<NPObject> v;
+
+  NULL_TO_NPVARIANT(variant_);
+  EXPECT_TRUE(NPVariantToValue(&v, variant_));
+  EXPECT_TRUE(NPObjectPointer<NPObject>() == v);
+
+  BOOLEAN_TO_NPVARIANT(false, variant_);
+  EXPECT_FALSE(NPVariantToValue(&v, variant_));
+}
+
+TEST_F(NPUtilsTest, TestDerivedObjectNPVariantToValue) {
+  NPObjectPointer<NPObject> object =
+      NPCreateObject<StrictMock<MockNPObject> >(NULL);
+  NPObjectPointer<StrictMock<MockNPObject> > v;
+
+  OBJECT_TO_NPVARIANT(object.Get(), variant_);
+  EXPECT_TRUE(NPVariantToValue(&v, variant_));
+  EXPECT_EQ(object, v);
+}
+
+TEST_F(NPUtilsTest,
+    TestDerivedObjectNPVariantToValueFailsIfValueHasDifferentType) {
+  NPObjectPointer<NPObject> object =
+      NPCreateObject<StrictMock<MockNPObject> >(NULL);
+  NPObjectPointer<MockNPObject> v;
+
+  OBJECT_TO_NPVARIANT(object.Get(), variant_);
+  EXPECT_FALSE(NPVariantToValue(&v, variant_));
+}
+
+TEST_F(NPUtilsTest, TestBoolValueToNPVariant) {
+  ValueToNPVariant(true, &variant_);
+  EXPECT_TRUE(NPVARIANT_IS_BOOLEAN(variant_));
+  EXPECT_TRUE(NPVARIANT_TO_BOOLEAN(variant_));
+
+  ValueToNPVariant(false, &variant_);
+  EXPECT_TRUE(NPVARIANT_IS_BOOLEAN(variant_));
+  EXPECT_FALSE(NPVARIANT_TO_BOOLEAN(variant_));
+}
+
+TEST_F(NPUtilsTest, TestIntValueToNPVariant) {
+  ValueToNPVariant(7, &variant_);
+  EXPECT_TRUE(NPVARIANT_IS_INT32(variant_));
+  EXPECT_EQ(7, NPVARIANT_TO_INT32(variant_));
+}
+
+TEST_F(NPUtilsTest, TestFloatValueToNPVariant) {
+  ValueToNPVariant(7.0f, &variant_);
+  EXPECT_TRUE(NPVARIANT_IS_DOUBLE(variant_));
+  EXPECT_EQ(7.0, NPVARIANT_TO_DOUBLE(variant_));
+}
+
+TEST_F(NPUtilsTest, TestDoubleValueToNPVariant) {
+  ValueToNPVariant(7.0, &variant_);
+  EXPECT_TRUE(NPVARIANT_IS_DOUBLE(variant_));
+  EXPECT_EQ(7.0, NPVARIANT_TO_DOUBLE(variant_));
+}
+
+TEST_F(NPUtilsTest, TestStringValueToNPVariant) {
+  ValueToNPVariant(std::string("hello"), &variant_);
+  EXPECT_TRUE(NPVARIANT_IS_STRING(variant_));
+  EXPECT_EQ(std::string("hello"),
+            std::string(variant_.value.stringValue.UTF8Characters,
+                        variant_.value.stringValue.UTF8Length));
+}
+
+TEST_F(NPUtilsTest, TestObjectValueToNPVariant) {
+  NPObjectPointer<NPObject> object =
+      NPCreateObject<StrictMock<MockNPObject> >(NULL);
+
+  ValueToNPVariant(object, &variant_);
+  EXPECT_TRUE(NPVARIANT_IS_OBJECT(variant_));
+  EXPECT_EQ(object.Get(), NPVARIANT_TO_OBJECT(variant_));
+
+  NPBrowser::get()->ReleaseVariantValue(&variant_);
+}
+
+TEST_F(NPUtilsTest, TestNullValueToNPVariant) {
+  ValueToNPVariant(NPObjectPointer<NPObject>(), &variant_);
+  EXPECT_TRUE(NPVARIANT_IS_NULL(variant_));
+}
+
+TEST_F(NPUtilsTest, CanCopyObjectSmartVariant) {
+  NPObjectPointer<NPObject> object =
+      NPCreateObject<StrictMock<MockNPObject> >(NULL);
+  EXPECT_EQ(1, object->referenceCount);
+  {
+    SmartNPVariant v1(object);
+    EXPECT_EQ(2, object->referenceCount);
+    {
+      SmartNPVariant v2(v1);
+      EXPECT_EQ(3, object->referenceCount);
+    }
+    EXPECT_EQ(2, object->referenceCount);
+  }
+  EXPECT_EQ(1, object->referenceCount);
+}
+
+TEST_F(NPUtilsTest, CanCopyStringSmartVariant) {
+  SmartNPVariant v1(std::string("hello"));
+  SmartNPVariant v2(v1);
+  std::string r;
+  EXPECT_TRUE(NPVariantToValue(&r, v2));
+  EXPECT_EQ(std::string("hello"), r);
+  EXPECT_NE(v1.value.stringValue.UTF8Characters,
+            v2.value.stringValue.UTF8Characters);
+}
+
+TEST_F(NPUtilsTest, CanReleaseSmartVariant) {
+  SmartNPVariant variant(std::string("hello"));
+  EXPECT_FALSE(variant.IsVoid());
+  variant.Release();
+  EXPECT_TRUE(variant.IsVoid());
+}
+
+template <typename T>
+class VariantMatcher : public testing::MatcherInterface<const NPVariant&> {
+ public:
+  explicit VariantMatcher(const T& value) : value_(value) {
+  }
+
+  virtual bool Matches(const NPVariant& variant) const {
+    T other_value;
+    return NPVariantToValue(&other_value, variant) && other_value == value_;
+  }
+
+  virtual void DescribeTo(::std::ostream* os) const {
+    *os << "equals " << value_;
+  }
+
+  virtual void DescribeNegationTo(::std::ostream* os) const {
+    *os << "does not equal " << value_;
+  }
+
+ private:
+  T value_;
+};
+
+template <typename T>
+Matcher<const NPVariant&> VariantMatches(const T& value) {
+  return MakeMatcher(new VariantMatcher<T>(value));
+}
+
+TEST_F(NPUtilsTest, CanDetermineIfObjectHasMethod) {
+  NPIdentifier name = NPBrowser::get()->GetStringIdentifier("foo");
+  NPObjectPointer<MockNPObject> object =
+      NPCreateObject<StrictMock<MockNPObject> >(NULL);
+
+  EXPECT_CALL(*object, HasMethod(name))
+    .WillOnce(Return(true));
+
+  EXPECT_TRUE(NPHasMethod(NULL, object, "foo"));
+}
+
+TEST_F(NPUtilsTest, CanInvokeVoidMethodWithNativeTypes) {
+  NPIdentifier name = NPBrowser::get()->GetStringIdentifier("foo");
+  NPObjectPointer<MockNPObject> object =
+      NPCreateObject<StrictMock<MockNPObject> >(NULL);
+
+  VOID_TO_NPVARIANT(variant_);
+
+  EXPECT_CALL(*object, Invoke(name, Pointee(VariantMatches<int32>(7)), 1, _))
+    .WillOnce(DoAll(SetArgumentPointee<3>(variant_),
+                    Return(true)));
+
+  EXPECT_TRUE(NPInvokeVoid(NULL, object, "foo", 7));
+}
+
+TEST_F(NPUtilsTest, InvokeVoidMethodCanFail) {
+  NPIdentifier name = NPBrowser::get()->GetStringIdentifier("foo");
+  NPObjectPointer<MockNPObject> object =
+      NPCreateObject<StrictMock<MockNPObject> >(NULL);
+
+  VOID_TO_NPVARIANT(variant_);
+
+  EXPECT_CALL(*object, Invoke(name, Pointee(VariantMatches<int32>(7)), 1, _))
+    .WillOnce(DoAll(SetArgumentPointee<3>(variant_),
+                    Return(false)));
+
+  EXPECT_FALSE(NPInvokeVoid(NULL, object, "foo", 7));
+}
+
+TEST_F(NPUtilsTest, CanInvokeNonVoidMethodWithNativeTypes) {
+  NPIdentifier name = NPBrowser::get()->GetStringIdentifier("foo");
+  NPObjectPointer<MockNPObject> object =
+      NPCreateObject<StrictMock<MockNPObject> >(NULL);
+
+  DOUBLE_TO_NPVARIANT(1.5, variant_);
+
+  EXPECT_CALL(*object, Invoke(name, Pointee(VariantMatches<int32>(7)), 1, _))
+    .WillOnce(DoAll(SetArgumentPointee<3>(variant_),
+                    Return(true)));
+
+  double r;
+  EXPECT_TRUE(NPInvoke(NULL, object, "foo", 7, &r));
+  EXPECT_EQ(1.5, r);
+}
+
+TEST_F(NPUtilsTest, InvokeNonVoidMethodCanFail) {
+  NPIdentifier name = NPBrowser::get()->GetStringIdentifier("foo");
+  NPObjectPointer<MockNPObject> object =
+      NPCreateObject<StrictMock<MockNPObject> >(NULL);
+
+  DOUBLE_TO_NPVARIANT(1.5, variant_);
+
+  EXPECT_CALL(*object, Invoke(name, Pointee(VariantMatches<int32>(7)), 1, _))
+    .WillOnce(DoAll(SetArgumentPointee<3>(variant_),
+                    Return(false)));
+
+  double r;
+  EXPECT_FALSE(NPInvoke(NULL, object, "foo", 7, &r));
+}
+
+TEST_F(NPUtilsTest, InvokeNonVoidMethodFailsIfResultIsIncompatible) {
+  NPIdentifier name = NPBrowser::get()->GetStringIdentifier("foo");
+  NPObjectPointer<MockNPObject> object =
+      NPCreateObject<StrictMock<MockNPObject> >(NULL);
+
+  DOUBLE_TO_NPVARIANT(1.5, variant_);
+
+  EXPECT_CALL(*object, Invoke(name, Pointee(VariantMatches<int32>(7)), 1, _))
+    .WillOnce(DoAll(SetArgumentPointee<3>(variant_),
+                    Return(true)));
+
+  int r;
+  EXPECT_FALSE(NPInvoke(NULL, object, "foo", 7, &r));
+}
+
+TEST_F(NPUtilsTest, CanDetermineIfObjectHasProperty) {
+  NPIdentifier name = NPBrowser::get()->GetStringIdentifier("foo");
+  NPObjectPointer<MockNPObject> object =
+      NPCreateObject<StrictMock<MockNPObject> >(NULL);
+
+  EXPECT_CALL(*object, HasProperty(name))
+    .WillOnce(Return(true));
+
+  EXPECT_TRUE(NPHasProperty(NULL, object, "foo"));
+}
+
+TEST_F(NPUtilsTest, CanGetPropertyValue) {
+  NPIdentifier name = NPBrowser::get()->GetStringIdentifier("foo");
+  NPObjectPointer<MockNPObject> object =
+      NPCreateObject<StrictMock<MockNPObject> >(NULL);
+
+  DOUBLE_TO_NPVARIANT(1.5, variant_);
+
+  EXPECT_CALL(*object, GetProperty(name, _))
+    .WillOnce(DoAll(SetArgumentPointee<1>(variant_),
+                    Return(true)));
+
+  double r;
+  EXPECT_TRUE(NPGetProperty(NULL, object, "foo", &r));
+}
+
+TEST_F(NPUtilsTest, NPGetPropertyReportsFailureIfResultTypeIsDifferent) {
+  NPIdentifier name = NPBrowser::get()->GetStringIdentifier("foo");
+  NPObjectPointer<MockNPObject> object =
+      NPCreateObject<StrictMock<MockNPObject> >(NULL);
+
+  DOUBLE_TO_NPVARIANT(1.5, variant_);
+
+  EXPECT_CALL(*object, GetProperty(name, _))
+    .WillOnce(DoAll(SetArgumentPointee<1>(variant_),
+                    Return(true)));
+
+  bool r;
+  EXPECT_FALSE(NPGetProperty(NULL, object, "foo", &r));
+}
+
+TEST_F(NPUtilsTest, NPGetPropertyReportsFailureFromGetProperty) {
+  NPIdentifier name = NPBrowser::get()->GetStringIdentifier("foo");
+  NPObjectPointer<MockNPObject> object =
+      NPCreateObject<StrictMock<MockNPObject> >(NULL);
+
+  EXPECT_CALL(*object, GetProperty(name, _))
+    .WillOnce(Return(false));
+
+  double r;
+  EXPECT_FALSE(NPGetProperty(NULL, object, "foo", &r));
+}
+
+TEST_F(NPUtilsTest, CanSetPropertyValue) {
+  NPIdentifier name = NPBrowser::get()->GetStringIdentifier("foo");
+  NPObjectPointer<MockNPObject> object =
+      NPCreateObject<StrictMock<MockNPObject> >(NULL);
+
+  EXPECT_CALL(*object, SetProperty(name, Pointee(VariantMatches(1.5))))
+    .WillOnce(Return(true));
+
+  EXPECT_TRUE(NPSetProperty(NULL, object, "foo", 1.5));
+}
+
+TEST_F(NPUtilsTest, NPSetPropertyReportsFailureFromSetProperty) {
+  NPIdentifier name = NPBrowser::get()->GetStringIdentifier("foo");
+  NPObjectPointer<MockNPObject> object =
+      NPCreateObject<StrictMock<MockNPObject> >(NULL);
+
+  EXPECT_CALL(*object, SetProperty(name, Pointee(VariantMatches(1.5))))
+    .WillOnce(Return(false));
+
+  EXPECT_FALSE(NPSetProperty(NULL, object, "foo", 1.5));
+}
+
+TEST_F(NPUtilsTest, CanRemovePropertyValue) {
+  NPIdentifier name = NPBrowser::get()->GetStringIdentifier("foo");
+  NPObjectPointer<MockNPObject> object =
+      NPCreateObject<StrictMock<MockNPObject> >(NULL);
+
+  EXPECT_CALL(*object, RemoveProperty(name))
+    .WillOnce(Return(true));
+
+  EXPECT_TRUE(NPRemoveProperty(NULL, object, "foo"));
+}
+
+}  // namespace np_utils
diff --git a/gpu/np_utils/webkit_browser.h b/gpu/np_utils/webkit_browser.h
new file mode 100644
index 0000000..6b57d05
--- /dev/null
+++ b/gpu/np_utils/webkit_browser.h
@@ -0,0 +1,117 @@
+// Copyright (c) 2006-2008 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 GPU_NP_UTILS_WEBKIT_BROWSER_H_
+#define GPU_NP_UTILS_WEBKIT_BROWSER_H_
+
+// TODO(apatrick): This does not belong in np_utils. np_utils should not be
+//    dependent on WebKit (and it isn't - that's why the member functions are
+//    inline).
+
+#include <stdlib.h>
+
+#include "gpu/np_utils/np_browser.h"
+#include "WebKit/api/public/WebBindings.h"
+
+typedef struct _NPNetscapeFuncs NPNetscapeFuncs;
+typedef struct _NPChromiumFuncs NPChromiumFuncs;
+
+namespace np_utils {
+
+// This class implements NPBrowser for the WebKit WebBindings.
+class WebKitBrowser : public NPBrowser {
+ public:
+  WebKitBrowser(): NPBrowser(NULL) {
+  }
+
+  // Standard functions from NPNetscapeFuncs.
+
+  virtual NPIdentifier GetStringIdentifier(const NPUTF8* name) {
+    return WebKit::WebBindings::getStringIdentifier(name);
+  }
+
+  virtual void* MemAlloc(size_t size) {
+    return malloc(size);
+  }
+
+  virtual void MemFree(void* p) {
+    free(p);
+  }
+
+  virtual NPObject* CreateObject(NPP npp, const NPClass* cl) {
+    return WebKit::WebBindings::createObject(npp, const_cast<NPClass*>(cl));
+  }
+
+  virtual NPObject* RetainObject(NPObject* object) {
+    return WebKit::WebBindings::retainObject(object);
+  }
+
+  virtual void ReleaseObject(NPObject* object) {
+    WebKit::WebBindings::releaseObject(object);
+  }
+
+  virtual void ReleaseVariantValue(NPVariant* variant) {
+    WebKit::WebBindings::releaseVariantValue(variant);
+  }
+
+  virtual bool HasProperty(NPP npp,
+                           NPObject* object,
+                           NPIdentifier name) {
+    return WebKit::WebBindings::hasProperty(npp, object, name);
+  }
+
+  virtual bool GetProperty(NPP npp,
+                           NPObject* object,
+                           NPIdentifier name,
+                           NPVariant* result) {
+    return WebKit::WebBindings::getProperty(npp, object, name, result);
+  }
+
+  virtual bool SetProperty(NPP npp,
+                           NPObject* object,
+                           NPIdentifier name,
+                           const NPVariant* result) {
+    return WebKit::WebBindings::setProperty(npp, object, name, result);
+  }
+
+  virtual bool RemoveProperty(NPP npp,
+                              NPObject* object,
+                              NPIdentifier name) {
+    return WebKit::WebBindings::removeProperty(npp, object, name);
+  }
+
+  virtual bool HasMethod(NPP npp,
+                           NPObject* object,
+                           NPIdentifier name) {
+    return WebKit::WebBindings::hasMethod(npp, object, name);
+  }
+
+  virtual bool Invoke(NPP npp,
+                      NPObject* object,
+                      NPIdentifier name,
+                      const NPVariant* args,
+                      uint32_t num_args,
+                      NPVariant* result) {
+    return WebKit::WebBindings::invoke(npp, object, name, args, num_args,
+                                       result);
+  }
+
+  virtual NPObject* GetWindowNPObject(NPP npp) {
+    NPObject* window;
+    if (NPERR_NO_ERROR == NPN_GetValue(npp,
+                                       NPNVWindowNPObject,
+                                       &window)) {
+      return window;
+    } else {
+      return NULL;
+    }
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(WebKitBrowser);
+};
+
+}  // namespace np_utils
+
+#endif  // GPU_NP_UTILS_WEBKIT_BROWSER_H_