Bug 1368776 - Part 13. Make ImageResource::GetFrameInternal also return the suggested size for the lookup. r=tnikkel

This commit is contained in:
Andrew Osmond 2017-11-17 06:45:27 -05:00
Родитель 2463bc3782
Коммит a1d47a973a
5 изменённых файлов: 58 добавлений и 43 удалений

Просмотреть файл

@ -62,8 +62,9 @@ ImageResource::AddCurrentImage(ImageContainer* aContainer,
MOZ_ASSERT(aContainer); MOZ_ASSERT(aContainer);
DrawResult drawResult; DrawResult drawResult;
IntSize size;
RefPtr<SourceSurface> surface; RefPtr<SourceSurface> surface;
Tie(drawResult, surface) = Tie(drawResult, size, surface) =
GetFrameInternal(aSize, FRAME_CURRENT, aFlags | FLAG_ASYNC_NOTIFY); GetFrameInternal(aSize, FRAME_CURRENT, aFlags | FLAG_ASYNC_NOTIFY);
if (!surface) { if (!surface) {
// The OS threw out some or all of our buffer. We'll need to wait for the // The OS threw out some or all of our buffer. We'll need to wait for the

Просмотреть файл

@ -7,12 +7,13 @@
#define mozilla_image_Image_h #define mozilla_image_Image_h
#include "mozilla/MemoryReporting.h" #include "mozilla/MemoryReporting.h"
#include "mozilla/Pair.h" #include "mozilla/Tuple.h"
#include "mozilla/TimeStamp.h" #include "mozilla/TimeStamp.h"
#include "gfx2DGlue.h" #include "gfx2DGlue.h"
#include "imgIContainer.h" #include "imgIContainer.h"
#include "ImageURL.h" #include "ImageURL.h"
#include "ImageContainer.h" #include "ImageContainer.h"
#include "LookupResult.h"
#include "nsStringFwd.h" #include "nsStringFwd.h"
#include "ProgressTracker.h" #include "ProgressTracker.h"
#include "SurfaceCache.h" #include "SurfaceCache.h"
@ -336,12 +337,13 @@ protected:
bool mAnimating:1; // Are we currently animating? bool mAnimating:1; // Are we currently animating?
bool mError:1; // Error handling bool mError:1; // Error handling
virtual Pair<DrawResult, RefPtr<gfx::SourceSurface>> virtual Tuple<DrawResult, gfx::IntSize, RefPtr<gfx::SourceSurface>>
GetFrameInternal(const gfx::IntSize& aSize, GetFrameInternal(const gfx::IntSize& aSize,
uint32_t aWhichFrame, uint32_t aWhichFrame,
uint32_t aFlags) uint32_t aFlags)
{ {
return MakePair(DrawResult::BAD_IMAGE, RefPtr<gfx::SourceSurface>()); return MakeTuple(DrawResult::BAD_IMAGE, aSize,
RefPtr<gfx::SourceSurface>());
} }
/** /**

Просмотреть файл

@ -102,6 +102,7 @@ public:
private: private:
LookupResult(const LookupResult&) = delete; LookupResult(const LookupResult&) = delete;
LookupResult& operator=(const LookupResult& aOther) = delete;
DrawableSurface mSurface; DrawableSurface mSurface;
MatchType mMatchType; MatchType mMatchType;

Просмотреть файл

@ -324,7 +324,7 @@ RasterImage::LookupFrameInternal(const IntSize& aSize,
PlaybackType::eStatic)); PlaybackType::eStatic));
} }
DrawableSurface LookupResult
RasterImage::LookupFrame(const IntSize& aSize, RasterImage::LookupFrame(const IntSize& aSize,
uint32_t aFlags, uint32_t aFlags,
PlaybackType aPlaybackType) PlaybackType aPlaybackType)
@ -340,7 +340,8 @@ RasterImage::LookupFrame(const IntSize& aSize,
IntSize requestedSize = CanDownscaleDuringDecode(aSize, aFlags) IntSize requestedSize = CanDownscaleDuringDecode(aSize, aFlags)
? aSize : mSize; ? aSize : mSize;
if (requestedSize.IsEmpty()) { if (requestedSize.IsEmpty()) {
return DrawableSurface(); // Can't decode to a surface of zero size. // Can't decode to a surface of zero size.
return LookupResult(MatchType::NOT_FOUND);
} }
LookupResult result = LookupResult result =
@ -348,7 +349,7 @@ RasterImage::LookupFrame(const IntSize& aSize,
if (!result && !mHasSize) { if (!result && !mHasSize) {
// We can't request a decode without knowing our intrinsic size. Give up. // We can't request a decode without knowing our intrinsic size. Give up.
return DrawableSurface(); return LookupResult(MatchType::NOT_FOUND);
} }
if (result.Type() == MatchType::NOT_FOUND || if (result.Type() == MatchType::NOT_FOUND ||
@ -380,11 +381,12 @@ RasterImage::LookupFrame(const IntSize& aSize,
if (!result) { if (!result) {
// We still weren't able to get a frame. Give up. // We still weren't able to get a frame. Give up.
return DrawableSurface(); return result;
} }
if (result.Surface()->GetCompositingFailed()) { if (result.Surface()->GetCompositingFailed()) {
return DrawableSurface(); DrawableSurface tmp = Move(result.Surface());
return result;
} }
MOZ_ASSERT(!result.Surface()->GetIsPaletted(), MOZ_ASSERT(!result.Surface()->GetIsPaletted(),
@ -403,10 +405,11 @@ RasterImage::LookupFrame(const IntSize& aSize,
// IsAborted acquires the monitor for the imgFrame. // IsAborted acquires the monitor for the imgFrame.
if (aFlags & (FLAG_SYNC_DECODE | FLAG_SYNC_DECODE_IF_FAST) && if (aFlags & (FLAG_SYNC_DECODE | FLAG_SYNC_DECODE_IF_FAST) &&
result.Surface()->IsAborted()) { result.Surface()->IsAborted()) {
return DrawableSurface(); DrawableSurface tmp = Move(result.Surface());
return result;
} }
return Move(result.Surface()); return result;
} }
bool bool
@ -569,55 +572,62 @@ RasterImage::GetFrameAtSize(const IntSize& aSize,
uint32_t aWhichFrame, uint32_t aWhichFrame,
uint32_t aFlags) uint32_t aFlags)
{ {
#ifdef DEBUG #ifdef DEBUG
NotifyDrawingObservers(); NotifyDrawingObservers();
#endif #endif
RefPtr<SourceSurface> surf = auto result = GetFrameInternal(aSize, aWhichFrame, aFlags);
GetFrameInternal(aSize, aWhichFrame, aFlags).second().forget(); RefPtr<SourceSurface> surf = mozilla::Get<2>(result).forget();
// If we are here, it suggests the image is embedded in a canvas or some // If we are here, it suggests the image is embedded in a canvas or some
// other path besides layers, and we won't need the file handle. // other path besides layers, and we won't need the file handle.
MarkSurfaceShared(surf); MarkSurfaceShared(surf);
return surf.forget(); return surf.forget();
} }
Pair<DrawResult, RefPtr<SourceSurface>> Tuple<DrawResult, IntSize, RefPtr<SourceSurface>>
RasterImage::GetFrameInternal(const IntSize& aSize, RasterImage::GetFrameInternal(const IntSize& aSize,
uint32_t aWhichFrame, uint32_t aWhichFrame,
uint32_t aFlags) uint32_t aFlags)
{ {
MOZ_ASSERT(aWhichFrame <= FRAME_MAX_VALUE); MOZ_ASSERT(aWhichFrame <= FRAME_MAX_VALUE);
if (aSize.IsEmpty()) { if (aSize.IsEmpty() || aWhichFrame > FRAME_MAX_VALUE) {
return MakePair(DrawResult::BAD_ARGS, RefPtr<SourceSurface>()); return MakeTuple(DrawResult::BAD_ARGS, aSize,
} RefPtr<SourceSurface>());
if (aWhichFrame > FRAME_MAX_VALUE) {
return MakePair(DrawResult::BAD_ARGS, RefPtr<SourceSurface>());
} }
if (mError) { if (mError) {
return MakePair(DrawResult::BAD_IMAGE, RefPtr<SourceSurface>()); return MakeTuple(DrawResult::BAD_IMAGE, aSize,
RefPtr<SourceSurface>());
} }
// Get the frame. If it's not there, it's probably the caller's fault for // Get the frame. If it's not there, it's probably the caller's fault for
// not waiting for the data to be loaded from the network or not passing // not waiting for the data to be loaded from the network or not passing
// FLAG_SYNC_DECODE. // FLAG_SYNC_DECODE.
DrawableSurface surface = LookupResult result =
LookupFrame(aSize, aFlags, ToPlaybackType(aWhichFrame)); LookupFrame(aSize, aFlags, ToPlaybackType(aWhichFrame));
if (!surface) {
// The surface cache may have suggested we use a different size than the
// given size in the future. This may or may not be accompanied by an
// actual surface, depending on what it has in its cache.
IntSize suggestedSize = result.SuggestedSize().IsEmpty()
? aSize : result.SuggestedSize();
MOZ_ASSERT_IF(result.Type() == MatchType::SUBSTITUTE_BECAUSE_BEST,
suggestedSize != aSize);
if (!result) {
// The OS threw this frame away and we couldn't redecode it. // The OS threw this frame away and we couldn't redecode it.
return MakePair(DrawResult::TEMPORARY_ERROR, RefPtr<SourceSurface>()); return MakeTuple(DrawResult::TEMPORARY_ERROR, suggestedSize,
RefPtr<SourceSurface>());
} }
RefPtr<SourceSurface> sourceSurface = surface->GetSourceSurface(); RefPtr<SourceSurface> surface = result.Surface()->GetSourceSurface();
if (!result.Surface()->IsFinished()) {
if (!surface->IsFinished()) { return MakeTuple(DrawResult::INCOMPLETE, suggestedSize, Move(surface));
return MakePair(DrawResult::INCOMPLETE, Move(sourceSurface));
} }
return MakePair(DrawResult::SUCCESS, Move(sourceSurface)); return MakeTuple(DrawResult::SUCCESS, suggestedSize, Move(surface));
} }
IntSize IntSize
@ -1149,8 +1159,10 @@ RasterImage::RequestDecodeForSizeInternal(const IntSize& aSize, uint32_t aFlags)
: aFlags & ~FLAG_SYNC_DECODE_IF_FAST; : aFlags & ~FLAG_SYNC_DECODE_IF_FAST;
// Perform a frame lookup, which will implicitly start decoding if needed. // Perform a frame lookup, which will implicitly start decoding if needed.
return LookupFrame(aSize, flags, mAnimationState ? PlaybackType::eAnimated PlaybackType playbackType = mAnimationState ? PlaybackType::eAnimated
: PlaybackType::eStatic); : PlaybackType::eStatic;
LookupResult result = LookupFrame(aSize, flags, playbackType);
return Move(result.Surface());
} }
static bool static bool
@ -1443,9 +1455,9 @@ RasterImage::Draw(gfxContext* aContext,
? aFlags ? aFlags
: aFlags & ~FLAG_HIGH_QUALITY_SCALING; : aFlags & ~FLAG_HIGH_QUALITY_SCALING;
DrawableSurface surface = LookupResult result =
LookupFrame(aSize, flags, ToPlaybackType(aWhichFrame)); LookupFrame(aSize, flags, ToPlaybackType(aWhichFrame));
if (!surface) { if (!result) {
// Getting the frame (above) touches the image and kicks off decoding. // Getting the frame (above) touches the image and kicks off decoding.
if (mDrawStartTime.IsNull()) { if (mDrawStartTime.IsNull()) {
mDrawStartTime = TimeStamp::Now(); mDrawStartTime = TimeStamp::Now();
@ -1454,10 +1466,10 @@ RasterImage::Draw(gfxContext* aContext,
} }
bool shouldRecordTelemetry = !mDrawStartTime.IsNull() && bool shouldRecordTelemetry = !mDrawStartTime.IsNull() &&
surface->IsFinished(); result.Surface()->IsFinished();
auto result = DrawInternal(Move(surface), aContext, aSize, auto drawResult = DrawInternal(Move(result.Surface()), aContext, aSize,
aRegion, aSamplingFilter, flags, aOpacity); aRegion, aSamplingFilter, flags, aOpacity);
if (shouldRecordTelemetry) { if (shouldRecordTelemetry) {
TimeDuration drawLatency = TimeStamp::Now() - mDrawStartTime; TimeDuration drawLatency = TimeStamp::Now() - mDrawStartTime;
@ -1471,7 +1483,7 @@ RasterImage::Draw(gfxContext* aContext,
mDrawStartTime = TimeStamp(); mDrawStartTime = TimeStamp();
} }
return result; return drawResult;
} }
//****************************************************************************** //******************************************************************************

Просмотреть файл

@ -35,7 +35,6 @@
#include "mozilla/Maybe.h" #include "mozilla/Maybe.h"
#include "mozilla/MemoryReporting.h" #include "mozilla/MemoryReporting.h"
#include "mozilla/NotNull.h" #include "mozilla/NotNull.h"
#include "mozilla/Pair.h"
#include "mozilla/TimeStamp.h" #include "mozilla/TimeStamp.h"
#include "mozilla/WeakPtr.h" #include "mozilla/WeakPtr.h"
#include "mozilla/UniquePtr.h" #include "mozilla/UniquePtr.h"
@ -291,9 +290,9 @@ private:
* @return a drawable surface, which may be empty if the requested surface * @return a drawable surface, which may be empty if the requested surface
* could not be found. * could not be found.
*/ */
DrawableSurface LookupFrame(const gfx::IntSize& aSize, LookupResult LookupFrame(const gfx::IntSize& aSize,
uint32_t aFlags, uint32_t aFlags,
PlaybackType aPlaybackType); PlaybackType aPlaybackType);
/// Helper method for LookupFrame(). /// Helper method for LookupFrame().
LookupResult LookupFrameInternal(const gfx::IntSize& aSize, LookupResult LookupFrameInternal(const gfx::IntSize& aSize,
@ -308,7 +307,7 @@ private:
uint32_t aFlags, uint32_t aFlags,
float aOpacity); float aOpacity);
Pair<DrawResult, RefPtr<gfx::SourceSurface>> Tuple<DrawResult, gfx::IntSize, RefPtr<gfx::SourceSurface>>
GetFrameInternal(const gfx::IntSize& aSize, GetFrameInternal(const gfx::IntSize& aSize,
uint32_t aWhichFrame, uint32_t aWhichFrame,
uint32_t aFlags) override; uint32_t aFlags) override;