cl3/gl.rs
1// Copyright (c) 2021-2024 Via Technology Ltd.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! `OpenCL` `OpenGL` Interoperability API.
16
17#![allow(unused_unsafe)]
18#![allow(non_camel_case_types, deprecated)]
19#![allow(clippy::not_unsafe_ptr_arg_deref, clippy::missing_safety_doc)]
20
21pub use opencl_sys::{
22 cl_GLenum, cl_GLint, cl_GLsync, cl_GLuint, cl_command_queue, cl_context, cl_context_properties,
23 cl_event, cl_gl_context_info, cl_gl_object_type, cl_gl_platform_info, cl_gl_texture_info,
24 cl_int, cl_mem, cl_mem_flags, cl_uint, CL_CGL_SHAREGROUP_KHR,
25 CL_COMMAND_GL_FENCE_SYNC_OBJECT_KHR, CL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR,
26 CL_DEVICES_FOR_GL_CONTEXT_KHR, CL_EGL_DISPLAY_KHR, CL_GLX_DISPLAY_KHR, CL_GL_CONTEXT_KHR,
27 CL_GL_MIPMAP_LEVEL, CL_GL_NUM_SAMPLES, CL_GL_OBJECT_BUFFER, CL_GL_OBJECT_RENDERBUFFER,
28 CL_GL_OBJECT_TEXTURE1D, CL_GL_OBJECT_TEXTURE1D_ARRAY, CL_GL_OBJECT_TEXTURE2D,
29 CL_GL_OBJECT_TEXTURE2D_ARRAY, CL_GL_OBJECT_TEXTURE3D, CL_GL_OBJECT_TEXTURE_BUFFER,
30 CL_GL_TEXTURE_TARGET, CL_INVALID_VALUE, CL_KHR_GL_SHARING, CL_SUCCESS, CL_WGL_HDC_KHR,
31};
32
33use super::info_type::InfoType;
34use super::{api_info_size, api_info_value, api_info_vector};
35#[allow(unused_imports)]
36use libc::{c_void, intptr_t, size_t};
37use std::mem;
38use std::ptr;
39
40/// Create an `OpenCL` buffer object for a context from an OpenGL buffer.
41/// Calls clCreateFromGLBuffer to create an `OpenCL` buffer object.
42///
43/// * `context` - a valid `OpenCL` context created from an OpenGL context.
44/// * `flags` - a bit-field used to specify allocation and usage information
45/// about the image memory object being created, see:
46/// [Memory Flags](https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_API.html#memory-flags-table).
47/// * `bufobj` - the OpenGL buffer.
48///
49/// returns a Result containing the new `OpenCL` buffer object
50/// or the error code from the `OpenCL` C API function.
51#[inline]
52pub unsafe fn create_from_gl_buffer(
53 context: cl_context,
54 flags: cl_mem_flags,
55 bufobj: cl_GLuint,
56) -> Result<cl_mem, cl_int> {
57 let mut status: cl_int = CL_INVALID_VALUE;
58 let mem = cl_call!(clCreateFromGLBuffer(context, flags, bufobj, &mut status));
59 if CL_SUCCESS == status {
60 Ok(mem)
61 } else {
62 Err(status)
63 }
64}
65
66/// Create an `OpenCL` image object, image array object, or image buffer object.
67///
68/// For a context from an OpenGL texture object, texture array object,
69/// texture buffer object, or a single face of an OpenGL cubemap texture object.
70/// Calls clCreateFromGLTexture to create an `OpenCL` memory object.
71///
72/// * `context` - a valid `OpenCL` context created from an OpenGL context.
73/// * `flags` - a bit-field used to specify allocation and usage information
74/// about the image memory object being created, see:
75/// [Memory Flags](https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_API.html#memory-flags-table).
76/// * `texture_target` - used to define the image type of texture.
77/// * `miplevel ` - used to define the mipmap level.
78/// * `texture ` - the name of a GL buffer texture object.
79///
80/// returns a Result containing the new `OpenCL` image object
81/// or the error code from the `OpenCL` C API function.
82#[inline]
83pub unsafe fn create_from_gl_texture(
84 context: cl_context,
85 flags: cl_mem_flags,
86 texture_target: cl_GLenum,
87 miplevel: cl_GLint,
88 texture: cl_GLuint,
89) -> Result<cl_mem, cl_int> {
90 let mut status: cl_int = CL_INVALID_VALUE;
91 let mem = cl_call!(clCreateFromGLTexture(
92 context,
93 flags,
94 texture_target,
95 miplevel,
96 texture,
97 &mut status,
98 ));
99 if CL_SUCCESS == status {
100 Ok(mem)
101 } else {
102 Err(status)
103 }
104}
105
106/// Create an `OpenCL` 2D image object from an OpenGL renderbuffer object.
107///
108/// Calls clCreateFromGLRenderbuffer to create an `OpenCL` buffer object.
109///
110/// * `context` - a valid `OpenCL` context created from an OpenGL context.
111/// * `flags` - a bit-field used to specify allocation and usage information
112/// about the image memory object being created, see:
113/// [Memory Flags](https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_API.html#memory-flags-table).
114/// * `renderbuffer` - a GL renderbuffer object.
115///
116/// returns a Result containing the new `OpenCL` image object
117/// or the error code from the `OpenCL` C API function.
118#[inline]
119pub unsafe fn create_from_gl_render_buffer(
120 context: cl_context,
121 flags: cl_mem_flags,
122 renderbuffer: cl_GLuint,
123) -> Result<cl_mem, cl_int> {
124 let mut status: cl_int = CL_INVALID_VALUE;
125 let mem = cl_call!(clCreateFromGLRenderbuffer(
126 context,
127 flags,
128 renderbuffer,
129 &mut status
130 ));
131 if CL_SUCCESS == status {
132 Ok(mem)
133 } else {
134 Err(status)
135 }
136}
137
138/// Query an OpenGL object used to create an `OpenCL` memory object.
139///
140/// Calls clGetGLObjectInfo to get the object type and name.
141///
142/// * `memobj` - a valid `OpenCL` memory object handle.
143///
144/// returns a Result containing the OpenGL object type and name
145/// or the error code from the `OpenCL` C API function.
146#[inline]
147pub fn get_gl_object_info(memobj: cl_mem) -> Result<(cl_GLuint, cl_GLuint), cl_int> {
148 let mut object_type: cl_uint = CL_GL_OBJECT_BUFFER;
149 let mut object_name: cl_uint = 0;
150 let status = unsafe {
151 cl_call!(clGetGLObjectInfo(
152 memobj,
153 &mut object_type,
154 &mut object_name
155 ))
156 };
157 if CL_SUCCESS == status {
158 Ok((object_type, object_name))
159 } else {
160 Err(status)
161 }
162}
163
164/// Get data about an OpenGL texture object.
165///
166/// Calls clGetGLTextureInfo to get the desired data about the texture object.
167pub fn get_gl_texture_data(
168 memobj: cl_mem,
169 param_name: cl_gl_texture_info,
170) -> Result<Vec<u8>, cl_int> {
171 api_info_size!(get_size, clGetGLTextureInfo);
172 let size = get_size(memobj, param_name)?;
173 api_info_vector!(get_vector, u8, clGetGLTextureInfo);
174 get_vector(memobj, param_name, size)
175}
176
177/// Get information about the GL texture object associated with a memory object.
178///
179/// Calls clGetGLTextureInfo to get the desired information.
180///
181/// * `memobj` - the `OpenCL` memory object.
182/// * `param_name` - the type of memory object information being queried, see:
183/// [Texture Info](https://www.khronos.org/registry/OpenCL//sdk/2.2/docs/man/html/clGetGLTextureInfo.html).
184///
185/// returns a Result containing the desired information in an `InfoType` enum
186/// or the error code from the `OpenCL` C API function.
187pub fn get_gl_texture_info(
188 memobj: cl_mem,
189 param_name: cl_gl_texture_info,
190) -> Result<InfoType, cl_int> {
191 match param_name {
192 CL_GL_TEXTURE_TARGET => {
193 api_info_value!(get_value, cl_GLenum, clGetGLTextureInfo);
194 Ok(InfoType::Uint(get_value(memobj, param_name)?))
195 }
196
197 CL_GL_MIPMAP_LEVEL | CL_GL_NUM_SAMPLES => {
198 api_info_value!(get_value, cl_GLint, clGetGLTextureInfo);
199 Ok(InfoType::Int(get_value(memobj, param_name)?))
200 }
201
202 _ => Ok(InfoType::VecUchar(get_gl_texture_data(memobj, param_name)?)),
203 }
204}
205
206/// Acquire `OpenCL` memory objects that have been created from `OpenGL` objects.
207/// Calls `clEnqueueAcquireGLObjects`.
208///
209/// * `command_queue` - a valid `OpenCL` `command_queue`.
210/// * `num_objects` - the number of memory objects to acquire.
211/// * `mem_objects` - the memory objects to acquire.
212/// * `num_events_in_wait_list` - the number of events in the wait list.
213/// * `event_wait_list` - the wait list events.
214///
215/// returns a Result containing the new `OpenCL` event
216/// or the error code from the `OpenCL` C API function.
217#[inline]
218pub unsafe fn enqueue_acquire_gl_objects(
219 command_queue: cl_command_queue,
220 num_objects: cl_uint,
221 mem_objects: *const cl_mem,
222 num_events_in_wait_list: cl_uint,
223 event_wait_list: *const cl_event,
224) -> Result<cl_event, cl_int> {
225 let mut event: cl_event = ptr::null_mut();
226 let status: cl_int = cl_call!(clEnqueueAcquireGLObjects(
227 command_queue,
228 num_objects,
229 mem_objects,
230 num_events_in_wait_list,
231 event_wait_list,
232 &mut event,
233 ));
234 if CL_SUCCESS == status {
235 Ok(event)
236 } else {
237 Err(status)
238 }
239}
240
241/// Release `OpenCL` memory objects that have been created from `OpenGL` objects.
242/// Calls `clEnqueueReleaseGLObjects`.
243///
244/// * `command_queue` - a valid `OpenCL` `command_queue`.
245/// * `num_objects` - the number of memory objects to acquire.
246/// * `mem_objects` - the memory objects to acquire.
247/// * `num_events_in_wait_list` - the number of events in the wait list.
248/// * `event_wait_list` - the wait list events.
249///
250/// returns a Result containing the new `OpenCL` event
251/// or the error code from the `OpenCL` C API function.
252#[inline]
253pub unsafe fn enqueue_release_gl_objects(
254 command_queue: cl_command_queue,
255 num_objects: cl_uint,
256 mem_objects: *const cl_mem,
257 num_events_in_wait_list: cl_uint,
258 event_wait_list: *const cl_event,
259) -> Result<cl_event, cl_int> {
260 let mut event: cl_event = ptr::null_mut();
261 let status: cl_int = cl_call!(clEnqueueReleaseGLObjects(
262 command_queue,
263 num_objects,
264 mem_objects,
265 num_events_in_wait_list,
266 event_wait_list,
267 &mut event,
268 ));
269 if CL_SUCCESS == status {
270 Ok(event)
271 } else {
272 Err(status)
273 }
274}
275
276/// Create an `OpenCL` 2D image object from an `OpenGL` 2D texture object,
277/// or a single face of an OpenGL cubemap texture object.
278///
279/// Calls clCreateFromGLTexture2D to create an `OpenCL` memory object.
280/// Deprecated in `CL_VERSION_1_2`, use `create_from_gl_texture`.
281///
282/// * `context` - a valid `OpenCL` context created from an OpenGL context.
283/// * `flags` - a bit-field used to specify allocation and usage information
284/// about the image memory object being created, see:
285/// [Memory Flags](https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_API.html#memory-flags-table).
286/// * `texture_target` - used to define the image type of texture.
287/// * `miplevel ` - used to define the mipmap level.
288/// * `texture ` - the name of a GL 2D, cubemap or rectangle texture object.
289///
290/// returns a Result containing the new `OpenCL` image object
291/// or the error code from the `OpenCL` C API function.
292#[cfg_attr(
293 any(
294 feature = "CL_VERSION_1_2",
295 feature = "CL_VERSION_2_0",
296 feature = "CL_VERSION_2_1",
297 feature = "CL_VERSION_2_2",
298 feature = "CL_VERSION_3_0"
299 ),
300 deprecated(
301 since = "0.1.0",
302 note = "From CL_VERSION_1_2 use create_from_gl_texture"
303 )
304)]
305#[inline]
306pub unsafe fn create_from_gl_texture_2d(
307 context: cl_context,
308 flags: cl_mem_flags,
309 texture_target: cl_GLenum,
310 miplevel: cl_GLint,
311 texture: cl_GLuint,
312) -> Result<cl_mem, cl_int> {
313 let mut status: cl_int = CL_INVALID_VALUE;
314 let mem = cl_call!(clCreateFromGLTexture2D(
315 context,
316 flags,
317 texture_target,
318 miplevel,
319 texture,
320 &mut status,
321 ));
322 if CL_SUCCESS == status {
323 Ok(mem)
324 } else {
325 Err(status)
326 }
327}
328
329/// Create an `OpenCL` 3D image object from an OpenGL 3D texture object.
330///
331/// Calls `clCreateFromGLTexture3D` to create an `OpenCL` memory object.
332/// Deprecated in `CL_VERSION_1_2`, use `create_from_gl_texture`.
333///
334/// * `context` - a valid `OpenCL` context created from an OpenGL context.
335/// * `flags` - a bit-field used to specify allocation and usage information
336/// about the image memory object being created, see:
337/// [Memory Flags](https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_API.html#memory-flags-table).
338/// * `texture_target` - used to define the image type of texture.
339/// * `miplevel ` - used to define the mipmap level.
340/// * `texture ` - the name of a GL 2D, cubemap or rectangle texture object.
341///
342/// returns a Result containing the new `OpenCL` image object
343/// or the error code from the `OpenCL` C API function.
344#[cfg_attr(
345 any(
346 feature = "CL_VERSION_1_2",
347 feature = "CL_VERSION_2_0",
348 feature = "CL_VERSION_2_1",
349 feature = "CL_VERSION_2_2",
350 feature = "CL_VERSION_3_0"
351 ),
352 deprecated(
353 since = "0.1.0",
354 note = "From CL_VERSION_1_2 use create_from_gl_texture"
355 )
356)]
357#[inline]
358pub unsafe fn create_from_gl_texture_3d(
359 context: cl_context,
360 flags: cl_mem_flags,
361 texture_target: cl_GLenum,
362 miplevel: cl_GLint,
363 texture: cl_GLuint,
364) -> Result<cl_mem, cl_int> {
365 let mut status: cl_int = CL_INVALID_VALUE;
366 let mem = cl_call!(clCreateFromGLTexture3D(
367 context,
368 flags,
369 texture_target,
370 miplevel,
371 texture,
372 &mut status,
373 ));
374 if CL_SUCCESS == status {
375 Ok(mem)
376 } else {
377 Err(status)
378 }
379}
380
381/// Get OpenGL context information.
382/// Calls `clGetGLContextInfoKHR` to get the desired information.
383///
384/// * `properties` - the `OpenCL` context properties.
385/// * `param_name` - the type of memory object information being queried, see:
386/// [Context Info](https://www.khronos.org/registry/OpenCL//sdk/2.2/docs/man/html/clGetGLContextInfoKHR.html).
387///
388/// returns a Result containing the desired information in an `InfoType` enum
389/// or the error code from the `OpenCL` C API function.
390#[cfg(any(feature = "cl_khr_gl_sharing", feature = "dynamic"))]
391pub fn get_gl_context_info_khr(
392 properties: *mut cl_context_properties,
393 param_name: cl_gl_context_info,
394) -> Result<InfoType, cl_int> {
395 match param_name {
396 CL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR => {
397 let mut data: intptr_t = 0;
398 let data_ptr: *mut intptr_t = &mut data;
399 let status = unsafe {
400 cl_call!(clGetGLContextInfoKHR(
401 properties,
402 param_name,
403 mem::size_of::<intptr_t>(),
404 data_ptr.cast::<c_void>(),
405 ptr::null_mut(),
406 ))
407 };
408 if CL_SUCCESS == status {
409 Ok(InfoType::Ptr(data))
410 } else {
411 Err(status)
412 }
413 }
414
415 CL_DEVICES_FOR_GL_CONTEXT_KHR => {
416 // Get the size
417 let mut size: size_t = 0;
418 let status = unsafe {
419 cl_call!(clGetGLContextInfoKHR(
420 properties,
421 param_name,
422 0,
423 ptr::null_mut(),
424 &mut size
425 ))
426 };
427 if CL_SUCCESS != status {
428 Err(status)
429 } else if 0 < size {
430 // Get the data
431 let count = size / mem::size_of::<intptr_t>();
432 let mut data: Vec<intptr_t> = Vec::with_capacity(count);
433 let status = unsafe {
434 cl_call!(clGetGLContextInfoKHR(
435 properties,
436 param_name,
437 size,
438 data.as_mut_ptr().cast::<c_void>(),
439 ptr::null_mut(),
440 ))
441 };
442 if CL_SUCCESS == status {
443 Ok(InfoType::VecIntPtr(data))
444 } else {
445 Err(status)
446 }
447 } else {
448 Ok(InfoType::VecIntPtr(Vec::default()))
449 }
450 }
451
452 _ => {
453 // Get the size
454 let mut size: size_t = 0;
455 let status = unsafe {
456 cl_call!(clGetGLContextInfoKHR(
457 properties,
458 param_name,
459 0,
460 ptr::null_mut(),
461 &mut size
462 ))
463 };
464 if CL_SUCCESS != status {
465 Err(status)
466 } else if 0 < size {
467 // Get the data
468 let mut data: Vec<u8> = Vec::with_capacity(size);
469 let status = unsafe {
470 cl_call!(clGetGLContextInfoKHR(
471 properties,
472 param_name,
473 size,
474 data.as_mut_ptr().cast::<c_void>(),
475 ptr::null_mut(),
476 ))
477 };
478 if CL_SUCCESS == status {
479 Ok(InfoType::VecUchar(data))
480 } else {
481 Err(status)
482 }
483 } else {
484 Ok(InfoType::VecUchar(Vec::default()))
485 }
486 }
487 }
488}
489
490/// Create an event object linked to an OpenGL sync object.
491/// Requires the `cl_khr_gl_event` extension
492/// Calls `clCreateEventFromGLsyncKHR`.
493///
494/// * `context` - a valid `OpenCL` context.
495/// * `sync` - the sync object in the GL share group associated with context.
496///
497/// returns a Result containing the new `OpenCL` event
498/// or the error code from the `OpenCL` C API function.
499#[cfg(any(feature = "cl_khr_gl_event", feature = "dynamic"))]
500#[inline]
501pub fn create_event_from_gl_sync_khr(
502 context: cl_context,
503 sync: cl_GLsync,
504) -> Result<cl_event, cl_int> {
505 let mut status: cl_int = CL_INVALID_VALUE;
506 let event: cl_event =
507 unsafe { cl_call!(clCreateEventFromGLsyncKHR(context, sync, &mut status)) };
508 if CL_SUCCESS == status {
509 Ok(event)
510 } else {
511 Err(status)
512 }
513}