Various fixes for the OpenGL ES 2.0 conformance tests.

Was failing 268 of 1198
Now failing 266 of 1198

ugh! all those changes only fixed 2 tests :-(

TEST=some unit test and conformance tests.
BUG=none

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@46572 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/gpu/command_buffer/service/buffer_manager.cc b/gpu/command_buffer/service/buffer_manager.cc
index dbc382c..ab5ab8ac 100644
--- a/gpu/command_buffer/service/buffer_manager.cc
+++ b/gpu/command_buffer/service/buffer_manager.cc
@@ -124,6 +124,18 @@
   return true;
 }
 
+bool BufferManager::GetClientId(GLuint service_id, GLuint* client_id) const {
+  // This doesn't need to be fast. It's only used during slow queries.
+  for (BufferInfoMap::const_iterator it = buffer_infos_.begin();
+       it != buffer_infos_.end(); ++it) {
+    if (it->second->service_id() == service_id) {
+      *client_id = it->first;
+      return true;
+    }
+  }
+  return false;
+}
+
 }  // namespace gles2
 }  // namespace gpu
 
diff --git a/gpu/command_buffer/service/buffer_manager.h b/gpu/command_buffer/service/buffer_manager.h
index 7eefd521..d944532 100644
--- a/gpu/command_buffer/service/buffer_manager.h
+++ b/gpu/command_buffer/service/buffer_manager.h
@@ -142,6 +142,9 @@
   // Removes a buffer info for the given buffer.
   void RemoveBufferInfo(GLuint client_id);
 
+  // Gets a client id for a given service id.
+  bool GetClientId(GLuint service_id, GLuint* client_id) const;
+
  private:
   // Info for each buffer in the system.
   // TODO(gman): Choose a faster container.
diff --git a/gpu/command_buffer/service/buffer_manager_unittest.cc b/gpu/command_buffer/service/buffer_manager_unittest.cc
index 2346f7cc..83a33fd 100644
--- a/gpu/command_buffer/service/buffer_manager_unittest.cc
+++ b/gpu/command_buffer/service/buffer_manager_unittest.cc
@@ -37,6 +37,9 @@
   EXPECT_EQ(0, info1->size());
   EXPECT_FALSE(info1->IsDeleted());
   EXPECT_EQ(kServiceBuffer1Id, info1->service_id());
+  GLuint client_id = 0;
+  EXPECT_TRUE(manager_.GetClientId(info1->service_id(), &client_id));
+  EXPECT_EQ(kClientBuffer1Id, client_id);
   info1->set_target(GL_ELEMENT_ARRAY_BUFFER);
   EXPECT_EQ(static_cast<GLenum>(GL_ELEMENT_ARRAY_BUFFER), info1->target());
   // Check we and set its size.
diff --git a/gpu/command_buffer/service/framebuffer_manager.cc b/gpu/command_buffer/service/framebuffer_manager.cc
index fb1014ad..1a7d739 100644
--- a/gpu/command_buffer/service/framebuffer_manager.cc
+++ b/gpu/command_buffer/service/framebuffer_manager.cc
@@ -46,6 +46,19 @@
   }
 }
 
+bool FramebufferManager::GetClientId(
+    GLuint service_id, GLuint* client_id) const {
+  // This doesn't need to be fast. It's only used during slow queries.
+  for (FramebufferInfoMap::const_iterator it = framebuffer_infos_.begin();
+       it != framebuffer_infos_.end(); ++it) {
+    if (it->second->service_id() == service_id) {
+      *client_id = it->first;
+      return true;
+    }
+  }
+  return false;
+}
+
 }  // namespace gles2
 }  // namespace gpu
 
diff --git a/gpu/command_buffer/service/framebuffer_manager.h b/gpu/command_buffer/service/framebuffer_manager.h
index db05c5b..3ecb54b 100644
--- a/gpu/command_buffer/service/framebuffer_manager.h
+++ b/gpu/command_buffer/service/framebuffer_manager.h
@@ -73,6 +73,9 @@
   // Removes a framebuffer info for the given framebuffer.
   void RemoveFramebufferInfo(GLuint client_id);
 
