使用NSView

时间:2018-10-29 09:33:55

标签: macos calayer nsview metal

我正在尝试将我的Opengl应用程序迁移到Metal,并且我在Metal实现中使用CAMetalLayer。 我在继承的NSView类对象上设置了以下属性:

self.layerContentsRedrawPolicy = NSViewLayerContentsRedrawDuringViewResize;
[self setWantsLayer:YES];

我已经检查了SO上的其他答案,例如NSView subclass - drawRect: not called

所以,我尝试按照上述答案中的建议分配代表,就像这样

[self.layer setDelegate:self];

,我收到以下编译错误:

Cannot initialize a parameter of type 'id<CALayerDelegate> _Nullable' with an lvalue of type 'MyNSView *'

此外,我还可以在https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/CoreAnimation_guide/SettingUpLayerObjects/SettingUpLayerObjects.html上看到用于设置图层对象的文档,其中指出:

  

对于具有自定义内容的支持图层的视图,您应继续   覆盖视图的方法来绘制图形。层支持的视图   自动使自己成为其层的委托并实施   所需的委托方法,您不应更改该方法   组态。相反,您应该实现视图的drawRect:   绘制内容的方法。

因此,据此,我什至不必设置委托,我已经在drawRect中实现了MyNSView函数。仍然没有被调用。

还有什么需要做的吗?

谢谢!

修改: 因此,我通过使图层遵循协议CALayerDelegate来解决了编译错误,但是仍然没有收到对drawLayerdrawRect的任何调用。

makeBackingLayer

- (CALayer*)makeBackingLayer
{
    id <MTLDevice> device = MTLCreateSystemDefaultDevice();
    CAMetalLayer *backingLayer   = [CAMetalLayer layer];
    backingLayer.opaque          = YES;
    backingLayer.device          = device;
    backingLayer.pixelFormat     = MTLPixelFormatBGRA8Unorm;
    backingLayer.framebufferOnly = YES;

//    [backingLayer setDelegate:self]; //Tried setting the delegate 
                                       //here as well

    return backingLayer;
}

初始化函数

self.layerContentsRedrawPolicy = NSViewLayerContentsRedrawDuringViewResize;
[self setWantsLayer:YES];
[self.layer setDelegate:self];

绘图功能

- (void)displayLayer:(CALayer *)layer
{
    [self drawRect:self.bounds];
}

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx {
    [self drawRect:self.bounds];
}

-(void) drawRect: (NSRect) dirtyRect
{
    [super drawRect:dirtyRect];
}

我已经实现了所有绘制功能,以检查是否有任何绘制功能被击中,但是我没有收到这些功能中的任何调用。

要向NSView绘制内容,我需要绘制屏幕外资源并从NSView的CALayer获取drawable,并在提交presentDrawable之前调用commandBuffer

1 个答案:

答案 0 :(得分:0)

由于这里没有太多可以调试的地方,所以我可以按照执行指令的顺序进行调试。事实证明,您呼叫的顺序:

[self setWantsLayer:YES];
self.layerContentsRedrawPolicy = NSViewLayerContentsRedrawDuringViewResize;

是造成此问题的原因。交换这两个语句后,我开始收到对我的displayLayer函数的调用。我仍然不知道为什么drawRect不会被支持层的NSView调用。

发布此消息以防万一此交换也解决了其他人的问题。