-[CALayer setNeedsDisplayInRect:] causes the whole layer to be redrawn - ios

I'm subclassing CALayer to provide my own drawing in method. For optimization I call -[MyLayer setNeedsDisplayInRect:] instead of -[MyLayer setNeedsDisplay]. In the drawing method I get the rect which should be redrawn via CGContextGetClipBoundingBox().
If I use this layer as the base layer of an UIView every thing works as expected. The problem arises, as soon as I use my custom layer as a sublayer of an other CALayer. Than CGContextGetClipBoundingBox() always returns the rect of the bounds of that layer.
Any ideas?
[EDIT]
It seems, that there is no guaranty, that the content of the CALayer is cached and only the dirty part gets redrawn. I did a small test and stored the rect that needs display as a separate property. The result was, that only this part was visible on the screen.
I'll now render to an image context and keep that image as a cache. In the draw method I'll only display the cached image.

Apple's documentation is unfortunately conflicting as the docs on -setNeedsDisplayInRect do not indicate whether the method works in practice. Based on my own experience, this technote sets it straight:
Note that, because of the way that iPhone/iPod touch/iPad updates its screen, the entire view will be redrawn if you call -setNeedsDisplayInRect: or -setNeedsDisplay:.
That being said, there are a number of things you can look into if you think that you are hitting a wall due to redundant drawing.
If drawing images, the biggest performance improvement you can make is to use images of the same dimensions at which you draw. If they're not, try to cache your image by rendering it to some offscreen bitmap context and bring it back later on.
Check out the shouldRasterize property on CALayer. This can be a godsend if you are trying to manipulate a layer whose sublayers potentially constitute a complex layer hierarchy. Be sure to check out how you're doing in Instruments by ticking the Color Hits Green and Misses Red box in the Core Animation instrument. If you see a lot of red, chances are using shouldRasterize is hurting more than it's helping.
Even better than shouldRasterize is to flatten your layer hierarchy, as then you can avoid the extra overhead that shouldRasterize incurs when flattening your layer hierarchy real time. Of course this is not always possible, but don't be afraid to try :)
If you're drawing images, try experimenting with your blending mode. If you happen to be drawing opaque images, there's no need to be using normal source over methods (which use both read/write bandwidth). Try kCGBlendModeCopy, which allows you to eliminate read bandwidth overhead.
Check out CGLayerRef, which allows you to cache Core Graphics output across various calls to your drawing methods. My experience is that, unless you're doing some hardcore pixel pushing, that this ends up being more costly than just redrawing. See this for an interesting read.
Above all, Instruments is your friend. Check out a couple videos from past WWDCs (2012, 2011, and 2010); they all have great info about how to fine-tune performance.
Please feel free to ask any further questions if something I've said makes little sense.

Related

For performance, is it better to hide or remove CALayers on iOS?

