1 /* -*- Mode: C++; tab-width: 2; 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/. */
8 #include "imgRequest.h"
9 #include "Layers.h" // for LayerManager
10 #include "WebRenderImageProvider.h"
11 #include "nsIObserverService.h"
12 #include "nsRefreshDriver.h"
13 #include "nsContentUtils.h"
14 #include "mozilla/Atomics.h"
15 #include "mozilla/gfx/Point.h"
16 #include "mozilla/gfx/Rect.h"
17 #include "mozilla/gfx/SourceSurfaceRawData.h"
18 #include "mozilla/Services.h"
19 #include "mozilla/SizeOfState.h"
20 #include "mozilla/TimeStamp.h"
21 #include "mozilla/Tuple.h" // for Tie
22 #include "mozilla/layers/SharedSurfacesChild.h"
27 WebRenderImageProvider::WebRenderImageProvider(const ImageResource
* aImage
)
28 : mProviderId(aImage
->GetImageProviderId()) {}
30 /* static */ ImageProviderId
WebRenderImageProvider::AllocateProviderId() {
31 // Callable on all threads.
32 static Atomic
<ImageProviderId
> sProviderId(0u);
36 ///////////////////////////////////////////////////////////////////////////////
38 ///////////////////////////////////////////////////////////////////////////////
40 ImageMemoryCounter::ImageMemoryCounter(imgRequest
* aRequest
,
41 SizeOfState
& aState
, bool aIsUsed
)
42 : mProgress(UINT32_MAX
),
49 // We don't have the image object yet, but we can get some information.
50 nsCOMPtr
<nsIURI
> imageURL
;
51 nsresult rv
= aRequest
->GetURI(getter_AddRefs(imageURL
));
52 if (NS_SUCCEEDED(rv
) && imageURL
) {
53 imageURL
->GetSpec(mURI
);
56 mType
= imgIContainer::TYPE_REQUEST
;
57 mHasError
= NS_FAILED(aRequest
->GetImageErrorCode());
58 mValidating
= !!aRequest
->GetValidator();
60 RefPtr
<ProgressTracker
> tracker
= aRequest
->GetProgressTracker();
62 mProgress
= tracker
->GetProgress();
66 ImageMemoryCounter::ImageMemoryCounter(imgRequest
* aRequest
, Image
* aImage
,
67 SizeOfState
& aState
, bool aIsUsed
)
68 : mProgress(UINT32_MAX
),
76 // Extract metadata about the image.
77 nsCOMPtr
<nsIURI
> imageURL(aImage
->GetURI());
79 imageURL
->GetSpec(mURI
);
84 aImage
->GetWidth(&width
);
85 aImage
->GetHeight(&height
);
86 mIntrinsicSize
.SizeTo(width
, height
);
88 mType
= aImage
->GetType();
89 mHasError
= aImage
->HasError();
90 mValidating
= !!aRequest
->GetValidator();
92 RefPtr
<ProgressTracker
> tracker
= aImage
->GetProgressTracker();
94 mProgress
= tracker
->GetProgress();
97 // Populate memory counters for source and decoded data.
98 mValues
.SetSource(aImage
->SizeOfSourceWithComputedFallback(aState
));
99 aImage
->CollectSizeOfSurfaces(mSurfaces
, aState
.mMallocSizeOf
);
102 for (const SurfaceMemoryCounter
& surfaceCounter
: mSurfaces
) {
103 mValues
+= surfaceCounter
.Values();
107 ///////////////////////////////////////////////////////////////////////////////
109 ///////////////////////////////////////////////////////////////////////////////
111 bool ImageResource::GetSpecTruncatedTo1k(nsCString
& aSpec
) const {
112 static const size_t sMaxTruncatedLength
= 1024;
114 mURI
->GetSpec(aSpec
);
115 if (sMaxTruncatedLength
>= aSpec
.Length()) {
119 aSpec
.Truncate(sMaxTruncatedLength
);
123 void ImageResource::CollectSizeOfSurfaces(
124 nsTArray
<SurfaceMemoryCounter
>& aCounters
,
125 MallocSizeOf aMallocSizeOf
) const {
126 SurfaceCache::CollectSizeOfSurfaces(ImageKey(this), aCounters
, aMallocSizeOf
);
130 ImageResource::ImageResource(nsIURI
* aURI
)
133 mAnimationConsumers(0),
134 mAnimationMode(kNormalAnimMode
),
138 mProviderId(WebRenderImageProvider::AllocateProviderId()) {}
140 ImageResource::~ImageResource() {
141 // Ask our ProgressTracker to drop its weak reference to us.
142 mProgressTracker
->ResetImage();
145 void ImageResource::IncrementAnimationConsumers() {
146 MOZ_ASSERT(NS_IsMainThread(),
147 "Main thread only to encourage serialization "
148 "with DecrementAnimationConsumers");
149 mAnimationConsumers
++;
152 void ImageResource::DecrementAnimationConsumers() {
153 MOZ_ASSERT(NS_IsMainThread(),
154 "Main thread only to encourage serialization "
155 "with IncrementAnimationConsumers");
156 MOZ_ASSERT(mAnimationConsumers
>= 1, "Invalid no. of animation consumers!");
157 mAnimationConsumers
--;
160 nsresult
ImageResource::GetAnimationModeInternal(uint16_t* aAnimationMode
) {
162 return NS_ERROR_FAILURE
;
165 NS_ENSURE_ARG_POINTER(aAnimationMode
);
167 *aAnimationMode
= mAnimationMode
;
171 nsresult
ImageResource::SetAnimationModeInternal(uint16_t aAnimationMode
) {
173 return NS_ERROR_FAILURE
;
176 NS_ASSERTION(aAnimationMode
== kNormalAnimMode
||
177 aAnimationMode
== kDontAnimMode
||
178 aAnimationMode
== kLoopOnceAnimMode
,
179 "Wrong Animation Mode is being set!");
181 mAnimationMode
= aAnimationMode
;
186 bool ImageResource::HadRecentRefresh(const TimeStamp
& aTime
) {
187 // Our threshold for "recent" is 1/2 of the default refresh-driver interval.
188 // This ensures that we allow for frame rates at least as fast as the
189 // refresh driver's default rate.
190 static TimeDuration recentThreshold
=
191 TimeDuration::FromMilliseconds(nsRefreshDriver::DefaultInterval() / 2.0);
193 if (!mLastRefreshTime
.IsNull() &&
194 aTime
- mLastRefreshTime
< recentThreshold
) {
198 // else, we can proceed with a refresh.
199 // But first, update our last refresh time:
200 mLastRefreshTime
= aTime
;
204 void ImageResource::EvaluateAnimation() {
205 if (!mAnimating
&& ShouldAnimate()) {
206 nsresult rv
= StartAnimation();
207 mAnimating
= NS_SUCCEEDED(rv
);
208 } else if (mAnimating
&& !ShouldAnimate()) {
213 void ImageResource::SendOnUnlockedDraw(uint32_t aFlags
) {
214 if (!mProgressTracker
) {
218 if (!(aFlags
& FLAG_ASYNC_NOTIFY
)) {
219 mProgressTracker
->OnUnlockedDraw();
221 NotNull
<RefPtr
<ImageResource
>> image
= WrapNotNull(this);
222 nsCOMPtr
<nsIEventTarget
> eventTarget
= mProgressTracker
->GetEventTarget();
223 nsCOMPtr
<nsIRunnable
> ev
= NS_NewRunnableFunction(
224 "image::ImageResource::SendOnUnlockedDraw", [=]() -> void {
225 RefPtr
<ProgressTracker
> tracker
= image
->GetProgressTracker();
227 tracker
->OnUnlockedDraw();
230 eventTarget
->Dispatch(CreateRenderBlockingRunnable(ev
.forget()),
236 void ImageResource::NotifyDrawingObservers() {
237 if (!mURI
|| !NS_IsMainThread()) {
241 if (!mURI
->SchemeIs("resource") && !mURI
->SchemeIs("chrome")) {
245 // Record the image drawing for startup performance testing.
246 nsCOMPtr
<nsIURI
> uri
= mURI
;
247 nsContentUtils::AddScriptRunner(NS_NewRunnableFunction(
248 "image::ImageResource::NotifyDrawingObservers", [uri
]() {
249 nsCOMPtr
<nsIObserverService
> obs
= services::GetObserverService();
250 NS_WARNING_ASSERTION(obs
, "Can't get an observer service handle");
254 obs
->NotifyObservers(nullptr, "image-drawing",
255 NS_ConvertUTF8toUTF16(spec
).get());
262 } // namespace mozilla