/**
 * Copyright (c) 2021 Dominic Masters
 * 
 * This software is released under the MIT License.
 * https://opensource.org/licenses/MIT
 */

#include "framebuffer.h"

void frameBufferInit(framebuffer_t *fb, int32_t w, int32_t h) {
  // At least one pixel
  if(w <= 0) w = 1;
  if(h <= 0) h = 1;

  // Create Color Attachment texture.
  textureInit(&fb->texture, w, h, NULL);

  // Create Frame Buffer
  glGenFramebuffers(1, &fb->fboId);
  glBindFramebuffer(GL_FRAMEBUFFER, fb->fboId);
  glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
    GL_TEXTURE_2D, fb->texture.id, 0
  );

  // Render Buffer
  glGenRenderbuffers(1, &fb->rboId);
  glBindRenderbuffer(GL_RENDERBUFFER, fb->rboId); 
  glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, w, h);
  glBindRenderbuffer(GL_RENDERBUFFER, 0);
  glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
    GL_RENDERBUFFER, fb->rboId
  );

  if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
    uint32_t error;
    error = 0;
  }

  glBindFramebuffer(GL_FRAMEBUFFER, 0);
}

void frameBufferUse(framebuffer_t *frameBuffer, bool clear) {
  glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer->fboId);
  glViewport(0, 0, frameBuffer->texture.width, frameBuffer->texture.height);

  if(clear) {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  }
}

void frameBufferResize(framebuffer_t *frameBuffer,int32_t width,int32_t height){
  if((
    frameBuffer->texture.width == width &&
    frameBuffer->texture.height == height
  )) return;

  frameBufferDispose(frameBuffer);
  frameBufferInit(frameBuffer, width, height);
}

void frameBufferUnbind(render_t *render, bool clear) {
  glBindFramebuffer(GL_FRAMEBUFFER, 0);
  glViewport(0, 0, render->width, render->height);

  if(clear) {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  }
}

void frameBufferDispose(framebuffer_t *frameBuffer) {
  glBindFramebuffer(GL_FRAMEBUFFER, 0);
  glBindRenderbuffer(GL_RENDERBUFFER, 0);
  glDeleteRenderbuffers(1, &frameBuffer->rboId);
  glDeleteFramebuffers(1, &frameBuffer->fboId);
  textureDispose(&frameBuffer->texture);
}