[go: nahoru, domu]

oop: Create a RasterInterface, and use it for Compositor Worker contexts.

This CL enables RasterInterface for Compositor Worker contexts in
content/renderer and content/browser.

RasterInterface provides a subset of GLES2Interface APIs required for
OOP Rasterization.  This will gradually diverge away from GLES2.

The initial change adds a client-side implementation of
RasterInterface on top of GLES2Interface.

Design Doc: https://goo.gl/Q6E1ZC
BUG=757607

Cq-Include-Trybots: master.tryserver.blink:linux_trusty_blink_rel;master.tryserver.chromium.android:android_optional_gpu_tests_rel;master.tryserver.chromium.linux:linux_optional_gpu_tests_rel;master.tryserver.chromium.mac:mac_optional_gpu_tests_rel;master.tryserver.chromium.win:win_optional_gpu_tests_rel
Change-Id: Iaefd861f0c51b9995ad27eb94de2068d0f9dab22
Reviewed-on: https://chromium-review.googlesource.com/778242
Commit-Queue: Victor Miura <vmiura@chromium.org>
Reviewed-by: Sadrul Chowdhury <sadrul@chromium.org>
Reviewed-by: danakj <danakj@chromium.org>
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
Reviewed-by: vmpstr <vmpstr@chromium.org>
Reviewed-by: Bo <boliu@chromium.org>
Reviewed-by: Eric Karl <ericrk@chromium.org>
Reviewed-by: Antoine Labour <piman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#523700}
diff --git a/android_webview/browser/aw_render_thread_context_provider.cc b/android_webview/browser/aw_render_thread_context_provider.cc
index 3f9bc9f..6c6ac9b5 100644
--- a/android_webview/browser/aw_render_thread_context_provider.cc
+++ b/android_webview/browser/aw_render_thread_context_provider.cc
@@ -121,6 +121,11 @@
   return context_->GetImplementation();
 }
 
+gpu::raster::RasterInterface* AwRenderThreadContextProvider::RasterContext() {
+  NOTIMPLEMENTED();
+  return nullptr;
+}
+
 gpu::ContextSupport* AwRenderThreadContextProvider::ContextSupport() {
   DCHECK(main_thread_checker_.CalledOnValidThread());
 
diff --git a/android_webview/browser/aw_render_thread_context_provider.h b/android_webview/browser/aw_render_thread_context_provider.h
index 8efcd5bb..e2b2f3a 100644
--- a/android_webview/browser/aw_render_thread_context_provider.h
+++ b/android_webview/browser/aw_render_thread_context_provider.h
@@ -51,6 +51,7 @@
   const gpu::Capabilities& ContextCapabilities() const override;
   const gpu::GpuFeatureInfo& GetGpuFeatureInfo() const override;
   gpu::gles2::GLES2Interface* ContextGL() override;
+  gpu::raster::RasterInterface* RasterContext() override;
   gpu::ContextSupport* ContextSupport() override;
   class GrContext* GrContext() override;
   viz::ContextCacheController* CacheController() override;
diff --git a/cc/BUILD.gn b/cc/BUILD.gn
index 168a79e..40a6486 100644
--- a/cc/BUILD.gn
+++ b/cc/BUILD.gn
@@ -363,6 +363,7 @@
     "//gpu",
     "//gpu/command_buffer/client:gles2_implementation",
     "//gpu/command_buffer/client:gles2_interface",
+    "//gpu/command_buffer/client:raster_interface",
     "//gpu/ipc:gl_in_process_context",
     "//gpu/skia_bindings:skia_bindings",
     "//gpu/vulkan:features",
@@ -728,6 +729,7 @@
     "//gpu:test_support",
     "//gpu/command_buffer/client:gles2_implementation",
     "//gpu/command_buffer/client:gles2_interface",
+    "//gpu/command_buffer/client:raster_interface",
     "//gpu/command_buffer/common:gles2_utils",
     "//gpu/ipc:gl_in_process_context",
     "//gpu/skia_bindings",
@@ -780,6 +782,7 @@
     "//components/viz/test:test_support",
     "//gpu",
     "//gpu:test_support",
+    "//gpu/command_buffer/client:gles2_implementation",
     "//gpu/command_buffer/common:gles2_utils",
     "//media",
     "//mojo/edk/system",
diff --git a/cc/DEPS b/cc/DEPS
index 96ddcce4..4c75c7d 100644
--- a/cc/DEPS
+++ b/cc/DEPS
@@ -6,12 +6,14 @@
   "+gpu/command_buffer/client/gles2_interface.h",
   "+gpu/command_buffer/client/gles2_interface_stub.h", # for tests
   "+gpu/command_buffer/client/gpu_memory_buffer_manager.h",
+  "+gpu/command_buffer/client/raster_implementation_gles.h",
   "+gpu/command_buffer/common/capabilities.h",
   "+gpu/command_buffer/common/discardable_handle.h",
   "+gpu/command_buffer/common/gpu_memory_allocation.h",
   "+gpu/command_buffer/common/gpu_memory_buffer_support.h",
   "+gpu/command_buffer/common/mailbox.h",
   "+gpu/command_buffer/common/mailbox_holder.h",
+  "+gpu/command_buffer/client/raster_interface.h",
   "+gpu/command_buffer/common/sync_token.h",
   "+gpu/command_buffer/common/texture_in_use_response.h",
   "+gpu/config/gpu_feature_info.h",
@@ -28,7 +30,7 @@
   "+ui/gl",
   "-cc/blink",
 ]