This is related to the following question: How to improve performance of CALayer animations?
I currently have a view that can have several hundred CALayers. I know having many CALayers will cause performance degradation limited by the processor, but I wanted to see if someone out there has experimented with several of the following methods and can provide guidance.
To better give you an idea of what I'm trying to do, imagine that I have a dot drawn on my layer. When I zoom in, I want the dot to become a star. When I zoom out, I want the star to go back to being a dot. Now imagine that I have hundreds of these dots.
Redrawing single layer vs Multiple pre-drawn layers
Instead of having 1 single layer where I redraw when the zoom changes, I've been experimenting with having 2 separate layers with it pre-drawn and when the zoom changes, I just hide the one and show the other.
[layer configureWithZoom:zoom];
[layer setNeedsDisplay];
vs
layer1.hidden = (zoom == DEFAULT_ZOOM);
layer2.hidden = (zoom != DEFAULT_ZOOM);
I understand that having a bunch of layers will increase my memory footprint and if I had 50 layers before, I now have 100 layers. But in terms of performance, will this help?
Hiding vs Removing
Given the above, I now have layers that aren't needed at all times. Is it better to hide those layers or remove them?
Setting layer.hidden = YES vs [layer removeFromSuperlayer] when I want it to go away.
Setting layer.hidden = NO vs [superlayer addSublayer:layer] when I want it to come back.
If I hide a layer, but animate the superlayer, is there a performance hit during animations because a sublayer is hidden instead of removed? How does that performance hit compare to adding/removing the sublayers?
Parent layer vs Direct layering
One of the problems with having separate layers is now that I need code to manage them as a unit. Previously changing the layer's position was as simple as layer.position = newCoordinates;. Now I would need to do:
layer1.position = newCoordinates1;
layer2.position = newCoordinates2;
I decided to simplify this and create a parent layer and add both layer1 and layer2 to it. My main layer can now just manipulate the parent layer instead of the individual layers. My parent layer would also handle the logic of which of the 2 layers to show or hide.
However, this now introduces a 3rd layer (at the start we had 1, now we have 3). I'm curious if a layer that has no actual drawing besides its sublayers has any impact on performance. Basically does an empty layer having 2 sublayers have a performance hit compared to having those 2 sublayers added directly to the superlayer.
Any guidance would be appreciated.
Redrawing single layer vs Multiple pre-drawn layers
It depends on how you draw here. I assume you're using drawInContext of a CALayer with some custom code? If yes, it will definitely help if the call of this drawing code is not necessary every time you change your zoom level.
The memory footprint from having double the layers as before really shouldn't hurt you here.
Hiding vs Removing
I'm working with a similar setup to yours for quite a time now and have hundreds (thousands) of CALayers at the same time on the screen. From my experiments I found out that there is a huge performance hit coming from hidden layers. For me it was always best to completely remove and re-add them later.
This is really really frustrating as it's nowhere said in the docs and usually you'd never come to the idea that a hidden layer costs (a lot of) performance.
Parent layer vs Direct layering
About your third question: I'm not 100 percent sure if your empty layer that functions as a parent for your two layers is a performance hit, but I would guess that it is (from my experience every extra layer that CA has to handle causes it to run slower).
The question is: Are you able to do it without a layer in between? Is there a certain order your layers have to be in?
You could write a custom class, subclassing NSObject, that takes your two layers, and that manages everything about them (changing position, removing and adding from superlayer etc). This way you would have an easy interface but no extra layer on screen.
If that is not an option, you could try to use CATransformLayer as a compositiing layer for your two layers. This layer doesn't do anything but be a layer for compositing (and it can be used for 3D). Maybe this one takes less performance than a "normal" CALayer in your scenario.
General performance adivce
If possible, do not use drawInContext to draw your layers. If you can, use CAShapeLayer for your stars, it is much faster and has nice anti-aliasing.
Keep a look at the CPU-meter built into Xcode (not the profiler). There you see the CPU-usage of "other processes". In CA-Apps which need a lot of performance, this "other processes" section is basically the CA-RenderServer (backboardd). Here you can see how much CPU your drawing costs right now.
Otherwise if you're concerned about your memory usage, check out the allocations profiler (this time the real profiler) and check how much memory the different versions of your code (50 vs. 100 layers) take.

How does drawRect and CGGraphicsContext work?

