1// 2// Copyright 2012 Francisco Jerez 3// 4// Permission is hereby granted, free of charge, to any person obtaining a 5// copy of this software and associated documentation files (the "Software"), 6// to deal in the Software without restriction, including without limitation 7// the rights to use, copy, modify, merge, publish, distribute, sublicense, 8// and/or sell copies of the Software, and to permit persons to whom the 9// Software is furnished to do so, subject to the following conditions: 10// 11// The above copyright notice and this permission notice shall be included in 12// all copies or substantial portions of the Software. 13// 14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 18// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20// OTHER DEALINGS IN THE SOFTWARE. 21// 22 23#include "api/util.hpp" 24#include "core/context.hpp" 25#include "core/platform.hpp" 26 27using namespace clover; 28 29CLOVER_API cl_context 30clCreateContext(const cl_context_properties *d_props, cl_uint num_devs, 31 const cl_device_id *d_devs, 32 void (CL_CALLBACK *pfn_notify)(const char *, const void *, 33 size_t, void *), 34 void *user_data, cl_int *r_errcode) try { 35 auto props = obj<property_list_tag>(d_props); 36 auto devs = objs(d_devs, num_devs); 37 38 if (!pfn_notify && user_data) 39 throw error(CL_INVALID_VALUE); 40 41 for (auto &prop : props) { 42 if (prop.first == CL_CONTEXT_PLATFORM) 43 find_platform(prop.second.as<cl_platform_id>()); 44 else 45 throw error(CL_INVALID_PROPERTY); 46 } 47 48 const auto notify = (!pfn_notify ? context::notify_action() : 49 [=](const char *s) { 50 pfn_notify(s, NULL, 0, user_data); 51 }); 52 53 ret_error(r_errcode, CL_SUCCESS); 54 return desc(new context(props, devs, notify)); 55 56} catch (error &e) { 57 ret_error(r_errcode, e); 58 return NULL; 59} 60 61CLOVER_API cl_context 62clCreateContextFromType(const cl_context_properties *d_props, 63 cl_device_type type, 64 void (CL_CALLBACK *pfn_notify)( 65 const char *, const void *, size_t, void *), 66 void *user_data, cl_int *r_errcode) try { 67 cl_platform_id d_platform; 68 cl_uint num_platforms; 69 cl_int ret; 70 std::vector<cl_device_id> devs; 71 cl_uint num_devices; 72 73 ret = clGetPlatformIDs(1, &d_platform, &num_platforms); 74 if (ret || !num_platforms) 75 throw error(CL_INVALID_PLATFORM); 76 77 ret = clGetDeviceIDs(d_platform, type, 0, NULL, &num_devices); 78 if (ret) 79 throw error(CL_DEVICE_NOT_FOUND); 80 devs.resize(num_devices); 81 ret = clGetDeviceIDs(d_platform, type, num_devices, devs.data(), 0); 82 if (ret) 83 throw error(CL_DEVICE_NOT_FOUND); 84 85 return clCreateContext(d_props, num_devices, devs.data(), pfn_notify, 86 user_data, r_errcode); 87 88} catch (error &e) { 89 ret_error(r_errcode, e); 90 return NULL; 91} 92 93CLOVER_API cl_int 94clRetainContext(cl_context d_ctx) try { 95 obj(d_ctx).retain(); 96 return CL_SUCCESS; 97 98} catch (error &e) { 99 return e.get(); 100} 101 102CLOVER_API cl_int 103clReleaseContext(cl_context d_ctx) try { 104 if (obj(d_ctx).release()) 105 delete pobj(d_ctx); 106 107 return CL_SUCCESS; 108 109} catch (error &e) { 110 return e.get(); 111} 112 113CLOVER_API cl_int 114clGetContextInfo(cl_context d_ctx, cl_context_info param, 115 size_t size, void *r_buf, size_t *r_size) try { 116 property_buffer buf { r_buf, size, r_size }; 117 auto &ctx = obj(d_ctx); 118 119 switch (param) { 120 case CL_CONTEXT_REFERENCE_COUNT: 121 buf.as_scalar<cl_uint>() = ctx.ref_count(); 122 break; 123 124 case CL_CONTEXT_NUM_DEVICES: 125 buf.as_scalar<cl_uint>() = ctx.devices().size(); 126 break; 127 128 case CL_CONTEXT_DEVICES: 129 buf.as_vector<cl_device_id>() = descs(ctx.devices()); 130 break; 131 132 case CL_CONTEXT_PROPERTIES: 133 buf.as_vector<cl_context_properties>() = desc(ctx.properties()); 134 break; 135 136 default: 137 throw error(CL_INVALID_VALUE); 138 } 139 140 return CL_SUCCESS; 141 142} catch (error &e) { 143 return e.get(); 144} 145 146CLOVER_API cl_int 147clSetContextDestructorCallback(cl_context d_ctx, 148 void (CL_CALLBACK *pfn_notify)(cl_context, void *), 149 void *user_data) try { 150 CLOVER_NOT_SUPPORTED_UNTIL("3.0"); 151 auto &ctx = obj(d_ctx); 152 153 if (!pfn_notify) 154 return CL_INVALID_VALUE; 155 156 ctx.destroy_notify([=]{ pfn_notify(d_ctx, user_data); }); 157 158 return CL_SUCCESS; 159 160} catch (error &e) { 161 return e.get(); 162} 163