+  // Gets a client id for a given service id.
+  bool GetClientId(GLuint service_id, GLuint* client_id) const;
+
  private:
   // Info for each framebuffer in the system.
   // TODO(gman): Choose a faster container.
diff --git a/gpu/command_buffer/service/framebuffer_manager_unittest.cc b/gpu/command_buffer/service/framebuffer_manager_unittest.cc
index 1c57c852..75d0da6 100644
--- a/gpu/command_buffer/service/framebuffer_manager_unittest.cc
+++ b/gpu/command_buffer/service/framebuffer_manager_unittest.cc
@@ -35,6 +35,9 @@
   ASSERT_TRUE(info1 != NULL);
   EXPECT_FALSE(info1->IsDeleted());
   EXPECT_EQ(kService1Id, info1->service_id());
+  GLuint client_id = 0;
+  EXPECT_TRUE(manager_.GetClientId(info1->service_id(), &client_id));
+  EXPECT_EQ(kClient1Id, client_id);
   // Check we get nothing for a non-existent framebuffer.
   EXPECT_TRUE(manager_.GetFramebufferInfo(kClient2Id) == NULL);
   // Check trying to a remove non-existent framebuffers does not crash.
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 988bc18..93f28f9 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -506,6 +506,25 @@
     return (info && !info->IsDeleted()) ? info : NULL;
   }
 
+  // Gets the program info for the given program. If it's not a program
+  // generates a GL error. Returns NULL if not program.
+  ProgramManager::ProgramInfo* GetProgramInfoNotShader(
+      GLuint client_id, const char* function_name) {
+    ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
+    if (!info) {
+      if (GetShaderInfo(client_id)) {
+        SetGLError(GL_INVALID_OPERATION,
+                   (std::string(function_name) +
+                    ": shader passed for program").c_str());
+      } else {
+        SetGLError(GL_INVALID_VALUE,
+                   (std::string(function_name) + ": unknown program").c_str());
+      }
+    }
+    return info;
+  }
+
+
   // Deletes the program info for the given program.
   void RemoveProgramInfo(GLuint client_id) {
     program_manager()->RemoveProgramInfo(client_id);
@@ -525,6 +544,25 @@
     return (info && !info->IsDeleted()) ? info : NULL;
   }
 
