From a645a01ee633cc29db993c17c845181f11b806ca Mon Sep 17 00:00:00 2001 From: David Anderson Date: Fri, 27 Oct 2017 11:59:39 -0700 Subject: [PATCH 01/15] Add a Talos test for displaylist mutation. (bug 1411804, r=jmaher, r=mattwoodrow) --- testing/talos/talos.json | 2 +- testing/talos/talos/test.py | 22 ++++++ .../layout/benchmarks/displaylist_mutate.html | 68 +++++++++++++++++++ .../tests/layout/displaylist_mutate.manifest | 1 + 4 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 testing/talos/talos/tests/layout/benchmarks/displaylist_mutate.html create mode 100644 testing/talos/talos/tests/layout/displaylist_mutate.manifest diff --git a/testing/talos/talos.json b/testing/talos/talos.json index de66b6a071c4..6fb1b9fc563b 100644 --- a/testing/talos/talos.json +++ b/testing/talos/talos.json @@ -47,7 +47,7 @@ "talos_options": ["--disable-stylo"] }, "g4-e10s": { - "tests": ["basic_compositor_video", "glvideo"] + "tests": ["basic_compositor_video", "glvideo", "displaylist_mutate"] }, "g4-stylo-disabled-e10s": { "tests": ["basic_compositor_video", "glvideo"], diff --git a/testing/talos/talos/test.py b/testing/talos/talos/test.py index e93a24d04a55..a0eabe3532b0 100644 --- a/testing/talos/talos/test.py +++ b/testing/talos/talos/test.py @@ -981,3 +981,25 @@ class tp6_facebook_heavy(tp6_facebook): tp6_facebook test ran against a heavy-user profile """ profile = 'simple' + +@register_test() +class displaylist_mutate(PageloaderTest): + """ + Test modifying single items in a large display list. Measure transaction speed + to the compositor. + """ + tpmanifest = '${talos}/tests/layout/displaylist_mutate.manifest' + tpcycles = 1 + tppagecycles = 5 + tploadnocache = True + tpmozafterpaint = False + tpchrome = False + gecko_profile_interval = 2 + gecko_profile_entries = 2000000 + win_counters = w7_counters = linux_counters = mac_counters = None + filters = filter.ignore_first.prepare(1) + filter.median.prepare() + """ASAP mode""" + preferences = {'layout.frame_rate': 0, + 'docshell.event_starvation_delay_hint': 1, + 'dom.send_after_paint_to_content': False} + unit = 'ms' diff --git a/testing/talos/talos/tests/layout/benchmarks/displaylist_mutate.html b/testing/talos/talos/tests/layout/benchmarks/displaylist_mutate.html new file mode 100644 index 000000000000..5adf64585fc1 --- /dev/null +++ b/testing/talos/talos/tests/layout/benchmarks/displaylist_mutate.html @@ -0,0 +1,68 @@ + + + + + + + + diff --git a/testing/talos/talos/tests/layout/displaylist_mutate.manifest b/testing/talos/talos/tests/layout/displaylist_mutate.manifest new file mode 100644 index 000000000000..0e09c83d3d40 --- /dev/null +++ b/testing/talos/talos/tests/layout/displaylist_mutate.manifest @@ -0,0 +1 @@ +% http://localhost/tests/layout/benchmarks/displaylist_mutate.html From ee86c85e9b43712793cfb3277e7cb7b4e0f530c4 Mon Sep 17 00:00:00 2001 From: Sebastian Hengst Date: Fri, 27 Oct 2017 21:25:52 +0200 Subject: [PATCH 02/15] Add a Talos test for displaylist mutation. (bug 1411804). Follow-up: Add empty line to fix linting issue. r=me DONTBUILD --HG-- extra : amend_source : b28a5efa400ba377e3ac5e75c09a8611d0e2f5ad --- testing/talos/talos/test.py | 1 + 1 file changed, 1 insertion(+) diff --git a/testing/talos/talos/test.py b/testing/talos/talos/test.py index a0eabe3532b0..b37240c3c0d0 100644 --- a/testing/talos/talos/test.py +++ b/testing/talos/talos/test.py @@ -982,6 +982,7 @@ class tp6_facebook_heavy(tp6_facebook): """ profile = 'simple' + @register_test() class displaylist_mutate(PageloaderTest): """ From 7e5658f95ba9c6a7a5411bd15a285afa938dacd1 Mon Sep 17 00:00:00 2001 From: Sebastian Hengst Date: Fri, 27 Oct 2017 21:42:19 +0200 Subject: [PATCH 03/15] Backed out 2 changesets (bug 1411804) for failing eslint in testing/talos/talos/tests/layout/benchmarks/displaylist_mutate.html. r=backout Backed out changeset 39ad112131fe (bug 1411804) Backed out changeset 9421a340f682 (bug 1411804) --- testing/talos/talos.json | 2 +- testing/talos/talos/test.py | 23 ------- .../layout/benchmarks/displaylist_mutate.html | 68 ------------------- .../tests/layout/displaylist_mutate.manifest | 1 - 4 files changed, 1 insertion(+), 93 deletions(-) delete mode 100644 testing/talos/talos/tests/layout/benchmarks/displaylist_mutate.html delete mode 100644 testing/talos/talos/tests/layout/displaylist_mutate.manifest diff --git a/testing/talos/talos.json b/testing/talos/talos.json index 6fb1b9fc563b..de66b6a071c4 100644 --- a/testing/talos/talos.json +++ b/testing/talos/talos.json @@ -47,7 +47,7 @@ "talos_options": ["--disable-stylo"] }, "g4-e10s": { - "tests": ["basic_compositor_video", "glvideo", "displaylist_mutate"] + "tests": ["basic_compositor_video", "glvideo"] }, "g4-stylo-disabled-e10s": { "tests": ["basic_compositor_video", "glvideo"], diff --git a/testing/talos/talos/test.py b/testing/talos/talos/test.py index b37240c3c0d0..e93a24d04a55 100644 --- a/testing/talos/talos/test.py +++ b/testing/talos/talos/test.py @@ -981,26 +981,3 @@ class tp6_facebook_heavy(tp6_facebook): tp6_facebook test ran against a heavy-user profile """ profile = 'simple' - - -@register_test() -class displaylist_mutate(PageloaderTest): - """ - Test modifying single items in a large display list. Measure transaction speed - to the compositor. - """ - tpmanifest = '${talos}/tests/layout/displaylist_mutate.manifest' - tpcycles = 1 - tppagecycles = 5 - tploadnocache = True - tpmozafterpaint = False - tpchrome = False - gecko_profile_interval = 2 - gecko_profile_entries = 2000000 - win_counters = w7_counters = linux_counters = mac_counters = None - filters = filter.ignore_first.prepare(1) + filter.median.prepare() - """ASAP mode""" - preferences = {'layout.frame_rate': 0, - 'docshell.event_starvation_delay_hint': 1, - 'dom.send_after_paint_to_content': False} - unit = 'ms' diff --git a/testing/talos/talos/tests/layout/benchmarks/displaylist_mutate.html b/testing/talos/talos/tests/layout/benchmarks/displaylist_mutate.html deleted file mode 100644 index 5adf64585fc1..000000000000 --- a/testing/talos/talos/tests/layout/benchmarks/displaylist_mutate.html +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - diff --git a/testing/talos/talos/tests/layout/displaylist_mutate.manifest b/testing/talos/talos/tests/layout/displaylist_mutate.manifest deleted file mode 100644 index 0e09c83d3d40..000000000000 --- a/testing/talos/talos/tests/layout/displaylist_mutate.manifest +++ /dev/null @@ -1 +0,0 @@ -% http://localhost/tests/layout/benchmarks/displaylist_mutate.html From 3096def3240bd97e67d9639f8705f8e8819d8b09 Mon Sep 17 00:00:00 2001 From: Nathan Froyd Date: Fri, 27 Oct 2017 16:07:47 -0400 Subject: [PATCH 04/15] Bug 1396892 - fix tautological pointer comparison warning, for real; r=me Whoops, the files that we care about in this directory are C++ files, so we should be turning warnings off in CXXFLAGS, not CFLAGS. --- memory/build/moz.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/memory/build/moz.build b/memory/build/moz.build index 7d017fe815e6..5e915cc75050 100644 --- a/memory/build/moz.build +++ b/memory/build/moz.build @@ -39,7 +39,7 @@ if CONFIG['OS_TARGET'] == 'Darwin' and (CONFIG['MOZ_REPLACE_MALLOC'] or Library('memory') if CONFIG['OS_TARGET'] == 'Android' and CONFIG['CC_TYPE'] == 'clang': - CFLAGS += [ + CXXFLAGS += [ '-Wno-tautological-pointer-compare', ] From 9f542cae153feb659194c050a26f787b0bbcbd53 Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Fri, 27 Oct 2017 22:14:02 +0200 Subject: [PATCH 05/15] Bug 1412293 - Get rid of GetWorkerCrossThreadDispatcher, r=qdot --- dom/workers/WorkerPrivate.cpp | 14 -------------- dom/workers/Workers.h | 3 --- 2 files changed, 17 deletions(-) diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp index d4182131e41b..10cb91142821 100644 --- a/dom/workers/WorkerPrivate.cpp +++ b/dom/workers/WorkerPrivate.cpp @@ -7215,20 +7215,6 @@ EventTarget::IsOnCurrentThreadInfallible() BEGIN_WORKERS_NAMESPACE -WorkerCrossThreadDispatcher* -GetWorkerCrossThreadDispatcher(JSContext* aCx, const JS::Value& aWorker) -{ - if (!aWorker.isObject()) { - return nullptr; - } - - JS::Rooted obj(aCx, &aWorker.toObject()); - WorkerPrivate* w = nullptr; - UNWRAP_OBJECT(Worker, &obj, w); - MOZ_ASSERT(w); - return w->GetCrossThreadDispatcher(); -} - // Force instantiation. template class WorkerPrivateParent; diff --git a/dom/workers/Workers.h b/dom/workers/Workers.h index fbcccd293f91..8d58cd6a5aec 100644 --- a/dom/workers/Workers.h +++ b/dom/workers/Workers.h @@ -366,9 +366,6 @@ public: PostTask(WorkerTask* aTask); }; -WorkerCrossThreadDispatcher* -GetWorkerCrossThreadDispatcher(JSContext* aCx, const JS::Value& aWorker); - // Random unique constant to facilitate JSPrincipal debugging const uint32_t kJSPrincipalsDebugToken = 0x7e2df9d2; From 1d874e8c701fa06ce18fae3e2193a472fe8f87bb Mon Sep 17 00:00:00 2001 From: Ben Kelly Date: Fri, 27 Oct 2017 16:11:57 -0400 Subject: [PATCH 06/15] Bug 1411528 Clear the intercept listening when synthesizing a redirect in HttpChannelChild. r=asuth --- netwerk/protocol/http/HttpChannelChild.cpp | 4 ++++ .../service-worker/redirected-response.https.html.ini | 11 ----------- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/netwerk/protocol/http/HttpChannelChild.cpp b/netwerk/protocol/http/HttpChannelChild.cpp index 5201bda9d349..42f3e865aa65 100644 --- a/netwerk/protocol/http/HttpChannelChild.cpp +++ b/netwerk/protocol/http/HttpChannelChild.cpp @@ -3624,6 +3624,10 @@ HttpChannelChild::OverrideWithSynthesizedResponse(nsAutoPtr& if (nsHttpChannel::WillRedirect(mResponseHead)) { mShouldInterceptSubsequentRedirect = true; + if (mInterceptListener) { + mInterceptListener->Cleanup(); + mInterceptListener = nullptr; + } // Continue with the original cross-process request rv = ContinueAsyncOpen(); return; diff --git a/testing/web-platform/meta/service-workers/service-worker/redirected-response.https.html.ini b/testing/web-platform/meta/service-workers/service-worker/redirected-response.https.html.ini index bf6bfad196d4..b5827facacf1 100644 --- a/testing/web-platform/meta/service-workers/service-worker/redirected-response.https.html.ini +++ b/testing/web-platform/meta/service-workers/service-worker/redirected-response.https.html.ini @@ -1,16 +1,5 @@ [redirected-response.https.html] type: testharness - disabled: - if debug and os == "win": https://bugzilla.mozilla.org/show_bug.cgi?id=1411528 - expected: - if debug and not stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): CRASH - if debug and not stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): CRASH - if debug and stylo and e10s and (os == "win") and (version == "10.0.15063") and (processor == "x86_64") and (bits == 64): CRASH - if debug and stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): CRASH - if debug and stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): CRASH - if debug and not stylo and e10s and (os == "win") and (version == "10.0.15063") and (processor == "x86_64") and (bits == 64): CRASH - if debug and stylo and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): CRASH - if debug and not stylo and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): CRASH [mode: "follow", no mode change] expected: FAIL From 936aff29b50295fde14d9d915d4302f3691d06b9 Mon Sep 17 00:00:00 2001 From: Nathan Froyd Date: Fri, 27 Oct 2017 17:08:20 -0400 Subject: [PATCH 07/15] Bug 1412405 - try harder to find a definition for isnanf in the custom linker; r=nalexander The comment with the accompanying change explains things, but the short version is that clang generates full calls to isnanf, which our dlsym-based symbol lookup in the custom linker cannot handle correctly. We therefore need to do extra work for isnanf to find the correct symbol. --- mozglue/linker/ElfLoader.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/mozglue/linker/ElfLoader.cpp b/mozglue/linker/ElfLoader.cpp index 7d9f992f1e27..0f82bd21f156 100644 --- a/mozglue/linker/ElfLoader.cpp +++ b/mozglue/linker/ElfLoader.cpp @@ -331,6 +331,25 @@ void * SystemElf::GetSymbolPtr(const char *symbol) const { void *sym = dlsym(dlhandle, symbol); + // Various bits of Gecko use isnanf, which gcc is happy to compile into + // inlined code using floating-point comparisons. clang, on the other hand, + // does not use inline code and generates full calls to isnanf. + // + // libm.so on Android defines isnanf as weak. dlsym always returns null for + // weak symbols. Which means that we'll never be able to resolve the symbol + // that clang generates here. However, said weak symbol for isnanf is just + // an alias for __isnanf, which is the real definition. So if we're asked + // for isnanf and we can't find it, try looking for __isnanf instead. The + // actual system linker uses alternate resolution interfaces and therefore + // does not encounter this issue. + // + // See also https://bugs.chromium.org/p/chromium/issues/detail?id=376828, + // from which this comment and this fix are adapted. + if (!sym && + !strcmp(symbol, "isnanf") && + !strcmp(GetName(), "libm.so")) { + sym = dlsym(dlhandle, "__isnanf"); + } DEBUG_LOG("dlsym(%p [\"%s\"], \"%s\") = %p", dlhandle, GetPath(), symbol, sym); ElfLoader::Singleton.lastError = dlerror(); return sym; From 9ddfb118203d1719adf5c26002f4c1827b11b373 Mon Sep 17 00:00:00 2001 From: sotaro Date: Sat, 28 Oct 2017 06:54:56 +0900 Subject: [PATCH 08/15] Bug 1412246 - Fix memory leak with WebRenderLayerManager::EndEmptyTransaction() r=nical --- gfx/layers/wr/WebRenderBridgeParent.cpp | 1 + gfx/layers/wr/WebRenderImageHost.cpp | 3 ++- gfx/layers/wr/WebRenderImageHost.h | 6 ++++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/gfx/layers/wr/WebRenderBridgeParent.cpp b/gfx/layers/wr/WebRenderBridgeParent.cpp index 86bc54ef119a..de7b19d9e221 100644 --- a/gfx/layers/wr/WebRenderBridgeParent.cpp +++ b/gfx/layers/wr/WebRenderBridgeParent.cpp @@ -782,6 +782,7 @@ WebRenderBridgeParent::RecvAddPipelineIdForCompositable(const wr::PipelineId& aP } wrHost->SetWrBridge(this); + wrHost->EnableUseAsyncImagePipeline(); mAsyncCompositables.Put(wr::AsUint64(aPipelineId), wrHost); mAsyncImageManager->AddAsyncImagePipeline(aPipelineId, wrHost); diff --git a/gfx/layers/wr/WebRenderImageHost.cpp b/gfx/layers/wr/WebRenderImageHost.cpp index f600b8447fd3..51a7b3378f3f 100644 --- a/gfx/layers/wr/WebRenderImageHost.cpp +++ b/gfx/layers/wr/WebRenderImageHost.cpp @@ -29,6 +29,7 @@ WebRenderImageHost::WebRenderImageHost(const TextureInfo& aTextureInfo) , ImageComposite() , mWrBridge(nullptr) , mWrBridgeBindings(0) + , mUseAsyncImagePipeline(false) {} WebRenderImageHost::~WebRenderImageHost() @@ -188,7 +189,7 @@ WebRenderImageHost::SetCurrentTextureHost(TextureHost* aTexture) } if (mWrBridge && - !mAsyncRef && + !mUseAsyncImagePipeline && !!mCurrentTextureHost && mCurrentTextureHost != aTexture && mCurrentTextureHost->AsWebRenderTextureHost()) { diff --git a/gfx/layers/wr/WebRenderImageHost.h b/gfx/layers/wr/WebRenderImageHost.h index 1fd99cd3857b..53ab719bb17e 100644 --- a/gfx/layers/wr/WebRenderImageHost.h +++ b/gfx/layers/wr/WebRenderImageHost.h @@ -73,6 +73,11 @@ public: void ClearWrBridge(); + void EnableUseAsyncImagePipeline() + { + mUseAsyncImagePipeline = true; + } + TextureHost* GetCurrentTextureHost() { return mCurrentTextureHost; } protected: @@ -84,6 +89,7 @@ protected: WebRenderBridgeParent* MOZ_NON_OWNING_REF mWrBridge; uint32_t mWrBridgeBindings; + bool mUseAsyncImagePipeline; CompositableTextureHostRef mCurrentTextureHost; }; From 29225326544c6857d14e933cf1705074be18c1ae Mon Sep 17 00:00:00 2001 From: Jeff Muizelaar Date: Fri, 27 Oct 2017 18:21:25 -0400 Subject: [PATCH 09/15] Bug 1380014. Expose GetFontKeyForUnscaledFont. r=lsalzman We'll use this to share fonts with BlobImages --- gfx/layers/wr/WebRenderBridgeChild.cpp | 36 ++++++++++++++++++-------- gfx/layers/wr/WebRenderBridgeChild.h | 1 + 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/gfx/layers/wr/WebRenderBridgeChild.cpp b/gfx/layers/wr/WebRenderBridgeChild.cpp index 4d6adba51838..dddf4d6d4229 100644 --- a/gfx/layers/wr/WebRenderBridgeChild.cpp +++ b/gfx/layers/wr/WebRenderBridgeChild.cpp @@ -294,19 +294,12 @@ WebRenderBridgeChild::GetFontKeyForScaledFont(gfx::ScaledFont* aScaledFont) return instanceKey; } - RefPtr unscaled = aScaledFont->GetUnscaledFont(); - MOZ_ASSERT(unscaled); - wr::IpcResourceUpdateQueue resources(GetShmemAllocator()); - wr::FontKey fontKey = { wr::IdNamespace { 0 }, 0}; - if (!mFontKeys.Get(unscaled, &fontKey)) { - FontFileDataSink sink = { &fontKey, this, &resources }; - if (!unscaled->GetFontFileData(WriteFontFileData, &sink)) { - return instanceKey; - } - - mFontKeys.Put(unscaled, fontKey); + wr::FontKey fontKey = GetFontKeyForUnscaledFont(aScaledFont->GetUnscaledFont()); + wr::FontKey nullKey = { wr::IdNamespace { 0 }, 0}; + if (fontKey == nullKey) { + return instanceKey; } instanceKey = GetNextFontInstanceKey(); @@ -324,6 +317,27 @@ WebRenderBridgeChild::GetFontKeyForScaledFont(gfx::ScaledFont* aScaledFont) mFontInstanceKeys.Put(aScaledFont, instanceKey); return instanceKey; + +} + +wr::FontKey +WebRenderBridgeChild::GetFontKeyForUnscaledFont(gfx::UnscaledFont* aUnscaled) +{ + MOZ_ASSERT(!mDestroyed); + + wr::FontKey fontKey = { wr::IdNamespace { 0 }, 0}; + if (!mFontKeys.Get(aUnscaled, &fontKey)) { + wr::IpcResourceUpdateQueue resources(GetShmemAllocator()); + FontFileDataSink sink = { &fontKey, this, &resources }; + if (!aUnscaled->GetFontFileData(WriteFontFileData, &sink)) { + return fontKey; + } + UpdateResources(resources); + + mFontKeys.Put(aUnscaled, fontKey); + } + + return fontKey; } void diff --git a/gfx/layers/wr/WebRenderBridgeChild.h b/gfx/layers/wr/WebRenderBridgeChild.h index 7d952321a382..768bf0950ca7 100644 --- a/gfx/layers/wr/WebRenderBridgeChild.h +++ b/gfx/layers/wr/WebRenderBridgeChild.h @@ -136,6 +136,7 @@ public: const wr::GlyphOptions* aGlyphOptions = nullptr); wr::FontInstanceKey GetFontKeyForScaledFont(gfx::ScaledFont* aScaledFont); + wr::FontKey GetFontKeyForUnscaledFont(gfx::UnscaledFont* aUnscaledFont); void RemoveExpiredFontKeys(); void ClearReadLocks(); From f1e1608327dad2b1711cfdb4aa3841818901fc86 Mon Sep 17 00:00:00 2001 From: Jeff Muizelaar Date: Fri, 27 Oct 2017 18:21:26 -0400 Subject: [PATCH 10/15] Bug 1380014. Add the ability to record UnscaledFonts by index. r=lsalzman --- gfx/2d/DrawEventRecorder.cpp | 2 +- gfx/2d/DrawEventRecorder.h | 20 +++++++ gfx/2d/DrawTargetRecording.cpp | 50 ++++++++-------- gfx/2d/InlineTranslator.h | 9 ++- gfx/2d/RecordedEvent.cpp | 2 + gfx/2d/RecordedEvent.h | 2 + gfx/2d/RecordedEventImpl.h | 106 +++++++++++++++++++++++++++++++++ 7 files changed, 165 insertions(+), 26 deletions(-) diff --git a/gfx/2d/DrawEventRecorder.cpp b/gfx/2d/DrawEventRecorder.cpp index 44123c4697fb..6dbd3012ba06 100644 --- a/gfx/2d/DrawEventRecorder.cpp +++ b/gfx/2d/DrawEventRecorder.cpp @@ -12,7 +12,7 @@ namespace gfx { using namespace std; -DrawEventRecorderPrivate::DrawEventRecorderPrivate() +DrawEventRecorderPrivate::DrawEventRecorderPrivate() : mExternalFonts(false) { } diff --git a/gfx/2d/DrawEventRecorder.h b/gfx/2d/DrawEventRecorder.h index e753c8d70fac..1d59eaab7fb0 100644 --- a/gfx/2d/DrawEventRecorder.h +++ b/gfx/2d/DrawEventRecorder.h @@ -13,6 +13,7 @@ #include #include +#include namespace mozilla { namespace gfx { @@ -85,6 +86,22 @@ public: return mStoredFontData.find(aFontDataKey) != mStoredFontData.end(); } + // Returns the index of the UnscaledFont + size_t GetUnscaledFontIndex(UnscaledFont *aFont) { + auto i = mUnscaledFontMap.find(aFont); + size_t index; + if (i == mUnscaledFontMap.end()) { + mUnscaledFonts.push_back(aFont); + index = mUnscaledFonts.size() - 1; + mUnscaledFontMap.insert({{aFont, index}}); + } else { + index = i->second; + } + return index; + } + + bool WantsExternalFonts() { return mExternalFonts; } + protected: virtual void Flush() = 0; @@ -92,6 +109,9 @@ protected: std::unordered_set mStoredFontData; std::unordered_set mStoredFonts; std::unordered_set mStoredSurfaces; + std::vector> mUnscaledFonts; + std::unordered_map mUnscaledFontMap; + bool mExternalFonts; }; class DrawEventRecorderFile : public DrawEventRecorderPrivate diff --git a/gfx/2d/DrawTargetRecording.cpp b/gfx/2d/DrawTargetRecording.cpp index 61c6cde21751..3f1b469d969f 100644 --- a/gfx/2d/DrawTargetRecording.cpp +++ b/gfx/2d/DrawTargetRecording.cpp @@ -332,32 +332,34 @@ DrawTargetRecording::FillGlyphs(ScaledFont *aFont, UserDataKey* userDataKey = reinterpret_cast(mRecorder.get()); if (!aFont->GetUserData(userDataKey)) { UnscaledFont* unscaledFont = aFont->GetUnscaledFont(); - if (!mRecorder->HasStoredObject(unscaledFont)) { - RecordedFontData fontData(unscaledFont); - RecordedFontDetails fontDetails; - if (fontData.GetFontDetails(fontDetails)) { - // Try to serialise the whole font, just in case this is a web font that - // is not present on the system. - if (!mRecorder->HasStoredFontData(fontDetails.fontDataKey)) { - mRecorder->RecordEvent(fontData); - mRecorder->AddStoredFontData(fontDetails.fontDataKey); - } - mRecorder->RecordEvent(RecordedUnscaledFontCreation(unscaledFont, fontDetails)); - } else { - // If that fails, record just the font description and try to load it from - // the system on the other side. - RecordedFontDescriptor fontDesc(unscaledFont); - if (fontDesc.IsValid()) { - mRecorder->RecordEvent(fontDesc); - } else { - gfxWarning() << "DrawTargetRecording::FillGlyphs failed to serialise UnscaledFont"; - } + if (mRecorder->WantsExternalFonts()) { + size_t index = mRecorder->GetUnscaledFontIndex(unscaledFont); + mRecorder->RecordEvent(RecordedScaledFontCreationByIndex(aFont, index)); + } else { + if (!mRecorder->HasStoredObject(unscaledFont)) { + RecordedFontData fontData(unscaledFont); + RecordedFontDetails fontDetails; + if (fontData.GetFontDetails(fontDetails)) { + // Try to serialise the whole font, just in case this is a web font that + // is not present on the system. + if (!mRecorder->HasStoredFontData(fontDetails.fontDataKey)) { + mRecorder->RecordEvent(fontData); + mRecorder->AddStoredFontData(fontDetails.fontDataKey); + } + mRecorder->RecordEvent(RecordedUnscaledFontCreation(unscaledFont, fontDetails)); + } else { + // If that fails, record just the font description and try to load it from + // the system on the other side. + RecordedFontDescriptor fontDesc(unscaledFont); + if (fontDesc.IsValid()) { + mRecorder->RecordEvent(fontDesc); + } else { + gfxWarning() << "DrawTargetRecording::FillGlyphs failed to serialise UnscaledFont"; + } + } + mRecorder->AddStoredObject(unscaledFont); } - mRecorder->AddStoredObject(unscaledFont); } - - mRecorder->RecordEvent(RecordedScaledFontCreation(aFont, unscaledFont)); - RecordingFontUserData *userData = new RecordingFontUserData; userData->refPtr = aFont; userData->recorder = mRecorder; diff --git a/gfx/2d/InlineTranslator.h b/gfx/2d/InlineTranslator.h index 2998c2b97745..72880625ef22 100644 --- a/gfx/2d/InlineTranslator.h +++ b/gfx/2d/InlineTranslator.h @@ -76,13 +76,19 @@ public: return result; } - UnscaledFont* LookupUnscaledFont(ReferencePtr aRefPtr) final + UnscaledFont* LookupUnscaledFont(ReferencePtr aRefPtr) override final { UnscaledFont* result = mUnscaledFonts.GetWeak(aRefPtr); MOZ_ASSERT(result); return result; } + virtual UnscaledFont* LookupUnscaledFontByIndex(size_t index) override final + { + UnscaledFont* result = mUnscaledFontTable[index]; + return result; + } + NativeFontResource* LookupNativeFontResource(uint64_t aKey) final { NativeFontResource* result = mNativeFontResources.GetWeak(aKey); @@ -179,6 +185,7 @@ private: RefPtr mBaseDT; void* mFontContext; + std::vector> mUnscaledFontTable; nsRefPtrHashtable, DrawTarget> mDrawTargets; nsRefPtrHashtable, Path> mPaths; nsRefPtrHashtable, SourceSurface> mSourceSurfaces; diff --git a/gfx/2d/RecordedEvent.cpp b/gfx/2d/RecordedEvent.cpp index 1da4aba7895e..f5c2022a7f25 100644 --- a/gfx/2d/RecordedEvent.cpp +++ b/gfx/2d/RecordedEvent.cpp @@ -88,6 +88,8 @@ RecordedEvent::GetEventName(EventType aType) return "Snapshot"; case SCALEDFONTCREATION: return "ScaledFontCreation"; + case SCALEDFONTCREATIONBYINDEX: + return "ScaledFontCreationByIndex"; case SCALEDFONTDESTRUCTION: return "ScaledFontDestruction"; case MASKSURFACE: diff --git a/gfx/2d/RecordedEvent.h b/gfx/2d/RecordedEvent.h index 6a25a228b836..03f6d8b9e2fe 100644 --- a/gfx/2d/RecordedEvent.h +++ b/gfx/2d/RecordedEvent.h @@ -89,6 +89,7 @@ public: virtual GradientStops *LookupGradientStops(ReferencePtr aRefPtr) = 0; virtual ScaledFont *LookupScaledFont(ReferencePtr aRefPtr) = 0; virtual UnscaledFont* LookupUnscaledFont(ReferencePtr aRefPtr) = 0; + virtual UnscaledFont* LookupUnscaledFontByIndex(size_t aIndex) { return nullptr; } virtual NativeFontResource *LookupNativeFontResource(uint64_t aKey) = 0; virtual void AddDrawTarget(ReferencePtr aRefPtr, DrawTarget *aDT) = 0; virtual void RemoveDrawTarget(ReferencePtr aRefPtr) = 0; @@ -241,6 +242,7 @@ public: GRADIENTSTOPSDESTRUCTION, SNAPSHOT, SCALEDFONTCREATION, + SCALEDFONTCREATIONBYINDEX, SCALEDFONTDESTRUCTION, MASKSURFACE, FILTERNODECREATION, diff --git a/gfx/2d/RecordedEventImpl.h b/gfx/2d/RecordedEventImpl.h index 114b865c6eeb..fe90056a294e 100644 --- a/gfx/2d/RecordedEventImpl.h +++ b/gfx/2d/RecordedEventImpl.h @@ -1068,6 +1068,49 @@ private: MOZ_IMPLICIT RecordedScaledFontCreation(S &aStream); }; +class RecordedScaledFontCreationByIndex : public RecordedEventDerived { +public: + + static void FontInstanceDataProc(const uint8_t* aData, uint32_t aSize, + const FontVariation* aVariations, uint32_t aNumVariations, + void* aBaton) + { + auto recordedScaledFontCreation = static_cast(aBaton); + recordedScaledFontCreation->SetFontInstanceData(aData, aSize, aVariations, aNumVariations); + } + + RecordedScaledFontCreationByIndex(ScaledFont* aScaledFont, size_t aUnscaledFontIndex) + : RecordedEventDerived(SCALEDFONTCREATIONBYINDEX) + , mRefPtr(aScaledFont) + , mUnscaledFontIndex(aUnscaledFontIndex) + , mGlyphSize(aScaledFont->GetSize()) + { + aScaledFont->GetFontInstanceData(FontInstanceDataProc, this); + } + + virtual bool PlayEvent(Translator *aTranslator) const; + + template void Record(S &aStream) const; + virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const; + + virtual std::string GetName() const { return "ScaledFont Creation"; } + virtual ReferencePtr GetObjectRef() const { return mRefPtr; } + + void SetFontInstanceData(const uint8_t *aData, uint32_t aSize); + +private: + friend class RecordedEvent; + + ReferencePtr mRefPtr; + size_t mUnscaledFontIndex; + Float mGlyphSize; + std::vector mInstanceData; + std::vector mVariations; + + template + MOZ_IMPLICIT RecordedScaledFontCreationByIndex(S &aStream); +}; + class RecordedScaledFontDestruction : public RecordedEventDerived { public: MOZ_IMPLICIT RecordedScaledFontDestruction(ReferencePtr aRefPtr) @@ -2954,6 +2997,68 @@ RecordedScaledFontCreation::RecordedScaledFontCreation(S &aStream) aStream.read((char*)mVariations.data(), sizeof(FontVariation) * numVariations); } +inline bool +RecordedScaledFontCreationByIndex::PlayEvent(Translator *aTranslator) const +{ + UnscaledFont* unscaledFont = aTranslator->LookupUnscaledFontByIndex(mUnscaledFontIndex); + if (!unscaledFont) { + gfxDevCrash(LogReason::UnscaledFontNotFound) << + "UnscaledFont lookup failed for key |" << hexa(mUnscaledFontIndex) << "|."; + return false; + } + + RefPtr scaledFont = + unscaledFont->CreateScaledFont(mGlyphSize, + mInstanceData.data(), mInstanceData.size(), + mVariations.data(), mVariations.size()); + + aTranslator->AddScaledFont(mRefPtr, scaledFont); + return true; +} + +template +void +RecordedScaledFontCreationByIndex::Record(S &aStream) const +{ + WriteElement(aStream, mRefPtr); + WriteElement(aStream, mUnscaledFontIndex); + WriteElement(aStream, mGlyphSize); + WriteElement(aStream, (size_t)mInstanceData.size()); + aStream.write((char*)mInstanceData.data(), mInstanceData.size()); + WriteElement(aStream, (size_t)mVariations.size()); + aStream.write((char*)mVariations.data(), sizeof(FontVariation) * mVariations.size()); +} + +inline void +RecordedScaledFontCreationByIndex::OutputSimpleEventInfo(std::stringstream &aStringStream) const +{ + aStringStream << "[" << mRefPtr << "] ScaledFont Created By Index"; +} + +inline void +RecordedScaledFontCreationByIndex::SetFontInstanceData(const uint8_t *aData, uint32_t aSize) +{ + mInstanceData.assign(aData, aData + aSize); +} + +template +RecordedScaledFontCreationByIndex::RecordedScaledFontCreationByIndex(S &aStream) + : RecordedEventDerived(SCALEDFONTCREATIONBYINDEX) +{ + ReadElement(aStream, mRefPtr); + ReadElement(aStream, mUnscaledFontIndex); + ReadElement(aStream, mGlyphSize); + + size_t size; + ReadElement(aStream, size); + mInstanceData.resize(size); + aStream.read((char*)mInstanceData.data(), size); + size_t numVariations; + ReadElement(aStream, numVariations); + mVariations.resize(numVariations); + aStream.read((char*)mVariations.data(), sizeof(FontVariation) * numVariations); +} + inline bool RecordedScaledFontDestruction::PlayEvent(Translator *aTranslator) const { @@ -3169,6 +3274,7 @@ RecordedFilterNodeSetInput::OutputSimpleEventInfo(std::stringstream &aStringStre f(GRADIENTSTOPSDESTRUCTION, RecordedGradientStopsDestruction); \ f(SNAPSHOT, RecordedSnapshot); \ f(SCALEDFONTCREATION, RecordedScaledFontCreation); \ + f(SCALEDFONTCREATIONBYINDEX, RecordedScaledFontCreationByIndex); \ f(SCALEDFONTDESTRUCTION, RecordedScaledFontDestruction); \ f(MASKSURFACE, RecordedMaskSurface); \ f(FILTERNODESETATTRIBUTE, RecordedFilterNodeSetAttribute); \ From ed62b1d4a17a81aa3625cd9a0e411c041724ca99 Mon Sep 17 00:00:00 2001 From: Jeff Muizelaar Date: Fri, 27 Oct 2017 18:21:27 -0400 Subject: [PATCH 11/15] Bug 1380014. Share fonts with WebRender. r=lsalzman This changes the serialization format a little bit. We now have an index at the end of the blob. This is currently used to store a list of the used font keys. In the future we'll add rects and can use it for invalidation. --- gfx/2d/DrawEventRecorder.cpp | 32 +++++ gfx/2d/DrawEventRecorder.h | 26 +++- gfx/2d/InlineTranslator.cpp | 1 + gfx/2d/InlineTranslator.h | 1 + gfx/2d/RecordedEvent.cpp | 34 +++++ gfx/2d/RecordedEvent.h | 4 + gfx/2d/RecordedEventImpl.h | 1 + gfx/layers/wr/WebRenderCommandBuilder.cpp | 12 +- gfx/webrender_bindings/Moz2DImageRenderer.cpp | 117 +++++++++++++++++- gfx/webrender_bindings/src/bindings.rs | 2 +- gfx/webrender_bindings/src/moz2d_renderer.rs | 80 +++++++++++- 11 files changed, 302 insertions(+), 8 deletions(-) diff --git a/gfx/2d/DrawEventRecorder.cpp b/gfx/2d/DrawEventRecorder.cpp index 6dbd3012ba06..ca415cf2799e 100644 --- a/gfx/2d/DrawEventRecorder.cpp +++ b/gfx/2d/DrawEventRecorder.cpp @@ -79,11 +79,42 @@ DrawEventRecorderMemory::DrawEventRecorderMemory() WriteHeader(mOutputStream); } +DrawEventRecorderMemory::DrawEventRecorderMemory(const SerializeResourcesFn &aFn) : + mSerializeCallback(aFn) +{ + mExternalFonts = true; + WriteHeader(mOutputStream); +} + + void DrawEventRecorderMemory::Flush() { } +void +DrawEventRecorderMemory::FlushItem(IntRect aRect) +{ + DetatchResources(); + WriteElement(mIndex, mOutputStream.mLength); + mSerializeCallback(mOutputStream, mUnscaledFonts); + WriteElement(mIndex, mOutputStream.mLength); + ClearResources(); +} + +void +DrawEventRecorderMemory::Finish() +{ + size_t indexOffset = mOutputStream.mLength; + // write out the index + mOutputStream.write(mIndex.mData, mIndex.mLength); + mIndex = MemStream(); + // write out the offset of the Index to the end of the output stream + WriteElement(mOutputStream, indexOffset); + ClearResources(); +} + + size_t DrawEventRecorderMemory::RecordingSize() { @@ -94,6 +125,7 @@ void DrawEventRecorderMemory::WipeRecording() { mOutputStream = MemStream(); + mIndex = MemStream(); WriteHeader(mOutputStream); } diff --git a/gfx/2d/DrawEventRecorder.h b/gfx/2d/DrawEventRecorder.h index 1d59eaab7fb0..ef29c8e6bc5a 100644 --- a/gfx/2d/DrawEventRecorder.h +++ b/gfx/2d/DrawEventRecorder.h @@ -14,6 +14,7 @@ #include #include +#include namespace mozilla { namespace gfx { @@ -26,7 +27,9 @@ public: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawEventRecorderPrivate) DrawEventRecorderPrivate(); virtual ~DrawEventRecorderPrivate() { } - virtual void Finish() { + virtual void Finish() { ClearResources(); } + virtual void FlushItem(IntRect) { } + void DetatchResources() { // The iteration is a bit awkward here because our iterator will // be invalidated by the removal for (auto font = mStoredFonts.begin(); font != mStoredFonts.end(); ) { @@ -37,7 +40,15 @@ public: auto oldSurface = surface++; (*oldSurface)->RemoveUserData(reinterpret_cast(this)); } + mStoredFonts.clear(); + mStoredSurfaces.clear(); + } + void ClearResources() { + mUnscaledFonts.clear(); + mStoredObjects.clear(); + mStoredFontData.clear(); + mUnscaledFontMap.clear(); } template @@ -148,6 +159,8 @@ private: std::ofstream mOutputStream; }; +typedef std::function> &aUnscaledFonts)> SerializeResourcesFn; + // WARNING: This should not be used in its existing state because // it is likely to OOM because of large continguous allocations. class DrawEventRecorderMemory final : public DrawEventRecorderPrivate @@ -159,6 +172,7 @@ public: * Constructs a DrawEventRecorder that stores the recording in memory. */ DrawEventRecorderMemory(); + explicit DrawEventRecorderMemory(const SerializeResourcesFn &aSerialize); void RecordEvent(const RecordedEvent &aEvent) override; @@ -173,9 +187,19 @@ public: * and processed in chunks, releasing memory as it goes. */ void WipeRecording(); + void Finish() override; + void FlushItem(IntRect) override; MemStream mOutputStream; + /* The index stream is of the form: + * ItemIndex { size_t dataEnd; size_t extraDataEnd; } + * It gets concatenated to the end of mOutputStream in Finish() + * The last size_t in the stream is offset of the begining of the + * index. + */ + MemStream mIndex; private: + SerializeResourcesFn mSerializeCallback; ~DrawEventRecorderMemory() {}; void Flush() override; diff --git a/gfx/2d/InlineTranslator.cpp b/gfx/2d/InlineTranslator.cpp index b28dc953d8fd..8fac5ed339a0 100644 --- a/gfx/2d/InlineTranslator.cpp +++ b/gfx/2d/InlineTranslator.cpp @@ -52,6 +52,7 @@ InlineTranslator::TranslateRecording(char *aData, size_t aLen) }; MemReader reader(aData, aLen); + uint32_t magicInt; ReadElement(reader, magicInt); if (magicInt != mozilla::gfx::kMagicInt) { diff --git a/gfx/2d/InlineTranslator.h b/gfx/2d/InlineTranslator.h index 72880625ef22..3508717c290f 100644 --- a/gfx/2d/InlineTranslator.h +++ b/gfx/2d/InlineTranslator.h @@ -128,6 +128,7 @@ public: void AddUnscaledFont(ReferencePtr aRefPtr, UnscaledFont *aUnscaledFont) final { + mUnscaledFontTable.push_back(aUnscaledFont); mUnscaledFonts.Put(aRefPtr, aUnscaledFont); } diff --git a/gfx/2d/RecordedEvent.cpp b/gfx/2d/RecordedEvent.cpp index f5c2022a7f25..1a68725357fe 100644 --- a/gfx/2d/RecordedEvent.cpp +++ b/gfx/2d/RecordedEvent.cpp @@ -117,6 +117,40 @@ RecordedEvent::GetEventName(EventType aType) } } +template +void RecordedEvent::RecordUnscaledFontImpl(UnscaledFont *aUnscaledFont, S& aOutput) { + RecordedFontData fontData(aUnscaledFont); + RecordedFontDetails fontDetails; + if (fontData.GetFontDetails(fontDetails)) { + // Try to serialise the whole font, just in case this is a web font that + // is not present on the system. + WriteElement(aOutput, fontData.mType); + fontData.RecordToStream(aOutput); + + auto r = RecordedUnscaledFontCreation(aUnscaledFont, fontDetails); + WriteElement(aOutput, r.mType); + r.RecordToStream(aOutput); + } else { + // If that fails, record just the font description and try to load it from + // the system on the other side. + RecordedFontDescriptor fontDesc(aUnscaledFont); + if (fontDesc.IsValid()) { + WriteElement(aOutput, fontDesc.RecordedEvent::mType); + fontDesc.RecordToStream(aOutput); + } else { + gfxWarning() << "DrawTargetRecording::FillGlyphs failed to serialise UnscaledFont"; + } + } +} + +void RecordedEvent::RecordUnscaledFont(UnscaledFont *aUnscaledFont, std::ostream *aOutput) { + RecordUnscaledFontImpl(aUnscaledFont, *aOutput); +} + +void RecordedEvent::RecordUnscaledFont(UnscaledFont *aUnscaledFont, MemStream &aOutput) { + RecordUnscaledFontImpl(aUnscaledFont, aOutput); +} + already_AddRefed Translator::CreateDrawTarget(ReferencePtr aRefPtr, const IntSize &aSize, SurfaceFormat aFormat) diff --git a/gfx/2d/RecordedEvent.h b/gfx/2d/RecordedEvent.h index 03f6d8b9e2fe..1477278086a9 100644 --- a/gfx/2d/RecordedEvent.h +++ b/gfx/2d/RecordedEvent.h @@ -313,6 +313,10 @@ protected: friend class DrawEventRecorderPrivate; friend class DrawEventRecorderFile; friend class DrawEventRecorderMemory; + static void RecordUnscaledFont(UnscaledFont *aUnscaledFont, std::ostream *aOutput); + static void RecordUnscaledFont(UnscaledFont *aUnscaledFont, MemStream &aOutput); + template + static void RecordUnscaledFontImpl(UnscaledFont *aUnscaledFont, S &aOutput); MOZ_IMPLICIT RecordedEvent(int32_t aType) : mType(aType) {} diff --git a/gfx/2d/RecordedEventImpl.h b/gfx/2d/RecordedEventImpl.h index fe90056a294e..bf9aebae221c 100644 --- a/gfx/2d/RecordedEventImpl.h +++ b/gfx/2d/RecordedEventImpl.h @@ -22,6 +22,7 @@ namespace gfx { template class RecordedEventDerived : public RecordedEvent { using RecordedEvent::RecordedEvent; + public: void RecordToStream(std::ostream &aStream) const { static_cast(this)->Record(aStream); } diff --git a/gfx/layers/wr/WebRenderCommandBuilder.cpp b/gfx/layers/wr/WebRenderCommandBuilder.cpp index b80b57049d32..e8082e687891 100644 --- a/gfx/layers/wr/WebRenderCommandBuilder.cpp +++ b/gfx/layers/wr/WebRenderCommandBuilder.cpp @@ -25,6 +25,8 @@ namespace mozilla { namespace layers { +using namespace gfx; + void WebRenderCommandBuilder::Destroy() { mLastCanvasDatas.Clear(); @@ -500,12 +502,20 @@ WebRenderCommandBuilder::GenerateFallbackData(nsDisplayItem* aItem, bool snapped; bool isOpaque = aItem->GetOpaqueRegion(aDisplayListBuilder, &snapped).Contains(clippedBounds); - RefPtr recorder = MakeAndAddRef(); + RefPtr recorder = MakeAndAddRef([&] (MemStream &aStream, std::vector> &aUnscaledFonts) { + size_t count = aUnscaledFonts.size(); + aStream.write((const char*)&count, sizeof(count)); + for (auto unscaled : aUnscaledFonts) { + wr::FontKey key = mManager->WrBridge()->GetFontKeyForUnscaledFont(unscaled); + aStream.write((const char*)&key, sizeof(key)); + } + }); RefPtr dummyDt = gfx::Factory::CreateDrawTarget(gfx::BackendType::SKIA, gfx::IntSize(1, 1), format); RefPtr dt = gfx::Factory::CreateRecordingDrawTarget(recorder, dummyDt, paintSize.ToUnknownSize()); PaintItemByDrawTarget(aItem, dt, paintRect, offset, aDisplayListBuilder, fallbackData->mBasicLayerManager, mManager, scale); + recorder->FlushItem(IntRect()); recorder->Finish(); Range bytes((uint8_t*)recorder->mOutputStream.mData, recorder->mOutputStream.mLength); diff --git a/gfx/webrender_bindings/Moz2DImageRenderer.cpp b/gfx/webrender_bindings/Moz2DImageRenderer.cpp index fdc7a329e799..514e89a71cfc 100644 --- a/gfx/webrender_bindings/Moz2DImageRenderer.cpp +++ b/gfx/webrender_bindings/Moz2DImageRenderer.cpp @@ -13,18 +13,97 @@ #include "webrender_ffi.h" #include +#include #ifdef MOZ_ENABLE_FREETYPE #include "mozilla/ThreadLocal.h" #endif +namespace std { + template <> + struct hash{ + public : + size_t operator()(const mozilla::wr::FontKey &key ) const + { + return hash()(mozilla::wr::AsUint64(key)); + } + }; +}; + + + namespace mozilla { + +using namespace gfx; + namespace wr { #ifdef MOZ_ENABLE_FREETYPE static MOZ_THREAD_LOCAL(FT_Library) sFTLibrary; #endif +struct FontTemplate { + void *mData; + size_t mSize; + int mIndex; + const VecU8 *mVec; +}; + +// we need to do special things for linux so that we have fonts per backend +std::unordered_map sFontDataTable; + +extern "C" { +void +AddFontData(wr::FontKey aKey, void *aData, size_t aSize, int aIndex, ArcVecU8 *aVec) { + auto i = sFontDataTable.find(aKey); + if (i == sFontDataTable.end()) { + FontTemplate font; + font.mData = aData; + font.mSize = aSize; + font.mIndex = aIndex; + font.mVec = wr_add_ref_arc(aVec); + sFontDataTable[aKey] = font; + } +} + +void +DeleteFontData(wr::FontKey aKey) { + auto i = sFontDataTable.find(aKey); + if (i != sFontDataTable.end()) { + sFontDataTable.erase(i); + wr_dec_ref_arc(i->second.mVec); + } +} +} + +RefPtr +GetUnscaledFont(Translator *aTranslator, wr::FontKey key) { + MOZ_ASSERT(sFontDataTable.find(key) != sFontDataTable.end()); + auto data = sFontDataTable[key]; + FontType type = +#ifdef XP_MACOSX + FontType::MAC; +#elif XP_WIN + FontType::DWRITE; +#elif ANDROID + FontType::FREETYPE; +#else + FontType::FONTCONFIG; +#endif + // makes a copy of the data + RefPtr fontResource = Factory::CreateNativeFontResource((uint8_t*)data.mData, data.mSize, + aTranslator->GetReferenceDrawTarget()->GetBackendType(), + type, + aTranslator->GetFontContext()); + RefPtr unscaledFont; + if (fontResource) { + // Instance data is only needed for GDI fonts which webrender does not + // support. + unscaledFont = fontResource->CreateUnscaledFont(data.mIndex, nullptr, 0); + } + return unscaledFont; +} + static bool Moz2DRenderCallback(const Range aBlob, gfx::IntSize aSize, gfx::SurfaceFormat aFormat, @@ -86,9 +165,43 @@ static bool Moz2DRenderCallback(const Range aBlob, dt = gfx::Factory::CreateTiledDrawTarget(tileset); } - gfx::InlineTranslator translator(dt, fontContext); + struct Reader { + const uint8_t *buf; + size_t len; + size_t pos; - auto ret = translator.TranslateRecording((char*)aBlob.begin().get(), aBlob.length()); + Reader(const uint8_t *buf, size_t len) : buf(buf), len(len), pos(0) {} + + size_t ReadSize() { + size_t ret; + MOZ_RELEASE_ASSERT(pos + sizeof(ret) <= len); + memcpy(&ret, buf + pos, sizeof(ret)); + pos += sizeof(ret); + return ret; + } + }; + //XXX: Make safe + size_t indexOffset = *(size_t*)(aBlob.end().get()-sizeof(size_t)); + Reader reader(aBlob.begin().get()+indexOffset, aBlob.length()-sizeof(size_t)-indexOffset); + + bool ret; + size_t offset = 0; + while (reader.pos < reader.len) { + size_t end = reader.ReadSize(); + size_t extra_end = reader.ReadSize(); + + gfx::InlineTranslator translator(dt, fontContext); + + size_t count = *(size_t*)(aBlob.begin().get() + end); + for (size_t i = 0; i < count; i++) { + wr::FontKey key = *(wr::FontKey*)(aBlob.begin() + end + sizeof(count) + sizeof(wr::FontKey)*i).get(); + RefPtr font = GetUnscaledFont(&translator, key); + translator.AddUnscaledFont(0, font); + } + Range blob(aBlob.begin() + offset, aBlob.begin() + end); + ret = translator.TranslateRecording((char*)blob.begin().get(), blob.length()); + offset = extra_end; + } #if 0 static int i = 0; diff --git a/gfx/webrender_bindings/src/bindings.rs b/gfx/webrender_bindings/src/bindings.rs index 166207f0489e..329f9dfe47f4 100644 --- a/gfx/webrender_bindings/src/bindings.rs +++ b/gfx/webrender_bindings/src/bindings.rs @@ -38,7 +38,7 @@ type WrPipelineId = PipelineId; /// cbindgen:field-names=[mNamespace, mHandle] type WrImageKey = ImageKey; /// cbindgen:field-names=[mNamespace, mHandle] -type WrFontKey = FontKey; +pub type WrFontKey = FontKey; /// cbindgen:field-names=[mNamespace, mHandle] type WrFontInstanceKey = FontInstanceKey; /// cbindgen:field-names=[mNamespace, mHandle] diff --git a/gfx/webrender_bindings/src/moz2d_renderer.rs b/gfx/webrender_bindings/src/moz2d_renderer.rs index 449935c21c1a..f9c916badc9f 100644 --- a/gfx/webrender_bindings/src/moz2d_renderer.rs +++ b/gfx/webrender_bindings/src/moz2d_renderer.rs @@ -1,8 +1,10 @@ +#![allow(improper_ctypes)] // this is needed so that rustc doesn't complain about passing the &Arc to an extern function use webrender_api::*; use bindings::{ByteSlice, MutByteSlice, wr_moz2d_render_cb}; use rayon::ThreadPool; use std::collections::hash_map::{HashMap, Entry}; +use std::mem; use std::ptr; use std::sync::mpsc::{channel, Sender, Receiver}; use std::sync::Arc; @@ -26,6 +28,48 @@ fn option_to_nullable(option: &Option) -> *const T { } } +fn to_usize(slice: &[u8]) -> usize { + convert_from_bytes(slice) +} + +fn convert_from_bytes(slice: &[u8]) -> T { + assert!(mem::size_of::() <= slice.len()); + let mut ret: T; + unsafe { + ret = mem::uninitialized(); + ptr::copy_nonoverlapping(slice.as_ptr(), + &mut ret as *mut T as *mut u8, + mem::size_of::()); + } + ret +} + +struct BufReader<'a> +{ + buf: &'a[u8], + pos: usize, +} + +impl<'a> BufReader<'a> { + fn new(buf: &'a[u8]) -> BufReader<'a> { + BufReader{ buf: buf, pos: 0 } + } + + fn read(&mut self) -> T { + let ret = convert_from_bytes(&self.buf[self.pos..]); + self.pos += mem::size_of::(); + ret + } + + fn read_font_key(&mut self) -> FontKey { + self.read() + } + + fn read_usize(&mut self) -> usize { + self.read() + } +} + impl BlobImageRenderer for Moz2dImageRenderer { fn add(&mut self, key: ImageKey, data: BlobImageData, tiling: Option) { self.blob_commands.insert(key, (Arc::new(data), tiling)); @@ -41,7 +85,7 @@ impl BlobImageRenderer for Moz2dImageRenderer { } fn request(&mut self, - _resources: &BlobImageResources, + resources: &BlobImageResources, request: BlobImageRequest, descriptor: &BlobImageDescriptor, _dirty_rect: Option) { @@ -61,6 +105,29 @@ impl BlobImageRenderer for Moz2dImageRenderer { let commands = Arc::clone(&blob.0); + fn process_fonts(mut extra_data: BufReader, resources: &BlobImageResources) { + let font_count = extra_data.read_usize(); + for _ in 0..font_count { + let key = extra_data.read_font_key(); + let template = resources.get_font_data(key); + if let &FontTemplate::Raw(ref data, ref index) = template { + unsafe { AddFontData(key, data.as_ptr(), data.len(), *index, data); } + } + resources.get_font_data(key); + } + } + let index_offset_pos = commands.len()-mem::size_of::(); + + let index_offset = to_usize(&commands[index_offset_pos..]); + { + let mut index = BufReader::new(&commands[index_offset..index_offset_pos]); + while index.pos < index.buf.len() { + let end = index.read_usize(); + let extra_end = index.read_usize(); + process_fonts(BufReader::new(&commands[end..extra_end]), resources); + } + } + self.workers.spawn(move || { let buf_size = (descriptor.width * descriptor.height @@ -120,14 +187,21 @@ impl BlobImageRenderer for Moz2dImageRenderer { // If we break out of the loop above it means the channel closed unexpectedly. Err(BlobImageError::Other("Channel closed".into())) } - - fn delete_font(&mut self, _font: FontKey) { + fn delete_font(&mut self, font: FontKey) { + unsafe { DeleteFontData(font); } } fn delete_font_instance(&mut self, _key: FontInstanceKey) { } } +use bindings::WrFontKey; +extern "C" { + #[allow(improper_ctypes)] + fn AddFontData(key: WrFontKey, data: *const u8, size: usize, index: u32, vec: &Arc>); + fn DeleteFontData(key: WrFontKey); +} + impl Moz2dImageRenderer { pub fn new(workers: Arc) -> Self { let (tx, rx) = channel(); From 4461b5e90fc41d3183d3c631eb46637a99d344c4 Mon Sep 17 00:00:00 2001 From: sotaro Date: Sat, 28 Oct 2017 07:30:13 +0900 Subject: [PATCH 12/15] Bug 1408573 - Change buffer allocation to fallible r=nical --- gfx/layers/ImageContainer.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/gfx/layers/ImageContainer.cpp b/gfx/layers/ImageContainer.cpp index 60ac7f3d388c..69d0450d8e2e 100644 --- a/gfx/layers/ImageContainer.cpp +++ b/gfx/layers/ImageContainer.cpp @@ -81,8 +81,9 @@ BufferRecycleBin::GetBuffer(uint32_t aSize) { MutexAutoLock lock(mLock); - if (mRecycledBuffers.IsEmpty() || mRecycledBufferSize != aSize) - return MakeUnique(aSize); + if (mRecycledBuffers.IsEmpty() || mRecycledBufferSize != aSize) { + return UniquePtr(new (fallible) uint8_t[aSize]); + } uint32_t last = mRecycledBuffers.Length() - 1; UniquePtr result = Move(mRecycledBuffers[last]); From 1c0b2d34a1bd7a8d24743e0ad4da8312a25a8584 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Sat, 21 Oct 2017 01:15:58 +0100 Subject: [PATCH 13/15] Bug 1385542 - Blocklist pghook.dll as it causes crashes. r=jimm --HG-- extra : rebase_source : e0a8b869388d5772697bf31e900b691534b93e63 --- mozglue/build/WindowsDllBlocklist.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mozglue/build/WindowsDllBlocklist.cpp b/mozglue/build/WindowsDllBlocklist.cpp index 2166af608b0a..9c088fbfa403 100644 --- a/mozglue/build/WindowsDllBlocklist.cpp +++ b/mozglue/build/WindowsDllBlocklist.cpp @@ -257,6 +257,9 @@ static const DllBlockInfo sWindowsDllBlocklist[] = { // Bug 1407337, crashes with OpenSC < 0.16.0 { "onepin-opensc-pkcs11.dll", MAKE_VERSION(0, 15, 0xffff, 0xffff) }, + // Avecto Privilege Guard causes crashes, bug 1385542 + { "pghook.dll", ALL_VERSIONS }, + { nullptr, 0 } }; From e25145c75896a892a2a85f1493a0963ca9a0968b Mon Sep 17 00:00:00 2001 From: Joel Maher Date: Fri, 27 Oct 2017 21:13:42 -0400 Subject: [PATCH 14/15] Bug 1412365 - jsdcov chunks need reducing now that we run on faster hardware. r=gmierz --- taskcluster/ci/test/mochitest.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/taskcluster/ci/test/mochitest.yml b/taskcluster/ci/test/mochitest.yml index efe640911ffb..19ba74f61a80 100644 --- a/taskcluster/ci/test/mochitest.yml +++ b/taskcluster/ci/test/mochitest.yml @@ -38,7 +38,7 @@ mochitest: android.*: 20 linux.*/debug: 16 linux64-asan/opt: 10 - linux64-*cov/opt: 10 + linux64-.*cov/opt: 10 default: 5 e10s: by-test-platform: @@ -48,7 +48,6 @@ mochitest: max-run-time: by-test-platform: android-4.3-arm7-api-16/debug: 7200 - linux64-jsdcov/opt: 10800 default: 5400 allow-software-gl-layers: false tier: @@ -96,7 +95,6 @@ mochitest-browser-chrome: by-test-platform: linux.*/debug: 16 linux64-asan/opt: 16 - linux64-jsdcov/opt: 35 default: 7 e10s: by-test-platform: From 5052f0826faf9cfb61bc4eac6f8c9d5500f0d91b Mon Sep 17 00:00:00 2001 From: Jeff Muizelaar Date: Fri, 27 Oct 2017 22:08:47 -0400 Subject: [PATCH 15/15] Bug 1380014. Keep the unscaled font alive. r=lsalzman This is the actual change the eliminates the font cache churn as well as eliminating the jank that comes when loading font for the first time. --- gfx/webrender_bindings/Moz2DImageRenderer.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/gfx/webrender_bindings/Moz2DImageRenderer.cpp b/gfx/webrender_bindings/Moz2DImageRenderer.cpp index 514e89a71cfc..965ba233ef47 100644 --- a/gfx/webrender_bindings/Moz2DImageRenderer.cpp +++ b/gfx/webrender_bindings/Moz2DImageRenderer.cpp @@ -47,6 +47,7 @@ struct FontTemplate { size_t mSize; int mIndex; const VecU8 *mVec; + RefPtr mUnscaledFont; }; // we need to do special things for linux so that we have fonts per backend @@ -79,7 +80,10 @@ DeleteFontData(wr::FontKey aKey) { RefPtr GetUnscaledFont(Translator *aTranslator, wr::FontKey key) { MOZ_ASSERT(sFontDataTable.find(key) != sFontDataTable.end()); - auto data = sFontDataTable[key]; + auto &data = sFontDataTable[key]; + if (data.mUnscaledFont) { + return data.mUnscaledFont; + } FontType type = #ifdef XP_MACOSX FontType::MAC; @@ -101,6 +105,7 @@ GetUnscaledFont(Translator *aTranslator, wr::FontKey key) { // support. unscaledFont = fontResource->CreateUnscaledFont(data.mIndex, nullptr, 0); } + data.mUnscaledFont = unscaledFont; return unscaledFont; }