clover: Switch context objects to the new model.
[mesa.git] / src / gallium / state_trackers / clover / api / memory.cpp
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/memory.hpp"
25 #include "core/format.hpp"
26
27 using namespace clover;
28
29 PUBLIC cl_mem
30 clCreateBuffer(cl_context ctx, cl_mem_flags flags, size_t size,
31 void *host_ptr, cl_int *errcode_ret) try {
32 if (!ctx)
33 throw error(CL_INVALID_CONTEXT);
34
35 if (bool(host_ptr) != bool(flags & (CL_MEM_USE_HOST_PTR |
36 CL_MEM_COPY_HOST_PTR)))
37 throw error(CL_INVALID_HOST_PTR);
38
39 if (!size)
40 throw error(CL_INVALID_BUFFER_SIZE);
41
42 if (flags & ~(CL_MEM_READ_WRITE | CL_MEM_WRITE_ONLY | CL_MEM_READ_ONLY |
43 CL_MEM_USE_HOST_PTR | CL_MEM_ALLOC_HOST_PTR |
44 CL_MEM_COPY_HOST_PTR))
45 throw error(CL_INVALID_VALUE);
46
47 ret_error(errcode_ret, CL_SUCCESS);
48 return new root_buffer(obj(ctx), flags, size, host_ptr);
49
50 } catch (error &e) {
51 ret_error(errcode_ret, e);
52 return NULL;
53 }
54
55 PUBLIC cl_mem
56 clCreateSubBuffer(cl_mem obj, cl_mem_flags flags, cl_buffer_create_type op,
57 const void *op_info, cl_int *errcode_ret) try {
58 root_buffer *parent = dynamic_cast<root_buffer *>(obj);
59
60 if (!parent)
61 throw error(CL_INVALID_MEM_OBJECT);
62
63 if ((flags & (CL_MEM_USE_HOST_PTR |
64 CL_MEM_ALLOC_HOST_PTR |
65 CL_MEM_COPY_HOST_PTR)) ||
66 (~flags & parent->flags() & (CL_MEM_READ_ONLY |
67 CL_MEM_WRITE_ONLY)))
68 throw error(CL_INVALID_VALUE);
69
70 if (op == CL_BUFFER_CREATE_TYPE_REGION) {
71 const cl_buffer_region *reg = (const cl_buffer_region *)op_info;
72
73 if (!reg ||
74 reg->origin > parent->size() ||
75 reg->origin + reg->size > parent->size())
76 throw error(CL_INVALID_VALUE);
77
78 if (!reg->size)
79 throw error(CL_INVALID_BUFFER_SIZE);
80
81 ret_error(errcode_ret, CL_SUCCESS);
82 return new sub_buffer(*parent, flags, reg->origin, reg->size);
83
84 } else {
85 throw error(CL_INVALID_VALUE);
86 }
87
88 } catch (error &e) {
89 ret_error(errcode_ret, e);
90 return NULL;
91 }
92
93 PUBLIC cl_mem
94 clCreateImage2D(cl_context d_ctx, cl_mem_flags flags,
95 const cl_image_format *format,
96 size_t width, size_t height, size_t row_pitch,
97 void *host_ptr, cl_int *errcode_ret) try {
98 auto &ctx = obj(d_ctx);
99
100 if (flags & ~(CL_MEM_READ_WRITE | CL_MEM_WRITE_ONLY | CL_MEM_READ_ONLY |
101 CL_MEM_USE_HOST_PTR | CL_MEM_ALLOC_HOST_PTR |
102 CL_MEM_COPY_HOST_PTR))
103 throw error(CL_INVALID_VALUE);
104
105 if (!format)
106 throw error(CL_INVALID_IMAGE_FORMAT_DESCRIPTOR);
107
108 if (width < 1 || height < 1)
109 throw error(CL_INVALID_IMAGE_SIZE);
110
111 if (bool(host_ptr) != bool(flags & (CL_MEM_USE_HOST_PTR |
112 CL_MEM_COPY_HOST_PTR)))
113 throw error(CL_INVALID_HOST_PTR);
114
115 if (!supported_formats(ctx, CL_MEM_OBJECT_IMAGE2D).count(*format))
116 throw error(CL_IMAGE_FORMAT_NOT_SUPPORTED);
117
118 ret_error(errcode_ret, CL_SUCCESS);
119 return new image2d(ctx, flags, format, width, height,
120 row_pitch, host_ptr);
121
122 } catch (error &e) {
123 ret_error(errcode_ret, e);
124 return NULL;
125 }
126
127 PUBLIC cl_mem
128 clCreateImage3D(cl_context d_ctx, cl_mem_flags flags,
129 const cl_image_format *format,
130 size_t width, size_t height, size_t depth,
131 size_t row_pitch, size_t slice_pitch,
132 void *host_ptr, cl_int *errcode_ret) try {
133 auto &ctx = obj(d_ctx);
134
135 if (flags & ~(CL_MEM_READ_WRITE | CL_MEM_WRITE_ONLY | CL_MEM_READ_ONLY |
136 CL_MEM_USE_HOST_PTR | CL_MEM_ALLOC_HOST_PTR |
137 CL_MEM_COPY_HOST_PTR))
138 throw error(CL_INVALID_VALUE);
139
140 if (!format)
141 throw error(CL_INVALID_IMAGE_FORMAT_DESCRIPTOR);
142
143 if (width < 1 || height < 1 || depth < 2)
144 throw error(CL_INVALID_IMAGE_SIZE);
145
146 if (bool(host_ptr) != bool(flags & (CL_MEM_USE_HOST_PTR |
147 CL_MEM_COPY_HOST_PTR)))
148 throw error(CL_INVALID_HOST_PTR);
149
150 if (!supported_formats(ctx, CL_MEM_OBJECT_IMAGE3D).count(*format))
151 throw error(CL_IMAGE_FORMAT_NOT_SUPPORTED);
152
153 ret_error(errcode_ret, CL_SUCCESS);
154 return new image3d(ctx, flags, format, width, height, depth,
155 row_pitch, slice_pitch, host_ptr);
156
157 } catch (error &e) {
158 ret_error(errcode_ret, e);
159 return NULL;
160 }
161
162 PUBLIC cl_int
163 clGetSupportedImageFormats(cl_context d_ctx, cl_mem_flags flags,
164 cl_mem_object_type type, cl_uint count,
165 cl_image_format *buf, cl_uint *count_ret) try {
166 auto &ctx = obj(d_ctx);
167
168 if (flags & ~(CL_MEM_READ_WRITE | CL_MEM_WRITE_ONLY | CL_MEM_READ_ONLY |
169 CL_MEM_USE_HOST_PTR | CL_MEM_ALLOC_HOST_PTR |
170 CL_MEM_COPY_HOST_PTR))
171 throw error(CL_INVALID_VALUE);
172
173 if (!count && buf)
174 throw error(CL_INVALID_VALUE);
175
176 auto formats = supported_formats(ctx, type);
177
178 if (buf)
179 std::copy_n(formats.begin(), std::min((cl_uint)formats.size(), count),
180 buf);
181 if (count_ret)
182 *count_ret = formats.size();
183
184 return CL_SUCCESS;
185
186 } catch (error &e) {
187 return e.get();
188 }
189
190 PUBLIC cl_int
191 clGetMemObjectInfo(cl_mem obj, cl_mem_info param,
192 size_t size, void *r_buf, size_t *r_size) try {
193 property_buffer buf { r_buf, size, r_size };
194
195 if (!obj)
196 return CL_INVALID_MEM_OBJECT;
197
198 switch (param) {
199 case CL_MEM_TYPE:
200 buf.as_scalar<cl_mem_object_type>() = obj->type();
201 break;
202
203 case CL_MEM_FLAGS:
204 buf.as_scalar<cl_mem_flags>() = obj->flags();
205 break;
206
207 case CL_MEM_SIZE:
208 buf.as_scalar<size_t>() = obj->size();
209 break;
210
211 case CL_MEM_HOST_PTR:
212 buf.as_scalar<void *>() = obj->host_ptr();
213 break;
214
215 case CL_MEM_MAP_COUNT:
216 buf.as_scalar<cl_uint>() = 0;
217 break;
218
219 case CL_MEM_REFERENCE_COUNT:
220 buf.as_scalar<cl_uint>() = obj->ref_count();
221 break;
222
223 case CL_MEM_CONTEXT:
224 buf.as_scalar<cl_context>() = &obj->ctx;
225 break;
226
227 case CL_MEM_ASSOCIATED_MEMOBJECT: {
228 sub_buffer *sub = dynamic_cast<sub_buffer *>(obj);
229 buf.as_scalar<cl_mem>() = (sub ? &sub->parent : NULL);
230 break;
231 }
232 case CL_MEM_OFFSET: {
233 sub_buffer *sub = dynamic_cast<sub_buffer *>(obj);
234 buf.as_scalar<size_t>() = (sub ? sub->offset() : 0);
235 break;
236 }
237 default:
238 throw error(CL_INVALID_VALUE);
239 }
240
241 return CL_SUCCESS;
242
243 } catch (error &e) {
244 return e.get();
245 }
246
247 PUBLIC cl_int
248 clGetImageInfo(cl_mem obj, cl_image_info param,
249 size_t size, void *r_buf, size_t *r_size) try {
250 property_buffer buf { r_buf, size, r_size };
251 image *img = dynamic_cast<image *>(obj);
252
253 if (!img)
254 return CL_INVALID_MEM_OBJECT;
255
256 switch (param) {
257 case CL_IMAGE_FORMAT:
258 buf.as_scalar<cl_image_format>() = img->format();
259 break;
260
261 case CL_IMAGE_ELEMENT_SIZE:
262 buf.as_scalar<size_t>() = 0;
263 break;
264
265 case CL_IMAGE_ROW_PITCH:
266 buf.as_scalar<size_t>() = img->row_pitch();
267 break;
268
269 case CL_IMAGE_SLICE_PITCH:
270 buf.as_scalar<size_t>() = img->slice_pitch();
271 break;
272
273 case CL_IMAGE_WIDTH:
274 buf.as_scalar<size_t>() = img->width();
275 break;
276
277 case CL_IMAGE_HEIGHT:
278 buf.as_scalar<size_t>() = img->height();
279 break;
280
281 case CL_IMAGE_DEPTH:
282 buf.as_scalar<size_t>() = img->depth();
283 break;
284
285 default:
286 throw error(CL_INVALID_VALUE);
287 }
288
289 return CL_SUCCESS;
290
291 } catch (error &e) {
292 return e.get();
293 }
294
295 PUBLIC cl_int
296 clRetainMemObject(cl_mem obj) {
297 if (!obj)
298 return CL_INVALID_MEM_OBJECT;
299
300 obj->retain();
301 return CL_SUCCESS;
302 }
303
304 PUBLIC cl_int
305 clReleaseMemObject(cl_mem obj) {
306 if (!obj)
307 return CL_INVALID_MEM_OBJECT;
308
309 if (obj->release())
310 delete obj;
311
312 return CL_SUCCESS;
313 }
314
315 PUBLIC cl_int
316 clSetMemObjectDestructorCallback(cl_mem obj,
317 void (CL_CALLBACK *pfn_notify)(cl_mem, void *),
318 void *user_data) {
319 if (!obj)
320 return CL_INVALID_MEM_OBJECT;
321
322 if (!pfn_notify)
323 return CL_INVALID_VALUE;
324
325 obj->destroy_notify([=]{ pfn_notify(obj, user_data); });
326
327 return CL_SUCCESS;
328 }