+  // Gets the shader info for the given shader. If it's not a shader generates a
+  // GL error. Returns NULL if not shader.
+  ShaderManager::ShaderInfo* GetShaderInfoNotProgram(
+      GLuint client_id, const char* function_name) {
+    ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
+    if (!info) {
+      if (GetProgramInfo(client_id)) {
+        SetGLError(
+            GL_INVALID_OPERATION,
+            (std::string(function_name) +
+             ": program passed for shader").c_str());
+      } else {
+        SetGLError(GL_INVALID_VALUE,
+                   (std::string(function_name) + ": unknown shader").c_str());
+      }
+    }
+    return info;
+  }
+
   // Deletes the shader info for the given shader.
   void RemoveShaderInfo(GLuint client_id) {
     shader_manager()->RemoveShaderInfo(client_id);
@@ -1949,6 +1987,87 @@
       *num_written = 1;
       *params = GL_TRUE;
       return true;
+    case GL_ARRAY_BUFFER_BINDING:
+      *num_written = 1;
+      if (bound_array_buffer_) {
+        GLuint client_id = 0;
+        buffer_manager()->GetClientId(bound_array_buffer_->service_id(),
+                                      &client_id);
+        *params = client_id;
+      } else {
+        *params = 0;
+      }
+      return true;
+    case GL_ELEMENT_ARRAY_BUFFER_BINDING:
+      *num_written = 1;
+      if (bound_element_array_buffer_) {
+        GLuint client_id = 0;
+        buffer_manager()->GetClientId(bound_element_array_buffer_->service_id(),
+                                      &client_id);
+        *params = client_id;
+      } else {
+        *params = 0;
+      }
+      return true;
+    case GL_FRAMEBUFFER_BINDING:
+      *num_written = 1;
+      if (bound_framebuffer_) {
+        GLuint client_id = 0;
+        framebuffer_manager()->GetClientId(
+            bound_framebuffer_->service_id(), &client_id);
+        *params = client_id;
+      } else {
+        *params = 0;
+      }
+      return true;
+    case GL_RENDERBUFFER_BINDING:
+      *num_written = 1;
+      if (bound_renderbuffer_) {
+        GLuint client_id = 0;
+        renderbuffer_manager()->GetClientId(
+            bound_renderbuffer_->service_id(), &client_id);
+        *params = client_id;
+      } else {
+        *params = 0;
+      }
+      return true;
+    case GL_CURRENT_PROGRAM:
+      *num_written = 1;
+      if (current_program_) {
+        GLuint client_id = 0;
+        program_manager()->GetClientId(
+            current_program_->service_id(), &client_id);
+        *params = client_id;
+      } else {
+        *params = 0;
+      }
+      return true;
+    case GL_TEXTURE_BINDING_2D: {
+        *num_written = 1;
+        TextureUnit& unit = texture_units_[active_texture_unit_];
+        if (unit.bound_texture_2d) {
+          GLuint client_id = 0;
+          texture_manager()->GetClientId(
+              unit.bound_texture_2d->service_id(), &client_id);
+          *params = client_id;
+        } else {
+          *params = 0;
+        }
+        return true;
+      }
+    case GL_TEXTURE_BINDING_CUBE_MAP: {
+        *num_written = 1;
+        TextureUnit& unit = texture_units_[active_texture_unit_];
+        if (unit.bound_texture_cube_map) {
+          GLuint client_id = 0;
+          texture_manager()->GetClientId(
+              unit.bound_texture_cube_map->service_id(), &client_id);
+          *params = client_id;
+        } else {
+          *params = 0;
+        }
+        return true;
+      }
     default:
       return false;
   }
@@ -1992,9 +2111,9 @@
 
 void GLES2DecoderImpl::DoGetProgramiv(
     GLuint program_id, GLenum pname, GLint* params) {
-  ProgramManager::ProgramInfo* info = GetProgramInfo(program_id);
+  ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
+      program_id, "glGetProgramiv");
   if (!info) {
-    SetGLError(GL_INVALID_VALUE, "glGetProgramiv: unknown program");
     return;
   }
   info->GetProgramiv(pname, params);
@@ -2002,9 +2121,10 @@
 
 error::Error GLES2DecoderImpl::HandleBindAttribLocation(
     uint32 immediate_data_size, const gles2::BindAttribLocation& c) {
-  ProgramManager::ProgramInfo* info = GetProgramInfo(c.program);
+  GLuint program = static_cast<GLuint>(c.program);
+  ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
+      program, "glBindAttribLocation");
   if (!info) {
-    SetGLError(GL_INVALID_VALUE, "glBindAttribLocation: unknown program");
     return error::kNoError;
   }
   GLuint index = static_cast<GLuint>(c.index);
@@ -2021,9 +2141,10 @@
 
 error::Error GLES2DecoderImpl::HandleBindAttribLocationImmediate(
     uint32 immediate_data_size, const gles2::BindAttribLocationImmediate& c) {
-  ProgramManager::ProgramInfo* info = GetProgramInfo(c.program);
+  GLuint program = static_cast<GLuint>(c.program);
+  ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
+      program, "glBindAttribLocation");
   if (!info) {
-    SetGLError(GL_INVALID_VALUE, "glBindAttribLocation: unknown program");
     return error::kNoError;
   }
   GLuint index = static_cast<GLuint>(c.index);
