// Copyright (c) 1985-2020 Intel Corporation
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.


#ifndef __CMRT_CROSS_PLATFORM_H__
#define __CMRT_CROSS_PLATFORM_H__

#include "mfx_common.h"
#include "cmrt_utility.h"
#include "asc_structures.h"

/* Applicable for old and new CMAPI */

#define CM_LINUX

#ifndef CM_NOINLINE
#ifndef CM_EMU
#ifndef __GNUC__
#define CM_NOINLINE __declspec(noinline)
#else
#define CM_NOINLINE __attribute__((noinline))
#endif
#else
#define CM_NOINLINE
#endif /* CM_EMU */
#endif

#ifndef CM_INLINE
#ifndef __GNUC__
#define CM_INLINE __forceinline
#else
#define CM_INLINE inline __attribute__((always_inline))
#endif
#endif

#if defined(__INTEL_COMPILER)
   #pragma warning(push)
   #pragma warning(disable:2289)
 #endif

#if defined(__clang__)
  #pragma clang diagnostic push
  #pragma clang diagnostic ignored "-Wnon-virtual-dtor"

  #pragma clang diagnostic push
  #pragma clang diagnostic ignored "-Wunused-private-field"
#else
#if defined(__GNUC__)
  #pragma GCC diagnostic push
  #pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
#endif
#endif

class SurfaceIndex
{
public:
    CM_NOINLINE SurfaceIndex() { index = 0; };
    CM_NOINLINE SurfaceIndex(const SurfaceIndex& _src) { index = _src.index; };
    CM_NOINLINE SurfaceIndex(const unsigned int& _n) { index = _n; };
    CM_NOINLINE SurfaceIndex& operator = (const unsigned int& _n) { this->index = _n; return *this; };
    CM_NOINLINE SurfaceIndex& operator + (const unsigned int& _n) { this->index += _n; return *this; };
    virtual unsigned int get_data(void) { return index; };

private:
    unsigned int index;
#ifdef CM_LINUX
    /*
     * Do not delete this line:
     * SurfaceIndex is commonly used as CM kernel function's parameter.
     * It has virutal table and has copy constructor, so GNU calling convetion will pass the object's pointer to kernel function.
     * This is different with Windows VC++, which always copies the entire object transferred on the callee's stack.
     *
     * Depending on the special object size after adding below "extra_byte",
     * SetKernelArg and SetThreadArg can recognize this object and follow GNU's convention to construct kernel function's stack.
     * Detail can be found on "https://github.com/intel/cm-compiler#documentation"
     */
    unsigned char extra_byte;
#endif
};

class SamplerIndex
{
public:
    CM_NOINLINE SamplerIndex() { index = 0; };
    CM_NOINLINE SamplerIndex(SamplerIndex& _src) { index = _src.get_data(); };
    CM_NOINLINE SamplerIndex(const unsigned int& _n) { index = _n; };
    CM_NOINLINE SamplerIndex& operator = (const unsigned int& _n) { this->index = _n; return *this; };
    virtual unsigned int get_data(void) { return index; };

private:
    unsigned int index;
#ifdef CM_LINUX
    /*
     * Do not delete this line:
     * Same reason as SurfaceIndex.
     */
    unsigned char extra_byte;
#endif
};

#if defined(__clang__)
  #pragma clang diagnostic pop // "-Wunused-private-field"
#endif

#ifdef _MSVC_LANG
#pragma warning(push)
#pragma warning(disable: 4100)
#pragma warning(disable: 4201)
#endif

typedef void * AbstractSurfaceHandle;
typedef void * AbstractDeviceHandle;

struct IDirect3DSurface9;
struct IDirect3DDeviceManager9;
struct ID3D11Texture2D;
struct ID3D11Device;

#ifdef __cplusplus
#   define EXTERN_C     extern "C"
#else
#   define EXTERN_C
#endif

#ifdef CM_LINUX
#define LONG INCORRECT_64BIT_LONG
#define ULONG INCORRECT_64BIT_ULONG
#ifdef __int64
#undef __int64
#endif

#include <time.h>
#include <va/va.h>

#define _tmain main

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <math.h>
#include <malloc.h>
#include <string.h>
#include <sys/time.h>
#include <pthread.h>
#include <x86intrin.h>
#include <iostream>

typedef int BOOL;

#ifndef FALSE
#define FALSE     0
#endif
#ifndef TRUE
#define TRUE      1
#endif

typedef char byte;
typedef unsigned char BYTE;
typedef unsigned int UINT32;
typedef UINT32 DWORD;
typedef int INT;
typedef unsigned int UINT;
typedef signed char INT8;
typedef unsigned char UINT8;
typedef signed short INT16;
typedef unsigned short UINT16;
typedef signed int INT32;
typedef signed long long INT64;
typedef unsigned long long UINT64;

typedef enum _VACMTEXTUREADDRESS {
    VACMTADDRESS_WRAP = 1,
    VACMTADDRESS_MIRROR = 2,
    VACMTADDRESS_CLAMP = 3,
    VACMTADDRESS_BORDER = 4,
    VACMTADDRESS_MIRRORONCE = 5,

    VACMTADDRESS_FORCE_DWORD = 0x7fffffff
} VACMTEXTUREADDRESS;

typedef enum _VACMTEXTUREFILTERTYPE {
    VACMTEXF_NONE = 0,
    VACMTEXF_POINT = 1,
    VACMTEXF_LINEAR = 2,
    VACMTEXF_ANISOTROPIC = 3,
    VACMTEXF_FLATCUBIC = 4,
    VACMTEXF_GAUSSIANCUBIC = 5,
    VACMTEXF_PYRAMIDALQUAD = 6,
    VACMTEXF_GAUSSIANQUAD = 7,
    VACMTEXF_CONVOLUTIONMONO = 8,    // Convolution filter for monochrome textures
    VACMTEXF_FORCE_DWORD = 0x7fffffff
} VACMTEXTUREFILTERTYPE;

#define CM_MAX_TIMEOUT 2

#define CM_ATTRIBUTE(attribute) __attribute__((attribute))

typedef enum _VA_CM_FORMAT {

    VA_CM_FMT_UNKNOWN = 0,

    VA_CM_FMT_A8R8G8B8 = 21,
    VA_CM_FMT_X8R8G8B8 = 22,
    VA_CM_FMT_A8 = 28,
    VA_CM_FMT_A2B10G10R10 = 31,
    VA_CM_FMT_A8B8G8R8 = 32,
    VA_CM_FMT_A16B16G16R16 = 36,
    VA_CM_FMT_P8 = 41,
    VA_CM_FMT_L8 = 50,
    VA_CM_FMT_A8L8 = 51,
    VA_CM_FMT_R16U = 57,
    VA_CM_FMT_V8U8 = 60,
    VA_CM_FMT_R8U = 62,
    VA_CM_FMT_D16 = 80,
    VA_CM_FMT_L16 = 81,
    VA_CM_FMT_A16B16G16R16F = 113,
    VA_CM_FMT_R32F = 114,
    VA_CM_FMT_NV12 = VA_FOURCC_NV12,
    VA_CM_FMT_UYVY = VA_FOURCC_UYVY,
    VA_CM_FMT_YUY2 = VA_FOURCC_YUY2,
    VA_CM_FMT_444P = VA_FOURCC_444P,
    VA_CM_FMT_411P = VA_FOURCC_411P,
    VA_CM_FMT_422H = VA_FOURCC_422H,
    VA_CM_FMT_422V = VA_FOURCC_422V,
    VA_CM_FMT_IMC3 = VA_FOURCC_IMC3,
    VA_CM_FMT_YV12 = VA_FOURCC_YV12,
    VA_CM_FMT_P010 = VA_FOURCC_P010,
    VA_CM_FMT_P016 = VA_FOURCC_P016,

    VA_CM_FMT_MAX = 0xFFFFFFFF
} VA_CM_FORMAT;

inline void * CM_ALIGNED_MALLOC(size_t size, size_t alignment)
{
    return memalign(alignment, size);
}

inline void CM_ALIGNED_FREE(void * memory)
{
    free(memory);
}

//multi-thread API:
#define THREAD_HANDLE pthread_t
inline void CM_THREAD_CREATE(THREAD_HANDLE *handle, void * start_routine, void * arg)
{
    int err = 0;
    err = pthread_create(handle, NULL, (void * (*)(void *))start_routine, arg);
    if (err) {
        printf(" cm create thread failed! \n");
        exit(-1);
    }
}
inline void CM_THREAD_EXIT(void * retval)
{
    pthread_exit(retval);
}

inline int CM_THREAD_JOIN(THREAD_HANDLE *handle_array, int thread_cnt)
{
    void *tret;
    for (int i = 0; i < thread_cnt; i++)
    {
        pthread_join(handle_array[i], &tret);
    }
    return 0;
}

#define CM_SURFACE_FORMAT                       VA_CM_FORMAT

#define CM_SURFACE_FORMAT_UNKNOWN               VA_CM_FMT_UNKNOWN
#define CM_SURFACE_FORMAT_A8R8G8B8              VA_CM_FMT_A8R8G8B8
#define CM_SURFACE_FORMAT_X8R8G8B8              VA_CM_FMT_X8R8G8B8
#define CM_SURFACE_FORMAT_A8B8G8R8              VA_CM_FMT_A8B8G8R8
#define CM_SURFACE_FORMAT_A8                    VA_CM_FMT_A8
#define CM_SURFACE_FORMAT_P8                    VA_CM_FMT_P8
#define CM_SURFACE_FORMAT_R32F                  VA_CM_FMT_R32F
#define CM_SURFACE_FORMAT_NV12                  VA_CM_FMT_NV12
#define CM_SURFACE_FORMAT_UYVY                  VA_CM_FMT_UYVY
#define CM_SURFACE_FORMAT_YUY2                  VA_CM_FMT_YUY2
#define CM_SURFACE_FORMAT_V8U8                  VA_CM_FMT_V8U8

#define CM_SURFACE_FORMAT_R8_UINT               VA_CM_FMT_R8U
#define CM_SURFACE_FORMAT_R16_UINT              VA_CM_FMT_R16U
#define CM_SURFACE_FORMAT_R16_SINT              VA_CM_FMT_A8L8
#define CM_SURFACE_FORMAT_D16                   VA_CM_FMT_D16
#define CM_SURFACE_FORMAT_L16                   VA_CM_FMT_L16
#define CM_SURFACE_FORMAT_A16B16G16R16          VA_CM_FMT_A16B16G16R16
#define CM_SURFACE_FORMAT_R10G10B10A2           VA_CM_FMT_A2B10G10R10
#define CM_SURFACE_FORMAT_A16B16G16R16F         VA_CM_FMT_A16B16G16R16F

#define CM_SURFACE_FORMAT_444P                  VA_CM_FMT_444P
#define CM_SURFACE_FORMAT_422H                  VA_CM_FMT_422H
#define CM_SURFACE_FORMAT_422V                  VA_CM_FMT_422V
#define CM_SURFACE_FORMAT_411P                  VA_CM_FMT_411P
#define CM_SURFACE_FORMAT_IMC3                  VA_CM_FMT_IMC3
#define CM_SURFACE_FORMAT_YV12                  VA_CM_FMT_YV12
#define CM_SURFACE_FORMAT_P010                  VA_CM_FMT_P010
#define CM_SURFACE_FORMAT_P016                  VA_CM_FMT_P016


#define CM_TEXTURE_ADDRESS_TYPE                 VACMTEXTUREADDRESS
#define CM_TEXTURE_ADDRESS_WRAP                 VACMTADDRESS_WRAP
#define CM_TEXTURE_ADDRESS_MIRROR               VACMTADDRESS_MIRROR
#define CM_TEXTURE_ADDRESS_CLAMP                VACMTADDRESS_CLAMP
#define CM_TEXTURE_ADDRESS_BORDER               VACMTADDRESS_BORDER
#define CM_TEXTURE_ADDRESS_MIRRORONCE           VACMTADDRESS_MIRRORONCE

#define CM_TEXTURE_FILTER_TYPE                  VACMTEXTUREFILTERTYPE
#define CM_TEXTURE_FILTER_TYPE_NONE             VACMTEXF_NONE
#define CM_TEXTURE_FILTER_TYPE_POINT            VACMTEXF_POINT
#define CM_TEXTURE_FILTER_TYPE_LINEAR           VACMTEXF_LINEAR
#define CM_TEXTURE_FILTER_TYPE_ANISOTROPIC      VACMTEXF_ANISOTROPIC
#define CM_TEXTURE_FILTER_TYPE_FLATCUBIC        VACMTEXF_FLATCUBIC
#define CM_TEXTURE_FILTER_TYPE_GAUSSIANCUBIC    VACMTEXF_GAUSSIANCUBIC
#define CM_TEXTURE_FILTER_TYPE_PYRAMIDALQUAD    VACMTEXF_PYRAMIDALQUAD
#define CM_TEXTURE_FILTER_TYPE_GAUSSIANQUAD     VACMTEXF_GAUSSIANQUAD
#define CM_TEXTURE_FILTER_TYPE_CONVOLUTIONMONO  VACMTEXF_CONVOLUTIONMONO

/* Surrport for common-used data type */
#define  _TCHAR char
#ifndef TRUE
#define TRUE 1
#endif

typedef int HKEY;

typedef unsigned int uint;
typedef unsigned int* PUINT;

typedef float FLOAT;
typedef unsigned long long DWORDLONG;
#ifndef ULONG_PTR
#define ULONG_PTR unsigned long
#endif

