/*
 * GStreamer
 * Copyright (C) 2015 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 <string.h>

#include "gstglbuffer.h"

#include "gstglcontext.h"
#include "gstglfuncs.h"
#include "gstglutils.h"

/**
 * SECTION:gstglbuffer
 * @title: GstGLBuffer
 * @short_description: memory subclass for GL buffers
 * @see_also: #GstMemory, #GstAllocator
 *
 * GstGLBuffer is a #GstMemory subclass providing support for the mapping of
 * GL buffers.
 *
 * Data is uploaded or downloaded from the GPU as is necessary.
 */

/* Implementation notes:
 *
 * Currently does not take into account GLES2 differences (no mapbuffer)
 */

#define USING_OPENGL(context) (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL, 1, 0))
#define USING_OPENGL3(context) (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL3, 3, 1))
#define USING_GLES(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES, 1, 0))
#define USING_GLES2(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 2, 0))
#define USING_GLES3(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 3, 0))

/* compatibility definitions... */
#ifndef GL_MAP_READ_BIT
#define GL_MAP_READ_BIT 0x0001
#endif
#ifndef GL_MAP_WRITE_BIT
#define GL_MAP_WRITE_BIT 0x0002
#endif
#ifndef GL_COPY_READ_BUFFER
#define GL_COPY_READ_BUFFER 0x8F36
#endif
#ifndef GL_COPY_WRITE_BUFFER
#define GL_COPY_WRITE_BUFFER 0x8F37
#endif

GST_DEBUG_CATEGORY_STATIC (GST_CAT_GL_BUFFER);
#define GST_CAT_DEFUALT GST_CAT_GL_BUFFER

static GstAllocator *_gl_buffer_allocator;

static gboolean
_gl_buffer_create (GstGLBuffer * gl_mem, GError ** error)
{
  const GstGLFuncs *gl = gl_mem->mem.context->gl_vtable;

  gl->GenBuffers (1, &gl_mem->id);
  gl->BindBuffer (gl_mem->target, gl_mem->id);
  gl->BufferData (gl_mem->target, gl_mem->mem.mem.maxsize, NULL,
      gl_mem->usage_hints);
  gl->BindBuffer (gl_mem->target, 0);

  return TRUE;
}

struct create_data
{
  GstGLBuffer *mem;
  gboolean result;
};

static void
_gl_buffer_init (GstGLBuffer * mem, GstAllocator * allocator,
    GstMemory * parent, GstGLContext * context, guint gl_target, guint gl_usage,
    GstAllocationParams * params, gsize size)
{
  mem->target = gl_target;
  mem->usage_hints = gl_usage;

  gst_gl_base_memory_init ((GstGLBaseMemory *) mem, allocator, parent, context,
      params, size, NULL, NULL);

  GST_CAT_DEBUG (GST_CAT_GL_BUFFER, "new GL buffer memory:%p size:%"
      G_GSIZE_FORMAT, mem, mem->mem.mem.maxsize);
}

static GstGLBuffer *
_gl_buffer_new (GstAllocator * allocator, GstMemory * parent,
    GstGLContext * context, guint gl_target, guint gl_usage,
    GstAllocationParams * params, gsize size)
{
  GstGLBuffer *ret = g_new0 (GstGLBuffer, 1);
  _gl_buffer_init (ret, allocator, parent, context, gl_target, gl_usage,
      params, size);

  return ret;
}

static gpointer
gst_gl_buffer_cpu_access (GstGLBuffer * mem, GstMapInfo * info, gsize size)
{
  const GstGLFuncs *gl = mem->mem.context->gl_vtable;
  gpointer data, ret;

  if (!gst_gl_base_memory_alloc_data (GST_GL_BASE_MEMORY_CAST (mem)))
    return NULL;

  ret = mem->mem.data;

  GST_CAT_LOG (GST_CAT_GL_BUFFER, "mapping id %d size %" G_GSIZE_FORMAT,
      mem->id, size);

  /* The extra data pointer indirection/memcpy is needed for coherent across
   * concurrent map()'s in both GL and CPU */
  if (GST_MEMORY_FLAG_IS_SET (mem, GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD)
      && (info->flags & GST_MAP_GL) == 0 && (info->flags & GST_MAP_READ) != 0) {
    gl->BindBuffer (mem->target, mem->id);

    if (gl->MapBufferRange) {
      /* FIXME: optionally remove this with a flag and return the
       * glMapBufferRange pointer (requires
       * GL_ARB_buffer_storage/GL4/GL_COHERENT_BIT) */
      guint gl_map_flags = GL_MAP_READ_BIT;

      data = gl->MapBufferRange (mem->target, 0, size, gl_map_flags);

      if (data)
        memcpy (mem->mem.data, data, size);

      gl->UnmapBuffer (mem->target);
      ret = mem->mem.data;
    } else if (gl->GetBufferSubData) {
      gl->GetBufferSubData (mem->target, 0, size, mem->mem.data);
      ret = mem->mem.data;
    } else {
      ret = NULL;
    }
    gl->BindBuffer (mem->target, 0);
  }

  return ret;
}

