Reland "Share one GLContext for all RasterDecoder when virtual context is used."


Original change's description:
> Revert "Share one GLContext for all RasterDecoder when virtual context is used."
>
> This reverts commit 1808a743048d147521eaffb386dc9f29b4ecae0e.
>
> Reason for revert: Null-dereference READ in gpu::gles2::ContextState::api
> https://crbug.com/912981
>
> Original change's description:
> > Share one GLContext for all RasterDecoder when virtual context is used.
> >
> > With this CL, we will create a GLContextVirtual in RasterDecoderContextState,
> > and share it with all raster decoders, display compositoer, etc. It is a
> > temporary solution. In follow up CLs, we will share the one GLContext with
> > GLES2 as well. In that case, we will use GLContext directly instead of
> > GLContextVirtual.
> >
> > Change-Id: If9b8d1f32e58b32a9d9f8cd07aa10c30432e3183
> > Bug: 902904
> > Reviewed-on: https://chromium-review.googlesource.com/c/1357463
> > Commit-Queue: Peng Huang <penghuang@chromium.org>
> > Reviewed-by: Antoine Labour <piman@chromium.org>
> > Cr-Commit-Position: refs/heads/master@{#614694}
>
> TBR=penghuang@chromium.org,piman@chromium.org
>
> Change-Id: I2eb66f211d408988f30bfb870425da80e0eb7a4b
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Bug: 902904
> Reviewed-on: https://chromium-review.googlesource.com/c/1368284
> Reviewed-by: Peng Huang <penghuang@chromium.org>
> Commit-Queue: Peng Huang <penghuang@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#614738}

TBR=penghuang@chromium.org,piman@chromium.org

Change-Id: Ie409d5d631509efa978a8741381cedbbbcdb3904
Bug: 902904
Reviewed-on: https://chromium-review.googlesource.com/c/1368031
Reviewed-by: Peng Huang <penghuang@chromium.org>
Commit-Queue: Peng Huang <penghuang@chromium.org>
Cr-Commit-Position: refs/heads/master@{#614796}
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h
index 64b4e99..4501800 100644
--- a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h
+++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h
@@ -140,7 +140,7 @@
   bool MakeCurrent();
 
   GrContext* gr_context() { return context_state_->gr_context; }
-  gl::GLContext* gl_context() { return context_state_->context.get(); }
+  gl::GLContext* gl_context() { return context_state_->context(); }
 
   const gpu::CommandBufferId command_buffer_id_;
   GpuServiceImpl* const gpu_service_;
diff --git a/components/viz/service/gl/gpu_service_impl.cc b/components/viz/service/gl/gpu_service_impl.cc
index eec9603..9ce7beb2 100644
--- a/components/viz/service/gl/gpu_service_impl.cc
+++ b/components/viz/service/gl/gpu_service_impl.cc
@@ -298,7 +298,7 @@
   // TODO(penghuang): https://crbug.com/899740 Support GLSurface which is not
   // compatible.
   DCHECK_EQ(surface->GetCompatibilityKey(),
-            context_state->surface->GetCompatibilityKey());
+            context_state->surface()->GetCompatibilityKey());
   DCHECK(!context_state->use_virtualized_gl_contexts);
   return context_state;
 }
diff --git a/gpu/command_buffer/service/decoder_context.h b/gpu/command_buffer/service/decoder_context.h
index abc53a0..523bf03 100644
--- a/gpu/command_buffer/service/decoder_context.h
+++ b/gpu/command_buffer/service/decoder_context.h
@@ -213,6 +213,12 @@
   // Methods required by GpuTracer
   //
   virtual gles2::Outputter* outputter() const = 0;
+
+  // Restores all attributs in the gl context state.
+  virtual void RestoreAllAttributes() const = 0;
+
+  // Restores texture states for a given service id.
+  virtual void RestoreTextureState(unsigned service_id) const = 0;
 };
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/gl_context_virtual_delegate.h b/gpu/command_buffer/service/gl_context_virtual_delegate.h
index 1b2ffc57..0db2f14 100644
--- a/gpu/command_buffer/service/gl_context_virtual_delegate.h
+++ b/gpu/command_buffer/service/gl_context_virtual_delegate.h
@@ -32,7 +32,6 @@
   // Restore States.
   virtual void RestoreGlobalState() const = 0;
   virtual void ClearAllAttributes() const = 0;
-  virtual void RestoreAllAttributes() const = 0;
   virtual void RestoreActiveTexture() const = 0;
   virtual void RestoreAllTextureUnitAndSamplerBindings(
       const gles2::ContextState* prev_state) const = 0;
@@ -42,7 +41,6 @@
   virtual void RestoreFramebufferBindings() const = 0;
   virtual void RestoreRenderbufferBindings() = 0;
   virtual void RestoreProgramBindings() const = 0;
-  virtual void RestoreTextureState(unsigned service_id) const = 0;
   virtual void RestoreTextureUnitBindings(unsigned unit) const = 0;
   virtual void RestoreVertexAttribArray(unsigned index) = 0;
   virtual void RestoreAllExternalTextureBindingsIfNeeded() = 0;
diff --git a/gpu/command_buffer/service/gl_state_restorer_impl.cc b/gpu/command_buffer/service/gl_state_restorer_impl.cc
index d47a8d4..0d20724 100644
--- a/gpu/command_buffer/service/gl_state_restorer_impl.cc
+++ b/gpu/command_buffer/service/gl_state_restorer_impl.cc
@@ -71,12 +71,14 @@
 
 void GLStateRestorerImpl::PauseQueries() {
   DCHECK(delegate_.get());
-  delegate_->GetQueryManager()->PauseQueries();
+  if (auto* query_manager = delegate_->GetQueryManager())
+    query_manager->PauseQueries();
 }
 
 void GLStateRestorerImpl::ResumeQueries() {
   DCHECK(delegate_.get());
-  delegate_->GetQueryManager()->ResumeQueries();
+  if (auto* query_manager = delegate_->GetQueryManager())
+    query_manager->ResumeQueries();
 }
 
 const gles2::ContextState* GLStateRestorerImpl::GetContextState() const {
diff --git a/gpu/command_buffer/service/gr_cache_controller.cc b/gpu/command_buffer/service/gr_cache_controller.cc
index 4bb1cc1..787ef40 100644
--- a/gpu/command_buffer/service/gr_cache_controller.cc
+++ b/gpu/command_buffer/service/gr_cache_controller.cc
@@ -21,7 +21,7 @@
 
 void GrCacheController::ScheduleGrContextCleanup() {
   DCHECK(task_runner_->BelongsToCurrentThread());
-  DCHECK(context_state_->context->IsCurrent(nullptr));
+  DCHECK(context_state_->IsCurrent(nullptr));
 
   if (!context_state_->gr_context)
     return;
@@ -35,7 +35,6 @@
   // a long while even if it is under budget. Below we set a call back to
   // purge all possible GrContext resources if the context itself is not being
   // used.
-  context_state_->context->DirtyVirtualContextState();
   context_state_->need_context_state_reset = true;
   context_state_->gr_context->performDeferredCleanup(
       std::chrono::seconds(kOldResourceCleanupDelaySeconds));
@@ -64,7 +63,6 @@
     return;
   }
 
-  context_state_->context->DirtyVirtualContextState();
   context_state_->need_context_state_reset = true;
   context_state_->gr_context->freeGpuResources();
 }
diff --git a/gpu/command_buffer/service/gr_cache_controller_unittest.cc b/gpu/command_buffer/service/gr_cache_controller_unittest.cc
index ccd865d..b4c489cc 100644
--- a/gpu/command_buffer/service/gr_cache_controller_unittest.cc
+++ b/gpu/command_buffer/service/gr_cache_controller_unittest.cc
@@ -8,6 +8,7 @@
 #include "base/test/test_mock_time_task_runner.h"
 #include "gpu/command_buffer/service/raster_decoder_context_state.h"
 #include "gpu/config/gpu_driver_bug_workarounds.h"