I am working with some stuff in Core Graphic's and I am looking for some additional clarification regarding a couple of topics.
drawRect:
I have an understanding of this and know it is where all of the drawing aspect's of a UIView goes, but am just unclear as to what is happening behind the scene's. What happen's when I create a UIView and fill out drawRect then set another object's UIView to be that custom view? When is drawRect being called?
CGGraphicsContext:
I know what the purpose of this is and understand the concept, but I can't see exactly how it is working.
For example:
CGContextSaveGState(context);
CGContextAddRect(context, rect);
CGContextClip(context);
CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0);
CGContextRestoreGState(context);
The code above is in my app and work's correctly. The thing that confuses me is how it is working. The idea of saving/restoring a context makes sense, but it appears like I am literally saving a context, using that exact same context to make change's, then restoring the same context once again. It just seem's like I am saving a context and then writing on top of that context, only to restore it. How is it getting saved to a point where when you restore it, it is a different instance of the context than what was just used to make changes? You use the same reference of the variable context in every situation.
Lastly I would appreciate any resource's for practice project's or example's on using Core Graphics. I am looking to improve my skill in the matter since I obviously don't have much at the current time.
What happen's when I create a UIView and fill out drawRect then set another object's UIView to be that custom view? When is drawRect being called?
Adding a view to a 'live' view graph marks the view's frame as in need of display. The main run loop then creates and coalesces invalid rects and soon returns to invoke drawing. It does not draw immediately upon invalidation. This is a good thing because resizing, for example, would result in significant overdrawing -- redundant work which would kill many apps' drawing performance. When drawing, a context is created to render to -- which ultimately outputs to its destination.
Graphics Contexts are abstractions which are free to work optimally for their destination -- a destination could be a device/screen, bitmap, PDF, etc.. However, a context handle (CGContextRef) itself refers to a destination and holds a set of parameters regarding its state (these parameters are all documented here). These parameter sets operate like stacks: Push = CGContextSaveGState, Pop = CGContextRestoreGState. Although the context pointer isn't changing, the stack of parameter sets is changing.
As far as resources, see Programming with Quartz. It's 8 years old now, and was originally written for OS X -- but that ultimately doesn't matter a whole lot because the fundamentals of the drawing system and APIs really haven't evolved significantly since then -- And that is what you intend to focus on. The APIs have been extended, so it would be good to review which APIs were introduced since 10.4 and see what problems they solve, but it's secretly a good thing for you because it helps maintain focus on the fundamental operation of the drawing system. Note that some functionalities were excluded from iOS (e.g. often due to floating point performance and memory constraints, I figure), so every example may not be usable on iOS, but I know of no better guide.
Tip: Your drawing code can be easily reused on OS X and iOS if you use Quartz rather than AppKit/UIKit. Plus, the Quartz APIs have a lower update frequency (i.e. the APIs tend to be longer lived).
-drawRect: gets called at some point after you (e.g. your view controller) have called the view's method -setNeedsDisplay or -setNeedsDisplayInRect:.
Saving the graphics state pushes the current graphics state onto a stack. The graphics state contains fill and stroke setting, the current transformation matrix etc. See Apple's documentation for details.
The Quartz 2D Programming Guide doesn't contain many examples but is otherwise quite thorough.
With quartz/ core graphics the context is literally a set of current parameters to use to draw the next drawing command on top of the previous drawing.
Saving the state let's you save all those parameters for later drawing commands that will reuse them.
Then you can set up a different set of parameters for some drawing commands.
Restoring the state gets you back to where you were.
I recommend the book
Programming with Quartz
2D and PDF Graphics in Mac OS X
Though a bit dated in some ways, it will really teach you how quartz / core graphics really flows.
Ok this is a very very deep topic to talk about. I'll explain a few things to my understanding & try to keep it simple. If I'm mistaken I hope someone can correct me out.
first of all there is concept of onscreen drawing and offscreen drawing. On screen drawing is taken place in GPU where offscreen drawing is taken place in CPU to draw things and then its given to GPU to display on the screen. Thats where drawRect() comes in to place (drawrect is only 1 way of doing the offscreen drawings btw). This is why in the drawRect template method (you will see when you make a subclass of UIView) there is a comment by Apple telling
"Only override drawRect: if you perform custom drawing. An empty implementation adversely affects performance during animation"
The reason is whenever there is drawRect method, the iOS would have to ask the CPU to takecare of the drawing which takes place in drawRect and hand it over to the GPU. (Dont get the idea that this is a bad thing :) ). So this is what happens in drawRect in an abstract level.
Now to the question of why save & restore same context over and over. Have you tried to read the description of the method in apple doc about save/restore context ? If you have, you'd notice that it shows all the graphical states which would be affected by this. Ok how does this help ?
Consider something like this. Lets say you're drawing on a rectangle where you have to limit this next part of the drawing on the right half of it and use shadows and antialiasing, etc. You can save your context before drawing the right side and set whatever properties you want and once you finish that, you can simply restore the context and you can continue with all the settings you had before without explicitly setting them again. It's a good practice as well when you do complex drawings as otherwise it would have weird outcomes you might not expect. something like this below
- drawRect()
{
CGContextSaveGState(context);
drawLeftPart(); // - 1
drawRightPart(); // - 2
someOtherDrawing(); // - 3
CGContextRestoreGState(context);
}
- drawLeftPart()
{
CGContextSaveGState(context);
// do your drawing
CGContextRestoreGState(context);
}
- drawRightPart()
{
CGContextSaveGState(context);
// do your drawing
CGContextRestoreGState(context);
}
- someOtherDrawing()
{
CGContextSaveGState(context);
// do your drawing
CGContextRestoreGState(context);
}
Now what ever properties you set in part 1 wont affect drawing of part 2 & 3 so forth.
Hope this helps,

The relationship between CoreGraphics, UIViews and CALayers

