//
// This file is part of MorphoGraphX - http://www.MorphoGraphX.org
// Copyright (C) 2012-2015 Richard S. Smith and collaborators.
//
// If you use MorphoGraphX in your work, please cite:
//   http://dx.doi.org/10.7554/eLife.05864
//
// MorphoGraphX is free software, and is licensed under under the terms of the 
// GNU General (GPL) Public License version 2.0, http://www.gnu.org/licenses.
// 
#ifndef CUDA_EXPORT_HPP
#define CUDA_EXPORT_HPP

#include <Config.hpp>
#include <cuda/CudaGlobal.hpp>
#include <Geometry.hpp>
#include <thrust/host_vector.h>

namespace mgx 
{
  // Define host_vector types used by MorphoGraphX
  typedef thrust::host_vector<uint> HVecU;
  typedef thrust::host_vector<ushort> HVecUS;
  typedef thrust::host_vector<float> HVecF;
  typedef thrust::host_vector<Point3u> HVec3U;
  typedef thrust::host_vector<Point3f> HVec3F;
  typedef thrust::host_vector<Point4f> HVec4F;

  cuda_EXPORT int initGPU();
  cuda_EXPORT int setHoldMemGPU(uint holdmem);
  cuda_EXPORT void freeMem();
  cuda_EXPORT void holdMem();
  cuda_EXPORT void memAvail(); 

  cuda_EXPORT int averageGPU(const Point3i &imgSize, const Point3i &radius,
    const HVecUS &srcdata, HVecUS &dstdata);
  cuda_EXPORT int medianGPU(const Point3i &imgSize, const Point3i &radius,
    const HVecUS &srcdata, HVecUS &dstdata);
  cuda_EXPORT int medianOfMediansGPU(const Point3i &imgSize, const Point3i &radius,
    const HVecUS &srcdata, HVecUS &dstdata);
  cuda_EXPORT int dilateGPU(const Point3i &imgSize, const Point3i &radius, bool roundNhbd,
    const HVecUS &srcdata, HVecUS &dstdata);
  cuda_EXPORT int erodeGPU(const Point3i &imgSize, const Point3i &radius, bool byLabel, bool roundNhbd,
    const HVecUS &srcdata, HVecUS &dstdata);
  cuda_EXPORT int gaussianBlurGPU(const Point3i &imgSize, const Point3f &imgStep,
    const Point3f &sigma, const HVecUS &srcdata, HVecUS &dstdata);
  cuda_EXPORT int sharpenGPU(const Point3i &imgSize, const Point3f &imgStep,
    const Point3f &sigma, const float amount, const HVecUS &srcdata, HVecUS &dstdata);
  cuda_EXPORT int applyKernelGPU(const Point3i &imgSize, const HVecF &kernelX,
    const HVecF &kernelY, const HVecF &kernelZ,
    const HVecUS &srcdata, HVecUS &dstdata);
  cuda_EXPORT int colorGradGPU(const Point3i &imgSize, float div, const HVecUS &srcdata,
    HVecUS &dstdata);
  cuda_EXPORT int edgeDetectGPU(const Point3i &imgSize, ushort lowthresh, ushort highthresh, 
    float mult, ushort fillval, const HVecUS &srcdata, HVecUS &dstdata);
  cuda_EXPORT int insideMeshGPU(const Point3i &base, const Point3i &size, 
    const Point3f &step, const Point3f &shift, const HVec3F &pts, 
    const HVec3U &tris, const HVec3F &nrmls, HVecUS &dstdata);
  cuda_EXPORT int nearMeshGPU(const Point3i &base, const Point3i &size, 
    const Point3f &step, const Point3f &shift, const HVec3F &pts, 
    const HVec3F &nrmls, float minDist, float maxDist, HVecUS &dstdata);
  cuda_EXPORT int clipStackGPU(const Point3i &imgSize, const Point3f &step, 
    const Point3f &shift, const Point3u &clipDo, HVec4F &pn, 
    const HVecUS &srcdata, HVecUS &dstdata);
  cuda_EXPORT int voxelEditGPU(const Point3i &base, const Point3i &size, 
    const Point3i &imgSize, const Point3f &step, const Point3f &shift, 
    const Point3f &p, const Point3f &pz, float radius, ushort color, 
    const Point3u &clipDo, const HVec4F &pn, HVecUS &data);
}
#endif
