Decouple ErrorState and ContextState.

Bug: 902904
Change-Id: Idaf970c574597d2436befccc4f0979392c125d89
Reviewed-on: https://chromium-review.googlesource.com/c/1362220
Reviewed-by: Antoine Labour <piman@chromium.org>
Commit-Queue: Peng Huang <penghuang@chromium.org>
Cr-Commit-Position: refs/heads/master@{#613851}
diff --git a/gpu/command_buffer/service/buffer_manager.cc b/gpu/command_buffer/service/buffer_manager.cc
index 493762d..3b71045 100644
--- a/gpu/command_buffer/service/buffer_manager.cc
+++ b/gpu/command_buffer/service/buffer_manager.cc
@@ -426,10 +426,12 @@
   memory_type_tracker_->TrackMemAlloc(buffer->size());
 }
 
-void BufferManager::ValidateAndDoBufferData(
-    ContextState* context_state, GLenum target, GLsizeiptr size,
-    const GLvoid* data, GLenum usage) {
-  ErrorState* error_state = context_state->GetErrorState();
+void BufferManager::ValidateAndDoBufferData(ContextState* context_state,
+                                            ErrorState* error_state,
+                                            GLenum target,
+                                            GLsizeiptr size,
+                                            const GLvoid* data,
+                                            GLenum usage) {
   if (!feature_info_->validators()->buffer_target.IsValid(target)) {
     ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
         error_state, "glBufferData", target, "target");
@@ -475,7 +477,6 @@
   }
 }
 
-
 void BufferManager::DoBufferData(
     ErrorState* error_state,
     Buffer* buffer,
@@ -514,11 +515,14 @@
   SetInfo(buffer, target, size, usage, use_shadow);
 }
 
-void BufferManager::ValidateAndDoBufferSubData(
-  ContextState* context_state, GLenum target, GLintptr offset, GLsizeiptr size,
-  const GLvoid * data) {
-  Buffer* buffer = RequestBufferAccess(context_state, target, offset, size,
-                                       "glBufferSubData");
+void BufferManager::ValidateAndDoBufferSubData(ContextState* context_state,
+                                               ErrorState* error_state,
+                                               GLenum target,
+                                               GLintptr offset,
+                                               GLsizeiptr size,
+                                               const GLvoid* data) {
+  Buffer* buffer = RequestBufferAccess(context_state, error_state, target,
+                                       offset, size, "glBufferSubData");
   if (!buffer) {
     return;
   }
@@ -535,20 +539,23 @@
   }
 }
 
