Module: Mesa
Branch: main
Commit: 2645003bdc527b5dc046366fce5e65b44b27334f
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=2645003bdc527b5dc046366fce5e65b44b27334f

Author: Antonio Gomes <antoniospg...@gmail.com>
Date:   Sat Aug 12 22:50:55 2023 -0300

rusticl: Create CL mem objects from GL

Reviewed-by: Karol Herbst <kher...@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21305>

---

 src/gallium/frontends/rusticl/api/icd.rs          |  27 ++-
 src/gallium/frontends/rusticl/api/memory.rs       | 217 ++++++++++++++++++++++
 src/gallium/frontends/rusticl/core/context.rs     |  34 ++++
 src/gallium/frontends/rusticl/core/gl.rs          | 206 +++++++++++++++++++-
 src/gallium/frontends/rusticl/core/memory.rs      |  73 ++++++++
 src/gallium/frontends/rusticl/core/util.rs        |   1 +
 src/gallium/frontends/rusticl/mesa/pipe/screen.rs |  37 ++++
 7 files changed, 585 insertions(+), 10 deletions(-)

diff --git a/src/gallium/frontends/rusticl/api/icd.rs 
b/src/gallium/frontends/rusticl/api/icd.rs
index 29fbbf4015b..bd033e5abb9 100644
--- a/src/gallium/frontends/rusticl/api/icd.rs
+++ b/src/gallium/frontends/rusticl/api/icd.rs
@@ -85,14 +85,14 @@ pub static DISPATCH: cl_icd_dispatch = cl_icd_dispatch {
     clEnqueueWaitForEvents: None,
     clEnqueueBarrier: Some(cl_enqueue_barrier),
     clGetExtensionFunctionAddress: Some(cl_get_extension_function_address),
-    clCreateFromGLBuffer: None,
-    clCreateFromGLTexture2D: None,
-    clCreateFromGLTexture3D: None,
-    clCreateFromGLRenderbuffer: None,
-    clGetGLObjectInfo: None,
-    clGetGLTextureInfo: None,
-    clEnqueueAcquireGLObjects: None,
-    clEnqueueReleaseGLObjects: None,
+    clCreateFromGLBuffer: Some(cl_create_from_gl_buffer),
+    clCreateFromGLTexture2D: Some(cl_create_from_gl_texture_2d),
+    clCreateFromGLTexture3D: Some(cl_create_from_gl_texture_3d),
+    clCreateFromGLRenderbuffer: Some(cl_create_from_gl_renderbuffer),
+    clGetGLObjectInfo: Some(cl_get_gl_object_info),
+    clGetGLTextureInfo: Some(cl_get_gl_texture_info),
+    clEnqueueAcquireGLObjects: Some(cl_enqueue_acquire_gl_objects),
+    clEnqueueReleaseGLObjects: Some(cl_enqueue_release_gl_objects),
     clGetGLContextInfoKHR: Some(cl_get_gl_context_info_khr),
     clGetDeviceIDsFromD3D10KHR: ptr::null_mut(),
     clCreateFromD3D10BufferKHR: ptr::null_mut(),
@@ -127,7 +127,7 @@ pub static DISPATCH: cl_icd_dispatch = cl_icd_dispatch {
     clEnqueueMarkerWithWaitList: Some(cl_enqueue_marker_with_wait_list),
     clEnqueueBarrierWithWaitList: Some(cl_enqueue_barrier_with_wait_list),
     clGetExtensionFunctionAddressForPlatform: 
Some(cl_get_extension_function_address_for_platform),
-    clCreateFromGLTexture: None,
+    clCreateFromGLTexture: Some(cl_create_from_gl_texture),
     clGetDeviceIDsFromD3D11KHR: ptr::null_mut(),
     clCreateFromD3D11BufferKHR: ptr::null_mut(),
     clCreateFromD3D11Texture2DKHR: ptr::null_mut(),
@@ -414,7 +414,16 @@ extern "C" fn cl_get_extension_function_address(
         "clCreateProgramWithILKHR" => cl_create_program_with_il as *mut 
::std::ffi::c_void,
 
         // cl_khr_gl_sharing
+        "clCreateFromGLBuffer" => cl_create_from_gl_buffer as *mut 
::std::ffi::c_void,
+        "clCreateFromGLRenderbuffer" => cl_create_from_gl_renderbuffer as *mut 
::std::ffi::c_void,
+        "clCreateFromGLTexture" => cl_create_from_gl_texture as *mut 
::std::ffi::c_void,
+        "clCreateFromGLTexture2D" => cl_create_from_gl_texture_2d as *mut 
::std::ffi::c_void,
+        "clCreateFromGLTexture3D" => cl_create_from_gl_texture_3d as *mut 
::std::ffi::c_void,
+        "clEnqueueAcquireGLObjects" => cl_enqueue_acquire_gl_objects as *mut 
::std::ffi::c_void,
+        "clEnqueueReleaseGLObjects" => cl_enqueue_release_gl_objects as *mut 
::std::ffi::c_void,
         "clGetGLContextInfoKHR" => cl_get_gl_context_info_khr as *mut 
::std::ffi::c_void,
+        "clGetGLObjectInfo" => cl_get_gl_object_info as *mut 
::std::ffi::c_void,
+        "clGetGLTextureInfo" => cl_get_gl_texture_info as *mut 
::std::ffi::c_void,
 
         // cl_arm_shared_virtual_memory
         "clEnqueueSVMFreeARM" => cl_enqueue_svm_free_arm as *mut 
::std::ffi::c_void,
diff --git a/src/gallium/frontends/rusticl/api/memory.rs 
b/src/gallium/frontends/rusticl/api/memory.rs
index 33941eb6298..d8c4f09fab0 100644
--- a/src/gallium/frontends/rusticl/api/memory.rs
+++ b/src/gallium/frontends/rusticl/api/memory.rs
@@ -7,6 +7,7 @@ use crate::api::util::*;
 use crate::core::context::Context;
 use crate::core::device::*;
 use crate::core::format::*;
+use crate::core::gl::*;
 use crate::core::memory::*;
 
 use mesa_rust_util::properties::Properties;
@@ -2887,3 +2888,219 @@ fn create_pipe(
 ) -> CLResult<cl_mem> {
     Err(CL_INVALID_OPERATION)
 }
+
+#[cl_info_entrypoint(cl_get_gl_texture_info)]
+impl CLInfo<cl_gl_texture_info> for cl_mem {
+    fn query(&self, q: cl_gl_texture_info, _: &[u8]) -> 
CLResult<Vec<MaybeUninit<u8>>> {
+        let mem = self.get_ref()?;
+        Ok(match *q {
+            CL_GL_MIPMAP_LEVEL => cl_prop::<cl_GLint>(0),
+            CL_GL_TEXTURE_TARGET => cl_prop::<cl_GLenum>(
+                mem.gl_obj
+                    .as_ref()
+                    .ok_or(CL_INVALID_GL_OBJECT)?
+                    .gl_object_target,
+            ),
+            _ => return Err(CL_INVALID_VALUE),
+        })
+    }
+}
+
+fn create_from_gl(
+    context: cl_context,
+    flags: cl_mem_flags,
+    target: cl_GLenum,
+    miplevel: cl_GLint,
+    texture: cl_GLuint,
+) -> CLResult<cl_mem> {
+    let c = context.get_arc()?;
+    let gl_ctx_manager = &c.gl_ctx_manager;
+
+    // CL_INVALID_CONTEXT if context associated with command_queue was not 
created from an OpenGL context
+    if gl_ctx_manager.is_none() {
+        return Err(CL_INVALID_CONTEXT);
+    }
+
+    // CL_INVALID_VALUE if values specified in flags are not valid or if value 
specified in
+    // texture_target is not one of the values specified in the description of 
texture_target.
+    validate_mem_flags(flags, target == GL_ARRAY_BUFFER)?;
+
+    // CL_INVALID_MIP_LEVEL if miplevel is greather than zero and the OpenGL
+    // implementation does not support creating from non-zero mipmap levels.
+    if miplevel > 0 {
+        return Err(CL_INVALID_MIP_LEVEL);
+    }
+
+    // CL_INVALID_CONTEXT if context [..] was not created from a GL context.
+    if let Some(gl_ctx_manager) = gl_ctx_manager {
+        let gl_export_manager =
+            gl_ctx_manager.export_object(target, flags as u32, miplevel, 
texture)?;
+
+        Ok(cl_mem::from_arc(Mem::from_gl(
+            c,
+            flags,
+            &gl_export_manager,
+        )?))
+    } else {
+        Err(CL_INVALID_CONTEXT)
+    }
+}
+
+#[cl_entrypoint]
+fn create_from_gl_texture(
+    context: cl_context,
+    flags: cl_mem_flags,
+    target: cl_GLenum,
+    miplevel: cl_GLint,
+    texture: cl_GLuint,
+) -> CLResult<cl_mem> {
+    // CL_INVALID_VALUE if values specified in flags are not valid or if value 
specified in
+    // texture_target is not one of the values specified in the description of 
texture_target.
+    if !is_valid_gl_texture(target) {
+        return Err(CL_INVALID_VALUE);
+    }
+
+    create_from_gl(context, flags, target, miplevel, texture)
+}
+
+#[cl_entrypoint]
+fn create_from_gl_texture_2d(
+    context: cl_context,
+    flags: cl_mem_flags,
+    target: cl_GLenum,
+    miplevel: cl_GLint,
+    texture: cl_GLuint,
+) -> CLResult<cl_mem> {
+    // CL_INVALID_VALUE if values specified in flags are not valid or if value 
specified in
+    // texture_target is not one of the values specified in the description of 
texture_target.
+    if !is_valid_gl_texture_2d(target) {
+        return Err(CL_INVALID_VALUE);
+    }
+
+    create_from_gl(context, flags, target, miplevel, texture)
+}
+
+#[cl_entrypoint]
+fn create_from_gl_texture_3d(
+    context: cl_context,
+    flags: cl_mem_flags,
+    target: cl_GLenum,
+    miplevel: cl_GLint,
+    texture: cl_GLuint,
+) -> CLResult<cl_mem> {
+    // CL_INVALID_VALUE if values specified in flags are not valid or if value 
specified in
+    // texture_target is not one of the values specified in the description of 
texture_target.
+    if target != GL_TEXTURE_3D {
+        return Err(CL_INVALID_VALUE);
+    }
+
+    create_from_gl(context, flags, target, miplevel, texture)
+}
+
+#[cl_entrypoint]
+fn create_from_gl_buffer(
+    context: cl_context,
+    flags: cl_mem_flags,
+    bufobj: cl_GLuint,
+) -> CLResult<cl_mem> {
+    create_from_gl(context, flags, GL_ARRAY_BUFFER, 0, bufobj)
+}
+
+#[cl_entrypoint]
+fn create_from_gl_renderbuffer(
+    context: cl_context,
+    flags: cl_mem_flags,
+    renderbuffer: cl_GLuint,
+) -> CLResult<cl_mem> {
+    create_from_gl(context, flags, GL_RENDERBUFFER, 0, renderbuffer)
+}
+
+#[cl_entrypoint]
+fn get_gl_object_info(
+    memobj: cl_mem,
+    gl_object_type: *mut cl_gl_object_type,
+    gl_object_name: *mut cl_GLuint,
+) -> CLResult<()> {
+    let m = memobj.get_ref()?;
+
+    match &m.gl_obj {
+        Some(gl_obj) => {
+            gl_object_type.write_checked(gl_obj.gl_object_type);
+            gl_object_name.write_checked(gl_obj.gl_object_name);
+        }
+        None => {
+            // CL_INVALID_GL_OBJECT if there is no GL object associated with 
memobj.
+            return Err(CL_INVALID_GL_OBJECT);
+        }
+    }
+
+    Ok(())
+}
+
+#[cl_entrypoint]
+fn enqueue_acquire_gl_objects(
+    command_queue: cl_command_queue,
+    num_objects: cl_uint,
+    mem_objects: *const cl_mem,
+    num_events_in_wait_list: cl_uint,
+    event_wait_list: *const cl_event,
+    event: *mut cl_event,
+) -> CLResult<()> {
+    let q = command_queue.get_arc()?;
+    let evs = event_list_from_cl(&q, num_events_in_wait_list, 
event_wait_list)?;
+    let objs = cl_mem::get_arc_vec_from_arr(mem_objects, num_objects)?;
+    let gl_ctx_manager = &q.context.gl_ctx_manager;
+
+    // CL_INVALID_CONTEXT if context associated with command_queue was not 
created from an OpenGL context
+    if gl_ctx_manager.is_none() {
+        return Err(CL_INVALID_CONTEXT);
+    }
+
+    // CL_INVALID_GL_OBJECT if memory objects in mem_objects have not been 
created from a GL object(s).
+    if objs.iter().any(|o| o.gl_obj.is_none()) {
+        return Err(CL_INVALID_GL_OBJECT);
+    }
+
+    create_and_queue(
+        q,
+        CL_COMMAND_ACQUIRE_GL_OBJECTS,
+        evs,
+        event,
+        false,
+        Box::new(|_, _| Ok(())),
+    )
+}
+
+#[cl_entrypoint]
+fn enqueue_release_gl_objects(
+    command_queue: cl_command_queue,
+    num_objects: cl_uint,
+    mem_objects: *const cl_mem,
+    num_events_in_wait_list: cl_uint,
+    event_wait_list: *const cl_event,
+    event: *mut cl_event,
+) -> CLResult<()> {
+    let q = command_queue.get_arc()?;
+    let evs = event_list_from_cl(&q, num_events_in_wait_list, 
event_wait_list)?;
+    let objs = cl_mem::get_arc_vec_from_arr(mem_objects, num_objects)?;
+    let gl_ctx_manager = &q.context.gl_ctx_manager;
+
+    // CL_INVALID_CONTEXT if context associated with command_queue was not 
created from an OpenGL context
+    if gl_ctx_manager.is_none() {
+        return Err(CL_INVALID_CONTEXT);
+    }
+
+    // CL_INVALID_GL_OBJECT if memory objects in mem_objects have not been 
created from a GL object(s).
+    if objs.iter().any(|o| o.gl_obj.is_none()) {
+        return Err(CL_INVALID_GL_OBJECT);
+    }
+
+    create_and_queue(
+        q,
+        CL_COMMAND_RELEASE_GL_OBJECTS,
+        evs,
+        event,
+        false,
+        Box::new(move |_, _| Ok(())),
+    )
+}
diff --git a/src/gallium/frontends/rusticl/core/context.rs 
b/src/gallium/frontends/rusticl/core/context.rs
index e475374ef0f..b9e518fe35f 100644
--- a/src/gallium/frontends/rusticl/core/context.rs
+++ b/src/gallium/frontends/rusticl/core/context.rs
@@ -9,6 +9,7 @@ use crate::impl_cl_type_trait;
 
 use mesa_rust::pipe::resource::*;
 use mesa_rust::pipe::screen::ResourceType;
+use mesa_rust_gen::pipe_format;
 use mesa_rust_util::properties::Properties;
 use rusticl_opencl_gen::*;
 
@@ -204,6 +205,39 @@ impl Context {
     pub fn remove_svm_ptr(&self, ptr: *const c_void) -> Option<Layout> {
         self.svm_ptrs.lock().unwrap().remove(&ptr)
     }
+
+    pub fn import_gl_buffer(
+        &self,
+        handle: u32,
+        modifier: u64,
+        image_type: cl_mem_object_type,
+        format: pipe_format,
+        gl_props: GLMemProps,
+    ) -> CLResult<HashMap<&'static Device, Arc<PipeResource>>> {
+        let mut res = HashMap::new();
+        let target = cl_mem_type_to_texture_target(image_type);
+
+        for dev in &self.devs {
+            let resource = dev
+                .screen()
+                .resource_import_dmabuf(
+                    handle,
+                    modifier,
+                    target,
+                    format,
+                    gl_props.stride,
+                    gl_props.width,
+                    gl_props.height,
+                    gl_props.depth,
+                    gl_props.array_size,
+                )
+                .ok_or(CL_OUT_OF_RESOURCES)?;
+
+            res.insert(*dev, Arc::new(resource));
+        }
+
+        Ok(res)
+    }
 }
 
 impl Drop for Context {
diff --git a/src/gallium/frontends/rusticl/core/gl.rs 
b/src/gallium/frontends/rusticl/core/gl.rs
index 3a0e4491b71..10eee45ee80 100644
--- a/src/gallium/frontends/rusticl/core/gl.rs
+++ b/src/gallium/frontends/rusticl/core/gl.rs
@@ -1,6 +1,7 @@
 use crate::api::icd::*;
+use crate::core::format::*;
 
-use libc_rust_gen::dlsym;
+use libc_rust_gen::{close, dlsym};
 use rusticl_opencl_gen::*;
 
 use std::ffi::CString;
@@ -166,6 +167,153 @@ impl GLCtxManager {
             Err(CL_INVALID_GL_SHAREGROUP_REFERENCE_KHR)
         }
     }
+
+    pub fn export_object(
+        &self,
+        target: cl_GLenum,
+        flags: u32,
+        miplevel: cl_GLint,
+        texture: cl_GLuint,
+    ) -> CLResult<GLExportManager> {
+        let xplat_manager = &self.xplat_manager;
+        let mut export_in = mesa_glinterop_export_in {
+            version: 1,
+            target: target,
+            obj: texture,
+            miplevel: miplevel as u32,
+            access: cl_to_interop_flags(flags),
+            ..Default::default()
+        };
+
+        let mut export_out = mesa_glinterop_export_out {
+            version: 2,
+            ..Default::default()
+        };
+
+        let err = unsafe {
+            match &self.gl_ctx {
+                GLCtx::EGL(disp, ctx) => {
+                    let egl_export_object_func = xplat_manager
+                        .MesaGLInteropEGLExportObject()?
+                        .ok_or(CL_INVALID_GL_SHAREGROUP_REFERENCE_KHR)?;
+
+                    egl_export_object_func(disp.cast(), ctx.cast(), &mut 
export_in, &mut export_out)
+                }
+                GLCtx::GLX(disp, ctx) => {
+                    let glx_export_object_func = xplat_manager
+                        .MesaGLInteropGLXExportObject()?
+                        .ok_or(CL_INVALID_GL_SHAREGROUP_REFERENCE_KHR)?;
+
+                    glx_export_object_func(disp.cast(), ctx.cast(), &mut 
export_in, &mut export_out)
+                }
+            }
+        };
+
+        if err != MESA_GLINTEROP_SUCCESS as i32 {
+            return Err(interop_to_cl_error(err));
+        }
+
+        // CL_INVALID_GL_OBJECT if bufobj is not a GL buffer object or is a GL 
buffer
+        // object but does not have an existing data store or the size of the 
buffer is 0.
+        if target == GL_ARRAY_BUFFER && export_out.buf_size == 0 {
+            return Err(CL_INVALID_GL_OBJECT);
+        }
+
+        Ok(GLExportManager {
+            export_in: export_in,
+            export_out: export_out,
+        })
+    }
+}
+
+#[derive(Clone)]
+pub struct GLMemProps {
+    pub height: u16,
+    pub depth: u16,
+    pub width: u32,
+    pub array_size: u16,
+    pub pixel_size: u8,
+    pub stride: u32,
+}
+
+impl GLMemProps {
+    pub fn size(&self) -> usize {
+        self.height as usize
+            * self.depth as usize
+            * self.array_size as usize
+            * self.width as usize
+            * self.pixel_size as usize
+    }
+}
+
+pub struct GLExportManager {
+    pub export_in: mesa_glinterop_export_in,
+    pub export_out: mesa_glinterop_export_out,
+}
+
+impl GLExportManager {
+    pub fn get_gl_mem_props(&self) -> CLResult<GLMemProps> {
+        let pixel_size = if self.is_gl_buffer() {
+            0
+        } else {
+            format_from_gl(self.export_out.internal_format)
+                .ok_or(CL_OUT_OF_HOST_MEMORY)?
+                .pixel_size()
+                .unwrap()
+        };
+
+        let mut height = self.export_out.height as u16;
+        let mut depth = self.export_out.depth as u16;
+        let mut width = self.export_out.width;
+        let mut array_size = 1;
+
+        // some fixups
+        match self.export_in.target {
+            GL_TEXTURE_1D_ARRAY => {
+                array_size = height;
+                height = 1;
+                depth = 1;
+            }
+            GL_TEXTURE_2D_ARRAY => {
+                array_size = depth;
+                depth = 1;
+            }
+            GL_ARRAY_BUFFER => {
+                array_size = 1;
+                width = self.export_out.buf_size as u32;
+                height = 1;
+                depth = 1;
+            }
+            _ => {}
+        }
+
+        Ok(GLMemProps {
+            height: height,
+            depth: depth,
+            width: width,
+            array_size: array_size,
+            pixel_size: pixel_size,
+            stride: self.export_out.stride,
+        })
+    }
+
+    pub fn is_gl_buffer(&self) -> bool {
+        self.export_out.internal_format == GL_NONE
+    }
+}
+
+impl Drop for GLExportManager {
+    fn drop(&mut self) {
+        unsafe {
+            close(self.export_out.dmabuf_fd);
+        }
+    }
+}
+
+pub struct GLObject {
+    pub gl_object_target: cl_GLenum,
+    pub gl_object_type: cl_gl_object_type,
+    pub gl_object_name: cl_GLuint,
 }
 
 pub fn interop_to_cl_error(error: i32) -> CLError {
@@ -181,3 +329,59 @@ pub fn interop_to_cl_error(error: i32) -> CLError {
         _ => CL_OUT_OF_HOST_MEMORY,
     }
 }
+
+pub fn cl_to_interop_flags(flags: u32) -> u32 {
+    match flags {
+        CL_MEM_READ_WRITE => MESA_GLINTEROP_ACCESS_READ_WRITE,
+        CL_MEM_READ_ONLY => MESA_GLINTEROP_ACCESS_READ_ONLY,
+        CL_MEM_WRITE_ONLY => MESA_GLINTEROP_ACCESS_WRITE_ONLY,
+        _ => 0,
+    }
+}
+
+pub fn target_from_gl(target: u32) -> CLResult<(u32, u32)> {
+    // CL_INVALID_IMAGE_FORMAT_DESCRIPTOR if the OpenGL texture
+    // internal format does not map to a supported OpenCL image format.
+    Ok(match target {
+        GL_ARRAY_BUFFER => (CL_MEM_OBJECT_BUFFER, CL_GL_OBJECT_BUFFER),
+        GL_RENDERBUFFER => (CL_MEM_OBJECT_IMAGE2D, CL_GL_OBJECT_RENDERBUFFER),
+        GL_TEXTURE_1D => (CL_MEM_OBJECT_IMAGE1D, CL_GL_OBJECT_TEXTURE1D),
+        GL_TEXTURE_1D_ARRAY => (CL_MEM_OBJECT_IMAGE1D_ARRAY, 
CL_GL_OBJECT_TEXTURE1D_ARRAY),
+        GL_TEXTURE_CUBE_MAP_NEGATIVE_X
+        | GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
+        | GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
+        | GL_TEXTURE_CUBE_MAP_POSITIVE_X
+        | GL_TEXTURE_CUBE_MAP_POSITIVE_Y
+        | GL_TEXTURE_CUBE_MAP_POSITIVE_Z
+        | GL_TEXTURE_2D
+        | GL_TEXTURE_RECTANGLE => (CL_MEM_OBJECT_IMAGE2D, 
CL_GL_OBJECT_TEXTURE2D),
+        GL_TEXTURE_2D_ARRAY => (CL_MEM_OBJECT_IMAGE2D_ARRAY, 
CL_GL_OBJECT_TEXTURE2D_ARRAY),
+        GL_TEXTURE_3D => (CL_MEM_OBJECT_IMAGE3D, CL_GL_OBJECT_TEXTURE3D),
+        _ => return Err(CL_INVALID_VALUE),
+    })
+}
+
+pub fn is_valid_gl_texture(target: u32) -> bool {
+    matches!(
+        target,
+        GL_TEXTURE_1D
+            | GL_TEXTURE_1D_ARRAY
+            | GL_TEXTURE_BUFFER
+            | GL_TEXTURE_2D_ARRAY
+            | GL_TEXTURE_3D
+    ) || is_valid_gl_texture_2d(target)
+}
+
+pub fn is_valid_gl_texture_2d(target: u32) -> bool {
+    matches!(
+        target,
+        GL_TEXTURE_2D
+            | GL_TEXTURE_RECTANGLE
+            | GL_TEXTURE_CUBE_MAP_NEGATIVE_X
+            | GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
+            | GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
+            | GL_TEXTURE_CUBE_MAP_POSITIVE_X
+            | GL_TEXTURE_CUBE_MAP_POSITIVE_Y
+            | GL_TEXTURE_CUBE_MAP_POSITIVE_Z
+    )
+}
diff --git a/src/gallium/frontends/rusticl/core/memory.rs 
b/src/gallium/frontends/rusticl/core/memory.rs
index ec7f3bb96a3..7ab9cb870de 100644
--- a/src/gallium/frontends/rusticl/core/memory.rs
+++ b/src/gallium/frontends/rusticl/core/memory.rs
@@ -4,6 +4,7 @@ use crate::api::util::*;
 use crate::core::context::*;
 use crate::core::device::*;
 use crate::core::format::*;
+use crate::core::gl::*;
 use crate::core::queue::*;
 use crate::core::util::*;
 use crate::impl_cl_type_trait;
@@ -118,6 +119,7 @@ pub struct Mem {
     pub image_elem_size: u8,
     pub props: Vec<cl_mem_properties>,
     pub cbs: Mutex<Vec<MemCB>>,
+    pub gl_obj: Option<GLObject>,
     res: Option<HashMap<&'static Device, Arc<PipeResource>>>,
     maps: Mutex<Mappings>,
 }
@@ -306,6 +308,7 @@ impl Mem {
             image_desc: cl_image_desc::default(),
             image_elem_size: 0,
             props: props,
+            gl_obj: None,
             cbs: Mutex::new(Vec::new()),
             res: Some(buffer),
             maps: Mappings::new(),
@@ -338,6 +341,7 @@ impl Mem {
             image_desc: cl_image_desc::default(),
             image_elem_size: 0,
             props: Vec::new(),
+            gl_obj: None,
             cbs: Mutex::new(Vec::new()),
             res: None,
             maps: Mappings::new(),
@@ -422,12 +426,81 @@ impl Mem {
             image_desc: api_image_desc,
             image_elem_size: image_elem_size,
             props: props,
+            gl_obj: None,
             cbs: Mutex::new(Vec::new()),
             res: texture,
             maps: Mappings::new(),
         }))
     }
 