I always used CoreGraphics and CoreAnimation, I understand how each of them works on their own, but not those edge cases when one have to talk with the other. I also understand that UIViews are a nice wrapper for CALayer, where CALayer does all the heavy lifting of rendering, and the UIView adds the touch-based responsiveness.
But, all the questions I have seen thus far, attack the problem from one side or the other, not the interplay between them, specially between CoreGraphics and CALayer.
Anyway, my question is ...
How does CoreGraphics relate to CALayer?
My understanding is that a CALayer wraps the CoreGraphics methods to draw itself, but does it once, and can live with the snapshot of itself until invalidated. But, how these drawing methods interplay with the sublayers of that layer? Are they exclusive?
For example, what happens when I have a UIView that has sub-views, and I overload the drawRect method? How does that affect the drawing of its sublayers?
Is it even a good idea to intermix the two inside the same function?
Also, I'm asking only about iOS, I understand that Mac is a different beast (and also have those fancy CIFilters, bastards!).
Prior Research
Here's some related questions I've researched beforehand:
confusion regarding quartz2d, core graphics, core animation, core images. This question asks the differences between each other, and the chosen answer indeed delivers, but it answers for each individual library as if the other didn't exist.
To Drawrect or not to Drawrect. Another great question, but it addresses only the subject of drawing CoreGraphics vs handing the problem to UIKit, but anyway, the chosen answer delivers parts of the puzzle.
Animating Pie Slices with Custom CALayer. Must be one of the most valuable tutorials I've seen in this subject, it's the only one that has guided me through to drawing a CALayer
What is different between CoreGraphics and CoreAnimation Absolutely disappointed on how quick the asker accepted the answer, I feel that there's a whole lot more going in here.
Various WWDC videos, but I haven't seen one that explains in detail the general scope. If anyone replies with a WWDC video that does, I'll consider that a valid answer.
I'll try to answer your question at a conceptual, 20,000ft level. I will try to disclaim my points where I'm over-generalizing, but I'll attempt to hit the common case.
Perhaps the easiest way to think about it is this: In the GPU's memory you have textures which, for the purposes of this discussion, are bitmap images. A CALayer might have a texture associated with it, or it might not. These cases would correspond to a layer with a -drawRect: method, and a layer that exists solely to contain sublayers, respectively. Conceptually, each layer that has a texture associated with it has a different texture all it's own (there are some details and optimizations that make this not strictly/universally true, but in the general, abstract case, it can help to think of it this way.) With that in mind, a superlayer's -drawRect: method has no effect on any of its sublayers' -drawRect: methods, and (again, in the general case) a sublayer's -drawRect: method has no effect on its superlayer's -drawRect: method. Each draws into its own texture (also called a "backing store") and then, based on the layer tree and the associated geometries and transforms, the GPU composites all these textures together into what you see on the screen. When one of the layers is invalidated, directly or indirectly (via -setNeedsDisplayInRect:), then when CA goes to display the next frame on screen, the invalid layers will be redrawn by virtue of having their -drawRect: methods called. That will update the associated texture, and once all the invalid layers' textures are updated, the GPU will composite them, generating the final bitmap that you see on-screen.
So to answer your first question: In the general case, no, there is no interplay between the -drawRect: methods of distinct CALayers.
As to your second question: For the purposes of this discussion you can think of UIViews as being the same as CALayers. The interrelationship with respect to drawing and textures is largely unchanged from that of non-UIView CALayers.
To your third question: Is it a good idea to intermix UIViews and CALayers? Every UIView has a CALayer backing it (all views in UIKit are layer-backed, which is not normally the case on OSX.) So at some level, they're "intermixed" whether you want them to be or not. It is perfectly fine to add CALayer sublayers to the layer that backs a UIView, although that layer will not have all the added functionality that UIView brings to the party. If that layer's purpose is just to generate an image for display, then that's fine. If you want the sub-layer/view to be a first class participant in touch handling, or to be positioned/sized using AutoLayout, then it will need to be a UIView. It's probably best to think of a UIView as a CALayer with a bunch of extra functionality added to it. If you need that functionality, use a UIView. If you don't, use a CALayer.
In sum: CoreGraphics is an API for drawing 2D graphics. One common use of CG (but not the only one) is to draw bitmap images. CoreAnimation is an API providing an organized framework for manipulating bitmaps on-screen. You could meaningfully use CoreAnimation without ever calling a CoreGraphics drawing primitive, for example, if all your textures were backed by images that were compiled into your application at build time.
Hopefully this is helpful. Leave comments if you need clarification, and I'll edit to oblige.

