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 THEBESLAYERBUFFER_H_
7 #define THEBESLAYERBUFFER_H_
9 #include "gfxContext.h"
10 #include "gfxASurface.h"
16 class AutoOpenSurface
;
20 * This class encapsulates the buffer used to retain ThebesLayer contents,
21 * i.e., the contents of the layer's GetVisibleRegion().
23 * This is a cairo/Thebes surface, but with a literal twist. Scrolling
24 * causes the layer's visible region to move. We want to keep
25 * reusing the same surface if the region size hasn't changed, but we don't
26 * want to keep moving the contents of the surface around in memory. So
28 * Consider just the vertical case, and suppose the buffer is H pixels
29 * high and we're scrolling down by N pixels. Instead of copying the
30 * buffer contents up by N pixels, we leave the buffer contents in place,
31 * and paint content rows H to H+N-1 into rows 0 to N-1 of the buffer.
32 * Then we can refresh the screen by painting rows N to H-1 of the buffer
33 * at row 0 on the screen, and then painting rows 0 to N-1 of the buffer
34 * at row H-N on the screen.
35 * mBufferRotation.y would be N in this example.
37 class ThebesLayerBuffer
{
39 typedef gfxASurface::gfxContentType ContentType
;
42 * Controls the size of the backing buffer of this.
43 * - SizedToVisibleBounds: the backing buffer is exactly the same
44 * size as the bounds of ThebesLayer's visible region
45 * - ContainsVisibleBounds: the backing buffer is large enough to
46 * fit visible bounds. May be larger.
48 enum BufferSizePolicy
{
53 ThebesLayerBuffer(BufferSizePolicy aBufferSizePolicy
)
54 : mBufferProvider(nullptr)
55 , mBufferRotation(0,0)
56 , mBufferSizePolicy(aBufferSizePolicy
)
58 MOZ_COUNT_CTOR(ThebesLayerBuffer
);
60 virtual ~ThebesLayerBuffer()
62 MOZ_COUNT_DTOR(ThebesLayerBuffer
);
66 * Wipe out all retained contents. Call this when the entire
67 * buffer becomes invalid.
72 mBufferProvider
= nullptr;
73 mBufferRect
.SetEmpty();
77 * This is returned by BeginPaint. The caller should draw into mContext.
78 * mRegionToDraw must be drawn. mRegionToInvalidate has been invalidated
79 * by ThebesLayerBuffer and must be redrawn on the screen.
80 * mRegionToInvalidate is set when the buffer has changed from
81 * opaque to transparent or vice versa, since the details of rendering can
82 * depend on the buffer type. mDidSelfCopy is true if we kept our buffer
83 * but used MovePixels() to shift its content.
90 nsRefPtr
<gfxContext
> mContext
;
91 nsIntRegion mRegionToDraw
;
92 nsIntRegion mRegionToInvalidate
;
97 PAINT_WILL_RESAMPLE
= 0x01,
98 PAINT_NO_ROTATION
= 0x02
101 * Start a drawing operation. This returns a PaintState describing what
102 * needs to be drawn to bring the buffer up to date in the visible region.
103 * This queries aLayer to get the currently valid and visible regions.
104 * The returned mContext may be null if mRegionToDraw is empty.
105 * Otherwise it must not be null.
106 * mRegionToInvalidate will contain mRegionToDraw.
107 * @param aFlags when PAINT_WILL_RESAMPLE is passed, this indicates that
108 * buffer will be resampled when rendering (i.e the effective transform
109 * combined with the scale for the resolution is not just an integer
110 * translation). This will disable buffer rotation (since we don't want
111 * to resample across the rotation boundary) and will ensure that we
112 * make the entire buffer contents valid (since we don't want to sample
113 * invalid pixels outside the visible region, if the visible region doesn't
114 * fill the buffer bounds).
116 PaintState
BeginPaint(ThebesLayer
* aLayer
, ContentType aContentType
,
123 * Return a new surface of |aSize| and |aType|.
124 * @param aFlags if ALLOW_REPEAT is set, then the buffer should be configured
125 * to allow repeat-mode, otherwise it should be in pad (clamp) mode
127 virtual already_AddRefed
<gfxASurface
>
128 CreateBuffer(ContentType aType
, const nsIntSize
& aSize
, uint32_t aFlags
) = 0;
131 * Get the underlying buffer, if any. This is useful because we can pass
132 * in the buffer as the default "reference surface" if there is one.
133 * Don't use it for anything else!
135 gfxASurface
* GetBuffer() { return mBuffer
; }
144 nsIntRect
GetQuadrantRectangle(XSide aXSide
, YSide aYSide
);
146 * If aMask is non-null, then it is used as an alpha mask for rendering this
147 * buffer. aMaskTransform must be non-null if aMask is non-null, and is used
148 * to adjust the coordinate space of the mask.
150 void DrawBufferQuadrant(gfxContext
* aTarget
, XSide aXSide
, YSide aYSide
,
153 const gfxMatrix
* aMaskTransform
);
154 void DrawBufferWithRotation(gfxContext
* aTarget
, float aOpacity
,
155 gfxASurface
* aMask
= nullptr,
156 const gfxMatrix
* aMaskTransform
= nullptr);
159 * |BufferRect()| is the rect of device pixels that this
160 * ThebesLayerBuffer covers. That is what DrawBufferWithRotation()
161 * will paint when it's called.
163 const nsIntRect
& BufferRect() const { return mBufferRect
; }
164 const nsIntPoint
& BufferRotation() const { return mBufferRotation
; }
166 already_AddRefed
<gfxASurface
>
167 SetBuffer(gfxASurface
* aBuffer
,
168 const nsIntRect
& aBufferRect
, const nsIntPoint
& aBufferRotation
)
170 nsRefPtr
<gfxASurface
> tmp
= mBuffer
.forget();
172 mBufferRect
= aBufferRect
;
173 mBufferRotation
= aBufferRotation
;
178 * Set the buffer provider only. This is used with surfaces that
179 * require explicit map/unmap, which |aProvider| is used to do on
180 * demand in this code.
182 * It's the caller's responsibility to ensure |aProvider| is valid
183 * for the duration of operations it requests of this
184 * ThebesLayerBuffer. It's also the caller's responsibility to
185 * unset the provider when inactive, by calling
186 * SetBufferProvider(nullptr).
188 void SetBufferProvider(AutoOpenSurface
* aProvider
)
190 mBufferProvider
= aProvider
;
191 if (!mBufferProvider
) {
194 // Only this buffer provider can give us a buffer. If we
195 // already have one, something has gone wrong.
196 MOZ_ASSERT(!mBuffer
);
201 * Get a context at the specified resolution for updating |aBounds|,
202 * which must be contained within a single quadrant.
204 already_AddRefed
<gfxContext
>
205 GetContextForQuadrantUpdate(const nsIntRect
& aBounds
);
208 // Buffer helpers. Don't use mBuffer directly; instead use one of
212 * Return the buffer's content type. Requires a valid buffer or
215 gfxASurface::gfxContentType
BufferContentType();
216 bool BufferSizeOkFor(const nsIntSize
& aSize
);
218 * If the buffer hasn't been mapped, map it and return it.
220 gfxASurface
* EnsureBuffer();
222 * True if we have a buffer where we can get it (but not necessarily
227 nsRefPtr
<gfxASurface
> mBuffer
;
229 * This member is only set transiently. It's used to map mBuffer
230 * when we're using surfaces that require explicit map/unmap.
232 AutoOpenSurface
* mBufferProvider
;
233 /** The area of the ThebesLayer that is covered by the buffer as a whole */
234 nsIntRect mBufferRect
;
236 * The x and y rotation of the buffer. Conceptually the buffer
237 * has its origin translated to mBufferRect.TopLeft() - mBufferRotation,
238 * is tiled to fill the plane, and the result is clipped to mBufferRect.
239 * So the pixel at mBufferRotation within the buffer is what gets painted at
240 * mBufferRect.TopLeft().
241 * This is "rotation" in the sense of rotating items in a linear buffer,
242 * where items falling off the end of the buffer are returned to the
243 * buffer at the other end, not 2D rotation!
245 nsIntPoint mBufferRotation
;
246 BufferSizePolicy mBufferSizePolicy
;
252 #endif /* THEBESLAYERBUFFER_H_ */