-void BufferManager::ValidateAndDoCopyBufferSubData(
-    ContextState* context_state, GLenum readtarget, GLenum writetarget,
-    GLintptr readoffset, GLintptr writeoffset, GLsizeiptr size) {
+void BufferManager::ValidateAndDoCopyBufferSubData(ContextState* context_state,
+                                                   ErrorState* error_state,
+                                                   GLenum readtarget,
+                                                   GLenum writetarget,
+                                                   GLintptr readoffset,
+                                                   GLintptr writeoffset,
+                                                   GLsizeiptr size) {
   const char* func_name = "glCopyBufferSubData";
-  Buffer* readbuffer = RequestBufferAccess(context_state, readtarget,
-                                           readoffset, size, func_name);
+  Buffer* readbuffer = RequestBufferAccess(
+      context_state, error_state, readtarget, readoffset, size, func_name);
   if (!readbuffer)
     return;
-  Buffer* writebuffer = RequestBufferAccess(context_state, writetarget,
-                                            writeoffset, size, func_name);
+  Buffer* writebuffer = RequestBufferAccess(
+      context_state, error_state, writetarget, writeoffset, size, func_name);
   if (!writebuffer)
     return;
 
-  ErrorState* error_state = context_state->GetErrorState();
   if (readbuffer == writebuffer &&
       ((writeoffset >= readoffset && writeoffset < readoffset + size) ||
        (readoffset >= writeoffset && readoffset < writeoffset + size))) {
@@ -592,12 +599,16 @@
 }
 
 void BufferManager::ValidateAndDoGetBufferParameteri64v(
-    ContextState* context_state, GLenum target, GLenum pname, GLint64* params) {
+    ContextState* context_state,
+    ErrorState* error_state,
+    GLenum target,
+    GLenum pname,
+    GLint64* params) {
   Buffer* buffer = GetBufferInfoForTarget(context_state, target);
   if (!buffer) {
-    ERRORSTATE_SET_GL_ERROR(
-        context_state->GetErrorState(), GL_INVALID_OPERATION,
-        "glGetBufferParameteri64v", "no buffer bound for target");
+    ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_OPERATION,
+                            "glGetBufferParameteri64v",
+                            "no buffer bound for target");
     return;
   }
   switch (pname) {
@@ -622,12 +633,16 @@
 }
 
 void BufferManager::ValidateAndDoGetBufferParameteriv(
-    ContextState* context_state, GLenum target, GLenum pname, GLint* params) {
+    ContextState* context_state,
+    ErrorState* error_state,
+    GLenum target,
+    GLenum pname,
+    GLint* params) {
   Buffer* buffer = GetBufferInfoForTarget(context_state, target);
   if (!buffer) {
-    ERRORSTATE_SET_GL_ERROR(
-        context_state->GetErrorState(), GL_INVALID_OPERATION,
-        "glGetBufferParameteriv", "no buffer bound for target");
+    ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_OPERATION,
+                            "glGetBufferParameteriv",
+                            "no buffer bound for target");
     return;
   }
   switch (pname) {
@@ -788,13 +803,12 @@
 }
 
 Buffer* BufferManager::RequestBufferAccess(ContextState* context_state,
+                                           ErrorState* error_state,
                                            GLenum target,
                                            GLintptr offset,
                                            GLsizeiptr size,
                                            const char* func_name) {
   DCHECK(context_state);
-  ErrorState* error_state = context_state->GetErrorState();
-
   Buffer* buffer = GetBufferInfoForTarget(context_state, target);
   if (!RequestBufferAccess(error_state, buffer, func_name,
                            "bound to target 0x%04x", target)) {
@@ -811,11 +825,10 @@
 }
 
 Buffer* BufferManager::RequestBufferAccess(ContextState* context_state,
+                                           ErrorState* error_state,
                                            GLenum target,
                                            const char* func_name) {
   DCHECK(context_state);
-  ErrorState* error_state = context_state->GetErrorState();
-
   Buffer* buffer = GetBufferInfoForTarget(context_state, target);
   return RequestBufferAccess(error_state, buffer, func_name,
                              "bound to target 0x%04x", target)
diff --git a/gpu/command_buffer/service/buffer_manager.h b/gpu/command_buffer/service/buffer_manager.h
index c21ea41..b9210a3 100644
--- a/gpu/command_buffer/service/buffer_manager.h
+++ b/gpu/command_buffer/service/buffer_manager.h
@@ -268,32 +268,47 @@
 
   // Validates a glBufferSubData, and then calls DoBufferData if validation was
   // successful.
-  void ValidateAndDoBufferSubData(
-      ContextState* context_state, GLenum target, GLintptr offset,
-      GLsizeiptr size, const GLvoid * data);
+  void ValidateAndDoBufferSubData(ContextState* context_state,
+                                  ErrorState* error_state,
+                                  GLenum target,
+                                  GLintptr offset,
+                                  GLsizeiptr size,
+                                  const GLvoid* data);
 
   // Validates a glBufferData, and then calls DoBufferData if validation was
   // successful.
-  void ValidateAndDoBufferData(
-      ContextState* context_state, GLenum target, GLsizeiptr size,
-      const GLvoid * data, GLenum usage);
+  void ValidateAndDoBufferData(ContextState* context_state,
+                               ErrorState* error_state,
+                               GLenum target,
+                               GLsizeiptr size,
+                               const GLvoid* data,
+                               GLenum usage);
 
   // Validates a glCopyBufferSubData, and then calls DoCopyBufferSubData if
   // validation was successful.
-  void ValidateAndDoCopyBufferSubData(
-      ContextState* context_state, GLenum readtarget, GLenum writetarget,
-      GLintptr readoffset, GLintptr writeoffset, GLsizeiptr size);
+  void ValidateAndDoCopyBufferSubData(ContextState* context_state,
+                                      ErrorState* error_state,
+                                      GLenum readtarget,
+                                      GLenum writetarget,
+                                      GLintptr readoffset,
+                                      GLintptr writeoffset,
+                                      GLsizeiptr size);
 
   // Validates a glGetBufferParameteri64v, and then calls GetBufferParameteri64v
   // if validation was successful.
-  void ValidateAndDoGetBufferParameteri64v(
-      ContextState* context_state, GLenum target, GLenum pname,
-      GLint64* params);
+  void ValidateAndDoGetBufferParameteri64v(ContextState* context_state,
+                                           ErrorState* error_state,
+                                           GLenum target,
+                                           GLenum pname,
+                                           GLint64* params);
 
   // Validates a glGetBufferParameteriv, and then calls GetBufferParameteriv if
   // validation was successful.
-  void ValidateAndDoGetBufferParameteriv(
-      ContextState* context_state, GLenum target, GLenum pname, GLint* params);
+  void ValidateAndDoGetBufferParameteriv(ContextState* context_state,
+                                         ErrorState* error_state,
+                                         GLenum target,
+                                         GLenum pname,
+                                         GLint* params);
 
   // Sets the target of a buffer. Returns false if the target can not be set.
   bool SetTarget(Buffer* buffer, GLenum target);
@@ -334,12 +349,14 @@
   // return nullptr if a GL error is generated.
   // Generates INVALID_VALUE if offset + size is out of range.
   Buffer* RequestBufferAccess(ContextState* context_state,
+                              ErrorState* error_state,
                               GLenum target,
                               GLintptr offset,
                               GLsizeiptr size,
                               const char* func_name);
   // Same as above, but assume to access the entire buffer.
   Buffer* RequestBufferAccess(ContextState* context_state,
+                              ErrorState* error_state,
                               GLenum target,
                               const char* func_name);
   // Same as above, but it can be any buffer rather than the buffer bound to
diff --git a/gpu/command_buffer/service/context_state.cc b/gpu/command_buffer/service/context_state.cc
index 7501a1e..9a6661e21 100644
--- a/gpu/command_buffer/service/context_state.cc
+++ b/gpu/command_buffer/service/context_state.cc
@@ -10,7 +10,6 @@
 
 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
 #include "gpu/command_buffer/service/buffer_manager.h"
-#include "gpu/command_buffer/service/error_state.h"
 #include "gpu/command_buffer/service/framebuffer_manager.h"
 #include "gpu/command_buffer/service/program_manager.h"
 #include "gpu/command_buffer/service/renderbuffer_manager.h"
@@ -223,12 +222,9 @@
 }
 
 ContextState::ContextState(FeatureInfo* feature_info,
-                           ErrorStateClient* error_state_client,
-                           Logger* logger,
                            bool track_texture_and_sampler_units)
     : track_texture_and_sampler_units(track_texture_and_sampler_units),
-      feature_info_(feature_info),
-      error_state_(ErrorState::Create(error_state_client, logger)) {
+      feature_info_(feature_info) {
   Initialize();
 }
 
@@ -629,10 +625,6 @@
   framebuffer_srgb_valid_ = false;
 }
 
-ErrorState* ContextState::GetErrorState() {
-  return error_state_.get();
-}
-
 void ContextState::EnableDisable(GLenum pname, bool enable) const {
   if (pname == GL_PRIMITIVE_RESTART_FIXED_INDEX &&
       feature_info_->feature_flags().emulate_primitive_restart_fixed_index) {
diff --git a/gpu/command_buffer/service/context_state.h b/gpu/command_buffer/service/context_state.h
index 4afd27fa..4af44a6 100644
--- a/gpu/command_buffer/service/context_state.h
+++ b/gpu/command_buffer/service/context_state.h
@@ -23,11 +23,8 @@
 namespace gles2 {
 
 class Buffer;
-class ErrorState;
-class ErrorStateClient;
 class FeatureInfo;
 class IndexedBufferBindingHost;
-class Logger;
 class Program;
 class Renderbuffer;
 class TransformFeedback;
@@ -195,8 +192,6 @@
   enum Dimension { k2D, k3D };
 
   ContextState(FeatureInfo* feature_info,
-               ErrorStateClient* error_state_client,
-               Logger* logger,
                bool track_texture_and_sampler_units = true);
   ~ContextState();
 
@@ -284,8 +279,6 @@
     api()->glStencilMaskSeparateFn(op, mask);
   }
 
-  ErrorState* GetErrorState();
-
   void SetBoundBuffer(GLenum target, Buffer* buffer);
   void RemoveBoundBuffer(Buffer* buffer);
 
@@ -430,7 +423,6 @@
 
   gl::GLApi* api_ = nullptr;
   FeatureInfo* feature_info_;
-  std::unique_ptr<ErrorState> error_state_;
 
   bool context_lost_ = false;
 };
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 987061c4..3fc2ebc 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -223,17 +223,16 @@
 
 // Local versions of the SET_GL_ERROR macros
 #define LOCAL_SET_GL_ERROR(error, function_name, msg) \
-    ERRORSTATE_SET_GL_ERROR(state_.GetErrorState(), error, function_name, msg)
-#define LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, value, label)          \
-  ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(state_.GetErrorState(), function_name, \
+  ERRORSTATE_SET_GL_ERROR(error_state_.get(), error, function_name, msg)
+#define LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, value, label)      \
+  ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(error_state_.get(), function_name, \
                                        static_cast<uint32_t>(value), label)
 #define LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name) \
-    ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(state_.GetErrorState(), \
-                                              function_name)
+  ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_.get(), function_name)
 #define LOCAL_PEEK_GL_ERROR(function_name) \
-    ERRORSTATE_PEEK_GL_ERROR(state_.GetErrorState(), function_name)
+  ERRORSTATE_PEEK_GL_ERROR(error_state_.get(), function_name)
 #define LOCAL_CLEAR_REAL_GL_ERRORS(function_name) \
-    ERRORSTATE_CLEAR_REAL_GL_ERRORS(state_.GetErrorState(), function_name)
+  ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_.get()) function_name)
 #define LOCAL_PERFORMANCE_WARNING(msg) \
     PerformanceWarning(__FILE__, __LINE__, msg)
 #define LOCAL_RENDER_WARNING(msg) \
@@ -302,11 +301,15 @@
 // unit zero in case the client has changed that to something invalid.
 class ScopedTextureBinder {
  public:
-  explicit ScopedTextureBinder(ContextState* state, GLuint id, GLenum target);
+  explicit ScopedTextureBinder(ContextState* state,
+                               ErrorState* error_state,
+                               GLuint id,
+                               GLenum target);
   ~ScopedTextureBinder();
 
  private:
   ContextState* state_;
+  ErrorState* error_state_;
   GLenum target_;
   DISALLOW_COPY_AND_ASSIGN(ScopedTextureBinder);
 };
@@ -315,11 +318,14 @@
 // object goes out of scope.
 class ScopedRenderBufferBinder {
  public:
-  explicit ScopedRenderBufferBinder(ContextState* state, GLuint id);
+  explicit ScopedRenderBufferBinder(ContextState* state,
+                                    ErrorState* error_state,
+                                    GLuint id);
   ~ScopedRenderBufferBinder();
 
  private:
   ContextState* state_;
+  ErrorState* error_state_;
   DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
 };
 
@@ -2512,6 +2518,8 @@
   DebugMarkerManager debug_marker_manager_;
   Logger logger_;
 
+  std::unique_ptr<ErrorState> error_state_;
+
   // All the state for this context.
   ContextState state_;
 
@@ -2806,12 +2814,11 @@
 }
 
 ScopedTextureBinder::ScopedTextureBinder(ContextState* state,
+                                         ErrorState* error_state,
                                          GLuint id,
                                          GLenum target)
-    : state_(state),
-      target_(target) {
-  ScopedGLErrorSuppressor suppressor(
-      "ScopedTextureBinder::ctor", state_->GetErrorState());
+    : state_(state), error_state_(error_state), target_(target) {
+  ScopedGLErrorSuppressor suppressor("ScopedTextureBinder::ctor", error_state_);
 
   // TODO(apatrick): Check if there are any other states that need to be reset
   // before binding a new texture.
@@ -2821,38 +2828,38 @@
 }
 
 ScopedTextureBinder::~ScopedTextureBinder() {
-  ScopedGLErrorSuppressor suppressor(
-      "ScopedTextureBinder::dtor", state_->GetErrorState());
+  ScopedGLErrorSuppressor suppressor("ScopedTextureBinder::dtor", error_state_);
   RestoreCurrentTextureBindings(state_, target_, 0);
   state_->RestoreActiveTexture();
 }
 
 ScopedRenderBufferBinder::ScopedRenderBufferBinder(ContextState* state,
+                                                   ErrorState* error_state,
                                                    GLuint id)
-    : state_(state) {
-  ScopedGLErrorSuppressor suppressor(
-      "ScopedRenderBufferBinder::ctor", state_->GetErrorState());
+    : state_(state), error_state_(error_state) {
+  ScopedGLErrorSuppressor suppressor("ScopedRenderBufferBinder::ctor",
+                                     error_state_);
   state->api()->glBindRenderbufferEXTFn(GL_RENDERBUFFER, id);
 }
 
 ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
-  ScopedGLErrorSuppressor suppressor(
-      "ScopedRenderBufferBinder::dtor", state_->GetErrorState());
+  ScopedGLErrorSuppressor suppressor("ScopedRenderBufferBinder::dtor",
+                                     error_state_);
   state_->RestoreRenderbufferBindings();
 }
 
 ScopedFramebufferBinder::ScopedFramebufferBinder(GLES2DecoderImpl* decoder,
                                                  GLuint id)
     : decoder_(decoder) {
-  ScopedGLErrorSuppressor suppressor(
-      "ScopedFramebufferBinder::ctor", decoder_->GetErrorState());
+  ScopedGLErrorSuppressor suppressor("ScopedFramebufferBinder::ctor",
+                                     decoder_->error_state_.get());
   decoder->api()->glBindFramebufferEXTFn(GL_FRAMEBUFFER, id);
   decoder->OnFboChanged();
 }
 
 ScopedFramebufferBinder::~ScopedFramebufferBinder() {
-  ScopedGLErrorSuppressor suppressor(
-      "ScopedFramebufferBinder::dtor", decoder_->GetErrorState());
+  ScopedGLErrorSuppressor suppressor("ScopedFramebufferBinder::dtor",
+                                     decoder_->error_state_.get());
   decoder_->RestoreCurrentFramebufferBindings();
 }
 
@@ -2867,8 +2874,8 @@
   if (!resolve_and_bind_)
     return;
   auto* api = decoder_->api();
-  ScopedGLErrorSuppressor suppressor(
-      "ScopedResolvedFramebufferBinder::ctor", decoder_->GetErrorState());
+  ScopedGLErrorSuppressor suppressor("ScopedResolvedFramebufferBinder::ctor",
+                                     decoder_->error_state_.get());
 
   // On old AMD GPUs on macOS, glColorMask doesn't work correctly for
   // multisampled renderbuffers and the alpha channel can be overwritten. This
@@ -2933,8 +2940,8 @@
   if (!resolve_and_bind_)
     return;
 
-  ScopedGLErrorSuppressor suppressor(
-      "ScopedResolvedFramebufferBinder::dtor", decoder_->GetErrorState());
+  ScopedGLErrorSuppressor suppressor("ScopedResolvedFramebufferBinder::dtor",
+                                     decoder_->error_state_.get());
   decoder_->RestoreCurrentFramebufferBindings();
   if (decoder_->state_.enable_flags.scissor_test) {
     decoder_->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
@@ -2956,7 +2963,8 @@
   auto* api = decoder_->api();
   api->glGenTexturesFn(1, &temp_texture_);
 
-  ScopedTextureBinder texture_binder(&decoder->state_, temp_texture_,
+  ScopedTextureBinder texture_binder(&decoder->state_,
+                                     decoder->error_state_.get(), temp_texture_,
                                      GL_TEXTURE_2D);
   if (width == 0 || height == 0) {
     // Copy the whole framebuffer if a rectangle isn't specified.
@@ -3018,49 +3026,39 @@
 void BackTexture::Create() {
   DCHECK_EQ(id(), 0u);
   ScopedGLErrorSuppressor suppressor("BackTexture::Create",
-                                     decoder_->state_.GetErrorState());
+                                     decoder_->error_state_.get());
   GLuint id;
   api()->glGenTexturesFn(1, &id);
 
   GLenum target = Target();
-  ScopedTextureBinder binder(&decoder_->state_, id, target);
+  ScopedTextureBinder binder(&decoder_->state_, decoder_->error_state_.get(),
+                             id, target);
 
   // No client id is necessary because this texture will never be directly
   // accessed by a client, only indirectly via a mailbox.
   texture_ref_ = TextureRef::Create(decoder_->texture_manager(), 0, id);
   decoder_->texture_manager()->SetTarget(texture_ref_.get(), target);
   decoder_->texture_manager()->SetParameteri(
-      "BackTexture::Create",
-      decoder_->GetErrorState(),
-      texture_ref_.get(),
-      GL_TEXTURE_MAG_FILTER,
-      GL_LINEAR);
+      "BackTexture::Create", decoder_->error_state_.get(), texture_ref_.get(),
+      GL_TEXTURE_MAG_FILTER, GL_LINEAR);
   decoder_->texture_manager()->SetParameteri(
-      "BackTexture::Create",
-      decoder_->GetErrorState(),
-      texture_ref_.get(),
-      GL_TEXTURE_MIN_FILTER,
-      GL_LINEAR);
+      "BackTexture::Create", decoder_->error_state_.get(), texture_ref_.get(),
+      GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   decoder_->texture_manager()->SetParameteri(
-      "BackTexture::Create",
-      decoder_->GetErrorState(),
-      texture_ref_.get(),
-      GL_TEXTURE_WRAP_S,
-      GL_CLAMP_TO_EDGE);
+      "BackTexture::Create", decoder_->error_state_.get(), texture_ref_.get(),
+      GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
   decoder_->texture_manager()->SetParameteri(
-      "BackTexture::Create",
-      decoder_->GetErrorState(),
-      texture_ref_.get(),
-      GL_TEXTURE_WRAP_T,
-      GL_CLAMP_TO_EDGE);
+      "BackTexture::Create", decoder_->error_state_.get(), texture_ref_.get(),
+      GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 }
 
 bool BackTexture::AllocateStorage(
     const gfx::Size& size, GLenum format, bool zero) {
   DCHECK_NE(id(), 0u);
   ScopedGLErrorSuppressor suppressor("BackTexture::AllocateStorage",
-                                     decoder_->state_.GetErrorState());
-  ScopedTextureBinder binder(&decoder_->state_, id(), Target());
+                                     decoder_->error_state_.get());
+  ScopedTextureBinder binder(&decoder_->state_, decoder_->error_state_.get(),
+                             id(), Target());
   uint32_t image_size = 0;
   GLES2Util::ComputeImageDataSizes(size.width(), size.height(), 1, format,
                                    GL_UNSIGNED_BYTE, 8, &image_size, nullptr,
@@ -3109,8 +3107,9 @@
 void BackTexture::Copy() {
   DCHECK_NE(id(), 0u);
   ScopedGLErrorSuppressor suppressor("BackTexture::Copy",
-                                     decoder_->state_.GetErrorState());
-  ScopedTextureBinder binder(&decoder_->state_, id(), Target());
+                                     decoder_->error_state_.get());
+  ScopedTextureBinder binder(&decoder_->state_, decoder_->error_state_.get(),
+                             id(), Target());
   api()->glCopyTexSubImage2DFn(Target(),
                                0,  // level
                                0, 0, 0, 0, size_.width(), size_.height());
@@ -3119,13 +3118,14 @@
 void BackTexture::Destroy() {
   if (image_) {
     DCHECK(texture_ref_);
-    ScopedTextureBinder binder(&decoder_->state_, id(), Target());
+    ScopedTextureBinder binder(&decoder_->state_, decoder_->error_state_.get(),
+                               id(), Target());
     DestroyNativeGpuMemoryBuffer(true);
   }
 
   if (texture_ref_) {
     ScopedGLErrorSuppressor suppressor("BackTexture::Destroy",
-                                       decoder_->state_.GetErrorState());
+                                       decoder_->error_state_.get());
     texture_ref_ = nullptr;
   }
   memory_tracker_.TrackMemFree(bytes_allocated_);
@@ -3216,7 +3216,7 @@
   if (image_) {
     ScopedGLErrorSuppressor suppressor(
         "BackTexture::DestroyNativeGpuMemoryBuffer",
-        decoder_->state_.GetErrorState());
+        decoder_->error_state_.get());
 
     image_->ReleaseTexImage(Target());
 
@@ -3245,7 +3245,7 @@
 
 void BackRenderbuffer::Create() {
   ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Create",
-                                     decoder_->state_.GetErrorState());
+                                     decoder_->error_state_.get());
   Destroy();
   api()->glGenRenderbuffersEXTFn(1, &id_);
 }
@@ -3254,8 +3254,9 @@
                                        GLenum format,
                                        GLsizei samples) {
   ScopedGLErrorSuppressor suppressor("BackRenderbuffer::AllocateStorage",
-                                     decoder_->state_.GetErrorState());
-  ScopedRenderBufferBinder binder(&decoder_->state_, id_);
+                                     decoder_->error_state_.get());
+  ScopedRenderBufferBinder binder(&decoder_->state_,
+                                  decoder_->error_state_.get(), id_);
 
   uint32_t estimated_size = 0;
   if (!decoder_->renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
@@ -3308,7 +3309,7 @@
 void BackRenderbuffer::Destroy() {
   if (id_ != 0) {
     ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Destroy",
-                                       decoder_->state_.GetErrorState());
+                                       decoder_->error_state_.get());
     api()->glDeleteRenderbuffersEXTFn(1, &id_);
     id_ = 0;
   }
@@ -3338,15 +3339,15 @@
 
 void BackFramebuffer::Create() {
   ScopedGLErrorSuppressor suppressor("BackFramebuffer::Create",
-                                     decoder_->GetErrorState());
+                                     decoder_->error_state_.get());
   Destroy();
   api()->glGenFramebuffersEXTFn(1, &id_);
 }
 
 void BackFramebuffer::AttachRenderTexture(BackTexture* texture) {
   DCHECK_NE(id_, 0u);
-  ScopedGLErrorSuppressor suppressor(
-      "BackFramebuffer::AttachRenderTexture", decoder_->GetErrorState());
+  ScopedGLErrorSuppressor suppressor("BackFramebuffer::AttachRenderTexture",
+                                     decoder_->error_state_.get());
   ScopedFramebufferBinder binder(decoder_, id_);
   GLuint attach_id = texture ? texture->id() : 0;
   api()->glFramebufferTexture2DEXTFn(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
@@ -3356,8 +3357,8 @@
 void BackFramebuffer::AttachRenderBuffer(GLenum target,
                                          BackRenderbuffer* render_buffer) {
   DCHECK_NE(id_, 0u);
-  ScopedGLErrorSuppressor suppressor(
-      "BackFramebuffer::AttachRenderBuffer", decoder_->GetErrorState());
+  ScopedGLErrorSuppressor suppressor("BackFramebuffer::AttachRenderBuffer",
+                                     decoder_->error_state_.get());
   ScopedFramebufferBinder binder(decoder_, id_);
   GLuint attach_id = render_buffer ? render_buffer->id() : 0;
   api()->glFramebufferRenderbufferEXTFn(GL_FRAMEBUFFER, target, GL_RENDERBUFFER,
@@ -3367,7 +3368,7 @@
 void BackFramebuffer::Destroy() {
   if (id_ != 0) {
     ScopedGLErrorSuppressor suppressor("BackFramebuffer::Destroy",
-                                       decoder_->GetErrorState());
+                                       decoder_->error_state_.get());
     api()->glDeleteFramebuffersEXTFn(1, &id_);
     id_ = 0;
   }
@@ -3380,7 +3381,7 @@
 GLenum BackFramebuffer::CheckStatus() {
   DCHECK_NE(id_, 0u);
   ScopedGLErrorSuppressor suppressor("BackFramebuffer::CheckStatus",
-                                     decoder_->GetErrorState());
+                                     decoder_->error_state_.get());
   ScopedFramebufferBinder binder(decoder_, id_);
   return api()->glCheckFramebufferStatusEXTFn(GL_FRAMEBUFFER);
 }
@@ -3409,7 +3410,8 @@
               base::BindRepeating(&DecoderClient::OnConsoleMessage,
                                   base::Unretained(client_),
                                   0)),
-      state_(group_->feature_info(), this, &logger_),
+      error_state_(ErrorState::Create(this, &logger_)),
+      state_(group_->feature_info()),
       attrib_0_buffer_id_(0),
       attrib_0_buffer_matches_value_(true),
       attrib_0_size_(0),
@@ -5156,7 +5158,7 @@
 }
 
 ErrorState* GLES2DecoderImpl::GetErrorState() {
-  return state_.GetErrorState();
+  return error_state_.get();
 }
 
 bool GLES2DecoderImpl::GetServiceTextureId(uint32_t client_texture_id,
@@ -7730,7 +7732,7 @@
                                                 GLsizei params_size) {
   // Just delegate it. Some validation is actually done before this.
   buffer_manager()->ValidateAndDoGetBufferParameteri64v(
-      &state_, target, pname, params);
+      &state_, error_state_.get(), target, pname, params);
 }
 
 void GLES2DecoderImpl::DoGetBufferParameteriv(GLenum target,
@@ -7739,7 +7741,7 @@
                                               GLsizei params_size) {
   // Just delegate it. Some validation is actually done before this.
   buffer_manager()->ValidateAndDoGetBufferParameteriv(
-      &state_, target, pname, params);
+      &state_, error_state_.get(), target, pname, params);
 }
 
 void GLES2DecoderImpl::DoBindAttribLocation(GLuint program_id,
@@ -9545,8 +9547,8 @@
         GL_INVALID_VALUE, "glSamplerParameterf", "unknown sampler");
     return;
   }
