rusticl: Create CL mem objects from GL

Reviewed-by: Karol Herbst <kherbst@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21305>
This commit is contained in:
Antonio Gomes 2023-08-12 22:50:55 -03:00 committed by Marge Bot
parent 0bafe8be2c
commit 2645003bdc
7 changed files with 585 additions and 10 deletions

View file

@ -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,

View file

@ -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(())),
)
}

View file

@ -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 {

View file

@ -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
)
}

View file

@ -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)

View file

@ -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,

View file

@ -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) }
}