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

#include <memory>

#include "base/logging.h"
#include "base/trace_event/trace_event.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_gl_api_implementation.h"
#include "ui/gl/gl_wgl_api_implementation.h"

namespace gl {

namespace {
const PIXELFORMATDESCRIPTOR kPixelFormatDescriptor = {
  sizeof(kPixelFormatDescriptor),    // Size of structure.
  1,                       // Default version.
  PFD_DRAW_TO_WINDOW |     // Window drawing support.
  PFD_SUPPORT_OPENGL |     // OpenGL support.
  PFD_DOUBLEBUFFER,        // Double buffering support (not stereo).
  PFD_TYPE_RGBA,           // RGBA color mode (not indexed).
  24,                      // 24 bit color mode.
  0, 0, 0, 0, 0, 0,        // Don't set RGB bits & shifts.
  8, 0,                    // 8 bit alpha
  0,                       // No accumulation buffer.
  0, 0, 0, 0,              // Ignore accumulation bits.
  0,                       // no z-buffer.
  0,                       // no stencil buffer.
  0,                       // No aux buffer.
  PFD_MAIN_PLANE,          // Main drawing plane (not overlay).
  0,                       // Reserved.
  0, 0, 0,                 // Layer masks ignored.
};

LRESULT CALLBACK IntermediateWindowProc(HWND window,
                                        UINT message,
                                        WPARAM w_param,
                                        LPARAM l_param) {
  switch (message) {
    case WM_ERASEBKGND:
      // Prevent windows from erasing the background.
      return 1;
    case WM_PAINT:
      // Do not paint anything.
      PAINTSTRUCT paint;
      if (BeginPaint(window, &paint))
        EndPaint(window, &paint);
      return 0;
    default:
      return DefWindowProc(window, message, w_param, l_param);
  }
}

class DisplayWGL {
 public:
  DisplayWGL()
      : module_handle_(0),
        window_class_(0),
        window_handle_(0),
        device_context_(0),
        pixel_format_(0) {
  }

  ~DisplayWGL() {
    if (window_handle_)
      DestroyWindow(window_handle_);
    if (window_class_)
      UnregisterClass(reinterpret_cast<wchar_t*>(window_class_),
                      module_handle_);
  }

  bool Init() {
    // We must initialize a GL context before we can bind to extension entry
    // points. This requires the device context for a window.
    if (!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT |
                           GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
                           reinterpret_cast<wchar_t*>(IntermediateWindowProc),
                           &module_handle_)) {
      LOG(ERROR) << "GetModuleHandleEx failed.";
      return false;
    }

    WNDCLASS intermediate_class;
    intermediate_class.style = CS_OWNDC;
    intermediate_class.lpfnWndProc = IntermediateWindowProc;
    intermediate_class.cbClsExtra = 0;
    intermediate_class.cbWndExtra = 0;
    intermediate_class.hInstance = module_handle_;
    intermediate_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    intermediate_class.hCursor = LoadCursor(NULL, IDC_ARROW);
    intermediate_class.hbrBackground = NULL;
    intermediate_class.lpszMenuName = NULL;
    intermediate_class.lpszClassName = L"Intermediate GL Window";
    window_class_ = RegisterClass(&intermediate_class);
    if (!window_class_) {
      LOG(ERROR) << "RegisterClass failed.";
      return false;
    }

    window_handle_ = CreateWindowEx(WS_EX_NOPARENTNOTIFY,
                                    reinterpret_cast<wchar_t*>(window_class_),
                                    L"",
                                    WS_OVERLAPPEDWINDOW,
                                    0,
                                    0,
                                    100,
                                    100,
                                    NULL,
                                    NULL,
                                    NULL,
                                    NULL);
    if (!window_handle_) {
      LOG(ERROR) << "CreateWindow failed.";
      return false;
    }

