/*
 * GStreamer
 * Copyright (C) 2018 Carlos Rafael Giani <dv@pseudoterminal.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include <poll.h>

#include "../gstgl_fwd.h"
#include <gst/gl/gstglcontext.h>
#include <gst/gl/egl/gstglcontext_egl.h>

#include "gstgldisplay_gbm.h"
#include "gstglwindow_gbm_egl.h"
#include "gstgl_gbm_utils.h"
#include "../gstglwindow_private.h"

#define GST_CAT_DEFAULT gst_gl_window_debug


#define GST_GL_WINDOW_GBM_EGL_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
    GST_TYPE_GL_WINDOW_GBM_EGL, GstGLWindowGBMEGLPrivate))


G_DEFINE_TYPE (GstGLWindowGBMEGL, gst_gl_window_gbm_egl, GST_TYPE_GL_WINDOW);


static guintptr gst_gl_window_gbm_egl_get_window_handle (GstGLWindow * window);
static guintptr gst_gl_window_gbm_egl_get_display (GstGLWindow * window);
static void gst_gl_window_gbm_egl_set_window_handle (GstGLWindow * window,
    guintptr handle);
static void gst_gl_window_gbm_egl_close (GstGLWindow * window);
static void gst_gl_window_gbm_egl_draw (GstGLWindow * window);

static gboolean gst_gl_window_gbm_init_surface (GstGLWindowGBMEGL * window_egl);
static void gst_gl_window_gbm_egl_cleanup (GstGLWindowGBMEGL * window_egl);



static void
gst_gl_window_gbm_egl_class_init (GstGLWindowGBMEGLClass * klass)
{
  GstGLWindowClass *window_class = (GstGLWindowClass *) klass;

  window_class->get_window_handle =
      GST_DEBUG_FUNCPTR (gst_gl_window_gbm_egl_get_window_handle);
  window_class->get_display =
      GST_DEBUG_FUNCPTR (gst_gl_window_gbm_egl_get_display);
  window_class->set_window_handle =
      GST_DEBUG_FUNCPTR (gst_gl_window_gbm_egl_set_window_handle);
  window_class->close = GST_DEBUG_FUNCPTR (gst_gl_window_gbm_egl_close);
  window_class->draw = GST_DEBUG_FUNCPTR (gst_gl_window_gbm_egl_draw);

  /* TODO: add support for set_render_rectangle (assuming this functionality
   * is possible with libdrm/gbm) */
}


static void
gst_gl_window_gbm_egl_init (GstGLWindowGBMEGL * window_gbm)
{
  window_gbm->gbm_surf = NULL;
  window_gbm->current_bo = NULL;
  window_gbm->prev_bo = NULL;
  window_gbm->waiting_for_flip = 0;
}


static guintptr
gst_gl_window_gbm_egl_get_window_handle (GstGLWindow * window)
{
  return (guintptr) GST_GL_WINDOW_GBM_EGL (window)->gbm_surf;
}


static guintptr
gst_gl_window_gbm_egl_get_display (GstGLWindow * window)
{
  return gst_gl_display_get_handle (window->display);
}


static void
gst_gl_window_gbm_egl_set_window_handle (G_GNUC_UNUSED GstGLWindow * window,
    G_GNUC_UNUSED guintptr handle)
{
  /* TODO: Currently, it is unclear how to use external GBM buffer objects,
   * since it is not defined how this would work together with DRM page flips
   */
}


static void
gst_gl_window_gbm_egl_close (GstGLWindow * window)
{
  GstGLWindowGBMEGL *window_egl = GST_GL_WINDOW_GBM_EGL (window);

  gst_gl_window_gbm_egl_cleanup (window_egl);

  GST_GL_WINDOW_CLASS (gst_gl_window_gbm_egl_parent_class)->close (window);
}


static void
_page_flip_handler (G_GNUC_UNUSED int fd, G_GNUC_UNUSED unsigned int frame,
    G_GNUC_UNUSED unsigned int sec, G_GNUC_UNUSED unsigned int usec, void *data)
{
  /* If we reach this point, it means the page flip has been completed.
   * Signal this by clearing the flag so the poll() loop in draw_cb()
   * can exit. */
  int *waiting_for_flip = data;
  *waiting_for_flip = 0;
}

