Source code

Revision control

Other Tools

1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
* License, v. 2.0. If a copy of the MPL was not distributed with this
5
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#ifndef GFX_READBACKLAYER_H
8
#define GFX_READBACKLAYER_H
9
10
#include <stdint.h> // for uint64_t
11
#include "Layers.h" // for Layer, etc
12
#include "mozilla/gfx/Rect.h" // for gfxRect
13
#include "mozilla/gfx/Point.h" // for IntPoint
14
#include "mozilla/mozalloc.h" // for operator delete
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
ReadbackSink() = default;
39
virtual ~ReadbackSink() = default;
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> BeginUpdate(
62
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
class ReadbackLayer : public Layer {
85
public:
86
MOZ_LAYER_DECL_NAME("ReadbackLayer", TYPE_READBACK)
87
88
virtual void ComputeEffectiveTransforms(
89
const gfx::Matrix4x4& aTransformToSurface) override {
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
mEffectiveTransform =
95
SnapTransform(GetLocalTransform(),
96
gfxRect(0, 0, mSize.width, mSize.height), nullptr) *
97
SnapTransformTranslation(aTransformToSurface, nullptr);
98
}
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
void SetSink(ReadbackSink* aSink) {
111
SetUnknown();
112
mSink = mozilla::WrapUnique(aSink);
113
}
114
ReadbackSink* GetSink() { return mSink.get(); }
115
116
/**
117
* CONSTRUCTION PHASE ONLY
118
* Set the size of content that should be read back. The readback area
119
* has its top-left at 0,0 and has size aSize.
120
* Can only be called while the sink is null!
121
*/
122
void SetSize(const gfx::IntSize& aSize) {
123
NS_ASSERTION(!mSink, "Should have no sink while changing size!");
124
mSize = aSize;
125
}
126
const gfx::IntSize& GetSize() { return mSize; }
127
gfx::IntRect GetRect() { return gfx::IntRect(gfx::IntPoint(0, 0), mSize); }
128
129
bool IsBackgroundKnown() {
130
return mBackgroundLayer || mBackgroundColor.a == 1.f;
131
}
132
133
void NotifyRemoved() {
134
SetUnknown();
135
mSink = nullptr;
136
}
137
138
void NotifyPaintedLayerRemoved(PaintedLayer* aLayer) {
139
if (mBackgroundLayer == aLayer) {
140
mBackgroundLayer = nullptr;
141
}
142
}
143
144
const nsIntPoint& GetBackgroundLayerOffset() {
145
return mBackgroundLayerOffset;
146
}
147
148
uint64_t AllocateSequenceNumber() { return ++mSequenceCounter; }
149
150
void SetUnknown() {
151
if (IsBackgroundKnown()) {
152
if (mSink) {
153
mSink->SetUnknown(AllocateSequenceNumber());
154
}
155
mBackgroundLayer = nullptr;
156
mBackgroundColor = gfx::DeviceColor();
157
}
158
}
159
160
protected:
161
friend class ReadbackProcessor;
162
163
ReadbackLayer(LayerManager* aManager, void* aImplData)
164
: Layer(aManager, aImplData),
165
mSequenceCounter(0),
166
mSize(0, 0),
167
mBackgroundLayer(nullptr),
168
mBackgroundLayerOffset(0, 0),
169
mBackgroundColor(gfx::DeviceColor()) {}
170
171
virtual void PrintInfo(std::stringstream& aStream,
172
const char* aPrefix) override;
173
174
virtual void DumpPacket(layerscope::LayersPacket* aPacket,
175
const void* aParent) override;
176
177
uint64_t mSequenceCounter;
178
UniquePtr<ReadbackSink> mSink;
179
gfx::IntSize mSize;
180
181
// This can refer to any (earlier) sibling PaintedLayer. That PaintedLayer
182
// must have mUsedForReadback set on it. If the PaintedLayer is removed
183
// for the container, this will be set to null by NotifyPaintedLayerRemoved.
184
// This PaintedLayer contains the contents which have previously been reported
185
// to mSink. The PaintedLayer had only an integer translation transform,
186
// and it covered the entire readback area. This layer also had only an
187
// integer translation transform.
188
PaintedLayer* mBackgroundLayer;
189
// When mBackgroundLayer is non-null, this is the offset to add to
190
// convert from the coordinates of mBackgroundLayer to the coordinates
191
// of this layer.
192
nsIntPoint mBackgroundLayerOffset;
193
// When mBackgroundColor is opaque, this is the color of the ColorLayer
194
// that contained the contents we reported to mSink, which covered the
195
// entire readback area.
196
gfx::DeviceColor mBackgroundColor;
197
};
198
199
} // namespace layers
200
} // namespace mozilla
201
202
#endif /* GFX_READBACKLAYER_H */