static void
gst_gl_buffer_upload_cpu_write (GstGLBuffer * mem, GstMapInfo * info,
    gsize size)
{
  const GstGLFuncs *gl = mem->mem.context->gl_vtable;
  gpointer data;

  if (!mem->mem.data)
    /* no data pointer has been written */
    return;

  /* The extra data pointer indirection/memcpy is needed for coherent across
   * concurrent map()'s in both GL and CPU */
  /* FIXME: uploading potentially half-written data for libav pushing READWRITE
   * mapped buffers */
  if (GST_MEMORY_FLAG_IS_SET (mem, GST_GL_BASE_MEMORY_TRANSFER_NEED_UPLOAD)
      || (mem->mem.map_flags & GST_MAP_WRITE) != 0) {
    gl->BindBuffer (mem->target, mem->id);

    if (gl->MapBufferRange) {
      /* FIXME: optionally remove this with a flag and return the
       * glMapBufferRange pointer (requires
       * GL_ARB_buffer_storage/GL4/GL_COHERENT_BIT) */
      guint gl_map_flags = GL_MAP_WRITE_BIT;

      data = gl->MapBufferRange (mem->target, 0, size, gl_map_flags);

      if (data)
        memcpy (data, mem->mem.data, size);

      gl->UnmapBuffer (mem->target);
    } else if (gl->BufferSubData) {
      gl->BufferSubData (mem->target, 0, size, mem->mem.data);
    }
    gl->BindBuffer (mem->target, 0);
  }
}

static gpointer
_gl_buffer_map (GstGLBuffer * mem, GstMapInfo * info, gsize size)
{
  const GstGLFuncs *gl = mem->mem.context->gl_vtable;

  if ((info->flags & GST_MAP_GL) != 0) {
    if (info->flags & GST_MAP_READ) {
      gst_gl_buffer_upload_cpu_write (mem, info, size);
    }
    gl->BindBuffer (mem->target, mem->id);
    return &mem->id;
  } else {
    return gst_gl_buffer_cpu_access (mem, info, size);
  }

  return NULL;
}

static void
_gl_buffer_unmap (GstGLBuffer * mem, GstMapInfo * info)
{
  const GstGLFuncs *gl = mem->mem.context->gl_vtable;

  if ((info->flags & GST_MAP_GL) != 0) {
    gl->BindBuffer (mem->target, 0);
  }
  /* XXX: optimistically transfer data */
}

/**
 * gst_gl_buffer_copy_buffer_sub_data:
 * @src: the source #GstGLBuffer
 * @dest: the destination #GstGLBuffer
 * @offset: the offset to copy from @src
 * @size: the size to copy from @src
 *
 * Copies @src into @dest using glCopyBufferSubData().
 *
 * Returns: whether the copy operation succeeded
 *
 * Since: 1.8
 */
static gboolean
gst_gl_buffer_copy_buffer_sub_data (GstGLBuffer * src,
    GstGLBuffer * dest, gssize offset, gssize size)
{
  const GstGLFuncs *gl = src->mem.context->gl_vtable;
  GstMapInfo sinfo, dinfo;

  if (!gl->CopyBufferSubData)
    /* This is GL(ES) 3.0+ only */
    return FALSE;

  if (!gst_memory_map ((GstMemory *) src, &sinfo, GST_MAP_READ | GST_MAP_GL)) {
    GST_CAT_WARNING (GST_CAT_GL_BUFFER,
        "failed to read map source memory %p", src);
    return FALSE;
  }

  if (!gst_memory_map ((GstMemory *) dest, &dinfo, GST_MAP_WRITE | GST_MAP_GL)) {
    GST_CAT_WARNING (GST_CAT_GL_BUFFER,
        "failed to write map destination memory %p", dest);
    gst_memory_unmap ((GstMemory *) src, &sinfo);
    return FALSE;
  }

  gl->BindBuffer (GL_COPY_READ_BUFFER, src->id);
  gl->BindBuffer (GL_COPY_WRITE_BUFFER, dest->id);
  gl->CopyBufferSubData (GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER,
      offset, 0, size);

  gst_memory_unmap ((GstMemory *) src, &sinfo);
  gst_memory_unmap ((GstMemory *) dest, &dinfo);

  return TRUE;
}

