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

#include "base/at_exit.h"
#include "base/base_paths.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/debug/trace_event.h"
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/native_library.h"
#include "base/path_service.h"
#include "base/strings/stringprintf.h"
#include "base/threading/thread_restrictions.h"
#include "base/win/windows_version.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_context_stub_with_extensions.h"
#include "ui/gl/gl_egl_api_implementation.h"
#include "ui/gl/gl_gl_api_implementation.h"
#include "ui/gl/gl_implementation.h"
#include "ui/gl/gl_osmesa_api_implementation.h"
#include "ui/gl/gl_surface_wgl.h"
#include "ui/gl/gl_wgl_api_implementation.h"

#if defined(ENABLE_SWIFTSHADER)
#include "software_renderer.h"
#endif

namespace gfx {

namespace {

// Version 43 is the latest version of D3DCompiler_nn.dll that works prior to
// Windows Vista.
const wchar_t kPreVistaD3DCompiler[] = L"D3DCompiler_43.dll";
const wchar_t kPostVistaD3DCompiler[] = L"D3DCompiler_46.dll";

void GL_BINDING_CALL MarshalClearDepthToClearDepthf(GLclampd depth) {
  glClearDepthf(static_cast<GLclampf>(depth));
}

void GL_BINDING_CALL MarshalDepthRangeToDepthRangef(GLclampd z_near,
                                                    GLclampd z_far) {
  glDepthRangef(static_cast<GLclampf>(z_near), static_cast<GLclampf>(z_far));
}

bool LoadD3DXLibrary(const base::FilePath& module_path,
                     const base::FilePath::StringType& name) {
  base::NativeLibrary library =
      base::LoadNativeLibrary(base::FilePath(name), NULL);
  if (!library) {
    library = base::LoadNativeLibrary(module_path.Append(name), NULL);
    if (!library) {
      DVLOG(1) << name << " not found.";
      return false;
    }
  }
  return true;
}

const unsigned char* AngleGetTraceCategoryEnabledFlag(const char* name) {
  return TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(name);
}

void AngleAddTraceEvent(char phase,
                        const unsigned char* category_group_enabled,
                        const char* name,
                        unsigned long long id,
                        int num_args,
                        const char** arg_names,
                        const unsigned char* arg_types,
                        const unsigned long long* arg_values,
                        unsigned char flags) {
  TRACE_EVENT_API_ADD_TRACE_EVENT(phase,
                                  category_group_enabled,
                                  name,
                                  id,
                                  num_args,
                                  arg_names,
                                  arg_types,
                                  arg_values,
                                  NULL,
                                  flags);
}

typedef const unsigned char* (*GetCategoryEnabledFlagFunc)(const char* name);
typedef void (*AddTraceEventFunc)(char phase,
                                  const unsigned char* categoryGroupEnabled,
                                  const char* name,
                                  unsigned long long id,
                                  int numArgs,
                                  const char** argNames,
                                  const unsigned char* argTypes,
                                  const unsigned long long* argValues,
                                  unsigned char flags);
typedef void (__stdcall *SetTraceFunctionPointersFunc)(
    GetCategoryEnabledFlagFunc get_category_enabled_flag,
    AddTraceEventFunc add_trace_event_func);

}  // namespace

void GetAllowedGLImplementations(std::vector<GLImplementation>* impls) {
  impls->push_back(kGLImplementationEGLGLES2);
  impls->push_back(kGLImplementationDesktopGL);
  impls->push_back(kGLImplementationOSMesaGL);
}

bool InitializeStaticGLBindings(GLImplementation implementation) {
  // Prevent reinitialization with a different implementation. Once the gpu
  // unit tests have initialized with kGLImplementationMock, we don't want to
  // later switch to another GL implementation.
  DCHECK_EQ(kGLImplementationNone, GetGLImplementation());

  // Allow the main thread or another to initialize these bindings
  // after instituting restrictions on I/O. Going forward they will
  // likely be used in the browser process on most platforms. The
  // one-time initialization cost is small, between 2 and 5 ms.
  base::ThreadRestrictions::ScopedAllowIO allow_io;

  switch (implementation) {
    case kGLImplementationOSMesaGL: {
      base::FilePath module_path;
      if (!PathService::Get(base::DIR_MODULE, &module_path)) {
        LOG(ERROR) << "PathService::Get failed.";
        return false;
      }

      base::NativeLibrary library = base::LoadNativeLibrary(
          module_path.Append(L"osmesa.dll"), NULL);
      if (!library) {
        DVLOG(1) << "osmesa.dll not found";
        return false;
      }

      GLGetProcAddressProc get_proc_address =
          reinterpret_cast<GLGetProcAddressProc>(
              base::GetFunctionPointerFromNativeLibrary(
                  library, "OSMesaGetProcAddress"));
      if (!get_proc_address) {
        DLOG(ERROR) << "OSMesaGetProcAddress not found.";
        base::UnloadNativeLibrary(library);
        return false;
      }

      SetGLGetProcAddressProc(get_proc_address);
      AddGLNativeLibrary(library);
      SetGLImplementation(kGLImplementationOSMesaGL);

      InitializeStaticGLBindingsGL();
      InitializeStaticGLBindingsOSMESA();
      break;
    }
    case kGLImplementationEGLGLES2: {
      base::FilePath module_path;
      if (!PathService::Get(base::DIR_MODULE, &module_path))
        return false;

      // Attempt to load the D3DX shader compiler using the default search path
      // and if that fails, using an absolute path. This is to ensure these DLLs
      // are loaded before ANGLE is loaded in case they are not in the default
      // search path. Prefer the post vista version.
      if (base::win::GetVersion() < base::win::VERSION_VISTA ||
          !LoadD3DXLibrary(module_path, kPostVistaD3DCompiler)) {
        LoadD3DXLibrary(module_path, kPreVistaD3DCompiler);
      }

      base::FilePath gles_path;
      const CommandLine* command_line = CommandLine::ForCurrentProcess();
      bool using_swift_shader =
          command_line->GetSwitchValueASCII(switches::kUseGL) == "swiftshader";
      if (using_swift_shader) {
        if (!command_line->HasSwitch(switches::kSwiftShaderPath))
          return false;
        gles_path =
            command_line->GetSwitchValuePath(switches::kSwiftShaderPath);
        // Preload library
        LoadLibrary(L"ddraw.dll");
      } else {
        gles_path = module_path;
      }

      // Load libglesv2.dll before libegl.dll because the latter is dependent on
      // the former and if there is another version of libglesv2.dll in the dll
      // search path, it will get loaded instead.
      base::NativeLibrary gles_library = base::LoadNativeLibrary(
          gles_path.Append(L"libglesv2.dll"), NULL);
      if (!gles_library) {
        DVLOG(1) << "libglesv2.dll not found";
        return false;
      }

      // When using EGL, first try eglGetProcAddress and then Windows
      // GetProcAddress on both the EGL and GLES2 DLLs.
      base::NativeLibrary egl_library = base::LoadNativeLibrary(
          gles_path.Append(L"libegl.dll"), NULL);
      if (!egl_library) {
        DVLOG(1) << "libegl.dll not found.";
        base::UnloadNativeLibrary(gles_library);
        return false;
      }

#if defined(ENABLE_SWIFTSHADER)
      if (using_swift_shader) {
        SetupSoftwareRenderer(gles_library);
      }
#endif

      if (!using_swift_shader) {
        SetTraceFunctionPointersFunc set_trace_function_pointers =
            reinterpret_cast<SetTraceFunctionPointersFunc>(
                base::GetFunctionPointerFromNativeLibrary(
                    gles_library, "SetTraceFunctionPointers"));
        if (set_trace_function_pointers) {
          set_trace_function_pointers(&AngleGetTraceCategoryEnabledFlag,
                                      &AngleAddTraceEvent);
        }
      }

      GLGetProcAddressProc get_proc_address =
          reinterpret_cast<GLGetProcAddressProc>(
              base::GetFunctionPointerFromNativeLibrary(
                  egl_library, "eglGetProcAddress"));
      if (!get_proc_address) {
        LOG(ERROR) << "eglGetProcAddress not found.";
        base::UnloadNativeLibrary(egl_library);
        base::UnloadNativeLibrary(gles_library);
        return false;
      }

      SetGLGetProcAddressProc(get_proc_address);
      AddGLNativeLibrary(egl_library);
      AddGLNativeLibrary(gles_library);
      SetGLImplementation(kGLImplementationEGLGLES2);

      InitializeStaticGLBindingsGL();
      InitializeStaticGLBindingsEGL();

      // These two functions take single precision float rather than double
      // precision float parameters in GLES.
      ::gfx::g_driver_gl.fn.glClearDepthFn = MarshalClearDepthToClearDepthf;
      ::gfx::g_driver_gl.fn.glDepthRangeFn = MarshalDepthRangeToDepthRangef;
      break;
    }
    case kGLImplementationDesktopGL: {
      base::NativeLibrary library = base::LoadNativeLibrary(
          base::FilePath(L"opengl32.dll"), NULL);
      if (!library) {
        DVLOG(1) << "opengl32.dll not found";
        return false;
      }

      GLGetProcAddressProc get_proc_address =
          reinterpret_cast<GLGetProcAddressProc>(
              base::GetFunctionPointerFromNativeLibrary(
                  library, "wglGetProcAddress"));
      if (!get_proc_address) {
        LOG(ERROR) << "wglGetProcAddress not found.";
        base::UnloadNativeLibrary(library);
        return false;
      }

      SetGLGetProcAddressProc(get_proc_address);
      AddGLNativeLibrary(library);
      SetGLImplementation(kGLImplementationDesktopGL);

      // Initialize GL surface and get some functions needed for the context
      // creation below.
      if (!GLSurfaceWGL::InitializeOneOff()) {
        LOG(ERROR) << "GLSurfaceWGL::InitializeOneOff failed.";
        return false;
      }
      wglCreateContextProc wglCreateContextFn =
          reinterpret_cast<wglCreateContextProc>(
              GetGLProcAddress("wglCreateContext"));
      wglDeleteContextProc wglDeleteContextFn =
          reinterpret_cast<wglDeleteContextProc>(
              GetGLProcAddress("wglDeleteContext"));
      wglMakeCurrentProc wglMakeCurrentFn =
          reinterpret_cast<wglMakeCurrentProc>(
              GetGLProcAddress("wglMakeCurrent"));

      // Create a temporary GL context to bind to entry points. This is needed
      // because wglGetProcAddress is specified to return NULL for all queries
      // if a context is not current in MSDN documentation, and the static
      // bindings may contain functions that need to be queried with
      // wglGetProcAddress. OpenGL wiki further warns that other error values
      // than NULL could also be returned from wglGetProcAddress on some
      // implementations, so we need to clear the WGL bindings and reinitialize
      // them after the context creation.
      HGLRC gl_context = wglCreateContextFn(GLSurfaceWGL::GetDisplayDC());
      if (!gl_context) {
        LOG(ERROR) << "Failed to create temporary context.";
        return false;
      }
      if (!wglMakeCurrentFn(GLSurfaceWGL::GetDisplayDC(), gl_context)) {
        LOG(ERROR) << "Failed to make temporary GL context current.";
        wglDeleteContextFn(gl_context);
        return false;
      }

      InitializeStaticGLBindingsGL();
      InitializeStaticGLBindingsWGL();

      wglMakeCurrent(NULL, NULL);
      wglDeleteContext(gl_context);

      break;
    }
    case kGLImplementationMockGL: {
      SetGLImplementation(kGLImplementationMockGL);
      InitializeStaticGLBindingsGL();
      break;
    }
    default:
      return false;
  }

  return true;
}

bool InitializeDynamicGLBindings(GLImplementation implementation,
    GLContext* context) {
  switch (implementation) {
    case kGLImplementationOSMesaGL:
      InitializeDynamicGLBindingsGL(context);
      InitializeDynamicGLBindingsOSMESA(context);
      break;
    case kGLImplementationEGLGLES2:
      InitializeDynamicGLBindingsGL(context);
      InitializeDynamicGLBindingsEGL(context);
      break;
    case kGLImplementationDesktopGL:
      InitializeDynamicGLBindingsGL(context);
      InitializeDynamicGLBindingsWGL(context);
      break;
    case kGLImplementationMockGL:
      if (!context) {
        scoped_refptr<GLContextStubWithExtensions> mock_context(
            new GLContextStubWithExtensions());
        mock_context->SetGLVersionString("3.0");
        InitializeDynamicGLBindingsGL(mock_context.get());
      } else
        InitializeDynamicGLBindingsGL(context);
      break;
    default:
      return false;
  }

  return true;
}

void InitializeDebugGLBindings() {
  InitializeDebugGLBindingsEGL();
  InitializeDebugGLBindingsGL();
  InitializeDebugGLBindingsOSMESA();
  InitializeDebugGLBindingsWGL();
}

void ClearGLBindings() {
  ClearGLBindingsEGL();
  ClearGLBindingsGL();
  ClearGLBindingsOSMESA();
  ClearGLBindingsWGL();
  SetGLImplementation(kGLImplementationNone);
  UnloadGLNativeLibraries();
}

bool GetGLWindowSystemBindingInfo(GLWindowSystemBindingInfo* info) {
  switch (GetGLImplementation()) {
    case kGLImplementationDesktopGL:
      return GetGLWindowSystemBindingInfoWGL(info);
    case kGLImplementationEGLGLES2:
      return GetGLWindowSystemBindingInfoEGL(info);
    default:
      return false;
  }
}

}  // namespace gfx
