// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/gl/gl_gl_api_implementation.h"

#include <algorithm>
#include <vector>

#include "base/command_line.h"
#include "base/strings/string_util.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_implementation.h"
#include "ui/gl/gl_state_restorer.h"
#include "ui/gl/gl_surface.h"
#include "ui/gl/gl_switches.h"
#include "ui/gl/gl_version_info.h"

namespace gfx {

// The GL Api being used. This could be g_real_gl or gl_trace_gl
static GLApi* g_gl = NULL;
// A GL Api that calls directly into the driver.
static RealGLApi* g_real_gl = NULL;
// A GL Api that does nothing but warn about illegal GL calls without a context
// current.
static NoContextGLApi* g_no_context_gl = NULL;
// A GL Api that calls TRACE and then calls another GL api.
static TraceGLApi* g_trace_gl = NULL;
// GL version used when initializing dynamic bindings.
static GLVersionInfo* g_version_info = NULL;

namespace {

static inline GLenum GetInternalFormat(GLenum internal_format) {
  if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
    if (internal_format == GL_BGRA_EXT || internal_format == GL_BGRA8_EXT)
      return GL_RGBA8;
  }
  return internal_format;
}

// TODO(epenner): Could the above function be merged into this and removed?
static inline GLenum GetTexInternalFormat(GLenum internal_format,
                                          GLenum format,
                                          GLenum type) {
  GLenum gl_internal_format = GetInternalFormat(internal_format);

  // g_version_info must be initialized when this function is bound.
  DCHECK(gfx::g_version_info);
  if (gfx::g_version_info->is_es3) {
    if (format == GL_RED_EXT) {
      switch (type) {
        case GL_UNSIGNED_BYTE:
          gl_internal_format = GL_R8_EXT;
          break;
        case GL_HALF_FLOAT_OES:
          gl_internal_format = GL_R16F_EXT;
          break;
        case GL_FLOAT:
          gl_internal_format = GL_R32F_EXT;
          break;
        default:
          NOTREACHED();
          break;
      }
      return gl_internal_format;
    } else if (format == GL_RG_EXT) {
      switch (type) {
        case GL_UNSIGNED_BYTE:
          gl_internal_format = GL_RG8_EXT;
          break;
        case GL_HALF_FLOAT_OES:
          gl_internal_format = GL_RG16F_EXT;
          break;
        case GL_FLOAT:
          gl_internal_format = GL_RG32F_EXT;
          break;
        default:
          NOTREACHED();
          break;
      }
      return gl_internal_format;
    }
  }

  if (type == GL_FLOAT && gfx::g_version_info->is_angle &&
      gfx::g_version_info->is_es && gfx::g_version_info->major_version == 2) {
    // It's possible that the texture is using a sized internal format, and
    // ANGLE exposing GLES2 API doesn't support those.
    // TODO(oetuaho@nvidia.com): Remove these conversions once ANGLE has the
    // support.
    // http://code.google.com/p/angleproject/issues/detail?id=556
    switch (format) {
      case GL_RGBA:
        gl_internal_format = GL_RGBA;
        break;
      case GL_RGB:
        gl_internal_format = GL_RGB;
        break;
      default:
        break;
    }
  }

  if (gfx::g_version_info->is_es)
    return gl_internal_format;

  if (type == GL_FLOAT) {
    switch (format) {
      case GL_RGBA:
        gl_internal_format = GL_RGBA32F_ARB;
        break;
      case GL_RGB:
        gl_internal_format = GL_RGB32F_ARB;
        break;
      case GL_LUMINANCE_ALPHA:
        gl_internal_format = GL_LUMINANCE_ALPHA32F_ARB;
        break;
      case GL_LUMINANCE:
        gl_internal_format = GL_LUMINANCE32F_ARB;
        break;
      case GL_ALPHA:
        gl_internal_format = GL_ALPHA32F_ARB;
        break;
      default:
        NOTREACHED();
        break;
    }
  } else if (type == GL_HALF_FLOAT_OES) {
    switch (format) {
      case GL_RGBA:
        gl_internal_format = GL_RGBA16F_ARB;
        break;
      case GL_RGB:
        gl_internal_format = GL_RGB16F_ARB;
        break;
      case GL_LUMINANCE_ALPHA:
        gl_internal_format = GL_LUMINANCE_ALPHA16F_ARB;
        break;
      case GL_LUMINANCE:
        gl_internal_format = GL_LUMINANCE16F_ARB;
        break;
      case GL_ALPHA:
        gl_internal_format = GL_ALPHA16F_ARB;
        break;
      default:
        NOTREACHED();
        break;
    }
  }
  return gl_internal_format;
}

static inline GLenum GetTexType(GLenum type) {
   if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
     if (type == GL_HALF_FLOAT_OES)
       return GL_HALF_FLOAT_ARB;
   }
   return type;
}

