1
\$\begingroup\$

I looked in the documentation, but I don't know how to get the texture ID.

void* texPtr = SixDegreesSDK_GetBackgroundTexture();
            if (texPtr != nil) {
                id<MTLTexture> mtlTexture = (__bridge id<MTLTexture>)texPtr;

                id<MTLDevice> device = [mtlTexture device];
                // !!! Not fond of creating a new command queue for every texture
                id<MTLCommandQueue> commandQueue = [device newCommandQueue];
                id<MTLCommandBuffer> commandBuffer = [commandQueue commandBuffer];
                id<MTLBlitCommandEncoder> blitEncoder = [commandBuffer blitCommandEncoder];

                NSUInteger textureWidth = mtlTexture.width;
                NSUInteger textureHeight = mtlTexture.height;
                NSUInteger rowbytes = mtlTexture.bufferBytesPerRow;
                MTLPixelFormat  pixFormat = mtlTexture.pixelFormat;
                CVPixelBufferRef _CVPixelBuffer = NULL;
                NSDictionary* cvBufferProperties = @{
                                                     (__bridge NSString*)kCVPixelBufferOpenGLCompatibilityKey : @YES,
                                                     (__bridge NSString*)kCVPixelBufferMetalCompatibilityKey : @YES,
                                                     };
                CVReturn cvret = CVPixelBufferCreate(kCFAllocatorDefault,
                                                     textureWidth, textureHeight,
                                                     kCVPixelFormatType_32RGBA,
                                                     (__bridge CFDictionaryRef)cvBufferProperties,
                                                     &_CVPixelBuffer);
                const IOSurfaceRef surface  = CVPixelBufferGetIOSurface(_CVPixelBuffer);             // available in ios11 sdk, ios4 runtime

                MTLTextureDescriptor* textureDescriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:pixFormat
                                                                                                             width:textureWidth
                                                                                                            height:textureHeight
                                                                                                         mipmapped:NO];
                id<MTLTexture> metalTexture = [device newTextureWithDescriptor:textureDescriptor
                                                                          ioSurface:surface
                                                                              plane:0];

                MTLRegion region = MTLRegionMake2D(0, 0, textureWidth, textureHeight);

                [blitEncoder copyFromTexture:mtlTexture
                                 sourceSlice:0
                                 sourceLevel:0
                                sourceOrigin:region.origin
                                  sourceSize:region.size
                                   toTexture:metalTexture
                            destinationSlice:0
                            destinationLevel:0
                           destinationOrigin:region.origin];

                [blitEncoder endEncoding];
                [commandBuffer commit];
                [self.mEAGLContext texImageIOSurface:surface target:GL_TEXTURE_2D internalFormat:GL_RGBA width:textureWidth height:textureHeight format:GL_RGBA type:GL_UNSIGNED_BYTE plane:0];
\$\endgroup\$
  • \$\begingroup\$ Why do you think there's a texture ID? If you had one, what would you do with it? \$\endgroup\$ – user1118321 Dec 8 '18 at 15:59
  • \$\begingroup\$ I'm sharing it with Ogre texture, that I need the texture ID and let ogre renders it.. \$\endgroup\$ – andre ahmed Dec 8 '18 at 16:00
  • \$\begingroup\$ You should have specified that in your question. You should also not crosspost the same question to different Stack Exchange sites. \$\endgroup\$ – user1118321 Dec 8 '18 at 16:13
  • \$\begingroup\$ I edited to include the additional detail. What's that code sample doing? Isn't it exactly what you're looking for? (The value seems to be of type id<MTLTexture>.) \$\endgroup\$ – Anko Dec 8 '18 at 19:46
  • \$\begingroup\$ @Anko I don't know how to call the blit command, and don't understand why I need to create an IOSurface for that purpose.. I already have the texture MTL from the SDK.. so why I need to create an IOSurface for it \$\endgroup\$ – andre ahmed Dec 8 '18 at 21:43
1
\$\begingroup\$

Ogre does not support Metal at this time. MTLTexture does not have any concept of a texture ID. If one library is returning a MTLTexture and the other expects an OpenGL texture ID, you'll need to copy the MTLTexture into an OpenGL texture created using IOSurfaces.

The documentation on IOSurfaces is a bit slim, unfortunately. Once you have an IOSurface, you can blit the MTLTexture into it using a MTLBlitCommandEncoder. You can then retrieve an OpenGL texture from the IOSurface via CGLTexImageIOSurface2D().

It might look something like this (not actually compiled, probably needs cleaning up):

NSDictionary* properties = @{ 
    IOSurfacePropertyKeyWidth : [NSNumber numberWithInt:textureWidth],
    IOSurfacePropertyKeyHeight : [NSNumber numberWithInt:textureHeight],
    IOSurfacePropertyKeyRowBytes : [NSNumber numberWithInt:rowbytes],
    IOSurfacePropertyKeyPixelFormat : [NSNumber numberWithInt:pixFormat],
    // ... etc. with any other relevant properties
};
IOSurface* ioSurface = [[IOSurface alloc] initWithProperties:properties];

Next you can get a MTLTexture from the IOSurface by doing this:

MTLTextureDescriptor* textureDescriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:pixFormat
                                                                                             width:textureWidth
                                                                                            height:textureHeight
                                                                                         mipmapped:NO];
id<MTLTexture> metalTexture = [metalDevice newTextureWithDescriptor:textureDescriptor
                                                          ioSurface:ioSurface
                                                              plane:0];

Now, I've never personally used a MTLBlitEncoder, so I don't know the gory details, but it looks like once you've created one, you can call -[MTLBlitCommandEncoder copyFromTexture:sourceSlice:sourceLevel:sourceOrigin:sourceSize:toTexture:destinationSlice:destinationLevel:destinationOrigin:]. I believe once that blit command has been completed, the IOSurface will contain the texture data. Apple has some sample code showing how to use them.

From there you can do:

GLint glTextureID = CGTexImageIOSurface2D(glContext, GL_TEXTURE_RECTANGLE_ARB, GL_RGBA, textureWidth, textureHeight, GL_BRGA, GL_UNSIGNED_INT_8_8_8_8_REV, ioSurface, 0);

(That assumes you want an 8-bit per channel RGBA texture and that the MTLTexture was in that format.)

Here's some additional sample code for sharing between Metal and OpenGL.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.