将uintptr_t转换为id< MTLTexture> [英] Convert uintptr_t to id<MTLTexture>

查看:434
本文介绍了将uintptr_t转换为id< MTLTexture>的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建简单的iOS插件,可以将纹理绘制到统一的Texture2D。我已经通过CreateExternalTexture()和UpdateExternalTexture()完成了它,它工作正常,但我很好奇我是否可以直接从iOS端填充Unity纹理。这是我的iOS插件代码:

I wanted to create simple iOS plugin which can draw the texture to unity Texture2D. I've done it by CreateExternalTexture() and UpdateExternalTexture(), it's working fine, but I'm curious if I can actually fill the Unity texture straight from iOS side. Here's my code of iOS plugin:

//
//  testTexturePlugin.m
//  Unity-iPhone
//
//  Created by user on 18/01/16.
//
//

#import <OpenGLES/ES2/gl.h>
#import <OpenGLES/ES2/glext.h>
#import <UIKit/UIKit.h>

#include "UnityMetalSupport.h"

#include <stdlib.h>
#include <stdint.h>

static UIImage* LoadImage()
{
    NSString* imageName = @"logo"; //[NSString stringWithUTF8String: filename];
    NSString* imagePath = [[NSBundle mainBundle] pathForResource: imageName ofType: @"png"];

    return [UIImage imageWithContentsOfFile: imagePath];
}

// you need to free this pointer
static void* LoadDataFromImage(UIImage* image)
{
    CGImageRef imageData    = image.CGImage;
    unsigned   imageW       = CGImageGetWidth(imageData);
    unsigned   imageH       = CGImageGetHeight(imageData);

    // for the sake of the sample we enforce 128x128 textures
    //assert(imageW == 128 && imageH == 128);

    void* textureData = ::malloc(imageW * imageH * 4);
    ::memset(textureData, 0x00, imageW * imageH * 4);

    CGContextRef textureContext = CGBitmapContextCreate(textureData, imageW, imageH, 8, imageW * 4, CGImageGetColorSpace(imageData), kCGImageAlphaPremultipliedLast);
    CGContextSetBlendMode(textureContext, kCGBlendModeCopy);
    CGContextDrawImage(textureContext, CGRectMake(0, 0, imageW, imageH), imageData);
    CGContextRelease(textureContext);

    return textureData;
}

static void CreateMetalTexture(uintptr_t texRef, void* data, unsigned w, unsigned h)
{
#if defined(__IPHONE_8_0) && !TARGET_IPHONE_SIMULATOR

    NSLog(@"texRef iOS = %lu", texRef);

    id<MTLTexture> tex = (id<MTLTexture>)(size_t)texRef;

    MTLRegion r = MTLRegionMake3D(0, 0, 0, w, h, 1);
    [tex replaceRegion: r mipmapLevel: 0 withBytes: data bytesPerRow: w * 4];

#else

#endif
}

extern "C" void FillUnityTexture(uintptr_t texRef)
{
    UIImage*    image       = LoadImage();
    void*       textureData = LoadDataFromImage(image);

    if (UnitySelectedRenderingAPI() == apiMetal)
        CreateMetalTexture(texRef, textureData, image.size.width, image.size.height);

    ::free(textureData);
}

这里是Unity代码:

And here's the Unity code:

using UnityEngine;
using System;
using System.Collections;
using System.Runtime.InteropServices;

public class TextureHandler : MonoBehaviour {

    [SerializeField]
    private Renderer _mesh;

    private Texture2D _meshTexture;

    [DllImport("__Internal")]
    private static extern void FillUnityTexture(IntPtr texRef);

    void Start () {

        _meshTexture = new Texture2D(200, 200, TextureFormat.ARGB32, false);
        _mesh.material.SetTextureScale ("_MainTex", new Vector2 (-1, -1));
        _mesh.material.mainTexture = _meshTexture;

        IntPtr texPtr = _meshTexture.GetNativeTexturePtr();
        Debug.Log("texPtr Unity = " + texPtr);

        FillUnityTexture(texPtr);
    }
}

Unity纹理上的指针传递给iOS插件没错,我查了一下。但我在iOS插件的这一行崩溃:

Pointer on the Unity texture is passing to the iOS plugin correctly, I checked. But I have the crash in this line on iOS plugin:

[tex replaceRegion: r mipmapLevel: 0 withBytes: data bytesPerRow: w * 4];

我很确定我有这个问题,因为Unity纹理上的指针转换错误(uintptr_t)到金属纹理(id)。

and I'm pretty sure that I have this problem because of wrong converting of the pointer on Unity texture (uintptr_t) to metal texture (id).

所以我的问题是 - 如何正确地将纹理指针转换为MTLTexture?

So my question is - how can I convert pointer to the texture to MTLTexture properly?

推荐答案

我想你应该读一下ARC。

I guess you should read about ARC.

您可以使用 __ bridge_retained 来转移新创建的 id< MTLTexture> <的所有权/ code>对象 uintptr_t 代码。如果要将 uintptr_t 转换回 id< MTLTexture> ,请使用 __ bridge 如果你不想转回所有权,或者当你这样做时使用 __ bridge_transfer

You can use __bridge_retained to transfer the ownership of newly created id<MTLTexture> object to uintptr_t code. When you want to convert the uintptr_t back to id<MTLTexture> use __bridge if you don't want to transfer the ownership back or use __bridge_transfer when you do.

这篇关于将uintptr_t转换为id&lt; MTLTexture&gt;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