static void GL_BINDING_CALL CustomTexImage2D(
    GLenum target, GLint level, GLint internalformat,
    GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type,
    const void* pixels) {
  GLenum gl_internal_format = GetTexInternalFormat(
      internalformat, format, type);
  GLenum gl_type = GetTexType(type);
  g_driver_gl.orig_fn.glTexImage2DFn(
      target, level, gl_internal_format, width, height, border, format, gl_type,
      pixels);
}

static void GL_BINDING_CALL CustomTexSubImage2D(
      GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width,
      GLsizei height, GLenum format, GLenum type, const void* pixels) {
  GLenum gl_type = GetTexType(type);
  g_driver_gl.orig_fn.glTexSubImage2DFn(
      target, level, xoffset, yoffset, width, height, format, gl_type, pixels);
}

static void GL_BINDING_CALL CustomTexStorage2DEXT(
    GLenum target, GLsizei levels, GLenum internalformat, GLsizei width,
    GLsizei height) {
  GLenum gl_internal_format = GetInternalFormat(internalformat);
  g_driver_gl.orig_fn.glTexStorage2DEXTFn(
      target, levels, gl_internal_format, width, height);
}

static void GL_BINDING_CALL CustomRenderbufferStorageEXT(
    GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
  GLenum gl_internal_format = GetInternalFormat(internalformat);
  g_driver_gl.orig_fn.glRenderbufferStorageEXTFn(
      target, gl_internal_format, width, height);
}

// The ANGLE and IMG variants of glRenderbufferStorageMultisample currently do
// not support BGRA render buffers so only the EXT one is customized. If
// GL_CHROMIUM_renderbuffer_format_BGRA8888 support is added to ANGLE then the
// ANGLE version should also be customized.
static void GL_BINDING_CALL CustomRenderbufferStorageMultisampleEXT(
    GLenum target, GLsizei samples, GLenum internalformat, GLsizei width,
    GLsizei height) {
  GLenum gl_internal_format = GetInternalFormat(internalformat);
  g_driver_gl.orig_fn.glRenderbufferStorageMultisampleEXTFn(
      target, samples, gl_internal_format, width, height);
}

}  // anonymous namespace

void DriverGL::InitializeCustomDynamicBindings(GLContext* context) {
  InitializeDynamicBindings(context);

  DCHECK(orig_fn.glTexImage2DFn == NULL);
  orig_fn.glTexImage2DFn = fn.glTexImage2DFn;
  fn.glTexImage2DFn =
      reinterpret_cast<glTexImage2DProc>(CustomTexImage2D);

  DCHECK(orig_fn.glTexSubImage2DFn == NULL);
  orig_fn.glTexSubImage2DFn = fn.glTexSubImage2DFn;
  fn.glTexSubImage2DFn =
      reinterpret_cast<glTexSubImage2DProc>(CustomTexSubImage2D);

  DCHECK(orig_fn.glTexStorage2DEXTFn == NULL);
  orig_fn.glTexStorage2DEXTFn = fn.glTexStorage2DEXTFn;
  fn.glTexStorage2DEXTFn =
      reinterpret_cast<glTexStorage2DEXTProc>(CustomTexStorage2DEXT);

  DCHECK(orig_fn.glRenderbufferStorageEXTFn == NULL);
  orig_fn.glRenderbufferStorageEXTFn = fn.glRenderbufferStorageEXTFn;
  fn.glRenderbufferStorageEXTFn =
      reinterpret_cast<glRenderbufferStorageEXTProc>(
      CustomRenderbufferStorageEXT);

  DCHECK(orig_fn.glRenderbufferStorageMultisampleEXTFn == NULL);
  orig_fn.glRenderbufferStorageMultisampleEXTFn =
      fn.glRenderbufferStorageMultisampleEXTFn;
  fn.glRenderbufferStorageMultisampleEXTFn =
      reinterpret_cast<glRenderbufferStorageMultisampleEXTProc>(
      CustomRenderbufferStorageMultisampleEXT);
}

static void GL_BINDING_CALL NullDrawClearFn(GLbitfield mask) {
  if (!g_driver_gl.null_draw_bindings_enabled)
    g_driver_gl.orig_fn.glClearFn(mask);
}

static void GL_BINDING_CALL
NullDrawDrawArraysFn(GLenum mode, GLint first, GLsizei count) {
  if (!g_driver_gl.null_draw_bindings_enabled)
    g_driver_gl.orig_fn.glDrawArraysFn(mode, first, count);
}

