Bug 853337 - Make sure we actually call Flush and MarkDirty on frames when we've done some decoding work. r=seth

This commit is contained in:
Joe Drew 2013-03-22 22:05:44 -04:00
parent 69823dcd0f
commit 84324f86de
6 changed files with 51 additions and 3 deletions

View File

@ -610,7 +610,9 @@ nsresult
nsICODecoder::AllocateFrame() nsICODecoder::AllocateFrame()
{ {
if (mContainedDecoder) { if (mContainedDecoder) {
return mContainedDecoder->AllocateFrame(); nsresult rv = mContainedDecoder->AllocateFrame();
mCurrentFrame = mContainedDecoder->GetCurrentFrame();
return rv;
} }
return Decoder::AllocateFrame(); return Decoder::AllocateFrame();

View File

@ -188,6 +188,8 @@ Decoder::AllocateFrame()
MOZ_ASSERT(mNeedsNewFrame); MOZ_ASSERT(mNeedsNewFrame);
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
MarkFrameDirty();
nsresult rv; nsresult rv;
if (mNewFrameData.mPaletteDepth) { if (mNewFrameData.mPaletteDepth) {
rv = mImage.EnsureFrame(mNewFrameData.mFrameNum, mNewFrameData.mOffsetX, rv = mImage.EnsureFrame(mNewFrameData.mFrameNum, mNewFrameData.mOffsetX,
@ -329,8 +331,6 @@ Decoder::PostFrameStop(RasterImage::FrameAlpha aFrameAlpha /* = RasterImage::kFr
// Flush any invalidations before we finish the frame // Flush any invalidations before we finish the frame
FlushInvalidations(); FlushInvalidations();
mCurrentFrame = nullptr;
// Fire notifications // Fire notifications
if (mObserver) { if (mObserver) {
mObserver->OnStopFrame(); mObserver->OnStopFrame();
@ -403,5 +403,15 @@ Decoder::NeedNewFrame(uint32_t framenum, uint32_t x_offset, uint32_t y_offset,
mNeedsNewFrame = true; mNeedsNewFrame = true;
} }
void
Decoder::MarkFrameDirty()
{
MOZ_ASSERT(NS_IsMainThread());
if (mCurrentFrame) {
mCurrentFrame->MarkImageDataDirty();
}
}
} // namespace image } // namespace image
} // namespace mozilla } // namespace mozilla

View File

@ -162,6 +162,12 @@ public:
// status code from that attempt. Clears mNewFrameData. // status code from that attempt. Clears mNewFrameData.
virtual nsresult AllocateFrame(); virtual nsresult AllocateFrame();
// Called when a chunk of decoding has been done and the frame needs to be
// marked as dirty. Must be called only on the main thread.
void MarkFrameDirty();
imgFrame* GetCurrentFrame() const { return mCurrentFrame; }
protected: protected:
/* /*

View File

@ -3399,6 +3399,8 @@ RasterImage::FinishedSomeDecoding(eShutdownIntent aIntent /* = eShutdownIntent_D
nsresult rv = NS_OK; nsresult rv = NS_OK;
if (image->mDecoder) { if (image->mDecoder) {
image->mDecoder->MarkFrameDirty();
if (request && request->mChunkCount && !image->mDecoder->IsSizeDecode()) { if (request && request->mChunkCount && !image->mDecoder->IsSizeDecode()) {
Telemetry::Accumulate(Telemetry::IMAGE_DECODE_CHUNKS, request->mChunkCount); Telemetry::Accumulate(Telemetry::IMAGE_DECODE_CHUNKS, request->mChunkCount);
} }

View File

@ -707,9 +707,36 @@ nsresult imgFrame::UnlockImageData()
if (mQuartzSurface) if (mQuartzSurface)
mQuartzSurface->Flush(); mQuartzSurface->Flush();
#endif #endif
return NS_OK; return NS_OK;
} }
void imgFrame::MarkImageDataDirty()
{
if (mImageSurface)
mImageSurface->Flush();
#ifdef USE_WIN_SURFACE
if (mWinSurface)
mWinSurface->Flush();
#endif
if (mImageSurface)
mImageSurface->MarkDirty();
#ifdef USE_WIN_SURFACE
if (mWinSurface)
mWinSurface->MarkDirty();
#endif
#ifdef XP_MACOSX
// The quartz image surface (ab)uses the flush method to get the
// cairo_image_surface data into a CGImage, so we have to call Flush() here.
if (mQuartzSurface)
mQuartzSurface->Flush();
#endif
}
int32_t imgFrame::GetTimeout() const int32_t imgFrame::GetTimeout() const
{ {
// Ensure a minimal time between updates so we don't throttle the UI thread. // Ensure a minimal time between updates so we don't throttle the UI thread.

View File

@ -69,6 +69,7 @@ public:
nsresult LockImageData(); nsresult LockImageData();
nsresult UnlockImageData(); nsresult UnlockImageData();
void MarkImageDataDirty();
nsresult GetSurface(gfxASurface **aSurface) const nsresult GetSurface(gfxASurface **aSurface) const
{ {