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

- Bug 1246851 (Part 1) - Add a new SurfacePipe API for writing to image surfaces in a safe and composable manner. r=njn (2e3353a6a7)
- Bug 1246851 (Part 2) - Add SurfaceFilter implementations for basic surface output operations. r=njn (fa30948a3f)
- Bug 1246851 (Part 3) - Add a factory for constructing SurfacePipes. r=njn (7a746d3ec8)
- Bug 1191347 - Explicitly release surfaces on the main thread in TestDecodeToSurface. r=me (fa1a68dc9a)
- Bug 1246851 (Part 4) - Add a test suite for SurfacePipes and SurfaceFilters. r=njn (380dc94c08)
- Bug 1247152 (Part 1) - Use SurfacePipe in the GIF decoder. r=njn (8b3d76f017)
- Bug 1247152 (Part 2) - Remove even more code from the GIF decoder. r=edwin (80c8cc5e1c)
- side effects Bug 1247152 (Part 1) (5b6cbf0ad5)
- Bug 1237232 - Properly check the result of Vector append() calls in security/. r=keeler (b06dce061f)
- Bug 1235308 - Fix -Wimplicit-fallthrough warnings in security/. r=keeler (ac5c3bf540)
- Bug 1235188 - Fix -Wformat warnings in security/certverifier/. r=keeler (25ee7ee77c)
- Bug 1004149 - Remove some dead code. r=keeler (59fedcb6a6)
- Bug 1004149 - Return mozilla::pkix::Result values in nsNSSHttpInterface functions. r=keeler (76933c7d94)
- Bug 1187173 - Disable warning C4623 on security/certverifier. r=briansmith (c1353b0577)
- Bug 1256484 - Disable C4456 and C4458 to unblock compilation on VS2015; r=keeler (b51ac368ba)
- Bug 1251009 - Remove unused nsICertificateDialogs.notifyCACertExists() method. r=keeler, r=mfinkle (9ca9aee3d0)
- Bug 1249224 - window.open() should open a new window in the same container, r=bz (c57c76ec2f)
- Bug 1245451 - add default nullptr value to mChrome. r=bsmedberg (3236ea34df)
- Bug 1255849. Add some documentation for AutoJSAPI instances that seem to be used just for cxpushing. r=bholley (60a81652de)
- Bug 1189554 - Make Saved Passwords dialog resizable on Windows again. r=smaug (a367796251)
- Bug 1252974 - Convert screen's available dimensions to CSS-pixel units in nsWindowWatcher. r=emk (5524055ab0)
- Bug 1233328 - Part 1: Ignore SHA-1 pins in PublicKeyPinningService.cpp. r=keeler (e5fe732a4b)
- Bug 1233328 - Part 2: Use SHA-256 StaticFingerprints directly instead창 of StaticPinset since the SHA-1 StaticFingerprints entry will always be null. r=keeler (50f88c76da)
- Bug 1256089 - Fix Mutex support for tier-3 platforms; r=froydnj (76ab483843)
- Bug 1257019 - Add move construction to js::Mutex<T>. r=terrence (383ad474ba)
- No bug, Automated HPKP preload list update from host bld-linux64-spot-309 - a=hpkp-update (0a6d3b9c40)
- No bug, Automated HPKP preload list update from host bld-linux64-spot-223 - a=hpkp-update (7b3dbac6f8)
- Bug 1255655 - Const-ify kPinset_* arrays. r=cykesiopka. (ddbaad40a0)
- No bug, Automated HPKP preload list update from host bld-linux64-spot-543 - a=hpkp-update (f5c37e366a)
- bug 1233853 - make nsSyncJPAKE aware of NSS shutdown r=jcj (9f74b5a46f)
- Bug 1215734 - Expand GeckoMediaPlugin sandbox policy for Clang 3.7 ASan. r=kang (a96e0429e5)
- part Bug 1154738 - Fixed WMFUtils.cpp compilation on mingw (9ba8bd1481)
- Bug 1256498. Explicitly convert to float. r=bas (ce97ef100e)
- Bug 1223736 - Part 1: Set correct effective transform on mask layers. r=thinker (a87514ac4f)
- Bug 1249813 - part 1 - revise nsShmImage to allow draw targets anywhere inside its bounds. r=jrmuizel (cba4cdf8c9)
- Bug 1249813 - part 2 - make Cairo mark a surface as clear if clip covers entire surface. r=jrmuizel (45ccfcfc15)
- Bug 1249813 - part 3 - tell the compositor if the root layer has opaque content so it can skip clears. r=mattwoodrow (2abaa0cf8b)
- Bug 1255303 - Use SurfaceFormat::B8G8R8X8 as back buffer if possible r=jrmuizel (5f81a83123)
- Bug 1253860 - Don't update the scrollbar unless we're actually painting. r=mstange (d3a2482408)
- Bug 1253860 - Add a flag on scroll frames indicating if they have an APZ counterpart. r=mstange (2aef746ee1)
- Bug 1253860 - Skip paints for main thread scrolls if we can ask APZ to handle the scrolling for us. r=mstange (4483da1f16)
- Bug 1244116 - Telemetry for mixed content requests by plugins. r=smaug, p=ally (fd5f87f666)
- Bug 1252829 - CSP Telemetry. r=ckerschb, p=bsmedberg (8d340fa824)
- Bug 1246464: Add 'const' to some stylesheet args in nsDocument methods. r=heycam (4e744d81d2)
- Bug 1255705 - Add some useful logging that can be enabled at compile time. r=botond (80f0202160)
- Bug 1255856 - Don't allow paint-skipping if there are windowed plugins on the page. r=mstange,jimm (25e6d8ed22)
- Bug 1256727 - Don't allow paint-skipping on pages with scroll-linked effects. r=mstange (a8bace52ff)
- Bug 1247098 - Take document resolution into account when computing root composition bounds for displayport base. r=tnikkel (1b7b61c82e)
- Bug 1250550 - Ensure a scroll event posted during a refresh driver tick fires during that same tick. r=mats (d5bfc24524)
- Bug 1253739 - Fix incorrect namespace on forward declaration. r=botond (dfc7aac51e)
- Bug 1253489 - Update SendFenceHandleIfPresent() r=nical (798c209dff)
- Bug 1253860 - Stop APZC from reprocessing stale metrics on unrelated layer tree updates. r=botond (1013df0068)
- Bug 1253860 - Add machinery to update APZ's scroll offset without a main-thread paint. r=botond (cb95baf9c6)
- Bug 1239564 - Post translate maskSurface to renderTarget. r=roc (66c56d227d)
- Bug 1223736 - Part 2: Draw masks in the correct coordinate space when doing 3d transforms in BasicCompositor. r=lsalzman (2d62616534)
- Bug 1223736 - Part 3: Remove the distinction between 2d and 3d masks since it only adds complexity. r=Bas (61c2306875)
- Bug 1137561 - Follow up VS2015 build error. r=masayuki (f12716a1ab)
- Bug 1217275 Fix missing \n in IMMHandler::HandleDocumentFeed(), it was replaced to empty string accidentally r=m_kato (3315b1c270)
- Bug 1243268 - Adjust ATOK workaround. r=masayuki (13af7184d1)
- Bug 1242690 - If a drag block is interrupted by something else, have it create a new drag block when it resumes. r=rbarker (fe3dc8deac)
- Bug 1242690 - Add untransforming of mouse events not in a drag block. r=rbarker (a39e715efe)
- Bug 1241991 - Switch mTreeLock from a Monitor to a Mutex. r=kats (0eca284591)
- Bug 1242690 - Further refine the mouse event untransformation code to only apply to events directed at a scrollbar. r=rbarker (5c92ca2807)
- Bug 1251608 - Add a root-content annotation to the APZ test data structure. r=botond (a1ee8e496a)
- Bug 1249748 - Ensure the mHandledByAPZ flag is set on WidgetTouchEvents that are handled by APZ. r=botond (11bdfae896)
- Bug 1242690 - Don't apply the main-thread callback transform for events in a drag block. r=rbarker (3db1405b68)
- Bug 1243589 - Use SingleTiledContentClient even for scrollable layers if the layer is smaller than a single tile. r=mattwoodrow (56bb664de1)
- Bug 1250517 - Differentiate between no critical display port and empty critical display port in ClientTiledPaintedLayer; r=kats (1b809fac8e)
- Bug 1255448 - Call ClientMultiTiledLayerBuffer::PaintThebes even when region to paint is empty. r=mattwoodrow (31ac878dc0)
- Bug 1255907 - Fix unification build issues in APZ & Layers. r=kats (9829525402)
- Bug 1256344 - If a long-press is interrupted by a non-touch block, don't dispatch the long-press event. r=botond (b3bdd0e58e)
- Bug 1256341 - Guard against scenarios where GenerateSingleTap is called without an active touch block. r=botond (d4ec208407)
- Bug 1230552 - Minor follow-up to add an assertion. rs=kats (6f9eec7bd4)
- Bug 1247964 - Allow InputBlockState::SetScrolledApzc to accept new APZC when it is an ancestor of the current APZC r=kats # Please enter the commit message for your changes. Lines starting (08ce9cfa98)
- Bug 1257264 - When apz.allow_immediate_handoff=false, APZ handoff should not occur when panning changes direction r=botond (6ec9ec22e6)
- Bug 1250213 - Ensure the scroll offset does not go outside the page bounds when going full screen r=kats (ace8e8a80c)
- Bug 1241332 - part 1, Request content repaint at end of APZ animation r=kats (74f7e249f2)
- Bug 1255705 - Generalize the NotifyLayersUpdated short-circuit codepath to trigger on empty transactions as well. r=botond (0344d44844)
- Bug 1250614 - Repeated zooming in bug on mobile Wikipedia site r=botond (459f02b8d3)
- Bug 1251001 - Input fields at the bottom of a page do not pan into view when gaining focus. r=botond (770102bf9f)
- Bug 1190093 (Comment Tweak) - Add better comments for nsIDocument::mIsShowing and mVisible. r=me DONTBUILD (e3822ef086)
- Bug 1217226: P1. Use VideoInfo display size data rather than attempt to detect value in stream. r=cpearce (a4a7e9b19a)
- Bug 1217226: P2. Implement WMFMediaDataDecoder::ConfigurationChanged. r=cpearce (52177525c5)
- fix misspatch (61a694fe3d)
- Bug 1249706: Added telemetry for the proportion of frames dropped keyed by several details. r=jya (cb459d971c)
- Bug 1202296 - Recreate the MFTDecoder when we want to disable DXVA. r=cpearce (d82999e94f)
- Bug 1176071 - Handle WMF MFTDecoder returning success but no output, with telemetry. r=mattwoodrow,r=vladan (da8017c92b)
- align, cleanup (9a86d51dfd)
- no bug - fix case of nsIDocShell.h in WindowsUIUtils.cpp (0ccabaa445)
- Bug 1187724 Don't dispatch KeyboardEvents when the target of WM_APPCOMMAND is a windowed plug-in for preventing deadlock r=jimm (7b6d83559c)
- Bug 1187178 - Use MOZ_WINSDK_MAXVER instead of #ifndef. r=jimm (06c949ddb9)
- bits of Bug 1165515 - Part 13-2: Replace usage of PRLogModuleLevel (7beaa2dcc4)
- Bug 1257791: Return correct DPI and printing scale from nsDeviceContextSpecWin when printing to PDF. r=jimm (87360301ea)
- Bug 1242295 - Fix compile error in nsDeviceContextSpecWin. r=jimm (d1d4680319)
- Bug 1229881 - fix off-by-one error in nsPrinterEnumeratorWin::GetPrinterNameList; r=dbaron; a=KWierso (439061ba50)
- Bug 1239683 - Replace NS_UNCONSTRAINEDSIZE with NS_MAXSIZE in windows/nsWindow.cpp. r=mats (4135189bec)
- Bug 1033488 - Send RTL information to child process by WM_INPUTLANGCHANGE. r=masayuki (eaf8f70d34)
- Bug 1238137 - Telemetry pings for main thread touch scrolling (Windows only). r=kats (f2194a2965)
- Bug 1156182 - Ensure nsWindow::Destroy() is called before destroying mPresentLock to avoid a race with the compositor thread. r=Bas (0452ffc641)
- Bug 1173617. Don't cache titlebar caption sizes unless the widget has a titlebar. r=jimm (b29e190504)
- Bug 580165 - Clean up dead code related to missing screen managers in widget. r=jimm (bf83f21ddc)
- Bug 1256501: Fix warning C4312 with 64-bit VS2015 in widget/windows/nsWindow.cpp; r=jimm (635151964e)
- Bug 1242690 - Squash together DispatchAPZAwareEvent and DispatchInputEvent. r=dvander (d7b4fea361)
- Bug 1242616: Add break in nsWindow.cpp WM_GETOBJECT handling. r=tbsaunde (eb516d4119)
- Bug 1239353 - Don't try to change DPI on the fly for popup windows, they remain connected to their parent's presShell and therefore need to share its resolution. r=emk (1491b84fd1)
- Bug 1246389 - Resize window appropriately on WM_DPICHANGED messages for dynamic resolution changes. r=emk (f3dbfcdbb1)
- Bug 1254019 - Don't attempt to resize a maximized window on DPI change; and when handling a DPI change, constrain the resized window to the screen bounds. r=emk (2047c2dcb5)
- Bug 1252191 - use UniquePtr instead of ScopedFreePtr in PoisonIOInterposerMac.cpp; r=aklotz (7c26e55b76)
- Bug 1233208: Disable IOInterposer on Beta and Release; r=froydnj (04a6f8b07c)
- crashreporter (377572bbb1)
- Bug 1055322 - The realloc for libnestegg should free with size 0. r=froydnj (ea624646ca)
- Bug 1236789. Avoid creating an unnecessary thread pool thread for tail-dispatch in TaskQueue. r=bholley (e7fb9e4373)
- Bug 1255655 - Const-ify named CIDs. r=froydnj. (03b414d92b)
- Bug 1250396 (part 1) - Document a subtle contraint on nsIAtom. r=froydnj. (ff279149ac)
- Bug 1250396 (part 2) - Remove nsStaticAtomStringType. r=froydnj. (5520507680)
- Bug 1255343 - Stop returning nsresult from NS_RegisterStaticAtoms; r=ehsan (de1d387937)
- Bug 1251495 - remove unnecessary Logging.h include from nsStaticAtom.h; r=erahm (5226a840fa)
This commit is contained in:
2024-03-20 23:36:16 +08:00
parent c2f9b5547e
commit c8732098b3
203 changed files with 12573 additions and 8333 deletions
+5
View File
@@ -13535,6 +13535,11 @@ public:
{
nsAutoPopupStatePusher popupStatePusher(mPopupState);
// We need to set up an AutoJSAPI here for the following reason: When we do
// OnLinkClickSync we'll eventually end up in nsGlobalWindow::OpenInternal
// which only does popup blocking if !LegacyIsCallerChromeOrNativeCode().
// So we need to fake things so that we don't look like native code as far
// as LegacyIsCallerNativeCode() is concerned.
AutoJSAPI jsapi;
if (mIsTrusted || jsapi.Init(mContent->OwnerDoc()->GetScopeObject())) {
mHandler->OnLinkClickSync(mContent, mURI,
+3 -1
View File
@@ -844,7 +844,7 @@ nsDOMWindowUtils::SendWheelEvent(float aX,
wheelEvent.refPoint = nsContentUtils::ToWidgetPoint(CSSPoint(aX, aY), offset, presContext);
widget->DispatchAPZAwareEvent(&wheelEvent);
widget->DispatchInputEvent(&wheelEvent);
if (widget->AsyncPanZoomEnabled()) {
// Computing overflow deltas is not compatible with APZ, so if APZ is
@@ -2596,6 +2596,8 @@ nsDOMWindowUtils::ZoomToFocusedInput()
uint32_t flags = layers::DISABLE_ZOOM_OUT;
if (!Preferences::GetBool("formhelper.autozoom")) {
flags |= layers::PAN_INTO_VIEW_ONLY;
} else {
flags |= layers::ONLY_ZOOM_TO_DEFAULT_SCALE;
}
CSSRect bounds = nsLayoutUtils::GetBoundingContentRect(content, rootScrollFrame);
+22 -2
View File
@@ -1573,6 +1573,26 @@ nsDocument::~nsDocument()
Accumulate(Telemetry::MIXED_CONTENT_PAGE_LOAD, mixedContentLevel);
Accumulate(Telemetry::SCROLL_LINKED_EFFECT_FOUND, mHasScrollLinkedEffect);
// record mixed object subrequest telemetry
if (mHasMixedContentObjectSubrequest) {
/* mixed object subrequest loaded on page*/
Accumulate(Telemetry::MIXED_CONTENT_OBJECT_SUBREQUEST, 1);
} else {
/* no mixed object subrequests loaded on page*/
Accumulate(Telemetry::MIXED_CONTENT_OBJECT_SUBREQUEST, 0);
}
// record CSP telemetry on this document
if (mHasCSP) {
Accumulate(Telemetry::CSP_DOCUMENTS_COUNT, 1);
}
if (mHasUnsafeInlineCSP) {
Accumulate(Telemetry::CSP_UNSAFE_INLINE_DOCUMENTS_COUNT, 1);
}
if (mHasUnsafeEvalCSP) {
Accumulate(Telemetry::CSP_UNSAFE_EVAL_DOCUMENTS_COUNT, 1);
}
}
}
@@ -2311,7 +2331,7 @@ nsDocument::RemoveDocStyleSheetsFromStyleSets()
void
nsDocument::RemoveStyleSheetsFromStyleSets(
nsTArray<StyleSheetHandle::RefPtr>& aSheets,
const nsTArray<StyleSheetHandle::RefPtr>& aSheets,
SheetType aType)
{
// The stylesheets should forget us
@@ -4151,7 +4171,7 @@ nsDocument::GetStyleSheetAt(int32_t aIndex) const
}
int32_t
nsDocument::GetIndexOfStyleSheet(StyleSheetHandle aSheet) const
nsDocument::GetIndexOfStyleSheet(const StyleSheetHandle aSheet) const
{
return mStyleSheets.IndexOf(aSheet);
}
+3 -2
View File
@@ -777,7 +777,8 @@ public:
*/
virtual int32_t GetNumberOfStyleSheets() const override;
virtual mozilla::StyleSheetHandle GetStyleSheetAt(int32_t aIndex) const override;
virtual int32_t GetIndexOfStyleSheet(mozilla::StyleSheetHandle aSheet) const override;
virtual int32_t GetIndexOfStyleSheet(
const mozilla::StyleSheetHandle aSheet) const override;
virtual void AddStyleSheet(mozilla::StyleSheetHandle aSheet) override;
virtual void RemoveStyleSheet(mozilla::StyleSheetHandle aSheet) override;
@@ -1490,7 +1491,7 @@ protected:
void RemoveDocStyleSheetsFromStyleSets();
void RemoveStyleSheetsFromStyleSets(
nsTArray<mozilla::StyleSheetHandle::RefPtr>& aSheets,
const nsTArray<mozilla::StyleSheetHandle::RefPtr>& aSheets,
mozilla::SheetType aType);
void ResetStylesheetsToURI(nsIURI* aURI);
void FillStyleSet(mozilla::StyleSetHandle aStyleSet);
+4
View File
@@ -12069,6 +12069,10 @@ nsGlobalWindow::OpenInternal(const nsAString& aUrl, const nsAString& aName,
}
}
// XXXbz When this gets fixed to not use LegacyIsCallerNativeCode()
// (indirectly) maybe we can nix the AutoJSAPI usage OnLinkClickEvent::Run.
// But note that if you change this to GetEntryGlobal(), say, then
// OnLinkClickEvent::Run will need a full-blown AutoEntryScript.
const bool checkForPopup = !nsContentUtils::LegacyIsCallerChromeOrNativeCode() &&
!isApp && !aDialog && !WindowExists(aName, !aCalledNoScript);
+57 -4
View File
@@ -633,6 +633,38 @@ public:
mHasMixedDisplayContentBlocked = aHasMixedDisplayContentBlocked;
}
/**
* Set the mixed content object subrequest flag for this document.
*/
void SetHasMixedContentObjectSubrequest(bool aHasMixedContentObjectSubrequest)
{
mHasMixedContentObjectSubrequest = aHasMixedContentObjectSubrequest;
}
/**
* Set CSP flag for this document.
*/
void SetHasCSP(bool aHasCSP)
{
mHasCSP = aHasCSP;
}
/**
* Set unsafe-inline CSP flag for this document.
*/
void SetHasUnsafeInlineCSP(bool aHasUnsafeInlineCSP)
{
mHasUnsafeInlineCSP = aHasUnsafeInlineCSP;
}
/**
* Set unsafe-eval CSP flag for this document.
*/
void SetHasUnsafeEvalCSP(bool aHasUnsafeEvalCSP)
{
mHasUnsafeEvalCSP = aHasUnsafeEvalCSP;
}
/**
* Get tracking content blocked flag for this document.
*/
@@ -979,7 +1011,8 @@ public:
* @param aSheet the sheet to get the index of
* @return aIndex the index of the sheet in the full list
*/
virtual int32_t GetIndexOfStyleSheet(mozilla::StyleSheetHandle aSheet) const = 0;
virtual int32_t GetIndexOfStyleSheet(
const mozilla::StyleSheetHandle aSheet) const = 0;
/**
* Replace the stylesheets in aOldSheets with the stylesheets in
@@ -2742,6 +2775,10 @@ public:
bool InlineScriptAllowedByCSP();
void ReportHasScrollLinkedEffect();
bool HasScrollLinkedEffect() const
{
return mHasScrollLinkedEffect;
}
protected:
bool GetUseCounter(mozilla::UseCounter aUseCounter)
@@ -2907,11 +2944,15 @@ protected:
// True iff we've ever fired a DOMTitleChanged event for this document
bool mHaveFiredTitleChange : 1;
// True iff IsShowing() should be returning true
// State for IsShowing(). mIsShowing starts off false. It becomes true when
// OnPageShow happens and becomes false when OnPageHide happens. So it's false
// before the initial load completes and when we're in bfcache or unloaded,
// true otherwise.
bool mIsShowing : 1;
// True iff the document "page" is not hidden (i.e. currently in the
// bfcache)
// State for IsVisible(). mVisible starts off true. It becomes false when
// OnPageHide happens, and becomes true again when OnPageShow happens. So
// it's false only when we're in bfcache or unloaded.
bool mVisible : 1;
// True if our content viewer has been removed from the docshell
@@ -2969,6 +3010,18 @@ protected:
// True if a document has blocked Mixed Display/Passive Content (see nsMixedContentBlocker.cpp)
bool mHasMixedDisplayContentBlocked : 1;
// True if a document loads a plugin object that attempts to load mixed content subresources through necko(see nsMixedContentBlocker.cpp)
bool mHasMixedContentObjectSubrequest : 1;
// True if a document load has a CSP attached.
bool mHasCSP : 1;
// True if a document load has a CSP with unsafe-eval attached.
bool mHasUnsafeEvalCSP : 1;
// True if a document load has a CSP with unsafe-inline attached.
bool mHasUnsafeInlineCSP : 1;
// True if a document has blocked Tracking Content
bool mHasTrackingContentBlocked : 1;
+1 -1
View File
@@ -1341,7 +1341,7 @@ bool TabParent::RecvDispatchWheelEvent(const mozilla::WidgetWheelEvent& aEvent)
localEvent.widget = widget;
localEvent.refPoint -= GetChildProcessOffset();
widget->DispatchAPZAwareEvent(&localEvent);
widget->DispatchInputEvent(&localEvent);
return true;
}
+56
View File
@@ -86,6 +86,10 @@ MediaFormatReader::Shutdown()
{
MOZ_ASSERT(OnTaskQueue());
if (HasVideo()) {
ReportDroppedFramesTelemetry();
}
mDemuxerInitRequest.DisconnectIfExists();
mMetadataPromise.RejectIfExists(ReadMetadataFailureReason::METADATA_ERROR, __func__);
mSeekPromise.RejectIfExists(NS_ERROR_FAILURE, __func__);
@@ -667,6 +671,7 @@ MediaFormatReader::NotifyNewOutput(TrackType aTrack, MediaData* aSample)
decoder.mOutput.AppendElement(aSample);
decoder.mNumSamplesOutput++;
decoder.mNumSamplesOutputTotal++;
decoder.mNumSamplesOutputTotalSinceTelemetry++;
ScheduleUpdate(aTrack);
}
@@ -910,6 +915,9 @@ MediaFormatReader::HandleDemuxedSamples(TrackType aTrack,
LOG("%s stream id has changed from:%d to:%d, draining decoder.",
TrackTypeToStr(aTrack), decoder.mLastStreamSourceID,
info->GetID());
if (aTrack == TrackType::kVideoTrack) {
ReportDroppedFramesTelemetry();
}
decoder.mNeedDraining = true;
decoder.mNextStreamSourceID = Some(info->GetID());
ScheduleUpdate(aTrack);
@@ -1371,6 +1379,7 @@ MediaFormatReader::OnVideoSkipCompleted(uint32_t aSkipped)
mDecoder->NotifyDecodedFrames(aSkipped, 0, aSkipped);
}
mVideo.mNumSamplesSkippedTotal += aSkipped;
mVideo.mNumSamplesSkippedTotalSinceTelemetry += aSkipped;
MOZ_ASSERT(!mVideo.mError); // We have flushed the decoder, no frame could
// have been decoded (and as such errored)
NotifyDecodingRequested(TrackInfo::kVideoTrack);
@@ -1700,4 +1709,51 @@ MediaFormatReader::GetMozDebugReaderData(nsAString& aString)
aString += NS_ConvertUTF8toUTF16(result);
}
void
MediaFormatReader::ReportDroppedFramesTelemetry()
{
MOZ_ASSERT(OnTaskQueue());
const VideoInfo* info =
mVideo.mInfo ? mVideo.mInfo->GetAsVideoInfo() : &mInfo.mVideo;
if (!info || !mVideo.mDecoder) {
return;
}
nsCString keyPhrase = nsCString("MimeType=");
keyPhrase.Append(info->mMimeType);
keyPhrase.Append("; ");
keyPhrase.Append("Resolution=");
keyPhrase.AppendInt(info->mDisplay.width);
keyPhrase.Append('x');
keyPhrase.AppendInt(info->mDisplay.height);
keyPhrase.Append("; ");
keyPhrase.Append("HardwareAcceleration=");
if (VideoIsHardwareAccelerated()) {
keyPhrase.Append(mVideo.mDecoder->GetDescriptionName());
keyPhrase.Append("enabled");
} else {
keyPhrase.Append("disabled");
}
if (mVideo.mNumSamplesOutputTotalSinceTelemetry) {
uint32_t percentage =
100 * mVideo.mNumSamplesSkippedTotalSinceTelemetry /
mVideo.mNumSamplesOutputTotalSinceTelemetry;
nsCOMPtr<nsIRunnable> task = NS_NewRunnableFunction([=]() -> void {
LOG("Reporting telemetry DROPPED_FRAMES_IN_VIDEO_PLAYBACK");
Telemetry::Accumulate(Telemetry::VIDEO_DETAILED_DROPPED_FRAMES_PROPORTION,
keyPhrase,
percentage);
});
AbstractThread::MainThread()->Dispatch(task.forget());
}
mVideo.mNumSamplesSkippedTotalSinceTelemetry = 0;
mVideo.mNumSamplesOutputTotalSinceTelemetry = 0;
}
} // namespace mozilla
+8
View File
@@ -234,6 +234,8 @@ private:
, mNumSamplesOutput(0)
, mNumSamplesOutputTotal(0)
, mNumSamplesSkippedTotal(0)
, mNumSamplesOutputTotalSinceTelemetry(0)
, mNumSamplesSkippedTotalSinceTelemetry(0)
, mSizeOfQueue(0)
, mIsHardwareAccelerated(false)
, mLastStreamSourceID(UINT32_MAX)
@@ -312,6 +314,9 @@ private:
uint64_t mNumSamplesOutputTotal;
uint64_t mNumSamplesSkippedTotal;
uint64_t mNumSamplesOutputTotalSinceTelemetry;
uint64_t mNumSamplesSkippedTotalSinceTelemetry;
// These get overriden in the templated concrete class.
// Indicate if we have a pending promise for decoded frame.
// Rejecting the promise will stop the reader from decoding ahead.
@@ -465,6 +470,9 @@ private:
{
OnSeekFailed(TrackType::kAudioTrack, aFailure);
}
void ReportDroppedFramesTelemetry();
// Temporary seek information while we wait for the data
Maybe<SeekTarget> mOriginalSeekTarget;
Maybe<media::TimeUnit> mPendingSeekTime;
+3 -1
View File
@@ -236,7 +236,9 @@ MFTDecoder::Output(RefPtr<IMFSample>* aOutput)
// Treat other errors as unexpected, and warn.
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
MOZ_ASSERT(output.pSample);
if (!output.pSample) {
return S_OK;
}
if (mDiscontinuity) {
output.pSample->SetUINT32(MFSampleExtension_Discontinuity, TRUE);
+11 -1
View File
@@ -10,7 +10,7 @@
#include "WMFUtils.h"
#include "nsTArray.h"
#include "TimeUnits.h"
#include "mozilla/Telemetry.h"
#include "mozilla/Logging.h"
extern mozilla::LogModule* GetPDMLog();
@@ -226,6 +226,16 @@ WMFAudioMFTManager::Output(int64_t aStreamOffset,
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
if (!sample) {
LOG("Audio MFTDecoder returned success but null output.");
nsCOMPtr<nsIRunnable> task = NS_NewRunnableFunction([]() -> void {
LOG("Reporting telemetry AUDIO_MFT_OUTPUT_NULL_SAMPLES");
Telemetry::Accumulate(Telemetry::ID::AUDIO_MFT_OUTPUT_NULL_SAMPLES, 1);
});
AbstractThread::MainThread()->Dispatch(task.forget());
return E_FAIL;
}
RefPtr<IMFMediaBuffer> buffer;
hr = sample->ConvertToContiguousBuffer(getter_AddRefs(buffer));
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
@@ -198,4 +198,27 @@ WMFMediaDataDecoder::IsHardwareAccelerated(nsACString& aFailureReason) const {
return mMFTManager && mMFTManager->IsHardwareAccelerated(aFailureReason);
}
nsresult
WMFMediaDataDecoder::ConfigurationChanged(const TrackInfo& aConfig)
{
MOZ_ASSERT(mCallback->OnReaderTaskQueue());
nsCOMPtr<nsIRunnable> runnable =
NS_NewRunnableMethodWithArg<UniquePtr<TrackInfo>&&>(
this,
&WMFMediaDataDecoder::ProcessConfigurationChanged,
aConfig.Clone());
mTaskQueue->Dispatch(runnable.forget());
return NS_OK;
}
void
WMFMediaDataDecoder::ProcessConfigurationChanged(UniquePtr<TrackInfo>&& aConfig)
{
if (mMFTManager) {
mMFTManager->ConfigurationChanged(*aConfig);
}
}
} // namespace mozilla
@@ -52,6 +52,8 @@ public:
virtual TrackInfo::TrackType GetType() = 0;
virtual void ConfigurationChanged(const TrackInfo& aConfig) {}
virtual const char* GetDescriptionName() const = 0;
protected:
@@ -83,6 +85,8 @@ public:
bool IsHardwareAccelerated(nsACString& aFailureReason) const override;
nsresult ConfigurationChanged(const TrackInfo& aConfig) override;
const char* GetDescriptionName() const override
{
return mMFTManager ? mMFTManager->GetDescriptionName() : "";
@@ -108,6 +112,10 @@ private:
void ProcessShutdown();
// Called on the task queue. Tell the MFT that the next Input will have a
// different configuration (typically resolution change).
void ProcessConfigurationChanged(UniquePtr<TrackInfo>&& aConfig);
RefPtr<FlushableTaskQueue> mTaskQueue;
MediaDataDecoderCallback* mCallback;
+3 -9
View File
@@ -39,7 +39,7 @@ HNsToFrames(int64_t aHNs, uint32_t aRate, int64_t* aOutFrames)
}
HRESULT
GetDefaultStride(IMFMediaType *aType, uint32_t* aOutStride)
GetDefaultStride(IMFMediaType *aType, uint32_t aWidth, uint32_t* aOutStride)
{
// Try to get the default stride from the media type.
HRESULT hr = aType->GetUINT32(MF_MT_DEFAULT_STRIDE, aOutStride);
@@ -49,16 +49,11 @@ GetDefaultStride(IMFMediaType *aType, uint32_t* aOutStride)
// Stride attribute not set, calculate it.
GUID subtype = GUID_NULL;
uint32_t width = 0;
uint32_t height = 0;
hr = aType->GetGUID(MF_MT_SUBTYPE, &subtype);
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
hr = MFGetAttributeSize(aType, MF_MT_FRAME_SIZE, &width, &height);
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
hr = wmf::MFGetStrideForBitmapInfoHeader(subtype.Data1, width, (LONG*)(aOutStride));
hr = wmf::MFGetStrideForBitmapInfoHeader(subtype.Data1, aWidth, (LONG*)(aOutStride));
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
return hr;
@@ -188,7 +183,7 @@ LoadDLLs()
#define ENSURE_FUNCTION_PTR_HELPER(FunctionType, FunctionName, DLL) \
static FunctionType FunctionName##Ptr = nullptr; \
if (!FunctionName##Ptr) { \
FunctionName##Ptr = (FunctionType) GetProcAddress(GetModuleHandleW(L#DLL), #FunctionName); \
FunctionName##Ptr = (FunctionType) GetProcAddress(GetModuleHandleW(L ## #DLL), #FunctionName); \
if (!FunctionName##Ptr) { \
NS_WARNING("Failed to get GetProcAddress of " #FunctionName " from " #DLL); \
return E_FAIL; \
@@ -282,7 +277,6 @@ MFCreateAlignedMemoryBuffer(DWORD cbMaxLength,
HRESULT
MFCreateDXGIDeviceManager(UINT *pResetToken, IMFDXGIDeviceManager **ppDXVAManager)
{
DECL_FUNCTION_PTR(MFCreateDXGIDeviceManager, UINT*, IMFDXGIDeviceManager**);
ENSURE_FUNCTION_PTR(MFCreateDXGIDeviceManager, mfplat.dll)
return (MFCreateDXGIDeviceManagerPtr)(pResetToken, ppDXVAManager);
}
+1 -1
View File
@@ -37,7 +37,7 @@ HRESULT
HNsToFrames(int64_t aHNs, uint32_t aRate, int64_t* aOutFrames);
HRESULT
GetDefaultStride(IMFMediaType *aType, uint32_t* aOutStride);
GetDefaultStride(IMFMediaType *aType, uint32_t aWidth, uint32_t* aOutStride);
int32_t
MFOffsetToInt32(const MFOffset& aOffset);
+95 -72
View File
@@ -21,6 +21,7 @@
#include "IMFYCbCrImage.h"
#include "mozilla/WindowsVersion.h"
#include "mozilla/Preferences.h"
#include "mozilla/Telemetry.h"
#include "nsPrintfCString.h"
extern mozilla::LogModule* GetPDMLog();
@@ -70,9 +71,14 @@ WMFVideoMFTManager::WMFVideoMFTManager(
mozilla::layers::LayersBackend aLayersBackend,
mozilla::layers::ImageContainer* aImageContainer,
bool aDXVAEnabled)
: mImageContainer(aImageContainer)
: mVideoInfo(aConfig)
, mVideoStride(0)
, mImageContainer(aImageContainer)
, mDXVAEnabled(aDXVAEnabled)
, mLayersBackend(aLayersBackend)
, mNullOutputCount(0)
, mGotValidOutputAfterNullOutput(false)
, mGotExcessiveNullOutput(false)
// mVideoStride, mVideoWidth, mVideoHeight, mUseHwAccel are initialized in
// Init().
{
@@ -98,6 +104,20 @@ WMFVideoMFTManager::~WMFVideoMFTManager()
if (mDXVA2Manager) {
DeleteOnMainThread(mDXVA2Manager);
}
// Record whether the video decoder successfully decoded, or output null
// samples but did/didn't recover.
uint32_t telemetry = (mNullOutputCount == 0) ? 0 :
(mGotValidOutputAfterNullOutput && mGotExcessiveNullOutput) ? 1 :
mGotExcessiveNullOutput ? 2 :
mGotValidOutputAfterNullOutput ? 3 :
4;
nsCOMPtr<nsIRunnable> task = NS_NewRunnableFunction([=]() -> void {
LOG(nsPrintfCString("Reporting telemetry VIDEO_MFT_OUTPUT_NULL_SAMPLES=%d", telemetry).get());
Telemetry::Accumulate(Telemetry::ID::VIDEO_MFT_OUTPUT_NULL_SAMPLES, telemetry);
});
AbstractThread::MainThread()->Dispatch(task.forget());
}
const GUID&
@@ -150,8 +170,6 @@ public:
bool
WMFVideoMFTManager::InitializeDXVA(bool aForceD3D9)
{
MOZ_ASSERT(!mDXVA2Manager);
// If we use DXVA but aren't running with a D3D layer manager then the
// readback of decoded video frames from GPU to CPU memory grinds painting
// to a halt, and makes playback performance *worse*.
@@ -159,6 +177,7 @@ WMFVideoMFTManager::InitializeDXVA(bool aForceD3D9)
mDXVAFailureReason.AssignLiteral("Hardware video decoding disabled or blacklisted");
return false;
}
MOZ_ASSERT(!mDXVA2Manager);
if (mLayersBackend != LayersBackend::LAYERS_D3D9 &&
mLayersBackend != LayersBackend::LAYERS_D3D11) {
mDXVAFailureReason.AssignLiteral("Unsupported layers backend");
@@ -250,13 +269,6 @@ WMFVideoMFTManager::InitInternal(bool aForceD3D9)
LOG("Video Decoder initialized, Using DXVA: %s", (mUseHwAccel ? "Yes" : "No"));
// Just in case ConfigureVideoFrameGeometry() does not set these
mVideoInfo = VideoInfo();
mVideoStride = 0;
mVideoWidth = 0;
mVideoHeight = 0;
mPictureRegion.SetEmpty();
return true;
}
@@ -323,36 +335,19 @@ WMFVideoMFTManager::Input(MediaRawData* aSample)
// This code tests if the given resolution can be supported directly on the GPU,
// and makes sure we only ask the MFT for DXVA if it can be supported properly.
bool
WMFVideoMFTManager::MaybeToggleDXVA(IMFMediaType* aType)
WMFVideoMFTManager::CanUseDXVA(IMFMediaType* aType)
{
MOZ_ASSERT(mDXVA2Manager);
// SupportsConfig only checks for valid h264 decoders currently.
if (!mDXVA2Manager || mStreamType != H264) {
return false;
if (mStreamType != H264) {
return true;
}
// Assume the current samples duration is representative for the
// entire video.
float framerate = 1000000.0 / mLastDuration;
if (mDXVA2Manager->SupportsConfig(aType, framerate)) {
if (!mUseHwAccel) {
// DXVA disabled, but supported for this resolution
ULONG_PTR manager = ULONG_PTR(mDXVA2Manager->GetDXVADeviceManager());
HRESULT hr = mDecoder->SendMFTMessage(MFT_MESSAGE_SET_D3D_MANAGER, manager);
if (SUCCEEDED(hr)) {
mUseHwAccel = true;
return true;
}
}
} else if (mUseHwAccel) {
// DXVA enabled, and not supported for this resolution
HRESULT hr = mDecoder->SendMFTMessage(MFT_MESSAGE_SET_D3D_MANAGER, 0);
MOZ_ASSERT(SUCCEEDED(hr), "Attempting to fall back to software failed?");
mUseHwAccel = false;
return true;
}
return false;
return mDXVA2Manager->SupportsConfig(aType, framerate);
}
HRESULT
@@ -366,14 +361,14 @@ WMFVideoMFTManager::ConfigureVideoFrameGeometry()
// change then we need to renegotiate our media types,
// and resubmit our previous frame (since the MFT appears
// to lose it otherwise).
if (MaybeToggleDXVA(mediaType)) {
hr = SetDecoderMediaTypes();
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
HRESULT hr = mDecoder->GetOutputMediaType(mediaType);
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
if (mUseHwAccel && !CanUseDXVA(mediaType)) {
mDXVAEnabled = false;
if (!Init()) {
return E_FAIL;
}
mDecoder->Input(mLastInput);
return S_OK;
}
// Verify that the video subtype is what we expect it to be.
@@ -387,26 +382,17 @@ WMFVideoMFTManager::ConfigureVideoFrameGeometry()
NS_ENSURE_TRUE(videoFormat == MFVideoFormat_NV12 || !mUseHwAccel, E_FAIL);
NS_ENSURE_TRUE(videoFormat == MFVideoFormat_YV12 || mUseHwAccel, E_FAIL);
nsIntRect pictureRegion;
hr = GetPictureRegion(mediaType, pictureRegion);
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
UINT32 width = 0, height = 0;
hr = MFGetAttributeSize(mediaType, MF_MT_FRAME_SIZE, &width, &height);
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
uint32_t aspectNum = 0, aspectDenom = 0;
hr = MFGetAttributeRatio(mediaType,
MF_MT_PIXEL_ASPECT_RATIO,
&aspectNum,
&aspectDenom);
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
mVideoInfo.mImage.width = width;
mVideoInfo.mImage.height = height;
nsIntRect pictureRegion = mVideoInfo.mImage;
// Calculate and validate the picture region and frame dimensions after
// scaling by the pixel aspect ratio.
nsIntSize frameSize = nsIntSize(width, height);
nsIntSize displaySize = nsIntSize(pictureRegion.width, pictureRegion.height);
ScaleDisplayByAspectRatio(displaySize, float(aspectNum) / float(aspectDenom));
nsIntSize displaySize = nsIntSize(mVideoInfo.mDisplay.width, mVideoInfo.mDisplay.height);
if (!IsValidVideoRegion(frameSize, pictureRegion, displaySize)) {
// Video track's frame sizes will overflow. Ignore the video track.
return E_FAIL;
@@ -418,18 +404,13 @@ WMFVideoMFTManager::ConfigureVideoFrameGeometry()
}
// Success! Save state.
mVideoInfo.mDisplay = displaySize;
GetDefaultStride(mediaType, &mVideoStride);
mVideoWidth = width;
mVideoHeight = height;
mPictureRegion = pictureRegion;
GetDefaultStride(mediaType, width, &mVideoStride);
LOG("WMFVideoMFTManager frame geometry frame=(%u,%u) stride=%u picture=(%d, %d, %d, %d) display=(%d,%d) PAR=%d:%d",
LOG("WMFVideoMFTManager frame geometry frame=(%u,%u) stride=%u picture=(%d, %d, %d, %d) display=(%d,%d)",
width, height,
mVideoStride,
mPictureRegion.x, mPictureRegion.y, mPictureRegion.width, mPictureRegion.height,
displaySize.width, displaySize.height,
aspectNum, aspectDenom);
pictureRegion.x, pictureRegion.y, pictureRegion.width, pictureRegion.height,
mVideoInfo.mDisplay.width, mVideoInfo.mDisplay.height);
return S_OK;
}
@@ -471,25 +452,28 @@ WMFVideoMFTManager::CreateBasicVideoFrame(IMFSample* aSample,
// i.e., Y, then V, then U.
VideoData::YCbCrBuffer b;
uint32_t videoWidth = mVideoInfo.mImage.width;
uint32_t videoHeight = mVideoInfo.mImage.height;
// Y (Y') plane
b.mPlanes[0].mData = data;
b.mPlanes[0].mStride = stride;
b.mPlanes[0].mHeight = mVideoHeight;
b.mPlanes[0].mWidth = mVideoWidth;
b.mPlanes[0].mHeight = videoHeight;
b.mPlanes[0].mWidth = videoWidth;
b.mPlanes[0].mOffset = 0;
b.mPlanes[0].mSkip = 0;
// The V and U planes are stored 16-row-aligned, so we need to add padding
// to the row heights to ensure the Y'CbCr planes are referenced properly.
uint32_t padding = 0;
if (mVideoHeight % 16 != 0) {
padding = 16 - (mVideoHeight % 16);
if (videoHeight % 16 != 0) {
padding = 16 - (videoHeight % 16);
}
uint32_t y_size = stride * (mVideoHeight + padding);
uint32_t v_size = stride * (mVideoHeight + padding) / 4;
uint32_t y_size = stride * (videoHeight + padding);
uint32_t v_size = stride * (videoHeight + padding) / 4;
uint32_t halfStride = (stride + 1) / 2;
uint32_t halfHeight = (mVideoHeight + 1) / 2;
uint32_t halfWidth = (mVideoWidth + 1) / 2;
uint32_t halfHeight = (videoHeight + 1) / 2;
uint32_t halfWidth = (videoWidth + 1) / 2;
// U plane (Cb)
b.mPlanes[1].mData = data + y_size + v_size;
@@ -518,7 +502,7 @@ WMFVideoMFTManager::CreateBasicVideoFrame(IMFSample* aSample,
VideoData::SetVideoDataToImage(image,
mVideoInfo,
b,
mPictureRegion,
mVideoInfo.mImage,
false);
RefPtr<VideoData> v =
@@ -530,7 +514,7 @@ WMFVideoMFTManager::CreateBasicVideoFrame(IMFSample* aSample,
image.forget(),
false,
-1,
mPictureRegion);
mVideoInfo.mImage);
v.forget(aOutVideoData);
return S_OK;
@@ -551,7 +535,7 @@ WMFVideoMFTManager::CreateD3DVideoFrame(IMFSample* aSample,
RefPtr<Image> image;
hr = mDXVA2Manager->CopyToImage(aSample,
mPictureRegion,
mVideoInfo.mImage,
mImageContainer,
getter_AddRefs(image));
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
@@ -569,7 +553,7 @@ WMFVideoMFTManager::CreateD3DVideoFrame(IMFSample* aSample,
image.forget(),
false,
-1,
mPictureRegion);
mVideoInfo.mImage);
NS_ENSURE_TRUE(v, E_FAIL);
v.forget(aOutVideoData);
@@ -610,6 +594,23 @@ WMFVideoMFTManager::Output(int64_t aStreamOffset,
continue;
}
if (SUCCEEDED(hr)) {
if (!sample) {
LOG("Video MFTDecoder returned success but no output!");
// On some machines/input the MFT returns success but doesn't output
// a video frame. If we detect this, try again, but only up to a
// point; after 250 failures, give up. Note we count all failures
// over the life of the decoder, as we may end up exiting with a
// NEED_MORE_INPUT and coming back to hit the same error. So just
// counting with a local variable (like typeChangeCount does) may
// not work in this situation.
++mNullOutputCount;
if (mNullOutputCount > 250) {
LOG("Excessive Video MFTDecoder returning success but no output; giving up");
mGotExcessiveNullOutput = true;
return E_FAIL;
}
continue;
}
break;
}
// Else unexpected error, assert, and bail.
@@ -630,6 +631,10 @@ WMFVideoMFTManager::Output(int64_t aStreamOffset,
aOutData = frame;
if (mNullOutputCount) {
mGotValidOutputAfterNullOutput = true;
}
return S_OK;
}
@@ -647,4 +652,22 @@ WMFVideoMFTManager::IsHardwareAccelerated(nsACString& aFailureReason) const
return mDecoder && mUseHwAccel;
}
const char*
WMFVideoMFTManager::GetDescriptionName() const
{
if (mDecoder && mUseHwAccel && mDXVA2Manager) {
return (mDXVA2Manager->IsD3D11()) ?
"D3D11 Hardware Decoder" : "D3D9 Hardware Decoder";
} else {
return "wmf software video decoder";
}
}
void
WMFVideoMFTManager::ConfigurationChanged(const TrackInfo& aConfig)
{
MOZ_ASSERT(aConfig.GetAsVideoInfo());
mVideoInfo = *aConfig.GetAsVideoInfo();
}
} // namespace mozilla
+9 -11
View File
@@ -39,12 +39,9 @@ public:
return TrackInfo::kVideoTrack;
}
const char* GetDescriptionName() const override
{
nsCString failureReason;
return IsHardwareAccelerated(failureReason)
? "wmf hardware video decoder" : "wmf software video decoder";
}
void ConfigurationChanged(const TrackInfo& aConfig) override;
const char* GetDescriptionName() const override;
private:
@@ -64,14 +61,11 @@ private:
HRESULT SetDecoderMediaTypes();
bool MaybeToggleDXVA(IMFMediaType* aType);
bool CanUseDXVA(IMFMediaType* aType);
// Video frame geometry.
VideoInfo mVideoInfo;
uint32_t mVideoStride;
uint32_t mVideoWidth;
uint32_t mVideoHeight;
nsIntRect mPictureRegion;
RefPtr<layers::ImageContainer> mImageContainer;
nsAutoPtr<DXVA2Manager> mDXVA2Manager;
@@ -79,7 +73,7 @@ private:
RefPtr<IMFSample> mLastInput;
float mLastDuration;
const bool mDXVAEnabled;
bool mDXVAEnabled;
const layers::LayersBackend mLayersBackend;
bool mUseHwAccel;
@@ -96,6 +90,10 @@ private:
const GUID& GetMFTGUID();
const GUID& GetMediaSubtypeGUID();
uint32_t mNullOutputCount;
bool mGotValidOutputAfterNullOutput;
bool mGotExcessiveNullOutput;
};
} // namespace mozilla
-3
View File
@@ -122,9 +122,6 @@ TCPServerSocket::Close()
void
TCPServerSocket::FireEvent(const nsAString& aType, TCPSocket* aSocket)
{
AutoJSAPI api;
api.Init(GetOwnerGlobal());
TCPServerSocketEventInit init;
init.mBubbles = false;
init.mCancelable = false;
+3
View File
@@ -626,6 +626,9 @@ nsCSPContext::SetRequestContext(nsIDOMDocument* aDOMDocument,
// console messages until it becomes available, see flushConsoleMessages
mQueueUpMessages = !mInnerWindowID;
mCallingChannelLoadGroup = doc->GetDocumentLoadGroup();
// set the flag on the document for CSP telemetry
doc->SetHasCSP(true);
}
else {
NS_WARNING("No Document in SetRequestContext; can not query loadgroup; sending reports may fail.");
+4
View File
@@ -81,6 +81,10 @@ class nsCSPContext : public nsIContentSecurityPolicy
mLoadingPrincipal = nullptr;
}
nsWeakPtr GetLoadingContext(){
return mLoadingContext;
}
private:
bool permitsInternal(CSPDirective aDir,
nsIURI* aContentLocation,
+8
View File
@@ -578,6 +578,10 @@ nsCSPParser::keywordSource()
}
if (CSP_IsKeyword(mCurToken, CSP_UNSAFE_INLINE)) {
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mCSPContext->GetLoadingContext());
if (doc) {
doc->SetHasUnsafeInlineCSP(true);
}
// make sure script-src only contains 'unsafe-inline' once;
// ignore duplicates and log warning
if (mUnsafeInlineKeywordSrc) {
@@ -593,6 +597,10 @@ nsCSPParser::keywordSource()
}
if (CSP_IsKeyword(mCurToken, CSP_UNSAFE_EVAL)) {
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mCSPContext->GetLoadingContext());
if (doc) {
doc->SetHasUnsafeEvalCSP(true);
}
return new nsCSPKeywordSrc(CSP_KeywordToEnum(mCurToken));
}
return nullptr;
+5
View File
@@ -799,6 +799,11 @@ nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect,
}
}
// set hasMixedContentObjectSubrequest on this object if necessary
if (aContentType == TYPE_OBJECT_SUBREQUEST) {
rootDoc->SetHasMixedContentObjectSubrequest(true);
}
// If the content is display content, and the pref says display content should be blocked, block it.
if (sBlockMixedDisplay && classification == eMixedDisplay) {
if (allowMixedContent) {
@@ -37,5 +37,6 @@ if CONFIG['MOZ_XUL']:
FINAL_LIBRARY = 'xul'
# For nsJSUtils
LOCAL_INCLUDES += [
'/docshell/base',
'/dom/base',
]
@@ -18,6 +18,7 @@
#include "nsJSUtils.h"
#include "plstr.h"
#include "nsDocShell.h"
#include "nsIBaseWindow.h"
#include "nsIBrowserDOMWindow.h"
#include "nsIDocShell.h"
@@ -81,6 +82,7 @@ struct nsWatcherWindowEntry
{
nsWatcherWindowEntry(nsIDOMWindow* aWindow, nsIWebBrowserChrome* aChrome)
: mChrome(nullptr)
{
#ifdef USEWEAKREFS
mWindow = do_GetWeakReference(aWindow);
@@ -451,6 +453,36 @@ nsWindowWatcher::OpenWindow2(nsIDOMWindow* aParent,
aResult);
}
// This static function checks if the aDocShell uses an UserContextId equal to
// nsIScriptSecurityManager::DEFAULT_USER_CONTEXT_ID or equal to the
// userContextId of subjectPrincipal, if not null.
static bool
CheckUserContextCompatibility(nsIDocShell* aDocShell)
{
MOZ_ASSERT(aDocShell);
uint32_t userContextId =
static_cast<nsDocShell*>(aDocShell)->GetOriginAttributes().mUserContextId;
if (userContextId == nsIScriptSecurityManager::DEFAULT_USER_CONTEXT_ID) {
return true;
}
nsCOMPtr<nsIPrincipal> subjectPrincipal =
nsContentUtils::GetCurrentJSContext()
? nsContentUtils::SubjectPrincipal() : nullptr;
if (!subjectPrincipal) {
return false;
}
uint32_t principalUserContextId;
nsresult rv = subjectPrincipal->GetUserContextId(&principalUserContextId);
NS_ENSURE_SUCCESS(rv, false);
return principalUserContextId == userContextId;
}
nsresult
nsWindowWatcher::OpenWindowInternal(nsIDOMWindow* aParent,
const char* aUrl,
@@ -606,6 +638,9 @@ nsWindowWatcher::OpenWindowInternal(nsIDOMWindow* aParent,
bool isCallerChrome =
nsContentUtils::LegacyIsCallerChromeOrNativeCode() && !openedFromRemoteTab;
// XXXbz Why is an AutoJSAPI good enough here? Wouldn't AutoEntryScript (so
// we affect the entry global) make more sense? Or do we just want to affect
// GetSubjectPrincipal()?
dom::AutoJSAPI jsapiChromeGuard;
bool windowTypeIsChrome =
@@ -692,6 +727,19 @@ nsWindowWatcher::OpenWindowInternal(nsIDOMWindow* aParent,
do_QueryInterface(newDocShellItem);
webNav->Stop(nsIWebNavigation::STOP_NETWORK);
}
// If this is a new window, but it's incompatible with the current
// userContextId, we ignore it and we pretend that nothing has been
// returned by ProvideWindow.
if (!windowIsNew && newDocShellItem) {
nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(newDocShellItem);
if (!CheckUserContextCompatibility(docShell)) {
newWindow = nullptr;
newDocShellItem = nullptr;
windowIsNew = false;
}
}
} else if (rv == NS_ERROR_ABORT) {
// NS_ERROR_ABORT means the window provider has flat-out rejected
// the open-window call and we should bail. Don't return an error
@@ -983,6 +1031,18 @@ nsWindowWatcher::OpenWindowInternal(nsIDOMWindow* aParent,
}
}
// If this is a new window, we must set the userContextId from the
// subjectPrincipal.
if (windowIsNew && subjectPrincipal) {
uint32_t userContextId;
rv = subjectPrincipal->GetUserContextId(&userContextId);
NS_ENSURE_SUCCESS(rv, rv);
auto* docShell = static_cast<nsDocShell*>(newDocShell.get());
docShell->SetUserContextId(userContextId);
}
if (isNewToplevelWindow) {
// Notify observers that the window is open and ready.
// The window has not yet started to load a document.
@@ -993,6 +1053,10 @@ nsWindowWatcher::OpenWindowInternal(nsIDOMWindow* aParent,
}
}
// Before loading the URI we want to be 100% sure that we use the correct
// userContextId.
MOZ_ASSERT(CheckUserContextCompatibility(newDocShell));
if (uriToLoad && aNavigate) {
newDocShell->LoadURI(
uriToLoad,
@@ -1628,7 +1692,7 @@ nsWindowWatcher::CalculateChromeFlags(nsIDOMWindow* aParent,
}
}
if (aDialog && !presenceFlag) {
if (aDialog && aFeaturesSpecified && !presenceFlag) {
chromeFlags = nsIWebBrowserChrome::CHROME_DEFAULT;
}
@@ -2140,8 +2204,14 @@ nsWindowWatcher::SizeOpenedDocShellItem(nsIDocShellTreeItem* aDocShellItem,
int32_t winWidth = width + (sizeChromeWidth ? 0 : chromeWidth),
winHeight = height + (sizeChromeHeight ? 0 : chromeHeight);
screen->GetAvailRectDisplayPix(&screenLeft, &screenTop, &screenWidth,
&screenHeight);
// Get screen dimensions (in device pixels)
screen->GetAvailRect(&screenLeft, &screenTop, &screenWidth,
&screenHeight);
// Convert them to CSS pixels
screenLeft = NSToIntRound(screenLeft / scale);
screenTop = NSToIntRound(screenTop / scale);
screenWidth = NSToIntRound(screenWidth / scale);
screenHeight = NSToIntRound(screenHeight / scale);
if (aSizeSpec.SizeSpecified()) {
/* Unlike position, force size out-of-bounds check only if
+5 -1
View File
@@ -2083,6 +2083,7 @@ _cairo_surface_paint (cairo_surface_t *surface,
cairo_clip_t *clip)
{
cairo_status_t status;
cairo_rectangle_int_t extents;
if (unlikely (surface->status))
return surface->status;
@@ -2114,7 +2115,10 @@ _cairo_surface_paint (cairo_surface_t *surface,
status = _cairo_surface_fallback_paint (surface, op, source, clip);
FINISH:
surface->is_clear = op == CAIRO_OPERATOR_CLEAR && clip == NULL;
surface->is_clear = op == CAIRO_OPERATOR_CLEAR &&
(clip == NULL ||
(_cairo_surface_get_extents (surface, &extents) &&
_cairo_clip_contains_rectangle (clip, &extents)));
return _cairo_surface_set_error (surface, status);
}
+5
View File
@@ -9,6 +9,7 @@
#include "Units.h" // for ScreenPoint
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
#include "mozilla/RefPtr.h" // for already_AddRefed, RefCounted
#include "mozilla/gfx/2D.h" // for DrawTarget
#include "mozilla/gfx/MatrixFwd.h" // for Matrix4x4
#include "mozilla/gfx/Point.h" // for IntSize, Point
#include "mozilla/gfx/Rect.h" // for Rect, IntRect
@@ -363,10 +364,14 @@ public:
* If aRenderBoundsOut is non-null, it will be set to the render bounds
* actually used by the compositor in window space. If aRenderBoundsOut
* is returned empty, composition should be aborted.
*
* If aOpaque is true, then all of aInvalidRegion will be drawn to with
* opaque content.
*/
virtual void BeginFrame(const nsIntRegion& aInvalidRegion,
const gfx::Rect* aClipRectIn,
const gfx::Rect& aRenderBounds,
bool aOpaque,
gfx::Rect* aClipRectOut = nullptr,
gfx::Rect* aRenderBoundsOut = nullptr) = 0;
+1 -2
View File
@@ -230,8 +230,7 @@ MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(OpenMode)
// We rely on the items in this enum being sequential
enum class MaskType : uint8_t {
MaskNone = 0, // no mask layer
Mask2d, // mask layer for layers with 2D transforms
Mask3d, // mask layer for layers with 3D transforms
Mask, // mask layer
NumMaskTypes
};
+1
View File
@@ -18,6 +18,7 @@
#include "mozilla/gfx/BaseSize.h" // for BaseSize
#include "mozilla/gfx/Tools.h"
#include "mozilla/gfx/Point.h" // for IntSize
#include "mozilla/layers/AsyncCanvasRenderer.h"
#include "mozilla/layers/PersistentBufferProvider.h"
#include "nsDebug.h" // for NS_ASSERTION, NS_WARNING, etc
#include "nsISupportsImpl.h" // for gfxContext::AddRef, etc
-4
View File
@@ -34,10 +34,6 @@ EffectMask::PrintInfo(std::stringstream& aStream, const char* aPrefix)
aStream << nsPrintfCString("EffectMask (0x%p)", this).get();
AppendToString(aStream, mSize, " [size=", "]");
AppendToString(aStream, mMaskTransform, " [mask-transform=", "]");
if (mIs3D) {
aStream << " [is-3d]";
}
}
void
-2
View File
@@ -85,7 +85,6 @@ struct EffectMask : public Effect
const gfx::Matrix4x4 &aMaskTransform)
: Effect(EffectTypes::MASK)
, mMaskTexture(aMaskTexture)
, mIs3D(false)
, mSize(aSize)
, mMaskTransform(aMaskTransform)
{}
@@ -93,7 +92,6 @@ struct EffectMask : public Effect
virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix);
TextureSource* mMaskTexture;
bool mIs3D;
gfx::IntSize mSize;
gfx::Matrix4x4 mMaskTransform;
};
+6
View File
@@ -234,6 +234,12 @@ public:
mDoSmoothScroll = aOther.mDoSmoothScroll;
}
void UpdateScrollInfo(uint32_t aScrollGeneration, const CSSPoint& aScrollOffset)
{
mScrollOffset = aScrollOffset;
mScrollGeneration = aScrollGeneration;
}
// Make a copy of this FrameMetrics object which does not have any pointers
// to heap-allocated memory (i.e. is Plain Old Data, or 'POD'), and is
// therefore safe to be placed into shared memory.
+1
View File
@@ -13,6 +13,7 @@
#include "mozilla/RefPtr.h" // for already_AddRefed
#include "mozilla/gfx/Point.h" // for IntSize
#include "mozilla/gfx/Types.h" // for SurfaceFormat
#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor
namespace mozilla {
namespace gfx {
-1
View File
@@ -1202,7 +1202,6 @@ SenderHelper::SendMaskEffect(GLContext* aGLContext,
// Expose packet creation here, so we could dump secondary mask effect attributes.
auto packet = MakeUnique<layerscope::Packet>();
TexturePacket::EffectMask* mask = packet->mutable_texture()->mutable_mask();
mask->set_mis3d(aEffect->mIs3D);
mask->mutable_msize()->set_w(aEffect->mSize.width);
mask->mutable_msize()->set_h(aEffect->mSize.height);
auto element = reinterpret_cast<const Float *>(&(aEffect->mMaskTransform));
+3
View File
@@ -9,6 +9,7 @@
#include <stdint.h>
#include <mozilla/UniquePtr.h>
#include "gfxMatrix.h"
namespace mozilla {
@@ -16,10 +17,12 @@ namespace gl { class GLContext; }
namespace layers {
namespace layerscope { class Packet; }
struct EffectChain;
class LayerComposite;
class TextureHost;
class LayerScope {
public:
+1 -5
View File
@@ -1466,11 +1466,7 @@ ContainerLayer::DefaultComputeEffectiveTransforms(const Matrix4x4& aTransformToS
ComputeEffectiveTransformsForChildren(idealTransform);
}
if (idealTransform.CanDraw2D()) {
ComputeEffectiveTransformForMaskLayers(aTransformToSurface);
} else {
ComputeEffectiveTransformForMaskLayers(Matrix4x4());
}
ComputeEffectiveTransformForMaskLayers(aTransformToSurface);
}
void
+71 -28
View File
@@ -7,6 +7,7 @@
#include "APZCTreeManager.h"
#include "AsyncPanZoomController.h"
#include "Compositor.h" // for Compositor
#include "DragTracker.h" // for DragTracker
#include "gfxPrefs.h" // for gfxPrefs
#include "HitTestingTreeNode.h" // for HitTestingTreeNode
#include "InputBlockState.h" // for InputBlockState
@@ -138,7 +139,7 @@ APZCTreeManager::UpdateHitTestingTree(CompositorBridgeParent* aCompositor,
{
APZThreadUtils::AssertOnCompositorThread();
MonitorAutoLock lock(mTreeLock);
MutexAutoLock lock(mTreeLock);
// For testing purposes, we log some data to the APZTestData associated with
// the layers id that originated this update.
@@ -492,6 +493,10 @@ APZCTreeManager::PrepareNodeForLayer(const LayerMetricsWrapper& aLayer,
aState.mPaintLogger.LogTestData(aMetrics.GetScrollId(),
"parentScrollId", apzc->GetParent()->GetGuid().mScrollId);
}
if (aMetrics.IsRootContent()) {
aState.mPaintLogger.LogTestData(aMetrics.GetScrollId(),
"isRootContent", true);
}
}
if (newApzc) {
@@ -614,10 +619,6 @@ WillHandleWheelEvent(WidgetWheelEvent* aEvent)
static bool
WillHandleMouseEvent(const WidgetMouseEventBase& aEvent)
{
if (!gfxPrefs::APZDragEnabled()) {
return false;
}
return aEvent.mMessage == eMouseMove ||
aEvent.mMessage == eMouseDown ||
aEvent.mMessage == eMouseUp;
@@ -666,14 +667,22 @@ APZCTreeManager::ReceiveInputEvent(InputData& aEvent,
switch (aEvent.mInputType) {
case MULTITOUCH_INPUT: {
MultiTouchInput& touchInput = aEvent.AsMultiTouchInput();
touchInput.mHandledByAPZ = true;
result = ProcessTouchInput(touchInput, aOutTargetGuid, aOutInputBlockId);
break;
} case MOUSE_INPUT: {
MouseInput& mouseInput = aEvent.AsMouseInput();
if (DragTracker::StartsDrag(mouseInput)) {
// If this is the start of a drag we need to unambiguously know if it's
// going to land on a scrollbar or not. We can't apply an untransform
// here without knowing that, so we need to ensure the untransform is
// a no-op.
FlushRepaintsToClearScreenToGeckoTransform();
}
bool hitScrollbar = false;
RefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(mouseInput.mOrigin,
&hitResult);
&hitResult, &hitScrollbar);
// When the mouse is outside the window we still want to handle dragging
// but we won't find an APZC. Fallback to root APZC then.
@@ -687,15 +696,36 @@ APZCTreeManager::ReceiveInputEvent(InputData& aEvent,
/* aTargetConfirmed = */ false,
mouseInput, aOutInputBlockId);
if (result == nsEventStatus_eConsumeDoDefault) {
// This input event is part of a drag block, so whether or not it is
// directed at a scrollbar depends on whether the drag block started
// on a scrollbar.
hitScrollbar = mInputQueue->IsDragOnScrollbar(hitScrollbar);
}
// Update the out-parameters so they are what the caller expects.
apzc->GetGuid(aOutTargetGuid);
// TODO Dagging on a scrollbar probably behaves differently from
// the other input types in that the gecko coordinates are the same
// as the screen coordinates even though the async transform on the APZC
// is changing. I'm not really sure at this point and it'll take some
// though to figure out properly.
//mouseInput.mOrigin = untransformedOrigin;
if (!hitScrollbar) {
// The input was not targeted at a scrollbar, so we untransform it
// like we do for other content. Scrollbars are "special" because they
// have special handling in AsyncCompositionManager when resolution is
// applied. TODO: we should find a better way to deal with this.
ScreenToParentLayerMatrix4x4 transformToApzc = GetScreenToApzcTransform(apzc);
ParentLayerToScreenMatrix4x4 transformToGecko = GetApzcToGeckoTransform(apzc);
ScreenToScreenMatrix4x4 outTransform = transformToApzc * transformToGecko;
Maybe<ScreenPoint> untransformedRefPoint = UntransformBy(
outTransform, mouseInput.mOrigin);
if (untransformedRefPoint) {
mouseInput.mOrigin = *untransformedRefPoint;
}
} else {
// Likewise, if the input was targeted at a scrollbar, we don't want to
// apply the callback transform in the main thread, so we remove the
// scrollid from the guid. We need to keep the layersId intact so
// that the response from the child process doesn't get discarded.
aOutTargetGuid->mScrollId = FrameMetrics::NULL_SCROLL_ID;
}
}
break;
} case SCROLLWHEEL_INPUT: {
@@ -865,6 +895,7 @@ APZCTreeManager::ProcessTouchInput(MultiTouchInput& aInput,
ScrollableLayerGuid* aOutTargetGuid,
uint64_t* aOutInputBlockId)
{
aInput.mHandledByAPZ = true;
if (aInput.mType == MultiTouchInput::MULTITOUCH_START) {
// If we are panned into overscroll and a second finger goes down,
// ignore that second touch point completely. The touch-start for it is
@@ -1125,6 +1156,7 @@ APZCTreeManager::ReceiveInputEvent(WidgetInputEvent& aEvent,
for (size_t i = 0; i < touchInput.mTouches.Length(); i++) {
*touchEvent.touches.AppendElement() = touchInput.mTouches[i].ToNewDOMTouch();
}
touchEvent.mFlags.mHandledByAPZ = touchInput.mHandledByAPZ;
return result;
}
case eWheelEventClass: {
@@ -1189,7 +1221,7 @@ void
APZCTreeManager::UpdateZoomConstraints(const ScrollableLayerGuid& aGuid,
const Maybe<ZoomConstraints>& aConstraints)
{
MonitorAutoLock lock(mTreeLock);
MutexAutoLock lock(mTreeLock);
RefPtr<HitTestingTreeNode> node = GetTargetNode(aGuid, nullptr);
MOZ_ASSERT(!node || node->GetApzc()); // any node returned must have an APZC
@@ -1248,7 +1280,7 @@ APZCTreeManager::FlushRepaintsToClearScreenToGeckoTransform()
// matched APZCs is the same. It is simplest to ensure that by flushing the
// pending repaint requests, which makes all of the untransforms empty (and
// therefore equal).
MonitorAutoLock lock(mTreeLock);
MutexAutoLock lock(mTreeLock);
mTreeLock.AssertCurrentThreadOwns();
ForEachNode(mRootNode.get(),
@@ -1273,7 +1305,7 @@ APZCTreeManager::CancelAnimation(const ScrollableLayerGuid &aGuid)
void
APZCTreeManager::AdjustScrollForSurfaceShift(const ScreenPoint& aShift)
{
MonitorAutoLock lock(mTreeLock);
MutexAutoLock lock(mTreeLock);
RefPtr<AsyncPanZoomController> apzc = FindRootContentOrRootApzc();
if (apzc) {
apzc->AdjustScrollForSurfaceShift(aShift);
@@ -1289,7 +1321,7 @@ APZCTreeManager::ClearTree()
APZThreadUtils::RunOnControllerThread(NewRunnableMethod(
mInputQueue.get(), &InputQueue::Clear));
MonitorAutoLock lock(mTreeLock);
MutexAutoLock lock(mTreeLock);
// Collect the nodes into a list, and then destroy each one.
// We can't destroy them as we collect them, because ForEachNode()
@@ -1311,7 +1343,7 @@ APZCTreeManager::ClearTree()
RefPtr<HitTestingTreeNode>
APZCTreeManager::GetRootNode() const
{
MonitorAutoLock lock(mTreeLock);
MutexAutoLock lock(mTreeLock);
return mRootNode;
}
@@ -1503,7 +1535,7 @@ APZCTreeManager::HitTestAPZC(const ScreenIntPoint& aPoint)
already_AddRefed<AsyncPanZoomController>
APZCTreeManager::GetTargetAPZC(const ScrollableLayerGuid& aGuid)
{
MonitorAutoLock lock(mTreeLock);
MutexAutoLock lock(mTreeLock);
RefPtr<HitTestingTreeNode> node = GetTargetNode(aGuid, nullptr);
MOZ_ASSERT(!node || node->GetApzc()); // any node returned must have an APZC
RefPtr<AsyncPanZoomController> apzc = node ? node->GetApzc() : nullptr;
@@ -1533,13 +1565,16 @@ APZCTreeManager::GetTargetNode(const ScrollableLayerGuid& aGuid,
}
already_AddRefed<AsyncPanZoomController>
APZCTreeManager::GetTargetAPZC(const ScreenPoint& aPoint, HitTestResult* aOutHitResult)
APZCTreeManager::GetTargetAPZC(const ScreenPoint& aPoint,
HitTestResult* aOutHitResult,
bool* aOutHitScrollbar)
{
MonitorAutoLock lock(mTreeLock);
MutexAutoLock lock(mTreeLock);
HitTestResult hitResult = HitNothing;
ParentLayerPoint point = ViewAs<ParentLayerPixel>(aPoint,
PixelCastJustification::ScreenIsParentLayerForRoot);
RefPtr<AsyncPanZoomController> target = GetAPZCAtPoint(mRootNode, point, &hitResult);
RefPtr<AsyncPanZoomController> target = GetAPZCAtPoint(mRootNode, point,
&hitResult, aOutHitScrollbar);
if (aOutHitResult) {
*aOutHitResult = hitResult;
@@ -1568,7 +1603,7 @@ APZCTreeManager::BuildOverscrollHandoffChain(const RefPtr<AsyncPanZoomController
// order in which scroll will be handed off to them.
// Grab tree lock since we'll be walking the APZC tree.
MonitorAutoLock lock(mTreeLock);
MutexAutoLock lock(mTreeLock);
// Build the chain. If there is a scroll parent link, we use that. This is
// needed to deal with scroll info layers, because they participate in handoff
@@ -1641,7 +1676,7 @@ APZCTreeManager::SetLongTapEnabled(bool aLongTapEnabled)
RefPtr<HitTestingTreeNode>
APZCTreeManager::FindScrollNode(const AsyncDragMetrics& aDragMetrics)
{
MonitorAutoLock lock(mTreeLock);
MutexAutoLock lock(mTreeLock);
return DepthFirstSearch(mRootNode.get(),
[&aDragMetrics](HitTestingTreeNode* aNode) {
@@ -1652,7 +1687,8 @@ APZCTreeManager::FindScrollNode(const AsyncDragMetrics& aDragMetrics)
AsyncPanZoomController*
APZCTreeManager::GetAPZCAtPoint(HitTestingTreeNode* aNode,
const ParentLayerPoint& aHitTestPoint,
HitTestResult* aOutHitResult)
HitTestResult* aOutHitResult,
bool* aOutHitScrollbar)
{
mTreeLock.AssertCurrentThreadOwns();
@@ -1704,6 +1740,13 @@ APZCTreeManager::GetAPZCAtPoint(HitTestingTreeNode* aNode,
if (*aOutHitResult != HitNothing) {
MOZ_ASSERT(resultNode);
if (aOutHitScrollbar) {
for (HitTestingTreeNode* n = resultNode; n; n = n->GetParent()) {
if (n->IsScrollbarNode()) {
*aOutHitScrollbar = true;
}
}
}
AsyncPanZoomController* result = resultNode->GetNearestContainingApzcWithSameLayersId();
if (!result) {
result = FindRootApzcForLayersId(resultNode->GetLayersId());
@@ -1872,7 +1915,7 @@ ScreenToParentLayerMatrix4x4
APZCTreeManager::GetScreenToApzcTransform(const AsyncPanZoomController *aApzc) const
{
Matrix4x4 result;
MonitorAutoLock lock(mTreeLock);
MutexAutoLock lock(mTreeLock);
// The comments below assume there is a chain of layers L..R with L and P having APZC instances as
// explained in the comment above. This function is called with aApzc at L, and the loop
@@ -1913,7 +1956,7 @@ ParentLayerToScreenMatrix4x4
APZCTreeManager::GetApzcToGeckoTransform(const AsyncPanZoomController *aApzc) const
{
Matrix4x4 result;
MonitorAutoLock lock(mTreeLock);
MutexAutoLock lock(mTreeLock);
// The comments below assume there is a chain of layers L..R with L and P having APZC instances as
// explained in the comment above. This function is called with aApzc at L, and the loop
@@ -1942,7 +1985,7 @@ APZCTreeManager::GetApzcToGeckoTransform(const AsyncPanZoomController *aApzc) co
already_AddRefed<AsyncPanZoomController>
APZCTreeManager::GetMultitouchTarget(AsyncPanZoomController* aApzc1, AsyncPanZoomController* aApzc2) const
{
MonitorAutoLock lock(mTreeLock);
MutexAutoLock lock(mTreeLock);
RefPtr<AsyncPanZoomController> apzc;
// For now, we only ever want to do pinching on the root-content APZC for
// a given layers id.
+8 -5
View File
@@ -17,7 +17,7 @@
#include "mozilla/gfx/Matrix.h" // for Matrix4x4
#include "mozilla/layers/APZUtils.h" // for HitTestResult
#include "mozilla/layers/TouchCounter.h"// for TouchCounter
#include "mozilla/Monitor.h" // for Monitor
#include "mozilla/Mutex.h" // for Mutex
#include "mozilla/TimeStamp.h" // for mozilla::TimeStamp
#include "mozilla/Vector.h" // for mozilla::Vector
#include "nsAutoPtr.h" // for nsRefPtr
@@ -44,7 +44,8 @@ enum AllowedTouchBehavior {
enum ZoomToRectBehavior : uint32_t {
DEFAULT_BEHAVIOR = 0,
DISABLE_ZOOM_OUT = 1 << 0,
PAN_INTO_VIEW_ONLY = 1 << 1
PAN_INTO_VIEW_ONLY = 1 << 1,
ONLY_ZOOM_TO_DEFAULT_SCALE = 1 << 2
};
class Layer;
@@ -437,7 +438,8 @@ public:
*/
RefPtr<HitTestingTreeNode> GetRootNode() const;
already_AddRefed<AsyncPanZoomController> GetTargetAPZC(const ScreenPoint& aPoint,
HitTestResult* aOutHitResult);
HitTestResult* aOutHitResult,
bool* aOutHitScrollbar = nullptr);
ScreenToParentLayerMatrix4x4 GetScreenToApzcTransform(const AsyncPanZoomController *aApzc) const;
ParentLayerToScreenMatrix4x4 GetApzcToGeckoTransform(const AsyncPanZoomController *aApzc) const;
private:
@@ -455,7 +457,8 @@ private:
GuidComparator aComparator);
AsyncPanZoomController* GetAPZCAtPoint(HitTestingTreeNode* aNode,
const ParentLayerPoint& aHitTestPoint,
HitTestResult* aOutHitResult);
HitTestResult* aOutHitResult,
bool* aOutHitScrollbar);
AsyncPanZoomController* FindRootApzcForLayersId(uint64_t aLayersId) const;
AsyncPanZoomController* FindRootContentApzcForLayersId(uint64_t aLayersId) const;
AsyncPanZoomController* FindRootContentOrRootApzc() const;
@@ -534,7 +537,7 @@ private:
* is considered part of the APZC tree management state.
* Finally, the lock needs to be held when accessing mZoomConstraints.
* IMPORTANT: See the note about lock ordering at the top of this file. */
mutable mozilla::Monitor mTreeLock;
mutable mozilla::Mutex mTreeLock;
RefPtr<HitTestingTreeNode> mRootNode;
/* Holds the zoom constraints for scrollable layers, as determined by the
* the main-thread gecko code. */
+105 -14
View File
@@ -1032,6 +1032,10 @@ static float GetAxisScale(AsyncDragMetrics::DragDirection aDir, T aValue) {
nsEventStatus AsyncPanZoomController::HandleDragEvent(const MouseInput& aEvent,
const AsyncDragMetrics& aDragMetrics)
{
if (!gfxPrefs::APZDragEnabled()) {
return nsEventStatus_eIgnore;
}
if (!GetApzcTreeManager()) {
return nsEventStatus_eConsumeNoDefault;
}
@@ -2035,7 +2039,13 @@ nsEventStatus AsyncPanZoomController::OnLongPress(const TapGestureInput& aEvent)
if (controller) {
CSSPoint geckoScreenPoint;
if (ConvertToGecko(aEvent.mPoint, &geckoScreenPoint)) {
if (CurrentTouchBlock()->IsDuringFastFling()) {
CancelableBlockState* block = CurrentInputBlock();
MOZ_ASSERT(block);
if (!block->AsTouchBlock()) {
APZC_LOG("%p dropping long-press because some non-touch block interrupted it\n", this);
return nsEventStatus_eIgnore;
}
if (block->AsTouchBlock()->IsDuringFastFling()) {
APZC_LOG("%p dropping long-press because of fast fling\n", this);
return nsEventStatus_eIgnore;
}
@@ -2057,8 +2067,21 @@ nsEventStatus AsyncPanZoomController::GenerateSingleTap(const ScreenIntPoint& aP
if (controller) {
CSSPoint geckoScreenPoint;
if (ConvertToGecko(aPoint, &geckoScreenPoint)) {
if (!CurrentTouchBlock()->SetSingleTapOccurred()) {
return nsEventStatus_eIgnore;
CancelableBlockState* block = CurrentInputBlock();
MOZ_ASSERT(block);
TouchBlockState* touch = block->AsTouchBlock();
// |block| may be a non-touch block in the case where this function is
// invoked by GestureEventListener on a timeout. In that case we already
// verified that the single tap is allowed so we let it through.
// XXX there is a bug here that in such a case the touch block that
// generated this tap will not get its mSingleTapOccurred flag set.
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1256344#c6
if (touch) {
if (touch->IsDuringFastFling()) {
APZC_LOG("%p dropping single-tap because it was during a fast-fling\n", this);
return nsEventStatus_eIgnore;
}
touch->SetSingleTapOccurred();
}
// Because this may be being running as part of APZCTreeManager::ReceiveInputEvent,
// calling controller->HandleSingleTap directly might mean that content receives
@@ -2326,7 +2349,18 @@ bool AsyncPanZoomController::AttemptScroll(ParentLayerPoint& aStartPoint,
ParentLayerPoint displacement = aStartPoint - aEndPoint;
ParentLayerPoint overscroll; // will be used outside monitor block
{
// If the direction of panning is reversed within the same input block,
// a later event in the block could potentially scroll an APZC earlier
// in the handoff chain, than an earlier event in the block (because
// the earlier APZC was scrolled to its extent in the original direction).
// If immediate handoff is disallowed, we want to disallow this (to
// preserve the property that a single input block only scrolls one APZC),
// so we skip the earlier APZC.
bool scrollThisApzc = gfxPrefs::APZAllowImmediateHandoff() ||
(CurrentInputBlock() && (!CurrentInputBlock()->GetScrolledApzc() || this == CurrentInputBlock()->GetScrolledApzc()));
if (scrollThisApzc) {
ReentrantMonitorAutoEnter lock(mMonitor);
ParentLayerPoint adjustedDisplacement;
@@ -2351,6 +2385,8 @@ bool AsyncPanZoomController::AttemptScroll(ParentLayerPoint& aStartPoint,
ScheduleCompositeAndMaybeRepaint();
UpdateSharedCompositorFrameMetrics();
}
} else {
overscroll = displacement;
}
// Adjust the start point to reflect the consumed portion of the scroll.
@@ -2683,7 +2719,10 @@ void AsyncPanZoomController::AdjustScrollForSurfaceShift(const ScreenPoint& aShi
/ mFrameMetrics.GetZoom();
APZC_LOG("%p adjusting scroll position by %s for surface shift\n",
this, Stringify(adjustment).c_str());
mFrameMetrics.ScrollBy(adjustment);
CSSPoint scrollOffset = mFrameMetrics.GetScrollOffset();
scrollOffset.y = mY.ClampOriginToScrollableRect(scrollOffset.y + adjustment.y);
scrollOffset.x = mX.ClampOriginToScrollableRect(scrollOffset.x + adjustment.x);
mFrameMetrics.SetScrollOffset(scrollOffset);
ScheduleCompositeAndMaybeRepaint();
UpdateSharedCompositorFrameMetrics();
}
@@ -2979,7 +3018,10 @@ bool AsyncPanZoomController::UpdateAnimation(const TimeStamp& aSampleTime,
mAnimation = nullptr;
SetState(NOTHING);
}
if (wantsRepaints) {
// Request a repaint at the end of the animation in case something such as a
// call to NotifyLayersUpdated was invoked during the animation and Gecko's
// current state is some intermediate point of the animation.
if (!continueAnimation || wantsRepaints) {
RequestContentRepaint();
}
UpdateSharedCompositorFrameMetrics();
@@ -3247,6 +3289,15 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aLayerMetri
ReentrantMonitorAutoEnter lock(mMonitor);
bool isDefault = mFrameMetrics.IsDefault();
if ((aLayerMetrics == mLastContentPaintMetrics) && !isDefault) {
// No new information here, skip it. Note that this is not just an
// optimization; it's correctness too. In the case where we get one of these
// stale aLayerMetrics *after* a call to NotifyScrollUpdated, processing the
// stale aLayerMetrics would clobber the more up-to-date information from
// NotifyScrollUpdated.
APZC_LOG("%p NotifyLayersUpdated short-circuit\n", this);
return;
}
mLastContentPaintMetrics = aLayerMetrics;
mFrameMetrics.SetScrollParentId(aLayerMetrics.GetScrollParentId());
@@ -3449,6 +3500,35 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aLayerMetri
UpdateSharedCompositorFrameMetrics();
}
void
AsyncPanZoomController::NotifyScrollUpdated(uint32_t aScrollGeneration,
const CSSPoint& aScrollOffset)
{
APZThreadUtils::AssertOnCompositorThread();
ReentrantMonitorAutoEnter lock(mMonitor);
APZC_LOG("%p NotifyScrollUpdated(%d, %s)\n", this, aScrollGeneration,
Stringify(aScrollOffset).c_str());
bool scrollOffsetUpdated = aScrollGeneration != mFrameMetrics.GetScrollGeneration();
if (!scrollOffsetUpdated) {
return;
}
APZC_LOG("%p updating scroll offset from %s to %s\n", this,
Stringify(mFrameMetrics.GetScrollOffset()).c_str(),
Stringify(aScrollOffset).c_str());
mFrameMetrics.UpdateScrollInfo(aScrollGeneration, aScrollOffset);
AcknowledgeScrollUpdate();
mExpectedGeckoMetrics.UpdateScrollInfo(aScrollGeneration, aScrollOffset);
CancelAnimation();
RequestContentRepaint();
UpdateSharedCompositorFrameMetrics();
// We don't call ScheduleComposite() here because that happens higher up
// in the call stack, when LayerTransactionParent handles this message.
// If we did it here it would incur an extra message posting unnecessarily.
}
void
AsyncPanZoomController::AcknowledgeScrollUpdate() const
{
@@ -3550,12 +3630,31 @@ void AsyncPanZoomController::ZoomToRect(CSSRect aRect, const uint32_t aFlags) {
FrameMetrics endZoomToMetrics = mFrameMetrics;
if (aFlags & PAN_INTO_VIEW_ONLY) {
targetZoom = currentZoom;
} else if(aFlags & ONLY_ZOOM_TO_DEFAULT_SCALE) {
CSSToParentLayerScale zoomAtDefaultScale =
mFrameMetrics.GetDevPixelsPerCSSPixel() * LayoutDeviceToParentLayerScale(1.0);
if (targetZoom.scale > zoomAtDefaultScale.scale) {
// Only change the zoom if we are less than the default zoom
if (currentZoom.scale < zoomAtDefaultScale.scale) {
targetZoom = zoomAtDefaultScale;
} else {
targetZoom = currentZoom;
}
}
}
endZoomToMetrics.SetZoom(CSSToParentLayerScale2D(targetZoom));
// Adjust the zoomToRect to a sensible position to prevent overscrolling.
CSSSize sizeAfterZoom = endZoomToMetrics.CalculateCompositedSizeInCssPixels();
// Vertically center the zoomed element in the screen.
if (!zoomOut && (sizeAfterZoom.height > aRect.height)) {
aRect.y -= (sizeAfterZoom.height - aRect.height) * 0.5f;
if (aRect.y < 0.0f) {
aRect.y = 0.0f;
}
}
// If either of these conditions are met, the page will be
// overscrolled after zoomed
if (aRect.y + sizeAfterZoom.height > cssPageRect.height) {
@@ -3567,14 +3666,6 @@ void AsyncPanZoomController::ZoomToRect(CSSRect aRect, const uint32_t aFlags) {
aRect.x = aRect.x > 0 ? aRect.x : 0;
}
// Vertically center the zoomed element in the screen.
if (!zoomOut && (sizeAfterZoom.height > aRect.height)) {
aRect.y -= (sizeAfterZoom.height - aRect.height) * 0.5f;
if (aRect.y < 0.0f) {
aRect.y = 0.0f;
}
}
endZoomToMetrics.SetScrollOffset(aRect.TopLeft());
StartAnimation(new ZoomAnimation(
+12 -5
View File
@@ -187,6 +187,13 @@ public:
void NotifyLayersUpdated(const FrameMetrics& aLayerMetrics, bool aIsFirstPaint,
bool aThisLayerTreeUpdated);
/**
* A lightweight version of NotifyLayersUpdated that allows just the scroll
* offset and scroll generation from the main thread to be propagated to APZ.
*/
void NotifyScrollUpdated(uint32_t aScrollGeneration,
const CSSPoint& aScrollOffset);
/**
* The platform implementation must set the compositor parent so that we can
* request composites.
@@ -614,11 +621,6 @@ protected:
*/
APZCTreeManager* GetApzcTreeManager() const;
/**
* Gets a ref to the input queue that is shared across the entire tree manager.
*/
const RefPtr<InputQueue>& GetInputQueue() const;
/**
* Convert ScreenPoint relative to the screen to CSSPoint relative
* to the parent document. This excludes the transient compositor transform.
@@ -813,6 +815,11 @@ public:
*/
void ResetTouchInputState();
/**
* Gets a ref to the input queue that is shared across the entire tree manager.
*/
const RefPtr<InputQueue>& GetInputQueue() const;
private:
void CancelAnimationAndGestureState();
+1
View File
@@ -10,6 +10,7 @@
#include "mozilla/TimeStamp.h"
#include <sstream>
#include "Units.h"
#include <vector>
namespace mozilla {
namespace layers {
+63
View File
@@ -0,0 +1,63 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#include "DragTracker.h"
#include "InputData.h"
#define DRAG_LOG(...)
// #define DRAG_LOG(...) printf_stderr("DRAG: " __VA_ARGS__)
namespace mozilla {
namespace layers {
DragTracker::DragTracker()
: mInDrag(false)
{
}
/*static*/ bool
DragTracker::StartsDrag(const MouseInput& aInput)
{
return aInput.IsLeftButton() && aInput.mType == MouseInput::MOUSE_DOWN;
}
/*static*/ bool
DragTracker::EndsDrag(const MouseInput& aInput)
{
return aInput.IsLeftButton() && aInput.mType == MouseInput::MOUSE_UP;
}
void
DragTracker::Update(const MouseInput& aInput)
{
if (StartsDrag(aInput)) {
DRAG_LOG("Starting drag\n");
mInDrag = true;
} else if (EndsDrag(aInput)) {
DRAG_LOG("Ending drag\n");
mInDrag = false;
mOnScrollbar = Nothing();
}
}
bool
DragTracker::InDrag() const
{
return mInDrag;
}
bool
DragTracker::IsOnScrollbar(bool aOnScrollbar)
{
if (!mOnScrollbar) {
DRAG_LOG("Setting hitscrollbar %d\n", aOnScrollbar);
mOnScrollbar = Some(aOnScrollbar);
}
return mOnScrollbar.value();
}
} // namespace layers
} // namespace mozilla
+39
View File
@@ -0,0 +1,39 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 mozilla_layers_DragTracker_h
#define mozilla_layers_DragTracker_h
#include "mozilla/EventForwards.h"
#include "mozilla/Maybe.h"
namespace mozilla {
class MouseInput;
namespace layers {
// DragTracker simply tracks a sequence of mouse inputs and allows us to tell
// if we are in a drag or not (i.e. the left mouse button went down and hasn't
// gone up yet).
class DragTracker
{
public:
DragTracker();
static bool StartsDrag(const MouseInput& aInput);
static bool EndsDrag(const MouseInput& aInput);
void Update(const MouseInput& aInput);
bool InDrag() const;
bool IsOnScrollbar(bool aOnScrollbar);
private:
Maybe<bool> mOnScrollbar;
bool mInDrag;
};
} // namespace layers
} // namespace mozilla
#endif /* mozilla_layers_DragTracker_h */
+7 -3
View File
@@ -444,7 +444,7 @@ void GestureEventListener::HandleInputTimeoutLongTap()
}
}
void GestureEventListener::HandleInputTimeoutMaxTap()
void GestureEventListener::HandleInputTimeoutMaxTap(bool aDuringFastFling)
{
GEL_LOG("Running max-tap timeout task in state %d\n", mState);
@@ -455,7 +455,9 @@ void GestureEventListener::HandleInputTimeoutMaxTap()
} else if (mState == GESTURE_FIRST_SINGLE_TOUCH_UP ||
mState == GESTURE_SECOND_SINGLE_TOUCH_DOWN) {
SetState(GESTURE_NONE);
TriggerSingleTapConfirmedEvent();
if (!aDuringFastFling) {
TriggerSingleTapConfirmedEvent();
}
} else {
NS_WARNING("Unhandled state upon MAX_TAP timeout");
SetState(GESTURE_NONE);
@@ -520,8 +522,10 @@ void GestureEventListener::CreateMaxTapTimeoutTask()
{
mLastTapInput = mLastTouchInput;
TouchBlockState* block = mAsyncPanZoomController->GetInputQueue()->CurrentTouchBlock();
mMaxTapTimeoutTask =
NewRunnableMethod(this, &GestureEventListener::HandleInputTimeoutMaxTap);
NewRunnableMethod(this, &GestureEventListener::HandleInputTimeoutMaxTap,
block->IsDuringFastFling());
mAsyncPanZoomController->PostDelayedTask(
mMaxTapTimeoutTask,
+1 -1
View File
@@ -137,7 +137,7 @@ private:
nsEventStatus HandleInputTouchMove();
nsEventStatus HandleInputTouchCancel();
void HandleInputTimeoutLongTap();
void HandleInputTimeoutMaxTap();
void HandleInputTimeoutMaxTap(bool aDuringFastFling);
void TriggerSingleTapConfirmedEvent();
@@ -12,6 +12,7 @@
#include "mozilla/layers/APZThreadUtils.h" // for AssertOnCompositorThread
#include "mozilla/layers/APZUtils.h" // for CompleteAsyncTransform
#include "mozilla/layers/AsyncCompositionManager.h" // for ViewTransform::operator Matrix4x4()
#include "mozilla/layers/AsyncDragMetrics.h" // for AsyncDragMetrics
#include "nsPrintfCString.h" // for nsPrintfCString
#include "UnitTransforms.h" // for ViewAs
@@ -114,6 +115,12 @@ HitTestingTreeNode::GetScrollSize() const
return mScrollSize;
}
bool
HitTestingTreeNode::IsScrollbarNode() const
{
return (mScrollDir != Layer::NONE);
}
void
HitTestingTreeNode::SetPrevSibling(HitTestingTreeNode* aSibling)
{
+1
View File
@@ -95,6 +95,7 @@ public:
void SetScrollbarData(FrameMetrics::ViewID aScrollViewId, Layer::ScrollDirection aDir, int32_t aScrollSize);
bool MatchesScrollDragMetrics(const AsyncDragMetrics& aDragMetrics) const;
int32_t GetScrollSize() const;
bool IsScrollbarNode() const;
/* Convert aPoint into the LayerPixel space for the layer corresponding to
* this node. */
+27 -8
View File
@@ -87,9 +87,33 @@ InputBlockState::IsTargetConfirmed() const
return mTargetConfirmed;
}
bool
InputBlockState::IsAncestorOf(AsyncPanZoomController* aA, AsyncPanZoomController* aB)
{
if (aA == aB) {
return true;
}
bool seenA = false;
for (size_t i = 0; i < mOverscrollHandoffChain->Length(); ++i) {
AsyncPanZoomController* apzc = mOverscrollHandoffChain->GetApzcAtIndex(i);
if (apzc == aB) {
return seenA;
}
if (apzc == aA) {
seenA = true;
}
}
return false;
}
void
InputBlockState::SetScrolledApzc(AsyncPanZoomController* aApzc)
{
// An input block should only have one scrolled APZC.
MOZ_ASSERT(!mScrolledApzc || mScrolledApzc == aApzc);
mScrolledApzc = aApzc;
}
@@ -716,16 +740,11 @@ TouchBlockState::IsDuringFastFling() const
return mDuringFastFling;
}
bool
void
TouchBlockState::SetSingleTapOccurred()
{
TBS_LOG("%p attempting to set single-tap occurred; disallowed=%d\n",
this, mDuringFastFling);
if (!mDuringFastFling) {
mSingleTapOccurred = true;
return true;
}
return false;
TBS_LOG("%p setting single-tap-occurred flag\n", this);
mSingleTapOccurred = true;
}
bool
+8 -3
View File
@@ -9,9 +9,11 @@
#include "InputData.h" // for MultiTouchInput
#include "mozilla/gfx/Matrix.h" // for Matrix4x4
#include "mozilla/layers/APZUtils.h" // for TouchBehaviorFlags
#include "mozilla/layers/AsyncDragMetrics.h"
#include "nsAutoPtr.h" // for nsRefPtr
#include "nsTArray.h" // for nsTArray
#include "TouchCounter.h"
namespace mozilla {
namespace layers {
@@ -54,6 +56,11 @@ public:
protected:
virtual void UpdateTargetApzc(const RefPtr<AsyncPanZoomController>& aTargetApzc);
private:
// Checks whether |aA| is an ancestor of |aB| (or the same as |aB|) in
// |mOverscrollHandoffChain|.
bool IsAncestorOf(AsyncPanZoomController* aA, AsyncPanZoomController* aB);
private:
RefPtr<AsyncPanZoomController> mTargetApzc;
bool mTargetConfirmed;
@@ -409,10 +416,8 @@ public:
/**
* Set the single-tap-occurred flag that indicates that this touch block
* triggered a single tap event.
* @return true if the flag was set. This may not happen if, for example,
* SetDuringFastFling was previously called.
*/
bool SetSingleTapOccurred();
void SetSingleTapOccurred();
/**
* @return true iff the single-tap-occurred flag is set on this block.
*/
+31 -7
View File
@@ -185,7 +185,7 @@ InputQueue::ReceiveMouseInput(const RefPtr<AsyncPanZoomController>& aTarget,
// On a new mouse down we can have a new target so we must force a new block
// with a new target.
bool newBlock = aEvent.mType == MouseInput::MOUSE_DOWN && aEvent.IsLeftButton();
bool newBlock = DragTracker::StartsDrag(aEvent);
DragBlockState* block = nullptr;
if (!newBlock && !mInputBlockQueue.IsEmpty()) {
@@ -196,8 +196,20 @@ InputQueue::ReceiveMouseInput(const RefPtr<AsyncPanZoomController>& aTarget,
block = nullptr;
}
if (!block && mDragTracker.InDrag()) {
// If there's no current drag block, but we're getting a move with a button
// down, we need to start a new drag block because we're obviously already
// in the middle of a drag (it probably got interrupted by something else).
INPQ_LOG("got a drag event outside a drag block, need to create a block to hold it\n");
newBlock = true;
}
mDragTracker.Update(aEvent);
if (!newBlock && !block) {
return nsEventStatus_eConsumeDoDefault;
// This input event is not in a drag block, so we're not doing anything
// with it, return eIgnore.
return nsEventStatus_eIgnore;
}
if (!block) {
@@ -218,7 +230,7 @@ InputQueue::ReceiveMouseInput(const RefPtr<AsyncPanZoomController>& aTarget,
block->AddEvent(aEvent.AsMouseInput());
// The first event will confirm the block or not.
// This input event created a new drag block, so return DoDefault.
return nsEventStatus_eConsumeDoDefault;
}
@@ -230,13 +242,12 @@ InputQueue::ReceiveMouseInput(const RefPtr<AsyncPanZoomController>& aTarget,
block->AddEvent(aEvent.AsMouseInput());
}
bool mouseUp = aEvent.mType == MouseInput::MOUSE_UP && aEvent.IsLeftButton();
if (mouseUp) {
if (DragTracker::EndsDrag(aEvent)) {
block->MarkMouseUpReceived();
}
// If we're not the first event then we need to wait for the confirmation of
// the block.
// The event was added to the drag block and could potentially cause
// scrolling, so return DoDefault.
return nsEventStatus_eConsumeDoDefault;
}
@@ -537,6 +548,19 @@ InputQueue::AllowScrollHandoff() const
return true;
}
bool
InputQueue::IsDragOnScrollbar(bool aHitScrollbar)
{
if (!mDragTracker.InDrag()) {
return false;
}
// Now that we know we are in a drag, get the info from the drag tracker.
// We keep it in the tracker rather than the block because the block can get
// interrupted by something else (like a wheel event) and then a new block
// will get created without the info we want. The tracker will persist though.
return mDragTracker.IsOnScrollbar(aHitScrollbar);
}
void
InputQueue::ScheduleMainThreadTimeout(const RefPtr<AsyncPanZoomController>& aTarget, uint64_t aInputBlockId) {
INPQ_LOG("scheduling main thread timeout for target %p\n", aTarget.get());
+11
View File
@@ -7,11 +7,13 @@
#define mozilla_layers_InputQueue_h
#include "APZUtils.h"
#include "DragTracker.h"
#include "InputData.h"
#include "mozilla/EventForwards.h"
#include "mozilla/UniquePtr.h"
#include "nsAutoPtr.h"
#include "nsTArray.h"
#include "TouchCounter.h"
namespace mozilla {
@@ -118,6 +120,12 @@ public:
* Whether the current pending block allows scroll handoff.
*/
bool AllowScrollHandoff() const;
/**
* If there is currently a drag in progress, return whether or not it was
* targeted at a scrollbar. If the drag was newly-created and doesn't know,
* use the provided |aOnScrollbar| to populate that information.
*/
bool IsDragOnScrollbar(bool aOnScrollbar);
private:
~InputQueue();
@@ -182,6 +190,9 @@ private:
// Track touches so we know when to clear mLastActiveApzc
TouchCounter mTouchCounter;
// Track mouse inputs so we know if we're in a drag or not
DragTracker mDragTracker;
};
} // namespace layers
@@ -10,6 +10,7 @@
#include <vector>
#include "nsAutoPtr.h"
#include "nsISupportsImpl.h" // for NS_INLINE_DECL_THREADSAFE_REFCOUNTING
#include "APZCTreeManager.h"
#include "APZUtils.h" // for CancelAnimationFlags
#include "Layers.h" // for Layer::ScrollDirection
#include "Units.h" // for ScreenPoint
+41 -43
View File
@@ -39,46 +39,6 @@ function convertTestData(testData) {
return result;
}
// ----------------------------------------------------------------
// Utilities for reconstructing the structure of the APZC tree from
// 'parentScrollId' entries in the APZ test data.
// ----------------------------------------------------------------
// Create a node with scroll id 'id' in the APZC tree.
function makeNode(id) {
return {scrollId: id, children: []};
}
// Find a node with scroll id 'id' in the APZC tree rooted at 'root'.
function findNode(root, id) {
if (root.scrollId == id) {
return root;
}
for (var i = 0; i < root.children.length; ++i) {
var subtreeResult = findNode(root.children[i], id);
if (subtreeResult != null) {
return subtreeResult;
}
}
return null;
}
// Add a child -> parent link to the APZC tree rooted at 'root'.
function addLink(root, child, parent) {
var parentNode = findNode(root, parent);
if (parentNode == null) {
parentNode = makeNode(parent);
root.children.push(parentNode);
}
parentNode.children.push(makeNode(child));
}
// Add a root node to the APZC tree. It will become a direct
// child of 'root'.
function addRoot(root, id) {
root.children.push(makeNode(id));
}
// Given APZ test data for a single paint on the compositor side,
// reconstruct the APZC tree structure from the 'parentScrollId'
// entries that were logged. More specifically, the subset of the
@@ -89,13 +49,51 @@ function buildApzcTree(paint) {
// The APZC tree can potentially have multiple root nodes,
// so we invent a node that is the parent of all roots.
// This 'root' does not correspond to an APZC.
var root = makeNode(-1);
var root = {scrollId: -1, children: []};
for (var scrollId in paint) {
paint[scrollId].children = [];
paint[scrollId].scrollId = scrollId;
}
for (var scrollId in paint) {
var parentNode = null;
if ("hasNoParentWithSameLayersId" in paint[scrollId]) {
addRoot(root, scrollId);
parentNode = root;
} else if ("parentScrollId" in paint[scrollId]) {
addLink(root, scrollId, paint[scrollId]["parentScrollId"]);
parentNode = paint[paint[scrollId].parentScrollId];
}
parentNode.children.push(paint[scrollId]);
}
return root;
}
// Given an APZC tree produced by buildApzcTree, return the RCD node in
// the tree, or null if there was none.
function findRcdNode(apzcTree) {
if (!!apzcTree.isRootContent) { // isRootContent will be undefined or "1"
return apzcTree;
}
for (var i = 0; i < apzcTree.children.length; i++) {
var rcd = findRcdNode(apzcTree.children[i]);
if (rcd != null) {
return rcd;
}
}
return null;
}
function flushApzRepaints(aCallback, aWindow = window) {
if (!aCallback) {
throw "A callback must be provided!";
}
var repaintDone = function() {
SpecialPowers.Services.obs.removeObserver(repaintDone, "apz-repaints-flushed", false);
setTimeout(aCallback, 0);
};
SpecialPowers.Services.obs.addObserver(repaintDone, "apz-repaints-flushed", false);
if (SpecialPowers.getDOMWindowUtils(aWindow).flushApzRepaints()) {
dump("Flushed APZ repaints, waiting for callback...\n");
} else {
dump("Flushing APZ repaints was a no-op, triggering callback directly...\n");
repaintDone();
}
}
@@ -125,6 +125,10 @@ ScrollFrame(nsIContent* aContent,
{
// Scroll the window to the desired spot
nsIScrollableFrame* sf = nsLayoutUtils::FindScrollableFrameFor(aMetrics.GetScrollId());
if (sf) {
sf->SetScrollableByAPZ(!aMetrics.IsScrollInfoLayer());
}
bool scrollUpdated = false;
CSSPoint apzScrollOffset = aMetrics.GetScrollOffset();
CSSPoint actualScrollOffset = ScrollFrameTo(sf, apzScrollOffset, scrollUpdated);
+1
View File
@@ -278,6 +278,7 @@ APZEventState::ProcessTouchEvent(const WidgetTouchEvent& aEvent,
// Since APZ doesn't know about it we don't want to send a response for
// this block; we want to just skip over it from the point of view of
// prevent-default notifications.
APZES_LOG("Got a synthetic touch-start!\n");
break;
}
if (isTouchPrevented) {
@@ -12,6 +12,7 @@
#include "mozilla/ClearOnShutdown.h" // for ClearOnShutdown
#include "mozilla/dom/CheckerboardReportServiceBinding.h" // for dom::CheckerboardReports
#include "nsContentUtils.h" // for nsContentUtils
#include "nsXULAppAPI.h"
namespace mozilla {
namespace layers {
+80 -25
View File
@@ -166,26 +166,34 @@ BasicCompositor::CreateRenderTargetFromSource(const IntRect &aRect,
}
already_AddRefed<CompositingRenderTarget>
BasicCompositor::CreateRenderTargetForWindow(const IntRect& aRect, SurfaceInitMode aInit, BufferMode aBufferMode)
BasicCompositor::CreateRenderTargetForWindow(const LayoutDeviceIntRect& aRect, SurfaceInitMode aInit, BufferMode aBufferMode)
{
if (aBufferMode != BufferMode::BUFFER_NONE) {
return CreateRenderTarget(aRect, aInit);
}
MOZ_ASSERT(mDrawTarget);
MOZ_ASSERT(aRect.width != 0 && aRect.height != 0, "Trying to create a render target of invalid size");
if (aRect.width * aRect.height == 0) {
return nullptr;
}
MOZ_ASSERT(mDrawTarget);
RefPtr<BasicCompositingRenderTarget> rt;
IntRect rect = aRect.ToUnknownRect();
// Adjust bounds rect to account for new origin at (0, 0).
IntRect rect(0, 0, aRect.XMost(), aRect.YMost());
RefPtr<BasicCompositingRenderTarget> rt = new BasicCompositingRenderTarget(mDrawTarget, rect);
if (aInit == INIT_MODE_CLEAR) {
mDrawTarget->ClearRect(gfx::Rect(aRect));
if (aBufferMode != BufferMode::BUFFER_NONE) {
RefPtr<DrawTarget> target = mWidget->CreateBackBufferDrawTarget(mDrawTarget, aRect);
if (!target) {
return nullptr;
}
rt = new BasicCompositingRenderTarget(target, rect);
} else {
IntRect windowRect = rect;
// Adjust bounds rect to account for new origin at (0, 0).
if (windowRect.Size() != mDrawTarget->GetSize()) {
windowRect.ExpandToEnclose(IntPoint(0, 0));
}
rt = new BasicCompositingRenderTarget(mDrawTarget, windowRect);
if (aInit == INIT_MODE_CLEAR) {
mDrawTarget->ClearRect(Rect(rect - rt->GetOrigin()));
}
}
return rt.forget();
@@ -389,6 +397,25 @@ RoundOut(Rect r)
return IntRect(r.x, r.y, r.width, r.height);
}
static void
SetupMask(const EffectChain& aEffectChain,
DrawTarget* aDest,
const IntPoint& aOffset,
RefPtr<SourceSurface>& aMaskSurface,
Matrix& aMaskTransform)
{
if (aEffectChain.mSecondaryEffects[EffectTypes::MASK]) {
EffectMask *effectMask = static_cast<EffectMask*>(aEffectChain.mSecondaryEffects[EffectTypes::MASK].get());
aMaskSurface = effectMask->mMaskTexture->AsSourceBasic()->GetSurface(aDest);
if (!aMaskSurface) {
gfxWarning() << "Invalid sourceMask effect";
}
MOZ_ASSERT(effectMask->mMaskTransform.Is2D(), "How did we end up with a 3D transform here?!");
aMaskTransform = effectMask->mMaskTransform.As2D();
aMaskTransform.PostTranslate(-aOffset.x, -aOffset.y);
}
}
void
BasicCompositor::DrawQuad(const gfx::Rect& aRect,
const gfx::Rect& aClipRect,
@@ -434,7 +461,8 @@ BasicCompositor::DrawQuad(const gfx::Rect& aRect,
// When we apply the 3D transformation, we do it against a temporary
// surface, so undo the coordinate offset.
new3DTransform = Matrix4x4::Translation(aRect.x, aRect.y, 0) * aTransform;
new3DTransform = aTransform;
new3DTransform.PreTranslate(aRect.x, aRect.y, 0);
}
buffer->PushClipRect(aClipRect);
@@ -444,16 +472,8 @@ BasicCompositor::DrawQuad(const gfx::Rect& aRect,
RefPtr<SourceSurface> sourceMask;
Matrix maskTransform;
if (aEffectChain.mSecondaryEffects[EffectTypes::MASK]) {
EffectMask *effectMask = static_cast<EffectMask*>(aEffectChain.mSecondaryEffects[EffectTypes::MASK].get());
sourceMask = effectMask->mMaskTexture->AsSourceBasic()->GetSurface(dest);
if (!sourceMask) {
gfxWarning() << "Invalid sourceMask effect";
}
MOZ_ASSERT(effectMask->mMaskTransform.Is2D(), "How did we end up with a 3D transform here?!");
MOZ_ASSERT(!effectMask->mIs3D);
maskTransform = effectMask->mMaskTransform.As2D();
maskTransform.PreTranslate(-offset.x, -offset.y);
if (aTransform.Is2D()) {
SetupMask(aEffectChain, dest, offset, sourceMask, maskTransform);
}
CompositionOp blendMode = CompositionOp::OP_OVER;
@@ -560,8 +580,40 @@ BasicCompositor::DrawQuad(const gfx::Rect& aRect,
Transform(temp, source, new3DTransform, transformBounds.TopLeft());
SetupMask(aEffectChain, buffer, offset, sourceMask, maskTransform);
// Adjust for the fact that our content now start at 0,0 instead
// of the top left of transformBounds.
transformBounds.MoveTo(0, 0);
buffer->DrawSurface(temp, transformBounds, transformBounds);
maskTransform.PostTranslate(-transformBounds.x, -transformBounds.y);
if (sourceMask) {
// Transform the source by it's normal transform, and then the inverse
// of the mask transform so that it's in the mask's untransformed
// coordinate space.
Matrix old = buffer->GetTransform();
Matrix sourceTransform = old;
Matrix inverseMask = maskTransform;
inverseMask.Invert();
sourceTransform *= inverseMask;
SurfacePattern source(temp, ExtendMode::CLAMP, sourceTransform);
buffer->PushClipRect(transformBounds);
// Mask in the untransformed coordinate space, and then transform
// by the mask transform to put the result back into destination
// coords.
buffer->SetTransform(maskTransform);
buffer->MaskSurface(source, sourceMask, Point(0, 0));
buffer->SetTransform(old);
buffer->PopClip();
} else {
buffer->DrawSurface(temp, transformBounds, transformBounds);
}
}
buffer->PopClip();
@@ -577,6 +629,7 @@ void
BasicCompositor::BeginFrame(const nsIntRegion& aInvalidRegion,
const gfx::Rect *aClipRectIn,
const gfx::Rect& aRenderBounds,
bool aOpaque,
gfx::Rect *aClipRectOut /* = nullptr */,
gfx::Rect *aRenderBoundsOut /* = nullptr */)
{
@@ -627,7 +680,9 @@ BasicCompositor::BeginFrame(const nsIntRegion& aInvalidRegion,
// Setup an intermediate render target to buffer all compositing. We will
// copy this into mDrawTarget (the widget), and/or mTarget in EndFrame()
RefPtr<CompositingRenderTarget> target =
CreateRenderTargetForWindow(mInvalidRect.ToUnknownRect(), INIT_MODE_CLEAR, bufferMode);
CreateRenderTargetForWindow(mInvalidRect,
aOpaque ? INIT_MODE_NONE : INIT_MODE_CLEAR,
bufferMode);
if (!target) {
if (!mTarget) {
mWidget->EndRemoteDrawingInRegion(mDrawTarget, mInvalidRegion);
+2 -1
View File
@@ -63,7 +63,7 @@ public:
const gfx::IntPoint &aSourcePoint) override;
virtual already_AddRefed<CompositingRenderTarget>
CreateRenderTargetForWindow(const gfx::IntRect& aRect,
CreateRenderTargetForWindow(const LayoutDeviceIntRect& aRect,
SurfaceInitMode aInit,
BufferMode aBufferMode);
@@ -97,6 +97,7 @@ public:
virtual void BeginFrame(const nsIntRegion& aInvalidRegion,
const gfx::Rect *aClipRectIn,
const gfx::Rect& aRenderBounds,
bool aOpaque,
gfx::Rect *aClipRectOut = nullptr,
gfx::Rect *aRenderBoundsOut = nullptr) override;
virtual void EndFrame() override;
+46 -31
View File
@@ -32,6 +32,7 @@ ClientTiledPaintedLayer::ClientTiledPaintedLayer(ClientLayerManager* const aMana
ClientLayerManager::PaintedLayerCreationHint aCreationHint)
: PaintedLayer(aManager, static_cast<ClientLayer*>(this), aCreationHint)
, mContentClient()
, mHaveSingleTiledContentClient(false)
{
MOZ_COUNT_CTOR(ClientTiledPaintedLayer);
mPaintData.mLastScrollOffset = ParentLayerPoint(0, 0);
@@ -181,13 +182,15 @@ ClientTiledPaintedLayer::BeginPaint()
+ displayportMetrics.GetCompositionBounds().TopLeft();
Maybe<LayerRect> criticalDisplayPortTransformed =
ApplyParentLayerToLayerTransform(transformDisplayPortToLayer, criticalDisplayPort, layerBounds);
if (!criticalDisplayPortTransformed) {
mPaintData.ResetPaintData();
return;
if (criticalDisplayPortTransformed) {
mPaintData.mCriticalDisplayPort = Some(RoundedToInt(*criticalDisplayPortTransformed));
} else {
mPaintData.mCriticalDisplayPort = Some(LayerIntRect(0, 0, 0, 0));
}
mPaintData.mCriticalDisplayPort = RoundedToInt(*criticalDisplayPortTransformed);
}
TILING_LOG("TILING %p: Critical displayport %s\n", this, Stringify(mPaintData.mCriticalDisplayPort).c_str());
TILING_LOG("TILING %p: Critical displayport %s\n", this,
mPaintData.mCriticalDisplayPort ?
Stringify(*mPaintData.mCriticalDisplayPort).c_str() : "not set");
// Store the resolution from the displayport ancestor layer. Because this is Gecko-side,
// before any async transforms have occurred, we can use the zoom for this.
@@ -200,11 +203,11 @@ ClientTiledPaintedLayer::BeginPaint()
ParentLayerToLayerMatrix4x4 transformToBounds = mPaintData.mTransformToCompBounds.Inverse();
Maybe<LayerRect> compositionBoundsTransformed = ApplyParentLayerToLayerTransform(
transformToBounds, scrollMetrics.GetCompositionBounds(), layerBounds);
if (!compositionBoundsTransformed) {
mPaintData.ResetPaintData();
return;
if (compositionBoundsTransformed) {
mPaintData.mCompositionBounds = *compositionBoundsTransformed;
} else {
mPaintData.mCompositionBounds.SetEmpty();
}
mPaintData.mCompositionBounds = *compositionBoundsTransformed;
TILING_LOG("TILING %p: Composition bounds %s\n", this, Stringify(mPaintData.mCompositionBounds).c_str());
// Calculate the scroll offset since the last transaction
@@ -260,7 +263,7 @@ ClientTiledPaintedLayer::UseProgressiveDraw() {
return false;
}
if (mPaintData.mCriticalDisplayPort.IsEmpty()) {
if (!mPaintData.mCriticalDisplayPort) {
// This catches three scenarios:
// 1) This layer doesn't have a scrolling ancestor
// 2) This layer is subject to OMTA transforms
@@ -279,7 +282,7 @@ ClientTiledPaintedLayer::UseProgressiveDraw() {
if (ClientManager()->AsyncPanZoomEnabled()) {
LayerMetricsWrapper scrollAncestor;
GetAncestorLayers(&scrollAncestor, nullptr, nullptr);
MOZ_ASSERT(scrollAncestor); // because mPaintData.mCriticalDisplayPort is non-empty
MOZ_ASSERT(scrollAncestor); // because mPaintData.mCriticalDisplayPort is set
const FrameMetrics& parentMetrics = scrollAncestor.Metrics();
if (!IsScrollingOnCompositor(parentMetrics)) {
return false;
@@ -295,22 +298,24 @@ ClientTiledPaintedLayer::RenderHighPrecision(nsIntRegion& aInvalidRegion,
LayerManager::DrawPaintedLayerCallback aCallback,
void* aCallbackData)
{
// If we have no high-precision stuff to draw, or we have started drawing low-precision
// already, then we shouldn't do anything there.
if (aInvalidRegion.IsEmpty() || mPaintData.mLowPrecisionPaintCount != 0) {
// If we have started drawing low-precision already, then we
// shouldn't do anything there.
if (mPaintData.mLowPrecisionPaintCount != 0) {
return false;
}
// Only draw progressively when the resolution is unchanged
if (UseProgressiveDraw() &&
// Only draw progressively when there is something to paint and the
// resolution is unchanged
if (!aInvalidRegion.IsEmpty() &&
UseProgressiveDraw() &&
mContentClient->GetTiledBuffer()->GetFrameResolution() == mPaintData.mResolution) {
// Store the old valid region, then clear it before painting.
// We clip the old valid region to the visible region, as it only gets
// used to decide stale content (currently valid and previously visible)
nsIntRegion oldValidRegion = mContentClient->GetTiledBuffer()->GetValidRegion();
oldValidRegion.And(oldValidRegion, aVisibleRegion);
if (!mPaintData.mCriticalDisplayPort.IsEmpty()) {
oldValidRegion.And(oldValidRegion, mPaintData.mCriticalDisplayPort.ToUnknownRect());
if (mPaintData.mCriticalDisplayPort) {
oldValidRegion.And(oldValidRegion, mPaintData.mCriticalDisplayPort->ToUnknownRect());
}
TILING_LOG("TILING %p: Progressive update with old valid region %s\n", this, Stringify(oldValidRegion).c_str());
@@ -319,11 +324,12 @@ ClientTiledPaintedLayer::RenderHighPrecision(nsIntRegion& aInvalidRegion,
oldValidRegion, &mPaintData, aCallback, aCallbackData);
}
// Otherwise do a non-progressive paint
// Otherwise do a non-progressive paint. We must do this even when
// the region to paint is empty as the valid region may have shrunk.
mValidRegion = aVisibleRegion;
if (!mPaintData.mCriticalDisplayPort.IsEmpty()) {
mValidRegion.And(mValidRegion, mPaintData.mCriticalDisplayPort.ToUnknownRect());
if (mPaintData.mCriticalDisplayPort) {
mValidRegion.And(mValidRegion, mPaintData.mCriticalDisplayPort->ToUnknownRect());
}
TILING_LOG("TILING %p: Non-progressive paint invalid region %s\n", this, Stringify(aInvalidRegion).c_str());
@@ -344,7 +350,8 @@ ClientTiledPaintedLayer::RenderLowPrecision(nsIntRegion& aInvalidRegion,
{
// Render the low precision buffer, if the visible region is larger than the
// critical display port.
if (!nsIntRegion(mPaintData.mCriticalDisplayPort.ToUnknownRect()).Contains(aVisibleRegion)) {
if (!mPaintData.mCriticalDisplayPort ||
!nsIntRegion(mPaintData.mCriticalDisplayPort->ToUnknownRect()).Contains(aVisibleRegion)) {
nsIntRegion oldValidRegion = mContentClient->GetLowPrecisionTiledBuffer()->GetValidRegion();
oldValidRegion.And(oldValidRegion, aVisibleRegion);
@@ -415,18 +422,26 @@ ClientTiledPaintedLayer::RenderLayer()
void *data = ClientManager()->GetPaintedLayerCallbackData();
IntSize layerSize = mVisibleRegion.ToUnknownRegion().GetBounds().Size();
if (mContentClient && !mContentClient->SupportsLayerSize(layerSize, ClientManager())) {
IntSize tileSize(gfxPlatform::GetPlatform()->GetTileWidth(),
gfxPlatform::GetPlatform()->GetTileHeight());
bool wantSingleTiledContentClient =
(mCreationHint == LayerManager::NONE || layerSize <= tileSize) &&
SingleTiledContentClient::ClientSupportsLayerSize(layerSize, ClientManager()) &&
gfxPrefs::LayersSingleTileEnabled();
if (mContentClient && mHaveSingleTiledContentClient && !wantSingleTiledContentClient) {
mContentClient = nullptr;
mValidRegion.SetEmpty();
}
if (!mContentClient) {
if (mCreationHint == LayerManager::NONE &&
SingleTiledContentClient::ClientSupportsLayerSize(layerSize, ClientManager()) &&
gfxPrefs::LayersSingleTileEnabled()) {
if (wantSingleTiledContentClient) {
mContentClient = new SingleTiledContentClient(this, ClientManager());
mHaveSingleTiledContentClient = true;
} else {
mContentClient = new MultiTiledContentClient(this, ClientManager());
mHaveSingleTiledContentClient = false;
}
mContentClient->Connect();
@@ -490,16 +505,16 @@ ClientTiledPaintedLayer::RenderLayer()
// critical displayport are discarded on the first update. Also make sure that we
// only draw stuff inside the critical displayport on the first update.
mValidRegion.And(mValidRegion, neededRegion);
if (!mPaintData.mCriticalDisplayPort.IsEmpty()) {
mValidRegion.And(mValidRegion, mPaintData.mCriticalDisplayPort.ToUnknownRect());
invalidRegion.And(invalidRegion, mPaintData.mCriticalDisplayPort.ToUnknownRect());
if (mPaintData.mCriticalDisplayPort) {
mValidRegion.And(mValidRegion, mPaintData.mCriticalDisplayPort->ToUnknownRect());
invalidRegion.And(invalidRegion, mPaintData.mCriticalDisplayPort->ToUnknownRect());
}
TILING_LOG("TILING %p: First-transaction valid region %s\n", this, Stringify(mValidRegion).c_str());
TILING_LOG("TILING %p: First-transaction invalid region %s\n", this, Stringify(invalidRegion).c_str());
} else {
if (!mPaintData.mCriticalDisplayPort.IsEmpty()) {
invalidRegion.And(invalidRegion, mPaintData.mCriticalDisplayPort.ToUnknownRect());
if (mPaintData.mCriticalDisplayPort) {
invalidRegion.And(invalidRegion, mPaintData.mCriticalDisplayPort->ToUnknownRect());
}
TILING_LOG("TILING %p: Repeat-transaction invalid region %s\n", this, Stringify(invalidRegion).c_str());
}
@@ -133,6 +133,9 @@ private:
void EndPaint();
RefPtr<TiledContentClient> mContentClient;
// Flag to indicate if mContentClient is a SingleTiledContentClient. This is
// only valid when mContentClient is non-null.
bool mHaveSingleTiledContentClient;
nsIntRegion mLowPrecisionValidRegion;
BasicTiledLayerPaintData mPaintData;
};
@@ -46,12 +46,6 @@ SingleTiledContentClient::ClientSupportsLayerSize(const gfx::IntSize& aSize, Cli
return aSize.width <= maxTextureSize && aSize.height <= maxTextureSize;
}
bool
SingleTiledContentClient::SupportsLayerSize(const gfx::IntSize& aSize, ClientLayerManager* aManager) const
{
return ClientSupportsLayerSize(aSize, aManager);
}
ClientSingleTiledLayerBuffer::ClientSingleTiledLayerBuffer(ClientTiledPaintedLayer* aPaintedLayer,
CompositableClient* aCompositableClient,
ClientLayerManager* aManager)
@@ -127,8 +127,6 @@ public:
virtual ClientTiledLayerBuffer* GetTiledBuffer() override { return mTiledBuffer; }
virtual ClientTiledLayerBuffer* GetLowPrecisionTiledBuffer() override { return nullptr; }
virtual bool SupportsLayerSize(const gfx::IntSize& aSize, ClientLayerManager* aManager) const override;
private:
RefPtr<ClientSingleTiledLayerBuffer> mTiledBuffer;
};
+104 -102
View File
@@ -916,47 +916,47 @@ ClientMultiTiledLayerBuffer::PaintThebes(const nsIntRegion& aNewValidRegion,
long start = PR_IntervalNow();
#endif
// If this region is empty XMost() - 1 will give us a negative value.
NS_ASSERTION(!aPaintRegion.GetBounds().IsEmpty(), "Empty paint region\n");
if (!gfxPrefs::TiledDrawTargetEnabled()) {
RefPtr<gfxContext> ctxt;
if (!aPaintRegion.IsEmpty()) {
const IntRect bounds = aPaintRegion.GetBounds();
{
PROFILER_LABEL("ClientMultiTiledLayerBuffer", "PaintThebesSingleBufferAlloc",
RefPtr<gfxContext> ctxt;
const IntRect bounds = aPaintRegion.GetBounds();
{
PROFILER_LABEL("ClientMultiTiledLayerBuffer", "PaintThebesSingleBufferAlloc",
js::ProfileEntry::Category::GRAPHICS);
mSinglePaintDrawTarget =
gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(
gfx::IntSize(ceilf(bounds.width * mResolution),
ceilf(bounds.height * mResolution)),
gfxPlatform::GetPlatform()->Optimal2DFormatForContent(
GetContentType()));
if (!mSinglePaintDrawTarget) {
return;
}
ctxt = new gfxContext(mSinglePaintDrawTarget);
mSinglePaintBufferOffset = nsIntPoint(bounds.x, bounds.y);
}
ctxt->NewPath();
ctxt->SetMatrix(
ctxt->CurrentMatrix().Scale(mResolution, mResolution).
Translate(-bounds.x, -bounds.y));
#ifdef GFX_TILEDLAYER_PREF_WARNINGS
if (PR_IntervalNow() - start > 3) {
printf_stderr("Slow alloc %i\n", PR_IntervalNow() - start);
}
start = PR_IntervalNow();
#endif
PROFILER_LABEL("ClientMultiTiledLayerBuffer", "PaintThebesSingleBufferDraw",
js::ProfileEntry::Category::GRAPHICS);
mSinglePaintDrawTarget =
gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(
gfx::IntSize(ceilf(bounds.width * mResolution),
ceilf(bounds.height * mResolution)),
gfxPlatform::GetPlatform()->Optimal2DFormatForContent(
GetContentType()));
if (!mSinglePaintDrawTarget) {
return;
}
ctxt = new gfxContext(mSinglePaintDrawTarget);
mSinglePaintBufferOffset = nsIntPoint(bounds.x, bounds.y);
mCallback(mPaintedLayer, ctxt, aPaintRegion, aDirtyRegion,
DrawRegionClip::NONE, nsIntRegion(), mCallbackData);
}
ctxt->NewPath();
ctxt->SetMatrix(
ctxt->CurrentMatrix().Scale(mResolution, mResolution).
Translate(-bounds.x, -bounds.y));
#ifdef GFX_TILEDLAYER_PREF_WARNINGS
if (PR_IntervalNow() - start > 3) {
printf_stderr("Slow alloc %i\n", PR_IntervalNow() - start);
}
start = PR_IntervalNow();
#endif
PROFILER_LABEL("ClientMultiTiledLayerBuffer", "PaintThebesSingleBufferDraw",
js::ProfileEntry::Category::GRAPHICS);
mCallback(mPaintedLayer, ctxt, aPaintRegion, aDirtyRegion,
DrawRegionClip::NONE, nsIntRegion(), mCallbackData);
}
#ifdef GFX_TILEDLAYER_PREF_WARNINGS
@@ -1132,79 +1132,81 @@ void ClientMultiTiledLayerBuffer::Update(const nsIntRegion& newValidRegion,
oldRetainedTiles.Clear();
for (size_t i = 0; i < newTileCount; ++i) {
const TileIntPoint tilePosition = newTiles.TilePosition(i);
IntPoint tileOffset = GetTileOffset(tilePosition);
nsIntRegion tileDrawRegion = IntRect(tileOffset, scaledTileSize);
tileDrawRegion.AndWith(aPaintRegion);
if (tileDrawRegion.IsEmpty()) {
continue;
}
TileClient& tile = mRetainedTiles[i];
if (!ValidateTile(tile, GetTileOffset(tilePosition), tileDrawRegion)) {
gfxCriticalError() << "ValidateTile failed";
}
}
if (gfxPrefs::TiledDrawTargetEnabled() && mMoz2DTiles.size() > 0) {
gfx::TileSet tileset;
for (size_t i = 0; i < mMoz2DTiles.size(); ++i) {
mMoz2DTiles[i].mTileOrigin -= mTilingOrigin;
}
tileset.mTiles = &mMoz2DTiles[0];
tileset.mTileCount = mMoz2DTiles.size();
RefPtr<DrawTarget> drawTarget = gfx::Factory::CreateTiledDrawTarget(tileset);
drawTarget->SetTransform(Matrix());
RefPtr<gfxContext> ctx = new gfxContext(drawTarget);
ctx->SetMatrix(
ctx->CurrentMatrix().Scale(mResolution, mResolution).Translate(ThebesPoint(-mTilingOrigin)));
mCallback(mPaintedLayer, ctx, aPaintRegion, aDirtyRegion,
DrawRegionClip::DRAW, nsIntRegion(), mCallbackData);
mMoz2DTiles.clear();
// Reset:
mTilingOrigin = IntPoint(std::numeric_limits<int32_t>::max(),
std::numeric_limits<int32_t>::max());
}
bool edgePaddingEnabled = gfxPrefs::TileEdgePaddingEnabled();
for (uint32_t i = 0; i < mRetainedTiles.Length(); ++i) {
TileClient& tile = mRetainedTiles[i];
// Only worry about padding when not doing low-res because it simplifies
// the math and the artifacts won't be noticable
// Edge padding prevents sampling artifacts when compositing.
if (edgePaddingEnabled && mResolution == 1 &&
tile.mFrontBuffer && tile.mFrontBuffer->IsLocked()) {
if (!aPaintRegion.IsEmpty()) {
for (size_t i = 0; i < newTileCount; ++i) {
const TileIntPoint tilePosition = newTiles.TilePosition(i);
IntPoint tileOffset = GetTileOffset(tilePosition);
// Strictly speakig we want the unscaled rect here, but it doesn't matter
// because we only run this code when the resolution is equal to 1.
IntRect tileRect = IntRect(tileOffset.x, tileOffset.y,
GetTileSize().width, GetTileSize().height);
IntPoint tileOffset = GetTileOffset(tilePosition);
nsIntRegion tileDrawRegion = IntRect(tileOffset, scaledTileSize);
tileDrawRegion.AndWith(aPaintRegion);
nsIntRegion tileValidRegion = mValidRegion;
tileValidRegion.OrWith(tileDrawRegion);
if (tileDrawRegion.IsEmpty()) {
continue;
}
// We only need to pad out if the tile has area that's not valid
if (!tileValidRegion.Contains(tileRect)) {
tileValidRegion = tileValidRegion.Intersect(tileRect);
// translate the region into tile space and pad
tileValidRegion.MoveBy(-IntPoint(tileOffset.x, tileOffset.y));
RefPtr<DrawTarget> drawTarget = tile.mFrontBuffer->BorrowDrawTarget();
PadDrawTargetOutFromRegion(drawTarget, tileValidRegion);
TileClient& tile = mRetainedTiles[i];
if (!ValidateTile(tile, GetTileOffset(tilePosition), tileDrawRegion)) {
gfxCriticalError() << "ValidateTile failed";
}
}
UnlockTile(tile);
if (gfxPrefs::TiledDrawTargetEnabled() && mMoz2DTiles.size() > 0) {
gfx::TileSet tileset;
for (size_t i = 0; i < mMoz2DTiles.size(); ++i) {
mMoz2DTiles[i].mTileOrigin -= mTilingOrigin;
}
tileset.mTiles = &mMoz2DTiles[0];
tileset.mTileCount = mMoz2DTiles.size();
RefPtr<DrawTarget> drawTarget = gfx::Factory::CreateTiledDrawTarget(tileset);
drawTarget->SetTransform(Matrix());
RefPtr<gfxContext> ctx = new gfxContext(drawTarget);
ctx->SetMatrix(
ctx->CurrentMatrix().Scale(mResolution, mResolution).Translate(ThebesPoint(-mTilingOrigin)));
mCallback(mPaintedLayer, ctx, aPaintRegion, aDirtyRegion,
DrawRegionClip::DRAW, nsIntRegion(), mCallbackData);
mMoz2DTiles.clear();
// Reset:
mTilingOrigin = IntPoint(std::numeric_limits<int32_t>::max(),
std::numeric_limits<int32_t>::max());
}
bool edgePaddingEnabled = gfxPrefs::TileEdgePaddingEnabled();
for (uint32_t i = 0; i < mRetainedTiles.Length(); ++i) {
TileClient& tile = mRetainedTiles[i];
// Only worry about padding when not doing low-res because it simplifies
// the math and the artifacts won't be noticable
// Edge padding prevents sampling artifacts when compositing.
if (edgePaddingEnabled && mResolution == 1 &&
tile.mFrontBuffer && tile.mFrontBuffer->IsLocked()) {
const TileIntPoint tilePosition = newTiles.TilePosition(i);
IntPoint tileOffset = GetTileOffset(tilePosition);
// Strictly speakig we want the unscaled rect here, but it doesn't matter
// because we only run this code when the resolution is equal to 1.
IntRect tileRect = IntRect(tileOffset.x, tileOffset.y,
GetTileSize().width, GetTileSize().height);
nsIntRegion tileDrawRegion = IntRect(tileOffset, scaledTileSize);
tileDrawRegion.AndWith(aPaintRegion);
nsIntRegion tileValidRegion = mValidRegion;
tileValidRegion.OrWith(tileDrawRegion);
// We only need to pad out if the tile has area that's not valid
if (!tileValidRegion.Contains(tileRect)) {
tileValidRegion = tileValidRegion.Intersect(tileRect);
// translate the region into tile space and pad
tileValidRegion.MoveBy(-IntPoint(tileOffset.x, tileOffset.y));
RefPtr<DrawTarget> drawTarget = tile.mFrontBuffer->BorrowDrawTarget();
PadDrawTargetOutFromRegion(drawTarget, tileValidRegion);
}
}
UnlockTile(tile);
}
}
mTiles = newTiles;
@@ -1685,7 +1687,7 @@ BasicTiledLayerPaintData::ResetPaintData()
mLowPrecisionPaintCount = 0;
mPaintFinished = false;
mCompositionBounds.SetEmpty();
mCriticalDisplayPort.SetEmpty();
mCriticalDisplayPort = Nothing();
}
} // namespace layers
+3 -6
View File
@@ -318,10 +318,10 @@ struct BasicTiledLayerPaintData {
/*
* The critical displayport of the content from the nearest ancestor layer
* that represents scrollable content with a display port set. Empty if a
* critical displayport is not set.
* that represents scrollable content with a display port set. isNothing()
* if a critical displayport is not set.
*/
LayerIntRect mCriticalDisplayPort;
Maybe<LayerIntRect> mCriticalDisplayPort;
/*
* The render resolution of the document that the content this layer
@@ -628,9 +628,6 @@ public:
};
virtual void UpdatedBuffer(TiledBufferType aType) = 0;
virtual bool SupportsLayerSize(const gfx::IntSize& aSize, ClientLayerManager* aManager) const
{ return true; }
private:
const char* mName;
};
+1 -3
View File
@@ -148,8 +148,7 @@ CompositableHost::SetCompositor(Compositor* aCompositor)
bool
CompositableHost::AddMaskEffect(EffectChain& aEffects,
const gfx::Matrix4x4& aTransform,
bool aIs3D)
const gfx::Matrix4x4& aTransform)
{
CompositableTextureSourceRef source;
RefPtr<TextureHost> host = GetAsTextureHost();
@@ -174,7 +173,6 @@ CompositableHost::AddMaskEffect(EffectChain& aEffects,
RefPtr<EffectMask> effect = new EffectMask(source,
source->GetSize(),
aTransform);
effect->mIs3D = aIs3D;
aEffects.mSecondaryEffects[EffectTypes::MASK] = effect;
return true;
}
+1 -2
View File
@@ -121,8 +121,7 @@ public:
* @return true if the effect was added, false otherwise.
*/
bool AddMaskEffect(EffectChain& aEffects,
const gfx::Matrix4x4& aTransform,
bool aIs3D = false);
const gfx::Matrix4x4& aTransform);
void RemoveMaskEffect();
@@ -8,6 +8,7 @@
#include "apz/src/AsyncPanZoomController.h" // for AsyncPanZoomController
#include "FrameMetrics.h" // for FrameMetrics
#include "Units.h" // for LayerRect, LayerPixel, etc
#include "CompositableHost.h" // for CompositableHost
#include "gfxEnv.h" // for gfxEnv
#include "gfxPrefs.h" // for gfxPrefs
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
@@ -30,6 +31,7 @@
#include "nsISupportsUtils.h" // for NS_ADDREF, NS_RELEASE
#include "nsRegion.h" // for nsIntRegion
#include "nsTArray.h" // for AutoTArray
#include <stack>
#include "TextRenderer.h" // for TextRenderer
#include <vector>
#include "VRManager.h" // for VRManager
@@ -899,13 +899,15 @@ LayerManagerComposite::Render(const nsIntRegion& aInvalidRegion)
CompositorBench(mCompositor, bounds);
MOZ_ASSERT(mRoot->GetOpacity() == 1);
bool opaqueContent = (mRoot->GetContentFlags() & Layer::CONTENT_OPAQUE) != 0;
if (mRoot->GetClipRect()) {
clipRect = *mRoot->GetClipRect();
Rect rect(clipRect.x, clipRect.y, clipRect.width, clipRect.height);
mCompositor->BeginFrame(aInvalidRegion, &rect, bounds, nullptr, &actualBounds);
mCompositor->BeginFrame(aInvalidRegion, &rect, bounds, opaqueContent, nullptr, &actualBounds);
} else {
gfx::Rect rect;
mCompositor->BeginFrame(aInvalidRegion, nullptr, bounds, &rect, &actualBounds);
mCompositor->BeginFrame(aInvalidRegion, nullptr, bounds, opaqueContent, &rect, &actualBounds);
clipRect = ParentLayerIntRect(rect.x, rect.y, rect.width, rect.height);
}
@@ -1158,8 +1160,10 @@ LayerManagerComposite::RenderToPresentationSurface()
nsIntRegion invalid;
Rect bounds(0.0f, 0.0f, scale * pageWidth, (float)actualHeight);
Rect rect, actualBounds;
MOZ_ASSERT(mRoot->GetOpacity() == 1);
bool opaqueContent = (mRoot->GetContentFlags() & Layer::CONTENT_OPAQUE) != 0;
mCompositor->BeginFrame(invalid, nullptr, bounds, &rect, &actualBounds);
mCompositor->BeginFrame(invalid, nullptr, bounds, opaqueContent, &rect, &actualBounds);
// The Java side of Fennec sets a scissor rect that accounts for
// chrome such as the URL bar. Override that so that the entire frame buffer
@@ -1462,8 +1466,7 @@ LayerManagerComposite::CreateRefLayerComposite()
}
LayerManagerComposite::AutoAddMaskEffect::AutoAddMaskEffect(Layer* aMaskLayer,
EffectChain& aEffects,
bool aIs3D)
EffectChain& aEffects)
: mCompositable(nullptr), mFailed(false)
{
if (!aMaskLayer) {
@@ -1477,7 +1480,7 @@ LayerManagerComposite::AutoAddMaskEffect::AutoAddMaskEffect(Layer* aMaskLayer,
return;
}
if (!mCompositable->AddMaskEffect(aEffects, aMaskLayer->GetEffectiveTransform(), aIs3D)) {
if (!mCompositable->AddMaskEffect(aEffects, aMaskLayer->GetEffectiveTransform())) {
mCompositable = nullptr;
mFailed = true;
}
+3 -9
View File
@@ -188,8 +188,7 @@ public:
{
public:
AutoAddMaskEffect(Layer* aMaskLayer,
EffectChain& aEffect,
bool aIs3D = false);
EffectChain& aEffect);
~AutoAddMaskEffect();
bool Failed() const { return mFailed; }
@@ -582,16 +581,11 @@ RenderWithAllMasks(Layer* aLayer, Compositor* aCompositor,
// no mask layers at all
}
bool firstMaskIs3D = false;
if (ContainerLayer* container = aLayer->AsContainerLayer()) {
firstMaskIs3D = !container->GetTransform().CanDraw2D();
}
if (maskLayerCount <= 1) {
// This is the common case. Render in one pass and return.
EffectChain effectChain(aLayer);
LayerManagerComposite::AutoAddMaskEffect
autoMaskEffect(firstMask, effectChain, firstMaskIs3D);
autoMaskEffect(firstMask, effectChain);
aLayer->AsLayerComposite()->AddBlendModeEffect(effectChain);
aRenderCallback(effectChain, gfx::Rect(aClipRect));
return;
@@ -630,7 +624,7 @@ RenderWithAllMasks(Layer* aLayer, Compositor* aCompositor,
{
EffectChain firstEffectChain(aLayer);
LayerManagerComposite::AutoAddMaskEffect
firstMaskEffect(firstMask, firstEffectChain, firstMaskIs3D);
firstMaskEffect(firstMask, firstEffectChain);
aRenderCallback(firstEffectChain, gfx::Rect(aClipRect - surfaceRect.TopLeft()));
// firstTarget now contains the transformed source with the first mask and
// opacity already applied.
+4
View File
@@ -565,6 +565,10 @@ public:
virtual void WaitAcquireFenceHandleSyncComplete() {};
virtual bool NeedsFenceHandle() { return false; }
virtual FenceHandle GetCompositorReleaseFence() { return FenceHandle(); }
protected:
FenceHandle mReleaseFenceHandle;
+2 -4
View File
@@ -14,8 +14,7 @@
// These must be in the same order as the Mask enum.
#define PS_MASK_NONE 0
#define PS_MASK_2D 1
#define PS_MASK_3D 2
#define PS_MASK 1
// These must be in the same order as CompositionOp.
#define PS_BLEND_MULTIPLY 0
@@ -50,8 +49,7 @@ BlendOpToShaderConstant(gfx::CompositionOp aOp) {
namespace {
static inline void BlendShaderConstantAsserts() {
static_assert(PS_MASK_NONE == int(mozilla::layers::MaskType::MaskNone), "shader constant is out of sync");
static_assert(PS_MASK_2D == int(mozilla::layers::MaskType::Mask2d), "shader constant is out of sync");
static_assert(PS_MASK_3D == int(mozilla::layers::MaskType::Mask3d), "shader constant is out of sync");
static_assert(PS_MASK == int(mozilla::layers::MaskType::Mask), "shader constant is out of sync");
static_assert(int(mozilla::gfx::CompositionOp::OP_LUMINOSITY) - int(mozilla::gfx::CompositionOp::OP_MULTIPLY) == 14,
"shader constants are out of sync");
}
+9 -16
View File
@@ -907,12 +907,7 @@ CompositorD3D11::DrawQuad(const gfx::Rect& aRect,
MaskType maskType = MaskType::MaskNone;
if (aEffectChain.mSecondaryEffects[EffectTypes::MASK]) {
if (aTransform.Is2D()) {
maskType = MaskType::Mask2d;
} else {
MOZ_ASSERT(aEffectChain.mPrimaryEffect->mType == EffectTypes::RGB);
maskType = MaskType::Mask3d;
}
maskType = MaskType::Mask;
EffectMask* maskEffect =
static_cast<EffectMask*>(aEffectChain.mSecondaryEffects[EffectTypes::MASK].get());
@@ -1129,6 +1124,7 @@ void
CompositorD3D11::BeginFrame(const nsIntRegion& aInvalidRegion,
const Rect* aClipRectIn,
const Rect& aRenderBounds,
bool aOpaque,
Rect* aClipRectOut,
Rect* aRenderBoundsOut)
{
@@ -1493,8 +1489,7 @@ DeviceAttachmentsD3D11::InitBlendShaders()
{
if (!mVSQuadBlendShader[MaskType::MaskNone]) {
InitVertexShader(sLayerQuadBlendVS, mVSQuadBlendShader, MaskType::MaskNone);
InitVertexShader(sLayerQuadBlendMaskVS, mVSQuadBlendShader, MaskType::Mask2d);
InitVertexShader(sLayerQuadBlendMask3DVS, mVSQuadBlendShader, MaskType::Mask3d);
InitVertexShader(sLayerQuadBlendMaskVS, mVSQuadBlendShader, MaskType::Mask);
}
if (!mBlendShader[MaskType::MaskNone]) {
InitPixelShader(sBlendShader, mBlendShader, MaskType::MaskNone);
@@ -1506,21 +1501,19 @@ bool
DeviceAttachmentsD3D11::CreateShaders()
{
InitVertexShader(sLayerQuadVS, mVSQuadShader, MaskType::MaskNone);
InitVertexShader(sLayerQuadMaskVS, mVSQuadShader, MaskType::Mask2d);
InitVertexShader(sLayerQuadMask3DVS, mVSQuadShader, MaskType::Mask3d);
InitVertexShader(sLayerQuadMaskVS, mVSQuadShader, MaskType::Mask);
InitPixelShader(sSolidColorShader, mSolidColorShader, MaskType::MaskNone);
InitPixelShader(sSolidColorShaderMask, mSolidColorShader, MaskType::Mask2d);
InitPixelShader(sSolidColorShaderMask, mSolidColorShader, MaskType::Mask);
InitPixelShader(sRGBShader, mRGBShader, MaskType::MaskNone);
InitPixelShader(sRGBShaderMask, mRGBShader, MaskType::Mask2d);
InitPixelShader(sRGBShaderMask, mRGBShader, MaskType::Mask);
InitPixelShader(sRGBAShader, mRGBAShader, MaskType::MaskNone);
InitPixelShader(sRGBAShaderMask, mRGBAShader, MaskType::Mask2d);
InitPixelShader(sRGBAShaderMask3D, mRGBAShader, MaskType::Mask3d);
InitPixelShader(sRGBAShaderMask, mRGBAShader, MaskType::Mask);
InitPixelShader(sYCbCrShader, mYCbCrShader, MaskType::MaskNone);
InitPixelShader(sYCbCrShaderMask, mYCbCrShader, MaskType::Mask2d);
InitPixelShader(sYCbCrShaderMask, mYCbCrShader, MaskType::Mask);
if (gfxPrefs::ComponentAlphaEnabled()) {
InitPixelShader(sComponentAlphaShader, mComponentAlphaShader, MaskType::MaskNone);
InitPixelShader(sComponentAlphaShaderMask, mComponentAlphaShader, MaskType::Mask2d);
InitPixelShader(sComponentAlphaShaderMask, mComponentAlphaShader, MaskType::Mask);
}
InitVertexShader(sOculus050VRDistortionVS, getter_AddRefs(mVRDistortionVS[VRHMDType::Oculus050]));
+1
View File
@@ -111,6 +111,7 @@ public:
virtual void BeginFrame(const nsIntRegion& aInvalidRegion,
const gfx::Rect *aClipRectIn,
const gfx::Rect& aRenderBounds,
bool aOpaque,
gfx::Rect *aClipRectOut = nullptr,
gfx::Rect *aRenderBoundsOut = nullptr) override;
+6 -55
View File
@@ -47,12 +47,6 @@ struct VS_OUTPUT {
};
struct VS_MASK_OUTPUT {
float4 vPosition : SV_Position;
float2 vTexCoords : TEXCOORD0;
float2 vMaskCoords : TEXCOORD1;
};
struct VS_MASK_3D_OUTPUT {
float4 vPosition : SV_Position;
float2 vTexCoords : TEXCOORD0;
float3 vMaskCoords : TEXCOORD1;
@@ -153,23 +147,6 @@ VS_MASK_OUTPUT LayerQuadMaskVS(const VS_INPUT aVertex)
// calculate the position on the mask texture
outp.vMaskCoords.x = (position.x - vMaskQuad.x) / vMaskQuad.z;
outp.vMaskCoords.y = (position.y - vMaskQuad.y) / vMaskQuad.w;
outp.vTexCoords = TexCoords(aVertex.vPosition.xy);
return outp;
}
VS_MASK_3D_OUTPUT LayerQuadMask3DVS(const VS_INPUT aVertex)
{
VS_MASK_3D_OUTPUT outp;
float4 position = TransformedPosition(aVertex.vPosition);
outp.vPosition = VertexPosition(position);
// calculate the position on the mask texture
position.xyz /= position.w;
outp.vMaskCoords.x = (position.x - vMaskQuad.x) / vMaskQuad.z;
outp.vMaskCoords.y = (position.y - vMaskQuad.y) / vMaskQuad.w;
// We use the w coord to do non-perspective correct interpolation:
// the quad might be transformed in 3D, in which case it will have some
// perspective. The graphics card will do perspective-correct interpolation
@@ -187,16 +164,9 @@ VS_MASK_3D_OUTPUT LayerQuadMask3DVS(const VS_INPUT aVertex)
}
float4 RGBAShaderMask(const VS_MASK_OUTPUT aVertex) : SV_Target
{
float2 maskCoords = aVertex.vMaskCoords;
float mask = tMask.Sample(sSampler, maskCoords).r;
return tRGB.Sample(sSampler, aVertex.vTexCoords) * fLayerOpacity * mask;
}
float4 RGBAShaderMask3D(const VS_MASK_3D_OUTPUT aVertex) : SV_Target
{
float2 maskCoords = aVertex.vMaskCoords.xy / aVertex.vMaskCoords.z;
float mask = tMask.Sample(LayerTextureSamplerLinear, maskCoords).r;
float mask = tMask.Sample(sSampler, maskCoords).r;
return tRGB.Sample(sSampler, aVertex.vTexCoords) * fLayerOpacity * mask;
}
@@ -206,7 +176,7 @@ float4 RGBShaderMask(const VS_MASK_OUTPUT aVertex) : SV_Target
result = tRGB.Sample(sSampler, aVertex.vTexCoords) * fLayerOpacity;
result.a = fLayerOpacity;
float2 maskCoords = aVertex.vMaskCoords;
float2 maskCoords = aVertex.vMaskCoords.xy / aVertex.vMaskCoords.z;
float mask = tMask.Sample(sSampler, maskCoords).r;
return result * mask;
}
@@ -240,7 +210,7 @@ float4 CalculateYCbCrColor(const float2 aTexCoords)
float4 YCbCrShaderMask(const VS_MASK_OUTPUT aVertex) : SV_Target
{
float2 maskCoords = aVertex.vMaskCoords;
float2 maskCoords = aVertex.vMaskCoords.xy / aVertex.vMaskCoords.z;
float mask = tMask.Sample(sSampler, maskCoords).r;
return CalculateYCbCrColor(aVertex.vTexCoords) * fLayerOpacity * mask;
@@ -254,7 +224,7 @@ PS_OUTPUT ComponentAlphaShaderMask(const VS_MASK_OUTPUT aVertex) : SV_Target
result.vAlpha = 1.0 - tRGBWhite.Sample(sSampler, aVertex.vTexCoords) + result.vSrc;
result.vSrc.a = result.vAlpha.g;
float2 maskCoords = aVertex.vMaskCoords;
float2 maskCoords = aVertex.vMaskCoords.xy / aVertex.vMaskCoords.z;
float mask = tMask.Sample(sSampler, maskCoords).r;
result.vSrc *= fLayerOpacity * mask;
result.vAlpha *= fLayerOpacity * mask;
@@ -264,7 +234,7 @@ PS_OUTPUT ComponentAlphaShaderMask(const VS_MASK_OUTPUT aVertex) : SV_Target
float4 SolidColorShaderMask(const VS_MASK_OUTPUT aVertex) : SV_Target
{
float2 maskCoords = aVertex.vMaskCoords;
float2 maskCoords = aVertex.vMaskCoords.xy / aVertex.vMaskCoords.z;
float mask = tMask.Sample(sSampler, maskCoords).r;
return fLayerColor * mask;
}
@@ -325,18 +295,6 @@ VS_BLEND_OUTPUT LayerQuadBlendMaskVS(const VS_INPUT aVertex)
{
VS_MASK_OUTPUT v = LayerQuadMaskVS(aVertex);
VS_BLEND_OUTPUT o;
o.vPosition = v.vPosition;
o.vTexCoords = v.vTexCoords;
o.vMaskCoords = float3(v.vMaskCoords, 0);
o.vBackdropCoords = BackdropPosition(v.vPosition);
return o;
}
VS_BLEND_OUTPUT LayerQuadBlendMask3DVS(const VS_INPUT aVertex)
{
VS_MASK_3D_OUTPUT v = LayerQuadMask3DVS(aVertex);
VS_BLEND_OUTPUT o;
o.vPosition = v.vPosition;
o.vTexCoords = v.vTexCoords;
@@ -367,7 +325,7 @@ float4 ComputeBlendSourceColor(const VS_BLEND_OUTPUT aVertex)
VS_MASK_OUTPUT tmp;
tmp.vPosition = aVertex.vPosition;
tmp.vTexCoords = aVertex.vTexCoords;
tmp.vMaskCoords = aVertex.vMaskCoords.xy;
tmp.vMaskCoords = aVertex.vMaskCoords;
if (iBlendConfig.x == PS_LAYER_RGB) {
return RGBShaderMask(tmp);
@@ -377,13 +335,6 @@ float4 ComputeBlendSourceColor(const VS_BLEND_OUTPUT aVertex)
return YCbCrShaderMask(tmp);
}
return SolidColorShaderMask(tmp);
} else if (iBlendConfig.y == PS_MASK_3D) {
// The only Mask 3D shader is RGBA.
VS_MASK_3D_OUTPUT tmp;
tmp.vPosition = aVertex.vPosition;
tmp.vTexCoords = aVertex.vTexCoords;
tmp.vMaskCoords = aVertex.vMaskCoords;
return RGBAShaderMask3D(tmp);
}
return float4(0.0, 0.0, 0.0, 1.0);
File diff suppressed because it is too large Load Diff
+24 -24
View File
@@ -1,6 +1,6 @@
#if 0
//
// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
// Generated by Microsoft (R) HLSL Shader Compiler 10.0.10011.16384
//
//
// Buffer Definitions:
@@ -16,9 +16,9 @@
//
// Resource Bindings:
//
// Name Type Format Dim Slot Elements
// ------------------------------ ---------- ------- ----------- ---- --------
// $Globals cbuffer NA NA 0 1
// Name Type Format Dim HLSL Bind Count
// ------------------------------ ---------- ------- ----------- -------------- ------
// $Globals cbuffer NA NA cb0 1
//
//
//
@@ -80,7 +80,7 @@
// approximately 10 instruction slots used
vs_4_0
dcl_constantbuffer cb0[2], immediateIndexed
dcl_constantbuffer CB0[2], immediateIndexed
dcl_input v0.xy
dcl_input v1.xy
dcl_input v2.xy
@@ -106,10 +106,10 @@ ret
const BYTE Oculus050VRDistortionVS[] =
{
68, 88, 66, 67, 3, 61,
196, 122, 10, 53, 44, 234,
18, 242, 195, 238, 42, 90,
72, 193, 1, 0, 0, 0,
68, 88, 66, 67, 92, 195,
173, 230, 45, 84, 78, 45,
143, 175, 88, 53, 65, 235,
243, 174, 1, 0, 0, 0,
244, 5, 0, 0, 6, 0,
0, 0, 56, 0, 0, 0,
108, 1, 0, 0, 44, 3,
@@ -303,9 +303,9 @@ const BYTE Oculus050VRDistortionVS[] =
83, 76, 32, 83, 104, 97,
100, 101, 114, 32, 67, 111,
109, 112, 105, 108, 101, 114,
32, 54, 46, 51, 46, 57,
54, 48, 48, 46, 49, 54,
51, 56, 52, 0, 171, 171,
32, 49, 48, 46, 48, 46,
49, 48, 48, 49, 49, 46,
49, 54, 51, 56, 52, 0,
73, 83, 71, 78, 152, 0,
0, 0, 5, 0, 0, 0,
8, 0, 0, 0, 128, 0,
@@ -364,15 +364,15 @@ const BYTE Oculus050VRDistortionVS[] =
ShaderBytes sOculus050VRDistortionVS = { Oculus050VRDistortionVS, sizeof(Oculus050VRDistortionVS) };
#if 0
//
// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
// Generated by Microsoft (R) HLSL Shader Compiler 10.0.10011.16384
//
//
// Resource Bindings:
//
// Name Type Format Dim Slot Elements
// ------------------------------ ---------- ------- ----------- ---- --------
// Linear sampler NA NA 0 1
// Texture texture float4 2d 0 1
// Name Type Format Dim HLSL Bind Count
// ------------------------------ ---------- ------- ----------- -------------- ------
// Linear sampler NA NA s0 1
// Texture texture float4 2d t0 1
//
//
//
@@ -442,10 +442,10 @@ ret
const BYTE Oculus050VRDistortionPS[] =
{
68, 88, 66, 67, 108, 219,
61, 216, 27, 0, 27, 222,
242, 132, 183, 21, 166, 141,
130, 39, 1, 0, 0, 0,
68, 88, 66, 67, 17, 210,
217, 234, 219, 61, 77, 84,
3, 36, 81, 127, 138, 35,
252, 53, 1, 0, 0, 0,
128, 4, 0, 0, 6, 0,
0, 0, 56, 0, 0, 0,
60, 1, 0, 0, 132, 2,
@@ -595,9 +595,9 @@ const BYTE Oculus050VRDistortionPS[] =
76, 32, 83, 104, 97, 100,
101, 114, 32, 67, 111, 109,
112, 105, 108, 101, 114, 32,
54, 46, 51, 46, 57, 54,
48, 48, 46, 49, 54, 51,
56, 52, 0, 171, 171, 171,
49, 48, 46, 48, 46, 49,
48, 48, 49, 49, 46, 49,
54, 51, 56, 52, 0, 171,
73, 83, 71, 78, 156, 0,
0, 0, 5, 0, 0, 0,
8, 0, 0, 0, 128, 0,
-3
View File
@@ -36,18 +36,15 @@ makeShaderPS RGBAShader
makeShaderPS ComponentAlphaShader
makeShaderPS YCbCrShader
makeShaderVS LayerQuadMaskVS
makeShaderVS LayerQuadMask3DVS
makeShaderPS SolidColorShaderMask
makeShaderPS RGBShaderMask
makeShaderPS RGBAShaderMask
makeShaderPS RGBAShaderMask3D
makeShaderPS YCbCrShaderMask
makeShaderPS ComponentAlphaShaderMask
# Mix-blend shaders
makeShaderVS LayerQuadBlendVS
makeShaderVS LayerQuadBlendMaskVS
makeShaderVS LayerQuadBlendMask3DVS
makeShaderPS BlendShader
SRC=CompositorD3D11VR.hlsl
+3 -6
View File
@@ -265,7 +265,7 @@ CompositorD3D9::DrawQuad(const gfx::Rect &aRect,
d3d9Device->SetVertexShaderConstantF(CBmLayerTransform, &aTransform._11, 4);
IntPoint origin = mCurrentRT->GetOrigin();
float renderTargetOffset[] = { origin.x, origin.y, 0, 0 };
float renderTargetOffset[] = { float(origin.x), float(origin.y), 0, 0 };
d3d9Device->SetVertexShaderConstantF(CBvRenderTargetOffset,
renderTargetOffset,
1);
@@ -291,11 +291,7 @@ CompositorD3D9::DrawQuad(const gfx::Rect &aRect,
MaskType maskType = MaskType::MaskNone;
if (aEffectChain.mSecondaryEffects[EffectTypes::MASK]) {
if (aTransform.Is2D()) {
maskType = MaskType::Mask2d;
} else {
maskType = MaskType::Mask3d;
}
maskType = MaskType::Mask;
}
gfx::Rect backdropDest;
@@ -682,6 +678,7 @@ void
CompositorD3D9::BeginFrame(const nsIntRegion& aInvalidRegion,
const Rect *aClipRectIn,
const Rect& aRenderBounds,
bool aOpaque,
Rect *aClipRectOut,
Rect *aRenderBoundsOut)
{
+1
View File
@@ -64,6 +64,7 @@ public:
virtual void BeginFrame(const nsIntRegion& aInvalidRegion,
const gfx::Rect *aClipRectIn,
const gfx::Rect& aRenderBounds,
bool aOpaque,
gfx::Rect *aClipRectOut = nullptr,
gfx::Rect *aRenderBoundsOut = nullptr) override;
+2 -22
View File
@@ -424,13 +424,6 @@ DeviceManagerD3D9::Init()
gfxCriticalError() << failCreateShaderMsg << "LayerQuadVSMask: " << gfx::hexa(hr);
return false;
}
hr = mDevice->CreateVertexShader((DWORD*)LayerQuadVSMask3D,
getter_AddRefs(mLayerVSMask3D));
if (FAILED(hr)) {
gfxCriticalError() << failCreateShaderMsg << "LayerQuadVSMask3D: " << gfx::hexa(hr);
return false;
}
hr = mDevice->CreatePixelShader((DWORD*)RGBShaderPSMask,
getter_AddRefs(mRGBPSMask));
@@ -448,14 +441,6 @@ DeviceManagerD3D9::Init()
return false;
}
hr = mDevice->CreatePixelShader((DWORD*)RGBAShaderPSMask3D,
getter_AddRefs(mRGBAPSMask3D));
if (FAILED(hr)) {
gfxCriticalError() << failCreateShaderMsg << "RGBAShaderPSMask3D: " << gfx::hexa(hr);
return false;
}
hr = mDevice->CreatePixelShader((DWORD*)ComponentPass1ShaderPSMask,
getter_AddRefs(mComponentPass1PSMask));
@@ -625,13 +610,8 @@ DeviceManagerD3D9::SetShaderMode(ShaderMode aMode, MaskType aMaskType)
maskTexRegister = 1;
break;
case RGBALAYER:
if (aMaskType == MaskType::Mask2d) {
mDevice->SetVertexShader(mLayerVSMask);
mDevice->SetPixelShader(mRGBAPSMask);
} else {
mDevice->SetVertexShader(mLayerVSMask3D);
mDevice->SetPixelShader(mRGBAPSMask3D);
}
mDevice->SetVertexShader(mLayerVSMask);
mDevice->SetPixelShader(mRGBAPSMask);
maskTexRegister = 1;
break;
case COMPONENTLAYERPASS1:
-2
View File
@@ -272,10 +272,8 @@ private:
/* As above, but using a mask layer */
RefPtr<IDirect3DVertexShader9> mLayerVSMask;
RefPtr<IDirect3DVertexShader9> mLayerVSMask3D;
RefPtr<IDirect3DPixelShader9> mRGBPSMask;
RefPtr<IDirect3DPixelShader9> mRGBAPSMask;
RefPtr<IDirect3DPixelShader9> mRGBAPSMask3D;
RefPtr<IDirect3DPixelShader9> mComponentPass1PSMask;
RefPtr<IDirect3DPixelShader9> mComponentPass2PSMask;
RefPtr<IDirect3DPixelShader9> mYCbCrPSMask;
File diff suppressed because it is too large Load Diff
+6 -58
View File
@@ -29,12 +29,6 @@ struct VS_OUTPUT {
};
struct VS_OUTPUT_MASK {
float4 vPosition : POSITION;
float2 vTexCoords : TEXCOORD0;
float2 vMaskCoords : TEXCOORD1;
};
struct VS_OUTPUT_MASK_3D {
float4 vPosition : POSITION;
float2 vTexCoords : TEXCOORD0;
float3 vMaskCoords : TEXCOORD1;
@@ -105,46 +99,7 @@ VS_OUTPUT_MASK LayerQuadVSMask(const VS_INPUT aVertex)
// calculate the position on the mask texture
outp.vMaskCoords.x = (position.x - vMaskQuad.x) / vMaskQuad.z;
outp.vMaskCoords.y = (position.y - vMaskQuad.y) / vMaskQuad.w;
size = vTextureCoords.zw;
outp.vTexCoords.x = vTextureCoords.x + aVertex.vPosition.x * size.x;
outp.vTexCoords.y = vTextureCoords.y + aVertex.vPosition.y * size.y;
return outp;
}
VS_OUTPUT_MASK_3D LayerQuadVSMask3D(const VS_INPUT aVertex)
{
VS_OUTPUT_MASK_3D outp;
float4 position = float4(0, 0, 0, 1);
// We use 4 component floats to uniquely describe a rectangle, by the structure
// of x, y, width, height. This allows us to easily generate the 4 corners
// of any rectangle from the 4 corners of the 0,0-1,1 quad that we use as the
// stream source for our LayerQuad vertex shader. We do this by doing:
// Xout = x + Xin * width
// Yout = y + Yin * height
float2 size = vLayerQuad.zw;
position.x = vLayerQuad.x + aVertex.vPosition.x * size.x;
position.y = vLayerQuad.y + aVertex.vPosition.y * size.y;
position = mul(mLayerTransform, position);
outp.vPosition.w = position.w;
outp.vPosition.xyz = position.xyz / position.w;
outp.vPosition = outp.vPosition - vRenderTargetOffset;
outp.vPosition.xyz *= outp.vPosition.w;
// adjust our vertices to match d3d9's pixel coordinate system
// which has pixel centers at integer locations
outp.vPosition.xy -= 0.5;
outp.vPosition = mul(mProjection, outp.vPosition);
// calculate the position on the mask texture
position.xyz /= position.w;
outp.vMaskCoords.x = (position.x - vMaskQuad.x) / vMaskQuad.z;
outp.vMaskCoords.y = (position.y - vMaskQuad.y) / vMaskQuad.w;
// correct for perspective correct interpolation, see comment in D3D10 shader
// correct for perspective correct interpolation, see comment in D3D11 shader
outp.vMaskCoords.z = 1;
outp.vMaskCoords *= position.w;
@@ -211,7 +166,7 @@ float4 ComponentPass1ShaderMask(const VS_OUTPUT_MASK aVertex) : COLOR
float4 src = tex2D(s2D, aVertex.vTexCoords);
float4 alphas = 1.0 - tex2D(s2DWhite, aVertex.vTexCoords) + src;
alphas.a = alphas.g;
float2 maskCoords = aVertex.vMaskCoords;
float2 maskCoords = aVertex.vMaskCoords.xy / aVertex.vMaskCoords.z;
float mask = tex2D(s2DMask, maskCoords).a;
return alphas * fLayerOpacity * mask;
}
@@ -221,19 +176,12 @@ float4 ComponentPass2ShaderMask(const VS_OUTPUT_MASK aVertex) : COLOR
float4 src = tex2D(s2D, aVertex.vTexCoords);
float4 alphas = 1.0 - tex2D(s2DWhite, aVertex.vTexCoords) + src;
src.a = alphas.g;
float2 maskCoords = aVertex.vMaskCoords;
float2 maskCoords = aVertex.vMaskCoords.xy / aVertex.vMaskCoords.z;
float mask = tex2D(s2DMask, maskCoords).a;
return src * fLayerOpacity * mask;
}
float4 RGBAShaderMask(const VS_OUTPUT_MASK aVertex) : COLOR
{
float2 maskCoords = aVertex.vMaskCoords;
float mask = tex2D(s2DMask, maskCoords).a;
return tex2D(s2D, aVertex.vTexCoords) * fLayerOpacity * mask;
}
float4 RGBAShaderMask3D(const VS_OUTPUT_MASK_3D aVertex) : COLOR
{
float2 maskCoords = aVertex.vMaskCoords.xy / aVertex.vMaskCoords.z;
float mask = tex2D(s2DMask, maskCoords).a;
@@ -245,7 +193,7 @@ float4 RGBShaderMask(const VS_OUTPUT_MASK aVertex) : COLOR
float4 result;
result = tex2D(s2D, aVertex.vTexCoords);
result.a = 1.0;
float2 maskCoords = aVertex.vMaskCoords;
float2 maskCoords = aVertex.vMaskCoords.xy / aVertex.vMaskCoords.z;
float mask = tex2D(s2DMask, maskCoords).a;
return result * fLayerOpacity * mask;
}
@@ -274,14 +222,14 @@ float4 YCbCrShaderMask(const VS_OUTPUT_MASK aVertex) : COLOR
color.b = yuv.g * 1.16438 + yuv.b * 2.01723;
color.a = 1.0f;
float2 maskCoords = aVertex.vMaskCoords;
float2 maskCoords = aVertex.vMaskCoords.xy / aVertex.vMaskCoords.z;
float mask = tex2D(s2DMask, maskCoords).a;
return color * fLayerOpacity * mask;
}
float4 SolidColorShaderMask(const VS_OUTPUT_MASK aVertex) : COLOR
{
float2 maskCoords = aVertex.vMaskCoords;
float2 maskCoords = aVertex.vMaskCoords.xy / aVertex.vMaskCoords.z;
float mask = tex2D(s2DMask, maskCoords).a;
return fLayerColor * mask;
}
-4
View File
@@ -20,12 +20,8 @@ fxc LayerManagerD3D9Shaders.hlsl -ESolidColorShader -nologo -Tps_2_0 -Fh$tempfil
cat $tempfile >> LayerManagerD3D9Shaders.h
fxc LayerManagerD3D9Shaders.hlsl -ELayerQuadVSMask -nologo -Fh$tempfile -VnLayerQuadVSMask
cat $tempfile >> LayerManagerD3D9Shaders.h
fxc LayerManagerD3D9Shaders.hlsl -ELayerQuadVSMask3D -nologo -Fh$tempfile -VnLayerQuadVSMask3D
cat $tempfile >> LayerManagerD3D9Shaders.h
fxc LayerManagerD3D9Shaders.hlsl -ERGBAShaderMask -nologo -Tps_2_0 -Fh$tempfile -VnRGBAShaderPSMask
cat $tempfile >> LayerManagerD3D9Shaders.h
fxc LayerManagerD3D9Shaders.hlsl -ERGBAShaderMask3D -nologo -Tps_2_0 -Fh$tempfile -VnRGBAShaderPSMask3D
cat $tempfile >> LayerManagerD3D9Shaders.h
fxc LayerManagerD3D9Shaders.hlsl -EComponentPass1ShaderMask -nologo -Tps_2_0 -Fh$tempfile -VnComponentPass1ShaderPSMask
cat $tempfile >> LayerManagerD3D9Shaders.h
fxc LayerManagerD3D9Shaders.hlsl -EComponentPass2ShaderMask -nologo -Tps_2_0 -Fh$tempfile -VnComponentPass2ShaderPSMask
@@ -133,7 +133,7 @@ CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation
MOZ_ASSERT(tex.get());
compositable->RemoveTextureHost(tex);
// send FenceHandle if present.
SendFenceHandleIfPresent(op.textureParent(), compositable);
SendFenceHandleIfPresent(op.textureParent());
break;
}
case CompositableOperation::TOpRemoveTextureAsync: {
@@ -150,8 +150,7 @@ CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation
GetChildProcessId(),
op.holderId(),
op.transactionId(),
op.textureParent(),
compositable);
op.textureParent());
// If the message is recievied via PLayerTransaction,
// Send message back via PImageBridge.
@@ -161,7 +160,7 @@ CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation
op.transactionId()));
} else {
// send FenceHandle if present.
SendFenceHandleIfPresent(op.textureParent(), compositable);
SendFenceHandleIfPresent(op.textureParent());
ReplyRemoveTexture(OpReplyRemoveTexture(op.holderId(),
op.transactionId()));
@@ -28,8 +28,7 @@ typedef std::vector<mozilla::layers::EditReply> EditReplyVector;
class CompositableParentManager : public ISurfaceAllocator
{
public:
virtual void SendFenceHandleIfPresent(PTextureParent* aTexture,
CompositableHost* aCompositableHost) = 0;
virtual void SendFenceHandleIfPresent(PTextureParent* aTexture) = 0;
virtual void SendAsyncMessage(const InfallibleTArray<AsyncParentMessageData>& aMessage) = 0;
+19 -27
View File
@@ -447,25 +447,22 @@ ImageBridgeParent::ReplyRemoveTexture(base::ProcessId aChildProcessId,
}
void
ImageBridgeParent::SendFenceHandleIfPresent(PTextureParent* aTexture,
CompositableHost* aCompositableHost)
ImageBridgeParent::SendFenceHandleIfPresent(PTextureParent* aTexture)
{
RefPtr<TextureHost> texture = TextureHost::AsTextureHost(aTexture);
if (!texture) {
if (!texture || !texture->NeedsFenceHandle()) {
return;
}
// Send a ReleaseFence of CompositorOGL.
if (aCompositableHost && aCompositableHost->GetCompositor()) {
FenceHandle fence = aCompositableHost->GetCompositor()->GetReleaseFence();
if (fence.IsValid()) {
mPendingAsyncMessage.push_back(OpDeliverFence(aTexture, nullptr,
fence));
}
FenceHandle fence = texture->GetCompositorReleaseFence();
if (fence.IsValid()) {
mPendingAsyncMessage.push_back(OpDeliverFence(aTexture, nullptr,
fence));
}
// Send a ReleaseFence that is set by HwcComposer2D.
FenceHandle fence = texture->GetAndResetReleaseFenceHandle();
// Send a ReleaseFence that is set to TextureHost by HwcComposer2D.
fence = texture->GetAndResetReleaseFenceHandle();
if (fence.IsValid()) {
mPendingAsyncMessage.push_back(OpDeliverFence(aTexture, nullptr,
fence));
@@ -475,26 +472,23 @@ ImageBridgeParent::SendFenceHandleIfPresent(PTextureParent* aTexture,
void
ImageBridgeParent::AppendDeliverFenceMessage(uint64_t aDestHolderId,
uint64_t aTransactionId,
PTextureParent* aTexture,
CompositableHost* aCompositableHost)
PTextureParent* aTexture)
{
RefPtr<TextureHost> texture = TextureHost::AsTextureHost(aTexture);
if (!texture) {
if (!texture || !texture->NeedsFenceHandle()) {
return;
}
// Send a ReleaseFence of CompositorOGL.
if (aCompositableHost && aCompositableHost->GetCompositor()) {
FenceHandle fence = aCompositableHost->GetCompositor()->GetReleaseFence();
if (fence.IsValid()) {
mPendingAsyncMessage.push_back(OpDeliverFenceToTracker(aDestHolderId,
aTransactionId,
fence));
}
FenceHandle fence = texture->GetCompositorReleaseFence();
if (fence.IsValid()) {
mPendingAsyncMessage.push_back(OpDeliverFenceToTracker(aDestHolderId,
aTransactionId,
fence));
}
// Send a ReleaseFence that is set by HwcComposer2D.
FenceHandle fence = texture->GetAndResetReleaseFenceHandle();
// Send a ReleaseFence that is set to TextureHost by HwcComposer2D.
fence = texture->GetAndResetReleaseFenceHandle();
if (fence.IsValid()) {
mPendingAsyncMessage.push_back(OpDeliverFenceToTracker(aDestHolderId,
aTransactionId,
@@ -506,8 +500,7 @@ ImageBridgeParent::AppendDeliverFenceMessage(uint64_t aDestHolderId,
ImageBridgeParent::AppendDeliverFenceMessage(base::ProcessId aChildProcessId,
uint64_t aDestHolderId,
uint64_t aTransactionId,
PTextureParent* aTexture,
CompositableHost* aCompositableHost)
PTextureParent* aTexture)
{
ImageBridgeParent* imageBridge = ImageBridgeParent::GetInstance(aChildProcessId);
if (!imageBridge) {
@@ -515,8 +508,7 @@ ImageBridgeParent::AppendDeliverFenceMessage(base::ProcessId aChildProcessId,
}
imageBridge->AppendDeliverFenceMessage(aDestHolderId,
aTransactionId,
aTexture,
aCompositableHost);
aTexture);
}
/*static*/ void
+3 -6
View File
@@ -59,8 +59,7 @@ public:
Create(Transport* aTransport, ProcessId aChildProcessId);
// CompositableParentManager
virtual void SendFenceHandleIfPresent(PTextureParent* aTexture,
CompositableHost* aCompositableHost) override;
virtual void SendFenceHandleIfPresent(PTextureParent* aTexture) override;
virtual void SendAsyncMessage(const InfallibleTArray<AsyncParentMessageData>& aMessage) override;
@@ -121,14 +120,12 @@ public:
void AppendDeliverFenceMessage(uint64_t aDestHolderId,
uint64_t aTransactionId,
PTextureParent* aTexture,
CompositableHost* aCompositableHost);
PTextureParent* aTexture);
static void AppendDeliverFenceMessage(base::ProcessId aChildProcessId,
uint64_t aDestHolderId,
uint64_t aTransactionId,
PTextureParent* aTexture,
CompositableHost* aCompositableHost);
PTextureParent* aTexture);
using CompositableParentManager::SendPendingAsyncMessages;
static void SendPendingAsyncMessages(base::ProcessId aChildProcessId);
+2 -1
View File
@@ -19,11 +19,12 @@ namespace mozilla {
namespace layout {
class RenderFrameChild;
class ShadowLayerForwarder;
} // namespace layout
namespace layers {
class ShadowLayerForwarder;
class LayerTransactionChild : public PLayerTransactionChild
, public AsyncTransactionTrackersHolder
{
+28 -13
View File
@@ -798,6 +798,25 @@ GetAPZCForViewID(Layer* aLayer, FrameMetrics::ViewID aScrollID)
return nullptr;
}
bool
LayerTransactionParent::RecvUpdateScrollOffset(
const FrameMetrics::ViewID& aScrollID,
const uint32_t& aScrollGeneration,
const CSSPoint& aScrollOffset)
{
if (mDestroyed || !layer_manager() || layer_manager()->IsDestroyed()) {
return false;
}
AsyncPanZoomController* controller = GetAPZCForViewID(mRoot, aScrollID);
if (!controller) {
return false;
}
controller->NotifyScrollUpdated(aScrollGeneration, aScrollOffset);
mShadowLayersManager->ForceComposite(this);
return true;
}
bool
LayerTransactionParent::RecvSetAsyncScrollOffset(const FrameMetrics::ViewID& aScrollID,
const float& aX, const float& aY)
@@ -983,8 +1002,7 @@ LayerTransactionParent::RecvChildAsyncMessages(InfallibleTArray<AsyncChildMessag
GetChildProcessId(),
op.holderId(),
op.transactionId(),
op.textureParent(),
compositable);
op.textureParent());
// Send message back via PImageBridge.
ImageBridgeParent::ReplyRemoveTexture(
GetChildProcessId(),
@@ -1046,25 +1064,22 @@ bool LayerTransactionParent::IsSameProcess() const
}
void
LayerTransactionParent::SendFenceHandleIfPresent(PTextureParent* aTexture,
CompositableHost* aCompositableHost)
LayerTransactionParent::SendFenceHandleIfPresent(PTextureParent* aTexture)
{
RefPtr<TextureHost> texture = TextureHost::AsTextureHost(aTexture);
if (!texture) {
if (!texture || !texture->NeedsFenceHandle()) {
return;
}
// Send a ReleaseFence of CompositorOGL.
if (aCompositableHost && aCompositableHost->GetCompositor()) {
FenceHandle fence = aCompositableHost->GetCompositor()->GetReleaseFence();
if (fence.IsValid()) {
mPendingAsyncMessage.push_back(OpDeliverFence(aTexture, nullptr,
fence));
}
FenceHandle fence = texture->GetCompositorReleaseFence();
if (fence.IsValid()) {
mPendingAsyncMessage.push_back(OpDeliverFence(aTexture, nullptr,
fence));
}
// Send a ReleaseFence that is set by HwcComposer2D.
FenceHandle fence = texture->GetAndResetReleaseFenceHandle();
// Send a ReleaseFence that is set to TextureHost by HwcComposer2D.
fence = texture->GetAndResetReleaseFenceHandle();
if (fence.IsValid()) {
mPendingAsyncMessage.push_back(OpDeliverFence(aTexture, nullptr,
fence));
+4 -2
View File
@@ -80,8 +80,7 @@ public:
void SetPendingTransactionId(uint64_t aId) { mPendingTransaction = aId; }
// CompositableParentManager
virtual void SendFenceHandleIfPresent(PTextureParent* aTexture,
CompositableHost* aCompositableHost) override;
virtual void SendFenceHandleIfPresent(PTextureParent* aTexture) override;
virtual void SendAsyncMessage(const InfallibleTArray<AsyncParentMessageData>& aMessage) override;
@@ -131,6 +130,9 @@ protected:
virtual bool RecvGetAnimationTransform(PLayerParent* aParent,
MaybeTransform* aTransform)
override;
virtual bool RecvUpdateScrollOffset(const FrameMetrics::ViewID& aScrollId,
const uint32_t& aScrollGeneration,
const CSSPoint& aScrollOffset) override;
virtual bool RecvSetAsyncScrollOffset(const FrameMetrics::ViewID& aId,
const float& aX, const float& aY) override;
virtual bool RecvSetAsyncZoom(const FrameMetrics::ViewID& aId,
+5
View File
@@ -22,6 +22,7 @@ using class mozilla::layers::APZTestData from "mozilla/layers/APZTestData.h";
using mozilla::layers::FrameMetrics::ViewID from "FrameMetrics.h";
using struct mozilla::layers::ScrollableLayerGuid from "FrameMetrics.h";
using mozilla::layers::LayersBackend from "mozilla/layers/LayersTypes.h";
using mozilla::CSSPoint from "Units.h";
/**
* The layers protocol is spoken between thread contexts that manage
@@ -89,6 +90,10 @@ parent:
// be void_t.
sync GetAnimationTransform(PLayer layer) returns (MaybeTransform transform);
// Updates the scroll offset and generation counter on the APZC for the
// given scroll id.
sync UpdateScrollOffset(ViewID id, uint32_t generation, CSSPoint offset);
// The next time the layer tree is composited, add this async scroll offset in
// CSS pixels for the given ViewID.
// Useful for testing rendering of async scrolling.
+1
View File
@@ -259,6 +259,7 @@ UNIFIED_SOURCES += [
'apz/src/AsyncPanZoomController.cpp',
'apz/src/Axis.cpp',
'apz/src/CheckerboardEvent.cpp',
'apz/src/DragTracker.cpp',
'apz/src/GestureEventListener.cpp',
'apz/src/HitTestingTreeNode.cpp',
'apz/src/InputBlockState.cpp',
+3 -5
View File
@@ -629,6 +629,7 @@ void
CompositorOGL::BeginFrame(const nsIntRegion& aInvalidRegion,
const Rect *aClipRectIn,
const Rect& aRenderBounds,
bool aOpaque,
Rect *aClipRectOut,
Rect *aRenderBoundsOut)
{
@@ -878,8 +879,7 @@ CompositorOGL::GetShaderConfigFor(Effect *aEffect,
}
}
config.SetColorMatrix(aColorMatrix);
config.SetMask2D(aMask == MaskType::Mask2d);
config.SetMask3D(aMask == MaskType::Mask3d);
config.SetMask(aMask == MaskType::Mask);
config.SetDEAA(aDEAAEnabled);
config.SetCompositionOp(aOp);
return config;
@@ -1069,9 +1069,7 @@ CompositorOGL::DrawQuad(const Rect& aRect,
maskQuadTransform._41 = float(-bounds.x)/bounds.width;
maskQuadTransform._42 = float(-bounds.y)/bounds.height;
maskType = effectMask->mIs3D
? MaskType::Mask3d
: MaskType::Mask2d;
maskType = MaskType::Mask;
} else {
maskType = MaskType::MaskNone;
}
+1
View File
@@ -401,6 +401,7 @@ private:
virtual void BeginFrame(const nsIntRegion& aInvalidRegion,
const gfx::Rect *aClipRectIn,
const gfx::Rect& aRenderBounds,
bool aOpaque,
gfx::Rect *aClipRectOut = nullptr,
gfx::Rect *aRenderBoundsOut = nullptr) override;
+10
View File
@@ -466,5 +466,15 @@ GrallocTextureHostOGL::BindTextureSource(CompositableTextureSourceRef& aTextureS
return true;
}
FenceHandle
GrallocTextureHostOGL::GetCompositorReleaseFence()
{
if (!mCompositor) {
return FenceHandle();
}
return mCompositor->GetReleaseFence();
}
} // namepsace layers
} // namepsace mozilla
+11
View File
@@ -60,6 +60,17 @@ public:
gl::GLContext* GetGLContext() const { return mCompositor ? mCompositor->gl() : nullptr; }
virtual bool NeedsFenceHandle() override
{
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
return true;
#else
return false;
#endif
}
virtual FenceHandle GetCompositorReleaseFence() override;
private:
void DestroyEGLImage();
+11 -27
View File
@@ -139,15 +139,9 @@ ShaderConfigOGL::SetBlur(bool aEnabled)
}
void
ShaderConfigOGL::SetMask2D(bool aEnabled)
ShaderConfigOGL::SetMask(bool aEnabled)
{
SetFeature(ENABLE_MASK_2D, aEnabled);
}
void
ShaderConfigOGL::SetMask3D(bool aEnabled)
{
SetFeature(ENABLE_MASK_3D, aEnabled);
SetFeature(ENABLE_MASK, aEnabled);
}
void
@@ -206,8 +200,7 @@ ProgramProfileOGL::GetProfileFor(ShaderConfigOGL aConfig)
vs << "varying vec2 vBackdropCoord;" << endl;
}
if (aConfig.mFeatures & ENABLE_MASK_2D ||
aConfig.mFeatures & ENABLE_MASK_3D) {
if (aConfig.mFeatures & ENABLE_MASK) {
vs << "uniform mat4 uMaskTransform;" << endl;
vs << "varying vec3 vMaskCoord;" << endl;
}
@@ -232,8 +225,7 @@ ProgramProfileOGL::GetProfileFor(ShaderConfigOGL aConfig)
vs << " ssPos = uMatrixProj * ssPos;" << endl;
vs << " ssPos.xy = ((ssPos.xy/ssPos.w)*0.5+0.5)*uViewportSize;" << endl;
if (aConfig.mFeatures & ENABLE_MASK_2D ||
aConfig.mFeatures & ENABLE_MASK_3D ||
if (aConfig.mFeatures & ENABLE_MASK ||
!(aConfig.mFeatures & ENABLE_RENDER_COLOR)) {
vs << " vec4 coordAdjusted;" << endl;
vs << " coordAdjusted.xy = aCoord.xy;" << endl;
@@ -278,14 +270,11 @@ ProgramProfileOGL::GetProfileFor(ShaderConfigOGL aConfig)
vs << " vec2 texCoord = aCoord.xy * textureRect.zw + textureRect.xy;" << endl;
vs << " vTexCoord = (uTextureTransform * vec4(texCoord, 0.0, 1.0)).xy;" << endl;
}
if (aConfig.mFeatures & ENABLE_MASK_2D ||
aConfig.mFeatures & ENABLE_MASK_3D) {
if (aConfig.mFeatures & ENABLE_MASK) {
vs << " vMaskCoord.xy = (uMaskTransform * (finalPosition / finalPosition.w)).xy;" << endl;
if (aConfig.mFeatures & ENABLE_MASK_3D) {
// correct for perspective correct interpolation, see comment in D3D10 shader
vs << " vMaskCoord.z = 1.0;" << endl;
vs << " vMaskCoord *= finalPosition.w;" << endl;
}
// correct for perspective correct interpolation, see comment in D3D11 shader
vs << " vMaskCoord.z = 1.0;" << endl;
vs << " vMaskCoord *= finalPosition.w;" << endl;
}
vs << " finalPosition.xy -= uRenderTargetOffset * finalPosition.w;" << endl;
vs << " finalPosition = uMatrixProj * finalPosition;" << endl;
@@ -376,8 +365,7 @@ ProgramProfileOGL::GetProfileFor(ShaderConfigOGL aConfig)
fs << "uniform sampler2D uBackdropTexture;" << endl;
}
if (aConfig.mFeatures & ENABLE_MASK_2D ||
aConfig.mFeatures & ENABLE_MASK_3D) {
if (aConfig.mFeatures & ENABLE_MASK) {
fs << "varying vec3 vMaskCoord;" << endl;
fs << "uniform sampler2D uMaskTexture;" << endl;
}
@@ -512,13 +500,10 @@ For [0,1] instead of [0,255], and to 5 places:
fs << " vec4 backdrop = texture2D(uBackdropTexture, vBackdropCoord);" << endl;
fs << " color = mixAndBlend(backdrop, color);" << endl;
}
if (aConfig.mFeatures & ENABLE_MASK_3D) {
if (aConfig.mFeatures & ENABLE_MASK) {
fs << " vec2 maskCoords = vMaskCoord.xy / vMaskCoord.z;" << endl;
fs << " COLOR_PRECISION float mask = texture2D(uMaskTexture, maskCoords).r;" << endl;
fs << " color *= mask;" << endl;
} else if (aConfig.mFeatures & ENABLE_MASK_2D) {
fs << " COLOR_PRECISION float mask = texture2D(uMaskTexture, vMaskCoord.xy).r;" << endl;
fs << " color *= mask;" << endl;
} else {
fs << " COLOR_PRECISION float mask = 1.0;" << endl;
fs << " color *= mask;" << endl;
@@ -542,8 +527,7 @@ For [0,1] instead of [0,255], and to 5 places:
result.mTextureCount = 1;
}
}
if (aConfig.mFeatures & ENABLE_MASK_2D ||
aConfig.mFeatures & ENABLE_MASK_3D) {
if (aConfig.mFeatures & ENABLE_MASK) {
result.mTextureCount = 1;
}
if (BlendOpIsMixBlendMode(blendOp)) {
+4 -6
View File
@@ -37,10 +37,9 @@ enum ShaderFeatures {
ENABLE_OPACITY=0x100,
ENABLE_BLUR=0x200,
ENABLE_COLOR_MATRIX=0x400,
ENABLE_MASK_2D=0x800,
ENABLE_MASK_3D=0x1000,
ENABLE_NO_PREMUL_ALPHA=0x2000,
ENABLE_DEAA=0x4000
ENABLE_MASK=0x800,
ENABLE_NO_PREMUL_ALPHA=0x1000,
ENABLE_DEAA=0x2000
};
class KnownUniform {
@@ -223,8 +222,7 @@ public:
void SetComponentAlpha(bool aEnabled);
void SetColorMatrix(bool aEnabled);
void SetBlur(bool aEnabled);
void SetMask2D(bool aEnabled);
void SetMask3D(bool aEnabled);
void SetMask(bool aEnabled);
void SetDEAA(bool aEnabled);
void SetCompositionOp(gfx::CompositionOp aOp);
void SetNoPremultipliedAlpha();
+2
View File
@@ -285,6 +285,8 @@ public:
protected:
friend class nsICODecoder;
friend class PalettedSurfaceSink;
friend class SurfaceSink;
virtual ~Decoder();
-55
View File
@@ -1,55 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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/. */
#include "Downscaler.h"
#include "mozilla/UniquePtrExtensions.h"
namespace mozilla {
namespace image {
Deinterlacer::Deinterlacer(const nsIntSize& aImageSize)
: mImageSize(aImageSize)
{
CheckedInt<size_t> bufferSize = mImageSize.width;
bufferSize *= mImageSize.height;
bufferSize *= sizeof(uint32_t);
if (!bufferSize.isValid()) {
return;
}
mBuffer = MakeUniqueFallible<uint8_t[]>(bufferSize.value());
}
uint32_t
Deinterlacer::RowSize() const
{
return mImageSize.width * sizeof(uint32_t);
}
uint8_t*
Deinterlacer::RowBuffer(uint32_t aRow)
{
uint32_t offset = aRow * RowSize();
MOZ_ASSERT(IsValid(), "Deinterlacer in invalid state");
MOZ_ASSERT(offset < mImageSize.width * mImageSize.height * sizeof(uint32_t),
"Row is outside of image");
return mBuffer.get() + offset;
}
void
Deinterlacer::PropagatePassToDownscaler(Downscaler& aDownscaler)
{
MOZ_ASSERT(IsValid(), "Deinterlacer in invalid state");
for (int32_t row = 0 ; row < mImageSize.height ; ++row) {
memcpy(aDownscaler.RowBuffer(), RowBuffer(row), RowSize());
aDownscaler.CommitRow();
}
}
} // namespace image
} // namespace mozilla

Some files were not shown because too many files have changed in this diff Show More