static void GL_BINDING_CALL NullDrawDrawElementsFn(GLenum mode,
                                                   GLsizei count,
                                                   GLenum type,
                                                   const void* indices) {
  if (!g_driver_gl.null_draw_bindings_enabled)
    g_driver_gl.orig_fn.glDrawElementsFn(mode, count, type, indices);
}

void DriverGL::InitializeNullDrawBindings() {
  DCHECK(orig_fn.glClearFn == NULL);
  orig_fn.glClearFn = fn.glClearFn;
  fn.glClearFn = NullDrawClearFn;

  DCHECK(orig_fn.glDrawArraysFn == NULL);
  orig_fn.glDrawArraysFn = fn.glDrawArraysFn;
  fn.glDrawArraysFn = NullDrawDrawArraysFn;

  DCHECK(orig_fn.glDrawElementsFn == NULL);
  orig_fn.glDrawElementsFn = fn.glDrawElementsFn;
  fn.glDrawElementsFn = NullDrawDrawElementsFn;

  null_draw_bindings_enabled = true;
}

bool DriverGL::HasInitializedNullDrawBindings() {
  return orig_fn.glClearFn != NULL && orig_fn.glDrawArraysFn != NULL &&
         orig_fn.glDrawElementsFn != NULL;
}

bool DriverGL::SetNullDrawBindingsEnabled(bool enabled) {
  DCHECK(orig_fn.glClearFn != NULL);
  DCHECK(orig_fn.glDrawArraysFn != NULL);
  DCHECK(orig_fn.glDrawElementsFn != NULL);

  bool before = null_draw_bindings_enabled;
  null_draw_bindings_enabled = enabled;
  return before;
}

void InitializeStaticGLBindingsGL() {
  g_current_gl_context_tls = new base::ThreadLocalPointer<GLApi>;
  g_driver_gl.InitializeStaticBindings();
  if (!g_real_gl) {
    g_real_gl = new RealGLApi();
    g_trace_gl = new TraceGLApi(g_real_gl);
    g_no_context_gl = new NoContextGLApi();
  }
  g_real_gl->Initialize(&g_driver_gl);
  g_gl = g_real_gl;
  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kEnableGPUServiceTracing)) {
    g_gl = g_trace_gl;
  }
  SetGLToRealGLApi();
}

GLApi* GetCurrentGLApi() {
  return g_current_gl_context_tls->Get();
}

void SetGLApi(GLApi* api) {
  g_current_gl_context_tls->Set(api);
}

void SetGLToRealGLApi() {
  SetGLApi(g_gl);
}

void SetGLApiToNoContext() {
  SetGLApi(g_no_context_gl);
}

const GLVersionInfo* GetGLVersionInfo() {
  return g_version_info;
}

void InitializeDynamicGLBindingsGL(GLContext* context) {
  g_driver_gl.InitializeCustomDynamicBindings(context);
  DCHECK(context && context->IsCurrent(NULL) && !g_version_info);
  g_version_info = new GLVersionInfo(context->GetGLVersion().c_str(),
      context->GetGLRenderer().c_str());
}

void InitializeDebugGLBindingsGL() {
  g_driver_gl.InitializeDebugBindings();
}

void InitializeNullDrawGLBindingsGL() {
  g_driver_gl.InitializeNullDrawBindings();
}

bool HasInitializedNullDrawGLBindingsGL() {
  return g_driver_gl.HasInitializedNullDrawBindings();
}

bool SetNullDrawGLBindingsEnabledGL(bool enabled) {
  return g_driver_gl.SetNullDrawBindingsEnabled(enabled);
}

void ClearGLBindingsGL() {
  if (g_real_gl) {
    delete g_real_gl;
    g_real_gl = NULL;
  }
  if (g_trace_gl) {
    delete g_trace_gl;
    g_trace_gl = NULL;
  }
  if (g_no_context_gl) {
    delete g_no_context_gl;
    g_no_context_gl = NULL;
  }
  g_gl = NULL;
  g_driver_gl.ClearBindings();
  if (g_current_gl_context_tls) {
    delete g_current_gl_context_tls;
    g_current_gl_context_tls = NULL;
  }
  if (g_version_info) {
    delete g_version_info;
    g_version_info = NULL;
  }
}

GLApi::GLApi() {
}

GLApi::~GLApi() {
  if (GetCurrentGLApi() == this)
    SetGLApi(NULL);
}

GLApiBase::GLApiBase()
    : driver_(NULL) {
}