/* Handle Type */
typedef void *HMODULE;
typedef void *HINSTANCE;
typedef int HANDLE;
typedef void *PVOID;
typedef int WINBOOL;
typedef BOOL *PBOOL;
typedef unsigned long ULONG;
typedef ULONG *PULONG;
typedef unsigned short USHORT;
typedef USHORT *PUSHORT;
typedef unsigned char UCHAR;
typedef UCHAR *PUCHAR;
typedef char CHAR;
typedef short SHORT;
typedef long LONG;
typedef double DOUBLE;

#define __int8 char
#define __int16 short
#define __int32 int
#define __int64 long long

typedef unsigned short WORD;
typedef float FLOAT;
typedef FLOAT *PFLOAT;
typedef BYTE *PBYTE;
typedef int *PINT;
typedef WORD *PWORD;
typedef DWORD *PDWORD;
typedef unsigned int *PUINT;
typedef LONG HRESULT;
typedef long long LONGLONG;

//Performance
EXTERN_C INT QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency);
EXTERN_C INT QueryPerformanceCounter(LARGE_INTEGER *lpPerformanceCount);

struct BITMAPFILEHEADER
{
    WORD  bfType;
    DWORD bfSize;
    WORD  bfReserved1;
    WORD  bfReserved2;
    DWORD bfOffBits;
}  __attribute__((packed));

struct BITMAPINFOHEADER
{
    DWORD biSize;
    DWORD  biWidth;
    DWORD  biHeight;
    WORD  biPlanes;
    WORD  biBitCount;
    DWORD biCompression;
    DWORD biSizeImage;
    DWORD  biXPelsPerMeter;
    DWORD  biYPelsPerMeter;
    DWORD biClrUsed;
    DWORD biClrImportant;
};

struct RGBQUAD
{
    BYTE rgbBlue;
    BYTE rgbGreen;
    BYTE rgbRed;
    BYTE rgbReserved;
};


#ifdef CMRT_EMU
// below macro definition is to workaround a bug in g++4.4
template<typename kernelFunctionTy>
inline void * CM_KERNEL_FUNCTION_TO_POINTER(kernelFunctionTy kernelFunction)
{
    return (void *)kernelFunction;
}
#define CM_KERNEL_FUNCTION2(...) #__VA_ARGS__, CM_KERNEL_FUNCTION_TO_POINTER(__VA_ARGS__)
#else
#define CM_KERNEL_FUNCTION2(...) #__VA_ARGS__
#endif

#ifdef CMRT_EMU
// below macro definition is to workaround a bug in g++4.4
template<typename kernelFunctionTy>
inline void * CM_KERNEL_FUNCTION_POINTER(kernelFunctionTy kernelFunction)
{
    return (void *)kernelFunction;
}
#define _NAME(...) #__VA_ARGS__, CM_KERNEL_FUNCTION_POINTER(__VA_ARGS__)
#else
#define _NAME(...) #__VA_ARGS__
#endif

#else // ifdef CM_LINUX

#define CM_ATTRIBUTE(attribute) __declspec(attribute)
#define CM_TYPE_NAME(type)  typeid(type).name()

inline void * CM_ALIGNED_MALLOC(size_t size, size_t alignment)
{
    return _aligned_malloc(size, alignment);
}

inline void CM_ALIGNED_FREE(void * memory)
{
    _aligned_free(memory);
}

#if !CM_METRO
//multi-thread API:
#define THREAD_HANDLE HANDLE
inline void CM_THREAD_CREATE(THREAD_HANDLE *handle, void * start_routine, void * arg)
{
    handle[0] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)start_routine, (LPVOID)arg, 0, NULL);
}
inline void CM_THREAD_EXIT(void * retval)
{
    ExitThread(0);
}

inline int CM_THREAD_JOIN(THREAD_HANDLE *handle_array, int thread_cnt)
{
    DWORD ret = WaitForMultipleObjects(thread_cnt, handle_array, true, INFINITE);
    return ret;
}
#endif

#define CM_SURFACE_FORMAT                       D3DFORMAT

#define CM_SURFACE_FORMAT_UNKNOWN               D3DFMT_UNKNOWN
#define CM_SURFACE_FORMAT_A8R8G8B8              D3DFMT_A8R8G8B8
#define CM_SURFACE_FORMAT_X8R8G8B8              D3DFMT_X8R8G8B8
#define CM_SURFACE_FORMAT_A8B8G8R8              D3DFMT_A8B8G8R8
#define CM_SURFACE_FORMAT_A8                    D3DFMT_A8
#define CM_SURFACE_FORMAT_P8                    D3DFMT_P8
#define CM_SURFACE_FORMAT_R32F                  D3DFMT_R32F
#define CM_SURFACE_FORMAT_NV12                  (D3DFORMAT)MAKEFOURCC('N','V','1','2')
#define CM_SURFACE_FORMAT_P016                  (D3DFORMAT)MAKEFOURCC('P','0','1','6')
#define CM_SURFACE_FORMAT_P010                  (D3DFORMAT)MAKEFOURCC('P','0','1','0')
#define CM_SURFACE_FORMAT_UYVY                  D3DFMT_UYVY
#define CM_SURFACE_FORMAT_YUY2                  D3DFMT_YUY2
#define CM_SURFACE_FORMAT_V8U8                  D3DFMT_V8U8
#define CM_SURFACE_FORMAT_A8L8                  D3DFMT_A8L8
#define CM_SURFACE_FORMAT_D16                   D3DFMT_D16
#define CM_SURFACE_FORMAT_L16                   D3DFMT_L16
#define CM_SURFACE_FORMAT_A16B16G16R16          D3DFMT_A16B16G16R16
#define CM_SURFACE_FORMAT_A16B16G16R16F         D3DFMT_A16B16G16R16F
#define CM_SURFACE_FORMAT_R10G10B10A2           D3DFMT_A2B10G10R10
#define CM_SURFACE_FORMAT_IRW0                  (D3DFORMAT)MAKEFOURCC('I','R','W','0')
#define CM_SURFACE_FORMAT_IRW1                  (D3DFORMAT)MAKEFOURCC('I','R','W','1')
#define CM_SURFACE_FORMAT_IRW2                  (D3DFORMAT)MAKEFOURCC('I','R','W','2')
#define CM_SURFACE_FORMAT_IRW3                  (D3DFORMAT)MAKEFOURCC('I','R','W','3')
#define CM_SURFACE_FORMAT_R16_FLOAT             D3DFMT_R16F  //beryl
#define CM_SURFACE_FORMAT_A8P8                  D3DFMT_A8P8
#define CM_SURFACE_FORMAT_I420                  (D3DFORMAT)MAKEFOURCC('I','4','2','0')
#define CM_SURFACE_FORMAT_IMC3                  (D3DFORMAT)MAKEFOURCC('I','M','C','3')
#define CM_SURFACE_FORMAT_IA44                  (D3DFORMAT)MAKEFOURCC('I','A','4','4')
#define CM_SURFACE_FORMAT_AI44                  (D3DFORMAT)MAKEFOURCC('A','I','4','4')
#define CM_SURFACE_FORMAT_P216                  (D3DFORMAT)MAKEFOURCC('P','2','1','6')
#define CM_SURFACE_FORMAT_Y410                  (D3DFORMAT)MAKEFOURCC('Y','4','1','0')
#define CM_SURFACE_FORMAT_Y416                  (D3DFORMAT)MAKEFOURCC('Y','4','1','6')
#define CM_SURFACE_FORMAT_Y210                  (D3DFORMAT)MAKEFOURCC('Y','2','1','0')
#define CM_SURFACE_FORMAT_Y216                  (D3DFORMAT)MAKEFOURCC('Y','2','1','6')
#define CM_SURFACE_FORMAT_AYUV                  (D3DFORMAT)MAKEFOURCC('A','Y','U','V')
#define CM_SURFACE_FORMAT_YV12                  (D3DFORMAT)MAKEFOURCC('Y','V','1','2')
#define CM_SURFACE_FORMAT_400P                  (D3DFORMAT)MAKEFOURCC('4','0','0','P')
#define CM_SURFACE_FORMAT_411P                  (D3DFORMAT)MAKEFOURCC('4','1','1','P')
#define CM_SURFACE_FORMAT_411R                  (D3DFORMAT)MAKEFOURCC('4','1','1','R')
#define CM_SURFACE_FORMAT_422H                  (D3DFORMAT)MAKEFOURCC('4','2','2','H')
#define CM_SURFACE_FORMAT_422V                  (D3DFORMAT)MAKEFOURCC('4','2','2','V')
#define CM_SURFACE_FORMAT_444P                  (D3DFORMAT)MAKEFOURCC('4','4','4','P')
#define CM_SURFACE_FORMAT_RGBP                  (D3DFORMAT)MAKEFOURCC('R','G','B','P')
#define CM_SURFACE_FORMAT_BGRP                  (D3DFORMAT)MAKEFOURCC('B','G','R','P')

#define CM_TEXTURE_ADDRESS_TYPE                 D3DTEXTUREADDRESS

#define CM_TEXTURE_ADDRESS_WRAP                 D3DTADDRESS_WRAP
#define CM_TEXTURE_ADDRESS_MIRROR               D3DTADDRESS_MIRROR
#define CM_TEXTURE_ADDRESS_CLAMP                D3DTADDRESS_CLAMP
#define CM_TEXTURE_ADDRESS_BORDER               D3DTADDRESS_BORDER
#define CM_TEXTURE_ADDRESS_MIRRORONCE           D3DTADDRESS_MIRRORONCE

#define CM_TEXTURE_FILTER_TYPE                  D3DTEXTUREFILTERTYPE

#define CM_TEXTURE_FILTER_TYPE_NONE             D3DTEXF_NONE
#define CM_TEXTURE_FILTER_TYPE_POINT            D3DTEXF_POINT
#define CM_TEXTURE_FILTER_TYPE_LINEAR           D3DTEXF_LINEAR
#define CM_TEXTURE_FILTER_TYPE_ANISOTROPIC      D3DTEXF_ANISOTROPIC
#define CM_TEXTURE_FILTER_TYPE_FLATCUBIC        D3DTEXF_FLATCUBIC
#define CM_TEXTURE_FILTER_TYPE_GAUSSIANCUBIC    D3DTEXF_GAUSSIANCUBIC
#define CM_TEXTURE_FILTER_TYPE_PYRAMIDALQUAD    D3DTEXF_PYRAMIDALQUAD
#define CM_TEXTURE_FILTER_TYPE_GAUSSIANQUAD     D3DTEXF_GAUSSIANQUAD
#define CM_TEXTURE_FILTER_TYPE_CONVOLUTIONMONO  D3DTEXF_CONVOLUTIONMONO


#ifdef CMRT_EMU
// CM_KERNEL_FUNCTION macro provides wrong kernel name w/ unexplicit template like CM_KERNEL_FUNCTION(kernel<T>)
#define CM_KERNEL_FUNCTION2(...) #__VA_ARGS__, (void *)(void (*) (void))__VA_ARGS__
#else
#define CM_KERNEL_FUNCTION2(...) #__VA_ARGS__
#endif

#ifdef CMRT_EMU
#define _NAME(...) #__VA_ARGS__, (void (*)(void))__VA_ARGS__
#else
#define _NAME(...) #__VA_ARGS__
#endif

#endif

#define CM_RT_API

#define CM_KERNEL_FUNCTION(...) CM_KERNEL_FUNCTION2(__VA_ARGS__)

#define CM_1_0          100
#define CM_2_0          200
#define CM_2_1          201
#define CM_2_2          202
#define CM_2_3          203
#define CM_2_4          204
#define CM_3_0          300
#define CM_4_0          400
#define CM_5_0          500
#define CM_6_0          600
#define CM_7_0          700

/* Return codes */

