/*
 * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * 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.
    * Neither the name of The Linux Foundation nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER 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 "gl_common.h"

#define __CLASS__ "GLCommon"

namespace sdm {

GLuint GLCommon::LoadProgram(int vertex_entries, const char **vertex, int fragment_entries,
                           const char **fragment) {
  GLuint prog_id = glCreateProgram();

  int vert_id = glCreateShader(GL_VERTEX_SHADER);
  int frag_id = glCreateShader(GL_FRAGMENT_SHADER);

  GL(glShaderSource(vert_id, vertex_entries, vertex, 0));
  GL(glCompileShader(vert_id));
  DumpShaderLog(vert_id);

  GL(glShaderSource(frag_id, fragment_entries, fragment, 0));
  GL(glCompileShader(frag_id));
  DumpShaderLog(frag_id);

  GL(glAttachShader(prog_id, vert_id));
  GL(glAttachShader(prog_id, frag_id));

  GL(glLinkProgram(prog_id));

  GL(glDetachShader(prog_id, vert_id));
  GL(glDetachShader(prog_id, frag_id));

  GL(glDeleteShader(vert_id));
  GL(glDeleteShader(frag_id));

  return prog_id;
}

void GLCommon::DumpShaderLog(int shader) {
  int success = 0;
  GLchar infoLog[512];
  GL(glGetShaderiv(shader, GL_COMPILE_STATUS, &success));
  if (!success) {
    glGetShaderInfoLog(shader, 512, NULL, infoLog);
    DLOGI("Shader Failed to compile: %s\n", infoLog);
  }
}

void GLCommon::MakeCurrent(const GLContext* ctx) {
  DTRACE_SCOPED();
  EGL(eglMakeCurrent(ctx->egl_display, ctx->egl_surface, ctx->egl_surface, ctx->egl_context));
}

void GLCommon::SetProgram(uint32_t id) {
  DTRACE_SCOPED();
  GL(glUseProgram(id));
}

void GLCommon::DeleteProgram(uint32_t id) {
  DTRACE_SCOPED();
  GL(glDeleteProgram(id));
}

void GLCommon::SetSourceBuffer(const private_handle_t *src_hnd) {
  DTRACE_SCOPED();
  EGLImageBuffer *src_buffer = image_wrapper_.wrap(reinterpret_cast<const void *>(src_hnd));

  GL(glActiveTexture(GL_TEXTURE0));
  if (src_buffer) {
    GL(glBindTexture(GL_TEXTURE_2D, src_buffer->getTexture(GL_TEXTURE_2D)));
  }
}

void GLCommon::SetDestinationBuffer(const private_handle_t *dst_hnd, const GLRect &dst_rect) {
  DTRACE_SCOPED();
  EGLImageBuffer *dst_buffer = image_wrapper_.wrap(reinterpret_cast<const void *>(dst_hnd));

  if (dst_buffer) {
    GL(glBindFramebuffer(GL_FRAMEBUFFER, dst_buffer->getFramebuffer()));
    float width = dst_rect.right - dst_rect.left;
    float height = dst_rect.bottom - dst_rect.top;
    GL(glViewport(dst_rect.left, dst_rect.top, width, height));
  }
}

int GLCommon::WaitOnInputFence(const shared_ptr<Fence> &in_fence) {
  DTRACE_SCOPED();

  int fd = Fence::Dup(in_fence);
  EGLint attribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fd, EGL_NONE};
  EGLSyncKHR sync = eglCreateSyncKHR(eglGetCurrentDisplay(), EGL_SYNC_NATIVE_FENCE_ANDROID,
                                     attribs);

  if (sync == EGL_NO_SYNC_KHR) {
    DLOGE("Failed to create sync from source fd: %s", Fence::GetStr(in_fence).c_str());
    close(fd);
    return -1;
  }

  EGL(eglWaitSyncKHR(eglGetCurrentDisplay(), sync, 0));
  EGL(eglDestroySyncKHR(eglGetCurrentDisplay(), sync));

  return 0;
}

int GLCommon::CreateOutputFence(shared_ptr<Fence> *out_fence) {
  DTRACE_SCOPED();
  EGLSyncKHR sync = eglCreateSyncKHR(eglGetCurrentDisplay(), EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);

  // Swap buffer.
  GL(glFlush());

  if (sync == EGL_NO_SYNC_KHR) {
    DLOGE("Failed to create egl sync fence");
    return -1;
  }

  int status = 0;
  int fd = eglDupNativeFenceFDANDROID(eglGetCurrentDisplay(), sync);
  if (fd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
    status = -1;
    DLOGE("Failed to dup sync");
  } else {
    *out_fence = Fence::Create(fd, "gl_out_fence");
  }
  EGL(eglDestroySyncKHR(eglGetCurrentDisplay(), sync));

  return status;
}

void GLCommon::DestroyContext(GLContext* ctx) {
  DTRACE_SCOPED();

  // Clear egl image buffers.
  image_wrapper_.Deinit();

  EGL(DeleteProgram(ctx->program_id));
  EGL(eglMakeCurrent(ctx->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
  EGL(eglDestroySurface(ctx->egl_display, ctx->egl_surface));
  EGL(eglDestroyContext(ctx->egl_display, ctx->egl_context));
  EGL(eglTerminate(ctx->egl_display));
}

void GLCommon::ClearCache() {
  // Clear cached handles.
  image_wrapper_.Deinit();
  image_wrapper_.Init();
}

void GLCommon::SetRealTimePriority() {
  // same as composer thread
  struct sched_param param = {0};
  param.sched_priority = 2;
  if (sched_setscheduler(0, SCHED_FIFO | SCHED_RESET_ON_FORK, &param) != 0) {
    DLOGE("Couldn't set SCHED_FIFO: %d", errno);
  }
}

}  // namespace sdm

