Issue #582

Use View Debugging

Run on device, Xcode -> Debug -> View debugging -> Rendering -> Color blended layer On Simulator -> Debug -> Color Blended Layer

Corner radius

Okay. Talked to a Core Animation engineer again:

  • cornerRadius was deliberately improved in Metal so it could be used everywhere.
  • Using a bitmap is WAY heavier in terms of memory and performance.
  • CALayer maskLayer is still heavy.

https://developer.apple.com/documentation/quartzcore/calayer/1410818-cornerradius

Setting the radius to a value greater than 0.0 causes the layer to begin drawing rounded corners on its background. By default, the corner radius does not apply to the image in the layer’s contents property; it applies only to the background color and border of the layer. However, setting the masksToBounds property to true causes the content to be clipped to the rounded corners.

https://developer.apple.com/documentation/quartzcore/calayer/1410896-maskstobounds

When the value of this property is true, Core Animation creates an implicit clipping mask that matches the bounds of the layer and includes any corner radius effects. If a value for the mask property is also specified, the two masks are multiplied to get the final mask value.

Mask layer

layer.cornerRadius, with or without layer.maskedCorners causes blending Use mask layer instead of layer.cornerRadius to avoid blending, but mask causes offscreen rendering

let mask = CAShapeLayer()
let path = UIBezierPath(
    roundedRect: bounds,
    byRoundingCorners: [.topLeft, .topRight, .bottomLeft, .bottomRight],
    cornerRadii: CGSize(width: 20, height: 20)
)
mask.path = path.cgPath
layer.mask = mask

Offscreen rendering

Instruments’ Core Animation Tool has an option called Color Offscreen-Rendered Yellow that will color regions yellow that have been rendered with an offscreen buffer (this option is also available in the Simulator’s Debug menu). Be sure to also check Color Hits Green and Misses Red. Green is for whenever an offscreen buffer is reused, while red is for when it had to be re-created.

Offscreen drawing on the other hand refers to the process of generating bitmap graphics in the background using the CPU before handing them off to the GPU for onscreen rendering. In iOS, offscreen drawing occurs automatically in any of the following cases:

Core Graphics (any class prefixed with CG*) The drawRect() method, even with an empty implementation. CALayers with a shouldRasterize property set to YES. CALayers using masks (setMasksToBounds) and dynamic shadows (setShadow*). Any text displayed on screen, including Core Text. Group opacity (UIViewGroupOpacity).

Instruments

Read more

@abstract Sets the corner rounding method to use on the ASDisplayNode.
There are three types of corner rounding provided by Texture: CALayer, Precomposited, and Clipping.

- ASCornerRoundingTypeDefaultSlowCALayer: uses CALayer's inefficient .cornerRadius property. Use
this type of corner in situations in which there is both movement through and movement underneath
the corner (very rare). This uses only .cornerRadius.

- ASCornerRoundingTypePrecomposited: corners are drawn using bezier paths to clip the content in a
CGContext / UIGraphicsContext. This requires .backgroundColor and .cornerRadius to be set. Use opaque
background colors when possible for optimal efficiency, but transparent colors are supported and much
more efficient than CALayer. The only limitation of this approach is that it cannot clip children, and
thus works best for ASImageNodes or containers showing a background around their children.

- ASCornerRoundingTypeClipping: overlays 4 separate opaque corners on top of the content that needs
corner rounding. Requires .backgroundColor and .cornerRadius to be set. Use clip corners in situations
in which is movement through the corner, with an opaque background (no movement underneath the corner).
Clipped corners are ideal for animating / resizing views, and still outperform CALayer.

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.

For example, writing your own draw method with Core Graphics means your rendering will technically be done in software (offscreen) as opposed to being hardware accelerated like it is when you use a normal CALayer. This is why manually rendering a UIImage with a CGContext is slower than just assigning the image to a UIImageView.

if layer’s contents is nil or this contents has a transparent background, you just need to set cornerRadius. For UILabel, UITextView and UIButton, you can just set layer’s backgroundColor and cornerRadius to get a rounded corner. Note: UILabel’s backgroundColor is not its layer’s backgroundColor.