-  
+
 specific_include_rules = {
   "in_process_context_provider\.cc": [
     "+gpu/command_buffer/client",
diff --git a/cc/raster/gpu_raster_buffer_provider.cc b/cc/raster/gpu_raster_buffer_provider.cc
index ec0fc0a..f1d915e 100644
--- a/cc/raster/gpu_raster_buffer_provider.cc
+++ b/cc/raster/gpu_raster_buffer_provider.cc
@@ -21,6 +21,7 @@
 #include "cc/resources/resource.h"
 #include "gpu/command_buffer/client/context_support.h"
 #include "gpu/command_buffer/client/gles2_interface.h"
+#include "gpu/command_buffer/client/raster_interface.h"
 #include "third_party/skia/include/core/SkMultiPictureDraw.h"
 #include "third_party/skia/include/core/SkPictureRecorder.h"
 #include "third_party/skia/include/core/SkSurface.h"
@@ -39,28 +40,28 @@
     const gfx::AxisTransform2d& transform,
     const RasterSource::PlaybackSettings& playback_settings,
     viz::ContextProvider* context_provider,
-    ResourceProvider::ScopedWriteLockGL* resource_lock,
+    ResourceProvider::ScopedWriteLockRaster* resource_lock,
     bool use_distance_field_text,
     int msaa_sample_count) {
-  gpu::gles2::GLES2Interface* gl = context_provider->ContextGL();
-  GLuint texture_id = resource_lock->ConsumeTexture(gl);
+  gpu::raster::RasterInterface* ri = context_provider->RasterContext();
+  GLuint texture_id = resource_lock->ConsumeTexture(ri);
 
-  gl->BeginRasterCHROMIUM(texture_id, raster_source->background_color(),
+  ri->BeginRasterCHROMIUM(texture_id, raster_source->background_color(),
                           msaa_sample_count, playback_settings.use_lcd_text,
                           use_distance_field_text,
                           resource_lock->PixelConfig());
   // TODO(enne): need to pass color space into this function as well.
   float recording_to_raster_scale =
       transform.scale() / raster_source->recording_scale_factor();
-  gl->RasterCHROMIUM(raster_source->GetDisplayItemList().get(),
+  ri->RasterCHROMIUM(raster_source->GetDisplayItemList().get(),
                      raster_full_rect.x(), raster_full_rect.y(),
                      playback_rect.x(), playback_rect.y(),
                      playback_rect.width(), playback_rect.height(),
                      transform.translation().x(), transform.translation().y(),
                      recording_to_raster_scale);
-  gl->EndRasterCHROMIUM();
+  ri->EndRasterCHROMIUM();
 
-  gl->DeleteTextures(1, &texture_id);
+  ri->DeleteTextures(1, &texture_id);
 }
 
 static void RasterizeSource(
@@ -72,13 +73,13 @@
     const gfx::AxisTransform2d& transform,
     const RasterSource::PlaybackSettings& playback_settings,
     viz::ContextProvider* context_provider,
-    ResourceProvider::ScopedWriteLockGL* resource_lock,
+    ResourceProvider::ScopedWriteLockRaster* resource_lock,
     bool use_distance_field_text,
     int msaa_sample_count) {
   ScopedGpuRaster gpu_raster(context_provider);
 
-  gpu::gles2::GLES2Interface* gl = context_provider->ContextGL();
-  GLuint texture_id = resource_lock->ConsumeTexture(gl);
+  gpu::raster::RasterInterface* ri = context_provider->RasterContext();
+  GLuint texture_id = resource_lock->ConsumeTexture(ri);
 
   {
     ResourceProvider::ScopedSkSurface scoped_surface(
@@ -106,7 +107,7 @@
         playback_rect, transform, playback_settings);
   }
 
-  gl->DeleteTextures(1, &texture_id);
+  ri->DeleteTextures(1, &texture_id);
 }
 
 }  // namespace
@@ -265,7 +266,7 @@
 }
 
 void GpuRasterBufferProvider::PlaybackOnWorkerThread(
-    ResourceProvider::ScopedWriteLockGL* resource_lock,
+    ResourceProvider::ScopedWriteLockRaster* resource_lock,
     const gpu::SyncToken& sync_token,
     bool resource_has_previous_content,
     const RasterSource* raster_source,
@@ -276,11 +277,11 @@
     const RasterSource::PlaybackSettings& playback_settings) {
   viz::ContextProvider::ScopedContextLock scoped_context(
       worker_context_provider_);
-  gpu::gles2::GLES2Interface* gl = scoped_context.ContextGL();
-  DCHECK(gl);
+  gpu::raster::RasterInterface* ri = scoped_context.RasterContext();
+  DCHECK(ri);
 
   // Synchronize with compositor. Nop if sync token is empty.
-  gl->WaitSyncTokenCHROMIUM(sync_token.GetConstData());
+  ri->WaitSyncTokenCHROMIUM(sync_token.GetConstData());
 
   gfx::Rect playback_rect = raster_full_rect;
   if (resource_has_previous_content) {
@@ -318,7 +319,7 @@
   }
 
   // Generate sync token for cross context synchronization.
-  resource_lock->set_sync_token(ResourceProvider::GenerateSyncTokenHelper(gl));
+  resource_lock->set_sync_token(ResourceProvider::GenerateSyncTokenHelper(ri));
 
   // Mark resource as synchronized when worker and compositor are in same stream
   // to prevent extra wait sync token calls.
diff --git a/cc/raster/gpu_raster_buffer_provider.h b/cc/raster/gpu_raster_buffer_provider.h
index d1f8634..57d75fba5 100644
--- a/cc/raster/gpu_raster_buffer_provider.h
+++ b/cc/raster/gpu_raster_buffer_provider.h
@@ -48,7 +48,7 @@
   void Shutdown() override;
 
   void PlaybackOnWorkerThread(
-      ResourceProvider::ScopedWriteLockGL* resource_lock,
+      ResourceProvider::ScopedWriteLockRaster* resource_lock,
       const gpu::SyncToken& sync_token,
       bool resource_has_previous_content,
       const RasterSource* raster_source,
@@ -82,7 +82,7 @@
 
    private:
     GpuRasterBufferProvider* const client_;
-    ResourceProvider::ScopedWriteLockGL lock_;
+    ResourceProvider::ScopedWriteLockRaster lock_;
     const bool resource_has_previous_content_;
 
     gpu::SyncToken sync_token_;
diff --git a/cc/raster/one_copy_raster_buffer_provider.cc b/cc/raster/one_copy_raster_buffer_provider.cc
index 35fc45bb..ea3487eb 100644
--- a/cc/raster/one_copy_raster_buffer_provider.cc
+++ b/cc/raster/one_copy_raster_buffer_provider.cc
@@ -24,6 +24,7 @@
 #include "gpu/command_buffer/client/context_support.h"
 #include "gpu/command_buffer/client/gles2_interface.h"
 #include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
+#include "gpu/command_buffer/client/raster_interface.h"
 #include "ui/gfx/buffer_format_util.h"
 
 namespace cc {
@@ -201,7 +202,7 @@
 
 void OneCopyRasterBufferProvider::PlaybackAndCopyOnWorkerThread(
     const Resource* resource,
-    ResourceProvider::ScopedWriteLockGL* resource_lock,
+    ResourceProvider::ScopedWriteLockRaster* resource_lock,
     const gpu::SyncToken& sync_token,
     const RasterSource* raster_source,
     const gfx::Rect& raster_full_rect,
@@ -230,10 +231,10 @@
     const gpu::SyncToken& sync_token) {
   viz::ContextProvider::ScopedContextLock scoped_context(
       worker_context_provider_);
-  gpu::gles2::GLES2Interface* gl = scoped_context.ContextGL();
-  DCHECK(gl);
+  gpu::raster::RasterInterface* ri = scoped_context.RasterContext();
+  DCHECK(ri);
   // Synchronize with compositor. Nop if sync token is empty.
-  gl->WaitSyncTokenCHROMIUM(sync_token.GetConstData());
+  ri->WaitSyncTokenCHROMIUM(sync_token.GetConstData());
 }
 
 void OneCopyRasterBufferProvider::PlaybackToStagingBuffer(
@@ -300,65 +301,65 @@
 
 void OneCopyRasterBufferProvider::CopyOnWorkerThread(
     StagingBuffer* staging_buffer,
-    ResourceProvider::ScopedWriteLockGL* resource_lock,
+    ResourceProvider::ScopedWriteLockRaster* resource_lock,
     const RasterSource* raster_source,
     const gfx::Rect& rect_to_copy) {
   viz::ContextProvider::ScopedContextLock scoped_context(
       worker_context_provider_);
-  gpu::gles2::GLES2Interface* gl = scoped_context.ContextGL();
-  DCHECK(gl);
+  gpu::raster::RasterInterface* ri = scoped_context.RasterContext();
+  DCHECK(ri);
 
-  GLuint texture_id = resource_lock->ConsumeTexture(gl);
+  GLuint texture_id = resource_lock->ConsumeTexture(ri);
 
   GLenum image_target = resource_provider_->GetImageTextureTarget(
       StagingBufferUsage(), staging_buffer->format);
 
   // Create and bind staging texture.
   if (!staging_buffer->texture_id) {
-    gl->GenTextures(1, &staging_buffer->texture_id);
-    gl->BindTexture(image_target, staging_buffer->texture_id);
-    gl->TexParameteri(image_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    gl->TexParameteri(image_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-    gl->TexParameteri(image_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-    gl->TexParameteri(image_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    ri->GenTextures(1, &staging_buffer->texture_id);
+    ri->BindTexture(image_target, staging_buffer->texture_id);
+    ri->TexParameteri(image_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    ri->TexParameteri(image_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    ri->TexParameteri(image_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    ri->TexParameteri(image_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
   } else {
-    gl->BindTexture(image_target, staging_buffer->texture_id);
+    ri->BindTexture(image_target, staging_buffer->texture_id);
   }
 
   // Create and bind image.
   if (!staging_buffer->image_id) {
     if (staging_buffer->gpu_memory_buffer) {
-      staging_buffer->image_id = gl->CreateImageCHROMIUM(
+      staging_buffer->image_id = ri->CreateImageCHROMIUM(
           staging_buffer->gpu_memory_buffer->AsClientBuffer(),
           staging_buffer->size.width(), staging_buffer->size.height(),
           GLInternalFormat(resource_lock->format()));
-      gl->BindTexImage2DCHROMIUM(image_target, staging_buffer->image_id);
+      ri->BindTexImage2DCHROMIUM(image_target, staging_buffer->image_id);
     }
   } else {
-    gl->ReleaseTexImage2DCHROMIUM(image_target, staging_buffer->image_id);
-    gl->BindTexImage2DCHROMIUM(image_target, staging_buffer->image_id);
+    ri->ReleaseTexImage2DCHROMIUM(image_target, staging_buffer->image_id);
+    ri->BindTexImage2DCHROMIUM(image_target, staging_buffer->image_id);
   }
 
   // Unbind staging texture.
-  gl->BindTexture(image_target, 0);
+  ri->BindTexture(image_target, 0);
 
   if (resource_provider_->use_sync_query()) {
     if (!staging_buffer->query_id)
-      gl->GenQueriesEXT(1, &staging_buffer->query_id);
+      ri->GenQueriesEXT(1, &staging_buffer->query_id);
 
 #if defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
     // TODO(reveman): This avoids a performance problem on ARM ChromeOS
     // devices. crbug.com/580166
-    gl->BeginQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM, staging_buffer->query_id);
+    ri->BeginQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM, staging_buffer->query_id);
 #else
-    gl->BeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM, staging_buffer->query_id);
+    ri->BeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM, staging_buffer->query_id);
 #endif
   }
 
   // Since compressed texture's cannot be pre-allocated we might have an
   // unallocated resource in which case we need to perform a full size copy.
   if (IsResourceFormatCompressed(resource_lock->format())) {
-    gl->CompressedCopyTextureCHROMIUM(staging_buffer->texture_id, texture_id);
+    ri->CompressedCopyTextureCHROMIUM(staging_buffer->texture_id, texture_id);
   } else {
     int bytes_per_row = ResourceUtil::UncheckedWidthInBytes<int>(
         rect_to_copy.width(), resource_lock->format());
@@ -373,7 +374,7 @@
       int rows_to_copy = std::min(chunk_size_in_rows, height - y);
       DCHECK_GT(rows_to_copy, 0);
 
-      gl->CopySubTextureCHROMIUM(
+      ri->CopySubTextureCHROMIUM(
           staging_buffer->texture_id, 0, GL_TEXTURE_2D, texture_id, 0, 0, y, 0,
           y, rect_to_copy.width(), rows_to_copy, false, false, false);
       y += rows_to_copy;
@@ -383,7 +384,7 @@
       bytes_scheduled_since_last_flush_ += rows_to_copy * bytes_per_row;
 
       if (bytes_scheduled_since_last_flush_ >= max_bytes_per_copy_operation_) {
-        gl->ShallowFlushCHROMIUM();
+        ri->ShallowFlushCHROMIUM();
         bytes_scheduled_since_last_flush_ = 0;
       }
     }
@@ -391,16 +392,16 @@
 
   if (resource_provider_->use_sync_query()) {
 #if defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
-    gl->EndQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM);
+    ri->EndQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM);
 #else
-    gl->EndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM);
+    ri->EndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM);
 #endif
   }
 
-  gl->DeleteTextures(1, &texture_id);
+  ri->DeleteTextures(1, &texture_id);
 
   // Generate sync token for cross context synchronization.
-  resource_lock->set_sync_token(ResourceProvider::GenerateSyncTokenHelper(gl));
+  resource_lock->set_sync_token(ResourceProvider::GenerateSyncTokenHelper(ri));
 
   // Mark resource as synchronized when worker and compositor are in same stream
   // to prevent extra wait sync token calls.
diff --git a/cc/raster/one_copy_raster_buffer_provider.h b/cc/raster/one_copy_raster_buffer_provider.h
index 9b87f229..14b41721e 100644
--- a/cc/raster/one_copy_raster_buffer_provider.h
+++ b/cc/raster/one_copy_raster_buffer_provider.h
@@ -51,7 +51,7 @@
   // Playback raster source and copy result into |resource|.
   void PlaybackAndCopyOnWorkerThread(
       const Resource* resource,
-      ResourceProvider::ScopedWriteLockGL* resource_lock,
+      ResourceProvider::ScopedWriteLockRaster* resource_lock,
       const gpu::SyncToken& sync_token,
       const RasterSource* raster_source,
       const gfx::Rect& raster_full_rect,
@@ -86,7 +86,7 @@
    private:
     OneCopyRasterBufferProvider* client_;
     const Resource* resource_;
-    ResourceProvider::ScopedWriteLockGL lock_;
+    ResourceProvider::ScopedWriteLockRaster lock_;
     uint64_t previous_content_id_;
 
     gpu::SyncToken sync_token_;
@@ -106,10 +106,11 @@
       const RasterSource::PlaybackSettings& playback_settings,
       uint64_t previous_content_id,
       uint64_t new_content_id);
-  void CopyOnWorkerThread(StagingBuffer* staging_buffer,
-                          ResourceProvider::ScopedWriteLockGL* resource_lock,
-                          const RasterSource* raster_source,
-                          const gfx::Rect& rect_to_copy);
+  void CopyOnWorkerThread(
+      StagingBuffer* staging_buffer,
+      ResourceProvider::ScopedWriteLockRaster* resource_lock,
+      const RasterSource* raster_source,
+      const gfx::Rect& rect_to_copy);
   gfx::BufferUsage StagingBufferUsage() const;
 
   viz::ContextProvider* const compositor_context_provider_;
diff --git a/cc/raster/raster_buffer_provider_perftest.cc b/cc/raster/raster_buffer_provider_perftest.cc
index 7b53d4bd..a95457e4 100644
--- a/cc/raster/raster_buffer_provider_perftest.cc
+++ b/cc/raster/raster_buffer_provider_perftest.cc
@@ -29,6 +29,7 @@
 #include "components/viz/common/gpu/context_provider.h"
 #include "components/viz/common/resources/platform_color.h"
 #include "components/viz/test/test_gpu_memory_buffer_manager.h"
+#include "gpu/command_buffer/client/raster_implementation_gles.h"
 #include "gpu/command_buffer/common/sync_token.h"
 #include "gpu/config/gpu_feature_info.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -85,6 +86,9 @@
       : context_gl_(new PerfGLES2Interface),
         cache_controller_(&support_, nullptr) {
     capabilities_.sync_query = true;
+
+    raster_context_ = std::make_unique<gpu::raster::RasterImplementationGLES>(
+        context_gl_.get(), capabilities_);
   }
 
   gpu::ContextResult BindToCurrentThread() override {
@@ -97,6 +101,9 @@
     return gpu_feature_info_;
   }
   gpu::gles2::GLES2Interface* ContextGL() override { return context_gl_.get(); }
+  gpu::raster::RasterInterface* RasterContext() override {
+    return raster_context_.get();
+  }
   gpu::ContextSupport* ContextSupport() override { return &support_; }
   class GrContext* GrContext() override {
     if (gr_context_)
@@ -122,6 +129,7 @@
   ~PerfContextProvider() override = default;
 
   std::unique_ptr<PerfGLES2Interface> context_gl_;
+  std::unique_ptr<gpu::raster::RasterInterface> raster_context_;
   sk_sp<class GrContext> gr_context_;
   TestContextSupport support_;
   viz::ContextCacheController cache_controller_;
diff --git a/cc/raster/staging_buffer_pool.cc b/cc/raster/staging_buffer_pool.cc
index bef94ed..dd7c829 100644
--- a/cc/raster/staging_buffer_pool.cc
+++ b/cc/raster/staging_buffer_pool.cc
@@ -13,7 +13,7 @@
 #include "base/trace_event/memory_dump_manager.h"
 #include "cc/base/container_util.h"
 #include "cc/resources/scoped_resource.h"
-#include "gpu/command_buffer/client/gles2_interface.h"
+#include "gpu/command_buffer/client/raster_interface.h"
 
 using base::trace_event::MemoryAllocatorDump;
 using base::trace_event::MemoryAllocatorDumpGuid;
@@ -32,30 +32,30 @@
 // Delay before a staging buffer might be released.
 const int kStagingBufferExpirationDelayMs = 1000;
 
-bool CheckForQueryResult(gpu::gles2::GLES2Interface* gl, unsigned query_id) {
+bool CheckForQueryResult(gpu::raster::RasterInterface* ri, unsigned query_id) {
   unsigned complete = 1;
-  gl->GetQueryObjectuivEXT(query_id, GL_QUERY_RESULT_AVAILABLE_EXT, &complete);
+  ri->GetQueryObjectuivEXT(query_id, GL_QUERY_RESULT_AVAILABLE_EXT, &complete);
   return !!complete;
 }
 
-void WaitForQueryResult(gpu::gles2::GLES2Interface* gl, unsigned query_id) {
+void WaitForQueryResult(gpu::raster::RasterInterface* ri, unsigned query_id) {
   TRACE_EVENT0("cc", "WaitForQueryResult");
 
   int attempts_left = kMaxCheckForQueryResultAvailableAttempts;
   while (attempts_left--) {
-    if (CheckForQueryResult(gl, query_id))
+    if (CheckForQueryResult(ri, query_id))
       break;
 
     // We have to flush the context to be guaranteed that a query result will
     // be available in a finite amount of time.
-    gl->ShallowFlushCHROMIUM();
+    ri->ShallowFlushCHROMIUM();
 
     base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(
         kCheckForQueryResultAvailableTickRateMs));
   }
 
   unsigned result = 0;
-  gl->GetQueryObjectuivEXT(query_id, GL_QUERY_RESULT_EXT, &result);
+  ri->GetQueryObjectuivEXT(query_id, GL_QUERY_RESULT_EXT, &result);
 }
 
 }  // namespace
@@ -74,17 +74,17 @@
   DCHECK_EQ(query_id, 0u);
 }
 
-void StagingBuffer::DestroyGLResources(gpu::gles2::GLES2Interface* gl) {
+void StagingBuffer::DestroyGLResources(gpu::raster::RasterInterface* ri) {
   if (query_id) {
-    gl->DeleteQueriesEXT(1, &query_id);
+    ri->DeleteQueriesEXT(1, &query_id);
     query_id = 0;
   }
   if (image_id) {
-    gl->DestroyImageCHROMIUM(image_id);
+    ri->DestroyImageCHROMIUM(image_id);
     image_id = 0;
   }
   if (texture_id) {
-    gl->DeleteTextures(1, &texture_id);
+    ri->DeleteTextures(1, &texture_id);
     texture_id = 0;
   }
 }
@@ -254,13 +254,13 @@
   viz::ContextProvider::ScopedContextLock scoped_context(
       worker_context_provider_);
 
-  gpu::gles2::GLES2Interface* gl = scoped_context.ContextGL();
-  DCHECK(gl);
+  gpu::raster::RasterInterface* ri = scoped_context.RasterContext();
+  DCHECK(ri);
 
   // Check if any busy buffers have become available.
   if (resource_provider_->use_sync_query()) {
     while (!busy_buffers_.empty()) {
-      if (!CheckForQueryResult(gl, busy_buffers_.front()->query_id))
+      if (!CheckForQueryResult(ri, busy_buffers_.front()->query_id))
         break;
 
       MarkStagingBufferAsFree(busy_buffers_.front().get());
@@ -277,12 +277,12 @@
       break;
 
     if (resource_provider_->use_sync_query()) {
-      WaitForQueryResult(gl, busy_buffers_.front()->query_id);
+      WaitForQueryResult(ri, busy_buffers_.front()->query_id);
       MarkStagingBufferAsFree(busy_buffers_.front().get());
       free_buffers_.push_back(PopFront(&busy_buffers_));
     } else {
       // Fall-back to glFinish if CHROMIUM_sync_query is not available.
-      gl->Finish();
+      ri->Finish();
       while (!busy_buffers_.empty()) {
         MarkStagingBufferAsFree(busy_buffers_.front().get());
         free_buffers_.push_back(PopFront(&busy_buffers_));
@@ -332,7 +332,7 @@
     if (free_buffers_.empty())
       break;
 
-    free_buffers_.front()->DestroyGLResources(gl);
+    free_buffers_.front()->DestroyGLResources(ri);
     MarkStagingBufferAsBusy(free_buffers_.front().get());
     RemoveStagingBuffer(free_buffers_.front().get());
     free_buffers_.pop_front();
@@ -401,8 +401,8 @@
     viz::ContextProvider::ScopedContextLock scoped_context(
         worker_context_provider_);
 
-    gpu::gles2::GLES2Interface* gl = scoped_context.ContextGL();
-    DCHECK(gl);
+    gpu::raster::RasterInterface* ri = scoped_context.RasterContext();
+    DCHECK(ri);
 
     // Note: Front buffer is guaranteed to be LRU so we can stop releasing
     // buffers as soon as we find a buffer that has been used since |time|.
@@ -410,7 +410,7 @@
       if (free_buffers_.front()->last_usage > time)
         return;
 
-      free_buffers_.front()->DestroyGLResources(gl);
+      free_buffers_.front()->DestroyGLResources(ri);
       MarkStagingBufferAsBusy(free_buffers_.front().get());
       RemoveStagingBuffer(free_buffers_.front().get());
       free_buffers_.pop_front();
@@ -420,7 +420,7 @@
       if (busy_buffers_.front()->last_usage > time)
         return;
 
-      busy_buffers_.front()->DestroyGLResources(gl);
+      busy_buffers_.front()->DestroyGLResources(ri);
       RemoveStagingBuffer(busy_buffers_.front().get());
       busy_buffers_.pop_front();
     }
diff --git a/cc/raster/staging_buffer_pool.h b/cc/raster/staging_buffer_pool.h
index 299831c4..34f5140 100644
--- a/cc/raster/staging_buffer_pool.h
+++ b/cc/raster/staging_buffer_pool.h
@@ -22,8 +22,8 @@
 #include "components/viz/common/gpu/context_provider.h"
 
 namespace gpu {
-namespace gles2 {
-class GLES2Interface;
+namespace raster {
+class RasterInterface;
 }
 }
 
@@ -34,7 +34,7 @@
   StagingBuffer(const gfx::Size& size, viz::ResourceFormat format);
   ~StagingBuffer();
 
-  void DestroyGLResources(gpu::gles2::GLES2Interface* gl);
+  void DestroyGLResources(gpu::raster::RasterInterface* gl);
   void OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd,
                     viz::ResourceFormat format,
                     bool is_free) const;
diff --git a/cc/resources/resource_provider.cc b/cc/resources/resource_provider.cc
index 0aef367..7f9e545 100644
--- a/cc/resources/resource_provider.cc
+++ b/cc/resources/resource_provider.cc
@@ -33,6 +33,7 @@
 #include "gpu/command_buffer/client/context_support.h"
 #include "gpu/command_buffer/client/gles2_interface.h"
 #include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
+#include "gpu/command_buffer/client/raster_interface.h"
 #include "gpu/command_buffer/common/gpu_memory_buffer_support.h"
 #include "skia/ext/texture_handle.h"
 #include "third_party/khronos/GLES2/gl2.h"
@@ -648,7 +649,7 @@
   resource->read_lock_fences_enabled = true;
 }
 
-ResourceProvider::ScopedWriteLockGL::ScopedWriteLockGL(
+ResourceProvider::ScopedWriteLockGpu::ScopedWriteLockGpu(
     ResourceProvider* resource_provider,
     viz::ResourceId resource_id)
     : resource_provider_(resource_provider), resource_id_(resource_id) {
@@ -667,7 +668,7 @@
   allocated_ = resource->allocated;
 }
 
-ResourceProvider::ScopedWriteLockGL::~ScopedWriteLockGL() {
+ResourceProvider::ScopedWriteLockGpu::~ScopedWriteLockGpu() {
   viz::internal::Resource* resource =
       resource_provider_->GetResource(resource_id_);
   DCHECK(resource->locked_for_write);
@@ -683,16 +684,11 @@
   resource_provider_->UnlockForWrite(resource);
 }
 
-GrPixelConfig ResourceProvider::ScopedWriteLockGL::PixelConfig() const {
+GrPixelConfig ResourceProvider::ScopedWriteLockGpu::PixelConfig() const {
   return ToGrPixelConfig(format_);
 }
 
-GLuint ResourceProvider::ScopedWriteLockGL::GetTexture() {
-  LazyAllocate(resource_provider_->ContextGL(), texture_id_);
-  return texture_id_;
-}
-
-void ResourceProvider::ScopedWriteLockGL::CreateMailbox() {
+void ResourceProvider::ScopedWriteLockGpu::CreateMailbox() {
   if (!mailbox_.IsZero())
     return;
   gpu::gles2::GLES2Interface* gl = resource_provider_->ContextGL();
@@ -701,17 +697,16 @@
   gl->ProduceTextureDirectCHROMIUM(texture_id_, mailbox_.name);
 }
 
-GLuint ResourceProvider::ScopedWriteLockGL::ConsumeTexture(
-    gpu::gles2::GLES2Interface* gl) {
-  DCHECK(gl);
-  DCHECK(!mailbox_.IsZero());
+ResourceProvider::ScopedWriteLockGL::ScopedWriteLockGL(
+    ResourceProvider* resource_provider,
+    viz::ResourceId resource_id)
+    : ScopedWriteLockGpu(resource_provider, resource_id) {}
 
-  GLuint texture_id = gl->CreateAndConsumeTextureCHROMIUM(mailbox_.name);
-  DCHECK(texture_id);
+ResourceProvider::ScopedWriteLockGL::~ScopedWriteLockGL() {}
 
-  LazyAllocate(gl, texture_id);
-
-  return texture_id;
+GLuint ResourceProvider::ScopedWriteLockGL::GetTexture() {
+  LazyAllocate(resource_provider_->ContextGL(), texture_id_);
+  return texture_id_;
 }
 
 void ResourceProvider::ScopedWriteLockGL::LazyAllocate(
@@ -753,6 +748,47 @@
   }
 }
 
+ResourceProvider::ScopedWriteLockRaster::ScopedWriteLockRaster(
+    ResourceProvider* resource_provider,
+    viz::ResourceId resource_id)
+    : ScopedWriteLockGpu(resource_provider, resource_id) {}
+
+ResourceProvider::ScopedWriteLockRaster::~ScopedWriteLockRaster() {}
+
+GLuint ResourceProvider::ScopedWriteLockRaster::ConsumeTexture(
+    gpu::raster::RasterInterface* ri) {
+  DCHECK(ri);
+  DCHECK(!mailbox_.IsZero());
+
+  GLuint texture_id = ri->CreateAndConsumeTextureCHROMIUM(mailbox_.name);
+  DCHECK(texture_id);
+
+  LazyAllocate(ri, texture_id);
+
+  return texture_id;
+}
+
+void ResourceProvider::ScopedWriteLockRaster::LazyAllocate(
+    gpu::raster::RasterInterface* ri,
+    GLuint texture_id) {
+  // ETC1 resources cannot be preallocated.
+  if (format_ == viz::ETC1)
+    return;
+
+  if (allocated_)
+    return;
+  allocated_ = true;
+
+  ri->BindTexture(target_, texture_id);
+  ri->TexStorageForRaster(
+      target_, format_, size_.width(), size_.height(),
+      is_overlay_ ? gpu::raster::kOverlay : gpu::raster::kNone);
+  if (is_overlay_ && color_space_.IsValid()) {
+    ri->SetColorSpaceMetadataCHROMIUM(
+        texture_id, reinterpret_cast<GLColorSpace>(&color_space_));
+  }
+}
+
 ResourceProvider::ScopedSkSurface::ScopedSkSurface(GrContext* gr_context,
                                                    GLuint texture_id,
                                                    GLenum texture_target,
@@ -1015,6 +1051,24 @@
   return sync_token;
 }
 
+gpu::SyncToken ResourceProvider::GenerateSyncTokenHelper(
+    gpu::raster::RasterInterface* ri) {
+  DCHECK(ri);
+  const uint64_t fence_sync = ri->InsertFenceSyncCHROMIUM();
+
+  // Barrier to sync worker context output to cc context.
+  ri->OrderingBarrierCHROMIUM();
+
+  // Generate sync token after the barrier for cross context synchronization.
+  gpu::SyncToken sync_token;
+  ri->GenUnverifiedSyncTokenCHROMIUM(fence_sync, sync_token.GetData());
+
+  DCHECK(sync_token.HasData() ||
+         ri->GetGraphicsResetStatusKHR() != GL_NO_ERROR);
+
+  return sync_token;
+}
+
 GLenum ResourceProvider::GetImageTextureTarget(
     gfx::BufferUsage usage,
     viz::ResourceFormat format) const {
diff --git a/cc/resources/resource_provider.h b/cc/resources/resource_provider.h
index caf9726..268857f 100644
--- a/cc/resources/resource_provider.h
+++ b/cc/resources/resource_provider.h
@@ -54,6 +54,9 @@
 namespace gles {
 class GLES2Interface;
 }
+namespace raster {
+class RasterInterface;
+}
 }
 
 namespace viz {
@@ -164,11 +167,11 @@
   // needed to read and write the resource contents. The user must ensure
   // that they only use GL locks on GL resources, etc, and this is enforced
   // by assertions.
-  class CC_EXPORT ScopedWriteLockGL {
+  class CC_EXPORT ScopedWriteLockGpu {
    public:
-    ScopedWriteLockGL(ResourceProvider* resource_provider,
-                      viz::ResourceId resource_id);
-    ~ScopedWriteLockGL();
+    ScopedWriteLockGpu(ResourceProvider* resource_provider,
+                       viz::ResourceId resource_id);
+    ~ScopedWriteLockGpu();
 
     GLenum target() const { return target_; }
     viz::ResourceFormat format() const { return format_; }
@@ -190,19 +193,11 @@
 
     void set_generate_mipmap() { generate_mipmap_ = true; }
 
-    // Returns texture id on compositor context, allocating if necessary.
-    GLuint GetTexture();
-
-    // Creates mailbox that can be consumed on another context.
+    // Creates mailbox on compositor context that can be consumed on another
+    // context.
     void CreateMailbox();
 
-    // Creates a texture id, allocating if necessary, on the given context. The
-    // texture id must be deleted by the caller.
-    GLuint ConsumeTexture(gpu::gles2::GLES2Interface* gl);
-
-   private:
-    void LazyAllocate(gpu::gles2::GLES2Interface* gl, GLuint texture_id);
-
+   protected:
     ResourceProvider* const resource_provider_;
     const viz::ResourceId resource_id_;
 
@@ -223,9 +218,41 @@
     bool synchronized_ = false;
     bool generate_mipmap_ = false;
 
+   private:
+    DISALLOW_COPY_AND_ASSIGN(ScopedWriteLockGpu);
+  };
+
+  class CC_EXPORT ScopedWriteLockGL : public ScopedWriteLockGpu {
+   public:
+    ScopedWriteLockGL(ResourceProvider* resource_provider,
+                      viz::ResourceId resource_id);
+    ~ScopedWriteLockGL();
+
+    // Returns texture id on compositor context, allocating if necessary.
+    GLuint GetTexture();
+
+   private:
+    void LazyAllocate(gpu::gles2::GLES2Interface* gl, GLuint texture_id);
+
     DISALLOW_COPY_AND_ASSIGN(ScopedWriteLockGL);
   };
 
+  class CC_EXPORT ScopedWriteLockRaster : public ScopedWriteLockGpu {
+   public:
+    ScopedWriteLockRaster(ResourceProvider* resource_provider,
+                          viz::ResourceId resource_id);
+    ~ScopedWriteLockRaster();
+
+    // Creates a texture id, allocating if necessary, on the given context. The
+    // texture id must be deleted by the caller.
+    GLuint ConsumeTexture(gpu::raster::RasterInterface* ri);
+
+   private:
+    void LazyAllocate(gpu::raster::RasterInterface* gl, GLuint texture_id);
+
+    DISALLOW_COPY_AND_ASSIGN(ScopedWriteLockRaster);
+  };
+
   // TODO(sunnyps): Move to //components/viz/common/gl_helper.h ?
   class CC_EXPORT ScopedSkSurface {
    public:
@@ -322,6 +349,8 @@
   static GLint GetActiveTextureUnit(gpu::gles2::GLES2Interface* gl);
 
   static gpu::SyncToken GenerateSyncTokenHelper(gpu::gles2::GLES2Interface* gl);
+  static gpu::SyncToken GenerateSyncTokenHelper(
+      gpu::raster::RasterInterface* ri);
 
   GLenum GetImageTextureTarget(gfx::BufferUsage usage,
                                viz::ResourceFormat format) const;
diff --git a/cc/resources/resource_provider_unittest.cc b/cc/resources/resource_provider_unittest.cc
index ff1ed9f..4f22efb 100644
--- a/cc/resources/resource_provider_unittest.cc
+++ b/cc/resources/resource_provider_unittest.cc
@@ -3482,7 +3482,7 @@
   resource_provider->DeleteResource(id);
 }
 
-TEST_P(ResourceProviderTest, ScopedWriteLockGL_Mailbox) {
+TEST_P(ResourceProviderTest, ScopedWriteLockRaster_Mailbox) {
   if (GetParam() != viz::ResourceType::kTexture)
     return;
   std::unique_ptr<AllocationTrackingContext3D> context_owned(
@@ -3515,7 +3515,7 @@
     EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(kTextureId));
     EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId));
     EXPECT_CALL(*context, texParameteri(_, _, _)).Times(AnyNumber());
-    ResourceProvider::ScopedWriteLockGL lock(resource_provider.get(), id);
+    ResourceProvider::ScopedWriteLockRaster lock(resource_provider.get(), id);
     Mock::VerifyAndClearExpectations(context);
 
     EXPECT_CALL(*context, produceTextureDirectCHROMIUM(kTextureId, _));
@@ -3529,7 +3529,7 @@
                                      kWidth, kHeight, 0, GLDataFormat(format),
                                      GLDataType(format), nullptr));
     EXPECT_EQ(kWorkerTextureId,
-              lock.ConsumeTexture(context_provider->ContextGL()));
+              lock.ConsumeTexture(context_provider->RasterContext()));
     Mock::VerifyAndClearExpectations(context);
 
     EXPECT_CALL(*context, RetireTextureId(kWorkerTextureId));
@@ -3539,21 +3539,21 @@
 
   // Subsequent uses will not create mailbox or allocate.
   {
-    ResourceProvider::ScopedWriteLockGL lock(resource_provider.get(), id);
+    ResourceProvider::ScopedWriteLockRaster lock(resource_provider.get(), id);
     lock.CreateMailbox();
     Mock::VerifyAndClearExpectations(context);
 
     EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_))
         .WillOnce(Return(kWorkerTextureId));
     EXPECT_EQ(kWorkerTextureId,
-              lock.ConsumeTexture(context_provider->ContextGL()));
+              lock.ConsumeTexture(context_provider->RasterContext()));
     Mock::VerifyAndClearExpectations(context);
 
     EXPECT_CALL(*context, RetireTextureId(kWorkerTextureId));
     context_provider->ContextGL()->DeleteTextures(1, &kWorkerTextureId);
 
     sync_token = ResourceProvider::GenerateSyncTokenHelper(
-        context_provider->ContextGL());
+        context_provider->RasterContext());
     lock.set_sync_token(sync_token);
     Mock::VerifyAndClearExpectations(context);
   }
@@ -3564,7 +3564,7 @@
   resource_provider->DeleteResource(id);
 }
 
-TEST_P(ResourceProviderTest, ScopedWriteLockGL_Mailbox_Overlay) {
+TEST_P(ResourceProviderTest, ScopedWriteLockRaster_Mailbox_Overlay) {
   if (GetParam() != viz::ResourceType::kTexture)
     return;
 
@@ -3600,7 +3600,7 @@
     EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(kTextureId));
     EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId));
     EXPECT_CALL(*context, texParameteri(_, _, _)).Times(AnyNumber());
-    ResourceProvider::ScopedWriteLockGL lock(resource_provider.get(), id);
+    ResourceProvider::ScopedWriteLockRaster lock(resource_provider.get(), id);
     Mock::VerifyAndClearExpectations(context);
 
     EXPECT_CALL(*context, produceTextureDirectCHROMIUM(kTextureId, _));
@@ -3614,7 +3614,7 @@
                                                     GL_SCANOUT_CHROMIUM, kWidth,
                                                     kHeight));
     EXPECT_EQ(kWorkerTextureId,
-              lock.ConsumeTexture(context_provider->ContextGL()));
+              lock.ConsumeTexture(context_provider->RasterContext()));
     Mock::VerifyAndClearExpectations(context);
 
     EXPECT_CALL(*context, RetireTextureId(kWorkerTextureId));
@@ -3624,18 +3624,18 @@
 
   // Subsequent uses will not create mailbox or allocate.
   {
-    ResourceProvider::ScopedWriteLockGL lock(resource_provider.get(), id);
+    ResourceProvider::ScopedWriteLockRaster lock(resource_provider.get(), id);
     lock.CreateMailbox();
     Mock::VerifyAndClearExpectations(context);
 
     EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_))
         .WillOnce(Return(kWorkerTextureId));
     EXPECT_EQ(kWorkerTextureId,
-              lock.ConsumeTexture(context_provider->ContextGL()));
+              lock.ConsumeTexture(context_provider->RasterContext()));
     Mock::VerifyAndClearExpectations(context);
 
     sync_token = ResourceProvider::GenerateSyncTokenHelper(
-        context_provider->ContextGL());
+        context_provider->RasterContext());
     lock.set_sync_token(sync_token);
 
     EXPECT_CALL(*context, RetireTextureId(kWorkerTextureId));
diff --git a/cc/test/DEPS b/cc/test/DEPS
index c5c9556..5e9cc03 100644
--- a/cc/test/DEPS
+++ b/cc/test/DEPS
@@ -6,6 +6,7 @@
   "+gpu/command_buffer/client/gles2_implementation.h",
   "+gpu/command_buffer/client/gles2_interface_stub.h",
   "+gpu/command_buffer/client/gles2_lib.h",
+  "+gpu/command_buffer/client/raster_implementation_gles.h",
   "+gpu/command_buffer/client/shared_memory_limits.h",
   "+gpu/command_buffer/common/gles2_cmd_utils.h",
   "+gpu/command_buffer/service/image_factory.h",
diff --git a/cc/test/test_context_provider.cc b/cc/test/test_context_provider.cc
index e95e25b..ac385c7 100644
--- a/cc/test/test_context_provider.cc
+++ b/cc/test/test_context_provider.cc
@@ -18,6 +18,7 @@
 #include "cc/test/test_gles2_interface.h"
 #include "cc/test/test_web_graphics_context_3d.h"
 #include "components/viz/common/gpu/context_cache_controller.h"
+#include "gpu/command_buffer/client/raster_implementation_gles.h"
 #include "gpu/skia_bindings/grcontext_for_gles2_interface.h"
 #include "third_party/skia/include/gpu/GrContext.h"
 #include "third_party/skia/include/gpu/gl/GrGLInterface.h"
@@ -189,6 +190,8 @@
   context_thread_checker_.DetachFromThread();
   context_gl_->set_test_context(context3d_.get());
   context3d_->set_test_support(support_.get());
+  raster_context_ = std::make_unique<gpu::raster::RasterImplementationGLES>(
+      context_gl_.get(), context3d_->test_capabilities());
   // Just pass nullptr to the viz::ContextCacheController for its task runner.
   // Idle handling is tested directly in viz::ContextCacheController's
   // unittests, and isn't needed here.
@@ -236,6 +239,10 @@
   return context_gl_.get();
 }
 
+gpu::raster::RasterInterface* TestContextProvider::RasterContext() {
+  return raster_context_.get();
+}
+
 gpu::ContextSupport* TestContextProvider::ContextSupport() {
   return support();
 }
diff --git a/cc/test/test_context_provider.h b/cc/test/test_context_provider.h
index 37d4b00..209ae66e 100644
--- a/cc/test/test_context_provider.h
+++ b/cc/test/test_context_provider.h
@@ -54,6 +54,7 @@
   const gpu::Capabilities& ContextCapabilities() const override;
   const gpu::GpuFeatureInfo& GetGpuFeatureInfo() const override;
   gpu::gles2::GLES2Interface* ContextGL() override;
+  gpu::raster::RasterInterface* RasterContext() override;
   gpu::ContextSupport* ContextSupport() override;
   class GrContext* GrContext() override;
   viz::ContextCacheController* CacheController() override;
@@ -96,6 +97,7 @@
   std::unique_ptr<TestContextSupport> support_;
   std::unique_ptr<TestWebGraphicsContext3D> context3d_;
   std::unique_ptr<TestGLES2Interface> context_gl_;
+  std::unique_ptr<gpu::raster::RasterInterface> raster_context_;
   std::unique_ptr<skia_bindings::GrContextForGLES2Interface> gr_context_;
   std::unique_ptr<viz::ContextCacheController> cache_controller_;
   const bool support_locking_ ALLOW_UNUSED_TYPE;
diff --git a/cc/test/test_in_process_context_provider.cc b/cc/test/test_in_process_context_provider.cc
index 36b677f..80c5113f 100644
--- a/cc/test/test_in_process_context_provider.cc
+++ b/cc/test/test_in_process_context_provider.cc
@@ -15,6 +15,7 @@
 #include "gpu/GLES2/gl2extchromium.h"
 #include "gpu/command_buffer/client/gles2_implementation.h"
 #include "gpu/command_buffer/client/gles2_lib.h"
+#include "gpu/command_buffer/client/raster_implementation_gles.h"
 #include "gpu/command_buffer/client/shared_memory_limits.h"
 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
 #include "gpu/ipc/gl_in_process_context.h"
@@ -78,6 +79,9 @@
       capabilities_.texture_format_bgra8888 = true;
       break;
   }