static void
draw_cb (gpointer data)
{
  GstGLWindowGBMEGL *window_egl = data;
  GstGLWindow *window = GST_GL_WINDOW (window_egl);
  GstGLContext *context = gst_gl_window_get_context (window);
  GstGLContextClass *context_class = GST_GL_CONTEXT_GET_CLASS (context);
  GstGLDisplayGBM *display = (GstGLDisplayGBM *) window->display;
  struct gbm_bo *next_bo;
  GstGLDRMFramebuffer *framebuf;
  int ret;

  drmEventContext evctx = {
    .version = DRM_EVENT_CONTEXT_VERSION,
    .page_flip_handler = _page_flip_handler,
  };

  struct pollfd pfd = {
    .fd = display->drm_fd,
    .events = POLLIN,
    .revents = 0,
  };

  /* Rendering, page flipping etc. are connect this way:
   *
   * The frames are stored in buffer objects (BOs). Inside the eglSwapBuffers()
   * call, GBM creates new BOs if necessary. BOs can be "locked" for rendering,
   * meaning that EGL cannot use them as a render target. If all available
   * BOs are locked, the GBM code inside eglSwapBuffers() creates a new,
   * unlocked one. We make use of this to implement triple buffering.
   *
   * There are 3 BOs in play:
   *
   * * next_bo: The BO we just rendered into.
   * * current_bo: The currently displayed BO.
   * * prev_bo: The previously displayed BO.
   *
   * current_bo and prev_bo are involed in page flipping. next_bo is not.
   *
   * Once rendering is done, the next_bo is retrieved and locked. Then, we 
   * wait until any ongoing page flipping finishes. Once it does, the
   * current_bo is displayed on screen, and the prev_bo isn't anymore. At
   * this point, it is safe to release the prev_bo, which unlocks it and
   * makes it available again as a render target. Then we initiate the
   * next page flipping; this time, we flip to next_bo. At that point,
   * next_bo becomes current_bo, and current_bo becomes prev_bo.
   */

  /*
   * There is a special case at the beginning. There is no currently
   * displayed BO at first, so we create an empty one to get the page
   * flipping cycle going. Also, we use this first BO for setting up
   * the CRTC.
   */
  if (window_egl->current_bo == NULL) {
    /* Call eglSwapBuffers() to create a BO. */
    context_class->swap_buffers (context);

    /* Lock the BO so we get our first current_bo. */
    window_egl->current_bo =
        gbm_surface_lock_front_buffer (window_egl->gbm_surf);
    framebuf = gst_gl_gbm_drm_fb_get_from_bo (window_egl->current_bo);

    /* Configure CRTC to show this first BO. */
    ret = drmModeSetCrtc (display->drm_fd, display->crtc_id, framebuf->fb_id,
        0, 0, &(display->drm_mode_connector->connector_id), 1,
        display->drm_mode_info);

    if (ret != 0) {
      GST_ERROR ("Could not set DRM CRTC: %s (%d)", g_strerror (errno), errno);
      /* XXX: it is not possible to communicate the error to the pipeline */
      return;
    }
  }

  /* Do the actual drawing */
  if (window->draw)
    window->draw (window->draw_data);

  /* Let the context class call eglSwapBuffers(). As mentioned above,
   * if necessary, this function creates a new unlocked framebuffer
   * that can be used as render target. */
  context_class->swap_buffers (context);
  gst_object_unref (context);

  next_bo = gbm_surface_lock_front_buffer (window_egl->gbm_surf);
  framebuf = gst_gl_gbm_drm_fb_get_from_bo (next_bo);
  GST_LOG ("rendered new frame into bo %p", (gpointer) next_bo);

  /* Wait until any ongoing page flipping is done. After this is done,
   * prev_bo is no longer involved in any page flipping, and can be
   * safely released. */
  while (window_egl->waiting_for_flip) {
    ret = poll (&pfd, 1, -1);
    if (ret < 0) {
      if (errno == EINTR)
        GST_DEBUG ("Signal caught during poll() call");
      else
        GST_ERROR ("poll() failed: %s (%d)", g_strerror (errno), errno);
      /* XXX: it is not possible to communicate errors and interruptions
       * to the pipeline */
      return;
    }

    drmHandleEvent (display->drm_fd, &evctx);
  }
  GST_LOG ("now showing bo %p", (gpointer) (window_egl->current_bo));

  /* Release prev_bo, since it is no longer shown on screen. */
  if (G_LIKELY (window_egl->prev_bo != NULL)) {
    gbm_surface_release_buffer (window_egl->gbm_surf, window_egl->prev_bo);
    GST_LOG ("releasing bo %p", (gpointer) (window_egl->prev_bo));
  }

  /* Presently, current_bo is shown on screen. Schedule the next page
   * flip, this time flip to next_bo. The flip happens asynchronously, so
   * we can continue and render etc. in the meantime. */
  window_egl->waiting_for_flip = 1;
  ret = drmModePageFlip (display->drm_fd, display->crtc_id, framebuf->fb_id,
      DRM_MODE_PAGE_FLIP_EVENT, &(window_egl->waiting_for_flip));
  if (ret != 0) {
    /* NOTE: According to libdrm sources, the page is _not_
     * considered flipped if drmModePageFlip() reports an error,
     * so we do not update the priv->current_bo pointer here */
    GST_ERROR ("Could not initialize GBM surface");
    /* XXX: it is not possible to communicate the error to the pipeline */
    return;
  }

  /* At this point, we relabel the current_bo as the prev_bo.
   * This may not actually be the case yet, but it will be soon - latest
   * when the wait loop above finishes.
   * Also, next_bo becomes current_bo. */
  window_egl->prev_bo = window_egl->current_bo;
  window_egl->current_bo = next_bo;
}


