Backed out changeset 177eae915693 (bug 1206581) for bustage
[gecko.git] / image / imgFrame.h
blob5f114fd5b0e37893923247e9e6a2f816ee71624c
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
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/. */
7 #ifndef mozilla_image_imgFrame_h
8 #define mozilla_image_imgFrame_h
10 #include "mozilla/MemoryReporting.h"
11 #include "mozilla/Monitor.h"
12 #include "mozilla/Move.h"
13 #include "mozilla/VolatileBuffer.h"
14 #include "gfxDrawable.h"
15 #include "imgIContainer.h"
16 #include "MainThreadUtils.h"
18 namespace mozilla {
19 namespace image {
21 class ImageRegion;
22 class DrawableFrameRef;
23 class RawAccessFrameRef;
25 enum class BlendMethod : int8_t {
26 // All color components of the frame, including alpha, overwrite the current
27 // contents of the frame's output buffer region.
28 SOURCE,
30 // The frame should be composited onto the output buffer based on its alpha,
31 // using a simple OVER operation.
32 OVER
35 enum class DisposalMethod : int8_t {
36 CLEAR_ALL = -1, // Clear the whole image, revealing what's underneath.
37 NOT_SPECIFIED, // Leave the frame and let the new frame draw on top.
38 KEEP, // Leave the frame and let the new frame draw on top.
39 CLEAR, // Clear the frame's area, revealing what's underneath.
40 RESTORE_PREVIOUS // Restore the previous (composited) frame.
43 enum class Opacity : uint8_t {
44 OPAQUE,
45 SOME_TRANSPARENCY
48 /**
49 * AnimationData contains all of the information necessary for using an imgFrame
50 * as part of an animation.
52 * It includes pointers to the raw image data of the underlying imgFrame, but
53 * does not own that data. A RawAccessFrameRef for the underlying imgFrame must
54 * outlive the AnimationData for it to remain valid.
56 struct AnimationData
58 AnimationData(uint8_t* aRawData, uint32_t aPaletteDataLength,
59 int32_t aRawTimeout, const nsIntRect& aRect,
60 BlendMethod aBlendMethod, DisposalMethod aDisposalMethod,
61 bool aHasAlpha)
62 : mRawData(aRawData)
63 , mPaletteDataLength(aPaletteDataLength)
64 , mRawTimeout(aRawTimeout)
65 , mRect(aRect)
66 , mBlendMethod(aBlendMethod)
67 , mDisposalMethod(aDisposalMethod)
68 , mHasAlpha(aHasAlpha)
69 { }
71 uint8_t* mRawData;
72 uint32_t mPaletteDataLength;
73 int32_t mRawTimeout;
74 nsIntRect mRect;
75 BlendMethod mBlendMethod;
76 DisposalMethod mDisposalMethod;
77 bool mHasAlpha;
80 /**
81 * ScalingData contains all of the information necessary for performing
82 * high-quality (CPU-based) scaling an imgFrame.
84 * It includes pointers to the raw image data of the underlying imgFrame, but
85 * does not own that data. A RawAccessFrameRef for the underlying imgFrame must
86 * outlive the ScalingData for it to remain valid.
88 struct ScalingData
90 ScalingData(uint8_t* aRawData,
91 gfx::IntSize aSize,
92 uint32_t aBytesPerRow,
93 gfx::SurfaceFormat aFormat)
94 : mRawData(aRawData)
95 , mSize(aSize)
96 , mBytesPerRow(aBytesPerRow)
97 , mFormat(aFormat)
98 { }
100 uint8_t* mRawData;
101 gfx::IntSize mSize;
102 uint32_t mBytesPerRow;
103 gfx::SurfaceFormat mFormat;
106 class imgFrame
108 typedef gfx::Color Color;
109 typedef gfx::DataSourceSurface DataSourceSurface;
110 typedef gfx::DrawTarget DrawTarget;
111 typedef gfx::Filter Filter;
112 typedef gfx::IntSize IntSize;
113 typedef gfx::SourceSurface SourceSurface;
114 typedef gfx::SurfaceFormat SurfaceFormat;
116 public:
117 MOZ_DECLARE_REFCOUNTED_TYPENAME(imgFrame)
118 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(imgFrame)
120 imgFrame();
123 * Initialize this imgFrame with an empty surface and prepare it for being
124 * written to by a decoder.
126 * This is appropriate for use with decoded images, but it should not be used
127 * when drawing content into an imgFrame, as it may use a different graphics
128 * backend than normal content drawing.
130 nsresult InitForDecoder(const nsIntSize& aImageSize,
131 const nsIntRect& aRect,
132 SurfaceFormat aFormat,
133 uint8_t aPaletteDepth = 0,
134 bool aNonPremult = false);
136 nsresult InitForDecoder(const nsIntSize& aSize,
137 SurfaceFormat aFormat,
138 uint8_t aPaletteDepth = 0)
140 return InitForDecoder(aSize, nsIntRect(0, 0, aSize.width, aSize.height),
141 aFormat, aPaletteDepth);
146 * Initialize this imgFrame with a new surface and draw the provided
147 * gfxDrawable into it.
149 * This is appropriate to use when drawing content into an imgFrame, as it
150 * uses the same graphics backend as normal content drawing. The downside is
151 * that the underlying surface may not be stored in a volatile buffer on all
152 * platforms, and raw access to the surface (using RawAccessRef()) may be much
153 * more expensive than in the InitForDecoder() case.
155 nsresult InitWithDrawable(gfxDrawable* aDrawable,
156 const nsIntSize& aSize,
157 const SurfaceFormat aFormat,
158 Filter aFilter,
159 uint32_t aImageFlags);
161 DrawableFrameRef DrawableRef();
162 RawAccessFrameRef RawAccessRef();
165 * Make this imgFrame permanently available for raw access.
167 * This is irrevocable, and should be avoided whenever possible, since it
168 * prevents this imgFrame from being optimized and makes it impossible for its
169 * volatile buffer to be freed.
171 * It is an error to call this without already holding a RawAccessFrameRef to
172 * this imgFrame.
174 void SetRawAccessOnly();
176 bool Draw(gfxContext* aContext, const ImageRegion& aRegion,
177 Filter aFilter, uint32_t aImageFlags);
179 nsresult ImageUpdated(const nsIntRect& aUpdateRect);
182 * Mark this imgFrame as completely decoded, and set final options.
184 * You must always call either Finish() or Abort() before releasing the last
185 * RawAccessFrameRef pointing to an imgFrame.
187 * @param aFrameOpacity Whether this imgFrame is opaque.
188 * @param aDisposalMethod For animation frames, how this imgFrame is cleared
189 * from the compositing frame before the next frame is
190 * displayed.
191 * @param aRawTimeout For animation frames, the timeout in milliseconds
192 * before the next frame is displayed. This timeout is
193 * not necessarily the timeout that will actually be
194 * used; see FrameAnimator::GetTimeoutForFrame.
195 * @param aBlendMethod For animation frames, a blending method to be used
196 * when compositing this frame.
198 void Finish(Opacity aFrameOpacity = Opacity::SOME_TRANSPARENCY,
199 DisposalMethod aDisposalMethod = DisposalMethod::KEEP,
200 int32_t aRawTimeout = 0,
201 BlendMethod aBlendMethod = BlendMethod::OVER);
204 * Mark this imgFrame as aborted. This informs the imgFrame that if it isn't
205 * completely decoded now, it never will be.
207 * You must always call either Finish() or Abort() before releasing the last
208 * RawAccessFrameRef pointing to an imgFrame.
210 void Abort();
213 * Returns true if this imgFrame is completely decoded.
215 bool IsImageComplete() const;
218 * Blocks until this imgFrame is either completely decoded, or is marked as
219 * aborted.
221 * Note that calling this on the main thread _blocks the main thread_. Be very
222 * careful in your use of this method to avoid excessive main thread jank or
223 * deadlock.
225 void WaitUntilComplete() const;
228 * Returns the number of bytes per pixel this imgFrame requires. This is a
229 * worst-case value that does not take into account the effects of format
230 * changes caused by Optimize(), since an imgFrame is not optimized throughout
231 * its lifetime.
233 uint32_t GetBytesPerPixel() const { return GetIsPaletted() ? 1 : 4; }
235 IntSize GetImageSize() const { return mImageSize; }
236 nsIntRect GetRect() const;
237 IntSize GetSize() const { return mSize; }
238 bool NeedsPadding() const { return mOffset != nsIntPoint(0, 0); }
239 void GetImageData(uint8_t** aData, uint32_t* length) const;
240 uint8_t* GetImageData() const;
242 bool GetIsPaletted() const;
243 void GetPaletteData(uint32_t** aPalette, uint32_t* length) const;
244 uint32_t* GetPaletteData() const;
245 uint8_t GetPaletteDepth() const { return mPaletteDepth; }
248 * Get the SurfaceFormat for this imgFrame.
250 * This should only be used for assertions.
252 SurfaceFormat GetFormat() const;
254 AnimationData GetAnimationData() const;
255 ScalingData GetScalingData() const;
257 bool GetCompositingFailed() const;
258 void SetCompositingFailed(bool val);
260 void SetOptimizable();
262 Color SinglePixelColor() const;
263 bool IsSinglePixel() const;
265 already_AddRefed<SourceSurface> GetSurface();
266 already_AddRefed<DrawTarget> GetDrawTarget();
268 void AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf, size_t& aHeapSizeOut,
269 size_t& aNonHeapSizeOut) const;
271 private: // methods
273 ~imgFrame();
275 nsresult LockImageData();
276 nsresult UnlockImageData();
277 nsresult Optimize();
279 void AssertImageDataLocked() const;
281 bool IsImageCompleteInternal() const;
282 nsresult ImageUpdatedInternal(const nsIntRect& aUpdateRect);
283 void GetImageDataInternal(uint8_t** aData, uint32_t* length) const;
284 uint32_t GetImageBytesPerRow() const;
285 uint32_t GetImageDataLength() const;
286 int32_t GetStride() const;
287 already_AddRefed<SourceSurface> GetSurfaceInternal();
289 uint32_t PaletteDataLength() const
291 return mPaletteDepth ? (size_t(1) << mPaletteDepth) * sizeof(uint32_t)
292 : 0;
295 struct SurfaceWithFormat {
296 RefPtr<gfxDrawable> mDrawable;
297 SurfaceFormat mFormat;
298 SurfaceWithFormat() { }
299 SurfaceWithFormat(gfxDrawable* aDrawable, SurfaceFormat aFormat)
300 : mDrawable(aDrawable), mFormat(aFormat)
302 bool IsValid() { return !!mDrawable; }
305 SurfaceWithFormat SurfaceForDrawing(bool aDoPadding,
306 bool aDoPartialDecode,
307 bool aDoTile,
308 gfxContext* aContext,
309 const nsIntMargin& aPadding,
310 gfxRect& aImageRect,
311 ImageRegion& aRegion,
312 SourceSurface* aSurface);
314 private: // data
315 friend class DrawableFrameRef;
316 friend class RawAccessFrameRef;
317 friend class UnlockImageDataRunnable;
319 //////////////////////////////////////////////////////////////////////////////
320 // Thread-safe mutable data, protected by mMonitor.
321 //////////////////////////////////////////////////////////////////////////////
323 mutable Monitor mMonitor;
325 RefPtr<DataSourceSurface> mImageSurface;
326 RefPtr<SourceSurface> mOptSurface;
328 RefPtr<VolatileBuffer> mVBuf;
329 VolatileBufferPtr<uint8_t> mVBufPtr;
331 nsIntRect mDecoded;
333 //! Number of RawAccessFrameRefs currently alive for this imgFrame.
334 int32_t mLockCount;
336 //! Raw timeout for this frame. (See FrameAnimator::GetTimeoutForFrame.)
337 int32_t mTimeout; // -1 means display forever.
339 DisposalMethod mDisposalMethod;
340 BlendMethod mBlendMethod;
341 SurfaceFormat mFormat;
343 bool mHasNoAlpha;
344 bool mAborted;
345 bool mOptimizable;
348 //////////////////////////////////////////////////////////////////////////////
349 // Effectively const data, only mutated in the Init methods.
350 //////////////////////////////////////////////////////////////////////////////
352 IntSize mImageSize;
353 IntSize mSize;
354 nsIntPoint mOffset;
356 // The palette and image data for images that are paletted, since Cairo
357 // doesn't support these images.
358 // The paletted data comes first, then the image data itself.
359 // Total length is PaletteDataLength() + GetImageDataLength().
360 uint8_t* mPalettedImageData;
361 uint8_t mPaletteDepth;
363 bool mNonPremult;
366 //////////////////////////////////////////////////////////////////////////////
367 // Main-thread-only mutable data.
368 //////////////////////////////////////////////////////////////////////////////
370 // Note that the data stored in gfx::Color is *non-alpha-premultiplied*.
371 Color mSinglePixelColor;
373 bool mSinglePixel;
374 bool mCompositingFailed;
378 * A reference to an imgFrame that holds the imgFrame's surface in memory,
379 * allowing drawing. If you have a DrawableFrameRef |ref| and |if (ref)| returns
380 * true, then calls to Draw() and GetSurface() are guaranteed to succeed.
382 class DrawableFrameRef final
384 public:
385 DrawableFrameRef() { }
387 explicit DrawableFrameRef(imgFrame* aFrame)
388 : mFrame(aFrame)
389 , mRef(aFrame->mVBuf)
391 if (mRef.WasBufferPurged()) {
392 mFrame = nullptr;
393 mRef = nullptr;
397 DrawableFrameRef(DrawableFrameRef&& aOther)
398 : mFrame(aOther.mFrame.forget())
399 , mRef(Move(aOther.mRef))
402 DrawableFrameRef& operator=(DrawableFrameRef&& aOther)
404 MOZ_ASSERT(this != &aOther, "Self-moves are prohibited");
405 mFrame = aOther.mFrame.forget();
406 mRef = Move(aOther.mRef);
407 return *this;
410 explicit operator bool() const { return bool(mFrame); }
412 imgFrame* operator->()
414 MOZ_ASSERT(mFrame);
415 return mFrame;
418 const imgFrame* operator->() const
420 MOZ_ASSERT(mFrame);
421 return mFrame;
424 imgFrame* get() { return mFrame; }
425 const imgFrame* get() const { return mFrame; }
427 void reset()
429 mFrame = nullptr;
430 mRef = nullptr;
433 private:
434 DrawableFrameRef(const DrawableFrameRef& aOther) = delete;
436 RefPtr<imgFrame> mFrame;
437 VolatileBufferPtr<uint8_t> mRef;
441 * A reference to an imgFrame that holds the imgFrame's surface in memory in a
442 * format appropriate for access as raw data. If you have a RawAccessFrameRef
443 * |ref| and |if (ref)| is true, then calls to GetImageData(), GetPaletteData(),
444 * and GetDrawTarget() are guaranteed to succeed. This guarantee is stronger
445 * than DrawableFrameRef, so everything that a valid DrawableFrameRef guarantees
446 * is also guaranteed by a valid RawAccessFrameRef.
448 * This may be considerably more expensive than is necessary just for drawing,
449 * so only use this when you need to read or write the raw underlying image data
450 * that the imgFrame holds.
452 * Once all an imgFrame's RawAccessFrameRefs go out of scope, new
453 * RawAccessFrameRefs cannot be created.
455 class RawAccessFrameRef final
457 public:
458 RawAccessFrameRef() { }
460 explicit RawAccessFrameRef(imgFrame* aFrame)
461 : mFrame(aFrame)
463 MOZ_ASSERT(mFrame, "Need a frame");
465 if (NS_FAILED(mFrame->LockImageData())) {
466 mFrame->UnlockImageData();
467 mFrame = nullptr;
471 RawAccessFrameRef(RawAccessFrameRef&& aOther)
472 : mFrame(aOther.mFrame.forget())
475 ~RawAccessFrameRef()
477 if (mFrame) {
478 mFrame->UnlockImageData();
482 RawAccessFrameRef& operator=(RawAccessFrameRef&& aOther)
484 MOZ_ASSERT(this != &aOther, "Self-moves are prohibited");
486 if (mFrame) {
487 mFrame->UnlockImageData();
490 mFrame = aOther.mFrame.forget();
492 return *this;
495 explicit operator bool() const { return bool(mFrame); }
497 imgFrame* operator->()
499 MOZ_ASSERT(mFrame);
500 return mFrame.get();
503 const imgFrame* operator->() const
505 MOZ_ASSERT(mFrame);
506 return mFrame;
509 imgFrame* get() { return mFrame; }
510 const imgFrame* get() const { return mFrame; }
512 void reset()
514 if (mFrame) {
515 mFrame->UnlockImageData();
517 mFrame = nullptr;
520 private:
521 RawAccessFrameRef(const RawAccessFrameRef& aOther) = delete;
523 RefPtr<imgFrame> mFrame;
526 } // namespace image
527 } // namespace mozilla
529 #endif // mozilla_image_imgFrame_h