// Copyright (c) 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 "gpu/command_buffer/service/framebuffer_manager.h"
#include "base/logging.h"
#include "base/strings/stringprintf.h"
#include "gpu/command_buffer/common/gles2_cmd_utils.h"
#include "gpu/command_buffer/service/renderbuffer_manager.h"
#include "gpu/command_buffer/service/texture_manager.h"
#include "ui/gl/gl_bindings.h"

namespace gpu {
namespace gles2 {

DecoderFramebufferState::DecoderFramebufferState()
    : clear_state_dirty(false),
      bound_read_framebuffer(NULL),
      bound_draw_framebuffer(NULL) {
}

DecoderFramebufferState::~DecoderFramebufferState() {
}

Framebuffer::FramebufferComboCompleteMap*
    Framebuffer::framebuffer_combo_complete_map_;

// Framebuffer completeness is not cacheable on OS X because of dynamic
// graphics switching.
// http://crbug.com/180876
#if defined(OS_MACOSX)
bool Framebuffer::allow_framebuffer_combo_complete_map_ = false;
#else
bool Framebuffer::allow_framebuffer_combo_complete_map_ = true;
#endif

void Framebuffer::ClearFramebufferCompleteComboMap() {
  if (framebuffer_combo_complete_map_) {
    framebuffer_combo_complete_map_->clear();
  }
}

class RenderbufferAttachment
    : public Framebuffer::Attachment {
 public:
  explicit RenderbufferAttachment(
      Renderbuffer* renderbuffer)
      : renderbuffer_(renderbuffer) {
  }

  virtual GLsizei width() const override {
    return renderbuffer_->width();
  }

  virtual GLsizei height() const override {
    return renderbuffer_->height();
  }

  virtual GLenum internal_format() const override {
    return renderbuffer_->internal_format();
  }

  virtual GLenum texture_type() const override {
    return 0;
  }

  virtual GLsizei samples() const override {
    return renderbuffer_->samples();
  }

  virtual GLuint object_name() const override {
    return renderbuffer_->client_id();
  }

  virtual bool cleared() const override {
    return renderbuffer_->cleared();
  }

  virtual void SetCleared(
      RenderbufferManager* renderbuffer_manager,
      TextureManager* /* texture_manager */,
      bool cleared) override {
    renderbuffer_manager->SetCleared(renderbuffer_.get(), cleared);
  }

  virtual bool IsTexture(
      TextureRef* /* texture */) const override {
    return false;
  }

  virtual bool IsRenderbuffer(
       Renderbuffer* renderbuffer) const override {
    return renderbuffer_.get() == renderbuffer;
  }

  virtual bool CanRenderTo() const override {
    return true;
  }

  virtual void DetachFromFramebuffer(Framebuffer* framebuffer) const override {
    // Nothing to do for renderbuffers.
  }

  virtual bool ValidForAttachmentType(
      GLenum attachment_type, uint32 max_color_attachments) override {
    uint32 need = GLES2Util::GetChannelsNeededForAttachmentType(
        attachment_type, max_color_attachments);
    uint32 have = GLES2Util::GetChannelsForFormat(internal_format());
    return (need & have) != 0;
  }

  Renderbuffer* renderbuffer() const {
    return renderbuffer_.get();
  }

  virtual size_t GetSignatureSize(
      TextureManager* texture_manager) const override {
    return renderbuffer_->GetSignatureSize();
  }

  virtual void AddToSignature(
      TextureManager* texture_manager, std::string* signature) const override {
    DCHECK(signature);
    renderbuffer_->AddToSignature(signature);
  }

  virtual void OnWillRenderTo() const override {}
  virtual void OnDidRenderTo() const override {}

 protected:
  virtual ~RenderbufferAttachment() { }

 private:
  scoped_refptr<Renderbuffer> renderbuffer_;

  DISALLOW_COPY_AND_ASSIGN(RenderbufferAttachment);
};

class TextureAttachment
    : public Framebuffer::Attachment {
 public:
  TextureAttachment(
      TextureRef* texture_ref, GLenum target, GLint level, GLsizei samples)
      : texture_ref_(texture_ref),
        target_(target),
        level_(level),
        samples_(samples) {
  }

  virtual GLsizei width() const override {
    GLsizei temp_width = 0;
    GLsizei temp_height = 0;
    texture_ref_->texture()->GetLevelSize(
        target_, level_, &temp_width, &temp_height);
    return temp_width;
  }

  virtual GLsizei height() const override {
    GLsizei temp_width = 0;
    GLsizei temp_height = 0;
    texture_ref_->texture()->GetLevelSize(
        target_, level_, &temp_width, &temp_height);
    return temp_height;
  }

  virtual GLenum internal_format() const override {
    GLenum temp_type = 0;
    GLenum temp_internal_format = 0;
    texture_ref_->texture()->GetLevelType(
        target_, level_, &temp_type, &temp_internal_format);
    return temp_internal_format;
  }

  virtual GLenum texture_type() const override {
    GLenum temp_type = 0;
    GLenum temp_internal_format = 0;
    texture_ref_->texture()->GetLevelType(
        target_, level_, &temp_type, &temp_internal_format);
    return temp_type;
  }

  virtual GLsizei samples() const override {
    return samples_;
  }

  virtual GLuint object_name() const override {
    return texture_ref_->client_id();
  }

  virtual bool cleared() const override {
    return texture_ref_->texture()->IsLevelCleared(target_, level_);
  }

  virtual void SetCleared(
      RenderbufferManager* /* renderbuffer_manager */,
      TextureManager* texture_manager,
      bool cleared) override {
    texture_manager->SetLevelCleared(
        texture_ref_.get(), target_, level_, cleared);
  }

  virtual bool IsTexture(TextureRef* texture) const override {
    return texture == texture_ref_.get();
  }

  virtual bool IsRenderbuffer(
       Renderbuffer* /* renderbuffer */)
          const override {
    return false;
  }

  TextureRef* texture() const {
    return texture_ref_.get();
  }

  virtual bool CanRenderTo() const override {
    return texture_ref_->texture()->CanRenderTo();
  }

  virtual void DetachFromFramebuffer(Framebuffer* framebuffer)
      const override {
    texture_ref_->texture()->DetachFromFramebuffer();
    framebuffer->OnTextureRefDetached(texture_ref_.get());
  }

  virtual bool ValidForAttachmentType(
      GLenum attachment_type, uint32 max_color_attachments) override {
    GLenum type = 0;
    GLenum internal_format = 0;
    if (!texture_ref_->texture()->GetLevelType(
        target_, level_, &type, &internal_format)) {
      return false;
    }
    uint32 need = GLES2Util::GetChannelsNeededForAttachmentType(
        attachment_type, max_color_attachments);
    uint32 have = GLES2Util::GetChannelsForFormat(internal_format);

    // Workaround for NVIDIA drivers that incorrectly expose these formats as
    // renderable:
    if (internal_format == GL_LUMINANCE || internal_format == GL_ALPHA ||
        internal_format == GL_LUMINANCE_ALPHA) {
      return false;
    }
    return (need & have) != 0;
  }

  virtual size_t GetSignatureSize(
      TextureManager* texture_manager) const override {
    return texture_manager->GetSignatureSize();
  }

  virtual void AddToSignature(
      TextureManager* texture_manager, std::string* signature) const override {
    DCHECK(signature);
    texture_manager->AddToSignature(
        texture_ref_.get(), target_, level_, signature);
  }

  virtual void OnWillRenderTo() const override {
    texture_ref_->texture()->OnWillModifyPixels();
  }

  virtual void OnDidRenderTo() const override {
    texture_ref_->texture()->OnDidModifyPixels();
  }

 protected:
  virtual ~TextureAttachment() {}

 private:
  scoped_refptr<TextureRef> texture_ref_;
  GLenum target_;
  GLint level_;
  GLsizei samples_;

  DISALLOW_COPY_AND_ASSIGN(TextureAttachment);
};

FramebufferManager::TextureDetachObserver::TextureDetachObserver() {}

FramebufferManager::TextureDetachObserver::~TextureDetachObserver() {}

FramebufferManager::FramebufferManager(
    uint32 max_draw_buffers, uint32 max_color_attachments)
    : framebuffer_state_change_count_(1),
      framebuffer_count_(0),
      have_context_(true),
      max_draw_buffers_(max_draw_buffers),
      max_color_attachments_(max_color_attachments) {
  DCHECK_GT(max_draw_buffers_, 0u);
  DCHECK_GT(max_color_attachments_, 0u);
}

FramebufferManager::~FramebufferManager() {
  DCHECK(framebuffers_.empty());
  // If this triggers, that means something is keeping a reference to a
  // Framebuffer belonging to this.
  CHECK_EQ(framebuffer_count_, 0u);
}

void Framebuffer::MarkAsDeleted() {
  deleted_ = true;
  while (!attachments_.empty()) {
    Attachment* attachment = attachments_.begin()->second.get();
    attachment->DetachFromFramebuffer(this);
    attachments_.erase(attachments_.begin());
  }
}

void FramebufferManager::Destroy(bool have_context) {
  have_context_ = have_context;
  framebuffers_.clear();
}

void FramebufferManager::StartTracking(
    Framebuffer* /* framebuffer */) {
  ++framebuffer_count_;
}

void FramebufferManager::StopTracking(
    Framebuffer* /* framebuffer */) {
  --framebuffer_count_;
}

void FramebufferManager::CreateFramebuffer(
    GLuint client_id, GLuint service_id) {
  std::pair<FramebufferMap::iterator, bool> result =
      framebuffers_.insert(
          std::make_pair(
              client_id,
              scoped_refptr<Framebuffer>(
                  new Framebuffer(this, service_id))));
  DCHECK(result.second);
}

Framebuffer::Framebuffer(
    FramebufferManager* manager, GLuint service_id)
    : manager_(manager),
      deleted_(false),
      service_id_(service_id),
      has_been_bound_(false),
      framebuffer_complete_state_count_id_(0) {
  manager->StartTracking(this);
  DCHECK_GT(manager->max_draw_buffers_, 0u);
  draw_buffers_.reset(new GLenum[manager->max_draw_buffers_]);
  draw_buffers_[0] = GL_COLOR_ATTACHMENT0;
  for (uint32 i = 1; i < manager->max_draw_buffers_; ++i)
    draw_buffers_[i] = GL_NONE;
}

Framebuffer::~Framebuffer() {
  if (manager_) {
    if (manager_->have_context_) {
      GLuint id = service_id();
      glDeleteFramebuffersEXT(1, &id);
    }
    manager_->StopTracking(this);
    manager_ = NULL;
  }
}

bool Framebuffer::HasUnclearedAttachment(
    GLenum attachment) const {
  AttachmentMap::const_iterator it =
      attachments_.find(attachment);
  if (it != attachments_.end()) {
    const Attachment* attachment = it->second.get();
    return !attachment->cleared();
  }
  return false;
}

bool Framebuffer::HasUnclearedColorAttachments() const {
  for (AttachmentMap::const_iterator it = attachments_.begin();
       it != attachments_.end(); ++it) {
    if (it->first >= GL_COLOR_ATTACHMENT0 &&
        it->first < GL_COLOR_ATTACHMENT0 + manager_->max_draw_buffers_) {
      const Attachment* attachment = it->second.get();
      if (!attachment->cleared())
        return true;
    }
  }
  return false;
}

void Framebuffer::ChangeDrawBuffersHelper(bool recover) const {
  scoped_ptr<GLenum[]> buffers(new GLenum[manager_->max_draw_buffers_]);
  for (uint32 i = 0; i < manager_->max_draw_buffers_; ++i)
    buffers[i] = GL_NONE;
  for (AttachmentMap::const_iterator it = attachments_.begin();
       it != attachments_.end(); ++it) {
    if (it->first >= GL_COLOR_ATTACHMENT0 &&
        it->first < GL_COLOR_ATTACHMENT0 + manager_->max_draw_buffers_) {
      buffers[it->first - GL_COLOR_ATTACHMENT0] = it->first;
    }
  }
  bool different = false;
  for (uint32 i = 0; i < manager_->max_draw_buffers_; ++i) {
    if (buffers[i] != draw_buffers_[i]) {
      different = true;
      break;
    }
  }
  if (different) {
    if (recover)
      glDrawBuffersARB(manager_->max_draw_buffers_, draw_buffers_.get());
    else
      glDrawBuffersARB(manager_->max_draw_buffers_, buffers.get());
  }
}

void Framebuffer::PrepareDrawBuffersForClear() const {
  bool recover = false;
  ChangeDrawBuffersHelper(recover);
}

void Framebuffer::RestoreDrawBuffersAfterClear() const {
  bool recover = true;
  ChangeDrawBuffersHelper(recover);
}

void Framebuffer::MarkAttachmentAsCleared(
      RenderbufferManager* renderbuffer_manager,
      TextureManager* texture_manager,
      GLenum attachment,
      bool cleared) {
  AttachmentMap::iterator it = attachments_.find(attachment);
  if (it != attachments_.end()) {
    Attachment* a = it->second.get();
    if (a->cleared() != cleared) {
      a->SetCleared(renderbuffer_manager,
                    texture_manager,
                    cleared);
    }
  }
}

void Framebuffer::MarkAttachmentsAsCleared(
      RenderbufferManager* renderbuffer_manager,
      TextureManager* texture_manager,
      bool cleared) {
  for (AttachmentMap::iterator it = attachments_.begin();
       it != attachments_.end(); ++it) {
    Attachment* attachment = it->second.get();
    if (attachment->cleared() != cleared) {
      attachment->SetCleared(renderbuffer_manager, texture_manager, cleared);
    }
  }
}

bool Framebuffer::HasDepthAttachment() const {
  return attachments_.find(GL_DEPTH_STENCIL_ATTACHMENT) != attachments_.end() ||
         attachments_.find(GL_DEPTH_ATTACHMENT) != attachments_.end();
}

bool Framebuffer::HasStencilAttachment() const {
  return attachments_.find(GL_DEPTH_STENCIL_ATTACHMENT) != attachments_.end() ||
         attachments_.find(GL_STENCIL_ATTACHMENT) != attachments_.end();
}

GLenum Framebuffer::GetColorAttachmentFormat() const {
  AttachmentMap::const_iterator it = attachments_.find(GL_COLOR_ATTACHMENT0);
  if (it == attachments_.end()) {
    return 0;
  }
  const Attachment* attachment = it->second.get();
  return attachment->internal_format();
}

GLenum Framebuffer::GetColorAttachmentTextureType() const {
  AttachmentMap::const_iterator it = attachments_.find(GL_COLOR_ATTACHMENT0);
  if (it == attachments_.end()) {
    return 0;
  }
  const Attachment* attachment = it->second.get();
  return attachment->texture_type();
}

GLenum Framebuffer::IsPossiblyComplete() const {
  if (attachments_.empty()) {
    return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
  }

  GLsizei width = -1;
  GLsizei height = -1;
  for (AttachmentMap::const_iterator it = attachments_.begin();
       it != attachments_.end(); ++it) {
    GLenum attachment_type = it->first;
    Attachment* attachment = it->second.get();
    if (!attachment->ValidForAttachmentType(attachment_type,
                                            manager_->max_color_attachments_)) {
      return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
    }
    if (width < 0) {
      width = attachment->width();
      height = attachment->height();
      if (width == 0 || height == 0) {
        return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
      }
    } else {
      if (attachment->width() != width || attachment->height() != height) {
        return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT;
      }
    }

    if (!attachment->CanRenderTo()) {
      return GL_FRAMEBUFFER_UNSUPPORTED;
    }
  }

  // This does not mean the framebuffer is actually complete. It just means our
  // checks passed.
  return GL_FRAMEBUFFER_COMPLETE;
}

GLenum Framebuffer::GetStatus(
    TextureManager* texture_manager, GLenum target) const {
  // Check if we have this combo already.
  std::string signature;
  if (allow_framebuffer_combo_complete_map_) {
    size_t signature_size = sizeof(target);
    for (AttachmentMap::const_iterator it = attachments_.begin();
         it != attachments_.end(); ++it) {
      Attachment* attachment = it->second.get();
      signature_size += sizeof(it->first) +
                        attachment->GetSignatureSize(texture_manager);
    }

    signature.reserve(signature_size);
    signature.append(reinterpret_cast<const char*>(&target), sizeof(target));

    for (AttachmentMap::const_iterator it = attachments_.begin();
         it != attachments_.end(); ++it) {
      Attachment* attachment = it->second.get();
      signature.append(reinterpret_cast<const char*>(&it->first),
                       sizeof(it->first));
      attachment->AddToSignature(texture_manager, &signature);
    }
    DCHECK(signature.size() == signature_size);

    if (!framebuffer_combo_complete_map_) {
      framebuffer_combo_complete_map_ = new FramebufferComboCompleteMap();
    }

    FramebufferComboCompleteMap::const_iterator it =
        framebuffer_combo_complete_map_->find(signature);
    if (it != framebuffer_combo_complete_map_->end()) {
      return GL_FRAMEBUFFER_COMPLETE;
    }
  }

  GLenum result = glCheckFramebufferStatusEXT(target);

  // Insert the new result into the combo map.
  if (allow_framebuffer_combo_complete_map_ &&
      result == GL_FRAMEBUFFER_COMPLETE) {
    framebuffer_combo_complete_map_->insert(std::make_pair(signature, true));
  }

  return result;
}

bool Framebuffer::IsCleared() const {
  // are all the attachments cleaared?
  for (AttachmentMap::const_iterator it = attachments_.begin();
       it != attachments_.end(); ++it) {
    Attachment* attachment = it->second.get();
    if (!attachment->cleared()) {
      return false;
    }
  }
  return true;
}

GLenum Framebuffer::GetDrawBuffer(GLenum draw_buffer) const {
  GLsizei index = static_cast<GLsizei>(
      draw_buffer - GL_DRAW_BUFFER0_ARB);
  CHECK(index >= 0 &&
        index < static_cast<GLsizei>(manager_->max_draw_buffers_));
  return draw_buffers_[index];
}

void Framebuffer::SetDrawBuffers(GLsizei n, const GLenum* bufs) {
  DCHECK(n <= static_cast<GLsizei>(manager_->max_draw_buffers_));
  for (GLsizei i = 0; i < n; ++i)
    draw_buffers_[i] = bufs[i];
}

bool Framebuffer::HasAlphaMRT() const {
  for (uint32 i = 0; i < manager_->max_draw_buffers_; ++i) {
    if (draw_buffers_[i] != GL_NONE) {
      const Attachment* attachment = GetAttachment(draw_buffers_[i]);
      if (!attachment)
        continue;
      if ((GLES2Util::GetChannelsForFormat(
               attachment->internal_format()) & 0x0008) != 0)
        return true;
    }
  }
  return false;
}

void Framebuffer::UnbindRenderbuffer(
    GLenum target, Renderbuffer* renderbuffer) {
  bool done;
  do {
    done = true;
    for (AttachmentMap::const_iterator it = attachments_.begin();
         it != attachments_.end(); ++it) {
      Attachment* attachment = it->second.get();
      if (attachment->IsRenderbuffer(renderbuffer)) {
        // TODO(gman): manually detach renderbuffer.
        // glFramebufferRenderbufferEXT(target, it->first, GL_RENDERBUFFER, 0);
        AttachRenderbuffer(it->first, NULL);
        done = false;
        break;
      }
    }
  } while (!done);
}

void Framebuffer::UnbindTexture(
    GLenum target, TextureRef* texture_ref) {
  bool done;
  do {
    done = true;
    for (AttachmentMap::const_iterator it = attachments_.begin();
         it != attachments_.end(); ++it) {
      Attachment* attachment = it->second.get();
      if (attachment->IsTexture(texture_ref)) {
        // TODO(gman): manually detach texture.
        // glFramebufferTexture2DEXT(target, it->first, GL_TEXTURE_2D, 0, 0);
        AttachTexture(it->first, NULL, GL_TEXTURE_2D, 0, 0);
        done = false;
        break;
      }
    }
  } while (!done);
}

Framebuffer* FramebufferManager::GetFramebuffer(
    GLuint client_id) {
  FramebufferMap::iterator it = framebuffers_.find(client_id);
  return it != framebuffers_.end() ? it->second.get() : NULL;
}

void FramebufferManager::RemoveFramebuffer(GLuint client_id) {
  FramebufferMap::iterator it = framebuffers_.find(client_id);
  if (it != framebuffers_.end()) {
    it->second->MarkAsDeleted();
    framebuffers_.erase(it);
  }
}

void Framebuffer::AttachRenderbuffer(
    GLenum attachment, Renderbuffer* renderbuffer) {
  const Attachment* a = GetAttachment(attachment);
  if (a)
    a->DetachFromFramebuffer(this);
  if (renderbuffer) {
    attachments_[attachment] = scoped_refptr<Attachment>(
        new RenderbufferAttachment(renderbuffer));
  } else {
    attachments_.erase(attachment);
  }
  framebuffer_complete_state_count_id_ = 0;
}

void Framebuffer::AttachTexture(
    GLenum attachment, TextureRef* texture_ref, GLenum target,
    GLint level, GLsizei samples) {
  const Attachment* a = GetAttachment(attachment);
  if (a)
    a->DetachFromFramebuffer(this);
  if (texture_ref) {
    attachments_[attachment] = scoped_refptr<Attachment>(
        new TextureAttachment(texture_ref, target, level, samples));
    texture_ref->texture()->AttachToFramebuffer();
  } else {
    attachments_.erase(attachment);
  }
  framebuffer_complete_state_count_id_ = 0;
}

const Framebuffer::Attachment*
    Framebuffer::GetAttachment(
        GLenum attachment) const {
  AttachmentMap::const_iterator it = attachments_.find(attachment);
  if (it != attachments_.end()) {
    return it->second.get();
  }
  return NULL;
}

void Framebuffer::OnTextureRefDetached(TextureRef* texture) {
  manager_->OnTextureRefDetached(texture);
}

void Framebuffer::OnWillRenderTo() const {
  for (AttachmentMap::const_iterator it = attachments_.begin();
       it != attachments_.end(); ++it) {
    it->second->OnWillRenderTo();
  }
}

void Framebuffer::OnDidRenderTo() const {
  for (AttachmentMap::const_iterator it = attachments_.begin();
       it != attachments_.end(); ++it) {
    it->second->OnDidRenderTo();
  }
}

bool FramebufferManager::GetClientId(
    GLuint service_id, GLuint* client_id) const {
  // This doesn't need to be fast. It's only used during slow queries.
  for (FramebufferMap::const_iterator it = framebuffers_.begin();
       it != framebuffers_.end(); ++it) {
    if (it->second->service_id() == service_id) {
      *client_id = it->first;
      return true;
    }
  }
  return false;
}

void FramebufferManager::MarkAttachmentsAsCleared(
    Framebuffer* framebuffer,
    RenderbufferManager* renderbuffer_manager,
    TextureManager* texture_manager) {
  DCHECK(framebuffer);
  framebuffer->MarkAttachmentsAsCleared(renderbuffer_manager,
                                        texture_manager,
                                        true);
  MarkAsComplete(framebuffer);
}

void FramebufferManager::MarkAsComplete(
    Framebuffer* framebuffer) {
  DCHECK(framebuffer);
  framebuffer->MarkAsComplete(framebuffer_state_change_count_);
}

bool FramebufferManager::IsComplete(
    Framebuffer* framebuffer) {
  DCHECK(framebuffer);
  return framebuffer->framebuffer_complete_state_count_id() ==
      framebuffer_state_change_count_;
}

void FramebufferManager::OnTextureRefDetached(TextureRef* texture) {
  for (TextureDetachObserverVector::iterator it =
           texture_detach_observers_.begin();
       it != texture_detach_observers_.end();
       ++it) {
    TextureDetachObserver* observer = *it;
    observer->OnTextureRefDetachedFromFramebuffer(texture);
  }
}

}  // namespace gles2
}  // namespace gpu