ios iPaint from WWDC 2012

In the Video Session 506 of Apples WWDC 2012 they showed a painting app which is made for high performance drawings (so the frame rate never gets below 30).
I tried to replicate the code but get stuck on multiple points.
What I am looking for is a basic drawing app (lines, Squares, Circles, bezier paths), which performs well even after hundreds of lines have been drawn.
The basic approach is to save the drawn lines (or circles bezierpaths etc) to an image after a certain numbers of them have been drawn, and then only refresh the new drawings, therefore not having to redraw all the already drawn lines.
But somehow I never get to a higher performance. How do I need to implement this? Do I need multiple layers? And how do I manage that not all layers in a view are redrawn, but only a certain sublayer?
If someone could provide me with a short example of a few lines drawn on an layer, then saving that layer to an image, an then drawing on top of that I would really appreciate it.
Thank you for any help to recreate the iPaint application, which is unfortunately not available for download from apple.
That is only half of the puzzle. The other half is to only refresh the minimum possible area of the view (via setNeedsDisplayInRect:). However, I have been through many different ways of drawing via Core Graphics. The caching is fine, but I don't use it anymore. I set the update rectangle as above, and then test each path before I stroke it (testing is fast, stroking is slow). If it is inside the update box, I stroke it, otherwise I ignore it.
I did not look at that session, but a traditional Quartz speedup has been to use CGLayers (not CALayers). You can think of a CGLayer as a cached drawing which may or may not be a bitmap (the system decides how best to cached it). If you have a backing bitmap context, you can use that as your "image" and draw the CGLayers into that (and then discard the layers) as you see fit. Read up on CGLayer (its in the Quartz documentation) and then see if this was what they talked about in that session.

When does a view (or layer) require offscreen rendering?

