/*******************************************************************************
 * Copyright (c) 2019-2020 The Khronos Group Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/

#ifndef OPENCL_CL_ICD_H
#define OPENCL_CL_ICD_H

#include <CL/cl.h>
#include <CL/cl_function_types.h>
#include <CL/cl_egl.h>
#include <CL/cl_ext.h>
#include <CL/cl_gl.h>
#include <CL/cl_platform.h>

#if defined(_WIN32)
#include <CL/cl_d3d11.h>
#include <CL/cl_d3d10.h>
#include <CL/cl_dx9_media_sharing.h>
#endif

#if defined(_WIN32) && defined(_MSC_VER) && __CL_HAS_ANON_STRUCT__
   /* Disable warning C4201: nonstandard extension used : nameless struct/union */
    #pragma warning( push )
    #pragma warning( disable : 4201 )
#endif

#ifdef __cplusplus
extern "C" {
#endif

/* Vendor dispatch table structure */

typedef struct _cl_icd_dispatch {
  /* OpenCL 1.0 */
#if __CL_HAS_ANON_STRUCT__
  __CL_ANON_STRUCT__ union {
#endif
    clGetPlatformIDs_t *clGetPlatformIDs;
#if __CL_HAS_ANON_STRUCT__
    /* Set to CL_ICD2_TAG_KHR for cl_khr_icd 2.0.0 */
    intptr_t clGetPlatformIDs_icd2_tag;
  };
#endif
  clGetPlatformInfo_t *clGetPlatformInfo;
  clGetDeviceIDs_t *clGetDeviceIDs;
  clGetDeviceInfo_t *clGetDeviceInfo;
  clCreateContext_t *clCreateContext;
  clCreateContextFromType_t *clCreateContextFromType;
  clRetainContext_t *clRetainContext;
  clReleaseContext_t *clReleaseContext;
  clGetContextInfo_t *clGetContextInfo;
  clCreateCommandQueue_t *clCreateCommandQueue;
  clRetainCommandQueue_t *clRetainCommandQueue;
  clReleaseCommandQueue_t *clReleaseCommandQueue;
  clGetCommandQueueInfo_t *clGetCommandQueueInfo;
  clSetCommandQueueProperty_t *clSetCommandQueueProperty;
  clCreateBuffer_t *clCreateBuffer;
  clCreateImage2D_t *clCreateImage2D;
  clCreateImage3D_t *clCreateImage3D;
  clRetainMemObject_t *clRetainMemObject;
  clReleaseMemObject_t *clReleaseMemObject;
  clGetSupportedImageFormats_t *clGetSupportedImageFormats;
  clGetMemObjectInfo_t *clGetMemObjectInfo;
  clGetImageInfo_t *clGetImageInfo;
  clCreateSampler_t *clCreateSampler;
  clRetainSampler_t *clRetainSampler;
  clReleaseSampler_t *clReleaseSampler;
  clGetSamplerInfo_t *clGetSamplerInfo;
  clCreateProgramWithSource_t *clCreateProgramWithSource;
  clCreateProgramWithBinary_t *clCreateProgramWithBinary;
  clRetainProgram_t *clRetainProgram;
  clReleaseProgram_t *clReleaseProgram;
  clBuildProgram_t *clBuildProgram;
#if __CL_HAS_ANON_STRUCT__
  __CL_ANON_STRUCT__ union {
#endif
    clUnloadCompiler_t *clUnloadCompiler;
#if __CL_HAS_ANON_STRUCT__
    /* Set to CL_ICD2_TAG_KHR for cl_khr_icd 2.0.0 */
    intptr_t clUnloadCompiler_icd2_tag;
  };
#endif
  clGetProgramInfo_t *clGetProgramInfo;
  clGetProgramBuildInfo_t *clGetProgramBuildInfo;
  clCreateKernel_t *clCreateKernel;
  clCreateKernelsInProgram_t *clCreateKernelsInProgram;
  clRetainKernel_t *clRetainKernel;
  clReleaseKernel_t *clReleaseKernel;
  clSetKernelArg_t *clSetKernelArg;
  clGetKernelInfo_t *clGetKernelInfo;
  clGetKernelWorkGroupInfo_t *clGetKernelWorkGroupInfo;
  clWaitForEvents_t *clWaitForEvents;
  clGetEventInfo_t *clGetEventInfo;
  clRetainEvent_t *clRetainEvent;
  clReleaseEvent_t *clReleaseEvent;
  clGetEventProfilingInfo_t *clGetEventProfilingInfo;
  clFlush_t *clFlush;
  clFinish_t *clFinish;
  clEnqueueReadBuffer_t *clEnqueueReadBuffer;
  clEnqueueWriteBuffer_t *clEnqueueWriteBuffer;
  clEnqueueCopyBuffer_t *clEnqueueCopyBuffer;
  clEnqueueReadImage_t *clEnqueueReadImage;
  clEnqueueWriteImage_t *clEnqueueWriteImage;
  clEnqueueCopyImage_t *clEnqueueCopyImage;
  clEnqueueCopyImageToBuffer_t *clEnqueueCopyImageToBuffer;
  clEnqueueCopyBufferToImage_t *clEnqueueCopyBufferToImage;
  clEnqueueMapBuffer_t *clEnqueueMapBuffer;
  clEnqueueMapImage_t *clEnqueueMapImage;
  clEnqueueUnmapMemObject_t *clEnqueueUnmapMemObject;
  clEnqueueNDRangeKernel_t *clEnqueueNDRangeKernel;
  clEnqueueTask_t *clEnqueueTask;
  clEnqueueNativeKernel_t *clEnqueueNativeKernel;
  clEnqueueMarker_t *clEnqueueMarker;
  clEnqueueWaitForEvents_t *clEnqueueWaitForEvents;
  clEnqueueBarrier_t *clEnqueueBarrier;
  clGetExtensionFunctionAddress_t *clGetExtensionFunctionAddress;
  clCreateFromGLBuffer_t *clCreateFromGLBuffer;
  clCreateFromGLTexture2D_t *clCreateFromGLTexture2D;
  clCreateFromGLTexture3D_t *clCreateFromGLTexture3D;
  clCreateFromGLRenderbuffer_t *clCreateFromGLRenderbuffer;
  clGetGLObjectInfo_t *clGetGLObjectInfo;
  clGetGLTextureInfo_t *clGetGLTextureInfo;
  clEnqueueAcquireGLObjects_t *clEnqueueAcquireGLObjects;
  clEnqueueReleaseGLObjects_t *clEnqueueReleaseGLObjects;
  clGetGLContextInfoKHR_t *clGetGLContextInfoKHR;

  /* cl_khr_d3d10_sharing */
#ifdef _WIN32
  clGetDeviceIDsFromD3D10KHR_t *clGetDeviceIDsFromD3D10KHR;
  clCreateFromD3D10BufferKHR_t *clCreateFromD3D10BufferKHR;
  clCreateFromD3D10Texture2DKHR_t *clCreateFromD3D10Texture2DKHR;
  clCreateFromD3D10Texture3DKHR_t *clCreateFromD3D10Texture3DKHR;
  clEnqueueAcquireD3D10ObjectsKHR_t *clEnqueueAcquireD3D10ObjectsKHR;
  clEnqueueReleaseD3D10ObjectsKHR_t *clEnqueueReleaseD3D10ObjectsKHR;
#else
  void *clGetDeviceIDsFromD3D10KHR;
  void *clCreateFromD3D10BufferKHR;
  void *clCreateFromD3D10Texture2DKHR;
  void *clCreateFromD3D10Texture3DKHR;
  void *clEnqueueAcquireD3D10ObjectsKHR;
  void *clEnqueueReleaseD3D10ObjectsKHR;
#endif

  /* OpenCL 1.1 */
#ifdef CL_VERSION_1_1
  clSetEventCallback_t *clSetEventCallback;
  clCreateSubBuffer_t *clCreateSubBuffer;
  clSetMemObjectDestructorCallback_t *clSetMemObjectDestructorCallback;
  clCreateUserEvent_t *clCreateUserEvent;
  clSetUserEventStatus_t *clSetUserEventStatus;
  clEnqueueReadBufferRect_t *clEnqueueReadBufferRect;
  clEnqueueWriteBufferRect_t *clEnqueueWriteBufferRect;
  clEnqueueCopyBufferRect_t *clEnqueueCopyBufferRect;
#else
  void *clSetEventCallback;
  void *clCreateSubBuffer;
  void *clSetMemObjectDestructorCallback;
  void *clCreateUserEvent;
  void *clSetUserEventStatus;
  void *clEnqueueReadBufferRect;
  void *clEnqueueWriteBufferRect;
  void *clEnqueueCopyBufferRect;
#endif

  /* cl_ext_device_fission */
  clCreateSubDevicesEXT_t *clCreateSubDevicesEXT;
  clRetainDeviceEXT_t *clRetainDeviceEXT;
  clReleaseDeviceEXT_t *clReleaseDeviceEXT;

  /* cl_khr_gl_event */
  clCreateEventFromGLsyncKHR_t *clCreateEventFromGLsyncKHR;

  /* OpenCL 1.2 */
#ifdef CL_VERSION_1_2
  clCreateSubDevices_t *clCreateSubDevices;
  clRetainDevice_t *clRetainDevice;
  clReleaseDevice_t *clReleaseDevice;
  clCreateImage_t *clCreateImage;
  clCreateProgramWithBuiltInKernels_t *clCreateProgramWithBuiltInKernels;
  clCompileProgram_t *clCompileProgram;
  clLinkProgram_t *clLinkProgram;
  clUnloadPlatformCompiler_t *clUnloadPlatformCompiler;
  clGetKernelArgInfo_t *clGetKernelArgInfo;
  clEnqueueFillBuffer_t *clEnqueueFillBuffer;
  clEnqueueFillImage_t *clEnqueueFillImage;
  clEnqueueMigrateMemObjects_t *clEnqueueMigrateMemObjects;
  clEnqueueMarkerWithWaitList_t *clEnqueueMarkerWithWaitList;
  clEnqueueBarrierWithWaitList_t *clEnqueueBarrierWithWaitList;
  clGetExtensionFunctionAddressForPlatform_t *
      clGetExtensionFunctionAddressForPlatform;
  clCreateFromGLTexture_t *clCreateFromGLTexture;
#else
  void *clCreateSubDevices;
  void *clRetainDevice;
  void *clReleaseDevice;
  void *clCreateImage;
  void *clCreateProgramWithBuiltInKernels;
  void *clCompileProgram;
  void *clLinkProgram;
  void *clUnloadPlatformCompiler;
  void *clGetKernelArgInfo;
  void *clEnqueueFillBuffer;
  void *clEnqueueFillImage;
  void *clEnqueueMigrateMemObjects;
  void *clEnqueueMarkerWithWaitList;
  void *clEnqueueBarrierWithWaitList;
  void *clGetExtensionFunctionAddressForPlatform;
  void *clCreateFromGLTexture;
#endif

  /* cl_khr_d3d11_sharing and cl_khr_dx9_media_sharing */
#ifdef _WIN32
  clGetDeviceIDsFromD3D11KHR_t *clGetDeviceIDsFromD3D11KHR;
  clCreateFromD3D11BufferKHR_t *clCreateFromD3D11BufferKHR;
  clCreateFromD3D11Texture2DKHR_t *clCreateFromD3D11Texture2DKHR;
  clCreateFromD3D11Texture3DKHR_t *clCreateFromD3D11Texture3DKHR;
  clCreateFromDX9MediaSurfaceKHR_t *clCreateFromDX9MediaSurfaceKHR;
  clEnqueueAcquireD3D11ObjectsKHR_t *clEnqueueAcquireD3D11ObjectsKHR;
  clEnqueueReleaseD3D11ObjectsKHR_t *clEnqueueReleaseD3D11ObjectsKHR;
  clGetDeviceIDsFromDX9MediaAdapterKHR_t *
      clGetDeviceIDsFromDX9MediaAdapterKHR;
  clEnqueueAcquireDX9MediaSurfacesKHR_t *
      clEnqueueAcquireDX9MediaSurfacesKHR;
  clEnqueueReleaseDX9MediaSurfacesKHR_t *
      clEnqueueReleaseDX9MediaSurfacesKHR;
#else
  void *clGetDeviceIDsFromD3D11KHR;
  void *clCreateFromD3D11BufferKHR;
  void *clCreateFromD3D11Texture2DKHR;
  void *clCreateFromD3D11Texture3DKHR;
  void *clCreateFromDX9MediaSurfaceKHR;
  void *clEnqueueAcquireD3D11ObjectsKHR;
  void *clEnqueueReleaseD3D11ObjectsKHR;
  void *clGetDeviceIDsFromDX9MediaAdapterKHR;
  void *clEnqueueAcquireDX9MediaSurfacesKHR;
  void *clEnqueueReleaseDX9MediaSurfacesKHR;
#endif

  /* cl_khr_egl_image */
  clCreateFromEGLImageKHR_t *clCreateFromEGLImageKHR;
  clEnqueueAcquireEGLObjectsKHR_t *clEnqueueAcquireEGLObjectsKHR;
  clEnqueueReleaseEGLObjectsKHR_t *clEnqueueReleaseEGLObjectsKHR;

  /* cl_khr_egl_event */
  clCreateEventFromEGLSyncKHR_t *clCreateEventFromEGLSyncKHR;

  /* OpenCL 2.0 */
#ifdef CL_VERSION_2_0
  clCreateCommandQueueWithProperties_t *clCreateCommandQueueWithProperties;
  clCreatePipe_t *clCreatePipe;
  clGetPipeInfo_t *clGetPipeInfo;
  clSVMAlloc_t *clSVMAlloc;
  clSVMFree_t *clSVMFree;
  clEnqueueSVMFree_t *clEnqueueSVMFree;
  clEnqueueSVMMemcpy_t *clEnqueueSVMMemcpy;
  clEnqueueSVMMemFill_t *clEnqueueSVMMemFill;
  clEnqueueSVMMap_t *clEnqueueSVMMap;
  clEnqueueSVMUnmap_t *clEnqueueSVMUnmap;
  clCreateSamplerWithProperties_t *clCreateSamplerWithProperties;
  clSetKernelArgSVMPointer_t *clSetKernelArgSVMPointer;
  clSetKernelExecInfo_t *clSetKernelExecInfo;
#else
  void *clCreateCommandQueueWithProperties;
  void *clCreatePipe;
  void *clGetPipeInfo;
  void *clSVMAlloc;
  void *clSVMFree;
  void *clEnqueueSVMFree;
  void *clEnqueueSVMMemcpy;
  void *clEnqueueSVMMemFill;
  void *clEnqueueSVMMap;
  void *clEnqueueSVMUnmap;
  void *clCreateSamplerWithProperties;
  void *clSetKernelArgSVMPointer;
  void *clSetKernelExecInfo;
#endif

  /* cl_khr_sub_groups */
  clGetKernelSubGroupInfoKHR_t *clGetKernelSubGroupInfoKHR;

  /* OpenCL 2.1 */
#ifdef CL_VERSION_2_1
  clCloneKernel_t *clCloneKernel;
  clCreateProgramWithIL_t *clCreateProgramWithIL;
  clEnqueueSVMMigrateMem_t *clEnqueueSVMMigrateMem;
  clGetDeviceAndHostTimer_t *clGetDeviceAndHostTimer;
  clGetHostTimer_t *clGetHostTimer;
  clGetKernelSubGroupInfo_t *clGetKernelSubGroupInfo;
  clSetDefaultDeviceCommandQueue_t *clSetDefaultDeviceCommandQueue;
#else
  void *clCloneKernel;
  void *clCreateProgramWithIL;
  void *clEnqueueSVMMigrateMem;
  void *clGetDeviceAndHostTimer;
  void *clGetHostTimer;
  void *clGetKernelSubGroupInfo;
  void *clSetDefaultDeviceCommandQueue;
#endif

  /* OpenCL 2.2 */
#ifdef CL_VERSION_2_2
  clSetProgramReleaseCallback_t *clSetProgramReleaseCallback;
  clSetProgramSpecializationConstant_t *clSetProgramSpecializationConstant;
#else
  void *clSetProgramReleaseCallback;
  void *clSetProgramSpecializationConstant;
#endif

  /* OpenCL 3.0 */
#ifdef CL_VERSION_3_0
  clCreateBufferWithProperties_t *clCreateBufferWithProperties;
  clCreateImageWithProperties_t *clCreateImageWithProperties;
  clSetContextDestructorCallback_t *clSetContextDestructorCallback;
#else
  void *clCreateBufferWithProperties;
  void *clCreateImageWithProperties;
  void *clSetContextDestructorCallback;
#endif

} cl_icd_dispatch;

#ifdef __cplusplus
}
#endif

#if defined(_WIN32) && defined(_MSC_VER) && __CL_HAS_ANON_STRUCT__
    #pragma warning( pop )
#endif

#endif /* #ifndef OPENCL_CL_ICD_H */
