// Copyright 2012 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 "cc/resources/resource_provider.h"

#include <stddef.h>
#include <stdint.h>

#include <algorithm>
#include <limits>
#include <unordered_map>

#include "base/atomic_sequence_num.h"
#include "base/macros.h"
#include "base/metrics/histogram.h"
#include "base/numerics/safe_math.h"
#include "base/stl_util.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "cc/resources/resource_util.h"
#include "components/viz/common/resources/platform_color.h"
#include "components/viz/common/resources/returned_resource.h"
#include "components/viz/common/resources/shared_bitmap_manager.h"
#include "components/viz/common/resources/transferable_resource.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/gpu_memory_buffer_manager.h"
#include "skia/ext/texture_handle.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "third_party/khronos/GLES2/gl2ext.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkSurface.h"
#include "third_party/skia/include/gpu/GrBackendSurface.h"
#include "third_party/skia/include/gpu/GrContext.h"
#include "third_party/skia/include/gpu/gl/GrGLTypes.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/vector2d.h"
#include "ui/gfx/icc_profile.h"
#include "ui/gl/trace_util.h"

using gpu::gles2::GLES2Interface;

namespace cc {

class TextureIdAllocator {
 public:
  TextureIdAllocator(GLES2Interface* gl,
                     size_t texture_id_allocation_chunk_size)
      : gl_(gl),
        id_allocation_chunk_size_(texture_id_allocation_chunk_size),
        ids_(new GLuint[texture_id_allocation_chunk_size]),
        next_id_index_(texture_id_allocation_chunk_size) {
    DCHECK(id_allocation_chunk_size_);
    DCHECK_LE(id_allocation_chunk_size_,
              static_cast<size_t>(std::numeric_limits<int>::max()));
  }

  ~TextureIdAllocator() {
    gl_->DeleteTextures(
        static_cast<int>(id_allocation_chunk_size_ - next_id_index_),
        ids_.get() + next_id_index_);
  }

  GLuint NextId() {
    if (next_id_index_ == id_allocation_chunk_size_) {
      gl_->GenTextures(static_cast<int>(id_allocation_chunk_size_), ids_.get());
      next_id_index_ = 0;
    }

    return ids_[next_id_index_++];
  }

 private:
  GLES2Interface* gl_;
  const size_t id_allocation_chunk_size_;
  std::unique_ptr<GLuint[]> ids_;
  size_t next_id_index_;

  DISALLOW_COPY_AND_ASSIGN(TextureIdAllocator);
};

namespace {

GLenum TextureToStorageFormat(viz::ResourceFormat format) {
  GLenum storage_format = GL_RGBA8_OES;
  switch (format) {
    case viz::RGBA_8888:
      break;
    case viz::BGRA_8888:
      storage_format = GL_BGRA8_EXT;
      break;
    case viz::RGBA_F16:
      storage_format = GL_RGBA16F_EXT;
      break;
    case viz::RGBA_4444:
    case viz::ALPHA_8:
    case viz::LUMINANCE_8:
    case viz::RGB_565:
    case viz::ETC1:
    case viz::RED_8:
    case viz::LUMINANCE_F16:
      NOTREACHED();
      break;
  }

  return storage_format;
}

bool IsFormatSupportedForStorage(viz::ResourceFormat format, bool use_bgra) {
  switch (format) {
    case viz::RGBA_8888:
    case viz::RGBA_F16:
      return true;
    case viz::BGRA_8888:
      return use_bgra;
    case viz::RGBA_4444:
    case viz::ALPHA_8:
    case viz::LUMINANCE_8:
    case viz::RGB_565:
    case viz::ETC1:
    case viz::RED_8:
    case viz::LUMINANCE_F16:
      return false;
  }
  return false;
}

class ScopedSetActiveTexture {
 public:
  ScopedSetActiveTexture(GLES2Interface* gl, GLenum unit)
      : gl_(gl), unit_(unit) {
    DCHECK_EQ(GL_TEXTURE0, ResourceProvider::GetActiveTextureUnit(gl_));

    if (unit_ != GL_TEXTURE0)
      gl_->ActiveTexture(unit_);
  }

  ~ScopedSetActiveTexture() {
    // Active unit being GL_TEXTURE0 is effectively the ground state.
    if (unit_ != GL_TEXTURE0)
      gl_->ActiveTexture(GL_TEXTURE0);
  }