Hellothis weekend I started to watch the 2011 WWDC videos. I've found really interesting topics about iOS. My favorites were about performance and graphics, but I've found two of them apparently in contradiction. Of course there is something that I didn't get.
The sessions that I'm talking about are Understanding UIKit Rendering -121 and Polishing your app -105.
Unfortunately sample code from 2011 is still not downloadable, so is pretty hard to have an overall view.
In one session they explain that most of times offscreen rendering should be avoided during visualization in scrollview etc. They fix the performance issues in the sample code almost drawing everything inside the -drawRect method.
In the other session the performance issue (on a table view) seems to be due to too much code in the -drawRect method of the table's cells.
First is not clear to me when an OffScreen rendering is required by the system, I've seen in the video that some quartz function such as: cornerRadious, shadowOffset, shadowColor requires it, but does exist a general rule?
Second I don't know if I understood well, but it seems that when there is no offscreen rendering adding layers or views is the way to go.
I hope someone could bring light about that..
Thanks,
Andrea
I don't think there is a rule written down anywhere, but hopefully this will help:
First, let's clear up some definitions. I think offscreen vs onscreen rendering is not the overriding concern most of the time, because offscreen rendering can be as fast as onscreen. The main issue is whether the rendering is done in hardware or software.
There is also very little practical difference between using layers and views. Views are just a thin wrapper around CALayer and they don't introduce a significant performance penalty most of the time. You can override the type of layer used by a view using the +layerClass method if you want to have a view backed by a CAShapeLayer or CATileLayer, etc.
Generally, on iOS, pixel effects and Quartz / Core Graphics drawing are not hardware accelerated, and most other things are.
The following things are not hardware accelerated, which means that they need to be done in software (offscreen):
Anything done in a drawRect. If your view has a drawRect, even an empty one, the drawing is not done in hardware, and there is a performance penalty.
Any layer with the shouldRasterize property set to YES.
Any layer with a mask or drop shadow.
Text (any kind, including UILabels, CATextLayers, Core Text, etc).
Any drawing you do yourself (either onscreen or offscreen) using a CGContext.
Most other things are hardware accelerated, so they are much faster. However, this may not mean what you think it does.
Any of the above types of drawing are slow compared to hardware accelerated drawing, however they don't necessarily slow down your app because they don't need to happen every frame. For example, drawing a drop shadow on a view is slow the first time, but after it is drawn it is cached, and is only redrawn if the view changes size or shape.
The same goes for rasterised views or views with a custom drawRect: the view typically isn't redrawn every frame, it is drawn once and then cached, so the performance after the view is first set up is no worse, unless the bounds change or you call setNeedsDisplay on it.
For good performance, the trick is to avoid using software drawing for views that change every frame. For example, if you need an animated vector shape you'll get better performance using CAShapeLayer or OpenGL than drawRect and Core Graphics. But if you draw a shape once and then don't need to change it, it won't make much difference.
Similarly, don't put a drop shadow on an animated view because it will slow down your frame rate. But a shadow on a view that doesn't change from frame to frame won't have much negative impact.
Another thing to watch out for is slowing down the view setup time. For example, suppose you have a page of text with drop shadows on all the text; this will take a very long time to draw initially since both the text and shadows all need to be rendered in software, but once drawn it will be fast. You will therefore want to set up this view in advance when your application loads, and keep a copy of it in memory so that the user doesn't have to wait ages for the view to display when it first appears on screen.
This is probably the reason for the apparent contradiction in the WWDC videos. For large, complex views that don't change every frame, drawing them once in software (after which they are cached and don't need to be redrawn) will yield better performance than having the hardware re-composite them every frame, even though it will be slower to draw the first time.
But for views that must be redrawn constantly, like table cells (the cells are recycled so they must be redrawn each time one cell scrolls offscreen and is re-used as it scrolls back onto the other side as a different row), software drawing may slow things down a lot.
Offscreen-rendering is one of the worst defined topics in iOS rendering, today. When Apple's UIKit engineers refer to offscreen-rendering, it has a very specific meaning, and a ton of third-party iOS dev blogs are getting it wrong.
When you override "drawRect:", you're drawing via the CPU, and spitting out a bitmap. The bitmap is packaged up and sent to separate process that lives in iOS, the render server. Ideally, the render server just displays the data on screen.
If you fiddle with properties on CALayer, like turning on drop shadows, the GPU will perform additional drawing. This additional work is what UIKit engineers mean when they say "off-screen rendering." This is always performed with hardware.
The issue with off-screen drawing isn't necessarily the drawing. The off-screen pass requires a context switch, as the GPU switches its drawing destination. During this switch, the GPU is idle.
While I don't know a full list of properties that trigger an off-screen pass, you can diagnose this with the Core Animation Instrument's "Color Offscreen-rendered layer" toggle. I assume any property other than alpha is performed via an offscreen pass.
With early iOS hardware, it was reasonable to say "do everything in drawRect." Nowadays GPUs are better, and UIKit has features like shouldRasterize. Today, it's a balancing act between the time spent in drawRect, the number of off-screen passes, and the amount of blending. For the full details, watch the 2014 WWDC session 419, "Advanced Graphics and Animation for iOS Apps."
That all said, it's good to understand what's going on behind-the-scenes, and keep it in the back of your head so you don't do anything insane, but you should start from the simplest solution. Then test it on the slowest hardware you support. If you aren't hitting 60FPS, use Instruments to measure things and figure it out. There are a few possible bottlenecks, and if you aren't using data to diagnose things, you're just guessing.
Offscreen rendering / Rendering on the CPU
The biggest bottlenecks to graphics performance are offscreen rendering and blending – they can happen for every frame of the animation and can cause choppy scrolling.
Offscreen rendering (software rendering) happens when it is necessary to do the drawing in software (offscreen) before it can be handed over to the GPU. Hardware does not handle text rendering and advanced compositions with masks and shadows.
The following will trigger offscreen rendering:
Any layer with a mask (layer.mask)
Any layer with layer.masksToBounds / view.clipsToBounds being true
Any layer with layer.allowsGroupOpacity set to YES and layer.opacity is less than 1.0
When does a view (or layer) require offscreen rendering?
Any layer with a drop shadow (layer.shadow*).
Tips on how to fix: https://markpospesel.wordpress.com/tag/performance/
Any layer with layer.shouldRasterize being true
Any layer with layer.cornerRadius, layer.edgeAntialiasingMask, layer.allowsEdgeAntialiasing
Any layer with layer.borderWith and layer.borderColor?
Missing reference / proof
Text (any kind, including UILabel, CATextLayer, Core Text, etc).
Most of the drawings you do with CGContext in drawRect:. Even an empty implementation will be rendered offscreen.
This post covers blending and other things affecting performance: What triggers offscreen rendering, blending and layoutSubviews in iOS?

Resources