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