 private:
  GLES2Interface* gl_;
  GLenum unit_;
};

// Generates process-unique IDs to use for tracing a ResourceProvider's
// resources.
base::AtomicSequenceNumber g_next_resource_provider_tracing_id;

}  // namespace

ResourceProvider::Resource::Resource(GLuint texture_id,
                                     const gfx::Size& size,
                                     Origin origin,
                                     GLenum target,
                                     GLenum filter,
                                     TextureHint hint,
                                     ResourceType type,
                                     viz::ResourceFormat format)
    : child_id(0),
      gl_id(texture_id),
      pixels(nullptr),
      lock_for_read_count(0),
      imported_count(0),
      exported_count(0),
      locked_for_write(false),
      lost(false),
      marked_for_deletion(false),
      allocated(false),
      read_lock_fences_enabled(false),
      has_shared_bitmap_id(false),
      is_overlay_candidate(false),
#if defined(OS_ANDROID)
      is_backed_by_surface_texture(false),
      wants_promotion_hint(false),
#endif
      size(size),
      origin(origin),
      target(target),
      original_filter(filter),
      filter(filter),
      image_id(0),
      hint(hint),
      type(type),
      usage(gfx::BufferUsage::GPU_READ_CPU_READ_WRITE),
      buffer_format(gfx::BufferFormat::RGBA_8888),
      format(format),
      shared_bitmap(nullptr) {
}

ResourceProvider::Resource::Resource(uint8_t* pixels,
                                     viz::SharedBitmap* bitmap,
                                     const gfx::Size& size,
                                     Origin origin,
                                     GLenum filter)
    : child_id(0),
      gl_id(0),
      pixels(pixels),
      lock_for_read_count(0),
      imported_count(0),
      exported_count(0),
      locked_for_write(false),
      lost(false),
      marked_for_deletion(false),
      allocated(false),
      read_lock_fences_enabled(false),
      has_shared_bitmap_id(!!bitmap),
      is_overlay_candidate(false),
#if defined(OS_ANDROID)
      is_backed_by_surface_texture(false),
      wants_promotion_hint(false),
#endif
      size(size),
      origin(origin),
      target(0),
      original_filter(filter),
      filter(filter),
      image_id(0),
      hint(TEXTURE_HINT_IMMUTABLE),
      type(RESOURCE_TYPE_BITMAP),
      buffer_format(gfx::BufferFormat::RGBA_8888),
      format(viz::RGBA_8888),
      shared_bitmap(bitmap) {
  DCHECK(origin == DELEGATED || pixels);
  if (bitmap)
    shared_bitmap_id = bitmap->id();
}

ResourceProvider::Resource::Resource(const viz::SharedBitmapId& bitmap_id,
                                     const gfx::Size& size,
                                     Origin origin,
                                     GLenum filter)
    : child_id(0),
      gl_id(0),
      pixels(nullptr),
      lock_for_read_count(0),
      imported_count(0),
      exported_count(0),
      locked_for_write(false),
      lost(false),
      marked_for_deletion(false),
      allocated(false),
      read_lock_fences_enabled(false),
      has_shared_bitmap_id(true),
      is_overlay_candidate(false),
#if defined(OS_ANDROID)
      is_backed_by_surface_texture(false),
      wants_promotion_hint(false),
#endif
      size(size),
      origin(origin),
      target(0),
      original_filter(filter),
      filter(filter),
      image_id(0),
      hint(TEXTURE_HINT_IMMUTABLE),
      type(RESOURCE_TYPE_BITMAP),
      buffer_format(gfx::BufferFormat::RGBA_8888),
      format(viz::RGBA_8888),
      shared_bitmap_id(bitmap_id),
      shared_bitmap(nullptr) {
}

ResourceProvider::Resource::Resource(Resource&& other) = default;

ResourceProvider::Resource::~Resource() = default;

void ResourceProvider::Resource::SetMailbox(
    const viz::TextureMailbox& mailbox) {
  DCHECK(!mailbox.sync_token().HasData() || IsGpuResourceType(type));
  mailbox_ = mailbox;
  synchronization_state_ =
      mailbox.sync_token().HasData() ? NEEDS_WAIT : SYNCHRONIZED;
}

void ResourceProvider::Resource::SetLocallyUsed() {
  synchronization_state_ = LOCALLY_USED;
  mailbox_.set_sync_token(gpu::SyncToken());
}

void ResourceProvider::Resource::SetSynchronized() {
  synchronization_state_ = SYNCHRONIZED;
}

void ResourceProvider::Resource::UpdateSyncToken(
    const gpu::SyncToken& sync_token) {
  DCHECK(IsGpuResourceType(type));
  // An empty sync token may be used if commands are guaranteed to have run on
  // the gpu process or in case of context loss.
  mailbox_.set_sync_token(sync_token);
  synchronization_state_ = sync_token.HasData() ? NEEDS_WAIT : SYNCHRONIZED;
}

int8_t* ResourceProvider::Resource::GetSyncTokenData() {
  return mailbox_.GetSyncTokenData();
}

void ResourceProvider::Resource::WaitSyncToken(gpu::gles2::GLES2Interface* gl) {
  if (synchronization_state_ != NEEDS_WAIT)
    return;
  DCHECK(gl);
  // In the case of context lost, this sync token may be empty (see comment in
  // the UpdateSyncToken() function). The WaitSyncTokenCHROMIUM() function
  // handles empty sync tokens properly so just wait anyways and update the
  // state the synchronized.
  gl->WaitSyncTokenCHROMIUM(mailbox_.sync_token().GetConstData());
  SetSynchronized();
}

ResourceProvider::Child::Child()
    : marked_for_deletion(false), needs_sync_tokens(true) {}

ResourceProvider::Child::Child(const Child& other) = default;

ResourceProvider::Child::~Child() {}

ResourceProvider::Settings::Settings(
    viz::ContextProvider* compositor_context_provider,
    bool delegated_sync_points_required,
    bool enable_color_correct_rasterization,
    const viz::ResourceSettings& resource_settings)
    : default_resource_type(resource_settings.use_gpu_memory_buffer_resources
                                ? RESOURCE_TYPE_GPU_MEMORY_BUFFER
                                : RESOURCE_TYPE_GL_TEXTURE),
      enable_color_correct_rasterization(enable_color_correct_rasterization),
      delegated_sync_points_required(delegated_sync_points_required) {
  if (!compositor_context_provider) {
    default_resource_type = RESOURCE_TYPE_BITMAP;
    // Pick an arbitrary limit here similar to what hardware might.
    max_texture_size = 16 * 1024;
    best_texture_format = viz::RGBA_8888;
    return;
  }

  DCHECK(IsGpuResourceType(default_resource_type));

  const auto& caps = compositor_context_provider->ContextCapabilities();
  use_texture_storage_ext = caps.texture_storage;
  use_texture_format_bgra = caps.texture_format_bgra8888;
  use_texture_usage_hint = caps.texture_usage;
  use_sync_query = caps.sync_query;

  if (caps.disable_one_component_textures) {
    yuv_resource_format = yuv_highbit_resource_format = viz::RGBA_8888;
  } else {
    yuv_resource_format = caps.texture_rg ? viz::RED_8 : viz::LUMINANCE_8;
    yuv_highbit_resource_format = caps.texture_half_float_linear
                                      ? viz::LUMINANCE_F16
                                      : yuv_resource_format;
  }

  GLES2Interface* gl = compositor_context_provider->ContextGL();
  gl->GetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);

  best_texture_format =
      viz::PlatformColor::BestSupportedTextureFormat(use_texture_format_bgra);
  best_render_buffer_format = viz::PlatformColor::BestSupportedTextureFormat(
      caps.render_buffer_format_bgra8888);
}

ResourceProvider::ResourceProvider(
    viz::ContextProvider* compositor_context_provider,
    viz::SharedBitmapManager* shared_bitmap_manager,
    gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
    BlockingTaskRunner* blocking_main_thread_task_runner,
    bool delegated_sync_points_required,
    bool enable_color_correct_rasterization,
    const viz::ResourceSettings& resource_settings)
    : settings_(compositor_context_provider,
                delegated_sync_points_required,
                enable_color_correct_rasterization,
                resource_settings),
      compositor_context_provider_(compositor_context_provider),
      shared_bitmap_manager_(shared_bitmap_manager),
      gpu_memory_buffer_manager_(gpu_memory_buffer_manager),
      blocking_main_thread_task_runner_(blocking_main_thread_task_runner),
      next_id_(1),
      next_child_(1),
      lost_context_provider_(false),
      buffer_to_texture_target_map_(
          resource_settings.buffer_to_texture_target_map),
      tracing_id_(g_next_resource_provider_tracing_id.GetNext()) {
  DCHECK(resource_settings.texture_id_allocation_chunk_size);
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  // In certain cases, ThreadTaskRunnerHandle isn't set (Android Webview).
  // Don't register a dump provider in these cases.
  // TODO(ericrk): Get this working in Android Webview. crbug.com/517156
  if (base::ThreadTaskRunnerHandle::IsSet()) {
    base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
        this, "cc::ResourceProvider", base::ThreadTaskRunnerHandle::Get());
  }

  if (!compositor_context_provider)
    return;

  DCHECK(!texture_id_allocator_);
  GLES2Interface* gl = ContextGL();
  texture_id_allocator_.reset(new TextureIdAllocator(
      gl, resource_settings.texture_id_allocation_chunk_size));
}

ResourceProvider::~ResourceProvider() {
  base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
      this);

  while (!children_.empty())
    DestroyChildInternal(children_.begin(), FOR_SHUTDOWN);
  while (!resources_.empty())
    DeleteResourceInternal(resources_.begin(), FOR_SHUTDOWN);

  GLES2Interface* gl = ContextGL();
  if (!IsGpuResourceType(settings_.default_resource_type)) {
    // We are not in GL mode, but double check before returning.
    DCHECK(!gl);
    return;
  }

  DCHECK(gl);
#if DCHECK_IS_ON()
  // Check that all GL resources has been deleted.
  for (ResourceMap::const_iterator itr = resources_.begin();
       itr != resources_.end(); ++itr) {
    DCHECK(!IsGpuResourceType(itr->second.type));
  }
#endif  // DCHECK_IS_ON()

  texture_id_allocator_ = nullptr;
  gl->Finish();
}

bool ResourceProvider::IsTextureFormatSupported(
    viz::ResourceFormat format) const {
  gpu::Capabilities caps;
  if (compositor_context_provider_)
    caps = compositor_context_provider_->ContextCapabilities();

  switch (format) {
    case viz::ALPHA_8:
    case viz::RGBA_4444:
    case viz::RGBA_8888:
    case viz::RGB_565:
    case viz::LUMINANCE_8:
      return true;
    case viz::BGRA_8888:
      return caps.texture_format_bgra8888;
    case viz::ETC1:
      return caps.texture_format_etc1;
    case viz::RED_8:
      return caps.texture_rg;
    case viz::LUMINANCE_F16:
    case viz::RGBA_F16:
      return caps.texture_half_float_linear;
  }

  NOTREACHED();
  return false;
}