    device_context_ = GetDC(window_handle_);
    pixel_format_ = ChoosePixelFormat(device_context_,
                                      &kPixelFormatDescriptor);
    if (pixel_format_ == 0) {
      LOG(ERROR) << "Unable to get the pixel format for GL context.";
      return false;
    }
    if (!SetPixelFormat(device_context_,
                        pixel_format_,
                        &kPixelFormatDescriptor)) {
      LOG(ERROR) << "Unable to set the pixel format for temporary GL context.";
      return false;
    }

    return true;
  }

  ATOM window_class() const { return window_class_; }
  HDC device_context() const { return device_context_; }
  int pixel_format() const { return pixel_format_; }

 private:
  HINSTANCE module_handle_;
  ATOM window_class_;
  HWND window_handle_;
  HDC device_context_;
  int pixel_format_;
};
DisplayWGL* g_display;
}  // namespace

GLSurfaceWGL::GLSurfaceWGL() {
}

GLSurfaceWGL::~GLSurfaceWGL() {
}

void* GLSurfaceWGL::GetDisplay() {
  return GetDisplayDC();
}

bool GLSurfaceWGL::InitializeOneOff() {
  static bool initialized = false;
  if (initialized)
    return true;

  DCHECK(g_display == NULL);
  std::unique_ptr<DisplayWGL> wgl_display(new DisplayWGL);
  if (!wgl_display->Init())
    return false;

  g_display = wgl_display.release();
  initialized = true;
  return true;
}

void GLSurfaceWGL::InitializeOneOffForTesting() {
  if (g_display == NULL) {
    g_display = new DisplayWGL;
  }
}

HDC GLSurfaceWGL::GetDisplayDC() {
  return g_display->device_context();
}

NativeViewGLSurfaceWGL::NativeViewGLSurfaceWGL(gfx::AcceleratedWidget window)
    : window_(window), child_window_(NULL), device_context_(NULL) {
  DCHECK(window);
}

NativeViewGLSurfaceWGL::~NativeViewGLSurfaceWGL() {
  Destroy();
}

bool NativeViewGLSurfaceWGL::Initialize(GLSurface::Format format) {
  DCHECK(!device_context_);

  RECT rect;
  if (!GetClientRect(window_, &rect)) {
    LOG(ERROR) << "GetClientRect failed.\n";
    Destroy();
    return false;
  }

  // Create a child window. WGL has problems using a window handle owned by
  // another process.
  child_window_ =
      CreateWindowEx(WS_EX_NOPARENTNOTIFY,
                     reinterpret_cast<wchar_t*>(g_display->window_class()),
                     L"",
                     WS_CHILDWINDOW | WS_DISABLED | WS_VISIBLE,
                     0,
                     0,
                     rect.right - rect.left,
                     rect.bottom - rect.top,
                     window_,
                     NULL,
                     NULL,
                     NULL);
  if (!child_window_) {
    LOG(ERROR) << "CreateWindow failed.\n";
    Destroy();
    return false;
  }

  // The GL context will render to this window.
  device_context_ = GetDC(child_window_);
  if (!device_context_) {
    LOG(ERROR) << "Unable to get device context for window.";
    Destroy();
    return false;
  }

  if (!SetPixelFormat(device_context_,
                      g_display->pixel_format(),
                      &kPixelFormatDescriptor)) {
    LOG(ERROR) << "Unable to set the pixel format for GL context.";
    Destroy();
    return false;
  }

  format_ = format;

  return true;
}

void NativeViewGLSurfaceWGL::Destroy() {
  if (child_window_ && device_context_)
    ReleaseDC(child_window_, device_context_);

  if (child_window_)
    DestroyWindow(child_window_);

  child_window_ = NULL;
  device_context_ = NULL;
}

bool NativeViewGLSurfaceWGL::Resize(const gfx::Size& size,
                                    float scale_factor,
                                    bool has_alpha) {
  RECT rect;
  if (!GetClientRect(window_, &rect)) {
    LOG(ERROR) << "Failed to get parent window size.";
    return false;
  }
  DCHECK(size.width() == (rect.right - rect.left) &&
         size.height() == (rect.bottom - rect.top));
  if (!MoveWindow(child_window_, 0, 0, size.width(), size.height(), FALSE)) {
    LOG(ERROR) << "Failed to resize child window.";
    return false;
  }
  return true;
}

