/*
 * GStreamer
 * Copyright (C) 2016 Matthew Waters <matthew@centricular.com>
 *
 * 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.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <gst/gl/gl.h>

#include <string.h>

#include "gstglquery.h"

#ifndef GL_TIME_ELAPSED
#define GL_TIME_ELAPSED 0x88BF
#endif

#ifndef GL_TIMESTAMP
#define GL_TIMESTAMP 0x8E28
#endif

#ifndef GL_QUERY_RESULT
#define GL_QUERY_RESULT 0x8866
#endif

#define GST_CAT_DEFAULT gst_gl_query_debug
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);

static void
_init_debug (void)
{
  static volatile gsize _init = 0;

  if (g_once_init_enter (&_init)) {
    GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "glquery", 0, "glquery element");
    g_once_init_leave (&_init, 1);
  }
}

static const gchar *
_query_type_to_string (guint query_type)
{
  switch (query_type) {
    case GST_GL_QUERY_TIME_ELAPSED:
    case GL_TIME_ELAPSED:
      return "time elapsed";
    case GL_TIMESTAMP:
    case GST_GL_QUERY_TIMESTAMP:
      return "timestamp";
    default:
      return "unknown";
  }
}

static guint
_gst_gl_query_type_to_gl (GstGLQueryType query_type)
{
  if (query_type == GST_GL_QUERY_TIME_ELAPSED)
    return GL_TIME_ELAPSED;
  if (query_type == GST_GL_QUERY_TIMESTAMP)
    return GL_TIMESTAMP;

  g_assert_not_reached ();
  return 0;
}

static gboolean
_query_type_supports_counter (guint gl_query_type)
{
  return gl_query_type == GL_TIMESTAMP;
}

static gboolean
_query_type_supports_begin_end (guint gl_query_type)
{
  return gl_query_type == GL_TIME_ELAPSED;
}

static gboolean
_context_supports_query_type (GstGLContext * context, guint gl_query_type)
{
  return gl_query_type != 0 && context->gl_vtable->GenQueries != NULL;
}

static gchar *
_log_time (gpointer user_data)
{
  GstGLQuery *query = user_data;
  gint64 result;

  result = gst_gl_query_result (query);

  return gst_info_strdup_printf ("%" GST_TIME_FORMAT, GST_TIME_ARGS (result));
}

void
gst_gl_query_init (GstGLQuery * query, GstGLContext * context,
    GstGLQueryType query_type)
{
  const GstGLFuncs *gl;

  g_return_if_fail (query != NULL);
  g_return_if_fail (GST_IS_GL_CONTEXT (context));
  gl = context->gl_vtable;

  memset (query, 0, sizeof (*query));

  _init_debug ();

  query->context = gst_object_ref (context);
  query->query_type = _gst_gl_query_type_to_gl (query_type);
  query->supported = _context_supports_query_type (context, query->query_type);

  if (query->supported)
    gl->GenQueries (1, &query->query_id);

  gst_gl_async_debug_init (&query->debug);
  query->debug.callback = _log_time;
  query->debug.user_data = query;
}

void
gst_gl_query_unset (GstGLQuery * query)
{
  const GstGLFuncs *gl;

  g_return_if_fail (query != NULL);
  if (query->start_called)
    g_critical ("Unsetting a running query. This may not be what you wanted."
        "Be sure to pair calls to gst_gl_query_start() and gst_gl_query_end()");

  GST_TRACE ("%p unsetting query %u", query, query->query_id);

  gl = query->context->gl_vtable;

  /* unset the debug object as it may callback to print the last message */
  gst_gl_async_debug_unset (&query->debug);

  if (query->query_id)
    gl->DeleteQueries (1, &query->query_id);

  gst_object_unref (query->context);
}

GstGLQuery *
gst_gl_query_new (GstGLContext * context, GstGLQueryType query_type)
{
  GstGLQuery *query = g_new0 (GstGLQuery, 1);

  gst_gl_query_init (query, context, query_type);

  return query;
}

void
gst_gl_query_free (GstGLQuery * query)
{
  g_return_if_fail (query != NULL);

  gst_gl_query_unset (query);
  g_free (query);
}

void
gst_gl_query_start (GstGLQuery * query)
{
  const GstGLFuncs *gl;

  g_return_if_fail (query != NULL);
  g_return_if_fail (_query_type_supports_begin_end (query->query_type));

  if (!query->supported)
    return;

  query->start_called = TRUE;
  gst_gl_async_debug_output_log_msg (&query->debug);

  GST_TRACE ("%p start query type \'%s\' id %u", query,
      _query_type_to_string (query->query_type), query->query_id);

  gl = query->context->gl_vtable;
  gl->BeginQuery (query->query_type, query->query_id);
}

void
gst_gl_query_end (GstGLQuery * query)
{
  const GstGLFuncs *gl;

  g_return_if_fail (query != NULL);
  g_return_if_fail (_query_type_supports_begin_end (query->query_type));

  if (!query->supported)
    return;
  g_return_if_fail (query->start_called);

  GST_TRACE ("%p end query type \'%s\' id %u", query,
      _query_type_to_string (query->query_type), query->query_id);

  gl = query->context->gl_vtable;

  gl->EndQuery (query->query_type);
  query->start_called = FALSE;
}

void
gst_gl_query_counter (GstGLQuery * query)
{
  const GstGLFuncs *gl;

  g_return_if_fail (query != NULL);
  g_return_if_fail (_query_type_supports_counter (query->query_type));

  if (!query->supported)
    return;

  GST_TRACE ("%p query counter type \'%s\' id %u", query,
      _query_type_to_string (query->query_type), query->query_id);

  gst_gl_async_debug_output_log_msg (&query->debug);

  gl = query->context->gl_vtable;
  gl->QueryCounter (query->query_id, query->query_type);
}

guint64
gst_gl_query_result (GstGLQuery * query)
{
  const GstGLFuncs *gl;
  guint64 ret;

  g_return_val_if_fail (query != NULL, 0);
  g_return_val_if_fail (!query->start_called, 0);

  if (!query->supported)
    return 0;

  gl = query->context->gl_vtable;
  if (gl->GetQueryObjectui64v) {
    gl->GetQueryObjectui64v (query->query_id, GL_QUERY_RESULT,
        (GLuint64 *) & ret);
  } else {
    guint tmp;
    gl->GetQueryObjectuiv (query->query_id, GL_QUERY_RESULT, &tmp);
    ret = tmp;
  }

  GST_TRACE ("%p get result %" G_GUINT64_FORMAT " type \'%s\' id %u", query,
      ret, _query_type_to_string (query->query_type), query->query_id);

  return ret;
}
