Platform/GFX/APZ: Difference between revisions

No edit summary
 
(9 intermediate revisions by 4 users not shown)
Line 1: Line 1:
== Introduction ==
== Introduction ==


The '''Async Pan/Zoom module (APZ)'''<sup>1</sup> is a platform component that allows panning and zooming to be performed asynchronously (on the compositor thread rather than the main thead).
The '''Async Pan/Zoom module (APZ)'''<sup>1</sup> is a platform component that allows panning and zooming to be performed asynchronously (on the compositor thread rather than the main thread).


For '''zooming''', this means that the APZ reacts to a pinch gesture immediately and instructs the compositor to scale the already-rendered layers at whatever resolution they have been rendered (so e.g. text becomes more blurry as you zoom in), and meanwhile sends a request to Gecko to re-render the content at a new resolution (with sharp text and all).
For '''zooming''', this means that the APZ reacts to a pinch gesture immediately and instructs the compositor to scale the already-rendered layers at whatever resolution they have been rendered (so e.g. text becomes more blurry as you zoom in), and meanwhile sends a request to Gecko to re-render the content at a new resolution (with sharp text and all).
Line 11: Line 11:
== Supported platforms ==
== Supported platforms ==


The APZ module is currently enabled on B2G and Metro. Fennec has a Java implementation of asynchronous panning and zooming, but the plan is to port Fennec to use the APZ module as well.
The APZ module is enabled on Fennec as of version 48. It is also enabled on desktop as of version 48 if e10s is enabled. The easiest way to check if it is enabled is by going to about:support and checking the "Asynchronous Pan/Zoom" line in the Graphics section.


The APZ module relies on [[Platform/GFX/OffMainThreadCompositing|OMTC]], so a prerequisite for porting it to a platform is for OMTC to work on that platform.
The APZ module relies on [[Platform/GFX/OffMainThreadCompositing|OMTC]], so a prerequisite for porting it to a platform is for OMTC to work on that platform.
Line 17: Line 17:
== AsyncPanZoomControllers ==
== AsyncPanZoomControllers ==