+
+  raster_context_ = std::make_unique<gpu::raster::RasterImplementationGLES>(
+      context_->GetImplementation(), capabilities_);
 }
 
 TestInProcessContextProvider::~TestInProcessContextProvider() = default;
@@ -90,6 +94,10 @@
   return context_->GetImplementation();
 }
 
+gpu::raster::RasterInterface* TestInProcessContextProvider::RasterContext() {
+  return raster_context_.get();
+}
+
 gpu::ContextSupport* TestInProcessContextProvider::ContextSupport() {
   return context_->GetImplementation();
 }
diff --git a/cc/test/test_in_process_context_provider.h b/cc/test/test_in_process_context_provider.h
index ce61f806..082755b 100644
--- a/cc/test/test_in_process_context_provider.h
+++ b/cc/test/test_in_process_context_provider.h
@@ -42,6 +42,7 @@
 
   gpu::ContextResult BindToCurrentThread() override;
   gpu::gles2::GLES2Interface* ContextGL() override;
+  gpu::raster::RasterInterface* RasterContext() override;
   gpu::ContextSupport* ContextSupport() override;
   class GrContext* GrContext() override;
   viz::ContextCacheController* CacheController() override;
@@ -63,6 +64,7 @@
   viz::TestGpuMemoryBufferManager gpu_memory_buffer_manager_;
   TestImageFactory image_factory_;
   std::unique_ptr<gpu::GLInProcessContext> context_;
+  std::unique_ptr<gpu::raster::RasterInterface> raster_context_;
   std::unique_ptr<skia_bindings::GrContextForGLES2Interface> gr_context_;
   std::unique_ptr<viz::ContextCacheController> cache_controller_;
   base::Lock context_lock_;
diff --git a/cc/tiles/gpu_image_decode_cache.cc b/cc/tiles/gpu_image_decode_cache.cc
index d85d273..fdfb369 100644
--- a/cc/tiles/gpu_image_decode_cache.cc
+++ b/cc/tiles/gpu_image_decode_cache.cc
@@ -23,7 +23,7 @@
 #include "cc/tiles/mipmap_util.h"
 #include "components/viz/common/gpu/context_provider.h"
 #include "gpu/command_buffer/client/context_support.h"
-#include "gpu/command_buffer/client/gles2_interface.h"
+#include "gpu/command_buffer/client/raster_interface.h"
 #include "gpu_image_decode_cache.h"
 #include "skia/ext/texture_handle.h"
 #include "third_party/skia/include/core/SkCanvas.h"
@@ -1324,7 +1324,7 @@
     if (image_data->mode == DecodedDataMode::GPU) {
       // Notify the discardable system of this image so it will count against
       // budgets.
-      context_->ContextGL()->InitializeDiscardableTextureCHROMIUM(
+      context_->RasterContext()->InitializeDiscardableTextureCHROMIUM(
           image_data->upload.gl_id());
     }
   }