bool ResourceProvider::IsRenderBufferFormatSupported(
    viz::ResourceFormat format) const {
  gpu::Capabilities caps;
  if (compositor_context_provider_)
    caps = compositor_context_provider_->ContextCapabilities();

  switch (format) {
    case viz::RGBA_4444:
    case viz::RGBA_8888:
    case viz::RGB_565:
      return true;
    case viz::BGRA_8888:
      return caps.render_buffer_format_bgra8888;
    case viz::RGBA_F16:
      // TODO(ccameron): This will always return false on pixel tests, which
      // makes it un-test-able until we upgrade Mesa.
      // https://crbug.com/687720
      return caps.texture_half_float_linear &&
             caps.color_buffer_half_float_rgba;
    case viz::LUMINANCE_8:
    case viz::ALPHA_8:
    case viz::RED_8:
    case viz::ETC1:
    case viz::LUMINANCE_F16:
      // We don't currently render into these formats. If we need to render into
      // these eventually, we should expand this logic.
      return false;
  }

  NOTREACHED();
  return false;
}

bool ResourceProvider::InUseByConsumer(viz::ResourceId id) {
  Resource* resource = GetResource(id);
  return resource->lock_for_read_count > 0 || resource->exported_count > 0 ||
         resource->lost;
}

bool ResourceProvider::IsLost(viz::ResourceId id) {
  Resource* resource = GetResource(id);
  return resource->lost;
}

void ResourceProvider::LoseResourceForTesting(viz::ResourceId id) {
  Resource* resource = GetResource(id);
  DCHECK(resource);
  resource->lost = true;
}

viz::ResourceFormat ResourceProvider::YuvResourceFormat(int bits) const {
  if (bits > 8) {
    return settings_.yuv_highbit_resource_format;
  } else {
    return settings_.yuv_resource_format;
  }
}

viz::ResourceId ResourceProvider::CreateResource(
    const gfx::Size& size,
    TextureHint hint,
    viz::ResourceFormat format,
    const gfx::ColorSpace& color_space) {
  DCHECK(!size.IsEmpty());
  switch (settings_.default_resource_type) {
    case RESOURCE_TYPE_GPU_MEMORY_BUFFER:
      // GPU memory buffers don't support viz::LUMINANCE_F16 yet.
      if (format != viz::LUMINANCE_F16) {
        return CreateGpuResource(
            size, hint, RESOURCE_TYPE_GPU_MEMORY_BUFFER, format,
            gfx::BufferUsage::GPU_READ_CPU_READ_WRITE, color_space);
      }
    // Fall through and use a regular texture.
    case RESOURCE_TYPE_GL_TEXTURE:
      return CreateGpuResource(size, hint, RESOURCE_TYPE_GL_TEXTURE, format,
                               gfx::BufferUsage::GPU_READ_CPU_READ_WRITE,
                               color_space);

    case RESOURCE_TYPE_BITMAP:
      DCHECK_EQ(viz::RGBA_8888, format);
      return CreateBitmapResource(size, color_space);
  }

  LOG(FATAL) << "Invalid default resource type.";
  return 0;
}

viz::ResourceId ResourceProvider::CreateGpuMemoryBufferResource(
    const gfx::Size& size,
    TextureHint hint,
    viz::ResourceFormat format,
    gfx::BufferUsage usage,
    const gfx::ColorSpace& color_space) {
  DCHECK(!size.IsEmpty());
  switch (settings_.default_resource_type) {
    case RESOURCE_TYPE_GPU_MEMORY_BUFFER:
    case RESOURCE_TYPE_GL_TEXTURE: {
      return CreateGpuResource(size, hint, RESOURCE_TYPE_GPU_MEMORY_BUFFER,
                               format, usage, color_space);
    }
    case RESOURCE_TYPE_BITMAP:
      DCHECK_EQ(viz::RGBA_8888, format);
      return CreateBitmapResource(size, color_space);
  }

  LOG(FATAL) << "Invalid default resource type.";
  return 0;
}

viz::ResourceId ResourceProvider::CreateGpuResource(
    const gfx::Size& size,
    TextureHint hint,
    ResourceType type,
    viz::ResourceFormat format,
    gfx::BufferUsage usage,
    const gfx::ColorSpace& color_space) {
  DCHECK_LE(size.width(), settings_.max_texture_size);
  DCHECK_LE(size.height(), settings_.max_texture_size);
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  // TODO(crbug.com/590317): We should not assume that all resources created by
  // ResourceProvider are GPU_READ_CPU_READ_WRITE. We should determine this
  // based on the current RasterBufferProvider's needs.
  GLenum target = type == RESOURCE_TYPE_GPU_MEMORY_BUFFER
                      ? GetImageTextureTarget(usage, format)
                      : GL_TEXTURE_2D;

  viz::ResourceId id = next_id_++;
  Resource* resource =
      InsertResource(id, Resource(0, size, Resource::INTERNAL, target,
                                  GL_LINEAR, hint, type, format));
  resource->usage = usage;
  resource->allocated = false;
  resource->color_space = color_space;
  return id;
}

viz::ResourceId ResourceProvider::CreateBitmapResource(
    const gfx::Size& size,
    const gfx::ColorSpace& color_space) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  std::unique_ptr<viz::SharedBitmap> bitmap =
      shared_bitmap_manager_->AllocateSharedBitmap(size);
  uint8_t* pixels = bitmap->pixels();
  DCHECK(pixels);

  viz::ResourceId id = next_id_++;
  Resource* resource = InsertResource(
      id,
      Resource(pixels, bitmap.release(), size, Resource::INTERNAL, GL_LINEAR));
  resource->allocated = true;
  resource->color_space = color_space;
  return id;
}

viz::ResourceId ResourceProvider::CreateResourceFromTextureMailbox(
    const viz::TextureMailbox& mailbox,
    std::unique_ptr<SingleReleaseCallbackImpl> release_callback_impl,
    bool read_lock_fences_enabled,
    gfx::BufferFormat buffer_format) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  // Just store the information. Mailbox will be consumed in LockForRead().
  viz::ResourceId id = next_id_++;
  DCHECK(mailbox.IsValid());
  Resource* resource = nullptr;
  if (mailbox.IsTexture()) {
    resource = InsertResource(
        id, Resource(0, mailbox.size_in_pixels(), Resource::EXTERNAL,
                     mailbox.target(),
                     mailbox.nearest_neighbor() ? GL_NEAREST : GL_LINEAR,
                     TEXTURE_HINT_IMMUTABLE, RESOURCE_TYPE_GL_TEXTURE,
                     viz::RGBA_8888));
  } else {
    DCHECK(mailbox.IsSharedMemory());
    viz::SharedBitmap* shared_bitmap = mailbox.shared_bitmap();
    uint8_t* pixels = shared_bitmap->pixels();
    DCHECK(pixels);
    resource = InsertResource(
        id, Resource(pixels, shared_bitmap, mailbox.size_in_pixels(),
                     Resource::EXTERNAL, GL_LINEAR));
  }
  resource->allocated = true;
  resource->SetMailbox(mailbox);
  resource->color_space = mailbox.color_space();
  resource->release_callback_impl =
      base::Bind(&SingleReleaseCallbackImpl::Run,
                 base::Owned(release_callback_impl.release()));
  resource->read_lock_fences_enabled = read_lock_fences_enabled;
  resource->buffer_format = buffer_format;
  resource->is_overlay_candidate = mailbox.is_overlay_candidate();