static GstGLBuffer *
_gl_buffer_copy (GstGLBuffer * src, gssize offset, gssize size)
{
  GstAllocator *allocator = src->mem.mem.allocator;
  GstAllocationParams params = { 0, src->mem.mem.align, 0, 0 };
  GstGLBuffer *dest = NULL;

  dest = _gl_buffer_new (allocator, NULL, src->mem.context,
      src->target, src->usage_hints, &params, src->mem.mem.maxsize);

  /* If not doing a full copy, then copy to sysmem, the 2D represention of the
   * texture would become wrong */
  if (GST_MEMORY_FLAG_IS_SET (src, GST_GL_BASE_MEMORY_TRANSFER_NEED_UPLOAD)) {
    if (!gst_gl_base_memory_memcpy (GST_GL_BASE_MEMORY_CAST (src),
            GST_GL_BASE_MEMORY_CAST (dest), offset, size)) {
      GST_CAT_WARNING (GST_CAT_GL_BUFFER, "Could not copy GL Buffer");
      gst_memory_unref (GST_MEMORY_CAST (dest));
      dest = NULL;
    }
  } else {
    if (!gst_gl_buffer_copy_buffer_sub_data (src, dest, offset, size)) {
      if (!gst_gl_base_memory_memcpy (GST_GL_BASE_MEMORY_CAST (src),
              GST_GL_BASE_MEMORY_CAST (dest), offset, size)) {
        GST_CAT_WARNING (GST_CAT_GL_BUFFER, "Could not copy GL Buffer");
        gst_memory_unref (GST_MEMORY_CAST (dest));
        dest = NULL;
      }
    }
  }

  return dest;
}

static GstMemory *
_gl_buffer_alloc (GstAllocator * allocator, gsize size,
    GstAllocationParams * params)
{
  g_critical ("Need to use gst_gl_base_memory_alloc() to allocate from "
      "this allocator");

  return NULL;
}

static void
_gl_buffer_destroy (GstGLBuffer * mem)
{
  const GstGLFuncs *gl = mem->mem.context->gl_vtable;

  gl->DeleteBuffers (1, &mem->id);
}

static void
_gst_gl_buffer_allocation_params_copy_data (GstGLBufferAllocationParams * src,
    GstGLBufferAllocationParams * dest)
{
  memset (dest, 0, sizeof (*dest));

  gst_gl_allocation_params_copy_data (&src->parent, &dest->parent);

  dest->gl_target = src->gl_target;
  dest->gl_usage = src->gl_usage;
}

static void
_gst_gl_buffer_allocation_params_free_data (GstGLBufferAllocationParams *
    params)
{
  gst_gl_allocation_params_free_data (&params->parent);
}

G_DEFINE_BOXED_TYPE (GstGLBufferAllocationParams,
    gst_gl_buffer_allocation_params,
    (GBoxedCopyFunc) gst_gl_allocation_params_copy,
    (GBoxedFreeFunc) gst_gl_allocation_params_free);

/**
 * gst_gl_buffer_allocation_params_new:
 * @context: a #GstGLContext
 * @alloc_size: the size in bytes to allocate
 * @alloc_params: (allow-none): the #GstAllocationParams for @tex_id
 * @gl_target: the OpenGL target to allocate
 * @gl_usage: the OpenGL usage hint to allocate with
 *
 * Returns: a new #GstGLBufferAllocationParams for allocating OpenGL buffer
 *          objects
 *
 * Since: 1.8
 */
GstGLBufferAllocationParams *
gst_gl_buffer_allocation_params_new (GstGLContext * context, gsize alloc_size,
    GstAllocationParams * alloc_params, guint gl_target, guint gl_usage)
{
  GstGLBufferAllocationParams *params;

  g_return_val_if_fail (GST_IS_GL_CONTEXT (context), NULL);
  g_return_val_if_fail (alloc_size > 0, NULL);

  params = g_new0 (GstGLBufferAllocationParams, 1);

  if (!gst_gl_allocation_params_init (&params->parent, sizeof (*params),
          GST_GL_ALLOCATION_PARAMS_ALLOC_FLAG_BUFFER |
          GST_GL_ALLOCATION_PARAMS_ALLOC_FLAG_ALLOC,
          (GstGLAllocationParamsCopyFunc)
          _gst_gl_buffer_allocation_params_copy_data,
          (GstGLAllocationParamsFreeFunc)
          _gst_gl_buffer_allocation_params_free_data, context, alloc_size,
          alloc_params, NULL, 0, NULL, NULL)) {
    g_free (params);
    return NULL;
  }

  params->gl_target = gl_target;
  params->gl_usage = gl_usage;

  return params;
}

