Resubmitting
http://codereview.chromium.org/668131

TEST=none
BUG=none

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@40721 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 54cef89..dbb49e99 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -434,6 +434,14 @@
   // Wrapper for glBindTexture since we need to track the current targets.
   void DoBindTexture(GLenum target, GLuint texture);
 
+  // Wrapper for BufferData.
+  void DoBufferData(
+    GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage);
+
+  // Wrapper for BufferSubData.
+  void DoBufferSubData(
+    GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
+
   // Wrapper for glCompileShader.
   void DoCompileShader(GLuint shader);
 
@@ -1503,10 +1511,15 @@
   BufferManager::BufferInfo* info = NULL;
   if (buffer) {
     info = GetBufferInfo(buffer);
-    if (!info) {
+    // Check the buffer exists
+    // Check that we are not trying to bind it to a different target.
+    if (!info || (info->target() != 0 && info->target() != target)) {
       SetGLError(GL_INVALID_OPERATION);
       return;
     }
+    if (info->target() == 0) {
+      info->set_target(target);
+    }
   }
   switch (target) {
     case GL_ARRAY_BUFFER:
@@ -1919,28 +1932,19 @@
                !ValidateGLenumIndexType(type)) {
       SetGLError(GL_INVALID_ENUM);
     } else {
-      GLsizeiptr buffer_size = bound_element_array_buffer_->size();
-      if (offset > buffer_size) {
+      GLuint max_vertex_accessed;
+      if (!bound_element_array_buffer_->GetMaxValueForRange(
+          offset, count, type, &max_vertex_accessed)) {
         SetGLError(GL_INVALID_OPERATION);
       } else {
-        GLsizei usable_size = buffer_size - offset;
-        GLsizei num_elements =
-            usable_size / GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
-        if (count > num_elements) {
-          SetGLError(GL_INVALID_OPERATION);
-        } else {
+        if (IsDrawValid(max_vertex_accessed)) {
+          bool has_non_renderable_textures;
+          SetBlackTextureForNonRenderableTextures(
+              &has_non_renderable_textures);
           const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
-          GLuint max_vertex_accessed =
-              bound_element_array_buffer_->GetMaxValueForRange(
-                  offset, count, type);
-          if (IsDrawValid(max_vertex_accessed)) {
-            bool has_non_renderable_textures;
-            SetBlackTextureForNonRenderableTextures(
-                &has_non_renderable_textures);
-            glDrawElements(mode, count, type, indices);
-            if (has_non_renderable_textures) {
-              RestoreStateForNonRenderableTextures();
-            }
+          glDrawElements(mode, count, type, indices);
+          if (has_non_renderable_textures) {
+            RestoreStateForNonRenderableTextures();
           }
         }
       }
@@ -2272,33 +2276,21 @@
   return error::kNoError;
 }
 
-error::Error 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);
-    if (!data) {
-      return error::kOutOfBounds;
-    }
-  }
+void GLES2DecoderImpl::DoBufferData(
+  GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage) {
   if (!ValidateGLenumBufferTarget(target) ||
       !ValidateGLenumBufferUsage(usage)) {
     SetGLError(GL_INVALID_ENUM);
-    return error::kNoError;
+    return;
   }
   if (size < 0) {
     SetGLError(GL_INVALID_VALUE);
-    return error::kNoError;
+    DoBufferData(target, size, data, usage);
   }
   BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
   if (!info) {
     SetGLError(GL_INVALID_OPERATION);
-    return error::kNoError;
+    DoBufferData(target, size, data, usage);
   }
   // Clear the buffer to 0 if no initial data was passed in.
   scoped_array<int8> zero;
@@ -2313,8 +2305,26 @@
   if (error != GL_NO_ERROR) {
     SetGLError(error);
   } else {
-    info->set_size(size);
+    info->SetSize(size);
+    info->SetRange(0, size, data);
   }
+}
+
+error::Error 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);
+    if (!data) {
+      return error::kOutOfBounds;
+    }
+  }
+  DoBufferData(target, size, data, usage);
   return error::kNoError;
 }
 
@@ -2328,29 +2338,21 @@
     return error::kOutOfBounds;
   }
   GLenum usage = static_cast<GLenum>(c.usage);
-  if (!ValidateGLenumBufferTarget(target) ||
-      !ValidateGLenumBufferUsage(usage)) {
-    SetGLError(GL_INVALID_ENUM);
-    return error::kNoError;
-  }
-  if (size < 0) {
-    SetGLError(GL_INVALID_VALUE);
-    return error::kNoError;
-  }
+  DoBufferData(target, size, data, usage);
+  return error::kNoError;
+}
+
+void GLES2DecoderImpl::DoBufferSubData(
+  GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
   BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
   if (!info) {
     SetGLError(GL_INVALID_OPERATION);
-    return error::kNoError;
   }
-  CopyRealGLErrorsToWrapper();
-  glBufferData(target, size, data, usage);
-  GLenum error = glGetError();
-  if (error != GL_NO_ERROR) {
-    SetGLError(error);
+  if (!info->SetRange(offset, size, data)) {
+    SetGLError(GL_INVALID_VALUE);
   } else {
-    info->set_size(size);
+    glBufferSubData(target, offset, size, data);
   }
-  return error::kNoError;
 }
 
 error::Error GLES2DecoderImpl::DoCompressedTexImage2D(