Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / gpu / command_buffer / service / gles2_cmd_decoder.cc
index 729ab26..008bdbe 100644 (file)
@@ -299,17 +299,18 @@ class ScopedGLErrorSuppressor {
   DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
 };
 
-// Temporarily changes a decoder's bound 2D texture and restore it when this
+// Temporarily changes a decoder's bound texture and restore it when this
 // object goes out of scope. Also temporarily switches to using active texture
 // unit zero in case the client has changed that to something invalid.
-class ScopedTexture2DBinder {
+class ScopedTextureBinder {
  public:
-  ScopedTexture2DBinder(ContextState* state, GLuint id);
-  ~ScopedTexture2DBinder();
+  ScopedTextureBinder(ContextState* state, GLuint id, GLenum target);
+  ~ScopedTextureBinder();
 
  private:
   ContextState* state_;
-  DISALLOW_COPY_AND_ASSIGN(ScopedTexture2DBinder);
+  GLenum target_;
+  DISALLOW_COPY_AND_ASSIGN(ScopedTextureBinder);
 };
 
 // Temporarily changes a decoder's bound render buffer and restore it when this
@@ -530,7 +531,7 @@ class GLES2DecoderImpl : public GLES2Decoder,
   virtual void Destroy(bool have_context) OVERRIDE;
   virtual void SetSurface(
       const scoped_refptr<gfx::GLSurface>& surface) OVERRIDE;
-  virtual bool ProduceFrontBuffer(const Mailbox& mailbox) OVERRIDE;
+  virtual void ProduceFrontBuffer(const Mailbox& mailbox) OVERRIDE;
   virtual bool ResizeOffscreenFrameBuffer(const gfx::Size& size) OVERRIDE;
   void UpdateParentTextureInfo();
   virtual bool MakeCurrent() OVERRIDE;
@@ -565,6 +566,9 @@ class GLES2DecoderImpl : public GLES2Decoder,
   virtual void RestoreFramebufferBindings() const OVERRIDE;
   virtual void RestoreTextureState(unsigned service_id) const OVERRIDE;
 
+  virtual void ClearAllAttributes() const OVERRIDE;
+  virtual void RestoreAllAttributes() const OVERRIDE;
+
   virtual QueryManager* GetQueryManager() OVERRIDE {
     return query_manager_.get();
   }
@@ -1717,35 +1721,55 @@ ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
   ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_, function_name_);
 }
 