@@ -2040,9 +2161,10 @@
 
 error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
     uint32 immediate_data_size, const gles2::BindAttribLocationBucket& c) {
-  ProgramManager::ProgramInfo* info = GetProgramInfo(c.program);
+  GLuint program = static_cast<GLuint>(c.program);
+  ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
+      program, "glBindAttribLocation");
   if (!info) {
-    SetGLError(GL_INVALID_VALUE, "glBindAttribLocation: unknown program");
     return error::kNoError;
   }
   GLuint index = static_cast<GLuint>(c.index);
@@ -2283,19 +2405,18 @@
 }
 
 void GLES2DecoderImpl::DoLinkProgram(GLuint program) {
-  ProgramManager::ProgramInfo* info = GetProgramInfo(program);
+  ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
+      program, "glLinkProgram");
   if (!info) {
-    SetGLError(GL_INVALID_OPERATION, "glLinkProgram: unknown program");
     return;
   }
-  CopyRealGLErrorsToWrapper();
   glLinkProgram(info->service_id());
-  GLenum error = glGetError();
-  if (error != GL_NO_ERROR) {
-    info->Reset();
-    SetGLError(error, NULL);
-  } else {
+  GLint success = 0;
+  glGetProgramiv(info->service_id(), GL_LINK_STATUS, &success);
+  if (success) {
     info->Update();
+  } else {
+    info->Reset();
   }
 };
 
@@ -2368,9 +2489,8 @@
   GLuint service_id = 0;
   ProgramManager::ProgramInfo* info = NULL;
   if (program) {
-    info = GetProgramInfo(program);
+    info = GetProgramInfoNotShader(program, "glUseProgram");
     if (!info) {
-      SetGLError(GL_INVALID_VALUE, "glUseProgram: unknown program");
       return;
     }
     if (!info->IsValid()) {
@@ -2618,9 +2738,9 @@
 // memory.)
 error::Error GLES2DecoderImpl::ShaderSourceHelper(
     GLuint client_id, const char* data, uint32 data_size) {
-  ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
+  ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
+      client_id, "glShaderSource");
   if (!info) {
-    SetGLError(GL_INVALID_VALUE, "glShaderSource: unknown shader");
     return error::kNoError;
   }
   // Note: We don't actually call glShaderSource here. We wait until
@@ -2663,9 +2783,9 @@
 }
 
 void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
-  ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
+  ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
+      client_id, "glCompileShader");
   if (!info) {
-    SetGLError(GL_INVALID_VALUE, "glCompileShader: unknown shader");
     return;
   }
   // Translate GL ES 2.0 shader to Desktop GL shader and pass that to
@@ -2711,9 +2831,9 @@
 
 void GLES2DecoderImpl::DoGetShaderiv(
     GLuint shader, GLenum pname, GLint* params) {
-  ShaderManager::ShaderInfo* info = GetShaderInfo(shader);
+  ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
+      shader, "glGetShaderiv");
   if (!info) {
-    SetGLError(GL_INVALID_VALUE, "glGetShaderiv: unknown shader");
     return;
   }
   if (pname == GL_SHADER_SOURCE_LENGTH) {
@@ -2726,12 +2846,12 @@
 error::Error GLES2DecoderImpl::HandleGetShaderSource(
     uint32 immediate_data_size, const gles2::GetShaderSource& c) {
   GLuint shader = c.shader;
-  ShaderManager::ShaderInfo* info = GetShaderInfo(shader);
   uint32 bucket_id = static_cast<uint32>(c.bucket_id);
   Bucket* bucket = CreateBucket(bucket_id);
+  ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
+      shader, "glGetShaderSource");
   if (!info) {
     bucket->SetSize(0);
-    SetGLError(GL_INVALID_VALUE, "glGetShaderSource: unknown shader");
     return error::kNoError;
   }
   bucket->SetFromString(info->source());
@@ -2741,15 +2861,15 @@
 error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
     uint32 immediate_data_size, const gles2::GetProgramInfoLog& c) {
   GLuint program = c.program;
-  ProgramManager::ProgramInfo* info = GetProgramInfo(program);
+  uint32 bucket_id = static_cast<uint32>(c.bucket_id);
+  Bucket* bucket = CreateBucket(bucket_id);
+  ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
+      program, "glGetProgramInfoLog");
   if (!info) {
-    SetGLError(GL_INVALID_VALUE, "glGetProgramInfoLog: unknown program");
     return error::kNoError;
   }
