Nsgraphicscontext становится null после установки cametallayer

Я пытаюсь переместить свое приложение на основе NSView, чтобы начать использовать GPU с Metal. Итак, я добавил CAMetalLayer следующим образом:

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

И сделайте задний слой вот так:

- (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];
    return backingLayer;
}

Я пишу весь этот код в моем классе CustomNSView, унаследованном от класса CustomParentNSView, который использует NSGraphicsContext для рисования некоторых вещей на экране. Теперь, когда я перемещаю CustomNSView в NSView с поддержкой уровня, когда я пытаюсь вызвать:

[NSGraphicsContext currentContext]

Это возвращает NULL.

  1. Должно ли это быть NULL для NSView с поддержкой уровня?

Я также попытался выяснить, где в предыдущей реализации генерировался NSGraphicsContext, и оказалось, что мое приложение нигде не устанавливало его. NSView сам настраивал NSGraphicsContext изнутри displayIfNeeded, прежде чем вызывать drawRect.

  1. Могу ли я по-прежнему использовать NSGraphicsContext для рендеринга в NSView, даже если он поддерживается слоем?

Спасибо!

Когда (в каком контексте) вы звоните в [NSGraphicsContext currentContext]? К чему вы ожидаете привлечь этот контекст? Если вы хотите рисовать с помощью NSGraphicsContext, не используйте металлический слой. Просто используйте обычный слой.

Ken Thomases 01.11.2018 15:31

@KenThomases Причина, по которой я использую Metal Layer, заключается в том, что я сначала хочу сделать какой-нибудь рисунок с помощью графического процессора, а затем нарисовать несколько конструкций Какао поверх рисунка, сделанного с помощью графического процессора. Раньше я использовал OpenGL, поэтому никогда не сталкивался с этой проблемой. Я ожидаю, что контекст будет оттянут к тому же NSView, к которому обратился графический процессор.

user007 12.11.2018 09:05

Это не сработает. Металлические слои и рисунок Какао исключают друг друга. Вы должны добавить подпредставления или подпредставления к виду, используя слой «Металл». Эти подпредставления могут рисовать другие элементы, которые появляются поверх содержимого, нарисованного металлом.

Ken Thomases 12.11.2018 17:32

@KenThomases есть ли документация, которая более подробно объясняет это исключительное поведение ?! Спасибо за информацию :-)

user007 12.11.2018 20:07

Что ж, документы для `CAMetalLayer говорит: «Чтобы визуализировать содержимое слоя, используйте метод nextDrawable для получения текстуры, а затем используйте ее в качестве цели визуализации в конвейере рендеринга Metal». То есть нет другого способа визуализировать содержимое такого слоя.

Ken Thomases 12.11.2018 20:48

@KenThomases Я попытался заменить металлический слой на CAOpenGLLayer, просто чтобы проверить, получаю ли я там контекст NSGraphicsContext, оказалось, что currentContext - это также NULL с CAOpenGLLayer. Итак, мы говорим, что рисование NSGraphicsContext невозможно с любым слоем?

user007 13.11.2018 08:34

Кроме того, в CALayerDelegate я вижу метод - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx, хотя в настоящее время я не могу вызвать эту функцию, должна ли эта функция также использоваться с CAMetalLayer?

user007 13.11.2018 08:43

И OpenGL, и Metal особенные. Им нужен необычный доступ к кадровому буферу. Они несовместимы с обычным рисунком Какао. Другие типы слоев работают с рисованием какао.

Ken Thomases 13.11.2018 15:59

Еще одна странная вещь, которую я заметил, заключалась в том, что getRectsBeingDrawn:count теперь не возвращает никаких rects, поскольку я получаю вызов displayLayer, а не вызов drawRect`. Устанавливаются ли dirtyRects только при вызове setNeedsDisplayInRect:updatedRect или есть какой-либо другой способ установить грязные прямоугольники, которые различаются по слоям? @KenThomases

user007 21.11.2018 08:19

Да, грязные прямоугольники устанавливаются только методами -setNeedsDisplay.... Кроме того, с помощью слоя Metal вы не можете рисовать только части. Вы должны все это перерисовать. Вы рисуете другую текстуру, а затем заменяете экранный контент этой текстурой. Если вам не удастся нарисовать (или хотя бы очистить) некоторые части текстуры, они будут просто мусором.

Ken Thomases 21.11.2018 16:56

@KenThomases Я пробовал использовать setNeedsDisplayInRect и getRectsBeingDrawn из NSView после того, как я сделал свой NSView поддерживаемым слоем, и getRectsBeingDrawn имеет тенденцию все время возвращать пустые прямоугольники. Это происходит потому, что мы должны рисовать все, а не часть представления?

user007 25.11.2018 13:41
0
11
196
0

Другие вопросы по теме