Confirmed users
138
edits
No edit summary |
|||
| Line 3: | Line 3: | ||
TextureClient and TextureHost are the way to share texture memory accross threads or processes. | TextureClient and TextureHost are the way to share texture memory accross threads or processes. | ||
For more information read the inline documentation | |||
* http://dxr.mozilla.org/mozilla-central/source/gfx/layers/client/TextureClient.h | |||
* http://dxr.mozilla.org/mozilla-central/source/gfx/layers/composite/TextureHost.h | |||
TODO[nical] much more goes here | TODO[nical] much more goes here | ||
| Line 12: | Line 18: | ||
In order to incrementally fix the badness of TextureClient and TextureHost, the classes have been marked deprecated and new texture clients and host were designed, using a more strict and defined memory model. The goal is now to replace all the usage of DeprecatedTexture* by the new classes. When writing new code, if possible please use the new classes. | In order to incrementally fix the badness of TextureClient and TextureHost, the classes have been marked deprecated and new texture clients and host were designed, using a more strict and defined memory model. The goal is now to replace all the usage of DeprecatedTexture* by the new classes. When writing new code, if possible please use the new classes. | ||
The biggest difference between deprecated and new textures is that deprecated did not own any shared data. Look at them as channels through which SurfaceDescriptors were sent from one side to the other. This caused ownership problems because Surface descriptor doesn't have any notion of ownership (it is just an IPDL generated structure for serialization). New textures on the other hand fully own their shared data. | The biggest difference between deprecated and new textures is that deprecated did not own any shared data. Look at them as channels through which several SurfaceDescriptors were sent from one side to the other. This caused ownership problems because Surface descriptor doesn't have any notion of ownership (it is just an IPDL generated structure for serialization). New textures on the other hand fully own their shared data. There should be no object referring to data shared with the compositor that is not doing so through a TextureClient (or TextureHost). This is important because TextureClient and TextureHost define a strict ownership protocol that is designed to cover all the (numerous) use cases in Gecko. So there is always one and only one TextureClient/Host pair per shared buffer. If there is need to send a new buffer, then a new TextureClient/Host pair is created along with it. This way it is possible to track the lifetime of buffers that are shared between several threads on the content side, plus the compositor thread (which lives in a separate process), which was not possible with the derpecated texture (the latter supposed that we could get away with loosing ownership of the buffers when sending them accross IPC, which turned out to be incompatible with the way Gecko works for some things like video and buffer rotation). | ||
=== Why is sharing textures between the content side and the compositor side so complicated? === | === Why is sharing textures between the content side and the compositor side so complicated? === | ||
| Line 23: | Line 29: | ||
There are other examples of this, but the bottom line is that in order to reduce the number of copies and the amount of memory we consume, we need to share things between a lot of threads simultaneously and this introduces more complicated ownership problems. It is not possible to fit a clean and simple memory model like SurfaceFlinger's without abandonning some optimizations that we do and without changing some of the things Gecko does that have been designed before we thought of compositing on a separate thread. | There are other examples of this, but the bottom line is that in order to reduce the number of copies and the amount of memory we consume, we need to share things between a lot of threads simultaneously and this introduces more complicated ownership problems. It is not possible to fit a clean and simple memory model like SurfaceFlinger's without abandonning some optimizations that we do and without changing some of the things Gecko does that have been designed before we thought of compositing on a separate thread. | ||
=== who owns the shared data with the new textures? === | |||
In short: the texture client owns the memory. | |||
==== Accessing the shared data ==== | |||
At any time both the TextureClient and the texture host can access the shared data. Accessing the data must be done between calls to Lock and Unlock. In general it is best to design CompositableClients and CompositableHosts in a way that the TextureClient never acquires a write lock while the TextureHost wants to read to avoid blocking the compositor thread. This can be done by playing with double buffering and synchronous compositable transactions. | |||
Some TextureClient/Host do not implement locking yet. When using them, we must ensure the client never writes while the host reads as above. This can currently be done in two ways: | |||
* Either force the host to read during synchronous transactions (using the texture flag TEXTURE_IMMEDIATE_UPLOAD) | |||
* Or completely forbid the client to write into the texture after it has been shared by marking the data as immutable (using the texture flag TEXTURE_IMMUTABLE). | |||
Immutable textures are particularly well suited for things like video streams, since the producer will create a new TextureClient for each frame so we know we will not need to write into the same texture twice. | |||
==== Deallocating the shared data ==== | |||
This is a trickier aspect. Deallocating shared data depends on which process should be responsible for it. | |||
The lifetime of bith TextureClient and TextureHost is governed by reference counting. | |||
The TextureClient can be kept alive by: | |||
* The producer of the data or indirectly (for instance the Image class holding a reference to a TextureClient). | |||
* The compositable client if the texture is currently in use (front or back buffer). | |||
The TextureHost can be kept alive by: | |||
* The IPDL glue between TextureClient and TextureHost (so a TextureHost *never* dies before its corresponding TextureClient). | |||
* The compositable host if the texture is currently in use. | |||
When the reference count of the TextureClient reaches zero, the Message OpRemoveTexture is sent to the TextureHost which removes the IPDL glue that keeps one of the references to the TextureHost. In most cases this will bring the reference count of the TextureHost to zero and the latter is destroyed. Otherwise it will be destroyed later when the CompositableHost doesn't use it anymore. | |||
When the message OpRemoveTexture is sent, there should be nothing capable of accessing the shared data (since the texture client is dead). | |||
The choice of what to do with the shared data depends of the TextureFlags of the TextureClient/Host pair when the message OpRemoveTexture is received by the host side. | |||
* 1) TEXTURE_DEALLOCATE_HOST (The most common case): We destroy the shared data on the host side. The client sends the OpRemoveTexture message asynchronously to the host and the host side can destroy the data (or it could decide to keep it alive until the TextureHost is destroyed, but this has not impact on the client side because nothing is holding on to the shared data there). | |||
* 2) TEXTURE_DEALLOCATE_CLIENT (when the shared data can only be destoyed by the client thread): The message opRemoveTexture is sent synchronously to the host. When the host receives the message it lets go of all of it's reference to the shared data and sends back the reply ReplyTextureRemoved. at the end of the transaction the client side receives this reply with the guarantee that nothing on the host side is holding on to the shared data, and desroys the shared data. | |||
* 3) none of the two flags are set: This means we want the shared data to be managed by something outside of layers. This is the case of the Gonk camera for instance. Basically this is identical to scenraio 2) but the texture is not deallocated upon receival of ReplyTextureRemoved. In this case the best is to add a mechanism to inform the external system that the buffer is not used anymore by layers when ReplyTextureRemoved is received. This has been specifically designed to fix some of the Gonk camera problems that we are having where both the camera and layers think they are owning the data at the same time, but the hook has not been implemented yet (TODO update this paragraph when it has been implemented!). | |||
== Migration to the new textures (Meta bug 893300)== | == Migration to the new textures (Meta bug 893300)== | ||