-  uint32 bucket_id = static_cast<uint32>(c.bucket_id);
   GLint len = 0;
   glGetProgramiv(info->service_id(), GL_INFO_LOG_LENGTH, &len);
-  Bucket* bucket = CreateBucket(bucket_id);
   bucket->SetSize(len + 1);
   glGetProgramInfoLog(
       info->service_id(),
@@ -2760,15 +2880,16 @@
 error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
     uint32 immediate_data_size, const gles2::GetShaderInfoLog& c) {
   GLuint shader = c.shader;
-  ShaderManager::ShaderInfo* info = GetShaderInfo(shader);
+  uint32 bucket_id = static_cast<uint32>(c.bucket_id);
+  Bucket* bucket = CreateBucket(bucket_id);
+  ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
+      shader, "glGetShaderInfoLog");
   if (!info) {
-    SetGLError(GL_INVALID_VALUE, "glGetShaderInfoLog: unknown shader");
+    bucket->SetSize(0);
     return error::kNoError;
   }
-  uint32 bucket_id = static_cast<uint32>(c.bucket_id);
   GLint len = 0;
   glGetShaderiv(info->service_id(), GL_INFO_LOG_LENGTH, &len);
-  Bucket* bucket = CreateBucket(bucket_id);
   bucket->SetSize(len + 1);
   glGetShaderInfoLog(
       info->service_id(),
@@ -2802,14 +2923,14 @@
 
 void GLES2DecoderImpl::DoAttachShader(
     GLuint program_client_id, GLint shader_client_id) {
-  ProgramManager::ProgramInfo* program_info = GetProgramInfo(program_client_id);
+  ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
+      program_client_id, "glAttachShader");
   if (!program_info) {
-    SetGLError(GL_INVALID_VALUE, "glAttachShader: unknown program");
     return;
   }
-  ShaderManager::ShaderInfo* shader_info = GetShaderInfo(shader_client_id);
+  ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
+      shader_client_id, "glAttachShader");
   if (!shader_info) {
-    SetGLError(GL_INVALID_VALUE, "glAttachShader: unknown shader");
     return;
   }
   glAttachShader(program_info->service_id(), shader_info->service_id());
@@ -2817,23 +2938,23 @@
 
 void GLES2DecoderImpl::DoDetachShader(
     GLuint program_client_id, GLint shader_client_id) {
-  ProgramManager::ProgramInfo* program_info = GetProgramInfo(program_client_id);
+  ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
+      program_client_id, "glDetachShader");
   if (!program_info) {
-    SetGLError(GL_INVALID_VALUE, "glDetachShader: unknown program");
     return;
   }
-  ShaderManager::ShaderInfo* shader_info = GetShaderInfo(shader_client_id);
+  ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
+      shader_client_id, "glDetachShader");
   if (!shader_info) {
-    SetGLError(GL_INVALID_VALUE, "glDetachShader: unknown shader");
     return;
   }
   glDetachShader(program_info->service_id(), shader_info->service_id());
 }
 
 void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
-  ProgramManager::ProgramInfo* info = GetProgramInfo(program_client_id);
+  ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
+      program_client_id, "glValidateProgram");
   if (!info) {
-    SetGLError(GL_INVALID_VALUE, "glValidateProgram: unknown program");
     return;
   }
   glValidateProgram(info->service_id());
@@ -2951,6 +3072,7 @@
     return error::kNoError;
   }
 
+  glFinish();
   if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
     // The user requested an out of range area. Get the results 1 line
     // at a time.