bool NativeViewGLSurfaceWGL::Recreate() {
  Destroy();
  if (!Initialize(format_)) {
    LOG(ERROR) << "Failed to create surface.";
    return false;
  }
  return true;
}

bool NativeViewGLSurfaceWGL::IsOffscreen() {
  return false;
}

gfx::SwapResult NativeViewGLSurfaceWGL::SwapBuffers() {
  TRACE_EVENT2("gpu", "NativeViewGLSurfaceWGL:RealSwapBuffers",
      "width", GetSize().width(),
      "height", GetSize().height());

  // Resize the child window to match the parent before swapping. Do not repaint
  // it as it moves.
  RECT rect;
  if (!GetClientRect(window_, &rect))
    return gfx::SwapResult::SWAP_FAILED;
  if (!MoveWindow(child_window_,
                  0,
                  0,
                  rect.right - rect.left,
                  rect.bottom - rect.top,
                  FALSE)) {
    return gfx::SwapResult::SWAP_FAILED;
  }

  DCHECK(device_context_);
  return ::SwapBuffers(device_context_) == TRUE ? gfx::SwapResult::SWAP_ACK
                                                : gfx::SwapResult::SWAP_FAILED;
}

gfx::Size NativeViewGLSurfaceWGL::GetSize() {
  RECT rect;
  BOOL result = GetClientRect(child_window_, &rect);
  DCHECK(result);
  return gfx::Size(rect.right - rect.left, rect.bottom - rect.top);
}

void* NativeViewGLSurfaceWGL::GetHandle() {
  return device_context_;
}

PbufferGLSurfaceWGL::PbufferGLSurfaceWGL(const gfx::Size& size)
    : size_(size),
      device_context_(NULL),
      pbuffer_(NULL) {
  // Some implementations of Pbuffer do not support having a 0 size. For such
  // cases use a (1, 1) surface.
  if (size_.GetArea() == 0)
    size_.SetSize(1, 1);
}

PbufferGLSurfaceWGL::~PbufferGLSurfaceWGL() {
  Destroy();
}

bool PbufferGLSurfaceWGL::Initialize(GLSurface::Format format) {
  DCHECK(!device_context_);

  if (!g_driver_wgl.fn.wglCreatePbufferARBFn) {
    LOG(ERROR) << "wglCreatePbufferARB not available.";
    Destroy();
    return false;
  }

  const int kNoAttributes[] = { 0 };
  pbuffer_ = wglCreatePbufferARB(g_display->device_context(),
                                 g_display->pixel_format(),
                                 size_.width(), size_.height(),
                                 kNoAttributes);

  if (!pbuffer_) {
    LOG(ERROR) << "Unable to create pbuffer.";
    Destroy();
    return false;
  }

  device_context_ = wglGetPbufferDCARB(static_cast<HPBUFFERARB>(pbuffer_));
  if (!device_context_) {
    LOG(ERROR) << "Unable to get pbuffer device context.";
    Destroy();
    return false;
  }

  return true;
}

void PbufferGLSurfaceWGL::Destroy() {
  if (pbuffer_ && device_context_)
    wglReleasePbufferDCARB(static_cast<HPBUFFERARB>(pbuffer_), device_context_);

  device_context_ = NULL;

  if (pbuffer_) {
    wglDestroyPbufferARB(static_cast<HPBUFFERARB>(pbuffer_));
    pbuffer_ = NULL;
  }
}

bool PbufferGLSurfaceWGL::IsOffscreen() {
  return true;
}

gfx::SwapResult PbufferGLSurfaceWGL::SwapBuffers() {
  NOTREACHED() << "Attempted to call SwapBuffers on a pbuffer.";
  return gfx::SwapResult::SWAP_FAILED;
}

gfx::Size PbufferGLSurfaceWGL::GetSize() {
  return size_;
}

void* PbufferGLSurfaceWGL::GetHandle() {
  return device_context_;
}

}  // namespace gl
