1 : /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 : * ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is Mozilla Corporation code.
16 : *
17 : * The Initial Developer of the Original Code is Mozilla Foundation.
18 : * Portions created by the Initial Developer are Copyright (C) 2011
19 : * the Initial Developer. All Rights Reserved.
20 : *
21 : * Contributor(s):
22 : * Robert O'Callahan <robert@ocallahan.org>
23 : *
24 : * Alternatively, the contents of this file may be used under the terms of
25 : * either the GNU General Public License Version 2 or later (the "GPL"), or
26 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 : * in which case the provisions of the GPL or the LGPL are applicable instead
28 : * of those above. If you wish to allow use of your version of this file only
29 : * under the terms of either the GPL or the LGPL, and not to allow others to
30 : * use your version of this file under the terms of the MPL, indicate your
31 : * decision by deleting the provisions above and replace them with the notice
32 : * and other provisions required by the GPL or the LGPL. If you do not delete
33 : * the provisions above, a recipient may use your version of this file under
34 : * the terms of any one of the MPL, the GPL or the LGPL.
35 : *
36 : * ***** END LICENSE BLOCK ***** */
37 :
38 : #ifndef GFX_READBACKLAYER_H
39 : #define GFX_READBACKLAYER_H
40 :
41 : #include "Layers.h"
42 :
43 : namespace mozilla {
44 : namespace layers {
45 :
46 : class ReadbackProcessor;
47 :
48 : /**
49 : * A ReadbackSink receives a stream of updates to a rectangle of pixels.
50 : * These update callbacks are always called on the main thread, either during
51 : * EndTransaction or from the event loop.
52 : */
53 : class THEBES_API ReadbackSink {
54 : public:
55 : ReadbackSink() {}
56 : virtual ~ReadbackSink() {}
57 :
58 : /**
59 : * Sends an update to indicate that the background is currently unknown.
60 : */
61 : virtual void SetUnknown(PRUint64 aSequenceNumber) = 0;
62 : /**
63 : * Called by the layer system to indicate that the contents of part of
64 : * the readback area are changing.
65 : * @param aRect is the rectangle of content that is being updated,
66 : * in the coordinate system of the ReadbackLayer.
67 : * @param aSequenceNumber updates issued out of order should be ignored.
68 : * Only use updates whose sequence counter is greater than all other updates
69 : * seen so far. Return null when a non-fresh sequence value is given.
70 : * @return a context into which the update should be drawn. This should be
71 : * set up to clip to aRect. Zero should never be passed as a sequence number.
72 : * If this returns null, EndUpdate should NOT be called. If it returns
73 : * non-null, EndUpdate must be called.
74 : *
75 : * We don't support partially unknown backgrounds. Therefore, the
76 : * first BeginUpdate after a SetUnknown will have the complete background.
77 : */
78 : virtual already_AddRefed<gfxContext>
79 : BeginUpdate(const nsIntRect& aRect, PRUint64 aSequenceNumber) = 0;
80 : /**
81 : * EndUpdate must be called immediately after BeginUpdate, without returning
82 : * to the event loop.
83 : * @param aContext the context returned by BeginUpdate
84 : * Implicitly Restore()s the state of aContext.
85 : */
86 : virtual void EndUpdate(gfxContext* aContext, const nsIntRect& aRect) = 0;
87 : };
88 :
89 : /**
90 : * A ReadbackLayer never renders anything. It enables clients to extract
91 : * the rendered contents of the layer tree below the ReadbackLayer.
92 : * The rendered contents are delivered asynchronously via calls to a
93 : * ReadbackSink object supplied by the client.
94 : *
95 : * This is a "best effort" API; it is possible for the layer system to tell
96 : * the ReadbackSink that the contents of the readback area are unknown.
97 : *
98 : * This API exists to work around the limitations of transparent windowless
99 : * plugin rendering APIs. It should not be used for anything else.
100 : */
101 0 : class THEBES_API ReadbackLayer : public Layer {
102 : public:
103 0 : MOZ_LAYER_DECL_NAME("ReadbackLayer", TYPE_READBACK)
104 :
105 0 : virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface)
106 : {
107 : // Snap our local transform first, and snap the inherited transform as well.
108 : // This makes our snapping equivalent to what would happen if our content
109 : // was drawn into a ThebesLayer (gfxContext would snap using the local
110 : // transform, then we'd snap again when compositing the ThebesLayer).
111 : mEffectiveTransform =
112 0 : SnapTransform(GetLocalTransform(), gfxRect(0, 0, mSize.width, mSize.height),
113 0 : nsnull)*
114 0 : SnapTransform(aTransformToSurface, gfxRect(0, 0, 0, 0), nsnull);
115 0 : }
116 :
117 : /**
118 : * CONSTRUCTION PHASE ONLY
119 : * Set the callback object to which readback updates will be delivered.
120 : * This also resets the "needed rectangle" so that on the next layer tree
121 : * transaction we will try to deliver the full contents of the readback
122 : * area to the sink.
123 : * This layer takes ownership of the sink. It will be deleted when the
124 : * layer is destroyed or when a new sink is set.
125 : * Initially the contents of the readback area are completely unknown.
126 : */
127 : void SetSink(ReadbackSink* aSink)
128 : {
129 : SetUnknown();
130 : mSink = aSink;
131 : }
132 0 : ReadbackSink* GetSink() { return mSink; }
133 :
134 : /**
135 : * CONSTRUCTION PHASE ONLY
136 : * Set the size of content that should be read back. The readback area
137 : * has its top-left at 0,0 and has size aSize.
138 : * Can only be called while the sink is null!
139 : */
140 : void SetSize(const nsIntSize& aSize)
141 : {
142 : NS_ASSERTION(!mSink, "Should have no sink while changing size!");
143 : mSize = aSize;
144 : }
145 0 : const nsIntSize& GetSize() { return mSize; }
146 0 : nsIntRect GetRect() { return nsIntRect(nsIntPoint(0, 0), mSize); }
147 :
148 0 : bool IsBackgroundKnown()
149 : {
150 0 : return mBackgroundLayer || mBackgroundColor.a == 1.0;
151 : }
152 :
153 0 : void NotifyRemoved() {
154 0 : SetUnknown();
155 0 : mSink = nsnull;
156 0 : }
157 :
158 0 : void NotifyThebesLayerRemoved(ThebesLayer* aLayer)
159 : {
160 0 : if (mBackgroundLayer == aLayer) {
161 0 : mBackgroundLayer = nsnull;
162 : }
163 0 : }
164 :
165 0 : const nsIntPoint& GetBackgroundLayerOffset() { return mBackgroundLayerOffset; }
166 :
167 0 : PRUint64 AllocateSequenceNumber() { return ++mSequenceCounter; }
168 :
169 0 : void SetUnknown()
170 : {
171 0 : if (IsBackgroundKnown()) {
172 0 : if (mSink) {
173 0 : mSink->SetUnknown(AllocateSequenceNumber());
174 : }
175 0 : mBackgroundLayer = nsnull;
176 0 : mBackgroundColor = gfxRGBA(0,0,0,0);
177 : }
178 0 : }
179 :
180 : protected:
181 : friend class ReadbackProcessor;
182 :
183 0 : ReadbackLayer(LayerManager* aManager, void* aImplData) :
184 : Layer(aManager, aImplData),
185 : mSequenceCounter(0),
186 : mSize(0,0),
187 : mBackgroundLayer(nsnull),
188 : mBackgroundLayerOffset(0, 0),
189 0 : mBackgroundColor(gfxRGBA(0,0,0,0))
190 0 : {}
191 :
192 : // Print interesting information about this into aTo. Internally
193 : // used to implement Dump*() and Log*().
194 : virtual nsACString& PrintInfo(nsACString& aTo, const char* aPrefix);
195 :
196 : PRUint64 mSequenceCounter;
197 : nsAutoPtr<ReadbackSink> mSink;
198 : nsIntSize mSize;
199 :
200 : // This can refer to any (earlier) sibling ThebesLayer. That ThebesLayer
201 : // must have mUsedForReadback set on it. If the ThebesLayer is removed
202 : // for the container, this will be set to null by NotifyThebesLayerRemoved.
203 : // This ThebesLayer contains the contents which have previously been reported
204 : // to mSink. The ThebesLayer had only an integer translation transform,
205 : // and it covered the entire readback area. This layer also had only an
206 : // integer translation transform.
207 : ThebesLayer* mBackgroundLayer;
208 : // When mBackgroundLayer is non-null, this is the offset to add to
209 : // convert from the coordinates of mBackgroundLayer to the coordinates
210 : // of this layer.
211 : nsIntPoint mBackgroundLayerOffset;
212 : // When mBackgroundColor is opaque, this is the color of the ColorLayer
213 : // that contained the contents we reported to mSink, which covered the
214 : // entire readback area.
215 : gfxRGBA mBackgroundColor;
216 : };
217 :
218 : }
219 : }
220 : #endif /* GFX_READBACKLAYER_H */
|