@@ -3041,9 +3163,9 @@
 error::Error GLES2DecoderImpl::GetAttribLocationHelper(
     GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
     const std::string& name_str) {
-  ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
+  ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
+      client_id, "glGetAttribLocation");
   if (!info) {
-    SetGLError(GL_INVALID_VALUE, "glGetAttribLocation: unknown program");
     return error::kNoError;
   }
   if (!info->IsValid()) {
@@ -3105,9 +3227,9 @@
 error::Error GLES2DecoderImpl::GetUniformLocationHelper(
     GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
     const std::string& name_str) {
-  ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
+  ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
+      client_id, "glUniformLocation");
   if (!info) {
-    SetGLError(GL_INVALID_VALUE, "glGetUniformLocation: unknown program");
     return error::kNoError;
   }
   if (!info->IsValid()) {
@@ -3518,9 +3640,9 @@
   *result_pointer = result;
   // Set the result size to 0 so the client does not have to check for success.
   result->SetNumResults(0);
-  ProgramManager::ProgramInfo* info = GetProgramInfo(program);
+  ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
+      program, "glGetUniform");
   if (!info) {
-    SetGLError(GL_INVALID_VALUE, "glGetUniform: unknown program");
     return false;
   }
   if (!info->IsValid()) {
@@ -3636,9 +3758,10 @@
 error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
     uint32 immediate_data_size, const gles2::GetAttachedShaders& c) {
   uint32 result_size = c.result_size;
-  ProgramManager::ProgramInfo* info = GetProgramInfo(c.program);
+  GLuint program = static_cast<GLuint>(c.program);
+  ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
+      program, "glGetAttachedShaders");
   if (!info) {
-    SetGLError(GL_INVALID_VALUE, "glGetAttachedShaders: unknown program");
     return error::kNoError;
   }
   typedef gles2::GetAttachedShaders::Result Result;
@@ -3681,14 +3804,9 @@
   if (result->success != 0) {
     return error::kInvalidArguments;
   }
-  ProgramManager::ProgramInfo* info = GetProgramInfo(program);
+  ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
+      program, "glGetActiveUniform");
   if (!info) {
-    SetGLError(GL_INVALID_VALUE, "glGetActiveUniform: unknown program");
-    return error::kNoError;
-  }
-  if (!info->IsValid()) {
-    // Program was not linked successfully. (ie, glLinkProgram)
-    SetGLError(GL_INVALID_OPERATION, "glGetActiveUniform: program not linked");
     return error::kNoError;
   }
   const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
@@ -3720,14 +3838,9 @@
   if (result->success != 0) {
     return error::kInvalidArguments;
   }
-  ProgramManager::ProgramInfo* info = GetProgramInfo(program);
+  ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
+      program, "glGetActiveAttrib");
   if (!info) {
-    SetGLError(GL_INVALID_VALUE, "glGetActiveAttrib: unknown program");
-    return error::kNoError;
-  }
-  if (!info->IsValid()) {
-    // Program was not linked successfully. (ie, glLinkProgram)
-    SetGLError(GL_INVALID_OPERATION, "glGetActiveAttrib: program not linked");
     return error::kNoError;
   }
   const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
index 759e54c..859e4d3 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
@@ -1317,6 +1317,7 @@
   GLint read_end_y = std::max(0, std::min(kHeight, in_read_y + in_read_height));
   GLint read_width = read_end_x - read_x;
   GLint read_height = read_end_y - read_y;
