// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "cc/resources/display_resource_provider.h"

#include "base/trace_event/trace_event.h"
#include "components/viz/common/gpu/context_provider.h"
#include "components/viz/common/resources/resource_format_utils.h"
#include "components/viz/common/resources/shared_bitmap_manager.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "third_party/skia/include/gpu/GrBackendSurface.h"

using gpu::gles2::GLES2Interface;

namespace cc {

class ScopedSetActiveTexture {
 public:
  ScopedSetActiveTexture(GLES2Interface* gl, GLenum unit)
      : gl_(gl), unit_(unit) {
    DCHECK_EQ(GL_TEXTURE0, DisplayResourceProvider::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_;
};

namespace {
// The resource id in DisplayResourceProvider starts from 2 to avoid
// conflicts with id from LayerTreeResourceProvider.
const unsigned int kDisplayInitialResourceId = 2;
}  // namespace

DisplayResourceProvider::DisplayResourceProvider(
    viz::ContextProvider* compositor_context_provider,
    viz::SharedBitmapManager* shared_bitmap_manager)
    : ResourceProvider(compositor_context_provider),
      next_id_(kDisplayInitialResourceId),
      shared_bitmap_manager_(shared_bitmap_manager) {}

DisplayResourceProvider::~DisplayResourceProvider() {
  while (!children_.empty())
    DestroyChildInternal(children_.begin(), FOR_SHUTDOWN);

  GLES2Interface* gl = ContextGL();
  if (gl)
    gl->Finish();
}

#if defined(OS_ANDROID)
void DisplayResourceProvider::SendPromotionHints(
    const OverlayCandidateList::PromotionHintInfoMap& promotion_hints) {
  GLES2Interface* gl = ContextGL();
  if (!gl)
    return;

  for (const auto& id : wants_promotion_hints_set_) {
    const ResourceMap::iterator it = resources_.find(id);
    if (it == resources_.end())
      continue;

    if (it->second.marked_for_deletion)
      continue;

    const viz::internal::Resource* resource = LockForRead(id);
    DCHECK(resource->wants_promotion_hint);

    // Insist that this is backed by a GPU texture.
    if (resource->is_gpu_resource_type()) {
      DCHECK(resource->gl_id);
      auto iter = promotion_hints.find(id);
      bool promotable = iter != promotion_hints.end();
      gl->OverlayPromotionHintCHROMIUM(resource->gl_id, promotable,
                                       promotable ? iter->second.x() : 0,
                                       promotable ? iter->second.y() : 0,
                                       promotable ? iter->second.width() : 0,
                                       promotable ? iter->second.height() : 0);
    }
    UnlockForRead(id);
  }
}

bool DisplayResourceProvider::IsBackedBySurfaceTexture(viz::ResourceId id) {
  viz::internal::Resource* resource = GetResource(id);
  return resource->is_backed_by_surface_texture;
}

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

size_t DisplayResourceProvider::CountPromotionHintRequestsForTesting() {
  return wants_promotion_hints_set_.size();
}

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

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

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

void DisplayResourceProvider::WaitSyncToken(viz::ResourceId id) {
  viz::internal::Resource* resource = GetResource(id);
  WaitSyncTokenInternal(resource);
#if defined(OS_ANDROID)
  // Now that the resource is synced, we may send it a promotion hint.  We could
  // sync all |wants_promotion_hint| resources elsewhere, and send 'no' to all
  // resources that weren't used.  However, there's no real advantage.
  if (resource->wants_promotion_hint)
    wants_promotion_hints_set_.insert(id);
#endif  // OS_ANDROID
}

DisplayResourceProvider::ScopedBatchReturnResources::ScopedBatchReturnResources(
    DisplayResourceProvider* resource_provider)
    : resource_provider_(resource_provider) {
  resource_provider_->SetBatchReturnResources(true);
}

DisplayResourceProvider::ScopedBatchReturnResources::
    ~ScopedBatchReturnResources() {
  resource_provider_->SetBatchReturnResources(false);
}

void DisplayResourceProvider::SetBatchReturnResources(bool batch) {
  DCHECK_NE(batch_return_resources_, batch);
  batch_return_resources_ = batch;
  if (!batch) {
    for (const auto& resources : batched_returning_resources_) {
      ChildMap::iterator child_it = children_.find(resources.first);
      DCHECK(child_it != children_.end());
      DeleteAndReturnUnusedResourcesToChild(child_it, NORMAL, resources.second);
    }
    batched_returning_resources_.clear();
  }
}

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

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

DisplayResourceProvider::Child::~Child() = default;

int DisplayResourceProvider::CreateChild(
    const ReturnCallback& return_callback) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  Child child_info;
  child_info.return_callback = return_callback;

  int child = next_child_++;
  children_[child] = child_info;
  return child;
}

void DisplayResourceProvider::SetChildNeedsSyncTokens(int child_id,
                                                      bool needs) {
  ChildMap::iterator it = children_.find(child_id);
  DCHECK(it != children_.end());
  it->second.needs_sync_tokens = needs;
}

void DisplayResourceProvider::DestroyChild(int child_id) {
  ChildMap::iterator it = children_.find(child_id);
  DCHECK(it != children_.end());
  DestroyChildInternal(it, NORMAL);
}

void DisplayResourceProvider::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 DisplayResourceProvider::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;
  std::vector<size_t> to_return_indices_unverified;