#define CM_SUCCESS                                  0
#define CM_FAILURE                                  -1
#define CM_NOT_IMPLEMENTED                          -2
#define CM_SURFACE_ALLOCATION_FAILURE               -3
#define CM_OUT_OF_HOST_MEMORY                       -4
#define CM_SURFACE_FORMAT_NOT_SUPPORTED             -5
#define CM_EXCEED_SURFACE_AMOUNT                    -6
#define CM_EXCEED_KERNEL_ARG_AMOUNT                 -7
#define CM_EXCEED_KERNEL_ARG_SIZE_IN_BYTE           -8
#define CM_INVALID_ARG_INDEX                        -9
#define CM_INVALID_ARG_VALUE                        -10
#define CM_INVALID_ARG_SIZE                         -11
#define CM_INVALID_THREAD_INDEX                     -12
#define CM_INVALID_WIDTH                            -13
#define CM_INVALID_HEIGHT                           -14
#define CM_INVALID_DEPTH                            -15
#define CM_INVALID_COMMON_ISA                       -16
#define CM_D3DDEVICEMGR_OPEN_HANDLE_FAIL            -17 // IDirect3DDeviceManager9::OpenDeviceHandle fail
#define CM_D3DDEVICEMGR_DXVA2_E_NEW_VIDEO_DEVICE    -18 // IDirect3DDeviceManager9::LockDevice return DXVA2_E_VIDEO_DEVICE_LOCKED
#define CM_D3DDEVICEMGR_LOCK_DEVICE_FAIL            -19 // IDirect3DDeviceManager9::LockDevice return other fail than DXVA2_E_VIDEO_DEVICE_LOCKED
#define CM_EXCEED_SAMPLER_AMOUNT                    -20
#define CM_EXCEED_MAX_KERNEL_PER_ENQUEUE            -21
#define CM_EXCEED_MAX_KERNEL_SIZE_IN_BYTE           -22
#define CM_EXCEED_MAX_THREAD_AMOUNT_PER_ENQUEUE     -23
#define CM_EXCEED_VME_STATE_G6_AMOUNT               -24
#define CM_INVALID_THREAD_SPACE                     -25
#define CM_EXCEED_MAX_TIMEOUT                       -26
#define CM_JITDLL_LOAD_FAILURE                      -27
#define CM_JIT_COMPILE_FAILURE                      -28
#define CM_JIT_COMPILESIM_FAILURE                   -29
#define CM_INVALID_THREAD_GROUP_SPACE               -30
#define CM_THREAD_ARG_NOT_ALLOWED                   -31
#define CM_INVALID_GLOBAL_BUFFER_INDEX              -32
#define CM_INVALID_BUFFER_HANDLER                   -33
#define CM_EXCEED_MAX_SLM_SIZE                      -34
#define CM_JITDLL_OLDER_THAN_ISA                    -35
#define CM_INVALID_HARDWARE_THREAD_NUMBER           -36
#define CM_GTPIN_INVOKE_FAILURE                     -37
#define CM_INVALIDE_L3_CONFIGURATION                -38
#define CM_INVALID_D3D11_TEXTURE2D_USAGE            -39
#define CM_INTEL_GFX_NOTFOUND                       -40
#define CM_GPUCOPY_INVALID_SYSMEM                   -41
#define CM_GPUCOPY_INVALID_WIDTH                    -42
#define CM_GPUCOPY_INVALID_STRIDE                   -43
#define CM_EVENT_DRIVEN_FAILURE                     -44
#define CM_LOCK_SURFACE_FAIL                        -45 // Lock surface failed
#define CM_INVALID_GENX_BINARY                      -46
#define CM_FEATURE_NOT_SUPPORTED_IN_DRIVER          -47 // driver out-of-sync
#define CM_QUERY_DLL_VERSION_FAILURE                -48 //Fail in getting DLL file version
#define CM_KERNELPAYLOAD_PERTHREADARG_MUTEX_FAIL    -49
#define CM_KERNELPAYLOAD_PERKERNELARG_MUTEX_FAIL    -50
#define CM_KERNELPAYLOAD_SETTING_FAILURE            -51
#define CM_KERNELPAYLOAD_SURFACE_INVALID_BTINDEX    -52
#define CM_NOT_SET_KERNEL_ARGUMENT                  -53
#define CM_GPUCOPY_INVALID_SURFACES                 -54
#define CM_GPUCOPY_INVALID_SIZE                     -55
#define CM_GPUCOPY_OUT_OF_RESOURCE                  -56
#define CM_DEVICE_INVALID_D3DDEVICE                 -57
#define CM_SURFACE_DELAY_DESTROY                    -58
#define CM_INVALID_VEBOX_STATE                      -59
#define CM_INVALID_VEBOX_SURFACE                    -60
#define CM_FEATURE_NOT_SUPPORTED_BY_HARDWARE        -61
#define CM_RESOURCE_USAGE_NOT_SUPPORT_READWRITE     -62
#define CM_MULTIPLE_MIPLEVELS_NOT_SUPPORTED         -63
#define CM_INVALID_UMD_CONTEXT                      -64
#define CM_INVALID_LIBVA_SURFACE                    -65
#define CM_INVALID_LIBVA_INITIALIZE                 -66
#define CM_KERNEL_THREADSPACE_NOT_SET               -67
#define CM_INVALID_KERNEL_THREADSPACE               -68
#define CM_KERNEL_THREADSPACE_THREADS_NOT_ASSOCIATED -69
#define CM_KERNEL_THREADSPACE_INTEGRITY_FAILED      -70
#define CM_INVALID_USERPROVIDED_GENBINARY           -71
#define CM_INVALID_PRIVATE_DATA                     -72
#define CM_INVALID_MOS_RESOURCE_HANDLE              -73
#define CM_SURFACE_CACHED                           -74
#define CM_SURFACE_IN_USE                           -75
#define CM_INVALID_GPUCOPY_KERNEL                   -76
#define CM_INVALID_DEPENDENCY_WITH_WALKING_PATTERN  -77
#define CM_INVALID_MEDIA_WALKING_PATTERN            -78
#define CM_FAILED_TO_ALLOCATE_SVM_BUFFER            -79
#define CM_EXCEED_MAX_POWER_OPTION_FOR_PLATFORM     -80
#define CM_INVALID_KERNEL_THREADGROUPSPACE          -81
#define CM_INVALID_KERNEL_SPILL_CODE                -82
#define CM_UMD_DRIVER_NOT_SUPPORTED                 -83
#define CM_INVALID_GPU_FREQUENCY_VALUE              -84
#define CM_SYSTEM_MEMORY_NOT_4KPAGE_ALIGNED         -85
#define CM_KERNEL_ARG_SETTING_FAILED                -86
#define CM_NO_AVAILABLE_SURFACE                     -87
#define CM_VA_SURFACE_NOT_SUPPORTED                 -88
#define CM_TOO_MUCH_THREADS                         -89
#define CM_NULL_POINTER                             -90
#define CM_EXCEED_MAX_NUM_2D_ALIASES                -91
#define CM_INVALID_PARAM_SIZE                       -92
#define CM_GT_UNSUPPORTED                           -93
#define CM_GTPIN_FLAG_NO_LONGER_SUPPORTED           -94
#define CM_PLATFORM_UNSUPPORTED_FOR_API             -95
#define CM_TASK_MEDIA_RESET                         -96
#define CM_KERNELPAYLOAD_SAMPLER_INVALID_BTINDEX    -97
#define CM_EXCEED_MAX_NUM_BUFFER_ALIASES            -98
#define CM_SYSTEM_MEMORY_NOT_4PIXELS_ALIGNED        -99
#define CM_FAILED_TO_CREATE_CURBE_SURFACE           -100
#define CM_INVALID_CAP_NAME                         -101

/* End of return codes */

typedef enum _GPU_PLATFORM {
    PLATFORM_INTEL_UNKNOWN = 0,
    PLATFORM_INTEL_SNB = 1,   //Sandy Bridge
    PLATFORM_INTEL_IVB = 2,   //Ivy Bridge
    PLATFORM_INTEL_HSW = 3,   //Haswell
    PLATFORM_INTEL_BDW = 4,   //Broadwell
    PLATFORM_INTEL_VLV = 5,   //ValleyView
    PLATFORM_INTEL_CHV = 6,   //CherryView
    PLATFORM_INTEL_SKL = 7,   //SKL
    PLATFORM_INTEL_BXT = 8,   //Broxton
    PLATFORM_INTEL_CNL = 9,   //Cannonlake
    PLATFORM_INTEL_ICL = 10,  //Icelake
    PLATFORM_INTEL_KBL = 11,  //Kabylake
    PLATFORM_INTEL_GLV = 12,  //Glenview
    PLATFORM_INTEL_ICLLP = 13,  //IcelakeLP
    PLATFORM_INTEL_TGLLP = 15,//TigerLakeLP
    PLATFORM_INTEL_GLK = 16,  //GeminiLake
    PLATFORM_INTEL_CFL = 17,  //CofeeLake
    PLATFORM_INTEL_EHL = 18, //ElkhartLake
    PLATFORM_INTEL_RKL = 19,  //RocketLake
    PLATFORM_INTEL_DG1 = 20,  //DG1
    PLATFORM_INTEL_ADL_S = 21,  //AlderLake
    PLATFORM_INTEL_DG2 = 22,  //DG2
    PLATFORM_INTEL_ADL_P = 23, //AlderLake
    PLATFORM_INTEL_ADL_N = 24, //AlderLake-N
} GPU_PLATFORM;

//Time in seconds before kernel should timeout
#define CM_MAX_TIMEOUT 2
//Time in milliseconds before kernel should timeout
#define CM_MAX_TIMEOUT_MS CM_MAX_TIMEOUT*1000
#define CM_MAX_TIMEOUT_SIM    600000

typedef enum _CM_STATUS
{
    CM_STATUS_QUEUED = 0,
    CM_STATUS_FLUSHED = 1,
    CM_STATUS_FINISHED = 2,
    CM_STATUS_STARTED = 3
} CM_STATUS;

enum CM_QUEUE_TYPE
{
    CM_QUEUE_TYPE_NONE = 0,
    CM_QUEUE_TYPE_RENDER = 1,
    CM_QUEUE_TYPE_COMPUTE = 2,
    CM_QUEUE_TYPE_VEBOX = 3
};

enum CM_QUEUE_SSEU_USAGE_HINT_TYPE
{
    CM_QUEUE_SSEU_USAGE_HINT_DEFAULT = 0,
    CM_QUEUE_SSEU_USAGE_HINT_VME = 1
};
struct CM_QUEUE_CREATE_OPTION
{
    CM_QUEUE_TYPE QueueType : 3;
    bool RunAloneMode : 1;
    unsigned int Reserved0 : 3;
    bool UserGPUContext : 1;
    unsigned int GPUContext : 8; // 11 - MOS_GPU_CONTEXT_RENDER3 for default, 12 - MOS_GPU_CONTEXT_RENDER4 for second render context handle.
    CM_QUEUE_SSEU_USAGE_HINT_TYPE SseuUsageHint : 3;
    unsigned int Reserved2 : 13;
};
//**********************************************************************
// Constants
//**********************************************************************
const CM_QUEUE_CREATE_OPTION CM_DEFAULT_QUEUE_CREATE_OPTION = { CM_QUEUE_TYPE_RENDER,  false, 0x0, false, 11, CM_QUEUE_SSEU_USAGE_HINT_DEFAULT, 0x0 };
const CM_QUEUE_CREATE_OPTION CM_VME_QUEUE_CREATE_OPTION     = { CM_QUEUE_TYPE_RENDER,  false, 0x0, false, 12, CM_QUEUE_SSEU_USAGE_HINT_VME,     0x0 };
const CM_QUEUE_CREATE_OPTION CM_COMPUTE_QUEUE_CREATE_OPTION = { CM_QUEUE_TYPE_COMPUTE, false, 0x0, false, 0,  CM_QUEUE_SSEU_USAGE_HINT_DEFAULT, 0x0 };


typedef struct _CM_SAMPLER_STATE
{
    CM_TEXTURE_FILTER_TYPE minFilterType;
    CM_TEXTURE_FILTER_TYPE magFilterType;
    CM_TEXTURE_ADDRESS_TYPE addressU;
    CM_TEXTURE_ADDRESS_TYPE addressV;
    CM_TEXTURE_ADDRESS_TYPE addressW;
} CM_SAMPLER_STATE;

typedef enum _CM_DEVICE_CAP_NAME
{
    CAP_KERNEL_COUNT_PER_TASK,
    CAP_KERNEL_BINARY_SIZE,
    CAP_SAMPLER_COUNT,
    CAP_SAMPLER_COUNT_PER_KERNEL,
    CAP_BUFFER_COUNT,
    CAP_SURFACE2D_COUNT,
    CAP_SURFACE3D_COUNT,
    CAP_SURFACE_COUNT_PER_KERNEL,
    CAP_ARG_COUNT_PER_KERNEL,
    CAP_ARG_SIZE_PER_KERNEL,
    CAP_USER_DEFINED_THREAD_COUNT_PER_TASK,
    CAP_HW_THREAD_COUNT,
    CAP_SURFACE2D_FORMAT_COUNT,
    CAP_SURFACE2D_FORMATS,
    CAP_SURFACE3D_FORMAT_COUNT,
    CAP_SURFACE3D_FORMATS,
    CAP_VME_STATE_COUNT,
    CAP_GPU_PLATFORM,
    CAP_GT_PLATFORM,
    CAP_MIN_FREQUENCY,
    CAP_MAX_FREQUENCY,
    CAP_L3_CONFIG,
    CAP_GPU_CURRENT_FREQUENCY,
    CAP_USER_DEFINED_THREAD_COUNT_PER_TASK_NO_THREAD_ARG,
    CAP_USER_DEFINED_THREAD_COUNT_PER_MEDIA_WALKER,
    CAP_USER_DEFINED_THREAD_COUNT_PER_THREAD_GROUP,
    CAP_SURFACE2DUP_COUNT,
    CAP_PLATFORM_INFO,
    CAP_MAX_BUFFER_SIZE
} CM_DEVICE_CAP_NAME;


typedef enum _CM_DEPENDENCY_PATTERN
{
    CM_NONE_DEPENDENCY = 0,    //All threads run parallel, scanline dispatch
    CM_WAVEFRONT = 1,
    CM_WAVEFRONT26 = 2,
    CM_VERTICAL_DEPENDENCY = 3,
    CM_HORIZONTAL_DEPENDENCY = 4,
} CM_DEPENDENCY_PATTERN;

typedef enum _CM_SAMPLER8x8_SURFACE_
{
    CM_AVS_SURFACE = 0,
    CM_VA_SURFACE = 1
}CM_SAMPLER8x8_SURFACE;

typedef enum _CM_SURFACE_ADDRESS_CONTROL_MODE_
{
    CM_SURFACE_CLAMP = 0,
    CM_SURFACE_MIRROR = 1
}CM_SURFACE_ADDRESS_CONTROL_MODE;

typedef struct _CM_SURFACE_DETAILS {
    UINT        width;
    UINT        height;
    UINT        depth;
    CM_SURFACE_FORMAT   format;
    UINT        planeIndex;
    UINT        pitch;
    UINT        slicePitch;
    UINT        SurfaceBaseAddress;
    UINT8       TiledSurface;
    UINT8       TileWalk;
    UINT        XOffset;
    UINT        YOffset;

}CM_SURFACE_DETAILS;