-  sampler_manager()->SetParameterf(
-      "glSamplerParameterf", GetErrorState(), sampler, pname, param);
+  sampler_manager()->SetParameterf("glSamplerParameterf", error_state_.get(),
+                                   sampler, pname, param);
 }
 
 void GLES2DecoderImpl::DoSamplerParameteri(
@@ -9557,8 +9559,8 @@
         GL_INVALID_VALUE, "glSamplerParameteri", "unknown sampler");
     return;
   }
-  sampler_manager()->SetParameteri(
-      "glSamplerParameteri", GetErrorState(), sampler, pname, param);
+  sampler_manager()->SetParameteri("glSamplerParameteri", error_state_.get(),
+                                   sampler, pname, param);
 }
 
 void GLES2DecoderImpl::DoSamplerParameterfv(GLuint client_id,
@@ -9571,8 +9573,8 @@
         GL_INVALID_VALUE, "glSamplerParameterfv", "unknown sampler");
     return;
   }
-  sampler_manager()->SetParameterf(
-      "glSamplerParameterfv", GetErrorState(), sampler, pname, params[0]);
+  sampler_manager()->SetParameterf("glSamplerParameterfv", error_state_.get(),
+                                   sampler, pname, params[0]);
 }
 
 void GLES2DecoderImpl::DoSamplerParameteriv(GLuint client_id,
@@ -9585,8 +9587,8 @@
         GL_INVALID_VALUE, "glSamplerParameteriv", "unknown sampler");
     return;
   }