#if defined(OS_ANDROID)
  resource->is_backed_by_surface_texture =
      mailbox.is_backed_by_surface_texture();
  resource->wants_promotion_hint = mailbox.wants_promotion_hint();
  if (resource->wants_promotion_hint)
    wants_promotion_hints_set_.insert(id);
#endif
  resource->color_space = mailbox.color_space();

  return id;
}

viz::ResourceId ResourceProvider::CreateResourceFromTextureMailbox(
    const viz::TextureMailbox& mailbox,
    std::unique_ptr<SingleReleaseCallbackImpl> release_callback_impl,
    bool read_lock_fences_enabled) {
  return CreateResourceFromTextureMailbox(
      mailbox, std::move(release_callback_impl), read_lock_fences_enabled,
      gfx::BufferFormat::RGBA_8888);
}

viz::ResourceId ResourceProvider::CreateResourceFromTextureMailbox(
    const viz::TextureMailbox& mailbox,
    std::unique_ptr<SingleReleaseCallbackImpl> release_callback_impl) {
  return CreateResourceFromTextureMailbox(
      mailbox, std::move(release_callback_impl), false);
}

void ResourceProvider::DeleteResource(viz::ResourceId id) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  ResourceMap::iterator it = resources_.find(id);
  CHECK(it != resources_.end());
  Resource* resource = &it->second;
  DCHECK(!resource->marked_for_deletion);
  DCHECK_EQ(resource->imported_count, 0);
  DCHECK(!resource->locked_for_write);

  if (resource->exported_count > 0 || resource->lock_for_read_count > 0 ||
      !ReadLockFenceHasPassed(resource)) {
    resource->marked_for_deletion = true;
    return;
  } else {
    DeleteResourceInternal(it, NORMAL);
  }
}

void ResourceProvider::DeleteResourceInternal(ResourceMap::iterator it,
                                              DeleteStyle style) {
  TRACE_EVENT0("cc", "ResourceProvider::DeleteResourceInternal");
  Resource* resource = &it->second;
  DCHECK(resource->exported_count == 0 || style != NORMAL);

#if defined(OS_ANDROID)
  // If this resource was interested in promotion hints, then remove it from
  // the set of resources that we'll notify.
  if (resource->wants_promotion_hint)
    wants_promotion_hints_set_.erase(it->first);
#endif

  // Exported resources are lost on shutdown.
  bool exported_resource_lost =
      style == FOR_SHUTDOWN && resource->exported_count > 0;
  // GPU resources are lost when context is lost.
  bool gpu_resource_lost =
      IsGpuResourceType(resource->type) && lost_context_provider_;
  bool lost_resource =
      resource->lost || exported_resource_lost || gpu_resource_lost;

  // Wait on sync token before deleting resources we own.
  if (!lost_resource && resource->origin == Resource::INTERNAL)
    resource->WaitSyncToken(ContextGL());

  if (resource->image_id) {
    DCHECK(resource->origin == Resource::INTERNAL);
    GLES2Interface* gl = ContextGL();
    DCHECK(gl);
    gl->DestroyImageCHROMIUM(resource->image_id);
  }

  if (resource->origin == Resource::EXTERNAL) {
    DCHECK(resource->mailbox().IsValid());
    gpu::SyncToken sync_token = resource->mailbox().sync_token();
    if (IsGpuResourceType(resource->type)) {
      DCHECK(resource->mailbox().IsTexture());
      GLES2Interface* gl = ContextGL();
      DCHECK(gl);
      if (resource->gl_id) {
        DCHECK_NE(Resource::NEEDS_WAIT, resource->synchronization_state());
        gl->DeleteTextures(1, &resource->gl_id);
        resource->gl_id = 0;
        if (!lost_resource) {
          const GLuint64 fence_sync = gl->InsertFenceSyncCHROMIUM();
          gl->ShallowFlushCHROMIUM();
          gl->GenSyncTokenCHROMIUM(fence_sync, sync_token.GetData());
        }
      }
    } else {
      DCHECK(resource->mailbox().IsSharedMemory());
      resource->shared_bitmap = nullptr;
      resource->pixels = nullptr;
    }
    resource->release_callback_impl.Run(sync_token, lost_resource,
                                        blocking_main_thread_task_runner_);
  }

  if (resource->gl_id) {
    GLES2Interface* gl = ContextGL();
    DCHECK(gl);
    gl->DeleteTextures(1, &resource->gl_id);
    resource->gl_id = 0;
  }
  if (resource->shared_bitmap) {
    DCHECK(resource->origin != Resource::EXTERNAL);
    DCHECK_EQ(RESOURCE_TYPE_BITMAP, resource->type);
    delete resource->shared_bitmap;
    resource->pixels = nullptr;
  }
  if (resource->pixels) {
    DCHECK(resource->origin == Resource::INTERNAL);
    delete[] resource->pixels;
    resource->pixels = nullptr;
  }
  if (resource->gpu_memory_buffer) {
    DCHECK(resource->origin == Resource::INTERNAL ||
           resource->origin == Resource::DELEGATED);
    resource->gpu_memory_buffer.reset();
  }
  resources_.erase(it);
}

void ResourceProvider::FlushPendingDeletions() const {
  if (auto* gl = ContextGL())
    gl->ShallowFlushCHROMIUM();
}

ResourceProvider::ResourceType ResourceProvider::GetResourceType(
    viz::ResourceId id) {
  return GetResource(id)->type;
}

GLenum ResourceProvider::GetResourceTextureTarget(viz::ResourceId id) {
  return GetResource(id)->target;
}

bool ResourceProvider::IsImmutable(viz::ResourceId id) {
  if (IsGpuResourceType(settings_.default_resource_type)) {
    return GetTextureHint(id) == TEXTURE_HINT_IMMUTABLE;
  } else {
    // Software resources are immutable; they cannot change format or be
    // resized.
    return true;
  }
}

ResourceProvider::TextureHint ResourceProvider::GetTextureHint(
    viz::ResourceId id) {
  return GetResource(id)->hint;
}

gfx::ColorSpace ResourceProvider::GetResourceColorSpaceForRaster(
    const Resource* resource) const {
  if (!settings_.enable_color_correct_rasterization)
    return gfx::ColorSpace();
  return resource->color_space;
}

void ResourceProvider::CopyToResource(viz::ResourceId id,
                                      const uint8_t* image,
                                      const gfx::Size& image_size) {
  Resource* resource = GetResource(id);
  DCHECK(!resource->locked_for_write);
  DCHECK(!resource->lock_for_read_count);
  DCHECK_EQ(resource->origin, Resource::INTERNAL);
  DCHECK_NE(resource->synchronization_state(), Resource::NEEDS_WAIT);
  DCHECK_EQ(resource->exported_count, 0);
  DCHECK(ReadLockFenceHasPassed(resource));

  DCHECK_EQ(image_size.width(), resource->size.width());
  DCHECK_EQ(image_size.height(), resource->size.height());

  if (resource->type == RESOURCE_TYPE_BITMAP) {
    DCHECK_EQ(RESOURCE_TYPE_BITMAP, resource->type);
    DCHECK(resource->allocated);
    DCHECK_EQ(viz::RGBA_8888, resource->format);
    SkImageInfo source_info =
        SkImageInfo::MakeN32Premul(image_size.width(), image_size.height());
    size_t image_stride = image_size.width() * 4;

    ScopedWriteLockSoftware lock(this, id);
    SkCanvas dest(lock.sk_bitmap());
    dest.writePixels(source_info, image, image_stride, 0, 0);
  } else {
    // No sync token needed because the lock will set synchronization state to
    // LOCALLY_USED and a sync token will be generated in PrepareSendToParent.
    ScopedWriteLockGL lock(this, id);
    GLuint texture_id = lock.GetTexture();
    DCHECK(texture_id);
    GLES2Interface* gl = ContextGL();
    DCHECK(gl);
    gl->BindTexture(resource->target, texture_id);
    if (resource->format == viz::ETC1) {
      DCHECK_EQ(resource->target, static_cast<GLenum>(GL_TEXTURE_2D));
      int image_bytes =
          ResourceUtil::CheckedSizeInBytes<int>(image_size, viz::ETC1);
      gl->CompressedTexImage2D(resource->target, 0, GLInternalFormat(viz::ETC1),
                               image_size.width(), image_size.height(), 0,
                               image_bytes, image);
    } else {
      gl->TexSubImage2D(resource->target, 0, 0, 0, image_size.width(),
                        image_size.height(), GLDataFormat(resource->format),
                        GLDataType(resource->format), image);
    }
  }
}