@@ -1387,15 +1387,15 @@
   images_pending_complete_lock_.clear();
 
   for (auto* image : images_pending_unlock_) {
-    context_->ContextGL()->UnlockDiscardableTextureCHROMIUM(
+    context_->RasterContext()->UnlockDiscardableTextureCHROMIUM(
         GlIdFromSkImage(image));
   }
   images_pending_unlock_.clear();
 
   for (auto& image : images_pending_deletion_) {
     uint32_t texture_id = GlIdFromSkImage(image.get());
-    if (context_->ContextGL()->LockDiscardableTextureCHROMIUM(texture_id)) {
-      context_->ContextGL()->DeleteTextures(1, &texture_id);
+    if (context_->RasterContext()->LockDiscardableTextureCHROMIUM(texture_id)) {
+      context_->RasterContext()->DeleteTextures(1, &texture_id);
     }
   }
   images_pending_deletion_.clear();
@@ -1418,7 +1418,7 @@
     return true;
 
   if (have_context_lock == HaveContextLock::kYes &&
-      context_->ContextGL()->LockDiscardableTextureCHROMIUM(
+      context_->RasterContext()->LockDiscardableTextureCHROMIUM(
           data->upload.gl_id())) {
     // If |have_context_lock|, we can immediately lock the image and send
     // the lock command to the GPU process.
diff --git a/cc/trees/layer_tree_frame_sink.cc b/cc/trees/layer_tree_frame_sink.cc
index f135e89..3d905212 100644
--- a/cc/trees/layer_tree_frame_sink.cc
+++ b/cc/trees/layer_tree_frame_sink.cc
@@ -15,7 +15,7 @@
 #include "components/viz/common/gpu/context_lost_observer.h"
 #include "gpu/GLES2/gl2extchromium.h"
 #include "gpu/command_buffer/client/context_support.h"
-#include "gpu/command_buffer/client/gles2_interface.h"
+#include "gpu/command_buffer/client/raster_interface.h"
 
 namespace cc {
 
@@ -89,8 +89,8 @@
     DCHECK(compositor_task_runner_->BelongsToCurrentThread());
     viz::ContextProvider::ScopedContextLock lock(
         worker_context_provider_.get());
-    if (worker_context_provider_->ContextGL()->GetGraphicsResetStatusKHR() !=
-        GL_NO_ERROR) {
+    if (worker_context_provider_->RasterContext()
+            ->GetGraphicsResetStatusKHR() != GL_NO_ERROR) {
       context_provider_->RemoveObserver(this);
       context_provider_ = nullptr;
       return false;
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 302e808aff..272f50e 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -87,6 +87,7 @@
 #include "gpu/GLES2/gl2extchromium.h"
 #include "gpu/command_buffer/client/context_support.h"
 #include "gpu/command_buffer/client/gles2_interface.h"
+#include "gpu/command_buffer/client/raster_interface.h"
 #include "services/metrics/public/cpp/ukm_recorder.h"
 #include "third_party/skia/include/gpu/GrContext.h"
 #include "ui/gfx/geometry/point_conversions.h"
@@ -2673,7 +2674,7 @@
     if (auto* worker_context =
             layer_tree_frame_sink_->worker_context_provider()) {
       viz::ContextProvider::ScopedContextLock hold(worker_context);
-      worker_context->ContextGL()->ShallowFlushCHROMIUM();
+      worker_context->RasterContext()->ShallowFlushCHROMIUM();
     }
   }
 }
diff --git a/cc/trees/layer_tree_host_pixeltest_tiles.cc b/cc/trees/layer_tree_host_pixeltest_tiles.cc
index 8f21cb8f..b35cac8f 100644
--- a/cc/trees/layer_tree_host_pixeltest_tiles.cc
+++ b/cc/trees/layer_tree_host_pixeltest_tiles.cc
@@ -12,7 +12,7 @@
 #include "cc/test/layer_tree_pixel_test.h"
 #include "components/viz/common/frame_sinks/copy_output_request.h"
 #include "components/viz/test/test_layer_tree_frame_sink.h"
-#include "gpu/command_buffer/client/gles2_interface.h"
+#include "gpu/command_buffer/client/raster_interface.h"
 
 #if !defined(OS_ANDROID)
 
@@ -183,7 +183,7 @@
       return;
 
     viz::ContextProvider::ScopedContextLock lock(context_provider);
-    lock.ContextGL()->Finish();
+    lock.RasterContext()->Finish();
   }
 
  protected:
diff --git a/cc/trees/layer_tree_host_unittest_context.cc b/cc/trees/layer_tree_host_unittest_context.cc
index 2b8eba9..2139ddf 100644
--- a/cc/trees/layer_tree_host_unittest_context.cc
+++ b/cc/trees/layer_tree_host_unittest_context.cc
@@ -38,6 +38,7 @@
 #include "components/viz/common/resources/single_release_callback.h"
 #include "components/viz/test/test_layer_tree_frame_sink.h"
 #include "gpu/GLES2/gl2extchromium.h"
+#include "gpu/command_buffer/client/raster_interface.h"
 #include "media/base/media.h"
 
 using media::VideoFrame;
@@ -1629,8 +1630,8 @@
     did_lose_context = true;
     viz::ContextProvider::ScopedContextLock scoped_context(
         host_impl->layer_tree_frame_sink()->worker_context_provider());
-    gpu::gles2::GLES2Interface* gl = scoped_context.ContextGL();
-    gl->LoseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
+    gpu::raster::RasterInterface* ri = scoped_context.RasterContext();
+    ri->LoseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
                             GL_INNOCENT_CONTEXT_RESET_ARB);
   }
 
diff --git a/components/viz/common/gpu/context_provider.h b/components/viz/common/gpu/context_provider.h
index 9bba657..f2be096 100644
--- a/components/viz/common/gpu/context_provider.h
+++ b/components/viz/common/gpu/context_provider.h
@@ -26,9 +26,13 @@
 namespace gpu {
 class ContextSupport;
 struct GpuFeatureInfo;
+
 namespace gles2 {
 class GLES2Interface;
 }
+namespace raster {
+class RasterInterface;
+}
 }  // namespace gpu
 
 namespace viz {
@@ -50,6 +54,10 @@
       return context_provider_->ContextGL();
     }
 
+    gpu::raster::RasterInterface* RasterContext() {
+      return context_provider_->RasterContext();
+    }
+
    private:
     ContextProvider* const context_provider_;
     base::AutoLock context_lock_;
@@ -64,9 +72,27 @@
   // can be used to provide access from multiple threads.
   virtual gpu::ContextResult BindToCurrentThread() = 0;
 
+  // Get a GLES2 interface to the 3d context.  Returns nullptr if the context
+  // provider was not bound to a thread, or if the GLES2 interface is not
+  // supported by this context.
   virtual gpu::gles2::GLES2Interface* ContextGL() = 0;
+
+  // Get a Raster interface to the 3d context.  Returns nullptr if the context
+  // provider was not bound to a thread, or if the Raster interface is not
+  // supported by this context.
+  virtual gpu::raster::RasterInterface* RasterContext() = 0;
+
+  // Get a ContextSupport interface to the 3d context.  Returns nullptr if the
+  // context provider was not bound to a thread.
   virtual gpu::ContextSupport* ContextSupport() = 0;
+
+  // Get a Raster interface to the 3d context.  Returns nullptr if the context
+  // provider was not bound to a thread, or if a GrContext fails to initialize
+  // on this context.
   virtual class GrContext* GrContext() = 0;
+
+  // Get a CacheController interface to the 3d context.  Returns nullptr if the
+  // context provider was not bound to a thread.
   virtual ContextCacheController* CacheController() = 0;
 
   // Invalidates the cached OpenGL state in GrContext.
diff --git a/components/viz/common/gpu/in_process_context_provider.cc b/components/viz/common/gpu/in_process_context_provider.cc
index 088a870c..f584395 100644
--- a/components/viz/common/gpu/in_process_context_provider.cc
+++ b/components/viz/common/gpu/in_process_context_provider.cc
@@ -14,6 +14,7 @@
 #include "components/viz/common/resources/platform_color.h"
 #include "gpu/GLES2/gl2extchromium.h"
 #include "gpu/command_buffer/client/gles2_implementation.h"
+#include "gpu/command_buffer/client/raster_implementation_gles.h"
 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
 #include "gpu/command_buffer/service/framebuffer_completeness_cache.h"
 #include "gpu/command_buffer/service/gpu_preferences.h"
@@ -85,6 +86,12 @@
   return context_->GetImplementation();
 }
 
+gpu::raster::RasterInterface* InProcessContextProvider::RasterContext() {
+  // RasterContext use isn't expected in viz compositor context.
+  DLOG(ERROR) << "Unexpected access to RasterContext()";
+  return nullptr;
+}
+
 gpu::ContextSupport* InProcessContextProvider::ContextSupport() {
   return context_->GetImplementation();
 }
diff --git a/components/viz/common/gpu/in_process_context_provider.h b/components/viz/common/gpu/in_process_context_provider.h
index da16824..18911df 100644
--- a/components/viz/common/gpu/in_process_context_provider.h
+++ b/components/viz/common/gpu/in_process_context_provider.h
@@ -51,6 +51,7 @@
 
   gpu::ContextResult BindToCurrentThread() override;
   gpu::gles2::GLES2Interface* ContextGL() override;
+  gpu::raster::RasterInterface* RasterContext() override;
   gpu::ContextSupport* ContextSupport() override;
   class GrContext* GrContext() override;
   ContextCacheController* CacheController() override;
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 3365810..3d6bbd6 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -90,6 +90,7 @@
     "//gpu",
     "//gpu/command_buffer/client:gles2_implementation",
     "//gpu/command_buffer/client:gles2_interface",
+    "//gpu/command_buffer/client:raster_interface",
     "//gpu/ipc/common:gpu_preferences_util",
     "//gpu/ipc/host",
     "//gpu/vulkan:features",
diff --git a/content/browser/compositor/gpu_process_transport_factory.cc b/content/browser/compositor/gpu_process_transport_factory.cc
index 954d61d..f4b6cd07 100644
--- a/content/browser/compositor/gpu_process_transport_factory.cc
+++ b/content/browser/compositor/gpu_process_transport_factory.cc
@@ -50,6 +50,7 @@
 #include "content/public/common/content_switches.h"
 #include "gpu/GLES2/gl2extchromium.h"
 #include "gpu/command_buffer/client/gles2_interface.h"
+#include "gpu/command_buffer/client/raster_interface.h"
 #include "gpu/command_buffer/client/shared_memory_limits.h"
 #include "gpu/command_buffer/common/mailbox.h"
 #include "gpu/config/gpu_driver_bug_workaround_type.h"
@@ -405,7 +406,7 @@
         // lock.
         viz::ContextProvider::ScopedContextLock lock(
             shared_worker_context_provider_.get());
-        lost = lock.ContextGL()->GetGraphicsResetStatusKHR() != GL_NO_ERROR;
+        lost = lock.RasterContext()->GetGraphicsResetStatusKHR() != GL_NO_ERROR;
       }
       if (lost)
         shared_worker_context_provider_ = nullptr;
