1,295
edits
| Line 91: | Line 91: | ||
Implicit layers can also change size, need to be scrolled, etc. | Implicit layers can also change size, need to be scrolled, etc. | ||
=== | === Proposal === | ||
==== LayerManager ==== | |||
Every layer belongs to a LayerManager. The idea is that a window will provide an associated LayerManager. (Documents being rendered by their own process will probably have their own LayerManagers.) Every layer in a layer tree must have the same LayerManager. | |||
Updates to the layer tree are performed within a transaction. Nested transactions are not needed or allowed. Only layer tree states between transactions will be rendered. Unless otherwise noted, all layer-related APIs | |||
may only be used within a transaction on the appropriate LayerManager, and only on the main thread. | |||
class LayerManager { | |||
void beginTransaction(); | |||
void setRoot(Layer*); | |||
void endTransaction(); | |||
}; | |||
LayerManager::SetRoot sets a layer to be the root layer. This is how you get a layer to be displayed. | |||
==== Layer ==== | |||
Layer is the superclass of all layers. A Layer could be anything that can be rendered into a destination surface. It has methods to set various properties that affect the rendering of a layer into its parent: opacity, transform, filter, etc... (For simplicity I'm only showing 'opacity' here.) | |||
class Layer { | class Layer { | ||
LayerManager getManager(); | |||
void setOpacity(TimeStamp, float); | |||
}; | }; | ||
Animated properties are supported. To animate, call a setter method one or more times, passing in different timestamped values. When we render, we use the last supplied property value that is before the current time. When calling a setter method with TimeStamp T, all values for times >= T are discarded. To set a constant value, just pass a null TimeStamp, which is interpreted as being at the beginning of time. | |||
Layers should be referenced counted. The LayerManager holds a reference to its root layer and parent layers hold references to their children. | |||
==== RenderedLayer ==== | |||
} | |||
A RenderedLayer is the basic leaf layer that you can render into using cairo/Thebes. | |||
class RenderedLayer : public Layer { | |||
RenderedLayer(LayerManager, ContainerLayer parent); | |||
gfxContext* beginDraw(const nsIntRegion& aVisibleRegion, | |||
const nsIntRegion& aChangedRegion, | |||
nsIntRegion* aRegionToDraw); | |||
void endDraw(); | |||
void copy(RenderedLayer, const nsIntRegion& aRegion, | |||
nsIntPoint aDelta); | |||
} | |||
RenderedLayers are conceptually infinite in extent. Each RenderedLayer has an internal "valid region" which is finite. (An implementation would create a surface large enough to hold the entire valid region.) The initial valid region is empty. The implementation is allowed to discard all or part of the buffered contents of a RenderedLayer between transactions. Drawing into the RenderedLayer adds to the valid region, and discarding parts of the buffer removes from the valid region. | |||
When calling beginDraw, the caller specifies in aVisibleRegion a region that needs to be valid when drawing is done. (This is the area that will be visible to the user.) The caller can also specify aChangedRegion to indicate that content in that region has changed and will need to be repainted. The implementation returns aRegionToDraw to indicate the area that must be repainted. Typically this will be aNeedRegion minus (the currently valid region minus aChangedRegion). aRegionToDraw is added to the valid region. | |||
The content in a RenderedLayer can change size. If the size decreases, aChangedRegion will include the area of content that has gone away, and aVisibleRegion will exclude that area. The implementation may trim its buffers appropriately. If the size increases the implementation will need to increase the buffer. | |||
It is possible for aRegionToDraw to return empty, e.g. when nothing changed and the entire visible area is still buffered. The caller should optimize by skipping painting in this case. | |||
For scrolling and to enable intelligent reuse of parts of RenderedLayers by other layers... | |||
==== ContainerLayer ==== | |||
class | class ContainerLayer { | ||
// Add an existing layer | // Add an existing layer | ||
addLayer(Layer); | addLayer(Layer); | ||
| Line 191: | Line 177: | ||
// done. The context cannot be used after finish() is called. | // done. The context cannot be used after finish() is called. | ||
gfxContext* getContext(); | gfxContext* getContext(); | ||
}; | |||
class YUVLayerBuilder : LayerBuilder { | |||
// Create a YUV layer with given size and format, and adopt the memory buffer | |||
YUVLayerBuilder(size, format, bufferToAdopt); | |||
}; | |||
class WebGLBufferLayerBuilder : LayerBuilder { | |||
// Create a layer that's a logical copy (ideally copy on write) of the | |||
// underlying buffer managed by a WebGL canvas | |||
WebGLLayerBuilder(webGLBuffer); | |||
}; | }; | ||
edits