ResourceProvider::Resource* ResourceProvider::InsertResource(
    viz::ResourceId id,
    Resource resource) {
  std::pair<ResourceMap::iterator, bool> result =
      resources_.insert(ResourceMap::value_type(id, std::move(resource)));
  DCHECK(result.second);
  return &result.first->second;
}

ResourceProvider::Resource* ResourceProvider::GetResource(viz::ResourceId id) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(id);
  ResourceMap::iterator it = resources_.find(id);
  DCHECK(it != resources_.end());
  return &it->second;
}

const ResourceProvider::Resource* ResourceProvider::LockForRead(
    viz::ResourceId id) {
  Resource* resource = GetResource(id);
  DCHECK(!resource->locked_for_write)
      << "locked for write: " << resource->locked_for_write;
  DCHECK_EQ(resource->exported_count, 0);
  // Uninitialized! Call SetPixels or LockForWrite first.
  DCHECK(resource->allocated);

  // Mailbox sync_tokens must be processed by a call to WaitSyncToken() prior to
  // calling LockForRead().
  DCHECK_NE(Resource::NEEDS_WAIT, resource->synchronization_state());

  if (IsGpuResourceType(resource->type) && !resource->gl_id) {
    DCHECK(resource->origin != Resource::INTERNAL);
    DCHECK(resource->mailbox().IsTexture());

    GLES2Interface* gl = ContextGL();
    DCHECK(gl);
    resource->gl_id = gl->CreateAndConsumeTextureCHROMIUM(
        resource->mailbox().target(), resource->mailbox().name());
    resource->SetLocallyUsed();
  }

  if (!resource->pixels && resource->has_shared_bitmap_id &&
      shared_bitmap_manager_) {
    std::unique_ptr<viz::SharedBitmap> bitmap =
        shared_bitmap_manager_->GetSharedBitmapFromId(
            resource->size, resource->shared_bitmap_id);
    if (bitmap) {
      resource->shared_bitmap = bitmap.release();
      resource->pixels = resource->shared_bitmap->pixels();
    }
  }

  resource->lock_for_read_count++;
  if (resource->read_lock_fences_enabled) {
    if (current_read_lock_fence_.get())
      current_read_lock_fence_->Set();
    resource->read_lock_fence = current_read_lock_fence_;
  }

  return resource;
}

void ResourceProvider::UnlockForRead(viz::ResourceId id) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  ResourceMap::iterator it = resources_.find(id);
  CHECK(it != resources_.end());

  Resource* resource = &it->second;
  DCHECK_GT(resource->lock_for_read_count, 0);
  DCHECK_EQ(resource->exported_count, 0);
  resource->lock_for_read_count--;
  if (resource->marked_for_deletion && !resource->lock_for_read_count) {
    if (!resource->child_id) {
      // The resource belongs to this ResourceProvider, so it can be destroyed.
      DeleteResourceInternal(it, NORMAL);
    } else {
      if (batch_return_resources_) {
        batched_returning_resources_[resource->child_id].push_back(id);
      } else {
        ChildMap::iterator child_it = children_.find(resource->child_id);
        ResourceIdArray unused;
        unused.push_back(id);
        DeleteAndReturnUnusedResourcesToChild(child_it, NORMAL, unused);
      }
    }
  }
}

ResourceProvider::Resource* ResourceProvider::LockForWrite(viz::ResourceId id) {
  DCHECK(CanLockForWrite(id));
  Resource* resource = GetResource(id);
  resource->WaitSyncToken(ContextGL());
  resource->SetLocallyUsed();
  resource->locked_for_write = true;
  return resource;
}

bool ResourceProvider::CanLockForWrite(viz::ResourceId id) {
  Resource* resource = GetResource(id);
  return !resource->locked_for_write && !resource->lock_for_read_count &&
         !resource->exported_count && resource->origin == Resource::INTERNAL &&
         !resource->lost && ReadLockFenceHasPassed(resource);
}

bool ResourceProvider::IsOverlayCandidate(viz::ResourceId id) {
  Resource* resource = GetResource(id);
  return resource->is_overlay_candidate;
}

gfx::BufferFormat ResourceProvider::GetBufferFormat(viz::ResourceId id) {
  Resource* resource = GetResource(id);
  return resource->buffer_format;
}

#if defined(OS_ANDROID)
bool ResourceProvider::IsBackedBySurfaceTexture(viz::ResourceId id) {
  Resource* resource = GetResource(id);
  return resource->is_backed_by_surface_texture;
}

bool ResourceProvider::WantsPromotionHint(viz::ResourceId id) {
  return wants_promotion_hints_set_.count(id) > 0;
}

size_t ResourceProvider::CountPromotionHintRequestsForTesting() {
  return wants_promotion_hints_set_.size();
}
#endif

void ResourceProvider::UnlockForWrite(Resource* resource) {
  DCHECK(resource->locked_for_write);
  DCHECK_EQ(resource->exported_count, 0);
  DCHECK(resource->origin == Resource::INTERNAL);
  resource->locked_for_write = false;
}

void ResourceProvider::EnableReadLockFencesForTesting(viz::ResourceId id) {
  Resource* resource = GetResource(id);
  DCHECK(resource);
  resource->read_lock_fences_enabled = true;
}

ResourceProvider::ScopedWriteLockGL::ScopedWriteLockGL(
    ResourceProvider* resource_provider,
    viz::ResourceId resource_id)
    : resource_provider_(resource_provider), resource_id_(resource_id) {
  Resource* resource = resource_provider->LockForWrite(resource_id);
  DCHECK(IsGpuResourceType(resource->type));
  resource_provider->CreateTexture(resource);
  type_ = resource->type;
  size_ = resource->size;
  format_ = resource->format;
  usage_ = resource->usage;
  color_space_ = resource_provider_->GetResourceColorSpaceForRaster(resource);
  texture_id_ = resource->gl_id;
  target_ = resource->target;
  hint_ = resource->hint;
  gpu_memory_buffer_ = std::move(resource->gpu_memory_buffer);
  image_id_ = resource->image_id;
  mailbox_ = resource->mailbox().mailbox();
  allocated_ = resource->allocated;
}

GrPixelConfig ResourceProvider::ScopedWriteLockGL::PixelConfig() const {
  return ToGrPixelConfig(format());
}