+#include "gpu/config/gpu_feature_info.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "third_party/skia/include/core/SkImage.h"
@@ -38,6 +39,7 @@
         std::move(share_group), std::move(surface), std::move(context),
         false /* use_virtualized_gl_contexts */, base::DoNothing());
     context_state_->InitializeGrContext(workarounds, nullptr);
+    context_state_->InitializeGL(workarounds, GpuFeatureInfo());
 
     controller_ =
         std::make_unique<GrCacheController>(context_state_.get(), task_runner_);
diff --git a/gpu/command_buffer/service/raster_decoder.cc b/gpu/command_buffer/service/raster_decoder.cc
index 7b9f9d8..e34d92f 100644
--- a/gpu/command_buffer/service/raster_decoder.cc
+++ b/gpu/command_buffer/service/raster_decoder.cc
@@ -72,16 +72,16 @@
 
 // Local versions of the SET_GL_ERROR macros
 #define LOCAL_SET_GL_ERROR(error, function_name, msg) \
-  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, \
+  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(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(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(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) RenderWarning(__FILE__, __LINE__, msg)
@@ -284,6 +284,8 @@
   }
   Capabilities GetCapabilities() override;
   const gles2::ContextState* GetContextState() override;
+
+  // TODO(penghuang): Remove unused context state related methods.
   void RestoreGlobalState() const override;
   void ClearAllAttributes() const override;
   void RestoreAllAttributes() const override;
@@ -302,6 +304,7 @@
   void RestoreVertexAttribArray(unsigned index) override;
   void RestoreAllExternalTextureBindingsIfNeeded() override;
   QueryManager* GetQueryManager() override;
+
   void SetQueryCallback(unsigned int query_client_id,
                         base::OnceClosure callback) override;
   gles2::GpuFenceManager* GetGpuFenceManager() override;
@@ -404,7 +407,10 @@
     return &it->second;
   }
 
-  gl::GLApi* api() const { return state_.api(); }
+  gles2::ContextState* state() const {
+    return raster_decoder_context_state_->context_state();
+  }
+  gl::GLApi* api() const { return state()->api(); }
   GrContext* gr_context() const {
     return raster_decoder_context_state_->gr_context;
   }