typedef struct _CM_AVS_COEFF_TABLE {
    float   FilterCoeff_0_0;
    float   FilterCoeff_0_1;
    float   FilterCoeff_0_2;
    float   FilterCoeff_0_3;
    float   FilterCoeff_0_4;
    float   FilterCoeff_0_5;
    float   FilterCoeff_0_6;
    float   FilterCoeff_0_7;
}CM_AVS_COEFF_TABLE;

typedef struct _CM_AVS_INTERNEL_COEFF_TABLE {
    BYTE   FilterCoeff_0_0;
    BYTE   FilterCoeff_0_1;
    BYTE   FilterCoeff_0_2;
    BYTE   FilterCoeff_0_3;
    BYTE   FilterCoeff_0_4;
    BYTE   FilterCoeff_0_5;
    BYTE   FilterCoeff_0_6;
    BYTE   FilterCoeff_0_7;
}CM_AVS_INTERNEL_COEFF_TABLE;

typedef struct _CM_CONVOLVE_COEFF_TABLE {
    float   FilterCoeff_0_0;
    float   FilterCoeff_0_1;
    float   FilterCoeff_0_2;
    float   FilterCoeff_0_3;
    float   FilterCoeff_0_4;
    float   FilterCoeff_0_5;
    float   FilterCoeff_0_6;
    float   FilterCoeff_0_7;
    float   FilterCoeff_0_8;
    float   FilterCoeff_0_9;
    float   FilterCoeff_0_10;
    float   FilterCoeff_0_11;
    float   FilterCoeff_0_12;
    float   FilterCoeff_0_13;
    float   FilterCoeff_0_14;
    float   FilterCoeff_0_15;
    float   FilterCoeff_0_16;
    float   FilterCoeff_0_17;
    float   FilterCoeff_0_18;
    float   FilterCoeff_0_19;
    float   FilterCoeff_0_20;
    float   FilterCoeff_0_21;
    float   FilterCoeff_0_22;
    float   FilterCoeff_0_23;
    float   FilterCoeff_0_24;
    float   FilterCoeff_0_25;
    float   FilterCoeff_0_26;
    float   FilterCoeff_0_27;
    float   FilterCoeff_0_28;
    float   FilterCoeff_0_29;
    float   FilterCoeff_0_30;
    float   FilterCoeff_0_31;
}CM_CONVOLVE_COEFF_TABLE;

/*
*   MISC SAMPLER8x8 State
*/
typedef struct _CM_MISC_STATE {
    //DWORD 0
    union {
        struct {
            DWORD   Row0 : 16;
            DWORD   Reserved : 8;
            DWORD   Width : 4;
            DWORD   Height : 4;
        };
        struct {
            DWORD value;
        };
    } DW0;

    //DWORD 1
    union {
        struct {
            DWORD   Row1 : 16;
            DWORD   Row2 : 16;
        };
        struct {
            DWORD value;
        };
    } DW1;

    //DWORD 2
    union {
        struct {
            DWORD   Row3 : 16;
            DWORD   Row4 : 16;
        };
        struct {
            DWORD value;
        };
    } DW2;

    //DWORD 3
    union {
        struct {
            DWORD   Row5 : 16;
            DWORD   Row6 : 16;
        };
        struct {
            DWORD value;
        };
    } DW3;

    //DWORD 4
    union {
        struct {
            DWORD   Row7 : 16;
            DWORD   Row8 : 16;
        };
        struct {
            DWORD value;
        };
    } DW4;

    //DWORD 5
    union {
        struct {
            DWORD   Row9 : 16;
            DWORD   Row10 : 16;
        };
        struct {
            DWORD value;
        };
    } DW5;

    //DWORD 6
    union {
        struct {
            DWORD   Row11 : 16;
            DWORD   Row12 : 16;
        };
        struct {
            DWORD value;
        };
    } DW6;

    //DWORD 7
    union {
        struct {
            DWORD   Row13 : 16;
            DWORD   Row14 : 16;
        };
        struct {
            DWORD value;
        };
    } DW7;
} CM_MISC_STATE;

typedef struct _CM_MISC_STATE_MSG {
    //DWORD 0
    union {
        struct {
            DWORD   Row0 : 16;
            DWORD   Reserved : 8;
            DWORD   Width : 4;
            DWORD   Height : 4;
        };
        struct {
            DWORD value;
        };
    }DW0;

    //DWORD 1
    union {
        struct {
            DWORD   Row1 : 16;
            DWORD   Row2 : 16;
        };
        struct {
            DWORD value;
        };
    }DW1;

    //DWORD 2
    union {
        struct {
            DWORD   Row3 : 16;
            DWORD   Row4 : 16;
        };
        struct {
            DWORD value;
        };
    }DW2;

    //DWORD 3
    union {
        struct {
            DWORD   Row5 : 16;
            DWORD   Row6 : 16;
        };
        struct {
            DWORD value;
        };
    }DW3;

    //DWORD 4
    union {
        struct {
            DWORD   Row7 : 16;
            DWORD   Row8 : 16;
        };
        struct {
            DWORD value;
        };
    }DW4;

    //DWORD 5
    union {
        struct {
            DWORD   Row9 : 16;
            DWORD   Row10 : 16;
        };
        struct {
            DWORD value;
        };
    }DW5;

    //DWORD 6
    union {
        struct {
            DWORD   Row11 : 16;
            DWORD   Row12 : 16;
        };
        struct {
            DWORD value;
        };
    }DW6;

    //DWORD 7
    union {
        struct {
            DWORD   Row13 : 16;
            DWORD   Row14 : 16;
        };
        struct {
            DWORD value;
        };
    }DW7;
} CM_MISC_STATE_MSG;

typedef enum _CM_FASTCOPY_OPTION
{
    CM_FASTCOPY_OPTION_NONBLOCKING  = 0x00,
    CM_FASTCOPY_OPTION_BLOCKING     = 0x01
} CM_FASTCOPY_OPTION;

#include <cstdint>
#include <cstddef>

#define CM_MIN_SURF_WIDTH   1
#define CM_MIN_SURF_HEIGHT  1
#define CM_MIN_SURF_DEPTH   2

#define CM_MAX_1D_SURF_WIDTH  0X40000000 // 2^30

//IVB+
#define CM_MAX_2D_SURF_WIDTH    16384
#define CM_MAX_2D_SURF_HEIGHT   16384

#define CM_MAX_3D_SURF_WIDTH    2048
#define CM_MAX_3D_SURF_HEIGHT   2048
#define CM_MAX_3D_SURF_DEPTH    2048

#define CM_MAX_OPTION_SIZE_IN_BYTE          512
#define CM_MAX_KERNEL_NAME_SIZE_IN_BYTE     256
#define CM_MAX_ISA_FILE_NAME_SIZE_IN_BYTE   256

#define CM_MAX_THREADSPACE_WIDTH_FOR_MW        511
#define CM_MAX_THREADSPACE_HEIGHT_FOR_MW       511
#define CM_MAX_THREADSPACE_WIDTH_FOR_MO        512
#define CM_MAX_THREADSPACE_HEIGHT_FOR_MO       512
#define CM_MAX_THREADSPACE_WIDTH_SKLUP_FOR_MW  2047
#define CM_MAX_THREADSPACE_HEIGHT_SKLUP_FOR_MW 2047

class CmEvent;
typedef void (*callback_function)(CmEvent*, void *);

extern class CmEvent *CM_NO_EVENT;

struct CM_SAMPLER_STATE_EX;

// Cm Device Create Option
#define CM_DEVICE_CREATE_OPTION_DEFAULT                     0
#define CM_DEVICE_CREATE_OPTION_SCRATCH_SPACE_DISABLE       1
#define CM_DEVICE_CREATE_OPTION_TDR_DISABLE                 64  //Work only for DX11 so far

#define CM_DEVICE_CREATE_OPTION_SURFACE_REUSE_ENABLE        1024

#define CM_DEVICE_CONFIG_MIDTHREADPREEMPTION_OFFSET           22
#define CM_DEVICE_CONFIG_MIDTHREADPREEMPTION_DISENABLE         (1 << CM_DEVICE_CONFIG_MIDTHREADPREEMPTION_OFFSET)

struct CM_VME_SURFACE_STATE_PARAM;

#define CM_MAX_DEPENDENCY_COUNT         8
#define CM_NUM_DWORD_FOR_MW_PARAM       16

/**************** L3/Cache ***************/
typedef enum _MEMORY_OBJECT_CONTROL
{
    MEMORY_OBJECT_CONTROL_SKL_DEFAULT = 0,
    MEMORY_OBJECT_CONTROL_SKL_NO_L3,
    MEMORY_OBJECT_CONTROL_SKL_NO_LLC_ELLC,
    MEMORY_OBJECT_CONTROL_SKL_NO_LLC,
    MEMORY_OBJECT_CONTROL_SKL_NO_ELLC,
    MEMORY_OBJECT_CONTROL_SKL_NO_LLC_L3,
    MEMORY_OBJECT_CONTROL_SKL_NO_ELLC_L3,
    MEMORY_OBJECT_CONTROL_SKL_NO_CACHE,
    MEMORY_OBJECT_CONTROL_SKL_COUNT,

    MEMORY_OBJECT_CONTROL_CNL_DEFAULT = 0,
    MEMORY_OBJECT_CONTROL_CNL_NO_L3,
    MEMORY_OBJECT_CONTROL_CNL_NO_LLC_ELLC,
    MEMORY_OBJECT_CONTROL_CNL_NO_LLC,
    MEMORY_OBJECT_CONTROL_CNL_NO_ELLC,
    MEMORY_OBJECT_CONTROL_CNL_NO_LLC_L3,
    MEMORY_OBJECT_CONTROL_CNL_NO_ELLC_L3,
    MEMORY_OBJECT_CONTROL_CNL_NO_CACHE,
    MEMORY_OBJECT_CONTROL_CNL_COUNT,

    MEMORY_OBJECT_CONTROL_ICL_DEFAULT = 0,
    MEMORY_OBJECT_CONTROL_ICL_COUNT,

    MEMORY_OBJECT_CONTROL_UNKNOWN = 0xff
} MEMORY_OBJECT_CONTROL;

typedef enum _MEMORY_TYPE {
    CM_USE_PTE,
    CM_UN_CACHEABLE,
    CM_WRITE_THROUGH,
    CM_WRITE_BACK,

    // BDW
    MEMORY_TYPE_BDW_UC_WITH_FENCE = 0,
    MEMORY_TYPE_BDW_UC,
    MEMORY_TYPE_BDW_WT,
    MEMORY_TYPE_BDW_WB

} MEMORY_TYPE;

struct L3ConfigRegisterValues
{
    unsigned int config_register0;
    unsigned int config_register1;
    unsigned int config_register2;
    unsigned int config_register3;
};

typedef enum _L3_SUGGEST_CONFIG
{
    BDW_L3_PLANE_DEFAULT = 0,
    BDW_L3_PLANE_1,
    BDW_L3_PLANE_2,
    BDW_L3_PLANE_3,
    BDW_L3_PLANE_4,
    BDW_L3_PLANE_5,
    BDW_L3_PLANE_6,
    BDW_L3_PLANE_7,
    BDW_L3_CONFIG_COUNT,

    SKL_L3_PLANE_DEFAULT = 0,
    SKL_L3_PLANE_1,
    SKL_L3_PLANE_2,
    SKL_L3_PLANE_3,
    SKL_L3_PLANE_4,
    SKL_L3_PLANE_5,
    SKL_L3_PLANE_6,
    SKL_L3_PLANE_7,
    SKL_L3_CONFIG_COUNT,

    CNL_L3_PLANE_DEFAULT = 0,
    CNL_L3_PLANE_1,
    CNL_L3_PLANE_2,
    CNL_L3_PLANE_3,
    CNL_L3_PLANE_4,
    CNL_L3_PLANE_5,
    CNL_L3_PLANE_6,
    CNL_L3_PLANE_7,
    CNL_L3_PLANE_8,
    CNL_L3_CONFIG_COUNT,

    ICL_L3_PLANE_DEFAULT = 0,
    ICL_L3_PLANE_1,
    ICL_L3_PLANE_2,
    ICL_L3_PLANE_3,
    ICL_L3_PLANE_4,
    ICL_L3_PLANE_5,
    ICL_L3_CONFIG_COUNT,  // ICL and CNL have the same recommended L3 settings, with ICL not supporting SLM directly.

    ICLLP_L3_PLANE_DEFAULT = 0,
    ICLLP_L3_PLANE_1,
    ICLLP_L3_PLANE_2,
    ICLLP_L3_PLANE_3,
    ICLLP_L3_PLANE_4,
    ICLLP_L3_PLANE_5,
    ICLLP_L3_PLANE_6,
    ICLLP_L3_PLANE_7,
    ICLLP_L3_PLANE_8,
    ICLLP_L3_CONFIG_COUNT,

    TGL_L3_PLANE_DEFAULT = 0,
    TGL_L3_PLANE_1,
    TGL_L3_PLANE_2,
    TGL_L3_PLANE_3,
    TGL_L3_PLANE_4,
    TGL_L3_PLANE_5,
    TGL_L3_PLANE_6,
    TGL_L3_CONFIG_COUNT,  // TGL and TGLLP have the same recommended L3 settings.

    BDW_SLM_PLANE_DEFAULT = BDW_L3_PLANE_5,
    SKL_SLM_PLANE_DEFAULT = SKL_L3_PLANE_5
} L3_SUGGEST_CONFIG;

