I am trying to migrate my Opengl application to Metal, and I am using CAMetalLayer
for the Metal implementation.
I have set the following properties on my inherited NSView
class object:
self.layerContentsRedrawPolicy = NSViewLayerContentsRedrawDuringViewResize;
[self setWantsLayer:YES];
I have checked other answers on SO, like NSView subclass - drawRect: not called
So, I tried assigning the delegate as suggested in answers above, something like this
[self.layer setDelegate:self];
and I get the following compilation error:
Cannot initialize a parameter of type 'id<CALayerDelegate> _Nullable' with an lvalue of type 'MyNSView *'
Moreover, I also see the documentation for setting up layer objects at https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/CoreAnimation_guide/SettingUpLayerObjects/SettingUpLayerObjects.html, which states this:
For layer-backed views with custom content, you should continue to override the view’s methods to do your drawing. A layer-backed view automatically makes itself the delegate of its layer and implements the needed delegate methods, and you should not change that configuration. Instead, you should implement your view’s drawRect: method to draw your content.
So, according to this, I don't even have to set the delegate in my case and I am already implementing the drawRect
function in MyNSView
. Still it doesn't get called.
Is there anything more that needs to be done?
Thanks!
Edit:
So, I fixed the compilation error by making my layer follow the protocol CALayerDelegate
, but still I don't get any calls to drawLayer
or 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;
}
init function
self.layerContentsRedrawPolicy = NSViewLayerContentsRedrawDuringViewResize;
[self setWantsLayer:YES];
[self.layer setDelegate:self];
Draw functions
- (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];
}
I have implemented all the draw functions to check if any of them get hit, but I don't receive a call on any of these functions.
For drawing content to the NSView, I draw to offscreen resources and the get the drawable
from CALayer of NSView and call presentDrawable
before committing on the commandBuffer
.
MTKView
? How did you arrange to useCAMetalLayer
for the layer? Did you override-makeBackingLayer
? If so, show that method and any place else you try to configure the layer. – Ken ThomasesmakeBackingLayer
to generate the layer. I'll update the question with relevant code snippets. – user007NSView
do you override? What other properties do you set on it? For example, do you override-wantsUpdateLayer
to return true? – Ken Thomases-wantsUpdateLayer
to return true, and then overrideUpdateLayer
. But, apparently that doesn't get called. I also tried changing thelayerContentsRedrawPolicy
toNSViewLayerContentsRedrawOnSetNeedsDisplay
and calling[nsView setNeedsDisplay:YES]
, after I callcommit
on the command buffer, but that doesn't seem to trigger drawing either. – user007