  GLES2Interface* gl = ContextGL();

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

    // TODO(xing.xu): remove locked_for_write.
    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 ||
                   (resource.is_gpu_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 (resource.is_gpu_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.sync_token();
    returned.count = resource.imported_count;
    returned.lost = is_lost;
    to_return.push_back(returned);

    if (resource.is_gpu_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. Store an
        // index into |to_return| instead of a pointer as vectors may realloc
        // and move their data.
        to_return_indices_unverified.push_back(to_return.size() - 1);
      }
    }

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

  for (size_t i : to_return_indices_unverified)
    unverified_sync_tokens.push_back(to_return[i].sync_token.GetData());

  gpu::SyncToken new_sync_token;
  if (!need_synchronization_resources.empty()) {
    DCHECK(child_info->needs_sync_tokens);
    DCHECK(gl);
    gl->GenUnverifiedSyncTokenCHROMIUM(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);

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

void DisplayResourceProvider::ReceiveFromChild(
    int child,
    const std::vector<viz::TransferableResource>& resources) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  GLES2Interface* gl = ContextGL();
  Child& child_info = children_.find(child)->second;
  DCHECK(!child_info.marked_for_deletion);
  for (std::vector<viz::TransferableResource>::const_iterator it =
           resources.begin();
       it != resources.end(); ++it) {
    ResourceIdMap::iterator resource_in_map_it =
        child_info.child_to_parent_map.find(it->id);
    if (resource_in_map_it != child_info.child_to_parent_map.end()) {
      viz::internal::Resource* resource =
          GetResource(resource_in_map_it->second);
      resource->marked_for_deletion = false;
      resource->imported_count++;
      continue;
    }

    if ((!it->is_software && !gl) ||
        (it->is_software && !shared_bitmap_manager_)) {
      TRACE_EVENT0(
          "cc", "DisplayResourceProvider::ReceiveFromChild dropping invalid");
      std::vector<viz::ReturnedResource> to_return;
      to_return.push_back(it->ToReturnedResource());
      child_info.return_callback.Run(to_return);
      continue;
    }

    viz::ResourceId local_id = next_id_++;
    viz::internal::Resource* resource = nullptr;
    if (it->is_software) {
      resource = InsertResource(
          local_id,
          viz::internal::Resource(it->size, viz::internal::Resource::DELEGATED,
                                  viz::ResourceTextureHint::kDefault,
                                  viz::ResourceType::kBitmap, viz::RGBA_8888,
                                  it->color_space));
      resource->has_shared_bitmap_id = true;
      resource->shared_bitmap_id = it->mailbox_holder.mailbox;
    } else {
      resource = InsertResource(
          local_id,
          viz::internal::Resource(it->size, viz::internal::Resource::DELEGATED,
                                  viz::ResourceTextureHint::kDefault,
                                  viz::ResourceType::kTexture, it->format,
                                  it->color_space));
      resource->target = it->mailbox_holder.texture_target;
      resource->filter = it->filter;
      resource->original_filter = it->filter;
      resource->min_filter = it->filter;
      resource->buffer_format = it->buffer_format;
      resource->mailbox = it->mailbox_holder.mailbox;
      resource->UpdateSyncToken(it->mailbox_holder.sync_token);
      resource->read_lock_fences_enabled = it->read_lock_fences_enabled;
      resource->is_overlay_candidate = it->is_overlay_candidate;
#if defined(OS_ANDROID)
      resource->is_backed_by_surface_texture = it->is_backed_by_surface_texture;
      resource->wants_promotion_hint = it->wants_promotion_hint;
#endif
    }
    resource->child_id = child;
    // Don't allocate a texture for a child.
    resource->allocated = true;
    resource->imported_count = 1;
    resource->id_in_child = it->id;
    child_info.child_to_parent_map[it->id] = local_id;
  }
}

void DisplayResourceProvider::DeclareUsedResourcesFromChild(
    int child,
    const viz::ResourceIdSet& resources_from_child) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  ChildMap::iterator child_it = children_.find(child);
  DCHECK(child_it != children_.end());
  Child& child_info = child_it->second;
  DCHECK(!child_info.marked_for_deletion);

  ResourceIdArray unused;
  for (ResourceIdMap::iterator it = child_info.child_to_parent_map.begin();
       it != child_info.child_to_parent_map.end(); ++it) {
    viz::ResourceId local_id = it->second;
    bool resource_is_in_use = resources_from_child.count(it->first) > 0;
    if (!resource_is_in_use)
      unused.push_back(local_id);
  }
  DeleteAndReturnUnusedResourcesToChild(child_it, NORMAL, unused);
}

const ResourceProvider::ResourceIdMap&
DisplayResourceProvider::GetChildToParentMap(int child) const {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  ChildMap::const_iterator it = children_.find(child);
  DCHECK(it != children_.end());
  DCHECK(!it->second.marked_for_deletion);
  return it->second.child_to_parent_map;
}

GLenum DisplayResourceProvider::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());
  viz::internal::Resource* resource = &it->second;
  DCHECK(resource->lock_for_read_count);
  // TODO(xing.xu): remove locked_for_write.
  DCHECK(!resource->locked_for_write);