/*
*  AVS SAMPLER8x8 STATE
*/
#define CM_NUM_COEFF_ROWS 17
#define CM_NUM_COEFF_ROWS_SKL 32
typedef struct _CM_AVS_NONPIPLINED_STATE {
    bool BypassXAF;
    bool BypassYAF;
    BYTE DefaultSharpLvl;
    BYTE maxDerivative4Pixels;
    BYTE maxDerivative8Pixels;
    BYTE transitionArea4Pixels;
    BYTE transitionArea8Pixels;
    CM_AVS_COEFF_TABLE Tbl0X[CM_NUM_COEFF_ROWS_SKL];
    CM_AVS_COEFF_TABLE Tbl0Y[CM_NUM_COEFF_ROWS_SKL];
    CM_AVS_COEFF_TABLE Tbl1X[CM_NUM_COEFF_ROWS_SKL];
    CM_AVS_COEFF_TABLE Tbl1Y[CM_NUM_COEFF_ROWS_SKL];
    bool bEnableRGBAdaptive;
    bool bAdaptiveFilterAllChannels;
}CM_AVS_NONPIPLINED_STATE;

typedef struct _CM_AVS_INTERNEL_NONPIPLINED_STATE {
    bool BypassXAF;
    bool BypassYAF;
    BYTE DefaultSharpLvl;
    BYTE maxDerivative4Pixels;
    BYTE maxDerivative8Pixels;
    BYTE transitionArea4Pixels;
    BYTE transitionArea8Pixels;
    CM_AVS_INTERNEL_COEFF_TABLE Tbl0X[CM_NUM_COEFF_ROWS_SKL];
    CM_AVS_INTERNEL_COEFF_TABLE Tbl0Y[CM_NUM_COEFF_ROWS_SKL];
    CM_AVS_INTERNEL_COEFF_TABLE Tbl1X[CM_NUM_COEFF_ROWS_SKL];
    CM_AVS_INTERNEL_COEFF_TABLE Tbl1Y[CM_NUM_COEFF_ROWS_SKL];
    bool bEnableRGBAdaptive;
    bool bAdaptiveFilterAllChannels;
}CM_AVS_INTERNEL_NONPIPLINED_STATE;

typedef struct _CM_AVS_STATE_MSG {
    bool AVSTYPE; //true nearest, false adaptive
    bool EightTapAFEnable; //HSW+
    bool BypassIEF; //ignored for BWL, moved to sampler8x8 payload.
    bool ShuffleOutputWriteback; //SKL mode only to be set when AVS msg sequence is 4x4 or 8x4
    bool HDCDirectWriteEnable;
    unsigned short GainFactor;
    unsigned char GlobalNoiseEstm;
    unsigned char StrongEdgeThr;
    unsigned char WeakEdgeThr;
    unsigned char StrongEdgeWght;
    unsigned char RegularWght;
    unsigned char NonEdgeWght;
    unsigned short wR3xCoefficient;
    unsigned short wR3cCoefficient;
    unsigned short wR5xCoefficient;
    unsigned short wR5cxCoefficient;
    unsigned short wR5cCoefficient;
    //For Non-piplined states
    unsigned short stateID;
    CM_AVS_NONPIPLINED_STATE * AvsState;
} CM_AVS_STATE_MSG;

typedef BYTE CM_AVS_STATE_MSG_EX[4244];
/*
*  CONVOLVE STATE DATA STRUCTURES
*/

//*-----------------------------------------------------------------------------
//| CM Convolve type for SKL+
//*-----------------------------------------------------------------------------
typedef enum _CM_CONVOLVE_SKL_TYPE
{
    CM_CONVOLVE_SKL_TYPE_2D = 0,
    CM_CONVOLVE_SKL_TYPE_1D = 1,
    CM_CONVOLVE_SKL_TYPE_1P = 2
} CM_CONVOLVE_SKL_TYPE;

#define CM_NUM_CONVOLVE_ROWS 16
#define CM_NUM_CONVOLVE_ROWS_SKL 32
typedef struct _CM_CONVOLVE_STATE_MSG {
    bool CoeffSize; //true 16-bit, false 8-bit
    byte SclDwnValue; //Scale down value
    byte Width; //Kernel Width
    byte Height; //Kernel Height
                 //SKL mode
    bool isVertical32Mode;
    bool isHorizontal32Mode;
    CM_CONVOLVE_SKL_TYPE nConvolveType;
    CM_CONVOLVE_COEFF_TABLE Table[CM_NUM_CONVOLVE_ROWS_SKL];
} CM_CONVOLVE_STATE_MSG;

enum CM_SAMPLER_STATE_TYPE {
    CM_SAMPLER8X8_AVS = 0,
    CM_SAMPLER8X8_CONV = 1,
    CM_SAMPLER8X8_MISC = 3,
    CM_SAMPLER8X8_CONV1DH = 4,
    CM_SAMPLER8X8_CONV1DV = 5,
    CM_SAMPLER8X8_AVS_EX = 6,
    CM_SAMPLER8X8_NONE
};

struct CM_SAMPLER_8X8_DESCR {
    CM_SAMPLER_STATE_TYPE stateType;
    union {
        CM_AVS_STATE_MSG *avs;
        CM_AVS_STATE_MSG_EX *avs_ex;
        CM_CONVOLVE_STATE_MSG *conv;
        CM_MISC_STATE_MSG *misc; //ERODE/DILATE/MINMAX
    };
};


struct CM_FLAG;

#define CM_NULL_SURFACE                     0xFFFF

//!
//! CM Sampler8X8
//!
class CmSampler8x8
{
public:
    CM_RT_API virtual INT GetIndex(SamplerIndex* & pIndex) = 0;

};
/***********END SAMPLER8X8********************/

class CmEvent
{
public:
    CM_RT_API virtual INT GetStatus(CM_STATUS& status) = 0;
    CM_RT_API virtual INT GetExecutionTime(UINT64& time) = 0;
    CM_RT_API virtual INT WaitForTaskFinished(DWORD dwTimeOutMs = CM_MAX_TIMEOUT_MS) = 0;
};

class CmThreadSpace;
class CmThreadGroupSpace;

class CmKernel
{
public:
    CM_RT_API virtual INT SetThreadCount(UINT count) = 0;
    CM_RT_API virtual INT SetKernelArg(UINT index, size_t size, const void * pValue) = 0;

    CM_RT_API virtual INT SetThreadArg(UINT threadId, UINT index, size_t size, const void * pValue) = 0;
    CM_RT_API virtual INT SetStaticBuffer(UINT index, const void * pValue) = 0;
    CM_RT_API virtual INT SetSurfaceBTI(SurfaceIndex* pSurface, UINT BTIndex) = 0;
    CM_RT_API virtual INT AssociateThreadSpace(CmThreadSpace* & pTS) = 0;
    CM_RT_API virtual INT AssociateThreadGroupSpace(CmThreadGroupSpace* & pTGS) = 0;
};

class CmTask
{
public:
    CM_RT_API virtual INT AddKernel(CmKernel *pKernel) = 0;
    CM_RT_API virtual INT Reset(void) = 0;
    CM_RT_API virtual INT AddSync(void) = 0;
};

class CmProgram;
class SurfaceIndex;
class SamplerIndex;

class CmBuffer
{
public:
    CM_RT_API virtual INT GetIndex(SurfaceIndex*& pIndex) = 0;
    CM_RT_API virtual INT ReadSurface(unsigned char* pSysMem, CmEvent* pEvent, UINT64 sysMemSize = 0xFFFFFFFFFFFFFFFFULL) = 0;
    CM_RT_API virtual INT WriteSurface(const unsigned char* pSysMem, CmEvent* pEvent, UINT64 sysMemSize = 0xFFFFFFFFFFFFFFFFULL) = 0;
    CM_RT_API virtual INT InitSurface(const DWORD initValue, CmEvent* pEvent) = 0;
    CM_RT_API virtual INT SelectMemoryObjectControlSetting(MEMORY_OBJECT_CONTROL option) = 0;
};

class CmBufferUP
{
public:
    CM_RT_API virtual INT GetIndex(SurfaceIndex*& pIndex) = 0;
    CM_RT_API virtual INT SelectMemoryObjectControlSetting(MEMORY_OBJECT_CONTROL option) = 0;
};

class CmBufferSVM;

typedef void * CmAbstractSurfaceHandle;

class CmSurface2D
{
public:
    CM_RT_API virtual INT GetIndex(SurfaceIndex*& pIndex) = 0;
#ifdef CM_WIN
    CM_RT_API virtual INT GetD3DSurface(CmAbstractSurfaceHandle& pD3DSurface) = 0;
#endif
    CM_RT_API virtual INT ReadSurface(unsigned char* pSysMem, CmEvent* pEvent, UINT64 sysMemSize = 0xFFFFFFFFFFFFFFFFULL) = 0;
    CM_RT_API virtual INT WriteSurface(const unsigned char* pSysMem, CmEvent* pEvent, UINT64 sysMemSize = 0xFFFFFFFFFFFFFFFFULL) = 0;
    CM_RT_API virtual INT ReadSurfaceStride(unsigned char* pSysMem, CmEvent* pEvent, const UINT stride, UINT64 sysMemSize = 0xFFFFFFFFFFFFFFFFULL) = 0;
    CM_RT_API virtual INT WriteSurfaceStride(const unsigned char* pSysMem, CmEvent* pEvent, const UINT stride, UINT64 sysMemSize = 0xFFFFFFFFFFFFFFFFULL) = 0;
    CM_RT_API virtual INT InitSurface(const DWORD initValue, CmEvent* pEvent) = 0;
#ifdef CM_WIN
    CM_RT_API virtual INT QuerySubresourceIndex(UINT& FirstArraySlice, UINT& FirstMipSlice) = 0;
#endif
#ifdef CM_LINUX
    CM_RT_API virtual INT GetVaSurfaceID(VASurfaceID  &iVASurface) = 0;
#endif
};

class CmSurface2DUP
{
public:
    CM_RT_API virtual INT GetIndex(SurfaceIndex*& pIndex) = 0;
    CM_RT_API virtual INT SelectMemoryObjectControlSetting(MEMORY_OBJECT_CONTROL option) = 0;
};

class CmSurface3D
{
public:
    CM_RT_API virtual INT GetIndex(SurfaceIndex*& pIndex) = 0;
    CM_RT_API virtual INT ReadSurface(unsigned char* pSysMem, CmEvent* pEvent, UINT64 sysMemSize = 0xFFFFFFFFFFFFFFFFULL) = 0;
    CM_RT_API virtual INT WriteSurface(const unsigned char* pSysMem, CmEvent* pEvent, UINT64 sysMemSize = 0xFFFFFFFFFFFFFFFFULL) = 0;
    CM_RT_API virtual INT InitSurface(const DWORD initValue, CmEvent* pEvent) = 0;
    CM_RT_API virtual INT SelectMemoryObjectControlSetting(MEMORY_OBJECT_CONTROL option) = 0;
};

class CmSampler
{
public:
    CM_RT_API virtual INT GetIndex(SamplerIndex* & pIndex) = 0;
};

class CmThreadSpace
{
public:
    CM_RT_API virtual INT AssociateThread(UINT x, UINT y, CmKernel* pKernel, UINT threadId) = 0;
    CM_RT_API virtual INT SelectThreadDependencyPattern(CM_DEPENDENCY_PATTERN pattern) = 0;
};

class CmThreadGroupSpace;

class CmVebox;

class CmQueue
{
public:
    CM_RT_API virtual INT Enqueue(CmTask* pTask, CmEvent* & pEvent, const CmThreadSpace* pTS = NULL) = 0;
    CM_RT_API virtual INT DestroyEvent(CmEvent* & pEvent) = 0;
    CM_RT_API virtual INT EnqueueWithGroup(CmTask* pTask, CmEvent* & pEvent, const CmThreadGroupSpace* pTGS = NULL) = 0;
    CM_RT_API virtual INT EnqueueCopyCPUToGPU(CmSurface2D* pSurface, const unsigned char* pSysMem, CmEvent* & pEvent) = 0;
    CM_RT_API virtual INT EnqueueCopyGPUToCPU(CmSurface2D* pSurface, unsigned char* pSysMem, CmEvent* & pEvent) = 0;
    CM_RT_API virtual INT EnqueueInitSurface2D(CmSurface2D* pSurface, const DWORD initValue, CmEvent* &pEvent) = 0;
    CM_RT_API virtual INT EnqueueCopyGPUToGPU(CmSurface2D* pOutputSurface, CmSurface2D* pInputSurface, UINT option, CmEvent* & pEvent) = 0;
    CM_RT_API virtual INT EnqueueCopyCPUToCPU(unsigned char* pDstSysMem, unsigned char* pSrcSysMem, UINT size, UINT option, CmEvent* & pEvent) = 0;

    CM_RT_API virtual INT EnqueueCopyCPUToGPUFullStride(CmSurface2D* pSurface, const unsigned char* pSysMem, const UINT widthStride, const UINT heightStride, const UINT option, CmEvent* & pEvent) = 0;
    CM_RT_API virtual INT EnqueueCopyGPUToCPUFullStride(CmSurface2D* pSurface, unsigned char* pSysMem, const UINT widthStride, const UINT heightStride, const UINT option, CmEvent* & pEvent) = 0;

    CM_RT_API virtual INT EnqueueWithHints(CmTask* pTask, CmEvent* & pEvent, UINT hints = 0) = 0;
    CM_RT_API virtual INT EnqueueVebox(CmVebox* pVebox, CmEvent* & pEvent) = 0;
};

class CmDevice;

typedef void(*IMG_WALKER_FUNTYPE)(void* img, void* arg);

