/*
 * Copyright (C) 2009 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "modules/webgl/WebGLFramebuffer.h"

#include "gpu/command_buffer/client/gles2_interface.h"
#include "modules/webgl/WebGLRenderbuffer.h"
#include "modules/webgl/WebGLRenderingContextBase.h"
#include "modules/webgl/WebGLTexture.h"

namespace blink {

namespace {

class WebGLRenderbufferAttachment final
    : public WebGLFramebuffer::WebGLAttachment {
 public:
  static WebGLFramebuffer::WebGLAttachment* Create(WebGLRenderbuffer*);

  virtual void Trace(blink::Visitor*);
  virtual void TraceWrappers(const ScriptWrappableVisitor* visitor) const {
    visitor->TraceWrappers(renderbuffer_);
  }

 private:
  explicit WebGLRenderbufferAttachment(WebGLRenderbuffer*);

  WebGLSharedObject* Object() const override;
  bool IsSharedObject(WebGLSharedObject*) const override;
  bool Valid() const override;
  void OnDetached(gpu::gles2::GLES2Interface*) override;
  void Attach(gpu::gles2::GLES2Interface*,
              GLenum target,
              GLenum attachment) override;
  void Unattach(gpu::gles2::GLES2Interface*,
                GLenum target,
                GLenum attachment) override;

  TraceWrapperMember<WebGLRenderbuffer> renderbuffer_;
};

WebGLFramebuffer::WebGLAttachment* WebGLRenderbufferAttachment::Create(
    WebGLRenderbuffer* renderbuffer) {
  return new WebGLRenderbufferAttachment(renderbuffer);
}

void WebGLRenderbufferAttachment::Trace(blink::Visitor* visitor) {
  visitor->Trace(renderbuffer_);
  WebGLFramebuffer::WebGLAttachment::Trace(visitor);
}

WebGLRenderbufferAttachment::WebGLRenderbufferAttachment(
    WebGLRenderbuffer* renderbuffer)
    : renderbuffer_(renderbuffer) {}

WebGLSharedObject* WebGLRenderbufferAttachment::Object() const {
  return renderbuffer_->Object() ? renderbuffer_.Get() : nullptr;
}

bool WebGLRenderbufferAttachment::IsSharedObject(
    WebGLSharedObject* object) const {
  return object == renderbuffer_;
}

bool WebGLRenderbufferAttachment::Valid() const {
  return renderbuffer_->Object();
}

void WebGLRenderbufferAttachment::OnDetached(gpu::gles2::GLES2Interface* gl) {
  renderbuffer_->OnDetached(gl);
}

void WebGLRenderbufferAttachment::Attach(gpu::gles2::GLES2Interface* gl,
                                         GLenum target,
                                         GLenum attachment) {
  GLuint object = ObjectOrZero(renderbuffer_.Get());
  gl->FramebufferRenderbuffer(target, attachment, GL_RENDERBUFFER, object);
}

void WebGLRenderbufferAttachment::Unattach(gpu::gles2::GLES2Interface* gl,
                                           GLenum target,
                                           GLenum attachment) {
  gl->FramebufferRenderbuffer(target, attachment, GL_RENDERBUFFER, 0);
}

class WebGLTextureAttachment final : public WebGLFramebuffer::WebGLAttachment {
 public:
  static WebGLFramebuffer::WebGLAttachment* Create(WebGLTexture*,
                                                   GLenum target,
                                                   GLint level,
                                                   GLint layer);

  virtual void Trace(blink::Visitor*);
  virtual void TraceWrappers(const ScriptWrappableVisitor* visitor) const {
    visitor->TraceWrappers(texture_);
  }

 private:
  WebGLTextureAttachment(WebGLTexture*,
                         GLenum target,
                         GLint level,
                         GLint layer);

  WebGLSharedObject* Object() const override;
  bool IsSharedObject(WebGLSharedObject*) const override;
  bool Valid() const override;
  void OnDetached(gpu::gles2::GLES2Interface*) override;
  void Attach(gpu::gles2::GLES2Interface*,
              GLenum target,
              GLenum attachment) override;
  void Unattach(gpu::gles2::GLES2Interface*,
                GLenum target,
                GLenum attachment) override;

  TraceWrapperMember<WebGLTexture> texture_;
  GLenum target_;
  GLint level_;
  GLint layer_;
};

WebGLFramebuffer::WebGLAttachment* WebGLTextureAttachment::Create(
    WebGLTexture* texture,
    GLenum target,
    GLint level,
    GLint layer) {
  return new WebGLTextureAttachment(texture, target, level, layer);
}

void WebGLTextureAttachment::Trace(blink::Visitor* visitor) {
  visitor->Trace(texture_);
  WebGLFramebuffer::WebGLAttachment::Trace(visitor);
}

WebGLTextureAttachment::WebGLTextureAttachment(WebGLTexture* texture,
                                               GLenum target,
                                               GLint level,
                                               GLint layer)
    : texture_(texture), target_(target), level_(level), layer_(layer) {}

WebGLSharedObject* WebGLTextureAttachment::Object() const {
  return texture_->Object() ? texture_.Get() : nullptr;
}

bool WebGLTextureAttachment::IsSharedObject(WebGLSharedObject* object) const {
  return object == texture_;
}

bool WebGLTextureAttachment::Valid() const {
  return texture_->Object();
}

void WebGLTextureAttachment::OnDetached(gpu::gles2::GLES2Interface* gl) {
  texture_->OnDetached(gl);
}

void WebGLTextureAttachment::Attach(gpu::gles2::GLES2Interface* gl,
                                    GLenum target,
                                    GLenum attachment) {
  GLuint object = ObjectOrZero(texture_.Get());
  if (target_ == GL_TEXTURE_3D || target_ == GL_TEXTURE_2D_ARRAY) {
    gl->FramebufferTextureLayer(target, attachment, object, level_, layer_);
  } else {
    gl->FramebufferTexture2D(target, attachment, target_, object, level_);
  }
}

void WebGLTextureAttachment::Unattach(gpu::gles2::GLES2Interface* gl,
                                      GLenum target,
                                      GLenum attachment) {
  // GL_DEPTH_STENCIL_ATTACHMENT attachment is valid in ES3.
  if (target_ == GL_TEXTURE_3D || target_ == GL_TEXTURE_2D_ARRAY) {
    gl->FramebufferTextureLayer(target, attachment, 0, level_, layer_);
  } else {
    gl->FramebufferTexture2D(target, attachment, target_, 0, level_);
  }
}

}  // anonymous namespace

WebGLFramebuffer::WebGLAttachment::WebGLAttachment() = default;

WebGLFramebuffer* WebGLFramebuffer::Create(WebGLRenderingContextBase* ctx) {
  return new WebGLFramebuffer(ctx, false);
}

WebGLFramebuffer* WebGLFramebuffer::CreateOpaque(
    WebGLRenderingContextBase* ctx) {
  return new WebGLFramebuffer(ctx, true);
}

WebGLFramebuffer::WebGLFramebuffer(WebGLRenderingContextBase* ctx, bool opaque)
    : WebGLContextObject(ctx),
      object_(0),
      has_ever_been_bound_(false),
      web_gl1_depth_stencil_consistent_(true),
      opaque_(opaque),
      read_buffer_(GL_COLOR_ATTACHMENT0) {
  ctx->ContextGL()->GenFramebuffers(1, &object_);
}

WebGLFramebuffer::~WebGLFramebuffer() {
  RunDestructor();
}

void WebGLFramebuffer::SetAttachmentForBoundFramebuffer(GLenum target,
                                                        GLenum attachment,
                                                        GLenum tex_target,
                                                        WebGLTexture* texture,
                                                        GLint level,
                                                        GLint layer) {
  DCHECK(object_);
  DCHECK(IsBound(target));
  if (Context()->IsWebGL2OrHigher()) {
    if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
      SetAttachmentInternal(target, GL_DEPTH_ATTACHMENT, tex_target, texture,
                            level, layer);
      SetAttachmentInternal(target, GL_STENCIL_ATTACHMENT, tex_target, texture,
                            level, layer);
    } else {
      SetAttachmentInternal(target, attachment, tex_target, texture, level,
                            layer);
    }
    GLuint texture_id = ObjectOrZero(texture);
    // texTarget can be 0 if detaching using framebufferTextureLayer.
    DCHECK(tex_target || !texture_id);
    switch (tex_target) {
      case 0:
      case GL_TEXTURE_3D:
      case GL_TEXTURE_2D_ARRAY:
        Context()->ContextGL()->FramebufferTextureLayer(
            target, attachment, texture_id, level, layer);
        break;
      default:
        DCHECK_EQ(layer, 0);
        Context()->ContextGL()->FramebufferTexture2D(
            target, attachment, tex_target, texture_id, level);
        break;
    }
  } else {
    DCHECK_EQ(layer, 0);
    SetAttachmentInternal(target, attachment, tex_target, texture, level,
                          layer);
    switch (attachment) {
      case GL_DEPTH_ATTACHMENT:
      case GL_STENCIL_ATTACHMENT:
      case GL_DEPTH_STENCIL_ATTACHMENT:
        CommitWebGL1DepthStencilIfConsistent(target);
        break;
      default:
        Context()->ContextGL()->FramebufferTexture2D(
            target, attachment, tex_target, ObjectOrZero(texture), level);
        break;
    }
  }
}

void WebGLFramebuffer::SetAttachmentForBoundFramebuffer(
    GLenum target,
    GLenum attachment,
    WebGLRenderbuffer* renderbuffer) {
  DCHECK(object_);
  DCHECK(IsBound(target));
  if (Context()->IsWebGL2OrHigher()) {
    if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
      SetAttachmentInternal(target, GL_DEPTH_ATTACHMENT, renderbuffer);
      SetAttachmentInternal(target, GL_STENCIL_ATTACHMENT, renderbuffer);
    } else {
      SetAttachmentInternal(target, attachment, renderbuffer);
    }
    Context()->ContextGL()->FramebufferRenderbuffer(
        target, attachment, GL_RENDERBUFFER, ObjectOrZero(renderbuffer));
  } else {
    SetAttachmentInternal(target, attachment, renderbuffer);
    switch (attachment) {
      case GL_DEPTH_ATTACHMENT:
      case GL_STENCIL_ATTACHMENT:
      case GL_DEPTH_STENCIL_ATTACHMENT:
        CommitWebGL1DepthStencilIfConsistent(target);
        break;
      default:
        Context()->ContextGL()->FramebufferRenderbuffer(
            target, attachment, GL_RENDERBUFFER, ObjectOrZero(renderbuffer));
        break;
    }
  }
}

WebGLSharedObject* WebGLFramebuffer::GetAttachmentObject(
    GLenum attachment) const {
  if (!object_)
    return nullptr;
  WebGLAttachment* attachment_object = GetAttachment(attachment);
  return attachment_object ? attachment_object->Object() : nullptr;
}

WebGLFramebuffer::WebGLAttachment* WebGLFramebuffer::GetAttachment(
    GLenum attachment) const {
  const AttachmentMap::const_iterator it = attachments_.find(attachment);
  return (it != attachments_.end()) ? it->value.Get() : nullptr;
}

void WebGLFramebuffer::RemoveAttachmentFromBoundFramebuffer(
    GLenum target,
    WebGLSharedObject* attachment) {
  DCHECK(IsBound(target));
  if (!object_)
    return;
  if (!attachment)
    return;

  bool check_more = true;
  bool is_web_gl1 = !Context()->IsWebGL2OrHigher();
  bool check_web_gl1_depth_stencil = false;
  while (check_more) {
    check_more = false;
    for (const auto& it : attachments_) {
      WebGLAttachment* attachment_object = it.value.Get();
      if (attachment_object->IsSharedObject(attachment)) {
        GLenum attachment_type = it.key;
        switch (attachment_type) {
          case GL_DEPTH_ATTACHMENT:
          case GL_STENCIL_ATTACHMENT:
          case GL_DEPTH_STENCIL_ATTACHMENT:
            if (is_web_gl1) {
              check_web_gl1_depth_stencil = true;
            } else {
              attachment_object->Unattach(Context()->ContextGL(), target,
                                          attachment_type);
            }
            break;
          default:
            attachment_object->Unattach(Context()->ContextGL(), target,
                                        attachment_type);
            break;
        }
        RemoveAttachmentInternal(target, attachment_type);
        check_more = true;
        break;
      }
    }
  }
  if (check_web_gl1_depth_stencil)
    CommitWebGL1DepthStencilIfConsistent(target);
}

GLenum WebGLFramebuffer::CheckDepthStencilStatus(const char** reason) const {
  // This function is called any time framebuffer completeness is checked, which
  // makes it the most convenient place to add this check.
  if (opaque_) {
    if (opaque_complete_)
      return GL_FRAMEBUFFER_COMPLETE;
    *reason = "cannot render to a WebVR layer outside of a frame callback";
    return GL_FRAMEBUFFER_UNSUPPORTED;
  }
  if (Context()->IsWebGL2OrHigher() || web_gl1_depth_stencil_consistent_)
    return GL_FRAMEBUFFER_COMPLETE;
  *reason = "conflicting DEPTH/STENCIL/DEPTH_STENCIL attachments";
  return GL_FRAMEBUFFER_UNSUPPORTED;
}

bool WebGLFramebuffer::HasStencilBuffer() const {
  WebGLAttachment* attachment = GetAttachment(GL_STENCIL_ATTACHMENT);
  if (!attachment)
    attachment = GetAttachment(GL_DEPTH_STENCIL_ATTACHMENT);
  return attachment && attachment->Valid();
}

void WebGLFramebuffer::DeleteObjectImpl(gpu::gles2::GLES2Interface* gl) {
  // Both the AttachmentMap and its WebGLAttachment objects are GCed
  // objects and cannot be accessed after the destructor has been
  // entered, as they may have been finalized already during the
  // same GC sweep. These attachments' OpenGL objects will be fully
  // destroyed once their JavaScript wrappers are collected.
  if (!DestructionInProgress()) {
    for (const auto& attachment : attachments_)
      attachment.value->OnDetached(gl);
  }

  gl->DeleteFramebuffers(1, &object_);
  object_ = 0;
}

bool WebGLFramebuffer::IsBound(GLenum target) const {
  return (Context()->GetFramebufferBinding(target) == this);
}

void WebGLFramebuffer::DrawBuffers(const Vector<GLenum>& bufs) {
  draw_buffers_ = bufs;
  filtered_draw_buffers_.resize(draw_buffers_.size());
  for (size_t i = 0; i < filtered_draw_buffers_.size(); ++i)
    filtered_draw_buffers_[i] = GL_NONE;
  DrawBuffersIfNecessary(true);
}

void WebGLFramebuffer::DrawBuffersIfNecessary(bool force) {
  if (Context()->IsWebGL2OrHigher() ||
      Context()->ExtensionEnabled(kWebGLDrawBuffersName)) {
    bool reset = force;
    // This filtering works around graphics driver bugs on Mac OS X.
    for (size_t i = 0; i < draw_buffers_.size(); ++i) {
      if (draw_buffers_[i] != GL_NONE && GetAttachment(draw_buffers_[i])) {
        if (filtered_draw_buffers_[i] != draw_buffers_[i]) {
          filtered_draw_buffers_[i] = draw_buffers_[i];
          reset = true;
        }
      } else {
        if (filtered_draw_buffers_[i] != GL_NONE) {
          filtered_draw_buffers_[i] = GL_NONE;
          reset = true;
        }
      }
    }
    if (reset) {
      Context()->ContextGL()->DrawBuffersEXT(filtered_draw_buffers_.size(),
                                             filtered_draw_buffers_.data());
    }
  }
}

void WebGLFramebuffer::SetAttachmentInternal(GLenum target,
                                             GLenum attachment,
                                             GLenum tex_target,
                                             WebGLTexture* texture,
                                             GLint level,
                                             GLint layer) {
  DCHECK(IsBound(target));
  DCHECK(object_);
  RemoveAttachmentInternal(target, attachment);
  if (texture && texture->Object()) {
    attachments_.insert(attachment, WebGLTextureAttachment::Create(
                                        texture, tex_target, level, layer));
    DrawBuffersIfNecessary(false);
    texture->OnAttached();
  }
}

void WebGLFramebuffer::SetAttachmentInternal(GLenum target,
                                             GLenum attachment,
                                             WebGLRenderbuffer* renderbuffer) {
  DCHECK(IsBound(target));
  DCHECK(object_);
  RemoveAttachmentInternal(target, attachment);
  if (renderbuffer && renderbuffer->Object()) {
    attachments_.insert(attachment,
                        WebGLRenderbufferAttachment::Create(renderbuffer));
    DrawBuffersIfNecessary(false);
    renderbuffer->OnAttached();
  }
}

void WebGLFramebuffer::RemoveAttachmentInternal(GLenum target,
                                                GLenum attachment) {
  DCHECK(IsBound(target));
  DCHECK(object_);

  WebGLAttachment* attachment_object = GetAttachment(attachment);
  if (attachment_object) {
    attachment_object->OnDetached(Context()->ContextGL());
    attachments_.erase(attachment);
    DrawBuffersIfNecessary(false);
  }
}

void WebGLFramebuffer::CommitWebGL1DepthStencilIfConsistent(GLenum target) {
  DCHECK(!Context()->IsWebGL2OrHigher());
  WebGLAttachment* depth_attachment = nullptr;
  WebGLAttachment* stencil_attachment = nullptr;
  WebGLAttachment* depth_stencil_attachment = nullptr;
  int count = 0;
  for (const auto& it : attachments_) {
    WebGLAttachment* attachment = it.value.Get();
    DCHECK(attachment);
    switch (it.key) {
      case GL_DEPTH_ATTACHMENT:
        depth_attachment = attachment;
        ++count;
        break;
      case GL_STENCIL_ATTACHMENT:
        stencil_attachment = attachment;
        ++count;
        break;
      case GL_DEPTH_STENCIL_ATTACHMENT:
        depth_stencil_attachment = attachment;
        ++count;
        break;
      default:
        break;
    }
  }

  web_gl1_depth_stencil_consistent_ = count <= 1;
  if (!web_gl1_depth_stencil_consistent_)
    return;

  gpu::gles2::GLES2Interface* gl = Context()->ContextGL();
  if (depth_attachment) {
    gl->FramebufferRenderbuffer(target, GL_DEPTH_STENCIL_ATTACHMENT,
                                GL_RENDERBUFFER, 0);
    depth_attachment->Attach(gl, target, GL_DEPTH_ATTACHMENT);
    gl->FramebufferRenderbuffer(target, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
                                0);
  } else if (stencil_attachment) {
    gl->FramebufferRenderbuffer(target, GL_DEPTH_STENCIL_ATTACHMENT,
                                GL_RENDERBUFFER, 0);
    gl->FramebufferRenderbuffer(target, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
                                0);
    stencil_attachment->Attach(gl, target, GL_STENCIL_ATTACHMENT);
  } else if (depth_stencil_attachment) {
    gl->FramebufferRenderbuffer(target, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
                                0);
    gl->FramebufferRenderbuffer(target, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
                                0);
    depth_stencil_attachment->Attach(gl, target, GL_DEPTH_STENCIL_ATTACHMENT);
  } else {
    gl->FramebufferRenderbuffer(target, GL_DEPTH_STENCIL_ATTACHMENT,
                                GL_RENDERBUFFER, 0);
    gl->FramebufferRenderbuffer(target, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
                                0);
    gl->FramebufferRenderbuffer(target, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
                                0);
  }
}

GLenum WebGLFramebuffer::GetDrawBuffer(GLenum draw_buffer) {
  int index = static_cast<int>(draw_buffer - GL_DRAW_BUFFER0_EXT);
  DCHECK_GE(index, 0);
  if (index < static_cast<int>(draw_buffers_.size()))
    return draw_buffers_[index];
  if (draw_buffer == GL_DRAW_BUFFER0_EXT)
    return GL_COLOR_ATTACHMENT0;
  return GL_NONE;
}

void WebGLFramebuffer::Trace(blink::Visitor* visitor) {
  visitor->Trace(attachments_);
  WebGLContextObject::Trace(visitor);
}

void WebGLFramebuffer::TraceWrappers(
    const ScriptWrappableVisitor* visitor) const {
  for (const auto& attachment : attachments_) {
    visitor->TraceWrappers(attachment.value);
  }
  WebGLContextObject::TraceWrappers(visitor);
}

}  // namespace blink
