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

- Bug 1247955 - Add telemetry for compacting GC r=terrence (71fc631b20)
- Bug 1200133 - Part1 - Change mochitest using TV Simulator Service. r=seanlin (bbddf95aae)
- bit of  Bug 1230674 - part 3, (253d2ab0ce)
- Bug 1144103 - Support screen recording r=mwu (694cd8f580)
- Bug 1237914 - Remove layers.screen-recording.enabled r=mwu (22edbe0944)
- Bug 1231042 - clean current composition task and related flag when screen off. r=mchang (45c996e32b)
- Bug 1137151: Marked destructor of |nsWindow| as protected, r=mwu (6ebb963472)
- Bug 1187503 - use external surface size on CompositorOGL r=nical (8481425ca9)
- Bug 1238876 - Move StartRemoteDrawing() implementation from nsWindow to nsScreenGonk r=mwu (9b7a2066d2)
- Bug 1006688 - Support capture screen via adb r=mwu (d651416c44)
- Bug 1244044 - remember display status; r=jerry (d8a252f081)
- Bug 1247570 - unbreak widget/gonk/nativewindow/FakeSurfaceComposer.cpp r=gwagner (de01fd3084)
- Bug 1020199 - Make sure APZ works with nested oop iframe. r=kats, r=dvander. (8f4285b97f)
- Bug 1235858 - Record the time stamp, use it for crash reports. r=botond (98d999aa25)
- Bug 1247671: Increase the crash logging length to 16 by default (+ small white space change in the comments) r=dvander (8a0995cb1c)
- Bug 867501 - Pref allows JS locale to be set to US English/C. r=khuey (8d6e5df33d)
- Bug 1207972: Move to using USER_INTERACTIVE and JOB_INTERACTIVE by default for the Windows content sandbox. r=tabraldes (494ecebd8e)
- Bug 1234673 - Avoid users from locales ar, fa, he, ur for e10s rollout to beta. r=jimm (adf49af577)
- Bug 1234675 - Ability to disable e10s for users with addons. r=Mossop (6abaeba541)
- Bug 1233837 support migration wizard override from distribution.ini, r=bsmedberg (98c95ecc4b)
- Bug 884831 - GTK3 - crash at browser end [@ XFreeColormap() ], r=karlt (13d9067ab0)
- Bug 1215078 - [Wayland] Configure display for Wayland session. r=karlt (c4417d3534)
- Bug 1111701 - Remove E10S_AUTOSTART histogram. r=dexter (56625e7353)
- Bug 1239520 - Enabled e10s on all configurations except release. r=billm (48c760a1f8)
- Bug 1241294 - Update E10S_AUTOSTART_STATUS telemetry probe (and rename it to E10S_STATUS). r=vladan (7217e4c9d3)
- Bug 1241959 - Add a description of e10s blocked status to about:support. r=jimm (b6cb2e6dac)
- Bug 1165818: Remove temporary Nightly only MozTemp-* clean-up code. r=jimm (fdb11aed0e)
- Bug 1243882 - Block e10s for locales based on Firefox's locale, not the OS. r=ehsan (873b09db0f)
- Bug 1235437 - Add annotation for major graphics preferences. r=bgirard (2e147567be)
- Bug 1237404 - Part 1. Exposing some functionality in gfxCrashReporterUtils. r=benwa (dc08c3ba92)
- Bug 1237404 - Part 2. Optimizing the main thread scenario. r=benwa (e5b6704b57)
- Bug 1237770: Disable D3D9 on XP with E10S. r=jrmuizel (6424700126)
- Bug 1210351 - Limit maximum computed tile size to 512x512. r=snorp (162839caf7)
- Bug 1221073 - Increase max tile size to 1024 again. r=mstange (29e8513390)
- Bug 990017. Prevent skia accelerated canvas backends from rendering content. r=jmuizelaar (b257281035)
- Bug 1178385. Add a pref to force enable hw video decode. r=milan (f69cde6047)
- Bug 1230196 - Allow release channel to run e10s. r=billm (ab5d0a464c)
- Bug 1231915 - Ignore the APZ pref if MOZ_ANDROID_APZ is enabled, since the pref doesn't cover all the relevant code. r=rbarker (3984b57173)
- Bug 1187464 - Part 1. We can get the wrong texture source type, so deal with it. Carry r=mstange (0d47ffdd65)
- Bug 1187464 - Part 2. RTTI for TextureSource debug purposes. Carry r=botond (af8b92042d)
- Bug 1187464 - Part 3. Check if GetSurface returned null. r=mstange (ab7de5dabb)
- Bug 1165407 - Properly flush the log stream after logging it. r=botond (6dd38e7e7a)
- Bug 1239844 - Log hexadecimal values in a more standard way. r=dholbert (aa7de36cfd)
- Bug 1241769 - Use Singleton pattern to nsScreenManagerGonk r=mwu (bb0c30ce80)
- Bug 1229262 - Fix nsScreenGonk's thread safety r=mwu (6c60907ce9)
- Bug 1165161 - stop bootAnim with "browser-ui-startup-complete" event. r=mwu (e40ddb816a)
- Bug 1230397 - Write safe mode pref on the main thread r=dbaron (0538d0353f)
- Bug 1172805 - Fix enum comparison warnings in nsAppShell. r=mwu (e77ec14fed)
- Bug 1215494 - Don't set b2g.safe_mode pref in child process. r=fabrice (3264d2c872)
- Bug 1192949 - Fix nsScreenGonk::SetMirroringScreen() r=mwu (39abf13ff4)
- Bug 1243413 - If a plugin window is hidden in an adjacent scroll frame due to APZ scroll state changes, make sure to show the plugin window after the scroll operation complete. r=kats (302f14476f)
- Bug 1187322 - Fix bustage. (5fe8e7b3e8)
- Bug 241788 - mozilla::Tokenizer - token type for \n should whitespace if given in constructor r=honzab (d4da4354c8)
- Bug 1237827 - Be sure to clear LayerComposite::mLayerComposited between each composite. r=mattwoodrow (cc02aef817)
- Bug 1244943 - Make PostProcessLayers aware of preserve-3d. r=mattwoodrow (48fadfdcf7)
- Bug 1229317 - Allow preserve-3d and opacity to be combined on the root element of a preserve-3d chain. r=roc (030c042699)
- Bug 1231564 - Don't take the compositor side layer-tree snapshot until after compositing. r=dvander (c0164b6464)
- Bug 1247445 - Rename Layer::GetEffectiveVisibleRegion GetLocalVisibleRegion. r=botond (35125c3f71)
- Bug 945613 - Part 3: #ifdef pragma for gcc >= 4.7.0. r=ehsan (67786ad3f8)
- Bug 1227210: Ensure the mask and the surface are in the right space when being blended. r=mattwoodrow (6745cd99f8)
- Bug 1229587 part 1 - Disable C4464 warning newly added in VS2015u1. r=keeler (65cf58d55d)
- Bug 1229587 part 2 - Use verbose format to disable C4061 to workaround bug of VS2015u1. r=keeler (8f8fb5190f)
- Bug 1189891 - Avoid including <cstring> from pkix/Input.h. r=bsmith (7202ad2de7)
- Bug 1207499 - Part 9: Remove use of expression closure from storage/. r=mak (cf0f139799)
- Bug 1230549 - Storage should pass more eslint rules. r=yoric (91e007dacb)
- Bug 1230549 - Make Storage pass basic eslint. r=yoric (37c88987e8)
- Bug 1237601 - Centralize storage xpcshell promise helpers (support patch). r=bkelly (ebee41dfae)
- Bug 1237601 - Perform storage close synchronously if async thread cannot be started. r=bkelly (855430997d)
- bug 1227008 use GtkPaperSize in GtkPageSetup directly, instead of maintaining a separate copy r=acomminos (cf1bade905)
- Bug 1205643 - Move scrollbar borders to slider to receive button events. r=karlt (76ece6a2fd)
- Bug 1141207 add gtk_print_settings_foreach to mozgtk.c. r=karlt (aee4b94e27)
- Bug 1206516 - Use temporary widget to construct style context for GtkInfoBar. r=karlt (1ce56b1799)
- bug 1205199 keep the socket alive as long as the plug window r=acomminos (bf1e4585da)
- Bug 1242135 - Annotate intentional and fix unintentional switch fallthroughs in widget/gtk/. r=karlt (102180ea0a)
- Bug 1221610 - Remove ToIntMargin(). r=jrmuizel. (5d234b1dd6)
- Bug 1238582 - Skip simulated OOM check in the case where we're growing within reserved space; r=Waldo (2d00fa9605)
- Bug 1242812 - Only check for simulated OOM in vectors when growing beyond reserved size r=Waldo (98ad0de5ff)
- Bug 1144745 - scale border returned by GetWidgetBorder(), r=karlt (8639c7b240)
- Bug 1184936 - Need convert from UTF8 for printer name. r=karlt (99e2863372)
- Bug 569295 - limit the number of bytes we attempt to upload to the storage servers. r=rnewman (8072be50bb)
- Bug 779430, try to not flush layout while we're in process to restore a bfcached document, r=bz (47d01dd107)
- Bug 1241579 - Convert services/ to use channel.open2() (r=sicking) (fd6ee21f67)
- Bug 1228510 - initialize 2 more variables. r=bas (e3d144854a)
- Bug 1229577 - Rename NewSurfaceDescriptorGralloc into SurfaceDescriptorGralloc. r=sotaro (99b8d621e4)
- Bug 1241665 - Correctly convert IOSurfaces to SourceSurfaces in MacIOSurfaceTextureSourceBasic and MacIOSurfaceTextureData. r=mattwoodrow (54ce8c1582)
- Bug 1241665 - Move IOSurface YCbCr conversion code to a new file MacIOSurfaceHelpers.cpp. r=mattwoodrow (aeb7f341cf)
- Bug 1191161 - p1 - Merge WrapEntireClassForJNI into WrapElementForJNI, r=jchen (684111ca72)
- Bug 1246775 - use already_AddRefed in PersistentBufferProvider interface. r=bas (373a63f129)
- Bug 1232231 - BorrowDrawTarget can return nullptr - be ready for it. r=nical (0156e1c412)
- Bug 1227224 - Further improvements to generic tree traversal algorithms. r=botond (f71854fea6)
- Bug 1234047 - Always reuse an existing TextureClient in IMFYCbCrImage if one exist. r=Bas (4c995d1668)
- Bug 1240668 - Duplicate GonkNativeHandle::NhObj in ImageClientSingle::UpdateImage() r=nical (ed213d6f07)
- Bug 1213095 - Inline the DispatchRepaintRequest function. r=botond (33d14a377c)
- Bug 1213095 - Don't allow RequestContentRepaint to mutate the provided FrameMetrics. r=botond (676e6082b5)
- Bug 1213095 - Ensure that stale FrameMetrics do not clobber more recent metrics for paint requests. r=botond (b6e75b0e37)
- Bug 1238040 - Update telemetry measures for checkerboarding. r=botond,vladan (e41963fce5)
- Bug 1238042 - Expose the checkerboard reports out to JS. r=ehsan,botond (986bb53bc5)
- Bug 1238137 - Define a telemetry histogram for tracking the input methods used to trigger scrolling. r=kats (9e366c56a5)
- remove unused (b0dc04a498)
- Bug 1238137 - Telemetry pings for APZ-driven scroll input methods. r=kats (3f026677bd)
- Bug 1241371. Properly update mLastUpdateImagesPos on scrollframes when the image visibility pass encounters them. r=mats (128edd5957)
- Bug 1241371. Don't schedule an image visibility update every time display port margins change. r=kats (9927515115)
- Bug 990916 - When setting a displayport, schedule a timer to remove it as well. r=tnikkel (ddd943226d)
- Bug 990916 - Track if a scrollframe is a scroll parent for something else. r=tnikkel (7128db6038)
- Bug 1245285 - part 1, Remove unused mRepaintInterval from AsyncPanZoomAnimation r=botond (ec516fe9f0)
- Bug 1245285 - part 2, Prevent Zoom and Overscroll animations from repainting durring animation r=botond (6a66a0005a)
- Bug 1245285 - part 3, Remove unused repaint_interval prefs r=botond (9987a58743)
- Bug 1243413 - Avoid hiding windowed plugins that aren't contained within the active scroll frame. r=roc (f059ce95da)
- Bug 1104356 - When doing a smooth scroll on a non-APZ'd scrollframe, fall back to the main thread machinery. r=kip (44d75dc20f)
- Bug 990916 - On displayport expiry, trigger another round of expiry up the ancestor chain. r=tnikkel (8ce9a22429)
- Bug 1245925 - Don't allow expiring the displayport on root scrollframes. r=tnikkel (2ec6218e2e)
- Bug 1236040 - When updating the scroll position, only schedule image visibility checks if the display port has changed. r=tn (aedac7070f)
- Bug 1234725. Don't change the dirty rect to the display port when building display lists for documents. r=mstange (6ff3e41934)
- Fix crash trying to allocate textures for oversize scrollbars. (bug 1214261, r=mstange) (b4b4fa368d)
- Bug 1234877 - Whether a scroll frame is async scrollable is determined by mWillBuildScrollableLayer, not by usingDisplayPort. r=tn (2daacb63f5)
- Bug 1241917 - Restrict subframe's displayport base to root composition bounds. r=tn (7e50ff6bae)
- Bug 1246443. Don't make nsLayoutUtils::MaybeCreateDisplayPort also set the displayport base anymore. r=botond (2970d8f2a6)
- Bug 1246443 - Only restrict displayport base to root composition bounds if content has displayport; r=tnikkel (a841dedff4)
- Bug 1208985 - Use height for scroll-snap-points-y percentage values; r=kip (17ce448e8b)
- Bug 1238040 - Add a telemetry probe for potential checkerboarding duration. r=botond,vladan (bdf18d520b)
- Bug 1240622 - Guard mCheckerboardEvent with a mutex to avoid races. r=botond (b81534272c)
- Bug 1240202 - Rename APZOverscrollHandoffTester to APZScrollHandoffTester. r=kats (3c165a103d)
- Bug 1240202 - Change input event generation utilities used by APZ gtests to take points instead of loose coordinates. r=kats (e29de86c33)
- Bug 1240202 - Avoid getting stuck in overscroll when the screen is tapped during an overscroll animation. r=kats (3822391d27)
- Bug 1225045: Fix stagefright include paths for ANDROID_VERSION >= 17, r=gps (1eabe097b5)
This commit is contained in:
2023-11-29 10:27:54 +08:00
parent 37dc78596e
commit 724e70642d
221 changed files with 6781 additions and 3558 deletions
+2
View File
@@ -431,6 +431,8 @@
@RESPATH@/components/nsLoginManagerPrompter.js
@RESPATH@/components/NetworkGeolocationProvider.manifest
@RESPATH@/components/NetworkGeolocationProvider.js
@RESPATH@/components/TVSimulatorService.js
@RESPATH@/components/TVSimulatorService.manifest
#ifdef MOZ_WEBRTC
@RESPATH@/components/PeerConnection.js
@RESPATH@/components/PeerConnection.manifest
+3
View File
@@ -569,6 +569,9 @@
@RESPATH@/components/SlowScriptDebug.manifest
@RESPATH@/components/SlowScriptDebug.js
@RESPATH@/components/TVSimulatorService.js
@RESPATH@/components/TVSimulatorService.manifest
#ifndef RELEASE_BUILD
@RESPATH@/components/InterAppComm.manifest
@RESPATH@/components/InterAppCommService.js
+4 -1
View File
@@ -2026,8 +2026,11 @@ KeyframeEffectReadOnly::CanAnimateTransformOnCompositor(
const nsIFrame* aFrame,
const nsIContent* aContent)
{
// Disallow OMTA for preserve-3d transform. Note that we check the style property
// rather than Extend3DContext() since that can recurse back into this function
// via HasOpacity().
if (aFrame->Combines3DTransformWithAncestors() ||
aFrame->Extend3DContext()) {
aFrame->StyleDisplay()->mTransformStyle == NS_STYLE_TRANSFORM_STYLE_PRESERVE_3D) {
if (aContent) {
nsCString message;
message.AppendLiteral("Gecko bug: Async animation of 'preserve-3d' "
+1 -3
View File
@@ -1576,9 +1576,7 @@ CanvasRenderingContext2D::ReturnTarget()
{
if (mTarget && mBufferProvider) {
CurrentState().transform = mTarget->GetTransform();
DrawTarget* oldDT = mTarget;
mTarget = nullptr;
mBufferProvider->ReturnAndUseDT(oldDT);
mBufferProvider->ReturnAndUseDT(mTarget.forget());
}
}
+14
View File
@@ -44,6 +44,7 @@
#include "mozilla/ipc/GeckoChildProcessHost.h"
#include "mozilla/ipc/TestShellChild.h"
#include "mozilla/jsipc/CrossProcessObjectWrappers.h"
#include "mozilla/layers/APZChild.h"
#include "mozilla/layers/CompositorChild.h"
#include "mozilla/layers/ImageBridgeChild.h"
#include "mozilla/layers/PCompositorChild.h"
@@ -1255,6 +1256,19 @@ ContentChild::AllocPGMPServiceChild(mozilla::ipc::Transport* aTransport,
return GMPServiceChild::Create(aTransport, aOtherProcess);
}
PAPZChild*
ContentChild::AllocPAPZChild(const TabId& aTabId)
{
return APZChild::Create(aTabId);
}
bool
ContentChild::DeallocPAPZChild(PAPZChild* aActor)
{
delete aActor;
return true;
}
PCompositorChild*
ContentChild::AllocPCompositorChild(mozilla::ipc::Transport* aTransport,
base::ProcessId aOtherProcess)
+5
View File
@@ -145,6 +145,11 @@ public:
AllocPGMPServiceChild(mozilla::ipc::Transport* transport,
base::ProcessId otherProcess) override;
PAPZChild*
AllocPAPZChild(const TabId& aTabId) override;
bool
DeallocPAPZChild(PAPZChild* aActor) override;
PCompositorChild*
AllocPCompositorChild(mozilla::ipc::Transport* aTransport,
base::ProcessId aOtherProcess) override;
+79 -1
View File
@@ -80,6 +80,7 @@
#include "mozilla/ipc/TestShellParent.h"
#include "mozilla/ipc/InputStreamUtils.h"
#include "mozilla/jsipc/CrossProcessObjectWrappers.h"
#include "mozilla/layers/PAPZParent.h"
#include "mozilla/layers/CompositorParent.h"
#include "mozilla/layers/ImageBridgeParent.h"
#include "mozilla/layers/SharedBufferManagerParent.h"
@@ -2026,11 +2027,61 @@ NestedBrowserLayerIds()
}
} // namespace
/* static */
bool
ContentParent::RecvAllocateLayerTreeId(uint64_t* aId)
ContentParent::AllocateLayerTreeId(TabParent* aTabParent, uint64_t* aId)
{
return AllocateLayerTreeId(aTabParent->Manager()->AsContentParent(),
aTabParent, aTabParent->GetTabId(), aId);
}
/* static */
bool
ContentParent::AllocateLayerTreeId(ContentParent* aContent,
TabParent* aTopLevel, const TabId& aTabId,
uint64_t* aId)
{
*aId = CompositorParent::AllocateLayerTreeId();
if (!gfxPlatform::AsyncPanZoomEnabled()) {
return true;
}
if (!aContent || !aTopLevel) {
return false;
}
return CompositorParent::UpdateRemoteContentController(*aId, aContent,
aTabId, aTopLevel);
}
bool
ContentParent::RecvAllocateLayerTreeId(const ContentParentId& aCpId,
const TabId& aTabId, uint64_t* aId)
{
// Protect against spoofing by a compromised child. aCpId must either
// correspond to the process that this ContentParent represents or be a
// child of it.
ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
if (ChildID() != aCpId) {
ContentParentId parent;
if (!cpm->GetParentProcessId(aCpId, &parent) ||
ChildID() != parent) {
return false;
}
}
// GetTopLevelTabParentByProcessAndTabId will make sure that aTabId
// lives in the process for aCpId.
RefPtr<ContentParent> contentParent = cpm->GetContentProcessById(aCpId);
RefPtr<TabParent> browserParent =
cpm->GetTopLevelTabParentByProcessAndTabId(aCpId, aTabId);
MOZ_ASSERT(contentParent && browserParent);
if (!AllocateLayerTreeId(contentParent, browserParent, aTabId, aId)) {
return false;
}
auto iter = NestedBrowserLayerIds().find(this);
if (iter == NestedBrowserLayerIds().end()) {
std::set<uint64_t> ids;
@@ -3401,6 +3452,21 @@ ContentParent::AllocPGMPServiceParent(mozilla::ipc::Transport* aTransport,
return GMPServiceParent::Create(aTransport, aOtherProcess);
}
PAPZParent*
ContentParent::AllocPAPZParent(const TabId& aTabId)
{
// The PAPZParent should just be created in the main process and then an IPDL
// constructor message sent to hook it up.
MOZ_CRASH("This shouldn't be called");
return nullptr;
}
bool
ContentParent::DeallocPAPZParent(PAPZParent* aActor)
{
return true;
}
PCompositorParent*
ContentParent::AllocPCompositorParent(mozilla::ipc::Transport* aTransport,
base::ProcessId aOtherProcess)
@@ -5767,6 +5833,18 @@ ContentParent::RecvGetGraphicsDeviceInitData(DeviceInitData* aOut)
return true;
}
bool
ContentParent::RecvGraphicsError(const nsCString& aError)
{
gfx::LogForwarder* lf = gfx::Factory::GetLogForwarder();
if (lf) {
std::stringstream message;
message << "CP+" << aError.get();
lf->UpdateStringsVector(message.str());
}
return true;
}
bool
ContentParent::RecvBeginDriverCrashGuard(const uint32_t& aGuardType, bool* aOutCrashed)
{
+16 -1
View File
@@ -502,6 +502,8 @@ public:
InfallibleTArray<FrameScriptInfo>* aFrameScripts,
nsCString* aURLToLoad) override;
static bool AllocateLayerTreeId(TabParent* aTabParent, uint64_t* aId);
protected:
void OnChannelConnected(int32_t pid) override;
@@ -645,10 +647,19 @@ private:
static void ForceKillTimerCallback(nsITimer* aTimer, void* aClosure);
static bool AllocateLayerTreeId(ContentParent* aContent,
TabParent* aTopLevel, const TabId& aTabId,
uint64_t* aId);
PGMPServiceParent*
AllocPGMPServiceParent(mozilla::ipc::Transport* aTransport,
base::ProcessId aOtherProcess) override;
PAPZParent*
AllocPAPZParent(const TabId& aTabId) override;
bool
DeallocPAPZParent(PAPZParent* aActor) override;
PCompositorParent*
AllocPCompositorParent(mozilla::ipc::Transport* aTransport,
base::ProcessId aOtherProcess) override;
@@ -993,7 +1004,9 @@ private:
virtual void ProcessingError(Result aCode, const char* aMsgName) override;
virtual bool RecvAllocateLayerTreeId(uint64_t* aId) override;
virtual bool RecvAllocateLayerTreeId(const ContentParentId& aCpId,
const TabId& aTabId,
uint64_t* aId) override;
virtual bool RecvDeallocateLayerTreeId(const uint64_t& aId) override;
@@ -1001,6 +1014,8 @@ private:
int32_t* aStatus,
bool* aSuccess) override;
virtual bool RecvGraphicsError(const nsCString& aError) override;
virtual bool
RecvBeginDriverCrashGuard(const uint32_t& aGuardType,
bool* aOutCrashed) override;
+2 -2
View File
@@ -28,9 +28,9 @@ SetUpSandboxEnvironment()
"SetUpSandboxEnvironment relies on nsDirectoryService being initialized");
// A low integrity temp only currently makes sense for Vista or Later and
// sandbox pref level 1.
// sandbox pref level >= 1.
if (!IsVistaOrLater() ||
Preferences::GetInt("security.sandbox.content.level") != 1) {
Preferences::GetInt("security.sandbox.content.level") < 1) {
return;
}
+1 -59
View File
@@ -56,13 +56,9 @@ using class mozilla::WidgetPluginEvent from "ipc/nsGUIEventIPC.h";
using struct mozilla::dom::RemoteDOMEvent from "mozilla/dom/TabMessageUtils.h";
using mozilla::dom::ScreenOrientationInternal from "mozilla/dom/ScreenOrientation.h";
using struct mozilla::layers::TextureFactoryIdentifier from "mozilla/layers/CompositorTypes.h";
using mozilla::CSSPoint from "Units.h";
using mozilla::CSSToScreenScale from "Units.h";
using mozilla::CommandInt from "mozilla/EventForwards.h";
using mozilla::Modifiers from "mozilla/EventForwards.h";
using mozilla::layers::GeckoContentController::APZStateChange from "mozilla/layers/GeckoContentController.h";
using mozilla::WritingMode from "mozilla/WritingModes.h";
using mozilla::layers::AsyncDragMetrics from "mozilla/layers/AsyncDragMetrics.h";
using mozilla::layers::TouchBehaviorFlags from "mozilla/layers/APZUtils.h";
using nsIWidget::TouchPointerState from "nsIWidget.h";
using struct LookAndFeelInt from "mozilla/widget/WidgetMessageUtils.h";
@@ -417,43 +413,6 @@ parent:
nsString aName, nsString aFeatures)
returns (bool windowOpened);
/**
* Instructs the TabParent to forward a request to zoom to a rect given in
* CSS pixels. This rect is relative to the document.
*/
async ZoomToRect(uint32_t aPresShellId, ViewID aViewId, CSSRect aRect, uint32_t aFlags);
/**
* We know for sure that content has either preventDefaulted or not
* preventDefaulted. This applies to an entire batch of touch events. It is
* expected that, if there are any DOM touch listeners, touch events will be
* batched and only processed for panning and zooming if content does not
* preventDefault.
*/
async ContentReceivedInputBlock(ScrollableLayerGuid aGuid, uint64_t aInputBlockId, bool aPreventDefault);
/**
* Notifies the APZ code of the results of the gecko hit-test for a
* particular input block. Each target corresponds to one touch point in the
* touch event.
*/
async SetTargetAPZC(uint64_t aInputBlockId, ScrollableLayerGuid[] aTargets);
/**
* Notifies the APZ code of the allowed touch-behaviours for a particular
* input block. Each item in the aFlags array corresponds to one touch point
* in the touch event.
*/
async SetAllowedTouchBehavior(uint64_t aInputBlockId, TouchBehaviorFlags[] aFlags);
/**
* Updates the zoom constraints for a scrollable frame in this tab.
* The zoom controller code lives on the parent side and so this allows it to
* have up-to-date zoom constraints.
*/
async UpdateZoomConstraints(uint32_t aPresShellId, ViewID aViewId,
MaybeZoomConstraints aConstraints);
/**
* Tells the containing widget whether the given input block results in a
* swipe. Should be called in response to a WidgetWheelEvent that has
@@ -537,9 +496,6 @@ parent:
prio(high) sync DispatchMouseEvent(WidgetMouseEvent event);
prio(high) sync DispatchKeyboardEvent(WidgetKeyboardEvent event);
// Start an APZ drag on a scrollbar
async StartScrollbarDrag(AsyncDragMetrics aDragMetrics);
async InvokeDragSession(IPCDataTransfer[] transfers, uint32_t action,
nsCString visualData, uint32_t width, uint32_t height,
uint32_t stride, uint8_t format,
@@ -575,20 +531,6 @@ child:
ScreenOrientationInternal orientation,
LayoutDeviceIntPoint chromeDisp) compressall;
async UpdateFrame(FrameMetrics frame);
// The following methods correspond to functions on the GeckoContentController
// interface in gfx/layers/apz/public/GeckoContentController.h. Refer to documentation
// in that file for these functions.
async RequestFlingSnap(ViewID aScrollID, CSSPoint aDestination);
async AcknowledgeScrollUpdate(ViewID aScrollId, uint32_t aScrollGeneration);
async HandleDoubleTap(CSSPoint aPoint, Modifiers aModifiers, ScrollableLayerGuid aGuid);
async HandleSingleTap(CSSPoint aPoint, Modifiers aModifiers, ScrollableLayerGuid aGuid);
async HandleLongTap(CSSPoint point, Modifiers aModifiers, ScrollableLayerGuid aGuid, uint64_t aInputBlockId);
async NotifyAPZStateChange(ViewID aViewId, APZStateChange aChange, int aArg);
async NotifyFlushComplete();
/**
* Sending an activate message moves focus to the child.
*/
@@ -660,7 +602,7 @@ child:
/**
* APZ notification for mouse scroll testing events.
*/
async MouseScrollTestEvent(ViewID aScrollId, nsString aEvent);
async MouseScrollTestEvent(uint64_t aLayersId, ViewID aScrollId, nsString aEvent);
async CompositionEvent(WidgetCompositionEvent event);
+8 -1
View File
@@ -4,6 +4,7 @@
* 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 protocol PAPZ;
include protocol PBackground;
include protocol PBlob;
include protocol PBluetooth;
@@ -467,6 +468,7 @@ prio(normal upto urgent) sync protocol PContent
parent opens PVRManager;
child opens PBackground;
manages PAPZ;
manages PBlob;
manages PBluetooth;
manages PBrowser;
@@ -569,6 +571,8 @@ child:
async PTestShell();
async PAPZ(TabId tabId);
async RegisterChrome(ChromePackage[] packages, SubstitutionMapping[] substitutions,
OverrideMapping[] overrides, nsCString locale, bool reset);
async RegisterChromeItem(ChromeRegistryItem item);
@@ -987,7 +991,7 @@ parent:
async CopyFavicon(URIParams oldURI, URIParams newURI, bool isPrivate);
// Tell the compositor to allocate a layer tree id for nested remote mozbrowsers.
sync AllocateLayerTreeId()
sync AllocateLayerTreeId(ContentParentId cpId, TabId tabId)
returns (uint64_t id);
async DeallocateLayerTreeId(uint64_t id);
@@ -1010,6 +1014,9 @@ parent:
sync GetGraphicsFeatureStatus(int32_t aFeature) returns (int32_t aStatus, bool aSuccess);
// Graphics errors
async GraphicsError(nsCString aError);
// Driver crash guards. aGuardType must be a member of CrashGuardType.
sync BeginDriverCrashGuard(uint32_t aGuardType) returns (bool crashDetected);
sync EndDriverCrashGuard(uint32_t aGuardType);
+119 -64
View File
@@ -16,6 +16,7 @@
#include "ContentChild.h"
#include "TabParent.h"
#include "mozilla/Preferences.h"
#include "mozilla/BrowserElementParent.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/EventListenerManager.h"
#include "mozilla/dom/workers/ServiceWorkerManager.h"
@@ -28,6 +29,7 @@
#include "ipc/Nuwa.h"
#endif
#include "mozilla/ipc/FileDescriptorUtils.h"
#include "mozilla/layers/APZChild.h"
#include "mozilla/layers/APZCCallbackHelper.h"
#include "mozilla/layers/APZCTreeManager.h"
#include "mozilla/layers/APZEventState.h"
@@ -37,6 +39,7 @@
#include "mozilla/layers/InputAPZContext.h"
#include "mozilla/layers/ShadowLayers.h"
#include "mozilla/layout/RenderFrameChild.h"
#include "mozilla/layout/RenderFrameParent.h"
#include "mozilla/LookAndFeel.h"
#include "mozilla/MouseEvents.h"
#include "mozilla/Move.h"
@@ -590,6 +593,7 @@ TabChild::TabChild(nsIContentChild* aManager,
, mIPCOpen(true)
, mParentIsActive(false)
, mDidSetRealShowInfo(false)
, mAPZChild(nullptr)
{
// In the general case having the TabParent tell us if APZ is enabled or not
// doesn't really work because the TabParent itself may not have a reference
@@ -603,7 +607,7 @@ TabChild::TabChild(nsIContentChild* aManager,
const nsTArray<TouchBehaviorFlags>& aFlags)
{
if (nsCOMPtr<nsITabChild> tabChild = do_QueryReferent(weakPtrThis)) {
static_cast<TabChild*>(tabChild.get())->SendSetAllowedTouchBehavior(aInputBlockId, aFlags);
static_cast<TabChild*>(tabChild.get())->SetAllowedTouchBehavior(aInputBlockId, aFlags);
}
};
@@ -711,6 +715,35 @@ TabChild::Observe(nsISupports *aSubject,
return NS_OK;
}
void
TabChild::ContentReceivedInputBlock(const ScrollableLayerGuid& aGuid,
uint64_t aInputBlockId,
bool aPreventDefault) const
{
if (mAPZChild) {
mAPZChild->SendContentReceivedInputBlock(aGuid, aInputBlockId,
aPreventDefault);
}
}
void
TabChild::SetTargetAPZC(uint64_t aInputBlockId,
const nsTArray<ScrollableLayerGuid>& aTargets) const
{
if (mAPZChild) {
mAPZChild->SendSetTargetAPZC(aInputBlockId, aTargets);
}
}
void
TabChild::SetAllowedTouchBehavior(uint64_t aInputBlockId,
const nsTArray<TouchBehaviorFlags>& aTargets) const
{
if (mAPZChild) {
mAPZChild->SendSetAllowedTouchBehavior(aInputBlockId, aTargets);
}
}
bool
TabChild::DoUpdateZoomConstraints(const uint32_t& aPresShellId,
const ViewID& aViewId,
@@ -723,9 +756,12 @@ TabChild::DoUpdateZoomConstraints(const uint32_t& aPresShellId,
return true;
}
return SendUpdateZoomConstraints(aPresShellId,
aViewId,
aConstraints);
if (!mAPZChild) {
return false;
}
return mAPZChild->SendUpdateZoomConstraints(aPresShellId, aViewId,
aConstraints);
}
nsresult
@@ -812,7 +848,7 @@ TabChild::Init()
bool aPreventDefault)
{
if (nsCOMPtr<nsITabChild> tabChild = do_QueryReferent(weakPtrThis)) {
static_cast<TabChild*>(tabChild.get())->SendContentReceivedInputBlock(aGuid, aInputBlockId, aPreventDefault);
static_cast<TabChild*>(tabChild.get())->ContentReceivedInputBlock(aGuid, aInputBlockId, aPreventDefault);
}
});
mAPZEventState = new APZEventState(mPuppetWidget, Move(callback));
@@ -1629,82 +1665,73 @@ TabChild::RecvUpdateDimensions(const CSSRect& rect, const CSSSize& size,
}
bool
TabChild::RecvUpdateFrame(const FrameMetrics& aFrameMetrics)
TabChild::UpdateFrame(const FrameMetrics& aFrameMetrics)
{
return TabChildBase::UpdateFrameHandler(aFrameMetrics);
}
bool
TabChild::RecvRequestFlingSnap(const FrameMetrics::ViewID& aScrollId,
const mozilla::CSSPoint& aDestination)
void
TabChild::HandleDoubleTap(const CSSPoint& aPoint, const Modifiers& aModifiers,
const ScrollableLayerGuid& aGuid)
{
APZCCallbackHelper::RequestFlingSnap(aScrollId, aDestination);
return true;
TABC_LOG("Handling double tap at %s with %p %p\n",
Stringify(aPoint).c_str(), mGlobal.get(), mTabChildGlobal.get());
if (!mGlobal || !mTabChildGlobal) {
return;
}
// Note: there is nothing to do with the modifiers here, as we are not
// synthesizing any sort of mouse event.
CSSPoint point = APZCCallbackHelper::ApplyCallbackTransform(aPoint, aGuid);
nsCOMPtr<nsIDocument> document = GetDocument();
CSSRect zoomToRect = CalculateRectToZoomTo(document, point);
// The double-tap can be dispatched by any scroll frame (so |aGuid| could be
// the guid of any scroll frame), but the zoom-to-rect operation must be
// performed by the root content scroll frame, so query its identifiers
// for the SendZoomToRect() call rather than using the ones from |aGuid|.
uint32_t presShellId;
ViewID viewId;
if (APZCCallbackHelper::GetOrCreateScrollIdentifiers(
document->GetDocumentElement(), &presShellId, &viewId) &&
mAPZChild) {
mAPZChild->SendZoomToRect(presShellId, viewId, zoomToRect,
DEFAULT_BEHAVIOR);
}
}
bool
TabChild::RecvAcknowledgeScrollUpdate(const ViewID& aScrollId,
const uint32_t& aScrollGeneration)
{
APZCCallbackHelper::AcknowledgeScrollUpdate(aScrollId, aScrollGeneration);
return true;
}
bool
TabChild::RecvHandleDoubleTap(const CSSPoint& aPoint, const Modifiers& aModifiers, const ScrollableLayerGuid& aGuid)
{
TABC_LOG("Handling double tap at %s with %p %p\n",
Stringify(aPoint).c_str(), mGlobal.get(), mTabChildGlobal.get());
if (!mGlobal || !mTabChildGlobal) {
return true;
}
// Note: there is nothing to do with the modifiers here, as we are not
// synthesizing any sort of mouse event.
CSSPoint point = APZCCallbackHelper::ApplyCallbackTransform(aPoint, aGuid);
nsCOMPtr<nsIDocument> document = GetDocument();
CSSRect zoomToRect = CalculateRectToZoomTo(document, point);
// The double-tap can be dispatched by any scroll frame (so |aGuid| could be
// the guid of any scroll frame), but the zoom-to-rect operation must be
// performed by the root content scroll frame, so query its identifiers
// for the SendZoomToRect() call rather than using the ones from |aGuid|.
uint32_t presShellId;
ViewID viewId;
if (APZCCallbackHelper::GetOrCreateScrollIdentifiers(
document->GetDocumentElement(), &presShellId, &viewId)) {
SendZoomToRect(presShellId, viewId, zoomToRect, DEFAULT_BEHAVIOR);
}
return true;
}
bool
TabChild::RecvHandleSingleTap(const CSSPoint& aPoint, const Modifiers& aModifiers, const ScrollableLayerGuid& aGuid)
void
TabChild::HandleSingleTap(const CSSPoint& aPoint,
const Modifiers& aModifiers,
const ScrollableLayerGuid& aGuid,
bool aCallTakeFocusForClickFromTap)
{
if (aCallTakeFocusForClickFromTap && mRemoteFrame) {
mRemoteFrame->SendTakeFocusForClickFromTap();
}
if (mGlobal && mTabChildGlobal) {
mAPZEventState->ProcessSingleTap(aPoint, aModifiers, aGuid);
}
return true;
}
bool
TabChild::RecvHandleLongTap(const CSSPoint& aPoint, const Modifiers& aModifiers, const ScrollableLayerGuid& aGuid, const uint64_t& aInputBlockId)
void
TabChild::HandleLongTap(const CSSPoint& aPoint, const Modifiers& aModifiers,
const ScrollableLayerGuid& aGuid,
const uint64_t& aInputBlockId)
{
if (mGlobal && mTabChildGlobal) {
mAPZEventState->ProcessLongTap(GetPresShell(), aPoint, aModifiers, aGuid,
aInputBlockId);
}
return true;
}
bool
TabChild::RecvNotifyAPZStateChange(const ViewID& aViewId,
const APZStateChange& aChange,
const int& aArg)
TabChild::NotifyAPZStateChange(const ViewID& aViewId,
const layers::GeckoContentController::APZStateChange& aChange,
const int& aArg)
{
mAPZEventState->ProcessAPZStateChange(GetDocument(), aViewId, aChange, aArg);
if (aChange == APZStateChange::TransformEnd) {
if (aChange == layers::GeckoContentController::APZStateChange::TransformEnd) {
// This is used by tests to determine when the APZ is done doing whatever
// it's doing. XXX generify this as needed when writing additional tests.
DispatchMessageManagerMessage(
@@ -1714,11 +1741,23 @@ TabChild::RecvNotifyAPZStateChange(const ViewID& aViewId,
return true;
}
bool
TabChild::RecvNotifyFlushComplete()
void
TabChild::StartScrollbarDrag(const layers::AsyncDragMetrics& aDragMetrics)
{
APZCCallbackHelper::NotifyFlushComplete();
return true;
if (mAPZChild) {
mAPZChild->SendStartScrollbarDrag(aDragMetrics);
}
}
void
TabChild::ZoomToRect(const uint32_t& aPresShellId,
const FrameMetrics::ViewID& aViewId,
const CSSRect& aRect,
const uint32_t& aFlags)
{
if (mAPZChild) {
mAPZChild->SendZoomToRect(aPresShellId, aViewId, aRect, aFlags);
}
}
bool
@@ -1836,8 +1875,21 @@ TabChild::RecvMouseWheelEvent(const WidgetWheelEvent& aEvent,
}
bool
TabChild::RecvMouseScrollTestEvent(const FrameMetrics::ViewID& aScrollId, const nsString& aEvent)
TabChild::RecvMouseScrollTestEvent(const uint64_t& aLayersId,
const FrameMetrics::ViewID& aScrollId, const nsString& aEvent)
{
if (aLayersId != mLayersId) {
RefPtr<TabParent> browser = TabParent::GetTabParentFromLayersId(aLayersId);
if (!browser) {
return false;
}
NS_DispatchToMainThread(NS_NewRunnableFunction(
[aLayersId, browser, aScrollId, aEvent] () -> void {
Unused << browser->SendMouseScrollTestEvent(aLayersId, aScrollId, aEvent);
}));
return true;
}
APZCCallbackHelper::NotifyMozMouseScrollEvent(aScrollId, aEvent);
return true;
}
@@ -2599,7 +2651,10 @@ TabChild::MakeHidden()
void
TabChild::UpdateHitRegion(const nsRegion& aRegion)
{
mRemoteFrame->SendUpdateHitRegion(aRegion);
mRemoteFrame->SendUpdateHitRegion(aRegion);
if (mAPZChild) {
mAPZChild->SendUpdateHitRegion(aRegion);
}
}
NS_IMETHODIMP
+43 -28
View File
@@ -37,6 +37,7 @@
#include "mozilla/dom/ipc/IdType.h"
#include "AudioChannelService.h"
#include "PuppetWidget.h"
#include "mozilla/layers/GeckoContentController.h"
class nsICachedFileDescriptorListener;
class nsIDOMWindowUtils;
@@ -47,7 +48,9 @@ class RenderFrameChild;
} // namespace layout
namespace layers {
class APZChild;
class APZEventState;
class AsyncDragMetrics;
class ImageCompositeNotification;
} // namespace layers
@@ -324,33 +327,6 @@ public:
const ScreenOrientationInternal& orientation,
const LayoutDeviceIntPoint& chromeDisp) override;
virtual bool RecvUpdateFrame(const layers::FrameMetrics& aFrameMetrics) override;
virtual bool RecvRequestFlingSnap(const ViewID& aScrollId,
const CSSPoint& aDestination) override;
virtual bool RecvAcknowledgeScrollUpdate(const ViewID& aScrollId,
const uint32_t& aScrollGeneration) override;
virtual bool RecvHandleDoubleTap(const CSSPoint& aPoint,
const Modifiers& aModifiers,
const mozilla::layers::ScrollableLayerGuid& aGuid) override;
virtual bool RecvHandleSingleTap(const CSSPoint& aPoint,
const Modifiers& aModifiers,
const mozilla::layers::ScrollableLayerGuid& aGuid) override;
virtual bool RecvHandleLongTap(const CSSPoint& aPoint,
const Modifiers& aModifiers,
const mozilla::layers::ScrollableLayerGuid& aGuid,
const uint64_t& aInputBlockId) override;
virtual bool RecvNotifyAPZStateChange(const ViewID& aViewId,
const APZStateChange& aChange,
const int& aArg) override;
virtual bool RecvNotifyFlushComplete() override;
virtual bool RecvActivate() override;
virtual bool RecvDeactivate() override;
@@ -402,7 +378,8 @@ public:
const int32_t& aModifiers,
const bool& aPreventDefault) override;
virtual bool RecvMouseScrollTestEvent(const FrameMetrics::ViewID& aScrollId,
virtual bool RecvMouseScrollTestEvent(const uint64_t& aLayersId,
const FrameMetrics::ViewID& aScrollId,
const nsString& aEvent) override;
virtual bool RecvNativeSynthesisResponse(const uint64_t& aObserverId,
@@ -585,6 +562,40 @@ public:
PRenderFrameChild* aRenderFrame,
const ShowInfo& aShowInfo);
void ContentReceivedInputBlock(const ScrollableLayerGuid& aGuid,
uint64_t aInputBlockId,
bool aPreventDefault) const;
void SetTargetAPZC(uint64_t aInputBlockId,
const nsTArray<ScrollableLayerGuid>& aTargets) const;
void HandleDoubleTap(const CSSPoint& aPoint,
const Modifiers& aModifiers,
const mozilla::layers::ScrollableLayerGuid& aGuid);
void HandleSingleTap(const CSSPoint& aPoint,
const Modifiers& aModifiers,
const mozilla::layers::ScrollableLayerGuid& aGuid,
bool aCallTakeFocusForClickFromTap);
void HandleLongTap(const CSSPoint& aPoint,
const Modifiers& aModifiers,
const mozilla::layers::ScrollableLayerGuid& aGuid,
const uint64_t& aInputBlockId);
void SetAllowedTouchBehavior(uint64_t aInputBlockId,
const nsTArray<TouchBehaviorFlags>& aFlags) const;
bool UpdateFrame(const FrameMetrics& aFrameMetrics);
bool NotifyAPZStateChange(const ViewID& aViewId,
const layers::GeckoContentController::APZStateChange& aChange,
const int& aArg);
void StartScrollbarDrag(const layers::AsyncDragMetrics& aDragMetrics);
void ZoomToRect(const uint32_t& aPresShellId,
const FrameMetrics::ViewID& aViewId,
const CSSRect& aRect,
const uint32_t& aFlags);
void SetAPZChild(layers::APZChild* aAPZChild)
{
mAPZChild = aAPZChild;
}
protected:
virtual ~TabChild();
@@ -695,6 +706,10 @@ private:
AutoTArray<bool, NUMBER_OF_AUDIO_CHANNELS> mAudioChannelsActive;
// APZChild clears this pointer from its destructor, so it shouldn't be a
// dangling pointer.
layers::APZChild* mAPZChild;
DISALLOW_EVIL_CONSTRUCTORS(TabChild);
};
-168
View File
@@ -977,14 +977,6 @@ TabParent::UpdateDimensions(const nsIntRect& rect, const ScreenIntSize& size)
}
}
void
TabParent::UpdateFrame(const FrameMetrics& aFrameMetrics)
{
if (!mIsDestroyed) {
Unused << SendUpdateFrame(aFrameMetrics);
}
}
void
TabParent::UIResolutionChanged()
{
@@ -1024,76 +1016,6 @@ TabParent::HandleAccessKey(nsTArray<uint32_t>& aCharCodes,
}
}
void
TabParent::RequestFlingSnap(const FrameMetrics::ViewID& aScrollId,
const mozilla::CSSPoint& aDestination)
{
if (!mIsDestroyed) {
Unused << SendRequestFlingSnap(aScrollId, aDestination);
}
}
void
TabParent::AcknowledgeScrollUpdate(const ViewID& aScrollId, const uint32_t& aScrollGeneration)
{
if (!mIsDestroyed) {
Unused << SendAcknowledgeScrollUpdate(aScrollId, aScrollGeneration);
}
}
void TabParent::HandleDoubleTap(const CSSPoint& aPoint,
Modifiers aModifiers,
const ScrollableLayerGuid &aGuid)
{
if (!mIsDestroyed) {
Unused << SendHandleDoubleTap(aPoint, aModifiers, aGuid);
}
}
void TabParent::HandleSingleTap(const CSSPoint& aPoint,
Modifiers aModifiers,
const ScrollableLayerGuid &aGuid)
{
if (!mIsDestroyed) {
Unused << SendHandleSingleTap(aPoint, aModifiers, aGuid);
}
}
void TabParent::HandleLongTap(const CSSPoint& aPoint,
Modifiers aModifiers,
const ScrollableLayerGuid &aGuid,
uint64_t aInputBlockId)
{
if (!mIsDestroyed) {
Unused << SendHandleLongTap(aPoint, aModifiers, aGuid, aInputBlockId);
}
}
void TabParent::NotifyAPZStateChange(ViewID aViewId,
APZStateChange aChange,
int aArg)
{
if (!mIsDestroyed) {
Unused << SendNotifyAPZStateChange(aViewId, aChange, aArg);
}
}
void
TabParent::NotifyMouseScrollTestEvent(const ViewID& aScrollId, const nsString& aEvent)
{
if (!mIsDestroyed) {
Unused << SendMouseScrollTestEvent(aScrollId, aEvent);
}
}
void
TabParent::NotifyFlushComplete()
{
if (!mIsDestroyed) {
Unused << SendNotifyFlushComplete();
}
}
void
TabParent::Activate()
{
@@ -1382,33 +1304,6 @@ CSSPoint TabParent::AdjustTapToChildWidget(const CSSPoint& aPoint)
return aPoint + (LayoutDevicePoint(GetChildProcessOffset()) * GetLayoutDeviceToCSSScale());
}
bool TabParent::SendHandleSingleTap(const CSSPoint& aPoint, const Modifiers& aModifiers, const ScrollableLayerGuid& aGuid)
{
if (mIsDestroyed) {
return false;
}
return PBrowserParent::SendHandleSingleTap(AdjustTapToChildWidget(aPoint), aModifiers, aGuid);
}
bool TabParent::SendHandleLongTap(const CSSPoint& aPoint, const Modifiers& aModifiers, const ScrollableLayerGuid& aGuid, const uint64_t& aInputBlockId)
{
if (mIsDestroyed) {
return false;
}
return PBrowserParent::SendHandleLongTap(AdjustTapToChildWidget(aPoint), aModifiers, aGuid, aInputBlockId);
}
bool TabParent::SendHandleDoubleTap(const CSSPoint& aPoint, const Modifiers& aModifiers, const ScrollableLayerGuid& aGuid)
{
if (mIsDestroyed) {
return false;
}
return PBrowserParent::SendHandleDoubleTap(AdjustTapToChildWidget(aPoint), aModifiers, aGuid);
}
bool TabParent::SendMouseWheelEvent(WidgetWheelEvent& event)
{
if (mIsDestroyed) {
@@ -2789,29 +2684,6 @@ TabParent::RecvBrowserFrameOpenWindow(PBrowserParent* aOpener,
return true;
}
bool
TabParent::RecvZoomToRect(const uint32_t& aPresShellId,
const ViewID& aViewId,
const CSSRect& aRect,
const uint32_t& aFlags)
{
if (RenderFrameParent* rfp = GetRenderFrame()) {
rfp->ZoomToRect(aPresShellId, aViewId, aRect, aFlags);
}
return true;
}
bool
TabParent::RecvUpdateZoomConstraints(const uint32_t& aPresShellId,
const ViewID& aViewId,
const MaybeZoomConstraints& aConstraints)
{
if (RenderFrameParent* rfp = GetRenderFrame()) {
rfp->UpdateZoomConstraints(aPresShellId, aViewId, aConstraints);
}
return true;
}
bool
TabParent::RecvRespondStartSwipeEvent(const uint64_t& aInputBlockId,
const bool& aStartSwipe)
@@ -2822,46 +2694,6 @@ TabParent::RecvRespondStartSwipeEvent(const uint64_t& aInputBlockId,
return true;
}
bool
TabParent::RecvContentReceivedInputBlock(const ScrollableLayerGuid& aGuid,
const uint64_t& aInputBlockId,
const bool& aPreventDefault)
{
if (RenderFrameParent* rfp = GetRenderFrame()) {
rfp->ContentReceivedInputBlock(aGuid, aInputBlockId, aPreventDefault);
}
return true;
}
bool
TabParent::RecvSetTargetAPZC(const uint64_t& aInputBlockId,
nsTArray<ScrollableLayerGuid>&& aTargets)
{
if (RenderFrameParent* rfp = GetRenderFrame()) {
rfp->SetTargetAPZC(aInputBlockId, aTargets);
}
return true;
}
bool
TabParent::RecvStartScrollbarDrag(const AsyncDragMetrics& aDragMetrics)
{
if (RenderFrameParent* rfp = GetRenderFrame()) {
rfp->StartScrollbarDrag(aDragMetrics);
}
return true;
}
bool
TabParent::RecvSetAllowedTouchBehavior(const uint64_t& aInputBlockId,
nsTArray<TouchBehaviorFlags>&& aFlags)
{
if (RenderFrameParent* rfp = GetRenderFrame()) {
rfp->SetAllowedTouchBehavior(aInputBlockId, aFlags);
}
return true;
}
already_AddRefed<nsILoadContext>
TabParent::GetLoadContext()
{
-71
View File
@@ -49,8 +49,6 @@ class CpowHolder;
} // namespace jsipc
namespace layers {
class AsyncDragMetrics;
struct FrameMetrics;
struct TextureFactoryIdentifier;
} // namespace layers
@@ -88,7 +86,6 @@ class TabParent final : public PBrowserParent
, public nsAPostRefreshObserver
{
typedef mozilla::dom::ClonedMessageData ClonedMessageData;
typedef mozilla::layers::AsyncDragMetrics AsyncDragMetrics;
virtual ~TabParent();
@@ -297,31 +294,9 @@ public:
virtual bool RecvDispatchFocusToTopLevelWindow() override;
virtual bool RecvZoomToRect(const uint32_t& aPresShellId,
const ViewID& aViewId,
const CSSRect& aRect,
const uint32_t& aFlags) override;
virtual bool
RecvUpdateZoomConstraints(const uint32_t& aPresShellId,
const ViewID& aViewId,
const MaybeZoomConstraints& aConstraints) override;
virtual bool RecvRespondStartSwipeEvent(const uint64_t& aInputBlockId,
const bool& aStartSwipe) override;
virtual bool
RecvContentReceivedInputBlock(const ScrollableLayerGuid& aGuid,
const uint64_t& aInputBlockId,
const bool& aPreventDefault) override;
virtual bool RecvSetTargetAPZC(const uint64_t& aInputBlockId,
nsTArray<ScrollableLayerGuid>&& aTargets) override;
virtual bool
RecvSetAllowedTouchBehavior(const uint64_t& aInputBlockId,
nsTArray<TouchBehaviorFlags>&& aTargets) override;
virtual bool
RecvDispatchWheelEvent(const mozilla::WidgetWheelEvent& aEvent) override;
@@ -331,9 +306,6 @@ public:
virtual bool
RecvDispatchKeyboardEvent(const mozilla::WidgetKeyboardEvent& aEvent) override;
virtual bool
RecvStartScrollbarDrag(const AsyncDragMetrics& aDragMetrics) override;
virtual PColorPickerParent*
AllocPColorPickerParent(const nsString& aTitle,
const nsString& aInitialColor) override;
@@ -365,8 +337,6 @@ public:
void UpdateDimensions(const nsIntRect& rect, const ScreenIntSize& size);
void UpdateFrame(const layers::FrameMetrics& aFrameMetrics);
void UIResolutionChanged();
void ThemeChanged();
@@ -375,34 +345,6 @@ public:
const bool& aIsTrusted,
const int32_t& aModifierMask);
void RequestFlingSnap(const FrameMetrics::ViewID& aScrollId,
const mozilla::CSSPoint& aDestination);
void AcknowledgeScrollUpdate(const ViewID& aScrollId,
const uint32_t& aScrollGeneration);
void HandleDoubleTap(const CSSPoint& aPoint,
Modifiers aModifiers,
const ScrollableLayerGuid& aGuid);
void HandleSingleTap(const CSSPoint& aPoint,
Modifiers aModifiers,
const ScrollableLayerGuid& aGuid);
void HandleLongTap(const CSSPoint& aPoint,
Modifiers aModifiers,
const ScrollableLayerGuid& aGuid,
uint64_t aInputBlockId);
void NotifyAPZStateChange(ViewID aViewId,
APZStateChange aChange,
int aArg);
void NotifyMouseScrollTestEvent(const ViewID& aScrollId,
const nsString& aEvent);
void NotifyFlushComplete();
void Activate();
void Deactivate();
@@ -482,19 +424,6 @@ public:
bool SendRealTouchEvent(WidgetTouchEvent& event);
bool SendHandleSingleTap(const CSSPoint& aPoint,
const Modifiers& aModifiers,
const ScrollableLayerGuid& aGuid);
bool SendHandleLongTap(const CSSPoint& aPoint,
const Modifiers& aModifiers,
const ScrollableLayerGuid& aGuid,
const uint64_t& aInputBlockId);
bool SendHandleDoubleTap(const CSSPoint& aPoint,
const Modifiers& aModifiers,
const ScrollableLayerGuid& aGuid);
virtual PDocumentRendererParent*
AllocPDocumentRendererParent(const nsRect& documentRect,
const gfx::Matrix& transform,
@@ -24,6 +24,7 @@
#endif
#include "mozilla/X11Util.h"
static void plug_added_cb(GtkWidget *widget, gpointer data);
static gboolean plug_removed_cb (GtkWidget *widget, gpointer data);
static void socket_unrealize_cb (GtkWidget *widget, gpointer data);
@@ -163,6 +164,9 @@ nsresult nsPluginNativeWindowGtk::CreateXEmbedWindow(bool aEnableXtFocus) {
// see plugin_window_filter_func() for details
g_object_set_data(G_OBJECT(mSocketWidget), "enable-xt-focus", (void *)aEnableXtFocus);
g_signal_connect(mSocketWidget, "plug_added",
G_CALLBACK(plug_added_cb), nullptr);
// Make sure to handle the plug_removed signal. If we don't the
// socket will automatically be destroyed when the plug is
// removed, which means we're destroying it more than once.
@@ -278,6 +282,32 @@ nsresult nsPluginNativeWindowGtk::CreateXtWindow() {
}
#endif
static void
plug_window_finalize_cb(gpointer socket, GObject* plug_window)
{
g_object_unref(socket);
}
static void
plug_added_cb(GtkWidget *socket, gpointer data)
{
// The plug window has been embedded, and gtk_socket_add_window() has added
// a filter to the socket's plug_window, passing the socket as data for the
// filter, so the socket must live as long as events may be received on the
// plug window.
//
// https://git.gnome.org/browse/gtk+/tree/gtk/gtksocket.c?h=3.18.7#n1124
g_object_ref(socket);
// When the socket is unrealized, perhaps during gtk_widget_destroy() from
// ~nsPluginNativeWindowGtk, the plug is removed. The plug in the child
// process then destroys its widget and window. When the browser process
// receives the DestroyNotify event for the plug window, GDK releases its
// reference to plugWindow. This is typically the last reference and so the
// weak ref callback triggers release of the socket.
GdkWindow* plugWindow = gtk_socket_get_plug_window(GTK_SOCKET(socket));
g_object_weak_ref(G_OBJECT(plugWindow), plug_window_finalize_cb, socket);
}
/* static */
gboolean
plug_removed_cb (GtkWidget *widget, gpointer data)
-532
View File
@@ -1,532 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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 "mozilla/dom/TVServiceRunnables.h"
#include "mozilla/dom/TVTypes.h"
#include "nsCOMPtr.h"
#include "nsIMutableArray.h"
#include "nsITimer.h"
#include "nsServiceManagerUtils.h"
#include "prtime.h"
#include "FakeTVService.h"
namespace mozilla {
namespace dom {
NS_IMPL_CYCLE_COLLECTION_CLASS(FakeTVService)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(FakeTVService)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSourceListener)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTuners)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChannels)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPrograms)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEITBroadcastedTimer)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mScanCompleteTimer)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(FakeTVService)
tmp->Shutdown();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSourceListener)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mTuners)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mChannels)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPrograms)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mEITBroadcastedTimer)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mScanCompleteTimer)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(FakeTVService)
NS_IMPL_CYCLE_COLLECTING_RELEASE(FakeTVService)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(FakeTVService)
NS_INTERFACE_MAP_ENTRY(nsITVService)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
FakeTVService::FakeTVService()
{
Init();
}
FakeTVService::~FakeTVService()
{
Shutdown();
}
void
FakeTVService::Init()
{
const char* sourceTypes1[2] = {"dvb-t", "dvb-c"};
nsCOMPtr<nsITVTunerData> tunerData1 = MockTuner(NS_LITERAL_STRING("1"), 2, sourceTypes1);
mTuners.AppendElement(tunerData1);
const char* sourceTypes2[1] = {"dvb-s"};
nsCOMPtr<nsITVTunerData> tunerData2 = MockTuner(NS_LITERAL_STRING("2"), 1, sourceTypes2);
mTuners.AppendElement(tunerData2);
nsCOMPtr<nsITVChannelData> channelData1 =
MockChannel(NS_LITERAL_STRING("networkId1"), NS_LITERAL_STRING("transportStreamId1"),
NS_LITERAL_STRING("serviceId1"), NS_LITERAL_STRING("tv"),
NS_LITERAL_STRING("1"), NS_LITERAL_STRING("name1"), true, true);
mChannels.AppendElement(channelData1);
nsCOMPtr<nsITVChannelData> channelData2 =
MockChannel(NS_LITERAL_STRING("networkId2"), NS_LITERAL_STRING("transportStreamId2"),
NS_LITERAL_STRING("serviceId2"), NS_LITERAL_STRING("radio"),
NS_LITERAL_STRING("2"), NS_LITERAL_STRING("name2"), true, true);
mChannels.AppendElement(channelData2);
uint64_t now = PR_Now();
const char* audioLanguages1[2] = {"eng", "jpn"};
const char* subtitleLanguages1[2] = {"fre", "spa"};
nsCOMPtr<nsITVProgramData> programData1 =
MockProgram(NS_LITERAL_STRING("eventId1"), NS_LITERAL_STRING("title1"),
now - 1, 3600000,
NS_LITERAL_STRING("description1"), NS_LITERAL_STRING("rating1"),
2, audioLanguages1, 2, subtitleLanguages1);
mPrograms.AppendElement(programData1);
nsCOMPtr<nsITVProgramData> programData2 =
MockProgram(NS_LITERAL_STRING("eventId2"), NS_LITERAL_STRING("title2"),
now + 3600000 , 3600000,
NS_LITERAL_STRING(""), NS_LITERAL_STRING(""),
0, nullptr, 0, nullptr);
mPrograms.AppendElement(programData2);
}
void
FakeTVService::Shutdown()
{
if (mEITBroadcastedTimer) {
mEITBroadcastedTimer->Cancel();
}
if (mScanCompleteTimer) {
mScanCompleteTimer->Cancel();
}
}
/* virtual */ NS_IMETHODIMP
FakeTVService::GetSourceListener(nsITVSourceListener** aSourceListener)
{
if (!mSourceListener) {
*aSourceListener = nullptr;
return NS_OK;
}
*aSourceListener = mSourceListener;
NS_ADDREF(*aSourceListener);
return NS_OK;
}
/* virtual */ NS_IMETHODIMP
FakeTVService::SetSourceListener(nsITVSourceListener* aSourceListener)
{
mSourceListener = aSourceListener;
return NS_OK;
}
/* virtual */ NS_IMETHODIMP
FakeTVService::GetTuners(nsITVServiceCallback* aCallback)
{
if (!aCallback) {
return NS_ERROR_INVALID_ARG;
}
nsCOMPtr<nsIMutableArray> tunerDataList = do_CreateInstance(NS_ARRAY_CONTRACTID);
if (!tunerDataList) {
return NS_ERROR_OUT_OF_MEMORY;
}
for (uint32_t i = 0; i < mTuners.Length(); i++) {
tunerDataList->AppendElement(mTuners[i], false);
}
nsCOMPtr<nsIRunnable> runnable =
new TVServiceNotifyRunnable(aCallback, tunerDataList);
return NS_DispatchToCurrentThread(runnable);
}
/* virtual */ NS_IMETHODIMP
FakeTVService::SetSource(const nsAString& aTunerId,
const nsAString& aSourceType,
nsITVServiceCallback* aCallback)
{
if (!aCallback) {
return NS_ERROR_INVALID_ARG;
}
for (uint32_t i = 0; i < mTuners.Length(); i++) {
nsString tunerId;
mTuners[i]->GetId(tunerId);
if (aTunerId.Equals(tunerId)) {
uint32_t sourceTypeCount;
char** sourceTypes;
mTuners[i]->GetSupportedSourceTypes(&sourceTypeCount, &sourceTypes);
for (uint32_t j = 0; j < sourceTypeCount; j++) {
nsString sourceType;
sourceType.AssignASCII(sourceTypes[j]);
if (aSourceType.Equals(sourceType)) {
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(sourceTypeCount, sourceTypes);
nsCOMPtr<nsIRunnable> runnable =
new TVServiceNotifyRunnable(aCallback, nullptr);
return NS_DispatchToCurrentThread(runnable);
}
}
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(sourceTypeCount, sourceTypes);
}
}
nsCOMPtr<nsIRunnable> runnable =
new TVServiceNotifyRunnable(aCallback, nullptr, nsITVServiceCallback::TV_ERROR_FAILURE);
return NS_DispatchToCurrentThread(runnable);
}
class EITBroadcastedCallback final : public nsITimerCallback
{
public:
NS_DECL_ISUPPORTS
EITBroadcastedCallback(const nsAString& aTunerId,
const nsAString& aSourceType,
nsITVSourceListener* aSourceListener,
nsITVChannelData* aChannelData)
: mTunerId(aTunerId)
, mSourceType(aSourceType)
, mSourceListener(aSourceListener)
, mChannelData(aChannelData)
{}
NS_IMETHODIMP
Notify(nsITimer* aTimer) override
{
// Notify mock EIT broadcasting.
nsITVProgramData** programDataList =
static_cast<nsITVProgramData **>(NS_Alloc(1 * sizeof(nsITVProgramData*)));
programDataList[0] = new TVProgramData();
programDataList[0]->SetEventId(NS_LITERAL_STRING("eventId"));
programDataList[0]->SetTitle(NS_LITERAL_STRING("title"));
programDataList[0]->SetStartTime(PR_Now() + 3600000);
programDataList[0]->SetDuration(3600000);
programDataList[0]->SetDescription(NS_LITERAL_STRING("description"));
programDataList[0]->SetRating(NS_LITERAL_STRING("rating"));
programDataList[0]->SetAudioLanguages(0, nullptr);
programDataList[0]->SetSubtitleLanguages(0, nullptr);
nsresult rv = mSourceListener->NotifyEITBroadcasted(mTunerId, mSourceType,
mChannelData,
programDataList, 1);
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(1, programDataList);
return rv;
}
private:
~EITBroadcastedCallback() {}
nsString mTunerId;
nsString mSourceType;
nsCOMPtr<nsITVSourceListener> mSourceListener;
nsCOMPtr<nsITVChannelData> mChannelData;
};
NS_IMPL_ISUPPORTS(EITBroadcastedCallback, nsITimerCallback)
class ScanCompleteCallback final : public nsITimerCallback
{
public:
NS_DECL_ISUPPORTS
ScanCompleteCallback(const nsAString& aTunerId,
const nsAString& aSourceType,
nsITVSourceListener* aSourceListener)
: mTunerId(aTunerId)
, mSourceType(aSourceType)
, mSourceListener(aSourceListener)
{}
NS_IMETHODIMP
Notify(nsITimer* aTimer) override
{
return mSourceListener->NotifyChannelScanComplete(mTunerId, mSourceType);
}
private:
~ScanCompleteCallback() {}
nsString mTunerId;
nsString mSourceType;
nsCOMPtr<nsITVSourceListener> mSourceListener;
};
NS_IMPL_ISUPPORTS(ScanCompleteCallback, nsITimerCallback)
/* virtual */ NS_IMETHODIMP
FakeTVService::StartScanningChannels(const nsAString& aTunerId,
const nsAString& aSourceType,
nsITVServiceCallback* aCallback)
{
if (!aCallback) {
return NS_ERROR_INVALID_ARG;
}
nsCOMPtr<nsIRunnable> runnable =
new TVServiceNotifyRunnable(aCallback, nullptr);
nsresult rv = NS_DispatchToCurrentThread(runnable);
NS_ENSURE_SUCCESS(rv, rv);
if (IsAllowed(aTunerId, aSourceType)) {
rv = mSourceListener->NotifyChannelScanned(aTunerId, aSourceType, mChannels[0]);
NS_ENSURE_SUCCESS(rv, rv);
// Set a timer. |notifyEITBroadcasted| will be called after the timer
// fires (10ms). (The timer could be canceled if |StopScanningChannels| gets
// called before firing.)
mEITBroadcastedTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
NS_ENSURE_TRUE(mEITBroadcastedTimer, NS_ERROR_OUT_OF_MEMORY);
RefPtr<EITBroadcastedCallback> eitBroadcastedCb =
new EITBroadcastedCallback(aTunerId, aSourceType, mSourceListener, mChannels[0]);
rv = mEITBroadcastedTimer->InitWithCallback(eitBroadcastedCb, 10,
nsITimer::TYPE_ONE_SHOT);
NS_ENSURE_SUCCESS(rv, rv);
// Set a timer. |notifyChannelScanComplete| will be called after the timer
// fires (20ms). (The timer could be canceled if |StopScanningChannels| gets
// called before firing.)
mScanCompleteTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
NS_ENSURE_TRUE(mScanCompleteTimer, NS_ERROR_OUT_OF_MEMORY);
RefPtr<ScanCompleteCallback> scanCompleteCb =
new ScanCompleteCallback(aTunerId, aSourceType, mSourceListener);
rv = mScanCompleteTimer->InitWithCallback(scanCompleteCb, 20,
nsITimer::TYPE_ONE_SHOT);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}
/* virtual */ NS_IMETHODIMP
FakeTVService::StopScanningChannels(const nsAString& aTunerId,
const nsAString& aSourceType,
nsITVServiceCallback* aCallback)
{
if (!aCallback) {
return NS_ERROR_INVALID_ARG;
}
if (mEITBroadcastedTimer) {
mEITBroadcastedTimer->Cancel();
mEITBroadcastedTimer = nullptr;
}
if (mScanCompleteTimer) {
mScanCompleteTimer->Cancel();
mScanCompleteTimer = nullptr;
}
nsresult rv = mSourceListener->NotifyChannelScanStopped(aTunerId, aSourceType);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIRunnable> runnable =
new TVServiceNotifyRunnable(aCallback, nullptr);
return NS_DispatchToCurrentThread(runnable);
}
/* virtual */ NS_IMETHODIMP
FakeTVService::ClearScannedChannelsCache()
{
// Fake service doesn't support channel cache, so there's nothing to do here.
return NS_OK;
}
/* virtual */ NS_IMETHODIMP
FakeTVService::SetChannel(const nsAString& aTunerId,
const nsAString& aSourceType,
const nsAString& aChannelNumber,
nsITVServiceCallback* aCallback)
{
if (!aCallback) {
return NS_ERROR_INVALID_ARG;
}
nsCOMPtr<nsIMutableArray> channelDataList = do_CreateInstance(NS_ARRAY_CONTRACTID);
if (!channelDataList) {
return NS_ERROR_OUT_OF_MEMORY;
}
if (IsAllowed(aTunerId, aSourceType)) {
for (uint32_t i = 0; i < mChannels.Length(); i++) {
nsString channelNumber;
mChannels[i]->GetNumber(channelNumber);
if (aChannelNumber.Equals(channelNumber)) {
channelDataList->AppendElement(mChannels[i], false);
break;
}
}
}
uint32_t length;
nsresult rv = channelDataList->GetLength(&length);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIRunnable> runnable = new TVServiceNotifyRunnable(
aCallback,
(length == 1) ? channelDataList : nullptr,
(length == 1) ? nsITVServiceCallback::TV_ERROR_OK : nsITVServiceCallback::TV_ERROR_FAILURE
);
return NS_DispatchToCurrentThread(runnable);
}
/* virtual */ NS_IMETHODIMP
FakeTVService::GetChannels(const nsAString& aTunerId,
const nsAString& aSourceType,
nsITVServiceCallback* aCallback)
{
if (!aCallback) {
return NS_ERROR_INVALID_ARG;
}
nsCOMPtr<nsIMutableArray> channelDataList = do_CreateInstance(NS_ARRAY_CONTRACTID);
if (!channelDataList) {
return NS_ERROR_OUT_OF_MEMORY;
}
if (IsAllowed(aTunerId, aSourceType)) {
for (uint32_t i = 0; i < mChannels.Length(); i++) {
channelDataList->AppendElement(mChannels[i], false);
}
}
nsCOMPtr<nsIRunnable> runnable =
new TVServiceNotifyRunnable(aCallback, channelDataList);
return NS_DispatchToCurrentThread(runnable);
}
/* virtual */ NS_IMETHODIMP
FakeTVService::GetPrograms(const nsAString& aTunerId,
const nsAString& aSourceType,
const nsAString& aChannelNumber,
uint64_t startTime,
uint64_t endTime,
nsITVServiceCallback* aCallback)
{
if (!aCallback) {
return NS_ERROR_INVALID_ARG;
}
nsCOMPtr<nsIMutableArray> programDataList = do_CreateInstance(NS_ARRAY_CONTRACTID);
if (!programDataList) {
return NS_ERROR_OUT_OF_MEMORY;
}
// Only return mock programs for the first channel.
nsString channelNumber;
mChannels[0]->GetNumber(channelNumber);
if (IsAllowed(aTunerId, aSourceType) && aChannelNumber.Equals(channelNumber)) {
for (uint32_t i = 0; i < mPrograms.Length(); i++) {
programDataList->AppendElement(mPrograms[i], false);
}
}
nsCOMPtr<nsIRunnable> runnable =
new TVServiceNotifyRunnable(aCallback, programDataList);
return NS_DispatchToCurrentThread(runnable);
}
/* virtual */ NS_IMETHODIMP
FakeTVService::GetOverlayId(const nsAString& aTunerId,
nsITVServiceCallback* aCallback)
{
if (!aCallback) {
return NS_ERROR_INVALID_ARG;
}
nsCOMPtr<nsIMutableArray> overlayIds = do_CreateInstance(NS_ARRAY_CONTRACTID);
if (!overlayIds) {
return NS_ERROR_OUT_OF_MEMORY;
}
// TODO Implement in follow-up patches.
nsCOMPtr<nsIRunnable> runnable =
new TVServiceNotifyRunnable(aCallback, overlayIds);
return NS_DispatchToCurrentThread(runnable);
}
bool
FakeTVService::IsAllowed(const nsAString& aTunerId,
const nsAString& aSourceType)
{
// Only allow for the first source of the first tuner.
nsString tunerId;
mTuners[0]->GetId(tunerId);
if (!aTunerId.Equals(tunerId)) {
return false;
}
uint32_t sourceTypeCount;
char** sourceTypes;
mTuners[0]->GetSupportedSourceTypes(&sourceTypeCount, &sourceTypes);
nsString sourceType;
sourceType.AssignASCII(sourceTypes[0]);
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(sourceTypeCount, sourceTypes);
if (!aSourceType.Equals(sourceType)) {
return false;
}
return true;
}
already_AddRefed<nsITVTunerData>
FakeTVService::MockTuner(const nsAString& aId,
uint32_t aSupportedSourceTypeCount,
const char** aSupportedSourceTypes)
{
nsCOMPtr<nsITVTunerData> tunerData = new TVTunerData();
tunerData->SetId(aId);
tunerData->SetSupportedSourceTypes(aSupportedSourceTypeCount, aSupportedSourceTypes);
return tunerData.forget();
}
already_AddRefed<nsITVChannelData>
FakeTVService::MockChannel(const nsAString& aNetworkId,
const nsAString& aTransportStreamId,
const nsAString& aServiceId,
const nsAString& aType,
const nsAString& aNumber,
const nsAString& aName,
bool aIsEmergency,
bool aIsFree)
{
nsCOMPtr<nsITVChannelData> channelData = new TVChannelData();
channelData->SetNetworkId(aNetworkId);
channelData->SetTransportStreamId(aTransportStreamId);
channelData->SetServiceId(aServiceId);
channelData->SetType(aType);
channelData->SetNumber(aNumber);
channelData->SetName(aName);
channelData->SetIsEmergency(aIsEmergency);
channelData->SetIsFree(aIsFree);
return channelData.forget();
}
already_AddRefed<nsITVProgramData>
FakeTVService::MockProgram(const nsAString& aEventId,
const nsAString& aTitle,
uint64_t aStartTime,
uint64_t aDuration,
const nsAString& aDescription,
const nsAString& aRating,
uint32_t aAudioLanguageCount,
const char** aAudioLanguages,
uint32_t aSubtitleLanguageCount,
const char** aSubtitleLanguages)
{
nsCOMPtr<nsITVProgramData> programData = new TVProgramData();
programData->SetEventId(aEventId);
programData->SetTitle(aTitle);
programData->SetStartTime(aStartTime);
programData->SetDuration(aDuration);
programData->SetDescription(aDescription);
programData->SetRating(aRating);
programData->SetAudioLanguages(aAudioLanguageCount, aAudioLanguages);
programData->SetSubtitleLanguages(aSubtitleLanguageCount, aSubtitleLanguages);
return programData.forget();
}
} // namespace dom
} // namespace mozilla
-84
View File
@@ -1,84 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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_dom_FakeTVService_h
#define mozilla_dom_FakeTVService_h
#include "nsCOMPtr.h"
#include "nsCycleCollectionParticipant.h"
#include "nsITVService.h"
#include "nsTArray.h"
#define FAKE_TV_SERVICE_CONTRACTID \
"@mozilla.org/tv/faketvservice;1"
#define FAKE_TV_SERVICE_CID \
{ 0x60fb3c53, 0x017f, 0x4340, { 0x91, 0x1b, 0xd5, 0x5c, 0x31, 0x28, 0x88, 0xb6 } }
class nsITimer;
class nsITVTunerData;
class nsITVChannelData;
class nsITVProgramData;
namespace mozilla {
namespace dom {
class FakeTVService final : public nsITVService
{
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS(FakeTVService)
NS_DECL_NSITVSERVICE
FakeTVService();
private:
~FakeTVService();
void Init();
void Shutdown();
bool IsAllowed(const nsAString& aTunerId,
const nsAString& aSourceType);
already_AddRefed<nsITVTunerData> MockTuner(const nsAString& aId,
uint32_t aSupportedSourceTypeCount,
const char** aSupportedSourceTypes);
already_AddRefed<nsITVChannelData> MockChannel(const nsAString& aNetworkId,
const nsAString& aTransportStreamId,
const nsAString& aServiceId,
const nsAString& aType,
const nsAString& aNumber,
const nsAString& aName,
bool aIsEmergency,
bool aIsFree);
already_AddRefed<nsITVProgramData> MockProgram(const nsAString& aEventId,
const nsAString& aTitle,
uint64_t aStartTime,
uint64_t aDuration,
const nsAString& aDescription,
const nsAString& aRating,
uint32_t aAudioLanguageCount,
const char** aAudioLanguages,
uint32_t aSubtitleLanguageCount,
const char** aSubtitleLanguages);
nsCOMPtr<nsITVSourceListener> mSourceListener;
// The real implementation may want to use more efficient data structures.
nsTArray<nsCOMPtr<nsITVTunerData>> mTuners;
nsTArray<nsCOMPtr<nsITVChannelData>> mChannels;
nsTArray<nsCOMPtr<nsITVProgramData>> mPrograms;
nsCOMPtr<nsITimer> mEITBroadcastedTimer;
nsCOMPtr<nsITimer> mScanCompleteTimer;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_FakeTVService_h
+3 -16
View File
@@ -4,7 +4,6 @@
* 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 "mozilla/dom/FakeTVService.h"
#include "mozilla/dom/TVListeners.h"
#include "mozilla/Preferences.h"
#include "nsITVService.h"
@@ -15,26 +14,14 @@
namespace mozilla {
namespace dom {
/* static */ already_AddRefed<FakeTVService>
TVServiceFactory::CreateFakeTVService()
{
RefPtr<FakeTVService> service = new FakeTVService();
return service.forget();
}
/* static */ already_AddRefed<nsITVService>
TVServiceFactory::AutoCreateTVService()
{
nsresult rv;
nsresult rv = NS_OK;
nsCOMPtr<nsITVService> service = do_CreateInstance(TV_SERVICE_CONTRACTID);
if (!service) {
if (Preferences::GetBool("dom.ignore_webidl_scope_checks", false)) {
// Fallback to the fake service.
service = do_CreateInstance(FAKE_TV_SERVICE_CONTRACTID, &rv);
} else {
// Fallback to the TV Simulator Service
service = do_CreateInstance(TV_SIMULATOR_SERVICE_CONTRACTID, &rv);
}
// Fallback to the TV Simulator Service
service = do_CreateInstance(TV_SIMULATOR_SERVICE_CONTRACTID, &rv);
if (NS_WARN_IF(NS_FAILED(rv))) {
return nullptr;
-4
View File
@@ -14,13 +14,9 @@ class nsITVService;
namespace mozilla {
namespace dom {
class FakeTVService;
class TVServiceFactory
{
public:
static already_AddRefed<FakeTVService> CreateFakeTVService();
static already_AddRefed<nsITVService> AutoCreateTVService();
};
+47 -29
View File
@@ -13,9 +13,11 @@ const Ci = Components.interfaces;
const Cr = Components.returnCode;
Cu.importGlobalProperties(["File"]);
Cu.import("resource://gre/modules/Services.jsm");
const TV_SIMULATOR_DUMMY_DIRECTORY = "dummy";
const TV_SIMULATOR_DUMMY_FILE = "settings.json";
const TV_SIMULATOR_DUMMY_DIRECTORY = "dummy";
const TV_SIMULATOR_DUMMY_FILE = "settings.json";
const TV_SIMULATOR_MOCK_DATA = Services.prefs.getCharPref("dom.testing.tv_mock_data");
// See http://seanyhlin.github.io/TV-Manager-API/#idl-def-TVSourceType
const TV_SOURCE_TYPES = ["dvb-t","dvb-t2","dvb-c","dvb-c2","dvb-s",
@@ -49,36 +51,16 @@ TVSimulatorService.prototype = {
return;
}
// Load the setting file from local JSON file.
// Synchrhronous File Reading.
let file = Cc["@mozilla.org/file/local;1"]
.createInstance(Ci.nsILocalFile);
file.initWithPath(this._getFilePath(TV_SIMULATOR_DUMMY_FILE));
let fstream = Cc["@mozilla.org/network/file-input-stream;1"]
.createInstance(Ci.nsIFileInputStream);
let cstream = Cc["@mozilla.org/intl/converter-input-stream;1"]
.createInstance(Ci.nsIConverterInputStream);
let settingStr = "";
try {
fstream.init(file, -1, 0, 0);
cstream.init(fstream,
"UTF-8",
1024,
Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
let str = {};
while (cstream.readString(0xffffffff, str) != 0) {
settingStr += str.value;
if (TV_SIMULATOR_MOCK_DATA) {
settingStr = TV_SIMULATOR_MOCK_DATA;
} else {
settingStr = this._getDummyData();
}
} catch(e) {
debug("Error occurred : " + e );
return;
} finally {
cstream.close();
}
let settingsObj;
@@ -281,10 +263,11 @@ TVSimulatorService.prototype = {
}
this._scanCompleteTimer = null;
let notifyResult = this._sourceListener.notifyChannelScanComplete(
this._scanningWrapTunerData.tuner.id,
this._scanningWrapTunerData.sourceType);
this._scanningWrapTunerData = null;
return this._sourceListener.notifyChannelScanComplete(
this._scanningWrapTunerData.tuner.id,
this._scanningWrapTunerData.sourceType);
return notifyResult;
},
stopScanningChannels: function TVSimStopScanningChannels(aTunerId, aSourceType, aCallback) {
@@ -434,6 +417,41 @@ TVSimulatorService.prototype = {
return videoBlobURL;
},
_getDummyData : function TVSimGetDummyData() {
// Load the setting file from local JSON file.
// Synchrhronous File Reading.
let file = Cc["@mozilla.org/file/local;1"]
.createInstance(Ci.nsILocalFile);
let fstream = Cc["@mozilla.org/network/file-input-stream;1"]
.createInstance(Ci.nsIFileInputStream);
let cstream = Cc["@mozilla.org/intl/converter-input-stream;1"]
.createInstance(Ci.nsIConverterInputStream);
let settingsStr = "";
try {
file.initWithPath(this._getFilePath(TV_SIMULATOR_DUMMY_FILE));
fstream.init(file, -1, 0, 0);
cstream.init(fstream,
"UTF-8",
1024,
Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
let str = {};
while (cstream.readString(0xffffffff, str) != 0) {
settingsStr += str.value;
}
} catch(e) {
debug("Catch the Exception when reading the dummy file:" + e );
throw e;
} finally {
cstream.close();
}
return settingsStr;
},
_getTunerMapKey: function TVSimGetTunerMapKey(aTunerId, aSourceType) {
return JSON.stringify({'tunerId': aTunerId, 'sourceType': aSourceType});
},
-2
View File
@@ -5,7 +5,6 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
EXPORTS.mozilla.dom += [
'FakeTVService.h',
'TVChannel.h',
'TVListeners.h',
'TVManager.h',
@@ -20,7 +19,6 @@ EXPORTS.mozilla.dom += [
]
UNIFIED_SOURCES += [
'FakeTVService.cpp',
'TVChannel.cpp',
'TVListeners.cpp',
'TVManager.cpp',
+14 -2
View File
@@ -9,8 +9,20 @@ function setupPrefsAndPermissions(callback) {
}
function setupPrefs(callback) {
SpecialPowers.pushPrefEnv({"set": [["dom.tv.enabled", true],
["dom.ignore_webidl_scope_checks", true]]}, function() {
let xhr = new XMLHttpRequest;
let data;
xhr.open("GET", "./mock_data.json", false);
xhr.send(null);
if (xhr.status == 200) {
data = xhr.responseText;
}
SpecialPowers.pushPrefEnv({"set": [
["dom.tv.enabled", true],
["dom.ignore_webidl_scope_checks", true],
["dom.testing.tv_mock_data", data]
]}, function() {
callback();
});
}
+4 -2
View File
@@ -1,6 +1,8 @@
[DEFAULT]
support-files = head.js
skip-if = (os == 'mac' && debug) || asan # Bug 1125477
support-files =
head.js
mock_data.json
[test_tv_non_permitted_app.html]
[test_tv_permitted_app.html]
[test_tv_get_tuners.html]
+99
View File
@@ -0,0 +1,99 @@
{
"tuners": [
{
"id":"1",
"supportedType": ["dvb-t"],
"sources": [
{
"type": "dvb-t",
"channels": [
{
"networkId": "32112",
"transportStreamId": "32112",
"serviceId": "40960",
"type": "tv",
"name": "TV #1",
"number" : 1,
"isEmergency": false,
"isFree" : true,
"videoFilePath": "tv1.ogv",
"programs": [
{"eventId":"734475972", "title":"News of Morning", "startTime":"1430686800", "duration":"10800", "description":"Morning News", "rating":"0", "audioLanguages":["eng"], "subtitleLanguages":["eng"]},
{"eventId":"422158917", "title":"News of Midnight", "startTime":"1431266400", "duration":"3600", "description":"Summary of today news", "rating":"0", "audioLanguages":["eng"], "subtitleLanguages":["eng"]},
{"eventId":"533612446", "title":"Entertainment Program", "startTime":"1431270000", "duration":"7200", "description":"Midnight entertainment program", "rating":"0", "audioLanguages":["eng"], "subtitleLanguages":["eng"]}
]
},
{
"_comment": "Channel Data",
"networkId": "32122",
"transportStreamId": "32122",
"serviceId": "40990",
"type": "tv",
"name": "TV #2",
"number" : 2,
"isEmergency": false,
"isFree" : true,
"videoFilePath": "tv2.ogv",
"programs": [
{"eventId":"931109607","title":"News of Morning", "startTime":"1430686800", "duration":"10800", "description":"Provide news in morning", "rating":"0", "audioLanguages":["eng"], "subtitleLanguages":["eng"]},
{"eventId":"297834220","title":"Weekly News", "startTime":"1431259200", "duration":"10800", "description":"Poopular Music program", "rating":"0", "audioLanguages":["eng"], "subtitleLanguages":["eng"]},
{"eventId":"866886159","title":"Weekly news", "startTime":"1431270000", "duration":"7200", "description":"Information program on Monday", "rating":"0", "audioLanguages":["eng"], "subtitleLanguages":["eng"]}
]
},
{
"_comment": "Channel Data",
"networkId": "32132",
"transportStreamId": "32132",
"serviceId": "41020",
"type": "tv",
"name": "TV #3",
"number" : 3,
"isEmergency": false,
"isFree" : true,
"videoFilePath": "tv1.ogv",
"programs": [
{"eventId":"734475972", "title":"News of Morning", "startTime":"1430686800", "duration":"10800", "description":"Morning News", "rating":"0", "audioLanguages":["eng"], "subtitleLanguages":["eng"]},
{"eventId":"586216742", "title":"Information Program", "startTime":"1430697600", "duration":"7200", "description":"Provide program Information.", "rating":"0", "audioLanguages":["eng"], "subtitleLanguages":["eng"]},
{"eventId":"533612446", "title":"Entertainment Program", "startTime":"1431270000", "duration":"7200", "description":"Midnight entertainment program", "rating":"0", "audioLanguages":["eng"], "subtitleLanguages":["eng"]}
]
},
{
"_comment": "Channel Data",
"networkId": "32142",
"transportStreamId": "32142",
"serviceId": "41040",
"type": "tv",
"name": "TV #5",
"number" : 4,
"isEmergency": false,
"isFree" : true,
"videoFilePath": "tv2.ogv",
"programs": [
{"eventId":"931109607","title":"News of Morning", "startTime":"1430686800", "duration":"10800", "description":"Provide news in morning", "rating":"0", "audioLanguages":["eng"], "subtitleLanguages":["eng"]},
{"eventId":"297834220","title":"Weekly News", "startTime":"1431259200", "duration":"10800", "description":"Poopular Music program", "rating":"0", "audioLanguages":["eng"], "subtitleLanguages":["eng"]},
{"eventId":"866886159","title":"Weekly news", "startTime":"1431270000", "duration":"7200", "description":"Information program on Monday", "rating":"0", "audioLanguages":["eng"], "subtitleLanguages":["eng"]}
]
},
{
"_comment": "Channel Data",
"networkId": "32152",
"transportStreamId": "32152",
"serviceId": "41060",
"type": "tv",
"name": "TV #5",
"number" : 5,
"isEmergency": false,
"isFree" : true,
"videoFilePath": "tv1.ogv",
"programs": [
{"eventId":"734475972", "title":"News of Morning", "startTime":"1430686800", "duration":"10800", "description":"Morning News", "rating":"0", "audioLanguages":["eng"], "subtitleLanguages":["eng"]},
{"eventId":"586216742", "title":"Information Program", "startTime":"1430697600", "duration":"7200", "description":"Provide program Information.", "rating":"0", "audioLanguages":["eng"], "subtitleLanguages":["eng"]},
{"eventId":"533612446", "title":"Entertainment Program", "startTime":"1431270000", "duration":"7200", "description":"Midnight entertainment program", "rating":"0", "audioLanguages":["eng"], "subtitleLanguages":["eng"]}
]
}
]
}
]
}
]
}
@@ -0,0 +1,48 @@
/* -*- Mode: IDL; 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/.
*/
/*
* This file declares data structures used to communicate checkerboard reports
* from C++ code to about:checkerboard (see bug 1238042). These dictionaries
* are NOT exposed to standard web content.
*/
enum CheckerboardReason {
"severe",
"recent"
};
// Individual checkerboard report. Contains fields for the severity of the
// checkerboard event, the timestamp at which it was reported, the detailed
// log of the event, and the reason this report was saved (currently either
// "severe" or "recent").
dictionary CheckerboardReport {
unsigned long severity;
DOMTimeStamp timestamp; // milliseconds since epoch
DOMString log;
CheckerboardReason reason;
};
// The guard function only allows creation of this interface on the
// about:checkerboard page, and only if it's in the parent process.
[Func="mozilla::dom::CheckerboardReportService::IsEnabled",
Constructor]
interface CheckerboardReportService {
/**
* Gets the available checkerboard reports.
*/
sequence<CheckerboardReport> getReports();
/**
* Gets the state of the apz.record_checkerboarding pref.
*/
boolean isRecordingEnabled();
/**
* Sets the state of the apz.record_checkerboarding pref.
*/
void setRecordingEnabled(boolean aEnabled);
};
+1
View File
@@ -77,6 +77,7 @@ WEBIDL_FILES = [
'ChannelMergerNode.webidl',
'ChannelSplitterNode.webidl',
'CharacterData.webidl',
'CheckerboardReportService.webidl',
'ChildNode.webidl',
'ChromeNodeList.webidl',
'ChromeNotifications.webidl',
+17 -9
View File
@@ -14,6 +14,7 @@
#ifdef MOZ_LOGGING
#include "mozilla/Logging.h"
#endif
#include "mozilla/Tuple.h"
#if defined(MOZ_WIDGET_GONK) || defined(MOZ_WIDGET_ANDROID)
#include "nsDebug.h"
@@ -95,8 +96,7 @@ public:
/// In the event of a crash, the crash report is annotated with first and
/// the last few of these errors, under the key GraphicsCriticalError.
/// The total number of errors stored in the crash report is controlled
/// by preference gfx.logging.crash.length (default is six, so by default,
/// the first as well as the last five would show up in the crash log.)
/// by preference gfx.logging.crash.length.
///
/// On platforms that support MOZ_LOGGING, the story is slightly more involved.
/// In that case, unless gfx.logging.level is set to 4 or higher, the output
@@ -130,6 +130,7 @@ enum class LogReason : int {
GlyphAllocFailedCG,
InvalidRect,
CannotDraw3D, // 20
IncompatibleBasicTexturedEffect,
// End
MustBeLessThanThis = 101,
};
@@ -196,19 +197,24 @@ struct CriticalLogger {
static void CrashAction(LogReason aReason);
};
// The int is the index of the Log call; if the number of logs exceeds some preset
// capacity we may not get all of them, so the indices help figure out which
// ones we did save. The double is expected to be the "TimeDuration",
// time in seconds since the process creation.
typedef mozilla::Tuple<int32_t,std::string,double> LoggingRecordEntry;
// Implement this interface and init the Factory with an instance to
// forward critical logs.
typedef std::vector<LoggingRecordEntry> LoggingRecord;
class LogForwarder {
public:
virtual ~LogForwarder() {}
virtual void Log(const std::string &aString) = 0;
virtual void CrashAction(LogReason aReason) = 0;
virtual bool UpdateStringsVector(const std::string& aString) = 0;
// Provide a copy of the logs to the caller. The int is the index
// of the Log call, if the number of logs exceeds some preset capacity
// we may not get all of them, so the indices help figure out which
// ones we did save.
virtual std::vector<std::pair<int32_t,std::string> > StringsVectorCopy() = 0;
// Provide a copy of the logs to the caller.
virtual LoggingRecord LoggingRecordCopy() = 0;
};
class NoLog
@@ -273,7 +279,7 @@ public:
if (!str.empty()) {
WriteLog(str);
}
mMessage.clear();
mMessage.str("");
}
Log &operator <<(char aChar) {
@@ -378,7 +384,9 @@ public:
template<typename T>
Log &operator<<(Hexa<T> aHex) {
if (MOZ_UNLIKELY(LogIt())) {
mMessage << "0x" << std::hex << aHex.mVal << std::dec;
mMessage << std::showbase << std::hex
<< aHex.mVal
<< std::noshowbase << std::dec;
}
return *this;
}
+4 -4
View File
@@ -220,6 +220,10 @@ IMFYCbCrImage::GetD3D9TextureClient(CompositableClient* aClient)
TextureClient*
IMFYCbCrImage::GetTextureClient(CompositableClient* aClient)
{
if (mTextureClient) {
return mTextureClient;
}
LayersBackend backend = aClient->GetForwarder()->GetCompositorBackendType();
ID3D11Device* device = gfxWindowsPlatform::GetPlatform()->GetD3D11ImageBridgeDevice();
@@ -231,10 +235,6 @@ IMFYCbCrImage::GetTextureClient(CompositableClient* aClient)
return nullptr;
}
if (mTextureClient) {
return mTextureClient;
}
RefPtr<ID3D11DeviceContext> ctx;
device->GetImmediateContext(getter_AddRefs(ctx));
+1 -1
View File
@@ -869,7 +869,7 @@ public:
already_AddRefed<gfx::SourceSurface> GetAsSourceSurface() { return nullptr; } ;
int32_t GetOverlayId() { return mOverlayId; }
const GonkNativeHandle& GetSidebandStream() { return mSidebandStream; }
GonkNativeHandle& GetSidebandStream() { return mSidebandStream; }
gfx::IntSize GetSize() { return mSize; }
+2 -2
View File
@@ -76,8 +76,8 @@ static gfxFloat RecoverZDepth(const Matrix4x4& aTransform, const gfxPoint& aPoin
* unsolved without changing our rendering code.
*/
static LayerSortOrder CompareDepth(Layer* aOne, Layer* aTwo) {
gfxRect ourRect = ThebesRect(aOne->GetEffectiveVisibleRegion().ToUnknownRegion().GetBounds());
gfxRect otherRect = ThebesRect(aTwo->GetEffectiveVisibleRegion().ToUnknownRegion().GetBounds());
gfxRect ourRect = ThebesRect(aOne->GetLocalVisibleRegion().ToUnknownRegion().GetBounds());
gfxRect otherRect = ThebesRect(aTwo->GetLocalVisibleRegion().ToUnknownRegion().GetBounds());
MOZ_ASSERT(aOne->GetParent() && aOne->GetParent()->Extend3DContext() &&
aTwo->GetParent() && aTwo->GetParent()->Extend3DContext());
+6 -6
View File
@@ -123,7 +123,7 @@ NotifySubdocumentInvalidationRecursive(Layer* aLayer, NotifySubDocInvalidationFu
NotifySubdocumentInvalidationRecursive(child, aCallback);
}
aCallback(container, container->GetVisibleRegion().ToUnknownRegion());
aCallback(container, container->GetLocalVisibleRegion().ToUnknownRegion());
}
struct LayerPropertiesBase : public LayerProperties
@@ -131,7 +131,7 @@ struct LayerPropertiesBase : public LayerProperties
explicit LayerPropertiesBase(Layer* aLayer)
: mLayer(aLayer)
, mMaskLayer(nullptr)
, mVisibleRegion(mLayer->GetEffectiveVisibleRegion().ToUnknownRegion())
, mVisibleRegion(mLayer->GetLocalVisibleRegion().ToUnknownRegion())
, mInvalidRegion(aLayer->GetInvalidRegion())
, mPostXScale(aLayer->GetPostXScale())
, mPostYScale(aLayer->GetPostYScale())
@@ -233,7 +233,7 @@ struct LayerPropertiesBase : public LayerProperties
virtual IntRect NewTransformedBounds()
{
return TransformRect(mLayer->GetVisibleRegion().ToUnknownRegion().GetBounds(),
return TransformRect(mLayer->GetLocalVisibleRegion().ToUnknownRegion().GetBounds(),
GetTransformForInvalidation(mLayer));
}
@@ -345,7 +345,7 @@ struct ContainerLayerProperties : public LayerPropertiesBase
}
if (invalidateChildsCurrentArea) {
aGeometryChanged = true;
AddTransformedRegion(result, child->GetVisibleRegion().ToUnknownRegion(),
AddTransformedRegion(result, child->GetLocalVisibleRegion().ToUnknownRegion(),
GetTransformForInvalidation(child));
if (aCallback) {
NotifySubdocumentInvalidationRecursive(child, aCallback);
@@ -477,7 +477,7 @@ struct ImageLayerProperties : public LayerPropertiesBase
{
ImageLayer* imageLayer = static_cast<ImageLayer*>(mLayer.get());
if (!imageLayer->GetVisibleRegion().ToUnknownRegion().IsEqual(mVisibleRegion)) {
if (!imageLayer->GetLocalVisibleRegion().ToUnknownRegion().IsEqual(mVisibleRegion)) {
aGeometryChanged = true;
IntRect result = NewTransformedBounds();
result = result.Union(OldTransformedBounds());
@@ -619,7 +619,7 @@ LayerPropertiesBase::ComputeDifferences(Layer* aRoot, NotifySubDocInvalidationFu
} else {
ClearInvalidations(aRoot);
}
IntRect result = TransformRect(aRoot->GetVisibleRegion().ToUnknownRegion().GetBounds(),
IntRect result = TransformRect(aRoot->GetLocalVisibleRegion().ToUnknownRegion().GetBounds(),
aRoot->GetLocalTransform());
result = result.Union(OldTransformedBounds());
if (aGeometryChanged != nullptr) {
+21 -13
View File
@@ -602,7 +602,7 @@ Layer::GetEffectiveClipRect()
}
const LayerIntRegion&
Layer::GetEffectiveVisibleRegion()
Layer::GetLocalVisibleRegion()
{
if (LayerComposite* shadow = AsLayerComposite()) {
return shadow->GetShadowVisibleRegion();
@@ -799,6 +799,11 @@ Layer::CalculateScissorRect(const RenderTargetIntRect& aCurrentScissorRect)
// When our visible region is empty, our parent may not have created the
// intermediate surface that we would require for correct clipping; however,
// this does not matter since we are invisible.
// Note that we do not use GetLocalVisibleRegion(), because that can be
// empty for a layer whose rendered contents have been async-scrolled
// completely offscreen, but for which we still need to draw a
// checkerboarding backround color, and calculating an empty scissor rect
// for such a layer would prevent that (see bug 1247452 comment 10).
return RenderTargetIntRect(currentClip.TopLeft(), RenderTargetIntSize(0, 0));
}
@@ -888,7 +893,7 @@ Layer::GetLocalTransform()
{
Matrix4x4 transform;
if (LayerComposite* shadow = AsLayerComposite())
transform = shadow->GetShadowTransform();
transform = shadow->GetShadowBaseTransform();
else
transform = mTransform;
@@ -1017,7 +1022,7 @@ Layer::GetVisibleRegionRelativeToRootLayer(nsIntRegion& aResult,
}
IntPoint offset;
aResult = GetEffectiveVisibleRegion().ToUnknownRegion();
aResult = GetLocalVisibleRegion().ToUnknownRegion();
for (Layer* layer = this; layer; layer = layer->GetParent()) {
gfx::Matrix matrix;
if (!layer->GetLocalTransform().Is2D(&matrix) ||
@@ -1054,7 +1059,7 @@ Layer::GetVisibleRegionRelativeToRootLayer(nsIntRegion& aResult,
// Retreive the translation from sibling to |layer|. The accumulated
// visible region is currently oriented with |layer|.
IntPoint siblingOffset = RoundedToInt(siblingMatrix.GetTranslation());
nsIntRegion siblingVisibleRegion(sibling->GetEffectiveVisibleRegion().ToUnknownRegion());
nsIntRegion siblingVisibleRegion(sibling->GetLocalVisibleRegion().ToUnknownRegion());
// Translate the siblings region to |layer|'s origin.
siblingVisibleRegion.MoveBy(-siblingOffset.x, -siblingOffset.y);
// Apply the sibling's clip.
@@ -1303,7 +1308,7 @@ ContainerLayer::HasMultipleChildren()
const Maybe<ParentLayerIntRect>& clipRect = child->GetEffectiveClipRect();
if (clipRect && clipRect->IsEmpty())
continue;
if (child->GetVisibleRegion().IsEmpty())
if (child->GetLocalVisibleRegion().IsEmpty())
continue;
++count;
if (count > 1)
@@ -1382,7 +1387,7 @@ ContainerLayer::DefaultComputeEffectiveTransforms(const Matrix4x4& aTransformToS
} else {
float opacity = GetEffectiveOpacity();
CompositionOp blendMode = GetEffectiveMixBlendMode();
if (((opacity != 1.0f || blendMode != CompositionOp::OP_OVER) && HasMultipleChildren()) ||
if (((opacity != 1.0f || blendMode != CompositionOp::OP_OVER) && (HasMultipleChildren() || Creates3DContextWithExtendingChildren())) ||
(!idealTransform.Is2D() && Creates3DContextWithExtendingChildren())) {
useIntermediateSurface = true;
} else {
@@ -1419,7 +1424,7 @@ ContainerLayer::DefaultComputeEffectiveTransforms(const Matrix4x4& aTransformToS
* the calculations performed by CalculateScissorRect above.
* Nor for a child with a mask layer.
*/
if (checkClipRect && (clipRect && !clipRect->IsEmpty() && !child->GetVisibleRegion().IsEmpty())) {
if (checkClipRect && (clipRect && !clipRect->IsEmpty() && !child->GetLocalVisibleRegion().IsEmpty())) {
useIntermediateSurface = true;
break;
}
@@ -1445,7 +1450,7 @@ ContainerLayer::DefaultComputeEffectiveTransforms(const Matrix4x4& aTransformToS
// transform while 2D is expected.
idealTransform.ProjectTo2D();
}
mUseIntermediateSurface = useIntermediateSurface && !GetEffectiveVisibleRegion().IsEmpty();
mUseIntermediateSurface = useIntermediateSurface && !GetLocalVisibleRegion().IsEmpty();
if (useIntermediateSurface) {
ComputeEffectiveTransformsForChildren(Matrix4x4::From2D(residual));
} else {
@@ -1475,7 +1480,7 @@ ContainerLayer::DefaultComputeSupportsComponentAlphaChildren(bool* aNeedsSurface
bool needsSurfaceCopy = false;
CompositionOp blendMode = GetEffectiveMixBlendMode();
if (UseIntermediateSurface()) {
if (GetEffectiveVisibleRegion().GetNumRects() == 1 &&
if (GetLocalVisibleRegion().GetNumRects() == 1 &&
(GetContentFlags() & Layer::CONTENT_OPAQUE))
{
mSupportsComponentAlphaChildren = true;
@@ -1884,6 +1889,9 @@ Layer::PrintInfo(std::stringstream& aStream, const char* aPrefix)
if (!mTransform.IsIdentity()) {
AppendToString(aStream, mTransform, " [transform=", "]");
}
if (!GetEffectiveTransform().IsIdentity()) {
AppendToString(aStream, GetEffectiveTransform(), " [effective-transform=", "]");
}
if (mTransformIsPerspective) {
aStream << " [perspective]";
}
@@ -2005,8 +2013,8 @@ Layer::DumpPacket(layerscope::LayersPacket* aPacket, const void* aParent)
if (const Maybe<ParentLayerIntRect>& clipRect = lc->GetShadowClipRect()) {
DumpRect(s->mutable_clip(), *clipRect);
}
if (!lc->GetShadowTransform().IsIdentity()) {
DumpTransform(s->mutable_transform(), lc->GetShadowTransform());
if (!lc->GetShadowBaseTransform().IsIdentity()) {
DumpTransform(s->mutable_transform(), lc->GetShadowBaseTransform());
}
if (!lc->GetShadowVisibleRegion().IsEmpty()) {
DumpRegion(s->mutable_vregion(), lc->GetShadowVisibleRegion().ToUnknownRegion());
@@ -2414,8 +2422,8 @@ PrintInfo(std::stringstream& aStream, LayerComposite* aLayerComposite)
if (const Maybe<ParentLayerIntRect>& clipRect = aLayerComposite->GetShadowClipRect()) {
AppendToString(aStream, *clipRect, " [shadow-clip=", "]");
}
if (!aLayerComposite->GetShadowTransform().IsIdentity()) {
AppendToString(aStream, aLayerComposite->GetShadowTransform(), " [shadow-transform=", "]");
if (!aLayerComposite->GetShadowBaseTransform().IsIdentity()) {
AppendToString(aStream, aLayerComposite->GetShadowBaseTransform(), " [shadow-transform=", "]");
}
if (!aLayerComposite->GetShadowVisibleRegion().IsEmpty()) {
AppendToString(aStream, aLayerComposite->GetShadowVisibleRegion().ToUnknownRegion(), " [shadow-visible=", "]");
+4 -4
View File
@@ -1351,7 +1351,7 @@ public:
/**
* Returns the local transform for this layer: either mTransform or,
* for shadow layers, GetShadowTransform(), in either case with the
* for shadow layers, GetShadowBaseTransform(), in either case with the
* pre- and post-scales applied.
*/
const gfx::Matrix4x4 GetLocalTransform();
@@ -1485,7 +1485,7 @@ public:
// values that should be used when drawing this layer to screen,
// accounting for this layer possibly being a shadow.
const Maybe<ParentLayerIntRect>& GetEffectiveClipRect();
const LayerIntRegion& GetEffectiveVisibleRegion();
const LayerIntRegion& GetLocalVisibleRegion();
bool Extend3DContext() {
return GetContentFlags() & CONTENT_EXTEND_3D_CONTEXT;
@@ -1507,7 +1507,7 @@ public:
// For containers extending 3D context, visible region
// is meaningless, since they are just intermediate result of
// content.
return !GetEffectiveVisibleRegion().IsEmpty() || Extend3DContext();
return !GetLocalVisibleRegion().IsEmpty() || Extend3DContext();
}
/**
@@ -2100,7 +2100,7 @@ public:
RenderTargetIntRect GetIntermediateSurfaceRect()
{
NS_ASSERTION(mUseIntermediateSurface, "Must have intermediate surface");
return RenderTargetIntRect::FromUnknownRect(GetEffectiveVisibleRegion().ToUnknownRegion().GetBounds());
return RenderTargetIntRect::FromUnknownRect(GetLocalVisibleRegion().ToUnknownRegion().GetBounds());
}
/**
+95
View File
@@ -0,0 +1,95 @@
/* -*- Mode: C++; tab-width: 20; 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 "MacIOSurfaceHelpers.h"
#include "mozilla/gfx/MacIOSurface.h"
#include "YCbCrUtils.h"
namespace mozilla {
using namespace gfx;
namespace layers {
already_AddRefed<SourceSurface>
CreateSourceSurfaceFromMacIOSurface(MacIOSurface* aSurface)
{
RefPtr<DataSourceSurface> dataSurface;
aSurface->Lock();
size_t bytesPerRow = aSurface->GetBytesPerRow();
size_t ioWidth = aSurface->GetDevicePixelWidth();
size_t ioHeight = aSurface->GetDevicePixelHeight();
SurfaceFormat format = aSurface->GetFormat() == SurfaceFormat::NV12 ? SurfaceFormat::B8G8R8X8 : SurfaceFormat::B8G8R8A8;
dataSurface = Factory::CreateDataSourceSurface(IntSize(ioWidth, ioHeight), format);
if (NS_WARN_IF(!dataSurface)) {
return nullptr;
}
DataSourceSurface::MappedSurface mappedSurface;
if (!dataSurface->Map(DataSourceSurface::WRITE, &mappedSurface))
return nullptr;
if (aSurface->GetFormat() == SurfaceFormat::NV12) {
if (aSurface->GetDevicePixelWidth() > PlanarYCbCrImage::MAX_DIMENSION ||
aSurface->GetDevicePixelHeight() > PlanarYCbCrImage::MAX_DIMENSION) {
return nullptr;
}
/* Extract and separate the CbCr planes */
size_t cbCrStride = aSurface->GetBytesPerRow(1);
size_t cbCrWidth = aSurface->GetDevicePixelWidth(1);
size_t cbCrHeight = aSurface->GetDevicePixelHeight(1);
auto cbPlane = MakeUnique<uint8_t[]>(cbCrWidth * cbCrHeight);
auto crPlane = MakeUnique<uint8_t[]>(cbCrWidth * cbCrHeight);
uint8_t* src = (uint8_t*)aSurface->GetBaseAddressOfPlane(1);
uint8_t* cbDest = cbPlane.get();
uint8_t* crDest = crPlane.get();
for (size_t i = 0; i < cbCrHeight; i++) {
uint8_t* rowSrc = src + cbCrStride * i;
for (size_t j = 0; j < cbCrWidth; j++) {
*cbDest = *rowSrc;
cbDest++;
rowSrc++;
*crDest = *rowSrc;
crDest++;
rowSrc++;
}
}
/* Convert to RGB */
PlanarYCbCrData data;
data.mYChannel = (uint8_t*)aSurface->GetBaseAddressOfPlane(0);
data.mYStride = aSurface->GetBytesPerRow(0);
data.mYSize = IntSize(aSurface->GetDevicePixelWidth(0), aSurface->GetDevicePixelHeight(0));
data.mCbChannel = cbPlane.get();
data.mCrChannel = crPlane.get();
data.mCbCrStride = cbCrWidth;
data.mCbCrSize = IntSize(cbCrWidth, cbCrHeight);
data.mPicSize = data.mYSize;
ConvertYCbCrToRGB(data, SurfaceFormat::B8G8R8X8, IntSize(ioWidth, ioHeight), mappedSurface.mData, mappedSurface.mStride);
} else {
unsigned char* ioData = (unsigned char*)aSurface->GetBaseAddress();
for (size_t i = 0; i < ioHeight; ++i) {
memcpy(mappedSurface.mData + i * mappedSurface.mStride,
ioData + i * bytesPerRow,
ioWidth * 4);
}
}
dataSurface->Unmap();
aSurface->Unlock();
return dataSurface.forget();
}
} // namespace gfx
} // namespace mozilla
+28
View File
@@ -0,0 +1,28 @@
/* -*- Mode: C++; tab-width: 20; 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 GFX_MACIOSURFACEHELPERS_H
#define GFX_MACIOSURFACEHELPERS_H
class MacIOSurface;
template<class T> struct already_AddRefed;
namespace mozilla {
namespace gfx {
class SourceSurface;
}
namespace layers {
// Unlike MacIOSurface::GetAsSurface, this also handles IOSurface formats
// with multiple planes and does YCbCr to RGB conversion, if necessary.
already_AddRefed<gfx::SourceSurface>
CreateSourceSurfaceFromMacIOSurface(MacIOSurface* aSurface);
} // namespace layers
} // namespace mozilla
#endif // GFX_MACIOSURFACEHELPERS_H
+2 -74
View File
@@ -3,12 +3,12 @@
* 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 "MacIOSurfaceHelpers.h"
#include "MacIOSurfaceImage.h"
#include "mozilla/layers/CompositableClient.h"
#include "mozilla/layers/CompositableForwarder.h"
#include "mozilla/layers/MacIOSurfaceTextureClientOGL.h"
#include "mozilla/UniquePtr.h"
#include "YCbCrUtils.h"
using namespace mozilla;
using namespace mozilla::layers;
@@ -30,77 +30,5 @@ MacIOSurfaceImage::GetTextureClient(CompositableClient* aClient)
already_AddRefed<SourceSurface>
MacIOSurfaceImage::GetAsSourceSurface()
{
RefPtr<DataSourceSurface> dataSurface;
mSurface->Lock();
size_t bytesPerRow = mSurface->GetBytesPerRow();
size_t ioWidth = mSurface->GetDevicePixelWidth();
size_t ioHeight = mSurface->GetDevicePixelHeight();
SurfaceFormat format = mSurface->GetFormat() == SurfaceFormat::NV12 ? SurfaceFormat::B8G8R8X8 : SurfaceFormat::B8G8R8A8;
dataSurface = Factory::CreateDataSourceSurface(IntSize(ioWidth, ioHeight), format);
if (NS_WARN_IF(!dataSurface)) {
return nullptr;
}
DataSourceSurface::MappedSurface mappedSurface;
if (!dataSurface->Map(DataSourceSurface::WRITE, &mappedSurface))
return nullptr;
if (mSurface->GetFormat() == SurfaceFormat::NV12) {
if (mSurface->GetDevicePixelWidth() > PlanarYCbCrImage::MAX_DIMENSION ||
mSurface->GetDevicePixelHeight() > PlanarYCbCrImage::MAX_DIMENSION) {
return nullptr;
}
/* Extract and separate the CbCr planes */
size_t cbCrStride = mSurface->GetBytesPerRow(1);
size_t cbCrWidth = mSurface->GetDevicePixelWidth(1);
size_t cbCrHeight = mSurface->GetDevicePixelHeight(1);
auto cbPlane = MakeUnique<uint8_t[]>(cbCrWidth * cbCrHeight);
auto crPlane = MakeUnique<uint8_t[]>(cbCrWidth * cbCrHeight);
uint8_t* src = (uint8_t*)mSurface->GetBaseAddressOfPlane(1);
uint8_t* cbDest = cbPlane.get();
uint8_t* crDest = crPlane.get();
for (size_t i = 0; i < cbCrHeight; i++) {
uint8_t* rowSrc = src + cbCrStride * i;
for (size_t j = 0; j < cbCrWidth; j++) {
*cbDest = *rowSrc;
cbDest++;
rowSrc++;
*crDest = *rowSrc;
crDest++;
rowSrc++;
}
}
/* Convert to RGB */
PlanarYCbCrData data;
data.mYChannel = (uint8_t*)mSurface->GetBaseAddressOfPlane(0);
data.mYStride = mSurface->GetBytesPerRow(0);
data.mYSize = IntSize(mSurface->GetDevicePixelWidth(0), mSurface->GetDevicePixelHeight(0));
data.mCbChannel = cbPlane.get();
data.mCrChannel = crPlane.get();
data.mCbCrStride = cbCrWidth;
data.mCbCrSize = IntSize(cbCrWidth, cbCrHeight);
data.mPicSize = data.mYSize;
ConvertYCbCrToRGB(data, SurfaceFormat::B8G8R8X8, IntSize(ioWidth, ioHeight), mappedSurface.mData, mappedSurface.mStride);
} else {
unsigned char* ioData = (unsigned char*)mSurface->GetBaseAddress();
for (size_t i = 0; i < ioHeight; ++i) {
memcpy(mappedSurface.mData + i * mappedSurface.mStride,
ioData + i * bytesPerRow,
ioWidth * 4);
}
}
dataSurface->Unmap();
mSurface->Unlock();
return dataSurface.forget();
return CreateSourceSurfaceFromMacIOSurface(mSurface);
}
+12 -5
View File
@@ -40,13 +40,13 @@ public:
* to have remained the same since the call to
* ReturnAndUseDT.
*/
virtual gfx::DrawTarget* GetDT(const gfx::IntRect& aPersistedRect) = 0;
virtual already_AddRefed<gfx::DrawTarget> GetDT(const gfx::IntRect& aPersistedRect) = 0;
/**
* Return a DrawTarget to the PersistentBufferProvider and indicate the
* contents of this DrawTarget is to be considered current by the
* BufferProvider
* BufferProvider. The caller should forget any references to the DrawTarget.
*/
virtual bool ReturnAndUseDT(gfx::DrawTarget* aDT) = 0;
virtual bool ReturnAndUseDT(already_AddRefed<gfx::DrawTarget> aDT) = 0;
virtual already_AddRefed<gfx::SourceSurface> GetSnapshot() = 0;
protected:
@@ -63,8 +63,15 @@ public:
bool IsValid() { return !!mDrawTarget; }
virtual LayersBackend GetType() { return LayersBackend::LAYERS_BASIC; }
gfx::DrawTarget* GetDT(const gfx::IntRect& aPersistedRect) { return mDrawTarget; }
bool ReturnAndUseDT(gfx::DrawTarget* aDT) { MOZ_ASSERT(mDrawTarget == aDT); return true; }
already_AddRefed<gfx::DrawTarget> GetDT(const gfx::IntRect& aPersistedRect) {
RefPtr<gfx::DrawTarget> dt(mDrawTarget);
return dt.forget();
}
bool ReturnAndUseDT(already_AddRefed<gfx::DrawTarget> aDT) {
RefPtr<gfx::DrawTarget> dt(aDT);
MOZ_ASSERT(mDrawTarget == dt);
return true;
}
virtual already_AddRefed<gfx::SourceSurface> GetSnapshot() { return mDrawTarget->Snapshot(); }
private:
RefPtr<gfx::DrawTarget> mDrawTarget;
+1 -1
View File
@@ -63,7 +63,7 @@ FindBackgroundLayer(ReadbackLayer* aLayer, nsIntPoint* aOffset)
nsIntPoint backgroundOffset(int32_t(backgroundTransform._31), int32_t(backgroundTransform._32));
IntRect rectInBackground(transformOffset - backgroundOffset, aLayer->GetSize());
const nsIntRegion visibleRegion = l->GetEffectiveVisibleRegion().ToUnknownRegion();
const nsIntRegion visibleRegion = l->GetLocalVisibleRegion().ToUnknownRegion();
if (!visibleRegion.Intersects(rectInBackground))
continue;
// Since l is present in the background, from here on we either choose l
+1 -1
View File
@@ -30,7 +30,7 @@ void RenderTraceLayers(Layer *aLayer, const char *aColor, const gfx::Matrix4x4 a
gfx::Matrix4x4 trans = aRootTransform * aLayer->GetTransform();
trans.ProjectTo2D();
gfx::IntRect clipRect = aLayer->GetEffectiveVisibleRegion().GetBounds();
gfx::IntRect clipRect = aLayer->GetLocalVisibleRegion().GetBounds();
Rect rect(clipRect.x, clipRect.y, clipRect.width, clipRect.height);
trans.TransformBounds(rect);
+3 -3
View File
@@ -222,13 +222,13 @@ RotatedContentBuffer::DrawTo(PaintedLayer* aLayer,
if (!aLayer->GetValidRegion().Contains(BufferRect()) ||
(ToData(aLayer)->GetClipToVisibleRegion() &&
!aLayer->GetVisibleRegion().ToUnknownRegion().Contains(BufferRect())) ||
IsClippingCheap(aTarget, aLayer->GetEffectiveVisibleRegion().ToUnknownRegion())) {
IsClippingCheap(aTarget, aLayer->GetLocalVisibleRegion().ToUnknownRegion())) {
// We don't want to draw invalid stuff, so we need to clip. Might as
// well clip to the smallest area possible --- the visible region.
// Bug 599189 if there is a non-integer-translation transform in aTarget,
// we might sample pixels outside GetEffectiveVisibleRegion(), which is wrong
// we might sample pixels outside GetLocalVisibleRegion(), which is wrong
// and may cause gray lines.
gfxUtils::ClipToRegion(aTarget, aLayer->GetEffectiveVisibleRegion().ToUnknownRegion());
gfxUtils::ClipToRegion(aTarget, aLayer->GetLocalVisibleRegion().ToUnknownRegion());
clipped = true;
}
+6 -1
View File
@@ -40,7 +40,12 @@ TextureWrapperImage::GetAsSourceSurface()
return nullptr;
}
return mTextureClient->BorrowDrawTarget()->Snapshot();
RefPtr<DrawTarget> dt = mTextureClient->BorrowDrawTarget();
if (!dt) {
return nullptr;
}
return dt->Snapshot();
}
TextureClient*
+144 -80
View File
@@ -8,19 +8,129 @@
#define mozilla_layers_TreeTraversal_h
#include <queue>
#include <stack>
namespace mozilla {
namespace layers {
/*
* Returned by |aAction| in ForEachNode. If the action returns
* TraversalFlag::Skip, the node's children are not added to the traverrsal
* stack. Otherwise, a return value of TraversalFlag::Continue indicates that
* ForEachNode should traverse each of the node's children.
* Returned by |aPostAction| and |aPreAction| in ForEachNode, indicates
* the behavior to follow either action:
*
* TraversalFlag::Skip - the node's children are not traversed. If this
* flag is returned by |aPreAction|, |aPostAction| is skipped for the
* current node, as well.
* TraversalFlag::Continue - traversal continues normally.
* TraversalFlag::Abort - traversal stops immediately.
*/
enum class TraversalFlag { Skip, Continue };
enum class TraversalFlag { Skip, Continue, Abort };
/*
* Do a depth-first traversal of the tree rooted at |aRoot|, performing
* |aPreAction| before traversal of children and |aPostAction| after.
*
* Returns true if traversal aborted, false if continued normally. If
* TraversalFlag::Skip is returned in |aPreAction|, then |aPostAction|
* is not performed.
*/
template <typename Node, typename PreAction, typename PostAction>
static auto ForEachNode(Node* aRoot, const PreAction& aPreAction, const PostAction& aPostAction) ->
typename EnableIf<IsSame<decltype(aPreAction(aRoot)), TraversalFlag>::value &&
IsSame<decltype(aPostAction(aRoot)),TraversalFlag>::value, bool>::Type
{
if (!aRoot) {
return false;
}
TraversalFlag result = aPreAction(aRoot);
if (result == TraversalFlag::Abort) {
return true;
}
if (result == TraversalFlag::Continue) {
for (Node* child = aRoot->GetLastChild();
child;
child = child->GetPrevSibling()) {
bool abort = ForEachNode(child, aPreAction, aPostAction);
if (abort) {
return true;
}
}
result = aPostAction(aRoot);
if (result == TraversalFlag::Abort) {
return true;
}
}
return false;
}
/*
* Do a depth-first traversal of the tree rooted at |aRoot|, performing
* |aPreAction| before traversal of children and |aPostAction| after.
*/
template <typename Node, typename PreAction, typename PostAction>
static auto ForEachNode(Node* aRoot, const PreAction& aPreAction, const PostAction& aPostAction) ->
typename EnableIf<IsSame<decltype(aPreAction(aRoot)), void>::value &&
IsSame<decltype(aPostAction(aRoot)),void>::value, void>::Type
{
if (!aRoot) {
return;
}
aPreAction(aRoot);
for (Node* child = aRoot->GetLastChild();
child;
child = child->GetPrevSibling()) {
ForEachNode(child, aPreAction, aPostAction);
}
aPostAction(aRoot);
}
/*
* ForEachNode pre-order traversal, using TraversalFlag.
*/
template <typename Node, typename PreAction>
auto ForEachNode(Node* aRoot, const PreAction& aPreAction) ->
typename EnableIf<IsSame<decltype(aPreAction(aRoot)), TraversalFlag>::value, bool>::Type
{
return ForEachNode(aRoot, aPreAction, [](Node* aNode){ return TraversalFlag::Continue; });
}
/*
* ForEachNode pre-order, not using TraversalFlag.
*/
template <typename Node, typename PreAction>
auto ForEachNode(Node* aRoot, const PreAction& aPreAction) ->
typename EnableIf<IsSame<decltype(aPreAction(aRoot)), void>::value, void>::Type
{
ForEachNode(aRoot, aPreAction, [](Node* aNode){});
}
/*
* ForEachNode post-order traversal, using TraversalFlag.
*/
template <typename Node, typename PostAction>
auto ForEachNodePostOrder(Node* aRoot, const PostAction& aPostAction) ->
typename EnableIf<IsSame<decltype(aPostAction(aRoot)), TraversalFlag>::value, bool>::Type
{
return ForEachNode(aRoot, [](Node* aNode){ return TraversalFlag::Continue; }, aPostAction);
}
/*
* ForEachNode post-order, not using TraversalFlag.
*/
template <typename Node, typename PostAction>
auto ForEachNodePostOrder(Node* aRoot, const PostAction& aPostAction) ->
typename EnableIf<IsSame<decltype(aPostAction(aRoot)), void>::value, void>::Type
{
ForEachNode(aRoot, [](Node* aNode){}, aPostAction);
}
/*
* Do a breadth-first search of the tree rooted at |aRoot|, and return the
@@ -57,97 +167,51 @@ Node* BreadthFirstSearch(Node* aRoot, const Condition& aCondition)
}
/*
* Do a depth-first search of the tree rooted at |aRoot|, and return the
* first visited node that satisfies |aCondition|, or nullptr if no such node
* was found.
* Do a pre-order, depth-first search of the tree rooted at |aRoot|, and
* return the first visited node that satisfies |aCondition|, or nullptr
* if no such node was found.
*
* |Node| should have methods GetLastChild() and GetPrevSibling().
*/
template <typename Node, typename Condition>
Node* DepthFirstSearch(Node* aRoot, const Condition& aCondition)
{
if (!aRoot) {
return nullptr;
}
Node* result = nullptr;
std::stack<Node*> stack;
stack.push(aRoot);
while (!stack.empty()) {
Node* node = stack.top();
stack.pop();
ForEachNode(aRoot,
[&aCondition, &result](Node* aNode)
{
if (aCondition(aNode)) {
result = aNode;
return TraversalFlag::Abort;
}
if (aCondition(node)) {
return node;
}
return TraversalFlag::Continue;
});
for (Node* child = node->GetLastChild();
child;
child = child->GetPrevSibling()) {
stack.push(child);
}
}
return nullptr;
return result;
}
/*
* Do a depth-first traversal of the tree rooted at |aRoot|, performing
* |aAction| for each node. |aAction| can return a TraversalFlag to determine
* whether or not to omit the children of a particular node.
*
* If |aAction| does not return a TraversalFlag, it must return nothing. There
* is no ForEachNode instance handling types other than void or TraversalFlag.
* Perform a post-order, depth-first search starting at aRoot.
*/
template <typename Node, typename Action>
auto ForEachNode(Node* aRoot, const Action& aAction) ->
typename EnableIf<IsSame<decltype(aAction(aRoot)), TraversalFlag>::value, void>::Type
template <typename Node, typename Condition>
Node* DepthFirstSearchPostOrder(Node* aRoot, const Condition& aCondition)
{
if (!aRoot) {
return;
}
Node* result = nullptr;
std::stack<Node*> stack;
stack.push(aRoot);
ForEachNodePostOrder(aRoot,
[&aCondition, &result](Node* aNode)
{
if (aCondition(aNode)) {
result = aNode;
return TraversalFlag::Abort;
}
while (!stack.empty()) {
Node* node = stack.top();
stack.pop();
return TraversalFlag::Continue;
});
TraversalFlag result = aAction(node);
if (result == TraversalFlag::Continue) {
for (Node* child = node->GetLastChild();
child;
child = child->GetPrevSibling()) {
stack.push(child);
}
}
}
}
template <typename Node, typename Action>
auto ForEachNode(Node* aRoot, const Action& aAction) ->
typename EnableIf<IsSame<decltype(aAction(aRoot)), void>::value, void>::Type
{
if (!aRoot) {
return;
}
std::stack<Node*> stack;
stack.push(aRoot);
while (!stack.empty()) {
Node* node = stack.top();
stack.pop();
aAction(node);
for (Node* child = node->GetLastChild();
child;
child = child->GetPrevSibling()) {
stack.push(child);
}
}
return result;
}
}
+15 -1
View File
@@ -12,6 +12,7 @@
#include "mozilla/Assertions.h" // for MOZ_ASSERT_HELPER2
#include "mozilla/EventForwards.h" // for Modifiers
#include "nsISupportsImpl.h"
#include "ThreadSafeRefcountingWithMainThreadDestruction.h"
class Task;
@@ -21,7 +22,12 @@ namespace layers {
class GeckoContentController
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GeckoContentController)
/**
* At least one class deriving from GeckoContentController needs to do
* synchronous cleanup on the main thread, so we use
* NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION.
*/
NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(GeckoContentController)
/**
* Requests a paint of the given FrameMetrics |aFrameMetrics| from Gecko.
@@ -88,6 +94,7 @@ public:
* controller. This method allows APZ to query the controller for such a
* region. A return value of true indicates that the controller has such a
* region, and it is returned in |aOutRegion|.
* This method needs to be called on the main thread.
* TODO: once bug 928833 is implemented, this should be removed, as
* APZ can then get the correct touch-sensitive region for each frame
* directly from the layer.
@@ -144,7 +151,14 @@ public:
*/
virtual void NotifyFlushComplete() = 0;
virtual void UpdateOverscrollVelocity(const float aX, const float aY) {}
virtual void UpdateOverscrollOffset(const float aX,const float aY) {}
GeckoContentController() {}
virtual void ChildAdopted() {}
/**
* Needs to be called on the main thread.
*/
virtual void Destroy() {}
protected:
+64 -71
View File
@@ -3,6 +3,7 @@
* 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 <stack>
#include "APZCTreeManager.h"
#include "AsyncPanZoomController.h"
#include "Compositor.h" // for Compositor
@@ -1502,7 +1503,20 @@ APZCTreeManager::GetTargetNode(const ScrollableLayerGuid& aGuid,
GuidComparator aComparator)
{
mTreeLock.AssertCurrentThreadOwns();
RefPtr<HitTestingTreeNode> target = FindTargetNode(mRootNode, aGuid, aComparator);
RefPtr<HitTestingTreeNode> target = DepthFirstSearchPostOrder(mRootNode.get(),
[&aGuid, &aComparator](HitTestingTreeNode* node)
{
bool matches = false;
if (node->GetApzc()) {
if (aComparator) {
matches = aComparator(aGuid, node->GetApzc()->GetGuid());
} else {
matches = node->GetApzc()->Matches(aGuid);
}
}
return matches;
}
);
return target.forget();
}
@@ -1612,36 +1626,6 @@ APZCTreeManager::SetLongTapEnabled(bool aLongTapEnabled)
NewRunnableFunction(GestureEventListener::SetLongTapEnabled, aLongTapEnabled));
}
HitTestingTreeNode*
APZCTreeManager::FindTargetNode(HitTestingTreeNode* aNode,
const ScrollableLayerGuid& aGuid,
GuidComparator aComparator)
{
mTreeLock.AssertCurrentThreadOwns();
// This walks the tree in depth-first, reverse order, so that it encounters
// APZCs front-to-back on the screen.
for (HitTestingTreeNode* node = aNode; node; node = node->GetPrevSibling()) {
HitTestingTreeNode* match = FindTargetNode(node->GetLastChild(), aGuid, aComparator);
if (match) {
return match;
}
bool matches = false;
if (node->GetApzc()) {
if (aComparator) {
matches = aComparator(aGuid, node->GetApzc()->GetGuid());
} else {
matches = node->GetApzc()->Matches(aGuid);
}
}
if (matches) {
return node;
}
}
return nullptr;
}
RefPtr<HitTestingTreeNode>
APZCTreeManager::FindScrollNode(const AsyncDragMetrics& aDragMetrics)
{
@@ -1662,51 +1646,60 @@ APZCTreeManager::GetAPZCAtPoint(HitTestingTreeNode* aNode,
// This walks the tree in depth-first, reverse order, so that it encounters
// APZCs front-to-back on the screen.
for (HitTestingTreeNode* node = aNode; node; node = node->GetPrevSibling()) {
if (node->IsOutsideClip(aHitTestPoint)) {
// If the point being tested is outside the clip region for this node
// then we don't need to test against this node or any of its children.
// Just skip it and move on.
APZCTM_LOG("Point %f %f outside clip for node %p\n",
aHitTestPoint.x, aHitTestPoint.y, node);
continue;
}
HitTestingTreeNode* resultNode;
HitTestingTreeNode* root = aNode;
std::stack<ParentLayerPoint> hitTestPoints;
hitTestPoints.push(aHitTestPoint);
AsyncPanZoomController* result = nullptr;
// First check the subtree rooted at this node, because deeper nodes
// are more "in front".
Maybe<LayerPoint> hitTestPointForChildLayers = node->Untransform(aHitTestPoint);
if (hitTestPointForChildLayers) {
ParentLayerPoint childPoint = ViewAs<ParentLayerPixel>(hitTestPointForChildLayers.ref(),
PixelCastJustification::MovingDownToChildren);
result = GetAPZCAtPoint(node->GetLastChild(), childPoint, aOutHitResult);
}
// If we didn't match anything in the subtree, check |node|.
if (*aOutHitResult == HitNothing) {
APZCTM_LOG("Testing ParentLayer point %s (Layer %s) against node %p\n",
Stringify(aHitTestPoint).c_str(),
hitTestPointForChildLayers ? Stringify(hitTestPointForChildLayers.ref()).c_str() : "nil",
node);
HitTestResult hitResult = node->HitTest(aHitTestPoint);
if (hitResult != HitTestResult::HitNothing) {
result = node->GetNearestContainingApzcWithSameLayersId();
if (!result) {
result = FindRootApzcForLayersId(node->GetLayersId());
MOZ_ASSERT(result);
ForEachNode(root,
[&hitTestPoints](HitTestingTreeNode* aNode) {
if (aNode->IsOutsideClip(hitTestPoints.top())) {
// If the point being tested is outside the clip region for this node
// then we don't need to test against this node or any of its children.
// Just skip it and move on.
APZCTM_LOG("Point %f %f outside clip for node %p\n",
hitTestPoints.top().x, hitTestPoints.top().y, aNode);
return TraversalFlag::Skip;
}
APZCTM_LOG("Successfully matched APZC %p via node %p (hit result %d)\n",
result, node, hitResult);
MOZ_ASSERT(hitResult == HitLayer || hitResult == HitDispatchToContentRegion);
// If event regions are disabled, *aOutHitResult will be HitLayer
*aOutHitResult = hitResult;
// First check the subtree rooted at this node, because deeper nodes
// are more "in front".
Maybe<LayerPoint> hitTestPointForChildLayers = aNode->Untransform(hitTestPoints.top());
APZCTM_LOG("Transformed ParentLayer point %s to layer %s\n",
Stringify(hitTestPoints.top()).c_str(),
hitTestPointForChildLayers ? Stringify(hitTestPointForChildLayers.ref()).c_str() : "nil");
if (!hitTestPointForChildLayers) {
return TraversalFlag::Skip;
}
hitTestPoints.push(ViewAs<ParentLayerPixel>(hitTestPointForChildLayers.ref(),
PixelCastJustification::MovingDownToChildren));
return TraversalFlag::Continue;
},
[&resultNode, &hitTestPoints, &aOutHitResult](HitTestingTreeNode* aNode) {
hitTestPoints.pop();
HitTestResult hitResult = aNode->HitTest(hitTestPoints.top());
APZCTM_LOG("Testing ParentLayer point %s against node %p\n",
Stringify(hitTestPoints.top()).c_str(), aNode);
if (hitResult != HitTestResult::HitNothing) {
resultNode = aNode;
MOZ_ASSERT(hitResult == HitLayer || hitResult == HitDispatchToContentRegion);
// If event regions are disabled, *aOutHitResult will be HitLayer
*aOutHitResult = hitResult;
return TraversalFlag::Abort;
}
return TraversalFlag::Continue;
}
}
);
if (*aOutHitResult != HitNothing) {
if (*aOutHitResult != HitNothing) {
MOZ_ASSERT(resultNode);
AsyncPanZoomController* result = resultNode->GetNearestContainingApzcWithSameLayersId();
if (!result) {
result = FindRootApzcForLayersId(resultNode->GetLayersId());
MOZ_ASSERT(result);
}
APZCTM_LOG("Successfully matched APZC %p via node %p (hit result %d)\n",
result, aNode, *aOutHitResult);
return result;
}
}
return nullptr;
+5 -10
View File
@@ -23,8 +23,7 @@ class AsyncPanZoomAnimation {
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AsyncPanZoomAnimation)
public:
explicit AsyncPanZoomAnimation(const TimeDuration& aRepaintInterval)
: mRepaintInterval(aRepaintInterval)
explicit AsyncPanZoomAnimation()
{ }
virtual bool DoSample(FrameMetrics& aFrameMetrics,
@@ -50,18 +49,14 @@ public:
return Move(mDeferredTasks);
}
/**
* Specifies how frequently (at most) we want to do repaints during the
* animation sequence. TimeDuration::Forever() will cause it to only repaint
* at the end of the animation.
*/
TimeDuration mRepaintInterval;
public:
virtual WheelScrollAnimation* AsWheelScrollAnimation() {
return nullptr;
}
virtual bool WantsRepaints() {
return true;
}
protected:
// Protected destructor, to discourage deletion outside of Release():
virtual ~AsyncPanZoomAnimation()
+204 -116
View File
@@ -37,6 +37,8 @@
#include "mozilla/StaticPtr.h" // for StaticAutoPtr
#include "mozilla/Telemetry.h" // for Telemetry
#include "mozilla/TimeStamp.h" // for TimeDuration, TimeStamp
#include "mozilla/dom/CheckerboardReportService.h" // for CheckerboardEventStorage
// note: CheckerboardReportService.h actually lives in gfx/layers/apz/util/
#include "mozilla/dom/KeyframeEffect.h" // for ComputedTimingFunction
#include "mozilla/dom/Touch.h" // for Touch
#include "mozilla/gfx/BasePoint.h" // for BasePoint
@@ -52,6 +54,7 @@
#include "mozilla/layers/CompositorParent.h" // for CompositorParent
#include "mozilla/layers/LayerTransactionParent.h" // for LayerTransactionParent
#include "mozilla/layers/PCompositorParent.h" // for PCompositorParent
#include "mozilla/layers/ScrollInputMethods.h" // for ScrollInputMethod
#include "mozilla/mozalloc.h" // for operator new, etc
#include "mozilla/unused.h" // for unused
#include "mozilla/FloatingPoint.h" // for FuzzyEquals*
@@ -153,6 +156,14 @@ using mozilla::gfx::PointTyped;
* pixels would make us drop to low-res at y=490...990.\n
* This value is in layer pixels.
*
* \li\b apz.displayport_expiry_ms
* While a scrollable frame is scrolling async, we set a displayport on it
* to make sure it is layerized. However this takes up memory, so once the
* scrolling stops we want to remove the displayport. This pref controls how
* long after scrolling stops the displayport is removed. A value of 0 will
* disable the expiry behavior entirely.
* Units: milliseconds
*
* \li\b apz.enlarge_displayport_when_clipped
* Pref that enables enlarging of the displayport along one axis when the
* generated displayport's size is beyond that of the scrollable rect on the
@@ -204,11 +215,6 @@ using mozilla::gfx::PointTyped;
* value of this pref, and (t1 - t0) is the amount of time, in milliseconds,
* that has elapsed between the two samples.
*
* \li\b apz.fling_repaint_interval
* Maximum amount of time flinging before sending a viewport change. This will
* asynchronously repaint the page.\n
* Units: milliseconds
*
* \li\b apz.fling_stop_on_tap_threshold
* When flinging, if the velocity is above this number, then a tap on the
* screen will stop the fling without dispatching a tap to content. If the
@@ -272,18 +278,9 @@ using mozilla::gfx::PointTyped;
* Units: screen pixels (for distance)
* screen pixels per millisecond (for velocity)
*
* \li\b apz.pan_repaint_interval
* Maximum amount of time while panning before sending a viewport change. This
* will asynchronously repaint the page. It is also forced when panning stops.
*
* \li\b apz.record_checkerboarding
* Whether or not to record detailed info on checkerboarding events.
*
* \li\b apz.smooth_scroll_repaint_interval
* Maximum amount of time doing a smooth scroll before sending a viewport
* change. This will asynchronously repaint the page.\n
* Units: milliseconds
*
* \li\b apz.test.logging_enabled
* Enable logging of APZ test data (see bug 961289).
*
@@ -433,8 +430,7 @@ public:
const RefPtr<const OverscrollHandoffChain>& aOverscrollHandoffChain,
bool aApplyAcceleration,
const RefPtr<const AsyncPanZoomController>& aScrolledApzc)
: AsyncPanZoomAnimation(TimeDuration::FromMilliseconds(gfxPrefs::APZFlingRepaintInterval()))
, mApzc(aApzc)
: mApzc(aApzc)
, mOverscrollHandoffChain(aOverscrollHandoffChain)
, mScrolledApzc(aScrolledApzc)
{
@@ -601,8 +597,7 @@ class ZoomAnimation: public AsyncPanZoomAnimation {
public:
ZoomAnimation(CSSPoint aStartOffset, CSSToParentLayerScale2D aStartZoom,
CSSPoint aEndOffset, CSSToParentLayerScale2D aEndZoom)
: AsyncPanZoomAnimation(TimeDuration::Forever())
, mTotalDuration(TimeDuration::FromMilliseconds(gfxPrefs::APZZoomAnimationDuration()))
: mTotalDuration(TimeDuration::FromMilliseconds(gfxPrefs::APZZoomAnimationDuration()))
, mStartOffset(aStartOffset)
, mStartZoom(aStartZoom)
, mEndOffset(aEndOffset)
@@ -639,6 +634,11 @@ public:
return true;
}
virtual bool WantsRepaints() override
{
return false;
}
private:
TimeDuration mDuration;
const TimeDuration mTotalDuration;
@@ -660,8 +660,7 @@ private:
class OverscrollAnimation: public AsyncPanZoomAnimation {
public:
explicit OverscrollAnimation(AsyncPanZoomController& aApzc, const ParentLayerPoint& aVelocity)
: AsyncPanZoomAnimation(TimeDuration::Forever())
, mApzc(aApzc)
: mApzc(aApzc)
{
mApzc.mX.StartOverscrollAnimation(aVelocity.x);
mApzc.mY.StartOverscrollAnimation(aVelocity.y);
@@ -691,6 +690,12 @@ public:
}
return true;
}
virtual bool WantsRepaints() override
{
return false;
}
private:
AsyncPanZoomController& mApzc;
};
@@ -703,9 +708,7 @@ public:
const nsPoint &aInitialVelocity,
const nsPoint& aDestination, double aSpringConstant,
double aDampingRatio)
: AsyncPanZoomAnimation(TimeDuration::FromMilliseconds(
gfxPrefs::APZSmoothScrollRepaintInterval()))
, mApzc(aApzc)
: mApzc(aApzc)
, mXAxisModel(aInitialPosition.x, aDestination.x, aInitialVelocity.x,
aSpringConstant, aDampingRatio)
, mYAxisModel(aInitialPosition.y, aDestination.y, aInitialVelocity.y,
@@ -863,7 +866,8 @@ AsyncPanZoomController::AsyncPanZoomController(uint64_t aLayersId,
mInputQueue(aInputQueue),
mAPZCId(sAsyncPanZoomControllerCount++),
mSharedLock(nullptr),
mAsyncTransformAppliedToContent(false)
mAsyncTransformAppliedToContent(false),
mCheckerboardEventLock("APZCBELock")
{
if (aGestures == USE_GESTURE_DETECTOR) {
mGestureEventListener = new GestureEventListener(this);
@@ -1032,6 +1036,9 @@ nsEventStatus AsyncPanZoomController::HandleDragEvent(const MouseInput& aEvent,
return nsEventStatus_eConsumeNoDefault;
}
mozilla::Telemetry::Accumulate(mozilla::Telemetry::SCROLL_INPUT_METHODS,
(uint32_t) ScrollInputMethod::ApzScrollbarDrag);
ReentrantMonitorAutoEnter lock(mMonitor);
CSSPoint scrollFramePoint = aEvent.mLocalOrigin / GetFrameMetrics().GetZoom();
// The scrollbar can be transformed with the frame but the pres shell
@@ -1337,7 +1344,13 @@ nsEventStatus AsyncPanZoomController::OnTouchEnd(const MultiTouchInput& aEvent)
if (CurrentTouchBlock()->GetActiveTouchCount() == 0) {
// It's possible we may be overscrolled if the user tapped during a
// previous overscroll pan. Make sure to snap back in this situation.
if (!SnapBackIfOverscrolled()) {
// An ancestor APZC could be overscrolled instead of this APZC, so
// walk the handoff chain as well.
CurrentTouchBlock()->GetOverscrollHandoffChain()->SnapBackOverscrolledApzc(this);
// SnapBackOverscrolledApzc() will put any APZC it causes to snap back
// into the OVERSCROLL_ANIMATION state. If that's not us, since we're
// done TOUCHING enter the NOTHING state.
if (mState != OVERSCROLL_ANIMATION) {
SetState(NOTHING);
}
}
@@ -1723,6 +1736,25 @@ AsyncPanZoomController::AllowScrollHandoffInCurrentBlock() const
return result;
}
static ScrollInputMethod
ScrollInputMethodForWheelDeltaType(ScrollWheelInput::ScrollDeltaType aDeltaType)
{
switch (aDeltaType) {
case ScrollWheelInput::SCROLLDELTA_LINE: {
return ScrollInputMethod::ApzWheelLine;
}
case ScrollWheelInput::SCROLLDELTA_PAGE: {
return ScrollInputMethod::ApzWheelPage;
}
case ScrollWheelInput::SCROLLDELTA_PIXEL: {
return ScrollInputMethod::ApzWheelPixel;
}
default:
MOZ_ASSERT_UNREACHABLE("unexpected scroll delta type");
return ScrollInputMethod::ApzWheelLine;
}
}
nsEventStatus AsyncPanZoomController::OnScrollWheel(const ScrollWheelInput& aEvent)
{
ParentLayerPoint delta = GetScrollWheelDelta(aEvent);
@@ -1746,6 +1778,9 @@ nsEventStatus AsyncPanZoomController::OnScrollWheel(const ScrollWheelInput& aEve
return nsEventStatus_eIgnore;
}
mozilla::Telemetry::Accumulate(mozilla::Telemetry::SCROLL_INPUT_METHODS,
(uint32_t) ScrollInputMethodForWheelDeltaType(aEvent.mDeltaType));
switch (aEvent.mScrollMode) {
case ScrollWheelInput::SCROLLMODE_INSTANT: {
ScreenPoint distance = ToScreenCoordinates(
@@ -1904,6 +1939,9 @@ nsEventStatus AsyncPanZoomController::OnPan(const PanGestureInput& aEvent, bool
HandlePanningUpdate(aEvent.mPanDisplacement);
mozilla::Telemetry::Accumulate(mozilla::Telemetry::SCROLL_INPUT_METHODS,
(uint32_t) ScrollInputMethod::ApzPanGesture);
ScreenPoint panDistance(fabs(aEvent.mPanDisplacement.x), fabs(aEvent.mPanDisplacement.y));
OverscrollHandoffState handoffState(
*CurrentPanGestureBlock()->GetOverscrollHandoffChain(),
@@ -2540,6 +2578,8 @@ void AsyncPanZoomController::TrackTouch(const MultiTouchInput& aEvent) {
UpdateWithTouchAtDevicePoint(aEvent);
if (prevTouchPoint != touchPoint) {
mozilla::Telemetry::Accumulate(mozilla::Telemetry::SCROLL_INPUT_METHODS,
(uint32_t) ScrollInputMethod::ApzTouch);
OverscrollHandoffState handoffState(
*CurrentTouchBlock()->GetOverscrollHandoffChain(),
panDistance,
@@ -2749,7 +2789,7 @@ void AsyncPanZoomController::FlushRepaintForNewInputBlock() {
APZC_LOG("%p flushing repaint for new input block\n", this);
ReentrantMonitorAutoEnter lock(mMonitor);
RequestContentRepaint(mFrameMetrics);
RequestContentRepaint();
UpdateSharedCompositorFrameMetrics();
}
@@ -2792,14 +2832,44 @@ int32_t AsyncPanZoomController::GetLastTouchIdentifier() const {
}
void AsyncPanZoomController::RequestContentRepaint() {
RequestContentRepaint(mFrameMetrics);
// Reinvoke this method on the main thread if it's not there already. It's
// important to do this before the call to CalculatePendingDisplayPort, so
// that CalculatePendingDisplayPort uses the most recent available version of
// mFrameMetrics, just before the paint request is dispatched to content.
if (!NS_IsMainThread()) {
// use the local variable to resolve the function overload.
auto func = static_cast<void (AsyncPanZoomController::*)()>
(&AsyncPanZoomController::RequestContentRepaint);
NS_DispatchToMainThread(NS_NewRunnableMethod(this, func));
return;
}
MOZ_ASSERT(NS_IsMainThread());
ReentrantMonitorAutoEnter lock(mMonitor);
ParentLayerPoint velocity = GetVelocityVector();
mFrameMetrics.SetDisplayPortMargins(CalculatePendingDisplayPort(mFrameMetrics, velocity));
mFrameMetrics.SetUseDisplayPortMargins(true);
mFrameMetrics.SetPaintRequestTime(TimeStamp::Now());
RequestContentRepaint(mFrameMetrics, velocity);
}
void AsyncPanZoomController::RequestContentRepaint(FrameMetrics& aFrameMetrics)
/*static*/ CSSRect
GetDisplayPortRect(const FrameMetrics& aFrameMetrics)
{
ParentLayerPoint velocity = GetVelocityVector();
aFrameMetrics.SetDisplayPortMargins(CalculatePendingDisplayPort(aFrameMetrics, velocity));
aFrameMetrics.SetUseDisplayPortMargins(true);
// This computation is based on what happens in CalculatePendingDisplayPort. If that
// changes then this might need to change too
CSSRect baseRect(aFrameMetrics.GetScrollOffset(),
aFrameMetrics.CalculateBoundedCompositedSizeInCssPixels());
baseRect.Inflate(aFrameMetrics.GetDisplayPortMargins() / aFrameMetrics.DisplayportPixelsPerCSSPixel());
return baseRect;
}
void
AsyncPanZoomController::RequestContentRepaint(const FrameMetrics& aFrameMetrics,
const ParentLayerPoint& aVelocity)
{
MOZ_ASSERT(NS_IsMainThread());
// If we're trying to paint what we already think is painted, discard this
// request since it's a pointless paint.
@@ -2822,47 +2892,25 @@ void AsyncPanZoomController::RequestContentRepaint(FrameMetrics& aFrameMetrics)
return;
}
aFrameMetrics.SetPaintRequestTime(TimeStamp::Now());
DispatchRepaintRequest(aFrameMetrics, velocity);
aFrameMetrics.SetPresShellId(mLastContentPaintMetrics.GetPresShellId());
}
/*static*/ CSSRect
GetDisplayPortRect(const FrameMetrics& aFrameMetrics)
{
// This computation is based on what happens in CalculatePendingDisplayPort. If that
// changes then this might need to change too
CSSRect baseRect(aFrameMetrics.GetScrollOffset(),
aFrameMetrics.CalculateBoundedCompositedSizeInCssPixels());
baseRect.Inflate(aFrameMetrics.GetDisplayPortMargins() / aFrameMetrics.DisplayportPixelsPerCSSPixel());
return baseRect;
}
void
AsyncPanZoomController::DispatchRepaintRequest(const FrameMetrics& aFrameMetrics,
const ParentLayerPoint& aVelocity)
{
RefPtr<GeckoContentController> controller = GetGeckoContentController();
if (!controller) {
return;
}
APZC_LOG_FM(aFrameMetrics, "%p requesting content repaint", this);
if (mCheckerboardEvent) {
std::stringstream info;
info << " velocity " << aVelocity;
std::string str = info.str();
mCheckerboardEvent->UpdateRendertraceProperty(
CheckerboardEvent::RequestedDisplayPort, GetDisplayPortRect(aFrameMetrics),
str);
{ // scope lock
MutexAutoLock lock(mCheckerboardEventLock);
if (mCheckerboardEvent && mCheckerboardEvent->IsRecordingTrace()) {
std::stringstream info;
info << " velocity " << aVelocity;
std::string str = info.str();
mCheckerboardEvent->UpdateRendertraceProperty(
CheckerboardEvent::RequestedDisplayPort, GetDisplayPortRect(aFrameMetrics),
str);
}
}
if (NS_IsMainThread()) {
controller->RequestContentRepaint(aFrameMetrics);
} else {
NS_DispatchToMainThread(NS_NewRunnableMethodWithArg<FrameMetrics>(
controller, &GeckoContentController::RequestContentRepaint, aFrameMetrics));
}
controller->RequestContentRepaint(aFrameMetrics);
mExpectedGeckoMetrics = aFrameMetrics;
mLastPaintRequestMetrics = aFrameMetrics;
}
@@ -2884,12 +2932,15 @@ bool AsyncPanZoomController::UpdateAnimation(const TimeStamp& aSampleTime,
if (mAnimation) {
bool continueAnimation = mAnimation->Sample(mFrameMetrics, sampleTimeDelta);
bool wantsRepaints = mAnimation->WantsRepaints();
*aOutDeferredTasks = mAnimation->TakeDeferredTasks();
if (!continueAnimation) {
mAnimation = nullptr;
SetState(NOTHING);
}
RequestContentRepaint();
if (wantsRepaints) {
RequestContentRepaint();
}
UpdateSharedCompositorFrameMetrics();
return true;
}
@@ -2963,11 +3014,14 @@ bool AsyncPanZoomController::AdvanceAnimations(const TimeStamp& aSampleTime)
requestAnimationFrame = UpdateAnimation(aSampleTime, &deferredTasks);
if (mCheckerboardEvent) {
mCheckerboardEvent->UpdateRendertraceProperty(
CheckerboardEvent::UserVisible,
CSSRect(mFrameMetrics.GetScrollOffset(),
mFrameMetrics.CalculateCompositedSizeInCssPixels()));
{ // scope lock
MutexAutoLock lock(mCheckerboardEventLock);
if (mCheckerboardEvent) {
mCheckerboardEvent->UpdateRendertraceProperty(
CheckerboardEvent::UserVisible,
CSSRect(mFrameMetrics.GetScrollOffset(),
mFrameMetrics.CalculateCompositedSizeInCssPixels()));
}
}
}
@@ -3084,24 +3138,42 @@ AsyncPanZoomController::ReportCheckerboard(const TimeStamp& aSampleTime)
// checkerboard once per composite though.
return;
}
uint32_t time = (aSampleTime - mLastCheckerboardReport).ToMilliseconds();
uint32_t magnitude = GetCheckerboardMagnitude();
// TODO: make this a function of velocity
mozilla::Telemetry::Accumulate(
mozilla::Telemetry::CHECKERBOARDED_CSSPIXELS_MS, magnitude * time);
mLastCheckerboardReport = aSampleTime;
if (!mCheckerboardEvent && gfxPrefs::APZRecordCheckerboarding()) {
mCheckerboardEvent = MakeUnique<CheckerboardEvent>();
bool recordTrace = gfxPrefs::APZRecordCheckerboarding();
bool forTelemetry = Telemetry::CanRecordExtended();
uint32_t magnitude = GetCheckerboardMagnitude();
MutexAutoLock lock(mCheckerboardEventLock);
if (!mCheckerboardEvent && (recordTrace || forTelemetry)) {
mCheckerboardEvent = MakeUnique<CheckerboardEvent>(recordTrace);
}
if (mCheckerboardEvent) {
if (mCheckerboardEvent->RecordFrameInfo(magnitude)) {
// This checkerboard event is done. TODO: save the info somewhere or
// dispatch it to telemetry or something. For now we just print it.
std::stringstream log(mCheckerboardEvent->GetLog());
print_stderr(log);
mCheckerboardEvent = nullptr;
if (magnitude) {
mPotentialCheckerboardTracker.CheckerboardSeen();
}
if (mCheckerboardEvent && mCheckerboardEvent->RecordFrameInfo(magnitude)) {
// This checkerboard event is done. Report some metrics to telemetry.
mozilla::Telemetry::Accumulate(mozilla::Telemetry::CHECKERBOARD_SEVERITY,
mCheckerboardEvent->GetSeverity());
mozilla::Telemetry::Accumulate(mozilla::Telemetry::CHECKERBOARD_PEAK,
mCheckerboardEvent->GetPeak());
mozilla::Telemetry::Accumulate(mozilla::Telemetry::CHECKERBOARD_DURATION,
(uint32_t)mCheckerboardEvent->GetDuration().ToMilliseconds());
mPotentialCheckerboardTracker.CheckerboardDone();
if (recordTrace) {
// if the pref is enabled, also send it to the storage class. it may be
// chosen for public display on about:checkerboard, the hall of fame for
// checkerboard events.
uint32_t severity = mCheckerboardEvent->GetSeverity();
std::string log = mCheckerboardEvent->GetLog();
NS_DispatchToMainThread(NS_NewRunnableFunction([severity, log]() {
RefPtr<CheckerboardEventStorage> storage = CheckerboardEventStorage::GetInstance();
storage->ReportCheckerboard(severity, log);
}));
}
mCheckerboardEvent = nullptr;
}
}
@@ -3139,36 +3211,39 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aLayerMetri
APZC_LOG_FM(aLayerMetrics, "%p got a NotifyLayersUpdated with aIsFirstPaint=%d, aThisLayerTreeUpdated=%d",
this, aIsFirstPaint, aThisLayerTreeUpdated);
if (mCheckerboardEvent) {
std::string str;
if (aThisLayerTreeUpdated) {
if (!aLayerMetrics.GetPaintRequestTime().IsNull()) {
// Note that we might get the paint request time as non-null, but with
// aThisLayerTreeUpdated false. That can happen if we get a layer transaction
// from a different process right after we get the layer transaction with
// aThisLayerTreeUpdated == true. In this case we want to ignore the
// paint request time because it was already dumped in the previous layer
// transaction.
TimeDuration paintTime = TimeStamp::Now() - aLayerMetrics.GetPaintRequestTime();
std::stringstream info;
info << " painttime " << paintTime.ToMilliseconds();
str = info.str();
} else {
// This might be indicative of a wasted paint particularly if it happens
// during a checkerboard event.
str = " (this layertree updated)";
{ // scope lock
MutexAutoLock lock(mCheckerboardEventLock);
if (mCheckerboardEvent && mCheckerboardEvent->IsRecordingTrace()) {
std::string str;
if (aThisLayerTreeUpdated) {
if (!aLayerMetrics.GetPaintRequestTime().IsNull()) {
// Note that we might get the paint request time as non-null, but with
// aThisLayerTreeUpdated false. That can happen if we get a layer transaction
// from a different process right after we get the layer transaction with
// aThisLayerTreeUpdated == true. In this case we want to ignore the
// paint request time because it was already dumped in the previous layer
// transaction.
TimeDuration paintTime = TimeStamp::Now() - aLayerMetrics.GetPaintRequestTime();
std::stringstream info;
info << " painttime " << paintTime.ToMilliseconds();
str = info.str();
} else {
// This might be indicative of a wasted paint particularly if it happens
// during a checkerboard event.
str = " (this layertree updated)";
}
}
}
mCheckerboardEvent->UpdateRendertraceProperty(
CheckerboardEvent::Page, aLayerMetrics.GetScrollableRect());
mCheckerboardEvent->UpdateRendertraceProperty(
CheckerboardEvent::PaintedDisplayPort,
aLayerMetrics.GetDisplayPort() + aLayerMetrics.GetScrollOffset(),
str);
if (!aLayerMetrics.GetCriticalDisplayPort().IsEmpty()) {
mCheckerboardEvent->UpdateRendertraceProperty(
CheckerboardEvent::PaintedCriticalDisplayPort,
aLayerMetrics.GetCriticalDisplayPort() + aLayerMetrics.GetScrollOffset());
CheckerboardEvent::Page, aLayerMetrics.GetScrollableRect());
mCheckerboardEvent->UpdateRendertraceProperty(
CheckerboardEvent::PaintedDisplayPort,
aLayerMetrics.GetDisplayPort() + aLayerMetrics.GetScrollOffset(),
str);
if (!aLayerMetrics.GetCriticalDisplayPort().IsEmpty()) {
mCheckerboardEvent->UpdateRendertraceProperty(
CheckerboardEvent::PaintedCriticalDisplayPort,
aLayerMetrics.GetCriticalDisplayPort() + aLayerMetrics.GetScrollOffset());
}
}
}
@@ -3456,9 +3531,6 @@ void AsyncPanZoomController::ZoomToRect(CSSRect aRect, const uint32_t aFlags) {
}
endZoomToMetrics.SetScrollOffset(aRect.TopLeft());
endZoomToMetrics.SetDisplayPortMargins(
CalculatePendingDisplayPort(endZoomToMetrics, ParentLayerPoint(0,0)));
endZoomToMetrics.SetUseDisplayPortMargins(true);
StartAnimation(new ZoomAnimation(
mFrameMetrics.GetScrollOffset(),
@@ -3468,7 +3540,21 @@ void AsyncPanZoomController::ZoomToRect(CSSRect aRect, const uint32_t aFlags) {
// Schedule a repaint now, so the new displayport will be painted before the
// animation finishes.
RequestContentRepaint(endZoomToMetrics);
ParentLayerPoint velocity(0, 0);
endZoomToMetrics.SetDisplayPortMargins(
CalculatePendingDisplayPort(endZoomToMetrics, velocity));
endZoomToMetrics.SetUseDisplayPortMargins(true);
endZoomToMetrics.SetPaintRequestTime(TimeStamp::Now());
if (NS_IsMainThread()) {
RequestContentRepaint(endZoomToMetrics, velocity);
} else {
// use a local var to resolve the function overload
auto func = static_cast<void (AsyncPanZoomController::*)(const FrameMetrics&, const ParentLayerPoint&)>
(&AsyncPanZoomController::RequestContentRepaint);
NS_DispatchToMainThread(
NS_NewRunnableMethodWithArgs<FrameMetrics, ParentLayerPoint>(
this, func, endZoomToMetrics, velocity));
}
}
}
@@ -3542,6 +3628,7 @@ void AsyncPanZoomController::DispatchStateChangeNotification(PanZoomState aOldSt
if (RefPtr<GeckoContentController> controller = GetGeckoContentController()) {
if (!IsTransformingState(aOldState) && IsTransformingState(aNewState)) {
mPotentialCheckerboardTracker.TransformStarted();
controller->NotifyAPZStateChange(
GetGuid(), APZStateChange::TransformBegin);
#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
@@ -3552,6 +3639,7 @@ void AsyncPanZoomController::DispatchStateChangeNotification(PanZoomState aOldSt
}
#endif
} else if (IsTransformingState(aOldState) && !IsTransformingState(aNewState)) {
mPotentialCheckerboardTracker.TransformStopped();
controller->NotifyAPZStateChange(
GetGuid(), APZStateChange::TransformEnd);
#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
+15 -16
View File
@@ -26,6 +26,7 @@
#include "LayersTypes.h"
#include "mozilla/gfx/Matrix.h"
#include "nsRegion.h"
#include "PotentialCheckerboardDurationTracker.h"
#include "base/message_loop.h"
@@ -577,27 +578,19 @@ protected:
/**
* Utility function to send updated FrameMetrics to Gecko so that it can paint
* the displayport area. Calls into GeckoContentController to do the actual
* work. Note that only one paint request can be active at a time. If a paint
* request is made while a paint is currently happening, it gets queued up. If
* a new paint request arrives before a paint is completed, the old request
* gets discarded.
* work. This call will use the current metrics. If this function is called
* from a non-main thread, it will redispatch itself to the main thread, and
* use the latest metrics during the redispatch.
*/
void RequestContentRepaint();
/**
* Tell the paint throttler to request a content repaint with the given
* metrics. (Helper function used by RequestContentRepaint.) If aThrottled
* is set to false, the repaint request is sent directly without going through
* the paint throttler. In particular, the GeckoContentController::RequestContentRepaint
* function will be invoked before this function returns.
* Send the provided metrics to Gecko to trigger a repaint. This function
* may filter duplicate calls with the same metrics. This function must be
* called on the main thread.
*/
void RequestContentRepaint(FrameMetrics& aFrameMetrics);
/**
* Actually send the next pending paint request to gecko.
*/
void DispatchRepaintRequest(const FrameMetrics& aFrameMetrics,
const ParentLayerPoint& aVelocity);
void RequestContentRepaint(const FrameMetrics& aFrameMetrics,
const ParentLayerPoint& aVelocity);
/**
* Gets the current frame metrics. This is *not* the Gecko copy stored in the
@@ -1106,10 +1099,16 @@ private:
* recording.
*/
private:
// Mutex protecting mCheckerboardEvent
Mutex mCheckerboardEventLock;
// This is created when this APZC instance is first included as part of a
// composite. If a checkerboard event takes place, this is destroyed at the
// end of the event, and a new one is created on the next composite.
UniquePtr<CheckerboardEvent> mCheckerboardEvent;
// This is used to track the total amount of time that we could reasonably
// be checkerboarding. Combined with other info, this allows us to meaningfully
// say how frequently users actually encounter checkerboarding.
PotentialCheckerboardDurationTracker mPotentialCheckerboardTracker;
};
} // namespace layers
+34 -4
View File
@@ -32,8 +32,9 @@ const char* CheckerboardEvent::sColors[] = {
"red",
};
CheckerboardEvent::CheckerboardEvent()
: mOriginTime(TimeStamp::Now())
CheckerboardEvent::CheckerboardEvent(bool aRecordTrace)
: mRecordTrace(aRecordTrace)
, mOriginTime(TimeStamp::Now())
, mCheckerboardingActive(false)
, mLastSampleTime(mOriginTime)
, mFrameCount(0)
@@ -43,10 +44,23 @@ CheckerboardEvent::CheckerboardEvent()
{
}
uint64_t
uint32_t
CheckerboardEvent::GetSeverity()
{
return mTotalPixelMs;
// Scale the total into a 32-bit value
return (uint32_t)sqrt((double)mTotalPixelMs);
}
uint32_t
CheckerboardEvent::GetPeak()
{
return mPeakPixels;
}
TimeDuration
CheckerboardEvent::GetDuration()
{
return mEndTime - mStartTime;
}
std::string
@@ -56,11 +70,20 @@ CheckerboardEvent::GetLog()
return mRendertraceInfo.str();
}
bool
CheckerboardEvent::IsRecordingTrace()
{
return mRecordTrace;
}
void
CheckerboardEvent::UpdateRendertraceProperty(RendertraceProperty aProperty,
const CSSRect& aRect,
const std::string& aExtraInfo)
{
if (!mRecordTrace) {
return;
}
MonitorAutoLock lock(mRendertraceLock);
if (!mCheckerboardingActive) {
mBufferedProperties[aProperty].Update(aProperty, aRect, aExtraInfo, lock);
@@ -76,6 +99,7 @@ CheckerboardEvent::LogInfo(RendertraceProperty aProperty,
const std::string& aExtraInfo,
const MonitorAutoLock& aProofOfLock)
{
MOZ_ASSERT(mRecordTrace);
if (mRendertraceInfo.tellp() >= LOG_LENGTH_LIMIT) {
// The log is already long enough, don't put more things into it. We'll
// append a truncation message when this event ends.
@@ -130,6 +154,9 @@ CheckerboardEvent::StartEvent()
mCheckerboardingActive = true;
mStartTime = TimeStamp::Now();
if (!mRecordTrace) {
return;
}
MonitorAutoLock lock(mRendertraceLock);
std::vector<PropertyValue> history;
for (int i = 0; i < MAX_RendertraceProperty; i++) {
@@ -148,6 +175,9 @@ CheckerboardEvent::StopEvent()
mCheckerboardingActive = false;
mEndTime = TimeStamp::Now();
if (!mRecordTrace) {
return;
}
MonitorAutoLock lock(mRendertraceLock);
if (mRendertraceInfo.tellp() >= LOG_LENGTH_LIMIT) {
mRendertraceInfo << "[logging aborted due to length limitations]\n";
+25 -2
View File
@@ -39,14 +39,25 @@ public:
static const char* sColors[MAX_RendertraceProperty];
public:
CheckerboardEvent();
explicit CheckerboardEvent(bool aRecordTrace);
/**
* Gets the "severity" of the checkerboard event. This doesn't have units,
* it's just useful for comparing two checkerboard events to see which one
* is worse, for some implementation-specific definition of "worse".
*/
uint64_t GetSeverity();
uint32_t GetSeverity();
/**
* Gets the number of CSS pixels that were checkerboarded at the peak of the
* checkerboard event.
*/
uint32_t GetPeak();
/**
* Gets the length of the checkerboard event.
*/
TimeDuration GetDuration();
/**
* Gets the raw log of the checkerboard event. This can be called any time,
@@ -55,6 +66,12 @@ public:
*/
std::string GetLog();
/**
* Returns true iff this event is recording a detailed trace of the event.
* This is the argument passed in to the constructor.
*/
bool IsRecordingTrace();
/**
* Provide a new value for one of the rects that is tracked for
* checkerboard events.
@@ -137,6 +154,12 @@ private:
};
private:
/**
* If true, we should log the various properties during the checkerboard
* event. If false, we only need to record things we need for telemetry
* measures.
*/
const bool mRecordTrace;
/**
* A base time so that the other timestamps can be turned into durations.
*/
@@ -0,0 +1,71 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et tw=80 : */
/* 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 "PotentialCheckerboardDurationTracker.h"
#include "mozilla/Telemetry.h" // for Telemetry
namespace mozilla {
namespace layers {
PotentialCheckerboardDurationTracker::PotentialCheckerboardDurationTracker()
: mInCheckerboard(false)
, mInTransform(false)
{
}
void
PotentialCheckerboardDurationTracker::CheckerboardSeen()
{
// This might get called while mInCheckerboard is already true
if (!Tracking()) {
mCurrentPeriodStart = TimeStamp::Now();
}
mInCheckerboard = true;
}
void
PotentialCheckerboardDurationTracker::CheckerboardDone()
{
MOZ_ASSERT(Tracking());
mInCheckerboard = false;
if (!Tracking()) {
mozilla::Telemetry::AccumulateTimeDelta(
mozilla::Telemetry::CHECKERBOARD_POTENTIAL_DURATION,
mCurrentPeriodStart);
}
}
void
PotentialCheckerboardDurationTracker::TransformStarted()
{
MOZ_ASSERT(!mInTransform);
if (!Tracking()) {
mCurrentPeriodStart = TimeStamp::Now();
}
mInTransform = true;
}
void
PotentialCheckerboardDurationTracker::TransformStopped()
{
MOZ_ASSERT(mInTransform);
mInTransform = false;
if (!Tracking()) {
mozilla::Telemetry::AccumulateTimeDelta(
mozilla::Telemetry::CHECKERBOARD_POTENTIAL_DURATION,
mCurrentPeriodStart);
}
}
bool
PotentialCheckerboardDurationTracker::Tracking() const
{
return mInTransform || mInCheckerboard;
}
} // namespace layers
} // namespace mozilla
@@ -0,0 +1,65 @@
/* -*- Mode: C++; tab-width: 8; 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_PotentialCheckerboardDurationTracker_h
#define mozilla_layers_PotentialCheckerboardDurationTracker_h
#include "mozilla/TimeStamp.h"
namespace mozilla {
namespace layers {
/**
* This class allows the owner to track the duration of time considered
* "potentially checkerboarding". This is the union of two possibly-intersecting
* sets of time periods. The first set is that in which checkerboarding was
* actually happening, since by definition it could potentially be happening.
* The second set is that in which the APZC is actively transforming content
* in the compositor, since it could potentially transform it so as to display
* checkerboarding to the user.
* The caller of this class calls the appropriate methods to indicate the start
* and stop of these two sets, and this class manages accumulating the union
* of the various durations.
*/
class PotentialCheckerboardDurationTracker {
public:
PotentialCheckerboardDurationTracker();
/**
* This should be called if checkerboarding is encountered. It can be called
* multiple times during a checkerboard event.
*/
void CheckerboardSeen();
/**
* This should be called when checkerboarding is done. It must have been
* preceded by one or more calls to CheckerboardSeen().
*/
void CheckerboardDone();
/**
* This should be called when a transform is started. Calls to this must be
* interleaved with calls to TransformStopped().
*/
void TransformStarted();
/**
* This should be called when a transform is stopped. Calls to this must be
* interleaved with calls to TransformStarted().
*/
void TransformStopped();
private:
bool Tracking() const;
private:
bool mInCheckerboard;
bool mInTransform;
TimeStamp mCurrentPeriodStart;
};
} // namespace layers
} // namespace mozilla
#endif // mozilla_layers_PotentialCheckerboardDurationTracker_h
+1 -2
View File
@@ -14,8 +14,7 @@ namespace mozilla {
namespace layers {
WheelScrollAnimation::WheelScrollAnimation(AsyncPanZoomController& aApzc, const nsPoint& aInitialPosition)
: AsyncPanZoomAnimation(TimeDuration::FromMilliseconds(gfxPrefs::APZSmoothScrollRepaintInterval()))
, AsyncScrollBase(aInitialPosition)
: AsyncScrollBase(aInitialPosition)
, mApzc(aApzc)
, mFinalDestination(aInitialPosition)
{
+67 -50
View File
@@ -32,21 +32,28 @@
// (which expects an untransformed point). We handle both cases by setting both
// the transformed and untransformed fields to the same value.
SingleTouchData
CreateSingleTouchData(int32_t aIdentifier, int aX, int aY)
CreateSingleTouchData(int32_t aIdentifier, const ScreenIntPoint& aPoint)
{
SingleTouchData touch(aIdentifier, ScreenIntPoint(aX, aY), ScreenSize(0, 0), 0, 0);
touch.mLocalScreenPoint = ParentLayerPoint(aX, aY);
SingleTouchData touch(aIdentifier, aPoint, ScreenSize(0, 0), 0, 0);
touch.mLocalScreenPoint = ParentLayerPoint(aPoint.x, aPoint.y);
return touch;
}
// Convenience wrapper for CreateSingleTouchData() that takes loose coordinates.
SingleTouchData
CreateSingleTouchData(int32_t aIdentifier, ScreenIntCoord aX, ScreenIntCoord aY)
{
return CreateSingleTouchData(aIdentifier, ScreenIntPoint(aX, aY));
}
PinchGestureInput
CreatePinchGestureInput(PinchGestureInput::PinchGestureType aType,
int aFocusX, int aFocusY,
const ScreenIntPoint& aFocus,
float aCurrentSpan, float aPreviousSpan)
{
PinchGestureInput result(aType, 0, TimeStamp(), ScreenPoint(aFocusX, aFocusY),
PinchGestureInput result(aType, 0, TimeStamp(), aFocus,
aCurrentSpan, aPreviousSpan, 0);
result.mLocalFocusPoint = ParentLayerPoint(aFocusX, aFocusY);
result.mLocalFocusPoint = ParentLayerPoint(aFocus.x, aFocus.y);
return result;
}
@@ -76,34 +83,38 @@ CreateMultiTouchInput(MultiTouchInput::MultiTouchType aType, TimeStamp aTime)
template<class InputReceiver>
nsEventStatus
TouchDown(const RefPtr<InputReceiver>& aTarget, int aX, int aY, TimeStamp aTime, uint64_t* aOutInputBlockId = nullptr)
TouchDown(const RefPtr<InputReceiver>& aTarget, const ScreenIntPoint& aPoint,
TimeStamp aTime, uint64_t* aOutInputBlockId = nullptr)
{
MultiTouchInput mti = CreateMultiTouchInput(MultiTouchInput::MULTITOUCH_START, aTime);
mti.mTouches.AppendElement(CreateSingleTouchData(0, aX, aY));
mti.mTouches.AppendElement(CreateSingleTouchData(0, aPoint));
return aTarget->ReceiveInputEvent(mti, nullptr, aOutInputBlockId);
}
template<class InputReceiver>
nsEventStatus
TouchMove(const RefPtr<InputReceiver>& aTarget, int aX, int aY, TimeStamp aTime)
TouchMove(const RefPtr<InputReceiver>& aTarget, const ScreenIntPoint& aPoint,
TimeStamp aTime)
{
MultiTouchInput mti = CreateMultiTouchInput(MultiTouchInput::MULTITOUCH_MOVE, aTime);
mti.mTouches.AppendElement(CreateSingleTouchData(0, aX, aY));
mti.mTouches.AppendElement(CreateSingleTouchData(0, aPoint));
return aTarget->ReceiveInputEvent(mti, nullptr, nullptr);
}
template<class InputReceiver>
nsEventStatus
TouchUp(const RefPtr<InputReceiver>& aTarget, int aX, int aY, TimeStamp aTime)
TouchUp(const RefPtr<InputReceiver>& aTarget, const ScreenIntPoint& aPoint,
TimeStamp aTime)
{
MultiTouchInput mti = CreateMultiTouchInput(MultiTouchInput::MULTITOUCH_END, aTime);
mti.mTouches.AppendElement(CreateSingleTouchData(0, aX, aY));
mti.mTouches.AppendElement(CreateSingleTouchData(0, aPoint));
return aTarget->ReceiveInputEvent(mti, nullptr, nullptr);
}
template<class InputReceiver>
void
Tap(const RefPtr<InputReceiver>& aTarget, int aX, int aY, MockContentControllerDelayed* aMcc,
Tap(const RefPtr<InputReceiver>& aTarget, const ScreenIntPoint& aPoint,
MockContentControllerDelayed* aMcc,
TimeDuration aTapLength,
nsEventStatus (*aOutEventStatuses)[2] = nullptr,
uint64_t* aOutInputBlockId = nullptr)
@@ -115,7 +126,7 @@ Tap(const RefPtr<InputReceiver>& aTarget, int aX, int aY, MockContentControllerD
aOutInputBlockId = &blockId;
}
nsEventStatus status = TouchDown(aTarget, aX, aY, aMcc->Time(), aOutInputBlockId);
nsEventStatus status = TouchDown(aTarget, aPoint, aMcc->Time(), aOutInputBlockId);
if (aOutEventStatuses) {
(*aOutEventStatuses)[0] = status;
}
@@ -127,7 +138,7 @@ Tap(const RefPtr<InputReceiver>& aTarget, int aX, int aY, MockContentControllerD
SetDefaultAllowedTouchBehavior(aTarget, *aOutInputBlockId);
}
status = TouchUp(aTarget, aX, aY, aMcc->Time());
status = TouchUp(aTarget, aPoint, aMcc->Time());
if (aOutEventStatuses) {
(*aOutEventStatuses)[1] = status;
}
@@ -135,11 +146,12 @@ Tap(const RefPtr<InputReceiver>& aTarget, int aX, int aY, MockContentControllerD
template<class InputReceiver>
void
TapAndCheckStatus(const RefPtr<InputReceiver>& aTarget, int aX, int aY,
MockContentControllerDelayed* aMcc, TimeDuration aTapLength)
TapAndCheckStatus(const RefPtr<InputReceiver>& aTarget,
const ScreenIntPoint& aPoint, MockContentControllerDelayed* aMcc,
TimeDuration aTapLength)
{
nsEventStatus statuses[2];
Tap(aTarget, aX, aY, aMcc, aTapLength, &statuses);
Tap(aTarget, aPoint, aMcc, aTapLength, &statuses);
EXPECT_EQ(nsEventStatus_eConsumeDoDefault, statuses[0]);
EXPECT_EQ(nsEventStatus_eConsumeDoDefault, statuses[1]);
}
@@ -148,8 +160,8 @@ template<class InputReceiver>
void
Pan(const RefPtr<InputReceiver>& aTarget,
MockContentControllerDelayed* aMcc,
const ScreenPoint& aTouchStart,
const ScreenPoint& aTouchEnd,
const ScreenIntPoint& aTouchStart,
const ScreenIntPoint& aTouchEnd,
bool aKeepFingerDown = false,
nsTArray<uint32_t>* aAllowedTouchBehaviors = nullptr,
nsEventStatus (*aOutEventStatuses)[4] = nullptr,
@@ -173,7 +185,9 @@ Pan(const RefPtr<InputReceiver>& aTarget,
}
// Make sure the move is large enough to not be handled as a tap
nsEventStatus status = TouchDown(aTarget, aTouchStart.x, aTouchStart.y + OVERCOME_TOUCH_TOLERANCE, aMcc->Time(), aOutInputBlockId);
nsEventStatus status = TouchDown(aTarget,
ScreenIntPoint(aTouchStart.x, aTouchStart.y + OVERCOME_TOUCH_TOLERANCE),
aMcc->Time(), aOutInputBlockId);
if (aOutEventStatuses) {
(*aOutEventStatuses)[0] = status;
}
@@ -190,14 +204,14 @@ Pan(const RefPtr<InputReceiver>& aTarget,
}
}
status = TouchMove(aTarget, aTouchStart.x, aTouchStart.y, aMcc->Time());
status = TouchMove(aTarget, aTouchStart, aMcc->Time());
if (aOutEventStatuses) {
(*aOutEventStatuses)[1] = status;
}
aMcc->AdvanceBy(TIME_BETWEEN_TOUCH_EVENT);
status = TouchMove(aTarget, aTouchEnd.x, aTouchEnd.y, aMcc->Time());
status = TouchMove(aTarget, aTouchEnd, aMcc->Time());
if (aOutEventStatuses) {
(*aOutEventStatuses)[2] = status;
}
@@ -205,7 +219,7 @@ Pan(const RefPtr<InputReceiver>& aTarget,
aMcc->AdvanceBy(TIME_BETWEEN_TOUCH_EVENT);
if (!aKeepFingerDown) {
status = TouchUp(aTarget, aTouchEnd.x, aTouchEnd.y, aMcc->Time());
status = TouchUp(aTarget, aTouchEnd, aMcc->Time());
} else {
status = nsEventStatus_eIgnore;
}
@@ -232,7 +246,7 @@ Pan(const RefPtr<InputReceiver>& aTarget,
nsEventStatus (*aOutEventStatuses)[4] = nullptr,
uint64_t* aOutInputBlockId = nullptr)
{
::Pan(aTarget, aMcc, ScreenPoint(10, aTouchStartY), ScreenPoint(10, aTouchEndY),
::Pan(aTarget, aMcc, ScreenIntPoint(10, aTouchStartY), ScreenIntPoint(10, aTouchEndY),
aKeepFingerDown, aAllowedTouchBehaviors, aOutEventStatuses, aOutInputBlockId);
}
@@ -279,19 +293,20 @@ ApzcPanNoFling(const RefPtr<TestAsyncPanZoomController>& aApzc,
template<class InputReceiver>
void
PinchWithPinchInput(const RefPtr<InputReceiver>& aTarget,
int aFocusX, int aFocusY, int aSecondFocusX, int aSecondFocusY, float aScale,
const ScreenIntPoint& aFocus,
const ScreenIntPoint& aSecondFocus, float aScale,
nsEventStatus (*aOutEventStatuses)[3] = nullptr)
{
nsEventStatus actualStatus = aTarget->ReceiveInputEvent(
CreatePinchGestureInput(PinchGestureInput::PINCHGESTURE_START,
aFocusX, aFocusY, 10.0, 10.0),
aFocus, 10.0, 10.0),
nullptr);
if (aOutEventStatuses) {
(*aOutEventStatuses)[0] = actualStatus;
}
actualStatus = aTarget->ReceiveInputEvent(
CreatePinchGestureInput(PinchGestureInput::PINCHGESTURE_SCALE,
aSecondFocusX, aSecondFocusY, 10.0 * aScale, 10.0),
aSecondFocus, 10.0 * aScale, 10.0),
nullptr);
if (aOutEventStatuses) {
(*aOutEventStatuses)[1] = actualStatus;
@@ -300,7 +315,7 @@ PinchWithPinchInput(const RefPtr<InputReceiver>& aTarget,
CreatePinchGestureInput(PinchGestureInput::PINCHGESTURE_END,
// note: negative values here tell APZC
// not to turn the pinch into a pan
aFocusX, aFocusY, -1.0, -1.0),
aFocus, -1.0, -1.0),
nullptr);
if (aOutEventStatuses) {
(*aOutEventStatuses)[2] = actualStatus;
@@ -310,11 +325,11 @@ PinchWithPinchInput(const RefPtr<InputReceiver>& aTarget,
template<class InputReceiver>
void
PinchWithPinchInputAndCheckStatus(const RefPtr<InputReceiver>& aTarget,
int aFocusX, int aFocusY, float aScale,
const ScreenIntPoint& aFocus, float aScale,
bool aShouldTriggerPinch)
{
nsEventStatus statuses[3]; // scalebegin, scale, scaleend
PinchWithPinchInput(aTarget, aFocusX, aFocusY, aFocusX, aFocusY, aScale, &statuses);
PinchWithPinchInput(aTarget, aFocus, aFocus, aScale, &statuses);
nsEventStatus expectedStatus = aShouldTriggerPinch
? nsEventStatus_eConsumeNoDefault
@@ -326,7 +341,7 @@ PinchWithPinchInputAndCheckStatus(const RefPtr<InputReceiver>& aTarget,
template<class InputReceiver>
void
PinchWithTouchInput(const RefPtr<InputReceiver>& aTarget,
int aFocusX, int aFocusY, float aScale,
const ScreenIntPoint& aFocus, float aScale,
int& inputId,
nsTArray<uint32_t>* aAllowedTouchBehaviors = nullptr,
nsEventStatus (*aOutEventStatuses)[4] = nullptr,
@@ -345,8 +360,8 @@ PinchWithTouchInput(const RefPtr<InputReceiver>& aTarget,
}
MultiTouchInput mtiStart = MultiTouchInput(MultiTouchInput::MULTITOUCH_START, 0, TimeStamp(), 0);
mtiStart.mTouches.AppendElement(CreateSingleTouchData(inputId, aFocusX, aFocusY));
mtiStart.mTouches.AppendElement(CreateSingleTouchData(inputId + 1, aFocusX, aFocusY));
mtiStart.mTouches.AppendElement(CreateSingleTouchData(inputId, aFocus));
mtiStart.mTouches.AppendElement(CreateSingleTouchData(inputId + 1, aFocus));
nsEventStatus status = aTarget->ReceiveInputEvent(mtiStart, aOutInputBlockId);
if (aOutEventStatuses) {
(*aOutEventStatuses)[0] = status;
@@ -360,24 +375,24 @@ PinchWithTouchInput(const RefPtr<InputReceiver>& aTarget,
}
MultiTouchInput mtiMove1 = MultiTouchInput(MultiTouchInput::MULTITOUCH_MOVE, 0, TimeStamp(), 0);
mtiMove1.mTouches.AppendElement(CreateSingleTouchData(inputId, aFocusX - pinchLength, aFocusY));
mtiMove1.mTouches.AppendElement(CreateSingleTouchData(inputId + 1, aFocusX + pinchLength, aFocusY));
mtiMove1.mTouches.AppendElement(CreateSingleTouchData(inputId, aFocus.x - pinchLength, aFocus.y));
mtiMove1.mTouches.AppendElement(CreateSingleTouchData(inputId + 1, aFocus.x + pinchLength, aFocus.y));
status = aTarget->ReceiveInputEvent(mtiMove1, nullptr);
if (aOutEventStatuses) {
(*aOutEventStatuses)[1] = status;
}
MultiTouchInput mtiMove2 = MultiTouchInput(MultiTouchInput::MULTITOUCH_MOVE, 0, TimeStamp(), 0);
mtiMove2.mTouches.AppendElement(CreateSingleTouchData(inputId, aFocusX - pinchLengthScaled, aFocusY));
mtiMove2.mTouches.AppendElement(CreateSingleTouchData(inputId + 1, aFocusX + pinchLengthScaled, aFocusY));
mtiMove2.mTouches.AppendElement(CreateSingleTouchData(inputId, aFocus.x - pinchLengthScaled, aFocus.y));
mtiMove2.mTouches.AppendElement(CreateSingleTouchData(inputId + 1, aFocus.x + pinchLengthScaled, aFocus.y));
status = aTarget->ReceiveInputEvent(mtiMove2, nullptr);
if (aOutEventStatuses) {
(*aOutEventStatuses)[2] = status;
}
MultiTouchInput mtiEnd = MultiTouchInput(MultiTouchInput::MULTITOUCH_END, 0, TimeStamp(), 0);
mtiEnd.mTouches.AppendElement(CreateSingleTouchData(inputId, aFocusX - pinchLengthScaled, aFocusY));
mtiEnd.mTouches.AppendElement(CreateSingleTouchData(inputId + 1, aFocusX + pinchLengthScaled, aFocusY));
mtiEnd.mTouches.AppendElement(CreateSingleTouchData(inputId, aFocus.x - pinchLengthScaled, aFocus.y));
mtiEnd.mTouches.AppendElement(CreateSingleTouchData(inputId + 1, aFocus.x + pinchLengthScaled, aFocus.y));
status = aTarget->ReceiveInputEvent(mtiEnd, nullptr);
if (aOutEventStatuses) {
(*aOutEventStatuses)[3] = status;
@@ -389,12 +404,12 @@ PinchWithTouchInput(const RefPtr<InputReceiver>& aTarget,
template<class InputReceiver>
void
PinchWithTouchInputAndCheckStatus(const RefPtr<InputReceiver>& aTarget,
int aFocusX, int aFocusY, float aScale,
const ScreenIntPoint& aFocus, float aScale,
int& inputId, bool aShouldTriggerPinch,
nsTArray<uint32_t>* aAllowedTouchBehaviors)
{
nsEventStatus statuses[4]; // down, move, move, up
PinchWithTouchInput(aTarget, aFocusX, aFocusY, aScale, inputId, aAllowedTouchBehaviors, &statuses);
PinchWithTouchInput(aTarget, aFocus, aScale, inputId, aAllowedTouchBehaviors, &statuses);
nsEventStatus expectedMoveStatus = aShouldTriggerPinch
? nsEventStatus_eConsumeDoDefault
@@ -406,12 +421,13 @@ PinchWithTouchInputAndCheckStatus(const RefPtr<InputReceiver>& aTarget,
template<class InputReceiver>
void
DoubleTap(const RefPtr<InputReceiver>& aTarget, int aX, int aY, MockContentControllerDelayed* aMcc,
DoubleTap(const RefPtr<InputReceiver>& aTarget, const ScreenIntPoint& aPoint,
MockContentControllerDelayed* aMcc,
nsEventStatus (*aOutEventStatuses)[4] = nullptr,
uint64_t (*aOutInputBlockIds)[2] = nullptr)
{
uint64_t blockId;
nsEventStatus status = TouchDown(aTarget, aX, aY, aMcc->Time(), &blockId);
nsEventStatus status = TouchDown(aTarget, aPoint, aMcc->Time(), &blockId);
if (aOutEventStatuses) {
(*aOutEventStatuses)[0] = status;
}
@@ -426,12 +442,12 @@ DoubleTap(const RefPtr<InputReceiver>& aTarget, int aX, int aY, MockContentContr
SetDefaultAllowedTouchBehavior(aTarget, blockId);
}
status = TouchUp(aTarget, aX, aY, aMcc->Time());
status = TouchUp(aTarget, aPoint, aMcc->Time());
if (aOutEventStatuses) {
(*aOutEventStatuses)[1] = status;
}
aMcc->AdvanceByMillis(10);
status = TouchDown(aTarget, aX, aY, aMcc->Time(), &blockId);
status = TouchDown(aTarget, aPoint, aMcc->Time(), &blockId);
if (aOutEventStatuses) {
(*aOutEventStatuses)[2] = status;
}
@@ -444,7 +460,7 @@ DoubleTap(const RefPtr<InputReceiver>& aTarget, int aX, int aY, MockContentContr
SetDefaultAllowedTouchBehavior(aTarget, blockId);
}
status = TouchUp(aTarget, aX, aY, aMcc->Time());
status = TouchUp(aTarget, aPoint, aMcc->Time());
if (aOutEventStatuses) {
(*aOutEventStatuses)[3] = status;
}
@@ -452,11 +468,12 @@ DoubleTap(const RefPtr<InputReceiver>& aTarget, int aX, int aY, MockContentContr
template<class InputReceiver>
void
DoubleTapAndCheckStatus(const RefPtr<InputReceiver>& aTarget, int aX, int aY,
MockContentControllerDelayed* aMcc, uint64_t (*aOutInputBlockIds)[2] = nullptr)
DoubleTapAndCheckStatus(const RefPtr<InputReceiver>& aTarget,
const ScreenIntPoint& aPoint, MockContentControllerDelayed* aMcc,
uint64_t (*aOutInputBlockIds)[2] = nullptr)
{
nsEventStatus statuses[4];
DoubleTap(aTarget, aX, aY, aMcc, &statuses, aOutInputBlockIds);
DoubleTap(aTarget, aPoint, aMcc, &statuses, aOutInputBlockIds);
EXPECT_EQ(nsEventStatus_eConsumeDoDefault, statuses[0]);
EXPECT_EQ(nsEventStatus_eConsumeDoDefault, statuses[1]);
EXPECT_EQ(nsEventStatus_eConsumeDoDefault, statuses[2]);
+3 -3
View File
@@ -22,7 +22,7 @@ TEST_F(APZCBasicTester, Overzoom) {
EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1);
PinchWithPinchInputAndCheckStatus(apzc, 50, 50, 0.5, true);
PinchWithPinchInputAndCheckStatus(apzc, ScreenIntPoint(50, 50), 0.5, true);
fm = apzc->GetFrameMetrics();
EXPECT_EQ(0.8f, fm.GetZoom().ToScaleFactor().scale);
@@ -295,8 +295,8 @@ TEST_F(APZCBasicTester, OverScroll_Bug1152051b) {
// to schedule a new one since we're still overscrolled. We don't pan because
// panning can trigger functions that clear the overscroll animation state
// in other ways.
TouchDown(apzc, 10, 10, mcc->Time(), nullptr);
TouchUp(apzc, 10, 10, mcc->Time());
TouchDown(apzc, ScreenIntPoint(10, 10), mcc->Time(), nullptr);
TouchUp(apzc, ScreenIntPoint(10, 10), mcc->Time());
// Sample the second overscroll animation to its end.
// If the ending of the first overscroll animation fails to clear state
@@ -186,18 +186,18 @@ TEST_F(APZEventRegionsTester, HitRegionImmediateResponse) {
// Tap in the exposed hit regions of each of the layers once and ensure
// the clicks are dispatched right away
Tap(manager, 10, 10, mcc, tapDuration);
Tap(manager, ScreenIntPoint(10, 10), mcc, tapDuration);
mcc->RunThroughDelayedTasks(); // this runs the tap event
check.Call("Tapped on left");
Tap(manager, 110, 110, mcc, tapDuration);
Tap(manager, ScreenIntPoint(110, 110), mcc, tapDuration);
mcc->RunThroughDelayedTasks(); // this runs the tap event
check.Call("Tapped on bottom");
Tap(manager, 110, 10, mcc, tapDuration);
Tap(manager, ScreenIntPoint(110, 10), mcc, tapDuration);
mcc->RunThroughDelayedTasks(); // this runs the tap event
check.Call("Tapped on root");
// Now tap on the dispatch-to-content region where the layers overlap
Tap(manager, 10, 110, mcc, tapDuration);
Tap(manager, ScreenIntPoint(10, 110), mcc, tapDuration);
mcc->RunThroughDelayedTasks(); // this runs the main-thread timeout
check.Call("Tap pending on d-t-c region");
mcc->RunThroughDelayedTasks(); // this runs the tap event
@@ -205,7 +205,7 @@ TEST_F(APZEventRegionsTester, HitRegionImmediateResponse) {
// Now let's do that again, but simulate a main-thread response
uint64_t inputBlockId = 0;
Tap(manager, 10, 110, mcc, tapDuration, nullptr, &inputBlockId);
Tap(manager, ScreenIntPoint(10, 110), mcc, tapDuration, nullptr, &inputBlockId);
nsTArray<ScrollableLayerGuid> targets;
targets.AppendElement(left->GetGuid());
manager->SetTargetAPZC(inputBlockId, targets);
@@ -221,7 +221,7 @@ TEST_F(APZEventRegionsTester, HitRegionAccumulatesChildren) {
// content controller, which indicates the input events got routed correctly
// to the APZC.
EXPECT_CALL(*mcc, HandleSingleTap(_, _, rootApzc->GetGuid())).Times(1);
Tap(manager, 10, 160, mcc, TimeDuration::FromMilliseconds(100));
Tap(manager, ScreenIntPoint(10, 160), mcc, TimeDuration::FromMilliseconds(100));
}
TEST_F(APZEventRegionsTester, Obscuration) {
@@ -260,7 +260,7 @@ TEST_F(APZEventRegionsTester, Bug1117712) {
// These touch events should hit the dispatch-to-content region of layers[3]
// and so get queued with that APZC as the tentative target.
uint64_t inputBlockId = 0;
Tap(manager, 55, 5, mcc, TimeDuration::FromMilliseconds(100), nullptr, &inputBlockId);
Tap(manager, ScreenIntPoint(55, 5), mcc, TimeDuration::FromMilliseconds(100), nullptr, &inputBlockId);
// But now we tell the APZ that really it hit layers[2], and expect the tap
// to be delivered at the correct coordinates.
EXPECT_CALL(*mcc, HandleSingleTap(CSSPoint(55, 5), 0, apzc2->GetGuid())).Times(1);
@@ -210,12 +210,12 @@ protected:
// Deliver a tap to abort the fling. Ensure that we get a HandleSingleTap
// call out of it if and only if the fling is slow.
EXPECT_CALL(*mcc, HandleSingleTap(_, 0, apzc->GetGuid())).Times(tapCallsExpected);
Tap(apzc, 10, 10, mcc, 0);
Tap(apzc, ScreenIntPoint(10, 10), mcc, 0);
while (mcc->RunThroughDelayedTasks());
// Deliver another tap, to make sure that taps are flowing properly once
// the fling is aborted.
Tap(apzc, 100, 100, mcc, 0);
Tap(apzc, ScreenIntPoint(100, 100), mcc, 0);
while (mcc->RunThroughDelayedTasks());
// Verify that we didn't advance any further after the fling was aborted, in either case.
@@ -247,7 +247,7 @@ protected:
EXPECT_GT(finalPoint.y, point.y);
// Now we put our finger down to stop the fling
TouchDown(apzc, 10, 10, mcc->Time(), &blockId);
TouchDown(apzc, ScreenIntPoint(10, 10), mcc->Time(), &blockId);
// Re-sample to make sure it hasn't moved
apzc->SampleContentTransformForFrame(&viewTransform, point, TimeDuration::FromMilliseconds(10));
@@ -264,7 +264,7 @@ protected:
EXPECT_EQ(finalPoint.y, point.y);
// clean up
TouchUp(apzc, 10, 10, mcc->Time());
TouchUp(apzc, ScreenIntPoint(10, 10), mcc->Time());
apzc->AssertStateIsReset();
}
@@ -300,7 +300,7 @@ TEST_F(APZCGestureDetectorTester, ShortPress) {
}
check.Call("pre-tap");
TapAndCheckStatus(apzc, 10, 10, mcc, TimeDuration::FromMilliseconds(100));
TapAndCheckStatus(apzc, ScreenIntPoint(10, 10), mcc, TimeDuration::FromMilliseconds(100));
check.Call("post-tap");
apzc->AssertStateIsReset();
@@ -320,7 +320,7 @@ TEST_F(APZCGestureDetectorTester, MediumPress) {
}
check.Call("pre-tap");
TapAndCheckStatus(apzc, 10, 10, mcc, TimeDuration::FromMilliseconds(400));
TapAndCheckStatus(apzc, ScreenIntPoint(10, 10), mcc, TimeDuration::FromMilliseconds(400));
check.Call("post-tap");
apzc->AssertStateIsReset();
@@ -333,7 +333,7 @@ protected:
uint64_t blockId = 0;
nsEventStatus status = TouchDown(apzc, 10, 10, mcc->Time(), &blockId);
nsEventStatus status = TouchDown(apzc, ScreenIntPoint(10, 10), mcc->Time(), &blockId);
EXPECT_EQ(nsEventStatus_eConsumeDoDefault, status);
if (gfxPrefs::TouchActionEnabled() && status != nsEventStatus_eConsumeNoDefault) {
@@ -376,7 +376,7 @@ protected:
// Finally, simulate lifting the finger. Since the long-press wasn't
// prevent-defaulted, we should get a long-tap-up event.
check.Call("preHandleSingleTap");
status = TouchUp(apzc, 10, 10, mcc->Time());
status = TouchUp(apzc, ScreenIntPoint(10, 10), mcc->Time());
mcc->RunThroughDelayedTasks();
EXPECT_EQ(nsEventStatus_eConsumeDoDefault, status);
check.Call("postHandleSingleTap");
@@ -394,7 +394,7 @@ protected:
touchEndY = 50;
uint64_t blockId = 0;
nsEventStatus status = TouchDown(apzc, touchX, touchStartY, mcc->Time(), &blockId);
nsEventStatus status = TouchDown(apzc, ScreenIntPoint(touchX, touchStartY), mcc->Time(), &blockId);
EXPECT_EQ(nsEventStatus_eConsumeDoDefault, status);
if (gfxPrefs::TouchActionEnabled() && status != nsEventStatus_eConsumeNoDefault) {
@@ -436,7 +436,7 @@ protected:
EXPECT_EQ(nsEventStatus_eConsumeDoDefault, status);
EXPECT_CALL(*mcc, HandleSingleTap(CSSPoint(touchX, touchEndY), 0, apzc->GetGuid())).Times(0);
status = TouchUp(apzc, touchX, touchEndY, mcc->Time());
status = TouchUp(apzc, ScreenIntPoint(touchX, touchEndY), mcc->Time());
EXPECT_EQ(nsEventStatus_eConsumeDoDefault, status);
ParentLayerPoint pointOut;
@@ -482,7 +482,7 @@ TEST_F(APZCGestureDetectorTester, DoubleTap) {
EXPECT_CALL(*mcc, HandleDoubleTap(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(1);
uint64_t blockIds[2];
DoubleTapAndCheckStatus(apzc, 10, 10, mcc, &blockIds);
DoubleTapAndCheckStatus(apzc, ScreenIntPoint(10, 10), mcc, &blockIds);
// responses to the two touchstarts
apzc->ContentReceivedInputBlock(blockIds[0], false);
@@ -499,7 +499,7 @@ TEST_F(APZCGestureDetectorTester, DoubleTapNotZoomable) {
EXPECT_CALL(*mcc, HandleDoubleTap(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(0);
uint64_t blockIds[2];
DoubleTapAndCheckStatus(apzc, 10, 10, mcc, &blockIds);
DoubleTapAndCheckStatus(apzc, ScreenIntPoint(10, 10), mcc, &blockIds);
// responses to the two touchstarts
apzc->ContentReceivedInputBlock(blockIds[0], false);
@@ -516,7 +516,7 @@ TEST_F(APZCGestureDetectorTester, DoubleTapPreventDefaultFirstOnly) {
EXPECT_CALL(*mcc, HandleDoubleTap(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(0);
uint64_t blockIds[2];
DoubleTapAndCheckStatus(apzc, 10, 10, mcc, &blockIds);
DoubleTapAndCheckStatus(apzc, ScreenIntPoint(10, 10), mcc, &blockIds);
// responses to the two touchstarts
apzc->ContentReceivedInputBlock(blockIds[0], true);
@@ -533,7 +533,7 @@ TEST_F(APZCGestureDetectorTester, DoubleTapPreventDefaultBoth) {
EXPECT_CALL(*mcc, HandleDoubleTap(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(0);
uint64_t blockIds[2];
DoubleTapAndCheckStatus(apzc, 10, 10, mcc, &blockIds);
DoubleTapAndCheckStatus(apzc, ScreenIntPoint(10, 10), mcc, &blockIds);
// responses to the two touchstarts
apzc->ContentReceivedInputBlock(blockIds[0], true);
@@ -549,7 +549,7 @@ TEST_F(APZCGestureDetectorTester, TapFollowedByPinch) {
EXPECT_CALL(*mcc, HandleSingleTap(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(1);
Tap(apzc, 10, 10, mcc, TimeDuration::FromMilliseconds(100));
Tap(apzc, ScreenIntPoint(10, 10), mcc, TimeDuration::FromMilliseconds(100));
int inputId = 0;
MultiTouchInput mti;
@@ -571,7 +571,7 @@ TEST_F(APZCGestureDetectorTester, TapFollowedByMultipleTouches) {
EXPECT_CALL(*mcc, HandleSingleTap(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(1);
Tap(apzc, 10, 10, mcc, TimeDuration::FromMilliseconds(100));
Tap(apzc, ScreenIntPoint(10, 10), mcc, TimeDuration::FromMilliseconds(100));
int inputId = 0;
MultiTouchInput mti;
+3 -3
View File
@@ -465,12 +465,12 @@ TEST_F(APZHitTestingTester, Bug1148350) {
EXPECT_CALL(check, Call("Tapped with interleaved transform"));
}
Tap(manager, 100, 100, mcc, TimeDuration::FromMilliseconds(100));
Tap(manager, ScreenIntPoint(100, 100), mcc, TimeDuration::FromMilliseconds(100));
mcc->RunThroughDelayedTasks();
check.Call("Tapped without transform");
uint64_t blockId;
TouchDown(manager, 100, 100, mcc->Time(), &blockId);
TouchDown(manager, ScreenIntPoint(100, 100), mcc->Time(), &blockId);
if (gfxPrefs::TouchActionEnabled()) {
SetDefaultAllowedTouchBehavior(manager, blockId);
}
@@ -480,7 +480,7 @@ TEST_F(APZHitTestingTester, Bug1148350) {
layers[0]->SetBaseTransform(Matrix4x4::Translation(0, 50, 0));
manager->UpdateHitTestingTree(nullptr, root, false, 0, 0);
TouchUp(manager, 100, 100, mcc->Time());
TouchUp(manager, ScreenIntPoint(100, 100), mcc->Time());
mcc->RunThroughDelayedTasks();
check.Call("Tapped with interleaved transform");
}
+12 -6
View File
@@ -44,9 +44,11 @@ protected:
int touchInputId = 0;
if (mGestureBehavior == AsyncPanZoomController::USE_GESTURE_DETECTOR) {
PinchWithTouchInputAndCheckStatus(apzc, 250, 300, 1.25, touchInputId, aShouldTriggerPinch, aAllowedTouchBehaviors);
PinchWithTouchInputAndCheckStatus(apzc, ScreenIntPoint(250, 300), 1.25,
touchInputId, aShouldTriggerPinch, aAllowedTouchBehaviors);
} else {
PinchWithPinchInputAndCheckStatus(apzc, 250, 300, 1.25, aShouldTriggerPinch);
PinchWithPinchInputAndCheckStatus(apzc, ScreenIntPoint(250, 300), 1.25,
aShouldTriggerPinch);
}
FrameMetrics fm = apzc->GetFrameMetrics();
@@ -72,9 +74,11 @@ protected:
// the visible area of the document in CSS pixels is x=930 y=5 w=50 h=100
if (mGestureBehavior == AsyncPanZoomController::USE_GESTURE_DETECTOR) {
PinchWithTouchInputAndCheckStatus(apzc, 250, 300, 0.5, touchInputId, aShouldTriggerPinch, aAllowedTouchBehaviors);
PinchWithTouchInputAndCheckStatus(apzc, ScreenIntPoint(250, 300), 0.5,
touchInputId, aShouldTriggerPinch, aAllowedTouchBehaviors);
} else {
PinchWithPinchInputAndCheckStatus(apzc, 250, 300, 0.5, aShouldTriggerPinch);
PinchWithPinchInputAndCheckStatus(apzc, ScreenIntPoint(250, 300), 0.5,
aShouldTriggerPinch);
}
fm = apzc->GetFrameMetrics();
@@ -142,7 +146,8 @@ TEST_F(APZCPinchGestureDetectorTester, Pinch_PreventDefault) {
int touchInputId = 0;
uint64_t blockId = 0;
PinchWithTouchInput(apzc, 250, 300, 1.25, touchInputId, nullptr, nullptr, &blockId);
PinchWithTouchInput(apzc, ScreenIntPoint(250, 300), 1.25, touchInputId,
nullptr, nullptr, &blockId);
// Send the prevent-default notification for the touch block
apzc->ContentReceivedInputBlock(blockId, true);
@@ -162,7 +167,8 @@ TEST_F(APZCPinchTester, Panning_TwoFinger_ZoomDisabled) {
MakeApzcUnzoomable();
nsEventStatus statuses[3]; // scalebegin, scale, scaleend
PinchWithPinchInput(apzc, 250, 350, 200, 300, 10, &statuses);
PinchWithPinchInput(apzc, ScreenIntPoint(250, 350), ScreenIntPoint(200, 300),
10, &statuses);
FrameMetrics fm = apzc->GetFrameMetrics();
@@ -8,12 +8,12 @@
#include "APZTestCommon.h"
#include "InputUtils.h"
class APZOverscrollHandoffTester : public APZCTreeManagerTester {
class APZScrollHandoffTester : public APZCTreeManagerTester {
protected:
UniquePtr<ScopedLayerTreeRegistration> registration;
TestAsyncPanZoomController* rootApzc;
void CreateOverscrollHandoffLayerTree1() {
void CreateScrollHandoffLayerTree1() {
const char* layerTreeSyntax = "c(t)";
nsIntRegion layerVisibleRegion[] = {
nsIntRegion(IntRect(0, 0, 100, 100)),
@@ -28,7 +28,7 @@ protected:
rootApzc = ApzcOf(root);
}
void CreateOverscrollHandoffLayerTree2() {
void CreateScrollHandoffLayerTree2() {
const char* layerTreeSyntax = "c(c(t))";
nsIntRegion layerVisibleRegion[] = {
nsIntRegion(IntRect(0, 0, 100, 100)),
@@ -48,7 +48,7 @@ protected:
rootApzc = ApzcOf(root);
}
void CreateOverscrollHandoffLayerTree3() {
void CreateScrollHandoffLayerTree3() {
const char* layerTreeSyntax = "c(c(t)c(t))";
nsIntRegion layerVisibleRegion[] = {
nsIntRegion(IntRect(0, 0, 100, 100)), // root
@@ -126,9 +126,9 @@ protected:
// Here we test that if the processing of a touch block is deferred while we
// wait for content to send a prevent-default message, overscroll is still
// handed off correctly when the block is processed.
TEST_F(APZOverscrollHandoffTester, DeferredInputEventProcessing) {
TEST_F(APZScrollHandoffTester, DeferredInputEventProcessing) {
// Set up the APZC tree.
CreateOverscrollHandoffLayerTree1();
CreateScrollHandoffLayerTree1();
TestAsyncPanZoomController* childApzc = ApzcOf(layers[1]);
@@ -154,9 +154,9 @@ TEST_F(APZOverscrollHandoffTester, DeferredInputEventProcessing) {
// one has been queued, overscroll handoff for the first block follows
// the original layer structure while overscroll handoff for the second block
// follows the new layer structure.
TEST_F(APZOverscrollHandoffTester, LayerStructureChangesWhileEventsArePending) {
TEST_F(APZScrollHandoffTester, LayerStructureChangesWhileEventsArePending) {
// Set up an initial APZC tree.
CreateOverscrollHandoffLayerTree1();
CreateScrollHandoffLayerTree1();
TestAsyncPanZoomController* childApzc = ApzcOf(layers[1]);
@@ -170,7 +170,7 @@ TEST_F(APZOverscrollHandoffTester, LayerStructureChangesWhileEventsArePending) {
// Modify the APZC tree to insert a new APZC 'middle' into the handoff chain
// between the child and the root.
CreateOverscrollHandoffLayerTree2();
CreateScrollHandoffLayerTree2();
RefPtr<Layer> middle = layers[1];
childApzc->SetWaitForMainThread();
TestAsyncPanZoomController* middleApzc = ApzcOf(middle);
@@ -202,11 +202,11 @@ TEST_F(APZOverscrollHandoffTester, LayerStructureChangesWhileEventsArePending) {
// Test that putting a second finger down on an APZC while a down-chain APZC
// is overscrolled doesn't result in being stuck in overscroll.
TEST_F(APZOverscrollHandoffTester, StuckInOverscroll_Bug1073250) {
TEST_F(APZScrollHandoffTester, StuckInOverscroll_Bug1073250) {
// Enable overscrolling.
SCOPED_GFX_PREF(APZOverscrollEnabled, bool, true);
CreateOverscrollHandoffLayerTree1();
CreateScrollHandoffLayerTree1();
TestAsyncPanZoomController* child = ApzcOf(layers[1]);
@@ -239,11 +239,11 @@ TEST_F(APZOverscrollHandoffTester, StuckInOverscroll_Bug1073250) {
// This is almost exactly like StuckInOverscroll_Bug1073250, except the
// APZC receiving the input events for the first touch block is the child
// (and thus not the same APZC that overscrolls, which is the parent).
TEST_F(APZOverscrollHandoffTester, StuckInOverscroll_Bug1231228) {
TEST_F(APZScrollHandoffTester, StuckInOverscroll_Bug1231228) {
// Enable overscrolling.
SCOPED_GFX_PREF(APZOverscrollEnabled, bool, true);
CreateOverscrollHandoffLayerTree1();
CreateScrollHandoffLayerTree1();
TestAsyncPanZoomController* child = ApzcOf(layers[1]);
@@ -273,17 +273,50 @@ TEST_F(APZOverscrollHandoffTester, StuckInOverscroll_Bug1231228) {
EXPECT_FALSE(rootApzc->IsOverscrolled());
}
TEST_F(APZScrollHandoffTester, StuckInOverscroll_Bug1240202a) {
// Enable overscrolling.
SCOPED_GFX_PREF(APZOverscrollEnabled, bool, true);
CreateScrollHandoffLayerTree1();
TestAsyncPanZoomController* child = ApzcOf(layers[1]);
// Pan, causing the parent APZC to overscroll.
Pan(manager, mcc, 60, 90, true /* keep finger down */);
EXPECT_FALSE(child->IsOverscrolled());
EXPECT_TRUE(rootApzc->IsOverscrolled());
// Lift the finger, triggering an overscroll animation
// (but don't allow it to run).
TouchUp(manager, ScreenIntPoint(10, 90), mcc->Time());
// Put the finger down again, interrupting the animation
// and entering the TOUCHING state.
TouchDown(manager, ScreenIntPoint(10, 90), mcc->Time());
// Lift the finger once again.
TouchUp(manager, ScreenIntPoint(10, 90), mcc->Time());
// Allow any animations to run their course.
child->AdvanceAnimationsUntilEnd();
rootApzc->AdvanceAnimationsUntilEnd();
// Make sure nothing is overscrolled.
EXPECT_FALSE(child->IsOverscrolled());
EXPECT_FALSE(rootApzc->IsOverscrolled());
}
// Test that flinging in a direction where one component of the fling goes into
// overscroll but the other doesn't, results in just the one component being
// handed off to the parent, while the original APZC continues flinging in the
// other direction.
TEST_F(APZOverscrollHandoffTester, PartialFlingHandoff) {
CreateOverscrollHandoffLayerTree1();
TEST_F(APZScrollHandoffTester, PartialFlingHandoff) {
CreateScrollHandoffLayerTree1();
// Fling up and to the left. The child APZC has room to scroll up, but not
// to the left, so the horizontal component of the fling should be handed
// off to the parent APZC.
Pan(manager, mcc, ScreenPoint(90, 90), ScreenPoint(55, 55));
Pan(manager, mcc, ScreenIntPoint(90, 90), ScreenIntPoint(55, 55));
RefPtr<TestAsyncPanZoomController> parent = ApzcOf(root);
RefPtr<TestAsyncPanZoomController> child = ApzcOf(layers[1]);
@@ -300,9 +333,9 @@ TEST_F(APZOverscrollHandoffTester, PartialFlingHandoff) {
// Here we test that if two flings are happening simultaneously, overscroll
// is handed off correctly for each.
TEST_F(APZOverscrollHandoffTester, SimultaneousFlings) {
TEST_F(APZScrollHandoffTester, SimultaneousFlings) {
// Set up an initial APZC tree.
CreateOverscrollHandoffLayerTree3();
CreateScrollHandoffLayerTree3();
RefPtr<TestAsyncPanZoomController> parent1 = ApzcOf(layers[1]);
RefPtr<TestAsyncPanZoomController> child1 = ApzcOf(layers[2]);
@@ -330,7 +363,7 @@ TEST_F(APZOverscrollHandoffTester, SimultaneousFlings) {
parent2->AssertStateIsFling();
}
TEST_F(APZOverscrollHandoffTester, Scrollgrab) {
TEST_F(APZScrollHandoffTester, Scrollgrab) {
// Set up the layer tree
CreateScrollgrabLayerTree();
@@ -345,7 +378,7 @@ TEST_F(APZOverscrollHandoffTester, Scrollgrab) {
EXPECT_EQ(15, childApzc->GetFrameMetrics().GetScrollOffset().y);
}
TEST_F(APZOverscrollHandoffTester, ScrollgrabFling) {
TEST_F(APZScrollHandoffTester, ScrollgrabFling) {
// Set up the layer tree
CreateScrollgrabLayerTree();
@@ -359,20 +392,20 @@ TEST_F(APZOverscrollHandoffTester, ScrollgrabFling) {
childApzc->AssertStateIsReset();
}
TEST_F(APZOverscrollHandoffTester, ScrollgrabFlingAcceleration1) {
TEST_F(APZScrollHandoffTester, ScrollgrabFlingAcceleration1) {
CreateScrollgrabLayerTree(true /* make parent scrollable */);
TestFlingAcceleration();
}
TEST_F(APZOverscrollHandoffTester, ScrollgrabFlingAcceleration2) {
TEST_F(APZScrollHandoffTester, ScrollgrabFlingAcceleration2) {
CreateScrollgrabLayerTree(false /* do not make parent scrollable */);
TestFlingAcceleration();
}
TEST_F(APZOverscrollHandoffTester, ImmediateHandoffDisallowed_Pan) {
TEST_F(APZScrollHandoffTester, ImmediateHandoffDisallowed_Pan) {
SCOPED_GFX_PREF(APZAllowImmediateHandoff, bool, false);
CreateOverscrollHandoffLayerTree1();
CreateScrollHandoffLayerTree1();
RefPtr<TestAsyncPanZoomController> parentApzc = ApzcOf(root);
RefPtr<TestAsyncPanZoomController> childApzc = ApzcOf(layers[1]);
@@ -394,10 +427,10 @@ TEST_F(APZOverscrollHandoffTester, ImmediateHandoffDisallowed_Pan) {
EXPECT_EQ(10, parentApzc->GetFrameMetrics().GetScrollOffset().y);
}
TEST_F(APZOverscrollHandoffTester, ImmediateHandoffDisallowed_Fling) {
TEST_F(APZScrollHandoffTester, ImmediateHandoffDisallowed_Fling) {
SCOPED_GFX_PREF(APZAllowImmediateHandoff, bool, false);
CreateOverscrollHandoffLayerTree1();
CreateScrollHandoffLayerTree1();
RefPtr<TestAsyncPanZoomController> parentApzc = ApzcOf(root);
RefPtr<TestAsyncPanZoomController> childApzc = ApzcOf(layers[1]);
+1 -1
View File
@@ -9,9 +9,9 @@ UNIFIED_SOURCES += [
'TestEventRegions.cpp',
'TestGestureDetector.cpp',
'TestHitTesting.cpp',
'TestOverscrollHandoff.cpp',
'TestPanning.cpp',
'TestPinching.cpp',
'TestScrollHandoff.cpp',
'TestTreeManager.cpp',
]
@@ -0,0 +1,184 @@
/* -*- 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 "CheckerboardReportService.h"
#include "gfxPrefs.h" // for gfxPrefs
#include "jsapi.h" // for JS_Now
#include "MainThreadUtils.h" // for NS_IsMainThread
#include "mozilla/Assertions.h" // for MOZ_ASSERT
#include "mozilla/ClearOnShutdown.h" // for ClearOnShutdown
#include "mozilla/dom/CheckerboardReportServiceBinding.h" // for dom::CheckerboardReports
#include "nsContentUtils.h" // for nsContentUtils
namespace mozilla {
namespace layers {
/*static*/ StaticRefPtr<CheckerboardEventStorage> CheckerboardEventStorage::sInstance;
/*static*/ already_AddRefed<CheckerboardEventStorage>
CheckerboardEventStorage::GetInstance()
{
// The instance in the parent process does all the work, so if this is getting
// called in the child process something is likely wrong.
MOZ_ASSERT(XRE_IsParentProcess());
MOZ_ASSERT(NS_IsMainThread());
if (!sInstance) {
sInstance = new CheckerboardEventStorage();
ClearOnShutdown(&sInstance);
}
RefPtr<CheckerboardEventStorage> instance = sInstance.get();
return instance.forget();
}
void
CheckerboardEventStorage::ReportCheckerboard(uint32_t aSeverity, const std::string& aLog)
{
MOZ_ASSERT(NS_IsMainThread());
if (aSeverity == 0) {
// This code assumes all checkerboard reports have a nonzero severity.
return;
}
CheckerboardReport severe(aSeverity, JS_Now(), aLog);
CheckerboardReport recent;
// First look in the "severe" reports to see if the new one belongs in that
// list.
for (int i = 0; i < SEVERITY_MAX_INDEX; i++) {
if (mCheckerboardReports[i].mSeverity >= severe.mSeverity) {
continue;
}
// The new one deserves to be in the "severe" list. Take the one getting
// bumped off the list, and put it in |recent| for possible insertion into
// the recents list.
recent = mCheckerboardReports[SEVERITY_MAX_INDEX - 1];
// Shuffle the severe list down, insert the new one.
for (int j = SEVERITY_MAX_INDEX - 1; j > i; j--) {
mCheckerboardReports[j] = mCheckerboardReports[j - 1];
}
mCheckerboardReports[i] = severe;
severe.mSeverity = 0; // mark |severe| as inserted
break;
}
// If |severe.mSeverity| is nonzero, the incoming report didn't get inserted
// into the severe list; put it into |recent| for insertion into the recent
// list.
if (severe.mSeverity) {
MOZ_ASSERT(recent.mSeverity == 0, "recent should be empty here");
recent = severe;
} // else |recent| may hold a report that got knocked out of the severe list.
if (recent.mSeverity == 0) {
// Nothing to be inserted into the recent list.
return;
}
// If it wasn't in the "severe" list, add it to the "recent" list.
for (int i = SEVERITY_MAX_INDEX; i < RECENT_MAX_INDEX; i++) {
if (mCheckerboardReports[i].mTimestamp >= recent.mTimestamp) {
continue;
}
// |recent| needs to be inserted at |i|. Shuffle the remaining ones down
// and insert it.
for (int j = RECENT_MAX_INDEX - 1; j > i; j--) {
mCheckerboardReports[j] = mCheckerboardReports[j - 1];
}
mCheckerboardReports[i] = recent;
break;
}
}
void
CheckerboardEventStorage::GetReports(nsTArray<dom::CheckerboardReport>& aOutReports)
{
MOZ_ASSERT(NS_IsMainThread());
for (int i = 0; i < RECENT_MAX_INDEX; i++) {
CheckerboardReport& r = mCheckerboardReports[i];
if (r.mSeverity == 0) {
continue;
}
dom::CheckerboardReport report;
report.mSeverity.Construct() = r.mSeverity;
report.mTimestamp.Construct() = r.mTimestamp / 1000; // micros to millis
report.mLog.Construct() = NS_ConvertUTF8toUTF16(r.mLog.c_str(), r.mLog.size());
report.mReason.Construct() = (i < SEVERITY_MAX_INDEX)
? dom::CheckerboardReason::Severe
: dom::CheckerboardReason::Recent;
aOutReports.AppendElement(report);
}
}
} // namespace layers
namespace dom {
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(CheckerboardReportService, mParent)
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(CheckerboardReportService, AddRef)
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(CheckerboardReportService, Release)
/*static*/ bool
CheckerboardReportService::IsEnabled(JSContext* aCtx, JSObject* aGlobal)
{
// Only allow this in the parent process
if (!XRE_IsParentProcess()) {
return false;
}
return nsContentUtils::IsSpecificAboutPage(aGlobal, "about:checkerboard");
}
/*static*/ already_AddRefed<CheckerboardReportService>
CheckerboardReportService::Constructor(const dom::GlobalObject& aGlobal, ErrorResult& aRv)
{
RefPtr<CheckerboardReportService> ces = new CheckerboardReportService(aGlobal.GetAsSupports());
return ces.forget();
}
CheckerboardReportService::CheckerboardReportService(nsISupports* aParent)
: mParent(aParent)
{
}
JSObject*
CheckerboardReportService::WrapObject(JSContext* aCtx, JS::Handle<JSObject*> aGivenProto)
{
return CheckerboardReportServiceBinding::Wrap(aCtx, this, aGivenProto);
}
nsISupports*
CheckerboardReportService::GetParentObject()
{
return mParent;
}
void
CheckerboardReportService::GetReports(nsTArray<dom::CheckerboardReport>& aOutReports)
{
RefPtr<mozilla::layers::CheckerboardEventStorage> instance =
mozilla::layers::CheckerboardEventStorage::GetInstance();
MOZ_ASSERT(instance);
instance->GetReports(aOutReports);
}
bool
CheckerboardReportService::IsRecordingEnabled() const
{
return gfxPrefs::APZRecordCheckerboarding();
}
void
CheckerboardReportService::SetRecordingEnabled(bool aEnabled)
{
gfxPrefs::SetAPZRecordCheckerboarding(aEnabled);
}
} // namespace dom
} // namespace mozilla
@@ -0,0 +1,141 @@
/* -*- 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_dom_CheckerboardReportService_h
#define mozilla_dom_CheckerboardReportService_h
#include <string>
#include "js/TypeDecls.h" // for JSContext, JSObject
#include "mozilla/ErrorResult.h" // for ErrorResult
#include "mozilla/StaticPtr.h" // for StaticRefPtr
#include "nsCOMPtr.h" // for nsCOMPtr
#include "nsISupports.h" // for NS_INLINE_DECL_REFCOUNTING
#include "nsWrapperCache.h" // for nsWrapperCache
namespace mozilla {
namespace dom {
struct CheckerboardReport;
}
namespace layers {
// CheckerboardEventStorage is a singleton that stores info on checkerboard
// events, so that they can be accessed from about:checkerboard and visualized.
// Note that this class is NOT threadsafe, and all methods must be called on
// the main thread.
class CheckerboardEventStorage
{
NS_INLINE_DECL_REFCOUNTING(CheckerboardEventStorage)
public:
/**
* Get the singleton instance.
*/
static already_AddRefed<CheckerboardEventStorage> GetInstance();
/**
* Save a checkerboard event log, optionally dropping older ones that were
* less severe or less recent. Zero-severity reports may be ignored entirely.
*/
void ReportCheckerboard(uint32_t aSeverity, const std::string& aLog);
/**
* Get the stored checkerboard reports.
*/
void GetReports(nsTArray<dom::CheckerboardReport>& aOutReports);
private:
/* Stuff for refcounted singleton */
CheckerboardEventStorage() {}
virtual ~CheckerboardEventStorage() {}
static StaticRefPtr<CheckerboardEventStorage> sInstance;
private:
/**
* Struct that this class uses internally to store a checkerboard report.
*/
struct CheckerboardReport {
uint32_t mSeverity; // if 0, this report is empty
int64_t mTimestamp; // microseconds since epoch, as from JS_Now()
std::string mLog;
CheckerboardReport()
: mSeverity(0)
, mTimestamp(0)
{}
CheckerboardReport(uint32_t aSeverity, int64_t aTimestamp,
const std::string& aLog)
: mSeverity(aSeverity)
, mTimestamp(aTimestamp)
, mLog(aLog)
{}
};
// The first 5 (indices 0-4) are the most severe ones in decreasing order
// of severity; the next 5 (indices 5-9) are the most recent ones that are
// not already in the "severe" list.
static const int SEVERITY_MAX_INDEX = 5;
static const int RECENT_MAX_INDEX = 10;
CheckerboardReport mCheckerboardReports[RECENT_MAX_INDEX];
};
} // namespace layers
namespace dom {
class GlobalObject;
/**
* CheckerboardReportService is a wrapper object that allows access to the
* stuff in CheckerboardEventStorage (above). We need this wrapper for proper
* garbage/cycle collection, since this can be accessed from JS.
*/
class CheckerboardReportService : public nsWrapperCache
{
public:
/**
* Check if the given page is allowed to access this object via the WebIDL
* bindings. It only returns true if the page is about:checkerboard.
*/
static bool IsEnabled(JSContext* aCtx, JSObject* aGlobal);
/*
* Other standard WebIDL binding glue.
*/
static already_AddRefed<CheckerboardReportService>
Constructor(const dom::GlobalObject& aGlobal, ErrorResult& aRv);
explicit CheckerboardReportService(nsISupports* aSupports);
JSObject* WrapObject(JSContext* aCtx, JS::Handle<JSObject*> aGivenProto) override;
nsISupports* GetParentObject();
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(CheckerboardReportService)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(CheckerboardReportService)
public:
/*
* The methods exposed via the webidl.
*/
void GetReports(nsTArray<dom::CheckerboardReport>& aOutReports);
bool IsRecordingEnabled() const;
void SetRecordingEnabled(bool aEnabled);
private:
virtual ~CheckerboardReportService() {}
nsCOMPtr<nsISupports> mParent;
};
} // namespace dom
} // namespace mozilla
#endif /* mozilla_layers_CheckerboardReportService_h */
+62
View File
@@ -0,0 +1,62 @@
/* -*- 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_ScrollInputMethods_h
#define mozilla_layers_ScrollInputMethods_h
namespace mozilla {
namespace layers {
/**
* An enumeration that lists various input methods used to trigger scrolling.
* Used as the values for the SCROLL_INPUT_METHODS telemetry histogram.
*/
enum class ScrollInputMethod {
// === Driven by APZ ===
ApzTouch, // touch events
ApzWheelPixel, // wheel events, pixel scrolling mode
ApzWheelLine, // wheel events, line scrolling mode
ApzWheelPage, // wheel events, page scrolling mode
ApzPanGesture, // pan gesture events (generally triggered by trackpad)
ApzScrollbarDrag, // dragging the scrollbar
// === Driven by the main thread ===
// Keyboard
MainThreadScrollLine, // line scrolling
// (generally triggered by up/down arrow keys)
MainThreadScrollCharacter, // character scrolling
// (generally triggered by left/right arrow keys)
MainThreadScrollPage, // page scrolling
// (generally triggered by PageUp/PageDown keys)
MainThreadCompleteScroll, // scrolling to the end of the scroll range
// (generally triggered by Home/End keys)
MainThreadScrollCaretIntoView, // scrolling to bring the caret into view
// after moving the caret via the keyboard
// Touch
MainThreadTouch, // touch events
// Scrollbar
MainThreadScrollbarDrag, // dragging the scrollbar
MainThreadScrollbarButtonClick, // clicking the buttons at the ends of the
// scrollback track
MainThreadScrollbarTrackClick, // clicking the scrollbar track above or
// below the thumb
// Autoscrolling
MainThreadAutoscrolling, // autoscrolling
// New input methods can be added at the end, up to a maximum of 64.
// They should only be added at the end, to preserve the numerical values
// of the existing enumerators.
};
} // namespace layers
} // namespace mozilla
#endif /* mozilla_layers_ScrollInputMethods_h */
+18 -3
View File
@@ -34,6 +34,7 @@ class DataTextureSourceBasic : public DataTextureSource
, public TextureSourceBasic
{
public:
virtual const char* Name() const override { return "DataTextureSourceBasic"; }
virtual TextureSourceBasic* AsSourceBasic() override { return this; }
@@ -201,6 +202,11 @@ DrawSurfaceWithTextureCoords(DrawTarget *aDest,
SourceSurface *aMask,
const Matrix* aMaskTransform)
{
if (!aSource) {
gfxWarning() << "DrawSurfaceWithTextureCoords problem " << gfx::hexa(aSource) << " and " << gfx::hexa(aMask);
return;
}
// Convert aTextureCoords into aSource's coordinate space
gfxRect sourceRect(aTextureCoords.x * aSource->GetSize().width,
aTextureCoords.y * aSource->GetSize().height,
@@ -422,6 +428,9 @@ BasicCompositor::DrawQuad(const gfx::Rect& aRect,
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();
@@ -456,15 +465,17 @@ BasicCompositor::DrawQuad(const gfx::Rect& aRect,
static_cast<TexturedEffect*>(aEffectChain.mPrimaryEffect.get());
TextureSourceBasic* source = texturedEffect->mTexture->AsSourceBasic();
if (texturedEffect->mPremultiplied) {
if (source && texturedEffect->mPremultiplied) {
DrawSurfaceWithTextureCoords(dest, aRect,
source->GetSurface(dest),
texturedEffect->mTextureCoords,
texturedEffect->mFilter,
DrawOptions(aOpacity, blendMode),
sourceMask, &maskTransform);
} else {
RefPtr<DataSourceSurface> srcData = source->GetSurface(dest)->GetDataSurface();
} else if (source) {
SourceSurface* srcSurf = source->GetSurface(dest);
if (srcSurf) {
RefPtr<DataSourceSurface> srcData = srcSurf->GetDataSurface();
// Yes, we re-create the premultiplied data every time.
// This might be better with a cache, eventually.
@@ -476,7 +487,11 @@ BasicCompositor::DrawQuad(const gfx::Rect& aRect,
texturedEffect->mFilter,
DrawOptions(aOpacity, blendMode),
sourceMask, &maskTransform);
}
} else {
gfxDevCrash(LogReason::IncompatibleBasicTexturedEffect) << "Bad for basic with " << texturedEffect->mTexture->Name() << " and " << gfx::hexa(sourceMask);
}
break;
}
case EffectTypes::YCBCR: {
+2
View File
@@ -23,6 +23,8 @@ public:
, mSize(aRect.Size())
{ }
virtual const char* Name() const override { return "BasicCompositingRenderTarget"; }
virtual gfx::IntSize GetSize() const override { return mSize; }
void BindRenderTarget();
+2 -2
View File
@@ -109,7 +109,7 @@ BasicContainerLayer::ChildrenPartitionVisibleRegion(const gfx::IntRect& aInRect)
return false;
nsIntPoint offset(int32_t(transform._31), int32_t(transform._32));
gfx::IntRect rect = aInRect.Intersect(GetEffectiveVisibleRegion().ToUnknownRegion().GetBounds() + offset);
gfx::IntRect rect = aInRect.Intersect(GetLocalVisibleRegion().ToUnknownRegion().GetBounds() + offset);
nsIntRegion covered;
for (Layer* l = mFirstChild; l; l = l->GetNextSibling()) {
@@ -121,7 +121,7 @@ BasicContainerLayer::ChildrenPartitionVisibleRegion(const gfx::IntRect& aInRect)
ThebesMatrix(childTransform).HasNonIntegerTranslation() ||
l->GetEffectiveOpacity() != 1.0)
return false;
nsIntRegion childRegion = l->GetEffectiveVisibleRegion().ToUnknownRegion();
nsIntRegion childRegion = l->GetLocalVisibleRegion().ToUnknownRegion();
childRegion.MoveBy(int32_t(childTransform._31), int32_t(childTransform._32));
childRegion.And(childRegion, rect);
if (l->GetClipRect()) {
+22 -8
View File
@@ -123,11 +123,22 @@ BasicLayerManager::PushGroupForLayer(gfxContext* aContext, Layer* aLayer, const
group.mMaskSurface = GetMaskForLayer(aLayer, &group.mMaskTransform);
return group;
}
aContext->Restore();
}
Matrix maskTransform;
RefPtr<SourceSurface> maskSurf = GetMaskForLayer(aLayer, &maskTransform);
if (maskSurf) {
// The returned transform will transform the mask to device space on the
// destination. Since the User->Device space transform will be applied
// to the mask by PopGroupAndBlend we need to adjust the transform to
// transform the mask to user space.
Matrix currentTransform = ToMatrix(group.mFinalTarget->CurrentMatrix());
currentTransform.Invert();
maskTransform = maskTransform * currentTransform;
}
if (aLayer->CanUseOpaqueSurface() &&
((didCompleteClip && aRegion.GetNumRects() == 1) ||
!aContext->CurrentMatrix().HasNonIntegerTranslation())) {
@@ -172,8 +183,12 @@ BasicLayerManager::PopGroupForLayer(PushedGroup &group)
RefPtr<SourceSurface> src = sourceDT->Snapshot();
if (group.mMaskSurface) {
dt->SetTransform(group.mMaskTransform * Matrix::Translation(-group.mFinalTarget->GetDeviceOffset()));
dt->MaskSurface(SurfacePattern(src, ExtendMode::CLAMP, Matrix::Translation(group.mGroupOffset.x, group.mGroupOffset.y)),
Point finalOffset = group.mFinalTarget->GetDeviceOffset();
dt->SetTransform(group.mMaskTransform * Matrix::Translation(-finalOffset));
Matrix surfTransform = group.mMaskTransform;
surfTransform.Invert();
dt->MaskSurface(SurfacePattern(src, ExtendMode::CLAMP, surfTransform *
Matrix::Translation(group.mGroupOffset.x, group.mGroupOffset.y)),
group.mMaskSurface, Point(0, 0), DrawOptions(group.mOpacity, group.mOperator));
} else {
// For now this is required since our group offset is in device space of the final target,
@@ -245,7 +260,7 @@ public:
// Set the opaque rect to match the bounds of the visible region.
void AnnotateOpaqueRect()
{
const nsIntRegion visibleRegion = mLayer->GetEffectiveVisibleRegion().ToUnknownRegion();
const nsIntRegion visibleRegion = mLayer->GetLocalVisibleRegion().ToUnknownRegion();
const IntRect& bounds = visibleRegion.GetBounds();
DrawTarget *dt = mTarget->GetDrawTarget();
@@ -432,7 +447,7 @@ MarkLayersHidden(Layer* aLayer, const IntRect& aClipRect,
return;
}
nsIntRegion region = aLayer->GetEffectiveVisibleRegion().ToUnknownRegion();
nsIntRegion region = aLayer->GetLocalVisibleRegion().ToUnknownRegion();
IntRect r = region.GetBounds();
TransformIntRect(r, transform, ToOutsideIntRect);
r.IntersectRect(r, aDirtyRect);
@@ -846,7 +861,6 @@ Transform3D(RefPtr<SourceSurface> aSource,
aDestRect.RoundOut();
// Create a surface the size of the transformed object.
RefPtr<gfxASurface> dest = aDest->CurrentSurface();
RefPtr<gfxImageSurface> destImage = new gfxImageSurface(IntSize(aDestRect.width,
aDestRect.height),
SurfaceFormat::A8R8G8B8_UINT32);
@@ -918,7 +932,7 @@ BasicLayerManager::FlushGroup(PaintLayerContext& aPaintContext, bool aNeedsClipT
if (!mTransactionIncomplete) {
if (aNeedsClipToVisibleRegion) {
gfxUtils::ClipToRegion(aPaintContext.mTarget,
aPaintContext.mLayer->GetEffectiveVisibleRegion().ToUnknownRegion());
aPaintContext.mLayer->GetLocalVisibleRegion().ToUnknownRegion());
}
CompositionOp op = GetEffectiveOperator(aPaintContext.mLayer);
@@ -1029,7 +1043,7 @@ BasicLayerManager::PaintLayer(gfxContext* aTarget,
paintLayerContext.Apply2DTransform();
const nsIntRegion visibleRegion = aLayer->GetEffectiveVisibleRegion().ToUnknownRegion();
const nsIntRegion visibleRegion = aLayer->GetLocalVisibleRegion().ToUnknownRegion();
// If needsGroup is true, we'll clip to the visible region after we've popped the group
if (needsClipToVisibleRegion && !needsGroup) {
gfxUtils::ClipToRegion(aTarget, visibleRegion);
@@ -1050,7 +1064,7 @@ BasicLayerManager::PaintLayer(gfxContext* aTarget,
if (is2D) {
if (needsGroup) {
PushedGroup pushedGroup =
PushGroupForLayer(aTarget, aLayer, aLayer->GetEffectiveVisibleRegion().ToUnknownRegion());
PushGroupForLayer(aTarget, aLayer, aLayer->GetLocalVisibleRegion().ToUnknownRegion());
PaintSelfOrChildren(paintLayerContext, pushedGroup.mGroupTarget);
PopGroupForLayer(pushedGroup);
} else {
+1 -1
View File
@@ -140,7 +140,7 @@ public:
struct PushedGroup
{
PushedGroup() : mFinalTarget(nullptr), mNeedsClipToVisibleRegion(false) {}
PushedGroup() : mFinalTarget(nullptr), mNeedsClipToVisibleRegion(false), mOperator(gfx::CompositionOp::OP_COUNT), mOpacity(0.0f){}
gfxContext* mFinalTarget;
RefPtr<gfxContext> mGroupTarget;
nsIntRegion mVisibleRegion;
+2 -2
View File
@@ -63,7 +63,7 @@ BasicPaintedLayer::PaintThebes(gfxContext* aContext,
mValidRegion.SetEmpty();
mContentClient->Clear();
nsIntRegion toDraw = IntersectWithClip(GetEffectiveVisibleRegion().ToUnknownRegion(), aContext);
nsIntRegion toDraw = IntersectWithClip(GetLocalVisibleRegion().ToUnknownRegion(), aContext);
RenderTraceInvalidateStart(this, "FFFF00", toDraw.GetBounds());
@@ -169,7 +169,7 @@ BasicPaintedLayer::Validate(LayerManager::DrawPaintedLayerCallback aCallback,
// from RGB to RGBA, because we might need to repaint with
// subpixel AA)
state.mRegionToInvalidate.And(state.mRegionToInvalidate,
GetEffectiveVisibleRegion().ToUnknownRegion());
GetLocalVisibleRegion().ToUnknownRegion());
SetAntialiasingFlags(this, target);
RenderTraceInvalidateStart(this, "FFFF00", state.mRegionToDraw.GetBounds());
+1 -1
View File
@@ -82,7 +82,7 @@ NeedsConvertFromYUVtoRGB565(int aHalFormat)
GrallocTextureHostBasic::GrallocTextureHostBasic(
TextureFlags aFlags,
const NewSurfaceDescriptorGralloc& aDescriptor)
const SurfaceDescriptorGralloc& aDescriptor)
: TextureHost(aFlags)
, mGrallocHandle(aDescriptor)
, mSize(0, 0)
+2 -2
View File
@@ -24,7 +24,7 @@ class GrallocTextureHostBasic : public TextureHost
{
public:
GrallocTextureHostBasic(TextureFlags aFlags,
const NewSurfaceDescriptorGralloc& aDescriptor);
const SurfaceDescriptorGralloc& aDescriptor);
virtual void SetCompositor(Compositor* aCompositor) override;
@@ -66,7 +66,7 @@ public:
protected:
RefPtr<BasicCompositor> mCompositor;
RefPtr<DataTextureSource> mTextureSource;
NewSurfaceDescriptorGralloc mGrallocHandle;
SurfaceDescriptorGralloc mGrallocHandle;
// gralloc buffer size.
gfx::IntSize mSize;
// Size reported by TextureClient, can be different in some cases (video?),
@@ -5,6 +5,7 @@
#include "MacIOSurfaceTextureHostBasic.h"
#include "mozilla/gfx/MacIOSurface.h"
#include "MacIOSurfaceHelpers.h"
namespace mozilla {
namespace layers {
@@ -33,7 +34,9 @@ MacIOSurfaceTextureSourceBasic::GetSize() const
gfx::SurfaceFormat
MacIOSurfaceTextureSourceBasic::GetFormat() const
{
return mSurface->HasAlpha() ? gfx::SurfaceFormat::R8G8B8A8 : gfx::SurfaceFormat::B8G8R8X8;
// Set the format the same way as CreateSourceSurfaceFromMacIOSurface.
return mSurface->GetFormat() == gfx::SurfaceFormat::NV12
? gfx::SurfaceFormat::B8G8R8X8 : gfx::SurfaceFormat::B8G8R8A8;
}
MacIOSurfaceTextureHostBasic::MacIOSurfaceTextureHostBasic(
@@ -51,7 +54,7 @@ gfx::SourceSurface*
MacIOSurfaceTextureSourceBasic::GetSurface(gfx::DrawTarget* aTarget)
{
if (!mSourceSurface) {
mSourceSurface = mSurface->GetAsSurface();
mSourceSurface = CreateSourceSurfaceFromMacIOSurface(mSurface);
}
return mSourceSurface;
}
@@ -31,6 +31,8 @@ public:
MacIOSurface* aSurface);
virtual ~MacIOSurfaceTextureSourceBasic();
virtual const char* Name() const override { return "MacIOSurfaceTextureSourceBasic"; }
virtual TextureSourceBasic* AsSourceBasic() override { return this; }
virtual gfx::IntSize GetSize() const override;
+3 -3
View File
@@ -30,9 +30,9 @@ CreateTextureHostBasic(const SurfaceDescriptor& aDesc,
}
#endif
#ifdef MOZ_WIDGET_GONK
if (aDesc.type() == SurfaceDescriptor::TNewSurfaceDescriptorGralloc) {
const NewSurfaceDescriptorGralloc& desc =
aDesc.get_NewSurfaceDescriptorGralloc();
if (aDesc.type() == SurfaceDescriptor::TSurfaceDescriptorGralloc) {
const SurfaceDescriptorGralloc& desc =
aDesc.get_SurfaceDescriptorGralloc();
return MakeAndAddRef<GrallocTextureHostBasic>(aFlags, desc);
}
#endif
+2
View File
@@ -22,6 +22,8 @@ class X11DataTextureSourceBasic : public DataTextureSource
public:
X11DataTextureSourceBasic() {};
virtual const char* Name() const override { return "X11DataTextureSourceBasic"; }
virtual bool Update(gfx::DataSourceSurface* aSurface,
nsIntRegion* aDestRegion = nullptr,
gfx::IntPoint* aSrcOffset = nullptr) override;
+2
View File
@@ -24,6 +24,8 @@ class X11TextureSourceBasic
public:
X11TextureSourceBasic(BasicCompositor* aCompositor, gfxXlibSurface* aSurface);
virtual const char* Name() const override { return "X11TextureSourceBasic"; }
virtual X11TextureSourceBasic* AsSourceBasic() override { return this; }
virtual gfx::IntSize GetSize() const override;
+1 -1
View File
@@ -75,7 +75,7 @@ ClientPaintedLayer::PaintThebes()
// from RGB to RGBA, because we might need to repaint with
// subpixel AA)
state.mRegionToInvalidate.And(state.mRegionToInvalidate,
GetEffectiveVisibleRegion().ToUnknownRegion());
GetLocalVisibleRegion().ToUnknownRegion());
bool didUpdate = false;
RotatedContentBuffer::DrawIterator iter;
+10 -1
View File
@@ -30,6 +30,7 @@
#include "nsISupportsImpl.h" // for Image::Release, etc
#include "nsRect.h" // for mozilla::gfx::IntRect
#include "mozilla/gfx/2D.h"
#include "ClientLayerManager.h"
#ifdef MOZ_WIDGET_GONK
#include "GrallocImages.h"
#endif
@@ -155,7 +156,15 @@ ImageClientSingle::UpdateImage(ImageContainer* aContainer, uint32_t aContentFlag
OverlayImage* overlayImage = static_cast<OverlayImage*>(image);
OverlaySource source;
if (overlayImage->GetSidebandStream().IsValid()) {
source.handle() = OverlayHandle(overlayImage->GetSidebandStream());
// Duplicate GonkNativeHandle::NhObj for ipc,
// since ParamTraits<GonkNativeHandle>::Write() absorbs native_handle_t.
RefPtr<GonkNativeHandle::NhObj> nhObj = overlayImage->GetSidebandStream().GetDupNhObj();
GonkNativeHandle handle(nhObj);
if (!handle.IsValid()) {
gfxWarning() << "ImageClientSingle::UpdateImage failed in GetDupNhObj";
return false;
}
source.handle() = OverlayHandle(handle);
} else {
source.handle() = OverlayHandle(overlayImage->GetOverlayId());
}
+8 -2
View File
@@ -373,8 +373,14 @@ public:
*/
already_AddRefed<gfx::DataSourceSurface> GetAsSurface() {
Lock(OpenMode::OPEN_READ);
RefPtr<gfx::SourceSurface> surf = BorrowDrawTarget()->Snapshot();
RefPtr<gfx::DataSourceSurface> data = surf->GetDataSurface();
RefPtr<gfx::DataSourceSurface> data;
RefPtr<gfx::DrawTarget> dt = BorrowDrawTarget();
if (dt) {
RefPtr<gfx::SourceSurface> surf = dt->Snapshot();
if (surf) {
data = surf->GetDataSurface();
}
}
Unlock();
return data.forget();
}
@@ -82,7 +82,7 @@ WalkTheTree(Layer* aLayer,
aHasRemote = true;
if (const CompositorParent::LayerTreeState* state = CompositorParent::GetIndirectShadowTree(ref->GetReferentId())) {
if (Layer* referent = state->mRoot) {
if (!ref->GetVisibleRegion().IsEmpty()) {
if (!ref->GetLocalVisibleRegion().IsEmpty()) {
dom::ScreenOrientationInternal chromeOrientation = aTargetConfig.orientation();
dom::ScreenOrientationInternal contentOrientation = state->mTargetConfig.orientation();
if (!IsSameDimension(chromeOrientation, contentOrientation) &&
@@ -690,7 +690,7 @@ AsyncCompositionManager::RecordShadowTransforms(Layer* aLayer)
if (!apzc) {
continue;
}
gfx::Matrix4x4 shadowTransform = aLayer->AsLayerComposite()->GetShadowTransform();
gfx::Matrix4x4 shadowTransform = aLayer->AsLayerComposite()->GetShadowBaseTransform();
if (!shadowTransform.Is2D()) {
continue;
}
@@ -1423,7 +1423,7 @@ AsyncCompositionManager::TransformShadowTree(TimeStamp aCurrentFrame,
LayerComposite* rootComposite = root->AsLayerComposite();
gfx::Matrix4x4 trans = rootComposite->GetShadowTransform();
gfx::Matrix4x4 trans = rootComposite->GetShadowBaseTransform();
trans *= gfx::Matrix4x4::From2D(mWorldTransform);
rootComposite->SetShadowTransform(trans);
@@ -97,7 +97,7 @@ static void DrawLayerInfo(const RenderTargetIntRect& aClipRect,
template<class ContainerT>
static gfx::IntRect ContainerVisibleRect(ContainerT* aContainer)
{
gfx::IntRect surfaceRect = aContainer->GetEffectiveVisibleRegion().ToUnknownRegion().GetBounds();
gfx::IntRect surfaceRect = aContainer->GetLocalVisibleRegion().ToUnknownRegion().GetBounds();
return surfaceRect;
}
@@ -109,12 +109,12 @@ static void PrintUniformityInfo(Layer* aLayer)
}
// Don't want to print a log for smaller layers
if (aLayer->GetEffectiveVisibleRegion().GetBounds().width < 300 ||
aLayer->GetEffectiveVisibleRegion().GetBounds().height < 300) {
if (aLayer->GetLocalVisibleRegion().GetBounds().width < 300 ||
aLayer->GetLocalVisibleRegion().GetBounds().height < 300) {
return;
}
Matrix4x4 transform = aLayer->AsLayerComposite()->GetShadowTransform();
Matrix4x4 transform = aLayer->AsLayerComposite()->GetShadowBaseTransform();
if (!transform.Is2D()) {
return;
}
@@ -237,7 +237,7 @@ ContainerRenderVR(ContainerT* aContainer,
IntRectToRect(static_cast<CanvasLayer*>(layer)->GetBounds());
} else {
layerBounds =
IntRectToRect(layer->GetEffectiveVisibleRegion().ToUnknownRegion().GetBounds());
IntRectToRect(layer->GetLocalVisibleRegion().ToUnknownRegion().GetBounds());
}
const gfx::Matrix4x4 childTransform = layer->GetEffectiveTransform();
layerBounds = childTransform.TransformBounds(layerBounds);
@@ -569,8 +569,8 @@ RenderLayers(ContainerT* aContainer,
if (layerToRender->HasLayerBeenComposited()) {
// Composer2D will compose this layer so skip GPU composition
// this time & reset composition flag for next composition phase
layerToRender->SetLayerComposited(false);
// this time. The flag will be reset for the next composition phase
// at the beginning of LayerManagerComposite::Rener().
gfx::IntRect clearRect = layerToRender->GetClearRect();
if (!clearRect.IsEmpty()) {
// Clear layer's visible rect on FrameBuffer with transparent pixels
@@ -630,7 +630,7 @@ CreateOrRecycleTarget(ContainerT* aContainer,
Compositor* compositor = aManager->GetCompositor();
SurfaceInitMode mode = INIT_MODE_CLEAR;
gfx::IntRect surfaceRect = ContainerVisibleRect(aContainer);
if (aContainer->GetEffectiveVisibleRegion().GetNumRects() == 1 &&
if (aContainer->GetLocalVisibleRegion().GetNumRects() == 1 &&
(aContainer->GetContentFlags() & Layer::CONTENT_OPAQUE))
{
mode = INIT_MODE_NONE;
@@ -655,7 +655,7 @@ CreateTemporaryTargetAndCopyFromBackground(ContainerT* aContainer,
LayerManagerComposite* aManager)
{
Compositor* compositor = aManager->GetCompositor();
gfx::IntRect visibleRect = aContainer->GetEffectiveVisibleRegion().ToUnknownRegion().GetBounds();
gfx::IntRect visibleRect = aContainer->GetLocalVisibleRegion().ToUnknownRegion().GetBounds();
RefPtr<CompositingRenderTarget> previousTarget = compositor->GetCurrentRenderTarget();
gfx::IntRect surfaceRect = gfx::IntRect(visibleRect.x, visibleRect.y,
visibleRect.width, visibleRect.height);
@@ -723,7 +723,7 @@ ContainerRender(ContainerT* aContainer,
return;
}
gfx::Rect visibleRect(aContainer->GetEffectiveVisibleRegion().ToUnknownRegion().GetBounds());
gfx::Rect visibleRect(aContainer->GetLocalVisibleRegion().ToUnknownRegion().GetBounds());
RefPtr<Compositor> compositor = aManager->GetCompositor();
#ifdef MOZ_DUMP_PAINTING
if (gfxEnv::DumpCompositorTextures()) {
+72 -7
View File
@@ -217,14 +217,54 @@ IntersectMaybeRects(const Maybe<RectType>& aRect1, const Maybe<RectType>& aRect2
return aRect2;
}
/**
* Get accumulated transform of from the context creating layer to the
* given layer.
*/
static Matrix4x4
GetAccTransformIn3DContext(Layer* aLayer) {
Matrix4x4 transform = aLayer->GetLocalTransform();
for (Layer* layer = aLayer->GetParent();
layer && layer->Extend3DContext();
layer = layer->GetParent()) {
transform = transform * layer->GetLocalTransform();
}
return transform;
}
void
LayerManagerComposite::PostProcessLayers(Layer* aLayer,
nsIntRegion& aOpaqueRegion,
LayerIntRegion& aVisibleRegion,
const Maybe<ParentLayerIntRect>& aClipFromAncestors)
{
if (aLayer->Extend3DContext()) {
// For layers participating 3D rendering context, their visible
// region should be empty (invisible), so we pass through them
// without doing anything.
// Direct children of the establisher may have a clip, becaue the
// item containing it; ex. of nsHTMLScrollFrame, may give it one.
Maybe<ParentLayerIntRect> layerClip =
aLayer->AsLayerComposite()->GetShadowClipRect();
Maybe<ParentLayerIntRect> ancestorClipForChildren =
IntersectMaybeRects(layerClip, aClipFromAncestors);
MOZ_ASSERT(!layerClip || !aLayer->Combines3DTransformWithAncestors(),
"Only direct children of the establisher could have a clip");
for (Layer* child = aLayer->GetLastChild();
child;
child = child->GetPrevSibling()) {
PostProcessLayers(child, aOpaqueRegion, aVisibleRegion,
ancestorClipForChildren);
}
return;
}
nsIntRegion localOpaque;
Matrix4x4 transform = aLayer->GetLocalTransform();
// Treat layers on the path to the root of the 3D rendering context as
// a giant layer if it is a leaf.
Matrix4x4 transform = GetAccTransformIn3DContext(aLayer);
Matrix transform2d;
Maybe<nsIntPoint> integerTranslation;
// If aLayer has a simple transform (only an integer translation) then we
@@ -242,6 +282,9 @@ LayerManagerComposite::PostProcessLayers(Layer* aLayer,
// from our ancestors.
LayerComposite* composite = aLayer->AsLayerComposite();
Maybe<ParentLayerIntRect> layerClip = composite->GetShadowClipRect();
MOZ_ASSERT(!layerClip || !aLayer->Combines3DTransformWithAncestors(),
"The layer with a clip should not participate "
"a 3D rendering context");
Maybe<ParentLayerIntRect> outsideClip =
IntersectMaybeRects(layerClip, aClipFromAncestors);
@@ -282,8 +325,12 @@ LayerManagerComposite::PostProcessLayers(Layer* aLayer,
// - They recalculate their visible regions, taking ancestorClipForChildren
// into account, and accumulate them into descendantsVisibleRegion.
LayerIntRegion descendantsVisibleRegion;
bool hasPreserve3DChild = false;
for (Layer* child = aLayer->GetLastChild(); child; child = child->GetPrevSibling()) {
PostProcessLayers(child, localOpaque, descendantsVisibleRegion, ancestorClipForChildren);
if (child->Extend3DContext()) {
hasPreserve3DChild = true;
}
}
// Recalculate our visible region.
@@ -291,7 +338,7 @@ LayerManagerComposite::PostProcessLayers(Layer* aLayer,
// If we have descendants, throw away the visible region stored on this
// layer, and use the region accumulated by our descendants instead.
if (aLayer->GetFirstChild()) {
if (aLayer->GetFirstChild() && !hasPreserve3DChild) {
visible = descendantsVisibleRegion;
}
@@ -422,11 +469,9 @@ LayerManagerComposite::UpdateAndRender()
mInvalidRegion.SetEmpty();
}
// Update cached layer tree information.
mClonedLayerTreeProperties = LayerProperties::CloneFrom(GetRoot());
if (invalid.IsEmpty() && !mWindowOverlayChanged) {
// Composition requested, but nothing has changed. Don't do any work.
mClonedLayerTreeProperties = LayerProperties::CloneFrom(GetRoot());
return;
}
@@ -450,6 +495,9 @@ LayerManagerComposite::UpdateAndRender()
#endif
mGeometryChanged = false;
mWindowOverlayChanged = false;
// Update cached layer tree information.
mClonedLayerTreeProperties = LayerProperties::CloneFrom(GetRoot());
}
already_AddRefed<DrawTarget>
@@ -757,6 +805,21 @@ LayerManagerComposite::PopGroupForLayerEffects(RefPtr<CompositingRenderTarget> a
Matrix4x4());
}
// Used to clear the 'mLayerComposited' flag at the beginning of each Render().
static void
ClearLayerFlags(Layer* aLayer) {
if (!aLayer) {
return;
}
if (aLayer->AsLayerComposite()) {
aLayer->AsLayerComposite()->SetLayerComposited(false);
}
for (Layer* child = aLayer->GetFirstChild(); child;
child = child->GetNextSibling()) {
ClearLayerFlags(child);
}
}
void
LayerManagerComposite::Render(const nsIntRegion& aInvalidRegion)
{
@@ -768,6 +831,8 @@ LayerManagerComposite::Render(const nsIntRegion& aInvalidRegion)
return;
}
ClearLayerFlags(mRoot);
// At this time, it doesn't really matter if these preferences change
// during the execution of the function; we should be safe in all
// permutations. However, may as well just get the values onces and
@@ -1038,7 +1103,7 @@ LayerManagerComposite::RenderToPresentationSurface()
EGLSurface surface = mirrorScreen->GetEGLSurface();
if (surface == LOCAL_EGL_NO_SURFACE) {
// Create GLContext
RefPtr<GLContext> gl = gl::GLContextProvider::CreateForWindow(mirrorScreenWidget);
RefPtr<GLContext> gl = gl::GLContextProvider::CreateForWindow(mirrorScreenWidget, false);
mirrorScreenWidget->SetNativeData(NS_NATIVE_OPENGL_CONTEXT,
reinterpret_cast<uintptr_t>(gl.get()));
surface = mirrorScreen->GetEGLSurface();
@@ -1185,7 +1250,7 @@ LayerManagerComposite::ComputeRenderIntegrityInternal(Layer* aLayer,
}
// See if there's any incomplete rendering
nsIntRegion incompleteRegion = aLayer->GetEffectiveVisibleRegion().ToUnknownRegion();
nsIntRegion incompleteRegion = aLayer->GetLocalVisibleRegion().ToUnknownRegion();
incompleteRegion.Sub(incompleteRegion, paintedLayer->GetValidRegion());
if (!incompleteRegion.IsEmpty()) {
+2 -2
View File
@@ -480,7 +480,7 @@ public:
float GetShadowOpacity() { return mShadowOpacity; }
const Maybe<ParentLayerIntRect>& GetShadowClipRect() { return mShadowClipRect; }
const LayerIntRegion& GetShadowVisibleRegion() { return mShadowVisibleRegion; }
const gfx::Matrix4x4& GetShadowTransform() { return mShadowTransform; }
const gfx::Matrix4x4& GetShadowBaseTransform() { return mShadowTransform; }
bool GetShadowTransformSetByAnimation() { return mShadowTransformSetByAnimation; }
bool HasLayerBeenComposited() { return mLayerComposited; }
gfx::IntRect GetClearRect() { return mClearRect; }
@@ -569,7 +569,7 @@ RenderWithAllMasks(Layer* aLayer, Compositor* aCompositor,
// into. The final mask gets rendered into the original render target.
// Calculate the size of the intermediate surfaces.
gfx::Rect visibleRect(aLayer->GetEffectiveVisibleRegion().ToUnknownRegion().GetBounds());
gfx::Rect visibleRect(aLayer->GetLocalVisibleRegion().ToUnknownRegion().GetBounds());
gfx::Matrix4x4 transform = aLayer->GetEffectiveTransform();
// TODO: Use RenderTargetIntRect and TransformBy here
gfx::IntRect surfaceRect =
@@ -112,7 +112,7 @@ PaintedLayerComposite::RenderLayer(const gfx::IntRect& aClipRect)
mBuffer->GetLayer() == this,
"buffer is corrupted");
const nsIntRegion visibleRegion = GetEffectiveVisibleRegion().ToUnknownRegion();
const nsIntRegion visibleRegion = GetLocalVisibleRegion().ToUnknownRegion();
#ifdef MOZ_DUMP_PAINTING
if (gfxEnv::DumpCompositorTextures()) {
+8 -1
View File
@@ -212,7 +212,7 @@ TextureHost::Create(const SurfaceDescriptor& aDesc,
case SurfaceDescriptor::TSurfaceDescriptorSharedGLTexture:
return CreateTextureHostOGL(aDesc, aDeallocator, aFlags);
case SurfaceDescriptor::TNewSurfaceDescriptorGralloc:
case SurfaceDescriptor::TSurfaceDescriptorGralloc:
case SurfaceDescriptor::TSurfaceDescriptorMacIOSurface:
if (aBackend == LayersBackend::LAYERS_OPENGL) {
return CreateTextureHostOGL(aDesc, aDeallocator, aFlags);
@@ -374,6 +374,13 @@ TextureSource::~TextureSource()
MOZ_COUNT_DTOR(TextureSource);
}
const char*
TextureSource::Name() const
{
MOZ_CRASH("TextureSource without class name");
return "TextureSource";
}
BufferTextureHost::BufferTextureHost(const BufferDescriptor& aDesc,
TextureFlags aFlags)
: TextureHost(aFlags)
+6
View File
@@ -88,6 +88,8 @@ public:
virtual ~TextureSource();
virtual const char* Name() const = 0;
/**
* Should be overridden in order to deallocate the data that is associated
* with the rendering backend, such as GL textures.
@@ -233,6 +235,8 @@ public:
: mUpdateSerial(0)
{}
virtual const char* Name() const override { return "DataTextureSource"; }
virtual DataTextureSource* AsDataTextureSource() override { return this; }
/**
@@ -724,6 +728,8 @@ public:
{}
virtual ~CompositingRenderTarget() {}
virtual const char* Name() const override { return "CompositingRenderTarget"; }
#ifdef MOZ_DUMP_PAINTING
virtual already_AddRefed<gfx::DataSourceSurface> Dump(Compositor* aCompositor) { return nullptr; }
#endif
+2
View File
@@ -21,6 +21,8 @@ public:
// Called when the underlying X surface has been changed.
// Useful for determining whether to rebind a GLXPixmap to a texture.
virtual void Updated() = 0;
virtual const char* Name() const override { return "X11TextureSource"; }
};
// TextureHost for Xlib-backed TextureSources.
+3
View File
@@ -253,6 +253,7 @@ public:
virtual ~DataTextureSourceD3D11();
virtual const char* Name() const override { return "DataTextureSourceD3D11"; }
// DataTextureSource
@@ -408,6 +409,8 @@ public:
const gfx::IntPoint& aOrigin,
DXGI_FORMAT aFormatOverride = DXGI_FORMAT_UNKNOWN);
virtual const char* Name() const override { return "CompositingRenderTargetD3D11"; }
virtual TextureSourceD3D11* AsSourceD3D11() override { return this; }
void BindRenderTarget(ID3D11DeviceContext* aContext);
+4
View File
@@ -112,6 +112,8 @@ public:
virtual ~DataTextureSourceD3D9();
virtual const char* Name() const override { return "DataTextureSourceD3D9"; }
// DataTextureSource
virtual bool Update(gfx::DataSourceSurface* aSurface,
@@ -398,6 +400,8 @@ public:
const gfx::IntRect& aRect);
virtual ~CompositingRenderTargetD3D9();
virtual const char* Name() const override { return "CompositingRenderTargetD3D9"; }
virtual TextureSourceD3D9* AsSourceD3D9() override
{
MOZ_ASSERT(mTexture,
+179
View File
@@ -0,0 +1,179 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=4 ts=8 et tw=80 : */
/* 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 "mozilla/layers/APZChild.h"
#include "mozilla/dom/TabChild.h"
#include "mozilla/layers/APZCCallbackHelper.h"
namespace mozilla {
namespace layers {
/**
* There are cases where we try to create the APZChild before the corresponding
* TabChild has been created, we use an observer for the "tab-child-created"
* topic to set the TabChild in the APZChild when it has been created.
*/
class TabChildCreatedObserver : public nsIObserver
{
public:
TabChildCreatedObserver(APZChild* aAPZChild, const dom::TabId& aTabId)
: mAPZChild(aAPZChild),
mTabId(aTabId)
{}
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
private:
virtual ~TabChildCreatedObserver()
{}
// TabChildCreatedObserver is owned by mAPZChild, and mAPZChild outlives its
// TabChildCreatedObserver, so the raw pointer is fine.
APZChild* mAPZChild;
dom::TabId mTabId;
};
NS_IMPL_ISUPPORTS(TabChildCreatedObserver, nsIObserver)
NS_IMETHODIMP
TabChildCreatedObserver::Observe(nsISupports* aSubject,
const char* aTopic,
const char16_t* aData)
{
MOZ_ASSERT(strcmp(aTopic, "tab-child-created") == 0);
nsCOMPtr<nsITabChild> tabChild(do_QueryInterface(aSubject));
NS_ENSURE_TRUE(tabChild, NS_ERROR_FAILURE);
dom::TabChild* browser = static_cast<dom::TabChild*>(tabChild.get());
if (browser->GetTabId() == mTabId) {
mAPZChild->SetBrowser(browser);
}
return NS_OK;
}
APZChild*
APZChild::Create(const dom::TabId& aTabId)
{
RefPtr<dom::TabChild> browser = dom::TabChild::FindTabChild(aTabId);
nsAutoPtr<APZChild> apz(new APZChild);
if (browser) {
apz->SetBrowser(browser);
} else {
RefPtr<TabChildCreatedObserver> observer =
new TabChildCreatedObserver(apz, aTabId);
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
if (!os ||
NS_FAILED(os->AddObserver(observer, "tab-child-created", false))) {
return nullptr;
}
apz->SetObserver(observer);
}
return apz.forget();
}
APZChild::~APZChild()
{
if (mObserver) {
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
os->RemoveObserver(mObserver, "tab-child-created");
} else {
mBrowser->SetAPZChild(nullptr);
}
}
bool
APZChild::RecvUpdateFrame(const FrameMetrics& aFrameMetrics)
{
return mBrowser->UpdateFrame(aFrameMetrics);
}
bool
APZChild::RecvRequestFlingSnap(const FrameMetrics::ViewID& aScrollId,
const mozilla::CSSPoint& aDestination)
{
APZCCallbackHelper::RequestFlingSnap(aScrollId, aDestination);
return true;
}
bool
APZChild::RecvAcknowledgeScrollUpdate(const ViewID& aScrollId,
const uint32_t& aScrollGeneration)
{
APZCCallbackHelper::AcknowledgeScrollUpdate(aScrollId, aScrollGeneration);
return true;
}
bool
APZChild::RecvHandleDoubleTap(const CSSPoint& aPoint,
const Modifiers& aModifiers,
const ScrollableLayerGuid& aGuid)
{
mBrowser->HandleDoubleTap(aPoint, aModifiers, aGuid);
return true;
}
bool
APZChild::RecvHandleSingleTap(const CSSPoint& aPoint,
const Modifiers& aModifiers,
const ScrollableLayerGuid& aGuid,
const bool& aCallTakeFocusForClickFromTap)
{
mBrowser->HandleSingleTap(aPoint, aModifiers, aGuid,
aCallTakeFocusForClickFromTap);
return true;
}
bool
APZChild::RecvHandleLongTap(const CSSPoint& aPoint,
const Modifiers& aModifiers,
const ScrollableLayerGuid& aGuid,
const uint64_t& aInputBlockId)
{
mBrowser->HandleLongTap(aPoint, aModifiers, aGuid, aInputBlockId);
return true;
}
bool
APZChild::RecvNotifyAPZStateChange(const ViewID& aViewId,
const APZStateChange& aChange,
const int& aArg)
{
return mBrowser->NotifyAPZStateChange(aViewId, aChange, aArg);
}
bool
APZChild::RecvNotifyFlushComplete()
{
APZCCallbackHelper::NotifyFlushComplete();
return true;
}
void
APZChild::SetObserver(nsIObserver* aObserver)
{
MOZ_ASSERT(!mBrowser);
mObserver = aObserver;
}
void
APZChild::SetBrowser(dom::TabChild* aBrowser)
{
MOZ_ASSERT(!mBrowser);
if (mObserver) {
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
os->RemoveObserver(mObserver, "tab-child-created");
mObserver = nullptr;
}
mBrowser = aBrowser;
mBrowser->SetAPZChild(this);
}
} // namespace layers
} // namespace mozilla
+72
View File
@@ -0,0 +1,72 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=4 ts=8 et tw=80 : */
/* 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_APZChild_h
#define mozilla_layers_APZChild_h
#include "mozilla/layers/PAPZChild.h"
class nsIObserver;
namespace mozilla {
namespace dom {
class TabChild;
} // namespace dom
namespace layers {
class APZChild final : public PAPZChild
{
public:
static APZChild* Create(const dom::TabId& aTabId);
~APZChild();
virtual bool RecvUpdateFrame(const FrameMetrics& frame) override;
virtual bool RecvRequestFlingSnap(const ViewID& aScrollID,
const CSSPoint& aDestination) override;
virtual bool RecvAcknowledgeScrollUpdate(const ViewID& aScrollId,
const uint32_t& aScrollGeneration) override;
virtual bool RecvHandleDoubleTap(const CSSPoint& aPoint,
const Modifiers& aModifiers,
const ScrollableLayerGuid& aGuid) override;
virtual bool RecvHandleSingleTap(const CSSPoint& aPoint,
const Modifiers& aModifiers,
const ScrollableLayerGuid& aGuid,
const bool& aCallTakeFocusForClickFromTap) override;
virtual bool RecvHandleLongTap(const CSSPoint& aPoint,
const Modifiers& aModifiers,
const ScrollableLayerGuid& aGuid,
const uint64_t& aInputBlockId) override;
virtual bool RecvNotifyAPZStateChange(const ViewID& aViewId,
const APZStateChange& aChange,
const int& aArg) override;
virtual bool RecvNotifyFlushComplete() override;
void SetBrowser(dom::TabChild* aBrowser);
private:
APZChild() {};
void SetObserver(nsIObserver* aObserver);
RefPtr<dom::TabChild> mBrowser;
RefPtr<nsIObserver> mObserver;
};
} // namespace layers
} // namespace mozilla
#endif // mozilla_layers_APZChild_h
+136 -9
View File
@@ -25,6 +25,7 @@
#include "mozilla/AutoRestore.h" // for AutoRestore
#include "mozilla/ClearOnShutdown.h" // for ClearOnShutdown
#include "mozilla/DebugOnly.h" // for DebugOnly
#include "mozilla/dom/ContentParent.h"
#include "mozilla/gfx/2D.h" // for DrawTarget
#include "mozilla/gfx/Point.h" // for IntSize
#include "mozilla/gfx/Rect.h" // for IntSize
@@ -43,7 +44,9 @@
#include "mozilla/layers/LayerManagerComposite.h"
#include "mozilla/layers/LayersTypes.h"
#include "mozilla/layers/PLayerTransactionParent.h"
#include "mozilla/layers/RemoteContentController.h"
#include "mozilla/layers/ShadowLayersManager.h" // for ShadowLayersManager
#include "mozilla/layout/RenderFrameParent.h"
#include "mozilla/media/MediaSystemResourceService.h" // for MediaSystemResourceService
#include "mozilla/mozalloc.h" // for operator new, etc
#include "mozilla/Telemetry.h"
@@ -75,6 +78,11 @@
#ifdef MOZ_WIDGET_GONK
#include "GeckoTouchDispatcher.h"
#include "nsScreenManagerGonk.h"
#endif
#ifdef MOZ_ANDROID_APZ
#include "AndroidBridge.h"
#endif
#include "LayerScope.h"
@@ -286,13 +294,20 @@ CompositorVsyncScheduler::Observer::Destroy()
CompositorVsyncScheduler::CompositorVsyncScheduler(CompositorParent* aCompositorParent, nsIWidget* aWidget)
: mCompositorParent(aCompositorParent)
, mLastCompose(TimeStamp::Now())
, mCurrentCompositeTask(nullptr)
, mIsObservingVsync(false)
, mNeedsComposite(0)
, mVsyncNotificationsSkipped(0)
, mCurrentCompositeTaskMonitor("CurrentCompositeTaskMonitor")
, mCurrentCompositeTask(nullptr)
, mSetNeedsCompositeMonitor("SetNeedsCompositeMonitor")
, mSetNeedsCompositeTask(nullptr)
#ifdef MOZ_WIDGET_GONK
#if ANDROID_VERSION >= 19
, mDisplayEnabled(false)
, mSetDisplayMonitor("SetDisplayMonitor")
, mSetDisplayTask(nullptr)
#endif
#endif
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aWidget != nullptr);
@@ -300,6 +315,11 @@ CompositorVsyncScheduler::CompositorVsyncScheduler(CompositorParent* aCompositor
mCompositorVsyncDispatcher = aWidget->GetCompositorVsyncDispatcher();
#ifdef MOZ_WIDGET_GONK
GeckoTouchDispatcher::GetInstance()->SetCompositorVsyncScheduler(this);
#if ANDROID_VERSION >= 19
RefPtr<nsScreenManagerGonk> screenManager = nsScreenManagerGonk::GetInstance();
screenManager->SetCompositorVsyncScheduler(this);
#endif
#endif
// mAsapScheduling is set on the main thread during init,
@@ -317,6 +337,54 @@ CompositorVsyncScheduler::~CompositorVsyncScheduler()
mCompositorVsyncDispatcher = nullptr;
}
#ifdef MOZ_WIDGET_GONK
#if ANDROID_VERSION >= 19
void
CompositorVsyncScheduler::SetDisplay(bool aDisplayEnable)
{
// SetDisplay() is usually called from nsScreenManager at main thread. Post
// to compositor thread if needs.
if (!CompositorParent::IsInCompositorThread()) {
MOZ_ASSERT(NS_IsMainThread());
MonitorAutoLock lock(mSetDisplayMonitor);
mSetDisplayTask = NewRunnableMethod(this,
&CompositorVsyncScheduler::SetDisplay,
aDisplayEnable);
ScheduleTask(mSetDisplayTask, 0);
return;
} else {
MonitorAutoLock lock(mSetDisplayMonitor);
mSetDisplayTask = nullptr;
}
if (mDisplayEnabled == aDisplayEnable) {
return;
}
mDisplayEnabled = aDisplayEnable;
if (!mDisplayEnabled) {
CancelCurrentSetNeedsCompositeTask();
CancelCurrentCompositeTask();
}
}
void
CompositorVsyncScheduler::CancelSetDisplayTask()
{
MOZ_ASSERT(CompositorParent::IsInCompositorThread());
MonitorAutoLock lock(mSetDisplayMonitor);
if (mSetDisplayTask) {
mSetDisplayTask->Cancel();
mSetDisplayTask = nullptr;
}
// CancelSetDisplayTask is only be called in clean-up process, so
// mDisplayEnabled could be false there.
mDisplayEnabled = false;
}
#endif //ANDROID_VERSION >= 19
#endif //MOZ_WIDGET_GONK
void
CompositorVsyncScheduler::Destroy()
{
@@ -324,6 +392,12 @@ CompositorVsyncScheduler::Destroy()
UnobserveVsync();
mVsyncObserver->Destroy();
mVsyncObserver = nullptr;
#ifdef MOZ_WIDGET_GONK
#if ANDROID_VERSION >= 19
CancelSetDisplayTask();
#endif
#endif
CancelCurrentSetNeedsCompositeTask();
CancelCurrentCompositeTask();
}
@@ -396,6 +470,15 @@ CompositorVsyncScheduler::SetNeedsComposite()
mSetNeedsCompositeTask = nullptr;
}
#ifdef MOZ_WIDGET_GONK
#if ANDROID_VERSION >= 19
// Skip composition when display off.
if (!mDisplayEnabled) {
return;
}
#endif
#endif
mNeedsComposite++;
if (!mIsObservingVsync && mNeedsComposite) {
ObserveVsync();
@@ -588,6 +671,7 @@ CompositorParent::CompositorParent(nsIWidget* aWidget,
, mLastPluginUpdateLayerTreeId(0)
, mPluginUpdateResponsePending(false)
, mDeferPluginWindows(false)
, mPluginWindowsHidden(false)
#endif
{
MOZ_ASSERT(NS_IsMainThread());
@@ -801,7 +885,7 @@ CompositorParent::Invalidate()
{
if (mLayerManager && mLayerManager->GetRoot()) {
mLayerManager->AddInvalidRegion(
mLayerManager->GetRoot()->GetVisibleRegion().ToUnknownRegion().GetBounds());
mLayerManager->GetRoot()->GetLocalVisibleRegion().ToUnknownRegion().GetBounds());
}
}
@@ -1568,23 +1652,57 @@ CompositorParent::RecvNotifyChildCreated(const uint64_t& child)
}
void
CompositorParent::NotifyChildCreated(const uint64_t& aChild)
CompositorParent::NotifyChildCreated(uint64_t aChild)
{
sIndirectLayerTreesLock->AssertCurrentThreadOwns();
sIndirectLayerTrees[aChild].mParent = this;
sIndirectLayerTrees[aChild].mLayerManager = mLayerManager;
}
/* static */ bool
CompositorParent::UpdateRemoteContentController(uint64_t aLayersId,
dom::ContentParent* aContent,
const dom::TabId& aTabId,
dom::TabParent* aTopLevel)
{
MOZ_ASSERT(NS_IsMainThread());
MonitorAutoLock lock(*sIndirectLayerTreesLock);
LayerTreeState& state = sIndirectLayerTrees[aLayersId];
// RemoteContentController needs to know the layers id and the top level
// TabParent, so we pass that to its constructor here and then set up the
// PAPZ protocol by calling SendPAPZConstructor (and pass in the tab id for
// the PBrowser that it corresponds to).
RefPtr<RemoteContentController> controller =
new RemoteContentController(aLayersId, aTopLevel);
if (!aContent->SendPAPZConstructor(controller, aTabId)) {
return false;
}
state.mController = controller;
return true;
}
bool
CompositorParent::RecvAdoptChild(const uint64_t& child)
{
MonitorAutoLock lock(*sIndirectLayerTreesLock);
NotifyChildCreated(child);
if (sIndirectLayerTrees[child].mLayerTree) {
sIndirectLayerTrees[child].mLayerTree->mLayerManager = mLayerManager;
RefPtr<GeckoContentController> controller;
{
MonitorAutoLock lock(*sIndirectLayerTreesLock);
NotifyChildCreated(child);
if (sIndirectLayerTrees[child].mLayerTree) {
sIndirectLayerTrees[child].mLayerTree->mLayerManager = mLayerManager;
}
if (sIndirectLayerTrees[child].mRoot) {
sIndirectLayerTrees[child].mRoot->AsLayerComposite()->SetLayerManager(mLayerManager);
}
controller = sIndirectLayerTrees[child].mController;
}
if (sIndirectLayerTrees[child].mRoot) {
sIndirectLayerTrees[child].mRoot->AsLayerComposite()->SetLayerManager(mLayerManager);
// Calling ChildAdopted on controller will acquire a lock, to avoid a
// potential deadlock between that lock and sIndirectLayerTreesLock we
// release sIndirectLayerTreesLock first before calling ChildAdopted.
if (mApzcTreeManager && controller) {
controller->ChildAdopted();
}
return true;
}
@@ -2134,6 +2252,14 @@ CompositorParent::UpdatePluginWindowState(uint64_t aId)
return false;
}
// If the plugin windows were hidden but now are not, we need to force
// update the metrics to make sure they are visible again.
if (mPluginWindowsHidden) {
PLUGINS_LOG("[%" PRIu64 "] re-showing", aId);
mPluginWindowsHidden = false;
pluginMetricsChanged = true;
}
if (!lts.mPluginData.Length()) {
// We will pass through here in cases where the previous shadow layer
// tree contained visible plugins and the new tree does not. All we need
@@ -2224,6 +2350,7 @@ CompositorParent::HideAllPluginWindows()
}
mDeferPluginWindows = true;
mPluginUpdateResponsePending = true;
mPluginWindowsHidden = true;
Unused << SendHideAllPlugins((uintptr_t)GetWidget());
ScheduleComposition();
}
+51 -4
View File
@@ -25,6 +25,7 @@
#include "mozilla/Monitor.h" // for Monitor
#include "mozilla/RefPtr.h" // for RefPtr
#include "mozilla/TimeStamp.h" // for TimeStamp
#include "mozilla/dom/ipc/IdType.h"
#include "mozilla/gfx/Point.h" // for IntSize
#include "mozilla/ipc/ProtocolUtils.h"
#include "mozilla/layers/GeckoContentController.h"
@@ -54,6 +55,7 @@ class Compositor;
class CompositorParent;
class LayerManagerComposite;
class LayerTransactionParent;
class PAPZParent;
struct ScopedLayerTreeRegistration
{
@@ -100,6 +102,20 @@ class CompositorVsyncScheduler
public:
explicit CompositorVsyncScheduler(CompositorParent* aCompositorParent, nsIWidget* aWidget);
#ifdef MOZ_WIDGET_GONK
// emulator-ics never trigger the display on/off, so compositor will always
// skip composition request at that device. Only check the display status
// with kk device and upon.
#if ANDROID_VERSION >= 19
// SetDisplay() and CancelSetDisplayTask() are used for the display on/off.
// It will clear all composition related task and flag, and skip another
// composition task during the display off. That could prevent the problem
// that compositor might show the old content at the first frame of display on.
void SetDisplay(bool aDisplayEnable);
#endif
#endif
bool NotifyVsync(TimeStamp aVsyncTimestamp);
void SetNeedsComposite();
void OnForceComposeToTarget();
@@ -126,7 +142,7 @@ public:
return mExpectedComposeStartTime;
}
#endif
private:
virtual ~CompositorVsyncScheduler();
@@ -136,6 +152,11 @@ private:
void DispatchTouchEvents(TimeStamp aVsyncTimestamp);
void DispatchVREvents(TimeStamp aVsyncTimestamp);
void CancelCurrentSetNeedsCompositeTask();
#ifdef MOZ_WIDGET_GONK
#if ANDROID_VERSION >= 19
void CancelSetDisplayTask();
#endif
#endif
class Observer final : public VsyncObserver
{
@@ -153,7 +174,6 @@ private:
CompositorParent* mCompositorParent;
TimeStamp mLastCompose;
CancelableTask* mCurrentCompositeTask;
#ifdef COMPOSITOR_PERFORMANCE_WARNING
TimeStamp mExpectedComposeStartTime;
@@ -167,9 +187,18 @@ private:
RefPtr<CompositorVsyncScheduler::Observer> mVsyncObserver;
mozilla::Monitor mCurrentCompositeTaskMonitor;
CancelableTask* mCurrentCompositeTask;
mozilla::Monitor mSetNeedsCompositeMonitor;
CancelableTask* mSetNeedsCompositeTask;
#ifdef MOZ_WIDGET_GONK
#if ANDROID_VERSION >= 19
bool mDisplayEnabled;
mozilla::Monitor mSetDisplayMonitor;
CancelableTask* mSetDisplayTask;
#endif
#endif
};
class CompositorUpdateObserver
@@ -256,7 +285,7 @@ public:
static void SetShadowProperties(Layer* aLayer);
void NotifyChildCreated(const uint64_t& aChild);
void NotifyChildCreated(uint64_t aChild);
void AsyncRender();
@@ -418,6 +447,22 @@ public:
nsIWidget* GetWidget() { return mWidget; }
void ForceComposeToTarget(gfx::DrawTarget* aTarget, const gfx::IntRect* aRect = nullptr);
/**
* Creates a new RemoteContentController for aTabId. Should only be called on
* the main thread.
*
* aLayersId The layers id for the browser corresponding to aTabId.
* aContentParent The ContentParent for the process that the TabChild for
* aTabId lives in.
* aBrowserParent The toplevel TabParent for aTabId.
*/
static bool UpdateRemoteContentController(uint64_t aLayersId,
dom::ContentParent* aContentParent,
const dom::TabId& aTabId,
dom::TabParent* aBrowserParent);
protected:
// Protected destructor, to discourage deletion outside of Release():
virtual ~CompositorParent();
@@ -432,7 +477,6 @@ protected:
virtual bool DeallocPLayerTransactionParent(PLayerTransactionParent* aLayers) override;
virtual void ScheduleTask(CancelableTask*, int);
void CompositeToTarget(gfx::DrawTarget* aTarget, const gfx::IntRect* aRect = nullptr);
void ForceComposeToTarget(gfx::DrawTarget* aTarget, const gfx::IntRect* aRect = nullptr);
void SetEGLSurfaceSize(int width, int height);
@@ -501,6 +545,9 @@ protected:
// indicates if plugin window visibility and metric updates are currently
// being defered due to a scroll operation.
bool mDeferPluginWindows;
// indicates if the plugin windows were hidden, and need to be made
// visible again even if their geometry has not changed.
bool mPluginWindowsHidden;
#endif
DISALLOW_EVIL_CONSTRUCTORS(CompositorParent);
+1 -1
View File
@@ -725,7 +725,7 @@ LayerTransactionParent::RecvGetAnimationTransform(PLayerParent* aParent,
// from the shadow transform by undoing the translations in
// AsyncCompositionManager::SampleValue.
Matrix4x4 transform = layer->AsLayerComposite()->GetShadowTransform();
Matrix4x4 transform = layer->AsLayerComposite()->GetShadowBaseTransform();
if (ContainerLayer* c = layer->AsContainerLayer()) {
// Undo the scale transform applied by AsyncCompositionManager::SampleValue
transform.PostScale(1.0f/c->GetInheritedXScale(),
+2 -2
View File
@@ -93,7 +93,7 @@ struct SurfaceDescriptorSharedGLTexture {
bool hasAlpha;
};
struct NewSurfaceDescriptorGralloc {
struct SurfaceDescriptorGralloc {
MaybeMagicGrallocBufferHandle buffer;
bool isOpaque;
};
@@ -138,7 +138,7 @@ union SurfaceDescriptor {
SurfaceTextureDescriptor;
EGLImageDescriptor;
SurfaceDescriptorMacIOSurface;
NewSurfaceDescriptorGralloc;
SurfaceDescriptorGralloc;
SurfaceDescriptorSharedGLTexture;
null_t;
};
+104
View File
@@ -0,0 +1,104 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: sw=2 ts=8 et :
*/
/* 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 "mozilla/GfxMessageUtils.h";
include protocol PContent;
using mozilla::CSSPoint from "Units.h";
using CSSRect from "Units.h";
using struct mozilla::layers::FrameMetrics from "FrameMetrics.h";
using struct mozilla::layers::ScrollableLayerGuid from "FrameMetrics.h";
using mozilla::layers::FrameMetrics::ViewID from "FrameMetrics.h";
using mozilla::layers::MaybeZoomConstraints from "FrameMetrics.h";
using mozilla::layers::TouchBehaviorFlags from "mozilla/layers/APZUtils.h";
using mozilla::layers::GeckoContentController::APZStateChange from "mozilla/layers/GeckoContentController.h";
using mozilla::dom::TabId from "mozilla/dom/ipc/IdType.h";
using mozilla::dom::ContentParentId from "mozilla/dom/ipc/IdType.h";
using mozilla::layers::AsyncDragMetrics from "mozilla/layers/AsyncDragMetrics.h";
using mozilla::Modifiers from "mozilla/EventForwards.h";
using class nsRegion from "nsRegion.h";
namespace mozilla {
namespace layers {
/**
* If APZ is enabled then one PAPZ will be opened per PBrowser between the
* process where the PBrowser child actor lives and the main process (the
* PBrowser parent actor doesn't necessarily live in the main process, for
* example with nested browsers). This will typically be set up when the layers
* id is allocated for the PBrowser.
*
* Opened through PContent and runs on the main thread in both parent and child.
*/
sync protocol PAPZ
{
manager PContent;
parent:
async UpdateHitRegion(nsRegion aRegion);
/**
* Instructs the TabParent to forward a request to zoom to a rect given in
* CSS pixels. This rect is relative to the document.
*/
async ZoomToRect(uint32_t aPresShellId, ViewID aViewId, CSSRect aRect, uint32_t aFlags);
/**
* We know for sure that content has either preventDefaulted or not
* preventDefaulted. This applies to an entire batch of touch events. It is
* expected that, if there are any DOM touch listeners, touch events will be
* batched and only processed for panning and zooming if content does not
* preventDefault.
*/
async ContentReceivedInputBlock(ScrollableLayerGuid aGuid, uint64_t aInputBlockId, bool aPreventDefault);
/**
* Notifies the APZ code of the results of the gecko hit-test for a
* particular input block. Each target corresponds to one touch point in the
* touch event.
*/
async SetTargetAPZC(uint64_t aInputBlockId, ScrollableLayerGuid[] aTargets);
// Start an APZ drag on a scrollbar
async StartScrollbarDrag(AsyncDragMetrics aDragMetrics);
/**
* Notifies the APZ code of the allowed touch-behaviours for a particular
* input block. Each item in the aFlags array corresponds to one touch point
* in the touch event.
*/
async SetAllowedTouchBehavior(uint64_t aInputBlockId, TouchBehaviorFlags[] aFlags);
/**
* Updates the zoom constraints for a scrollable frame in this tab.
* The zoom controller code lives on the parent side and so this allows it to
* have up-to-date zoom constraints.
*/
async UpdateZoomConstraints(uint32_t aPresShellId, ViewID aViewId,
MaybeZoomConstraints aConstraints);
child:
async UpdateFrame(FrameMetrics frame);
// The following methods correspond to functions on the GeckoContentController
// interface in gfx/layers/apz/public/GeckoContentController.h. Refer to documentation
// in that file for these functions.
async RequestFlingSnap(ViewID aScrollID, CSSPoint aDestination);
async AcknowledgeScrollUpdate(ViewID aScrollId, uint32_t aScrollGeneration);
async HandleDoubleTap(CSSPoint aPoint, Modifiers aModifiers, ScrollableLayerGuid aGuid);
async HandleSingleTap(CSSPoint aPoint, Modifiers aModifiers, ScrollableLayerGuid aGuid, bool aCallTakeFocusForClickFromTap);
async HandleLongTap(CSSPoint point, Modifiers aModifiers, ScrollableLayerGuid aGuid, uint64_t aInputBlockId);
async NotifyAPZStateChange(ViewID aViewId, APZStateChange aChange, int aArg);
async NotifyFlushComplete();
async __delete__();
};
} // layers
} // mozilla
+3 -1
View File
@@ -7,16 +7,18 @@
include LayersSurfaces;
include LayersMessages;
include protocol PBrowser;
include protocol PLayer;
include protocol PLayerTransaction;
include "mozilla/GfxMessageUtils.h";
include "nsRegion.h";
using struct mozilla::null_t from "ipc/IPCMessageUtils.h";
using struct mozilla::layers::TextureFactoryIdentifier from "mozilla/layers/CompositorTypes.h";
using struct mozilla::layers::FrameMetrics from "FrameMetrics.h";
using mozilla::layers::FrameMetrics::ViewID from "FrameMetrics.h";
using mozilla::layers::MaybeZoomConstraints from "FrameMetrics.h";
using mozilla::layers::LayersBackend from "mozilla/layers/LayersTypes.h";
using mozilla::layers::TouchBehaviorFlags from "mozilla/layers/APZUtils.h";
using mozilla::CrossProcessMutexHandle from "mozilla/ipc/CrossProcessMutex.h";
using mozilla::ipc::SharedMemoryBasic::Handle from "mozilla/ipc/SharedMemoryBasic.h";
using mozilla::LayoutDeviceIntPoint from "Units.h";
+384
View File
@@ -0,0 +1,384 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: sw=2 ts=8 et :
*/
/* 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 "mozilla/layers/RemoteContentController.h"
#include "base/message_loop.h"
#include "base/task.h"
#include "MainThreadUtils.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/TabParent.h"
#include "mozilla/layers/APZCTreeManager.h"
#include "mozilla/layers/APZThreadUtils.h"
#include "mozilla/layers/CompositorParent.h"
#include "mozilla/layout/RenderFrameParent.h"
#include "mozilla/unused.h"
#include "Units.h"
#ifdef MOZ_WIDGET_ANDROID
#include "AndroidBridge.h"
#endif
namespace mozilla {
namespace layers {
RemoteContentController::RemoteContentController(uint64_t aLayersId,
dom::TabParent* aBrowserParent)
: mUILoop(MessageLoop::current())
, mLayersId(aLayersId)
, mBrowserParent(aBrowserParent)
, mMutex("RemoteContentController")
{
MOZ_ASSERT(NS_IsMainThread());
}
RemoteContentController::~RemoteContentController()
{
if (mBrowserParent) {
Unused << PAPZParent::Send__delete__(this);
}
}
void
RemoteContentController::RequestContentRepaint(const FrameMetrics& aFrameMetrics)
{
MOZ_ASSERT(NS_IsMainThread());
if (CanSend()) {
Unused << SendUpdateFrame(aFrameMetrics);
}
}
void
RemoteContentController::RequestFlingSnap(const FrameMetrics::ViewID& aScrollId,
const mozilla::CSSPoint& aDestination)
{
if (MessageLoop::current() != mUILoop) {
// We have to send this message from the "UI thread" (main
// thread).
mUILoop->PostTask(
FROM_HERE,
NewRunnableMethod(this, &RemoteContentController::RequestFlingSnap,
aScrollId, aDestination));
return;
}
if (CanSend()) {
Unused << SendRequestFlingSnap(aScrollId, aDestination);
}
}
void
RemoteContentController::AcknowledgeScrollUpdate(const FrameMetrics::ViewID& aScrollId,
const uint32_t& aScrollGeneration)
{
if (MessageLoop::current() != mUILoop) {
// We have to send this message from the "UI thread" (main
// thread).
mUILoop->PostTask(
FROM_HERE,
NewRunnableMethod(this, &RemoteContentController::AcknowledgeScrollUpdate,
aScrollId, aScrollGeneration));
return;
}
if (CanSend()) {
Unused << SendAcknowledgeScrollUpdate(aScrollId, aScrollGeneration);
}
}
void
RemoteContentController::HandleDoubleTap(const CSSPoint& aPoint,
Modifiers aModifiers,
const ScrollableLayerGuid& aGuid)
{
if (MessageLoop::current() != mUILoop) {
// We have to send this message from the "UI thread" (main
// thread).
mUILoop->PostTask(
FROM_HERE,
NewRunnableMethod(this, &RemoteContentController::HandleDoubleTap,
aPoint, aModifiers, aGuid));
return;
}
if (CanSend()) {
Unused << SendHandleDoubleTap(aPoint, aModifiers, aGuid);
}
}
void
RemoteContentController::HandleSingleTap(const CSSPoint& aPoint,
Modifiers aModifiers,
const ScrollableLayerGuid& aGuid)
{
if (MessageLoop::current() != mUILoop) {
// We have to send this message from the "UI thread" (main
// thread).
mUILoop->PostTask(
FROM_HERE,
NewRunnableMethod(this, &RemoteContentController::HandleSingleTap,
aPoint, aModifiers, aGuid));
return;
}
bool callTakeFocusForClickFromTap;
layout::RenderFrameParent* frame;
if (mBrowserParent && (frame = mBrowserParent->GetRenderFrame()) &&
mLayersId == frame->GetLayersId()) {
// Avoid going over IPC and back for calling TakeFocusForClickFromTap,
// since the right RenderFrameParent is living in this process.
frame->TakeFocusForClickFromTap();
callTakeFocusForClickFromTap = false;
} else {
callTakeFocusForClickFromTap = true;
}
if (CanSend()) {
Unused << SendHandleSingleTap(aPoint, aModifiers, aGuid,
callTakeFocusForClickFromTap);
}
}
void
RemoteContentController::HandleLongTap(const CSSPoint& aPoint,
Modifiers aModifiers,
const ScrollableLayerGuid& aGuid,
uint64_t aInputBlockId)
{
if (MessageLoop::current() != mUILoop) {
// We have to send this message from the "UI thread" (main
// thread).
mUILoop->PostTask(
FROM_HERE,
NewRunnableMethod(this, &RemoteContentController::HandleLongTap,
aPoint, aModifiers, aGuid, aInputBlockId));
return;
}
if (CanSend()) {
Unused << SendHandleLongTap(aPoint, aModifiers, aGuid, aInputBlockId);
}
}
void
RemoteContentController::PostDelayedTask(Task* aTask, int aDelayMs)
{
#ifdef MOZ_ANDROID_APZ
AndroidBridge::Bridge()->PostTaskToUiThread(aTask, aDelayMs);
#else
(MessageLoop::current() ? MessageLoop::current() : mUILoop)->
PostDelayedTask(FROM_HERE, aTask, aDelayMs);
#endif
}
bool
RemoteContentController::GetTouchSensitiveRegion(CSSRect* aOutRegion)
{
MutexAutoLock lock(mMutex);
if (mTouchSensitiveRegion.IsEmpty()) {
return false;
}
*aOutRegion = CSSRect::FromAppUnits(mTouchSensitiveRegion.GetBounds());
return true;
}
void
RemoteContentController::NotifyAPZStateChange(const ScrollableLayerGuid& aGuid,
APZStateChange aChange,
int aArg)
{
if (MessageLoop::current() != mUILoop) {
mUILoop->PostTask(
FROM_HERE,
NewRunnableMethod(this, &RemoteContentController::NotifyAPZStateChange,
aGuid, aChange, aArg));
return;
}
if (CanSend()) {
Unused << SendNotifyAPZStateChange(aGuid.mScrollId, aChange, aArg);
}
}
void
RemoteContentController::NotifyMozMouseScrollEvent(const FrameMetrics::ViewID& aScrollId,
const nsString& aEvent)
{
if (MessageLoop::current() != mUILoop) {
mUILoop->PostTask(
FROM_HERE,
NewRunnableMethod(this, &RemoteContentController::NotifyMozMouseScrollEvent,
aScrollId, aEvent));
return;
}
if (mBrowserParent) {
Unused << mBrowserParent->SendMouseScrollTestEvent(mLayersId, aScrollId, aEvent);
}
}
void
RemoteContentController::NotifyFlushComplete()
{
MOZ_ASSERT(NS_IsMainThread());
if (CanSend()) {
Unused << SendNotifyFlushComplete();
}
}
bool
RemoteContentController::RecvUpdateHitRegion(const nsRegion& aRegion)
{
MutexAutoLock lock(mMutex);
mTouchSensitiveRegion = aRegion;
return true;
}
bool
RemoteContentController::RecvZoomToRect(const uint32_t& aPresShellId,
const ViewID& aViewId,
const CSSRect& aRect,
const uint32_t& aFlags)
{
if (RefPtr<APZCTreeManager> apzcTreeManager = GetApzcTreeManager()) {
apzcTreeManager->ZoomToRect(ScrollableLayerGuid(mLayersId, aPresShellId, aViewId),
aRect, aFlags);
}
return true;
}
bool
RemoteContentController::RecvContentReceivedInputBlock(const ScrollableLayerGuid& aGuid,
const uint64_t& aInputBlockId,
const bool& aPreventDefault)
{
if (aGuid.mLayersId != mLayersId) {
// Guard against bad data from hijacked child processes
NS_ERROR("Unexpected layers id in RecvContentReceivedInputBlock; dropping message...");
return false;
}
if (RefPtr<APZCTreeManager> apzcTreeManager = GetApzcTreeManager()) {
APZThreadUtils::RunOnControllerThread(NewRunnableMethod(
apzcTreeManager.get(), &APZCTreeManager::ContentReceivedInputBlock,
aInputBlockId, aPreventDefault));
}
return true;
}
bool
RemoteContentController::RecvStartScrollbarDrag(const AsyncDragMetrics& aDragMetrics)
{
if (RefPtr<APZCTreeManager> apzcTreeManager = GetApzcTreeManager()) {
ScrollableLayerGuid guid(mLayersId, aDragMetrics.mPresShellId,
aDragMetrics.mViewId);
APZThreadUtils::RunOnControllerThread(
NewRunnableMethod(apzcTreeManager.get(),
&APZCTreeManager::StartScrollbarDrag,
guid, aDragMetrics));
}
return true;
}
bool
RemoteContentController::RecvSetTargetAPZC(const uint64_t& aInputBlockId,
nsTArray<ScrollableLayerGuid>&& aTargets)
{
for (size_t i = 0; i < aTargets.Length(); i++) {
if (aTargets[i].mLayersId != mLayersId) {
// Guard against bad data from hijacked child processes
NS_ERROR("Unexpected layers id in SetTargetAPZC; dropping message...");
return false;
}
}
if (RefPtr<APZCTreeManager> apzcTreeManager = GetApzcTreeManager()) {
// need a local var to disambiguate between the SetTargetAPZC overloads.
void (APZCTreeManager::*setTargetApzcFunc)(uint64_t, const nsTArray<ScrollableLayerGuid>&)
= &APZCTreeManager::SetTargetAPZC;
APZThreadUtils::RunOnControllerThread(NewRunnableMethod(
apzcTreeManager.get(), setTargetApzcFunc,
aInputBlockId, aTargets));
}
return true;
}
bool
RemoteContentController::RecvSetAllowedTouchBehavior(const uint64_t& aInputBlockId,
nsTArray<TouchBehaviorFlags>&& aFlags)
{
if (RefPtr<APZCTreeManager> apzcTreeManager = GetApzcTreeManager()) {
APZThreadUtils::RunOnControllerThread(NewRunnableMethod(
apzcTreeManager.get(), &APZCTreeManager::SetAllowedTouchBehavior,
aInputBlockId, Move(aFlags)));
}
return true;
}
bool
RemoteContentController::RecvUpdateZoomConstraints(const uint32_t& aPresShellId,
const ViewID& aViewId,
const MaybeZoomConstraints& aConstraints)
{
if (RefPtr<APZCTreeManager> apzcTreeManager = GetApzcTreeManager()) {
apzcTreeManager->UpdateZoomConstraints(ScrollableLayerGuid(mLayersId, aPresShellId, aViewId),
aConstraints);
}
return true;
}
void
RemoteContentController::ActorDestroy(ActorDestroyReason aWhy)
{
{
MutexAutoLock lock(mMutex);
mApzcTreeManager = nullptr;
}
mBrowserParent = nullptr;
}
// TODO: Remove once upgraded to GCC 4.8+ on linux. Calling a static member
// function (like PAPZParent::Send__delete__) in a lambda leads to a bogus
// error: "'this' was not captured for this lambda function".
//
// (see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51494)
static void
DeletePAPZParent(PAPZParent* aPAPZ)
{
Unused << PAPZParent::Send__delete__(aPAPZ);
}
void
RemoteContentController::Destroy()
{
RefPtr<RemoteContentController> controller = this;
NS_DispatchToMainThread(NS_NewRunnableFunction([controller] {
if (controller->CanSend()) {
DeletePAPZParent(controller);
}
}));
}
void
RemoteContentController::ChildAdopted()
{
// Clear the cached APZCTreeManager.
MutexAutoLock lock(mMutex);
mApzcTreeManager = nullptr;
}
already_AddRefed<APZCTreeManager>
RemoteContentController::GetApzcTreeManager()
{
// We can't get a ref to the APZCTreeManager until after the child is
// created and the static getter knows which CompositorParent is
// instantiated with this layers ID. That's why try to fetch it when
// we first need it and cache the result.
MutexAutoLock lock(mMutex);
if (!mApzcTreeManager) {
mApzcTreeManager = CompositorParent::GetAPZCTreeManager(mLayersId);
}
RefPtr<APZCTreeManager> apzcTreeManager(mApzcTreeManager);
return apzcTreeManager.forget();
}
} // namespace layers
} // namespace mozilla
+130
View File
@@ -0,0 +1,130 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: sw=2 ts=8 et :
*/
/* 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_RemoteContentController_h
#define mozilla_layers_RemoteContentController_h
#include "mozilla/layers/GeckoContentController.h"
#include "mozilla/layers/PAPZParent.h"
namespace mozilla {
namespace dom {
class TabParent;
}
namespace layers {
class APZCTreeManager;
/**
* RemoteContentController uses the PAPZ protocol to implement a
* GeckoContentController for a browser living in a remote process.
* Most of the member functions can be called on any thread, exceptions are
* annotated in comments. The PAPZ protocol runs on the main thread (so all the
* Recv* member functions do too).
*/
class RemoteContentController : public GeckoContentController
, public PAPZParent
{
using GeckoContentController::APZStateChange;
public:
explicit RemoteContentController(uint64_t aLayersId,
dom::TabParent* aBrowserParent);
virtual ~RemoteContentController();
// Needs to be called on the main thread.
virtual void RequestContentRepaint(const FrameMetrics& aFrameMetrics) override;
virtual void RequestFlingSnap(const FrameMetrics::ViewID& aScrollId,
const mozilla::CSSPoint& aDestination) override;
virtual void AcknowledgeScrollUpdate(const FrameMetrics::ViewID& aScrollId,
const uint32_t& aScrollGeneration) override;
virtual void HandleDoubleTap(const CSSPoint& aPoint,
Modifiers aModifiers,
const ScrollableLayerGuid& aGuid) override;
virtual void HandleSingleTap(const CSSPoint& aPoint,
Modifiers aModifiers,
const ScrollableLayerGuid& aGuid) override;
virtual void HandleLongTap(const CSSPoint& aPoint,
Modifiers aModifiers,
const ScrollableLayerGuid& aGuid,
uint64_t aInputBlockId) override;
virtual void PostDelayedTask(Task* aTask, int aDelayMs) override;
virtual bool GetTouchSensitiveRegion(CSSRect* aOutRegion) override;
virtual void NotifyAPZStateChange(const ScrollableLayerGuid& aGuid,
APZStateChange aChange,
int aArg) override;
virtual void NotifyMozMouseScrollEvent(const FrameMetrics::ViewID& aScrollId,
const nsString& aEvent) override;
// Needs to be called on the main thread.
virtual void NotifyFlushComplete() override;
virtual bool RecvUpdateHitRegion(const nsRegion& aRegion) override;
virtual bool RecvZoomToRect(const uint32_t& aPresShellId,
const ViewID& aViewId,
const CSSRect& aRect,
const uint32_t& aFlags) override;
virtual bool RecvContentReceivedInputBlock(const ScrollableLayerGuid& aGuid,
const uint64_t& aInputBlockId,
const bool& aPreventDefault) override;
virtual bool RecvStartScrollbarDrag(const AsyncDragMetrics& aDragMetrics) override;
virtual bool RecvSetTargetAPZC(const uint64_t& aInputBlockId,
nsTArray<ScrollableLayerGuid>&& aTargets) override;
virtual bool RecvSetAllowedTouchBehavior(const uint64_t& aInputBlockId,
nsTArray<TouchBehaviorFlags>&& aFlags) override;
virtual bool RecvUpdateZoomConstraints(const uint32_t& aPresShellId,
const ViewID& aViewId,
const MaybeZoomConstraints& aConstraints) override;
virtual void ActorDestroy(ActorDestroyReason aWhy) override;
virtual void Destroy() override;
virtual void ChildAdopted() override;
private:
bool CanSend()
{
MOZ_ASSERT(NS_IsMainThread());
return !!mBrowserParent;
}
already_AddRefed<APZCTreeManager> GetApzcTreeManager();
MessageLoop* mUILoop;
uint64_t mLayersId;
RefPtr<dom::TabParent> mBrowserParent;
// Mutex protecting members below accessed from multiple threads.
mozilla::Mutex mMutex;
RefPtr<APZCTreeManager> mApzcTreeManager;
nsRegion mTouchSensitiveRegion;
};
} // namespace layers
} // namespace mozilla
#endif // mozilla_layers_RemoteContentController_h

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