mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 14:18:48 +00:00
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:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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' "
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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);
|
||||
};
|
||||
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
};
|
||||
|
||||
|
||||
@@ -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});
|
||||
},
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
@@ -77,6 +77,7 @@ WEBIDL_FILES = [
|
||||
'ChannelMergerNode.webidl',
|
||||
'ChannelSplitterNode.webidl',
|
||||
'CharacterData.webidl',
|
||||
'CheckerboardReportService.webidl',
|
||||
'ChildNode.webidl',
|
||||
'ChromeNodeList.webidl',
|
||||
'ChromeNotifications.webidl',
|
||||
|
||||
+17
-9
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
@@ -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; }
|
||||
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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
@@ -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
@@ -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());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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]);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
+59
-26
@@ -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]);
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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: {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -82,7 +82,7 @@ NeedsConvertFromYUVtoRGB565(int aHalFormat)
|
||||
|
||||
GrallocTextureHostBasic::GrallocTextureHostBasic(
|
||||
TextureFlags aFlags,
|
||||
const NewSurfaceDescriptorGralloc& aDescriptor)
|
||||
const SurfaceDescriptorGralloc& aDescriptor)
|
||||
: TextureHost(aFlags)
|
||||
, mGrallocHandle(aDescriptor)
|
||||
, mSize(0, 0)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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
|
||||
@@ -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";
|
||||
|
||||
@@ -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
|
||||
@@ -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
Reference in New Issue
Block a user