+  EXPECT_CALL(*gl_, Finish()).Times(1).RetiresOnSaturation();
   if (read_width > 0 && read_height > 0) {
     for (GLint yy = read_y; yy < read_end_y; ++yy) {
       EXPECT_CALL(
@@ -1399,6 +1400,7 @@
      .WillOnce(Return(GL_NO_ERROR))
      .WillOnce(Return(GL_NO_ERROR))
      .RetiresOnSaturation();
+  EXPECT_CALL(*gl_, Finish()).Times(1).RetiresOnSaturation();
   EXPECT_CALL(
       *gl_, ReadPixels(0, 0, kWidth, kHeight, GL_RGB, GL_UNSIGNED_BYTE, _))
       .WillOnce(Invoke(&emu, &ReadPixelsEmulator::ReadPixels));
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2.cc
index caadef6..832e0c5 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2.cc
@@ -34,11 +34,9 @@
 
 template <>
 void GLES2DecoderTestBase::SpecializedSetup<LinkProgram, 0>() {
-  EXPECT_CALL(*gl_, GetError())
-      .WillOnce(Return(GL_NO_ERROR))
-      .WillOnce(Return(GL_NO_ERROR))
-      .RetiresOnSaturation();
   InSequence dummy;
+  EXPECT_CALL(*gl_, GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _))
+      .WillOnce(SetArgumentPointee<2>(1));
   EXPECT_CALL(*gl_, GetProgramiv(kServiceProgramId, GL_ACTIVE_ATTRIBUTES, _))
       .WillOnce(SetArgumentPointee<2>(0));
   EXPECT_CALL(
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
index 9da6955..e16f0a4 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
@@ -296,14 +296,11 @@
 
   {
     InSequence s;
-    EXPECT_CALL(*gl_, GetError())
-        .WillOnce(Return(GL_NO_ERROR))
-        .RetiresOnSaturation();
     EXPECT_CALL(*gl_, LinkProgram(service_id))
         .Times(1)
         .RetiresOnSaturation();
-    EXPECT_CALL(*gl_, GetError())
-        .WillOnce(Return(GL_NO_ERROR))
+    EXPECT_CALL(*gl_, GetProgramiv(service_id, GL_LINK_STATUS, _))
+        .WillOnce(SetArgumentPointee<2>(1))
         .RetiresOnSaturation();
     EXPECT_CALL(*gl_,
         GetProgramiv(service_id, GL_ACTIVE_ATTRIBUTES, _))
diff --git a/gpu/command_buffer/service/program_manager.cc b/gpu/command_buffer/service/program_manager.cc
index afd9bce..5b86014a 100644
--- a/gpu/command_buffer/service/program_manager.cc
+++ b/gpu/command_buffer/service/program_manager.cc
@@ -51,7 +51,8 @@
     }
   }
 
-  GLint num_uniforms;
+  GLint num_uniforms = 0;
+  max_len = 0;
   glGetProgramiv(service_id_, GL_ACTIVE_UNIFORMS, &num_uniforms);
   glGetProgramiv(service_id_, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_len);
   name_buffer.reset(new char[max_len]);
@@ -257,6 +258,18 @@
   }
 }
 
+bool ProgramManager::GetClientId(GLuint service_id, GLuint* client_id) const {
+  // This doesn't need to be fast. It's only used during slow queries.
+  for (ProgramInfoMap::const_iterator it = program_infos_.begin();
+       it != program_infos_.end(); ++it) {
+    if (it->second->service_id() == service_id) {
+      *client_id = it->first;
+      return true;
+    }
+  }
+  return false;
+}
+
 }  // namespace gles2
 }  // namespace gpu
 
diff --git a/gpu/command_buffer/service/program_manager.h b/gpu/command_buffer/service/program_manager.h
index 078f8a5..feb263c 100644
--- a/gpu/command_buffer/service/program_manager.h
+++ b/gpu/command_buffer/service/program_manager.h
@@ -168,6 +168,9 @@
   // Deletes the program info for the given program.
   void RemoveProgramInfo(GLuint client_id);
 
+  // Gets a client id for a given service id.
+  bool GetClientId(GLuint service_id, GLuint* client_id) const;
+
   // Returns true if prefix is invalid for gl.
   static bool IsInvalidPrefix(const char* name, size_t length);
 
diff --git a/gpu/command_buffer/service/program_manager_unittest.cc b/gpu/command_buffer/service/program_manager_unittest.cc
index b8b318c..6767646 100644
--- a/gpu/command_buffer/service/program_manager_unittest.cc
+++ b/gpu/command_buffer/service/program_manager_unittest.cc
@@ -47,6 +47,9 @@
   ProgramManager::ProgramInfo* info1 = manager_.GetProgramInfo(kClient1Id);
   ASSERT_TRUE(info1 != NULL);
   EXPECT_EQ(kService1Id, info1->service_id());