-  sampler_manager()->SetParameteri(
-      "glSamplerParameteriv", GetErrorState(), sampler, pname, params[0]);
+  sampler_manager()->SetParameteri("glSamplerParameteriv", error_state_.get(),
+                                   sampler, pname, params[0]);
 }
 
 void GLES2DecoderImpl::DoTexParameterf(
@@ -9598,8 +9600,8 @@
     return;
   }
 
-  texture_manager()->SetParameterf(
-      "glTexParameterf", GetErrorState(), texture, pname, param);
+  texture_manager()->SetParameterf("glTexParameterf", error_state_.get(),
+                                   texture, pname, param);
 }
 
 void GLES2DecoderImpl::DoTexParameteri(
@@ -9611,8 +9613,8 @@
     return;
   }
 
-  texture_manager()->SetParameteri(
-      "glTexParameteri", GetErrorState(), texture, pname, param);
+  texture_manager()->SetParameteri("glTexParameteri", error_state_.get(),
+                                   texture, pname, param);
 }
 
 void GLES2DecoderImpl::DoTexParameterfv(GLenum target,
@@ -9625,8 +9627,8 @@
     return;
   }
 
-  texture_manager()->SetParameterf(
-      "glTexParameterfv", GetErrorState(), texture, pname, *params);
+  texture_manager()->SetParameterf("glTexParameterfv", error_state_.get(),
+                                   texture, pname, *params);
 }
 
 void GLES2DecoderImpl::DoTexParameteriv(GLenum target,
@@ -9640,8 +9642,8 @@
     return;
   }
 
