Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / cc / resources / resource_provider.cc
index d88bdd2..1522886 100644 (file)
@@ -25,7 +25,6 @@
 #include "third_party/khronos/GLES2/gl2ext.h"
 #include "third_party/skia/include/core/SkSurface.h"
 #include "third_party/skia/include/gpu/GrContext.h"
-#include "third_party/skia/include/gpu/SkGpuDevice.h"
 #include "ui/gfx/frame_time.h"
 #include "ui/gfx/rect.h"
 #include "ui/gfx/vector2d.h"
@@ -81,11 +80,12 @@ GLenum TextureToStorageFormat(ResourceFormat format) {
   return storage_format;
 }
 
-bool IsFormatSupportedForStorage(ResourceFormat format) {
+bool IsFormatSupportedForStorage(ResourceFormat format, bool use_bgra) {
   switch (format) {
     case RGBA_8888:
-    case BGRA_8888:
       return true;
+    case BGRA_8888:
+      return use_bgra;
     case RGBA_4444:
     case ALPHA_8:
     case LUMINANCE_8:
@@ -111,18 +111,6 @@ GrPixelConfig ToGrPixelConfig(ResourceFormat format) {
   return kSkia8888_GrPixelConfig;
 }
 
-void CopyBitmap(const SkBitmap& src, uint8_t* dst, SkColorType dst_color_type) {
-  SkImageInfo dst_info = src.info();
-  dst_info.fColorType = dst_color_type;
-  // TODO(kaanb): The GL pipeline assumes a 4-byte alignment for the
-  // bitmap data. There will be no need to call SkAlign4 once crbug.com/293728
-  // is fixed.
-  const size_t dst_row_bytes = SkAlign4(dst_info.minRowBytes());
-  CHECK_EQ(0u, dst_row_bytes % 4);
-  bool success = src.readPixels(dst_info, dst, dst_row_bytes, 0, 0);
-  CHECK_EQ(true, success);
-}
-
 class ScopedSetActiveTexture {
  public:
   ScopedSetActiveTexture(GLES2Interface* gl, GLenum unit)
@@ -248,7 +236,7 @@ ResourceProvider::Resource::Resource()
       bound_image_id(0),
       texture_pool(0),
       wrap_mode(0),
-      hint(TextureUsageAny),
+      hint(TextureHintImmutable),
       type(InvalidType),
       format(RGBA_8888),
       shared_bitmap(NULL) {
@@ -263,7 +251,7 @@ ResourceProvider::Resource::Resource(GLuint texture_id,
                                      GLenum filter,
                                      GLenum texture_pool,
                                      GLint wrap_mode,
-                                     TextureUsageHint hint,
+                                     TextureHint hint,
                                      ResourceFormat format)
     : child_id(0),
       gl_id(texture_id),
@@ -337,7 +325,7 @@ ResourceProvider::Resource::Resource(uint8_t* pixels,
       bound_image_id(0),
       texture_pool(0),
       wrap_mode(wrap_mode),
-      hint(TextureUsageAny),
+      hint(TextureHintImmutable),
       type(Bitmap),
       format(RGBA_8888),
       shared_bitmap(bitmap) {
@@ -381,7 +369,7 @@ ResourceProvider::Resource::Resource(const SharedBitmapId& bitmap_id,
       bound_image_id(0),
       texture_pool(0),
       wrap_mode(wrap_mode),
-      hint(TextureUsageAny),
+      hint(TextureHintImmutable),
       type(Bitmap),
       format(RGBA_8888),
       shared_bitmap_id(bitmap_id),
@@ -389,190 +377,6 @@ ResourceProvider::Resource::Resource(const SharedBitmapId& bitmap_id,
   DCHECK(wrap_mode == GL_CLAMP_TO_EDGE || wrap_mode == GL_REPEAT);
 }
 
-ResourceProvider::RasterBuffer::RasterBuffer(
-    const Resource* resource,
-    ResourceProvider* resource_provider)
-    : resource_(resource),
-      resource_provider_(resource_provider),
-      locked_canvas_(NULL),
-      canvas_save_count_(0) {
-  DCHECK(resource_);
-  DCHECK(resource_provider_);
-}
-
-ResourceProvider::RasterBuffer::~RasterBuffer() {}
-
-SkCanvas* ResourceProvider::RasterBuffer::LockForWrite() {
-  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
-               "ResourceProvider::RasterBuffer::LockForWrite");
-
-  DCHECK(!locked_canvas_);
-
-  locked_canvas_ = DoLockForWrite();
-  canvas_save_count_ = locked_canvas_ ? locked_canvas_->save() : 0;
-  return locked_canvas_;
-}
-
-bool ResourceProvider::RasterBuffer::UnlockForWrite() {
-  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
-               "ResourceProvider::RasterBuffer::UnlockForWrite");
-
-  if (locked_canvas_) {
-    locked_canvas_->restoreToCount(canvas_save_count_);
-    locked_canvas_ = NULL;
-  }
-  return DoUnlockForWrite();
-}
-
-ResourceProvider::GpuRasterBuffer::GpuRasterBuffer(
-    const Resource* resource,
-    ResourceProvider* resource_provider,
-    bool use_distance_field_text)
-    : RasterBuffer(resource, resource_provider),
-      surface_generation_id_(0u),
-      use_distance_field_text_(use_distance_field_text) {
-}
-
-ResourceProvider::GpuRasterBuffer::~GpuRasterBuffer() {
-}
-
-SkCanvas* ResourceProvider::GpuRasterBuffer::DoLockForWrite() {
-  if (!surface_)
-    surface_ = CreateSurface();
-  surface_generation_id_ = surface_ ? surface_->generationID() : 0u;
-  return surface_ ? surface_->getCanvas() : NULL;
-}
-
-bool ResourceProvider::GpuRasterBuffer::DoUnlockForWrite() {
-  // generationID returns a non-zero, unique value corresponding to the content
-  // of surface. Hence, a change since DoLockForWrite was called means the
-  // surface has changed.
-  return surface_ ? surface_generation_id_ != surface_->generationID() : false;
-}
-
-skia::RefPtr<SkSurface> ResourceProvider::GpuRasterBuffer::CreateSurface() {
-  DCHECK_EQ(GLTexture, resource()->type);
-  DCHECK(resource()->gl_id);
-
-  class GrContext* gr_context = resource_provider()->GrContext();
-  // TODO(alokp): Implement TestContextProvider::GrContext().
-  if (!gr_context)
-    return skia::RefPtr<SkSurface>();
-
-  GrBackendTextureDesc desc;
-  desc.fFlags = kRenderTarget_GrBackendTextureFlag;
-  desc.fWidth = resource()->size.width();
-  desc.fHeight = resource()->size.height();
-  desc.fConfig = ToGrPixelConfig(resource()->format);
-  desc.fOrigin = kTopLeft_GrSurfaceOrigin;
-  desc.fTextureHandle = resource()->gl_id;
-  skia::RefPtr<GrTexture> gr_texture =
-      skia::AdoptRef(gr_context->wrapBackendTexture(desc));
-  SkSurface::TextRenderMode text_render_mode =
-      use_distance_field_text_ ? SkSurface::kDistanceField_TextRenderMode
-                               : SkSurface::kStandard_TextRenderMode;
-  return skia::AdoptRef(SkSurface::NewRenderTargetDirect(
-      gr_texture->asRenderTarget(), text_render_mode));
-}
-
-ResourceProvider::BitmapRasterBuffer::BitmapRasterBuffer(
-    const Resource* resource,
-    ResourceProvider* resource_provider)
-    : RasterBuffer(resource, resource_provider),
-      mapped_buffer_(NULL),
-      raster_bitmap_generation_id_(0u) {}
-
-ResourceProvider::BitmapRasterBuffer::~BitmapRasterBuffer() {}
-
-SkCanvas* ResourceProvider::BitmapRasterBuffer::DoLockForWrite() {
-  DCHECK(!mapped_buffer_);
-  DCHECK(!raster_canvas_);
-
-  int stride = 0;
-  mapped_buffer_ = MapBuffer(&stride);
-  if (!mapped_buffer_)
-    return NULL;
-
-  switch (resource()->format) {
-    case RGBA_4444:
-      // Use the default stride if we will eventually convert this
-      // bitmap to 4444.
-      raster_bitmap_.allocN32Pixels(resource()->size.width(),
-                                    resource()->size.height());
-      break;
-    case RGBA_8888:
-    case BGRA_8888: {
-      SkImageInfo info = SkImageInfo::MakeN32Premul(resource()->size.width(),
-                                                    resource()->size.height());
-      if (0 == stride)
-        stride = info.minRowBytes();
-      raster_bitmap_.installPixels(info, mapped_buffer_, stride);
-      break;
-    }
-    case ALPHA_8:
-    case LUMINANCE_8:
-    case RGB_565:
-    case ETC1:
-      NOTREACHED();
-      break;
-  }
-  raster_canvas_ = skia::AdoptRef(new SkCanvas(raster_bitmap_));
-  raster_bitmap_generation_id_ = raster_bitmap_.getGenerationID();
-  return raster_canvas_.get();
-}
-
-bool ResourceProvider::BitmapRasterBuffer::DoUnlockForWrite() {
-  raster_canvas_.clear();
-
-  // getGenerationID returns a non-zero, unique value corresponding to the
-  // pixels in bitmap. Hence, a change since DoLockForWrite was called means the
-  // bitmap has changed.
-  bool raster_bitmap_changed =
-      raster_bitmap_generation_id_ != raster_bitmap_.getGenerationID();
-
-  if (raster_bitmap_changed) {
-    SkColorType buffer_colorType =
-        ResourceFormatToSkColorType(resource()->format);
-    if (mapped_buffer_ && (buffer_colorType != raster_bitmap_.colorType()))
-      CopyBitmap(raster_bitmap_, mapped_buffer_, buffer_colorType);
-  }
-  raster_bitmap_.reset();
-
-  UnmapBuffer();
-  mapped_buffer_ = NULL;
-  return raster_bitmap_changed;
-}
-
-ResourceProvider::ImageRasterBuffer::ImageRasterBuffer(
-    const Resource* resource,
-    ResourceProvider* resource_provider)
-    : BitmapRasterBuffer(resource, resource_provider) {}
-
-ResourceProvider::ImageRasterBuffer::~ImageRasterBuffer() {}
-
-uint8_t* ResourceProvider::ImageRasterBuffer::MapBuffer(int* stride) {
-  return resource_provider()->MapImage(resource(), stride);
-}
-
-void ResourceProvider::ImageRasterBuffer::UnmapBuffer() {
-  resource_provider()->UnmapImage(resource());
-}
-
-ResourceProvider::PixelRasterBuffer::PixelRasterBuffer(
-    const Resource* resource,
-    ResourceProvider* resource_provider)
-    : BitmapRasterBuffer(resource, resource_provider) {}
-
-ResourceProvider::PixelRasterBuffer::~PixelRasterBuffer() {}
-
-uint8_t* ResourceProvider::PixelRasterBuffer::MapBuffer(int* stride) {
-  return resource_provider()->MapPixelBuffer(resource(), stride);
-}
-
-void ResourceProvider::PixelRasterBuffer::UnmapBuffer() {
-  resource_provider()->UnmapPixelBuffer(resource());
-}
-
 ResourceProvider::Child::Child() : marked_for_deletion(false) {}
 
 ResourceProvider::Child::~Child() {}
@@ -580,6 +384,7 @@ ResourceProvider::Child::~Child() {}
 scoped_ptr<ResourceProvider> ResourceProvider::Create(
     OutputSurface* output_surface,
     SharedBitmapManager* shared_bitmap_manager,
+    BlockingTaskRunner* blocking_main_thread_task_runner,
     int highp_threshold_min,
     bool use_rgba_4444_texture_format,
     size_t id_allocation_chunk_size,
@@ -587,6 +392,7 @@ scoped_ptr<ResourceProvider> ResourceProvider::Create(
   scoped_ptr<ResourceProvider> resource_provider(
       new ResourceProvider(output_surface,
                            shared_bitmap_manager,
+                           blocking_main_thread_task_runner,
                            highp_threshold_min,
                            use_rgba_4444_texture_format,
                            id_allocation_chunk_size,
@@ -629,7 +435,7 @@ bool ResourceProvider::AllowOverlay(ResourceId id) {
 ResourceProvider::ResourceId ResourceProvider::CreateResource(
     const gfx::Size& size,
     GLint wrap_mode,
-    TextureUsageHint hint,
+    TextureHint hint,
     ResourceFormat format) {
   DCHECK(!size.IsEmpty());
   switch (default_resource_type_) {
@@ -655,7 +461,7 @@ ResourceProvider::ResourceId ResourceProvider::CreateManagedResource(
     const gfx::Size& size,
     GLenum target,
     GLint wrap_mode,
-    TextureUsageHint hint,
+    TextureHint hint,
     ResourceFormat format) {
   DCHECK(!size.IsEmpty());
   switch (default_resource_type_) {
@@ -682,7 +488,7 @@ ResourceProvider::ResourceId ResourceProvider::CreateGLTexture(
     GLenum target,
     GLenum texture_pool,
     GLint wrap_mode,
-    TextureUsageHint hint,
+    TextureHint hint,
     ResourceFormat format) {
   DCHECK_LE(size.width(), max_texture_size_);
   DCHECK_LE(size.height(), max_texture_size_);
@@ -741,7 +547,7 @@ ResourceProvider::ResourceId ResourceProvider::CreateResourceFromIOSurface(
                     GL_LINEAR,
                     GL_TEXTURE_POOL_UNMANAGED_CHROMIUM,
                     GL_CLAMP_TO_EDGE,
-                    TextureUsageAny,
+                    TextureHintImmutable,
                     RGBA_8888);
   LazyCreate(&resource);
   GLES2Interface* gl = ContextGL();
@@ -756,7 +562,7 @@ ResourceProvider::ResourceId ResourceProvider::CreateResourceFromIOSurface(
 
 ResourceProvider::ResourceId ResourceProvider::CreateResourceFromTextureMailbox(
     const TextureMailbox& mailbox,
-    scoped_ptr<SingleReleaseCallback> release_callback) {
+    scoped_ptr<SingleReleaseCallbackImpl> release_callback_impl) {
   DCHECK(thread_checker_.CalledOnValidThread());
   // Just store the information. Mailbox will be consumed in LockForRead().
   ResourceId id = next_id_++;
@@ -770,7 +576,7 @@ ResourceProvider::ResourceId ResourceProvider::CreateResourceFromTextureMailbox(
                         GL_LINEAR,
                         0,
                         GL_CLAMP_TO_EDGE,
-                        TextureUsageAny,
+                        TextureHintImmutable,
                         RGBA_8888);
   } else {
     DCHECK(mailbox.IsSharedMemory());
@@ -792,9 +598,9 @@ ResourceProvider::ResourceId ResourceProvider::CreateResourceFromTextureMailbox(
   }
   resource.allocated = true;
   resource.mailbox = mailbox;
-  resource.release_callback =
-      base::Bind(&SingleReleaseCallback::Run,
-                 base::Owned(release_callback.release()));
+  resource.release_callback_impl =
+      base::Bind(&SingleReleaseCallbackImpl::Run,
+                 base::Owned(release_callback_impl.release()));
   resource.allow_overlay = mailbox.allow_overlay();
   return id;
 }
@@ -826,10 +632,6 @@ void ResourceProvider::DeleteResourceInternal(ResourceMap::iterator it,
   if (style == ForShutdown && resource->exported_count > 0)
     lost_resource = true;
 
-  resource->gpu_raster_buffer.reset();
-  resource->image_raster_buffer.reset();
-  resource->pixel_raster_buffer.reset();
-
   if (resource->image_id) {
     DCHECK(resource->origin == Resource::Internal);
     GLES2Interface* gl = ContextGL();
@@ -878,7 +680,8 @@ void ResourceProvider::DeleteResourceInternal(ResourceMap::iterator it,
         resource->shared_bitmap = NULL;
       }
     }
-    resource->release_callback.Run(sync_point, lost_resource);
+    resource->release_callback_impl.Run(
+        sync_point, lost_resource, blocking_main_thread_task_runner_);
   }
   if (resource->gl_id) {
     GLES2Interface* gl = ContextGL();
@@ -1033,12 +836,13 @@ const ResourceProvider::Resource* ResourceProvider::LockForRead(ResourceId id) {
   if (resource->type == GLTexture && !resource->gl_id) {
     DCHECK(resource->origin != Resource::Internal);
     DCHECK(resource->mailbox.IsTexture());
+
+    // Mailbox sync_points must be processed by a call to
+    // WaitSyncPointIfNeeded() prior to calling LockForRead().
+    DCHECK(!resource->mailbox.sync_point());
+
     GLES2Interface* gl = ContextGL();
     DCHECK(gl);
-    if (resource->mailbox.sync_point()) {
-      GLC(gl, gl->WaitSyncPointCHROMIUM(resource->mailbox.sync_point()));
-      resource->mailbox.set_sync_point(0);
-    }
     resource->gl_id = texture_id_allocator_->NextId();
     GLC(gl, gl->BindTexture(resource->target, resource->gl_id));
     GLC(gl,
@@ -1059,7 +863,7 @@ const ResourceProvider::Resource* ResourceProvider::LockForRead(ResourceId id) {
 
   resource->lock_for_read_count++;
   if (resource->read_lock_fences_enabled) {
-    if (current_read_lock_fence_)
+    if (current_read_lock_fence_.get())
       current_read_lock_fence_->Set();
     resource->read_lock_fence = current_read_lock_fence_;
   }
@@ -1204,20 +1008,24 @@ ResourceProvider::ScopedWriteLockSoftware::~ScopedWriteLockSoftware() {
   resource_provider_->UnlockForWrite(resource_id_);
 }
 
-ResourceProvider::ResourceProvider(OutputSurface* output_surface,
-                                   SharedBitmapManager* shared_bitmap_manager,
-                                   int highp_threshold_min,
-                                   bool use_rgba_4444_texture_format,
-                                   size_t id_allocation_chunk_size,
-                                   bool use_distance_field_text)
+ResourceProvider::ResourceProvider(
+    OutputSurface* output_surface,
+    SharedBitmapManager* shared_bitmap_manager,
+    BlockingTaskRunner* blocking_main_thread_task_runner,
+    int highp_threshold_min,
+    bool use_rgba_4444_texture_format,
+    size_t id_allocation_chunk_size,
+    bool use_distance_field_text)
     : output_surface_(output_surface),
       shared_bitmap_manager_(shared_bitmap_manager),
+      blocking_main_thread_task_runner_(blocking_main_thread_task_runner),
       lost_output_surface_(false),
       highp_threshold_min_(highp_threshold_min),
       next_id_(1),
       next_child_(1),
       default_resource_type_(InvalidType),
       use_texture_storage_ext_(false),
+      use_texture_format_bgra_(false),
       use_texture_usage_hint_(false),
       use_compressed_texture_etc1_(false),
       max_texture_size_(0),
@@ -1256,6 +1064,7 @@ void ResourceProvider::InitializeGL() {
 
   bool use_bgra = caps.gpu.texture_format_bgra8888;
   use_texture_storage_ext_ = caps.gpu.texture_storage;
+  use_texture_format_bgra_ = caps.gpu.texture_format_bgra8888;
   use_texture_usage_hint_ = caps.gpu.texture_usage;
   use_compressed_texture_etc1_ = caps.gpu.texture_format_etc1;
   use_sync_query_ = caps.gpu.sync_query;
@@ -1397,7 +1206,8 @@ void ResourceProvider::ReceiveFromChild(
       TRACE_EVENT0("cc", "ResourceProvider::ReceiveFromChild dropping invalid");
       ReturnedResourceArray to_return;
       to_return.push_back(it->ToReturnedResource());
-      child_info.return_callback.Run(to_return);
+      child_info.return_callback.Run(to_return,
+                                     blocking_main_thread_task_runner_);
       continue;
     }
 
@@ -1417,7 +1227,7 @@ void ResourceProvider::ReceiveFromChild(
                           it->filter,
                           0,
                           it->is_repeated ? GL_REPEAT : GL_CLAMP_TO_EDGE,
-                          TextureUsageAny,
+                          TextureHintImmutable,
                           it->format);
       resource.mailbox = TextureMailbox(it->mailbox_holder.mailbox,
                                         it->mailbox_holder.texture_target,
@@ -1523,7 +1333,7 @@ void ResourceProvider::ReceiveReturnsFromParent(
     // Need to wait for the current read lock fence to pass before we can
     // recycle this resource.
     if (resource->read_lock_fences_enabled) {
-      if (current_read_lock_fence_)
+      if (current_read_lock_fence_.get())
         current_read_lock_fence_->Set();
       resource->read_lock_fence = current_read_lock_fence_;
     }
@@ -1712,7 +1522,8 @@ void ResourceProvider::DeleteAndReturnUnusedResourcesToChild(
   }
 
   if (!to_return.empty())
-    child_info->return_callback.Run(to_return);
+    child_info->return_callback.Run(to_return,
+                                    blocking_main_thread_task_runner_);
 
   if (child_info->marked_for_deletion &&
       child_info->parent_to_child_map.empty()) {
@@ -1721,67 +1532,11 @@ void ResourceProvider::DeleteAndReturnUnusedResourcesToChild(
   }
 }
 
-SkCanvas* ResourceProvider::MapGpuRasterBuffer(ResourceId id) {
-  // Resource needs to be locked for write since GpuRasterBuffer writes
-  // directly to it.
-  LockForWrite(id);
-  Resource* resource = GetResource(id);
-  if (!resource->gpu_raster_buffer.get()) {
-    resource->gpu_raster_buffer.reset(
-        new GpuRasterBuffer(resource, this, use_distance_field_text_));
-  }
-  return resource->gpu_raster_buffer->LockForWrite();
-}
-
-void ResourceProvider::UnmapGpuRasterBuffer(ResourceId id) {
-  Resource* resource = GetResource(id);
-  DCHECK(resource->gpu_raster_buffer.get());
-  resource->gpu_raster_buffer->UnlockForWrite();
-  UnlockForWrite(id);
-}
-
-SkCanvas* ResourceProvider::MapImageRasterBuffer(ResourceId id) {
-  Resource* resource = GetResource(id);
-  AcquireImage(resource);
-  if (!resource->image_raster_buffer.get())
-    resource->image_raster_buffer.reset(new ImageRasterBuffer(resource, this));
-  return resource->image_raster_buffer->LockForWrite();
-}
-
-bool ResourceProvider::UnmapImageRasterBuffer(ResourceId id) {
-  Resource* resource = GetResource(id);
-  resource->dirty_image = true;
-  return resource->image_raster_buffer->UnlockForWrite();
-}
-
-void ResourceProvider::AcquirePixelRasterBuffer(ResourceId id) {
-  Resource* resource = GetResource(id);
-  AcquirePixelBuffer(resource);
-  resource->pixel_raster_buffer.reset(new PixelRasterBuffer(resource, this));
-}
-
-void ResourceProvider::ReleasePixelRasterBuffer(ResourceId id) {
-  Resource* resource = GetResource(id);
-  resource->pixel_raster_buffer.reset();
-  ReleasePixelBuffer(resource);
-}
-
-SkCanvas* ResourceProvider::MapPixelRasterBuffer(ResourceId id) {
-  Resource* resource = GetResource(id);
-  DCHECK(resource->pixel_raster_buffer.get());
-  return resource->pixel_raster_buffer->LockForWrite();
-}
-
-bool ResourceProvider::UnmapPixelRasterBuffer(ResourceId id) {
-  Resource* resource = GetResource(id);
-  DCHECK(resource->pixel_raster_buffer.get());
-  return resource->pixel_raster_buffer->UnlockForWrite();
-}
-
-void ResourceProvider::AcquirePixelBuffer(Resource* resource) {
+void ResourceProvider::AcquirePixelBuffer(ResourceId id) {
   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
                "ResourceProvider::AcquirePixelBuffer");
 
+  Resource* resource = GetResource(id);
   DCHECK(resource->origin == Resource::Internal);
   DCHECK_EQ(resource->exported_count, 0);
   DCHECK(!resource->image_id);
@@ -1803,10 +1558,11 @@ void ResourceProvider::AcquirePixelBuffer(Resource* resource) {
   gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
 }
 
-void ResourceProvider::ReleasePixelBuffer(Resource* resource) {
+void ResourceProvider::ReleasePixelBuffer(ResourceId id) {
   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
                "ResourceProvider::ReleasePixelBuffer");
 
+  Resource* resource = GetResource(id);
   DCHECK(resource->origin == Resource::Internal);
   DCHECK_EQ(resource->exported_count, 0);
   DCHECK(!resource->image_id);
@@ -1835,11 +1591,11 @@ void ResourceProvider::ReleasePixelBuffer(Resource* resource) {
   gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
 }
 
-uint8_t* ResourceProvider::MapPixelBuffer(const Resource* resource,
-                                          int* stride) {
+uint8_t* ResourceProvider::MapPixelBuffer(ResourceId id, int* stride) {
   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
                "ResourceProvider::MapPixelBuffer");
 
+  Resource* resource = GetResource(id);
   DCHECK(resource->origin == Resource::Internal);
   DCHECK_EQ(resource->exported_count, 0);
   DCHECK(!resource->image_id);
@@ -1859,10 +1615,11 @@ uint8_t* ResourceProvider::MapPixelBuffer(const Resource* resource,
   return image;
 }
 
-void ResourceProvider::UnmapPixelBuffer(const Resource* resource) {
+void ResourceProvider::UnmapPixelBuffer(ResourceId id) {
   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
                "ResourceProvider::UnmapPixelBuffer");
 
+  Resource* resource = GetResource(id);
   DCHECK(resource->origin == Resource::Internal);
   DCHECK_EQ(resource->exported_count, 0);
   DCHECK(!resource->image_id);
@@ -1877,10 +1634,9 @@ void ResourceProvider::UnmapPixelBuffer(const Resource* resource) {
   gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
 }
 
-GLenum ResourceProvider::BindForSampling(
-    ResourceProvider::ResourceId resource_id,
-    GLenum unit,
-    GLenum filter) {
+GLenum ResourceProvider::BindForSampling(ResourceId resource_id,
+                                         GLenum unit,
+                                         GLenum filter) {
   DCHECK(thread_checker_.CalledOnValidThread());
   GLES2Interface* gl = ContextGL();
   ResourceMap::iterator it = resources_.find(resource_id);
@@ -1967,6 +1723,7 @@ void ResourceProvider::ForceSetPixelsToComplete(ResourceId id) {
                "ResourceProvider::ForceSetPixelsToComplete");
 
   Resource* resource = GetResource(id);
+
   DCHECK(resource->locked_for_write);
   DCHECK(resource->pending_set_pixels);
   DCHECK(!resource->set_pixels_completion_forced);
@@ -1986,6 +1743,7 @@ bool ResourceProvider::DidSetPixelsComplete(ResourceId id) {
                "ResourceProvider::DidSetPixelsComplete");
 
   Resource* resource = GetResource(id);
+
   DCHECK(resource->locked_for_write);
   DCHECK(resource->pending_set_pixels);
 
@@ -2033,9 +1791,11 @@ void ResourceProvider::LazyCreate(Resource* resource) {
   // Create and set texture properties. Allocation is delayed until needed.
   GLC(gl, gl->BindTexture(resource->target, resource->gl_id));
   GLC(gl,
-      gl->TexParameteri(resource->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
+      gl->TexParameteri(
+          resource->target, GL_TEXTURE_MIN_FILTER, resource->original_filter));
   GLC(gl,
-      gl->TexParameteri(resource->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
+      gl->TexParameteri(
+          resource->target, GL_TEXTURE_MAG_FILTER, resource->original_filter));
   GLC(gl,
       gl->TexParameteri(
           resource->target, GL_TEXTURE_WRAP_S, resource->wrap_mode));
@@ -2045,7 +1805,7 @@ void ResourceProvider::LazyCreate(Resource* resource) {
   GLC(gl,
       gl->TexParameteri(
           resource->target, GL_TEXTURE_POOL_CHROMIUM, resource->texture_pool));
-  if (use_texture_usage_hint_ && resource->hint == TextureUsageFramebuffer) {
+  if (use_texture_usage_hint_ && (resource->hint & TextureHintFramebuffer)) {
     GLC(gl,
         gl->TexParameteri(resource->target,
                           GL_TEXTURE_USAGE_ANGLE,
@@ -2059,10 +1819,10 @@ void ResourceProvider::AllocateForTesting(ResourceId id) {
 
 void ResourceProvider::LazyAllocate(Resource* resource) {
   DCHECK(resource);
+  if (resource->allocated)
+    return;
   LazyCreate(resource);
-
-  DCHECK(resource->gl_id || resource->allocated);
-  if (resource->allocated || !resource->gl_id)
+  if (!resource->gl_id)
     return;
   resource->allocated = true;
   GLES2Interface* gl = ContextGL();
@@ -2070,8 +1830,9 @@ void ResourceProvider::LazyAllocate(Resource* resource) {
   DCHECK_EQ(resource->target, static_cast<GLenum>(GL_TEXTURE_2D));
   ResourceFormat format = resource->format;
   GLC(gl, gl->BindTexture(GL_TEXTURE_2D, resource->gl_id));
-  if (use_texture_storage_ext_ && IsFormatSupportedForStorage(format) &&
-      resource->hint != TextureUsageFramebuffer) {
+  if (use_texture_storage_ext_ &&
+      IsFormatSupportedForStorage(format, use_texture_format_bgra_) &&
+      (resource->hint & TextureHintImmutable)) {
     GLenum storage_format = TextureToStorageFormat(format);
     GLC(gl,
         gl->TexStorage2DEXT(
@@ -2106,17 +1867,16 @@ void ResourceProvider::BindImageForSampling(Resource* resource) {
   resource->dirty_image = false;
 }
 
-void ResourceProvider::EnableReadLockFences(ResourceProvider::ResourceId id) {
+void ResourceProvider::EnableReadLockFences(ResourceId id) {
   Resource* resource = GetResource(id);
   resource->read_lock_fences_enabled = true;
 }
 
-void ResourceProvider::AcquireImage(Resource* resource) {
+void ResourceProvider::AcquireImage(ResourceId id) {
+  Resource* resource = GetResource(id);
   DCHECK(resource->origin == Resource::Internal);
   DCHECK_EQ(resource->exported_count, 0);
-
-  if (resource->type != GLTexture)
-    return;
+  DCHECK_EQ(GLTexture, resource->type);
 
   if (resource->image_id)
     return;
@@ -2132,9 +1892,11 @@ void ResourceProvider::AcquireImage(Resource* resource) {
   DCHECK(resource->image_id);
 }
 
-void ResourceProvider::ReleaseImage(Resource* resource) {
+void ResourceProvider::ReleaseImage(ResourceId id) {
+  Resource* resource = GetResource(id);
   DCHECK(resource->origin == Resource::Internal);
   DCHECK_EQ(resource->exported_count, 0);
+  DCHECK_EQ(GLTexture, resource->type);
 
   if (!resource->image_id)
     return;
@@ -2148,36 +1910,93 @@ void ResourceProvider::ReleaseImage(Resource* resource) {
   resource->allocated = false;
 }
 
-uint8_t* ResourceProvider::MapImage(const Resource* resource, int* stride) {
+uint8_t* ResourceProvider::MapImage(ResourceId id, int* stride) {
+  Resource* resource = GetResource(id);
   DCHECK(ReadLockFenceHasPassed(resource));
   DCHECK(resource->origin == Resource::Internal);
   DCHECK_EQ(resource->exported_count, 0);
+  DCHECK(resource->image_id);
 
-  if (resource->type == GLTexture) {
-    DCHECK(resource->image_id);
-    GLES2Interface* gl = ContextGL();
-    DCHECK(gl);
-    // MapImageCHROMIUM should be called prior to GetImageParameterivCHROMIUM.
-    uint8_t* pixels =
-        static_cast<uint8_t*>(gl->MapImageCHROMIUM(resource->image_id));
-    gl->GetImageParameterivCHROMIUM(
-        resource->image_id, GL_IMAGE_ROWBYTES_CHROMIUM, stride);
-    return pixels;
-  }
-  DCHECK_EQ(Bitmap, resource->type);
-  *stride = 0;
-  return resource->pixels;
+  LockForWrite(id);
+
+  GLES2Interface* gl = ContextGL();
+  DCHECK(gl);
+  // MapImageCHROMIUM should be called prior to GetImageParameterivCHROMIUM.
+  uint8_t* pixels =
+      static_cast<uint8_t*>(gl->MapImageCHROMIUM(resource->image_id));
+  gl->GetImageParameterivCHROMIUM(
+      resource->image_id, GL_IMAGE_ROWBYTES_CHROMIUM, stride);
+  return pixels;
 }
 
-void ResourceProvider::UnmapImage(const Resource* resource) {
+void ResourceProvider::UnmapImage(ResourceId id) {
+  Resource* resource = GetResource(id);
   DCHECK(resource->origin == Resource::Internal);
   DCHECK_EQ(resource->exported_count, 0);
+  DCHECK(resource->image_id);
+  DCHECK(resource->locked_for_write);
 
-  if (resource->image_id) {
-    GLES2Interface* gl = ContextGL();
-    DCHECK(gl);
-    gl->UnmapImageCHROMIUM(resource->image_id);
-  }
+  GLES2Interface* gl = ContextGL();
+  DCHECK(gl);
+  gl->UnmapImageCHROMIUM(resource->image_id);
+  resource->dirty_image = true;
+
+  UnlockForWrite(id);
+}
+
+void ResourceProvider::AcquireSkSurface(ResourceId id) {
+  Resource* resource = GetResource(id);
+  DCHECK(resource->origin == Resource::Internal);
+  DCHECK_EQ(resource->exported_count, 0);
+  DCHECK_EQ(GLTexture, resource->type);
+
+  if (resource->sk_surface)
+    return;
+
+  class GrContext* gr_context = GrContext();
+  // TODO(alokp): Implement TestContextProvider::GrContext().
+  if (!gr_context)
+    return;
+
+  LazyAllocate(resource);
+
+  GrBackendTextureDesc desc;
+  desc.fFlags = kRenderTarget_GrBackendTextureFlag;
+  desc.fWidth = resource->size.width();
+  desc.fHeight = resource->size.height();
+  desc.fConfig = ToGrPixelConfig(resource->format);
+  desc.fOrigin = kTopLeft_GrSurfaceOrigin;
+  desc.fTextureHandle = resource->gl_id;
+  skia::RefPtr<GrTexture> gr_texture =
+      skia::AdoptRef(gr_context->wrapBackendTexture(desc));
+  SkSurface::TextRenderMode text_render_mode =
+      use_distance_field_text_ ? SkSurface::kDistanceField_TextRenderMode
+                               : SkSurface::kStandard_TextRenderMode;
+  resource->sk_surface = skia::AdoptRef(SkSurface::NewRenderTargetDirect(
+      gr_texture->asRenderTarget(), text_render_mode));
+}
+
+void ResourceProvider::ReleaseSkSurface(ResourceId id) {
+  Resource* resource = GetResource(id);
+  DCHECK(resource->origin == Resource::Internal);
+  DCHECK_EQ(resource->exported_count, 0);
+  DCHECK_EQ(GLTexture, resource->type);
+
+  resource->sk_surface.clear();
+}
+
+SkSurface* ResourceProvider::LockForWriteToSkSurface(ResourceId id) {
+  Resource* resource = GetResource(id);
+  DCHECK(resource->origin == Resource::Internal);
+  DCHECK_EQ(resource->exported_count, 0);
+  DCHECK_EQ(GLTexture, resource->type);
+
+  LockForWrite(id);
+  return resource->sk_surface.get();
+}
+
+void ResourceProvider::UnlockForWriteToSkSurface(ResourceId id) {
+  UnlockForWrite(id);
 }
 
 void ResourceProvider::CopyResource(ResourceId source_id, ResourceId dest_id) {
@@ -2187,6 +2006,7 @@ void ResourceProvider::CopyResource(ResourceId source_id, ResourceId dest_id) {
   DCHECK(!source_resource->lock_for_read_count);
   DCHECK(source_resource->origin == Resource::Internal);
   DCHECK_EQ(source_resource->exported_count, 0);
+  DCHECK_EQ(GLTexture, source_resource->type);
   DCHECK(source_resource->allocated);
   LazyCreate(source_resource);
 
@@ -2195,45 +2015,52 @@ void ResourceProvider::CopyResource(ResourceId source_id, ResourceId dest_id) {
   DCHECK(!dest_resource->lock_for_read_count);
   DCHECK(dest_resource->origin == Resource::Internal);
   DCHECK_EQ(dest_resource->exported_count, 0);
+  DCHECK_EQ(GLTexture, dest_resource->type);
   LazyCreate(dest_resource);
 
   DCHECK_EQ(source_resource->type, dest_resource->type);
   DCHECK_EQ(source_resource->format, dest_resource->format);
   DCHECK(source_resource->size == dest_resource->size);
 
-  if (source_resource->type == GLTexture) {
-    GLES2Interface* gl = ContextGL();
-    DCHECK(gl);
-    if (source_resource->image_id && source_resource->dirty_image) {
-      gl->BindTexture(source_resource->target, source_resource->gl_id);
-      BindImageForSampling(source_resource);
-    }
-    DCHECK(use_sync_query_) << "CHROMIUM_sync_query extension missing";
-    if (!source_resource->gl_read_lock_query_id)
-      gl->GenQueriesEXT(1, &source_resource->gl_read_lock_query_id);
-    gl->BeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM,
-                      source_resource->gl_read_lock_query_id);
-    DCHECK(!dest_resource->image_id);
-    dest_resource->allocated = true;
-    gl->CopyTextureCHROMIUM(dest_resource->target,
-                            source_resource->gl_id,
-                            dest_resource->gl_id,
-                            0,
-                            GLInternalFormat(dest_resource->format),
-                            GLDataType(dest_resource->format));
-    // End query and create a read lock fence that will prevent access to
-    // source resource until CopyTextureCHROMIUM command has completed.
-    gl->EndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM);
-    source_resource->read_lock_fence = make_scoped_refptr(
-        new QueryFence(gl, source_resource->gl_read_lock_query_id));
-  } else {
-    DCHECK_EQ(Bitmap, source_resource->type);
-    DCHECK_EQ(RGBA_8888, source_resource->format);
-    LazyAllocate(dest_resource);
-
-    size_t bytes = SharedBitmap::CheckedSizeInBytes(source_resource->size);
-    memcpy(dest_resource->pixels, source_resource->pixels, bytes);
+  GLES2Interface* gl = ContextGL();
+  DCHECK(gl);
+  if (source_resource->image_id && source_resource->dirty_image) {
+    gl->BindTexture(source_resource->target, source_resource->gl_id);
+    BindImageForSampling(source_resource);
   }
+  DCHECK(use_sync_query_) << "CHROMIUM_sync_query extension missing";
+  if (!source_resource->gl_read_lock_query_id)
+    gl->GenQueriesEXT(1, &source_resource->gl_read_lock_query_id);
+  gl->BeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM,
+                    source_resource->gl_read_lock_query_id);
+  DCHECK(!dest_resource->image_id);
+  dest_resource->allocated = true;
+  gl->CopyTextureCHROMIUM(dest_resource->target,
+                          source_resource->gl_id,
+                          dest_resource->gl_id,
+                          0,
+                          GLInternalFormat(dest_resource->format),
+                          GLDataType(dest_resource->format));
+  // End query and create a read lock fence that will prevent access to
+  // source resource until CopyTextureCHROMIUM command has completed.
+  gl->EndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM);
+  source_resource->read_lock_fence = make_scoped_refptr(
+      new QueryFence(gl, source_resource->gl_read_lock_query_id));
+}
+
+void ResourceProvider::WaitSyncPointIfNeeded(ResourceId id) {
+  Resource* resource = GetResource(id);
+  DCHECK_EQ(resource->exported_count, 0);
+  DCHECK(resource->allocated);
+  if (resource->type != GLTexture || resource->gl_id)
+    return;
+  if (!resource->mailbox.sync_point())
+    return;
+  DCHECK(resource->mailbox.IsValid());
+  GLES2Interface* gl = ContextGL();
+  DCHECK(gl);
+  GLC(gl, gl->WaitSyncPointCHROMIUM(resource->mailbox.sync_point()));
+  resource->mailbox.set_sync_point(0);
 }
 
 GLint ResourceProvider::GetActiveTextureUnit(GLES2Interface* gl) {