+  GLuint client_id = 0;
+  EXPECT_TRUE(manager_.GetClientId(info1->service_id(), &client_id));
+  EXPECT_EQ(kClient1Id, client_id);
   // Check we get nothing for a non-existent program.
   EXPECT_TRUE(manager_.GetProgramInfo(kClient2Id) == NULL);
   // Check trying to a remove non-existent programs does not crash.
diff --git a/gpu/command_buffer/service/renderbuffer_manager.cc b/gpu/command_buffer/service/renderbuffer_manager.cc
index fe07d01..63aee26 100644
--- a/gpu/command_buffer/service/renderbuffer_manager.cc
+++ b/gpu/command_buffer/service/renderbuffer_manager.cc
@@ -34,6 +34,19 @@
   }
 }
 
+bool RenderbufferManager::GetClientId(
+    GLuint service_id, GLuint* client_id) const {
+  // This doesn't need to be fast. It's only used during slow queries.
+  for (RenderbufferInfoMap::const_iterator it = renderbuffer_infos_.begin();
+       it != renderbuffer_infos_.end(); ++it) {
+    if (it->second->service_id() == service_id) {
+      *client_id = it->first;
+      return true;
+    }
+  }
+  return false;
+}
+
 }  // namespace gles2
 }  // namespace gpu
 
diff --git a/gpu/command_buffer/service/renderbuffer_manager.h b/gpu/command_buffer/service/renderbuffer_manager.h
index 8e2f70b..e896117 100644
--- a/gpu/command_buffer/service/renderbuffer_manager.h
+++ b/gpu/command_buffer/service/renderbuffer_manager.h
@@ -73,6 +73,9 @@
   // Removes a renderbuffer info for the given renderbuffer.
   void RemoveRenderbufferInfo(GLuint client_id);
 
+  // Gets a client id for a given service id.
+  bool GetClientId(GLuint service_id, GLuint* client_id) const;
+
  private:
   // Info for each renderbuffer in the system.
   // TODO(gman): Choose a faster container.
diff --git a/gpu/command_buffer/service/renderbuffer_manager_unittest.cc b/gpu/command_buffer/service/renderbuffer_manager_unittest.cc
index bebd8fce..0cedaea 100644
--- a/gpu/command_buffer/service/renderbuffer_manager_unittest.cc
+++ b/gpu/command_buffer/service/renderbuffer_manager_unittest.cc
@@ -33,6 +33,9 @@
   RenderbufferManager::RenderbufferInfo* info1 =
       manager_.GetRenderbufferInfo(kClient1Id);
   ASSERT_TRUE(info1 != NULL);
+  GLuint client_id = 0;
+  EXPECT_TRUE(manager_.GetClientId(info1->service_id(), &client_id));
+  EXPECT_EQ(kClient1Id, client_id);
   EXPECT_FALSE(info1->cleared());
   info1->set_cleared();
   EXPECT_TRUE(info1->cleared());
diff --git a/gpu/command_buffer/service/texture_manager_unittest.cc b/gpu/command_buffer/service/texture_manager_unittest.cc
index 50af31af..9c5fa3e 100644
--- a/gpu/command_buffer/service/texture_manager_unittest.cc
+++ b/gpu/command_buffer/service/texture_manager_unittest.cc
@@ -47,6 +47,9 @@
   TextureManager::TextureInfo* info1 = manager_.GetTextureInfo(kClient1Id);
   ASSERT_TRUE(info1 != NULL);
   EXPECT_EQ(kService1Id, info1->service_id());
+  GLuint client_id = 0;
+  EXPECT_TRUE(manager_.GetClientId(info1->service_id(), &client_id));
+  EXPECT_EQ(kClient1Id, client_id);
   // Check we get nothing for a non-existent texture.
   EXPECT_TRUE(manager_.GetTextureInfo(kClient2Id) == NULL);
   // Check trying to a remove non-existent textures does not crash.