  ScopedSetActiveTexture scoped_active_tex(gl, unit);
  GLenum target = resource->target;
  gl->BindTexture(target, resource->gl_id);
  GLenum min_filter = filter;
  if (filter == GL_LINEAR) {
    switch (resource->mipmap_state) {
      case viz::internal::Resource::INVALID:
        break;
      case viz::internal::Resource::GENERATE:
        DCHECK(compositor_context_provider_);
        DCHECK(
            compositor_context_provider_->ContextCapabilities().texture_npot);
        gl->GenerateMipmap(target);
        resource->mipmap_state = viz::internal::Resource::VALID;
      // fall-through
      case viz::internal::Resource::VALID:
        min_filter = GL_LINEAR_MIPMAP_LINEAR;
        break;
    }
  }
  if (min_filter != resource->min_filter) {
    gl->TexParameteri(target, GL_TEXTURE_MIN_FILTER, min_filter);
    resource->min_filter = min_filter;
  }
  if (filter != resource->filter) {
    gl->TexParameteri(target, GL_TEXTURE_MAG_FILTER, filter);
    resource->filter = filter;
  }

  return target;
}

bool DisplayResourceProvider::InUse(viz::ResourceId id) {
  viz::internal::Resource* resource = GetResource(id);
  return resource->lock_for_read_count > 0 || resource->lost;
}

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

DisplayResourceProvider::ScopedReadLockGL::ScopedReadLockGL(
    DisplayResourceProvider* resource_provider,
    viz::ResourceId resource_id)
    : resource_provider_(resource_provider), resource_id_(resource_id) {
  const viz::internal::Resource* resource =
      resource_provider->LockForRead(resource_id);
  texture_id_ = resource->gl_id;
  target_ = resource->target;
  size_ = resource->size;
  color_space_ = resource->color_space;
}

const viz::internal::Resource* DisplayResourceProvider::LockForRead(
    viz::ResourceId id) {
  viz::internal::Resource* resource = GetResource(id);
  // TODO(xing.xu): remove locked_for_write.
  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(viz::internal::Resource::NEEDS_WAIT,
            resource->synchronization_state());

  if (resource->is_gpu_resource_type() && !resource->gl_id) {
    DCHECK(resource->origin != viz::internal::Resource::INTERNAL);
    DCHECK(!resource->mailbox.IsZero());

    GLES2Interface* gl = ContextGL();
    DCHECK(gl);
    resource->gl_id =
        gl->CreateAndConsumeTextureCHROMIUM(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->SetSharedBitmap(bitmap.get());
      resource->owned_shared_bitmap = std::move(bitmap);
    }
  }

  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 DisplayResourceProvider::UnlockForRead(viz::ResourceId id) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  ResourceMap::iterator it = resources_.find(id);
  CHECK(it != resources_.end());

  viz::internal::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);
      }
    }
  }
}