-static void RestoreCurrentTexture2DBindings(ContextState* state) {
+static void RestoreCurrentTextureBindings(ContextState* state, GLenum target) {
   TextureUnit& info = state->texture_units[0];
   GLuint last_id;
-  if (info.bound_texture_2d.get()) {
-    last_id = info.bound_texture_2d->service_id();
+  scoped_refptr<TextureRef> texture_ref;
+  switch (target) {
+    case GL_TEXTURE_2D:
+      texture_ref = info.bound_texture_2d;
+      break;
+    case GL_TEXTURE_CUBE_MAP:
+      texture_ref = info.bound_texture_cube_map;
+      break;
+    case GL_TEXTURE_EXTERNAL_OES:
+      texture_ref = info.bound_texture_external_oes;
+      break;
+    case GL_TEXTURE_RECTANGLE_ARB:
+      texture_ref = info.bound_texture_rectangle_arb;
+      break;
+    default:
+      NOTREACHED();
+      break;
+  }
+  if (texture_ref.get()) {
+    last_id = texture_ref->service_id();
   } else {
     last_id = 0;
   }
 
-  glBindTexture(GL_TEXTURE_2D, last_id);
+  glBindTexture(target, last_id);
   glActiveTexture(GL_TEXTURE0 + state->active_texture_unit);
 }
 
-ScopedTexture2DBinder::ScopedTexture2DBinder(ContextState* state,
-                                             GLuint id)
-    : state_(state) {
+ScopedTextureBinder::ScopedTextureBinder(ContextState* state,
+                                         GLuint id,
+                                         GLenum target)
+    : state_(state),
+      target_(target) {
   ScopedGLErrorSuppressor suppressor(
-      "ScopedTexture2DBinder::ctor", state_->GetErrorState());
+      "ScopedTextureBinder::ctor", state_->GetErrorState());
 
   // TODO(apatrick): Check if there are any other states that need to be reset
   // before binding a new texture.
   glActiveTexture(GL_TEXTURE0);
-  glBindTexture(GL_TEXTURE_2D, id);
+  glBindTexture(target, id);
 }
 
-ScopedTexture2DBinder::~ScopedTexture2DBinder() {
+ScopedTextureBinder::~ScopedTextureBinder() {
   ScopedGLErrorSuppressor suppressor(
-      "ScopedTexture2DBinder::dtor", state_->GetErrorState());
-  RestoreCurrentTexture2DBindings(state_);
+      "ScopedTextureBinder::dtor", state_->GetErrorState());
+  RestoreCurrentTextureBindings(state_, target_);
 }
 
 ScopedRenderBufferBinder::ScopedRenderBufferBinder(ContextState* state,
@@ -1869,7 +1893,7 @@ void BackTexture::Create() {
                                      state_->GetErrorState());
   Destroy();
   glGenTextures(1, &id_);
-  ScopedTexture2DBinder binder(state_, id_);
+  ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
@@ -1893,7 +1917,7 @@ bool BackTexture::AllocateStorage(
   DCHECK_NE(id_, 0u);
   ScopedGLErrorSuppressor suppressor("BackTexture::AllocateStorage",
                                      state_->GetErrorState());
-  ScopedTexture2DBinder binder(state_, id_);
+  ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
   uint32 image_size = 0;
   GLES2Util::ComputeImageDataSizes(
       size.width(), size.height(), format, GL_UNSIGNED_BYTE, 8, &image_size,
@@ -1934,7 +1958,7 @@ void BackTexture::Copy(const gfx::Size& size, GLenum format) {
   DCHECK_NE(id_, 0u);
   ScopedGLErrorSuppressor suppressor("BackTexture::Copy",
                                      state_->GetErrorState());
-  ScopedTexture2DBinder binder(state_, id_);
+  ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
   glCopyTexImage2D(GL_TEXTURE_2D,
                    0,  // level
                    format,
@@ -2634,6 +2658,8 @@ bool GLES2DecoderImpl::InitializeShaderTranslator() {
     driver_bug_workarounds |= SH_INIT_GL_POSITION;
   if (workarounds().unfold_short_circuit_as_ternary_operation)
     driver_bug_workarounds |= SH_UNFOLD_SHORT_CIRCUIT;
+  if (workarounds().init_varyings_without_static_use)
+    driver_bug_workarounds |= SH_INIT_VARYINGS_WITHOUT_STATIC_USE;
 
   ShaderTranslatorCache* cache = ShaderTranslatorCache::GetInstance();
   vertex_translator_ = cache->GetTranslator(
@@ -3314,9 +3340,11 @@ void GLES2DecoderImpl::SetSurface(
   RestoreCurrentFramebufferBindings();
 }
 
-bool GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox& mailbox) {
-  if (!offscreen_saved_color_texture_.get())
-    return false;
+void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox& mailbox) {
+  if (!offscreen_saved_color_texture_.get()) {
+    LOG(ERROR) << "Called ProduceFrontBuffer on a non-offscreen context";
+    return;
+  }
   if (!offscreen_saved_color_texture_info_.get()) {
     GLuint service_id = offscreen_saved_color_texture_->id();
     offscreen_saved_color_texture_info_ = TextureRef::Create(
@@ -3325,10 +3353,8 @@ bool GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox& mailbox) {
                                  GL_TEXTURE_2D);
     UpdateParentTextureInfo();
   }
-  gpu::gles2::MailboxName name;
-  memcpy(name.key, mailbox.name, sizeof(mailbox.name));
-  return mailbox_manager()->ProduceTexture(
-      GL_TEXTURE_2D, name, offscreen_saved_color_texture_info_->texture());
+  mailbox_manager()->ProduceTexture(
+      GL_TEXTURE_2D, mailbox, offscreen_saved_color_texture_info_->texture());
 }
 
 bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
@@ -3616,8 +3642,9 @@ void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
     buffer = GetBuffer(client_id);
     if (!buffer) {
       if (!group_->bind_generates_resource()) {
-        LOG(ERROR) << "glBindBuffer: id not generated by glGenBuffers";
-        current_decoder_error_ = error::kGenericError;
+        LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
+                           "glBindBuffer",
+                           "id not generated by glGenBuffers");
         return;
       }
 
@@ -3763,6 +3790,20 @@ void GLES2DecoderImpl::RestoreTextureState(unsigned service_id) const {
   }
 }
 
+void GLES2DecoderImpl::ClearAllAttributes() const {
+  for (uint32 i = 0; i < group_->max_vertex_attribs(); ++i) {
+    if (i != 0) // Never disable attribute 0
+      glDisableVertexAttribArray(i);
+    if(features().angle_instanced_arrays)
+      glVertexAttribDivisorANGLE(i, 0);
+  }
+}
+
+void GLES2DecoderImpl::RestoreAllAttributes() const {
+  for (uint32 i = 0; i < group_->max_vertex_attribs(); ++i)
+    RestoreAttribute(i);
+}
+
 void GLES2DecoderImpl::OnFboChanged() const {
   if (workarounds().restore_scissor_on_fbo_change)
     state_.fbo_binding_for_scissor_workaround_dirty_ = true;
@@ -3791,10 +3832,10 @@ void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
     framebuffer = GetFramebuffer(client_id);
     if (!framebuffer) {
       if (!group_->bind_generates_resource()) {
-         LOG(ERROR)
-             << "glBindFramebuffer: id not generated by glGenFramebuffers";
-         current_decoder_error_ = error::kGenericError;
-         return;
+        LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
+                           "glBindFramebuffer",
+                           "id not generated by glGenFramebuffers");
+        return;
       }
 
       // It's a new id so make a framebuffer framebuffer for it.
@@ -3839,9 +3880,9 @@ void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
     renderbuffer = GetRenderbuffer(client_id);
     if (!renderbuffer) {
       if (!group_->bind_generates_resource()) {
-        LOG(ERROR)
-            << "glBindRenderbuffer: id not generated by glGenRenderbuffers";
-        current_decoder_error_ = error::kGenericError;
+        LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
+                           "glBindRenderbuffer",
+                           "id not generated by glGenRenderbuffers");
         return;
       }
 
@@ -3857,7 +3898,7 @@ void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
     }
     renderbuffer->MarkAsValid();
   }
-  LogClientServiceForInfo(renderbuffer, client_id, "glBindRenerbuffer");
+  LogClientServiceForInfo(renderbuffer, client_id, "glBindRenderbuffer");
   state_.bound_renderbuffer = renderbuffer;
   glBindRenderbufferEXT(target, service_id);
 }
@@ -3869,9 +3910,10 @@ void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
     texture_ref = GetTexture(client_id);
     if (!texture_ref) {
       if (!group_->bind_generates_resource()) {
-         LOG(ERROR) << "glBindTexture: id not generated by glGenTextures";
-         current_decoder_error_ = error::kGenericError;
-         return;
+        LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
+                           "glBindTexture",
+                           "id not generated by glGenTextures");
+        return;
       }
 
       // It's a new id so make a texture texture for it.
@@ -4975,7 +5017,7 @@ void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
   if (!framebuffer) {
     LOCAL_SET_GL_ERROR(
         GL_INVALID_OPERATION,
-        "glFramebufferAttachmentParameteriv", "no framebuffer bound");
+        "glGetFramebufferAttachmentParameteriv", "no framebuffer bound");
     return;
   }
   if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
@@ -5117,14 +5159,14 @@ bool GLES2DecoderImpl::ValidateRenderbufferStorageMultisample(
            width, height, samples, internalformat, &estimated_size)) {
     LOCAL_SET_GL_ERROR(
         GL_OUT_OF_MEMORY,
-        "glRenderbufferStorageMultsample", "dimensions too large");
+        "glRenderbufferStorageMultisample", "dimensions too large");
     return false;
   }
 
   if (!EnsureGPUMemoryAvailable(estimated_size)) {
     LOCAL_SET_GL_ERROR(
         GL_OUT_OF_MEMORY,
-        "glRenderbufferStorageMultsample", "out of memory");
+        "glRenderbufferStorageMultisample", "out of memory");
     return false;
   }
 
@@ -5396,13 +5438,14 @@ void GLES2DecoderImpl::DoLinkProgram(GLuint program_id) {
   if (program->Link(shader_manager(),
                     vertex_translator,
                     fragment_translator,
-                    feature_info_.get(),
+                    workarounds().count_all_in_varyings_packing ?
+                        Program::kCountAll : Program::kCountOnlyStaticallyUsed,
                     shader_cache_callback_)) {
     if (program == state_.current_program.get()) {
-      if (workarounds().use_current_program_after_successful_link) {
+      if (workarounds().use_current_program_after_successful_link)
         glUseProgram(program->service_id());
-      }
-      program_manager()->ClearUniforms(program);
+      if (workarounds().clear_uniforms_before_first_program_use)
+        program_manager()->ClearUniforms(program);
     }
   }
 };
@@ -5651,7 +5694,7 @@ void GLES2DecoderImpl::DoUniform1i(GLint fake_location, GLint v0) {
   GLsizei count = 1;
   GLint real_location = -1;
   if (!PrepForSetUniformByLocation(
-      fake_location, "glUniform1iv", valid_int_vec1_base_info,
+      fake_location, "glUniform1i", valid_int_vec1_base_info,
       &real_location, &type, &count)) {
     return;
   }
@@ -5868,6 +5911,8 @@ void GLES2DecoderImpl::DoUseProgram(GLuint program_id) {
   glUseProgram(service_id);
   if (state_.current_program.get()) {
     program_manager()->UseProgram(state_.current_program.get());
+    if (workarounds().clear_uniforms_before_first_program_use)
+      program_manager()->ClearUniforms(program);
   }
 }
 
@@ -5884,9 +5929,6 @@ void GLES2DecoderImpl::PerformanceWarning(
 
 void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
     Texture* texture, GLenum textarget) {
-  // This might be supported in the future.
-  if (textarget != GL_TEXTURE_2D)
-    return;
   // Image is already in use if texture is attached to a framebuffer.
   if (texture && !texture->IsAttachedToFramebuffer()) {
     gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
@@ -5896,16 +5938,13 @@ void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
           GetErrorState());
       glBindTexture(textarget, texture->service_id());
       image->WillUseTexImage();
-      RestoreCurrentTexture2DBindings(&state_);
+      RestoreCurrentTextureBindings(&state_, textarget);
     }
   }
 }
 
 void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
     Texture* texture, GLenum textarget) {
-  // This might be supported in the future.
-  if (textarget != GL_TEXTURE_2D)
-    return;
   // Image is still in use if texture is attached to a framebuffer.
   if (texture && !texture->IsAttachedToFramebuffer()) {
     gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
@@ -5915,7 +5954,7 @@ void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
           GetErrorState());
       glBindTexture(textarget, texture->service_id());
       image->DidUseTexImage();
-      RestoreCurrentTexture2DBindings(&state_);
+      RestoreCurrentTextureBindings(&state_, textarget);
     }
   }
 }
