// 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"

#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_);

  SbGlEnum gl_error;

  // Create the framebuffer object.
  GL_CALL_SIMPLE(glGenFramebuffers(1, &framebuffer_handle_));
  gl_error = GL_CALL_SIMPLE(glGetError());
  if (gl_error != GL_NO_ERROR) {
    LOG(ERROR) << "Error creating new framebuffer. Error = " << gl_error;
    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));
  gl_error = GL_CALL_SIMPLE(glGetError());
  if (gl_error != GL_NO_ERROR) {
    LOG(ERROR) << "Error creating new texture. Error = " << gl_error;
    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