EXTERN_C CM_RT_API INT CMRT_GetSurfaceDetails(CmEvent* pEvent, UINT kernIndex, UINT surfBTI, CM_SURFACE_DETAILS& outDetails);
EXTERN_C CM_RT_API void CMRT_PrepareGTPinBuffers(void* ptr0, int size0InBytes, void* ptr1, int size1InBytes, void* ptr2, int size2InBytes);
EXTERN_C CM_RT_API void CMRT_SetGTPinArguments(char* commandLine, void* gtpinInvokeStruct);
EXTERN_C CM_RT_API void CMRT_EnableGTPinMarkers(void);

EXTERN_C CM_RT_API INT DestroyCmDevice(CmDevice* &pD);



EXTERN_C CM_RT_API UINT CMRT_GetKernelCount(CmEvent *pEvent);
EXTERN_C CM_RT_API INT CMRT_GetKernelName(CmEvent *pEvent, UINT index, char** KernelName);
EXTERN_C CM_RT_API INT CMRT_GetKernelThreadSpace(CmEvent *pEvent, UINT index, UINT* localWidth, UINT* localHeight, UINT* globalWidth, UINT* globalHeight);
EXTERN_C CM_RT_API INT CMRT_GetSubmitTime(CmEvent *pEvent, LARGE_INTEGER* time);
EXTERN_C CM_RT_API INT CMRT_GetHWStartTime(CmEvent *pEvent, LARGE_INTEGER* time);
EXTERN_C CM_RT_API INT CMRT_GetHWEndTime(CmEvent *pEvent, LARGE_INTEGER* time);
EXTERN_C CM_RT_API INT CMRT_GetCompleteTime(CmEvent *pEvent, LARGE_INTEGER* time);
EXTERN_C CM_RT_API INT CMRT_SetEventCallback(CmEvent* pEvent, callback_function function, void* user_data);
EXTERN_C CM_RT_API INT CMRT_Enqueue(CmQueue* pQueue, CmTask* pTask, CmEvent** pEvent, const CmThreadSpace* pTS = NULL);

EXTERN_C CM_RT_API INT CMRT_GetEnqueueTime(CmEvent *pEvent, LARGE_INTEGER* time);

EXTERN_C CM_RT_API const char* GetCmErrorString(int Code);

#if defined(CM_WIN)
namespace CmDx9
{
    class CmDevice
    {
    public:

        CM_RT_API virtual INT GetD3DDeviceManager(IDirect3DDeviceManager9* & pDeviceManager) = 0;

        CM_RT_API virtual INT CreateBuffer(UINT size, CmBuffer* & pSurface) = 0;
        CM_RT_API virtual INT CreateSurface2D(UINT width, UINT height, CM_SURFACE_FORMAT format, CmSurface2D* & pSurface) = 0;
        CM_RT_API virtual INT CreateSurface3D(UINT width, UINT height, UINT depth, CM_SURFACE_FORMAT format, CmSurface3D* & pSurface) = 0;

        CM_RT_API virtual INT CreateSurface2D(IDirect3DSurface9* pD3DSurf, CmSurface2D* & pSurface) = 0;
        CM_RT_API virtual INT CreateSurface2D(IDirect3DSurface9** pD3DSurf, const UINT surfaceCount, CmSurface2D**  pSpurface) = 0;

        CM_RT_API virtual INT DestroySurface(CmBuffer* & pSurface) = 0;
        CM_RT_API virtual INT DestroySurface(CmSurface2D* & pSurface) = 0;
        CM_RT_API virtual INT DestroySurface(CmSurface3D* & pSurface) = 0;

        CM_RT_API virtual INT CreateQueue(CmQueue* & pQueue) = 0;
        CM_RT_API virtual INT LoadProgram(void* pCommonISACode, const UINT size, CmProgram*& pProgram, const char* options = NULL) = 0;
        CM_RT_API virtual INT CreateKernel(CmProgram* pProgram, const char* kernelName, CmKernel* & pKernel, const char* options = NULL) = 0;
        CM_RT_API virtual INT CreateKernel(CmProgram* pProgram, const char* kernelName, const void * fncPnt, CmKernel* & pKernel, const char* options = NULL) = 0;
        CM_RT_API virtual INT CreateSampler(const CM_SAMPLER_STATE & sampleState, CmSampler* & pSampler) = 0;

        CM_RT_API virtual INT DestroyKernel(CmKernel*& pKernel) = 0;
        CM_RT_API virtual INT DestroySampler(CmSampler*& pSampler) = 0;
        CM_RT_API virtual INT DestroyProgram(CmProgram*& pProgram) = 0;
        CM_RT_API virtual INT DestroyThreadSpace(CmThreadSpace* & pTS) = 0;

        CM_RT_API virtual INT CreateTask(CmTask *& pTask) = 0;
        CM_RT_API virtual INT DestroyTask(CmTask*& pTask) = 0;

        CM_RT_API virtual INT GetCaps(CM_DEVICE_CAP_NAME capName, size_t& capValueSize, void* pCapValue) = 0;

        CM_RT_API virtual INT CreateThreadSpace(UINT width, UINT height, CmThreadSpace* & pTS) = 0;

        CM_RT_API virtual INT CreateBufferUP(UINT size, void* pSystMem, CmBufferUP* & pSurface) = 0;
        CM_RT_API virtual INT DestroyBufferUP(CmBufferUP* & pSurface) = 0;

        CM_RT_API virtual INT GetSurface2DInfo(UINT width, UINT height, CM_SURFACE_FORMAT format, UINT & pitch, UINT & physicalSize) = 0;
        CM_RT_API virtual INT CreateSurface2DUP(UINT width, UINT height, CM_SURFACE_FORMAT format, void* pSysMem, CmSurface2DUP* & pSurface) = 0;
        CM_RT_API virtual INT DestroySurface2DUP(CmSurface2DUP* & pSurface) = 0;

        CM_RT_API virtual INT CreateVmeSurfaceG7_5(CmSurface2D* pCurSurface, CmSurface2D** pForwardSurface, CmSurface2D** pBackwardSurface, const UINT surfaceCountForward, const UINT surfaceCountBackward, SurfaceIndex* & pVmeIndex) = 0;
        CM_RT_API virtual INT DestroyVmeSurfaceG7_5(SurfaceIndex* & pVmeIndex) = 0;
        CM_RT_API virtual INT CreateSampler8x8(const CM_SAMPLER_8X8_DESCR  & smplDescr, CmSampler8x8*& psmplrState) = 0;
        CM_RT_API virtual INT DestroySampler8x8(CmSampler8x8*& pSampler) = 0;
        CM_RT_API virtual INT CreateSampler8x8Surface(CmSurface2D* p2DSurface, SurfaceIndex* & pDIIndex, CM_SAMPLER8x8_SURFACE surf_type = CM_VA_SURFACE, CM_SURFACE_ADDRESS_CONTROL_MODE = CM_SURFACE_CLAMP) = 0;
        CM_RT_API virtual INT DestroySampler8x8Surface(SurfaceIndex* & pDIIndex) = 0;

        CM_RT_API virtual INT CreateThreadGroupSpace(UINT thrdSpaceWidth, UINT thrdSpaceHeight, UINT grpSpaceWidth, UINT grpSpaceHeight, CmThreadGroupSpace*& pTGS) = 0;
        CM_RT_API virtual INT DestroyThreadGroupSpace(CmThreadGroupSpace*& pTGS) = 0;
        CM_RT_API virtual INT SetL3Config(const L3ConfigRegisterValues *l3_c) = 0;
        CM_RT_API virtual INT SetSuggestedL3Config(L3_SUGGEST_CONFIG l3_s_c) = 0;

        CM_RT_API virtual INT SetCaps(CM_DEVICE_CAP_NAME capName, size_t capValueSize, void* pCapValue) = 0;

        CM_RT_API virtual INT CreateSamplerSurface2D(CmSurface2D* p2DSurface, SurfaceIndex* & pSamplerSurfaceIndex) = 0;
        CM_RT_API virtual INT CreateSamplerSurface3D(CmSurface3D* p3DSurface, SurfaceIndex* & pSamplerSurfaceIndex) = 0;
        CM_RT_API virtual INT DestroySamplerSurface(SurfaceIndex* & pSamplerSurfaceIndex) = 0;

        CM_RT_API virtual INT InitPrintBuffer(size_t printbufsize = 1048576) = 0;
        CM_RT_API virtual INT FlushPrintBuffer() = 0;

        CM_RT_API virtual INT CreateVebox(CmVebox* & pVebox) = 0; //HSW
        CM_RT_API virtual INT DestroyVebox(CmVebox* & pVebox) = 0; //HSW

        CM_RT_API virtual INT CreateBufferSVM(UINT size, void* & pSystMem, uint32_t access_flag, CmBufferSVM* & pSurface) = 0;
        CM_RT_API virtual INT DestroyBufferSVM(CmBufferSVM* & pSurface) = 0;
        CM_RT_API virtual INT CreateSamplerSurface2DUP(CmSurface2DUP* p2DUPSurface, SurfaceIndex* & pSamplerSurfaceIndex) = 0;

        CM_RT_API virtual INT CloneKernel(CmKernel * &pKernelDest, CmKernel * pKernelSrc) = 0;

        CM_RT_API virtual INT CreateSurface2DAlias(CmSurface2D* p2DSurface, SurfaceIndex* &aliasSurfaceIndex) = 0;

        CM_RT_API virtual INT CreateHevcVmeSurfaceG10(CmSurface2D* pCurSurface, CmSurface2D** pForwardSurface, CmSurface2D** pBackwardSurface, const UINT surfaceCountForward, const UINT surfaceCountBackward, SurfaceIndex* & pVmeIndex) = 0;
        CM_RT_API virtual INT DestroyHevcVmeSurfaceG10(SurfaceIndex* & pVmeIndex) = 0;
        CM_RT_API virtual INT CreateSamplerEx(const CM_SAMPLER_STATE_EX & sampleState, CmSampler* & pSampler) = 0;
        CM_RT_API virtual INT FlushPrintBufferIntoFile(const char *filename) = 0;
        CM_RT_API virtual INT CreateThreadGroupSpaceEx(UINT thrdSpaceWidth, UINT thrdSpaceHeight, UINT thrdSpaceDepth, UINT grpSpaceWidth, UINT grpSpaceHeight, UINT grpSpaceDepth, CmThreadGroupSpace*& pTGS) = 0;

        CM_RT_API virtual INT CreateSampler8x8SurfaceEx(CmSurface2D* p2DSurface, SurfaceIndex* & pDIIndex, CM_SAMPLER8x8_SURFACE surf_type = CM_VA_SURFACE, CM_SURFACE_ADDRESS_CONTROL_MODE = CM_SURFACE_CLAMP, CM_FLAG* pFlag = NULL) = 0;
        CM_RT_API virtual INT CreateSamplerSurface2DEx(CmSurface2D* p2DSurface, SurfaceIndex* & pSamplerSurfaceIndex, CM_FLAG* pFlag = NULL) = 0;
        CM_RT_API virtual INT CreateBufferAlias(CmBuffer *pBuffer, SurfaceIndex* &pAliasIndex) = 0;

        CM_RT_API virtual INT SetVmeSurfaceStateParam(SurfaceIndex* pVmeIndex, CM_VME_SURFACE_STATE_PARAM *pSSParam) = 0;

        CM_RT_API virtual int32_t GetVISAVersion(uint32_t& majorVersion, uint32_t& minorVersion) = 0;
        CM_RT_API virtual int32_t CreateQueueEx(CmQueue *&pQueue, CM_QUEUE_CREATE_OPTION QueueCreateOption = CM_DEFAULT_QUEUE_CREATE_OPTION) = 0;
        //adding new functions in the bottom is a must
    };
}

namespace CmDx11
{
    class CmDevice
    {
    public:

        CM_RT_API virtual INT CreateBuffer(UINT size, CmBuffer* & pSurface) = 0;
        CM_RT_API virtual INT CreateSurface2D(UINT width, UINT height, CM_SURFACE_FORMAT format, CmSurface2D* & pSurface) = 0;
        CM_RT_API virtual INT CreateSurface3D(UINT width, UINT height, UINT depth, CM_SURFACE_FORMAT format, CmSurface3D* & pSurface) = 0;

        CM_RT_API virtual INT CreateSurface2D(ID3D11Texture2D* pD3DSurf, CmSurface2D* & pSurface) = 0;
        CM_RT_API virtual INT CreateSurface2D(ID3D11Texture2D** pD3DSurf, const UINT surfaceCount, CmSurface2D**  pSpurface) = 0;

        CM_RT_API virtual INT DestroySurface(CmBuffer* & pSurface) = 0;
        CM_RT_API virtual INT DestroySurface(CmSurface2D* & pSurface) = 0;
        CM_RT_API virtual INT DestroySurface(CmSurface3D* & pSurface) = 0;

        CM_RT_API virtual INT CreateQueue(CmQueue* & pQueue) = 0;
        CM_RT_API virtual INT LoadProgram(void* pCommonISACode, const UINT size, CmProgram*& pProgram, const char* options = NULL) = 0;
        CM_RT_API virtual INT CreateKernel(CmProgram* pProgram, const char* kernelName, CmKernel* & pKernel, const char* options = NULL) = 0;
        CM_RT_API virtual INT CreateKernel(CmProgram* pProgram, const char* kernelName, const void * fncPnt, CmKernel* & pKernel, const char* options = NULL) = 0;
        CM_RT_API virtual INT CreateSampler(const CM_SAMPLER_STATE & sampleState, CmSampler* & pSampler) = 0;

        CM_RT_API virtual INT DestroyKernel(CmKernel*& pKernel) = 0;
        CM_RT_API virtual INT DestroySampler(CmSampler*& pSampler) = 0;
        CM_RT_API virtual INT DestroyProgram(CmProgram*& pProgram) = 0;
        CM_RT_API virtual INT DestroyThreadSpace(CmThreadSpace* & pTS) = 0;

