COMPMID-417: Allow loading of custom OpenCL library

Change-Id: Ic26266f164ec26f9f2923c0ffe366fea37b970ae
Reviewed-on: http://mpd-gerrit.cambridge.arm.com/80090
Tested-by: Kaizen <jeremy.johnson+kaizengerrit@arm.com>
Reviewed-by: Anthony Barbier <anthony.barbier@arm.com>
diff --git a/arm_compute/core/CL/OpenCL.h b/arm_compute/core/CL/OpenCL.h
index 2fae35c..644608f 100644
--- a/arm_compute/core/CL/OpenCL.h
+++ b/arm_compute/core/CL/OpenCL.h
@@ -24,6 +24,9 @@
 #ifndef __ARM_COMPUTE_OPENCL_H__
 #define __ARM_COMPUTE_OPENCL_H__
 
+#include <string>
+#include <utility>
+
 /* Configure the Khronos C++ wrapper to target OpenCL 1.2: */
 #define CL_HPP_ENABLE_EXCEPTIONS
 #define CL_HPP_CL_1_2_DEFAULT_BUILD
@@ -34,10 +37,79 @@
 namespace cl
 {
 static const NDRange Range_128_1 = NDRange(128, 1);
-}
+} // namespace cl
 
 namespace arm_compute
 {
 bool opencl_is_available();
-}
+
+class CLSymbols final
+{
+private:
+    CLSymbols() = default;
+    void load_symbols(void *handle);
+
+public:
+    static CLSymbols &get();
+    bool load(const std::string &library);
+    bool load_default();
+
+    using clBuildProgram_func            = cl_int (*)(cl_program, cl_uint, const cl_device_id *, const char *, void (*pfn_notify)(cl_program, void *), void *);
+    using clEnqueueNDRangeKernel_func    = cl_int (*)(cl_command_queue, cl_kernel, cl_uint, const size_t *, const size_t *, const size_t *, cl_uint, const cl_event *, cl_event *);
+    using clSetKernelArg_func            = cl_int (*)(cl_kernel, cl_uint, size_t, const void *);
+    using clReleaseMemObject_func        = cl_int (*)(cl_mem);
+    using clEnqueueUnmapMemObject_func   = cl_int (*)(cl_command_queue, cl_mem, void *, cl_uint, const cl_event *, cl_event *);
+    using clRetainCommandQueue_func      = cl_int (*)(cl_command_queue command_queue);
+    using clReleaseContext_func          = cl_int (*)(cl_context);
+    using clReleaseEvent_func            = cl_int (*)(cl_event);
+    using clEnqueueWriteBuffer_func      = cl_int (*)(cl_command_queue, cl_mem, cl_bool, size_t, size_t, const void *, cl_uint, const cl_event *, cl_event *);
+    using clEnqueueReadBuffer_func       = cl_int (*)(cl_command_queue, cl_mem, cl_bool, size_t, size_t, void *, cl_uint, const cl_event *, cl_event *);
+    using clGetProgramBuildInfo_func     = cl_int (*)(cl_program, cl_device_id, cl_program_build_info, size_t, void *, size_t *);
+    using clRetainProgram_func           = cl_int (*)(cl_program program);
+    using clEnqueueMapBuffer_func        = void *(*)(cl_command_queue, cl_mem, cl_bool, cl_map_flags, size_t, size_t, cl_uint, const cl_event *, cl_event *, cl_int *);
+    using clReleaseCommandQueue_func     = cl_int (*)(cl_command_queue);
+    using clCreateProgramWithBinary_func = cl_program (*)(cl_context, cl_uint, const cl_device_id *, const size_t *, const unsigned char **, cl_int *, cl_int *);
+    using clRetainContext_func           = cl_int (*)(cl_context context);
+    using clReleaseProgram_func          = cl_int (*)(cl_program program);
+    using clFlush_func                   = cl_int (*)(cl_command_queue command_queue);
+    using clGetProgramInfo_func          = cl_int (*)(cl_program, cl_program_info, size_t, void *, size_t *);
+    using clCreateKernel_func            = cl_kernel (*)(cl_program, const char *, cl_int *);
+    using clRetainKernel_func            = cl_int (*)(cl_kernel kernel);
+    using clCreateBuffer_func            = cl_mem (*)(cl_context, cl_mem_flags, size_t, void *, cl_int *);
+    using clCreateProgramWithSource_func = cl_program (*)(cl_context, cl_uint, const char **, const size_t *, cl_int *);
+    using clReleaseKernel_func           = cl_int (*)(cl_kernel kernel);
+    using clGetDeviceInfo_func           = cl_int (*)(cl_device_id, cl_device_info, size_t, void *, size_t *);
+    using clGetDeviceIDs_func            = cl_int (*)(cl_platform_id, cl_device_type, cl_uint, cl_device_id *, cl_uint *);
+
+    clBuildProgram_func            clBuildProgram            = nullptr;
+    clEnqueueNDRangeKernel_func    clEnqueueNDRangeKernel    = nullptr;
+    clSetKernelArg_func            clSetKernelArg            = nullptr;
+    clReleaseKernel_func           clReleaseKernel           = nullptr;
+    clCreateProgramWithSource_func clCreateProgramWithSource = nullptr;
+    clCreateBuffer_func            clCreateBuffer            = nullptr;
+    clRetainKernel_func            clRetainKernel            = nullptr;
+    clCreateKernel_func            clCreateKernel            = nullptr;
+    clGetProgramInfo_func          clGetProgramInfo          = nullptr;
+    clFlush_func                   clFlush                   = nullptr;
+    clReleaseProgram_func          clReleaseProgram          = nullptr;
+    clRetainContext_func           clRetainContext           = nullptr;
+    clCreateProgramWithBinary_func clCreateProgramWithBinary = nullptr;
+    clReleaseCommandQueue_func     clReleaseCommandQueue     = nullptr;
+    clEnqueueMapBuffer_func        clEnqueueMapBuffer        = nullptr;
+    clRetainProgram_func           clRetainProgram           = nullptr;
+    clGetProgramBuildInfo_func     clGetProgramBuildInfo     = nullptr;
+    clEnqueueReadBuffer_func       clEnqueueReadBuffer       = nullptr;
+    clEnqueueWriteBuffer_func      clEnqueueWriteBuffer      = nullptr;
+    clReleaseEvent_func            clReleaseEvent            = nullptr;
+    clReleaseContext_func          clReleaseContext          = nullptr;
+    clRetainCommandQueue_func      clRetainCommandQueue      = nullptr;
+    clEnqueueUnmapMemObject_func   clEnqueueUnmapMemObject   = nullptr;
+    clReleaseMemObject_func        clReleaseMemObject        = nullptr;
+    clGetDeviceInfo_func           clGetDeviceInfo           = nullptr;
+    clGetDeviceIDs_func            clGetDeviceIDs            = nullptr;
+
+private:
+    std::pair<bool, bool> _loaded{ false, false };
+};
+} // namespace arm_compute
 #endif /* __ARM_COMPUTE_OPENCL_H__ */