GLApiBase::~GLApiBase() {
}

void GLApiBase::InitializeBase(DriverGL* driver) {
  driver_ = driver;
}

RealGLApi::RealGLApi() {
}

RealGLApi::~RealGLApi() {
}

void RealGLApi::Initialize(DriverGL* driver) {
  InitializeBase(driver);
}

void RealGLApi::glFlushFn() {
  GLApiBase::glFlushFn();
}

void RealGLApi::glFinishFn() {
  GLApiBase::glFinishFn();
}

TraceGLApi::~TraceGLApi() {
}

NoContextGLApi::NoContextGLApi() {
}

NoContextGLApi::~NoContextGLApi() {
}

VirtualGLApi::VirtualGLApi()
    : real_context_(NULL),
      current_context_(NULL) {
}

VirtualGLApi::~VirtualGLApi() {
}

void VirtualGLApi::Initialize(DriverGL* driver, GLContext* real_context) {
  InitializeBase(driver);
  real_context_ = real_context;

  DCHECK(real_context->IsCurrent(NULL));
  std::string ext_string(
      reinterpret_cast<const char*>(driver_->fn.glGetStringFn(GL_EXTENSIONS)));
  std::vector<std::string> ext;
  Tokenize(ext_string, " ", &ext);

  std::vector<std::string>::iterator it;
  // We can't support GL_EXT_occlusion_query_boolean which is
  // based on GL_ARB_occlusion_query without a lot of work virtualizing
  // queries.
  it = std::find(ext.begin(), ext.end(), "GL_EXT_occlusion_query_boolean");
  if (it != ext.end())
    ext.erase(it);

  extensions_ = JoinString(ext, " ");
}

bool VirtualGLApi::MakeCurrent(GLContext* virtual_context, GLSurface* surface) {
  bool switched_contexts = g_current_gl_context_tls->Get() != this;
  GLSurface* current_surface = GLSurface::GetCurrent();
  if (switched_contexts || surface != current_surface) {
    // MakeCurrent 'lite' path that avoids potentially expensive MakeCurrent()
    // calls if the GLSurface uses the same underlying surface or renders to
    // an FBO.
    if (switched_contexts || !current_surface ||
        !virtual_context->IsCurrent(surface)) {
      if (!real_context_->MakeCurrent(surface)) {
        return false;
      }
    }
  }

  DCHECK_EQ(real_context_, GLContext::GetRealCurrent());
  DCHECK(real_context_->IsCurrent(NULL));
  DCHECK(virtual_context->IsCurrent(surface));

  if (switched_contexts || virtual_context != current_context_) {
#if DCHECK_IS_ON()
    GLenum error = glGetErrorFn();
    // Accepting a context loss error here enables using debug mode to work on
    // context loss handling in virtual context mode.
    // There should be no other errors from the previous context leaking into
    // the new context.
    DCHECK(error == GL_NO_ERROR || error == GL_CONTEXT_LOST_KHR);
#endif

    // Set all state that is different from the real state
    GLApi* temp = GetCurrentGLApi();
    SetGLToRealGLApi();
    if (virtual_context->GetGLStateRestorer()->IsInitialized()) {
      virtual_context->GetGLStateRestorer()->RestoreState(
          (current_context_ && !switched_contexts)
              ? current_context_->GetGLStateRestorer()
              : NULL);
    }
    SetGLApi(temp);
    current_context_ = virtual_context;
  }
  SetGLApi(this);

  virtual_context->SetCurrent(surface);
  if (!surface->OnMakeCurrent(virtual_context)) {
    LOG(ERROR) << "Could not make GLSurface current.";
    return false;
  }
  return true;
}

void VirtualGLApi::OnReleaseVirtuallyCurrent(GLContext* virtual_context) {
  if (current_context_ == virtual_context)
    current_context_ = NULL;
}

const GLubyte* VirtualGLApi::glGetStringFn(GLenum name) {
  switch (name) {
    case GL_EXTENSIONS:
      return reinterpret_cast<const GLubyte*>(extensions_.c_str());
    default:
      return driver_->fn.glGetStringFn(name);
  }
}

void VirtualGLApi::glFlushFn() {
  GLApiBase::glFlushFn();
}

void VirtualGLApi::glFinishFn() {
  GLApiBase::glFinishFn();
}

ScopedSetGLToRealGLApi::ScopedSetGLToRealGLApi()
    : old_gl_api_(GetCurrentGLApi()) {
  SetGLToRealGLApi();
}

ScopedSetGLToRealGLApi::~ScopedSetGLToRealGLApi() {
  SetGLApi(old_gl_api_);
}

}  // namespace gfx