@@ -422,7 +428,8 @@
 
   bool IsRobustnessSupported() {
     return has_robustness_extension_ &&
-           context_->WasAllocatedUsingRobustnessExtension();
+           raster_decoder_context_state_->context()
+               ->WasAllocatedUsingRobustnessExtension();
   }
 
   const gl::GLVersionInfo& gl_version_info() {
@@ -598,7 +605,6 @@
   // only if not returning an error.
   error::Error current_decoder_error_ = error::kNoError;
 
-  scoped_refptr<gl::GLSurface> surface_;
   scoped_refptr<gl::GLContext> context_;
 
   DecoderClient* client_;
@@ -606,6 +612,7 @@
   gles2::DebugMarkerManager debug_marker_manager_;
   gles2::Logger logger_;
   std::unique_ptr<gles2::ErrorState> error_state_;
+  bool context_lost_ = false;
 
   // The ContextGroup for this decoder uses to track resources.
   scoped_refptr<gles2::ContextGroup> group_;
@@ -615,9 +622,6 @@
 
   std::unique_ptr<QueryManager> query_manager_;
 
-  // All the state for this context.
-  gles2::ContextState state_;
-
   gles2::GLES2Util util_;
 
   // An optional behaviour to lose the context and group when OOM.
@@ -737,8 +741,6 @@
       raster_decoder_context_state_(std::move(raster_decoder_context_state)),
       validators_(new Validators),
       feature_info_(group_->feature_info()),
-      state_(group_->feature_info(),
-             false /* track_texture_and_sampler_units */),
       service_logging_(
           group_->gpu_preferences().enable_gpu_service_logging_gpu),
       gpu_decoder_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
@@ -767,8 +769,6 @@
   DCHECK(context->IsCurrent(surface.get()));
   DCHECK(!context_.get());
 
-  state_.set_api(gl::g_current_gl_context);
-
   set_initialized();
 
   if (!offscreen) {
@@ -781,7 +781,8 @@
   if (group_->gpu_preferences().enable_gpu_command_logging)
     SetLogCommands(true);
 
-  surface_ = surface;
+  DCHECK_EQ(surface.get(), raster_decoder_context_state_->surface());
+  DCHECK_EQ(context.get(), raster_decoder_context_state_->context());
   context_ = context;
 
   // Create GPU Tracer for timing values.
@@ -799,22 +800,15 @@
     Destroy(true);
     return result;
   }
+
   CHECK_GL_ERROR();
 
-  state_.InitGenericAttribs(group_->max_vertex_attribs());
-
-  query_manager_.reset(new QueryManager());
+  query_manager_ = std::make_unique<QueryManager>();
 
   has_robustness_extension_ = features().arb_robustness ||
                               features().khr_robustness ||
                               features().ext_robustness;
 
-  // Set all the default state because some GL drivers get it wrong.
-  // TODO(backer): Not all of this state needs to be initialized. Reduce the set
-  // if perf becomes a problem.
-  state_.InitCapabilities(nullptr);
-  state_.InitState(nullptr);
-
   if (attrib_helper.enable_oop_rasterization) {
     if (!features().chromium_raster_transport) {
       LOG(ERROR) << "ContextResult::kFatalFailure: "
@@ -836,7 +830,8 @@
   if (!initialized())
     return;
 
-  DCHECK(!have_context || context_->IsCurrent(nullptr));
+  DCHECK(!have_context ||
+         raster_decoder_context_state_->context()->IsCurrent(nullptr));
 
   if (have_context) {
     if (copy_tex_image_blit_.get()) {
@@ -861,14 +856,8 @@
     if (group_ && group_->texture_manager()) {
       group_->texture_manager()->MarkContextLost();
     }
-
-    state_.MarkContextLost();
   }
 
-  // Unbind everything.
-  state_.bound_pixel_pack_buffer = nullptr;
-  state_.bound_pixel_unpack_buffer = nullptr;
-
   copy_tex_image_blit_.reset();
   copy_texture_chromium_.reset();
 
@@ -884,8 +873,6 @@
 
   // Destroy the surface before the context, some surface destructors make GL
   // calls.
-  surface_ = nullptr;
-
   if (context_.get()) {
     context_->ReleaseCurrent(nullptr);
     context_ = nullptr;
@@ -897,23 +884,22 @@
 
 // Make this decoder's GL context current.
 bool RasterDecoderImpl::MakeCurrent() {
-  DCHECK(surface_);
   if (!context_.get())
     return false;
 
-  if (WasContextLost()) {
+  if (context_lost_) {
     LOG(ERROR) << "  RasterDecoderImpl: Trying to make lost context current.";
     return false;
   }
 
-  // TODO(https://crbug.com/902904): Switch to
-  // raster_decoder_context_state_->MakeCurrent(nullptr).
-  if (!context_->MakeCurrent(surface_.get())) {
+  if (raster_decoder_context_state_->context_lost() ||
+      !raster_decoder_context_state_->MakeCurrent(nullptr)) {
     LOG(ERROR) << "  RasterDecoderImpl: Context lost during MakeCurrent.";
     MarkContextLost(error::kMakeCurrentFailed);
     group_->LoseContexts(error::kUnknown);
     return false;
   }
+
   DCHECK_EQ(api(), gl::g_current_gl_context);
 
   if (CheckResetStatus()) {
@@ -934,7 +920,7 @@
 }
 
 gl::GLSurface* RasterDecoderImpl::GetGLSurface() {
-  return surface_.get();
+  return raster_decoder_context_state_->surface();
 }
 
 Capabilities RasterDecoderImpl::GetCapabilities() {
@@ -966,18 +952,12 @@
 }
 
 const gles2::ContextState* RasterDecoderImpl::GetContextState() {
-  if (raster_decoder_context_state_->need_context_state_reset) {
-    // Returning nullptr to force full state restoration by the caller.  We do
-    // this because GrContext changes to GL state are untracked in our state_.
-    return nullptr;
-  }
-
-  return &state_;
+  NOTREACHED();
+  return nullptr;
 }
 
 void RasterDecoderImpl::RestoreGlobalState() const {
   raster_decoder_context_state_->PessimisticallyResetGrContext();
-  state_.RestoreGlobalState(nullptr);
 }
 
 void RasterDecoderImpl::ClearAllAttributes() const {}
@@ -987,10 +967,6 @@
 }
 
 void RasterDecoderImpl::RestoreState(const gles2::ContextState* prev_state) {
-  TRACE_EVENT1("gpu", "RasterDecoderImpl::RestoreState", "context",
-               logger_.GetLogPrefix());
-  state_.RestoreState(prev_state);
-  raster_decoder_context_state_->need_context_state_reset = false;
   raster_decoder_context_state_->PessimisticallyResetGrContext();
 }
 
@@ -1010,36 +986,22 @@
 
 void RasterDecoderImpl::RestoreBufferBinding(unsigned int target) {
   raster_decoder_context_state_->PessimisticallyResetGrContext();
-  if (target == GL_PIXEL_PACK_BUFFER) {
-    state_.UpdatePackParameters();
-  } else if (target == GL_PIXEL_UNPACK_BUFFER) {
-    state_.UpdateUnpackParameters();
-  }
-  api()->glBindBufferFn(target, 0);
 }
 
 void RasterDecoderImpl::RestoreBufferBindings() const {
   raster_decoder_context_state_->PessimisticallyResetGrContext();
-  state_.RestoreBufferBindings();
 }
 
 void RasterDecoderImpl::RestoreFramebufferBindings() const {
   raster_decoder_context_state_->PessimisticallyResetGrContext();
-  state_.fbo_binding_for_scissor_workaround_dirty = true;
-  state_.stencil_state_changed_since_validation = true;
-
-  if (workarounds().flush_on_framebuffer_change)
-    api()->glFlushFn();
 }
 
 void RasterDecoderImpl::RestoreRenderbufferBindings() {
   raster_decoder_context_state_->PessimisticallyResetGrContext();
-  state_.RestoreRenderbufferBindings();
 }
 
 void RasterDecoderImpl::RestoreProgramBindings() const {
   raster_decoder_context_state_->PessimisticallyResetGrContext();
-  state_.RestoreProgramSettings(nullptr, false);
 }
 
 void RasterDecoderImpl::RestoreTextureState(unsigned service_id) const {
@@ -1067,7 +1029,7 @@
 }
 
 void RasterDecoderImpl::RestoreVertexAttribArray(unsigned index) {
-  NOTIMPLEMENTED();
+  raster_decoder_context_state_->PessimisticallyResetGrContext();
 }
 
 void RasterDecoderImpl::RestoreAllExternalTextureBindingsIfNeeded() {
@@ -1096,13 +1058,12 @@
 }
 
 bool RasterDecoderImpl::HasPendingQueries() const {
-  return query_manager_.get() && query_manager_->HavePendingQueries();
+  return query_manager_ && query_manager_->HavePendingQueries();
 }
 
 void RasterDecoderImpl::ProcessPendingQueries(bool did_finish) {
-  if (!query_manager_.get())
-    return;
-  query_manager_->ProcessPendingQueries(did_finish);
+  if (query_manager_)
+    query_manager_->ProcessPendingQueries(did_finish);
 }
 
 bool RasterDecoderImpl::HasMoreIdleWork() const {
@@ -1137,7 +1098,7 @@
 }
 
 bool RasterDecoderImpl::WasContextLost() const {
-  return raster_decoder_context_state_->context_lost;
+  return context_lost_;
 }
 
 bool RasterDecoderImpl::WasContextLostByRobustnessExtension() const {
@@ -1150,16 +1111,14 @@
     return;
 
   // Don't make GL calls in here, the context might not be current.
+  context_lost_ = true;
   command_buffer_service()->SetContextLostReason(reason);
   current_decoder_error_ = error::kLostContext;
-
-  state_.MarkContextLost();
-  raster_decoder_context_state_->MarkContextLost();
 }
 
 bool RasterDecoderImpl::CheckResetStatus() {
   DCHECK(!WasContextLost());
-  DCHECK(context_->IsCurrent(nullptr));
+  DCHECK(raster_decoder_context_state_->context()->IsCurrent(nullptr));
 
   if (IsRobustnessSupported()) {
     // If the reason for the call was a GL error, we can try to determine the
@@ -1201,7 +1160,7 @@
 }
 
 void RasterDecoderImpl::SetIgnoreCachedStateForTest(bool ignore) {
-  state_.SetIgnoreCachedStateForTest(ignore);
+  state()->SetIgnoreCachedStateForTest(ignore);
 }
 
 gles2::ImageManager* RasterDecoderImpl::GetImageManagerForTest() {
@@ -1440,12 +1399,12 @@
   {
     const bool state_is_dirty =
         raster_decoder_context_state_->need_context_state_reset;
-    ScopedTextureBinder binder(&state_, texture->target(),
+    ScopedTextureBinder binder(state(), texture->target(),
                                texture->service_id(), gr_context(),
                                state_is_dirty);
     base::Optional<ScopedPixelUnpackState> pixel_unpack_state;
     if (raster_decoder_context_state_->need_context_state_reset) {
-      pixel_unpack_state.emplace(&state_, gr_context(), group_->feature_info());
+      pixel_unpack_state.emplace(state(), gr_context(), group_->feature_info());
     }
     // Add extra scope to destroy zero and the object it owns right
     // after its usage.
@@ -1882,7 +1841,7 @@
   GLint dest_level = 0;
 
   ScopedTextureBinder binder(
-      &state_, texture_manager(), dest_texture_ref, dest_target, gr_context(),
+      state(), texture_manager(), dest_texture_ref, dest_target, gr_context(),
       raster_decoder_context_state_->need_context_state_reset);
   base::Optional<ScopedPixelUnpackState> pixel_unpack_state;
 
@@ -1921,7 +1880,7 @@
       // If the image is in shared memory, we may need upload the pixel data
       // with SubTexImage2D, so we need reset pixel unpack state if gl context
       // state has been touched by skia.
-      pixel_unpack_state.emplace(&state_, gr_context(), group_->feature_info());
+      pixel_unpack_state.emplace(state(), gr_context(), group_->feature_info());
     }
   } else {
     if (!source_texture->GetLevelSize(source_target, 0 /* level */,
@@ -1982,7 +1941,7 @@
             source_internal_format) == GL_SRGB ||
         gles2::GLES2Util::GetColorEncodingFromInternalFormat(
             dest_internal_format) == GL_SRGB;
-    state_.EnableDisableFramebufferSRGB(enable_framebuffer_srgb);
+    state()->EnableDisableFramebufferSRGB(enable_framebuffer_srgb);
   }
 
   // Clear the source texture if necessary.
@@ -2095,7 +2054,8 @@
     gl::GLImage* image = texture->GetLevelImage(textarget, 0, &image_state);
     if (image && image_state == gles2::Texture::UNBOUND) {
       ScopedGLErrorSuppressor suppressor(
-          "RasterDecoderImpl::DoBindOrCopyTexImageIfNeeded", GetErrorState());
+          "RasterDecoderImpl::DoBindOrCopyTexImageIfNeeded",
+          error_state_.get());
       api()->glBindTextureFn(textarget, texture->service_id());
       if (!image->BindTexImage(textarget)) {
         // Note: We update the state to COPIED prior to calling CopyTexImage()
diff --git a/gpu/command_buffer/service/raster_decoder_context_state.cc b/gpu/command_buffer/service/raster_decoder_context_state.cc
index 5ebefe8..9dc7b516 100644
--- a/gpu/command_buffer/service/raster_decoder_context_state.cc
+++ b/gpu/command_buffer/service/raster_decoder_context_state.cc
@@ -7,6 +7,8 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/trace_event/memory_dump_manager.h"
 #include "gpu/command_buffer/common/activity_flags.h"
+#include "gpu/command_buffer/service/context_state.h"
+#include "gpu/command_buffer/service/gl_context_virtual.h"
 #include "gpu/command_buffer/service/service_transfer_cache.h"
 #include "gpu/config/gpu_driver_bug_workarounds.h"
 #include "gpu/vulkan/buildflags.h"
@@ -30,17 +32,19 @@
     bool use_virtualized_gl_contexts,
     base::OnceClosure context_lost_callback,
     viz::VulkanContextProvider* vulkan_context_provider)
-    : share_group(std::move(share_group)),
-      surface(std::move(surface)),
-      context(std::move(context)),
-      use_virtualized_gl_contexts(use_virtualized_gl_contexts),
+    : use_virtualized_gl_contexts(use_virtualized_gl_contexts),
       context_lost_callback(std::move(context_lost_callback)),
       vk_context_provider(vulkan_context_provider),
 #if BUILDFLAG(ENABLE_VULKAN)
       gr_context(vk_context_provider ? vk_context_provider->GetGrContext()
                                      : nullptr),
 #endif
-      use_vulkan_gr_context(!!gr_context) {
+      use_vulkan_gr_context(!!gr_context),
+      share_group_(std::move(share_group)),
+      context_(context),
+      real_context_(std::move(context)),
+      surface_(std::move(surface)),
+      weak_ptr_factory_(this) {
   if (base::ThreadTaskRunnerHandle::IsSet()) {
     base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
         this, "RasterDecoderContextState", base::ThreadTaskRunnerHandle::Get());
@@ -60,10 +64,10 @@
     GpuProcessActivityFlags* activity_flags,
     gl::ProgressReporter* progress_reporter) {
   if (!use_vulkan_gr_context) {
-    DCHECK(context->IsCurrent(surface.get()));
+    DCHECK(context_->IsCurrent(surface()));
 
     sk_sp<GrGLInterface> interface(gl::init::CreateGrGLInterface(
-        *context->GetVersionInfo(), workarounds.use_es2_for_oopr,
+        *context_->GetVersionInfo(), workarounds.use_es2_for_oopr,
         progress_reporter));
     if (!interface) {
       LOG(ERROR) << "OOP raster support disabled: GrGLInterface creation "
@@ -111,6 +115,77 @@
   transfer_cache = std::make_unique<ServiceTransferCache>();
 }
 
+bool RasterDecoderContextState::InitializeGL(
+    const GpuDriverBugWorkarounds& gpu_driver_bug_workarounds,
+    const GpuFeatureInfo& gpu_feature_info) {
+  if (use_vulkan_gr_context)
+    return true;
+  DCHECK(!context_state_);
+
+  feature_info_ = base::MakeRefCounted<gles2::FeatureInfo>(
+      gpu_driver_bug_workarounds, gpu_feature_info);
+
+  feature_info_->Initialize(gpu::CONTEXT_TYPE_OPENGLES2,
+                            false /* is_passthrough_cmd_decoder */,
+                            gles2::DisallowedFeatures());
+
+  auto* api = gl::g_current_gl_context;
+  const GLint kGLES2RequiredMinimumVertexAttribs = 8u;
+  GLint max_vertex_attribs = 0;
+  api->glGetIntegervFn(GL_MAX_VERTEX_ATTRIBS, &max_vertex_attribs);
+  if (max_vertex_attribs < kGLES2RequiredMinimumVertexAttribs)
+    return false;
+
+  context_state_ = std::make_unique<gles2::ContextState>(
+      feature_info_.get(), false /* track_texture_and_sampler_units */);
+
+  context_state_->set_api(api);
+  context_state_->InitGenericAttribs(max_vertex_attribs);
+
+  // Set all the default state because some GL drivers get it wrong.
+  // TODO(backer): Not all of this state needs to be initialized. Reduce the set
+  // if perf becomes a problem.
+  context_state_->InitCapabilities(nullptr);
+  context_state_->InitState(nullptr);
+
+  if (use_virtualized_gl_contexts) {
+    auto virtual_context = base::MakeRefCounted<GLContextVirtual>(
+        share_group_.get(), real_context_.get(),
+        weak_ptr_factory_.GetWeakPtr());
+    if (!virtual_context->Initialize(surface_.get(), gl::GLContextAttribs()))
+      return false;
+    context_ = std::move(virtual_context);
+    MakeCurrent(nullptr);
+  }
+  return true;
+}
+
+bool RasterDecoderContextState::MakeCurrent(gl::GLSurface* surface) {
+  if (context_lost_)
+    return false;
+
+  if (!context_->MakeCurrent(surface ? surface : surface_.get())) {
+    MarkContextLost();
+    return false;
+  }
+  return true;
+}
+
+void RasterDecoderContextState::MarkContextLost() {
+  if (!context_lost_) {
+    context_lost_ = true;
+    context_state_->MarkContextLost();
+    if (gr_context)
+      gr_context->abandonContext();
+    std::move(context_lost_callback).Run();
+  }
+  // TODO notify gpu channel manager.
+}
+
+bool RasterDecoderContextState::IsCurrent(gl::GLSurface* surface) {
+  return context_->IsCurrent(surface);
+}
+
 bool RasterDecoderContextState::OnMemoryDump(
     const base::trace_event::MemoryDumpArgs& args,
     base::trace_event::ProcessMemoryDump* pmd) {
@@ -127,7 +202,7 @@
   }
 
   // Ensure the context is current before doing any GPU cleanup.
-  context->MakeCurrent(surface.get());
+  MakeCurrent(nullptr);
 
   switch (memory_pressure_level) {
     case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE:
@@ -155,28 +230,92 @@
     gr_context->resetContext();
 }
 
-void RasterDecoderContextState::MarkContextLost() {
-  if (!context_lost) {
-    context_lost = true;
-    if (gr_context)
-      gr_context->abandonContext();
-    std::move(context_lost_callback).Run();
-  }
+bool RasterDecoderContextState::initialized() const {
+  return true;
 }
 
-bool RasterDecoderContextState::MakeCurrent(gl::GLSurface* current_surface) {
-  if (context_lost)
-    return false;
-
-  if (context->IsCurrent(current_surface))
-    return true;
-
-  if (!context->MakeCurrent(current_surface ? current_surface
-                                            : surface.get())) {
-    MarkContextLost();
-    return false;
+const gles2::ContextState* RasterDecoderContextState::GetContextState() {
+  if (need_context_state_reset) {
+    // Returning nullptr to force full state restoration by the caller.  We do
+    // this because GrContext changes to GL state are untracked in our
+    // context_state_.
+    return nullptr;
   }
-  return true;
+  return context_state_.get();
+}
+
+void RasterDecoderContextState::RestoreState(
+    const gles2::ContextState* prev_state) {
+  PessimisticallyResetGrContext();
+  context_state_->RestoreState(prev_state);
+}
+
+void RasterDecoderContextState::RestoreGlobalState() const {
+  PessimisticallyResetGrContext();
+  context_state_->RestoreGlobalState(nullptr);
+}
+void RasterDecoderContextState::ClearAllAttributes() const {}
+
+void RasterDecoderContextState::RestoreActiveTexture() const {
+  PessimisticallyResetGrContext();
+}
+
+void RasterDecoderContextState::RestoreAllTextureUnitAndSamplerBindings(
+    const gles2::ContextState* prev_state) const {
+  PessimisticallyResetGrContext();
+}
+
+void RasterDecoderContextState::RestoreActiveTextureUnitBinding(
+    unsigned int target) const {
+  PessimisticallyResetGrContext();
+}
+
+void RasterDecoderContextState::RestoreBufferBinding(unsigned int target) {
+  PessimisticallyResetGrContext();
+  if (target == GL_PIXEL_PACK_BUFFER) {
+    context_state_->UpdatePackParameters();
+  } else if (target == GL_PIXEL_UNPACK_BUFFER) {
+    context_state_->UpdateUnpackParameters();
+  }
+  context_state_->api()->glBindBufferFn(target, 0);
+}
+
+void RasterDecoderContextState::RestoreBufferBindings() const {
+  PessimisticallyResetGrContext();
+  context_state_->RestoreBufferBindings();
+}
+
+void RasterDecoderContextState::RestoreFramebufferBindings() const {
+  PessimisticallyResetGrContext();
+  context_state_->fbo_binding_for_scissor_workaround_dirty = true;
+  context_state_->stencil_state_changed_since_validation = true;
+}
+
+void RasterDecoderContextState::RestoreRenderbufferBindings() {
+  PessimisticallyResetGrContext();
+  context_state_->RestoreRenderbufferBindings();
+}
+
+void RasterDecoderContextState::RestoreProgramBindings() const {
+  PessimisticallyResetGrContext();
+  context_state_->RestoreProgramSettings(nullptr, false);
+}
+
+void RasterDecoderContextState::RestoreTextureUnitBindings(
+    unsigned unit) const {
+  PessimisticallyResetGrContext();
+}
+
+void RasterDecoderContextState::RestoreVertexAttribArray(unsigned index) {
+  NOTIMPLEMENTED();
+}
+
+void RasterDecoderContextState::RestoreAllExternalTextureBindingsIfNeeded() {
+  PessimisticallyResetGrContext();
+}
+
+QueryManager* RasterDecoderContextState::GetQueryManager() {
+  return nullptr;
 }
 
 }  // namespace raster
diff --git a/gpu/command_buffer/service/raster_decoder_context_state.h b/gpu/command_buffer/service/raster_decoder_context_state.h
index 84bed6c..d34c622 100644
--- a/gpu/command_buffer/service/raster_decoder_context_state.h
+++ b/gpu/command_buffer/service/raster_decoder_context_state.h
@@ -7,8 +7,10 @@
 
 #include "base/memory/memory_pressure_listener.h"
 #include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
 #include "base/trace_event/memory_dump_provider.h"
 #include "gpu/command_buffer/common/skia_utils.h"
+#include "gpu/command_buffer/service/gl_context_virtual_delegate.h"
 #include "gpu/gpu_gles2_export.h"
 #include "third_party/skia/include/gpu/GrContext.h"
 #include "ui/gl/progress_reporter.h"
@@ -25,14 +27,21 @@
 
 namespace gpu {
 class GpuDriverBugWorkarounds;
+struct GpuFeatureInfo;
 class GpuProcessActivityFlags;
 class ServiceTransferCache;
+namespace gles2 {
+class FeatureInfo;
+struct ContextState;
+}  // namespace gles2
 
 namespace raster {
 
+// TODO(penghuang): Make RasterDecoderContextState a class.
 struct GPU_GLES2_EXPORT RasterDecoderContextState
-    : public base::RefCounted<RasterDecoderContextState>,
-      public base::trace_event::MemoryDumpProvider {
+    : public base::trace_event::MemoryDumpProvider,
+      public gpu::GLContextVirtualDelegate,
+      public base::RefCounted<RasterDecoderContextState> {
  public:
   // TODO: Refactor code to have seperate constructor for GL and Vulkan and not
   // initialize/use GL related info for vulkan and vice-versa.
@@ -48,20 +57,27 @@
                            GrContextOptions::PersistentCache* cache,
                            GpuProcessActivityFlags* activity_flags = nullptr,
                            gl::ProgressReporter* progress_reporter = nullptr);
+
+  // TODO(penghuang) do not depend on ContextGroup.
+  bool InitializeGL(const GpuDriverBugWorkarounds& gpu_driver_bug_workarounds,
+                    const GpuFeatureInfo& gpu_feature_info);
+
+  bool MakeCurrent(gl::GLSurface* surface);
+  void MarkContextLost();
+  bool IsCurrent(gl::GLSurface* surface);
+
   void PurgeMemory(
       base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level);
 
   void PessimisticallyResetGrContext() const;
 
-  void MarkContextLost();
+  gl::GLShareGroup* share_group() { return share_group_.get(); }
+  gl::GLContext* context() { return context_.get(); }
+  gl::GLContext* real_context() { return real_context_.get(); }
+  gl::GLSurface* surface() { return surface_.get(); }
+  gles2::ContextState* context_state() const { return context_state_.get(); }
+  bool context_lost() const { return context_lost_; }
 
-  // surface == nullptr indicates that caller doesn't care what surface is
-  // current with the context.
-  bool MakeCurrent(gl::GLSurface* current_surface);
-
-  scoped_refptr<gl::GLShareGroup> share_group;
-  scoped_refptr<gl::GLSurface> surface;
-  scoped_refptr<gl::GLContext> context;
   sk_sp<GrContext> owned_gr_context;
   std::unique_ptr<ServiceTransferCache> transfer_cache;
   const bool use_virtualized_gl_contexts = false;
@@ -69,7 +85,6 @@
   viz::VulkanContextProvider* vk_context_provider = nullptr;
   GrContext* gr_context = nullptr;
   const bool use_vulkan_gr_context = false;
-  bool context_lost = false;
   size_t glyph_cache_max_texture_bytes = 0u;
 
   // |need_context_state_reset| is set whenever Skia may have altered the
@@ -84,7 +99,43 @@
 
  private:
   friend class base::RefCounted<RasterDecoderContextState>;
+
   ~RasterDecoderContextState() override;
+
+  // gpu::GLContextVirtualDelegate implementation.
+  bool initialized() const override;
+  const gles2::ContextState* GetContextState() override;
+  void RestoreState(const gles2::ContextState* prev_state) override;
+  void RestoreGlobalState() const override;
+  void ClearAllAttributes() const override;
+  void RestoreActiveTexture() const override;
+  void RestoreAllTextureUnitAndSamplerBindings(
+      const gles2::ContextState* prev_state) const override;
+  void RestoreActiveTextureUnitBinding(unsigned int target) const override;
+  void RestoreBufferBinding(unsigned int target) override;
+  void RestoreBufferBindings() const override;
+  void RestoreFramebufferBindings() const override;
+  void RestoreRenderbufferBindings() override;
+  void RestoreProgramBindings() const override;
+  void RestoreTextureUnitBindings(unsigned unit) const override;
+  void RestoreVertexAttribArray(unsigned index) override;
+  void RestoreAllExternalTextureBindingsIfNeeded() override;
+  QueryManager* GetQueryManager() override;
+
+  scoped_refptr<gl::GLShareGroup> share_group_;
+  scoped_refptr<gl::GLContext> context_;
+  scoped_refptr<gl::GLContext> real_context_;
+  scoped_refptr<gl::GLSurface> surface_;
+  scoped_refptr<gles2::FeatureInfo> feature_info_;
+
+  // raster decoders and display compositor share this context_state_.
+  std::unique_ptr<gles2::ContextState> context_state_;
+
+  bool context_lost_ = false;
+
+  base::WeakPtrFactory<RasterDecoderContextState> weak_ptr_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(RasterDecoderContextState);
 };
 
 }  // namespace raster
diff --git a/gpu/command_buffer/service/raster_decoder_unittest.cc b/gpu/command_buffer/service/raster_decoder_unittest.cc
index 89d2836..efce9b9 100644
--- a/gpu/command_buffer/service/raster_decoder_unittest.cc
+++ b/gpu/command_buffer/service/raster_decoder_unittest.cc
@@ -214,6 +214,10 @@
     gl::GLSurfaceTestSupport::InitializeOneOff();
     gpu::GpuDriverBugWorkarounds workarounds;
 
+    GpuFeatureInfo gpu_feature_info;
+    gpu_feature_info.status_values[GPU_FEATURE_TYPE_OOP_RASTERIZATION] =
+        kGpuFeatureStatusEnabled;
+
     scoped_refptr<gl::GLShareGroup> share_group = new gl::GLShareGroup();
     scoped_refptr<gl::GLSurface> surface =
         gl::init::CreateOffscreenGLSurface(gfx::Size());
@@ -225,10 +229,8 @@
         std::move(share_group), std::move(surface), std::move(context),
         false /* use_virtualized_gl_contexts */, base::DoNothing());
     context_state_->InitializeGrContext(workarounds, nullptr);
+    context_state_->InitializeGL(workarounds, gpu_feature_info);
 
-    GpuFeatureInfo gpu_feature_info;
-    gpu_feature_info.status_values[GPU_FEATURE_TYPE_OOP_RASTERIZATION] =
-        kGpuFeatureStatusEnabled;
     scoped_refptr<gles2::FeatureInfo> feature_info =
         new gles2::FeatureInfo(workarounds, gpu_feature_info);
     group_ = new gles2::ContextGroup(
@@ -263,10 +265,10 @@
     ContextCreationAttribs attribs;
     attribs.enable_oop_rasterization = true;
     attribs.enable_raster_interface = true;
-    CHECK_EQ(
-        decoder->Initialize(context_state_->surface, context_state_->context,
-                            true, gles2::DisallowedFeatures(), attribs),
-        ContextResult::kSuccess);
+    CHECK_EQ(decoder->Initialize(context_state_->surface(),
+                                 context_state_->context(), true,
+                                 gles2::DisallowedFeatures(), attribs),
+             ContextResult::kSuccess);
     return decoder;
   }
 
@@ -313,7 +315,7 @@
   EXPECT_TRUE(context_state_->need_context_state_reset);
 
   decoder1->Destroy(true);
-  context_state_->context->MakeCurrent(context_state_->surface.get());
+  context_state_->MakeCurrent(nullptr);
   decoder2->Destroy(true);
 
   // Make sure the context is preserved across decoders.
diff --git a/gpu/command_buffer/service/raster_decoder_unittest_base.cc b/gpu/command_buffer/service/raster_decoder_unittest_base.cc
index 0c9edddb..af44348 100644
--- a/gpu/command_buffer/service/raster_decoder_unittest_base.cc
+++ b/gpu/command_buffer/service/raster_decoder_unittest_base.cc
@@ -230,7 +230,10 @@
   // we can use the ContextGroup to figure out how the real RasterDecoder
   // will initialize itself.
   command_buffer_service_.reset(new FakeCommandBufferServiceBase());
-  mock_decoder_.reset(new MockRasterDecoder(command_buffer_service_.get()));
+  command_buffer_service_for_mock_decoder_.reset(
+      new FakeCommandBufferServiceBase());
+  mock_decoder_.reset(
+      new MockRasterDecoder(command_buffer_service_for_mock_decoder_.get()));
 
   EXPECT_EQ(group_->Initialize(mock_decoder_.get(), context_type,
                                gles2::DisallowedFeatures()),
@@ -250,6 +253,14 @@
       init.lose_context_when_out_of_memory;
   attribs.context_type = context_type;
 
+  // Setup expections for RasterDecoderContextState::InitializeGL()
+  // It will initialize a FeatureInfo and
+  gles2::TestHelper::SetupFeatureInfoInitExpectationsWithGLVersion(
+      gl_.get(), all_extensions.c_str(), "" /* gl_renderer */,
+      init.gl_version.c_str(), CONTEXT_TYPE_OPENGLES2);
+  EXPECT_CALL(*gl_, GetIntegerv(GL_MAX_VERTEX_ATTRIBS, _))
+      .WillOnce(SetArgPointee<1>(8u))
+      .RetiresOnSaturation();
   SetupInitCapabilitiesExpectations(group_->feature_info()->IsES3Capable());
   SetupInitStateExpectations(group_->feature_info()->IsES3Capable());
 
@@ -257,6 +268,10 @@
       new gl::GLShareGroup(), surface_, context_,
       feature_info->workarounds().use_virtualized_gl_contexts,
       base::DoNothing());
+
+  raster_decoder_context_state_->InitializeGL(init.workarounds,
+                                              gpu_feature_info);
+
   decoder_.reset(RasterDecoder::Create(this, command_buffer_service_.get(),
                                        &outputter_, group_.get(),
                                        raster_decoder_context_state_));
@@ -266,9 +281,10 @@
   copy_texture_manager_ = new gles2::MockCopyTextureResourceManager();
   decoder_->SetCopyTextureResourceManagerForTest(copy_texture_manager_);
 
-  ASSERT_EQ(decoder_->Initialize(surface_, context_, true,
-                                 gles2::DisallowedFeatures(), attribs),
-            gpu::ContextResult::kSuccess);
+  ASSERT_EQ(
+      decoder_->Initialize(surface_, raster_decoder_context_state_->context(),
+                           true, gles2::DisallowedFeatures(), attribs),
+      gpu::ContextResult::kSuccess);
 
   EXPECT_CALL(*context_, MakeCurrent(surface_.get())).WillOnce(Return(true));
   if (context_->WasAllocatedUsingRobustnessExtension()) {
@@ -302,6 +318,7 @@
   decoder_.reset();
   group_->Destroy(mock_decoder_.get(), false);
   command_buffer_service_.reset();
+  command_buffer_service_for_mock_decoder_.reset();
   ::gl::MockGLInterface::SetGLInterface(nullptr);
   gl_.reset();
   gl::init::ShutdownGL(false);
diff --git a/gpu/command_buffer/service/raster_decoder_unittest_base.h b/gpu/command_buffer/service/raster_decoder_unittest_base.h
index 1eae7d8..84e84f9b 100644
--- a/gpu/command_buffer/service/raster_decoder_unittest_base.h
+++ b/gpu/command_buffer/service/raster_decoder_unittest_base.h
@@ -250,6 +250,8 @@
   std::unique_ptr<FakeCommandBufferServiceBase> command_buffer_service_;
   gles2::TraceOutputter outputter_;
   std::unique_ptr<MockRasterDecoder> mock_decoder_;
+  std::unique_ptr<FakeCommandBufferServiceBase>
+      command_buffer_service_for_mock_decoder_;
   std::unique_ptr<RasterDecoder> decoder_;
 
   GLuint client_texture_id_;
diff --git a/gpu/command_buffer/service/raster_decoder_unittest_context_lost.cc b/gpu/command_buffer/service/raster_decoder_unittest_context_lost.cc
index be57e397a..57bd17f 100644
--- a/gpu/command_buffer/service/raster_decoder_unittest_context_lost.cc
+++ b/gpu/command_buffer/service/raster_decoder_unittest_context_lost.cc
@@ -145,6 +145,7 @@
   EXPECT_CALL(*context_, MakeCurrent(surface_.get())).WillOnce(Return(false));
   // Expect the group to be lost.
   EXPECT_CALL(*mock_decoder_, MarkContextLost(error::kUnknown)).Times(1);
+  EXPECT_FALSE(decoder_->WasContextLost());
   decoder_->MakeCurrent();
   EXPECT_TRUE(decoder_->WasContextLost());
   EXPECT_EQ(error::kMakeCurrentFailed, GetContextLostReason());
@@ -285,18 +286,6 @@
   EXPECT_EQ(error::kInnocent, GetContextLostReason());
 }
 
-TEST_P(RasterDecoderLostContextTest, LoseVirtualContextWithRobustness) {
-  InitWithVirtualContextsAndRobustness();
-  EXPECT_CALL(*mock_decoder_, MarkContextLost(error::kUnknown)).Times(1);
-  // Signal guilty....
-  DoGetErrorWithContextLost(GL_GUILTY_CONTEXT_RESET_KHR);
-  EXPECT_TRUE(decoder_->WasContextLost());
-  EXPECT_TRUE(decoder_->WasContextLostByRobustnessExtension());
-  // ...but make sure we don't pretend, since for virtual contexts we don't
-  // know if this was really the guilty client.
-  EXPECT_EQ(error::kUnknown, GetContextLostReason());
-}
-
 TEST_P(RasterDecoderLostContextTest, LoseGroupFromRobustness) {
   // If one context in a group is lost through robustness,
   // the other ones should also get lost and query the reset status.
diff --git a/gpu/command_buffer/service/shared_image_backing_factory_ahardwarebuffer_unittest.cc b/gpu/command_buffer/service/shared_image_backing_factory_ahardwarebuffer_unittest.cc
index 99fde99..a810817 100644
--- a/gpu/command_buffer/service/shared_image_backing_factory_ahardwarebuffer_unittest.cc
+++ b/gpu/command_buffer/service/shared_image_backing_factory_ahardwarebuffer_unittest.cc
@@ -16,6 +16,7 @@
 #include "gpu/command_buffer/service/shared_image_representation.h"
 #include "gpu/command_buffer/service/texture_manager.h"
 #include "gpu/config/gpu_driver_bug_workarounds.h"
+#include "gpu/config/gpu_feature_info.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/skia/include/core/SkImage.h"
 #include "third_party/skia/include/core/SkSurface.h"
@@ -56,6 +57,7 @@
         std::move(share_group), surface_, context_,
         false /* use_virtualized_gl_contexts */, base::DoNothing());
     context_state_->InitializeGrContext(workarounds, nullptr);
+    context_state_->InitializeGL(workarounds, GpuFeatureInfo());
 
     memory_type_tracker_ = std::make_unique<MemoryTypeTracker>(nullptr);
     shared_image_representation_factory_ =
diff --git a/gpu/command_buffer/service/shared_image_backing_factory_gl_texture_unittest.cc b/gpu/command_buffer/service/shared_image_backing_factory_gl_texture_unittest.cc
index 6e6b802..c813a51 100644
--- a/gpu/command_buffer/service/shared_image_backing_factory_gl_texture_unittest.cc
+++ b/gpu/command_buffer/service/shared_image_backing_factory_gl_texture_unittest.cc
@@ -59,6 +59,7 @@
         std::move(share_group), surface_, context_,
         false /* use_virtualized_gl_contexts */, base::DoNothing());
     context_state_->InitializeGrContext(workarounds, nullptr);
+    context_state_->InitializeGL(workarounds, GpuFeatureInfo());
 
     memory_type_tracker_ = std::make_unique<MemoryTypeTracker>(nullptr);
     shared_image_representation_factory_ =
diff --git a/gpu/command_buffer/service/wrapped_sk_image.cc b/gpu/command_buffer/service/wrapped_sk_image.cc
index 911e917..ae7940f 100644
--- a/gpu/command_buffer/service/wrapped_sk_image.cc
+++ b/gpu/command_buffer/service/wrapped_sk_image.cc
@@ -30,9 +30,9 @@
 class WrappedSkImage : public SharedImageBacking {
  public:
   ~WrappedSkImage() override {
-    DCHECK(context_state_->context_lost ||
-           context_state_->context->IsCurrent(nullptr));
-    if (!context_state_->context_lost)
+    DCHECK(context_state_->context_lost() ||
+           context_state_->context()->IsCurrent(nullptr));
+    if (!context_state_->context_lost())
       context_state_->need_context_state_reset = true;
   }
 
@@ -70,9 +70,9 @@
   sk_sp<SkSurface> GetSkSurface(int final_msaa_count,
                                 SkColorType color_type,
                                 const SkSurfaceProps& surface_props) {
-    if (context_state_->context_lost)
+    if (context_state_->context_lost())
       return nullptr;
-    DCHECK(context_state_->context->IsCurrent(nullptr));
+    DCHECK(context_state_->context()->IsCurrent(nullptr));
     GrBackendTexture gr_texture =
         image_->getBackendTexture(/*flushPendingGrContextIO=*/true);
     DCHECK(gr_texture.isValid());
@@ -113,9 +113,9 @@
   }
 
   bool Initialize(const SkImageInfo& info) {
-    if (context_state_->context_lost)
+    if (context_state_->context_lost())
       return false;
-    DCHECK(context_state_->context->IsCurrent(nullptr));
+    DCHECK(context_state_->context()->IsCurrent(nullptr));
 
     context_state_->need_context_state_reset = true;
 
diff --git a/gpu/command_buffer/tests/fuzzer_main.cc b/gpu/command_buffer/tests/fuzzer_main.cc
index daad321..06f7f63 100644
--- a/gpu/command_buffer/tests/fuzzer_main.cc
+++ b/gpu/command_buffer/tests/fuzzer_main.cc
@@ -366,6 +366,7 @@
             share_group_, surface_, context_,
             config_.workarounds.use_virtualized_gl_contexts, base::DoNothing());
     context_state->InitializeGrContext(config_.workarounds, nullptr);
+    context_state->InitializeGL(config_.workarounds, gpu_feature_info);
     decoder_.reset(raster::RasterDecoder::Create(
         command_buffer_.get(), command_buffer_->service(), &outputter_,
         context_group.get(), std::move(context_state)));
diff --git a/gpu/ipc/in_process_command_buffer.cc b/gpu/ipc/in_process_command_buffer.cc
index 827a1f5..9cd41524 100644
--- a/gpu/ipc/in_process_command_buffer.cc
+++ b/gpu/ipc/in_process_command_buffer.cc
@@ -563,6 +563,8 @@
       context_state_ = base::MakeRefCounted<raster::RasterDecoderContextState>(
           gl_share_group_, surface_, real_context, use_virtualized_gl_context_,
           base::DoNothing());
+      context_state_->InitializeGL(workarounds,
+                                   task_executor_->gpu_feature_info());
       gr_shader_cache_ = params.gr_shader_cache;
       context_state_->InitializeGrContext(workarounds, params.gr_shader_cache,
                                           params.activity_flags);
@@ -582,18 +584,22 @@
     }
 
     if (use_virtualized_gl_context_) {
-      context_ = base::MakeRefCounted<GLContextVirtual>(
-          gl_share_group_.get(), real_context.get(), decoder_->AsWeakPtr());
-      if (!context_->Initialize(
-              surface_.get(),
-              GenerateGLContextAttribs(params.attribs, context_group_.get()))) {
-        // TODO(piman): This might not be fatal, we could recurse into
-        // CreateGLContext to get more info, tho it should be exceedingly
-        // rare and may not be recoverable anyway.
-        DestroyOnGpuThread();
-        LOG(ERROR) << "ContextResult::kFatalFailure: "
-                      "Failed to initialize virtual GL context.";
-        return gpu::ContextResult::kFatalFailure;
+      if (context_state_) {
+        context_ = context_state_->context();
+      } else {
+        context_ = base::MakeRefCounted<GLContextVirtual>(
+            gl_share_group_.get(), real_context.get(), decoder_->AsWeakPtr());
+        if (!context_->Initialize(surface_.get(),
+                                  GenerateGLContextAttribs(
+                                      params.attribs, context_group_.get()))) {
+          // TODO(piman): This might not be fatal, we could recurse into
+          // CreateGLContext to get more info, tho it should be exceedingly
+          // rare and may not be recoverable anyway.
+          DestroyOnGpuThread();
+          LOG(ERROR) << "ContextResult::kFatalFailure: "
+                        "Failed to initialize virtual GL context.";
+          return gpu::ContextResult::kFatalFailure;
+        }
       }
 
       if (!context_->MakeCurrent(surface_.get())) {
diff --git a/gpu/ipc/service/gpu_channel_manager.cc b/gpu/ipc/service/gpu_channel_manager.cc
index e72dc596..124f6865 100644
--- a/gpu/ipc/service/gpu_channel_manager.cc
+++ b/gpu/ipc/service/gpu_channel_manager.cc
@@ -319,7 +319,7 @@
 
   if (raster_decoder_context_state_) {
     gr_cache_controller_.reset();
-    raster_decoder_context_state_->context_lost = true;
+    raster_decoder_context_state_->MarkContextLost();
     raster_decoder_context_state_.reset();
   }
 
@@ -353,7 +353,7 @@
 scoped_refptr<raster::RasterDecoderContextState>
 GpuChannelManager::GetRasterDecoderContextState(ContextResult* result) {
   if (raster_decoder_context_state_ &&
-      !raster_decoder_context_state_->context_lost) {
+      !raster_decoder_context_state_->context_lost()) {
     *result = ContextResult::kSuccess;
     return raster_decoder_context_state_;
   }
@@ -442,6 +442,14 @@
                      /*synthetic_loss=*/false),
       vulkan_context_provider_);
 
+  if (!vulkan_context_provider_) {
+    if (!raster_decoder_context_state_->InitializeGL(
+            gpu_driver_bug_workarounds(), gpu_feature_info())) {
+      raster_decoder_context_state_ = nullptr;
+      return nullptr;
+    }
+  }
+
   const bool enable_raster_transport =
       gpu_feature_info_.status_values[GPU_FEATURE_TYPE_OOP_RASTERIZATION] ==
       gpu::kGpuFeatureStatusEnabled;
diff --git a/gpu/ipc/service/raster_command_buffer_stub.cc b/gpu/ipc/service/raster_command_buffer_stub.cc
index 78adb55..1751107 100644
--- a/gpu/ipc/service/raster_command_buffer_stub.cc
+++ b/gpu/ipc/service/raster_command_buffer_stub.cc
@@ -119,8 +119,8 @@
     return result;
   }
 
-  surface_ = raster_decoder_context_state->surface;
-  share_group_ = raster_decoder_context_state->share_group;
+  surface_ = raster_decoder_context_state->surface();
+  share_group_ = raster_decoder_context_state->share_group();
   use_virtualized_gl_context_ =
       raster_decoder_context_state->use_virtualized_gl_contexts;
 
@@ -138,26 +138,9 @@
   crash_keys::gpu_gl_context_is_virtual.Set(use_virtualized_gl_context_ ? "1"
                                                                         : "0");
 
-  scoped_refptr<gl::GLContext> context = raster_decoder_context_state->context;
-  if (use_virtualized_gl_context_) {
-    context = base::MakeRefCounted<GLContextVirtual>(
-        share_group_.get(), context.get(), decoder->AsWeakPtr());
-    if (!context->Initialize(surface_.get(),
-                             GenerateGLContextAttribs(init_params.attribs,
-                                                      context_group_.get()))) {
-      // The real context created above for the default offscreen surface
-      // might not be compatible with this surface.
-      context = nullptr;
-      // TODO(piman): This might not be fatal, we could recurse into
-      // CreateGLContext to get more info, tho it should be exceedingly
-      // rare and may not be recoverable anyway.
-      LOG(ERROR) << "ContextResult::kFatalFailure: "
-                    "Failed to initialize virtual GL context.";
-      return gpu::ContextResult::kFatalFailure;
-    }
-  }
-
-  if (!context->MakeCurrent(surface_.get())) {
+  scoped_refptr<gl::GLContext> context =
+      raster_decoder_context_state->context();
+  if (!raster_decoder_context_state->MakeCurrent(nullptr)) {
     LOG(ERROR) << "ContextResult::kTransientFailure: "
                   "Failed to make context current.";
     return gpu::ContextResult::kTransientFailure;
@@ -196,22 +179,6 @@
   if (!active_url_.is_empty())
     manager->delegate()->DidCreateOffscreenContext(active_url_);
 
-  if (use_virtualized_gl_context_) {
-    // If virtualized GL contexts are in use, then real GL context state
-    // is in an indeterminate state, since the GLStateRestorer was not
-    // initialized at the time the GLContextVirtual was made current. In
-    // the case that this command decoder is the next one to be
-    // processed, force a "full virtual" MakeCurrent to be performed.
-    // Note that GpuChannel's initialization of the gpu::Capabilities
-    // expects the context to be left current.
-    context->ForceReleaseVirtuallyCurrent();
-    if (!context->MakeCurrent(surface_.get())) {
-      LOG(ERROR) << "ContextResult::kTransientFailure: "
-                    "Failed to make context current after initialization.";
-      return gpu::ContextResult::kTransientFailure;
-    }
-  }
-
   manager->delegate()->DidCreateContextSuccessfully();
   initialized_ = true;
   return gpu::ContextResult::kSuccess;
diff --git a/gpu/ipc/service/shared_image_stub.cc b/gpu/ipc/service/shared_image_stub.cc
index 6b7ed3ec..26aebcd 100644
--- a/gpu/ipc/service/shared_image_stub.cc
+++ b/gpu/ipc/service/shared_image_stub.cc
@@ -146,13 +146,16 @@
 
 bool SharedImageStub::MakeContextCurrent() {
   DCHECK(context_state_);
-  DCHECK(!context_state_->context_lost);
+  DCHECK(!context_state_->context_lost());
 
   // |factory_| never writes to the surface, so pass nullptr to
   // improve performance. https://crbug.com/457431
-  if (context_state_->MakeCurrent(nullptr)) {
+  auto* context = context_state_->real_context();
+  if (context->IsCurrent(nullptr) ||
+      context_state_->real_context()->MakeCurrent(context_state_->surface())) {
     return true;
   } else {
+    context_state_->MarkContextLost();
     LOG(ERROR) << "SharedImageStub: MakeCurrent failed";
     return false;
   }
@@ -169,7 +172,7 @@
       return false;
     }
     DCHECK(context_state_);
-    DCHECK(!context_state_->context_lost);
+    DCHECK(!context_state_->context_lost());
     if (!MakeContextCurrent())
       return false;
     gpu::GpuMemoryBufferFactory* gmb_factory =
@@ -184,13 +187,12 @@
     return true;
   } else {
     DCHECK(context_state_);
-    if (context_state_->context_lost) {
+    if (context_state_->context_lost()) {
       LOG(ERROR) << "SharedImageStub: context already lost";
       return false;
     } else {
       if (MakeContextCurrent())
         return true;
-      context_state_->context_lost = true;
       return false;
     }
   }