@@ -5956,15 +5995,17 @@ bool GLES2DecoderImpl::PrepareTexturesForRender() {
           continue;
         }
 
-        Texture* texture = texture_ref->texture();
-        gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
-        if (image && !texture->IsAttachedToFramebuffer()) {
-          ScopedGLErrorSuppressor suppressor(
-              "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
-          textures_set = true;
-          glActiveTexture(GL_TEXTURE0 + texture_unit_index);
-          image->WillUseTexImage();
-          continue;
+        if (textarget != GL_TEXTURE_CUBE_MAP) {
+          Texture* texture = texture_ref->texture();
+          gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
+          if (image && !texture->IsAttachedToFramebuffer()) {
+            ScopedGLErrorSuppressor suppressor(
+                "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
+            textures_set = true;
+            glActiveTexture(GL_TEXTURE0 + texture_unit_index);
+            image->WillUseTexImage();
+            continue;
+          }
         }
       }
       // else: should this be an error?
@@ -5998,15 +6039,17 @@ void GLES2DecoderImpl::RestoreStateForTextures() {
           continue;
         }
 
-        Texture* texture = texture_ref->texture();
-        gfx::GLImage* image =
-            texture->GetLevelImage(texture_unit.bind_target, 0);
-        if (image && !texture->IsAttachedToFramebuffer()) {
-          ScopedGLErrorSuppressor suppressor(
-              "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
-          glActiveTexture(GL_TEXTURE0 + texture_unit_index);
-          image->DidUseTexImage();
-          continue;
+        if (texture_unit.bind_target != GL_TEXTURE_CUBE_MAP) {
+          Texture* texture = texture_ref->texture();
+          gfx::GLImage* image =
+              texture->GetLevelImage(texture_unit.bind_target, 0);
+          if (image && !texture->IsAttachedToFramebuffer()) {
+            ScopedGLErrorSuppressor suppressor(
+                "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
+            glActiveTexture(GL_TEXTURE0 + texture_unit_index);
+            image->DidUseTexImage();
+            continue;
+          }
         }
       }
     }
@@ -6597,7 +6640,11 @@ void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
         vertex_translator_.get() : fragment_translator_.get();
   }
 
-  program_manager()->DoCompileShader(shader, translator, feature_info_.get());
+  program_manager()->DoCompileShader(
+     shader,
+     translator,
+     feature_info_->feature_flags().angle_translated_shader_source ?
+         ProgramManager::kANGLE : ProgramManager::kGL);
 };
 
 void GLES2DecoderImpl::DoGetShaderiv(
@@ -6647,7 +6694,7 @@ error::Error GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
   uint32 bucket_id = static_cast<uint32>(c.bucket_id);
   Bucket* bucket = CreateBucket(bucket_id);
   Shader* shader = GetShaderInfoNotProgram(
-      shader_id, "glTranslatedGetShaderSourceANGLE");
+      shader_id, "glGetTranslatedShaderSourceANGLE");
   if (!shader) {
     bucket->SetSize(0);
     return error::kNoError;
@@ -7257,7 +7304,7 @@ error::Error GLES2DecoderImpl::HandleReadPixels(
     return error::kNoError;
   }
 
-  LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixel");
+  LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixels");
 
   ScopedResolvedFrameBufferBinder binder(this, false, true);
 
@@ -7349,7 +7396,7 @@ error::Error GLES2DecoderImpl::HandlePixelStorei(
     case GL_UNPACK_ALIGNMENT:
         if (!validators_->pixel_store_alignment.IsValid(param)) {
             LOCAL_SET_GL_ERROR(
-                GL_INVALID_VALUE, "glPixelStore", "param GL_INVALID_VALUE");
+                GL_INVALID_VALUE, "glPixelStorei", "param GL_INVALID_VALUE");
             return error::kNoError;
         }
         break;
@@ -7478,7 +7525,7 @@ error::Error GLES2DecoderImpl::GetUniformLocationHelper(
     return error::kNoError;
   }
   Program* program = GetProgramInfoNotShader(
-      client_id, "glUniformLocation");
+      client_id, "glGetUniformLocation");
   if (!program) {
     return error::kNoError;
   }
@@ -7855,7 +7902,7 @@ bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
     case GL_ETC1_RGB8_OES: {
       LOCAL_SET_GL_ERROR(
           GL_INVALID_OPERATION, function_name,
-          "TexsubImage2d not supported for ECT1_RGB8_OES textures");
+          "not supported for ECT1_RGB8_OES textures");
       return false;
     }
     default:
@@ -8112,7 +8159,7 @@ void GLES2DecoderImpl::DoCompressedTexSubImage2D(
     return;
   }
   if (!texture->ValidForTexture(
-      target, level, xoffset, yoffset, width, height, format, type)) {
+      target, level, xoffset, yoffset, width, height, type)) {
     LOCAL_SET_GL_ERROR(
         GL_INVALID_VALUE, "glCompressedTexSubImage2D", "bad dimensions.");
     return;
@@ -8181,9 +8228,9 @@ void GLES2DecoderImpl::DoCopyTexImage2D(
         GL_INVALID_VALUE, "glCopyTexImage2D", "dimensions out of range");
     return;
   }
-  if (!texture_manager()->ValidateTextureParameters(
-      state_.GetErrorState(), "glCopyTexImage2D", target, internal_format,
-      GL_UNSIGNED_BYTE, level)) {
+  if (!texture_manager()->ValidateFormatAndTypeCombination(
+      state_.GetErrorState(), "glCopyTexImage2D", internal_format,
+      GL_UNSIGNED_BYTE)) {
     return;
   }
 
@@ -8296,7 +8343,7 @@ void GLES2DecoderImpl::DoCopyTexSubImage2D(
   GLenum format = 0;
   if (!texture->GetLevelType(target, level, &type, &format) ||
       !texture->ValidForTexture(
-          target, level, xoffset, yoffset, width, height, format, type)) {
+          target, level, xoffset, yoffset, width, height, type)) {
     LOCAL_SET_GL_ERROR(
         GL_INVALID_VALUE, "glCopyTexSubImage2D", "bad dimensions.");
     return;
@@ -8402,14 +8449,6 @@ bool GLES2DecoderImpl::ValidateTexSubImage2D(
     LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "height < 0");
     return false;
   }
-  if (!validators_->texture_format.IsValid(format)) {
-    LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
-    return false;
-  }
-  if (!validators_->pixel_type.IsValid(type)) {
-    LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type");
-    return false;
-  }
   TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
       &state_, target);
   if (!texture_ref) {
@@ -8426,10 +8465,8 @@ bool GLES2DecoderImpl::ValidateTexSubImage2D(
         GL_INVALID_OPERATION, function_name, "level does not exist.");
     return false;
   }