        CM_RT_API virtual INT CreateTask(CmTask *& pTask) = 0;
        CM_RT_API virtual INT DestroyTask(CmTask*& pTask) = 0;

        CM_RT_API virtual INT GetCaps(CM_DEVICE_CAP_NAME capName, size_t& capValueSize, void* pCapValue) = 0;

        CM_RT_API virtual INT CreateThreadSpace(UINT width, UINT height, CmThreadSpace* & pTS) = 0;

        CM_RT_API virtual INT CreateBufferUP(UINT size, void* pSystMem, CmBufferUP* & pSurface) = 0;
        CM_RT_API virtual INT DestroyBufferUP(CmBufferUP* & pSurface) = 0;

        CM_RT_API virtual INT GetSurface2DInfo(UINT width, UINT height, CM_SURFACE_FORMAT format, UINT & pitch, UINT & physicalSize) = 0;
        CM_RT_API virtual INT CreateSurface2DUP(UINT width, UINT height, CM_SURFACE_FORMAT format, void* pSysMem, CmSurface2DUP* & pSurface) = 0;
        CM_RT_API virtual INT DestroySurface2DUP(CmSurface2DUP* & pSurface) = 0;

        CM_RT_API virtual INT CreateVmeSurfaceG7_5(CmSurface2D* pCurSurface, CmSurface2D** pForwardSurface, CmSurface2D** pBackwardSurface, const UINT surfaceCountForward, const UINT surfaceCountBackward, SurfaceIndex* & pVmeIndex) = 0;
        CM_RT_API virtual INT DestroyVmeSurfaceG7_5(SurfaceIndex* & pVmeIndex) = 0;
        CM_RT_API virtual INT CreateSampler8x8(const CM_SAMPLER_8X8_DESCR  & smplDescr, CmSampler8x8*& psmplrState) = 0;
        CM_RT_API virtual INT DestroySampler8x8(CmSampler8x8*& pSampler) = 0;
        CM_RT_API virtual INT CreateSampler8x8Surface(CmSurface2D* p2DSurface, SurfaceIndex* & pDIIndex, CM_SAMPLER8x8_SURFACE surf_type = CM_VA_SURFACE, CM_SURFACE_ADDRESS_CONTROL_MODE = CM_SURFACE_CLAMP) = 0;
        CM_RT_API virtual INT DestroySampler8x8Surface(SurfaceIndex* & pDIIndex) = 0;

        CM_RT_API virtual INT CreateThreadGroupSpace(UINT thrdSpaceWidth, UINT thrdSpaceHeight, UINT grpSpaceWidth, UINT grpSpaceHeight, CmThreadGroupSpace*& pTGS) = 0;
        CM_RT_API virtual INT DestroyThreadGroupSpace(CmThreadGroupSpace*& pTGS) = 0;
        CM_RT_API virtual INT SetL3Config(const L3ConfigRegisterValues *l3_c) = 0;
        CM_RT_API virtual INT SetSuggestedL3Config(L3_SUGGEST_CONFIG l3_s_c) = 0;

        CM_RT_API virtual INT SetCaps(CM_DEVICE_CAP_NAME capName, size_t capValueSize, void* pCapValue) = 0;

        CM_RT_API virtual INT GetD3D11Device(ID3D11Device* &pD3D11Device) = 0;

        CM_RT_API virtual INT CreateSamplerSurface2D(CmSurface2D* p2DSurface, SurfaceIndex* & pSamplerSurfaceIndex) = 0;
        CM_RT_API virtual INT CreateSamplerSurface3D(CmSurface3D* p3DSurface, SurfaceIndex* & pSamplerSurfaceIndex) = 0;
        CM_RT_API virtual INT DestroySamplerSurface(SurfaceIndex* & pSamplerSurfaceIndex) = 0;

        CM_RT_API virtual INT InitPrintBuffer(size_t printbufsize = 1048576) = 0;
        CM_RT_API virtual INT FlushPrintBuffer() = 0;

        CM_RT_API virtual INT CreateSurface2DSubresource(ID3D11Texture2D* pD3D11Texture2D, UINT subresourceCount, CmSurface2D** ppSurfaces, UINT& createdSurfaceCount, UINT option = 0) = 0;
        CM_RT_API virtual INT CreateSurface2DbySubresourceIndex(ID3D11Texture2D* pD3D11Texture2D, UINT FirstArraySlice, UINT FirstMipSlice, CmSurface2D* &pSurface) = 0;

        CM_RT_API virtual INT CreateVebox(CmVebox* & pVebox) = 0; //HSW
        CM_RT_API virtual INT DestroyVebox(CmVebox* & pVebox) = 0; //HSW

        CM_RT_API virtual INT CreateBufferSVM(UINT size, void* & pSystMem, uint32_t access_flag, CmBufferSVM* & pSurface) = 0;
        CM_RT_API virtual INT DestroyBufferSVM(CmBufferSVM* & pSurface) = 0;
        CM_RT_API virtual INT CreateSamplerSurface2DUP(CmSurface2DUP* p2DUPSurface, SurfaceIndex* & pSamplerSurfaceIndex) = 0;

        CM_RT_API virtual INT CloneKernel(CmKernel * &pKernelDest, CmKernel * pKernelSrc) = 0;

        CM_RT_API virtual INT CreateSurface2DAlias(CmSurface2D* p2DSurface, SurfaceIndex* &aliasSurfaceIndex) = 0;

        CM_RT_API virtual INT CreateHevcVmeSurfaceG10(CmSurface2D* pCurSurface, CmSurface2D** pForwardSurface, CmSurface2D** pBackwardSurface, const UINT surfaceCountForward, const UINT surfaceCountBackward, SurfaceIndex* & pVmeIndex) = 0;
        CM_RT_API virtual INT DestroyHevcVmeSurfaceG10(SurfaceIndex* & pVmeIndex) = 0;
        CM_RT_API virtual INT CreateSamplerEx(const CM_SAMPLER_STATE_EX & sampleState, CmSampler* & pSampler) = 0;
        CM_RT_API virtual INT FlushPrintBufferIntoFile(const char *filename) = 0;
        CM_RT_API virtual INT CreateThreadGroupSpaceEx(UINT thrdSpaceWidth, UINT thrdSpaceHeight, UINT thrdSpaceDepth, UINT grpSpaceWidth, UINT grpSpaceHeight, UINT grpSpaceDepth, CmThreadGroupSpace*& pTGS) = 0;

        CM_RT_API virtual INT CreateSampler8x8SurfaceEx(CmSurface2D* p2DSurface, SurfaceIndex* & pDIIndex, CM_SAMPLER8x8_SURFACE surf_type = CM_VA_SURFACE, CM_SURFACE_ADDRESS_CONTROL_MODE = CM_SURFACE_CLAMP, CM_FLAG* pFlag = NULL) = 0;
        CM_RT_API virtual INT CreateSamplerSurface2DEx(CmSurface2D* p2DSurface, SurfaceIndex* & pSamplerSurfaceIndex, CM_FLAG* pFlag = NULL) = 0;
        CM_RT_API virtual INT CreateBufferAlias(CmBuffer *pBuffer, SurfaceIndex* &pAliasIndex) = 0;

        CM_RT_API virtual INT SetVmeSurfaceStateParam(SurfaceIndex* pVmeIndex, CM_VME_SURFACE_STATE_PARAM *pSSParam) = 0;

        CM_RT_API virtual int32_t GetVISAVersion(uint32_t& majorVersion, uint32_t& minorVersion) = 0;
        CM_RT_API virtual int32_t CreateQueueEx(CmQueue *&pQueue, CM_QUEUE_CREATE_OPTION QueueCreateOption = CM_DEFAULT_QUEUE_CREATE_OPTION) = 0;
        //adding new functions in the bottom is a must
    };
}
#else
#if defined(CM_LINUX)
namespace CmLinux
{
    class CmDevice
    {
    public:

        CM_RT_API virtual INT CreateBuffer(UINT size, CmBuffer* & pSurface) = 0;
        CM_RT_API virtual INT CreateSurface2D(UINT width, UINT height, CM_SURFACE_FORMAT format, CmSurface2D* & pSurface) = 0;
        CM_RT_API virtual INT CreateSurface3D(UINT width, UINT height, UINT depth, CM_SURFACE_FORMAT format, CmSurface3D* & pSurface) = 0;

        CM_RT_API virtual INT CreateSurface2D(VASurfaceID iVASurface, CmSurface2D* & pSurface) = 0;
        CM_RT_API virtual INT CreateSurface2D(VASurfaceID* iVASurface, const UINT surfaceCount, CmSurface2D** pSurface) = 0;

        CM_RT_API virtual INT DestroySurface(CmBuffer* & pSurface) = 0;
        CM_RT_API virtual INT DestroySurface(CmSurface2D* & pSurface) = 0;
        CM_RT_API virtual INT DestroySurface(CmSurface3D* & pSurface) = 0;

        CM_RT_API virtual INT CreateQueue(CmQueue* & pQueue) = 0;
        CM_RT_API virtual INT LoadProgram(void* pCommonISACode, const UINT size, CmProgram*& pProgram, const char* options = NULL) = 0;
        CM_RT_API virtual INT CreateKernel(CmProgram* pProgram, const char* kernelName, CmKernel* & pKernel, const char* options = NULL) = 0;
        CM_RT_API virtual INT CreateKernel(CmProgram* pProgram, const char* kernelName, const void * fncPnt, CmKernel* & pKernel, const char* options = NULL) = 0;
        CM_RT_API virtual INT CreateSampler(const CM_SAMPLER_STATE & sampleState, CmSampler* & pSampler) = 0;

        CM_RT_API virtual INT DestroyKernel(CmKernel*& pKernel) = 0;
        CM_RT_API virtual INT DestroySampler(CmSampler*& pSampler) = 0;
        CM_RT_API virtual INT DestroyProgram(CmProgram*& pProgram) = 0;
        CM_RT_API virtual INT DestroyThreadSpace(CmThreadSpace* & pTS) = 0;

        CM_RT_API virtual INT CreateTask(CmTask *& pTask) = 0;
        CM_RT_API virtual INT DestroyTask(CmTask*& pTask) = 0;

        CM_RT_API virtual INT GetCaps(CM_DEVICE_CAP_NAME capName, size_t& capValueSize, void* pCapValue) = 0;

        CM_RT_API virtual INT CreateThreadSpace(UINT width, UINT height, CmThreadSpace* & pTS) = 0;

        CM_RT_API virtual INT CreateBufferUP(UINT size, void* pSystMem, CmBufferUP* & pSurface) = 0;
        CM_RT_API virtual INT DestroyBufferUP(CmBufferUP* & pSurface) = 0;

        CM_RT_API virtual INT GetSurface2DInfo(UINT width, UINT height, CM_SURFACE_FORMAT format, UINT & pitch, UINT & physicalSize) = 0;
        CM_RT_API virtual INT CreateSurface2DUP(UINT width, UINT height, CM_SURFACE_FORMAT format, void* pSysMem, CmSurface2DUP* & pSurface) = 0;
        CM_RT_API virtual INT DestroySurface2DUP(CmSurface2DUP* & pSurface) = 0;

        CM_RT_API virtual INT CreateVmeSurfaceG7_5(CmSurface2D* pCurSurface, CmSurface2D** pForwardSurface, CmSurface2D** pBackwardSurface, const UINT surfaceCountForward, const UINT surfaceCountBackward, SurfaceIndex* & pVmeIndex) = 0;
        CM_RT_API virtual INT DestroyVmeSurfaceG7_5(SurfaceIndex* & pVmeIndex) = 0;
        CM_RT_API virtual INT CreateSampler8x8(const CM_SAMPLER_8X8_DESCR  & smplDescr, CmSampler8x8*& psmplrState) = 0;
        CM_RT_API virtual INT DestroySampler8x8(CmSampler8x8*& pSampler) = 0;
        CM_RT_API virtual INT CreateSampler8x8Surface(CmSurface2D* p2DSurface, SurfaceIndex* & pDIIndex, CM_SAMPLER8x8_SURFACE surf_type = CM_VA_SURFACE, CM_SURFACE_ADDRESS_CONTROL_MODE = CM_SURFACE_CLAMP) = 0;
        CM_RT_API virtual INT DestroySampler8x8Surface(SurfaceIndex* & pDIIndex) = 0;

        CM_RT_API virtual INT CreateThreadGroupSpace(UINT thrdSpaceWidth, UINT thrdSpaceHeight, UINT grpSpaceWidth, UINT grpSpaceHeight, CmThreadGroupSpace*& pTGS) = 0;
        CM_RT_API virtual INT DestroyThreadGroupSpace(CmThreadGroupSpace*& pTGS) = 0;
        CM_RT_API virtual INT SetL3Config(const L3ConfigRegisterValues *l3_c) = 0;
        CM_RT_API virtual INT SetSuggestedL3Config(L3_SUGGEST_CONFIG l3_s_c) = 0;

        CM_RT_API virtual INT SetCaps(CM_DEVICE_CAP_NAME capName, size_t capValueSize, void* pCapValue) = 0;

        CM_RT_API virtual INT CreateSamplerSurface2D(CmSurface2D* p2DSurface, SurfaceIndex* & pSamplerSurfaceIndex) = 0;
        CM_RT_API virtual INT CreateSamplerSurface3D(CmSurface3D* p3DSurface, SurfaceIndex* & pSamplerSurfaceIndex) = 0;
        CM_RT_API virtual INT DestroySamplerSurface(SurfaceIndex* & pSamplerSurfaceIndex) = 0;

