// 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_glx_api_implementation.h"

#include "base/command_line.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "ui/gl/gl_implementation.h"

namespace gl {

RealGLXApi* g_real_glx;

void InitializeStaticGLBindingsGLX() {
  g_driver_glx.InitializeStaticBindings();
  if (!g_real_glx) {
    g_real_glx = new RealGLXApi();
  }
  g_real_glx->Initialize(&g_driver_glx);
  g_current_glx_context = g_real_glx;
  g_driver_glx.InitializeExtensionBindings();
}

void InitializeDebugGLBindingsGLX() {
  g_driver_glx.InitializeDebugBindings();
}

void ClearGLBindingsGLX() {
  if (g_real_glx) {
    delete g_real_glx;
    g_real_glx = NULL;
  }
  g_current_glx_context = NULL;
  g_driver_glx.ClearBindings();
}

GLXApi::GLXApi() {
}

GLXApi::~GLXApi() {
}

GLXApiBase::GLXApiBase()
    : driver_(NULL) {
}

GLXApiBase::~GLXApiBase() {
}

void GLXApiBase::InitializeBase(DriverGLX* driver) {
  driver_ = driver;
}

RealGLXApi::RealGLXApi() {
}

RealGLXApi::~RealGLXApi() {
}

void RealGLXApi::Initialize(DriverGLX* driver) {
  InitializeWithCommandLine(driver, base::CommandLine::ForCurrentProcess());
}

void RealGLXApi::InitializeWithCommandLine(DriverGLX* driver,
                                           base::CommandLine* command_line) {
  DCHECK(command_line);
  InitializeBase(driver);

  const std::string disabled_extensions = command_line->GetSwitchValueASCII(
      switches::kDisableGLExtensions);
  disabled_exts_.clear();
  filtered_exts_ = "";
  if (!disabled_extensions.empty()) {
    disabled_exts_ =
        base::SplitString(disabled_extensions, ", ;",
                          base::KEEP_WHITESPACE,
                          base::SPLIT_WANT_NONEMPTY);
  }
}

const char* RealGLXApi::glXQueryExtensionsStringFn(Display* dpy,
                                                   int screen) {
  if (filtered_exts_.size())
    return filtered_exts_.c_str();

  if (!driver_->fn.glXQueryExtensionsStringFn)
    return NULL;

  const char* str = GLXApiBase::glXQueryExtensionsStringFn(dpy, screen);
  if (!str)
    return NULL;

  filtered_exts_ = FilterGLExtensionList(str, disabled_exts_);
  return filtered_exts_.c_str();
}

TraceGLXApi::~TraceGLXApi() {
}

bool GetGLWindowSystemBindingInfoGLX(GLWindowSystemBindingInfo* info) {
  Display* display = glXGetCurrentDisplay();
  const int kDefaultScreen = 0;
  const char* vendor =
      glXQueryServerString(display, kDefaultScreen, GLX_VENDOR);
  const char* version =
      glXQueryServerString(display, kDefaultScreen, GLX_VERSION);
  const char* extensions =
      glXQueryServerString(display, kDefaultScreen, GLX_EXTENSIONS);
  *info = GLWindowSystemBindingInfo();
  if (vendor)
    info->vendor = vendor;
  if (version)
    info->version = version;
  if (extensions)
    info->extensions = extensions;
  info->direct_rendering = !!glXIsDirect(display, glXGetCurrentContext());
  return true;
}

}  // namespace gl