static void
gst_gl_window_gbm_egl_draw (GstGLWindow * window)
{
  gst_gl_window_send_message (window, (GstGLWindowCB) draw_cb, window);
}


static gboolean
gst_gl_window_gbm_init_surface (GstGLWindowGBMEGL * window_egl)
{
  /* NOTE: This function cannot be called in the open() vmethod
   * since context_egl->egl_display and context_egl->egl_config
   * must have been set to valid values at this point, and open()
   * is called _before_ these are set.
   * Also, eglInitialize() is called _after_ the open() vmethod,
   * which means that the return value of gbm_surface_create()
   * contains some function pointers that are set to NULL and
   * shouldn't be. This is because Mesa's eglInitialize() loads
   * the DRI2 driver and the relevant functions aren't available
   * until then.
   *
   * Therefore, this function is called instead inside
   * gst_gl_window_gbm_egl_create_window(), which in turn is
   * called inside gst_gl_context_egl_create_context(). */

  GstGLWindow *window = GST_GL_WINDOW (window_egl);
  GstGLDisplayGBM *display = (GstGLDisplayGBM *) window->display;
  drmModeModeInfo *drm_mode_info = display->drm_mode_info;
  GstGLContext *context = gst_gl_window_get_context (window);
  GstGLContextEGL *context_egl = GST_GL_CONTEXT_EGL (context);
  EGLint gbm_format;

  /* With GBM-based EGL displays and configs, the native visual ID
   * is a GBM pixel format. */
  if (!eglGetConfigAttrib (context_egl->egl_display, context_egl->egl_config,
          EGL_NATIVE_VISUAL_ID, &gbm_format)) {
    GST_ERROR ("eglGetConfigAttrib failed: %s",
        gst_egl_get_error_string (eglGetError ()));
    return FALSE;
  }

  /* Create a GBM surface that shall contain the BOs we are
   * going to render into. */
  window_egl->gbm_surf = gbm_surface_create (display->gbm_dev,
      drm_mode_info->hdisplay, drm_mode_info->vdisplay, gbm_format,
      GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);

  gst_gl_window_resize (window, drm_mode_info->hdisplay,
      drm_mode_info->vdisplay);

  GST_DEBUG ("Successfully created GBM surface");

  return TRUE;
}


static void
gst_gl_window_gbm_egl_cleanup (GstGLWindowGBMEGL * window_egl)
{
  if (window_egl->gbm_surf != NULL) {
    if (window_egl->current_bo != NULL) {
      gbm_surface_release_buffer (window_egl->gbm_surf, window_egl->current_bo);
      window_egl->current_bo = NULL;
    }

    gbm_surface_destroy (window_egl->gbm_surf);
    window_egl->gbm_surf = NULL;
  }
}


/* Must be called in the gl thread */
GstGLWindowGBMEGL *
gst_gl_window_gbm_egl_new (GstGLDisplay * display)
{
  GstGLWindowGBMEGL *window_egl;

  if ((gst_gl_display_get_handle_type (display) & GST_GL_DISPLAY_TYPE_GBM) == 0)
    /* we require a GBM display to create windows */
    return NULL;

  window_egl = g_object_new (GST_TYPE_GL_WINDOW_GBM_EGL, NULL);

  return window_egl;
}


gboolean
gst_gl_window_gbm_egl_create_window (GstGLWindowGBMEGL * window_egl)
{
  return gst_gl_window_gbm_init_surface (window_egl);
}