        CM_RT_API virtual INT InitPrintBuffer(size_t printbufsize = 1048576) = 0;
        CM_RT_API virtual INT FlushPrintBuffer() = 0;

        CM_RT_API virtual INT CreateVebox(CmVebox* & pVebox) = 0; //HSW
        CM_RT_API virtual INT DestroyVebox(CmVebox* & pVebox) = 0; //HSW

        CM_RT_API virtual INT GetVaDpy(VADisplay* & pva_dpy) = 0;
        CM_RT_API virtual INT CreateVaSurface2D(UINT width, UINT height, CM_SURFACE_FORMAT format, VASurfaceID & iVASurface, CmSurface2D* & pSurface) = 0;

        CM_RT_API virtual INT CreateBufferSVM(UINT size, void* & pSystMem, uint32_t access_flag, CmBufferSVM* & pSurface) = 0;
        CM_RT_API virtual INT DestroyBufferSVM(CmBufferSVM* & pSurface) = 0;
        CM_RT_API virtual INT CreateSamplerSurface2DUP(CmSurface2DUP* p2DUPSurface, SurfaceIndex* & pSamplerSurfaceIndex) = 0;

        CM_RT_API virtual INT CloneKernel(CmKernel * &pKernelDest, CmKernel * pKernelSrc) = 0;

        CM_RT_API virtual INT CreateSurface2DAlias(CmSurface2D* p2DSurface, SurfaceIndex* &aliasSurfaceIndex) = 0;

        CM_RT_API virtual INT CreateHevcVmeSurfaceG10(CmSurface2D* pCurSurface, CmSurface2D** pForwardSurface, CmSurface2D** pBackwardSurface, const UINT surfaceCountForward, const UINT surfaceCountBackward, SurfaceIndex* & pVmeIndex) = 0;
        CM_RT_API virtual INT DestroyHevcVmeSurfaceG10(SurfaceIndex* & pVmeIndex) = 0;
        CM_RT_API virtual INT CreateSamplerEx(const CM_SAMPLER_STATE_EX & sampleState, CmSampler* & pSampler) = 0;
        CM_RT_API virtual INT FlushPrintBufferIntoFile(const char *filename) = 0;
        CM_RT_API virtual INT CreateThreadGroupSpaceEx(UINT thrdSpaceWidth, UINT thrdSpaceHeight, UINT thrdSpaceDepth, UINT grpSpaceWidth, UINT grpSpaceHeight, UINT grpSpaceDepth, CmThreadGroupSpace*& pTGS) = 0;

        CM_RT_API virtual INT CreateSampler8x8SurfaceEx(CmSurface2D* p2DSurface, SurfaceIndex* & pDIIndex, CM_SAMPLER8x8_SURFACE surf_type = CM_VA_SURFACE, CM_SURFACE_ADDRESS_CONTROL_MODE = CM_SURFACE_CLAMP, CM_FLAG* pFlag = NULL) = 0;
        CM_RT_API virtual INT CreateSamplerSurface2DEx(CmSurface2D* p2DSurface, SurfaceIndex* & pSamplerSurfaceIndex, CM_FLAG* pFlag = NULL) = 0;
        CM_RT_API virtual INT CreateBufferAlias(CmBuffer *pBuffer, SurfaceIndex* &pAliasIndex) = 0;

        CM_RT_API virtual INT SetVmeSurfaceStateParam(SurfaceIndex* pVmeIndex, CM_VME_SURFACE_STATE_PARAM *pSSParam) = 0;

        CM_RT_API virtual int32_t GetVISAVersion(uint32_t& majorVersion, uint32_t& minorVersion) = 0;
        CM_RT_API virtual int32_t CreateQueueEx(CmQueue *&pQueue, CM_QUEUE_CREATE_OPTION QueueCreateOption = CM_DEFAULT_QUEUE_CREATE_OPTION) = 0;
        //adding new functions in the bottom is a must
    };
}
#endif
#endif

typedef void * AbstractSurfaceHandle;
typedef void * AbstractDeviceHandle;
typedef L3ConfigRegisterValues L3_CONFIG_REGISTER_VALUES;

class CmDevice
{
public:
    CM_RT_API virtual INT GetDevice(AbstractDeviceHandle & pDevice) = 0;
    CM_RT_API virtual INT CreateBuffer(UINT size, CmBuffer* & pSurface) = 0;
    CM_RT_API virtual INT CreateSurface2D(UINT width, UINT height, CM_SURFACE_FORMAT format, CmSurface2D* & pSurface) = 0;
    CM_RT_API virtual INT CreateSurface3D(UINT width, UINT height, UINT depth, CM_SURFACE_FORMAT format, CmSurface3D* & pSurface) = 0;
    CM_RT_API virtual INT CreateSurface2D(mfxHDLPair D3DSurfPair, CmSurface2D* & pSurface) = 0;
    CM_RT_API virtual INT CreateSurface2D(AbstractSurfaceHandle pD3DSurf, CmSurface2D* & pSurface) = 0;
    //CM_RT_API virtual INT CreateSurface2D( AbstractSurfaceHandle * pD3DSurf, const UINT surfaceCount, CmSurface2D**  pSpurface ) = 0;
    CM_RT_API virtual INT DestroySurface(CmBuffer* & pSurface) = 0;
    CM_RT_API virtual INT DestroySurface(CmSurface2D* & pSurface) = 0;
    CM_RT_API virtual INT DestroySurface(CmSurface3D* & pSurface) = 0;
    CM_RT_API virtual INT CreateQueue(CmQueue* & pQueue) = 0;
    CM_RT_API virtual INT LoadProgram(void* pCommonISACode, const UINT size, CmProgram*& pProgram, const char* options = NULL) = 0;
    CM_RT_API virtual INT CreateKernel(CmProgram* pProgram, const char* kernelName, CmKernel* & pKernel, const char* options = NULL) = 0;
    CM_RT_API virtual INT CreateKernel(CmProgram* pProgram, const char* kernelName, const void * fncPnt, CmKernel* & pKernel, const char* options = NULL) = 0;
    CM_RT_API virtual INT CreateSampler(const CM_SAMPLER_STATE & sampleState, CmSampler* & pSampler) = 0;
    CM_RT_API virtual INT DestroyKernel(CmKernel*& pKernel) = 0;
    CM_RT_API virtual INT DestroySampler(CmSampler*& pSampler) = 0;
    CM_RT_API virtual INT DestroyProgram(CmProgram*& pProgram) = 0;
    CM_RT_API virtual INT DestroyThreadSpace(CmThreadSpace* & pTS) = 0;
    CM_RT_API virtual INT CreateTask(CmTask *& pTask) = 0;
    CM_RT_API virtual INT DestroyTask(CmTask*& pTask) = 0;
    CM_RT_API virtual INT GetCaps(CM_DEVICE_CAP_NAME capName, size_t& capValueSize, void* pCapValue) = 0;
    CM_RT_API virtual INT CreateThreadSpace(UINT width, UINT height, CmThreadSpace* & pTS) = 0;
    CM_RT_API virtual INT CreateBufferUP(UINT size, void* pSystMem, CmBufferUP* & pSurface) = 0;
    CM_RT_API virtual INT DestroyBufferUP(CmBufferUP* & pSurface) = 0;
    CM_RT_API virtual INT GetSurface2DInfo(UINT width, UINT height, CM_SURFACE_FORMAT format, UINT & pitch, UINT & physicalSize) = 0;
    CM_RT_API virtual INT CreateSurface2DUP(UINT width, UINT height, CM_SURFACE_FORMAT format, void* pSysMem, CmSurface2DUP* & pSurface) = 0;
    CM_RT_API virtual INT DestroySurface2DUP(CmSurface2DUP* & pSurface) = 0;
    CM_RT_API virtual INT CreateVmeSurfaceG7_5(CmSurface2D* pCurSurface, CmSurface2D** pForwardSurface, CmSurface2D** pBackwardSurface, const UINT surfaceCountForward, const UINT surfaceCountBackward, SurfaceIndex* & pVmeIndex) = 0;
    CM_RT_API virtual INT DestroyVmeSurfaceG7_5(SurfaceIndex* & pVmeIndex) = 0;
    CM_RT_API virtual INT CreateSampler8x8(const CM_SAMPLER_8X8_DESCR  & smplDescr, CmSampler8x8*& psmplrState) = 0;
    CM_RT_API virtual INT DestroySampler8x8(CmSampler8x8*& pSampler) = 0;
    CM_RT_API virtual INT CreateSampler8x8Surface(CmSurface2D* p2DSurface, SurfaceIndex* & pDIIndex, CM_SAMPLER8x8_SURFACE surf_type = CM_VA_SURFACE, CM_SURFACE_ADDRESS_CONTROL_MODE = CM_SURFACE_CLAMP) = 0;
    CM_RT_API virtual INT DestroySampler8x8Surface(SurfaceIndex* & pDIIndex) = 0;
    CM_RT_API virtual INT CreateThreadGroupSpace(UINT thrdSpaceWidth, UINT thrdSpaceHeight, UINT grpSpaceWidth, UINT grpSpaceHeight, CmThreadGroupSpace*& pTGS) = 0;
    CM_RT_API virtual INT DestroyThreadGroupSpace(CmThreadGroupSpace*& pTGS) = 0;
    CM_RT_API virtual INT SetL3Config(const L3_CONFIG_REGISTER_VALUES *l3_c) = 0;
    CM_RT_API virtual INT SetSuggestedL3Config(L3_SUGGEST_CONFIG l3_s_c) = 0;
    CM_RT_API virtual INT SetCaps(CM_DEVICE_CAP_NAME capName, size_t capValueSize, void* pCapValue) = 0;
    CM_RT_API virtual INT CreateSamplerSurface2D(CmSurface2D* p2DSurface, SurfaceIndex* & pSamplerSurfaceIndex) = 0;
    CM_RT_API virtual INT CreateSamplerSurface3D(CmSurface3D* p3DSurface, SurfaceIndex* & pSamplerSurfaceIndex) = 0;
    CM_RT_API virtual INT DestroySamplerSurface(SurfaceIndex* & pSamplerSurfaceIndex) = 0;
    CM_RT_API virtual INT InitPrintBuffer(size_t printbufsize = 1048576) = 0;
    CM_RT_API virtual INT FlushPrintBuffer() = 0;
    CM_RT_API virtual INT CreateSurface2DSubresource(AbstractSurfaceHandle pD3D11Texture2D, UINT subresourceCount, CmSurface2D** ppSurfaces, UINT& createdSurfaceCount, UINT option = 0) = 0;
    CM_RT_API virtual INT CreateSurface2DbySubresourceIndex(AbstractSurfaceHandle pD3D11Texture2D, UINT FirstArraySlice, UINT FirstMipSlice, CmSurface2D* &pSurface) = 0;
    CM_RT_API virtual int32_t CreateQueueEx(CmQueue *&pQueue, CM_QUEUE_CREATE_OPTION QueueCreateOption = CM_DEFAULT_QUEUE_CREATE_OPTION) = 0;
};

#if defined(CM_WIN)
INT CreateCmDevice(CmDevice* &pD, UINT& version, IDirect3DDeviceManager9 * pD3DDeviceMgr = NULL, UINT mode = CM_DEVICE_CREATE_OPTION_DEFAULT);
INT CreateCmDevice(CmDevice* &pD, UINT& version, ID3D11Device * pD3D11Device = NULL, UINT mode = CM_DEVICE_CREATE_OPTION_DEFAULT);
INT CreateCmDeviceEmu(CmDevice* &pDevice, UINT& version, IDirect3DDeviceManager9 * pD3DDeviceMgr = NULL);
INT CreateCmDeviceEmu(CmDevice* &pDevice, UINT& version, ID3D11Device * pD3D11Device = NULL);
INT CreateCmDeviceSim(CmDevice* &pDevice, UINT& version, IDirect3DDeviceManager9 * pD3DDeviceMgr = NULL);
INT CreateCmDeviceSim(CmDevice* &pDevice, UINT& version, ID3D11Device * pD3D11Device = NULL);
#else //#if defined(CM_WIN)
INT CreateCmDevice(CmDevice* &pD, UINT& version, VADisplay va_dpy = NULL, UINT mode = CM_DEVICE_CREATE_OPTION_DEFAULT);
INT CreateCmDeviceEmu(CmDevice* &pDevice, UINT& version, VADisplay va_dpy = NULL);
INT CreateCmDeviceSim(CmDevice* &pDevice, UINT& version);
#endif //#if defined(CM_WIN)

INT DestroyCmDevice(CmDevice* &pDevice);
INT DestroyCmDeviceEmu(CmDevice* &pDevice);
INT DestroyCmDeviceSim(CmDevice* &pDevice);

int ReadProgram(CmDevice * device, CmProgram *& program, const unsigned char * buffer, unsigned int len);
int ReadProgramJit(CmDevice * device, CmProgram *& program, const unsigned char * buffer, unsigned int len);
int CreateKernel(CmDevice * device, CmProgram * program, const char * kernelName, const void * fncPnt, CmKernel *& kernel, const char * options = NULL);

#ifdef _MSVC_LANG
#pragma warning(pop)
#endif

#if !defined(CM_WIN)
#undef LONG
#undef ULONG
#endif

#if defined(__INTEL_COMPILER)
  #pragma warning(pop)
#endif

#if defined(__clang__)
  #pragma clang diagnostic pop
#else
#if defined(__GNUC__)
  #pragma GCC diagnostic pop
#endif
#endif

#endif // __CMRT_CROSS_PLATFORM_H__