-  texture_manager()->SetParameteri(
-      "glTexParameteriv", GetErrorState(), texture, pname, *params);
+  texture_manager()->SetParameteri("glTexParameteriv", error_state_.get(),
+                                   texture, pname, *params);
 }
 
 bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
@@ -9754,7 +9756,7 @@
     uniform_block_sizes[index] = static_cast<GLsizeiptr>(info.data_size);
   }
   return buffer_manager()->RequestBuffersAccess(
-      state_.GetErrorState(), state_.indexed_uniform_buffer_bindings.get(),
+      error_state_.get(), state_.indexed_uniform_buffer_bindings.get(),
       uniform_block_sizes, 1, func_name, "uniform buffers");
 }
 
@@ -10375,7 +10377,7 @@
     gl::GLImage* image = texture->GetLevelImage(textarget, 0, &image_state);
     if (image && image_state == Texture::UNBOUND) {
       ScopedGLErrorSuppressor suppressor(
-          "GLES2DecoderImpl::DoBindOrCopyTexImageIfNeeded", GetErrorState());
+          "GLES2DecoderImpl::DoBindOrCopyTexImageIfNeeded", error_state_.get());
       if (texture_unit)
         api()->glActiveTextureFn(texture_unit);
       api()->glBindTextureFn(textarget, texture->service_id());
@@ -10402,7 +10404,8 @@
                                            GLsizeiptr size) {
   // Just delegate it. Some validation is actually done before this.
   buffer_manager()->ValidateAndDoCopyBufferSubData(
-      &state_, readtarget, writetarget, readoffset, writeoffset, size);
+      &state_, error_state_.get(), readtarget, writetarget, readoffset,
+      writeoffset, size);
 }
 
 bool GLES2DecoderImpl::PrepareTexturesForRender() {
@@ -10970,7 +10973,7 @@
     }
 
     if (!buffer_manager()->RequestBuffersAccess(
-            state_.GetErrorState(), state_.bound_transform_feedback.get(),
+            error_state_.get(), state_.bound_transform_feedback.get(),
             state_.current_program->GetTransformFeedbackVaryingSizes(),
             *vertices_drawn, function_name, "transformfeedback buffers")) {
       return false;
@@ -11208,7 +11211,7 @@
   }
 
   Buffer* element_array_buffer = buffer_manager()->RequestBufferAccess(
-      &state_, GL_ELEMENT_ARRAY_BUFFER, function_name);
+      &state_, error_state_.get(), GL_ELEMENT_ARRAY_BUFFER, function_name);
   if (!element_array_buffer) {
     return error::kNoError;
   }
@@ -12570,7 +12573,7 @@
       return error::kInvalidArguments;
     }
     if (!buffer_manager()->RequestBufferAccess(
-            state_.GetErrorState(), buffer, func_name, "pixel pack buffer")) {
+            error_state_.get(), buffer, func_name, "pixel pack buffer")) {
       return error::kNoError;
     }
     uint32_t size = 0;
@@ -13594,15 +13597,16 @@
       return error::kOutOfBounds;
     }
   }
-  buffer_manager()->ValidateAndDoBufferData(&state_, target, size, data, usage);
+  buffer_manager()->ValidateAndDoBufferData(&state_, error_state_.get(), target,
+                                            size, data, usage);
   return error::kNoError;
 }
 
 void GLES2DecoderImpl::DoBufferSubData(
   GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
   // Just delegate it. Some validation is actually done before this.
-  buffer_manager()->ValidateAndDoBufferSubData(
-      &state_, target, offset, size, data);
+  buffer_manager()->ValidateAndDoBufferSubData(&state_, error_state_.get(),
+                                               target, offset, size, data);
 }
 
 bool GLES2DecoderImpl::ClearLevel(Texture* texture,
@@ -13783,7 +13787,7 @@
   GLsizei bytes_required = 0;
   if (!GetCompressedTexSizeInBytes("ClearCompressedTextureLevel", width, height,
                                    1, format, &bytes_required,
-                                   state_.GetErrorState())) {
+                                   error_state_.get())) {
     return false;
   }
 
@@ -14091,7 +14095,7 @@
                                                      const GLvoid* data) {
   GLsizei bytes_required = 0;
   if (!GetCompressedTexSizeInBytes(function_name, width, height, depth, format,
-                                   &bytes_required, state_.GetErrorState())) {
+                                   &bytes_required, error_state_.get())) {
     return false;
   }
 
@@ -14104,7 +14108,7 @@
   Buffer* buffer = state_.bound_pixel_unpack_buffer.get();
   if (buffer &&
       !buffer_manager()->RequestBufferAccess(
-          state_.GetErrorState(), buffer, reinterpret_cast<GLintptr>(data),
+          error_state_.get(), buffer, reinterpret_cast<GLintptr>(data),
           static_cast<GLsizeiptr>(bytes_required), function_name,
           "pixel unpack buffer")) {
     return false;
@@ -14533,7 +14537,8 @@
     pixels, pixels_size, padding,
     TextureManager::DoTexImageArguments::kTexImage2D };
   texture_manager()->ValidateAndDoTexImage(
-      &texture_state_, &state_, &framebuffer_state_, func_name, args);
+      &texture_state_, &state_, error_state_.get(), &framebuffer_state_,
+      func_name, args);
 
   // This may be a slow command.  Exit command processing to allow for
   // context preemption and GPU watchdog checks.
@@ -14630,7 +14635,8 @@
     pixels, pixels_size, padding,
     TextureManager::DoTexImageArguments::kTexImage3D };
   texture_manager()->ValidateAndDoTexImage(
-      &texture_state_, &state_, &framebuffer_state_, func_name, args);
+      &texture_state_, &state_, error_state_.get(), &framebuffer_state_,
+      func_name, args);
 
   // This may be a slow command.  Exit command processing to allow for
   // context preemption and GPU watchdog checks.
@@ -14921,7 +14927,8 @@
   }
 
   DCHECK(texture_manager()->ValidateTextureParameters(
-      GetErrorState(), func_name, true, format, type, internal_format, level));
+      error_state_.get(), func_name, true, format, type, internal_format,
+      level));
 
   // Only target image size is validated here.
   if (!GLES2Util::ComputeImageDataSizes(width, height, 1, format, type,
@@ -15009,8 +15016,8 @@
         0,
         TextureManager::DoTexImageArguments::kTexImage2D};
     texture_manager()->WorkaroundCopyTexImageCubeMap(
-        &texture_state_, &state_, &framebuffer_state_, texture_ref, func_name,
-        args);
+        &texture_state_, &state_, error_state_.get(), &framebuffer_state_,
+        texture_ref, func_name, args);
   }
 
   if (src.x() != x || src.y() != y ||
@@ -15054,8 +15061,9 @@
           target, i, final_internal_format, width, height, 1, border,
           format, type, nullptr, pixels_size, 0,
           TextureManager::DoTexImageArguments::kTexImage2D };
-        texture_manager()->WorkaroundCopyTexImageCubeMap(&texture_state_,
-            &state_, &framebuffer_state_, texture_ref, func_name, args);
+        texture_manager()->WorkaroundCopyTexImageCubeMap(
+            &texture_state_, &state_, error_state_.get(), &framebuffer_state_,
+            texture_ref, func_name, args);
       }
     }
 
