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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19// OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20// SOFTWARE.
21//
22
23#include "api/util.hpp"
24#include "core/context.hpp"
25
26using namespace clover;
27
28PUBLIC cl_context
29clCreateContext(const cl_context_properties *props, cl_uint num_devs,
30                const cl_device_id *devs,
31                void (CL_CALLBACK *pfn_notify)(const char *, const void *,
32                                               size_t, void *),
33                void *user_data, cl_int *errcode_ret) try {
34   auto mprops = property_map(props);
35
36   if (!devs || !num_devs ||
37       (!pfn_notify && user_data))
38      throw error(CL_INVALID_VALUE);
39
40   if (any_of(is_zero<cl_device_id>(), devs, devs + num_devs))
41      throw error(CL_INVALID_DEVICE);
42
43   for (auto p : mprops) {
44      if (!(p.first == CL_CONTEXT_PLATFORM &&
45            (cl_platform_id)p.second == NULL))
46         throw error(CL_INVALID_PROPERTY);
47   }
48
49   ret_error(errcode_ret, CL_SUCCESS);
50   return new context(
51      property_vector(mprops),
52      std::vector<cl_device_id>(devs, devs + num_devs));
53
54} catch(error &e) {
55   ret_error(errcode_ret, e);
56   return NULL;
57}
58
59PUBLIC cl_context
60clCreateContextFromType(const cl_context_properties *props,
61                        cl_device_type type,
62                        void (CL_CALLBACK *pfn_notify)(
63                           const char *, const void *, size_t, void *),
64                        void *user_data, cl_int *errcode_ret) {
65   cl_device_id dev;
66   cl_int ret;
67
68   ret = clGetDeviceIDs(0, type, 1, &dev, 0);
69   if (ret) {
70      ret_error(errcode_ret, ret);
71      return NULL;
72   }
73
74   return clCreateContext(props, 1, &dev, pfn_notify, user_data, errcode_ret);
75}
76
77PUBLIC cl_int
78clRetainContext(cl_context ctx) {
79   if (!ctx)
80      return CL_INVALID_CONTEXT;
81
82   ctx->retain();
83   return CL_SUCCESS;
84}
85
86PUBLIC cl_int
87clReleaseContext(cl_context ctx) {
88   if (!ctx)
89      return CL_INVALID_CONTEXT;
90
91   if (ctx->release())
92      delete ctx;
93
94   return CL_SUCCESS;
95}
96
97PUBLIC cl_int
98clGetContextInfo(cl_context ctx, cl_context_info param,
99                 size_t size, void *buf, size_t *size_ret) {
100   if (!ctx)
101      return CL_INVALID_CONTEXT;
102
103   switch (param) {
104   case CL_CONTEXT_REFERENCE_COUNT:
105      return scalar_property<cl_uint>(buf, size, size_ret, ctx->ref_count());
106
107   case CL_CONTEXT_NUM_DEVICES:
108      return scalar_property<cl_uint>(buf, size, size_ret, ctx->devs.size());
109
110   case CL_CONTEXT_DEVICES:
111      return vector_property<cl_device_id>(buf, size, size_ret, ctx->devs);
112
113   case CL_CONTEXT_PROPERTIES:
114      return vector_property<cl_context_properties>(buf, size, size_ret,
115                                                    ctx->props());
116
117   default:
118      return CL_INVALID_VALUE;
119   }
120}
121