+    pub fn from_gl(
+        context: Arc<Context>,
+        flags: cl_mem_flags,
+        gl_export_manager: &GLExportManager,
+    ) -> CLResult<Arc<Mem>> {
+        let export_in = &gl_export_manager.export_in;
+        let export_out = &gl_export_manager.export_out;
+
+        let (mem_type, gl_object_type) = target_from_gl(export_in.target)?;
+        let gl_mem_props = gl_export_manager.get_gl_mem_props()?;
+
+        // Handle Buffers
+        let (image_format, pipe_format) = if gl_export_manager.is_gl_buffer() {
+            (cl_image_format::default(), pipe_format::PIPE_FORMAT_NONE)
+        } else {
+            let image_format =
+                
format_from_gl(export_out.internal_format).ok_or(CL_OUT_OF_HOST_MEMORY)?;
+            (image_format, image_format.to_pipe_format().unwrap())
+        };
+
+        let texture = context.import_gl_buffer(
+            export_out.dmabuf_fd as u32,
+            export_out.modifier,
+            mem_type,
+            pipe_format,
+            gl_mem_props.clone(),
+        )?;
+
+        let gl_obj = GLObject {
+            gl_object_target: gl_export_manager.export_in.target,
+            gl_object_type: gl_object_type,
+            gl_object_name: export_in.obj,
+        };
+
+        let desc = cl_image_desc {
+            image_type: mem_type,
+            image_width: gl_mem_props.width as usize,
+            image_height: gl_mem_props.height as usize,
+            image_depth: gl_mem_props.depth as usize,
+            image_array_size: gl_mem_props.array_size as usize,
+            image_row_pitch: 0,
+            image_slice_pitch: 0,
+            num_mip_levels: 1,
+            num_samples: 1,
+            ..Default::default()
+        };
+
+        Ok(Arc::new(Self {
+            base: CLObjectBase::new(),
+            context: context,
+            parent: None,
+            mem_type: mem_type,
+            flags: flags,
+            size: gl_mem_props.size(),
+            offset: 0,
+            host_ptr: ptr::null_mut(),
+            image_format: image_format,
+            pipe_format: pipe_format,
+            image_desc: desc,
+            image_elem_size: gl_mem_props.pixel_size,
+            props: Vec::new(),
+            gl_obj: Some(gl_obj),
+            cbs: Mutex::new(Vec::new()),
+            res: Some(texture),
+            maps: Mappings::new(),
+        }))
+    }
+
     pub fn pixel_size(&self) -> Option<u8> {
         if self.is_buffer() {
             Some(1)
diff --git a/src/gallium/frontends/rusticl/core/util.rs 
b/src/gallium/frontends/rusticl/core/util.rs
index 27f03d7303b..8bb42184a41 100644
--- a/src/gallium/frontends/rusticl/core/util.rs
+++ b/src/gallium/frontends/rusticl/core/util.rs
@@ -7,6 +7,7 @@ use std::mem;
 
 pub fn cl_mem_type_to_texture_target(mem_type: cl_mem_object_type) -> 
pipe_texture_target {
     match mem_type {
+        CL_MEM_OBJECT_BUFFER => pipe_texture_target::PIPE_BUFFER,
         CL_MEM_OBJECT_IMAGE1D => pipe_texture_target::PIPE_TEXTURE_1D,
         CL_MEM_OBJECT_IMAGE2D => pipe_texture_target::PIPE_TEXTURE_2D,
         CL_MEM_OBJECT_IMAGE3D => pipe_texture_target::PIPE_TEXTURE_3D,
diff --git a/src/gallium/frontends/rusticl/mesa/pipe/screen.rs 
b/src/gallium/frontends/rusticl/mesa/pipe/screen.rs
index bcac249cefc..427ecc982f9 100644
--- a/src/gallium/frontends/rusticl/mesa/pipe/screen.rs
+++ b/src/gallium/frontends/rusticl/mesa/pipe/screen.rs
@@ -225,6 +225,43 @@ impl PipeScreen {
         self.resource_create_from_user(&tmpl, mem)
     }
 
+    pub fn resource_import_dmabuf(
+        &self,
+        handle: u32,
+        modifier: u64,
+        target: pipe_texture_target,
+        format: pipe_format,
+        stride: u32,
+        width: u32,
+        height: u16,
+        depth: u16,
+        array_size: u16,
+    ) -> Option<PipeResource> {
+        let mut tmpl = pipe_resource::default();
+        let mut handle = winsys_handle {
+            type_: WINSYS_HANDLE_TYPE_FD,
+            handle: handle,
+            modifier: modifier,
+            format: format as u64,
+            stride: stride,
+            ..Default::default()
+        };
+
+        tmpl.set_target(target);
+        tmpl.set_format(format);
+        tmpl.width0 = width;
+        tmpl.height0 = height;
+        tmpl.depth0 = depth;
+        tmpl.array_size = array_size;
+
+        unsafe {
+            PipeResource::new(
+                (*self.screen).resource_from_handle.unwrap()(self.screen, 
&tmpl, &mut handle, 0),
+                false,
+            )
+        }
+    }
+
     pub fn param(&self, cap: pipe_cap) -> i32 {
         unsafe { (*self.screen).get_param.unwrap()(self.screen, cap) }
     }

Reply via email to