@@ -413,10 +414,13 @@
 
     if (!shared_worker_context_provider_) {
       bool need_alpha_channel = false;
-      const bool support_locking = true;
+      bool support_locking = true;
+      bool support_gles2_interface = true;
+      bool support_raster_interface = true;
       shared_worker_context_provider_ = CreateContextCommon(
           gpu_channel_host, gpu::kNullSurfaceHandle, need_alpha_channel,
-          false /* support_stencil */, support_locking, nullptr,
+          false /* support_stencil */, support_locking, support_gles2_interface,
+          support_raster_interface, nullptr,
           ui::command_buffer_metrics::BROWSER_WORKER_CONTEXT);
       auto result = shared_worker_context_provider_->BindToCurrentThread();
       if (result != gpu::ContextResult::kSuccess) {
@@ -437,10 +441,12 @@
       gpu::SurfaceHandle surface_handle = data->surface_handle;
       bool need_alpha_channel = false;
       bool support_locking = false;
+      bool support_gles2_interface = true;
+      bool support_raster_interface = false;
       context_provider = CreateContextCommon(
           std::move(gpu_channel_host), surface_handle, need_alpha_channel,
-          support_stencil, support_locking,
-          shared_worker_context_provider_.get(),
+          support_stencil, support_locking, support_gles2_interface,
+          support_raster_interface, shared_worker_context_provider_.get(),
           ui::command_buffer_metrics::DISPLAY_COMPOSITOR_ONSCREEN_CONTEXT);
       // On Mac, GpuCommandBufferMsg_SwapBuffersCompleted must be handled in
       // a nested run loop during resize.
@@ -989,9 +995,12 @@
   // don't step on each other.
   bool need_alpha_channel = false;
   bool support_locking = false;
+  bool support_gles2_interface = true;
+  bool support_raster_interface = false;
   shared_main_thread_contexts_ = CreateContextCommon(
       std::move(gpu_channel_host), gpu::kNullSurfaceHandle, need_alpha_channel,
-      false, support_locking, nullptr,
+      false, support_locking, support_gles2_interface, support_raster_interface,
+      nullptr,
       ui::command_buffer_metrics::BROWSER_OFFSCREEN_MAINTHREAD_CONTEXT);
   shared_main_thread_contexts_->AddObserver(this);
   auto result = shared_main_thread_contexts_->BindToCurrentThread();
@@ -1078,6 +1087,8 @@
     bool need_alpha_channel,
     bool need_stencil_bits,
     bool support_locking,
+    bool support_gles2_interface,
+    bool support_raster_interface,
     ui::ContextProviderCommandBuffer* shared_context_provider,
     ui::command_buffer_metrics::ContextType type) {
   DCHECK(gpu_channel_host);
@@ -1111,6 +1122,8 @@
   attributes.bind_generates_resource = false;
   attributes.lose_context_when_out_of_memory = true;
   attributes.buffer_preserved = false;
+  attributes.enable_gles2_interface = support_gles2_interface;
+  attributes.enable_raster_interface = support_raster_interface;
 
   constexpr bool automatic_flushes = false;
 
diff --git a/content/browser/compositor/gpu_process_transport_factory.h b/content/browser/compositor/gpu_process_transport_factory.h
index f59fcc5..a3d607e 100644
--- a/content/browser/compositor/gpu_process_transport_factory.h
+++ b/content/browser/compositor/gpu_process_transport_factory.h
@@ -138,6 +138,8 @@
       bool need_alpha_channel,
       bool need_stencil_bits,
       bool support_locking,
+      bool support_gles2_interface,
+      bool support_raster_interface,
       ui::ContextProviderCommandBuffer* shared_context_provider,
       ui::command_buffer_metrics::ContextType type);
 
diff --git a/content/browser/compositor/viz_process_transport_factory.cc b/content/browser/compositor/viz_process_transport_factory.cc
index eb06c0d..e436753 100644
--- a/content/browser/compositor/viz_process_transport_factory.cc
+++ b/content/browser/compositor/viz_process_transport_factory.cc
@@ -44,6 +44,8 @@
 scoped_refptr<ui::ContextProviderCommandBuffer> CreateContextProviderImpl(
     scoped_refptr<gpu::GpuChannelHost> gpu_channel_host,
     bool support_locking,
+    bool support_gles2_interface,
+    bool support_raster_interface,
     ui::ContextProviderCommandBuffer* shared_context_provider,
     ui::command_buffer_metrics::ContextType type) {
   constexpr bool kAutomaticFlushes = false;
@@ -57,6 +59,8 @@
   attributes.bind_generates_resource = false;
   attributes.lose_context_when_out_of_memory = true;
   attributes.buffer_preserved = false;
+  attributes.enable_gles2_interface = support_gles2_interface;
+  attributes.enable_raster_interface = support_raster_interface;
 
   GURL url("chrome://gpu/VizProcessTransportFactory::CreateContextProvider");
   return base::MakeRefCounted<ui::ContextProviderCommandBuffer>(
@@ -470,7 +474,11 @@
 bool VizProcessTransportFactory::CreateContextProviders(
     scoped_refptr<gpu::GpuChannelHost> gpu_channel_host) {
   constexpr bool kSharedWorkerContextSupportsLocking = true;
+  constexpr bool kSharedWorkerContextSupportsGLES2 = true;
+  constexpr bool kSharedWorkerContextSupportsRaster = true;
   constexpr bool kCompositorContextSupportsLocking = false;
+  constexpr bool kCompositorContextSupportsGLES2 = true;
+  constexpr bool kCompositorContextSupportsRaster = false;
 
   if (CheckContextLost(compositor_context_provider_.get())) {
     // Both will be lost because they are in the same share group.
@@ -480,8 +488,9 @@
 
   if (!shared_worker_context_provider_) {
     shared_worker_context_provider_ = CreateContextProviderImpl(
-        gpu_channel_host, kSharedWorkerContextSupportsLocking, nullptr,
-        ui::command_buffer_metrics::BROWSER_WORKER_CONTEXT);
+        gpu_channel_host, kSharedWorkerContextSupportsLocking,
+        kSharedWorkerContextSupportsGLES2, kSharedWorkerContextSupportsRaster,
+        nullptr, ui::command_buffer_metrics::BROWSER_WORKER_CONTEXT);
 
     auto result = shared_worker_context_provider_->BindToCurrentThread();
     if (result != gpu::ContextResult::kSuccess) {
@@ -493,6 +502,7 @@
   if (!compositor_context_provider_) {
     compositor_context_provider_ = CreateContextProviderImpl(
         std::move(gpu_channel_host), kCompositorContextSupportsLocking,
+        kCompositorContextSupportsGLES2, kCompositorContextSupportsRaster,
         shared_worker_context_provider_.get(),
         ui::command_buffer_metrics::UI_COMPOSITOR_CONTEXT);
     compositor_context_provider_->SetDefaultTaskRunner(resize_task_runner_);
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn
index a3845acf..997157f9 100644
--- a/content/renderer/BUILD.gn
+++ b/content/renderer/BUILD.gn
@@ -579,6 +579,7 @@
     "//gin",
     "//gpu",
     "//gpu/command_buffer/client:gles2_interface",
+    "//gpu/command_buffer/client:raster_interface",
     "//media",
     "//media:media_features",
     "//media/blink",
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index b2acca3..395f293 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -137,6 +137,8 @@
 #include "device/gamepad/public/cpp/gamepads.h"
 #include "gin/public/debug.h"
 #include "gpu/GLES2/gl2extchromium.h"
+#include "gpu/command_buffer/client/gles2_interface.h"
+#include "gpu/command_buffer/client/raster_interface.h"
 #include "gpu/command_buffer/client/shared_memory_limits.h"
 #include "gpu/config/gpu_switches.h"
 #include "gpu/ipc/client/command_buffer_proxy_impl.h"
@@ -373,14 +375,17 @@
     scoped_refptr<gpu::GpuChannelHost> gpu_channel_host,
     const gpu::SharedMemoryLimits& limits,
     bool support_locking,
+    bool support_gles2_interface,
+    bool support_raster_interface,
     bool support_oop_rasterization,
     ui::command_buffer_metrics::ContextType type,
     int32_t stream_id,
     gpu::SchedulingPriority stream_priority) {
   DCHECK(gpu_channel_host);
   // This is used to create a few different offscreen contexts:
-  // - The shared main thread context (offscreen) used by blink for canvas.
-  // - The worker context (offscreen) used for GPU raster and video decoding.
+  // - The shared main thread context, used by blink for 2D Canvas.
+  // - The compositor worker context, used for GPU raster.
+  // - The media context, used for accelerated video decoding.
   // This is for an offscreen context, so the default framebuffer doesn't need
   // alpha, depth, stencil, antialiasing.
   gpu::gles2::ContextCreationAttribHelper attributes;
@@ -391,6 +396,8 @@
   attributes.sample_buffers = 0;
   attributes.bind_generates_resource = false;
   attributes.lose_context_when_out_of_memory = true;
+  attributes.enable_gles2_interface = support_gles2_interface;
+  attributes.enable_raster_interface = support_raster_interface;
   attributes.enable_oop_rasterization = support_oop_rasterization;
 
   const bool automatic_flushes = false;
@@ -1487,9 +1494,12 @@
   // use lower limits than the default.
   gpu::SharedMemoryLimits limits = gpu::SharedMemoryLimits::ForMailboxContext();
   bool support_locking = true;
+  bool support_gles2_interface = true;
+  bool support_raster_interface = false;
   bool support_oop_rasterization = false;
   scoped_refptr<ui::ContextProviderCommandBuffer> media_context_provider =
       CreateOffscreenContext(gpu_channel_host, limits, support_locking,
+                             support_gles2_interface, support_raster_interface,
                              support_oop_rasterization,
                              ui::command_buffer_metrics::MEDIA_CONTEXT,
                              kGpuStreamIdDefault, kGpuStreamPriorityDefault);
@@ -1540,9 +1550,12 @@
   }
 
   bool support_locking = false;
+  bool support_gles2_interface = true;
+  bool support_raster_interface = false;
   bool support_oop_rasterization = false;
   shared_main_thread_contexts_ = CreateOffscreenContext(
       std::move(gpu_channel_host), gpu::SharedMemoryLimits(), support_locking,
+      support_gles2_interface, support_raster_interface,
       support_oop_rasterization,
       ui::command_buffer_metrics::RENDERER_MAINTHREAD_CONTEXT,
       kGpuStreamIdDefault, kGpuStreamPriorityDefault);
@@ -2106,6 +2119,9 @@
   attributes.sample_buffers = 0;
   attributes.bind_generates_resource = false;
   attributes.lose_context_when_out_of_memory = true;
+  attributes.enable_gles2_interface = true;
+  attributes.enable_raster_interface = false;
+  attributes.enable_oop_rasterization = false;
 
   constexpr bool automatic_flushes = false;
   constexpr bool support_locking = false;
@@ -2414,7 +2430,7 @@
     // Note: If context is lost, delete reference after releasing the lock.
     viz::ContextProvider::ScopedContextLock lock(
         shared_worker_context_provider_.get());
-    if (shared_worker_context_provider_->ContextGL()
+    if (shared_worker_context_provider_->RasterContext()
             ->GetGraphicsResetStatusKHR() == GL_NO_ERROR)
       return shared_worker_context_provider_;
   }
@@ -2437,8 +2453,11 @@
   bool support_oop_rasterization =
       base::CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kEnableOOPRasterization);
+  bool support_gles2_interface = !support_oop_rasterization;
+  bool support_raster_interface = true;
   shared_worker_context_provider_ = CreateOffscreenContext(
       std::move(gpu_channel_host), gpu::SharedMemoryLimits(), support_locking,
+      support_gles2_interface, support_raster_interface,
       support_oop_rasterization,
       ui::command_buffer_metrics::RENDER_WORKER_CONTEXT, stream_id,
       stream_priority);
diff --git a/gpu/BUILD.gn b/gpu/BUILD.gn
index e18d0b5..9cb00be 100644
--- a/gpu/BUILD.gn
+++ b/gpu/BUILD.gn
@@ -244,6 +244,7 @@
     "command_buffer/client/mapped_memory_unittest.cc",
     "command_buffer/client/program_info_manager_unittest.cc",
     "command_buffer/client/query_tracker_unittest.cc",
+    "command_buffer/client/raster_implementation_gles_unittest.cc",
     "command_buffer/client/ring_buffer_test.cc",
     "command_buffer/client/transfer_buffer_unittest.cc",
     "command_buffer/client/vertex_array_object_manager_unittest.cc",
@@ -384,6 +385,7 @@
     "//base/test:test_support",
     "//base/third_party/dynamic_annotations",
     "//cc/paint",
+    "//components/viz/common:resource_format",
     "//gpu/command_buffer/client:gles2_c_lib",
     "//gpu/command_buffer/client:gles2_implementation",
     "//gpu/command_buffer/common:gles2_utils",
diff --git a/gpu/command_buffer/client/BUILD.gn b/gpu/command_buffer/client/BUILD.gn
index bc76c435..2392c44d1 100644
--- a/gpu/command_buffer/client/BUILD.gn
+++ b/gpu/command_buffer/client/BUILD.gn
@@ -150,6 +150,17 @@
   ]
 }
 
+source_set("raster_interface") {
+  sources = [
+    "raster_interface.h",
+  ]
+  public_configs = [ "//third_party/khronos:khronos_headers" ]
+  deps = [
+    "//base",
+    "//components/viz/common:resource_format",
+  ]
+}
+
 # Library emulates GLES2 using command_buffers.
 component("gles2_implementation") {
   sources = gles2_implementation_source_files
@@ -169,10 +180,17 @@
 
   if (!is_nacl) {
     deps += [
+      ":raster_interface",
       "//cc/paint",
+      "//components/viz/common:resource_format",
       "//ui/gfx:color_space",
       "//ui/gfx/ipc/color",
     ]
+
+    sources += [
+      "raster_implementation_gles.cc",
+      "raster_implementation_gles.h",
+    ]
   }
 }
 
diff --git a/gpu/command_buffer/client/DEPS b/gpu/command_buffer/client/DEPS
index 58bc085..516d9f6 100644
--- a/gpu/command_buffer/client/DEPS
+++ b/gpu/command_buffer/client/DEPS
@@ -2,4 +2,6 @@
   "+ui/latency",
   "+cc/paint",
   "+third_party/skia",
+  "+components/viz/common/resources/resource_format.h",
+  "+components/viz/common/resources/resource_format_utils.h",
 ]
diff --git a/gpu/command_buffer/client/raster_implementation_gles.cc b/gpu/command_buffer/client/raster_implementation_gles.cc
new file mode 100644
index 0000000..5fc46dcb
--- /dev/null
+++ b/gpu/command_buffer/client/raster_implementation_gles.cc
@@ -0,0 +1,300 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu/command_buffer/client/raster_implementation_gles.h"
+
+#include "base/logging.h"
+#include "components/viz/common/resources/resource_format_utils.h"
+#include "gpu/GLES2/gl2extchromium.h"
+#include "gpu/command_buffer/common/capabilities.h"
+
+namespace gpu {
+namespace raster {
+
+RasterImplementationGLES::RasterImplementationGLES(
+    gles2::GLES2Interface* gl,
+    const gpu::Capabilities& caps)
+    : gl_(gl),
+      use_texture_storage_(caps.texture_storage),
+      use_texture_storage_image_(caps.texture_storage_image) {}
+
+RasterImplementationGLES::~RasterImplementationGLES() {}
+
+void RasterImplementationGLES::Finish() {
+  gl_->Finish();
+}
+
+void RasterImplementationGLES::ShallowFlushCHROMIUM() {
+  gl_->ShallowFlushCHROMIUM();
+}
+
+void RasterImplementationGLES::OrderingBarrierCHROMIUM() {
+  gl_->OrderingBarrierCHROMIUM();
+}
+
+GLuint64 RasterImplementationGLES::InsertFenceSyncCHROMIUM() {
+  return gl_->InsertFenceSyncCHROMIUM();
+}
+
+void RasterImplementationGLES::GenSyncTokenCHROMIUM(GLuint64 fence_sync,
+                                                    GLbyte* sync_token) {
+  gl_->GenSyncTokenCHROMIUM(fence_sync, sync_token);
+}
+
+void RasterImplementationGLES::GenUnverifiedSyncTokenCHROMIUM(
+    GLuint64 fence_sync,
+    GLbyte* sync_token) {
+  gl_->GenUnverifiedSyncTokenCHROMIUM(fence_sync, sync_token);
+}
+
+void RasterImplementationGLES::VerifySyncTokensCHROMIUM(GLbyte** sync_tokens,
+                                                        GLsizei count) {
+  gl_->VerifySyncTokensCHROMIUM(sync_tokens, count);
+}
+
+void RasterImplementationGLES::WaitSyncTokenCHROMIUM(const GLbyte* sync_token) {
+  gl_->WaitSyncTokenCHROMIUM(sync_token);
+}
+
+GLenum RasterImplementationGLES::GetError() {
+  return gl_->GetError();
+}
+
+GLenum RasterImplementationGLES::GetGraphicsResetStatusKHR() {
+  return gl_->GetGraphicsResetStatusKHR();
+}
+
+void RasterImplementationGLES::GetIntegerv(GLenum pname, GLint* params) {
+  gl_->GetIntegerv(pname, params);
+}
+
+void RasterImplementationGLES::LoseContextCHROMIUM(GLenum current,
+                                                   GLenum other) {
+  gl_->LoseContextCHROMIUM(current, other);
+}
+
+void RasterImplementationGLES::GenQueriesEXT(GLsizei n, GLuint* queries) {
+  gl_->GenQueriesEXT(n, queries);
+}
+
+void RasterImplementationGLES::DeleteQueriesEXT(GLsizei n,
+                                                const GLuint* queries) {
+  gl_->DeleteQueriesEXT(n, queries);
+}
+
+void RasterImplementationGLES::BeginQueryEXT(GLenum target, GLuint id) {
+  gl_->BeginQueryEXT(target, id);
+}
+
+void RasterImplementationGLES::EndQueryEXT(GLenum target) {
+  gl_->EndQueryEXT(target);
+}
+
+void RasterImplementationGLES::GetQueryObjectuivEXT(GLuint id,
+                                                    GLenum pname,
+                                                    GLuint* params) {
+  gl_->GetQueryObjectuivEXT(id, pname, params);
+}
+
+void RasterImplementationGLES::GenTextures(GLsizei n, GLuint* textures) {
+  gl_->GenTextures(n, textures);
+}
+
+void RasterImplementationGLES::DeleteTextures(GLsizei n,
+                                              const GLuint* textures) {
+  gl_->DeleteTextures(n, textures);
+};
+
+void RasterImplementationGLES::BindTexture(GLenum target, GLuint texture) {
+  gl_->BindTexture(target, texture);
+};
+
+void RasterImplementationGLES::ActiveTexture(GLenum texture) {
+  gl_->ActiveTexture(texture);
+}
+
+void RasterImplementationGLES::GenerateMipmap(GLenum target) {
+  gl_->GenerateMipmap(target);
+}
+
+void RasterImplementationGLES::SetColorSpaceMetadataCHROMIUM(
+    GLuint texture_id,
+    GLColorSpace color_space) {
+  gl_->SetColorSpaceMetadataCHROMIUM(texture_id, color_space);
+}
+
+void RasterImplementationGLES::TexParameteri(GLenum target,
+                                             GLenum pname,
+                                             GLint param) {
+  gl_->TexParameteri(target, pname, param);
+}
+
+void RasterImplementationGLES::GenMailboxCHROMIUM(GLbyte* mailbox) {
+  gl_->GenMailboxCHROMIUM(mailbox);
+}
+
+void RasterImplementationGLES::ProduceTextureDirectCHROMIUM(
+    GLuint texture,
+    const GLbyte* mailbox) {
+  gl_->ProduceTextureDirectCHROMIUM(texture, mailbox);
+}
+
+GLuint RasterImplementationGLES::CreateAndConsumeTextureCHROMIUM(
+    const GLbyte* mailbox) {
+  return gl_->CreateAndConsumeTextureCHROMIUM(mailbox);
+}
+
+GLuint RasterImplementationGLES::CreateImageCHROMIUM(ClientBuffer buffer,
+                                                     GLsizei width,
+                                                     GLsizei height,
+                                                     GLenum internalformat) {
+  return gl_->CreateImageCHROMIUM(buffer, width, height, internalformat);
+}
+
+void RasterImplementationGLES::BindTexImage2DCHROMIUM(GLenum target,
+                                                      GLint imageId) {
+  gl_->BindTexImage2DCHROMIUM(target, imageId);
+}
+
+void RasterImplementationGLES::ReleaseTexImage2DCHROMIUM(GLenum target,
+                                                         GLint imageId) {
+  gl_->ReleaseTexImage2DCHROMIUM(target, imageId);
+}
+
+void RasterImplementationGLES::DestroyImageCHROMIUM(GLuint image_id) {
+  gl_->DestroyImageCHROMIUM(image_id);
+}
+
+void RasterImplementationGLES::TexImage2D(GLenum target,
+                                          GLint level,
+                                          GLint internalformat,
+                                          GLsizei width,
+                                          GLsizei height,
+                                          GLint border,
+                                          GLenum format,
+                                          GLenum type,
+                                          const void* pixels) {
+  gl_->TexImage2D(target, level, internalformat, width, height, border, format,
+                  type, pixels);
+}
+
+void RasterImplementationGLES::TexSubImage2D(GLenum target,
+                                             GLint level,
+                                             GLint xoffset,
+                                             GLint yoffset,
+                                             GLsizei width,
+                                             GLsizei height,
+                                             GLenum format,
+                                             GLenum type,
+                                             const void* pixels) {
+  gl_->TexSubImage2D(target, level, xoffset, yoffset, width, height, format,
+                     type, pixels);
+}
+
+void RasterImplementationGLES::CompressedTexImage2D(GLenum target,
+                                                    GLint level,
+                                                    GLenum internalformat,
+                                                    GLsizei width,
+                                                    GLsizei height,
+                                                    GLint border,
+                                                    GLsizei imageSize,
+                                                    const void* data) {
+  gl_->CompressedTexImage2D(target, level, internalformat, width, height,
+                            border, imageSize, data);
+}
+
+void RasterImplementationGLES::TexStorageForRaster(
+    GLenum target,
+    viz::ResourceFormat format,
+    GLsizei width,
+    GLsizei height,
+    RasterTexStorageFlags flags) {
+  if (flags & kOverlay) {
+    DCHECK(use_texture_storage_image_);
+    gl_->TexStorage2DImageCHROMIUM(target, viz::TextureStorageFormat(format),
+                                   GL_SCANOUT_CHROMIUM, width, height);
+  } else if (use_texture_storage_) {
+    GLint levels = 1;
+    gl_->TexStorage2DEXT(target, levels, viz::TextureStorageFormat(format),
+                         width, height);
+  } else {
+    gl_->TexImage2D(target, 0, viz::GLInternalFormat(format), width, height, 0,
+                    viz::GLDataFormat(format), viz::GLDataType(format),
+                    nullptr);
+  }
+}
+
+void RasterImplementationGLES::CopySubTextureCHROMIUM(
+    GLuint source_id,
+    GLint source_level,
+    GLenum dest_target,
+    GLuint dest_id,
+    GLint dest_level,
+    GLint xoffset,
+    GLint yoffset,
+    GLint x,
+    GLint y,
+    GLsizei width,
+    GLsizei height,
+    GLboolean unpack_flip_y,
+    GLboolean unpack_premultiply_alpha,
+    GLboolean unpack_unmultiply_alpha) {
+  gl_->CopySubTextureCHROMIUM(source_id, source_level, dest_target, dest_id,
+                              dest_level, xoffset, yoffset, x, y, width, height,
+                              unpack_flip_y, unpack_premultiply_alpha,
+                              unpack_unmultiply_alpha);
+}
+
+void RasterImplementationGLES::CompressedCopyTextureCHROMIUM(GLuint source_id,
+                                                             GLuint dest_id) {
+  gl_->CompressedCopyTextureCHROMIUM(source_id, dest_id);
+}
+
+void RasterImplementationGLES::InitializeDiscardableTextureCHROMIUM(
+    GLuint texture_id) {
+  gl_->InitializeDiscardableTextureCHROMIUM(texture_id);
+}
+
+void RasterImplementationGLES::UnlockDiscardableTextureCHROMIUM(
+    GLuint texture_id) {
+  gl_->UnlockDiscardableTextureCHROMIUM(texture_id);
+}
+
+bool RasterImplementationGLES::LockDiscardableTextureCHROMIUM(
+    GLuint texture_id) {
+  return gl_->LockDiscardableTextureCHROMIUM(texture_id);
+}
+
+void RasterImplementationGLES::BeginRasterCHROMIUM(
+    GLuint texture_id,
+    GLuint sk_color,
+    GLuint msaa_sample_count,
+    GLboolean can_use_lcd_text,
+    GLboolean use_distance_field_text,
+    GLint pixel_config) {
+  gl_->BeginRasterCHROMIUM(texture_id, sk_color, msaa_sample_count,
+                           can_use_lcd_text, use_distance_field_text,
+                           pixel_config);
+};
+
+void RasterImplementationGLES::RasterCHROMIUM(const cc::DisplayItemList* list,
+                                              GLint translate_x,
+                                              GLint translate_y,
+                                              GLint clip_x,
+                                              GLint clip_y,
+                                              GLint clip_w,
+                                              GLint clip_h,
+                                              GLfloat post_translate_x,
+                                              GLfloat post_translate_y,
+                                              GLfloat post_scale) {
+  gl_->RasterCHROMIUM(list, translate_x, translate_y, clip_x, clip_y, clip_w,
+                      clip_h, post_translate_x, post_translate_y, post_scale);
+}
+
+void RasterImplementationGLES::EndRasterCHROMIUM() {
+  gl_->EndRasterCHROMIUM();
+}
+
+}  // namespace raster
+}  // namespace gpu
diff --git a/gpu/command_buffer/client/raster_implementation_gles.h b/gpu/command_buffer/client/raster_implementation_gles.h
new file mode 100644
index 0000000..b046006
--- /dev/null
+++ b/gpu/command_buffer/client/raster_implementation_gles.h
@@ -0,0 +1,161 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GPU_COMMAND_BUFFER_CLIENT_RASTER_IMPLEMENTATION_GLES_H_
+#define GPU_COMMAND_BUFFER_CLIENT_RASTER_IMPLEMENTATION_GLES_H_
+
+#include "base/macros.h"
+#include "gles2_impl_export.h"
+#include "gpu/command_buffer/client/gles2_interface.h"
+#include "gpu/command_buffer/client/raster_interface.h"
+#include "gpu/command_buffer/common/capabilities.h"
+
+namespace gpu {
+namespace raster {
+
+struct Capabilities;
+
+// An implementation of RasterInterface on top of GLES2Interface.
+class GLES2_IMPL_EXPORT RasterImplementationGLES : public RasterInterface {
+ public:
+  RasterImplementationGLES(gles2::GLES2Interface* gl,
+                           const gpu::Capabilities& caps);
+  ~RasterImplementationGLES() override;
+
+  // Command buffer Flush / Finish.
+  void Finish() override;
+  void ShallowFlushCHROMIUM() override;
+  void OrderingBarrierCHROMIUM() override;
+
+  // SyncTokens.
+  GLuint64 InsertFenceSyncCHROMIUM() override;
+  void GenSyncTokenCHROMIUM(GLuint64 fence_sync, GLbyte* sync_token) override;
+  void GenUnverifiedSyncTokenCHROMIUM(GLuint64 fence_sync,
+                                      GLbyte* sync_token) override;
+  void VerifySyncTokensCHROMIUM(GLbyte** sync_tokens, GLsizei count) override;
+  void WaitSyncTokenCHROMIUM(const GLbyte* sync_token) override;
+
+  // Command buffer state.
+  GLenum GetError() override;
+  GLenum GetGraphicsResetStatusKHR() override;
+  void GetIntegerv(GLenum pname, GLint* params) override;
+  void LoseContextCHROMIUM(GLenum current, GLenum other) override;
+
+  // Queries: GL_COMMANDS_ISSUED_CHROMIUM / GL_COMMANDS_COMPLETED_CHROMIUM.
+  void GenQueriesEXT(GLsizei n, GLuint* queries) override;
+  void DeleteQueriesEXT(GLsizei n, const GLuint* queries) override;
+  void BeginQueryEXT(GLenum target, GLuint id) override;
+  void EndQueryEXT(GLenum target) override;
+  void GetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint* params) override;
+
+  // Texture objects.
+  void GenTextures(GLsizei n, GLuint* textures) override;
+  void DeleteTextures(GLsizei n, const GLuint* textures) override;
+  void BindTexture(GLenum target, GLuint texture) override;
+  void ActiveTexture(GLenum texture) override;
+  void GenerateMipmap(GLenum target) override;
+  void SetColorSpaceMetadataCHROMIUM(GLuint texture_id,
+                                     GLColorSpace color_space) override;
+  void TexParameteri(GLenum target, GLenum pname, GLint param) override;
+
+  // Mailboxes.
+  void GenMailboxCHROMIUM(GLbyte* mailbox) override;
+  void ProduceTextureDirectCHROMIUM(GLuint texture,
+                                    const GLbyte* mailbox) override;
+  GLuint CreateAndConsumeTextureCHROMIUM(const GLbyte* mailbox) override;
+
+  // Image objects.
+  GLuint CreateImageCHROMIUM(ClientBuffer buffer,
+                             GLsizei width,
+                             GLsizei height,
+                             GLenum internalformat) override;
+  void BindTexImage2DCHROMIUM(GLenum target, GLint imageId) override;
+  void ReleaseTexImage2DCHROMIUM(GLenum target, GLint imageId) override;
+  void DestroyImageCHROMIUM(GLuint image_id) override;
+
+  // Texture allocation and copying.
+  void TexImage2D(GLenum target,
+                  GLint level,
+                  GLint internalformat,
+                  GLsizei width,
+                  GLsizei height,
+                  GLint border,
+                  GLenum format,
+                  GLenum type,
+                  const void* pixels) override;
+  void TexSubImage2D(GLenum target,
+                     GLint level,
+                     GLint xoffset,
+                     GLint yoffset,
+                     GLsizei width,
+                     GLsizei height,
+                     GLenum format,
+                     GLenum type,
+                     const void* pixels) override;
+  void CompressedTexImage2D(GLenum target,
+                            GLint level,
+                            GLenum internalformat,
+                            GLsizei width,
+                            GLsizei height,
+                            GLint border,
+                            GLsizei imageSize,
+                            const void* data) override;
+  void TexStorageForRaster(GLenum target,
+                           viz::ResourceFormat format,
+                           GLsizei width,
+                           GLsizei height,
+                           RasterTexStorageFlags flags) override;
+
+  void CopySubTextureCHROMIUM(GLuint source_id,
+                              GLint source_level,
+                              GLenum dest_target,
+                              GLuint dest_id,
+                              GLint dest_level,
+                              GLint xoffset,
+                              GLint yoffset,
+                              GLint x,
+                              GLint y,
+                              GLsizei width,
+                              GLsizei height,
+                              GLboolean unpack_flip_y,
+                              GLboolean unpack_premultiply_alpha,
+                              GLboolean unpack_unmultiply_alpha) override;
+  void CompressedCopyTextureCHROMIUM(GLuint source_id, GLuint dest_id) override;
+
+  // Discardable textures.
+  void InitializeDiscardableTextureCHROMIUM(GLuint texture_id) override;
+  void UnlockDiscardableTextureCHROMIUM(GLuint texture_id) override;
+  bool LockDiscardableTextureCHROMIUM(GLuint texture_id) override;
+
+  // OOP-Raster
+  void BeginRasterCHROMIUM(GLuint texture_id,
+                           GLuint sk_color,
+                           GLuint msaa_sample_count,
+                           GLboolean can_use_lcd_text,
+                           GLboolean use_distance_field_text,
+                           GLint pixel_config) override;
+  void RasterCHROMIUM(const cc::DisplayItemList* list,
+                      GLint translate_x,
+                      GLint translate_y,
+                      GLint clip_x,
+                      GLint clip_y,
+                      GLint clip_w,
+                      GLint clip_h,
+                      GLfloat post_translate_x,
+                      GLfloat post_translate_y,
+                      GLfloat post_scale) override;
+  void EndRasterCHROMIUM() override;
+
+ private:
+  gles2::GLES2Interface* gl_;
+  bool use_texture_storage_;
+  bool use_texture_storage_image_;
+
+  DISALLOW_COPY_AND_ASSIGN(RasterImplementationGLES);
+};
+
+}  // namespace raster
+}  // namespace gpu
+
+#endif  // GPU_COMMAND_BUFFER_CLIENT_RASTER_IMPLEMENTATION_GLES_H_
diff --git a/gpu/command_buffer/client/raster_implementation_gles_unittest.cc b/gpu/command_buffer/client/raster_implementation_gles_unittest.cc
new file mode 100644
index 0000000..ea4fa32
--- /dev/null
+++ b/gpu/command_buffer/client/raster_implementation_gles_unittest.cc
@@ -0,0 +1,651 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu/command_buffer/client/raster_implementation_gles.h"
+
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#include <GLES2/gl2extchromium.h>
+#include <GLES3/gl3.h>
+
+#include "cc/paint/display_item_list.h"
+#include "components/viz/common/resources/resource_format_utils.h"
+#include "gpu/GLES2/gl2extchromium.h"
+#include "gpu/command_buffer/client/gles2_interface_stub.h"
+#include "gpu/command_buffer/common/capabilities.h"
+#include "gpu/command_buffer/common/mailbox.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/gpu/GrTypes.h"
+#include "ui/gfx/color_space.h"
+
+using testing::_;
+using testing::Return;
+using testing::SetArgPointee;
+
+namespace gpu {
+namespace raster {
+
+class RasterMockGLES2Interface : public gles2::GLES2InterfaceStub {
+ public:
+  // Command buffer Flush / Finish.
+  MOCK_METHOD0(Finish, void());
+  MOCK_METHOD0(ShallowFlushCHROMIUM, void());
+  MOCK_METHOD0(OrderingBarrierCHROMIUM, void());
+
+  // SyncTokens.
+  MOCK_METHOD0(InsertFenceSyncCHROMIUM, GLuint64());
+  MOCK_METHOD2(GenSyncTokenCHROMIUM,
+               void(GLuint64 fence_sync, GLbyte* sync_token));
+  MOCK_METHOD2(GenUnverifiedSyncTokenCHROMIUM,
+               void(GLuint64 fence_sync, GLbyte* sync_token));
+  MOCK_METHOD2(VerifySyncTokensCHROMIUM,
+               void(GLbyte** sync_tokens, GLsizei count));
+  MOCK_METHOD1(WaitSyncTokenCHROMIUM, void(const GLbyte* sync_token));
+
+  // Command buffer state.
+  MOCK_METHOD0(GetError, GLenum());
+  MOCK_METHOD0(GetGraphicsResetStatusKHR, GLenum());
+  MOCK_METHOD2(GetIntegerv, void(GLenum pname, GLint* params));
+  MOCK_METHOD2(LoseContextCHROMIUM, void(GLenum current, GLenum other));
+
+  // Queries: GL_COMMANDS_ISSUED_CHROMIUM / GL_COMMANDS_COMPLETED_CHROMIUM.
+  MOCK_METHOD2(GenQueriesEXT, void(GLsizei n, GLuint* queries));
+  MOCK_METHOD2(DeleteQueriesEXT, void(GLsizei n, const GLuint* queries));
+  MOCK_METHOD2(BeginQueryEXT, void(GLenum target, GLuint id));
+  MOCK_METHOD1(EndQueryEXT, void(GLenum target));
+  MOCK_METHOD3(GetQueryObjectuivEXT,
+               void(GLuint id, GLenum pname, GLuint* params));
+
+  // Texture objects.
+  MOCK_METHOD2(GenTextures, void(GLsizei n, GLuint* textures));
+  MOCK_METHOD2(DeleteTextures, void(GLsizei n, const GLuint* textures));
+  MOCK_METHOD2(BindTexture, void(GLenum target, GLuint texture));
+  MOCK_METHOD1(ActiveTexture, void(GLenum texture));
+  MOCK_METHOD1(GenerateMipmap, void(GLenum target));
+  MOCK_METHOD2(SetColorSpaceMetadataCHROMIUM,
+               void(GLuint texture_id, GLColorSpace color_space));
+  MOCK_METHOD3(TexParameteri, void(GLenum target, GLenum pname, GLint param));
+
+  // Mailboxes.
+  MOCK_METHOD1(GenMailboxCHROMIUM, void(GLbyte*));
+  MOCK_METHOD2(ProduceTextureDirectCHROMIUM,
+               void(GLuint texture, const GLbyte* mailbox));
+  MOCK_METHOD1(CreateAndConsumeTextureCHROMIUM, GLuint(const GLbyte* mailbox));
+
+  // Image objects.
+  MOCK_METHOD4(CreateImageCHROMIUM,
+               GLuint(ClientBuffer buffer,
+                      GLsizei width,
+                      GLsizei height,
+                      GLenum internalformat));
+  MOCK_METHOD2(BindTexImage2DCHROMIUM, void(GLenum target, GLint imageId));
+  MOCK_METHOD2(ReleaseTexImage2DCHROMIUM, void(GLenum target, GLint imageId));
+  MOCK_METHOD1(DestroyImageCHROMIUM, void(GLuint image_id));
+
+  // Texture allocation and copying.
+  MOCK_METHOD9(TexImage2D,
+               void(GLenum target,
+                    GLint level,
+                    GLint internalformat,
+                    GLsizei width,
+                    GLsizei height,
+                    GLint border,
+                    GLenum format,
+                    GLenum type,
+                    const void* pixels));
+  MOCK_METHOD9(TexSubImage2D,
+               void(GLenum target,
+                    GLint level,
+                    GLint xoffset,
+                    GLint yoffset,
+                    GLsizei width,
+                    GLsizei height,
+                    GLenum format,
+                    GLenum type,
+                    const void* pixels));
+  MOCK_METHOD8(CompressedTexImage2D,
+               void(GLenum target,
+                    GLint level,
+                    GLenum internalformat,
+                    GLsizei width,
+                    GLsizei height,
+                    GLint border,
+                    GLsizei imageSize,
+                    const void* data));
+  MOCK_METHOD2(CompressedCopyTextureCHROMIUM,
+               void(GLuint source_id, GLuint dest_id));
+  MOCK_METHOD5(TexStorage2DEXT,
+               void(GLenum target,
+                    GLsizei levels,
+                    GLenum internalFormat,
+                    GLsizei width,
+                    GLsizei height));
+  MOCK_METHOD5(TexStorage2DImageCHROMIUM,
+               void(GLenum target,
+                    GLenum internalFormat,
+                    GLenum bufferUsage,
+                    GLsizei width,
+                    GLsizei height));
+
+  // Discardable textures.
+  MOCK_METHOD1(InitializeDiscardableTextureCHROMIUM, void(GLuint texture_id));
+  MOCK_METHOD1(UnlockDiscardableTextureCHROMIUM, void(GLuint texture_id));
+  MOCK_METHOD1(LockDiscardableTextureCHROMIUM, bool(GLuint texture_id));
+
+  // OOP-Raster
+  MOCK_METHOD6(BeginRasterCHROMIUM,
+               void(GLuint texture_id,
+                    GLuint sk_color,
+                    GLuint msaa_sample_count,
+                    GLboolean can_use_lcd_text,
+                    GLboolean use_distance_field_text,
+                    GLint pixel_config));
+  MOCK_METHOD10(RasterCHROMIUM,
+                void(const cc::DisplayItemList* list,
+                     GLint translate_x,
+                     GLint translate_y,
+                     GLint clip_x,
+                     GLint clip_y,
+                     GLint clip_w,
+                     GLint clip_h,
+                     GLfloat post_translate_x,
+                     GLfloat post_translate_y,
+                     GLfloat post_scale));
+  MOCK_METHOD0(EndRasterCHROMIUM, void());
+};
+
+class RasterImplementationGLESTest : public testing::Test {
+ protected:
+  RasterImplementationGLESTest() {}
+
+  void SetUp() override {
+    gl_.reset(new RasterMockGLES2Interface());
+
+    ri_.reset(new RasterImplementationGLES(gl_.get(), gpu::Capabilities()));
+  }
+
+  void TearDown() override {}
+
+  void SetUpWithCapabilities(const gpu::Capabilities& capabilities) {
+    ri_.reset(new RasterImplementationGLES(gl_.get(), capabilities));
+  }
+
+  std::unique_ptr<RasterMockGLES2Interface> gl_;
+  std::unique_ptr<RasterImplementationGLES> ri_;
+};
+
+TEST_F(RasterImplementationGLESTest, Finish) {
+  EXPECT_CALL(*gl_, Finish()).Times(1);
+  ri_->Finish();
+}
+
+TEST_F(RasterImplementationGLESTest, ShallowFlushCHROMIUM) {
+  EXPECT_CALL(*gl_, ShallowFlushCHROMIUM()).Times(1);
+  ri_->ShallowFlushCHROMIUM();
+}
+
+TEST_F(RasterImplementationGLESTest, OrderingBarrierCHROMIUM) {
+  EXPECT_CALL(*gl_, OrderingBarrierCHROMIUM()).Times(1);
+  ri_->OrderingBarrierCHROMIUM();
+}
+
+TEST_F(RasterImplementationGLESTest, InsertFenceSyncCHROMIUM) {
+  const GLuint64 kFenceSync = 0x123u;
+  GLuint64 fence_sync = 0;
+
+  EXPECT_CALL(*gl_, InsertFenceSyncCHROMIUM()).WillOnce(Return(kFenceSync));
+  fence_sync = ri_->InsertFenceSyncCHROMIUM();
+  EXPECT_EQ(kFenceSync, fence_sync);
+}
+
+TEST_F(RasterImplementationGLESTest, GenSyncTokenCHROMIUM) {
+  const GLuint64 kFenceSync = 0x123u;
+  GLbyte sync_token_data[GL_SYNC_TOKEN_SIZE_CHROMIUM] = {};
+
+  EXPECT_CALL(*gl_, GenSyncTokenCHROMIUM(kFenceSync, sync_token_data)).Times(1);
+  ri_->GenSyncTokenCHROMIUM(kFenceSync, sync_token_data);
+}
+
+TEST_F(RasterImplementationGLESTest, GenUnverifiedSyncTokenCHROMIUM) {
+  const GLuint64 kFenceSync = 0x123u;
+  GLbyte sync_token_data[GL_SYNC_TOKEN_SIZE_CHROMIUM] = {};
+
+  EXPECT_CALL(*gl_, GenUnverifiedSyncTokenCHROMIUM(kFenceSync, sync_token_data))
+      .Times(1);
+  ri_->GenUnverifiedSyncTokenCHROMIUM(kFenceSync, sync_token_data);
+}
+
+TEST_F(RasterImplementationGLESTest, VerifySyncTokensCHROMIUM) {
+  const GLsizei kNumSyncTokens = 2;
+  GLbyte sync_token_data[GL_SYNC_TOKEN_SIZE_CHROMIUM][kNumSyncTokens] = {};
+  GLbyte* sync_tokens[2] = {sync_token_data[0], sync_token_data[1]};
+
+  EXPECT_CALL(*gl_, VerifySyncTokensCHROMIUM(sync_tokens, kNumSyncTokens))
+      .Times(1);
+  ri_->VerifySyncTokensCHROMIUM(sync_tokens, kNumSyncTokens);
+}
+
+TEST_F(RasterImplementationGLESTest, WaitSyncTokenCHROMIUM) {
+  GLbyte sync_token_data[GL_SYNC_TOKEN_SIZE_CHROMIUM] = {};
+
+  EXPECT_CALL(*gl_, WaitSyncTokenCHROMIUM(sync_token_data)).Times(1);
+  ri_->WaitSyncTokenCHROMIUM(sync_token_data);
+}
+
+TEST_F(RasterImplementationGLESTest, GetError) {
+  const GLuint kGLInvalidOperation = GL_INVALID_OPERATION;
+
+  EXPECT_CALL(*gl_, GetError()).WillOnce(Return(kGLInvalidOperation));
+  GLenum error = ri_->GetError();
+  EXPECT_EQ(kGLInvalidOperation, error);
+}
+
+TEST_F(RasterImplementationGLESTest, GetGraphicsResetStatusKHR) {
+  const GLuint kGraphicsResetStatus = GL_UNKNOWN_CONTEXT_RESET_KHR;
+
+  EXPECT_CALL(*gl_, GetGraphicsResetStatusKHR())
+      .WillOnce(Return(kGraphicsResetStatus));
+  GLenum status = ri_->GetGraphicsResetStatusKHR();
+  EXPECT_EQ(kGraphicsResetStatus, status);
+}
+
+TEST_F(RasterImplementationGLESTest, GetIntegerv) {
+  const GLint kActiveTexture = 3;
+  GLint active_texture = 0;
+
+  EXPECT_CALL(*gl_, GetIntegerv(GL_ACTIVE_TEXTURE, &active_texture))
+      .WillOnce(SetArgPointee<1>(kActiveTexture));
+  ri_->GetIntegerv(GL_ACTIVE_TEXTURE, &active_texture);
+  EXPECT_EQ(kActiveTexture, active_texture);
+}
+
+TEST_F(RasterImplementationGLESTest, LoseContextCHROMIUM) {
+  const GLenum kCurrent = GL_GUILTY_CONTEXT_RESET_ARB;
+  const GLenum kOther = GL_INNOCENT_CONTEXT_RESET_ARB;
+
+  EXPECT_CALL(*gl_, LoseContextCHROMIUM(kCurrent, kOther)).Times(1);
+  ri_->LoseContextCHROMIUM(kCurrent, kOther);
+}
+
+TEST_F(RasterImplementationGLESTest, GenQueriesEXT) {
+  const GLsizei kNumQueries = 2;
+  GLuint queries[kNumQueries] = {};
+
+  EXPECT_CALL(*gl_, GenQueriesEXT(kNumQueries, queries)).Times(1);
+  ri_->GenQueriesEXT(kNumQueries, queries);
+}
+
+TEST_F(RasterImplementationGLESTest, DeleteQueriesEXT) {
+  const GLsizei kNumQueries = 2;
+  GLuint queries[kNumQueries] = {2, 3};
+
+  EXPECT_CALL(*gl_, DeleteQueriesEXT(kNumQueries, queries)).Times(1);
+  ri_->DeleteQueriesEXT(kNumQueries, queries);
+}
+
+TEST_F(RasterImplementationGLESTest, BeginQueryEXT) {
+  const GLsizei kQueryTarget = GL_COMMANDS_ISSUED_CHROMIUM;
+  const GLuint kQueryId = 23;
+
+  EXPECT_CALL(*gl_, BeginQueryEXT(kQueryTarget, kQueryId)).Times(1);
+  ri_->BeginQueryEXT(kQueryTarget, kQueryId);
+}
+
+TEST_F(RasterImplementationGLESTest, EndQueryEXT) {
+  const GLsizei kQueryTarget = GL_COMMANDS_ISSUED_CHROMIUM;
+
+  EXPECT_CALL(*gl_, EndQueryEXT(kQueryTarget)).Times(1);
+  ri_->EndQueryEXT(kQueryTarget);
+}
+
+TEST_F(RasterImplementationGLESTest, GetQueryObjectuivEXT) {
+  const GLuint kQueryId = 23;
+  const GLsizei kQueryParam = GL_QUERY_RESULT_AVAILABLE_EXT;
+  GLuint result = 0;
+
+  EXPECT_CALL(*gl_, GetQueryObjectuivEXT(kQueryId, kQueryParam, &result))
+      .Times(1);
+  ri_->GetQueryObjectuivEXT(kQueryId, kQueryParam, &result);
+}
+
+// MOCK_METHOD2(DeleteTextures, void(GLsizei n, const GLuint* textures));
+TEST_F(RasterImplementationGLESTest, GenTextures) {
+  const GLsizei kNumTextures = 2;
+  GLuint texture_ids[kNumTextures] = {};
+
+  EXPECT_CALL(*gl_, GenTextures(kNumTextures, texture_ids)).Times(1);
+  ri_->GenTextures(kNumTextures, texture_ids);
+}
+
+TEST_F(RasterImplementationGLESTest, DeleteTextures) {
+  const GLsizei kNumTextures = 2;
+  GLuint texture_ids[kNumTextures] = {2, 3};
+
+  EXPECT_CALL(*gl_, DeleteTextures(kNumTextures, texture_ids)).Times(1);
+  ri_->DeleteTextures(kNumTextures, texture_ids);
+}
+
+TEST_F(RasterImplementationGLESTest, BindTexture) {
+  const GLenum kTarget = GL_TEXTURE_2D;
+  const GLuint kTextureId = 23;
+
+  EXPECT_CALL(*gl_, BindTexture(kTarget, kTextureId)).Times(1);
+  ri_->BindTexture(kTarget, kTextureId);
+}
+
+TEST_F(RasterImplementationGLESTest, ActiveTexture) {
+  const GLenum kTextureUnit = GL_TEXTURE0;
+
+  EXPECT_CALL(*gl_, ActiveTexture(kTextureUnit)).Times(1);
+  ri_->ActiveTexture(kTextureUnit);
+}
+
+TEST_F(RasterImplementationGLESTest, GenerateMipmap) {
+  const GLenum kTarget = GL_TEXTURE_2D;
+
+  EXPECT_CALL(*gl_, GenerateMipmap(kTarget)).Times(1);
+  ri_->GenerateMipmap(kTarget);
+}
+
+TEST_F(RasterImplementationGLESTest, SetColorSpaceMetadataCHROMIUM) {
+  const GLuint kTextureId = 23;
+  gfx::ColorSpace color_space;
+
+  EXPECT_CALL(*gl_,
+              SetColorSpaceMetadataCHROMIUM(
+                  kTextureId, reinterpret_cast<GLColorSpace>(&color_space)))
+      .Times(1);
+  ri_->SetColorSpaceMetadataCHROMIUM(
+      kTextureId, reinterpret_cast<GLColorSpace>(&color_space));
+}
+
+TEST_F(RasterImplementationGLESTest, TexParameteri) {
+  const GLenum kTarget = GL_TEXTURE_2D;
+  const GLenum kPname = GL_TEXTURE_MIN_FILTER;
+  const GLint kParam = GL_NEAREST;
+
+  EXPECT_CALL(*gl_, TexParameteri(kTarget, kPname, kParam)).Times(1);
+  ri_->TexParameteri(kTarget, kPname, kParam);
+}
+
+TEST_F(RasterImplementationGLESTest, GenMailboxCHROMIUM) {
+  gpu::Mailbox mailbox;
+  EXPECT_CALL(*gl_, GenMailboxCHROMIUM(mailbox.name)).Times(1);
+  ri_->GenMailboxCHROMIUM(mailbox.name);
+}
+
+TEST_F(RasterImplementationGLESTest, ProduceTextureDirectCHROMIUM) {
+  const GLuint kTextureId = 23;
+  GLuint texture_id = 0;
+  gpu::Mailbox mailbox;
+
+  EXPECT_CALL(*gl_, GenTextures(1, &texture_id))
+      .WillOnce(SetArgPointee<1>(kTextureId));
+  EXPECT_CALL(*gl_, GenMailboxCHROMIUM(mailbox.name)).Times(1);
+  EXPECT_CALL(*gl_, ProduceTextureDirectCHROMIUM(kTextureId, mailbox.name))
+      .Times(1);
+
+  ri_->GenTextures(1, &texture_id);
+  ri_->GenMailboxCHROMIUM(mailbox.name);
+  ri_->ProduceTextureDirectCHROMIUM(texture_id, mailbox.name);
+}
+
+TEST_F(RasterImplementationGLESTest, CreateAndConsumeTextureCHROMIUM) {
+  const GLuint kTextureId = 23;
+  GLuint texture_id = 0;
+  gpu::Mailbox mailbox;
+
+  EXPECT_CALL(*gl_, CreateAndConsumeTextureCHROMIUM(mailbox.name))
+      .WillOnce(Return(kTextureId));
+  texture_id = ri_->CreateAndConsumeTextureCHROMIUM(mailbox.name);
+  EXPECT_EQ(kTextureId, texture_id);
+}
+
+TEST_F(RasterImplementationGLESTest, CreateImageCHROMIUM) {
+  const GLsizei kWidth = 256;
+  const GLsizei kHeight = 128;
+  const GLenum kInternalFormat = GL_RGBA;
+  const GLint kImageId = 23;
+  const ClientBuffer client_buffer = 0;
+  GLint image_id = 0;
+
+  EXPECT_CALL(*gl_, CreateImageCHROMIUM(client_buffer, kWidth, kHeight,
+                                        kInternalFormat))
+      .WillOnce(Return(kImageId));
+  image_id =
+      ri_->CreateImageCHROMIUM(client_buffer, kWidth, kHeight, kInternalFormat);
+  EXPECT_EQ(kImageId, image_id);
+}
+
+TEST_F(RasterImplementationGLESTest, BindTexImage2DCHROMIUM) {
+  const GLenum kTarget = GL_TEXTURE_2D;
+  const GLint kImageId = 23;
+
+  EXPECT_CALL(*gl_, BindTexImage2DCHROMIUM(kTarget, kImageId)).Times(1);
+  ri_->BindTexImage2DCHROMIUM(kTarget, kImageId);
+}
+
+TEST_F(RasterImplementationGLESTest, ReleaseTexImage2DCHROMIUM) {
+  const GLenum kTarget = GL_TEXTURE_2D;
+  const GLint kImageId = 23;
+
+  EXPECT_CALL(*gl_, ReleaseTexImage2DCHROMIUM(kTarget, kImageId)).Times(1);
+  ri_->ReleaseTexImage2DCHROMIUM(kTarget, kImageId);
+}
+
+TEST_F(RasterImplementationGLESTest, DestroyImageCHROMIUM) {
+  const GLint kImageId = 23;
+
+  EXPECT_CALL(*gl_, DestroyImageCHROMIUM(kImageId)).Times(1);
+  ri_->DestroyImageCHROMIUM(kImageId);
+}
+
+TEST_F(RasterImplementationGLESTest, TexImage2D) {
+  const GLenum target = GL_TEXTURE_2D;
+  const GLint level = 1;
+  const GLint internalformat = GL_RGBA;
+  const GLsizei width = 2;
+  const GLsizei height = 8;
+  const GLint border = 0;
+  const GLenum format = GL_RGBA;
+  const GLenum type = GL_UNSIGNED_BYTE;
+  const unsigned char pixels[64] = {};
+
+  EXPECT_CALL(*gl_, TexImage2D(target, level, internalformat, width, height,
+                               border, format, type, pixels))
+      .Times(1);
+  ri_->TexImage2D(target, level, internalformat, width, height, border, format,
+                  type, pixels);
+}
+
+TEST_F(RasterImplementationGLESTest, TexSubImage2D) {
+  const GLenum target = GL_TEXTURE_2D;
+  const GLint level = 1;
+  const GLint xoffset = 10;
+  const GLint yoffset = 11;
+  const GLsizei width = 2;
+  const GLsizei height = 8;
+  const GLenum format = GL_RGBA;
+  const GLenum type = GL_UNSIGNED_BYTE;
+  const unsigned char pixels[64] = {};
+
+  EXPECT_CALL(*gl_, TexSubImage2D(target, level, xoffset, yoffset, width,
+                                  height, format, type, pixels))
+      .Times(1);
+  ri_->TexSubImage2D(target, level, xoffset, yoffset, width, height, format,
+                     type, pixels);
+}
+
+TEST_F(RasterImplementationGLESTest, CompressedTexImage2D) {
+  const GLenum target = GL_TEXTURE_2D;
+  const GLint level = 1;
+  const GLint internalformat = viz::GLInternalFormat(viz::ETC1);
+  const GLsizei width = 2;
+  const GLsizei height = 8;
+  const GLint border = 0;
+  const GLsizei image_size = 64;
+  const unsigned char data[64] = {};
+
+  EXPECT_CALL(*gl_, CompressedTexImage2D(target, level, internalformat, width,
+                                         height, border, image_size, data))
+      .Times(1);
+  ri_->CompressedTexImage2D(target, level, internalformat, width, height,
+                            border, image_size, data);
+}
+
+TEST_F(RasterImplementationGLESTest, CompressedCopyTextureCHROMIUM) {
+  const GLuint source_id = 23;
+  const GLuint dest_id = 24;
+
+  EXPECT_CALL(*gl_, CompressedCopyTextureCHROMIUM(source_id, dest_id)).Times(1);
+  ri_->CompressedCopyTextureCHROMIUM(source_id, dest_id);
+}
+
+TEST_F(RasterImplementationGLESTest, TexStorageForRasterTexImage2D) {
+  const GLenum kTarget = GL_TEXTURE_2D;
+  const GLsizei kWidth = 2;
+  const GLsizei kHeight = 8;
+  const int kNumTestFormats = 11;
+  viz::ResourceFormat test_formats[kNumTestFormats] = {
+      viz::RGBA_8888,     viz::RGBA_4444, viz::BGRA_8888, viz::ALPHA_8,
+      viz::LUMINANCE_8,   viz::RGB_565,   viz::ETC1,      viz::RED_8,
+      viz::LUMINANCE_F16, viz::RGBA_F16,  viz::R16_EXT};
+
+  for (int i = 0; i < kNumTestFormats; i++) {
+    viz::ResourceFormat format = test_formats[i];
+    EXPECT_CALL(*gl_, TexImage2D(kTarget, 0, viz::GLInternalFormat(format),
+                                 kWidth, kHeight, 0, viz::GLDataFormat(format),
+                                 viz::GLDataType(format), nullptr))
+        .Times(1);
+    ri_->TexStorageForRaster(kTarget, format, kWidth, kHeight,
+                             gpu::raster::kNone);
+  }
+}
+
+TEST_F(RasterImplementationGLESTest, TexStorageForRasterTexStorage2DEXT) {
+  gpu::Capabilities capabilities;
+  capabilities.texture_storage = true;
+  SetUpWithCapabilities(capabilities);
+
+  const GLenum kTarget = GL_TEXTURE_2D;
+  const GLsizei kWidth = 2;
+  const GLsizei kHeight = 8;
+  const int kNumTestFormats = 10;
+  const int kLevels = 1;
+  viz::ResourceFormat test_formats[kNumTestFormats] = {
+      viz::RGBA_8888,   viz::RGBA_4444, viz::BGRA_8888, viz::ALPHA_8,
+      viz::LUMINANCE_8, viz::RGB_565,   viz::RED_8,     viz::LUMINANCE_F16,
+      viz::RGBA_F16,    viz::R16_EXT};
+
+  for (int i = 0; i < kNumTestFormats; i++) {
+    viz::ResourceFormat format = test_formats[i];
+    EXPECT_CALL(*gl_, TexStorage2DEXT(kTarget, kLevels,
+                                      viz::TextureStorageFormat(format), kWidth,
+                                      kHeight))
+        .Times(1);
+    ri_->TexStorageForRaster(kTarget, format, kWidth, kHeight,
+                             gpu::raster::kNone);
+  }
+}
+
+TEST_F(RasterImplementationGLESTest, TexStorageForRasterOverlay) {
+  gpu::Capabilities capabilities;
+  capabilities.texture_storage_image = true;
+  SetUpWithCapabilities(capabilities);
+
+  const GLenum kTarget = GL_TEXTURE_2D;
+  const GLsizei kWidth = 2;
+  const GLsizei kHeight = 8;
+  const int kNumTestFormats = 10;
+  viz::ResourceFormat test_formats[kNumTestFormats] = {
+      viz::RGBA_8888,   viz::RGBA_4444, viz::BGRA_8888, viz::ALPHA_8,
+      viz::LUMINANCE_8, viz::RGB_565,   viz::RED_8,     viz::LUMINANCE_F16,
+      viz::RGBA_F16,    viz::R16_EXT};
+
+  for (int i = 0; i < kNumTestFormats; i++) {
+    viz::ResourceFormat format = test_formats[i];
+    EXPECT_CALL(*gl_, TexStorage2DImageCHROMIUM(
+                          kTarget, viz::TextureStorageFormat(format),
+                          GL_SCANOUT_CHROMIUM, kWidth, kHeight))
+        .Times(1);
+    ri_->TexStorageForRaster(kTarget, format, kWidth, kHeight,
+                             gpu::raster::kOverlay);
+  }
+}
+
+TEST_F(RasterImplementationGLESTest, InitializeDiscardableTextureCHROMIUM) {
+  const GLuint kTextureId = 23;
+
+  EXPECT_CALL(*gl_, InitializeDiscardableTextureCHROMIUM(kTextureId)).Times(1);
+  ri_->InitializeDiscardableTextureCHROMIUM(kTextureId);
+}
+
+TEST_F(RasterImplementationGLESTest, UnlockDiscardableTextureCHROMIUM) {
+  const GLuint kTextureId = 23;
+
+  EXPECT_CALL(*gl_, UnlockDiscardableTextureCHROMIUM(kTextureId)).Times(1);
+  ri_->UnlockDiscardableTextureCHROMIUM(kTextureId);
+}
+
+TEST_F(RasterImplementationGLESTest, LockDiscardableTextureCHROMIUM) {
+  const GLuint kTextureId = 23;
+  bool ret = false;
+
+  EXPECT_CALL(*gl_, LockDiscardableTextureCHROMIUM(kTextureId))
+      .WillOnce(Return(true));
+  ret = ri_->LockDiscardableTextureCHROMIUM(kTextureId);
+  EXPECT_EQ(true, ret);
+
+  EXPECT_CALL(*gl_, LockDiscardableTextureCHROMIUM(kTextureId))
+      .WillOnce(Return(false));
+  ret = ri_->LockDiscardableTextureCHROMIUM(kTextureId);
+  EXPECT_EQ(false, ret);
+}
+
+TEST_F(RasterImplementationGLESTest, BeginRasterCHROMIUM) {
+  const GLuint texture_id = 23;
+  const GLuint sk_color = 0x226688AAu;
+  const GLuint msaa_sample_count = 4;
+  const GLboolean can_use_lcd_text = GL_TRUE;
+  const GLboolean use_distance_field_text = GL_FALSE;
+  const GLint pixel_config = kRGBA_8888_GrPixelConfig;
+  EXPECT_CALL(*gl_, BeginRasterCHROMIUM(texture_id, sk_color, msaa_sample_count,
+                                        can_use_lcd_text,
+                                        use_distance_field_text, pixel_config))
+      .Times(1);
+  ri_->BeginRasterCHROMIUM(texture_id, sk_color, msaa_sample_count,
+                           can_use_lcd_text, use_distance_field_text,
+                           pixel_config);
+}
+
+TEST_F(RasterImplementationGLESTest, RasterCHROMIUM) {
+  scoped_refptr<cc::DisplayItemList> display_list = new cc::DisplayItemList;
+  const GLint translate_x = 1;
+  const GLint translate_y = 2;
+  const GLint clip_x = 3;
+  const GLint clip_y = 4;
+  const GLint clip_w = 5;
+  const GLint clip_h = 6;
+  const GLfloat post_translate_x = 7.0f;
+  const GLfloat post_translate_y = 8.0f;
+  const GLfloat post_scale = 9.0f;
+
+  EXPECT_CALL(
+      *gl_, RasterCHROMIUM(display_list.get(), translate_x, translate_y, clip_x,
+                           clip_y, clip_w, clip_h, post_translate_x,
+                           post_translate_y, post_scale))
+      .Times(1);
+  ri_->RasterCHROMIUM(display_list.get(), translate_x, translate_y, clip_x,
+                      clip_y, clip_w, clip_h, post_translate_x,
+                      post_translate_y, post_scale);
+}
+
+TEST_F(RasterImplementationGLESTest, EndRasterCHROMIUM) {
+  EXPECT_CALL(*gl_, EndRasterCHROMIUM()).Times(1);
+  ri_->EndRasterCHROMIUM();
+}
+
+}  // namespace raster
+}  // namespace gpu
diff --git a/gpu/command_buffer/client/raster_interface.h b/gpu/command_buffer/client/raster_interface.h
new file mode 100644
index 0000000..2adf81c
--- /dev/null
+++ b/gpu/command_buffer/client/raster_interface.h
@@ -0,0 +1,161 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GPU_COMMAND_BUFFER_CLIENT_RASTER_INTERFACE_H_
+#define GPU_COMMAND_BUFFER_CLIENT_RASTER_INTERFACE_H_
+
+#include <GLES2/gl2.h>
+#include "base/compiler_specific.h"
+#include "components/viz/common/resources/resource_format.h"
+
+namespace cc {
+class DisplayItemList;
+}  // namespace cc
+
+extern "C" typedef struct _ClientBuffer* ClientBuffer;
+extern "C" typedef struct _GLColorSpace* GLColorSpace;
+
+namespace gpu {
+namespace raster {
+
+enum RasterTexStorageFlags { kNone = 0, kOverlay = (1 << 0) };
+
+class RasterInterface {
+ public:
+  RasterInterface() {}
+  virtual ~RasterInterface() {}
+
+  // Command buffer Flush / Finish.
+  virtual void Finish() = 0;
+  virtual void ShallowFlushCHROMIUM() = 0;
+  virtual void OrderingBarrierCHROMIUM() = 0;
+
+  // SyncTokens.
+  virtual GLuint64 InsertFenceSyncCHROMIUM() = 0;
+  virtual void GenSyncTokenCHROMIUM(GLuint64 fence_sync,
+                                    GLbyte* sync_token) = 0;
+  virtual void GenUnverifiedSyncTokenCHROMIUM(GLuint64 fence_sync,
+                                              GLbyte* sync_token) = 0;
+  virtual void VerifySyncTokensCHROMIUM(GLbyte** sync_tokens,
+                                        GLsizei count) = 0;
+  virtual void WaitSyncTokenCHROMIUM(const GLbyte* sync_token) = 0;
+
+  // Command buffer state.
+  virtual GLenum GetError() = 0;
+  virtual GLenum GetGraphicsResetStatusKHR() = 0;
+  virtual void GetIntegerv(GLenum pname, GLint* params) = 0;
+  virtual void LoseContextCHROMIUM(GLenum current, GLenum other) = 0;
+
+  // Queries: GL_COMMANDS_ISSUED_CHROMIUM / GL_COMMANDS_COMPLETED_CHROMIUM.
+  virtual void GenQueriesEXT(GLsizei n, GLuint* queries) = 0;
+  virtual void DeleteQueriesEXT(GLsizei n, const GLuint* queries) = 0;
+  virtual void BeginQueryEXT(GLenum target, GLuint id) = 0;
+  virtual void EndQueryEXT(GLenum target) = 0;
+  virtual void GetQueryObjectuivEXT(GLuint id,
+                                    GLenum pname,
+                                    GLuint* params) = 0;
+
+  // Texture objects.
+  virtual void GenTextures(GLsizei n, GLuint* textures) = 0;
+  virtual void DeleteTextures(GLsizei n, const GLuint* textures) = 0;
+  virtual void BindTexture(GLenum target, GLuint texture) = 0;
+  virtual void ActiveTexture(GLenum texture) = 0;
+  virtual void GenerateMipmap(GLenum target) = 0;
+  virtual void SetColorSpaceMetadataCHROMIUM(GLuint texture_id,
+                                             GLColorSpace color_space) = 0;
+  virtual void TexParameteri(GLenum target, GLenum pname, GLint param) = 0;
+
+  // Mailboxes.
+  virtual void GenMailboxCHROMIUM(GLbyte* mailbox) = 0;
+  virtual void ProduceTextureDirectCHROMIUM(GLuint texture,
+                                            const GLbyte* mailbox) = 0;
+  virtual GLuint CreateAndConsumeTextureCHROMIUM(const GLbyte* mailbox) = 0;
+
+  // Image objects.
+  virtual GLuint CreateImageCHROMIUM(ClientBuffer buffer,
+                                     GLsizei width,
+                                     GLsizei height,
+                                     GLenum internalformat) = 0;
+  virtual void BindTexImage2DCHROMIUM(GLenum target, GLint imageId) = 0;
+  virtual void ReleaseTexImage2DCHROMIUM(GLenum target, GLint imageId) = 0;
+  virtual void DestroyImageCHROMIUM(GLuint image_id) = 0;
+
+  // Texture allocation and copying.
+  virtual void TexImage2D(GLenum target,
+                          GLint level,
+                          GLint internalformat,
+                          GLsizei width,
+                          GLsizei height,
+                          GLint border,
+                          GLenum format,
+                          GLenum type,
+                          const void* pixels) = 0;
+  virtual void TexSubImage2D(GLenum target,
+                             GLint level,
+                             GLint xoffset,
+                             GLint yoffset,
+                             GLsizei width,
+                             GLsizei height,
+                             GLenum format,
+                             GLenum type,
+                             const void* pixels) = 0;
+  virtual void CompressedTexImage2D(GLenum target,
+                                    GLint level,
+                                    GLenum internalformat,
+                                    GLsizei width,
+                                    GLsizei height,
+                                    GLint border,
+                                    GLsizei imageSize,
+                                    const void* data) = 0;
+  virtual void TexStorageForRaster(GLenum target,
+                                   viz::ResourceFormat format,
+                                   GLsizei width,
+                                   GLsizei height,
+                                   RasterTexStorageFlags flags) = 0;
+  virtual void CopySubTextureCHROMIUM(GLuint source_id,
+                                      GLint source_level,
+                                      GLenum dest_target,
+                                      GLuint dest_id,
+                                      GLint dest_level,
+                                      GLint xoffset,
+                                      GLint yoffset,
+                                      GLint x,
+                                      GLint y,
+                                      GLsizei width,
+                                      GLsizei height,
+                                      GLboolean unpack_flip_y,
+                                      GLboolean unpack_premultiply_alpha,
+                                      GLboolean unpack_unmultiply_alpha) = 0;
+  virtual void CompressedCopyTextureCHROMIUM(GLuint source_id,
+                                             GLuint dest_id) = 0;
+
+  // Discardable textures.
+  virtual void InitializeDiscardableTextureCHROMIUM(GLuint texture_id) = 0;
+  virtual void UnlockDiscardableTextureCHROMIUM(GLuint texture_id) = 0;
+  virtual bool LockDiscardableTextureCHROMIUM(GLuint texture_id) = 0;
+
+  // OOP-Raster
+  virtual void BeginRasterCHROMIUM(GLuint texture_id,
+                                   GLuint sk_color,
+                                   GLuint msaa_sample_count,
+                                   GLboolean can_use_lcd_text,
+                                   GLboolean use_distance_field_text,
+                                   GLint pixel_config) = 0;
+  virtual void RasterCHROMIUM(const cc::DisplayItemList* list,
+                              GLint translate_x,
+                              GLint translate_y,
+                              GLint clip_x,
+                              GLint clip_y,
+                              GLint clip_w,
+                              GLint clip_h,
+                              GLfloat post_translate_x,
+                              GLfloat post_translate_y,
+                              GLfloat post_scale) = 0;
+  virtual void EndRasterCHROMIUM() = 0;
+};
+
+}  // namespace raster
+}  // namespace gpu
+
+#endif  // GPU_COMMAND_BUFFER_CLIENT_RASTER_INTERFACE_H_
diff --git a/gpu/command_buffer/common/gles2_cmd_utils.h b/gpu/command_buffer/common/gles2_cmd_utils.h
index 9a85d82..0044d5b 100644
--- a/gpu/command_buffer/common/gles2_cmd_utils.h
+++ b/gpu/command_buffer/common/gles2_cmd_utils.h
@@ -343,6 +343,8 @@
   bool should_use_native_gmb_for_backbuffer = false;
   bool own_offscreen_surface = false;
   bool single_buffer = false;
+  bool enable_gles2_interface = true;
+  bool enable_raster_interface = false;
   bool enable_oop_rasterization = false;
   bool enable_swap_timestamps_if_supported = false;
 
diff --git a/gpu/ipc/common/gpu_command_buffer_traits_multi.h b/gpu/ipc/common/gpu_command_buffer_traits_multi.h
index 9f51eb5..992dad1 100644
--- a/gpu/ipc/common/gpu_command_buffer_traits_multi.h
+++ b/gpu/ipc/common/gpu_command_buffer_traits_multi.h
@@ -173,6 +173,8 @@
   IPC_STRUCT_TRAITS_MEMBER(own_offscreen_surface)
   IPC_STRUCT_TRAITS_MEMBER(single_buffer)
   IPC_STRUCT_TRAITS_MEMBER(color_space)
+  IPC_STRUCT_TRAITS_MEMBER(enable_gles2_interface)
+  IPC_STRUCT_TRAITS_MEMBER(enable_raster_interface)
   IPC_STRUCT_TRAITS_MEMBER(enable_oop_rasterization)
   IPC_STRUCT_TRAITS_MEMBER(enable_swap_timestamps_if_supported)
 IPC_STRUCT_TRAITS_END()
diff --git a/gpu/ipc/service/gpu_channel.cc b/gpu/ipc/service/gpu_channel.cc
index bfc11ae..6745702 100644
--- a/gpu/ipc/service/gpu_channel.cc
+++ b/gpu/ipc/service/gpu_channel.cc
@@ -621,7 +621,9 @@
 
   std::unique_ptr<CommandBufferStub> stub;
   if (gpu_channel_manager_->gpu_preferences().enable_raster_decoder &&
-      init_params.attribs.enable_oop_rasterization) {
+      init_params.attribs.enable_oop_rasterization &&
+      init_params.attribs.enable_raster_interface &&
+      !init_params.attribs.enable_gles2_interface) {
     stub = std::make_unique<RasterCommandBufferStub>(
         this, init_params, command_buffer_id, sequence_id, stream_id, route_id);
   } else {
diff --git a/services/ui/public/cpp/gpu/context_provider_command_buffer.cc b/services/ui/public/cpp/gpu/context_provider_command_buffer.cc
index 7c4f151..7e36c276 100644
--- a/services/ui/public/cpp/gpu/context_provider_command_buffer.cc
+++ b/services/ui/public/cpp/gpu/context_provider_command_buffer.cc
@@ -22,6 +22,7 @@
 #include "gpu/command_buffer/client/gles2_implementation.h"
 #include "gpu/command_buffer/client/gles2_trace_implementation.h"
 #include "gpu/command_buffer/client/gpu_switches.h"
+#include "gpu/command_buffer/client/raster_implementation_gles.h"
 #include "gpu/command_buffer/client/transfer_buffer.h"
 #include "gpu/command_buffer/common/constants.h"
 #include "gpu/ipc/client/command_buffer_proxy_impl.h"
@@ -357,11 +358,38 @@
   DCHECK_EQ(bind_result_, gpu::ContextResult::kSuccess);
   CheckValidThreadOrLockAcquired();
 
+  if (!attributes_.enable_gles2_interface) {
+    DLOG(ERROR) << "Unexpected access to ContextGL()";
+    return nullptr;
+  }
+
   if (trace_impl_)
     return trace_impl_.get();
   return gles2_impl_.get();
 }
 
+gpu::raster::RasterInterface* ContextProviderCommandBuffer::RasterContext() {
+  DCHECK(bind_tried_);
+  DCHECK_EQ(bind_result_, gpu::ContextResult::kSuccess);
+  CheckValidThreadOrLockAcquired();
+
+  if (raster_impl_)
+    return raster_impl_.get();
+
+  if (!attributes_.enable_raster_interface) {
+    DLOG(ERROR) << "Unexpected access to RasterContext()";
+    return nullptr;
+  }
+
+  if (!gles2_impl_.get())
+    return nullptr;
+
+  raster_impl_ = std::make_unique<gpu::raster::RasterImplementationGLES>(
+      gles2_impl_.get(), ContextCapabilities());
+
+  return raster_impl_.get();
+}
+
 gpu::ContextSupport* ContextProviderCommandBuffer::ContextSupport() {
   return gles2_impl_.get();
 }
@@ -374,19 +402,29 @@
   if (gr_context_)
     return gr_context_->get();
 
+  // TODO(vmiura): crbug.com/793508 Disable access to GrContext if
+  // enable_gles2_interface is disabled, after removing any dependencies on
+  // GrContext in OOP-Raster.
+
   size_t max_resource_cache_bytes;
   size_t max_glyph_cache_texture_bytes;
   skia_bindings::GrContextForGLES2Interface::
       DetermineCacheLimitsFromAvailableMemory(&max_resource_cache_bytes,
                                               &max_glyph_cache_texture_bytes);
+  gpu::gles2::GLES2Interface* gl_interface;
+  if (trace_impl_)
+    gl_interface = trace_impl_.get();
+  else
+    gl_interface = gles2_impl_.get();
+
   gr_context_.reset(new skia_bindings::GrContextForGLES2Interface(
-      ContextGL(), ContextCapabilities(), max_resource_cache_bytes,
+      gl_interface, ContextCapabilities(), max_resource_cache_bytes,
       max_glyph_cache_texture_bytes));
   cache_controller_->SetGrContext(gr_context_->get());
 
   // If GlContext is already lost, also abandon the new GrContext.
   if (gr_context_->get() &&
-      ContextGL()->GetGraphicsResetStatusKHR() != GL_NO_ERROR)
+      gles2_impl_->GetGraphicsResetStatusKHR() != GL_NO_ERROR)
     gr_context_->get()->abandonContext();
 
   return gr_context_->get();