static GstGLBuffer *
_gl_buffer_alloc_mem (GstGLBufferAllocator * allocator,
    GstGLBufferAllocationParams * params)
{
  guint alloc_flags = params->parent.alloc_flags;

  g_return_val_if_fail (alloc_flags &
      GST_GL_ALLOCATION_PARAMS_ALLOC_FLAG_BUFFER, NULL);
  g_return_val_if_fail (alloc_flags & GST_GL_ALLOCATION_PARAMS_ALLOC_FLAG_ALLOC,
      NULL);

  return _gl_buffer_new (GST_ALLOCATOR (allocator), NULL,
      params->parent.context, params->gl_target, params->gl_usage,
      params->parent.alloc_params, params->parent.alloc_size);
}

G_DEFINE_TYPE (GstGLBufferAllocator, gst_gl_buffer_allocator,
    GST_TYPE_GL_BASE_MEMORY_ALLOCATOR);

static void
gst_gl_buffer_allocator_class_init (GstGLBufferAllocatorClass * klass)
{
  GstAllocatorClass *allocator_class = (GstAllocatorClass *) klass;
  GstGLBaseMemoryAllocatorClass *gl_base;

  gl_base = (GstGLBaseMemoryAllocatorClass *) klass;

  gl_base->alloc = (GstGLBaseMemoryAllocatorAllocFunction) _gl_buffer_alloc_mem;
  gl_base->create = (GstGLBaseMemoryAllocatorCreateFunction) _gl_buffer_create;
  gl_base->map = (GstGLBaseMemoryAllocatorMapFunction) _gl_buffer_map;
  gl_base->unmap = (GstGLBaseMemoryAllocatorUnmapFunction) _gl_buffer_unmap;
  gl_base->copy = (GstGLBaseMemoryAllocatorCopyFunction) _gl_buffer_copy;
  gl_base->destroy =
      (GstGLBaseMemoryAllocatorDestroyFunction) _gl_buffer_destroy;

  allocator_class->alloc = _gl_buffer_alloc;
}

static void
gst_gl_buffer_allocator_init (GstGLBufferAllocator * allocator)
{
  GstAllocator *alloc = GST_ALLOCATOR_CAST (allocator);

  alloc->mem_type = GST_GL_BUFFER_ALLOCATOR_NAME;

  GST_OBJECT_FLAG_SET (allocator, GST_ALLOCATOR_FLAG_CUSTOM_ALLOC);
}

/**
 * gst_gl_buffer_init_once:
 *
 * Initializes the GL Buffer allocator. It is safe to call this function
 * multiple times.  This must be called before any other #GstGLBuffer operation.
 *
 * Since: 1.8
 */
void
gst_gl_buffer_init_once (void)
{
  static volatile gsize _init = 0;

  if (g_once_init_enter (&_init)) {
    gst_gl_base_memory_init_once ();

    GST_DEBUG_CATEGORY_INIT (GST_CAT_GL_BUFFER, "glbuffer", 0, "OpenGL Buffer");

    _gl_buffer_allocator =
        g_object_new (gst_gl_buffer_allocator_get_type (), NULL);
    gst_object_ref_sink (_gl_buffer_allocator);

    /* The allocator is never unreffed */
    GST_OBJECT_FLAG_SET (_gl_buffer_allocator, GST_OBJECT_FLAG_MAY_BE_LEAKED);

    gst_allocator_register (GST_GL_BUFFER_ALLOCATOR_NAME,
        gst_object_ref (_gl_buffer_allocator));
    g_once_init_leave (&_init, 1);
  }
}

/**
 * gst_is_gl_buffer:
 * @mem:a #GstMemory
 *
 * Returns: whether the memory at @mem is a #GstGLBuffer
 *
 * Since: 1.8
 */
gboolean
gst_is_gl_buffer (GstMemory * mem)
{
  return mem != NULL && mem->allocator != NULL &&
      g_type_is_a (G_OBJECT_TYPE (mem->allocator),
      GST_TYPE_GL_BUFFER_ALLOCATOR);
}
