/*
 * GStreamer
 * Copyright (C) 2015 Alessandro Decina <twi@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 "iosglmemory.h"

GST_DEBUG_CATEGORY_STATIC (GST_CAT_IOS_GL_MEMORY);
#define GST_CAT_DEFAULT GST_CAT_IOS_GL_MEMORY

G_DEFINE_TYPE (GstIOSGLMemoryAllocator, gst_ios_gl_memory_allocator,
    GST_TYPE_GL_MEMORY_ALLOCATOR);

typedef struct
{
  GstIOSGLMemory *memory;
} ContextThreadData;

static GstAllocator *_ios_gl_memory_allocator;

static void
_ios_gl_memory_destroy (GstGLBaseMemory * gl_mem)
{
  GstIOSGLMemory *mem = (GstIOSGLMemory *) gl_mem;

  mem->gl_notify (mem->gl_data);
  gst_memory_unref (GST_MEMORY_CAST (mem->cv_mem));
  GST_GL_BASE_MEMORY_ALLOCATOR_CLASS
      (gst_ios_gl_memory_allocator_parent_class)->destroy (gl_mem);
}

static gpointer
_ios_gl_memory_allocator_map (GstGLBaseMemory * bmem,
    GstMapInfo * info, gsize size)
{
  GstGLMemory *gl_mem = (GstGLMemory *) bmem;
  GstIOSGLMemory *mem = (GstIOSGLMemory *) gl_mem;

  if (info->flags & GST_MAP_GL)
    return &gl_mem->tex_id;
  return GST_MEMORY_CAST (mem->cv_mem)->allocator->
      mem_map (GST_MEMORY_CAST (mem->cv_mem), size, info->flags);
}

static void
_ios_gl_memory_allocator_unmap (GstGLBaseMemory * bmem, GstMapInfo * info)
{
  GstIOSGLMemory *mem = (GstIOSGLMemory *) bmem;

  if (!(info->flags & GST_MAP_GL))
    GST_MEMORY_CAST (mem->cv_mem)->allocator->
        mem_unmap (GST_MEMORY_CAST (mem->cv_mem));
}

static GstMemory *
_mem_alloc (GstAllocator * allocator, gsize size, GstAllocationParams * params)
{
  g_warning ("use gst_ios_gl_memory_new_wrapped () to allocate from this "
      "IOSGL allocator");

  return NULL;
}

static void
gst_ios_gl_memory_allocator_class_init (GstIOSGLMemoryAllocatorClass * klass)
{
  GstAllocatorClass *allocator_class = (GstAllocatorClass *) klass;
  GstGLBaseMemoryAllocatorClass *gl_base_allocator_class =
      (GstGLBaseMemoryAllocatorClass *) klass;

  allocator_class->alloc = _mem_alloc;
  gl_base_allocator_class->destroy = _ios_gl_memory_destroy;
  gl_base_allocator_class->map = _ios_gl_memory_allocator_map;
  gl_base_allocator_class->unmap = _ios_gl_memory_allocator_unmap;
}

static void
gst_ios_gl_memory_allocator_init (GstIOSGLMemoryAllocator * allocator)
{
  GstAllocator *alloc = GST_ALLOCATOR_CAST (allocator);

  alloc->mem_type = GST_IOS_GL_MEMORY_ALLOCATOR_NAME;
  GST_OBJECT_FLAG_SET (allocator, GST_ALLOCATOR_FLAG_CUSTOM_ALLOC);
}

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

  if (g_once_init_enter (&_init)) {
    GST_DEBUG_CATEGORY_INIT (GST_CAT_IOS_GL_MEMORY, "iosurface", 0,
        "IOSGL Buffer");

    _ios_gl_memory_allocator =
        g_object_new (GST_TYPE_IOS_GL_MEMORY_ALLOCATOR, NULL);
    gst_object_ref_sink (_ios_gl_memory_allocator);

    gst_allocator_register (GST_IOS_GL_MEMORY_ALLOCATOR_NAME,
        gst_object_ref (_ios_gl_memory_allocator));
    g_once_init_leave (&_init, 1);
  }
}

gboolean
gst_is_ios_gl_memory (GstMemory * mem)
{
  return mem != NULL && mem->allocator != NULL &&
      g_type_is_a (G_OBJECT_TYPE (mem->allocator),
      GST_TYPE_IOS_GL_MEMORY_ALLOCATOR);
}

static GstIOSGLMemory *
_ios_gl_memory_new (GstGLContext * context,
    GstAppleCoreVideoMemory * cv_mem,
    GstGLTextureTarget target,
    GstGLFormat tex_format,
    guint tex_id,
    GstVideoInfo * info,
    guint plane,
    GstVideoAlignment * valign, gpointer gl_data, GDestroyNotify gl_notify)
{
  GstIOSGLMemory *mem;

  mem = g_new0 (GstIOSGLMemory, 1);
  mem->gl_mem.tex_id = tex_id;
  mem->gl_mem.texture_wrapped = TRUE;
  gst_gl_memory_init (&mem->gl_mem, _ios_gl_memory_allocator, NULL, context,
      target, tex_format, NULL, info, plane, valign, NULL, NULL);
  mem->cv_mem = cv_mem;
  mem->gl_data = gl_data;
  mem->gl_notify = gl_notify;

  GST_MINI_OBJECT_FLAG_SET (mem, GST_MEMORY_FLAG_READONLY);

  return mem;
}

GstIOSGLMemory *
gst_ios_gl_memory_new_wrapped (GstGLContext * context,
    GstAppleCoreVideoMemory * cv_mem,
    GstGLTextureTarget target,
    GstGLFormat tex_format,
    guint tex_id,
    GstVideoInfo * info,
    guint plane,
    GstVideoAlignment * valign, gpointer gl_data, GDestroyNotify gl_notify)
{
  return _ios_gl_memory_new (context, cv_mem, target, tex_format, tex_id, info,
      plane, valign, gl_data, gl_notify);
}
