Merged in recent changes to command buffer code.
TEST=none
BUG=none

Review URL: http://codereview.chromium.org/434063

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@33095 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 159c5c5..d6f2aba 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -43,11 +43,11 @@
 // Checks if there is enough immediate data.
 template<typename T>
 bool CheckImmediateDataSize(
-    unsigned int arg_count,
+    uint32 immediate_data_size,
     GLuint count,
     size_t size,
     unsigned int elements_per_unit) {
-  return ImmediateDataSize<T>(arg_count) == count * size * elements_per_unit;
+  return immediate_data_size == count * size * elements_per_unit;
 }
 
 // A struct to hold info about each command.
@@ -149,12 +149,16 @@
 
 }  // anonymous namespace.
 
+#if defined(OS_LINUX)
 GLES2Decoder::GLES2Decoder()
-#ifdef OS_LINUX
-    : window_(NULL) {
-#endif
-#ifdef OS_WIN
-    : hwnd_(NULL) {
+    : debug_(false),
+      window_(NULL) {
+#elif defined(OS_WIN)
+GLES2Decoder::GLES2Decoder()
+    : debug_(false),
+      hwnd_(NULL) {
+#else
+GLES2Decoder::GLES2Decoder() {
 #endif
 }
 
@@ -311,7 +315,7 @@
   // typesafe way.
   #define GLES2_CMD_OP(name) \
      ParseError Handle ## name(             \
-       unsigned int arg_count,              \
+       uint32 immediate_data_size,          \
        const gles2::name& args);            \
 
   GLES2_COMMAND_LIST(GLES2_CMD_OP)
@@ -669,28 +673,44 @@
     unsigned int command,
     unsigned int arg_count,
     const void* cmd_data) {
+  parse_error::ParseError result;
+  if (debug()) {
+    // TODO(gman): Change output to something useful for NaCl.
+    const char* f = GetCommandName(command);
+    printf("cmd: %s\n", GetCommandName(command));
+  }
   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)) {
+      uint32 immediate_data_size =
+          (arg_count - info_arg_count) * sizeof(CommandBufferEntry);  // NOLINT
       switch (command) {
         #define GLES2_CMD_OP(name)                                 \
           case name::kCmdId:                                       \
-            return Handle ## name(                                 \
-                arg_count,                                         \
+            result = Handle ## name(                               \
+                immediate_data_size,                               \
                 *static_cast<const name*>(cmd_data));              \
+            break;                                                 \
 
         GLES2_COMMAND_LIST(GLES2_CMD_OP)
-
         #undef GLES2_CMD_OP
+        if (debug()) {
+          if (glGetError() != 0) {
+            // TODO(gman): Change output to something useful for NaCl.
+            printf("GL ERROR b4: %s\n", GetCommandName(command));
+          }
+        }
       }
     } else {
-      return parse_error::kParseInvalidArguments;
+      result = parse_error::kParseInvalidArguments;
     }
+  } else {
+    result = DoCommonCommand(command, arg_count, cmd_data);
   }
-  return DoCommonCommand(command, arg_count, cmd_data);
+  return result;
 }
 
 }  // namespace gles2
@@ -786,7 +806,7 @@
 }
 
 parse_error::ParseError GLES2DecoderImpl::HandleDrawElements(
-    unsigned int arg_count, const gles2::DrawElements& c) {
+    uint32 immediate_data_size, const gles2::DrawElements& c) {
   if (bound_element_array_buffer_ != 0) {
     GLenum mode = c.mode;
     GLsizei count = c.count;
@@ -831,14 +851,21 @@
 }  // anonymous namespace.
 
 parse_error::ParseError GLES2DecoderImpl::HandleShaderSource(
-    unsigned int arg_count, const gles2::ShaderSource& c) {
-  GLuint shader = c.shader;
+    uint32 immediate_data_size, const gles2::ShaderSource& c) {
+  GLuint shader;
+  if (!id_map_.GetServiceId(c.shader, &shader)) {
+    SetGLError(GL_INVALID_VALUE);
+    return parse_error::kParseNoError;
+  }
   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);
+      // TODO(gman): Manually implement validation.
+      ValidateShaderSource(
+          this, immediate_data_size, shader, count, data,
+          reinterpret_cast<const GLint*>(1));
   if (result != parse_error::kParseNoError) {
     return result;
   }
@@ -847,15 +874,19 @@
 }
 
 parse_error::ParseError GLES2DecoderImpl::HandleShaderSourceImmediate(
-  unsigned int arg_count, const gles2::ShaderSourceImmediate& c) {
-  GLuint shader = c.shader;
+  uint32 immediate_data_size, const gles2::ShaderSourceImmediate& c) {
+  GLuint shader;
+  if (!id_map_.GetServiceId(c.shader, &shader)) {
+    SetGLError(GL_INVALID_VALUE);
+    return parse_error::kParseNoError;
+  }
   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);