Inside the APZ module, every scrollable layer has an [https://mxr.mozilla.org/mozilla-central/source/gfx/layers/ipc/AsyncPanZoomController.h AsyncPanZoomController] (APZC). Scrollable layers roughly correspond to the root document, documents in iframes, and overflow:scroll elements. See [[Platform/GFX/OffMainThreadCompositing|OMTC]] for more information about layers.
Inside the APZ module, every scrollable layer has an [http://dxr.mozilla.org/mozilla-central/source/gfx/layers/apz/src/AsyncPanZoomController.h AsyncPanZoomController] (APZC). Scrollable layers roughly correspond to the root document, documents in iframes, and overflow:scroll elements. See [[Platform/GFX/OffMainThreadCompositing|OMTC]] for more information about layers.


The APZCs are arranged in a tree whose structure reflects the structure of the layer tree containing the layers that they correspond to, except that the APZC tree only has nodes for scrollable layers, while the layer tree has nodes for all layers. The APZC tree is managed by a class called [https://mxr.mozilla.org/mozilla-central/source/gfx/layers/composite/APZCTreeManager.h APZCTreeManager]. The APZCTreeManager is the interface through which the outside world interacts with the APZ module - there is no access to the APZCs directly, but the APZCTreeManager provides methods that operate on a specific APZC in the tree.
The APZCs are arranged in a tree whose structure reflects the structure of the layer tree containing the layers that they correspond to, except that the APZC tree only has nodes for scrollable layers, while the layer tree has nodes for all layers. The APZC tree is managed by a class called [http://dxr.mozilla.org/mozilla-central/source/gfx/layers/apz/src/APZCTreeManager.h APZCTreeManager]. The APZCTreeManager is the interface through which the outside world interacts with the APZ module - there is no access to the APZCs directly, but the APZCTreeManager provides methods that operate on a specific APZC in the tree.
These methods identify an APZC using three integer identifiers, grouped in a structure called '''ScrollableLayerGuid'''. The three identifiers are:
These methods identify an APZC using three integer identifiers, grouped in a structure called '''ScrollableLayerGuid'''. The three identifiers are:
# A '''layers id''', which identifies the layer tree that the scrollable layer belongs to. Layers ids are maintained by the compositor, with CompositorParent::RootLayerTreeId() returning the layers id for the root layer tree, and CompositorParent::AllocateLayerTreeId() allocating a layers id for a new layer tree.
# A '''layers id''', which identifies the layer tree that the scrollable layer belongs to. Layers ids are maintained by the compositor, with CompositorParent::RootLayerTreeId() returning the layers id for the root layer tree, and CompositorParent::AllocateLayerTreeId() allocating a layers id for a new layer tree.
Line 34: Line 34:


* When the compositor receives an update to the layer tree, it propagates this update to the APZCTreeManager by calling APZCTreeManager::UpdatePanZoomControllerTree(). This function updates the tree of APZCs to reflect the tree of scrollable layers in the updated layer tree.
* When the compositor receives an update to the layer tree, it propagates this update to the APZCTreeManager by calling APZCTreeManager::UpdatePanZoomControllerTree(). This function updates the tree of APZCs to reflect the tree of scrollable layers in the updated layer tree.
* Every time the compositor composites a frame, it queries each APZC for its current async transform (see AsyncPanZoomController::SampleContentTransformForFrame()). The APZC modifies this transform as the user pans and zooms.
* Every time the compositor composites a frame, it queries each APZC for its current async transform (see AsyncPanZoomController::GetCurrentAsyncTransform()). The APZC modifies this transform as the user pans and zooms.
* APZCs can schedule a composite by calling CompositorParent::ScheduleRenderOnCompositorThread().
* APZCs can schedule a composite (for the next frame of a scroll animation, for instance) by calling CompositorParent::ScheduleRenderOnCompositorThread().


=== Widget code ===
=== Widget code ===


The '''widget code''' is a platform-specific component of a browser implementation that interfaces with the native widget implementation. It corresponds roughly to the following pieces of code:
The '''widget code''' is a platform-specific component of a browser implementation that interfaces with the native widget implementation. The widget code interacts with the APZ in the following ways:
* On B2G: [https://mxr.mozilla.org/mozilla-central/source/layout/ipc/RenderFrameParent.h RenderFrameParent]/[https://mxr.mozilla.org/mozilla-central/source/layout/ipc/RenderFrameChild.h RenderFrameChild] and [https://mxr.mozilla.org/mozilla-central/source/dom/ipc/TabParent.h TabParent]/[https://mxr.mozilla.org/mozilla-central/source/dom/ipc/TabChild.h TabChild]
* On Metro: [https://mxr.mozilla.org/mozilla-central/source/widget/windows/winrt/MetroWidget.h MetroWidget] and [https://mxr.mozilla.org/mozilla-central/source/widget/windows/winrt/MetroInput.h MetroInput]
* On Fennec (which doesn't use the APZ yet): [https://mxr.mozilla.org/mozilla-central/source/mobile/android/base/GeckoAppShell.java GeckoAppShell] and [https://mxr.mozilla.org/mozilla-central/source/mobile/android/base/gfx/GeckoLayerClient.java GeckoLayerClient], which communicate with native code via [http://mxr.mozilla.org/mozilla-central/source/widget/android/AndroidJNI.cpp AndroidJNI].
 
The widget code interacts with the APZ in the following ways:


* forwards relevant input events to the APZ (APZCTreeManager::ReceiveInputEvent())
* forwards relevant input events to the APZ (APZCTreeManager::ReceiveInputEvent())
* notifies the APZ about Gecko events that are relevant to it, such as:
* notifies the APZ about Gecko events that are relevant to it, such as:
** a reflow that causes a change in the dimensions of a scrollable layer (APZCTreeManager::UpdateCompositionBounds())
** how content responded to an input event (APZCTreeManager::ContentReceivedInputBlock())
** a scrollTo performed by content (APZCTreeManager::UpdateScrollOffset())
** a change in the zoom constraints (APZCTreeManager::UpdateZoomConstraints())
** a request to zoom in to a rectangle (APZCTreeManager::ZoomToRect())
** a request to zoom in to a rectangle (APZCTreeManager::ZoomToRect())


In addition, the widget code provides APZ with an interface for interacting with Gecko, called '''[https://mxr.mozilla.org/mozilla-central/source/gfx/layers/ipc/GeckoContentController.h GeckoContentController]'''. The implementation of this interface is different for each platform. It may even be different for different APZCs within one platform (for example, in the B2G browser, APZCs representing scrollable elements in content processes use the RemoteContentController implementation, while those representing scrollable elements in the parent process will use a different implementation (currently being developed in {{bug|912657}})).
In addition, the widget code provides APZ with an interface for interacting with Gecko, called '''[http://dxr.mozilla.org/mozilla-central/source/gfx/layers/apz/public/GeckoContentController.h GeckoContentController]'''. The implementation of this interface is different for different platforms. It may even be different for different APZCs within one platform, depending on which process the controller lives in.


GeckoContentController allows the APZ to do the following:
GeckoContentController allows the APZ to do the following:


* request a repaint (GeckoContentController::RequestContentRepaint())
* request a repaint (GeckoContentController::RequestContentRepaint())
* request handling of various gestures, such as single taps, double taps, and long taps (GeckoContentController::HandleSingleTap() etc.)
* request handling of various gestures, such as single taps, double taps, and long taps (GeckoContentController::HandleTap() etc.)
* fire async scroll events (GeckoContentController::SendAsyncScrollDOMEvent())
* fire state change notifications (GeckoContentController::NotifyAPZStateChange())
* schedule arbitrary actions to be performed on the Gecko thread (GeckoContentController::PostDelayedTask())
* schedule arbitrary actions to be performed with a delay (GeckoContentController::PostDelayedTask())


== Threads and processes ==
== Threads and processes ==


When OMTC is enabled on a platform (which is a requirement for using the APZC), the compositor runs on its own thread, called the '''compositor thread'''. APZCs and the APZCTreeManager can be thought of as living on the compositor thread, although they can be used in certain ways by other threads (usually the Gecko thread, or the platform UI thread if there is one). [https://mxr.mozilla.org/mozilla-central/source/gfx/layers/composite/APZCTreeManager.h APZCTreeManager.h] documents which APZCTreeManager methods can be called on which threads.
When OMTC is enabled on a platform (which is a requirement for using the APZC), the compositor runs on its own thread, called the '''compositor thread'''. APZCs and the APZCTreeManager can be thought of as living on the compositor thread, although they can be used in certain ways by other threads (usually the Gecko thread, or the platform UI thread if there is one). [http://dxr.mozilla.org/mozilla-central/source/gfx/layers/apz/src/APZCTreeManager.h APZCTreeManager.h] documents which APZCTreeManager methods can be called on which threads.


On B2G, there are not only multiple threads but also multiple processes, as each app (or in the case of the browser, each tab) has its own process. In this setup, only the parent process has a compositor thread, and all APZCs live in the parent process, even ones corresponding to layers from a child thread.
On some platforms there are not only multiple threads but also multiple processes. In this setup, the compositor lives in the GPU process (if there is one - currently Windows only), or the UI process otherwise. All the APZCs live in the same process as the compositor, even ones corresponding to layers from a content process.


== Coordinate systems ==
== Coordinate systems ==
Line 73: Line 68:
* [https://staktrace.com/spout/entry.php?id=800 Unraveling coordinate systems]
* [https://staktrace.com/spout/entry.php?id=800 Unraveling coordinate systems]
* [https://staktrace.com/spout/entry.php?id=801 Unraveling coordinate systems, part 2]
* [https://staktrace.com/spout/entry.php?id=801 Unraveling coordinate systems, part 2]
* [http://mxr.mozilla.org/mozilla-central/source/gfx/layers/composite/APZCTreeManager.cpp#900 The comment above APZCTreeManager::GetInputTransforms()]
* [https://searchfox.org/mozilla-central/rev/6f86cc3479f80ace97f62634e2c82a483d1ede40/gfx/layers/apz/src/APZCTreeManager.cpp#2795 The comment above APZCTreeManager::GetScreenToAPZCTransform()]
* [https://bug935219.bugzilla.mozilla.org/attachment.cgi?id=8380975 Diagram illustrating the coordinate confusion that gave rise to bug 935219]
* [https://bug935219.bugzilla.mozilla.org/attachment.cgi?id=8380975 Diagram illustrating the coordinate confusion that gave rise to bug 935219]


Line 81: Line 76:


This logging can be turned on by setting the "apz.printtree" pref to "true".
This logging can be turned on by setting the "apz.printtree" pref to "true".
Additional logging can be enabled by looking for *_LOG macros at the top of .cpp files, and setting the MOZ_LOG environment variable appropriately. For example, setting <tt>MOZ_LOG=apz.inputqueue:4</tt> is often useful for tracing input events through the APZ code.


== Main APZ-related projects on the horizon ==
== Main APZ-related projects on the horizon ==


(In no particular order)
See [https://github.com/orgs/FirefoxGraphics/projects/7 the APZ planning GitHub project].
 
* <strike>Turn on APZ in all Gaia apps - {{bug|909877}}</strike>
* Fix up issues in Gaia with APZ enabled - {{bug|949585}}
* <strike>Make APZ work well for Metro - {{bug|886321}}</strike>
* <strike>Make APZ work even better in Metro - {{bug|963116}}</strike> (Metro project cancelled)
* <strike>Implement support for Fennec-like dynamic toolbar on B2G - {{bug|860812}}</strike>
* Improve hit detection for the different touch-sensitive regions - {{bug|928833}}
* <strike>Implement support for the CSS touch-action property - {{bug|795567}}</strike>
* Implement touch-action bindings for B2G and enable it - {{bug|960316}}, {{bug|960209}}
* Switch Fennec over from the Java version to the C++ APZ - {{bug|776030}}
* Reduce input latency by changing the threading model - {{bug|930939}}
* Get APZ turned on for desktop platforms - {{bug|944938}} for OS X
* Smooth scrolling API for content/script - {{bug|928839}}


== FAQ ==
== FAQ ==
Line 103: Line 87:
If you have questions about anything APZ-related, please add them here, and somebody watching this page will try to answer it.
If you have questions about anything APZ-related, please add them here, and somebody watching this page will try to answer it.


; What platforms is APZ currently enabled on? [2014-01-14] : As of January 8, 2014, APZ is currently enabled in all B2G processes that are not the root process (i.e. this includes all browser content and Gaia apps). It is also enabled on Firefox Metro (when running in metro mode).
; What platforms is APZ currently enabled on? [2016-09-13] : APZ is currently enabled in all B2G processes, Firefox desktop with e10s enabled, and Fennec.


; How does APZ impact the onload event? Will this impact user perceived performance? [2014-01-28] : In general APZ shouldn't really impact the onload event. We might be painting a larger area now but if the app is well-behaved and doesn't trigger a lot of paints the impact from this should not be very large. If there are reports of delayed onload because of APZ, it would be useful to get profiles with and without APZ enabled to compare.
; How does APZ impact the onload event? Will this impact user perceived performance? [2014-01-28] : In general APZ shouldn't really impact the onload event. We might be painting a larger area now but if the app is well-behaved and doesn't trigger a lot of paints the impact from this should not be very large. If there are reports of delayed onload because of APZ, it would be useful to get profiles with and without APZ enabled to compare.
Line 115: Line 99:
== Where to go for more answers ==
== Where to go for more answers ==


APZ now has its own IRC channel, #apz. You can also try #gfx and #developers. Ping kats, botond, tn, BenWa or Cwiiis.
APZ now has its own matrix channel, #apz:mozilla.org. You can also try #gfx:mozilla.org and #developers:mozilla.org. Ping kats, botond, mstange, or tnikkel.
Confirmed users
586

edits