-  if (format != internal_format) {
-    LOCAL_SET_GL_ERROR(
-        GL_INVALID_OPERATION,
-        function_name, "format does not match internal format.");
+  if (!texture_manager()->ValidateTextureParameters(state_.GetErrorState(),
+      function_name, format, type, internal_format, level)) {
     return false;
   }
   if (type != current_type) {
@@ -8445,7 +8482,7 @@ bool GLES2DecoderImpl::ValidateTexSubImage2D(
     return false;
   }
   if (!texture->ValidForTexture(
-          target, level, xoffset, yoffset, width, height, format, type)) {
+          target, level, xoffset, yoffset, width, height, type)) {
     LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "bad dimensions.");
     return false;
   }
@@ -9102,7 +9139,7 @@ error::Error GLES2DecoderImpl::HandleGetMultipleIntegervCHROMIUM(
     uint32 num = util_.GLGetNumValuesReturned(enums[ii]);
     if (num == 0) {
       LOCAL_SET_GL_ERROR_INVALID_ENUM(
-          "glGetMulitpleCHROMIUM", enums[ii], "pname");
+          "glGetMultipleCHROMIUM", enums[ii], "pname");
       return error::kNoError;
     }
     // Num will never be more than 4.
@@ -9120,7 +9157,7 @@ error::Error GLES2DecoderImpl::HandleGetMultipleIntegervCHROMIUM(
   if (result_size != static_cast<uint32>(c.size)) {
     LOCAL_SET_GL_ERROR(
         GL_INVALID_VALUE,
-        "glGetMulitpleCHROMIUM", "bad size GL_INVALID_VALUE");
+        "glGetMultipleCHROMIUM", "bad size GL_INVALID_VALUE");
     return error::kNoError;
   }
 
