Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
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/. */
6 #ifndef ROTATEDBUFFER_H_
7 #define ROTATEDBUFFER_H_
9 #include "gfxTypes.h"
10 #include <stdint.h> // for uint32_t
11 #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
12 #include "mozilla/RefPtr.h" // for RefPtr, TemporaryRef
13 #include "mozilla/gfx/2D.h" // for DrawTarget, etc
14 #include "mozilla/mozalloc.h" // for operator delete
15 #include "nsAutoPtr.h" // for nsRefPtr
16 #include "nsCOMPtr.h" // for already_AddRefed
17 #include "nsDebug.h" // for NS_RUNTIMEABORT
18 #include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc
19 #include "nsPoint.h" // for nsIntPoint
20 #include "nsRect.h" // for nsIntRect
21 #include "nsRegion.h" // for nsIntRegion
22 #include "LayersTypes.h"
24 struct nsIntSize;
26 namespace mozilla {
27 namespace gfx {
28 class Matrix;
29 }
31 namespace layers {
33 class TextureClient;
34 class ThebesLayer;
36 /**
37 * This is a cairo/Thebes surface, but with a literal twist. Scrolling
38 * causes the layer's visible region to move. We want to keep
39 * reusing the same surface if the region size hasn't changed, but we don't
40 * want to keep moving the contents of the surface around in memory. So
41 * we use a trick.
42 * Consider just the vertical case, and suppose the buffer is H pixels
43 * high and we're scrolling down by N pixels. Instead of copying the
44 * buffer contents up by N pixels, we leave the buffer contents in place,
45 * and paint content rows H to H+N-1 into rows 0 to N-1 of the buffer.
46 * Then we can refresh the screen by painting rows N to H-1 of the buffer
47 * at row 0 on the screen, and then painting rows 0 to N-1 of the buffer
48 * at row H-N on the screen.
49 * mBufferRotation.y would be N in this example.
50 */
51 class RotatedBuffer {
52 public:
53 typedef gfxContentType ContentType;
55 RotatedBuffer(gfx::DrawTarget* aDTBuffer, gfx::DrawTarget* aDTBufferOnWhite,
56 const nsIntRect& aBufferRect,
57 const nsIntPoint& aBufferRotation)
58 : mDTBuffer(aDTBuffer)
59 , mDTBufferOnWhite(aDTBufferOnWhite)
60 , mBufferRect(aBufferRect)
61 , mBufferRotation(aBufferRotation)
62 , mDidSelfCopy(false)
63 { }
64 RotatedBuffer()
65 : mDidSelfCopy(false)
66 { }
68 /*
69 * Which buffer should be drawn to/read from.
70 */
71 enum ContextSource {
72 BUFFER_BLACK, // The normal buffer, or buffer with black background when using component alpha.
73 BUFFER_WHITE, // The buffer with white background, only valid with component alpha.
74 BUFFER_BOTH // The combined black/white buffers, only valid for writing operations, not reading.
75 };
76 // It is the callers repsonsibility to ensure aTarget is flushed after calling
77 // this method.
78 void DrawBufferWithRotation(gfx::DrawTarget* aTarget, ContextSource aSource,
79 float aOpacity = 1.0,
80 gfx::CompositionOp aOperator = gfx::CompositionOp::OP_OVER,
81 gfx::SourceSurface* aMask = nullptr,
82 const gfx::Matrix* aMaskTransform = nullptr) const;
84 /**
85 * |BufferRect()| is the rect of device pixels that this
86 * RotatedBuffer covers. That is what DrawBufferWithRotation()
87 * will paint when it's called.
88 */
89 const nsIntRect& BufferRect() const { return mBufferRect; }
90 const nsIntPoint& BufferRotation() const { return mBufferRotation; }
92 virtual bool HaveBuffer() const { return mDTBuffer; }
93 virtual bool HaveBufferOnWhite() const { return mDTBufferOnWhite; }
95 protected:
97 enum XSide {
98 LEFT, RIGHT
99 };
100 enum YSide {
101 TOP, BOTTOM
102 };
103 nsIntRect GetQuadrantRectangle(XSide aXSide, YSide aYSide) const;
105 gfx::Rect GetSourceRectangle(XSide aXSide, YSide aYSide) const;
107 /*
108 * If aMask is non-null, then it is used as an alpha mask for rendering this
109 * buffer. aMaskTransform must be non-null if aMask is non-null, and is used
110 * to adjust the coordinate space of the mask.
111 */
112 void DrawBufferQuadrant(gfx::DrawTarget* aTarget, XSide aXSide, YSide aYSide,
113 ContextSource aSource,
114 float aOpacity,
115 gfx::CompositionOp aOperator,
116 gfx::SourceSurface* aMask,
117 const gfx::Matrix* aMaskTransform) const;
119 RefPtr<gfx::DrawTarget> mDTBuffer;
120 RefPtr<gfx::DrawTarget> mDTBufferOnWhite;
121 /** The area of the ThebesLayer that is covered by the buffer as a whole */
122 nsIntRect mBufferRect;
123 /**
124 * The x and y rotation of the buffer. Conceptually the buffer
125 * has its origin translated to mBufferRect.TopLeft() - mBufferRotation,
126 * is tiled to fill the plane, and the result is clipped to mBufferRect.
127 * So the pixel at mBufferRotation within the buffer is what gets painted at
128 * mBufferRect.TopLeft().
129 * This is "rotation" in the sense of rotating items in a linear buffer,
130 * where items falling off the end of the buffer are returned to the
131 * buffer at the other end, not 2D rotation!
132 */
133 nsIntPoint mBufferRotation;
134 // When this is true it means that all pixels have moved inside the buffer.
135 // It's not possible to sync with another buffer without a full copy.
136 bool mDidSelfCopy;
137 };
139 // Mixin class for classes which need logic for loaning out a draw target.
140 // See comments on BorrowDrawTargetForQuadrantUpdate.
141 class BorrowDrawTarget
142 {
143 protected:
144 void ReturnDrawTarget(gfx::DrawTarget*& aReturned);
146 // The draw target loaned by BorrowDrawTargetForQuadrantUpdate. It should not
147 // be used, we just keep a reference to ensure it is kept alive and so we can
148 // correctly restore state when it is returned.
149 RefPtr<gfx::DrawTarget> mLoanedDrawTarget;
150 gfx::Matrix mLoanedTransform;
151 };
153 /**
154 * This class encapsulates the buffer used to retain ThebesLayer contents,
155 * i.e., the contents of the layer's GetVisibleRegion().
156 */
157 class RotatedContentBuffer : public RotatedBuffer
158 , public BorrowDrawTarget
159 {
160 public:
161 typedef gfxContentType ContentType;
163 /**
164 * Controls the size of the backing buffer of this.
165 * - SizedToVisibleBounds: the backing buffer is exactly the same
166 * size as the bounds of ThebesLayer's visible region
167 * - ContainsVisibleBounds: the backing buffer is large enough to
168 * fit visible bounds. May be larger.
169 */
170 enum BufferSizePolicy {
171 SizedToVisibleBounds,
172 ContainsVisibleBounds
173 };
175 RotatedContentBuffer(BufferSizePolicy aBufferSizePolicy)
176 : mBufferProvider(nullptr)
177 , mBufferProviderOnWhite(nullptr)
178 , mBufferSizePolicy(aBufferSizePolicy)
179 {
180 MOZ_COUNT_CTOR(RotatedContentBuffer);
181 }
182 virtual ~RotatedContentBuffer()
183 {
184 MOZ_COUNT_DTOR(RotatedContentBuffer);
185 }
187 /**
188 * Wipe out all retained contents. Call this when the entire
189 * buffer becomes invalid.
190 */
191 void Clear()
192 {
193 mDTBuffer = nullptr;
194 mDTBufferOnWhite = nullptr;
195 mBufferProvider = nullptr;
196 mBufferProviderOnWhite = nullptr;
197 mBufferRect.SetEmpty();
198 }
200 /**
201 * This is returned by BeginPaint. The caller should draw into mTarget.
202 * mRegionToDraw must be drawn. mRegionToInvalidate has been invalidated
203 * by RotatedContentBuffer and must be redrawn on the screen.
204 * mRegionToInvalidate is set when the buffer has changed from
205 * opaque to transparent or vice versa, since the details of rendering can
206 * depend on the buffer type. mDidSelfCopy is true if we kept our buffer
207 * but used MovePixels() to shift its content.
208 */
209 struct PaintState {
210 PaintState()
211 : mMode(SurfaceMode::SURFACE_NONE)
212 , mContentType(gfxContentType::SENTINEL)
213 , mDidSelfCopy(false)
214 {}
216 nsIntRegion mRegionToDraw;
217 nsIntRegion mRegionToInvalidate;
218 SurfaceMode mMode;
219 DrawRegionClip mClip;
220 ContentType mContentType;
221 bool mDidSelfCopy;
222 };
224 enum {
225 PAINT_WILL_RESAMPLE = 0x01,
226 PAINT_NO_ROTATION = 0x02,
227 PAINT_CAN_DRAW_ROTATED = 0x04
228 };
229 /**
230 * Start a drawing operation. This returns a PaintState describing what
231 * needs to be drawn to bring the buffer up to date in the visible region.
232 * This queries aLayer to get the currently valid and visible regions.
233 * The returned mTarget may be null if mRegionToDraw is empty.
234 * Otherwise it must not be null.
235 * mRegionToInvalidate will contain mRegionToDraw.
236 * @param aFlags when PAINT_WILL_RESAMPLE is passed, this indicates that
237 * buffer will be resampled when rendering (i.e the effective transform
238 * combined with the scale for the resolution is not just an integer
239 * translation). This will disable buffer rotation (since we don't want
240 * to resample across the rotation boundary) and will ensure that we
241 * make the entire buffer contents valid (since we don't want to sample
242 * invalid pixels outside the visible region, if the visible region doesn't
243 * fill the buffer bounds).
244 * PAINT_CAN_DRAW_ROTATED can be passed if the caller supports drawing
245 * rotated content that crosses the physical buffer boundary. The caller
246 * will need to call BorrowDrawTargetForPainting multiple times to achieve
247 * this.
248 */
249 PaintState BeginPaint(ThebesLayer* aLayer,
250 uint32_t aFlags);
252 struct DrawIterator {
253 friend class RotatedContentBuffer;
254 friend class ContentClientIncremental;
255 DrawIterator()
256 : mCount(0)
257 {}
259 nsIntRegion mDrawRegion;
261 private:
262 uint32_t mCount;
263 };
265 /**
266 * Fetch a DrawTarget for rendering. The DrawTarget remains owned by
267 * this. See notes on BorrowDrawTargetForQuadrantUpdate.
268 * May return null. If the return value is non-null, it must be
269 * 'un-borrowed' using ReturnDrawTarget.
270 *
271 * If PAINT_CAN_DRAW_ROTATED was specified for BeginPaint, then the caller
272 * must call this function repeatedly (with an iterator) until it returns
273 * nullptr. The caller should draw the mDrawRegion of the iterator instead
274 * of mRegionToDraw in the PaintState.
275 *
276 * @param aPaintState Paint state data returned by a call to BeginPaint
277 * @param aIter Paint state iterator. Only required if PAINT_CAN_DRAW_ROTATED
278 * was specified to BeginPaint.
279 */
280 gfx::DrawTarget* BorrowDrawTargetForPainting(const PaintState& aPaintState,
281 DrawIterator* aIter = nullptr);
283 enum {
284 ALLOW_REPEAT = 0x01,
285 BUFFER_COMPONENT_ALPHA = 0x02 // Dual buffers should be created for drawing with
286 // component alpha.
287 };
288 /**
289 * Return a new surface of |aSize| and |aType|.
290 * @param aFlags if ALLOW_REPEAT is set, then the buffer should be configured
291 * to allow repeat-mode, otherwise it should be in pad (clamp) mode
292 * If the created buffer supports azure content, then the result(s) will
293 * be returned in aBlackDT/aWhiteDT, otherwise aBlackSurface/aWhiteSurface
294 * will be used.
295 */
296 virtual void
297 CreateBuffer(ContentType aType, const nsIntRect& aRect, uint32_t aFlags,
298 RefPtr<gfx::DrawTarget>* aBlackDT, RefPtr<gfx::DrawTarget>* aWhiteDT) = 0;
300 /**
301 * Get the underlying buffer, if any. This is useful because we can pass
302 * in the buffer as the default "reference surface" if there is one.
303 * Don't use it for anything else!
304 */
305 gfx::DrawTarget* GetDTBuffer() { return mDTBuffer; }
306 gfx::DrawTarget* GetDTBufferOnWhite() { return mDTBufferOnWhite; }
308 /**
309 * Complete the drawing operation. The region to draw must have been
310 * drawn before this is called. The contents of the buffer are drawn
311 * to aTarget.
312 */
313 void DrawTo(ThebesLayer* aLayer,
314 gfx::DrawTarget* aTarget,
315 float aOpacity,
316 gfx::CompositionOp aOp,
317 gfx::SourceSurface* aMask,
318 const gfx::Matrix* aMaskTransform);
320 protected:
321 // new texture client versions
322 void SetBufferProvider(TextureClient* aClient)
323 {
324 // Only this buffer provider can give us a buffer. If we
325 // already have one, something has gone wrong.
326 MOZ_ASSERT(!aClient || !mDTBuffer);
328 mBufferProvider = aClient;
329 if (!mBufferProvider) {
330 mDTBuffer = nullptr;
331 }
332 }
334 void SetBufferProviderOnWhite(TextureClient* aClient)
335 {
336 // Only this buffer provider can give us a buffer. If we
337 // already have one, something has gone wrong.
338 MOZ_ASSERT(!aClient || !mDTBufferOnWhite);
340 mBufferProviderOnWhite = aClient;
341 if (!mBufferProviderOnWhite) {
342 mDTBufferOnWhite = nullptr;
343 }
344 }
346 /**
347 * Get a draw target at the specified resolution for updating |aBounds|,
348 * which must be contained within a single quadrant.
349 *
350 * The result should only be held temporarily by the caller (it will be kept
351 * alive by this). Once used it should be returned using ReturnDrawTarget.
352 * BorrowDrawTargetForQuadrantUpdate may not be called more than once without
353 * first calling ReturnDrawTarget.
354 *
355 * ReturnDrawTarget will restore the transform on the draw target. But it is
356 * the callers responsibility to restore the clip. The caller should flush the
357 * draw target, if necessary.
358 */
359 gfx::DrawTarget*
360 BorrowDrawTargetForQuadrantUpdate(const nsIntRect& aBounds,
361 ContextSource aSource,
362 DrawIterator* aIter);
364 static bool IsClippingCheap(gfx::DrawTarget* aTarget, const nsIntRegion& aRegion);
366 protected:
367 /**
368 * Return the buffer's content type. Requires a valid buffer or
369 * buffer provider.
370 */
371 gfxContentType BufferContentType();
372 bool BufferSizeOkFor(const nsIntSize& aSize);
373 /**
374 * If the buffer hasn't been mapped, map it.
375 */
376 bool EnsureBuffer();
377 bool EnsureBufferOnWhite();
379 // Flush our buffers if they are mapped.
380 void FlushBuffers();
382 /**
383 * True if we have a buffer where we can get it (but not necessarily
384 * mapped currently).
385 */
386 virtual bool HaveBuffer() const;
387 virtual bool HaveBufferOnWhite() const;
389 /**
390 * Any actions that should be performed at the last moment before we begin
391 * rendering the next frame. I.e., after we calculate what we will draw,
392 * but before we rotate the buffer and possibly create new buffers.
393 * aRegionToDraw is the region which is guaranteed to be overwritten when
394 * drawing the next frame.
395 */
396 virtual void FinalizeFrame(const nsIntRegion& aRegionToDraw) {}
398 /**
399 * These members are only set transiently. They're used to map mDTBuffer
400 * when we're using surfaces that require explicit map/unmap. Only one
401 * may be used at a time.
402 */
403 TextureClient* mBufferProvider;
404 TextureClient* mBufferProviderOnWhite;
406 BufferSizePolicy mBufferSizePolicy;
407 };
409 }
410 }
412 #endif /* ROTATEDBUFFER_H_ */