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

#include "base/memory/ptr_util.h"
#include "base/stl_util.h"
#include "base/strings/string_split.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 gl {

// The GL state for when no context is bound
static CurrentGL* g_no_context_current_gl = nullptr;

// If the null draw bindings are currently enabled.
// TODO: Consider adding a new GLApi that no-ops these functions
static bool g_null_draw_bindings_enabled = false;

// If the GL debug bindings are enabled.
static bool g_debug_bindings_enabled = false;

namespace {

static inline GLenum GetInternalFormat(const GLVersionInfo* version,
                                       GLenum internal_format) {
  if (!version->is_es) {
    if (internal_format == GL_BGRA_EXT || internal_format == GL_BGRA8_EXT)
      return GL_RGBA8;
  }
  if (version->is_es3 && version->is_mesa) {
    // Mesa bug workaround: Mipmapping does not work when using GL_BGRA_EXT
    if (internal_format == GL_BGRA_EXT)
      return GL_RGBA;
  }
  return internal_format;
}

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

  // g_version_info must be initialized when this function is bound.
  if (version->is_es3) {
    if (internal_format == GL_RED_EXT) {
      // GL_EXT_texture_rg case in ES2.
      switch (type) {
        case GL_UNSIGNED_BYTE:
          gl_internal_format = GL_R8_EXT;
          break;
        case GL_UNSIGNED_SHORT:
          gl_internal_format = GL_R16_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 (internal_format == GL_RG_EXT) {
      // GL_EXT_texture_rg case in ES2.
      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 && version->is_angle && version->is_es &&
      version->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 (version->IsAtLeastGL(2, 1) || version->IsAtLeastGLES(3, 0)) {
    switch (internal_format) {
      case GL_SRGB_EXT:
        gl_internal_format = GL_SRGB8;
        break;
      case GL_SRGB_ALPHA_EXT:
        gl_internal_format = GL_SRGB8_ALPHA8;
        break;
      default:
        break;
    }
  }

  if (version->is_es2)
    return gl_internal_format;

  // For ES3, use sized float/half_float internal formats whenever posssible.
  if (type == GL_FLOAT) {
    switch (internal_format) {
      // We need to map all the unsized internal formats from ES2 clients.
      case GL_RGBA:
        gl_internal_format = GL_RGBA32F;
        break;
      case GL_RGB:
        gl_internal_format = GL_RGB32F;
        break;
      case GL_LUMINANCE_ALPHA:
        if (!version->is_es)
          gl_internal_format = GL_LUMINANCE_ALPHA32F_ARB;
        break;
      case GL_LUMINANCE:
        if (!version->is_es)
          gl_internal_format = GL_LUMINANCE32F_ARB;
        break;
      case GL_ALPHA:
        if (!version->is_es)
          gl_internal_format = GL_ALPHA32F_ARB;
        break;
      // RED and RG are reached here because on Desktop GL core profile,
      // LUMINANCE/ALPHA formats are emulated through RED and RG in Chrome.
      case GL_RED:
        gl_internal_format = GL_R32F;
        break;
      case GL_RG:
        gl_internal_format = GL_RG32F;
        break;
      default:
        // We can't assert here because if the client context is ES3,
        // all sized internal_format will reach here.
        break;
    }
  } else if (type == GL_HALF_FLOAT_OES) {
    switch (internal_format) {
      case GL_RGBA:
        gl_internal_format = GL_RGBA16F;
        break;
      case GL_RGB:
        gl_internal_format = GL_RGB16F;
        break;
      case GL_LUMINANCE_ALPHA:
        if (!version->is_es)
          gl_internal_format = GL_LUMINANCE_ALPHA16F_ARB;
        break;
      case GL_LUMINANCE:
        if (!version->is_es)
          gl_internal_format = GL_LUMINANCE16F_ARB;
        break;
      case GL_ALPHA:
        if (!version->is_es)
          gl_internal_format = GL_ALPHA16F_ARB;
        break;
      // RED and RG are reached here because on Desktop GL core profile,
      // LUMINANCE/ALPHA formats are emulated through RED and RG in Chrome.
      case GL_RED:
        gl_internal_format = GL_R16F;
        break;
      case GL_RG:
        gl_internal_format = GL_RG16F;
        break;
      default:
        NOTREACHED();
        break;
    }
  }

  return gl_internal_format;
}

static inline GLenum GetTexFormat(const GLVersionInfo* version, GLenum format) {
  GLenum gl_format = format;

  if (version->IsAtLeastGL(2, 1) || version->IsAtLeastGLES(3, 0)) {
    switch (format) {
      case GL_SRGB_EXT:
        gl_format = GL_RGB;
        break;
      case GL_SRGB_ALPHA_EXT:
        gl_format = GL_RGBA;
        break;
      default:
        break;
    }
  }

  return gl_format;
}

static inline GLenum GetPixelType(const GLVersionInfo* version,
                                  GLenum type,
                                  GLenum format) {
  if (!version->is_es2) {
    if (type == GL_HALF_FLOAT_OES) {
      if (version->is_es) {
        // For ES3+, use HALF_FLOAT instead of HALF_FLOAT_OES whenever possible.
        switch (format) {
          case GL_LUMINANCE:
          case GL_LUMINANCE_ALPHA:
          case GL_ALPHA:
            return type;
          default:
            break;
        }
      }
      return GL_HALF_FLOAT;
    }
  }
  return type;
}

}  // anonymous namespace

void InitializeStaticGLBindingsGL() {
  g_current_gl_context_tls = new base::ThreadLocalPointer<CurrentGL>;
  g_no_context_current_gl = new CurrentGL;
  g_no_context_current_gl->Api = new NoContextGLApi;
}

void ClearBindingsGL() {
  if (g_no_context_current_gl) {
    delete g_no_context_current_gl->Api;
    delete g_no_context_current_gl->Driver;
    delete g_no_context_current_gl->Version;
    delete g_no_context_current_gl;
    g_no_context_current_gl = nullptr;
  }

  if (g_current_gl_context_tls) {
    delete g_current_gl_context_tls;
    g_current_gl_context_tls = nullptr;
  }
}

void InitializeDebugGLBindingsGL() {
  g_debug_bindings_enabled = true;
}

bool GetDebugGLBindingsInitializedGL() {
  return g_debug_bindings_enabled;
}

bool SetNullDrawGLBindingsEnabled(bool enabled) {
  bool old_value = g_null_draw_bindings_enabled;
  g_null_draw_bindings_enabled = enabled;
  return old_value;
}

bool GetNullDrawBindingsEnabled() {
  return g_null_draw_bindings_enabled;
}

void SetCurrentGL(CurrentGL* current) {
  CurrentGL* new_current = current ? current : g_no_context_current_gl;
  g_current_gl_context_tls->Set(new_current);
}

GLApi::GLApi() {
}

GLApi::~GLApi() {
}

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::glGetIntegervFn(GLenum pname, GLint* params) {
  if (pname == GL_NUM_EXTENSIONS && disabled_exts_.size()) {
    InitializeFilteredExtensionsIfNeeded();
    *params = static_cast<GLint>(filtered_exts_.size());
  } else {
    GLApiBase::glGetIntegervFn(pname, params);
  }
}

const GLubyte* RealGLApi::glGetStringFn(GLenum name) {
  if (name == GL_EXTENSIONS && disabled_exts_.size()) {
    InitializeFilteredExtensionsIfNeeded();
    return reinterpret_cast<const GLubyte*>(filtered_exts_str_.c_str());
  }
  return GLApiBase::glGetStringFn(name);
}

const GLubyte* RealGLApi::glGetStringiFn(GLenum name, GLuint index) {
  if (name == GL_EXTENSIONS && disabled_exts_.size()) {
    InitializeFilteredExtensionsIfNeeded();
    if (index >= filtered_exts_.size()) {
      return nullptr;
    }
    return reinterpret_cast<const GLubyte*>(filtered_exts_[index].c_str());
  }
  return GLApiBase::glGetStringiFn(name, index);
}

void RealGLApi::glTexImage2DFn(GLenum target,
                               GLint level,
                               GLint internalformat,
                               GLsizei width,
                               GLsizei height,
                               GLint border,
                               GLenum format,
                               GLenum type,
                               const void* pixels) {
  GLenum gl_internal_format =
      GetTexInternalFormat(version_.get(), internalformat, format, type);
  GLenum gl_format = GetTexFormat(version_.get(), format);
  GLenum gl_type = GetPixelType(version_.get(), type, format);

  // TODO(yizhou): Check if cubemap, 3d texture or texture2d array has the same
  // bug on intel mac.
  if (gl_workarounds_.reset_teximage2d_base_level && target == GL_TEXTURE_2D) {
    GLint base_level = 0;
    GLApiBase::glGetTexParameterivFn(target, GL_TEXTURE_BASE_LEVEL,
                                     &base_level);
    if (base_level) {
      GLApiBase::glTexParameteriFn(target, GL_TEXTURE_BASE_LEVEL, 0);
      GLApiBase::glTexImage2DFn(target, level, gl_internal_format, width,
                                height, border, gl_format, gl_type, pixels);
      GLApiBase::glTexParameteriFn(target, GL_TEXTURE_BASE_LEVEL, base_level);
      return;
    }
  }
  GLApiBase::glTexImage2DFn(target, level, gl_internal_format, width, height,
                            border, gl_format, gl_type, pixels);
}

void RealGLApi::glTexSubImage2DFn(GLenum target,
                                  GLint level,
                                  GLint xoffset,
                                  GLint yoffset,
                                  GLsizei width,
                                  GLsizei height,
                                  GLenum format,
                                  GLenum type,
                                  const void* pixels) {
  GLenum gl_format = GetTexFormat(version_.get(), format);
  GLenum gl_type = GetPixelType(version_.get(), type, format);
  GLApiBase::glTexSubImage2DFn(target, level, xoffset, yoffset, width, height,
                               gl_format, gl_type, pixels);
}

void RealGLApi::glTexStorage2DEXTFn(GLenum target,
                                    GLsizei levels,
                                    GLenum internalformat,
                                    GLsizei width,
                                    GLsizei height) {
  GLenum gl_internal_format = GetInternalFormat(version_.get(), internalformat);
  GLApiBase::glTexStorage2DEXTFn(target, levels, gl_internal_format, width,
                                 height);
}

void RealGLApi::glRenderbufferStorageEXTFn(GLenum target,
                                           GLenum internalformat,
                                           GLsizei width,
                                           GLsizei height) {
  GLenum gl_internal_format = GetInternalFormat(version_.get(), internalformat);
  GLApiBase::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.
void RealGLApi::glRenderbufferStorageMultisampleEXTFn(GLenum target,
                                                      GLsizei samples,
                                                      GLenum internalformat,
                                                      GLsizei width,
                                                      GLsizei height) {
  GLenum gl_internal_format = GetInternalFormat(version_.get(), internalformat);
  GLApiBase::glRenderbufferStorageMultisampleEXTFn(
      target, samples, gl_internal_format, width, height);
}

void RealGLApi::glRenderbufferStorageMultisampleFn(GLenum target,
                                                   GLsizei samples,
                                                   GLenum internalformat,
                                                   GLsizei width,
                                                   GLsizei height) {
  GLenum gl_internal_format = GetInternalFormat(version_.get(), internalformat);
  GLApiBase::glRenderbufferStorageMultisampleFn(
      target, samples, gl_internal_format, width, height);
}

void RealGLApi::glReadPixelsFn(GLint x,
                               GLint y,
                               GLsizei width,
                               GLsizei height,
                               GLenum format,
                               GLenum type,
                               void* pixels) {
  GLenum gl_type = GetPixelType(version_.get(), type, format);
  GLApiBase::glReadPixelsFn(x, y, width, height, format, gl_type, pixels);
}

void RealGLApi::glClearFn(GLbitfield mask) {
  if (!g_null_draw_bindings_enabled)
    GLApiBase::glClearFn(mask);
}

void RealGLApi::glClearColorFn(GLclampf red,
                               GLclampf green,
                               GLclampf blue,
                               GLclampf alpha) {
  if (gl_workarounds_.clear_to_zero_or_one_broken && (1 == red || 0 == red) &&
      (1 == green || 0 == green) && (1 == blue || 0 == blue) &&
      (1 == alpha || 0 == alpha)) {
    if (1 == alpha)
      alpha = 2;
    else
      alpha = -1;
  }
  GLApiBase::glClearColorFn(red, green, blue, alpha);
}

void RealGLApi::glDrawArraysFn(GLenum mode, GLint first, GLsizei count) {
  if (!g_null_draw_bindings_enabled)
    GLApiBase::glDrawArraysFn(mode, first, count);
}

void RealGLApi::glDrawElementsFn(GLenum mode,
                                 GLsizei count,
                                 GLenum type,
                                 const void* indices) {
  if (!g_null_draw_bindings_enabled)
    GLApiBase::glDrawElementsFn(mode, count, type, indices);
}

void RealGLApi::glClearDepthFn(GLclampd depth) {
  // OpenGL ES only has glClearDepthf, forward the parameters from glClearDepth.
  // Many mock tests expect only glClearDepth is called so don't make the
  // interception when testing with mocks.
  if (version_->is_es && GetGLImplementation() != kGLImplementationMockGL) {
    DCHECK(driver_->fn.glClearDepthfFn);
    GLApiBase::glClearDepthfFn(static_cast<GLclampf>(depth));
  } else {
    DCHECK(driver_->fn.glClearDepthFn);
    GLApiBase::glClearDepthFn(depth);
  }
}

void RealGLApi::glDepthRangeFn(GLclampd z_near, GLclampd z_far) {
  // OpenGL ES only has glDepthRangef, forward the parameters from glDepthRange.
  // Many mock tests expect only glDepthRange is called so don't make the
  // interception when testing with mocks.
  if (version_->is_es && GetGLImplementation() != kGLImplementationMockGL) {
    DCHECK(driver_->fn.glDepthRangefFn);
    GLApiBase::glDepthRangefFn(static_cast<GLclampf>(z_near),
                               static_cast<GLclampf>(z_far));
  } else {
    DCHECK(driver_->fn.glDepthRangeFn);
    GLApiBase::glDepthRangeFn(z_near, z_far);
  }
}

void RealGLApi::InitializeFilteredExtensionsIfNeeded() {
  DCHECK(disabled_exts_.size());
  if (filtered_exts_.size())
    return;
  DCHECK(filtered_exts_str_.empty());
  if (WillUseGLGetStringForExtensions(this)) {
    filtered_exts_str_ = FilterGLExtensionList(
        reinterpret_cast<const char*>(GLApiBase::glGetStringFn(GL_EXTENSIONS)),
        disabled_exts_);
    filtered_exts_ = base::SplitString(
        filtered_exts_str_, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
  } else {
    GLint num_extensions = 0;
    GLApiBase::glGetIntegervFn(GL_NUM_EXTENSIONS, &num_extensions);
    for (GLint i = 0; i < num_extensions; ++i) {
      const char* gl_extension = reinterpret_cast<const char*>(
          GLApiBase::glGetStringiFn(GL_EXTENSIONS, i));
      DCHECK(gl_extension);
      if (!base::ContainsValue(disabled_exts_, gl_extension))
        filtered_exts_.push_back(gl_extension);
    }
    filtered_exts_str_ = base::JoinString(filtered_exts_, " ");
  }
}

void RealGLApi::SetDisabledExtensions(const std::string& disabled_extensions) {
  ClearCachedGLExtensions();
  disabled_exts_.clear();
  if (disabled_extensions.empty())
    return;
  disabled_exts_ =
      base::SplitString(disabled_extensions, ", ;", base::KEEP_WHITESPACE,
                        base::SPLIT_WANT_NONEMPTY);
  DCHECK(disabled_exts_.size());
}

void RealGLApi::ClearCachedGLExtensions() {
  filtered_exts_.clear();
  filtered_exts_str_.clear();
}

void RealGLApi::set_gl_workarounds(const GLWorkarounds& workarounds) {
  gl_workarounds_ = workarounds;
}

void RealGLApi::set_version(std::unique_ptr<GLVersionInfo> version) {
  version_ = std::move(version);
}

TraceGLApi::~TraceGLApi() {
}

DebugGLApi::DebugGLApi(GLApi* gl_api) : gl_api_(gl_api) {}

DebugGLApi::~DebugGLApi() {}

NoContextGLApi::NoContextGLApi() {
}

NoContextGLApi::~NoContextGLApi() {
}

}  // namespace gl