ResourceProvider::ScopedWriteLockGL::~ScopedWriteLockGL() {
  Resource* resource = resource_provider_->GetResource(resource_id_);
  DCHECK(resource->locked_for_write);
  resource->allocated = allocated_;
  if (gpu_memory_buffer_) {
    resource->gpu_memory_buffer = std::move(gpu_memory_buffer_);
    resource->allocated = true;
    resource->is_overlay_candidate = true;
    resource->buffer_format = resource->gpu_memory_buffer->GetFormat();
    // GpuMemoryBuffer provides direct access to the memory used by the GPU.
    // Read lock fences are required to ensure that we're not trying to map a
    // buffer that is currently in-use by the GPU.
    resource->read_lock_fences_enabled = true;
    resource->image_id = image_id_;
  }
  // Don't set empty sync token otherwise resource will be marked synchronized.
  if (has_sync_token_)
    resource->UpdateSyncToken(sync_token_);
  if (synchronized_)
    resource->SetSynchronized();
  resource_provider_->UnlockForWrite(resource);
}

GLuint ResourceProvider::ScopedWriteLockGL::GetTexture() {
  LazyAllocate(resource_provider_->ContextGL(), texture_id_);
  return texture_id_;
}

void ResourceProvider::ScopedWriteLockGL::CreateMailbox() {
  if (!mailbox_.IsZero())
    return;
  Resource* resource = resource_provider_->GetResource(resource_id_);
  resource_provider_->CreateMailbox(resource);
  mailbox_ = resource->mailbox().mailbox();
}

GLuint ResourceProvider::ScopedWriteLockGL::ConsumeTexture(
    gpu::gles2::GLES2Interface* gl) {
  DCHECK(gl);
  DCHECK(!mailbox_.IsZero());

  GLuint texture_id =
      gl->CreateAndConsumeTextureCHROMIUM(target_, mailbox_.name);
  DCHECK(texture_id);

  LazyAllocate(gl, texture_id);

  return texture_id;
}

void ResourceProvider::ScopedWriteLockGL::LazyAllocate(
    gpu::gles2::GLES2Interface* gl,
    GLuint texture_id) {
  if (allocated_)
    return;
  allocated_ = true;
  if (type_ == RESOURCE_TYPE_GPU_MEMORY_BUFFER) {
    AllocateGpuMemoryBuffer(gl, texture_id);
  } else {
    AllocateTexture(gl, texture_id);
  }
}

void ResourceProvider::ScopedWriteLockGL::AllocateGpuMemoryBuffer(
    gpu::gles2::GLES2Interface* gl,
    GLuint texture_id) {
  DCHECK(!gpu_memory_buffer_);
  DCHECK(!image_id_);

  gpu_memory_buffer_ =
      resource_provider_->gpu_memory_buffer_manager()->CreateGpuMemoryBuffer(
          size_, BufferFormat(format_), usage_, gpu::kNullSurfaceHandle);
  // Avoid crashing in release builds if GpuMemoryBuffer allocation fails.
  // http://crbug.com/554541
  if (!gpu_memory_buffer_)
    return;

  if (color_space_.IsValid())
    gpu_memory_buffer_->SetColorSpaceForScanout(color_space_);

#if defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
  // TODO(reveman): This avoids a performance problem on ARM ChromeOS
  // devices. This only works with shared memory backed buffers.
  // crbug.com/580166
  DCHECK_EQ(gpu_memory_buffer_->GetHandle().type, gfx::SHARED_MEMORY_BUFFER);
#endif

  image_id_ = gl->CreateImageCHROMIUM(gpu_memory_buffer_->AsClientBuffer(),
                                      size_.width(), size_.height(),
                                      GLInternalFormat(format_));
  DCHECK(image_id_ || gl->GetGraphicsResetStatusKHR() != GL_NO_ERROR);
  gl->BindTexture(target_, texture_id);
  gl->BindTexImage2DCHROMIUM(target_, image_id_);
}

void ResourceProvider::ScopedWriteLockGL::AllocateTexture(
    gpu::gles2::GLES2Interface* gl,
    GLuint texture_id) {
  DCHECK(gl);
  if (format_ == viz::ETC1)  // ETC1 does not support preallocation.
    return;
  gl->BindTexture(target_, texture_id);
  const ResourceProvider::Settings& settings = resource_provider_->settings_;
  if (settings.use_texture_storage_ext &&
      IsFormatSupportedForStorage(format_, settings.use_texture_format_bgra) &&
      (hint_ & ResourceProvider::TEXTURE_HINT_IMMUTABLE)) {
    GLenum storage_format = TextureToStorageFormat(format_);
    gl->TexStorage2DEXT(target_, 1, storage_format, size_.width(),
                        size_.height());
  } else {
    gl->TexImage2D(target_, 0, GLInternalFormat(format_), size_.width(),
                   size_.height(), 0, GLDataFormat(format_),
                   GLDataType(format_), nullptr);
  }
}

ResourceProvider::ScopedSkSurface::ScopedSkSurface(GrContext* gr_context,
                                                   GLuint texture_id,
                                                   GLenum texture_target,
                                                   const gfx::Size& size,
                                                   viz::ResourceFormat format,
                                                   bool use_distance_field_text,
                                                   bool can_use_lcd_text,
                                                   int msaa_sample_count) {
  GrGLTextureInfo texture_info;
  texture_info.fID = texture_id;
  texture_info.fTarget = texture_target;
  GrBackendTexture backend_texture(size.width(), size.height(),
                                   ToGrPixelConfig(format), texture_info);
  uint32_t flags =
      use_distance_field_text ? SkSurfaceProps::kUseDistanceFieldFonts_Flag : 0;
  // Use unknown pixel geometry to disable LCD text.
  SkSurfaceProps surface_props(flags, kUnknown_SkPixelGeometry);
  if (can_use_lcd_text) {
    // LegacyFontHost will get LCD text and skia figures out what type to use.
    surface_props =
        SkSurfaceProps(flags, SkSurfaceProps::kLegacyFontHost_InitType);
  }
  surface_ = SkSurface::MakeFromBackendTextureAsRenderTarget(
      gr_context, backend_texture, kTopLeft_GrSurfaceOrigin, msaa_sample_count,
      nullptr, &surface_props);
}

ResourceProvider::ScopedSkSurface::~ScopedSkSurface() {
  if (surface_)
    surface_->prepareForExternalIO();
}

void ResourceProvider::PopulateSkBitmapWithResource(SkBitmap* sk_bitmap,
                                                    const Resource* resource) {
  DCHECK_EQ(viz::RGBA_8888, resource->format);
  SkImageInfo info = SkImageInfo::MakeN32Premul(resource->size.width(),
                                                resource->size.height());
  sk_bitmap->installPixels(info, resource->pixels, info.minRowBytes());
}

ResourceProvider::ScopedWriteLockSoftware::ScopedWriteLockSoftware(
    ResourceProvider* resource_provider,
    viz::ResourceId resource_id)
    : resource_provider_(resource_provider), resource_id_(resource_id) {
  Resource* resource = resource_provider->LockForWrite(resource_id);
  resource_provider->PopulateSkBitmapWithResource(&sk_bitmap_, resource);
  color_space_ = resource_provider->GetResourceColorSpaceForRaster(resource);
  DCHECK(valid());
}

ResourceProvider::ScopedWriteLockSoftware::~ScopedWriteLockSoftware() {
  Resource* resource = resource_provider_->GetResource(resource_id_);
  resource->SetSynchronized();
  resource_provider_->UnlockForWrite(resource);
}
ResourceProvider::SynchronousFence::SynchronousFence(
    gpu::gles2::GLES2Interface* gl)
    : gl_(gl), has_synchronized_(true) {}

ResourceProvider::SynchronousFence::~SynchronousFence() {}

void ResourceProvider::SynchronousFence::Set() {
  has_synchronized_ = false;
}

bool ResourceProvider::SynchronousFence::HasPassed() {
  if (!has_synchronized_) {
    has_synchronized_ = true;
    Synchronize();
  }
  return true;
}