@@ -15091,7 +15099,7 @@
       {
         // Copy from the read framebuffer into |temp_texture|.
         api()->glGenTexturesFn(1, &temp_texture);
-        ScopedTextureBinder binder(&state_, temp_texture,
+        ScopedTextureBinder binder(&state_, error_state_.get(), temp_texture,
                                    source_texture_target);
         api()->glCopyTexImage2DFn(source_texture_target, 0,
                                   temp_internal_format, x, y, width, height,
@@ -15124,8 +15132,9 @@
           target, level, final_internal_format, width, height, 1, border,
           format, type, nullptr, pixels_size, 0,
           TextureManager::DoTexImageArguments::kTexImage2D };
-        texture_manager()->WorkaroundCopyTexImageCubeMap(&texture_state_,
-            &state_, &framebuffer_state_, texture_ref, func_name, args);
+        texture_manager()->WorkaroundCopyTexImageCubeMap(
+            &texture_state_, &state_, error_state_.get(), &framebuffer_state_,
+            texture_ref, func_name, args);
       }
       if (workarounds().clear_pixel_unpack_buffer_before_copyteximage)
         state_.PushTextureUnpackState();
@@ -15441,9 +15450,9 @@
       target, level, xoffset, yoffset, 0, width, height, 1,
       format, type, pixels, pixels_size, padding,
       TextureManager::DoTexSubImageArguments::kTexSubImage2D};
-  texture_manager()->ValidateAndDoTexSubImage(this, &texture_state_, &state_,
-                                              &framebuffer_state_,
-                                              func_name, args);
+  texture_manager()->ValidateAndDoTexSubImage(
+      this, &texture_state_, &state_, error_state_.get(), &framebuffer_state_,
+      func_name, args);
 
   // This may be a slow command.  Exit command processing to allow for
   // context preemption and GPU watchdog checks.
@@ -15535,9 +15544,9 @@
       target, level, xoffset, yoffset, zoffset, width, height, depth,
       format, type, pixels, pixels_size, padding,
       TextureManager::DoTexSubImageArguments::kTexSubImage3D};
-  texture_manager()->ValidateAndDoTexSubImage(this, &texture_state_, &state_,
-                                              &framebuffer_state_,
-                                              func_name, args);
+  texture_manager()->ValidateAndDoTexSubImage(
+      this, &texture_state_, &state_, error_state_.get(), &framebuffer_state_,
+      func_name, args);
 
   // This may be a slow command.  Exit command processing to allow for
   // context preemption and GPU watchdog checks.
@@ -16200,8 +16209,8 @@
 
     if (offscreen_size_.width() == 0 || offscreen_size_.height() == 0)
       return;
-    ScopedGLErrorSuppressor suppressor(
-        "GLES2DecoderImpl::DoSwapBuffers", GetErrorState());
+    ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::DoSwapBuffers",
+                                       error_state_.get());
 
     if (IsOffscreenBufferMultisampled()) {
       // For multisampled buffers, resolve the frame buffer.
@@ -17331,7 +17340,7 @@
   GLenum format =
       TextureManager::ExtractFormatFromStorageFormat(internal_format);
   if (!texture_manager()->ValidateTextureParameters(
-          GetErrorState(), kFunctionName, true, format, dest_type,
+          error_state_.get(), kFunctionName, true, format, dest_type,
           internal_format, dest_level)) {
     return;
   }
@@ -17663,8 +17672,8 @@
   if (image && dest_internal_format == source_internal_format &&
       dest_level == 0 && !unpack_flip_y && !unpack_premultiply_alpha_change &&
       !dither) {
-    ScopedTextureBinder binder(&state_, dest_texture->service_id(),
-                               dest_binding_target);
+    ScopedTextureBinder binder(&state_, error_state_.get(),
+                               dest_texture->service_id(), dest_binding_target);
     if (image->CopyTexSubImage(dest_target, gfx::Point(xoffset, yoffset),
                                gfx::Rect(x, y, width, height))) {
       return;
@@ -17844,7 +17853,7 @@
         GLsizei level_size;
         if (!GetCompressedTexSizeInBytes(
                 function_name, level_width, level_height, level_depth,
-                internal_format, &level_size, state_.GetErrorState())) {
+                internal_format, &level_size, error_state_.get())) {
           // GetCompressedTexSizeInBytes() already generates a GL error.
           return;
         }
@@ -17973,7 +17982,7 @@
                width, "height", height);
 
   ScopedGLErrorSuppressor suppressor(
-      "GLES2CmdDecoder::DoTexStorage2DImageCHROMIUM", state_.GetErrorState());
+      "GLES2CmdDecoder::DoTexStorage2DImageCHROMIUM", error_state_.get());
 
   if (!texture_manager()->ValidForTarget(target, 0, width, height, 1)) {
     LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexStorage2DImageCHROMIUM",
@@ -18340,7 +18349,7 @@
 
   {
     ScopedGLErrorSuppressor suppressor(
-        "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", GetErrorState());
+        "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", error_state_.get());
 
     // Note: We fallback to using CopyTexImage() before the texture is used
     // when BindTexImage() fails.
@@ -18394,7 +18403,7 @@
 
   if (image_state == Texture::BOUND) {
     ScopedGLErrorSuppressor suppressor(
-        "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", GetErrorState());
+        "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", error_state_.get());
 
     image->ReleaseTexImage(target);
     texture_manager()->SetLevelInfo(texture_ref, target, 0, GL_RGBA, 0, 0, 1, 0,
@@ -18792,7 +18801,7 @@
     return error::kNoError;
   }
   Buffer* buffer = buffer_manager()->RequestBufferAccess(
-      &state_, target, offset, size, func_name);
+      &state_, error_state_.get(), target, offset, size, func_name);
   if (!buffer) {
     // An error is already set.
     return error::kNoError;
@@ -20090,7 +20099,7 @@
 
 void GLES2DecoderImpl::ClearFramebufferForWorkaround(GLbitfield mask) {
   ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::ClearWorkaround",
-                                     GetErrorState());
+                                     error_state_.get());
   clear_framebuffer_blit_->ClearFramebuffer(
       this, gfx::Size(viewport_max_width_, viewport_max_height_), mask,
       state_.color_clear_red, state_.color_clear_green, state_.color_clear_blue,
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_context_state.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_context_state.cc
index 6c11caac..145cbcd 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_context_state.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_context_state.cc
@@ -198,7 +198,7 @@
 
   // Construct a previous ContextState with all texture bindings
   // set to default textures.
-  ContextState prev_state(nullptr, nullptr, nullptr);
+  ContextState prev_state(nullptr);
   InitializeContextState(&prev_state, std::numeric_limits<uint32_t>::max(), 0);
 
   InSequence sequence;
@@ -221,7 +221,7 @@
 
   // Construct a previous ContextState with all texture bindings
   // set to default textures.
-  ContextState prev_state(nullptr, nullptr, nullptr);
+  ContextState prev_state(nullptr);
   InitializeContextState(&prev_state, std::numeric_limits<uint32_t>::max(), 0);
 
   InSequence sequence;
@@ -251,7 +251,7 @@
 
   // Construct a previous ContextState with all texture bindings
   // set to default textures.
-  ContextState prev_state(nullptr, nullptr, nullptr);
+  ContextState prev_state(nullptr);
   InitializeContextState(&prev_state, std::numeric_limits<uint32_t>::max(), 0);
 
   InSequence sequence;
@@ -284,7 +284,7 @@
   // Construct a previous ContextState with GL_TEXTURE_2D target in
   // GL_TEXTURE0 unit bound to a non-default texture and the rest
   // set to default textures.
-  ContextState prev_state(nullptr, nullptr, nullptr);
+  ContextState prev_state(nullptr);
   InitializeContextState(&prev_state, 0, kServiceTextureId);
 
   InSequence sequence;
@@ -316,7 +316,7 @@
   // Construct a previous ContextState with GL_TEXTURE_2D target in
   // GL_TEXTURE1 unit bound to a non-default texture and the rest
   // set to default textures.
-  ContextState prev_state(nullptr, nullptr, nullptr);
+  ContextState prev_state(nullptr);
   InitializeContextState(&prev_state, 1, kServiceTextureId);
 
   InSequence sequence;
@@ -353,7 +353,7 @@
   // Construct a previous ContextState with GL_TEXTURE_2D target in
   // GL_TEXTURE0 unit bound to a non-default texture and the rest
   // set to default textures.
-  ContextState prev_state(nullptr, nullptr, nullptr);
+  ContextState prev_state(nullptr);
   InitializeContextState(&prev_state, 0, kServiceTextureId);
 
   InSequence sequence;
@@ -383,7 +383,7 @@
   // Construct a previous ContextState with GL_TEXTURE_2D target in
   // GL_TEXTURE1 unit bound to a non-default texture and the rest
   // set to default textures.
-  ContextState prev_state(nullptr, nullptr, nullptr);
+  ContextState prev_state(nullptr);
   InitializeContextState(&prev_state, 1, kServiceTextureId);
 
   InSequence sequence;
@@ -447,7 +447,7 @@
 
   // Construct a previous ContextState assuming an ES3 context and with all
   // texture bindings set to default textures.
-  ContextState prev_state(feature_info.get(), nullptr, nullptr);
+  ContextState prev_state(feature_info.get());
   InitializeContextState(&prev_state, std::numeric_limits<uint32_t>::max(), 0);
 
   InSequence sequence;
@@ -468,7 +468,7 @@
   // Construct a previous ContextState assuming an ES3 context and with all
   // texture bindings set to default textures.
   SamplerManager sampler_manager(feature_info.get());
-  ContextState prev_state(feature_info.get(), nullptr, nullptr);
+  ContextState prev_state(feature_info.get());
   InitializeContextState(&prev_state, std::numeric_limits<uint32_t>::max(), 0);
   // Set up a sampler in the previous state. The client_id and service_id
   // don't matter except that they're non-zero.
diff --git a/gpu/command_buffer/service/raster_decoder.cc b/gpu/command_buffer/service/raster_decoder.cc
index 12295d0..29deee4 100644
--- a/gpu/command_buffer/service/raster_decoder.cc
+++ b/gpu/command_buffer/service/raster_decoder.cc
@@ -72,17 +72,16 @@
 
 // Local versions of the SET_GL_ERROR macros
 #define LOCAL_SET_GL_ERROR(error, function_name, msg) \
-  ERRORSTATE_SET_GL_ERROR(state_.GetErrorState(), error, function_name, msg)
-#define LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, value, label)          \
-  ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(state_.GetErrorState(), function_name, \
+  ERRORSTATE_SET_GL_ERROR(GetErrorState(), error, function_name, msg)
+#define LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, value, label)   \
+  ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(GetErrorState(), function_name, \
                                        static_cast<uint32_t>(value), label)
-#define LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name)         \
-  ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(state_.GetErrorState(), \
-                                            function_name)
+#define LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name) \
+  ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(GetErrorState(), function_name)
 #define LOCAL_PEEK_GL_ERROR(function_name) \
-  ERRORSTATE_PEEK_GL_ERROR(state_.GetErrorState(), function_name)
+  ERRORSTATE_PEEK_GL_ERROR(GetErrorState(), function_name)
 #define LOCAL_CLEAR_REAL_GL_ERRORS(function_name) \
-  ERRORSTATE_CLEAR_REAL_GL_ERRORS(state_.GetErrorState(), function_name)
+  ERRORSTATE_CLEAR_REAL_GL_ERRORS(GetErrorState(), function_name)
 #define LOCAL_PERFORMANCE_WARNING(msg) \
   PerformanceWarning(__FILE__, __LINE__, msg)
 #define LOCAL_RENDER_WARNING(msg) RenderWarning(__FILE__, __LINE__, msg)
@@ -606,6 +605,7 @@
 
   gles2::DebugMarkerManager debug_marker_manager_;
   gles2::Logger logger_;
+  std::unique_ptr<gles2::ErrorState> error_state_;
 
   // The ContextGroup for this decoder uses to track resources.
   scoped_refptr<gles2::ContextGroup> group_;
@@ -731,13 +731,12 @@
               base::BindRepeating(&DecoderClient::OnConsoleMessage,
                                   base::Unretained(client_),
                                   0)),
+      error_state_(gles2::ErrorState::Create(this, &logger_)),
       group_(group),
       raster_decoder_context_state_(std::move(raster_decoder_context_state)),
       validators_(new Validators),
       feature_info_(group_->feature_info()),
       state_(group_->feature_info(),
-             this,
-             &logger_,
              false /* track_texture_and_sampler_units */),
       service_logging_(
           group_->gpu_preferences().enable_gpu_service_logging_gpu),
@@ -1369,7 +1368,7 @@
 }
 
 gles2::ErrorState* RasterDecoderImpl::GetErrorState() {
-  return state_.GetErrorState();
+  return error_state_.get();
 }
 
 std::unique_ptr<gles2::AbstractTexture>