@@ -9713,15 +9750,9 @@ void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
 
   int source_width, source_height, dest_width, dest_height;
 
-  if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
-    gfx::GLImage* image =
-        source_texture->GetLevelImage(source_texture->target(), 0);
-    if (!image) {
-      LOCAL_SET_GL_ERROR(
-          GL_INVALID_OPERATION,
-          "glCopyTextureChromium", "No external image");
-      return;
-    }
+  gfx::GLImage* image =
+      source_texture->GetLevelImage(source_texture->target(), 0);
+  if (image) {
     gfx::Size size = image->GetSize();
     source_width = size.width();
     source_height = size.height();
@@ -9749,6 +9780,14 @@ void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
     }
   }
 
+  // Clear the source texture if necessary.
+  if (!texture_manager()->ClearTextureLevel(
+          this, source_texture_ref, source_texture->target(), 0)) {
+    LOCAL_SET_GL_ERROR(
+        GL_OUT_OF_MEMORY, "glCopyTextureCHROMIUM", "dimensions too big");
+    return;
+  }
+
   // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
   // needed because it takes 10s of milliseconds to initialize.
   if (!copy_texture_CHROMIUM_.get()) {
@@ -9783,7 +9822,7 @@ void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
         0, internal_format, dest_type, NULL);
     GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
     if (error != GL_NO_ERROR) {
-      RestoreCurrentTexture2DBindings(&state_);
+      RestoreCurrentTextureBindings(&state_, GL_TEXTURE_2D);
       return;
     }
 
