drawRect не вызывается для отрисовки на основе слоя с NSView - PullRequest
0 голосов
/ 29 октября 2018

Я пытаюсь перенести мое приложение Opengl в Metal, и я использую CAMetalLayer для реализации Metal. Я установил следующие свойства для моего унаследованного NSView объекта класса:

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

Я проверил другие ответы на SO, например, Подкласс NSView - drawRect: не вызвано

Итак, я попытался назначить делегата, как предложено в ответах выше, что-то вроде этого

[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 я рисую за пределами экрана и получаю drawable от CALayer NSView и вызываю presentDrawable перед фиксацией на commandBuffer.

1 Ответ

0 голосов
/ 28 ноября 2018

Так как здесь было не так много, что я мог отладить, чтобы найти, где была введена ошибка, поэтому я начал играть с порядком, в котором выполнялись инструкции. И, как выясняется, порядок, в котором вы звоните:

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

вызывало проблему. Поменяв местами эти два оператора, я начал получать вызов моей функции displayLayer. Я до сих пор не могу понять, почему drawRect не вызывается для NSView со слоями.

Размещение этого сообщения на случай, если этот обмен исправит проблему и для кого-то еще.

...