bool DisplayResourceProvider::ReadLockFenceHasPassed(
    const viz::internal::Resource* resource) {
  return !resource->read_lock_fence || resource->read_lock_fence->HasPassed();
}

DisplayResourceProvider::ScopedReadLockGL::~ScopedReadLockGL() {
  resource_provider_->UnlockForRead(resource_id_);
}

DisplayResourceProvider::ScopedSamplerGL::ScopedSamplerGL(
    DisplayResourceProvider* resource_provider,
    viz::ResourceId resource_id,
    GLenum filter)
    : resource_lock_(resource_provider, resource_id),
      unit_(GL_TEXTURE0),
      target_(resource_provider->BindForSampling(resource_id, unit_, filter)) {}

DisplayResourceProvider::ScopedSamplerGL::ScopedSamplerGL(
    DisplayResourceProvider* resource_provider,
    viz::ResourceId resource_id,
    GLenum unit,
    GLenum filter)
    : resource_lock_(resource_provider, resource_id),
      unit_(unit),
      target_(resource_provider->BindForSampling(resource_id, unit_, filter)) {}

DisplayResourceProvider::ScopedSamplerGL::~ScopedSamplerGL() = default;

DisplayResourceProvider::ScopedReadLockSkImage::ScopedReadLockSkImage(
    DisplayResourceProvider* resource_provider,
    viz::ResourceId resource_id)
    : resource_provider_(resource_provider), resource_id_(resource_id) {
  const viz::internal::Resource* resource =
      resource_provider->LockForRead(resource_id);
  if (resource_provider_->resource_sk_image_.find(resource_id) !=
      resource_provider_->resource_sk_image_.end()) {
    // Use cached sk_image.
    sk_image_ =
        resource_provider_->resource_sk_image_.find(resource_id)->second;
  } else if (resource->gl_id) {
    GrGLTextureInfo texture_info;
    texture_info.fID = resource->gl_id;
    texture_info.fTarget = resource->target;
    GrBackendTexture backend_texture(
        resource->size.width(), resource->size.height(),
        ToGrPixelConfig(resource->format), texture_info);
    sk_image_ = SkImage::MakeFromTexture(
        resource_provider->compositor_context_provider_->GrContext(),
        backend_texture, kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType,
        nullptr);
  } else if (resource->pixels) {
    SkBitmap sk_bitmap;
    resource_provider->PopulateSkBitmapWithResource(&sk_bitmap, resource);
    sk_bitmap.setImmutable();
    sk_image_ = SkImage::MakeFromBitmap(sk_bitmap);
  } else {
    // During render process shutdown, ~RenderMessageFilter which calls
    // ~HostSharedBitmapClient (which deletes shared bitmaps from child)
    // can race with OnBeginFrameDeadline which draws a frame.
    // In these cases, shared bitmaps (and this read lock) won't be valid.
    // Renderers need to silently handle locks failing until this race
    // is fixed.  DCHECK that this is the only case where there are no pixels.
    DCHECK(!resource->shared_bitmap_id.IsZero());
  }
}

DisplayResourceProvider::ScopedReadLockSkImage::~ScopedReadLockSkImage() {
  resource_provider_->UnlockForRead(resource_id_);
}

DisplayResourceProvider::ScopedReadLockSoftware::ScopedReadLockSoftware(
    DisplayResourceProvider* resource_provider,
    viz::ResourceId resource_id)
    : resource_provider_(resource_provider), resource_id_(resource_id) {
  const viz::internal::Resource* resource =
      resource_provider->LockForRead(resource_id);
  resource_provider->PopulateSkBitmapWithResource(&sk_bitmap_, resource);
}

DisplayResourceProvider::ScopedReadLockSoftware::~ScopedReadLockSoftware() {
  resource_provider_->UnlockForRead(resource_id_);
}

DisplayResourceProvider::SynchronousFence::SynchronousFence(
    gpu::gles2::GLES2Interface* gl)
    : gl_(gl), has_synchronized_(true) {}

DisplayResourceProvider::SynchronousFence::~SynchronousFence() = default;

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

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

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

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

}  // namespace cc
