// Copyright 2017 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "starboard/configuration.h"
#if SB_API_VERSION >= 12 || SB_HAS(GLES2)

#include "cobalt/renderer/backend/egl/framebuffer.h"

#include "base/logging.h"
#include "cobalt/renderer/backend/egl/graphics_context.h"
#include "cobalt/renderer/backend/egl/texture.h"
#include "cobalt/renderer/backend/egl/utils.h"
#include "cobalt/renderer/egl_and_gles.h"

namespace cobalt {
namespace renderer {
namespace backend {

FramebufferEGL::FramebufferEGL(GraphicsContextEGL* graphics_context,
                               const math::Size& size, GLenum color_format,
                               GLenum depth_format)
    : graphics_context_(graphics_context), size_(size), error_(false) {
  GraphicsContextEGL::ScopedMakeCurrent scoped_make_current(graphics_context_);

  // Create the framebuffer object.
  GL_CALL_SIMPLE(glGenFramebuffers(1, &framebuffer_handle_));
  if (GL_CALL_SIMPLE(glGetError()) != GL_NO_ERROR) {
    LOG(ERROR) << "Error creating new framebuffer.";
    error_ = true;
    return;
  }
  GL_CALL(glBindFramebuffer(GL_FRAMEBUFFER, framebuffer_handle_));

  // Create and attach a texture for color.
  GLuint color_handle = 0;
  GL_CALL_SIMPLE(glGenTextures(1, &color_handle));
  if (GL_CALL_SIMPLE(glGetError()) != GL_NO_ERROR) {
    LOG(ERROR) << "Error creating new texture.";
    error_ = true;
    GL_CALL(glBindFramebuffer(GL_FRAMEBUFFER, 0));
    GL_CALL(glDeleteFramebuffers(1, &framebuffer_handle_));
    return;
  }

  GL_CALL(glBindTexture(GL_TEXTURE_2D, color_handle));
  GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
  GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
  GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
  GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
  GL_CALL_SIMPLE(glTexImage2D(GL_TEXTURE_2D, 0, color_format, size_.width(),
                              size_.height(), 0, color_format, GL_UNSIGNED_BYTE,
                              0));
  if (GL_CALL_SIMPLE(glGetError()) != GL_NO_ERROR) {
    LOG(ERROR) << "Error allocating new texture backing for a framebuffer.";
    error_ = true;
    GL_CALL(glBindTexture(GL_TEXTURE_2D, 0));
    GL_CALL(glDeleteTextures(1, &color_handle));
    GL_CALL(glBindFramebuffer(GL_FRAMEBUFFER, 0));
    GL_CALL(glDeleteFramebuffers(1, &framebuffer_handle_));
    return;
  }

  GL_CALL(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
                                 GL_TEXTURE_2D, color_handle, 0));
  GL_CALL(glBindTexture(GL_TEXTURE_2D, 0));
  color_texture_.reset(new TextureEGL(graphics_context_, color_handle, size_,
                                      color_format, GL_TEXTURE_2D,
                                      base::Closure()));

  // Create and attach a depth buffer if requested.
  depthbuffer_handle_ = 0;
  if (depth_format != GL_NONE) {
    if (!CreateDepthAttachment(depth_format)) {
      LOG(ERROR) << "Error creating depth attachment for framebuffer.";
      error_ = true;
      GL_CALL(glBindFramebuffer(GL_FRAMEBUFFER, 0));
      GL_CALL(glDeleteFramebuffers(1, &framebuffer_handle_));
      color_texture_.reset();
      return;
    }
  }

  // Verify the framebuffer object is valid.
  DCHECK_EQ(GL_CALL_SIMPLE(glCheckFramebufferStatus(GL_FRAMEBUFFER)),
            GL_FRAMEBUFFER_COMPLETE);
  GL_CALL(glBindFramebuffer(GL_FRAMEBUFFER, 0));
}

void FramebufferEGL::EnsureDepthBufferAttached(GLenum depth_format) {
  if (depthbuffer_handle_ == 0) {
    GraphicsContextEGL::ScopedMakeCurrent scoped_make_current(
        graphics_context_);

    GL_CALL(glBindFramebuffer(GL_FRAMEBUFFER, framebuffer_handle_));
    CreateDepthAttachment(depth_format);

    // Verify the framebuffer object is valid.
    DCHECK_EQ(GL_CALL_SIMPLE(glCheckFramebufferStatus(GL_FRAMEBUFFER)),
              GL_FRAMEBUFFER_COMPLETE);
    GL_CALL(glBindFramebuffer(GL_FRAMEBUFFER, 0));
  }
}

FramebufferEGL::~FramebufferEGL() {
  if (!error_) {
    GraphicsContextEGL::ScopedMakeCurrent scoped_make_current(
        graphics_context_);
    GL_CALL(glDeleteFramebuffers(1, &framebuffer_handle_));
    if (depthbuffer_handle_ != 0) {
      GL_CALL(glDeleteRenderbuffers(1, &depthbuffer_handle_));
    }
  }
}

bool FramebufferEGL::CreateDepthAttachment(GLenum depth_format) {
  GL_CALL_SIMPLE(glGenRenderbuffers(1, &depthbuffer_handle_));
  if (GL_CALL_SIMPLE(glGetError()) != GL_NO_ERROR) {
    LOG(ERROR) << "Error creating depth buffer object.";
    return false;
  }
  GL_CALL(glBindRenderbuffer(GL_RENDERBUFFER, depthbuffer_handle_));
  GL_CALL_SIMPLE(glRenderbufferStorage(GL_RENDERBUFFER, depth_format,
                                       size_.width(), size_.height()));
  if (GL_CALL_SIMPLE(glGetError()) != GL_NO_ERROR) {
    LOG(ERROR) << "Error allocating memory for depth buffer.";
    GL_CALL(glBindRenderbuffer(GL_RENDERBUFFER, 0));
    GL_CALL(glDeleteRenderbuffers(1, &depthbuffer_handle_));
    return false;
  }
  GL_CALL(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
                                    GL_RENDERBUFFER, depthbuffer_handle_));
  GL_CALL(glBindRenderbuffer(GL_RENDERBUFFER, 0));

  return true;
}

}  // namespace backend
}  // namespace renderer
}  // namespace cobalt

#endif  // SB_API_VERSION >= 12 || SB_HAS(GLES2)
