我正在尝试将我的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
来解决了编译错误,但是仍然没有收到对drawLayer
或drawRect
的任何调用。
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
。
答案 0 :(得分:0)
由于这里没有太多可以调试的地方,所以我可以按照执行指令的顺序进行调试。事实证明,您呼叫的顺序:
[self setWantsLayer:YES];
self.layerContentsRedrawPolicy = NSViewLayerContentsRedrawDuringViewResize;
是造成此问题的原因。交换这两个语句后,我开始收到对我的displayLayer
函数的调用。我仍然不知道为什么drawRect
不会被支持层的NSView调用。
发布此消息以防万一此交换也解决了其他人的问题。