+          this, immediate_data_size, shader, count, data, NULL);
   if (result != parse_error::kParseNoError) {
     return result;
   }
@@ -864,7 +895,7 @@
 }
 
 parse_error::ParseError GLES2DecoderImpl::HandleVertexAttribPointer(
-    unsigned int arg_count, const gles2::VertexAttribPointer& c) {
+    uint32 immediate_data_size, const gles2::VertexAttribPointer& c) {
   if (bound_array_buffer_ != 0) {
     GLuint indx = c.indx;
     GLint size = c.size;
@@ -873,9 +904,11 @@
     GLsizei stride = c.stride;
     GLuint offset = c.offset;
     const void* ptr = reinterpret_cast<const void*>(c.offset);
+    // TODO(gman): Do manual validation.
     parse_error::ParseError result =
         ValidateVertexAttribPointer(
-            this, arg_count, indx, size, type, normalized, stride, ptr);
+            this, immediate_data_size, indx, size, type, normalized, stride,
+            reinterpret_cast<const void*>(1));
     if (result != parse_error::kParseNoError) {
       return result;
     }
@@ -887,55 +920,308 @@
 }
 
 parse_error::ParseError GLES2DecoderImpl::HandleReadPixels(
-    unsigned int arg_count, const gles2::ReadPixels& c) {
+    uint32 immediate_data_size, 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.
+    uint32 immediate_data_size, const gles2::PixelStorei& c) {
+  GLenum pname = c.pname;
+  GLenum param = c.param;
+  parse_error::ParseError result =
+    ValidatePixelStorei(this, immediate_data_size, pname, param);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glPixelStorei(pname, param);
+  switch (pname) {
+  case GL_PACK_ALIGNMENT:
+      pack_alignment_ = param;
+      break;
+  case GL_UNPACK_ALIGNMENT:
+      unpack_alignment_ = param;
+      break;
+  default:
+      // Validation should have prevented us from getting here.
+      DCHECK(false);
+      break;
+  }
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetAttribLocation(
+    uint32 immediate_data_size, 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);
+  GLint* location = GetSharedMemoryAs<GLint*>(
+      c.location_shm_id, c.location_shm_offset, sizeof(GLint));
+  if (!location || !name) {
+    return parse_error::kParseOutOfBounds;
+  }
+  String name_str(name, name_size);
+  *location = glGetAttribLocation(program, name_str.c_str());
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetAttribLocationImmediate(
+    uint32 immediate_data_size, 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.
+  GLint* location = GetSharedMemoryAs<GLint*>(
+      c.location_shm_id, c.location_shm_offset, sizeof(GLint));
+  if (!location || !name) {
+    return parse_error::kParseOutOfBounds;
+  }
+  String name_str(name, name_size);
+  *location = glGetAttribLocation(program, name_str.c_str());
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetUniformLocation(
+    uint32 immediate_data_size, 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);
+  GLint* location = GetSharedMemoryAs<GLint*>(
+      c.location_shm_id, c.location_shm_offset, sizeof(GLint));
+  if (!location || !name) {
+    return parse_error::kParseOutOfBounds;
+  }
+  String name_str(name, name_size);
+  *location = glGetUniformLocation(program, name_str.c_str());
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetUniformLocationImmediate(
+    uint32 immediate_data_size, 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.
+  GLint* location = GetSharedMemoryAs<GLint*>(
+      c.location_shm_id, c.location_shm_offset, sizeof(GLint));
+  if (!location || !name) {
+    return parse_error::kParseOutOfBounds;
+  }
+  String name_str(name, name_size);
+  *location = glGetUniformLocation(program, name_str.c_str());
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleBufferData(
+    uint32 immediate_data_size, 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);
+  const void* data = NULL;
+  if (data_shm_id != 0 || data_shm_offset != 0) {
+    data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
+    parse_error::ParseError result =
+        ValidateBufferData(this, immediate_data_size, target, size, data,
+                           usage);
+    if (result != parse_error::kParseNoError) {
+      return result;
+    }
+  }
+  // TODO(gman): Validate case where data is NULL.
+  glBufferData(target, size, data, usage);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleBufferDataImmediate(
+    uint32 immediate_data_size, 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.
+  // TODO(gman): Handle case where data is NULL.
+  parse_error::ParseError result =
+      ValidateBufferDataImmediate(this, immediate_data_size, target, size, data,
+                                  usage);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glBufferData(target, size, data, usage);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleCompressedTexImage2D(
+    uint32 immediate_data_size, const gles2::CompressedTexImage2D& c) {
+  GLenum target = static_cast<GLenum>(c.target);
+  GLint level = static_cast<GLint>(c.level);
+  GLenum internal_format = 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 image_size = 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);
+  const void* data = NULL;
+  if (data_shm_id != 0 || data_shm_offset != 0) {
+    data = GetSharedMemoryAs<const void*>(
+        data_shm_id, data_shm_offset, image_size);
+    parse_error::ParseError result =
+        ValidateCompressedTexImage2D(
+            this, immediate_data_size, target, level, internal_format, width,
+            height, border, image_size, data);
+    if (result != parse_error::kParseNoError) {
+      return result;
+    }
+  }
+  // TODO(gman): Validate case where data is NULL.
+  glCompressedTexImage2D(
+      target, level, internal_format, width, height, border, image_size, data);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleCompressedTexImage2DImmediate(
+    uint32 immediate_data_size, const gles2::CompressedTexImage2DImmediate& c) {
+  GLenum target = static_cast<GLenum>(c.target);
+  GLint level = static_cast<GLint>(c.level);
+  GLenum internal_format = 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 image_size = static_cast<GLsizei>(c.imageSize);
+  const void* data = GetImmediateDataAs<const void*>(c);
+  // Immediate version.
+  // TODO(gman): Handle case where data is NULL.
+  parse_error::ParseError result =
+      ValidateCompressedTexImage2DImmediate(
+          this, immediate_data_size, target, level, internal_format, width,
+          height, border, image_size, data);
+  if (result != parse_error::kParseNoError) {
+    return result;
+  }
+  glCompressedTexImage2D(
+      target, level, internal_format, width, height, border, image_size, data);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleTexImage2D(
+    uint32 immediate_data_size, const gles2::TexImage2D& c) {
+  GLenum target = static_cast<GLenum>(c.target);
+  GLint level = static_cast<GLint>(c.level);
+  GLint internal_format = 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 = NULL;
+  if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
+    pixels = GetSharedMemoryAs<const void*>(
+        pixels_shm_id, pixels_shm_offset, pixels_size);
+    parse_error::ParseError result =
+        ValidateTexImage2D(
+            this, immediate_data_size, target, level, internal_format, width,
+            height, border, format, type, pixels);
+    if (result != parse_error::kParseNoError) {
+      return result;
+    }
+  }
+  // TODO(gman): Validate case where data is NULL.
+  glTexImage2D(
+      target, level, internal_format, width, height, border, format, type,
+      pixels);
+  return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleTexImage2DImmediate(
+    uint32 immediate_data_size, 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.
+  // TODO(gman): Handle case where data is NULL.
+  parse_error::ParseError result =
+      ValidateTexImage2DImmediate(
+          this, immediate_data_size, 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::HandleGetVertexAttribPointerv(
-    unsigned int arg_count, const gles2::GetVertexAttribPointerv& c) {
+    uint32 immediate_data_size, const gles2::GetVertexAttribPointerv& c) {
   // TODO(gman): Implement.
   return parse_error::kParseNoError;
 }
 
 parse_error::ParseError GLES2DecoderImpl::HandleGetUniformiv(
-    unsigned int arg_count, const gles2::GetUniformiv& c) {
+    uint32 immediate_data_size, const gles2::GetUniformiv& c) {
   // TODO(gman): Implement.
   return parse_error::kParseNoError;
 }
 
 parse_error::ParseError GLES2DecoderImpl::HandleGetUniformfv(
-    unsigned int arg_count, const gles2::GetUniformfv& c) {
+    uint32 immediate_data_size, const gles2::GetUniformfv& c) {
   // TODO(gman): Implement.
   return parse_error::kParseNoError;
 }
 
 parse_error::ParseError GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
-    unsigned int arg_count, const gles2::GetShaderPrecisionFormat& c) {
+    uint32 immediate_data_size, const gles2::GetShaderPrecisionFormat& c) {
   // TODO(gman): Implement.
   return parse_error::kParseNoError;
 }
 
 parse_error::ParseError GLES2DecoderImpl::HandleGetAttachedShaders(
-    unsigned int arg_count, const gles2::GetAttachedShaders& c) {
+    uint32 immediate_data_size, const gles2::GetAttachedShaders& c) {
   // TODO(gman): Implement.
   return parse_error::kParseNoError;
 }
 
 parse_error::ParseError GLES2DecoderImpl::HandleGetActiveUniform(
-    unsigned int arg_count, const gles2::GetActiveUniform& c) {
+    uint32 immediate_data_size, const gles2::GetActiveUniform& c) {
   // TODO(gman): Implement.
   return parse_error::kParseNoError;
 }
 
 parse_error::ParseError GLES2DecoderImpl::HandleGetActiveAttrib(
-    unsigned int arg_count, const gles2::GetActiveAttrib& c) {
+    uint32 immediate_data_size, const gles2::GetActiveAttrib& c) {
   // TODO(gman): Implement.
   return parse_error::kParseNoError;
 }