diff --git a/services/ui/public/cpp/gpu/context_provider_command_buffer.h b/services/ui/public/cpp/gpu/context_provider_command_buffer.h
index ef7f9ff..d0a9922 100644
--- a/services/ui/public/cpp/gpu/context_provider_command_buffer.h
+++ b/services/ui/public/cpp/gpu/context_provider_command_buffer.h
@@ -35,6 +35,9 @@
 class GLES2Implementation;
 class GLES2TraceImplementation;
 }
+namespace raster {
+class RasterImplementationGLES;
+}
 }
 
 namespace skia_bindings {
@@ -70,6 +73,7 @@
   // viz::ContextProvider implementation.
   gpu::ContextResult BindToCurrentThread() override;
   gpu::gles2::GLES2Interface* ContextGL() override;
+  gpu::raster::RasterInterface* RasterContext() override;
   gpu::ContextSupport* ContextSupport() override;
   class GrContext* GrContext() override;
   viz::ContextCacheController* CacheController() override;
@@ -142,6 +146,7 @@
   std::unique_ptr<gpu::TransferBuffer> transfer_buffer_;
   std::unique_ptr<gpu::gles2::GLES2Implementation> gles2_impl_;
   std::unique_ptr<gpu::gles2::GLES2TraceImplementation> trace_impl_;
+  std::unique_ptr<gpu::raster::RasterImplementationGLES> raster_impl_;
   std::unique_ptr<skia_bindings::GrContextForGLES2Interface> gr_context_;
   std::unique_ptr<viz::ContextCacheController> cache_controller_;
 
diff --git a/ui/compositor/test/in_process_context_provider.cc b/ui/compositor/test/in_process_context_provider.cc
index 0755542..8309ae6 100644
--- a/ui/compositor/test/in_process_context_provider.cc
+++ b/ui/compositor/test/in_process_context_provider.cc
@@ -14,6 +14,7 @@
 #include "components/viz/common/gpu/context_cache_controller.h"
 #include "gpu/command_buffer/client/gles2_implementation.h"
 #include "gpu/command_buffer/client/gles2_lib.h"
+#include "gpu/command_buffer/client/raster_implementation_gles.h"
 #include "gpu/command_buffer/client/shared_memory_limits.h"
 #include "gpu/ipc/gl_in_process_context.h"
 #include "gpu/skia_bindings/grcontext_for_gles2_interface.h"
@@ -112,6 +113,10 @@
   context_->GetImplementation()->TraceBeginCHROMIUM(
       "gpu_toplevel", unique_context_name.c_str());
 
+  raster_context_ = std::make_unique<gpu::raster::RasterImplementationGLES>(
+      context_->GetImplementation(),
+      context_->GetImplementation()->capabilities());
+
   return bind_result_;
 }
 
