From 996887f40fb89c1e95bf7e4ed0af1406fe2b6428 Mon Sep 17 00:00:00 2001 From: Mihai Moldovan Date: Sat, 27 Apr 2019 05:14:42 +0200 Subject: When using XRENDER, create Xlib-based offscreen image surfaces. Mozilla tried to enable XRENDER support with backends other than Cairo in 286348:e13aaaaf1962 / https://hg.mozilla.org/mozilla-central/rev/e13aaaaf1962 - at least until they decided to completely remove XRENDER support. The change looked innocent enough, but actually turned out to do exactly the opposite: it forcefully enabled image offscreen surfaces with GTK2 when it was previously disabled (since gfxPrefs::UseImageOffscreenSurfaces() will always return true) and, by extension, disabled the XRENDER-based functionality by creating a non-Xlib surface. Interestingly, a previously enabled double buffering check was also disabled by this, but since the comment for this was diverging with the code, that behavior just sounds like yet another bug. Instead of disabling image offscreen surfaces (at least when using the GTK2 backend), let's force the creation of Xlib-based image surfaces when XRENDER support is enabled. This will let UXP use the more common/modern code paths, but also make scrolling much faster again. Too fast scrolling may induce tearing (if not smoothed), but on the other hand performs much better in remote computing contexts. As an added benefit, GTK3-based builds should roughly behave the same way. Further tests with the GTK3-backend enabled will be required in the future. --- gfx/thebes/gfxPlatformGtk.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'gfx') diff --git a/gfx/thebes/gfxPlatformGtk.cpp b/gfx/thebes/gfxPlatformGtk.cpp index be75332d6..6b5593524 100644 --- a/gfx/thebes/gfxPlatformGtk.cpp +++ b/gfx/thebes/gfxPlatformGtk.cpp @@ -156,7 +156,7 @@ gfxPlatformGtk::CreateOffscreenSurface(const IntSize& aSize, if (gdkScreen) { // When forcing PaintedLayers to use image surfaces for content, // force creation of gfxImageSurface surfaces. - if (gfxVars::UseXRender() && !UseImageOffscreenSurfaces()) { + if (gfxVars::UseXRender()) { Screen *screen = gdk_x11_screen_get_xscreen(gdkScreen); XRenderPictFormat* xrenderFormat = gfxXlibSurface::FindRenderFormat(DisplayOfScreen(screen), @@ -166,13 +166,6 @@ gfxPlatformGtk::CreateOffscreenSurface(const IntSize& aSize, newSurface = gfxXlibSurface::Create(screen, xrenderFormat, aSize); } - } else { - // We're not going to use XRender, so we don't need to - // search for a render format - newSurface = new gfxImageSurface(aSize, aFormat); - // The gfxImageSurface ctor zeroes this for us, no need to - // waste time clearing again - needsClear = false; } } #endif @@ -182,6 +175,10 @@ gfxPlatformGtk::CreateOffscreenSurface(const IntSize& aSize, // e.g., no display, no RENDER, bad size, etc. // Fall back to image surface for the data. newSurface = new gfxImageSurface(aSize, aFormat); + + // The gfxImageSurface ctor zeroes this for us, no need to + // waste time clearing again + needsClear = false; } if (newSurface->CairoStatus()) { -- cgit v1.2.3 From 2fd3007864d0c37b5bcc5ea9ca85d53d96fd83c5 Mon Sep 17 00:00:00 2001 From: Mihai Moldovan Date: Wed, 22 May 2019 21:10:26 +0200 Subject: Enable double buffering when using XRENDER. This fixes flickering/bars/stripes showing up during quickly-updating operations on Intel hardware when using XRENDER. For more information, refer to the code comment. See #1061 --- gfx/layers/client/ContentClient.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'gfx') diff --git a/gfx/layers/client/ContentClient.cpp b/gfx/layers/client/ContentClient.cpp index 3373230a9..50e159a23 100644 --- a/gfx/layers/client/ContentClient.cpp +++ b/gfx/layers/client/ContentClient.cpp @@ -78,8 +78,21 @@ ContentClient::CreateContentClient(CompositableForwarder* aForwarder) // We can't use double buffering when using image content with // Xrender support on Linux, as ContentHostDoubleBuffered is not // suited for direct uploads to the server. + // FIXME: Even though the comment above suggests that double buffering + // is supposed to be disabled when Xrender support is being enabled + // (and used), it really wasn't. Historically, + // UseImageOffscreenSurfaces() was always false in GTK2 builds, thus + // triggering the check, regardless of UseXRender(). + // Some time later, offscreen surfaces were always enabled, but the + // Xrender functionality broke due to not using Xlib-based surfaces. + // Using Xlib-based surfaces compatible with Xrender operations seems + // to lead to weird graphical artifacts (bars and stripes) on some + // hardware (Intel-based?) when displaying quickly-changing content, + // so contrary to the statement above we'd better enable double + // buffering - which also seems to not have any negative performance + // impact. if (!gfxPlatformGtk::GetPlatform()->UseImageOffscreenSurfaces() || - !gfxVars::UseXRender()) + gfxVars::UseXRender()) #endif { useDoubleBuffering = (LayerManagerComposite::SupportsDirectTexturing() && -- cgit v1.2.3 From 73f9b2c70d4653fb47c7f60d6c11aa26a0c0b850 Mon Sep 17 00:00:00 2001 From: Gaming4JC Date: Thu, 23 May 2019 19:47:59 -0400 Subject: Issue #1101 - Support gzip-compressed SVGs in OpenType+SVG fonts --- gfx/thebes/gfxSVGGlyphs.cpp | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'gfx') diff --git a/gfx/thebes/gfxSVGGlyphs.cpp b/gfx/thebes/gfxSVGGlyphs.cpp index a7615eca8..23f68f590 100644 --- a/gfx/thebes/gfxSVGGlyphs.cpp +++ b/gfx/thebes/gfxSVGGlyphs.cpp @@ -31,6 +31,7 @@ #include "nsSMILAnimationController.h" #include "gfxContext.h" #include "harfbuzz/hb.h" +#include "zlib.h" #include "mozilla/dom/ImageTracker.h" #define SVG_CONTENT_TYPE NS_LITERAL_CSTRING("image/svg+xml") @@ -285,7 +286,44 @@ gfxSVGGlyphsDocument::gfxSVGGlyphsDocument(const uint8_t *aBuffer, gfxSVGGlyphs *aSVGGlyphs) : mOwner(aSVGGlyphs) { + if (aBufLen >= 14 && aBuffer[0] == 31 && aBuffer[1] == 139) { + // It's a gzip-compressed document; decompress it before parsing. + // The original length (modulo 2^32) is found in the last 4 bytes + // of the data, stored in little-endian format. We read it as + // individual bytes to avoid possible alignment issues. + // (Note that if the original length was >2^32, then origLen here + // will be incorrect; but then the inflate() call will not return + // Z_STREAM_END and we'll bail out safely.) + size_t origLen = (size_t(aBuffer[aBufLen - 1]) << 24) + + (size_t(aBuffer[aBufLen - 2]) << 16) + + (size_t(aBuffer[aBufLen - 3]) << 8) + + size_t(aBuffer[aBufLen - 4]); + AutoTArray outBuf; + if (outBuf.SetLength(origLen, mozilla::fallible)) { + z_stream s = {0}; + s.next_in = const_cast(aBuffer); + s.avail_in = aBufLen; + s.next_out = outBuf.Elements(); + s.avail_out = outBuf.Length(); + // The magic number 16 here is the zlib flag to expect gzip format, + // see http://www.zlib.net/manual.html#Advanced + if (Z_OK == inflateInit2(&s, 16 + MAX_WBITS)) { + int result = inflate(&s, Z_FINISH); + if (Z_STREAM_END == result) { + MOZ_ASSERT(size_t(s.next_out - outBuf.Elements()) == origLen); + ParseDocument(outBuf.Elements(), outBuf.Length()); + } else { + NS_WARNING("Failed to decompress SVG glyphs document"); + } + inflateEnd(&s); + } + } else { + NS_WARNING("Failed to allocate memory for SVG glyphs document"); + } + } else { ParseDocument(aBuffer, aBufLen); + } + if (!mDocument) { NS_WARNING("Could not parse SVG glyphs document"); return; -- cgit v1.2.3 From 47c52f2dc2cc4eb4f5582a7ca50b682548b1708c Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Mon, 27 May 2019 17:59:55 +0200 Subject: Port an upstream Skia fix. --- gfx/skia/skia/src/core/SkPath.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'gfx') diff --git a/gfx/skia/skia/src/core/SkPath.cpp b/gfx/skia/skia/src/core/SkPath.cpp index fc3db3ee5..88a449993 100644 --- a/gfx/skia/skia/src/core/SkPath.cpp +++ b/gfx/skia/skia/src/core/SkPath.cpp @@ -1620,10 +1620,10 @@ void SkPath::reverseAddPath(const SkPath& srcPath) { src = tmp.set(srcPath); } - SkPathRef::Editor ed(&fPathRef, src->fPathRef->countPoints(), src->fPathRef->countVerbs()); + SkPathRef::Editor ed(&fPathRef, src->countPoints(), src->countVerbs()); const SkPoint* pts = src->fPathRef->pointsEnd(); - // we will iterator through src's verbs backwards + // we will iterate through src's verbs backwards const uint8_t* verbs = src->fPathRef->verbsMemBegin(); // points at the last verb const uint8_t* verbsEnd = src->fPathRef->verbs(); // points just past the first verb const SkScalar* conicWeights = src->fPathRef->conicWeightsEnd(); @@ -1743,6 +1743,7 @@ void SkPath::transform(const SkMatrix& matrix, SkPath* dst) const { SkPathRef::CreateTransformedCopy(&dst->fPathRef, *fPathRef.get(), matrix); if (this != dst) { + dst->fLastMoveToIndex = fLastMoveToIndex; dst->fFillType = fFillType; dst->fConvexity = kUnknown_Convexity; dst->fIsVolatile = fIsVolatile; -- cgit v1.2.3 From 9b655e3666a6eae6f217e584ef3915c8ff99ddc1 Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Tue, 28 May 2019 15:18:04 +0200 Subject: Make extra sure Compositables don't refer back to layers after reassignment. --- gfx/layers/composite/CanvasLayerComposite.cpp | 6 +++++- gfx/layers/composite/ImageLayerComposite.cpp | 9 +++++++-- gfx/layers/composite/PaintedLayerComposite.cpp | 9 +++++++-- 3 files changed, 19 insertions(+), 5 deletions(-) (limited to 'gfx') diff --git a/gfx/layers/composite/CanvasLayerComposite.cpp b/gfx/layers/composite/CanvasLayerComposite.cpp index 3c8299e05..86f25b1ee 100644 --- a/gfx/layers/composite/CanvasLayerComposite.cpp +++ b/gfx/layers/composite/CanvasLayerComposite.cpp @@ -43,9 +43,13 @@ bool CanvasLayerComposite::SetCompositableHost(CompositableHost* aHost) { switch (aHost->GetType()) { - case CompositableType::IMAGE: + case CompositableType::IMAGE: { + if (mCompositableHost && aHost != mCompositableHost) { + mCompositableHost->Detach(this); + } mCompositableHost = aHost; return true; + } default: return false; } diff --git a/gfx/layers/composite/ImageLayerComposite.cpp b/gfx/layers/composite/ImageLayerComposite.cpp index bac9f3790..6867aaa22 100644 --- a/gfx/layers/composite/ImageLayerComposite.cpp +++ b/gfx/layers/composite/ImageLayerComposite.cpp @@ -50,9 +50,14 @@ bool ImageLayerComposite::SetCompositableHost(CompositableHost* aHost) { switch (aHost->GetType()) { - case CompositableType::IMAGE: - mImageHost = static_cast(aHost); + case CompositableType::IMAGE: { + ImageHost* newImageHost = static_cast(aHost); + if (mImageHost && newImageHost != mImageHost) { + mImageHost->Detach(this); + } + mImageHost = newImageHost; return true; + } default: return false; } diff --git a/gfx/layers/composite/PaintedLayerComposite.cpp b/gfx/layers/composite/PaintedLayerComposite.cpp index b58f5d690..232cc4ef4 100644 --- a/gfx/layers/composite/PaintedLayerComposite.cpp +++ b/gfx/layers/composite/PaintedLayerComposite.cpp @@ -49,9 +49,14 @@ PaintedLayerComposite::SetCompositableHost(CompositableHost* aHost) switch (aHost->GetType()) { case CompositableType::CONTENT_TILED: case CompositableType::CONTENT_SINGLE: - case CompositableType::CONTENT_DOUBLE: - mBuffer = static_cast(aHost); + case CompositableType::CONTENT_DOUBLE: { + ContentHost* newBuffer = static_cast(aHost); + if (mBuffer && newBuffer != mBuffer) { + mBuffer->Detach(this); + } + mBuffer = newBuffer; return true; + } default: return false; } -- cgit v1.2.3