This commit is contained in:
velzie committed 2026-06-30 11:46:22 -04:00
1 parent 03c5732115
commit badd1b3ea0
13 files changed
+485 -15

No files matched your search

+22
View File
@@ -741,6 +741,15 @@ std::vector<LayersId> APZCTreeManager::UpdateHitTestingTree(
// APZC instances
MutexAutoLock lock(mMapLock);
mApzcMap = std::move(state.mApzcMap);
{
static int s_apzcLog = 0;
if (s_apzcLog < 6) {
s_apzcLog++;
printf("APZ-DIAG UpdateHitTestingTree: APZC count=%zu\n",
mApzcMap.size());
fflush(stdout);
}
}
for (auto& mapping : mApzcMap) {
AsyncPanZoomController* parent = mapping.second.apzc->GetParent();
@@ -1711,6 +1720,19 @@ APZEventResult APZCTreeManager::ReceiveInputEvent(
state.mHit = GetTargetAPZC(wheelInput.mOrigin);
wheelInput.mHandledByAPZ = WillHandleInput(wheelInput);
{
static int s_wlog = 0;
if (s_wlog < 8) {
s_wlog++;
printf(
"APZ-DIAG wheel hit: origin=(%.1f,%.1f) handledByAPZ=%d "
"targetApzc=%p\n",
(double)wheelInput.mOrigin.x, (double)wheelInput.mOrigin.y,
(int)wheelInput.mHandledByAPZ,
(void*)state.mHit.mTargetApzc.get());
fflush(stdout);
}
}
if (!wheelInput.mHandledByAPZ) {
return state.Finish(*this, std::move(aCallback));
}
+14
View File
@@ -326,6 +326,20 @@ APZEventResult APZInputBridge::ReceiveInputEvent(
}
case eWheelEventClass: {
WidgetWheelEvent& wheelEvent = *aEvent.AsWheelEvent();
{
Maybe<APZWheelAction> a = ActionForWheelEvent(&wheelEvent);
static int s_wa = 0;
if (s_wa < 8) {
s_wa++;
printf(
"APZ-DIAG InputBridge wheel: msg=%d deltaMode=%d dY=%.1f "
"action=%d\n",
(int)wheelEvent.mMessage, (int)wheelEvent.mDeltaMode,
(double)wheelEvent.mDeltaY,
a.isSome() ? (int)a.value() : -1);
fflush(stdout);
}
}
if (Maybe<APZWheelAction> action = ActionForWheelEvent(&wheelEvent)) {
ScrollWheelInput::ScrollMode scrollMode =
+9 -1
View File
@@ -64,7 +64,15 @@ void APZSampler::SetSamplerThread(const wr::WrWindowId& aWindowId) {
void APZSampler::SampleForWebRender(const wr::WrWindowId& aWindowId,
const uint64_t* aGeneratedFrameId,
wr::Transaction* aTransaction) {
if (RefPtr<APZSampler> sampler = GetSampler(aWindowId)) {
RefPtr<APZSampler> sampler = GetSampler(aWindowId);
static int s_smpLog = 0;
if (s_smpLog < 3) {
s_smpLog++;
printf("APZ-DIAG SampleForWebRender called, sampler=%p\n",
(void*)sampler.get());
fflush(stdout);
}
if (sampler) {
wr::TransactionWrapper txn(aTransaction);
Maybe<VsyncId> vsyncId =
aGeneratedFrameId ? Some(VsyncId{*aGeneratedFrameId}) : Nothing();
@@ -683,6 +683,19 @@ static bool PrepareForSetTargetAPZCNotification(
nsIFrame* target = nsLayoutUtils::GetFrameForPoint(relativeTo, point);
ScrollContainerFrame* scrollAncestor =
GetScrollContainerFor(target, aRootFrame);
{
static int s_prep = 0;
if (s_prep < 20) {
s_prep++;
printf("APZ-TGT prepare: target=%p scrollAncestor=%p isRoot=%d\n",
(void*)target, (void*)scrollAncestor,
scrollAncestor ? (int)(scrollAncestor ==
aRootFrame->PresShell()
->GetRootScrollContainerFrame())
: -1);
fflush(stdout);
}
}
// Assuming that if there's no scrollAncestor, there's already a displayPort.
nsCOMPtr<dom::Element> dpElement =
@@ -816,6 +829,20 @@ APZCCallbackHelper::SendSetTargetAPZCNotification(nsIWidget* aWidget,
const WidgetGUIEvent& aEvent,
const LayersId& aLayersId,
uint64_t aInputBlockId) {
{
static int s_sstg = 0;
if (s_sstg < 20) {
s_sstg++;
PresShell* ps = aDocument ? aDocument->GetPresShell() : nullptr;
printf(
"APZ-TGT send: widget=%d doc=%d presShell=%d inputBlock=%llu "
"sLast=%llu\n",
(int)!!aWidget, (int)!!aDocument, (int)!!ps,
(unsigned long long)aInputBlockId,
(unsigned long long)sLastTargetAPZCNotificationInputBlock);
fflush(stdout);
}
}
if (!aWidget || !aDocument) {
return nullptr;
}
@@ -271,6 +271,9 @@ void CompositorBridgeParent::Initialize() {
mApzcTreeManager = APZCTreeManager::Create(mRootLayerTreeID);
mApzSampler = new APZSampler(mApzcTreeManager, true);
mApzUpdater = new APZUpdater(mApzcTreeManager, true);
printf("APZ-INIT: CompositorBridgeParent created APZCTreeManager (UseAPZ=1)\n");
} else {
printf("APZ-INIT: UseAPZ=0 (no APZCTreeManager)\n");
}
CompositorAnimationStorage* animationStorage = GetAnimationStorage();
+110 -14
View File
@@ -14,7 +14,10 @@
#include "mozilla/layers/StackingContextHelper.h"
#include "mozilla/layers/PTextureChild.h"
#include "mozilla/layers/WebRenderLayerManager.h"
#include "mozilla/layers/WebRenderBridgeParent.h"
#include "mozilla/layers/CompositorThread.h"
#include "mozilla/webrender/WebRenderAPI.h"
#include "nsThreadUtils.h"
#include "PDMFactory.h"
namespace mozilla {
@@ -106,8 +109,20 @@ void WebRenderBridgeChild::UpdateResources(
nsTArray<ipc::Shmem> largeShmems;
aResources.Flush(resourceUpdates, smallShmems, largeShmems);
this->SendUpdateResources(mIdNamespace, resourceUpdates, smallShmems,
std::move(largeShmems));
if (RefPtr<WebRenderBridgeParent> p =
WebRenderBridgeParent::GetInProcess(wr::AsUint64(mPipelineId));
p && CompositorThread()) {
CompositorThread()->Dispatch(NS_NewRunnableFunction(
"WRBridgeInProcessUpdateResources",
[p, ns = mIdNamespace, u = std::move(resourceUpdates),
s = std::move(smallShmems), l = std::move(largeShmems)]() mutable {
p->InProcessUpdateResources(ns, std::move(u), std::move(s),
std::move(l));
}));
} else {
this->SendUpdateResources(mIdNamespace, resourceUpdates, smallShmems,
std::move(largeShmems));
}
}
bool WebRenderBridgeChild::EndTransaction(
@@ -120,6 +135,21 @@ bool WebRenderBridgeChild::EndTransaction(
MOZ_ASSERT(mIsInTransaction);
TimeStamp fwdTime = TimeStamp::Now();
{
static TimeStamp s_lastEnd;
static int s_etDiag = 0;
if (s_etDiag < 40) {
s_etDiag++;
double intervalMs =
s_lastEnd.IsNull() ? 0.0 : (fwdTime - s_lastEnd).ToMilliseconds();
double paintMs = aTxnStartTime.IsNull()
? 0.0
: (fwdTime - aTxnStartTime).ToMilliseconds();
printf("ET-DIAG mainPaintMs=%.1f intervalMs=%.1f\n", paintMs, intervalMs);
fflush(stdout);
}
s_lastEnd = fwdTime;
}
if (!aRenderOffscreen) {
MergeWebRenderParentCommands();
@@ -133,11 +163,31 @@ bool WebRenderBridgeChild::EndTransaction(
}
mSentDisplayList = true;
bool ret = this->SendSetDisplayList(
std::move(aDisplayListData), mDestroyedActors, GetFwdTransactionId(),
aTransactionId, aContainsSVGGroup, aVsyncId, aVsyncStartTime,
aRefreshStartTime, aTxnStartTime, aTxnURL, fwdTime, payloads,
aRenderOffscreen);
bool ret = true;
if (RefPtr<WebRenderBridgeParent> p =
WebRenderBridgeParent::GetInProcess(wr::AsUint64(mPipelineId));
p && CompositorThread()) {
CompositorThread()->Dispatch(NS_NewRunnableFunction(
"WRBridgeInProcessSetDisplayList",
[p, dl = std::move(aDisplayListData),
destroy = std::move(mDestroyedActors), fwdTxn = GetFwdTransactionId(),
txnId = aTransactionId, svg = aContainsSVGGroup, vsyncId = aVsyncId,
vsyncStart = aVsyncStartTime, refreshStart = aRefreshStartTime,
txnStart = aTxnStartTime, url = nsCString(aTxnURL), fwdTime,
pl = std::move(payloads),
offscreen = aRenderOffscreen]() mutable {
p->InProcessSetDisplayList(
std::move(dl), std::move(destroy), fwdTxn, txnId, svg, vsyncId,
vsyncStart, refreshStart, txnStart, url, fwdTime, std::move(pl),
offscreen);
}));
} else {
ret = this->SendSetDisplayList(
std::move(aDisplayListData), mDestroyedActors, GetFwdTransactionId(),
aTransactionId, aContainsSVGGroup, aVsyncId, aVsyncStartTime,
aRefreshStartTime, aTxnStartTime, aTxnURL, fwdTime, payloads,
aRenderOffscreen);
}
// With multiple render roots, we may not have sent all of our
// mParentCommands, so go ahead and go through our mParentCommands and ensure
@@ -170,10 +220,28 @@ void WebRenderBridgeChild::EndEmptyTransaction(
mManager->TakeCompositionPayloads(payloads);
}
this->SendEmptyTransaction(
aFocusTarget, std::move(aTransactionData), mDestroyedActors,
GetFwdTransactionId(), aTransactionId, aVsyncId, aVsyncStartTime,
aRefreshStartTime, aTxnStartTime, aTxnURL, fwdTime, payloads);
if (RefPtr<WebRenderBridgeParent> p =
WebRenderBridgeParent::GetInProcess(wr::AsUint64(mPipelineId));
p && CompositorThread()) {
CompositorThread()->Dispatch(NS_NewRunnableFunction(
"WRBridgeInProcessEmptyTransaction",
[p, focus = aFocusTarget, txnData = std::move(aTransactionData),
destroy = std::move(mDestroyedActors), fwdTxn = GetFwdTransactionId(),
txnId = aTransactionId, vsyncId = aVsyncId,
vsyncStart = aVsyncStartTime, refreshStart = aRefreshStartTime,
txnStart = aTxnStartTime, url = nsCString(aTxnURL), fwdTime,
pl = std::move(payloads)]() mutable {
p->InProcessEmptyTransaction(
focus, std::move(txnData), std::move(destroy), fwdTxn, txnId,
vsyncId, vsyncStart, refreshStart, txnStart, url, fwdTime,
std::move(pl));
}));
} else {
this->SendEmptyTransaction(
aFocusTarget, std::move(aTransactionData), mDestroyedActors,
GetFwdTransactionId(), aTransactionId, aVsyncId, aVsyncStartTime,
aRefreshStartTime, aTxnStartTime, aTxnURL, fwdTime, payloads);
}
// With multiple render roots, we may not have sent all of our
// mParentCommands, so go ahead and go through our mParentCommands and ensure
@@ -188,7 +256,17 @@ void WebRenderBridgeChild::ProcessWebRenderParentCommands() {
if (HasWebRenderParentCommands()) {
MergeWebRenderParentCommands();
this->SendParentCommands(mIdNamespace, mParentCommands);
if (RefPtr<WebRenderBridgeParent> p =
WebRenderBridgeParent::GetInProcess(wr::AsUint64(mPipelineId));
p && CompositorThread()) {
CompositorThread()->Dispatch(NS_NewRunnableFunction(
"WRBridgeInProcessParentCommands",
[p, ns = mIdNamespace, cmds = std::move(mParentCommands)]() mutable {
p->InProcessParentCommands(ns, std::move(cmds));
}));
} else {
this->SendParentCommands(mIdNamespace, mParentCommands);
}
mParentCommands.Clear();
}
}
@@ -379,7 +457,17 @@ void WebRenderBridgeChild::Connect(CompositableClient* aCompositable,
mCompositables.InsertOrUpdate(uint64_t(handle), aCompositable);
aCompositable->InitIPDL(handle);
SendNewCompositable(handle, aCompositable->GetTextureInfo());
if (RefPtr<WebRenderBridgeParent> p =
WebRenderBridgeParent::GetInProcess(wr::AsUint64(mPipelineId));
p && CompositorThread()) {
CompositorThread()->Dispatch(NS_NewRunnableFunction(
"WRBridgeInProcessNewCompositable",
[p, handle, info = aCompositable->GetTextureInfo()]() mutable {
p->InProcessNewCompositable(handle, info);
}));
} else {
SendNewCompositable(handle, aCompositable->GetTextureInfo());
}
}
bool WebRenderBridgeChild::AddOpDestroy(const OpDestroy& aOp) {
@@ -399,7 +487,15 @@ void WebRenderBridgeChild::ReleaseCompositable(
return;
}
if (!DestroyInTransaction(aHandle)) {
SendReleaseCompositable(aHandle);
if (RefPtr<WebRenderBridgeParent> p =
WebRenderBridgeParent::GetInProcess(wr::AsUint64(mPipelineId));
p && CompositorThread()) {
CompositorThread()->Dispatch(NS_NewRunnableFunction(
"WRBridgeInProcessReleaseCompositable",
[p, h = aHandle]() mutable { p->InProcessReleaseCompositable(h); }));
} else {
SendReleaseCompositable(aHandle);
}
}
mCompositables.Remove(aHandle.Value());
}
+181
View File
@@ -17,8 +17,14 @@
#include "mozilla/CheckedInt.h"
#include "mozilla/Range.h"
#include "mozilla/EnumeratedRange.h"
#include "mozilla/StaticMutex.h"
#include "mozilla/StaticPrefs_gfx.h"
#include "mozilla/StaticPrefs_webgl.h"
#include "mozilla/layers/PTextureParent.h"
#include "mozilla/layers/PTextureChild.h"
#include "mozilla/ipc/SideVariant.h"
#include "nsTHashMap.h"
#include "prenv.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/gfx/gfxVars.h"
#include "mozilla/gfx/GPUParent.h"
@@ -349,6 +355,7 @@ WebRenderBridgeParent::WebRenderBridgeParent(
mRemoteTextureTxnScheduler =
RemoteTextureTxnScheduler::Create(aCompositorBridge);
RegisterInProcess();
}
WebRenderBridgeParent::WebRenderBridgeParent(
@@ -376,6 +383,7 @@ WebRenderBridgeParent::WebRenderBridgeParent(
mLateInit->mAsyncImageManager->AddPipeline(mPipelineId, this);
mRemoteTextureTxnScheduler =
RemoteTextureTxnScheduler::Create(aCompositorBridge);
RegisterInProcess();
}
WebRenderBridgeParent::WebRenderBridgeParent(const wr::PipelineId& aPipelineId,
@@ -400,6 +408,169 @@ WebRenderBridgeParent::~WebRenderBridgeParent() {
wr::AsUint64(mPipelineId));
}
// In-process direct-dispatch registry. The map owns a strong ref so a registered
// parent is always alive for a lookup (no cross-thread refcount-revival race);
// teardown removes it in Destroy(). Opt-in via GECKO_WR_DIRECT.
static StaticMutex sWRBPRegistryMutex;
static nsTHashMap<uint64_t, RefPtr<WebRenderBridgeParent>>* sWRBPRegistry =
nullptr;
static bool WRDirectEnabled() {
static const bool sEnabled = !!PR_GetEnv("GECKO_WR_DIRECT");
return sEnabled;
}
void WebRenderBridgeParent::RegisterInProcess() {
if (!WRDirectEnabled()) {
return;
}
static bool sLogged = false;
if (!sLogged) {
sLogged = true;
printf("WR-DIRECT: in-process WebRender transaction path enabled\n");
}
StaticMutexAutoLock lock(sWRBPRegistryMutex);
if (!sWRBPRegistry) {
sWRBPRegistry = new nsTHashMap<uint64_t, RefPtr<WebRenderBridgeParent>>();
}
sWRBPRegistry->InsertOrUpdate(wr::AsUint64(mPipelineId), this);
}
void WebRenderBridgeParent::UnregisterInProcess() {
StaticMutexAutoLock lock(sWRBPRegistryMutex);
if (sWRBPRegistry) {
sWRBPRegistry->Remove(wr::AsUint64(mPipelineId));
}
}
/* static */
already_AddRefed<WebRenderBridgeParent> WebRenderBridgeParent::GetInProcess(
uint64_t aPipelineId) {
StaticMutexAutoLock lock(sWRBPRegistryMutex);
if (!sWRBPRegistry) {
return nullptr;
}
RefPtr<WebRenderBridgeParent> parent;
sWRBPRegistry->Get(aPipelineId, &parent);
return parent.forget();
}
void WebRenderBridgeParent::XlateTexture(
NotNull<ipc::SideVariant<PTextureParent*, PTextureChild*>>& aField) {
if (aField.IsParent()) {
return;
}
PTextureChild* child = aField.AsChild().get();
IProtocol* actor = Lookup(child->Id());
MOZ_ASSERT(actor, "in-process PTexture has no parent-side actor");
if (!actor) {
return;
}
ipc::SideVariant<PTextureParent*, PTextureChild*> sv;
sv = static_cast<PTextureParent*>(actor);
aField = WrapNotNull(sv);
}
void WebRenderBridgeParent::TranslateActors(nsTArray<OpDestroy>& aOps) {
for (auto& op : aOps) {
if (op.type() == OpDestroy::TPTexture) {
XlateTexture(op.get_PTexture());
}
}
}
void WebRenderBridgeParent::TranslateActors(
nsTArray<WebRenderParentCommand>& aCommands) {
for (auto& cmd : aCommands) {
if (cmd.type() != WebRenderParentCommand::TCompositableOperation) {
continue;
}
auto& detail = cmd.get_CompositableOperation().detail();
switch (detail.type()) {
case CompositableOperationDetail::TOpRemoveTexture:
XlateTexture(detail.get_OpRemoveTexture().texture());
break;
case CompositableOperationDetail::TOpUseTexture:
for (auto& tt : detail.get_OpUseTexture().textures()) {
XlateTexture(tt.texture());
}
break;
default:
break;
}
}
}
void WebRenderBridgeParent::TranslateActors(
nsTArray<OpUpdateResource>& aUpdates) {
for (auto& up : aUpdates) {
if (up.type() == OpUpdateResource::TOpPushExternalImageForTexture) {
XlateTexture(up.get_OpPushExternalImageForTexture().texture());
}
}
}
void WebRenderBridgeParent::InProcessUpdateResources(
const wr::IdNamespace& aIdNamespace, nsTArray<OpUpdateResource>&& aUpdates,
nsTArray<RefCountedShmem>&& aSmallShmems,
nsTArray<ipc::Shmem>&& aLargeShmems) {
TranslateActors(aUpdates);
(void)RecvUpdateResources(aIdNamespace, std::move(aUpdates),
std::move(aSmallShmems), std::move(aLargeShmems));
}
void WebRenderBridgeParent::InProcessParentCommands(
const wr::IdNamespace& aIdNamespace,
nsTArray<WebRenderParentCommand>&& aCommands) {
TranslateActors(aCommands);
(void)RecvParentCommands(aIdNamespace, std::move(aCommands));
}
void WebRenderBridgeParent::InProcessNewCompositable(
const CompositableHandle& aHandle, const TextureInfo& aInfo) {
(void)RecvNewCompositable(aHandle, aInfo);
}
void WebRenderBridgeParent::InProcessReleaseCompositable(
const CompositableHandle& aHandle) {
(void)RecvReleaseCompositable(aHandle);
}
void WebRenderBridgeParent::InProcessSetDisplayList(
DisplayListData&& aDisplayList, nsTArray<OpDestroy>&& aToDestroy,
uint64_t aFwdTransactionId, TransactionId aTransactionId,
bool aContainsSVGGroup, VsyncId aVsyncId, TimeStamp aVsyncStartTime,
TimeStamp aRefreshStartTime, TimeStamp aTxnStartTime, nsCString aTxnURL,
TimeStamp aFwdTime, nsTArray<CompositionPayload>&& aPayloads,
bool aRenderOffscreen) {
TranslateActors(aToDestroy);
TranslateActors(aDisplayList.mCommands);
TranslateActors(aDisplayList.mResourceUpdates);
(void)RecvSetDisplayList(
std::move(aDisplayList), std::move(aToDestroy), aFwdTransactionId,
aTransactionId, aContainsSVGGroup, aVsyncId, aVsyncStartTime,
aRefreshStartTime, aTxnStartTime, aTxnURL, aFwdTime, std::move(aPayloads),
aRenderOffscreen);
}
void WebRenderBridgeParent::InProcessEmptyTransaction(
const FocusTarget& aFocusTarget, Maybe<TransactionData>&& aTransactionData,
nsTArray<OpDestroy>&& aToDestroy, uint64_t aFwdTransactionId,
TransactionId aTransactionId, VsyncId aVsyncId, TimeStamp aVsyncStartTime,
TimeStamp aRefreshStartTime, TimeStamp aTxnStartTime, nsCString aTxnURL,
TimeStamp aFwdTime, nsTArray<CompositionPayload>&& aPayloads) {
TranslateActors(aToDestroy);
if (aTransactionData) {
TranslateActors(aTransactionData->mCommands);
TranslateActors(aTransactionData->mResourceUpdates);
}
(void)RecvEmptyTransaction(aFocusTarget, std::move(aTransactionData),
std::move(aToDestroy), aFwdTransactionId,
aTransactionId, aVsyncId, aVsyncStartTime,
aRefreshStartTime, aTxnStartTime, aTxnURL, aFwdTime,
std::move(aPayloads));
}
/* static */
already_AddRefed<WebRenderBridgeParent> WebRenderBridgeParent::CreateDestroyed(
const wr::PipelineId& aPipelineId, nsCString&& aError) {
@@ -534,6 +705,7 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::HandleShutdown() {
}
void WebRenderBridgeParent::Destroy() {
UnregisterInProcess();
if (!EnsureInitialized()) {
return;
}
@@ -1353,6 +1525,15 @@ bool WebRenderBridgeParent::ProcessDisplayListData(
// Note that this needs to happen before the display list transaction is
// sent to WebRender, so that the UpdateHitTestingTree call is guaranteed to
// be in the updater queue at the time that the scene swap completes.
{
static int s_sdLog = 0;
if (s_sdLog < 5) {
s_sdLog++;
printf("APZ-DIAG WRBP::SetDisplayList scrollData=%d\n",
(int)(bool)aDisplayList.mScrollData);
fflush(stdout);
}
}
if (aDisplayList.mScrollData) {
UpdateAPZScrollData(aWrEpoch, std::move(aDisplayList.mScrollData.ref()));
}
+40
View File
@@ -199,6 +199,38 @@ class WebRenderBridgeParent final : public PWebRenderBridgeParent,
void Destroy();
// In-process direct dispatch: when the compositor is in this process, a
// WebRenderBridgeChild hands the transaction's moved C++ payload straight to
// the compositor thread instead of through IPDL (skipping Pickle
// serialization). GetInProcess() finds the parent for a pipeline id; the
// InProcess* methods run on the compositor thread, translate child-side actor
// references (PTexture) to this side via Lookup(), then invoke the Recv path.
// Opt-in: only populated when GECKO_WR_DIRECT is set in the environment.
static already_AddRefed<WebRenderBridgeParent> GetInProcess(
uint64_t aPipelineId);
void InProcessUpdateResources(const wr::IdNamespace& aIdNamespace,
nsTArray<OpUpdateResource>&& aUpdates,
nsTArray<RefCountedShmem>&& aSmallShmems,
nsTArray<ipc::Shmem>&& aLargeShmems);
void InProcessParentCommands(const wr::IdNamespace& aIdNamespace,
nsTArray<WebRenderParentCommand>&& aCommands);
void InProcessNewCompositable(const CompositableHandle& aHandle,
const TextureInfo& aInfo);
void InProcessReleaseCompositable(const CompositableHandle& aHandle);
void InProcessSetDisplayList(
DisplayListData&& aDisplayList, nsTArray<OpDestroy>&& aToDestroy,
uint64_t aFwdTransactionId, TransactionId aTransactionId,
bool aContainsSVGGroup, VsyncId aVsyncId, TimeStamp aVsyncStartTime,
TimeStamp aRefreshStartTime, TimeStamp aTxnStartTime, nsCString aTxnURL,
TimeStamp aFwdTime, nsTArray<CompositionPayload>&& aPayloads,
bool aRenderOffscreen);
void InProcessEmptyTransaction(
const FocusTarget& aFocusTarget, Maybe<TransactionData>&& aTransactionData,
nsTArray<OpDestroy>&& aToDestroy, uint64_t aFwdTransactionId,
TransactionId aTransactionId, VsyncId aVsyncId, TimeStamp aVsyncStartTime,
TimeStamp aRefreshStartTime, TimeStamp aTxnStartTime, nsCString aTxnURL,
TimeStamp aFwdTime, nsTArray<CompositionPayload>&& aPayloads);
// CompositorVsyncSchedulerOwner
bool IsPendingComposite() override { return false; }
void FinishPendingComposite() override {}
@@ -400,6 +432,14 @@ class WebRenderBridgeParent final : public PWebRenderBridgeParent,
void DeleteImage(const wr::ImageKey& aKey, wr::TransactionBuilder& aUpdates);
void ReleaseTextureOfImage(const wr::ImageKey& aKey);
void RegisterInProcess();
void UnregisterInProcess();
void XlateTexture(
NotNull<ipc::SideVariant<PTextureParent*, PTextureChild*>>& aField);
void TranslateActors(nsTArray<OpDestroy>& aOps);
void TranslateActors(nsTArray<WebRenderParentCommand>& aCommands);
void TranslateActors(nsTArray<OpUpdateResource>& aUpdates);
bool ProcessWebRenderParentCommands(
const nsTArray<WebRenderParentCommand>& aCommands,
wr::TransactionBuilder& aTxn);
+10
View File
@@ -3988,6 +3988,16 @@ bool gfxPlatform::UseDesktopZoomingScrollbars() {
/*static*/
bool gfxPlatform::AsyncPanZoomEnabled() {
#if defined(__EMSCRIPTEN__)
// The wasm embedding is single-process (no e10s) but runs an in-process
// WebRender compositor. The layers.async-pan-zoom.enabled pref defaults to true
// (and is mirror:once, so a late runtime SetBool can't reliably disable it), and
// the e10s/Fission gates below would also force it on -- so gate APZ directly on
// the GECKO_APZ env var instead. Cleanly opt-in: default OFF -> the correct
// layout-hit-test scroll path (APZ-on currently mis-targets nested scroll
// containers because subframe displayports aren't activated -- see embed-input).
return getenv("GECKO_APZ") != nullptr;
#endif
#if !defined(MOZ_WIDGET_ANDROID) && !defined(MOZ_WIDGET_UIKIT)
// For XUL applications (everything but Firefox on Android)
// we only want to use APZ when E10S is enabled. If
+9
View File
@@ -892,8 +892,17 @@ void RenderThread::UpdateAndRender(
// and for avoiding GPU queue is filled with too much tasks.
// WaitForGPU's implementation is different for each platform.
auto timerId = glean::wr::gpu_wait_time.Start();
TimeStamp gpuS = TimeStamp::Now();
renderer->WaitForGPU();
double gpuWaitMs = (TimeStamp::Now() - gpuS).ToMilliseconds();
glean::wr::gpu_wait_time.StopAndAccumulate(std::move(timerId));
static int s_renderDiag = 0;
if (s_renderDiag < 40) {
s_renderDiag++;
printf("RENDER-DIAG renderCPU=%.1fms gpuWait=%.1fms\n",
(end - start).ToMilliseconds(), gpuWaitMs);
fflush(stdout);
}
} else {
// Update frame id for NotifyPipelinesUpdated() when rendering does not
// happen, either because rendering was not requested or the frame was
+12
View File
@@ -3048,6 +3048,18 @@ void nsLayoutUtils::PaintFrame(gfxContext* aRenderingContext, nsIFrame* aFrame,
(void)rootScrollContainerFrame->DecideScrollableLayer(
builder, &displayPortBase, &temp,
/* aSetBase = */ true);
static int s_dpRoot = 0;
if (s_dpRoot < 6) {
s_dpRoot++;
printf(
"APZ-DIAG root paint: paintingToWindow=%d apzEnabled=%d "
"rootHasDisplayPort=%d\n",
(int)builder->IsPaintingToWindow(),
(int)nsLayoutUtils::AsyncPanZoomEnabled(aFrame),
(int)DisplayPortUtils::HasDisplayPort(
rootScrollContainerFrame->GetContent()));
fflush(stdout);
}
}
// In the case where we use APZ for the given popup frame, we need to set the
+22
View File
@@ -296,6 +296,17 @@ nsIWidget::ContentAndAPZEventStatus PuppetWidget::DispatchInputEvent(
return status;
}
#if defined(__EMSCRIPTEN__)
// Single-process wasm: APZ is wired LOCALLY on this widget (mAPZC, via the
// in-process compositor) and there is no mBrowserChild to forward input to.
// Use the base-class APZ routing (mAPZC->InputBridge()->ReceiveInputEvent +
// ProcessUntransformedAPZEvent) instead of the remote SendDispatch* path below,
// which would otherwise drop the event here (mBrowserChild is null).
if (mAPZC && !mBrowserChild) {
return nsIWidget::DispatchInputEvent(aEvent);
}
#endif
if (!mBrowserChild) {
return status;
}
@@ -493,6 +504,17 @@ void PuppetWidget::UpdateZoomConstraints(
}
bool PuppetWidget::AsyncPanZoomEnabled() const {
#if defined(__EMSCRIPTEN__)
// Single-process wasm: the in-process compositor (GetWindowRenderer ->
// CreateCompositor) wires an APZCTreeManager directly on this widget (mAPZC),
// so report APZ enabled when it is present. mBrowserChild is null here, so the
// default IPC-based check below would otherwise always return false -- which
// also suppresses WebRenderLayerManager sending scroll data (no hit-testing
// tree for APZ) and routes wheel input around APZ.
if (mAPZC) {
return true;
}
#endif
return mBrowserChild && mBrowserChild->AsyncPanZoomEnabled();
}
+26
View File
@@ -1108,6 +1108,20 @@ nsEventStatus nsIWidget::ProcessUntransformedAPZEvent(
UniquePtr<WidgetEvent> original(aEvent->Duplicate());
nsEventStatus status = DispatchEvent(aEvent);
if (aEvent->AsWheelEvent()) {
static int s_tgt = 0;
if (s_tgt < 20) {
s_tgt++;
printf(
"APZ-TGT: mAPZC=%d routed=%d dropped=%d inputBlockId=%llu "
"apzEventState=%d\n",
(int)!!mAPZC, (int)InputAPZContext::WasRoutedToChildProcess(),
(int)InputAPZContext::WasDropped(),
(unsigned long long)inputBlockId, (int)!!mAPZEventState);
fflush(stdout);
}
}
if (mAPZC && !InputAPZContext::WasRoutedToChildProcess() &&
!InputAPZContext::WasDropped() && inputBlockId) {
// EventStateManager did not route the event into the child process and
@@ -1417,6 +1431,18 @@ Document* nsIWidget::GetDocument() const {
return presShell->GetDocument();
}
}
#if defined(__EMSCRIPTEN__)
// Windowless content (PuppetWidget) attaches its PresShell via the ATTACHED
// widget listener, not mWidgetListener, so the base lookup returns null. Fall
// back to it -- otherwise APZ's SetTargetAPZC subframe-activation no-ops (no
// document), nested overflow:scroll containers never get an APZC, and APZ
// mis-targets the root. See gfxPlatform::AsyncPanZoomEnabled / embed-input.
if (mAttachedWidgetListener) {
if (PresShell* presShell = mAttachedWidgetListener->GetPresShell()) {
return presShell->GetDocument();
}
}
#endif
return nullptr;
}