objc2 icon indicating copy to clipboard operation
objc2 copied to clipboard

Support protocol.MTLDevice.methods."newTextureWithDescriptor:iosurface:plane:"

Open sotaroikeda opened this issue 1 year ago • 1 comments

The newTextureWithDescriptor:iosurface:plane: is not supported. It is necessary for https://github.com/gfx-rs/wgpu/pull/5641 to be used by gecko see Bug 1910043.

sotaroikeda avatar Aug 01 '24 00:08 sotaroikeda

Indeed, it is intentionally skipped because we don't expose IOSurfaceRef in any shape or form.

The proper solution needs support for CoreFoundation, for now you can do something like:

#[repr(transparent)]
struct IOSurfaceRefWrapper(io_surface::IOSurfaceRef);

// SAFETY: `IOSurfaceRefWrapper` is `#[repr(transparent)]` over
// `IOSurfaceRef`, which is a typedef to `struct __IOSurface *`.
unsafe impl Encode for IOSurfaceRefWrapper {
    const ENCODING: Encoding = Encoding::Pointer(&Encoding::Struct("__IOSurface", &[]));
}

pub fn new_with_descriptor_surface_plane(
    device: &ProtocolObject<dyn MTLDevice>,
    descriptor: &MTLTextureDescriptor,
    surface: io_surface::IOSurfaceRef,
    plane: NSUInteger,
) -> Retained<ProtocolObject<dyn MTLTexture>> {
    let surface = IOSurfaceRefWrapper(surface);
    msg_send_id![device, newTextureWithDescriptor: descriptor, iosurface: surface, plane: plane]
}

This approach is somewhat documented in here.

madsmtm avatar Aug 11 '24 19:08 madsmtm

Update: We now have fairly good support for CoreFoundation, and by extension IOSurfaceRef from the IOSurface framework too.

So I've now un-skipped the newTextureWithDescriptor:iosurface:plane: method, to be released soon.

madsmtm avatar Jan 09 '25 03:01 madsmtm

@madsmtm May I ask how it is possible to create an IOSurface reference (IOSurfaceRef) from IOSurface?

let surface = IOSurface::new();

The created surface is a Retained<IOSurface>.

I need it for functions such as IOSurfaceLock and IOSurfaceGetBaseAddress.

pub fn IOSurfaceLock(
  buffer: &IOSurfaceRef,
  options: IOSurfaceLockOptions,
  seed: *mut u32,
) -> libc::kern_return_t;

Thanks.

ghost avatar Jan 25 '25 02:01 ghost

It should be possible, since the Objective-C IOSurface is toll-free bridged to IOSurfaceRef, but it isn't yet, see https://github.com/madsmtm/objc2/issues/693.

madsmtm avatar Jan 25 '25 20:01 madsmtm

For now, you can do something like:

use objc2_core_foundation::CFRetained;
use objc2::rc::Retained;
use objc2_io_surface::{IOSurfaceRef, IOSurface};

let iosurface = IOSurface::new();
let iosurface_ref: CFRetained<IOSurfaceRef> = unsafe { CFRetained::from_raw(NonNull::new(Retained::into_raw(iosurface)).unwrap().cast()) };

madsmtm avatar Jan 25 '25 20:01 madsmtm

Thanks for your reply.

I noticed there are methods (e.g, lockWithOptions_seed) that I can with the IOSurface, but I still require an IOSurfaceRef for the CVPixelBufferCreateWithIOSurface function. For now, I added my own function, until that is implemented.

I would also like to make suggestion for a function similar to NSDictionary's from_slice method, but for creating an IOSurface with properties.

Right now, I have to do the following:

let keys: &[&IOSurfacePropertyKey; 2] = &[
  IOSurfacePropertyKeyWidth,
  IOSurfacePropertyKeyHeight,
  // ...
];

let values: &[&AnyObject; 2] = &[
  &*NSNumber::new_u32(width),
  &*NSNumber::new_u32(height),
  // ...
];

let properties = NSDictionary::from_slices(keys, values);

IOSurface::initWithProperties(IOSurface::alloc(), &*properties).unwrap()

Maybe there could be a method to do the allocation?

ghost avatar Jan 26 '25 05:01 ghost

Adding more methods to CFDictionary is tracked in https://github.com/madsmtm/objc2/issues/692 (and I agree that it's a glaring omission).

Maybe there could be a method to do the allocation?

I'm not sure what you mean by this?

madsmtm avatar Jan 26 '25 13:01 madsmtm

Adding more methods to CFDictionary is tracked in #692 (and I agree that it's a glaring omission).

Maybe there could be a method to do the allocation?

I'm not sure what you mean by this?

Could there be a method added to IOSurface that takes in properties, allocates an IOSurface, initalizes an IOSurface with the properties, and returns it?

For example:

fn from_properties(
  properties: &NSDictionary<IOSurfacePropertyKey, AnyObject>,
) -> Option<Retained<Self>> {
  unsafe { Self::initWithProperties(Self::alloc(), properties) }
}

ghost avatar Jan 26 '25 16:01 ghost

Ah, I understand now.

I'm fairly reluctant to add such simple helpers, as it obscures what's actually happening (you now have to look at the method definition to know that it's calling the Objective-C method initWithProperties:).

Instead, I'd rather mark initWithProperties as safe, and then wait for arbitrary self types (which are fairly close to stabilization), then your code would become as simple as:

IOSurface::alloc().initWithProperties(properties)

madsmtm avatar Jan 26 '25 16:01 madsmtm

Ah, I understand now.

I'm fairly reluctant to add such simple helpers, as it obscures what's actually happening (you now have to look at the method definition to know that it's calling the Objective-C method initWithProperties:).

Instead, I'd rather mark initWithProperties as safe, and then wait for arbitrary self types (which are fairly close to stabilization), then your code would become as simple as:

IOSurface::alloc().initWithProperties(properties)

Ok, that seems better. Thank you

ghost avatar Jan 26 '25 17:01 ghost