/*
 *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "test/linux/glx_renderer.h"

#include <assert.h>
#include <stdlib.h>

#include <X11/Xatom.h>
#include <X11/Xlib.h>

#include "common_video/libyuv/include/webrtc_libyuv.h"

namespace webrtc {
namespace test {

GlxRenderer::GlxRenderer(size_t width, size_t height)
    : width_(width),
      height_(height),
      display_(NULL),
      context_(NULL) {
  assert(width > 0);
  assert(height > 0);
}

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

bool GlxRenderer::Init(const char* window_title) {
  if ((display_ = XOpenDisplay(NULL)) == NULL) {
    Destroy();
    return false;
  }

  int screen = DefaultScreen(display_);

  XVisualInfo* vi;
  int attr_list[] = { GLX_DOUBLEBUFFER, GLX_RGBA, GLX_RED_SIZE, 4,
                      GLX_GREEN_SIZE, 4, GLX_BLUE_SIZE, 4, GLX_DEPTH_SIZE, 16,
                      None, };

  if ((vi = glXChooseVisual(display_, screen, attr_list)) == NULL) {
    Destroy();
    return false;
  }

  context_ = glXCreateContext(display_, vi, 0, true);
  if (context_ == NULL) {
    Destroy();
    return false;
  }

  XSetWindowAttributes window_attributes;
  window_attributes.colormap = XCreateColormap(
      display_, RootWindow(display_, vi->screen), vi->visual, AllocNone);
  window_attributes.border_pixel = 0;
  window_attributes.event_mask = StructureNotifyMask | ExposureMask;
  window_ = XCreateWindow(display_, RootWindow(display_, vi->screen), 0, 0,
                          width_, height_, 0, vi->depth, InputOutput,
                          vi->visual, CWBorderPixel | CWColormap | CWEventMask,
                          &window_attributes);
  XFree(vi);

  XSetStandardProperties(display_, window_, window_title, window_title, None,
                         NULL, 0, NULL);

  Atom wm_delete = XInternAtom(display_, "WM_DELETE_WINDOW", True);
  if (wm_delete != None) {
    XSetWMProtocols(display_, window_, &wm_delete, 1);
  }

  XMapRaised(display_, window_);

  if (!glXMakeCurrent(display_, window_, context_)) {
    Destroy();
    return false;
  }
  GlRenderer::Init();
  if (!glXMakeCurrent(display_, None, NULL)) {
    Destroy();
    return false;
  }

  Resize(width_, height_);
  return true;
}

void GlxRenderer::Destroy() {
  if (context_ != NULL) {
    glXMakeCurrent(display_, window_, context_);
    GlRenderer::Destroy();
    glXMakeCurrent(display_, None, NULL);
    glXDestroyContext(display_, context_);
    context_ = NULL;
  }

  if (display_ != NULL) {
    XCloseDisplay(display_);
    display_ = NULL;
  }
}

GlxRenderer* GlxRenderer::Create(const char* window_title, size_t width,
                                 size_t height) {
  GlxRenderer* glx_renderer = new GlxRenderer(width, height);
  if (!glx_renderer->Init(window_title)) {
    // TODO(pbos): Add GLX-failed warning here?
    delete glx_renderer;
    return NULL;
  }
  return glx_renderer;
}

void GlxRenderer::Resize(size_t width, size_t height) {
  width_ = width;
  height_ = height;
  if (!glXMakeCurrent(display_, window_, context_)) {
    abort();
  }
  GlRenderer::ResizeViewport(width_, height_);
  if (!glXMakeCurrent(display_, None, NULL)) {
    abort();
  }

  XSizeHints* size_hints = XAllocSizeHints();
  if (size_hints == NULL) {
    abort();
  }
  size_hints->flags = PAspect;
  size_hints->min_aspect.x = size_hints->max_aspect.x = width_;
  size_hints->min_aspect.y = size_hints->max_aspect.y = height_;
  XSetWMNormalHints(display_, window_, size_hints);
  XFree(size_hints);

  XWindowChanges wc;
  wc.width = static_cast<int>(width);
  wc.height = static_cast<int>(height);
  XConfigureWindow(display_, window_, CWWidth | CWHeight, &wc);
}

void GlxRenderer::OnFrame(const webrtc::VideoFrame& frame) {
  if (static_cast<size_t>(frame.width()) != width_ ||
      static_cast<size_t>(frame.height()) != height_) {
    Resize(static_cast<size_t>(frame.width()),
           static_cast<size_t>(frame.height()));
  }

  XEvent event;
  if (!glXMakeCurrent(display_, window_, context_)) {
    abort();
  }
  while (XPending(display_)) {
    XNextEvent(display_, &event);
    switch (event.type) {
      case ConfigureNotify:
        GlRenderer::ResizeViewport(event.xconfigure.width,
                                   event.xconfigure.height);
        break;
      default:
        break;
    }
  }

  GlRenderer::OnFrame(frame);
  glXSwapBuffers(display_, window_);

  if (!glXMakeCurrent(display_, None, NULL)) {
    abort();
  }
}
}  // test
}  // webrtc
