mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 21:31:04 +00:00
Bug 689623. Part 8. Add an 'unlocked draw' notification for images that are drawn when not locked so we catch any images that become visible through a means other than scrolling. r=joe,mats
This commit is contained in:
parent
4c9c378b53
commit
45f8b4f1f9
@ -122,6 +122,11 @@ nsImageLoadingContent::Notify(imgIRequest* aRequest,
|
||||
return OnImageIsAnimated(aRequest);
|
||||
}
|
||||
|
||||
if (aType == imgINotificationObserver::UNLOCKED_DRAW) {
|
||||
OnUnlockedDraw();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (aType == imgINotificationObserver::LOAD_COMPLETE) {
|
||||
// We should definitely have a request here
|
||||
NS_ABORT_IF_FALSE(aRequest, "no request?");
|
||||
@ -229,6 +234,20 @@ nsImageLoadingContent::OnStopRequest(imgIRequest* aRequest,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsImageLoadingContent::OnUnlockedDraw()
|
||||
{
|
||||
nsPresContext* presContext = GetFramePresContext();
|
||||
if (!presContext)
|
||||
return;
|
||||
|
||||
nsIPresShell* presShell = presContext->PresShell();
|
||||
if (!presShell)
|
||||
return;
|
||||
|
||||
presShell->EnsureImageInVisibleList(this);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsImageLoadingContent::OnImageIsAnimated(imgIRequest *aRequest)
|
||||
{
|
||||
|
@ -183,6 +183,7 @@ protected:
|
||||
void UnbindFromTree(bool aDeep, bool aNullParent);
|
||||
|
||||
nsresult OnStopRequest(imgIRequest* aRequest, nsresult aStatus);
|
||||
void OnUnlockedDraw();
|
||||
nsresult OnImageIsAnimated(imgIRequest *aRequest);
|
||||
|
||||
private:
|
||||
|
@ -14,7 +14,7 @@ interface imgIRequest;
|
||||
|
||||
[ptr] native nsIntRect(nsIntRect);
|
||||
|
||||
[scriptable, builtinclass, uuid(90b3d21c-317d-4d96-93c0-12add64a26bf)]
|
||||
[scriptable, builtinclass, uuid(ac65c702-7771-4f6d-b18b-1c7d806ce3c1)]
|
||||
interface imgINotificationObserver : nsISupports
|
||||
{
|
||||
const long SIZE_AVAILABLE = 1;
|
||||
@ -23,7 +23,8 @@ interface imgINotificationObserver : nsISupports
|
||||
const long LOAD_COMPLETE = 4;
|
||||
const long DECODE_COMPLETE = 5;
|
||||
const long DISCARD = 6;
|
||||
const long IS_ANIMATED = 7;
|
||||
const long UNLOCKED_DRAW = 7;
|
||||
const long IS_ANIMATED = 8;
|
||||
|
||||
[noscript] void notify(in imgIRequest aProxy, in long aType, [const] in nsIntRect aRect);
|
||||
};
|
||||
|
@ -3107,6 +3107,15 @@ RasterImage::Draw(gfxContext *aContext,
|
||||
DiscardTracker::Reset(&mDiscardTrackerNode);
|
||||
}
|
||||
|
||||
// We would like to just check if we have a zero lock count, but we can't do
|
||||
// that for animated images because in EnsureAnimExists we lock the image and
|
||||
// never unlock so that animated images always have their lock count >= 1. In
|
||||
// that case we use our animation consumers count as a proxy for lock count.
|
||||
if (mLockCount == 0 || (mAnim && mAnimationConsumers == 0)) {
|
||||
if (mStatusTracker)
|
||||
mStatusTracker->GetDecoderObserver()->OnUnlockedDraw();
|
||||
}
|
||||
|
||||
// We use !mDecoded && mHasSourceData to mean discarded.
|
||||
if (!mDecoded && mHasSourceData) {
|
||||
mDrawStartTime = TimeStamp::Now();
|
||||
|
@ -109,6 +109,11 @@ public:
|
||||
* image will initiate a new series of progressive decode notifications.
|
||||
*/
|
||||
virtual void OnDiscard() = 0;
|
||||
|
||||
/**
|
||||
* Called when we are asked to Draw an image that is not locked.
|
||||
*/
|
||||
virtual void OnUnlockedDraw() = 0;
|
||||
};
|
||||
|
||||
// We must define a destructor because derived classes call our destructor from
|
||||
|
@ -767,6 +767,17 @@ void imgRequestProxy::OnDiscard()
|
||||
}
|
||||
}
|
||||
|
||||
void imgRequestProxy::OnUnlockedDraw()
|
||||
{
|
||||
LOG_FUNC(GetImgLog(), "imgRequestProxy::OnUnlockedDraw");
|
||||
|
||||
if (mListener && !mCanceled) {
|
||||
// Hold a ref to the listener while we call it, just in case.
|
||||
nsCOMPtr<imgINotificationObserver> kungFuDeathGrip(mListener);
|
||||
mListener->Notify(this, imgINotificationObserver::UNLOCKED_DRAW, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void imgRequestProxy::OnImageIsAnimated()
|
||||
{
|
||||
LOG_FUNC(GetImgLog(), "imgRequestProxy::OnImageIsAnimated");
|
||||
|
@ -143,6 +143,7 @@ protected:
|
||||
void OnStopFrame ();
|
||||
void OnStopDecode ();
|
||||
void OnDiscard ();
|
||||
void OnUnlockedDraw ();
|
||||
void OnImageIsAnimated ();
|
||||
|
||||
/* non-virtual sort-of-nsIRequestObserver methods */
|
||||
|
@ -165,6 +165,18 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnUnlockedDraw()
|
||||
{
|
||||
NS_ABORT_IF_FALSE(mTracker->GetImage(),
|
||||
"OnUnlockedDraw callback before we've created our image");
|
||||
mTracker->RecordUnlockedDraw();
|
||||
|
||||
nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mTracker->mConsumers);
|
||||
while (iter.HasMore()) {
|
||||
mTracker->SendUnlockedDraw(iter.GetNext());
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnImageIsAnimated()
|
||||
{
|
||||
NS_ABORT_IF_FALSE(mTracker->GetImage(),
|
||||
@ -568,6 +580,13 @@ imgStatusTracker::RecordDiscard()
|
||||
mImageStatus &= ~statusBitsToClear;
|
||||
}
|
||||
|
||||
void
|
||||
imgStatusTracker::RecordUnlockedDraw()
|
||||
{
|
||||
NS_ABORT_IF_FALSE(mImage,
|
||||
"RecordUnlockedDraw called before we have an Image");
|
||||
}
|
||||
|
||||
void
|
||||
imgStatusTracker::SendImageIsAnimated(imgRequestProxy* aProxy)
|
||||
{
|
||||
@ -593,6 +612,13 @@ imgStatusTracker::SendDiscard(imgRequestProxy* aProxy)
|
||||
aProxy->OnDiscard();
|
||||
}
|
||||
|
||||
void
|
||||
imgStatusTracker::SendUnlockedDraw(imgRequestProxy* aProxy)
|
||||
{
|
||||
if (!aProxy->NotificationsDeferred())
|
||||
aProxy->OnUnlockedDraw();
|
||||
}
|
||||
|
||||
void
|
||||
imgStatusTracker::RecordFrameChanged(const nsIntRect* aDirtyRect)
|
||||
{
|
||||
|
@ -145,6 +145,8 @@ public:
|
||||
void SendStopDecode(imgRequestProxy* aProxy, nsresult aStatus);
|
||||
void RecordDiscard();
|
||||
void SendDiscard(imgRequestProxy* aProxy);
|
||||
void RecordUnlockedDraw();
|
||||
void SendUnlockedDraw(imgRequestProxy* aProxy);
|
||||
void RecordImageIsAnimated();
|
||||
void SendImageIsAnimated(imgRequestProxy *aProxy);
|
||||
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include "nsInterfaceHashtable.h"
|
||||
#include "nsEventStates.h"
|
||||
#include "nsPresArena.h"
|
||||
#include "nsIImageLoadingContent.h"
|
||||
|
||||
class nsIContent;
|
||||
class nsIDocument;
|
||||
@ -120,10 +121,10 @@ typedef struct CapturingContentInfo {
|
||||
nsIContent* mContent;
|
||||
} CapturingContentInfo;
|
||||
|
||||
// 15f6c268-e40f-42a9-a7eb-e5e10a5840a1
|
||||
// 835b3946-1a4f-4132-b3ce-2e2e8be377c8
|
||||
#define NS_IPRESSHELL_IID \
|
||||
{ 0x15f6c268, 0xe40f, 0x42a9, \
|
||||
{ 0xa7, 0xeb, 0xe5, 0xe1, 0x0a, 0x58, 0x40, 0xa1 } }
|
||||
{ 0x835b3946, 0x1a4f, 0x4132, \
|
||||
{ 0xb3, 0xce, 0x2e, 0x2e, 0x8b, 0xe3, 0x77, 0xc8 } }
|
||||
|
||||
// debug VerifyReflow flags
|
||||
#define VERIFY_REFLOW_ON 0x01
|
||||
@ -1327,6 +1328,9 @@ public:
|
||||
// with images that are in the display list aList.
|
||||
virtual void RebuildImageVisibility(const nsDisplayList& aList) = 0;
|
||||
|
||||
// Ensures the image is in the list of visible images.
|
||||
virtual void EnsureImageInVisibleList(nsIImageLoadingContent* aImage) = 0;
|
||||
|
||||
/**
|
||||
* Refresh observer management.
|
||||
*/
|
||||
|
@ -5415,6 +5415,27 @@ PresShell::ScheduleImageVisibilityUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PresShell::EnsureImageInVisibleList(nsIImageLoadingContent* aImage)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
// if it has a frame make sure its in this presshell
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(aImage);
|
||||
if (content) {
|
||||
PresShell* shell = static_cast<PresShell*>(content->OwnerDoc()->GetShell());
|
||||
MOZ_ASSERT(!shell || shell == this, "wrong shell");
|
||||
}
|
||||
#endif
|
||||
|
||||
// This check could be slow.
|
||||
if (mVisibleImages.Contains(aImage)) {
|
||||
return;
|
||||
}
|
||||
|
||||
mVisibleImages.AppendElement(aImage);
|
||||
aImage->IncrementVisibleCount();
|
||||
}
|
||||
|
||||
class nsAutoNotifyDidPaint
|
||||
{
|
||||
public:
|
||||
|
@ -339,6 +339,8 @@ public:
|
||||
|
||||
virtual void RebuildImageVisibility(const nsDisplayList& aList);
|
||||
|
||||
virtual void EnsureImageInVisibleList(nsIImageLoadingContent* aImage);
|
||||
|
||||
protected:
|
||||
virtual ~PresShell();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user