import changes from `dev' branch of rmottola/Arctic-Fox:

- Bug 1187401 (Part 1) - Simplify the condition that determines whether we set RasterImage::mHasBeenDecoded. r=tn (69be36e7ef)
- Bug 1187401 (Part 2) - Eliminate the nsresult return value from RasterImage::SetMetadata, since it's not used anymore. r=tn (dc521c4b9f)
- Bug 1187401 (Part 3) - For consistency, call DoError if SetMetadata sees a negative size. r=tn (d9ca8ec91b)
- Bug 1207183 - micro-optimize removing work items from DecodePool's queues; r=seth (6bd2717e3a)
- No bug - Fix out-of-date comment in Decoder.cpp. r=me (54fdbbd444)
- Bug 1181324 - Eliminate the duplicate mRefCnt member in MultipartImage. r=seth (c4512a443e)
- Bug 1180105 - Do not leak the SourceSurface returned from imgIContainer::GetFrame in BlockUntilDecodedAndFinishObserving; r=seth (1cadbffc53)
- Bug 1181909 - Fix potential null dereference in NextPartObserver. r=tn (cfd8ad0119)
- Bug 108603 - Remove NS_IMPL_QUERY_INTERFACE_INHERITED0. r=mccr8, r=froydnj (4bfa6771fc)
- Bug 1159502 - Don't block onload for multipart images. r=tn (8b50eadf39)
- Bug 1200413 - Part 1: Re-write RefCountedInsideLambdaChecker to use captures instead of checking for DeclRef instances, r=ehsan (80ef99efe2)
- Bug 1200413 - Part 2: Make lambdas in ProgressTracker.cpp capture strong references, r=seth (9e4d96dffa)
- Bug 1194557 - Ensure that if the image was locked before RecoverFromLossOfFrames() was called, it's still locked afterwards. r=tn (ea4dc6ea9f)
- code style (ad3773ba42)
- Bug 1167590 - Mark imgRequestProxy::mListener as MOZ_UNSAFE_REF. r=seth (946ffaed8a)
- Bug 1148397 - Fix data race on imgRequest::mHadInsecureRedirect. r=tanvi (e73d0664f3)
- No bug - Tweak formatting of logging statement in imgRequest. r=me (cab2bcb014)
- Bug 1180126 - Read content disposition regardless of content type in imgRequest::PrepareForNewPart. r=tn (2934597743)
- Bug 1139225 - Followup - Remove duplicate multiPartChannel variable. (7f7f555a0b)
- Bug 1141398 - Do not always revalidate image cache entries for file URIs. r=tn (31d73cb508)
- Bug 1183563 - Fix incorrect mixed content warning after internal redirects. r=tanvi, r=seth (12a6c8a15f)
- Bug 1150127 - Stop leaking windows via imgCacheValidator. r=baku (a7809c5fa7)
- bits of Bug 1102048 (Part 20, imgLoader) (b2098c8a5a)
- (No bug) - Correct blatantly lying comment in imgLoader.cpp. r=me DONTBUILD (64c42a5b09)
- Bug 1160592 - Report image source size again in about:memory. r=dholbert (4e04cf3c3e)
- Add an assertion for the first argument of NewImageChannel, no bug (4c8f087a8f)
- Bug 1127534 - Remove assertion before creating a channel (r=sicking) (988692dc91)
- Bug 1175371 - Make VectorImage wait to deliver LOAD_COMPLETE until its size is available. r=dholbert (3c81e0daff)
- Bug 1181323 - Move nsSVGRenderingObserver's isupports/refcounting decl to subclasses, since one subclass (nsSVGFilterReference) already has its own redundant copy of the decl. r=dholbert (6171171c2c)
- Bug 1161722 - If we're shutting down, don't warn about untracked unlocked surfaces. r=dholbert (f7e18ce481)
- Bug 1170877 - Track how many times the SurfaceCache has overflowed and report it in about:memory. r=dholbert (884176cb1d)
- Bug 1161743 - Upgrade 'WARNING: Not expiration-tracking an unlocked surface' to an assertion. r=dholbert (9900169e7b)
- Bug 1167557 - Crash when a null surface is passed to SurfaceCache::Insert. r=dholbert (b3c4cf60aa)
- remove bypass cache not fonud either in FF nor TF (3ed4056a27)
- Missing bit Bug 1102048 (Part 25, header guards) - Make image/src files comply (cb8ed2428f)
- No bug - Remove obsolete comment in SourceBuffer.h. r=me (6e9c233448)
- coding style (94b7269690)
- Bug 1157065 - GFX: 2D: Add Loongson3 MMI helpers. r=jrmuizel (ebce946c91)
- reverto to FF52 and TFF settings (e147a8c7b5)
- Bug 1134599 - Fix rpi build target. r=jrmuizel, r=shuang (b9722f860c)
- Bug 1129147 - Part 1. Take CanvasPath into a separate file, to avoid circular dependency. r=roc (859bcad807)
- Bug 1129147 - Part 2. Path option to addHitRegion. r=ehsan r=gw280 (b2ab08a8a1)
- Bug 1206076: Use a specialized PersistentBufferProvider for Canvas2D when using a SkiaGL DrawTarget. r=jrmuizel (859589caf8)
- Bug 1188752 - Addendum: Make PersistentBufferProviderBasic constructor explicit. r=bustage on a CLOSED TREE (a27a4dc974)
- style (72a65dcb26)
- Bug 1198574 - Remove unnecessary argument for PersistentBufferProvider. r=bas (dca718bba8)
- Bug 1163124 - The initial value of the canvas filter property should be "none". r=roc (59df6a01d8)
This commit is contained in:
2022-05-20 09:45:08 +08:00
parent f1d1e16669
commit e7535dc94b
45 changed files with 747 additions and 273 deletions
+1 -1
View File
@@ -904,7 +904,7 @@ pref("devtools.debugger.unix-domain-socket", "/data/local/debugger-socket");
// falling back to Skia/software for smaller canvases
#ifdef MOZ_WIDGET_GONK
pref("gfx.canvas.azure.backends", "skia");
pref("gfx.canvas.azure.accelerated", true);
pref("gfx.canvas.azure.accelerated", false);
#endif
// Turn on dynamic cache size for Skia
+13 -11
View File
@@ -951,13 +951,7 @@ DiagnosticsMatcher::DiagnosticsMatcher() {
// lambda, where the declaration they reference is not inside the lambda.
// This excludes arguments and local variables, leaving only captured
// variables.
astMatcher.addMatcher(
lambdaExpr(hasDescendant(
declRefExpr(hasType(pointerType(pointee(isRefCounted()))),
to(decl().bind("decl")))
.bind("declref")),
unless(hasDescendant(decl(equalsBoundNode("decl"))))),
&refCountedInsideLambdaChecker);
astMatcher.addMatcher(lambdaExpr().bind("lambda"), &refCountedInsideLambdaChecker);
// Older clang versions such as the ones used on the infra recognize these
// conversions as 'operator _Bool', but newer clang versions recognize these
@@ -1241,11 +1235,19 @@ void DiagnosticsMatcher::RefCountedInsideLambdaChecker::run(
"Refcounted variable %0 of type %1 cannot be captured by a lambda");
unsigned noteID = Diag.getDiagnosticIDs()->getCustomDiagID(
DiagnosticIDs::Note, "Please consider using a smart pointer");
const DeclRefExpr *declref = Result.Nodes.getNodeAs<DeclRefExpr>("declref");
const LambdaExpr *Lambda = Result.Nodes.getNodeAs<LambdaExpr>("lambda");
Diag.Report(declref->getLocStart(), errorID)
<< declref->getFoundDecl() << declref->getType()->getPointeeType();
Diag.Report(declref->getLocStart(), noteID);
for (const LambdaCapture Capture : Lambda->captures()) {
if (Capture.capturesVariable()) {
QualType Pointee = Capture.getCapturedVar()->getType()->getPointeeType();
if (!Pointee.isNull() && isClassRefCounted(Pointee)) {
Diag.Report(Capture.getLocation(), errorID)
<< Capture.getCapturedVar() << Pointee;
Diag.Report(Capture.getLocation(), noteID);
}
}
}
}
void DiagnosticsMatcher::ExplicitOperatorBoolChecker::run(
@@ -67,9 +67,9 @@ void foo() {
take(argsp);
take(localsp);
});
take([ptr](R* argptr) {
take([ptr](R* argptr) { // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
R* localptr;
ptr->method(); // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
ptr->method();
argptr->method();
localptr->method();
});
@@ -79,9 +79,9 @@ void foo() {
argsp->method();
localsp->method();
});
take([ptr](R* argptr) {
take([ptr](R* argptr) { // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
R* localptr;
take(ptr); // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
take(ptr);
take(argptr);
take(localptr);
});
+1 -1
View File
@@ -900,7 +900,7 @@ DOMInterfaces = {
'Path2D': {
'nativeType': 'mozilla::dom::CanvasPath',
'headerFile': 'CanvasRenderingContext2D.h'
'headerFile': 'CanvasPath.h'
},
'PeerConnectionImpl': {
+91
View File
@@ -0,0 +1,91 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef CanvasPath_h
#define CanvasPath_h
#include "mozilla/Attributes.h"
#include "mozilla/RefPtr.h"
#include "nsWrapperCache.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/ErrorResult.h"
namespace mozilla {
namespace dom {
enum class CanvasWindingRule : uint32_t;
class SVGMatrix;
class CanvasPath final :
public nsWrapperCache
{
public:
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(CanvasPath)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(CanvasPath)
nsCOMPtr<nsISupports> GetParentObject() { return mParent; }
JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
static already_AddRefed<CanvasPath> Constructor(const GlobalObject& aGlobal,
ErrorResult& rv);
static already_AddRefed<CanvasPath> Constructor(const GlobalObject& aGlobal,
CanvasPath& aCanvasPath,
ErrorResult& rv);
static already_AddRefed<CanvasPath> Constructor(const GlobalObject& aGlobal,
const nsAString& aPathString,
ErrorResult& rv);
void ClosePath();
void MoveTo(double x, double y);
void LineTo(double x, double y);
void QuadraticCurveTo(double cpx, double cpy, double x, double y);
void BezierCurveTo(double cp1x, double cp1y,
double cp2x, double cp2y,
double x, double y);
void ArcTo(double x1, double y1, double x2, double y2, double radius,
ErrorResult& error);
void Rect(double x, double y, double w, double h);
void Arc(double x, double y, double radius,
double startAngle, double endAngle, bool anticlockwise,
ErrorResult& error);
void Ellipse(double x, double y, double radiusX, double radiusY,
double rotation, double startAngle, double endAngle,
bool anticlockwise, ErrorResult& error);
void LineTo(const gfx::Point& aPoint);
void BezierTo(const gfx::Point& aCP1,
const gfx::Point& aCP2,
const gfx::Point& aCP3);
already_AddRefed<gfx::Path> GetPath(const CanvasWindingRule& aWinding,
const gfx::DrawTarget* aTarget) const;
explicit CanvasPath(nsISupports* aParent);
// already_AddRefed arg because the return value from Path::CopyToBuilder()
// is passed directly and we can't drop the only ref to have a raw pointer.
CanvasPath(nsISupports* aParent,
already_AddRefed<gfx::PathBuilder> aPathBuilder);
void AddPath(CanvasPath& aCanvasPath,
const Optional<NonNull<SVGMatrix>>& aMatrix);
private:
virtual ~CanvasPath() {}
nsCOMPtr<nsISupports> mParent;
static gfx::Float ToFloat(double aValue) { return gfx::Float(aValue); }
mutable RefPtr<gfx::Path> mPath;
mutable RefPtr<gfx::PathBuilder> mPathBuilder;
void EnsurePathBuilder() const;
};
} // namespace dom
} // namespace mozilla
#endif /* CanvasPath_h */
+18 -12
View File
@@ -101,6 +101,7 @@
#include "nsCCUncollectableMarker.h"
#include "nsWrapperCacheInlines.h"
#include "mozilla/dom/CanvasRenderingContext2DBinding.h"
#include "mozilla/dom/CanvasPath.h"
#include "mozilla/dom/HTMLImageElement.h"
#include "mozilla/dom/HTMLVideoElement.h"
#include "mozilla/dom/SVGMatrix.h"
@@ -1402,13 +1403,14 @@ CanvasRenderingContext2D::EnsureTarget(RenderingMode aRenderingMode)
DemoteOldestContextIfNecessary();
mBufferProvider = nullptr;
#if USE_SKIA_GPU
SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue();
#if USE_SKIA_GPU
if (glue && glue->GetGrContext() && glue->GetGLContext()) {
mTarget = Factory::CreateDrawTargetSkiaWithGrContext(glue->GetGrContext(), size, format);
if (mTarget) {
AddDemotableContext(this);
mBufferProvider = new PersistentBufferProviderBasic(mTarget);
} else {
printf_stderr("Failed to create a SkiaGL DrawTarget, falling back to software\n");
mode = RenderingMode::SoftwareBackendMode;
@@ -3360,15 +3362,24 @@ CanvasRenderingContext2D::MeasureText(const nsAString& rawText,
void
CanvasRenderingContext2D::AddHitRegion(const HitRegionOptions& options, ErrorResult& error)
{
// check if the path is valid
EnsureUserSpacePath(CanvasWindingRule::Nonzero);
if(!mPath) {
RefPtr<gfx::Path> path;
if (options.mPath) {
path = options.mPath->GetPath(CanvasWindingRule::Nonzero, mTarget);
}
if (!path) {
// check if the path is valid
EnsureUserSpacePath(CanvasWindingRule::Nonzero);
path = mPath;
}
if(!path) {
error.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
return;
}
// get the bounds of the current path. They are relative to the canvas
mgfx::Rect bounds(mPath->GetBounds(mTarget->GetTransform()));
mgfx::Rect bounds(path->GetBounds(mTarget->GetTransform()));
if ((bounds.width == 0) || (bounds.height == 0) || !bounds.IsFinite()) {
// The specified region has no pixels.
error.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
@@ -3397,7 +3408,7 @@ CanvasRenderingContext2D::AddHitRegion(const HitRegionOptions& options, ErrorRes
RegionInfo info;
info.mId = options.mId;
info.mElement = options.mControl;
RefPtr<PathBuilder> pathBuilder = mPath->TransformedCopyToBuilder(mTarget->GetTransform());
RefPtr<PathBuilder> pathBuilder = path->TransformedCopyToBuilder(mTarget->GetTransform());
info.mPath = pathBuilder->Finish();
mHitRegionsOptions.InsertElementAt(0, info);
@@ -5598,12 +5609,7 @@ CanvasRenderingContext2D::GetBufferProvider(LayerManager* aManager)
return nullptr;
}
mBufferProvider = aManager->CreatePersistentBufferProvider(mTarget->GetSize(), mTarget->GetFormat());
RefPtr<SourceSurface> surf = mTarget->Snapshot();
mTarget = mBufferProvider->GetDT(IntRect(IntPoint(), mTarget->GetSize()));
mTarget->CopySurface(surf, IntRect(IntPoint(), mTarget->GetSize()), IntPoint());
mBufferProvider = new PersistentBufferProviderBasic(mTarget);
return mBufferProvider;
}
+2 -66
View File
@@ -44,77 +44,12 @@ class StringOrCanvasGradientOrCanvasPattern;
class OwningStringOrCanvasGradientOrCanvasPattern;
class TextMetrics;
class CanvasFilterChainObserver;
class CanvasPath;
extern const mozilla::gfx::Float SIGMA_MAX;
template<typename T> class Optional;
class CanvasPath final :
public nsWrapperCache
{
public:
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(CanvasPath)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(CanvasPath)
nsCOMPtr<nsISupports> GetParentObject() { return mParent; }
JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto);
static already_AddRefed<CanvasPath> Constructor(const GlobalObject& aGlobal,
ErrorResult& rv);
static already_AddRefed<CanvasPath> Constructor(const GlobalObject& aGlobal,
CanvasPath& aCanvasPath,
ErrorResult& rv);
static already_AddRefed<CanvasPath> Constructor(const GlobalObject& aGlobal,
const nsAString& aPathString,
ErrorResult& rv);
void ClosePath();
void MoveTo(double x, double y);
void LineTo(double x, double y);
void QuadraticCurveTo(double cpx, double cpy, double x, double y);
void BezierCurveTo(double cp1x, double cp1y,
double cp2x, double cp2y,
double x, double y);
void ArcTo(double x1, double y1, double x2, double y2, double radius,
ErrorResult& error);
void Rect(double x, double y, double w, double h);
void Arc(double x, double y, double radius,
double startAngle, double endAngle, bool anticlockwise,
ErrorResult& error);
void Ellipse(double x, double y, double radiusX, double radiusY,
double rotation, double startAngle, double endAngle,
bool anticlockwise, ErrorResult& error);
void LineTo(const gfx::Point& aPoint);
void BezierTo(const gfx::Point& aCP1,
const gfx::Point& aCP2,
const gfx::Point& aCP3);
already_AddRefed<gfx::Path> GetPath(const CanvasWindingRule& aWinding,
const gfx::DrawTarget* aTarget) const;
explicit CanvasPath(nsISupports* aParent);
// already_AddRefed arg because the return value from Path::CopyToBuilder()
// is passed directly and we can't drop the only ref to have a raw pointer.
CanvasPath(nsISupports* aParent,
already_AddRefed<gfx::PathBuilder> aPathBuilder);
void AddPath(CanvasPath& aCanvasPath,
const Optional<NonNull<SVGMatrix>>& aMatrix);
private:
virtual ~CanvasPath() {}
nsCOMPtr<nsISupports> mParent;
static gfx::Float ToFloat(double aValue) { return gfx::Float(aValue); }
mutable RefPtr<gfx::Path> mPath;
mutable RefPtr<gfx::PathBuilder> mPathBuilder;
void EnsurePathBuilder() const;
};
struct CanvasBidiProcessor;
class CanvasRenderingContext2DUserData;
class CanvasDrawObserver;
@@ -977,6 +912,7 @@ protected:
fillRule(mozilla::gfx::FillRule::FILL_WINDING),
lineCap(mozilla::gfx::CapStyle::BUTT),
lineJoin(mozilla::gfx::JoinStyle::MITER_OR_BEVEL),
filterString(MOZ_UTF16("none")),
imageSmoothingEnabled(true),
fontExplicitLanguage(false)
{ }
+1
View File
@@ -28,6 +28,7 @@ EXPORTS.mozilla.ipc += [
EXPORTS.mozilla.dom += [
'CanvasGradient.h',
'CanvasPath.h',
'CanvasPattern.h',
'CanvasRenderingContext2D.h',
'CanvasUtils.h',
+17 -1
View File
@@ -32,16 +32,29 @@ SpecialPowers.pushPrefEnv({"set": [["canvas.hitregions.enabled", true]]}, functi
ctx.rect(20, 20, 100, 75);
ctx.fill();
ctx.addHitRegion({id: "a"});
ctx.beginPath();
ctx.fillStyle = "red";
ctx.rect(60, 40, 100, 75);
ctx.fill();
ctx.addHitRegion({id: "b"});
var mypath = new Path2D();
mypath.rect(80, 60, 10, 10);
ctx.beginPath();
ctx.fillStyle = "yellow";
ctx.rect(80, 60, 10, 10);
ctx.fill();
ctx.addHitRegion({id: "c"});
ctx.addHitRegion({id: "c", path: mypath});
ctx.beginPath();
ctx.fillStyle = "green";
ctx.rect(60, 60, 10, 10); // This region is on purpose not the hit region
ctx.fill();
var mypath = new Path2D();
mypath.rect(70, 30, 10, 10);
ctx.addHitRegion({id: "d", path: mypath});
synthesizeMouse(input, 25,25, {type: "mousedown"});
is(regionId, "a", "Hit region a", ". Found: " + regionId);
@@ -55,6 +68,9 @@ SpecialPowers.pushPrefEnv({"set": [["canvas.hitregions.enabled", true]]}, functi
synthesizeMouse(input, 85,65, {type: "mousedown"});
is(regionId, "c", "Hit region c", ". Found: " + regionId);
synthesizeMouse(input, 75,35, {type: "mousedown"});
is(regionId, "d", "Hit region d", ". Found: " + regionId);
ctx.removeHitRegion("c");
synthesizeMouse(input, 85,65, {type: "mousedown"});
is(regionId, "b", "Hit region b", ". Found: " + regionId);
+6
View File
@@ -81,10 +81,14 @@ static int sMaxStreamVolumeTbl[AUDIO_STREAM_CNT] = {
};
// A bitwise variable for recording what kind of headset is attached.
static int sHeadsetState;
#if defined(MOZ_B2G_BT) || ANDROID_VERSION >= 17
static bool sBluetoothA2dpEnabled;
#endif
static const int kBtSampleRate = 8000;
static bool sSwitchDone = true;
#ifdef MOZ_B2G_BT
static bool sA2dpSwitchDone = true;
#endif
namespace mozilla {
namespace dom {
@@ -216,6 +220,7 @@ static void ProcessDelayedAudioRoute(SwitchState aState)
sSwitchDone = true;
}
#ifdef MOZ_B2G_BT
static void ProcessDelayedA2dpRoute(audio_policy_dev_state_t aState, const nsCString aAddress)
{
if (sA2dpSwitchDone)
@@ -228,6 +233,7 @@ static void ProcessDelayedA2dpRoute(audio_policy_dev_state_t aState, const nsCSt
AudioSystem::setParameters(0, cmd);
sA2dpSwitchDone = true;
}
#endif
NS_IMPL_ISUPPORTS(AudioManager, nsIAudioManager, nsIObserver)
@@ -21,6 +21,7 @@ dictionary ContextAttributes2D {
};
dictionary HitRegionOptions {
Path2D? path = null;
DOMString id = "";
Element? control = null;
};
+196
View File
@@ -0,0 +1,196 @@
/*
============================================================================
Name : MMIHelpers.h
Author : Heiher <r@hev.cc>
Version : 0.0.1
Copyright : Copyright (c) 2015 everyone.
Description : The helpers for x86 SSE to Loongson MMI.
============================================================================
*/
#ifndef __MMI_HELPERS_H__
#define __MMI_HELPERS_H__
#define __mm_packxxxx(_f, _D, _d, _s, _t) \
#_f" %["#_t"], %["#_d"h], %["#_s"h] \n\t" \
#_f" %["#_D"l], %["#_d"l], %["#_s"l] \n\t" \
"punpckhwd %["#_D"h], %["#_D"l], %["#_t"] \n\t" \
"punpcklwd %["#_D"l], %["#_D"l], %["#_t"] \n\t"
#define _mm_or(_D, _d, _s) \
"or %["#_D"h], %["#_d"h], %["#_s"h] \n\t" \
"or %["#_D"l], %["#_d"l], %["#_s"l] \n\t"
#define _mm_xor(_D, _d, _s) \
"xor %["#_D"h], %["#_d"h], %["#_s"h] \n\t" \
"xor %["#_D"l], %["#_d"l], %["#_s"l] \n\t"
#define _mm_and(_D, _d, _s) \
"and %["#_D"h], %["#_d"h], %["#_s"h] \n\t" \
"and %["#_D"l], %["#_d"l], %["#_s"l] \n\t"
/* SSE: pandn */
#define _mm_pandn(_D, _d, _s) \
"pandn %["#_D"h], %["#_d"h], %["#_s"h] \n\t" \
"pandn %["#_D"l], %["#_d"l], %["#_s"l] \n\t"
/* SSE: pshuflw */
#define _mm_pshuflh(_D, _d, _s) \
"mov.d %["#_D"h], %["#_d"h] \n\t" \
"pshufh %["#_D"l], %["#_d"l], %["#_s"] \n\t"
/* SSE: psllw (bits) */
#define _mm_psllh(_D, _d, _s) \
"psllh %["#_D"h], %["#_d"h], %["#_s"] \n\t" \
"psllh %["#_D"l], %["#_d"l], %["#_s"] \n\t"
/* SSE: pslld (bits) */
#define _mm_psllw(_D, _d, _s) \
"psllw %["#_D"h], %["#_d"h], %["#_s"] \n\t" \
"psllw %["#_D"l], %["#_d"l], %["#_s"] \n\t"
/* SSE: psllq (bits) */
#define _mm_pslld(_D, _d, _s) \
"dsll %["#_D"h], %["#_d"h], %["#_s"] \n\t" \
"dsll %["#_D"l], %["#_d"l], %["#_s"] \n\t"
/* SSE: pslldq (bytes) */
#define _mm_psllq(_D, _d, _s, _s64, _tf) \
"subu %["#_tf"], %["#_s64"], %["#_s"] \n\t" \
"dsrl %["#_tf"], %["#_d"l], %["#_tf"] \n\t" \
"dsll %["#_D"h], %["#_d"h], %["#_s"] \n\t" \
"dsll %["#_D"l], %["#_d"l], %["#_s"] \n\t" \
"or %["#_D"h], %["#_D"h], %["#_tf"] \n\t"
/* SSE: psrlw (bits) */
#define _mm_psrlh(_D, _d, _s) \
"psrlh %["#_D"h], %["#_d"h], %["#_s"] \n\t" \
"psrlh %["#_D"l], %["#_d"l], %["#_s"] \n\t"
/* SSE: psrld (bits) */
#define _mm_psrlw(_D, _d, _s) \
"psrlw %["#_D"h], %["#_d"h], %["#_s"] \n\t" \
"psrlw %["#_D"l], %["#_d"l], %["#_s"] \n\t"
/* SSE: psrlq (bits) */
#define _mm_psrld(_D, _d, _s) \
"dsrl %["#_D"h], %["#_d"h], %["#_s"] \n\t" \
"dsrl %["#_D"l], %["#_d"l], %["#_s"] \n\t"
/* SSE: psrldq (bytes) */
#define _mm_psrlq(_D, _d, _s, _s64, _tf) \
"subu %["#_tf"], %["#_s64"], %["#_s"] \n\t" \
"dsll %["#_tf"], %["#_d"h], %["#_tf"] \n\t" \
"dsrl %["#_D"h], %["#_d"h], %["#_s"] \n\t" \
"dsrl %["#_D"l], %["#_d"l], %["#_s"] \n\t" \
"or %["#_D"l], %["#_D"l], %["#_tf"] \n\t"
/* SSE: psrad */
#define _mm_psraw(_D, _d, _s) \
"psraw %["#_D"h], %["#_d"h], %["#_s"] \n\t" \
"psraw %["#_D"l], %["#_d"l], %["#_s"] \n\t"
/* SSE: paddb */
#define _mm_paddb(_D, _d, _s) \
"paddb %["#_D"h], %["#_d"h], %["#_s"h] \n\t" \
"paddb %["#_D"l], %["#_d"l], %["#_s"l] \n\t"
/* SSE: paddw */
#define _mm_paddh(_D, _d, _s) \
"paddh %["#_D"h], %["#_d"h], %["#_s"h] \n\t" \
"paddh %["#_D"l], %["#_d"l], %["#_s"l] \n\t"
/* SSE: paddd */
#define _mm_paddw(_D, _d, _s) \
"paddw %["#_D"h], %["#_d"h], %["#_s"h] \n\t" \
"paddw %["#_D"l], %["#_d"l], %["#_s"l] \n\t"
/* SSE: paddq */
#define _mm_paddd(_D, _d, _s) \
"dadd %["#_D"h], %["#_d"h], %["#_s"h] \n\t" \
"dadd %["#_D"l], %["#_d"l], %["#_s"l] \n\t"
/* SSE: psubw */
#define _mm_psubh(_D, _d, _s) \
"psubh %["#_D"h], %["#_d"h], %["#_s"h] \n\t" \
"psubh %["#_D"l], %["#_d"l], %["#_s"l] \n\t"
/* SSE: psubd */
#define _mm_psubw(_D, _d, _s) \
"psubw %["#_D"h], %["#_d"h], %["#_s"h] \n\t" \
"psubw %["#_D"l], %["#_d"l], %["#_s"l] \n\t"
/* SSE: pmaxub */
#define _mm_pmaxub(_D, _d, _s) \
"pmaxub %["#_D"h], %["#_d"h], %["#_s"h] \n\t" \
"pmaxub %["#_D"l], %["#_d"l], %["#_s"l] \n\t"
/* SSE: pmullw */
#define _mm_pmullh(_D, _d, _s) \
"pmullh %["#_D"h], %["#_d"h], %["#_s"h] \n\t" \
"pmullh %["#_D"l], %["#_d"l], %["#_s"l] \n\t"
/* SSE: pmulhw */
#define _mm_pmulhh(_D, _d, _s) \
"pmulhh %["#_D"h], %["#_d"h], %["#_s"h] \n\t" \
"pmulhh %["#_D"l], %["#_d"l], %["#_s"l] \n\t"
/* SSE: pmuludq */
#define _mm_pmuluw(_D, _d, _s) \
"pmuluw %["#_D"h], %["#_d"h], %["#_s"h] \n\t" \
"pmuluw %["#_D"l], %["#_d"l], %["#_s"l] \n\t"
/* SSE: packsswb */
#define _mm_packsshb(_D, _d, _s, _t) \
__mm_packxxxx(packsshb, _D, _d, _s, _t)
/* SSE: packssdw */
#define _mm_packsswh(_D, _d, _s, _t) \
__mm_packxxxx(packsswh, _D, _d, _s, _t)
/* SSE: packuswb */
#define _mm_packushb(_D, _d, _s, _t) \
__mm_packxxxx(packushb, _D, _d, _s, _t)
/* SSE: punpcklbw */
#define _mm_punpcklbh(_D, _d, _s) \
"punpckhbh %["#_D"h], %["#_d"l], %["#_s"l] \n\t" \
"punpcklbh %["#_D"l], %["#_d"l], %["#_s"l] \n\t"
/* SSE: punpcklwd */
#define _mm_punpcklhw(_D, _d, _s) \
"punpckhhw %["#_D"h], %["#_d"l], %["#_s"l] \n\t" \
"punpcklhw %["#_D"l], %["#_d"l], %["#_s"l] \n\t"
/* SSE: punpckldq */
#define _mm_punpcklwd(_D, _d, _s) \
"punpckhwd %["#_D"h], %["#_d"l], %["#_s"l] \n\t" \
"punpcklwd %["#_D"l], %["#_d"l], %["#_s"l] \n\t"
/* SSE: punpcklqdq */
#define _mm_punpckldq(_D, _d, _s) \
"mov.d %["#_D"h], %["#_s"l] \n\t" \
"mov.d %["#_D"l], %["#_d"l] \n\t"
/* SSE: punpckhbw */
#define _mm_punpckhbh(_D, _d, _s) \
"punpcklbh %["#_D"l], %["#_d"h], %["#_s"h] \n\t" \
"punpckhbh %["#_D"h], %["#_d"h], %["#_s"h] \n\t"
/* SSE: punpckhwd */
#define _mm_punpckhhw(_D, _d, _s) \
"punpcklhw %["#_D"l], %["#_d"h], %["#_s"h] \n\t" \
"punpckhhw %["#_D"h], %["#_d"h], %["#_s"h] \n\t"
/* SSE: punpckhdq */
#define _mm_punpckhwd(_D, _d, _s) \
"punpcklwd %["#_D"l], %["#_d"h], %["#_s"h] \n\t" \
"punpckhwd %["#_D"h], %["#_d"h], %["#_s"h] \n\t"
/* SSE: punpckhqdq */
#define _mm_punpckhdq(_D, _d, _s) \
"mov.d %["#_D"l], %["#_d"h] \n\t" \
"mov.d %["#_D"h], %["#_s"h] \n\t"
#endif /* __MMI_HELPERS_H__ */
+2
View File
@@ -101,6 +101,7 @@ SourceSurfaceSkia::InitFromTexture(DrawTargetSkia* aOwner,
SurfaceFormat aFormat)
{
MOZ_ASSERT(aOwner, "null GrContext");
#ifdef USE_SKIA_GPU
GrBackendTextureDesc skiaTexGlue;
mSize.width = skiaTexGlue.fWidth = aSize.width;
mSize.height = skiaTexGlue.fHeight = aSize.height;
@@ -117,6 +118,7 @@ SourceSurfaceSkia::InitFromTexture(DrawTargetSkia* aOwner,
mBitmap.setPixelRef(texRef);
mFormat = aFormat;
mStride = mBitmap.rowBytes();
#endif
mDrawTarget = aOwner;
return true;
+10 -6
View File
@@ -168,15 +168,19 @@ ImageOperations::ResizeMethod ResizeMethodToAlgorithmMethod(
// GPU-acceleration in the cases where it is possible. So now we just
// pick the appropriate software method for each resize quality.
switch (method) {
// Users of RESIZE_GOOD are willing to trade a lot of quality to
// get speed, allowing the use of linear resampling to get hardware
// acceleration (SRB). Hence any of our "good" software filters
// will be acceptable, and we use the fastest one, Hamming-1.
case ImageOperations::RESIZE_GOOD:
// In visual tests we see that Hamming-1 is not as good as
// Lanczos-2, however it is about 40% faster, and Lanczos-2 itself is
// Users of RESIZE_BETTER are willing to trade some quality in order
// to improve performance, but are guaranteed not to devolve to a linear
// resampling. In visual tests we see that Hamming-1 is not as good as
// Lanczos-2, however it is about 40% faster and Lanczos-2 itself is
// about 30% faster than Lanczos-3. The use of Hamming-1 has been deemed
// an unacceptable trade-off between quality and speed due to the limited
// pixel space it operates in (<50%) before switching to HQ scaling
// becomes necessary to retain the fidelity of images.
// an acceptable trade-off between quality and speed.
case ImageOperations::RESIZE_BETTER:
return ImageOperations::RESIZE_LANCZOS2;
return ImageOperations::RESIZE_HAMMING1;
default:
return ImageOperations::RESIZE_LANCZOS3;
}
+2 -2
View File
@@ -165,12 +165,12 @@ LayerManager::CreatePersistentBufferProvider(const mozilla::gfx::IntSize &aSize,
mozilla::gfx::SurfaceFormat aFormat)
{
RefPtr<PersistentBufferProviderBasic> bufferProvider =
new PersistentBufferProviderBasic(this, aSize, aFormat,
new PersistentBufferProviderBasic(aSize, aFormat,
gfxPlatform::GetPlatform()->GetPreferredCanvasBackend());
if (!bufferProvider->IsValid()) {
bufferProvider =
new PersistentBufferProviderBasic(this, aSize, aFormat,
new PersistentBufferProviderBasic(aSize, aFormat,
gfxPlatform::GetPlatform()->GetFallbackCanvasBackend());
}
+2 -2
View File
@@ -16,8 +16,8 @@ using namespace gfx;
namespace layers {
PersistentBufferProviderBasic::PersistentBufferProviderBasic(LayerManager* aManager, gfx::IntSize aSize,
gfx::SurfaceFormat aFormat, gfx::BackendType aBackend)
PersistentBufferProviderBasic::PersistentBufferProviderBasic(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
gfx::BackendType aBackend)
{
mDrawTarget = gfxPlatform::GetPlatform()->CreateDrawTargetForBackend(aBackend, aSize, aFormat);
}
+7 -5
View File
@@ -7,7 +7,7 @@
#define MOZILLA_GFX_PersistentBUFFERPROVIDER_H
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
#include "mozilla/RefPtr.h" // for RefPtr, TemporaryRef, etc
#include "mozilla/RefPtr.h" // for RefPtr, already_AddRefed, etc
#include "mozilla/layers/LayersTypes.h"
#include "mozilla/layers/CompositableForwarder.h"
#include "mozilla/gfx/Types.h"
@@ -57,8 +57,9 @@ class PersistentBufferProviderBasic : public PersistentBufferProvider
public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PersistentBufferProviderBasic)
PersistentBufferProviderBasic(LayerManager* aManager, gfx::IntSize aSize,
gfx::SurfaceFormat aFormat, gfx::BackendType aBackend);
PersistentBufferProviderBasic(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
gfx::BackendType aBackend);
explicit PersistentBufferProviderBasic(gfx::DrawTarget* aTarget) : mDrawTarget(aTarget) {}
bool IsValid() { return !!mDrawTarget; }
virtual LayersBackend GetType() { return LayersBackend::LAYERS_BASIC; }
@@ -69,6 +70,7 @@ private:
RefPtr<gfx::DrawTarget> mDrawTarget;
};
}
}
} // namespace layers
} // namespace mozilla
#endif
+1 -1
View File
@@ -1104,6 +1104,7 @@ void
gfxPlatform::InitializeSkiaCacheLimits()
{
if (UseAcceleratedSkiaCanvas()) {
#ifdef USE_SKIA_GPU
bool usingDynamicCache = gfxPrefs::CanvasSkiaGLDynamicCache();
int cacheItemLimit = gfxPrefs::CanvasSkiaGLCacheItems();
int cacheSizeLimit = gfxPrefs::CanvasSkiaGLCacheSize();
@@ -1125,7 +1126,6 @@ gfxPlatform::InitializeSkiaCacheLimits()
printf_stderr("Determined SkiaGL cache limits: Size %i, Items: %i\n", cacheSizeLimit, cacheItemLimit);
#endif
#ifdef USE_SKIA_GPU
mSkiaGlue->GetGrContext()->setResourceCacheLimits(cacheItemLimit, cacheSizeLimit);
#endif
}
+1 -1
View File
@@ -246,7 +246,7 @@ private:
{
Work work;
work.mType = Work::Type::DECODE;
work.mDecoder = aQueue.LastElement();
work.mDecoder = aQueue.LastElement().forget();
aQueue.RemoveElementAt(aQueue.Length() - 1);
return work;
+3 -2
View File
@@ -431,9 +431,10 @@ Decoder::PostIsAnimated(int32_t aFirstFrameTimeout)
}
void
Decoder::PostFrameStop(Opacity aFrameOpacity /* = Opacity::TRANSPARENT */,
Decoder::PostFrameStop(Opacity aFrameOpacity
/* = Opacity::SOME_TRANSPARENCY */,
DisposalMethod aDisposalMethod
/* = DisposalMethod::KEEP */,
/* = DisposalMethod::KEEP */,
int32_t aTimeout /* = 0 */,
BlendMethod aBlendMethod /* = BlendMethod::OVER */)
{
-5
View File
@@ -196,7 +196,6 @@ public:
bool HasDecoderError() const { return NS_FAILED(mFailCode); }
bool ShouldReportError() const { return mShouldReportError; }
nsresult GetDecoderError() const { return mFailCode; }
void PostResizeError() { PostDataError(); }
/// Did we finish decoding enough that calling Decode() again would be useless?
bool GetDecodeDone() const
@@ -205,10 +204,6 @@ public:
HasError() || mDataDone;
}
/// Did we finish decoding enough to set |RasterImage::mHasBeenDecoded|?
// XXX(seth): This will be removed in bug 1187401.
bool GetDecodeTotallyDone() const { return mDecodeDone && !IsMetadataDecode(); }
/// Are we in the middle of a frame right now? Used for assertions only.
bool InFrame() const { return mInFrame; }
+25 -10
View File
@@ -38,10 +38,16 @@ public:
void BlockUntilDecodedAndFinishObserving()
{
// Use GetFrame() to block until our image finishes decoding.
mImage->GetFrame(imgIContainer::FRAME_CURRENT,
imgIContainer::FLAG_SYNC_DECODE);
nsRefPtr<SourceSurface> surface =
mImage->GetFrame(imgIContainer::FRAME_CURRENT,
imgIContainer::FLAG_SYNC_DECODE);
FinishObserving();
// GetFrame() should've sent synchronous notifications that would have
// caused us to call FinishObserving() (and null out mImage) already. If for
// some reason it didn't, we should do so here.
if (mImage) {
FinishObserving();
}
}
virtual void Notify(int32_t aType,
@@ -129,9 +135,7 @@ MultipartImage::~MultipartImage()
mTracker->ResetImage();
}
NS_IMPL_QUERY_INTERFACE_INHERITED0(MultipartImage, ImageWrapper)
NS_IMPL_ADDREF(MultipartImage)
NS_IMPL_RELEASE(MultipartImage)
NS_IMPL_ISUPPORTS_INHERITED0(MultipartImage, ImageWrapper)
void
MultipartImage::BeginTransitionToPart(Image* aNextPart)
@@ -154,7 +158,16 @@ MultipartImage::BeginTransitionToPart(Image* aNextPart)
mNextPart->IncrementAnimationConsumers();
}
void MultipartImage::FinishTransition()
static Progress
FilterProgress(Progress aProgress)
{
// Filter out onload blocking notifications, since we don't want to block
// onload for multipart images.
return aProgress & ~(FLAG_ONLOAD_BLOCKED | FLAG_ONLOAD_UNBLOCKED);
}
void
MultipartImage::FinishTransition()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mNextPart, "Should have a next part here");
@@ -169,7 +182,8 @@ void MultipartImage::FinishTransition()
mTracker->ResetForNewRequest();
nsRefPtr<ProgressTracker> currentPartTracker =
InnerImage()->GetProgressTracker();
mTracker->SyncNotifyProgress(currentPartTracker->GetProgress());
mTracker
->SyncNotifyProgress(FilterProgress(currentPartTracker->GetProgress()));
return;
}
@@ -189,8 +203,9 @@ void MultipartImage::FinishTransition()
// Finally, send all the notifications for the new current part and send a
// FRAME_UPDATE notification so that observers know to redraw.
mTracker->SyncNotifyProgress(newCurrentPartTracker->GetProgress(),
GetMaxSizedIntRect());
mTracker
->SyncNotifyProgress(FilterProgress(newCurrentPartTracker->GetProgress()),
GetMaxSizedIntRect());
}
already_AddRefed<imgIContainer>
+1 -1
View File
@@ -25,7 +25,7 @@ class MultipartImage
{
public:
MOZ_DECLARE_REFCOUNTED_TYPENAME(MultipartImage)
NS_DECL_ISUPPORTS
NS_DECL_ISUPPORTS_INHERITED
void BeginTransitionToPart(Image* aNextPart);
+2 -2
View File
@@ -56,7 +56,7 @@ struct Orientation
Flip flip;
};
}
}
} // namespace image
} // namespace mozilla
#endif // mozilla_image_Orientation_h
+7 -5
View File
@@ -441,13 +441,14 @@ void
ProgressTracker::AddObserver(IProgressObserver* aObserver)
{
MOZ_ASSERT(NS_IsMainThread());
nsRefPtr<IProgressObserver> observer = aObserver;
mObservers.Write([=](ObserverTable* aTable) {
MOZ_ASSERT(!aTable->Get(aObserver, nullptr),
MOZ_ASSERT(!aTable->Get(observer, nullptr),
"Adding duplicate entry for image observer");
WeakPtr<IProgressObserver> weakPtr = aObserver;
aTable->Put(aObserver, weakPtr);
WeakPtr<IProgressObserver> weakPtr = observer.get();
aTable->Put(observer, weakPtr);
});
}
@@ -455,11 +456,12 @@ bool
ProgressTracker::RemoveObserver(IProgressObserver* aObserver)
{
MOZ_ASSERT(NS_IsMainThread());
nsRefPtr<IProgressObserver> observer = aObserver;
// Remove the observer from the list.
bool removed = mObservers.Write([=](ObserverTable* aTable) {
bool removed = aTable->Get(aObserver, nullptr);
aTable->Remove(aObserver);
bool removed = aTable->Get(observer, nullptr);
aTable->Remove(observer);
return removed;
});
+18 -18
View File
@@ -819,20 +819,22 @@ RasterImage::OnAddedFrame(uint32_t aNewFrameCount,
}
}
nsresult
void
RasterImage::SetMetadata(const ImageMetadata& aMetadata,
bool aFromMetadataDecode)
{
MOZ_ASSERT(NS_IsMainThread());
if (mError) {
return NS_ERROR_FAILURE;
return;
}
if (aMetadata.HasSize()) {
IntSize size = aMetadata.GetSize();
if (size.width < 0 || size.height < 0) {
return NS_ERROR_INVALID_ARG;
NS_WARNING("Image has negative intrinsic size");
DoError();
return;
}
MOZ_ASSERT(aMetadata.HasOrientation());
@@ -843,7 +845,7 @@ RasterImage::SetMetadata(const ImageMetadata& aMetadata,
NS_WARNING("Image changed size or orientation on redecode! "
"This should not happen!");
DoError();
return NS_ERROR_UNEXPECTED;
return;
}
// Set the size and flag that we have it.
@@ -887,8 +889,6 @@ RasterImage::SetMetadata(const ImageMetadata& aMetadata,
Set("hotspotX", intwrapx);
Set("hotspotY", intwrapy);
}
return NS_OK;
}
NS_IMETHODIMP
@@ -1074,7 +1074,7 @@ RasterImage::NotifyForLoadEvent(Progress aProgress)
if (mError) {
aProgress |= FLAG_HAS_ERROR;
}
// Notify our listeners, which will fire this image's load event.
NotifyProgress(aProgress);
}
@@ -1374,6 +1374,11 @@ RasterImage::RecoverFromInvalidFrames(const IntSize& aSize, uint32_t aFlags)
// Discard all existing frames, since they're probably all now invalid.
SurfaceCache::RemoveImage(ImageKey(this));
// Relock the image if it's supposed to be locked.
if (mLockCount > 0) {
SurfaceCache::LockImage(ImageKey(this));
}
// Animated images require some special handling, because we normally require
// that they never be discarded.
if (mAnim) {
@@ -1707,22 +1712,20 @@ RasterImage::FinalizeDecoder(Decoder* aDecoder)
MOZ_ASSERT(aDecoder->HasError() || !aDecoder->InFrame(),
"Finalizing a decoder in the middle of a frame");
bool wasMetadata = aDecoder->IsMetadataDecode();
bool done = aDecoder->GetDecodeDone();
// If the decoder detected an error, log it to the error console.
if (aDecoder->ShouldReportError() && !aDecoder->WasAborted()) {
ReportDecoderError(aDecoder);
}
// Record all the metadata the decoder gathered about this image.
nsresult rv = SetMetadata(aDecoder->GetImageMetadata(),
aDecoder->IsMetadataDecode());
if (NS_FAILED(rv)) {
aDecoder->PostResizeError();
}
SetMetadata(aDecoder->GetImageMetadata(), wasMetadata);
MOZ_ASSERT(mError || mHasSize || !aDecoder->HasSize(),
"Should have handed off size by now");
"SetMetadata should've gotten a size");
if (aDecoder->GetDecodeTotallyDone() && !mError) {
if (!wasMetadata && aDecoder->GetDecodeDone() && !aDecoder->WasAborted()) {
// Flag that we've been decoded before.
mHasBeenDecoded = true;
if (mAnim) {
@@ -1735,9 +1738,6 @@ RasterImage::FinalizeDecoder(Decoder* aDecoder)
aDecoder->TakeInvalidRect(),
aDecoder->GetSurfaceFlags());
bool wasMetadata = aDecoder->IsMetadataDecode();
bool done = aDecoder->GetDecodeDone();
if (!wasMetadata && aDecoder->ChunkCount()) {
/*Telemetry::Accumulate(Telemetry::IMAGE_DECODE_CHUNKS,
aDecoder->ChunkCount());*/
+5 -5
View File
@@ -325,7 +325,7 @@ private:
* @param aFromMetadataDecode True if this metadata came from a metadata
* decode; false if it came from a full decode.
*/
nsresult SetMetadata(const ImageMetadata& aMetadata, bool aFromMetadataDecode);
void SetMetadata(const ImageMetadata& aMetadata, bool aFromMetadataDecode);
/**
* In catastrophic circumstances like a GPU driver crash, the contents of our
@@ -347,10 +347,10 @@ private: // data
/// If this has a value, we're waiting for SetSize() to send the load event.
Maybe<Progress> mLoadProgress;
nsCOMPtr<nsIProperties> mProperties;
nsCOMPtr<nsIProperties> mProperties;
/// If this image is animated, a FrameAnimator which manages its animation.
UniquePtr<FrameAnimator> mAnim;
UniquePtr<FrameAnimator> mAnim;
// Image locking.
uint32_t mLockCount;
@@ -360,7 +360,7 @@ private: // data
// How many times we've decoded this image.
// This is currently only used for statistics
int32_t mDecodeCount;
int32_t mDecodeCount;
// If the image contains multiple resolutions, a hint as to which one
// should be used
@@ -378,7 +378,7 @@ private: // data
DrawResult mLastImageContainerDrawResult;
#ifdef DEBUG
uint32_t mFramesNotified;
uint32_t mFramesNotified;
#endif
// The source data for this image.
+2 -2
View File
@@ -35,8 +35,8 @@ class SVGSVGElement;
namespace image {
class SVGDocumentWrapper final : public nsIStreamListener,
public nsIObserver,
nsSupportsWeakReference
public nsIObserver,
nsSupportsWeakReference
{
public:
SVGDocumentWrapper();
+2 -7
View File
@@ -120,7 +120,8 @@ public:
/// If at the end, returns the status passed to SourceBuffer::Complete().
nsresult CompletionStatus() const
{
MOZ_ASSERT(mState == COMPLETE, "Calling CompletionStatus() in the wrong state");
MOZ_ASSERT(mState == COMPLETE,
"Calling CompletionStatus() in the wrong state");
return mState == COMPLETE ? mData.mAtEnd.mStatus : NS_OK;
}
@@ -209,12 +210,6 @@ private:
* keep a list of consumers which are waiting for new data, and to resume them
* when the producer appends more. All consumers must implement the IResumable
* interface to make this possible.
*
* XXX(seth): We should add support for compacting a SourceBuffer. To do this,
* we need to have SourceBuffer keep track of how many live
* SourceBufferIterator's point to it. When the SourceBuffer is complete and no
* live SourceBufferIterator's for it remain, we can compact its contents into a
* single chunk.
*/
class SourceBuffer final
{
+19 -1
View File
@@ -35,6 +35,7 @@
#include "nsSize.h"
#include "nsTArray.h"
#include "prsystem.h"
#include "ShutdownTracker.h"
#include "SVGImageContext.h"
using std::max;
@@ -436,6 +437,7 @@ public:
, mMaxCost(aSurfaceCacheSize)
, mAvailableCost(aSurfaceCacheSize)
, mLockedCost(0)
, mOverflowCount(0)
{
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
if (os) {
@@ -483,6 +485,7 @@ public:
// If this is bigger than we can hold after discarding everything we can,
// refuse to cache it.
if (MOZ_UNLIKELY(!CanHoldAfterDiscarding(aCost))) {
mOverflowCount++;
return InsertOutcome::FAILURE;
}
@@ -582,7 +585,8 @@ public:
} else {
// Our call to AddObject must have failed in StartTracking; most likely
// we're in XPCOM shutdown right now.
NS_WARNING("Not expiration-tracking an unlocked surface!");
NS_ASSERTION(ShutdownTracker::ShutdownHasStarted(),
"Not expiration-tracking an unlocked surface!");
}
DebugOnly<bool> foundInCosts = mCosts.RemoveElementSorted(costEntry);
@@ -863,6 +867,14 @@ public:
"imagelib surface cache.");
NS_ENSURE_SUCCESS(rv, rv);
rv = MOZ_COLLECT_REPORT("imagelib-surface-cache-overflow-count",
KIND_OTHER, UNITS_COUNT,
mOverflowCount,
"Count of how many times the surface cache has hit "
"its capacity and been unable to insert a new "
"surface.");
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
@@ -962,6 +974,7 @@ private:
const Cost mMaxCost;
Cost mAvailableCost;
Cost mLockedCost;
size_t mOverflowCount;
};
NS_IMPL_ISUPPORTS(SurfaceCacheImpl, nsIMemoryReporter)
@@ -1079,6 +1092,11 @@ SurfaceCache::Insert(imgFrame* aSurface,
return InsertOutcome::FAILURE;
}
// Refuse null surfaces.
if (!aSurface) {
MOZ_CRASH("Don't pass null surfaces to SurfaceCache::Insert");
}
MutexAutoLock lock(sInstance->GetMutex());
Cost cost = ComputeCost(aSurface->GetSize(), aSurface->GetBytesPerPixel());
return sInstance->Insert(aSurface, cost, aImageKey, aSurfaceKey);
+45 -41
View File
@@ -9,7 +9,6 @@
#include "gfxContext.h"
#include "gfxDrawable.h"
#include "gfxPlatform.h"
#include "gfxPrefs.h" // for surface cache size
#include "gfxUtils.h"
#include "imgFrame.h"
#include "mozilla/AutoRestore.h"
@@ -49,6 +48,8 @@ namespace image {
// Helper-class: SVGRootRenderingObserver
class SVGRootRenderingObserver final : public nsSVGRenderingObserver {
public:
NS_DECL_ISUPPORTS
SVGRootRenderingObserver(SVGDocumentWrapper* aDocWrapper,
VectorImage* aVectorImage)
: nsSVGRenderingObserver()
@@ -67,10 +68,6 @@ public:
mInObserverList = true;
}
virtual ~SVGRootRenderingObserver()
{
StopListening();
}
void ResumeHonoringInvalidations()
{
@@ -78,6 +75,11 @@ public:
}
protected:
virtual ~SVGRootRenderingObserver()
{
StopListening();
}
virtual Element* GetTarget() override
{
return mDocWrapper->GetRootSVGElem();
@@ -115,6 +117,8 @@ protected:
bool mHonoringInvalidations;
};
NS_IMPL_ISUPPORTS(SVGRootRenderingObserver, nsIMutationObserver)
class SVGParseCompleteListener final : public nsStubDocumentObserver {
public:
NS_DECL_ISUPPORTS
@@ -418,13 +422,18 @@ VectorImage::OnImageDataComplete(nsIRequest* aRequest,
if (NS_FAILED(aStatus)) {
finalStatus = aStatus;
}
Progress loadProgress = LoadCompleteProgress(aLastPart, mError, finalStatus);
// Actually fire OnStopRequest.
if (mProgressTracker) {
mProgressTracker->SyncNotifyProgress(LoadCompleteProgress(aLastPart,
mError,
finalStatus));
if (mIsFullyLoaded || mError) {
// Our document is loaded, so we're ready to notify now.
mProgressTracker->SyncNotifyProgress(loadProgress);
} else {
// Record our progress so far; we'll actually send the notifications in
// OnSVGDocumentLoaded or OnSVGDocumentError.
mLoadProgress = Some(loadProgress);
}
return finalStatus;
}
@@ -867,32 +876,12 @@ VectorImage::CreateSurfaceAndShow(const SVGDrawingParameters& aParams)
nsRefPtr<gfxDrawable> svgDrawable =
new gfxCallbackDrawable(cb, aParams.size);
// We take an early exit without using the surface cache if too large,
// because for vector images this can cause bad perf issues if large sizes
// are scaled repeatedly (a rather common scenario) that can quickly exhaust
// the cache.
// Similar to max image size calculations, this has a max cap and size check.
// max cap = 8000 (pixels); size check = 5% of cache
int32_t maxDimension = 8000;
int32_t maxCacheElemSize = (gfxPrefs::ImageMemSurfaceCacheMaxSizeKB() * 1024) / 20;
bool bypassCache = bool(aParams.flags & FLAG_BYPASS_SURFACE_CACHE) ||
// Refuse to cache animated images:
// XXX(seth): We may remove this restriction in bug 922893.
mHaveAnimations ||
// The image is too big to fit in the cache:
!SurfaceCache::CanHold(aParams.size) ||
// Image x or y is larger than our cache cap:
aParams.size.width > maxDimension ||
aParams.size.height > maxDimension;
if (!bypassCache) {
// This is separated out to make sure width and height are sane at this point
// and the result can't overflow. Note: keep maxDimension low enough so that
// (maxDimension)^2 x 4 < INT32_MAX.
// Assuming surface size for any rendered vector image is RGBA, so 4Bpp.
bypassCache = (aParams.size.width * aParams.size.height * 4) > maxCacheElemSize;
}
!SurfaceCache::CanHold(aParams.size);
if (bypassCache) {
return Show(svgDrawable, aParams);
}
@@ -1193,12 +1182,19 @@ VectorImage::OnSVGDocumentLoaded()
// Tell *our* observers that we're done loading.
if (mProgressTracker) {
mProgressTracker->SyncNotifyProgress(FLAG_SIZE_AVAILABLE |
FLAG_HAS_TRANSPARENCY |
FLAG_FRAME_COMPLETE |
FLAG_DECODE_COMPLETE |
FLAG_ONLOAD_UNBLOCKED,
GetMaxSizedIntRect());
Progress progress = FLAG_SIZE_AVAILABLE |
FLAG_HAS_TRANSPARENCY |
FLAG_FRAME_COMPLETE |
FLAG_DECODE_COMPLETE |
FLAG_ONLOAD_UNBLOCKED;
// Merge in any saved progress from OnImageDataComplete.
if (mLoadProgress) {
progress |= *mLoadProgress;
mLoadProgress = Nothing();
}
mProgressTracker->SyncNotifyProgress(progress, GetMaxSizedIntRect());
}
EvaluateAnimation();
@@ -1215,10 +1211,18 @@ VectorImage::OnSVGDocumentError()
mError = true;
if (mProgressTracker) {
// Unblock page load.
mProgressTracker->SyncNotifyProgress(FLAG_DECODE_COMPLETE |
FLAG_ONLOAD_UNBLOCKED |
FLAG_HAS_ERROR);
// Notify observers about the error and unblock page load.
Progress progress = FLAG_DECODE_COMPLETE |
FLAG_ONLOAD_UNBLOCKED |
FLAG_HAS_ERROR;
// Merge in any saved progress from OnImageDataComplete.
if (mLoadProgress) {
progress |= *mLoadProgress;
mLoadProgress = Nothing();
}
mProgressTracker->SyncNotifyProgress(progress);
}
}
+7 -1
View File
@@ -23,7 +23,7 @@ class SVGLoadEventListener;
class SVGParseCompleteListener;
class VectorImage final : public ImageResource,
public nsIStreamListener
public nsIStreamListener
{
public:
NS_DECL_ISUPPORTS
@@ -102,6 +102,12 @@ private:
/// Count of locks on this image (roughly correlated to visible instances).
uint32_t mLockCount;
// Stored result from the Necko load of the image, which we save in
// OnImageDataComplete if the underlying SVG document isn't loaded. If we save
// this, we actually notify this progress (and clear this value) in
// OnSVGDocumentLoaded or OnSVGDocumentError.
Maybe<Progress> mLoadProgress;
bool mIsInitialized; // Have we been initialized?
bool mDiscardable; // Are we discardable?
bool mIsFullyLoaded; // Has the SVG document finished
+52 -16
View File
@@ -219,6 +219,8 @@ private:
const char* aPathPrefix,
const ImageMemoryCounter& aCounter)
{
nsresult rv;
nsAutoCString pathPrefix(NS_LITERAL_CSTRING("explicit/"));
pathPrefix.Append(aPathPrefix);
pathPrefix.Append(aCounter.Type() == imgIContainer::TYPE_RASTER
@@ -239,7 +241,13 @@ private:
pathPrefix.Append(")/");
return ReportSurfaces(aHandleReport, aData, pathPrefix, aCounter);
rv = ReportSurfaces(aHandleReport, aData, pathPrefix, aCounter);
NS_ENSURE_SUCCESS(rv, rv);
rv = ReportSourceValue(aHandleReport, aData, pathPrefix, aCounter.Values());
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
static nsresult ReportSurfaces(nsIHandleReportCallback* aHandleReport,
@@ -344,10 +352,7 @@ private:
{
nsresult rv;
rv = ReportValue(aHandleReport, aData, KIND_HEAP, aPathPrefix,
"source",
"Raster image source data and vector image documents.",
aCounter.Source());
rv = ReportSourceValue(aHandleReport, aData, aPathPrefix, aCounter);
NS_ENSURE_SUCCESS(rv, rv);
rv = ReportValue(aHandleReport, aData, KIND_HEAP, aPathPrefix,
@@ -365,6 +370,21 @@ private:
return NS_OK;
}
static nsresult ReportSourceValue(nsIHandleReportCallback* aHandleReport,
nsISupports* aData,
const nsACString& aPathPrefix,
const MemoryCounter& aCounter)
{
nsresult rv;
rv = ReportValue(aHandleReport, aData, KIND_HEAP, aPathPrefix,
"source",
"Raster image source data and vector image documents.",
aCounter.Source());
return rv;
}
static nsresult ReportValue(nsIHandleReportCallback* aHandleReport,
nsISupports* aData,
int32_t aKind,
@@ -706,6 +726,8 @@ NewImageChannel(nsIChannel** aResult,
nsIPrincipal* aLoadingPrincipal,
nsISupports* aRequestingContext)
{
MOZ_ASSERT(aResult);
nsresult rv;
nsCOMPtr<nsIHttpChannel> newHttpChannel;
@@ -768,7 +790,9 @@ NewImageChannel(nsIChannel** aResult,
// we should always have a requestingNode, or we are loading something
// outside a document, in which case the triggeringPrincipal
// should always be the systemPrincipal.
MOZ_ASSERT(nsContentUtils::IsSystemPrincipal(triggeringPrincipal));
// However, there are two exceptions: one is Notifications and the
// other one is Favicons which create a channel in the parent prcoess
// in which case we can't get a requestingNode.
rv = NS_NewChannel(aResult,
aURI,
triggeringPrincipal,
@@ -1446,9 +1470,8 @@ imgLoader::PutIntoCache(const ImageCacheKey& aKey, imgCacheEntry* entry)
LOG_STATIC_FUNC_WITH_PARAM(GetImgLog(),
"imgLoader::PutIntoCache", "uri", aKey.Spec());
// Check to see if this request already exists in the cache and is being
// loaded on a different thread. If so, don't allow this entry to be added to
// the cache.
// Check to see if this request already exists in the cache. If so, we'll
// replace the old version.
nsRefPtr<imgCacheEntry> tmpCacheEntry;
if (cache.Get(aKey, getter_AddRefs(tmpCacheEntry)) && tmpCacheEntry) {
MOZ_LOG(GetImgLog(), LogLevel::Debug,
@@ -1813,7 +1836,7 @@ imgLoader::ValidateEntry(imgCacheEntry* aEntry,
// XXX: nullptr seems to be a 'special' key value that indicates that NO
// validation is required.
//
void *key = (void*)aCX;
void *key = (void*) aCX;
if (request->LoadId() != key) {
// If we would need to revalidate this entry, but we're being told to
// bypass the cache, we don't allow this entry to be used.
@@ -2976,6 +2999,9 @@ imgCacheValidator::RemoveProxy(imgRequestProxy* aProxy)
NS_IMETHODIMP
imgCacheValidator::OnStartRequest(nsIRequest* aRequest, nsISupports* ctxt)
{
// We may be holding on to a document, so ensure that it's released.
nsCOMPtr<nsISupports> context = mContext.forget();
// If for some reason we don't still have an existing request (probably
// because OnStartRequest got delivered more than once), just bail.
if (!mRequest) {
@@ -3024,7 +3050,7 @@ imgCacheValidator::OnStartRequest(nsIRequest* aRequest, nsISupports* ctxt)
// We don't need to load this any more.
aRequest->Cancel(NS_BINDING_ABORTED);
mRequest->SetLoadId(mContext);
mRequest->SetLoadId(context);
mRequest->SetValidator(nullptr);
mRequest = nullptr;
@@ -3067,7 +3093,7 @@ imgCacheValidator::OnStartRequest(nsIRequest* aRequest, nsISupports* ctxt)
nsCOMPtr<nsIURI> originalURI;
channel->GetOriginalURI(getter_AddRefs(originalURI));
mNewRequest->Init(originalURI, uri, mHadInsecureRedirect, aRequest, channel,
mNewEntry, mContext, loadingPrincipal, corsmode, refpol);
mNewEntry, context, loadingPrincipal, corsmode, refpol);
mDestListener = new ProxyListener(mNewRequest);
@@ -3093,11 +3119,19 @@ imgCacheValidator::OnStartRequest(nsIRequest* aRequest, nsISupports* ctxt)
return mDestListener->OnStartRequest(aRequest, ctxt);
}
/* void onStopRequest (in nsIRequest request, in nsISupports ctxt, in nsresult status); */
NS_IMETHODIMP imgCacheValidator::OnStopRequest(nsIRequest *aRequest, nsISupports *ctxt, nsresult status)
/* void onStopRequest (in nsIRequest request, in nsISupports ctxt,
in nsresult status); */
NS_IMETHODIMP
imgCacheValidator::OnStopRequest(nsIRequest* aRequest,
nsISupports* ctxt,
nsresult status)
{
if (!mDestListener)
// Be sure we've released the document that we may have been holding on to.
mContext = nullptr;
if (!mDestListener) {
return NS_OK;
}
return mDestListener->OnStopRequest(aRequest, ctxt, status);
}
@@ -3180,7 +3214,9 @@ imgCacheValidator::
if (NS_FAILED(oldChannel->GetURI(getter_AddRefs(oldURI))) ||
NS_FAILED(oldURI->SchemeIs("https", &isHttps)) ||
NS_FAILED(oldURI->SchemeIs("chrome", &isChrome)) ||
NS_FAILED(NS_URIChainHasFlags(oldURI, nsIProtocolHandler::URI_IS_LOCAL_RESOURCE , &schemeLocal)) ||
NS_FAILED(NS_URIChainHasFlags(oldURI,
nsIProtocolHandler::URI_IS_LOCAL_RESOURCE,
&schemeLocal)) ||
(!isHttps && !isChrome && !schemeLocal)) {
mHadInsecureRedirect = true;
}
+28 -22
View File
@@ -634,17 +634,6 @@ imgRequest::SetCacheValidation(imgCacheEntry* aCacheEntry, nsIRequest* aRequest)
aCacheEntry->SetMustValidate(bMustRevalidate);
}
}
// We always need to validate file URIs.
nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
if (channel) {
nsCOMPtr<nsIURI> uri;
channel->GetURI(getter_AddRefs(uri));
bool isfile = false;
uri->SchemeIs("file", &isfile);
if (isfile)
aCacheEntry->SetMustValidate(isfile);
}
}
}
@@ -718,6 +707,13 @@ imgRequest::GetMultipart() const
return mIsMultiPartChannel;
}
bool
imgRequest::HadInsecureRedirect() const
{
MutexAutoLock lock(mMutex);
return mHadInsecureRedirect;
}
/** nsIRequestObserver methods **/
NS_IMETHODIMP
@@ -737,7 +733,7 @@ imgRequest::OnStartRequest(nsIRequest* aRequest, nsISupports* ctxt)
mIsMultiPartChannel = bool(multiPartChannel);
}
// If we're not multipart, we shouldn't have an image yet
// If we're not multipart, we shouldn't have an image yet.
if (image && !multiPartChannel) {
MOZ_ASSERT_UNREACHABLE("Already have an image for a non-multipart request");
Cancel(NS_IMAGELIB_ERROR_FAILURE);
@@ -752,7 +748,6 @@ imgRequest::OnStartRequest(nsIRequest* aRequest, nsISupports* ctxt)
* https://bugzilla.mozilla.org/show_bug.cgi?id=339610
*/
if (!mRequest) {
nsCOMPtr<nsIMultiPartChannel> multiPartChannel = do_QueryInterface(aRequest);
MOZ_ASSERT(multiPartChannel, "Should have mRequest unless we're multipart");
nsCOMPtr<nsIChannel> baseChannel;
multiPartChannel->GetBaseChannel(getter_AddRefs(baseChannel));
@@ -950,20 +945,20 @@ PrepareForNewPart(nsIRequest* aRequest, nsIInputStream* aInStr, uint32_t aCount,
nsCOMPtr<nsIChannel> chan(do_QueryInterface(aRequest));
if (result.mContentType.IsEmpty()) {
nsresult rv = NS_ERROR_FAILURE;
if (chan) {
rv = chan->GetContentType(result.mContentType);
chan->GetContentDispositionHeader(result.mContentDisposition);
}
nsresult rv = chan ? chan->GetContentType(result.mContentType)
: NS_ERROR_FAILURE;
if (NS_FAILED(rv)) {
MOZ_LOG(GetImgLog(),
LogLevel::Error, ("imgRequest::PrepareForNewPart "
"-- Content type unavailable from the channel\n"));
LogLevel::Error, ("imgRequest::PrepareForNewPart -- "
"Content type unavailable from the channel\n"));
return result;
}
}
if (chan) {
chan->GetContentDispositionHeader(result.mContentDisposition);
}
MOZ_LOG(GetImgLog(), LogLevel::Debug,
("imgRequest::PrepareForNewPart -- Got content type %s\n",
result.mContentType.get()));
@@ -1269,7 +1264,18 @@ imgRequest::OnRedirectVerifyCallback(nsresult result)
nsIProtocolHandler::URI_IS_LOCAL_RESOURCE,
&schemeLocal)) ||
(!isHttps && !isChrome && !schemeLocal)) {
mHadInsecureRedirect = true;
MutexAutoLock lock(mMutex);
// The csp directive upgrade-insecure-requests performs an internal redirect
// to upgrade all requests from http to https before any data is fetched from
// the network. Do not pollute mHadInsecureRedirect in case of such an internal
// redirect.
nsCOMPtr<nsILoadInfo> loadInfo = mChannel->GetLoadInfo();
bool upgradeInsecureRequests = loadInfo ? loadInfo->GetUpgradeInsecureRequests()
: false;
if (!upgradeInsecureRequests) {
mHadInsecureRedirect = true;
}
}
// Update the current URI.
+5 -5
View File
@@ -44,10 +44,10 @@ class ProgressTracker;
struct NewPartResult;
class imgRequest final : public nsIStreamListener,
public nsIThreadRetargetableStreamListener,
public nsIChannelEventSink,
public nsIInterfaceRequestor,
public nsIAsyncVerifyRedirectCallback
public nsIThreadRetargetableStreamListener,
public nsIChannelEventSink,
public nsIInterfaceRequestor,
public nsIAsyncVerifyRedirectCallback
{
typedef mozilla::image::Image Image;
typedef mozilla::image::ImageCacheKey ImageCacheKey;
@@ -118,7 +118,7 @@ public:
// Returns whether we went through an insecure (non-HTTPS) redirect at some
// point during loading. This does not consider the current URI.
bool HadInsecureRedirect() const { return mHadInsecureRedirect; }
bool HadInsecureRedirect() const;
// The CORS mode for which we loaded this image.
int32_t GetCORSMode() const { return mCORSMode; }
+4 -1
View File
@@ -203,7 +203,10 @@ private:
// mListener is only promised to be a weak ref (see imgILoader.idl),
// but we actually keep a strong ref to it until we've seen our
// first OnStopRequest.
imgINotificationObserver* mListener;
imgINotificationObserver* MOZ_UNSAFE_REF("Observers must call Cancel() or "
"CancelAndForgetObserver() before "
"they are destroyed") mListener;
nsCOMPtr<nsILoadGroup> mLoadGroup;
nsLoadFlags mLoadFlags;
-2
View File
@@ -19,7 +19,6 @@ MOCHITEST_CHROME_MANIFESTS += ['test/mochitest/chrome.ini']
XPCSHELL_TESTS_MANIFESTS += ['test/unit/xpcshell.ini']
XPIDL_SOURCES += [
'imgICache.idl',
'imgIContainer.idl',
@@ -36,7 +35,6 @@ XPIDL_SOURCES += [
XPIDL_MODULE = 'imglib2'
EXPORTS += [
'ImageCacheKey.h',
'ImageLogging.h',
@@ -0,0 +1,24 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
var timer = Components.classes["@mozilla.org/timer;1"];
var waitTimer = timer.createInstance(Components.interfaces.nsITimer);
function handleRequest(request, response) {
response.setHeader("Content-Type", "text/html", false);
response.setHeader("Cache-Control", "no-cache", false);
response.setStatusLine(request.httpVersion, 200, "OK");
response.processAsync();
waitForFinish(response);
}
function waitForFinish(response) {
if (getSharedState("all-parts-done") === "1") {
response.write("done");
response.finish();
} else {
waitTimer.initWithCallback(function() {waitForFinish(response);}, 10,
Components.interfaces.nsITimer.TYPE_ONE_SHOT);
}
}
+63
View File
@@ -0,0 +1,63 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
var counter = 100;
var timer = Components.classes["@mozilla.org/timer;1"];
var partTimer = timer.createInstance(Components.interfaces.nsITimer);
function getFileAsInputStream(aFilename) {
var file = Components.classes["@mozilla.org/file/directory_service;1"]
.getService(Components.interfaces.nsIProperties)
.get("CurWorkD", Components.interfaces.nsIFile);
file.append("tests");
file.append("image");
file.append("test");
file.append("mochitest");
file.append(aFilename);
var fileStream = Components.classes['@mozilla.org/network/file-input-stream;1']
.createInstance(Components.interfaces.nsIFileInputStream);
fileStream.init(file, 1, 0, false);
return fileStream;
}
function handleRequest(request, response)
{
response.setHeader("Content-Type",
"multipart/x-mixed-replace;boundary=BOUNDARYOMG", false);
response.setHeader("Cache-Control", "no-cache", false);
response.setStatusLine(request.httpVersion, 200, "OK");
// We're sending parts off in a delayed fashion, to let the tests occur.
response.processAsync();
response.write("--BOUNDARYOMG\r\n");
sendParts(response);
}
function sendParts(response) {
if (counter-- == 0) {
sendClose(response);
setSharedState("all-parts-done", "1");
return;
}
sendNextPart(response);
partTimer.initWithCallback(function() {sendParts(response);}, 1,
Components.interfaces.nsITimer.TYPE_ONE_SHOT);
}
function sendClose(response) {
response.write("--BOUNDARYOMG--\r\n");
response.finish();
}
function sendNextPart(response) {
var nextPartHead = "Content-Type: image/jpeg\r\n\r\n";
var inputStream = getFileAsInputStream("damon.jpg");
response.bodyOutputStream.write(nextPartHead, nextPartHead.length);
response.bodyOutputStream.writeFrom(inputStream, inputStream.available());
inputStream.close();
// Toss in the boundary, so the browser can know this part is complete
response.write("--BOUNDARYOMG\r\n");
}
+3
View File
@@ -30,6 +30,8 @@ support-files =
bug89419.sjs
bug900200.png
bug900200-ref.png
bug1180105.sjs
bug1180105-waiter.sjs
clear.gif
clear.png
clear2.gif
@@ -86,6 +88,7 @@ skip-if = (toolkit == 'android' && processor == 'x86') #x86 only
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only
[test_bug89419-2.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only
[test_bug1180105.html]
[test_animation_operators.html]
[test_drawDiscardedImage.html]
skip-if = toolkit == "gonk" #Bug 997034 - canvas.toDataURL() often causes lost connection to device.
+46
View File
@@ -0,0 +1,46 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1180105
-->
<head>
<title>Test for Bug 1180105</title>
<script type="application/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body onload="initializeOnload()">
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1180105">Mozilla Bug 1180105</a>
<p id="display"></p>
<pre id="test">
<script type="application/javascript">
SimpleTest.waitForExplicitFinish();
const WAITER_URL = "bug1180105-waiter.sjs";
function initializeOnload() {
var firstimg = document.createElement('img');
firstimg.src = "bug1180105.sjs";
document.getElementById('content').appendChild(firstimg);
waitForFinish();
}
function waitForFinish() {
var loader = document.getElementById("loader");
loader.src = WAITER_URL;
loader.onload = function() {
var img = document.getElementsByTagName('img')[0];
ok(img.width > 0, "Image should be loaded by now");
SimpleTest.finish();
};
}
</script>
</pre>
<div id="content">>
<iframe id="loader"></iframe>
</div>
</body>
</html>
+2 -3
View File
@@ -21,9 +21,6 @@
using namespace mozilla;
using namespace mozilla::dom;
// nsSVGRenderingObserver impl
NS_IMPL_ISUPPORTS(nsSVGRenderingObserver, nsIMutationObserver)
void
nsSVGRenderingObserver::StartListening()
{
@@ -220,6 +217,8 @@ nsSVGFrameReferenceFromProperty::Get()
return mFrame;
}
NS_IMPL_ISUPPORTS(nsSVGRenderingObserverProperty, nsIMutationObserver)
void
nsSVGRenderingObserverProperty::DoUpdate()
{
+4 -3
View File
@@ -55,9 +55,6 @@ public:
: mInObserverList(false)
{}
// nsISupports
NS_DECL_ISUPPORTS
// nsIMutationObserver
NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
@@ -174,6 +171,8 @@ private:
class nsSVGRenderingObserverProperty : public nsSVGIDRenderingObserver {
public:
NS_DECL_ISUPPORTS
nsSVGRenderingObserverProperty(nsIURI* aURI, nsIFrame *aFrame,
bool aReferenceImage)
: nsSVGIDRenderingObserver(aURI, aFrame->GetContent(), aReferenceImage)
@@ -181,6 +180,8 @@ public:
{}
protected:
virtual ~nsSVGRenderingObserverProperty() {}
virtual void DoUpdate() override;
nsSVGFrameReferenceFromProperty mFrameReference;
+2 -2
View File
@@ -698,10 +698,10 @@ pref("gfx.canvas.azure.backends", "direct2d1.1,direct2d,skia,cairo");
pref("gfx.content.azure.backends", "direct2d1.1,direct2d,cairo");
#else
#ifdef XP_MACOSX
pref("gfx.content.azure.backends", "cg");
pref("gfx.canvas.azure.backends", "skia,cg");
// Accelerated cg canvas where available (10.7+)
pref("gfx.canvas.azure.accelerated", true);
pref("gfx.content.azure.backends", "cg");
pref("gfx.canvas.azure.accelerated", false);
#else
pref("gfx.canvas.azure.backends", "skia,cairo");
pref("gfx.content.azure.backends", "cairo");
+2 -6
View File
@@ -1014,11 +1014,6 @@ NS_IMETHODIMP_(MozExternalRefCountType) Class::Release(void) \
MOZ_FOR_EACH(NS_INTERFACE_TABLE_ENTRY, (aClass,), (__VA_ARGS__)) \
NS_INTERFACE_TABLE_END
#define NS_IMPL_QUERY_INTERFACE_INHERITED0(aClass, aSuper) \
NS_INTERFACE_TABLE_HEAD(aClass) \
NS_INTERFACE_TABLE_INHERITED0(aClass) \
NS_INTERFACE_TABLE_TAIL_INHERITING(aSuper)
#define NS_IMPL_QUERY_INTERFACE_INHERITED(aClass, aSuper, ...) \
NS_INTERFACE_TABLE_HEAD(aClass) \
NS_INTERFACE_TABLE_INHERITED(aClass, __VA_ARGS__) \
@@ -1043,7 +1038,8 @@ NS_IMETHODIMP_(MozExternalRefCountType) Class::Release(void) \
NS_IMPL_QUERY_INTERFACE(aClass, __VA_ARGS__)
#define NS_IMPL_ISUPPORTS_INHERITED0(aClass, aSuper) \
NS_IMPL_QUERY_INTERFACE_INHERITED0(aClass, aSuper) \
NS_INTERFACE_TABLE_HEAD(aClass) \
NS_INTERFACE_TABLE_TAIL_INHERITING(aSuper) \
NS_IMPL_ADDREF_INHERITED(aClass, aSuper) \
NS_IMPL_RELEASE_INHERITED(aClass, aSuper) \