Line data Source code
1 : /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 : * This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : #ifndef GFX_READBACKLAYER_H
7 : #define GFX_READBACKLAYER_H
8 :
9 : #include <stdint.h> // for uint64_t
10 : #include "Layers.h" // for Layer, etc
11 : #include "mozilla/gfx/Rect.h" // for gfxRect
12 : #include "mozilla/gfx/Point.h" // for IntPoint
13 : #include "mozilla/mozalloc.h" // for operator delete
14 : #include "nsAutoPtr.h" // for nsAutoPtr
15 : #include "nsCOMPtr.h" // for already_AddRefed
16 : #include "nsDebug.h" // for NS_ASSERTION
17 : #include "nsPoint.h" // for nsIntPoint
18 : #include "nscore.h" // for nsACString
19 :
20 : class gfxContext;
21 :
22 : namespace mozilla {
23 : namespace layers {
24 :
25 : class ReadbackProcessor;
26 :
27 : namespace layerscope {
28 : class LayersPacket;
29 : } // namespace layerscope
30 :
31 : /**
32 : * A ReadbackSink receives a stream of updates to a rectangle of pixels.
33 : * These update callbacks are always called on the main thread, either during
34 : * EndTransaction or from the event loop.
35 : */
36 : class ReadbackSink {
37 : public:
38 0 : ReadbackSink() {}
39 0 : virtual ~ReadbackSink() {}
40 :
41 : /**
42 : * Sends an update to indicate that the background is currently unknown.
43 : */
44 : virtual void SetUnknown(uint64_t aSequenceNumber) = 0;
45 : /**
46 : * Called by the layer system to indicate that the contents of part of
47 : * the readback area are changing.
48 : * @param aRect is the rectangle of content that is being updated,
49 : * in the coordinate system of the ReadbackLayer.
50 : * @param aSequenceNumber updates issued out of order should be ignored.
51 : * Only use updates whose sequence counter is greater than all other updates
52 : * seen so far. Return null when a non-fresh sequence value is given.
53 : * @return a context into which the update should be drawn. This should be
54 : * set up to clip to aRect. Zero should never be passed as a sequence number.
55 : * If this returns null, EndUpdate should NOT be called. If it returns
56 : * non-null, EndUpdate must be called.
57 : *
58 : * We don't support partially unknown backgrounds. Therefore, the
59 : * first BeginUpdate after a SetUnknown will have the complete background.
60 : */
61 : virtual already_AddRefed<gfx::DrawTarget>
62 : BeginUpdate(const gfx::IntRect& aRect, uint64_t aSequenceNumber) = 0;
63 : /**
64 : * EndUpdate must be called immediately after BeginUpdate, without returning
65 : * to the event loop.
66 : * @param aContext the context returned by BeginUpdate
67 : * Implicitly Restore()s the state of aContext.
68 : */
69 : virtual void EndUpdate(const gfx::IntRect& aRect) = 0;
70 : };
71 :
72 : /**
73 : * A ReadbackLayer never renders anything. It enables clients to extract
74 : * the rendered contents of the layer tree below the ReadbackLayer.
75 : * The rendered contents are delivered asynchronously via calls to a
76 : * ReadbackSink object supplied by the client.
77 : *
78 : * This is a "best effort" API; it is possible for the layer system to tell
79 : * the ReadbackSink that the contents of the readback area are unknown.
80 : *
81 : * This API exists to work around the limitations of transparent windowless
82 : * plugin rendering APIs. It should not be used for anything else.
83 : */
84 0 : class ReadbackLayer : public Layer {
85 : public:
86 0 : MOZ_LAYER_DECL_NAME("ReadbackLayer", TYPE_READBACK)
87 :
88 0 : virtual void ComputeEffectiveTransforms(const gfx::Matrix4x4& aTransformToSurface) override
89 : {
90 : // Snap our local transform first, and snap the inherited transform as well.
91 : // This makes our snapping equivalent to what would happen if our content
92 : // was drawn into a PaintedLayer (gfxContext would snap using the local
93 : // transform, then we'd snap again when compositing the PaintedLayer).
94 0 : mEffectiveTransform =
95 0 : SnapTransform(GetLocalTransform(), gfxRect(0, 0, mSize.width, mSize.height),
96 0 : nullptr)*
97 0 : SnapTransformTranslation(aTransformToSurface, nullptr);
98 0 : }
99 :
100 : /**
101 : * CONSTRUCTION PHASE ONLY
102 : * Set the callback object to which readback updates will be delivered.
103 : * This also resets the "needed rectangle" so that on the next layer tree
104 : * transaction we will try to deliver the full contents of the readback
105 : * area to the sink.
106 : * This layer takes ownership of the sink. It will be deleted when the
107 : * layer is destroyed or when a new sink is set.
108 : * Initially the contents of the readback area are completely unknown.
109 : */
110 0 : void SetSink(ReadbackSink* aSink)
111 : {
112 0 : SetUnknown();
113 0 : mSink = aSink;
114 0 : }
115 0 : ReadbackSink* GetSink() { return mSink; }
116 :
117 : /**
118 : * CONSTRUCTION PHASE ONLY
119 : * Set the size of content that should be read back. The readback area
120 : * has its top-left at 0,0 and has size aSize.
121 : * Can only be called while the sink is null!
122 : */
123 0 : void SetSize(const gfx::IntSize& aSize)
124 : {
125 0 : NS_ASSERTION(!mSink, "Should have no sink while changing size!");
126 0 : mSize = aSize;
127 0 : }
128 0 : const gfx::IntSize& GetSize() { return mSize; }
129 0 : gfx::IntRect GetRect() { return gfx::IntRect(gfx::IntPoint(0, 0), mSize); }
130 :
131 0 : bool IsBackgroundKnown()
132 : {
133 0 : return mBackgroundLayer || mBackgroundColor.a == 1.f;
134 : }
135 :
136 0 : void NotifyRemoved() {
137 0 : SetUnknown();
138 0 : mSink = nullptr;
139 0 : }
140 :
141 0 : void NotifyPaintedLayerRemoved(PaintedLayer* aLayer)
142 : {
143 0 : if (mBackgroundLayer == aLayer) {
144 0 : mBackgroundLayer = nullptr;
145 : }
146 0 : }
147 :
148 0 : const nsIntPoint& GetBackgroundLayerOffset() { return mBackgroundLayerOffset; }
149 :
150 0 : uint64_t AllocateSequenceNumber() { return ++mSequenceCounter; }
151 :
152 0 : void SetUnknown()
153 : {
154 0 : if (IsBackgroundKnown()) {
155 0 : if (mSink) {
156 0 : mSink->SetUnknown(AllocateSequenceNumber());
157 : }
158 0 : mBackgroundLayer = nullptr;
159 0 : mBackgroundColor = gfx::Color();
160 : }
161 0 : }
162 :
163 : protected:
164 : friend class ReadbackProcessor;
165 :
166 0 : ReadbackLayer(LayerManager* aManager, void* aImplData) :
167 : Layer(aManager, aImplData),
168 : mSequenceCounter(0),
169 : mSize(0,0),
170 : mBackgroundLayer(nullptr),
171 : mBackgroundLayerOffset(0, 0),
172 0 : mBackgroundColor(gfx::Color())
173 0 : {}
174 :
175 : virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix) override;
176 :
177 : virtual void DumpPacket(layerscope::LayersPacket* aPacket, const void* aParent) override;
178 :
179 : uint64_t mSequenceCounter;
180 : nsAutoPtr<ReadbackSink> mSink;
181 : gfx::IntSize mSize;
182 :
183 : // This can refer to any (earlier) sibling PaintedLayer. That PaintedLayer
184 : // must have mUsedForReadback set on it. If the PaintedLayer is removed
185 : // for the container, this will be set to null by NotifyPaintedLayerRemoved.
186 : // This PaintedLayer contains the contents which have previously been reported
187 : // to mSink. The PaintedLayer had only an integer translation transform,
188 : // and it covered the entire readback area. This layer also had only an
189 : // integer translation transform.
190 : PaintedLayer* mBackgroundLayer;
191 : // When mBackgroundLayer is non-null, this is the offset to add to
192 : // convert from the coordinates of mBackgroundLayer to the coordinates
193 : // of this layer.
194 : nsIntPoint mBackgroundLayerOffset;
195 : // When mBackgroundColor is opaque, this is the color of the ColorLayer
196 : // that contained the contents we reported to mSink, which covered the
197 : // entire readback area.
198 : gfx::Color mBackgroundColor;
199 : };
200 :
201 : } // namespace layers
202 : } // namespace mozilla
203 :
204 : #endif /* GFX_READBACKLAYER_H */
|