void ResourceProvider::SynchronousFence::Wait() {
  HasPassed();
}

void ResourceProvider::SynchronousFence::Synchronize() {
  TRACE_EVENT0("cc", "ResourceProvider::SynchronousFence::Synchronize");
  gl_->Finish();
}

void ResourceProvider::DestroyChildInternal(ChildMap::iterator it,
                                            DeleteStyle style) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  Child& child = it->second;
  DCHECK(style == FOR_SHUTDOWN || !child.marked_for_deletion);

  ResourceIdArray resources_for_child;

  for (ResourceIdMap::iterator child_it = child.child_to_parent_map.begin();
       child_it != child.child_to_parent_map.end(); ++child_it) {
    viz::ResourceId id = child_it->second;
    resources_for_child.push_back(id);
  }

  child.marked_for_deletion = true;

  DeleteAndReturnUnusedResourcesToChild(it, style, resources_for_child);
}

void ResourceProvider::DeleteAndReturnUnusedResourcesToChild(
    ChildMap::iterator child_it,
    DeleteStyle style,
    const ResourceIdArray& unused) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(child_it != children_.end());
  Child* child_info = &child_it->second;

  if (unused.empty() && !child_info->marked_for_deletion)
    return;

  std::vector<viz::ReturnedResource> to_return;
  to_return.reserve(unused.size());
  std::vector<viz::ReturnedResource*> need_synchronization_resources;
  std::vector<GLbyte*> unverified_sync_tokens;

  GLES2Interface* gl = ContextGL();

  for (viz::ResourceId local_id : unused) {
    ResourceMap::iterator it = resources_.find(local_id);
    CHECK(it != resources_.end());
    Resource& resource = it->second;

    DCHECK(!resource.locked_for_write);

    viz::ResourceId child_id = resource.id_in_child;
    DCHECK(child_info->child_to_parent_map.count(child_id));

    bool is_lost = resource.lost ||
                   (IsGpuResourceType(resource.type) && lost_context_provider_);
    if (resource.exported_count > 0 || resource.lock_for_read_count > 0) {
      if (style != FOR_SHUTDOWN) {
        // Defer this resource deletion.
        resource.marked_for_deletion = true;
        continue;
      }
      // We can't postpone the deletion, so we'll have to lose it.
      is_lost = true;
    } else if (!ReadLockFenceHasPassed(&resource)) {
      // TODO(dcastagna): see if it's possible to use this logic for
      // the branch above too, where the resource is locked or still exported.
      if (style != FOR_SHUTDOWN && !child_info->marked_for_deletion) {
        // Defer this resource deletion.
        resource.marked_for_deletion = true;
        continue;
      }
      // We can't postpone the deletion, so we'll have to lose it.
      is_lost = true;
    }

    if (IsGpuResourceType(resource.type) &&
        resource.filter != resource.original_filter) {
      DCHECK(resource.target);
      DCHECK(resource.gl_id);
      DCHECK(gl);
      gl->BindTexture(resource.target, resource.gl_id);
      gl->TexParameteri(resource.target, GL_TEXTURE_MIN_FILTER,
                        resource.original_filter);
      gl->TexParameteri(resource.target, GL_TEXTURE_MAG_FILTER,
                        resource.original_filter);
      resource.SetLocallyUsed();
    }

    viz::ReturnedResource returned;
    returned.id = child_id;
    returned.sync_token = resource.mailbox().sync_token();
    returned.count = resource.imported_count;
    returned.lost = is_lost;
    to_return.push_back(returned);

    if (IsGpuResourceType(resource.type) && child_info->needs_sync_tokens) {
      if (resource.needs_sync_token()) {
        need_synchronization_resources.push_back(&to_return.back());
      } else if (returned.sync_token.HasData() &&
                 !returned.sync_token.verified_flush()) {
        // Before returning any sync tokens, they must be verified.
        unverified_sync_tokens.push_back(returned.sync_token.GetData());
      }
    }

    child_info->child_to_parent_map.erase(child_id);
    resource.imported_count = 0;
    DeleteResourceInternal(it, style);
  }

  gpu::SyncToken new_sync_token;
  if (!need_synchronization_resources.empty()) {
    DCHECK(child_info->needs_sync_tokens);
    DCHECK(gl);
    const uint64_t fence_sync = gl->InsertFenceSyncCHROMIUM();
    gl->OrderingBarrierCHROMIUM();
    gl->GenUnverifiedSyncTokenCHROMIUM(fence_sync, new_sync_token.GetData());
    unverified_sync_tokens.push_back(new_sync_token.GetData());
  }

  if (!unverified_sync_tokens.empty()) {
    DCHECK(child_info->needs_sync_tokens);
    DCHECK(gl);
    gl->VerifySyncTokensCHROMIUM(unverified_sync_tokens.data(),
                                 unverified_sync_tokens.size());
  }

  // Set sync token after verification.
  for (viz::ReturnedResource* returned : need_synchronization_resources)
    returned->sync_token = new_sync_token;

  if (!to_return.empty())
    child_info->return_callback.Run(to_return,
                                    blocking_main_thread_task_runner_);

  if (child_info->marked_for_deletion &&
      child_info->child_to_parent_map.empty()) {
    children_.erase(child_it);
  }
}

GLenum ResourceProvider::BindForSampling(viz::ResourceId resource_id,
                                         GLenum unit,
                                         GLenum filter) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  GLES2Interface* gl = ContextGL();
  ResourceMap::iterator it = resources_.find(resource_id);
  DCHECK(it != resources_.end());
  Resource* resource = &it->second;
  DCHECK(resource->lock_for_read_count);
  DCHECK(!resource->locked_for_write);

  ScopedSetActiveTexture scoped_active_tex(gl, unit);
  GLenum target = resource->target;
  gl->BindTexture(target, resource->gl_id);
  if (filter != resource->filter) {
    gl->TexParameteri(target, GL_TEXTURE_MIN_FILTER, filter);
    gl->TexParameteri(target, GL_TEXTURE_MAG_FILTER, filter);
    resource->filter = filter;
  }

  return target;
}

void ResourceProvider::CreateForTesting(viz::ResourceId id) {
  CreateTexture(GetResource(id));
}