@@ -9960,10 +9999,15 @@ error::Error GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
 }
 
 void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target,
-                                                const GLbyte* mailbox) {
+                                                const GLbyte* data) {
   TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
       "context", logger_.GetLogPrefix(),
-      "mailbox[0]", static_cast<unsigned char>(mailbox[0]));
+      "mailbox[0]", static_cast<unsigned char>(data[0]));
+
+  const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
+  DLOG_IF(ERROR, !mailbox.Verify()) << "ProduceTextureCHROMIUM was passed a "
+                                       "mailbox that was not generated by "
+                                       "GenMailboxCHROMIUM.";
 
   TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
       &state_, target);
@@ -9982,22 +10026,18 @@ void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target,
     return;
   }
 
-  if (!group_->mailbox_manager()->ProduceTexture(
-      target,
-      *reinterpret_cast<const MailboxName*>(mailbox),
-      produced)) {
-    LOCAL_SET_GL_ERROR(
-        GL_INVALID_OPERATION,
-        "glProduceTextureCHROMIUM", "invalid mailbox name");
-    return;
-  }
+  group_->mailbox_manager()->ProduceTexture(target, mailbox, produced);
 }
 
 void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target,
-                                                const GLbyte* mailbox) {
+                                                const GLbyte* data) {
   TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
       "context", logger_.GetLogPrefix(),
-      "mailbox[0]", static_cast<unsigned char>(mailbox[0]));
+      "mailbox[0]", static_cast<unsigned char>(data[0]));
+  const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
+  DLOG_IF(ERROR, !mailbox.Verify()) << "ConsumeTextureCHROMIUM was passed a "
+                                       "mailbox that was not generated by "
+                                       "GenMailboxCHROMIUM.";
 
   scoped_refptr<TextureRef> texture_ref =
       texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
@@ -10014,10 +10054,7 @@ void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target,
         "glConsumeTextureCHROMIUM", "unknown texture for target");
     return;
   }
-  Texture* texture =
-      group_->mailbox_manager()->ConsumeTexture(
-      target,
-      *reinterpret_cast<const MailboxName*>(mailbox));
+  Texture* texture = group_->mailbox_manager()->ConsumeTexture(target, mailbox);
   if (!texture) {
     LOCAL_SET_GL_ERROR(
         GL_INVALID_OPERATION,
@@ -10084,6 +10121,13 @@ void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
     GLenum target, GLint image_id) {
   TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
 
+  if (target == GL_TEXTURE_CUBE_MAP) {
+    LOCAL_SET_GL_ERROR(
+        GL_INVALID_ENUM,
+        "glBindTexImage2DCHROMIUM", "invalid target");
+    return;
+  }
+
   // Default target might be conceptually valid, but disallow it to avoid
   // accidents.
   TextureRef* texture_ref =