Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / gpu / command_buffer / service / gles2_cmd_decoder.cc
index e68823d..65fc86d 100644 (file)
 
 #include "base/at_exit.h"
 #include "base/bind.h"
+#include "base/callback_helpers.h"
 #include "base/command_line.h"
 #include "base/debug/trace_event.h"
 #include "base/debug/trace_event_synthetic_delay.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/numerics/safe_math.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "build/build_config.h"
@@ -55,6 +57,7 @@
 #include "gpu/command_buffer/service/texture_manager.h"
 #include "gpu/command_buffer/service/vertex_array_manager.h"
 #include "gpu/command_buffer/service/vertex_attrib_manager.h"
+#include "third_party/smhasher/src/City.h"
 #include "ui/gl/gl_bindings.h"
 #include "ui/gl/gl_fence.h"
 #include "ui/gl/gl_image.h"
@@ -69,9 +72,6 @@
 #include "base/win/win_util.h"
 #endif
 
-// TODO(zmo): we can't include "City.h" due to type def conflicts.
-extern uint64 CityHash64(const char*, size_t);
-
 namespace gpu {
 namespace gles2 {
 
@@ -80,6 +80,7 @@ namespace {
 static const char kOESDerivativeExtension[] = "GL_OES_standard_derivatives";
 static const char kEXTFragDepthExtension[] = "GL_EXT_frag_depth";
 static const char kEXTDrawBuffersExtension[] = "GL_EXT_draw_buffers";
+static const char kEXTShaderTextureLodExtension[] = "GL_EXT_shader_texture_lod";
 
 #if !defined(ANGLE_SH_VERSION) || ANGLE_SH_VERSION < 108
 khronos_uint64_t CityHashForAngle(const char* name, unsigned int len) {
@@ -277,15 +278,6 @@ static bool StringIsValidForGLES(const char* str) {
   return true;
 }
 
-// Wrapper for glEnable/glDisable that doesn't suck.
-static void EnableDisable(GLenum pname, bool enable) {
-  if (enable) {
-    glEnable(pname);
-  } else {
-    glDisable(pname);
-  }
-}
-
 // This class prevents any GL errors that occur when it is in scope from
 // being reported to the client.
 class ScopedGLErrorSuppressor {
@@ -518,6 +510,29 @@ struct FenceCallback {
   scoped_ptr<gfx::GLFence> fence;
 };
 
+class AsyncUploadTokenCompletionObserver
+    : public AsyncPixelTransferCompletionObserver {
+ public:
+  explicit AsyncUploadTokenCompletionObserver(uint32 async_upload_token)
+      : async_upload_token_(async_upload_token) {
+  }
+
+  virtual void DidComplete(const AsyncMemoryParams& mem_params) OVERRIDE {
+    DCHECK(mem_params.buffer());
+    void* data = mem_params.GetDataAddress();
+    AsyncUploadSync* sync = static_cast<AsyncUploadSync*>(data);
+    sync->SetAsyncUploadToken(async_upload_token_);
+  }
+
+ private:
+  virtual ~AsyncUploadTokenCompletionObserver() {
+  }
+
+  uint32 async_upload_token_;
+
+  DISALLOW_COPY_AND_ASSIGN(AsyncUploadTokenCompletionObserver);
+};
+
 // }  // anonymous namespace.
 
 bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id,
@@ -586,14 +601,11 @@ class GLES2DecoderImpl : public GLES2Decoder,
       unsigned int target) const OVERRIDE {
     state_.RestoreActiveTextureUnitBinding(target);
   }
-  virtual void RestoreAttribute(unsigned index) const OVERRIDE {
-    state_.RestoreAttribute(index);
-  }
   virtual void RestoreBufferBindings() const OVERRIDE {
     state_.RestoreBufferBindings();
   }
   virtual void RestoreGlobalState() const OVERRIDE {
-    state_.RestoreGlobalState();
+    state_.RestoreGlobalState(NULL);
   }
   virtual void RestoreProgramBindings() const OVERRIDE {
     state_.RestoreProgramBindings();
@@ -640,6 +652,7 @@ class GLES2DecoderImpl : public GLES2Decoder,
   virtual void ResetAsyncPixelTransferManagerForTest() OVERRIDE;
   virtual void SetAsyncPixelTransferManagerForTest(
       AsyncPixelTransferManager* manager) OVERRIDE;
+  virtual void SetIgnoreCachedStateForTest(bool ignore) OVERRIDE;
   void ProcessFinishedAsyncTransfers();
 
   virtual bool GetServiceTextureId(uint32 client_texture_id,
@@ -717,6 +730,13 @@ class GLES2DecoderImpl : public GLES2Decoder,
   bool GenVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
   void DeleteVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
 
+  // Helper for async upload token completion notification callback.
+  base::Closure AsyncUploadTokenCompletionClosure(uint32 async_upload_token,
+                                                  uint32 sync_data_shm_id,
+                                                  uint32 sync_data_shm_offset);
+
+
+
   // Workarounds
   void OnFboChanged() const;
   void OnUseFramebuffer() const;
@@ -742,6 +762,10 @@ class GLES2DecoderImpl : public GLES2Decoder,
     return group_->shader_manager();
   }
 
+  ShaderTranslatorCache* shader_translator_cache() {
+    return group_->shader_translator_cache();
+  }
+
   const TextureManager* texture_manager() const {
     return group_->texture_manager();
   }
@@ -1073,9 +1097,12 @@ class GLES2DecoderImpl : public GLES2Decoder,
   }
 
   // Creates a vertex attrib manager for the given vertex array.
-  void CreateVertexAttribManager(GLuint client_id, GLuint service_id) {
+  scoped_refptr<VertexAttribManager> CreateVertexAttribManager(
+      GLuint client_id,
+      GLuint service_id,
+      bool client_visible) {
     return vertex_array_manager()->CreateVertexAttribManager(
-      client_id, service_id, group_->max_vertex_attribs());
+        client_id, service_id, group_->max_vertex_attribs(), client_visible);
   }
 
   void DoBindAttribLocation(GLuint client_id, GLuint index, const char* name);
@@ -1625,9 +1652,6 @@ class GLES2DecoderImpl : public GLES2Decoder,
   bool unpack_premultiply_alpha_;
   bool unpack_unpremultiply_alpha_;
 
-  // Default vertex attribs manager, used when no VAOs are bound.
-  scoped_refptr<VertexAttribManager> default_vertex_attrib_manager_;
-
   // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
   GLuint attrib_0_buffer_id_;
 
@@ -1721,6 +1745,7 @@ class GLES2DecoderImpl : public GLES2Decoder,
   bool derivatives_explicitly_enabled_;
   bool frag_depth_explicitly_enabled_;
   bool draw_buffers_explicitly_enabled_;
+  bool shader_texture_lod_explicitly_enabled_;
 
   bool compile_shader_always_succeeds_;
 
@@ -1899,7 +1924,7 @@ ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
   glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid);
   const int width = decoder_->offscreen_size_.width();
   const int height = decoder_->offscreen_size_.height();
-  glDisable(GL_SCISSOR_TEST);
+  decoder->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
   decoder->BlitFramebufferHelper(0,
                                  0,
                                  width,
@@ -1921,7 +1946,7 @@ ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
       "ScopedResolvedFrameBufferBinder::dtor", decoder_->GetErrorState());
   decoder_->RestoreCurrentFramebufferBindings();
   if (decoder_->state_.enable_flags.scissor_test) {
-    glEnable(GL_SCISSOR_TEST);
+    decoder_->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
   }
 }
 
@@ -2224,6 +2249,7 @@ GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
       derivatives_explicitly_enabled_(false),
       frag_depth_explicitly_enabled_(false),
       draw_buffers_explicitly_enabled_(false),
+      shader_texture_lod_explicitly_enabled_(false),
       compile_shader_always_succeeds_(false),
       lose_context_when_out_of_memory_(false),
       service_logging_(CommandLine::ForCurrentProcess()->HasSwitch(
@@ -2324,16 +2350,25 @@ bool GLES2DecoderImpl::Initialize(
   disallowed_features_ = disallowed_features;
 
   state_.attrib_values.resize(group_->max_vertex_attribs());
-  default_vertex_attrib_manager_ = new VertexAttribManager();
-  default_vertex_attrib_manager_->Initialize(
+  vertex_array_manager_.reset(new VertexArrayManager());
+
+  GLuint default_vertex_attrib_service_id = 0;
+  if (features().native_vertex_array_object) {
+    glGenVertexArraysOES(1, &default_vertex_attrib_service_id);
+    glBindVertexArrayOES(default_vertex_attrib_service_id);
+  }
+
+  state_.default_vertex_attrib_manager =
+      CreateVertexAttribManager(0, default_vertex_attrib_service_id, false);
+
+  state_.default_vertex_attrib_manager->Initialize(
       group_->max_vertex_attribs(),
       feature_info_->workarounds().init_vertex_attributes);
 
-  // vertex_attrib_manager is set to default_vertex_attrib_manager_ by this call
+  // vertex_attrib_manager is set to default_vertex_attrib_manager by this call
   DoBindVertexArrayOES(0);
 
   query_manager_.reset(new QueryManager(this, feature_info_.get()));
-  vertex_array_manager_.reset(new VertexArrayManager());
 
   util_.set_num_compressed_texture_formats(
       validators_->compressed_texture_format.GetValues().size());
@@ -2358,20 +2393,20 @@ bool GLES2DecoderImpl::Initialize(
       ref = texture_manager()->GetDefaultTextureInfo(
           GL_TEXTURE_EXTERNAL_OES);
       state_.texture_units[tt].bound_texture_external_oes = ref;
-      glBindTexture(GL_TEXTURE_EXTERNAL_OES, ref->service_id());
+      glBindTexture(GL_TEXTURE_EXTERNAL_OES, ref ? ref->service_id() : 0);
     }
     if (features().arb_texture_rectangle) {
       ref = texture_manager()->GetDefaultTextureInfo(
           GL_TEXTURE_RECTANGLE_ARB);
       state_.texture_units[tt].bound_texture_rectangle_arb = ref;
-      glBindTexture(GL_TEXTURE_RECTANGLE_ARB, ref->service_id());
+      glBindTexture(GL_TEXTURE_RECTANGLE_ARB, ref ? ref->service_id() : 0);
     }
     ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
     state_.texture_units[tt].bound_texture_cube_map = ref;
-    glBindTexture(GL_TEXTURE_CUBE_MAP, ref->service_id());
+    glBindTexture(GL_TEXTURE_CUBE_MAP, ref ? ref->service_id() : 0);
     ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
     state_.texture_units[tt].bound_texture_2d = ref;
-    glBindTexture(GL_TEXTURE_2D, ref->service_id());
+    glBindTexture(GL_TEXTURE_2D, ref ? ref->service_id() : 0);
   }
   glActiveTexture(GL_TEXTURE0);
   CHECK_GL_ERROR();
@@ -2562,8 +2597,8 @@ bool GLES2DecoderImpl::Initialize(
   state_.scissor_height = state_.viewport_height;
 
   // Set all the default state because some GL drivers get it wrong.
-  state_.InitCapabilities();
-  state_.InitState();
+  state_.InitCapabilities(NULL);
+  state_.InitState(NULL);
   glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
 
   DoBindBuffer(GL_ARRAY_BUFFER, 0);
@@ -2637,6 +2672,7 @@ Capabilities GLES2DecoderImpl::GetCapabilities() {
   caps.texture_storage = feature_info_->feature_flags().ext_texture_storage;
   caps.discard_framebuffer =
       feature_info_->feature_flags().ext_discard_framebuffer;
+  caps.sync_query = feature_info_->feature_flags().chromium_sync_query;
 
 #if defined(OS_MACOSX)
   // This is unconditionally true on mac, no need to test for it at runtime.
@@ -2644,6 +2680,7 @@ Capabilities GLES2DecoderImpl::GetCapabilities() {
 #endif
 
   caps.post_sub_buffer = supports_post_sub_buffer_;
+  caps.map_image = !!image_manager();
 
   return caps;
 }
@@ -2692,6 +2729,9 @@ bool GLES2DecoderImpl::InitializeShaderTranslator() {
     resources.EXT_draw_buffers = draw_buffers_explicitly_enabled_;
     if (!draw_buffers_explicitly_enabled_)
       resources.MaxDrawBuffers = 1;
+#if (ANGLE_SH_VERSION >= 123)
+    resources.EXT_shader_texture_lod = shader_texture_lod_explicitly_enabled_;
+#endif
   } else {
     resources.OES_standard_derivatives =
         features().oes_standard_derivatives ? 1 : 0;
@@ -2703,6 +2743,10 @@ bool GLES2DecoderImpl::InitializeShaderTranslator() {
         features().ext_draw_buffers ? 1 : 0;
     resources.EXT_frag_depth =
         features().ext_frag_depth ? 1 : 0;
+#if (ANGLE_SH_VERSION >= 123)
+    resources.EXT_shader_texture_lod =
+        features().ext_shader_texture_lod ? 1 : 0;
+#endif
   }
 
   ShShaderSpec shader_spec = force_webgl_glsl_validation_ ? SH_WEBGL_SPEC
@@ -2730,9 +2774,10 @@ bool GLES2DecoderImpl::InitializeShaderTranslator() {
   if (workarounds().unroll_for_loop_with_sampler_array_index)
     driver_bug_workarounds |= SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX;
 
-  ShaderTranslatorCache* cache = ShaderTranslatorCache::GetInstance();
-  vertex_translator_ = cache->GetTranslator(
-      SH_VERTEX_SHADER, shader_spec, &resources,
+  vertex_translator_ = shader_translator_cache()->GetTranslator(
+      SH_VERTEX_SHADER,
+      shader_spec,
+      &resources,
       implementation_type,
       static_cast<ShCompileOptions>(driver_bug_workarounds));
   if (!vertex_translator_.get()) {
@@ -2741,8 +2786,10 @@ bool GLES2DecoderImpl::InitializeShaderTranslator() {
     return false;
   }
 
-  fragment_translator_ = cache->GetTranslator(
-      SH_FRAGMENT_SHADER, shader_spec, &resources,
+  fragment_translator_ = shader_translator_cache()->GetTranslator(
+      SH_FRAGMENT_SHADER,
+      shader_spec,
+      &resources,
       implementation_type,
       static_cast<ShCompileOptions>(driver_bug_workarounds));
   if (!fragment_translator_.get()) {
@@ -3016,12 +3063,12 @@ bool GLES2DecoderImpl::CheckFramebufferValid(
     if (backbuffer_needs_clear_bits_) {
       glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
           offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
-      glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+      state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
       glClearStencil(0);
       glStencilMask(-1);
       glClearDepth(1.0f);
-      glDepthMask(true);
-      glDisable(GL_SCISSOR_TEST);
+      state_.SetDeviceDepthMask(GL_TRUE);
+      state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
       glClear(backbuffer_needs_clear_bits_);
       backbuffer_needs_clear_bits_ = 0;
       RestoreClearState();
@@ -3270,7 +3317,7 @@ void GLES2DecoderImpl::Destroy(bool have_context) {
 
   // Unbind everything.
   state_.vertex_attrib_manager = NULL;
-  default_vertex_attrib_manager_ = NULL;
+  state_.default_vertex_attrib_manager = NULL;
   state_.texture_units.clear();
   state_.bound_array_buffer = NULL;
   state_.current_queries.clear();
@@ -3377,6 +3424,11 @@ void GLES2DecoderImpl::Destroy(bool have_context) {
   offscreen_resolved_frame_buffer_.reset();
   offscreen_resolved_color_texture_.reset();
 
+  // Need to release these before releasing |group_| which may own the
+  // ShaderTranslatorCache.
+  fragment_translator_ = NULL;
+  vertex_translator_ = NULL;
+
   // Should destroy the transfer manager before the texture manager held
   // by the context group.
   async_pixel_transfer_manager_.reset();
@@ -3519,13 +3571,13 @@ bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
     ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
     glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
         offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
-    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+    state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
     glClearStencil(0);
-    glStencilMaskSeparate(GL_FRONT, -1);
-    glStencilMaskSeparate(GL_BACK, -1);
+    state_.SetDeviceStencilMaskSeparate(GL_FRONT, -1);
+    state_.SetDeviceStencilMaskSeparate(GL_BACK, -1);
     glClearDepth(0);
-    glDepthMask(GL_TRUE);
-    glDisable(GL_SCISSOR_TEST);
+    state_.SetDeviceDepthMask(GL_TRUE);
+    state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
     RestoreClearState();
   }
@@ -3788,23 +3840,25 @@ bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
 
 void GLES2DecoderImpl::ApplyDirtyState() {
   if (framebuffer_state_.clear_state_dirty) {
-    glColorMask(
-        state_.color_mask_red, state_.color_mask_green, state_.color_mask_blue,
-        state_.color_mask_alpha &&
-            BoundFramebufferHasColorAttachmentWithAlpha(true));
+    bool have_alpha = BoundFramebufferHasColorAttachmentWithAlpha(true);
+    state_.SetDeviceColorMask(state_.color_mask_red,
+                              state_.color_mask_green,
+                              state_.color_mask_blue,
+                              state_.color_mask_alpha && have_alpha);
+
     bool have_depth = BoundFramebufferHasDepthAttachment();
-    glDepthMask(state_.depth_mask && have_depth);
-    EnableDisable(GL_DEPTH_TEST, state_.enable_flags.depth_test && have_depth);
+    state_.SetDeviceDepthMask(state_.depth_mask && have_depth);
+
     bool have_stencil = BoundFramebufferHasStencilAttachment();
-    glStencilMaskSeparate(
+    state_.SetDeviceStencilMaskSeparate(
         GL_FRONT, have_stencil ? state_.stencil_front_writemask : 0);
-    glStencilMaskSeparate(
+    state_.SetDeviceStencilMaskSeparate(
         GL_BACK, have_stencil ? state_.stencil_back_writemask : 0);
-    EnableDisable(
+
+    state_.SetDeviceCapabilityState(
+        GL_DEPTH_TEST, state_.enable_flags.depth_test && have_depth);
+    state_.SetDeviceCapabilityState(
         GL_STENCIL_TEST, state_.enable_flags.stencil_test && have_stencil);
-    EnableDisable(GL_CULL_FACE, state_.enable_flags.cull_face);
-    EnableDisable(GL_SCISSOR_TEST, state_.enable_flags.scissor_test);
-    EnableDisable(GL_BLEND, state_.enable_flags.blend);
     framebuffer_state_.clear_state_dirty = false;
   }
 }
@@ -3860,6 +3914,11 @@ void GLES2DecoderImpl::RestoreTextureState(unsigned service_id) const {
 }
 
 void GLES2DecoderImpl::ClearAllAttributes() const {
+  // Must use native VAO 0, as RestoreAllAttributes can't fully restore
+  // other VAOs.
+  if (feature_info_->feature_flags().native_vertex_array_object)
+    glBindVertexArrayOES(0);
+
   for (uint32 i = 0; i < group_->max_vertex_attribs(); ++i) {
     if (i != 0) // Never disable attribute 0
       glDisableVertexAttribArray(i);
@@ -3869,8 +3928,11 @@ void GLES2DecoderImpl::ClearAllAttributes() const {
 }
 
 void GLES2DecoderImpl::RestoreAllAttributes() const {
-  for (uint32 i = 0; i < group_->max_vertex_attribs(); ++i)
-    RestoreAttribute(i);
+  state_.RestoreVertexAttribs();
+}
+
+void GLES2DecoderImpl::SetIgnoreCachedStateForTest(bool ignore) {
+  state_.SetIgnoreCachedStateForTest(ignore);
 }
 
 void GLES2DecoderImpl::OnFboChanged() const {
@@ -3997,21 +4059,25 @@ void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
   } else {
     texture_ref = texture_manager()->GetDefaultTextureInfo(target);
   }
-  Texture* texture = texture_ref->texture();
 
   // Check the texture exists
-  // Check that we are not trying to bind it to a different target.
-  if (texture->target() != 0 && texture->target() != target) {
-    LOCAL_SET_GL_ERROR(
-        GL_INVALID_OPERATION,
-        "glBindTexture", "texture bound to more than 1 target.");
-    return;
-  }
-  LogClientServiceForInfo(texture, client_id, "glBindTexture");
-  if (texture->target() == 0) {
-    texture_manager()->SetTarget(texture_ref, target);
+  if (texture_ref) {
+    Texture* texture = texture_ref->texture();
+    // Check that we are not trying to bind it to a different target.
+    if (texture->target() != 0 && texture->target() != target) {
+      LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
+                         "glBindTexture",
+                         "texture bound to more than 1 target.");
+      return;
+    }
+    LogClientServiceForInfo(texture, client_id, "glBindTexture");
+    if (texture->target() == 0) {
+      texture_manager()->SetTarget(texture_ref, target);
+    }
+    glBindTexture(target, texture->service_id());
+  } else {
+    glBindTexture(target, 0);
   }
-  glBindTexture(target, texture->service_id());
 
   TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
   unit.bind_target = target;
@@ -4439,7 +4505,7 @@ bool GLES2DecoderImpl::GetHelper(
       *num_written = 1;
       if (params) {
         if (state_.vertex_attrib_manager.get() !=
-            default_vertex_attrib_manager_.get()) {
+            state_.default_vertex_attrib_manager.get()) {
           GLuint client_id = 0;
           vertex_array_manager_->GetClientId(
               state_.vertex_attrib_manager->service_id(), &client_id);
@@ -4511,14 +4577,12 @@ bool GLES2DecoderImpl::GetHelper(
         params[0] = unpack_unpremultiply_alpha_;
       }
       return true;
-#if defined(OS_CHROMEOS)
     case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
       *num_written = 1;
       if (params) {
         params[0] = group_->bind_generates_resource() ? 1 : 0;
       }
       return true;
-#endif
     default:
       if (pname >= GL_DRAW_BUFFER0_ARB &&
           pname < GL_DRAW_BUFFER0_ARB + group_->max_draw_buffers()) {
@@ -4654,7 +4718,7 @@ error::Error GLES2DecoderImpl::HandleBindAttribLocation(
   if (name == NULL) {
     return error::kOutOfBounds;
   }
-  String name_str(name, name_size);
+  std::string name_str(name, name_size);
   DoBindAttribLocation(program, index, name_str.c_str());
   return error::kNoError;
 }
@@ -4719,7 +4783,7 @@ error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUM(
   if (name == NULL) {
     return error::kOutOfBounds;
   }
-  String name_str(name, name_size);
+  std::string name_str(name, name_size);
   DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
   return error::kNoError;
 }
@@ -4964,7 +5028,7 @@ void GLES2DecoderImpl::ClearUnclearedAttachments(
         (GLES2Util::GetChannelsForFormat(
              framebuffer->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f :
                                                                        1.0f);
-    glColorMask(true, true, true, true);
+    state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
     clear_bits |= GL_COLOR_BUFFER_BIT;
   }
 
@@ -4978,11 +5042,11 @@ void GLES2DecoderImpl::ClearUnclearedAttachments(
   if (framebuffer->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
       framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
     glClearDepth(1.0f);
-    glDepthMask(true);
+    state_.SetDeviceDepthMask(GL_TRUE);
     clear_bits |= GL_DEPTH_BUFFER_BIT;
   }
 
-  glDisable(GL_SCISSOR_TEST);
+  state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
   glClear(clear_bits);
 
   framebuffer_manager()->MarkAttachmentsAsCleared(
@@ -5008,7 +5072,7 @@ void GLES2DecoderImpl::RestoreClearState() {
   glClearStencil(state_.stencil_clear);
   glClearDepth(state_.depth_clear);
   if (state_.enable_flags.scissor_test) {
-    glEnable(GL_SCISSOR_TEST);
+    state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
   }
 }
 
@@ -5185,10 +5249,11 @@ void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM(
     return;
   }
 
-  glDisable(GL_SCISSOR_TEST);
+  state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
   BlitFramebufferHelper(
       srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
-  EnableDisable(GL_SCISSOR_TEST, state_.enable_flags.scissor_test);
+  state_.SetDeviceCapabilityState(GL_SCISSOR_TEST,
+                                  state_.enable_flags.scissor_test);
 }
 
 void GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(
@@ -5427,11 +5492,11 @@ bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity(
   GLboolean scissor_enabled = false;
   glGetBooleanv(GL_SCISSOR_TEST, &scissor_enabled);
   if (scissor_enabled)
-    glDisable(GL_SCISSOR_TEST);
+    state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
 
-  GLboolean color_mask[4] = {true, true, true, true};
+  GLboolean color_mask[4] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE};
   glGetBooleanv(GL_COLOR_WRITEMASK, color_mask);
-  glColorMask(true, true, true, true);
+  state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
 
   GLfloat clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f};
   glGetFloatv(GL_COLOR_CLEAR_VALUE, clear_color);
@@ -5460,9 +5525,10 @@ bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity(
 
   // Restore cached state.
   if (scissor_enabled)
-    glEnable(GL_SCISSOR_TEST);
+    state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
 
-  glColorMask(color_mask[0], color_mask[1], color_mask[2], color_mask[3]);
+  state_.SetDeviceColorMask(
+      color_mask[0], color_mask[1], color_mask[2], color_mask[3]);
   glClearColor(clear_color[0], clear_color[1], clear_color[2], clear_color[3]);
   glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, draw_framebuffer);
   glBindFramebufferEXT(GL_READ_FRAMEBUFFER, read_framebuffer);
@@ -7039,7 +7105,7 @@ error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
   if (!state_.bound_array_buffer.get() ||
       state_.bound_array_buffer->IsDeleted()) {
     if (state_.vertex_attrib_manager.get() ==
-        default_vertex_attrib_manager_.get()) {
+        state_.default_vertex_attrib_manager.get()) {
       LOCAL_SET_GL_ERROR(
           GL_INVALID_VALUE, "glVertexAttribPointer", "no array buffer bound");
       return error::kNoError;
@@ -7491,6 +7557,9 @@ error::Error GLES2DecoderImpl::HandlePixelStorei(
 error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
     uint32 immediate_data_size, const cmds::PostSubBufferCHROMIUM& c) {
   TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
+  {
+    TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
+  }
   if (!supports_post_sub_buffer_) {
     LOCAL_SET_GL_ERROR(
         GL_INVALID_OPERATION,
@@ -7514,6 +7583,16 @@ error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
   }
 }
 
+error::Error GLES2DecoderImpl::HandleScheduleOverlayPlaneCHROMIUM(
+    uint32 immediate_data_size,
+    const cmds::ScheduleOverlayPlaneCHROMIUM& c) {
+  NOTIMPLEMENTED() << "Overlay supported isn't finished.";
+  LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
+                     "glScheduleOverlayPlaneCHROMIUM",
+                     "function not implemented");
+  return error::kNoError;
+}
+
 error::Error GLES2DecoderImpl::GetAttribLocationHelper(
     GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
     const std::string& name_str) {
@@ -7554,7 +7633,7 @@ error::Error GLES2DecoderImpl::HandleGetAttribLocation(
   if (!name) {
     return error::kOutOfBounds;
   }
-  String name_str(name, name_size);
+  std::string name_str(name, name_size);
   return GetAttribLocationHelper(
     c.program, c.location_shm_id, c.location_shm_offset, name_str);
 }
@@ -7613,7 +7692,7 @@ error::Error GLES2DecoderImpl::HandleGetUniformLocation(
   if (!name) {
     return error::kOutOfBounds;
   }
-  String name_str(name, name_size);
+  std::string name_str(name, name_size);
   return GetUniformLocationHelper(
     c.program, c.location_shm_id, c.location_shm_offset, name_str);
 }
@@ -7682,6 +7761,14 @@ error::Error GLES2DecoderImpl::HandleGetString(
                                  std::string());
             }
           }
+          if (!shader_texture_lod_explicitly_enabled_) {
+            size_t offset = extensions.find(kEXTShaderTextureLodExtension);
+            if (std::string::npos != offset) {
+              extensions.replace(offset,
+                                 arraysize(kEXTShaderTextureLodExtension),
+                                 std::string());
+            }
+          }
         } else {
           extensions = feature_info_->extensions().c_str();
         }
@@ -7757,8 +7844,8 @@ bool GLES2DecoderImpl::ClearLevel(
     glClearStencil(0);
     glStencilMask(-1);
     glClearDepth(1.0f);
-    glDepthMask(true);
-    glDisable(GL_SCISSOR_TEST);
+    state_.SetDeviceDepthMask(GL_TRUE);
+    state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
     glClear(GL_DEPTH_BUFFER_BIT | (have_stencil ? GL_STENCIL_BUFFER_BIT : 0));
 
     RestoreClearState();
@@ -7832,15 +7919,17 @@ const int kS3TCBlockWidth = 4;
 const int kS3TCBlockHeight = 4;
 const int kS3TCDXT1BlockSize = 8;
 const int kS3TCDXT3AndDXT5BlockSize = 16;
-const int kETC1BlockWidth = 4;
-const int kETC1BlockHeight = 4;
-const int kETC1BlockSize = 8;
 
 bool IsValidDXTSize(GLint level, GLsizei size) {
   return (size == 1) ||
          (size == 2) || !(size % kS3TCBlockWidth);
 }
 
+bool IsValidPVRTCSize(GLint level, GLsizei size) {
+  // Ensure that the size is a power of two
+  return (size & (size - 1)) == 0;
+}
+
 }  // anonymous namespace.
 
 bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
@@ -7849,8 +7938,10 @@ bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
   unsigned int bytes_required = 0;
 
   switch (format) {
+    case GL_ATC_RGB_AMD:
     case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
-    case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: {
+    case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+    case GL_ETC1_RGB8_OES: {
         int num_blocks_across =
             (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
         int num_blocks_down =
@@ -7859,6 +7950,8 @@ bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
         bytes_required = num_blocks * kS3TCDXT1BlockSize;
         break;
       }
+    case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
+    case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
     case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
     case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
         int num_blocks_across =
@@ -7869,13 +7962,14 @@ bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
         bytes_required = num_blocks * kS3TCDXT3AndDXT5BlockSize;
         break;
       }
-    case GL_ETC1_RGB8_OES: {
-        int num_blocks_across =
-            (width + kETC1BlockWidth - 1) / kETC1BlockWidth;
-        int num_blocks_down =
-            (height + kETC1BlockHeight - 1) / kETC1BlockHeight;
-        int num_blocks = num_blocks_across * num_blocks_down;
-        bytes_required = num_blocks * kETC1BlockSize;
+    case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
+    case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG: {
+        bytes_required = (std::max(width, 8) * std::max(height, 8) * 4 + 7)/8;
+        break;
+      }
+    case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
+    case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
+        bytes_required = (std::max(width, 16) * std::max(height, 8) * 2 + 7)/8;
         break;
       }
     default:
@@ -7908,7 +8002,10 @@ bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
       }
       return true;
     }
-    case GL_ETC1_RGB8_OES:
+    case GL_ATC_RGB_AMD:
+    case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
+    case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
+    case GL_ETC1_RGB8_OES: {
       if (width <= 0 || height <= 0) {
         LOCAL_SET_GL_ERROR(
             GL_INVALID_OPERATION, function_name,
@@ -7916,6 +8013,20 @@ bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
         return false;
       }
       return true;
+    }
+    case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
+    case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
+    case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
+    case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
+      if (!IsValidPVRTCSize(level, width) ||
+          !IsValidPVRTCSize(level, height)) {
+        LOCAL_SET_GL_ERROR(
+            GL_INVALID_OPERATION, function_name,
+            "width or height invalid for level");
+        return false;
+      }
+      return true;
+    }
     default:
       return false;
   }
@@ -7957,12 +8068,43 @@ bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
       return ValidateCompressedTexDimensions(
           function_name, level, width, height, format);
     }
+    case GL_ATC_RGB_AMD:
+    case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
+    case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD: {
+      LOCAL_SET_GL_ERROR(
+          GL_INVALID_OPERATION, function_name,
+          "not supported for ATC textures");
+      return false;
+    }
     case GL_ETC1_RGB8_OES: {
       LOCAL_SET_GL_ERROR(
           GL_INVALID_OPERATION, function_name,
           "not supported for ECT1_RGB8_OES textures");
       return false;
     }
+    case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
+    case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
+    case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
+    case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
+      if ((xoffset != 0) || (yoffset != 0)) {
+        LOCAL_SET_GL_ERROR(
+            GL_INVALID_OPERATION, function_name,
+            "xoffset and yoffset must be zero");
+        return false;
+      }
+      GLsizei tex_width = 0;
+      GLsizei tex_height = 0;
+      if (!texture->GetLevelSize(target, level, &tex_width, &tex_height) ||
+          width != tex_width ||
+          height != tex_height) {
+        LOCAL_SET_GL_ERROR(
+            GL_INVALID_OPERATION, function_name,
+            "dimensions must match existing texture level dimensions");
+        return false;
+      }
+      return ValidateCompressedTexDimensions(
+          function_name, level, width, height, format);
+    }
     default:
       return false;
   }
@@ -8981,7 +9123,7 @@ void GLES2DecoderImpl::DoSwapBuffers() {
                "offscreen", is_offscreen,
                "frame", this_frame_number);
   {
-    TRACE_EVENT_SYNTHETIC_DELAY("gpu.SwapBuffers");
+    TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
   }
 
   bool is_tracing;
@@ -9029,8 +9171,8 @@ void GLES2DecoderImpl::DoSwapBuffers() {
           ScopedFrameBufferBinder binder(this,
                                          offscreen_saved_frame_buffer_->id());
           glClearColor(0, 0, 0, 0);
-          glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
-          glDisable(GL_SCISSOR_TEST);
+          state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+          state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
           glClear(GL_COLOR_BUFFER_BIT);
           RestoreClearState();
         }
@@ -9154,6 +9296,7 @@ error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
   bool desire_standard_derivatives = false;
   bool desire_frag_depth = false;
   bool desire_draw_buffers = false;
+  bool desire_shader_texture_lod = false;
   if (force_webgl_glsl_validation_) {
     desire_standard_derivatives =
         feature_str.find("GL_OES_standard_derivatives") != std::string::npos;
@@ -9161,6 +9304,8 @@ error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
         feature_str.find("GL_EXT_frag_depth") != std::string::npos;
     desire_draw_buffers =
         feature_str.find("GL_EXT_draw_buffers") != std::string::npos;
+    desire_shader_texture_lod =
+        feature_str.find("GL_EXT_shader_texture_lod") != std::string::npos;
   }
 
   if (desire_webgl_glsl_validation != force_webgl_glsl_validation_ ||
@@ -9171,6 +9316,7 @@ error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
     derivatives_explicitly_enabled_ |= desire_standard_derivatives;
     frag_depth_explicitly_enabled_ |= desire_frag_depth;
     draw_buffers_explicitly_enabled_ |= desire_draw_buffers;
+    shader_texture_lod_explicitly_enabled_ |= desire_shader_texture_lod;
     InitializeShaderTranslator();
   }
 
@@ -9378,7 +9524,7 @@ bool GLES2DecoderImpl::GenQueriesEXTHelper(
       return false;
     }
   }
-  // NOTE: We don't generate Query objects here. Only in BeginQueryEXT
+  query_manager_->GenQueries(n, client_ids);
   return true;
 }
 
@@ -9393,8 +9539,8 @@ void GLES2DecoderImpl::DeleteQueriesEXTHelper(
         state_.current_queries.erase(it);
 
       query->Destroy(true);
-      query_manager_->RemoveQuery(client_ids[ii]);
     }
+    query_manager_->RemoveQuery(client_ids[ii]);
   }
 }
 
@@ -9457,6 +9603,14 @@ error::Error GLES2DecoderImpl::HandleBeginQueryEXT(
     case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM:
     case GL_GET_ERROR_QUERY_CHROMIUM:
       break;
+    case GL_COMMANDS_COMPLETED_CHROMIUM:
+      if (!features().chromium_sync_query) {
+        LOCAL_SET_GL_ERROR(
+            GL_INVALID_OPERATION, "glBeginQueryEXT",
+            "not enabled for commands completed queries");
+        return error::kNoError;
+      }
+      break;
     default:
       if (!features().occlusion_query_boolean) {
         LOCAL_SET_GL_ERROR(
@@ -9480,24 +9634,12 @@ error::Error GLES2DecoderImpl::HandleBeginQueryEXT(
 
   QueryManager::Query* query = query_manager_->GetQuery(client_id);
   if (!query) {
-    // TODO(gman): Decide if we need this check.
-    //
-    // Checks id was made by glGenQueries
-    //
-    // From the POV of OpenGL ES 2.0 you need to call glGenQueriesEXT
-    // for all Query ids but from the POV of the command buffer service maybe
-    // you don't.
-    //
-    // The client can enforce this. I don't think the service cares.
-    //
-    // IdAllocatorInterface* id_allocator =
-    //     group_->GetIdAllocator(id_namespaces::kQueries);
-    // if (!id_allocator->InUse(client_id)) {
-    //   LOCAL_SET_GL_ERROR(
-    //       GL_INVALID_OPERATION,
-    //       "glBeginQueryEXT", "id not made by glGenQueriesEXT");
-    //   return error::kNoError;
-    // }
+    if (!query_manager_->IsValidQuery(client_id)) {
+      LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
+                         "glBeginQueryEXT",
+                         "id not made by glGenQueriesEXT");
+      return error::kNoError;
+    }
     query = query_manager_->CreateQuery(
         target, client_id, sync_shm_id, sync_shm_offset);
   }
@@ -9554,14 +9696,14 @@ bool GLES2DecoderImpl::GenVertexArraysOESHelper(
   if (!features().native_vertex_array_object) {
     // Emulated VAO
     for (GLsizei ii = 0; ii < n; ++ii) {
-      CreateVertexAttribManager(client_ids[ii], 0);
+      CreateVertexAttribManager(client_ids[ii], 0, true);
     }
   } else {
     scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
 
     glGenVertexArraysOES(n, service_ids.get());
     for (GLsizei ii = 0; ii < n; ++ii) {
-      CreateVertexAttribManager(client_ids[ii], service_ids[ii]);
+      CreateVertexAttribManager(client_ids[ii], service_ids[ii], true);
     }
   }
 
@@ -9575,7 +9717,7 @@ void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
         GetVertexAttribManager(client_ids[ii]);
     if (vao && !vao->IsDeleted()) {
       if (state_.vertex_attrib_manager.get() == vao) {
-        state_.vertex_attrib_manager = default_vertex_attrib_manager_;
+        DoBindVertexArrayOES(0);
       }
       RemoveVertexAttribManager(client_ids[ii]);
     }
@@ -9584,7 +9726,6 @@ void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
 
 void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id) {
   VertexAttribManager* vao = NULL;
-  GLuint service_id = 0;
   if (client_id != 0) {
     vao = GetVertexAttribManager(client_id);
     if (!vao) {
@@ -9596,11 +9737,9 @@ void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id) {
           "glBindVertexArrayOES", "bad vertex array id.");
       current_decoder_error_ = error::kNoError;
       return;
-    } else {
-      service_id = vao->service_id();
     }
   } else {
-    vao = default_vertex_attrib_manager_.get();
+    vao = state_.default_vertex_attrib_manager.get();
   }
 
   // Only set the VAO state if it's changed
@@ -9609,6 +9748,7 @@ void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id) {
     if (!features().native_vertex_array_object) {
       EmulateVertexArrayState();
     } else {
+      GLuint service_id = vao->service_id();
       glBindVertexArrayOES(service_id);
     }
   }
@@ -9788,6 +9928,8 @@ static GLenum ExtractFormatFromStorageFormat(GLenum internalformat) {
 void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
     GLenum target, GLuint source_id, GLuint dest_id, GLint level,
     GLenum internal_format, GLenum dest_type) {
+  TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopyTextureCHROMIUM");
+
   TextureRef* dest_texture_ref = GetTexture(dest_id);
   TextureRef* source_texture_ref = GetTexture(source_id);
 
@@ -9807,7 +9949,8 @@ void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
   Texture* dest_texture = dest_texture_ref->texture();
   if (dest_texture->target() != GL_TEXTURE_2D ||
       (source_texture->target() != GL_TEXTURE_2D &&
-      source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) {
+       source_texture->target() != GL_TEXTURE_RECTANGLE_ARB &&
+       source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) {
     LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
                        "glCopyTextureCHROMIUM",
                        "invalid texture target binding");
@@ -10375,6 +10518,29 @@ bool GLES2DecoderImpl::ValidateAsyncTransfer(
   return true;
 }
 
+base::Closure GLES2DecoderImpl::AsyncUploadTokenCompletionClosure(
+    uint32 async_upload_token,
+    uint32 sync_data_shm_id,
+    uint32 sync_data_shm_offset) {
+  scoped_refptr<gpu::Buffer> buffer = GetSharedMemoryBuffer(sync_data_shm_id);
+  if (!buffer || !buffer->GetDataAddress(sync_data_shm_offset,
+                                         sizeof(AsyncUploadSync)))
+    return base::Closure();
+
+  AsyncMemoryParams mem_params(buffer,
+                               sync_data_shm_offset,
+                               sizeof(AsyncUploadSync));
+
+  scoped_refptr<AsyncUploadTokenCompletionObserver> observer(
+      new AsyncUploadTokenCompletionObserver(async_upload_token));
+
+  return base::Bind(
+      &AsyncPixelTransferManager::AsyncNotifyCompletion,
+      base::Unretained(GetAsyncPixelTransferManager()),
+      mem_params,
+      observer);
+}
+
 error::Error GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
     uint32 immediate_data_size, const cmds::AsyncTexImage2DCHROMIUM& c) {
   TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
@@ -10391,6 +10557,21 @@ error::Error GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
   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;
+  uint32 async_upload_token = static_cast<uint32>(c.async_upload_token);
+  uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id);
+  uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
+
+  base::ScopedClosureRunner scoped_completion_callback;
+  if (async_upload_token) {
+    base::Closure completion_closure =
+        AsyncUploadTokenCompletionClosure(async_upload_token,
+                                          sync_data_shm_id,
+                                          sync_data_shm_offset);
+    if (completion_closure.is_null())
+      return error::kInvalidArguments;
+
+    scoped_completion_callback.Reset(completion_closure);
+  }
 
   // TODO(epenner): Move this and copies of this memory validation
   // into ValidateTexImage2D step.
@@ -10477,6 +10658,21 @@ error::Error GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
   GLsizei height = static_cast<GLsizei>(c.height);
   GLenum format = static_cast<GLenum>(c.format);
   GLenum type = static_cast<GLenum>(c.type);
+  uint32 async_upload_token = static_cast<uint32>(c.async_upload_token);
+  uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id);
+  uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
+
+  base::ScopedClosureRunner scoped_completion_callback;
+  if (async_upload_token) {
+    base::Closure completion_closure =
+        AsyncUploadTokenCompletionClosure(async_upload_token,
+                                          sync_data_shm_id,
+                                          sync_data_shm_offset);
+    if (completion_closure.is_null())
+      return error::kInvalidArguments;
+
+    scoped_completion_callback.Reset(completion_closure);
+  }
 
   // TODO(epenner): Move this and copies of this memory validation
   // into ValidateTexSubImage2D step.
@@ -10579,6 +10775,15 @@ error::Error GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
   return error::kNoError;
 }
 
+error::Error GLES2DecoderImpl::HandleWaitAllAsyncTexImage2DCHROMIUM(
+    uint32 immediate_data_size, const cmds::WaitAllAsyncTexImage2DCHROMIUM& c) {
+  TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
+
+  GetAsyncPixelTransferManager()->WaitAllAsyncTexImage2D();
+  ProcessFinishedAsyncTransfers();
+  return error::kNoError;
+}
+
 void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
     TextureRef* texture_ref) {
   Texture* texture = texture_ref->texture();