void ResourceProvider::CreateTexture(Resource* resource) {
  if (!IsGpuResourceType(resource->type))
    return;

  if (resource->gl_id)
    return;

  DCHECK_EQ(resource->origin, Resource::INTERNAL);
  DCHECK(!resource->mailbox().IsValid());

  resource->gl_id = texture_id_allocator_->NextId();
  DCHECK(resource->gl_id);

  GLES2Interface* gl = ContextGL();
  DCHECK(gl);

  // Create and set texture properties. Allocation is delayed until needed.
  gl->BindTexture(resource->target, resource->gl_id);
  gl->TexParameteri(resource->target, GL_TEXTURE_MIN_FILTER,
                    resource->original_filter);
  gl->TexParameteri(resource->target, GL_TEXTURE_MAG_FILTER,
                    resource->original_filter);
  gl->TexParameteri(resource->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  gl->TexParameteri(resource->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  if (settings_.use_texture_usage_hint &&
      (resource->hint & TEXTURE_HINT_FRAMEBUFFER)) {
    gl->TexParameteri(resource->target, GL_TEXTURE_USAGE_ANGLE,
                      GL_FRAMEBUFFER_ATTACHMENT_ANGLE);
  }
}

void ResourceProvider::CreateMailbox(Resource* resource) {
  if (!IsGpuResourceType(resource->type))
    return;

  if (resource->mailbox().IsValid())
    return;

  CreateTexture(resource);

  DCHECK(resource->gl_id);
  DCHECK_EQ(resource->origin, Resource::INTERNAL);

  gpu::gles2::GLES2Interface* gl = ContextGL();
  DCHECK(gl);

  gpu::MailboxHolder mailbox_holder;
  mailbox_holder.texture_target = resource->target;
  gl->GenMailboxCHROMIUM(mailbox_holder.mailbox.name);
  gl->ProduceTextureDirectCHROMIUM(resource->gl_id,
                                   mailbox_holder.texture_target,
                                   mailbox_holder.mailbox.name);
  resource->SetMailbox(viz::TextureMailbox(mailbox_holder));
  resource->SetLocallyUsed();
}

void ResourceProvider::AllocateForTesting(viz::ResourceId id) {
  Resource* resource = GetResource(id);
  if (!resource->allocated) {
    // Software and external resources are marked allocated on creation.
    DCHECK(IsGpuResourceType(resource->type));
    DCHECK_EQ(resource->origin, Resource::INTERNAL);
    ScopedWriteLockGL resource_lock(this, id);
    resource_lock.GetTexture();  // Allocates texture.
  }
}

void ResourceProvider::CreateAndBindImage(Resource* resource) {
  DCHECK(resource->gpu_memory_buffer);
#if defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
  // TODO(reveman): This avoids a performance problem on ARM ChromeOS
  // devices. This only works with shared memory backed buffers.
  // crbug.com/580166
  DCHECK_EQ(resource->gpu_memory_buffer->GetHandle().type,
            gfx::SHARED_MEMORY_BUFFER);
#endif
  CreateTexture(resource);

  gpu::gles2::GLES2Interface* gl = ContextGL();
  DCHECK(gl);

  if (!resource->image_id) {
    resource->image_id = gl->CreateImageCHROMIUM(
        resource->gpu_memory_buffer->AsClientBuffer(), resource->size.width(),
        resource->size.height(), GLInternalFormat(resource->format));
    DCHECK(resource->image_id ||
           gl->GetGraphicsResetStatusKHR() != GL_NO_ERROR);
    gl->BindTexture(resource->target, resource->gl_id);
    gl->BindTexImage2DCHROMIUM(resource->target, resource->image_id);
  } else {
    gl->BindTexture(resource->target, resource->gl_id);
    gl->ReleaseTexImage2DCHROMIUM(resource->target, resource->image_id);
    gl->BindTexImage2DCHROMIUM(resource->target, resource->image_id);
  }
}

void ResourceProvider::WaitSyncToken(viz::ResourceId id) {
  GetResource(id)->WaitSyncToken(ContextGL());
}

GLint ResourceProvider::GetActiveTextureUnit(gpu::gles2::GLES2Interface* gl) {
  GLint active_unit = 0;
  gl->GetIntegerv(GL_ACTIVE_TEXTURE, &active_unit);
  return active_unit;
}

gpu::SyncToken ResourceProvider::GenerateSyncTokenHelper(
    gpu::gles2::GLES2Interface* gl) {
  DCHECK(gl);
  const uint64_t fence_sync = gl->InsertFenceSyncCHROMIUM();

  // Barrier to sync worker context output to cc context.
  gl->OrderingBarrierCHROMIUM();

  // Generate sync token after the barrier for cross context synchronization.
  gpu::SyncToken sync_token;
  gl->GenUnverifiedSyncTokenCHROMIUM(fence_sync, sync_token.GetData());

  DCHECK(sync_token.HasData() ||
         gl->GetGraphicsResetStatusKHR() != GL_NO_ERROR);

  return sync_token;
}

GLenum ResourceProvider::GetImageTextureTarget(gfx::BufferUsage usage,
                                               viz::ResourceFormat format) {
  gfx::BufferFormat buffer_format = BufferFormat(format);
  auto found = buffer_to_texture_target_map_.find(
      viz::BufferToTextureTargetKey(usage, buffer_format));
  DCHECK(found != buffer_to_texture_target_map_.end());
  return found->second;
}

void ResourceProvider::ValidateResource(viz::ResourceId id) const {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(id);
  DCHECK(resources_.find(id) != resources_.end());
}

GLES2Interface* ResourceProvider::ContextGL() const {
  viz::ContextProvider* context_provider = compositor_context_provider_;
  return context_provider ? context_provider->ContextGL() : nullptr;
}

bool ResourceProvider::IsGLContextLost() const {
  return ContextGL()->GetGraphicsResetStatusKHR() != GL_NO_ERROR;
}

bool ResourceProvider::OnMemoryDump(
    const base::trace_event::MemoryDumpArgs& args,
    base::trace_event::ProcessMemoryDump* pmd) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  const uint64_t tracing_process_id =
      base::trace_event::MemoryDumpManager::GetInstance()
          ->GetTracingProcessId();

  for (const auto& resource_entry : resources_) {
    const auto& resource = resource_entry.second;

    bool backing_memory_allocated = false;
    switch (resource.type) {
      case RESOURCE_TYPE_GPU_MEMORY_BUFFER:
        backing_memory_allocated = !!resource.gpu_memory_buffer;
        break;
      case RESOURCE_TYPE_GL_TEXTURE:
        backing_memory_allocated = !!resource.gl_id;
        break;
      case RESOURCE_TYPE_BITMAP:
        backing_memory_allocated = resource.has_shared_bitmap_id;
        break;
    }

    if (!backing_memory_allocated) {
      // Don't log unallocated resources - they have no backing memory.
      continue;
    }

    // Resource IDs are not process-unique, so log with the ResourceProvider's
    // unique id.
    std::string dump_name =
        base::StringPrintf("cc/resource_memory/provider_%d/resource_%d",
                           tracing_id_, resource_entry.first);
    base::trace_event::MemoryAllocatorDump* dump =
        pmd->CreateAllocatorDump(dump_name);

    uint64_t total_bytes = ResourceUtil::UncheckedSizeInBytesAligned<size_t>(
        resource.size, resource.format);
    dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
                    base::trace_event::MemoryAllocatorDump::kUnitsBytes,
                    static_cast<uint64_t>(total_bytes));

    // Resources may be shared across processes and require a shared GUID to
    // prevent double counting the memory.
    base::trace_event::MemoryAllocatorDumpGuid guid;
    base::UnguessableToken shared_memory_guid;
    switch (resource.type) {
      case RESOURCE_TYPE_GPU_MEMORY_BUFFER:
        guid =
            resource.gpu_memory_buffer->GetGUIDForTracing(tracing_process_id);
        shared_memory_guid =
            resource.gpu_memory_buffer->GetHandle().handle.GetGUID();
        break;
      case RESOURCE_TYPE_GL_TEXTURE:
        DCHECK(resource.gl_id);
        guid = gl::GetGLTextureClientGUIDForTracing(
            compositor_context_provider_->ContextSupport()
                ->ShareGroupTracingGUID(),
            resource.gl_id);
        break;
      case RESOURCE_TYPE_BITMAP:
        DCHECK(resource.has_shared_bitmap_id);
        guid = viz::GetSharedBitmapGUIDForTracing(resource.shared_bitmap_id);
        if (resource.shared_bitmap) {
          shared_memory_guid =
              resource.shared_bitmap->GetSharedMemoryHandle().GetGUID();
        }
        break;
    }

    DCHECK(!guid.empty());

    const int kImportance = 2;
    if (!shared_memory_guid.is_empty()) {
      pmd->CreateSharedMemoryOwnershipEdge(dump->guid(), shared_memory_guid,
                                           kImportance);
    } else {
      pmd->CreateSharedGlobalAllocatorDump(guid);
      pmd->AddOwnershipEdge(dump->guid(), guid, kImportance);
    }
  }

  return true;
}

}  // namespace cc
