Bug 1451469 - Add a TransactionWrapper class. r?nical
The TransactionBuilder class comes with a bunch of baggage (it
automatically allocates/deallocates a transaction under the hood) which
we will want to avoid for the RB callbacks into APZ. This patch adds a
lightweight TransactionWrapper class that APZ can use to provide the
async transform info and that will be simpler to use in the callback
from rust code.
MozReview-Commit-ID: 1ywhx4TIzGd
--- a/gfx/layers/apz/public/APZSampler.h
+++ b/gfx/layers/apz/public/APZSampler.h
@@ -15,17 +15,17 @@
#include "nsTArray.h"
#include "Units.h"
namespace mozilla {
class TimeStamp;
namespace wr {
-class TransactionBuilder;
+class TransactionWrapper;
struct WrTransformProperty;
struct WrWindowId;
} // namespace wr
namespace layers {
class APZCTreeManager;
class LayerMetricsWrapper;
@@ -47,17 +47,17 @@ public:
/**
* This function is invoked from rust on the render backend thread when it
* is created. It effectively tells the APZSampler "the current thread is
* the sampler thread for this window id" and allows APZSampler to remember
* which thread it is.
*/
static void SetSamplerThread(const wr::WrWindowId& aWindowId);
- bool PushStateToWR(wr::TransactionBuilder& aTxn,
+ bool PushStateToWR(wr::TransactionWrapper& aTxn,
const TimeStamp& aSampleTime);
bool SampleAnimations(const LayerMetricsWrapper& aLayer,
const TimeStamp& aSampleTime);
/**
* Compute the updated shadow transform for a scroll thumb layer that
* reflects async scrolling of the associated scroll frame.
--- a/gfx/layers/apz/src/APZCTreeManager.cpp
+++ b/gfx/layers/apz/src/APZCTreeManager.cpp
@@ -586,17 +586,17 @@ APZCTreeManager::UpdateHitTestingTree(La
{
AssertOnUpdaterThread();
UpdateHitTestingTreeImpl(aRootLayerTreeId, aScrollWrapper, aIsFirstPaint,
aOriginatingLayersId, aPaintSequenceNumber);
}
bool
-APZCTreeManager::PushStateToWR(wr::TransactionBuilder& aTxn,
+APZCTreeManager::PushStateToWR(wr::TransactionWrapper& aTxn,
const TimeStamp& aSampleTime)
{
AssertOnSamplerThread();
MutexAutoLock lock(mMapLock);
bool activeAnimations = false;
for (const auto& mapping : mApzcMap) {
AsyncPanZoomController* apzc = mapping.second;
--- a/gfx/layers/apz/src/APZCTreeManager.h
+++ b/gfx/layers/apz/src/APZCTreeManager.h
@@ -30,17 +30,17 @@
#if defined(MOZ_WIDGET_ANDROID)
#include "mozilla/layers/AndroidDynamicToolbarAnimator.h"
#endif // defined(MOZ_WIDGET_ANDROID)
namespace mozilla {
class MultiTouchInput;
namespace wr {
-class TransactionBuilder;
+class TransactionWrapper;
class WebRenderAPI;
struct WrTransformProperty;
}
namespace layers {
class Layer;
class AsyncPanZoomController;
@@ -219,17 +219,17 @@ public:
* async scroll position. It also advances APZ animations to the specified
* sample time. In effect it is the webrender equivalent of (part of) the
* code in AsyncCompositionManager. If scrollbar transforms need updating
* to reflect the async scroll position, the updated transforms are appended
* to the provided transaction as well.
* Returns true if any APZ animations are in progress and we need to keep
* compositing.
*/
- bool PushStateToWR(wr::TransactionBuilder& aTxn,
+ bool PushStateToWR(wr::TransactionWrapper& aTxn,
const TimeStamp& aSampleTime);
/**
* Walk the tree of APZCs and flushes the repaint requests for all the APZCS
* corresponding to the given layers id. Finally, sends a flush complete
* notification to the GeckoContentController for the layers id.
*/
void FlushApzRepaints(LayersId aLayersId);
--- a/gfx/layers/apz/src/APZSampler.cpp
+++ b/gfx/layers/apz/src/APZSampler.cpp
@@ -57,17 +57,17 @@ APZSampler::SetSamplerThread(const wr::W
if (RefPtr<APZSampler> sampler = GetSampler(aWindowId)) {
// Ensure nobody tried to use the updater thread before this point.
MOZ_ASSERT(!sampler->mSamplerThreadQueried);
sampler->mSamplerThreadId = Some(PlatformThread::CurrentId());
}
}
bool
-APZSampler::PushStateToWR(wr::TransactionBuilder& aTxn,
+APZSampler::PushStateToWR(wr::TransactionWrapper& aTxn,
const TimeStamp& aSampleTime)
{
// This function will be removed eventually since we'll have WR pull
// the transforms from APZ instead.
return mApz->PushStateToWR(aTxn, aSampleTime);
}
bool
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -3568,22 +3568,24 @@ AsyncPanZoomController::RequestContentRe
mLastPaintRequestMetrics = aFrameMetrics;
}
bool AsyncPanZoomController::UpdateAnimation(const TimeStamp& aSampleTime,
nsTArray<RefPtr<Runnable>>* aOutDeferredTasks)
{
AssertOnSamplerThread();
- // This function may get called multiple with the same sample time, because
- // there may be multiple layers with this APZC, and each layer invokes this
- // function during composition. However we only want to do one animation step
- // per composition so we need to deduplicate these calls first.
+ // This function may get called multiple with the same sample time, for two
+ // reasons: (1) there may be multiple layers with this APZC, and each layer
+ // invokes this function during composition, and (2) we might composite
+ // multiple times at the same timestamp.
+ // However we only want to do one animation step per composition so we need
+ // to deduplicate these calls first.
if (mLastSampleTime == aSampleTime) {
- return false;
+ return (mAnimation != nullptr);
}
// Sample the composited async transform once per composite. Note that we
// call this after the |mLastSampleTime == aSampleTime| check, to ensure
// it's only called once per APZC on each composite.
bool needComposite = SampleCompositedAsyncTransform();
TimeDuration sampleTimeDelta = aSampleTime - mLastSampleTime;
--- a/gfx/layers/wr/WebRenderBridgeParent.cpp
+++ b/gfx/layers/wr/WebRenderBridgeParent.cpp
@@ -543,17 +543,21 @@ WebRenderBridgeParent::PushAPZStateToWR(
TimeStamp animationTime = cbp->GetTestingTimeStamp().valueOr(
mCompositorScheduler->GetLastComposeTime());
TimeDuration frameInterval = cbp->GetVsyncInterval();
// As with the non-webrender codepath in AsyncCompositionManager, we want to
// use the timestamp for the next vsync when advancing animations.
if (frameInterval != TimeDuration::Forever()) {
animationTime += frameInterval;
}
- return apz->PushStateToWR(aTxn, animationTime);
+ // The TransactionWrapper shares the underlying transaction object with
+ // aTxn. When we exit this scope the TransactionWrapper is destroyed but
+ // the underlying transaction lives on in aTxn.
+ wr::TransactionWrapper txn(aTxn.Raw());
+ return apz->PushStateToWR(txn, animationTime);
}
return false;
}
mozilla::ipc::IPCResult
WebRenderBridgeParent::RecvSetDisplayList(const gfx::IntSize& aSize,
InfallibleTArray<WebRenderParentCommand>&& aCommands,
InfallibleTArray<OpDestroy>&& aToDestroy,
--- a/gfx/webrender_bindings/WebRenderAPI.cpp
+++ b/gfx/webrender_bindings/WebRenderAPI.cpp
@@ -247,16 +247,37 @@ TransactionBuilder::SetWindowParameters(
void
TransactionBuilder::UpdateScrollPosition(const wr::WrPipelineId& aPipelineId,
const layers::FrameMetrics::ViewID& aScrollId,
const wr::LayoutPoint& aScrollPosition)
{
wr_transaction_scroll_layer(mTxn, aPipelineId, aScrollId, aScrollPosition);
}
+TransactionWrapper::TransactionWrapper(Transaction* aTxn)
+ : mTxn(aTxn)
+{
+}
+
+void
+TransactionWrapper::AppendTransformProperties(const nsTArray<wr::WrTransformProperty>& aTransformArray)
+{
+ wr_transaction_append_transform_properties(
+ mTxn,
+ aTransformArray.IsEmpty() ? nullptr : aTransformArray.Elements(),
+ aTransformArray.Length());
+}
+
+void
+TransactionWrapper::UpdateScrollPosition(const wr::WrPipelineId& aPipelineId,
+ const layers::FrameMetrics::ViewID& aScrollId,
+ const wr::LayoutPoint& aScrollPosition)
+{
+ wr_transaction_scroll_layer(mTxn, aPipelineId, aScrollId, aScrollPosition);
+}
/*static*/ void
WebRenderAPI::InitExternalLogHandler()
{
// Redirect the webrender's log to gecko's log system.
// The current log level is "error".
mozilla::wr::wr_init_external_log_handler(wr::WrLogLevelFilter::Error);
}
--- a/gfx/webrender_bindings/WebRenderAPI.h
+++ b/gfx/webrender_bindings/WebRenderAPI.h
@@ -142,16 +142,29 @@ public:
Transaction* Raw() { return mTxn; }
wr::ResourceUpdates* RawUpdates() { return mResourceUpdates; }
protected:
Transaction* mTxn;
wr::ResourceUpdates* mResourceUpdates;
};
+class TransactionWrapper
+{
+public:
+ explicit TransactionWrapper(Transaction* aTxn);
+
+ void AppendTransformProperties(const nsTArray<wr::WrTransformProperty>& aTransformArray);
+ void UpdateScrollPosition(const wr::WrPipelineId& aPipelineId,
+ const layers::FrameMetrics::ViewID& aScrollId,
+ const wr::LayoutPoint& aScrollPosition);
+private:
+ Transaction* mTxn;
+};
+
class WebRenderAPI
{
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebRenderAPI);
public:
/// This can be called on the compositor thread only.
static already_AddRefed<WebRenderAPI> Create(layers::CompositorBridgeParent* aBridge,
RefPtr<widget::CompositorWidget>&& aWidget,