Gecko:TransparentLayersAndSubpixelAA

From MozillaWiki
Jump to: navigation, search

Problem

Subpixel AA rendered to transparent surfaces needs component alpha to not look bad. Graphics backends do not support component alpha in a performant way.

Retained layers made us use transparent surfaces a lot more, e.g. when content without an opaque background is being scrolled.

Plan

  • Do more analysis to make surfaces opaque in more cases. In particular, for a layer that has transparent content but is over a background that is completely one solid color, we can pull that solid color up into the layer and draw it into the layer's background. This will make most cases of scrolling over a solid color background not use transparent surfaces. This is a no-brainer since working with opaque surfaces is always a performance win.
  • For each ThebesLayer, make FrameLayerBuilder report if we have any text at all, and if any of that text is over a transparent background.
  • In BasicLayerManager, when painting a ThebesLayer that is transparent and contains text, consider treating the layer as non-retained. That is, we'll have no buffer and just repaint the entire layer (that intersects the paint dirty region) directly to the backbuffer or nearest enclosing temporary buffer. This will eliminate quality regressions due to retained layers. Retained layer scrolling speedups should mostly be retained since many common cases will still be a lot faster. Only pages where text moves relative to its background during scrolling should be slowed, and they shouldn't get slower than they were before retained layers.

The rules for whether a transparent layer with text needs to be non-retained vary by surface type. Some backends (Quartz, XRender, GDI) can draw subpixel-AA text into a transparent surface with full fidelity as long as it's all over opaque pixels. Other backends (D2D) cannot draw text into transparent surfaces without losing fidelity, even if the text is all over opaque pixels.

  • A similar trick should work for LayerManagerD3D9 and D2D, and for LayerManagerOGL and X, since on those combinations we can render directly into the backbuffer or temporary surface (right?).
  • For LayerManagerOGL and Quartz, and LayerManagerD3D9 and GDI, we still have a problem. We can't render directly onto the layer manager's backbuffer or temporary surfaces as far as I know. However, in some situations we can still win. In particular, if our transparent ThebesLayer with text is directly over another ThebesLayer, we can draw the transparent ThebesLayer into the lower ThebesLayer's buffer directly (and then invalidate the drawn area of the lower ThebesLayer after compositing with it). Or we could copy the contents of the lower ThebesLayer's buffer into the transparent ThebesLayer before drawing. There are performance tradeoffs here. The former approach is more conservative, in that it more closely approximates what we did before retained layers.