// 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/prioritized_resource.h"

#include <algorithm>

#include "cc/resources/platform_color.h"
#include "cc/resources/prioritized_resource_manager.h"
#include "cc/resources/priority_calculator.h"
#include "cc/trees/proxy.h"

namespace cc {

PrioritizedResource::PrioritizedResource(PrioritizedResourceManager* manager,
                                         gfx::Size size,
                                         GLenum format)
    : size_(size),
      format_(format),
      bytes_(0),
      contents_swizzled_(false),
      priority_(PriorityCalculator::LowestPriority()),
      is_above_priority_cutoff_(false),
      is_self_managed_(false),
      backing_(NULL),
      manager_(NULL) {
  // manager_ is set in RegisterTexture() so validity can be checked.
  DCHECK(format || size.IsEmpty());
  if (format)
    bytes_ = Resource::MemorySizeBytes(size, format);
  if (manager)
    manager->RegisterTexture(this);
}

PrioritizedResource::~PrioritizedResource() {
  if (manager_)
    manager_->UnregisterTexture(this);
}

void PrioritizedResource::SetTextureManager(
    PrioritizedResourceManager* manager) {
  if (manager_ == manager)
    return;
  if (manager_)
    manager_->UnregisterTexture(this);
  if (manager)
    manager->RegisterTexture(this);
}

void PrioritizedResource::SetDimensions(gfx::Size size, GLenum format) {
  if (format_ != format || size_ != size) {
    is_above_priority_cutoff_ = false;
    format_ = format;
    size_ = size;
    bytes_ = Resource::MemorySizeBytes(size, format);
    DCHECK(manager_ || !backing_);
    if (manager_)
      manager_->ReturnBackingTexture(this);
  }
}

bool PrioritizedResource::RequestLate() {
  if (!manager_)
    return false;
  return manager_->RequestLate(this);
}

bool PrioritizedResource::BackingResourceWasEvicted() const {
  return backing_ ? backing_->ResourceHasBeenDeleted() : false;
}

void PrioritizedResource::AcquireBackingTexture(
    ResourceProvider* resource_provider) {
  DCHECK(is_above_priority_cutoff_);
  if (is_above_priority_cutoff_)
    manager_->AcquireBackingTextureIfNeeded(this, resource_provider);
}

void PrioritizedResource::SetPixels(ResourceProvider* resource_provider,
                                    const uint8_t* image,
                                    gfx::Rect image_rect,
                                    gfx::Rect source_rect,
                                    gfx::Vector2d dest_offset) {
  DCHECK(is_above_priority_cutoff_);
  if (is_above_priority_cutoff_)
    AcquireBackingTexture(resource_provider);
  DCHECK(backing_);
  resource_provider->SetPixels(
      resource_id(), image, image_rect, source_rect, dest_offset);

  // The component order may be bgra if we uploaded bgra pixels to rgba
  // texture. Mark contents as swizzled if image component order is
  // different than texture format.
  contents_swizzled_ = !PlatformColor::SameComponentOrder(format_);
}

void PrioritizedResource::Link(Backing* backing) {
  DCHECK(backing);
  DCHECK(!backing->owner_);
  DCHECK(!backing_);

  backing_ = backing;
  backing_->owner_ = this;
}

void PrioritizedResource::Unlink() {
  DCHECK(backing_);
  DCHECK(backing_->owner_ == this);

  backing_->owner_ = NULL;
  backing_ = NULL;
}

void PrioritizedResource::SetToSelfManagedMemoryPlaceholder(size_t bytes) {
  SetDimensions(gfx::Size(), GL_RGBA);
  set_is_self_managed(true);
  bytes_ = bytes;
}

PrioritizedResource::Backing::Backing(unsigned id,
                                      ResourceProvider* resource_provider,
                                      gfx::Size size,
                                      GLenum format)
    : Resource(id, size, format),
      owner_(NULL),
      priority_at_last_priority_update_(PriorityCalculator::LowestPriority()),
      was_above_priority_cutoff_at_last_priority_update_(false),
      in_drawing_impl_tree_(false),
#ifdef NDEBUG
      resource_has_been_deleted_(false) {}
#else
      resource_has_been_deleted_(false),
      resource_provider_(resource_provider) {}
#endif

PrioritizedResource::Backing::~Backing() {
  DCHECK(!owner_);
  DCHECK(resource_has_been_deleted_);
}

void PrioritizedResource::Backing::DeleteResource(
    ResourceProvider* resource_provider) {
  DCHECK(!proxy() || proxy()->IsImplThread());
  DCHECK(!resource_has_been_deleted_);
#ifndef NDEBUG
  DCHECK(resource_provider == resource_provider_);
#endif

  resource_provider->DeleteResource(id());
  set_id(0);
  resource_has_been_deleted_ = true;
}

bool PrioritizedResource::Backing::ResourceHasBeenDeleted() const {
  DCHECK(!proxy() || proxy()->IsImplThread());
  return resource_has_been_deleted_;
}

bool PrioritizedResource::Backing::CanBeRecycled() const {
  DCHECK(!proxy() || proxy()->IsImplThread());
  return !was_above_priority_cutoff_at_last_priority_update_ &&
         !in_drawing_impl_tree_;
}

void PrioritizedResource::Backing::UpdatePriority() {
  DCHECK(!proxy() ||
         (proxy()->IsImplThread() && proxy()->IsMainThreadBlocked()));
  if (owner_) {
    priority_at_last_priority_update_ = owner_->request_priority();
    was_above_priority_cutoff_at_last_priority_update_ =
        owner_->is_above_priority_cutoff();
  } else {
    priority_at_last_priority_update_ = PriorityCalculator::LowestPriority();
    was_above_priority_cutoff_at_last_priority_update_ = false;
  }
}

void PrioritizedResource::Backing::UpdateInDrawingImplTree() {
  DCHECK(!proxy() ||
         (proxy()->IsImplThread() && proxy()->IsMainThreadBlocked()));
  in_drawing_impl_tree_ = !!owner();
  if (!in_drawing_impl_tree_) {
    DCHECK_EQ(priority_at_last_priority_update_,
              PriorityCalculator::LowestPriority());
  }
}

void PrioritizedResource::ReturnBackingTexture() {
  DCHECK(manager_ || !backing_);
  if (manager_)
    manager_->ReturnBackingTexture(this);
}

const Proxy* PrioritizedResource::Backing::proxy() const {
  if (!owner_ || !owner_->resource_manager())
    return NULL;
  return owner_->resource_manager()->ProxyForDebug();
}

}  // namespace cc