@@ -131,6 +136,12 @@
   return context_->GetImplementation();
 }
 
+gpu::raster::RasterInterface* InProcessContextProvider::RasterContext() {
+  CheckValidThreadOrLockAcquired();
+
+  return raster_context_.get();
+}
+
 gpu::ContextSupport* InProcessContextProvider::ContextSupport() {
   CheckValidThreadOrLockAcquired();
 
diff --git a/ui/compositor/test/in_process_context_provider.h b/ui/compositor/test/in_process_context_provider.h
index f114da1..9b8bd92 100644
--- a/ui/compositor/test/in_process_context_provider.h
+++ b/ui/compositor/test/in_process_context_provider.h
@@ -53,6 +53,7 @@
   const gpu::Capabilities& ContextCapabilities() const override;
   const gpu::GpuFeatureInfo& GetGpuFeatureInfo() const override;
   gpu::gles2::GLES2Interface* ContextGL() override;
+  gpu::raster::RasterInterface* RasterContext() override;
   gpu::ContextSupport* ContextSupport() override;
   class GrContext* GrContext() override;
   viz::ContextCacheController* CacheController() override;
@@ -91,6 +92,7 @@
 
   std::unique_ptr<gpu::GLInProcessContext> context_;
   std::unique_ptr<skia_bindings::GrContextForGLES2Interface> gr_context_;
+  std::unique_ptr<gpu::raster::RasterInterface> raster_context_;
   std::unique_ptr<viz::ContextCacheController> cache_controller_;
 
   const bool support_locking_ ALLOW_UNUSED_TYPE;