diff --git a/gpu/command_buffer/service/texture_manager.cc b/gpu/command_buffer/service/texture_manager.cc
index dfc14b3..b6cd283 100644
--- a/gpu/command_buffer/service/texture_manager.cc
+++ b/gpu/command_buffer/service/texture_manager.cc
@@ -2605,12 +2605,11 @@
   return texture;
 }
 
-bool TextureManager::ValidateTexImage(
-    ContextState* state,
-    const char* function_name,
-    const DoTexImageArguments& args,
-    TextureRef** texture_ref) {
-  ErrorState* error_state = state->GetErrorState();
+bool TextureManager::ValidateTexImage(ContextState* state,
+                                      ErrorState* error_state,
+                                      const char* function_name,
+                                      const DoTexImageArguments& args,
+                                      TextureRef** texture_ref) {
   const Validators* validators = feature_info_->validators();
   if (((args.command_type == DoTexImageArguments::kTexImage2D) &&
        !validators->texture_target.IsValid(args.target)) ||
@@ -2727,6 +2726,7 @@
 void TextureManager::DoCubeMapWorkaround(
     DecoderTextureState* texture_state,
     ContextState* state,
+    ErrorState* error_state,
     DecoderFramebufferState* framebuffer_state,
     TextureRef* texture_ref,
     const char* function_name,
@@ -2761,7 +2761,7 @@
   for (GLenum face : undefined_faces) {
     new_args.target = face;
     new_args.pixels = zero.get();
-    DoTexImage(texture_state, state, framebuffer_state,
+    DoTexImage(texture_state, state, error_state, framebuffer_state,
                function_name, texture_ref, new_args);
     texture->MarkLevelAsInternalWorkaround(face, args.level);
   }
@@ -2771,11 +2771,13 @@
 void TextureManager::ValidateAndDoTexImage(
     DecoderTextureState* texture_state,
     ContextState* state,
+    ErrorState* error_state,
     DecoderFramebufferState* framebuffer_state,
     const char* function_name,
     const DoTexImageArguments& args) {
   TextureRef* texture_ref;
-  if (!ValidateTexImage(state, function_name, args, &texture_ref)) {
+  if (!ValidateTexImage(state, error_state, function_name, args,
+                        &texture_ref)) {
     return;
   }
 
@@ -2799,7 +2801,7 @@
             GL_SRGB));
 
   if (need_cube_map_workaround && !buffer) {
-    DoCubeMapWorkaround(texture_state, state, framebuffer_state,
+    DoCubeMapWorkaround(texture_state, state, error_state, framebuffer_state,
                         texture_ref, function_name, args);
   }
 
@@ -2815,8 +2817,9 @@
       // The rows overlap in unpack memory. Upload the texture row by row to
       // work around driver bug.
 
-      ReserveTexImageToBeFilled(texture_state, state, framebuffer_state,
-                                function_name, texture_ref, args);
+      ReserveTexImageToBeFilled(texture_state, state, error_state,
+                                framebuffer_state, function_name, texture_ref,
+                                args);
 
       DoTexSubImageArguments sub_args = {
           args.target, args.level, 0, 0, 0, args.width, args.height, args.depth,
@@ -2839,8 +2842,9 @@
     const PixelStoreParams unpack_params(state->GetUnpackParams(dimension));
     if (unpack_params.image_height != 0 &&
         unpack_params.image_height != args.height) {
-      ReserveTexImageToBeFilled(texture_state, state, framebuffer_state,
-                                function_name, texture_ref, args);
+      ReserveTexImageToBeFilled(texture_state, state, error_state,
+                                framebuffer_state, function_name, texture_ref,
+                                args);
 
       DoTexSubImageArguments sub_args = {
           args.target,
@@ -2871,8 +2875,9 @@
     if (buffer_size - args.pixels_size - ToGLuint(args.pixels) < args.padding) {
       // In ValidateTexImage(), we already made sure buffer size is no less
       // than offset + pixels_size.
-      ReserveTexImageToBeFilled(texture_state, state, framebuffer_state,
-                                function_name, texture_ref, args);
+      ReserveTexImageToBeFilled(texture_state, state, error_state,
+                                framebuffer_state, function_name, texture_ref,
+                                args);
 
       DoTexSubImageArguments sub_args = {
           args.target, args.level, 0, 0, 0, args.width, args.height, args.depth,
@@ -2886,13 +2891,14 @@
       return;
     }
   }
-  DoTexImage(texture_state, state, framebuffer_state,
+  DoTexImage(texture_state, state, error_state, framebuffer_state,
              function_name, texture_ref, args);
 }
 
 void TextureManager::ReserveTexImageToBeFilled(
     DecoderTextureState* texture_state,
     ContextState* state,
+    ErrorState* error_state,
     DecoderFramebufferState* framebuffer_state,
     const char* function_name,
     TextureRef* texture_ref,
@@ -2903,17 +2909,17 @@
   DoTexImageArguments new_args = args;
   new_args.pixels = nullptr;
   // pixels_size might be incorrect, but it's not used in this case.
-  DoTexImage(texture_state, state, framebuffer_state, function_name,
-             texture_ref, new_args);
+  DoTexImage(texture_state, state, error_state, framebuffer_state,
+             function_name, texture_ref, new_args);
   glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer->service_id());
   state->SetBoundBuffer(GL_PIXEL_UNPACK_BUFFER, buffer);
 }
 
 bool TextureManager::ValidateTexSubImage(ContextState* state,
+                                         ErrorState* error_state,
                                          const char* function_name,
                                          const DoTexSubImageArguments& args,
                                          TextureRef** texture_ref) {
-  ErrorState* error_state = state->GetErrorState();
   const Validators* validators = feature_info_->validators();
 
   if ((args.command_type == DoTexSubImageArguments::kTexSubImage2D &&
@@ -3024,13 +3030,14 @@
     DecoderContext* decoder,
     DecoderTextureState* texture_state,
     ContextState* state,
+    ErrorState* error_state,
     DecoderFramebufferState* framebuffer_state,
     const char* function_name,
     const DoTexSubImageArguments& args) {
   TRACE_EVENT0("gpu", "TextureManager::ValidateAndDoTexSubImage");
-  ErrorState* error_state = state->GetErrorState();
   TextureRef* texture_ref;
-  if (!ValidateTexSubImage(state, function_name, args, &texture_ref)) {
+  if (!ValidateTexSubImage(state, error_state, function_name, args,
+                           &texture_ref)) {
     return;
   }
 
@@ -3431,14 +3438,13 @@
   return format;
 }
 
-void TextureManager::DoTexImage(
-    DecoderTextureState* texture_state,
-    ContextState* state,
-    DecoderFramebufferState* framebuffer_state,
-    const char* function_name,
-    TextureRef* texture_ref,
-    const DoTexImageArguments& args) {
-  ErrorState* error_state = state->GetErrorState();
+void TextureManager::DoTexImage(DecoderTextureState* texture_state,
+                                ContextState* state,
+                                ErrorState* error_state,
+                                DecoderFramebufferState* framebuffer_state,
+                                const char* function_name,
+                                TextureRef* texture_ref,
+                                const DoTexImageArguments& args) {
   Texture* texture = texture_ref->texture();
   GLsizei tex_width = 0;
   GLsizei tex_height = 0;
diff --git a/gpu/command_buffer/service/texture_manager.h b/gpu/command_buffer/service/texture_manager.h
index 4a51448..4e96738 100644
--- a/gpu/command_buffer/service/texture_manager.h
+++ b/gpu/command_buffer/service/texture_manager.h
@@ -1069,20 +1069,20 @@
     TexImageCommandType command_type;
   };
 
-  bool ValidateTexImage(
-    ContextState* state,
-    const char* function_name,
-    const DoTexImageArguments& args,
-    // Pointer to TextureRef filled in if validation successful.
-    // Presumes the pointer is valid.
-    TextureRef** texture_ref);
+  bool ValidateTexImage(ContextState* state,
+                        ErrorState* error_state,
+                        const char* function_name,
+                        const DoTexImageArguments& args,
+                        // Pointer to TextureRef filled in if validation
+                        // successful. Presumes the pointer is valid.
+                        TextureRef** texture_ref);
 
-  void ValidateAndDoTexImage(
-    DecoderTextureState* texture_state,
-    ContextState* state,
-    DecoderFramebufferState* framebuffer_state,
-    const char* function_name,
-    const DoTexImageArguments& args);
+  void ValidateAndDoTexImage(DecoderTextureState* texture_state,
+                             ContextState* state,
+                             ErrorState* error_state,
+                             DecoderFramebufferState* framebuffer_state,
+                             const char* function_name,
+                             const DoTexImageArguments& args);
 
   struct DoTexSubImageArguments {
     enum TexSubImageCommandType {
@@ -1106,17 +1106,18 @@
     TexSubImageCommandType command_type;
   };
 
-  bool ValidateTexSubImage(
-      ContextState* state,
-      const char* function_name,
-      const DoTexSubImageArguments& args,
-      // Pointer to TextureRef filled in if validation successful.
-      // Presumes the pointer is valid.
-      TextureRef** texture_ref);
+  bool ValidateTexSubImage(ContextState* state,
+                           ErrorState* error_state,
+                           const char* function_name,
+                           const DoTexSubImageArguments& args,
+                           // Pointer to TextureRef filled in if validation
+                           // successful. Presumes the pointer is valid.
+                           TextureRef** texture_ref);
 
   void ValidateAndDoTexSubImage(DecoderContext* decoder,
                                 DecoderTextureState* texture_state,
                                 ContextState* state,
+                                ErrorState* error_state,
                                 DecoderFramebufferState* framebuffer_state,
                                 const char* function_name,
                                 const DoTexSubImageArguments& args);
@@ -1162,14 +1163,14 @@
   static GLenum AdjustTexStorageFormat(const gles2::FeatureInfo* feature_info,
                                        GLenum format);
 
-  void WorkaroundCopyTexImageCubeMap(
-      DecoderTextureState* texture_state,
-      ContextState* state,
-      DecoderFramebufferState* framebuffer_state,
-      TextureRef* texture_ref,
-      const char* function_name,
-      const DoTexImageArguments& args) {
-    DoCubeMapWorkaround(texture_state, state, framebuffer_state,
+  void WorkaroundCopyTexImageCubeMap(DecoderTextureState* texture_state,
+                                     ContextState* state,
+                                     ErrorState* error_state,
+                                     DecoderFramebufferState* framebuffer_state,
+                                     TextureRef* texture_ref,
+                                     const char* function_name,
+                                     const DoTexImageArguments& args) {
+    DoCubeMapWorkaround(texture_state, state, error_state, framebuffer_state,
                         texture_ref, function_name, args);
   }
 
@@ -1182,19 +1183,20 @@
       GLenum target,
       GLuint* black_texture);
 
-  void DoTexImage(
-      DecoderTextureState* texture_state,
-      ContextState* state,
-      DecoderFramebufferState* framebuffer_state,
-      const char* function_name,
-      TextureRef* texture_ref,
-      const DoTexImageArguments& args);
+  void DoTexImage(DecoderTextureState* texture_state,
+                  ContextState* state,
+                  ErrorState* error_state,
+                  DecoderFramebufferState* framebuffer_state,
+                  const char* function_name,
+                  TextureRef* texture_ref,
+                  const DoTexImageArguments& args);
 
   // Reserve memory for the texture and set its attributes so it can be filled
   // with TexSubImage. The image contents are undefined after this function,
   // so make sure it's subsequently filled in its entirety.
   void ReserveTexImageToBeFilled(DecoderTextureState* texture_state,
                                  ContextState* state,
+                                 ErrorState* error_state,
                                  DecoderFramebufferState* framebuffer_state,
                                  const char* function_name,
                                  TextureRef* texture_ref,
@@ -1216,13 +1218,13 @@
       const DoTexSubImageArguments& args,
       const PixelStoreParams& unpack_params);
 
-  void DoCubeMapWorkaround(
-      DecoderTextureState* texture_state,
-      ContextState* state,
-      DecoderFramebufferState* framebuffer_state,
-      TextureRef* texture_ref,
-      const char* function_name,
-      const DoTexImageArguments& args);
+  void DoCubeMapWorkaround(DecoderTextureState* texture_state,
+                           ContextState* state,
+                           ErrorState* error_state,
+                           DecoderFramebufferState* framebuffer_state,
+                           TextureRef* texture_ref,
+                           const char* function_name,
+                           const DoTexImageArguments& args);
 
   void StartTracking(TextureRef* texture);
   void StopTracking(TextureRef* texture);