what is layer in core animation - cocoa

In core animation or in App kit When we say layer-backed view or simply add a layer in the view,then actually what we mean by the layer.

A simple Google search:
The CALayer is the canvas upon which everything in Core Animation is painted. When you define movement, color changes, image effects, and so on, those are applied to CALayer objects. From a code perspective, CALayers are a lightweight representation similar to an NSView. In fact, NSView objects can be manipulated via their CALayer. This is referred to as being layer-backed.

A CALayer is an object which manages and draws upon a GL surface, and can manipulate that surface's location in three dimensions, without needing to redraw its contents.

Related

What is the correct way to optimise scrolling performance of NSImageView and NSView

I need to improve the scrolling performance of a view for annotating on top of an image.
Currently I have the following:
- annotationView (custom NSView)
- imageView (NSImageView)
- contentView (custom NSView)
- clipView (NSClipView)
- scrollView (NScrollView)
The images are quite large PDFs and PNGs and scrolling is poor unless I make the imageView layer backed, which I am just doing in Interface Builder. Scrolling is then pretty smooth.
However the PNG images override everything on top of the imageView, whereas the PDF images remain correctly in the background.
Why is this and how can I fix that?
To get even better performance I would also like to make the annotationView layer backed as well but if I do that the entire view becomes black - with the exception of the annotations being draw on the annotationView. How can I make this layer backed view transparent but still allow for the shapes to be draw on it. It seems I can make it transparent but then everything becomes transparent, including the drawn shapes.
Is there a better way to achieve this? The annotations are simply shapes and text that need to be placed at specific positions over the image which I am currently just drawing in response to mouse positions.
The short answer is to use layer backed views and use CGContext for drawing and not the simpler NSView drawing APIs.
By default macOS does not use GPU based graphics, unlike iOS.
macOS provides a high level API that uses the CPU rather than the GPU for graphics operations.
So in my case I switched everything to layer backed NSViews - you can set this in Interface Builder or simply add 'wantsLayer = true' in the NSView initialisation code (init()).
Avoid using NSImageView, instead use a layer backed view and set the layer.content = NSIMage, you may have to also set the layers background colour or you might get some areas of the background not being cleared when scrolling.
This works for me - I have big PDF images in the background - building layouts and a layer backed view on top of that for placing annotations.
Scrolling around is now buttery smooth. Images seem to load instantly.
For the most part its pretty easy - just set up right from the start and save yourself a lot of headaches.

Can I force CALayer to use setNeedsDisplayInRect: rather than setNeedsDisplay for custom property

I have custom property and I override +needsDisplayForKey: to return YES for this property.
My -drawInContext: method is pretty complex while the rectangle affected by my custom property is pretty small. I'd like to optimize it.
The solution I'm thinking about is to implement custom setter where I'll explicitly mark affected rectangle to display. One thing I'm not sure about is that such implementation would be equal to original one and will handle implicit animation. (rdar://11008555)
Will it be equal or there is a better solution? (Target platforms are 10.6+)
There is no way to draw on a portion of a CALayer. Core Animation layers are implemented as textures on OpenGL surfaces. When you implement custom drawing, what essentially happens is that your drawing commands are used to build a bitmap and then that bitmap is set as the texture for the CALayer's OpenGL surface.
What you could do is manage a bitmap cache (using an NSImage or CGContext) for the layer yourself. That way you could just modify the part of the bitmap that requires redrawing, then draw the image to the layer using setContents:.

CAOpenGLLayer displaying remote Context

I have a sub-classed CAOpenGLLayer class which overrides drawInCGLContext there I draw a rectangle with OpenGL. The CAOpenGLLayer is added to a CALayer and shown.
So when I would like to draw something I would need to do it in drawInCGLContext with this architecture.
What I would like to have is a sort of context used by an other class to draw, animate or render to but will be displayed every time drawInCGLContext occurs.
So basically the only thing my subclass should do is display a remote (OpenGL)context, what's the best way to achieve this? Or should I consider a different approach?
*Not using a CALayer is not an option.
Have you considered using a frame buffer object (FBO)? You can create one which is backed by a texture. Your "remote" drawing class could draw into the FBO, which will cause the drawing to go to the texture that backs it. You can then use that texture elsewhere, like blitting it to the screen in your CAOpenGLLayer subclass. See this link for details of how to use an FBO.

Core Animation architecture

From the documentation it appears that core animation layer is above OpenGL and Quartz2D. i.e.
executing a core animation command should produce a sequence of Quartz2D and OpenGL commands Am I right?
In interface builder, under the View Effects tab, we can set the core animation layer. What happens internally there?When we tick Context View option, contents on screen (buttons, scrolls etc) are not drawn using main context or currentContext(view), but new Bitmap Context is created for them. What is happening under the hood there?
Can somebody please explain me relationship between CoreAnimation Layer and Quartz2d/OpenGL?
Core Animation layers are essentially high-level abstractions of OpenGL surfaces. They are stored and manipulated by the GPU and so manipulation of the layers is extremely fast. CALayer objects by themselves are very lightweight and have no event handling.
Layer-backed NSView objects (which is what you get if you enable the checkboxes in Interface Builder) are views that draw their content into a Core Animation layer, again stored in the GPU's memory and with the same performance advantages as plain CALayer objects, but with all the functionality of a normal NSView.
What happens is that the view's content is rendered (via Quartz) to its backing layer (essentially an OpenGL texture). The view then only needs to draw again if the content of the layer changes.
Changes in position, scale, rotation etc of the view's layer do not require the view's content be redrawn. This means that most of the time the CPU does not have to get involved in constantly redrawing the view.

drawRect makes scrolling slow in UIScrollView

I've got a UIScrollView with a (custom) UIView inside of it.
In my scrollViewDidScroll-method I'm calling
[myCustomView setNeedsDisplay];
This makes the scrolling noticeably slower, if I'm implementing the drawRect: method in my custom UIView - even if it's completely empty.
As soon as I delete the drawRect: method, it's smooth again.
I have absolutely no idea, why... anyone of you?
I hate drawrect too
"It's because of the way hardware-accellerated animation works in Cocoa.
If you don't have a custom drawRect method, the system caches the pixels for your view in video memory. When it needs to redraw them, it just blits the pixels onto the screen.
If you have a custom drawRect method, the system instead has to call your drawRect method to render the pixels in main memory, then copy those pixels into video memory, THEN draw the pixels to the screen for each an every frame. The docs say to avoid drawRect if you can.
I think main memory and video memory are shared on most/all iOS devices, but the system still has a lot more work to do when you implement a drawRect method for a view.
You would probably be better served to use an OpenGL layer and render to that with OpenGL calls, since OpenGL talks directly with the display hardware."
link to that quote: http://www.iphonedevsdk.com/forum/iphone-sdk-development/80637-drawrect-makes-scrolling-slow-uiscrollview.html

Resources