mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 895358 - Part 2, Enable progressive tile rendering in B2G; r=BenWa,kats,Cwiiis
This commit is contained in:
parent
b4a3fdd32a
commit
ffd53db5e1
@ -85,6 +85,15 @@ pref("mozilla.widget.use-buffer-pixmap", true);
|
||||
pref("mozilla.widget.disable-native-theme", true);
|
||||
pref("layout.reflow.synthMouseMove", false);
|
||||
pref("layers.enable-tiles", false);
|
||||
/*
|
||||
Cross Process Mutex is not supported on Mac OS X so progressive
|
||||
paint can not be enabled for B2G on Mac OS X desktop
|
||||
*/
|
||||
#ifdef MOZ_WIDGET_COCOA
|
||||
pref("layers.progressive-paint", false);
|
||||
#else
|
||||
pref("layers.progressive-paint", false);
|
||||
#endif
|
||||
|
||||
/* download manager (don't show the window or alert) */
|
||||
pref("browser.download.useDownloadDir", true);
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "ClientTiledThebesLayer.h" // for ClientTiledThebesLayer
|
||||
#include "GeckoProfiler.h" // for PROFILER_LABEL
|
||||
#include "ClientLayerManager.h" // for ClientLayerManager
|
||||
#include "CompositorChild.h" // for CompositorChild
|
||||
#include "gfxContext.h" // for gfxContext, etc
|
||||
#include "gfxPlatform.h" // for gfxPlatform
|
||||
#include "gfxRect.h" // for gfxRect
|
||||
@ -77,8 +78,8 @@ namespace layers {
|
||||
TiledContentClient::TiledContentClient(ClientTiledThebesLayer* aThebesLayer,
|
||||
ClientLayerManager* aManager)
|
||||
: CompositableClient(aManager->AsShadowForwarder())
|
||||
, mTiledBuffer(aThebesLayer, aManager)
|
||||
, mLowPrecisionTiledBuffer(aThebesLayer, aManager)
|
||||
, mTiledBuffer(aThebesLayer, aManager, &mSharedFrameMetricsHelper)
|
||||
, mLowPrecisionTiledBuffer(aThebesLayer, aManager, &mSharedFrameMetricsHelper)
|
||||
{
|
||||
MOZ_COUNT_CTOR(TiledContentClient);
|
||||
|
||||
@ -101,11 +102,138 @@ TiledContentClient::LockCopyAndWrite(TiledBufferType aType)
|
||||
buffer->ClearPaintedRegion();
|
||||
}
|
||||
|
||||
SharedFrameMetricsHelper::SharedFrameMetricsHelper()
|
||||
: mLastProgressiveUpdateWasLowPrecision(false)
|
||||
, mProgressiveUpdateWasInDanger(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(SharedFrameMetricsHelper);
|
||||
}
|
||||
|
||||
SharedFrameMetricsHelper::~SharedFrameMetricsHelper()
|
||||
{
|
||||
MOZ_COUNT_DTOR(SharedFrameMetricsHelper);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
FuzzyEquals(float a, float b) {
|
||||
return (fabsf(a - b) < 1e-6);
|
||||
}
|
||||
|
||||
bool
|
||||
SharedFrameMetricsHelper::UpdateFromCompositorFrameMetrics(
|
||||
ContainerLayer* aLayer,
|
||||
bool aHasPendingNewThebesContent,
|
||||
bool aLowPrecision,
|
||||
ScreenRect& aCompositionBounds,
|
||||
CSSToScreenScale& aZoom)
|
||||
{
|
||||
MOZ_ASSERT(aLayer);
|
||||
|
||||
CompositorChild* compositor = CompositorChild::Get();
|
||||
|
||||
if (!compositor) {
|
||||
FindFallbackContentFrameMetrics(aLayer, aCompositionBounds, aZoom);
|
||||
return false;
|
||||
}
|
||||
|
||||
const FrameMetrics& contentMetrics = aLayer->GetFrameMetrics();
|
||||
FrameMetrics compositorMetrics;
|
||||
|
||||
if (!compositor->LookupCompositorFrameMetrics(contentMetrics.mScrollId,
|
||||
compositorMetrics)) {
|
||||
FindFallbackContentFrameMetrics(aLayer, aCompositionBounds, aZoom);
|
||||
return false;
|
||||
}
|
||||
|
||||
aCompositionBounds = ScreenRect(compositorMetrics.mCompositionBounds);
|
||||
aZoom = compositorMetrics.mZoom;
|
||||
|
||||
// Reset the checkerboard risk flag when switching to low precision
|
||||
// rendering.
|
||||
if (aLowPrecision && !mLastProgressiveUpdateWasLowPrecision) {
|
||||
// Skip low precision rendering until we're at risk of checkerboarding.
|
||||
if (!mProgressiveUpdateWasInDanger) {
|
||||
return true;
|
||||
}
|
||||
mProgressiveUpdateWasInDanger = false;
|
||||
}
|
||||
mLastProgressiveUpdateWasLowPrecision = aLowPrecision;
|
||||
|
||||
// Always abort updates if the resolution has changed. There's no use
|
||||
// in drawing at the incorrect resolution.
|
||||
if (!FuzzyEquals(compositorMetrics.mZoom.scale, contentMetrics.mZoom.scale)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Never abort drawing if we can't be sure we've sent a more recent
|
||||
// display-port. If we abort updating when we shouldn't, we can end up
|
||||
// with blank regions on the screen and we open up the risk of entering
|
||||
// an endless updating cycle.
|
||||
if (fabsf(contentMetrics.mScrollOffset.x - compositorMetrics.mScrollOffset.x) <= 2 &&
|
||||
fabsf(contentMetrics.mScrollOffset.y - compositorMetrics.mScrollOffset.y) <= 2 &&
|
||||
fabsf(contentMetrics.mDisplayPort.x - compositorMetrics.mDisplayPort.x) <= 2 &&
|
||||
fabsf(contentMetrics.mDisplayPort.y - compositorMetrics.mDisplayPort.y) <= 2 &&
|
||||
fabsf(contentMetrics.mDisplayPort.width - compositorMetrics.mDisplayPort.width) <= 2 &&
|
||||
fabsf(contentMetrics.mDisplayPort.height - compositorMetrics.mDisplayPort.height)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// When not a low precision pass and the page is in danger of checker boarding
|
||||
// abort update.
|
||||
if (!aLowPrecision && !mProgressiveUpdateWasInDanger) {
|
||||
if (AboutToCheckerboard(contentMetrics, compositorMetrics)) {
|
||||
mProgressiveUpdateWasInDanger = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Abort drawing stale low-precision content if there's a more recent
|
||||
// display-port in the pipeline.
|
||||
if (aLowPrecision && !aHasPendingNewThebesContent) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
SharedFrameMetricsHelper::FindFallbackContentFrameMetrics(ContainerLayer* aLayer,
|
||||
ScreenRect& aCompositionBounds,
|
||||
CSSToScreenScale& aZoom) {
|
||||
if (!aLayer) {
|
||||
return;
|
||||
}
|
||||
|
||||
ContainerLayer* layer = aLayer;
|
||||
const FrameMetrics* contentMetrics = &(layer->GetFrameMetrics());
|
||||
|
||||
// Walk up the layer tree until a valid composition bounds is found
|
||||
while (layer && contentMetrics->mCompositionBounds.IsEmpty()) {
|
||||
layer = layer->GetParent();
|
||||
contentMetrics = layer ? &(layer->GetFrameMetrics()) : contentMetrics;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!contentMetrics->mCompositionBounds.IsEmpty());
|
||||
|
||||
aCompositionBounds = ScreenRect(contentMetrics->mCompositionBounds);
|
||||
aZoom = contentMetrics->mZoom;
|
||||
return;
|
||||
}
|
||||
|
||||
bool
|
||||
SharedFrameMetricsHelper::AboutToCheckerboard(const FrameMetrics& aContentMetrics,
|
||||
const FrameMetrics& aCompositorMetrics)
|
||||
{
|
||||
return !aContentMetrics.mDisplayPort.Contains(aCompositorMetrics.CalculateCompositedRectInCssPixels() - aCompositorMetrics.mScrollOffset);
|
||||
}
|
||||
|
||||
BasicTiledLayerBuffer::BasicTiledLayerBuffer(ClientTiledThebesLayer* aThebesLayer,
|
||||
ClientLayerManager* aManager)
|
||||
ClientLayerManager* aManager,
|
||||
SharedFrameMetricsHelper* aHelper)
|
||||
: mThebesLayer(aThebesLayer)
|
||||
, mManager(aManager)
|
||||
, mLastPaintOpaque(false)
|
||||
, mSharedFrameMetricsHelper(aHelper)
|
||||
{
|
||||
}
|
||||
|
||||
@ -193,7 +321,8 @@ BasicTiledLayerBuffer::GetSurfaceDescriptorTiles()
|
||||
|
||||
/* static */ BasicTiledLayerBuffer
|
||||
BasicTiledLayerBuffer::OpenDescriptor(ISurfaceAllocator *aAllocator,
|
||||
const SurfaceDescriptorTiles& aDescriptor)
|
||||
const SurfaceDescriptorTiles& aDescriptor,
|
||||
SharedFrameMetricsHelper* aHelper)
|
||||
{
|
||||
return BasicTiledLayerBuffer(aAllocator,
|
||||
aDescriptor.validRegion(),
|
||||
@ -201,7 +330,8 @@ BasicTiledLayerBuffer::OpenDescriptor(ISurfaceAllocator *aAllocator,
|
||||
aDescriptor.tiles(),
|
||||
aDescriptor.retainedWidth(),
|
||||
aDescriptor.retainedHeight(),
|
||||
aDescriptor.resolution());
|
||||
aDescriptor.resolution(),
|
||||
aHelper);
|
||||
}
|
||||
|
||||
void
|
||||
@ -474,9 +604,25 @@ BasicTiledLayerBuffer::ComputeProgressiveUpdateRegion(const nsIntRegion& aInvali
|
||||
// caused by there being an incoming, more relevant paint.
|
||||
ScreenRect compositionBounds;
|
||||
CSSToScreenScale zoom;
|
||||
if (mManager->ProgressiveUpdateCallback(!staleRegion.Contains(aInvalidRegion),
|
||||
compositionBounds, zoom,
|
||||
!drawingLowPrecision)) {
|
||||
#if defined(MOZ_WIDGET_ANDROID)
|
||||
bool abortPaint = mManager->ProgressiveUpdateCallback(!staleRegion.Contains(aInvalidRegion),
|
||||
compositionBounds, zoom,
|
||||
!drawingLowPrecision);
|
||||
#else
|
||||
MOZ_ASSERT(mSharedFrameMetricsHelper);
|
||||
|
||||
ContainerLayer* parent = mThebesLayer->AsLayer()->GetParent();
|
||||
|
||||
bool abortPaint =
|
||||
mSharedFrameMetricsHelper->UpdateFromCompositorFrameMetrics(
|
||||
parent,
|
||||
!staleRegion.Contains(aInvalidRegion),
|
||||
drawingLowPrecision,
|
||||
compositionBounds,
|
||||
zoom);
|
||||
#endif
|
||||
|
||||
if (abortPaint) {
|
||||
// We ignore if front-end wants to abort if this is the first,
|
||||
// non-low-precision paint, as in that situation, we're about to override
|
||||
// front-end's page/viewport metrics.
|
||||
|
@ -168,6 +168,47 @@ struct BasicTiledLayerPaintData {
|
||||
class ClientTiledThebesLayer;
|
||||
class ClientLayerManager;
|
||||
|
||||
class SharedFrameMetricsHelper
|
||||
{
|
||||
public:
|
||||
SharedFrameMetricsHelper();
|
||||
~SharedFrameMetricsHelper();
|
||||
|
||||
/**
|
||||
* This is called by the BasicTileLayer to determine if it is still interested
|
||||
* in the update of this display-port to continue. We can return true here
|
||||
* to abort the current update and continue with any subsequent ones. This
|
||||
* is useful for slow-to-render pages when the display-port starts lagging
|
||||
* behind enough that continuing to draw it is wasted effort.
|
||||
*/
|
||||
bool UpdateFromCompositorFrameMetrics(ContainerLayer* aLayer,
|
||||
bool aHasPendingNewThebesContent,
|
||||
bool aLowPrecision,
|
||||
ScreenRect& aCompositionBounds,
|
||||
CSSToScreenScale& aZoom);
|
||||
|
||||
/**
|
||||
* When a shared FrameMetrics can not be found for a given layer,
|
||||
* this function is used to find the first non-empty composition bounds
|
||||
* by traversing up the layer tree.
|
||||
*/
|
||||
void FindFallbackContentFrameMetrics(ContainerLayer* aLayer,
|
||||
ScreenRect& aCompositionBounds,
|
||||
CSSToScreenScale& aZoom);
|
||||
/**
|
||||
* Determines if the compositor's upcoming composition bounds has fallen
|
||||
* outside of the contents display port. If it has then the compositor
|
||||
* will start to checker board. Checker boarding is when the compositor
|
||||
* tries to composite a tile and it is not available. Historically
|
||||
* a tile with a checker board pattern was used. Now a blank tile is used.
|
||||
*/
|
||||
bool AboutToCheckerboard(const FrameMetrics& aContentMetrics,
|
||||
const FrameMetrics& aCompositorMetrics);
|
||||
private:
|
||||
bool mLastProgressiveUpdateWasLowPrecision;
|
||||
bool mProgressiveUpdateWasInDanger;
|
||||
};
|
||||
|
||||
/**
|
||||
* Provide an instance of TiledLayerBuffer backed by image surfaces.
|
||||
* This buffer provides an implementation to ValidateTile using a
|
||||
@ -181,11 +222,13 @@ class BasicTiledLayerBuffer
|
||||
|
||||
public:
|
||||
BasicTiledLayerBuffer(ClientTiledThebesLayer* aThebesLayer,
|
||||
ClientLayerManager* aManager);
|
||||
ClientLayerManager* aManager,
|
||||
SharedFrameMetricsHelper* aHelper);
|
||||
BasicTiledLayerBuffer()
|
||||
: mThebesLayer(nullptr)
|
||||
, mManager(nullptr)
|
||||
, mLastPaintOpaque(false)
|
||||
, mSharedFrameMetricsHelper(nullptr)
|
||||
{}
|
||||
|
||||
BasicTiledLayerBuffer(ISurfaceAllocator* aAllocator,
|
||||
@ -194,8 +237,10 @@ public:
|
||||
const InfallibleTArray<TileDescriptor>& aTiles,
|
||||
int aRetainedWidth,
|
||||
int aRetainedHeight,
|
||||
float aResolution)
|
||||
float aResolution,
|
||||
SharedFrameMetricsHelper* aHelper)
|
||||
{
|
||||
mSharedFrameMetricsHelper = aHelper;
|
||||
mValidRegion = aValidRegion;
|
||||
mPaintedRegion = aPaintedRegion;
|
||||
mRetainedWidth = aRetainedWidth;
|
||||
@ -249,7 +294,8 @@ public:
|
||||
SurfaceDescriptorTiles GetSurfaceDescriptorTiles();
|
||||
|
||||
static BasicTiledLayerBuffer OpenDescriptor(ISurfaceAllocator* aAllocator,
|
||||
const SurfaceDescriptorTiles& aDescriptor);
|
||||
const SurfaceDescriptorTiles& aDescriptor,
|
||||
SharedFrameMetricsHelper* aHelper);
|
||||
|
||||
protected:
|
||||
BasicTiledLayerTile ValidateTile(BasicTiledLayerTile aTile,
|
||||
@ -283,6 +329,7 @@ private:
|
||||
nsRefPtr<gfxImageSurface> mSinglePaintBuffer;
|
||||
RefPtr<gfx::DrawTarget> mSinglePaintDrawTarget;
|
||||
nsIntPoint mSinglePaintBufferOffset;
|
||||
SharedFrameMetricsHelper* mSharedFrameMetricsHelper;
|
||||
|
||||
BasicTiledLayerTile ValidateTileInternal(BasicTiledLayerTile aTile,
|
||||
const nsIntPoint& aTileOrigin,
|
||||
@ -341,6 +388,7 @@ public:
|
||||
void LockCopyAndWrite(TiledBufferType aType);
|
||||
|
||||
private:
|
||||
SharedFrameMetricsHelper mSharedFrameMetricsHelper;
|
||||
BasicTiledLayerBuffer mTiledBuffer;
|
||||
BasicTiledLayerBuffer mLowPrecisionTiledBuffer;
|
||||
};
|
||||
|
@ -156,6 +156,7 @@ APZCTreeManager::UpdatePanZoomControllerTree(CompositorParent* aCompositor,
|
||||
apzc = new AsyncPanZoomController(aLayersId, this, state->mController,
|
||||
AsyncPanZoomController::USE_GESTURE_DETECTOR);
|
||||
apzc->SetCompositorParent(aCompositor);
|
||||
apzc->SetCrossProcessCompositorParent(state->mCrossProcessParent);
|
||||
} else {
|
||||
// If there was already an APZC for the layer clear the tree pointers
|
||||
// so that it doesn't continue pointing to APZCs that should no longer
|
||||
|
@ -80,13 +80,13 @@ TiledContentHost::PaintedTiledLayerBuffer(ISurfaceAllocator* aAllocator,
|
||||
const SurfaceDescriptorTiles& aTiledDescriptor)
|
||||
{
|
||||
if (aTiledDescriptor.resolution() < 1) {
|
||||
mLowPrecisionMainMemoryTiledBuffer = BasicTiledLayerBuffer::OpenDescriptor(aAllocator, aTiledDescriptor);
|
||||
mLowPrecisionMainMemoryTiledBuffer = BasicTiledLayerBuffer::OpenDescriptor(aAllocator, aTiledDescriptor, nullptr);
|
||||
mLowPrecisionRegionToUpload.Or(mLowPrecisionRegionToUpload,
|
||||
mLowPrecisionMainMemoryTiledBuffer.GetPaintedRegion());
|
||||
mLowPrecisionMainMemoryTiledBuffer.ClearPaintedRegion();
|
||||
mPendingLowPrecisionUpload = true;
|
||||
} else {
|
||||
mMainMemoryTiledBuffer = BasicTiledLayerBuffer::OpenDescriptor(aAllocator, aTiledDescriptor);
|
||||
mMainMemoryTiledBuffer = BasicTiledLayerBuffer::OpenDescriptor(aAllocator, aTiledDescriptor, nullptr);
|
||||
mRegionToUpload.Or(mRegionToUpload, mMainMemoryTiledBuffer.GetPaintedRegion());
|
||||
mMainMemoryTiledBuffer.ClearPaintedRegion();
|
||||
mPendingUpload = true;
|
||||
|
@ -14,10 +14,12 @@
|
||||
#include "FrameMetrics.h" // for FrameMetrics, etc
|
||||
#include "GestureEventListener.h" // for GestureEventListener
|
||||
#include "InputData.h" // for MultiTouchInput, etc
|
||||
#include "LayerTransactionParent.h" // for LayerTransactionParent
|
||||
#include "Units.h" // for CSSRect, CSSPoint, etc
|
||||
#include "base/message_loop.h" // for MessageLoop
|
||||
#include "base/task.h" // for NewRunnableMethod, etc
|
||||
#include "base/tracked.h" // for FROM_HERE
|
||||
#include "gfxPlatform.h" // for gfxPlatform::UseProgressiveTilePainting
|
||||
#include "gfxTypes.h" // for gfxFloat
|
||||
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
|
||||
#include "mozilla/BasicEvents.h" // for Modifiers, MODIFIER_*
|
||||
@ -38,8 +40,10 @@
|
||||
#include "mozilla/layers/AsyncCompositionManager.h" // for ViewTransform
|
||||
#include "mozilla/layers/Axis.h" // for AxisX, AxisY, Axis, etc
|
||||
#include "mozilla/layers/GeckoContentController.h"
|
||||
#include "mozilla/layers/PCompositorParent.h" // for PCompositorParent
|
||||
#include "mozilla/layers/TaskThrottler.h" // for TaskThrottler
|
||||
#include "mozilla/mozalloc.h" // for operator new, etc
|
||||
#include "mozilla/unused.h" // for unused
|
||||
#include "nsAlgorithm.h" // for clamped
|
||||
#include "nsAutoPtr.h" // for nsRefPtr
|
||||
#include "nsCOMPtr.h" // for already_AddRefed
|
||||
@ -53,6 +57,7 @@
|
||||
#include "nsTArray.h" // for nsTArray, nsTArray_Impl, etc
|
||||
#include "nsThreadUtils.h" // for NS_IsMainThread
|
||||
#include "nsTraceRefcnt.h" // for MOZ_COUNT_CTOR, etc
|
||||
#include "SharedMemoryBasic.h" // for SharedMemoryBasic
|
||||
|
||||
// #define APZC_ENABLE_RENDERTRACE
|
||||
|
||||
@ -242,6 +247,11 @@ static bool gAsyncZoomDisabled = false;
|
||||
*/
|
||||
static bool gCrossSlideEnabled = false;
|
||||
|
||||
/**
|
||||
* Pref that enables progressive tile painting
|
||||
*/
|
||||
static bool gUseProgressiveTilePainting = false;
|
||||
|
||||
/**
|
||||
* Is aAngle within the given threshold of the horizontal axis?
|
||||
* @param aAngle an angle in radians in the range [0, pi]
|
||||
@ -272,6 +282,9 @@ static inline void LogRendertraceRect(const ScrollableLayerGuid& aGuid, const ch
|
||||
|
||||
static TimeStamp sFrameTime;
|
||||
|
||||
// Counter used to give each APZC a unique id
|
||||
static uint32_t sAsyncPanZoomControllerCount = 0;
|
||||
|
||||
static TimeStamp
|
||||
GetFrameTime() {
|
||||
if (sFrameTime.IsNull()) {
|
||||
@ -361,6 +374,7 @@ AsyncPanZoomController::InitializeGlobalState()
|
||||
Preferences::AddBoolVarCache(&gAsyncZoomDisabled, "apz.asynczoom.disabled", gAsyncZoomDisabled);
|
||||
Preferences::AddBoolVarCache(&gCrossSlideEnabled, "apz.cross_slide.enabled", gCrossSlideEnabled);
|
||||
Preferences::AddIntVarCache(&gAxisLockMode, "apz.axis_lock_mode", gAxisLockMode);
|
||||
gUseProgressiveTilePainting = gfxPlatform::UseProgressiveTilePainting();
|
||||
|
||||
gComputedTimingFunction = new ComputedTimingFunction();
|
||||
gComputedTimingFunction->Init(
|
||||
@ -373,6 +387,7 @@ AsyncPanZoomController::AsyncPanZoomController(uint64_t aLayersId,
|
||||
GeckoContentController* aGeckoContentController,
|
||||
GestureBehavior aGestures)
|
||||
: mLayersId(aLayersId),
|
||||
mCrossProcessCompositorParent(nullptr),
|
||||
mPaintThrottler(GetFrameTime()),
|
||||
mGeckoContentController(aGeckoContentController),
|
||||
mRefPtrMonitor("RefPtrMonitor"),
|
||||
@ -390,7 +405,10 @@ AsyncPanZoomController::AsyncPanZoomController(uint64_t aLayersId,
|
||||
mCurrentAsyncScrollOffset(0, 0),
|
||||
mAsyncScrollTimeoutTask(nullptr),
|
||||
mHandlingTouchQueue(false),
|
||||
mTreeManager(aTreeManager)
|
||||
mTreeManager(aTreeManager),
|
||||
mAPZCId(sAsyncPanZoomControllerCount++),
|
||||
mSharedFrameMetricsBuffer(nullptr),
|
||||
mSharedLock(nullptr)
|
||||
{
|
||||
MOZ_COUNT_CTOR(AsyncPanZoomController);
|
||||
|
||||
@ -403,6 +421,18 @@ AsyncPanZoomController::AsyncPanZoomController(uint64_t aLayersId,
|
||||
}
|
||||
|
||||
AsyncPanZoomController::~AsyncPanZoomController() {
|
||||
|
||||
PCompositorParent* compositor =
|
||||
(mCrossProcessCompositorParent ? mCrossProcessCompositorParent : mCompositorParent.get());
|
||||
|
||||
// Only send the release message if the SharedFrameMetrics has been created.
|
||||
if (compositor && mSharedFrameMetricsBuffer) {
|
||||
unused << compositor->SendReleaseSharedCompositorFrameMetrics(mFrameMetrics.mScrollId, mAPZCId);
|
||||
}
|
||||
|
||||
delete mSharedFrameMetricsBuffer;
|
||||
delete mSharedLock;
|
||||
|
||||
MOZ_COUNT_DTOR(AsyncPanZoomController);
|
||||
}
|
||||
|
||||
@ -548,6 +578,7 @@ nsEventStatus AsyncPanZoomController::OnTouchStart(const MultiTouchInput& aEvent
|
||||
ReentrantMonitorAutoEnter lock(mMonitor);
|
||||
RequestContentRepaint();
|
||||
ScheduleComposite();
|
||||
UpdateSharedCompositorFrameMetrics();
|
||||
}
|
||||
// Fall through.
|
||||
case FLING:
|
||||
@ -652,6 +683,7 @@ nsEventStatus AsyncPanZoomController::OnTouchEnd(const MultiTouchInput& aEvent)
|
||||
{
|
||||
ReentrantMonitorAutoEnter lock(mMonitor);
|
||||
RequestContentRepaint();
|
||||
UpdateSharedCompositorFrameMetrics();
|
||||
}
|
||||
mX.EndTouch();
|
||||
mY.EndTouch();
|
||||
@ -760,6 +792,7 @@ nsEventStatus AsyncPanZoomController::OnScale(const PinchGestureInput& aEvent) {
|
||||
ScheduleComposite();
|
||||
// We don't want to redraw on every scale, so don't use
|
||||
// RequestContentRepaint()
|
||||
UpdateSharedCompositorFrameMetrics();
|
||||
}
|
||||
|
||||
mLastZoomFocus = focusPoint;
|
||||
@ -783,6 +816,7 @@ nsEventStatus AsyncPanZoomController::OnScaleEnd(const PinchGestureInput& aEvent
|
||||
ReentrantMonitorAutoEnter lock(mMonitor);
|
||||
ScheduleComposite();
|
||||
RequestContentRepaint();
|
||||
UpdateSharedCompositorFrameMetrics();
|
||||
}
|
||||
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
@ -996,6 +1030,7 @@ void AsyncPanZoomController::AttemptScroll(const ScreenPoint& aStartPoint,
|
||||
if (timePaintDelta.ToMilliseconds() > gPanRepaintInterval) {
|
||||
RequestContentRepaint();
|
||||
}
|
||||
UpdateSharedCompositorFrameMetrics();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1104,6 +1139,10 @@ void AsyncPanZoomController::SetCompositorParent(CompositorParent* aCompositorPa
|
||||
mCompositorParent = aCompositorParent;
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::SetCrossProcessCompositorParent(PCompositorParent* aCrossProcessCompositorParent) {
|
||||
mCrossProcessCompositorParent = aCrossProcessCompositorParent;
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::ScrollBy(const CSSPoint& aOffset) {
|
||||
mFrameMetrics.mScrollOffset += aOffset;
|
||||
}
|
||||
@ -1332,6 +1371,7 @@ bool AsyncPanZoomController::UpdateAnimation(const TimeStamp& aSampleTime)
|
||||
SendAsyncScrollEvent();
|
||||
RequestContentRepaint();
|
||||
}
|
||||
UpdateSharedCompositorFrameMetrics();
|
||||
mLastSampleTime = aSampleTime;
|
||||
return true;
|
||||
}
|
||||
@ -1450,6 +1490,7 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aLayerMetri
|
||||
mY.CancelTouch();
|
||||
|
||||
mFrameMetrics = aLayerMetrics;
|
||||
ShareCompositorFrameMetrics();
|
||||
SetState(NOTHING);
|
||||
} else {
|
||||
// If we're not taking the aLayerMetrics wholesale we still need to pull
|
||||
@ -1477,6 +1518,7 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aLayerMetri
|
||||
if (needContentRepaint) {
|
||||
RequestContentRepaint();
|
||||
}
|
||||
UpdateSharedCompositorFrameMetrics();
|
||||
}
|
||||
|
||||
const FrameMetrics& AsyncPanZoomController::GetFrameMetrics() {
|
||||
@ -1709,5 +1751,64 @@ ScrollableLayerGuid AsyncPanZoomController::GetGuid()
|
||||
return ScrollableLayerGuid(mLayersId, mFrameMetrics);
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::UpdateSharedCompositorFrameMetrics()
|
||||
{
|
||||
mMonitor.AssertCurrentThreadIn();
|
||||
|
||||
FrameMetrics* frame = mSharedFrameMetricsBuffer ?
|
||||
static_cast<FrameMetrics*>(mSharedFrameMetricsBuffer->memory()) : nullptr;
|
||||
|
||||
if (gUseProgressiveTilePainting && frame && mSharedLock) {
|
||||
mSharedLock->Lock();
|
||||
*frame = mFrameMetrics;
|
||||
mSharedLock->Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::ShareCompositorFrameMetrics() {
|
||||
|
||||
PCompositorParent* compositor =
|
||||
(mCrossProcessCompositorParent ? mCrossProcessCompositorParent : mCompositorParent.get());
|
||||
|
||||
// Only create the shared memory buffer if it hasn't already been created,
|
||||
// we are using progressive tile painting, and we have a
|
||||
// compositor to pass the shared memory back to the content process/thread.
|
||||
if (!mSharedFrameMetricsBuffer && gUseProgressiveTilePainting && compositor) {
|
||||
|
||||
// Create shared memory and initialize it with the current FrameMetrics value
|
||||
mSharedFrameMetricsBuffer = new ipc::SharedMemoryBasic;
|
||||
FrameMetrics* frame = nullptr;
|
||||
mSharedFrameMetricsBuffer->Create(sizeof(FrameMetrics));
|
||||
mSharedFrameMetricsBuffer->Map(sizeof(FrameMetrics));
|
||||
frame = static_cast<FrameMetrics*>(mSharedFrameMetricsBuffer->memory());
|
||||
|
||||
if (frame) {
|
||||
|
||||
{ // scope the monitor, only needed to copy the FrameMetrics.
|
||||
ReentrantMonitorAutoEnter lock(mMonitor);
|
||||
*frame = mFrameMetrics;
|
||||
}
|
||||
|
||||
// Get the process id of the content process
|
||||
base::ProcessId pId = compositor->OtherProcess();
|
||||
ipc::SharedMemoryBasic::Handle mem = ipc::SharedMemoryBasic::NULLHandle();
|
||||
|
||||
// Get the shared memory handle to share with the content process
|
||||
mSharedFrameMetricsBuffer->ShareToProcess(pId, &mem);
|
||||
|
||||
// Get the cross process mutex handle to share with the content process
|
||||
mSharedLock = new CrossProcessMutex("AsyncPanZoomControlLock");
|
||||
CrossProcessMutexHandle handle = mSharedLock->ShareToProcess(pId);
|
||||
|
||||
// Send the shared memory handle and cross process handle to the content
|
||||
// process by an asynchronous ipc call. Include the APZC unique ID
|
||||
// so the content process know which APZC sent this shared FrameMetrics.
|
||||
if (!compositor->SendSharedCompositorFrameMetrics(mem, handle, mAPZCId)) {
|
||||
APZC_LOG("Failed to share FrameMetrics with content process.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
#ifndef mozilla_layers_AsyncPanZoomController_h
|
||||
#define mozilla_layers_AsyncPanZoomController_h
|
||||
|
||||
#include "CrossProcessMutex.h"
|
||||
#include "GeckoContentController.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/EventForwards.h"
|
||||
@ -22,12 +23,20 @@
|
||||
#include "base/message_loop.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace ipc {
|
||||
|
||||
class SharedMemoryBasic;
|
||||
|
||||
}
|
||||
|
||||
namespace layers {
|
||||
|
||||
struct ScrollableLayerGuid;
|
||||
class CompositorParent;
|
||||
class GestureEventListener;
|
||||
class ContainerLayer;
|
||||
class PCompositorParent;
|
||||
class ViewTransform;
|
||||
class APZCTreeManager;
|
||||
class AsyncPanZoomAnimation;
|
||||
@ -180,6 +189,14 @@ public:
|
||||
*/
|
||||
void SetCompositorParent(CompositorParent* aCompositorParent);
|
||||
|
||||
/**
|
||||
* The platform implementation must set the cross process compositor if
|
||||
* there is one associated with the layer tree. The cross process compositor
|
||||
* allows the APZC to share its FrameMetrics with the content process.
|
||||
* The shared FrameMetrics is used in progressive paint updates.
|
||||
*/
|
||||
void SetCrossProcessCompositorParent(PCompositorParent* aCrossProcessCompositorParent);
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// These methods can be called from any thread.
|
||||
//
|
||||
@ -544,6 +561,7 @@ private:
|
||||
|
||||
uint64_t mLayersId;
|
||||
nsRefPtr<CompositorParent> mCompositorParent;
|
||||
PCompositorParent* mCrossProcessCompositorParent;
|
||||
TaskThrottler mPaintThrottler;
|
||||
|
||||
/* Access to the following two fields is protected by the mRefPtrMonitor,
|
||||
@ -704,6 +722,9 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
/* Unique id assigned to each APZC. Used with ViewID to uniquely identify
|
||||
* shared FrameMeterics used in progressive tile painting. */
|
||||
const uint32_t mAPZCId;
|
||||
/* This is the visible region of the layer that this APZC corresponds to, in
|
||||
* that layer's screen pixels (the same coordinate system in which this APZC
|
||||
* receives events in ReceiveInputEvent()). */
|
||||
@ -713,6 +734,20 @@ private:
|
||||
gfx3DMatrix mAncestorTransform;
|
||||
/* This is the CSS transform for this APZC's layer. */
|
||||
gfx3DMatrix mCSSTransform;
|
||||
|
||||
ipc::SharedMemoryBasic* mSharedFrameMetricsBuffer;
|
||||
CrossProcessMutex* mSharedLock;
|
||||
/**
|
||||
* Called when ever mFrameMetrics is updated so that if it is being
|
||||
* shared with the content process the shared FrameMetrics may be updated.
|
||||
*/
|
||||
void UpdateSharedCompositorFrameMetrics();
|
||||
/**
|
||||
* Create a shared memory buffer for containing the FrameMetrics and
|
||||
* a CrossProcessMutex that may be shared with the content process
|
||||
* for use in progressive tiled update calculations.
|
||||
*/
|
||||
void ShareCompositorFrameMetrics();
|
||||
};
|
||||
|
||||
class AsyncPanZoomAnimation {
|
||||
|
@ -52,6 +52,18 @@ CompositorChild::Destroy()
|
||||
SendStop();
|
||||
}
|
||||
|
||||
bool
|
||||
CompositorChild::LookupCompositorFrameMetrics(const FrameMetrics::ViewID aId,
|
||||
FrameMetrics& aFrame)
|
||||
{
|
||||
SharedFrameMetricsData* data = mFrameMetricsTable.Get(aId);
|
||||
if (data) {
|
||||
data->CopyFrameMetrics(&aFrame);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*static*/ PCompositorChild*
|
||||
CompositorChild::Create(Transport* aTransport, ProcessId aOtherProcess)
|
||||
{
|
||||
@ -73,7 +85,7 @@ CompositorChild::Create(Transport* aTransport, ProcessId aOtherProcess)
|
||||
return sCompositor = child.forget().get();
|
||||
}
|
||||
|
||||
/*static*/ PCompositorChild*
|
||||
/*static*/ CompositorChild*
|
||||
CompositorChild::Get()
|
||||
{
|
||||
// This is only expected to be used in child processes.
|
||||
@ -131,6 +143,80 @@ CompositorChild::ActorDestroy(ActorDestroyReason aWhy)
|
||||
NewRunnableMethod(this, &CompositorChild::Release));
|
||||
}
|
||||
|
||||
bool
|
||||
CompositorChild::RecvSharedCompositorFrameMetrics(
|
||||
const mozilla::ipc::SharedMemoryBasic::Handle& metrics,
|
||||
const CrossProcessMutexHandle& handle,
|
||||
const uint32_t& aAPZCId)
|
||||
{
|
||||
SharedFrameMetricsData* data = new SharedFrameMetricsData(metrics, handle, aAPZCId);
|
||||
mFrameMetricsTable.Put(data->GetViewID(), data);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CompositorChild::RecvReleaseSharedCompositorFrameMetrics(
|
||||
const ViewID& aId,
|
||||
const uint32_t& aAPZCId)
|
||||
{
|
||||
SharedFrameMetricsData* data = mFrameMetricsTable.Get(aId);
|
||||
// The SharedFrameMetricsData may have been removed previously if
|
||||
// a SharedFrameMetricsData with the same ViewID but later APZCId had
|
||||
// been store and over wrote it.
|
||||
if (data && (data->GetAPZCId() == aAPZCId)) {
|
||||
mFrameMetricsTable.Remove(aId);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
CompositorChild::SharedFrameMetricsData::SharedFrameMetricsData(
|
||||
const ipc::SharedMemoryBasic::Handle& metrics,
|
||||
const CrossProcessMutexHandle& handle,
|
||||
const uint32_t& aAPZCId) :
|
||||
mBuffer(nullptr),
|
||||
mMutex(nullptr),
|
||||
mAPZCId(aAPZCId)
|
||||
{
|
||||
mBuffer = new ipc::SharedMemoryBasic(metrics);
|
||||
mBuffer->Map(sizeof(FrameMetrics));
|
||||
mMutex = new CrossProcessMutex(handle);
|
||||
MOZ_COUNT_CTOR(SharedFrameMetricsData);
|
||||
}
|
||||
|
||||
CompositorChild::SharedFrameMetricsData::~SharedFrameMetricsData()
|
||||
{
|
||||
// When the hash table deletes the class, delete
|
||||
// the shared memory and mutex.
|
||||
delete mMutex;
|
||||
delete mBuffer;
|
||||
MOZ_COUNT_DTOR(SharedFrameMetricsData);
|
||||
}
|
||||
|
||||
void
|
||||
CompositorChild::SharedFrameMetricsData::CopyFrameMetrics(FrameMetrics* aFrame)
|
||||
{
|
||||
FrameMetrics* frame = static_cast<FrameMetrics*>(mBuffer->memory());
|
||||
MOZ_ASSERT(frame);
|
||||
mMutex->Lock();
|
||||
*aFrame = *frame;
|
||||
mMutex->Unlock();
|
||||
}
|
||||
|
||||
FrameMetrics::ViewID
|
||||
CompositorChild::SharedFrameMetricsData::GetViewID()
|
||||
{
|
||||
FrameMetrics* frame = static_cast<FrameMetrics*>(mBuffer->memory());
|
||||
MOZ_ASSERT(frame);
|
||||
// Not locking to read of mScrollId since it should not change after being
|
||||
// initially set.
|
||||
return frame->mScrollId;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
CompositorChild::SharedFrameMetricsData::GetAPZCId()
|
||||
{
|
||||
return mAPZCId;
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
@ -13,7 +13,9 @@
|
||||
#include "mozilla/ipc/ProtocolUtils.h"
|
||||
#include "mozilla/layers/PCompositorChild.h"
|
||||
#include "nsAutoPtr.h" // for nsRefPtr
|
||||
#include "nsClassHashtable.h" // for nsClassHashtable
|
||||
#include "nsCOMPtr.h" // for nsCOMPtr
|
||||
#include "nsHashKeys.h" // for nsUint64HashKey
|
||||
#include "nsISupportsImpl.h" // for NS_INLINE_DECL_REFCOUNTING
|
||||
|
||||
class nsIObserver;
|
||||
@ -23,6 +25,7 @@ namespace layers {
|
||||
|
||||
class ClientLayerManager;
|
||||
class CompositorParent;
|
||||
class FrameMetrics;
|
||||
|
||||
class CompositorChild : public PCompositorChild
|
||||
{
|
||||
@ -33,6 +36,13 @@ public:
|
||||
|
||||
void Destroy();
|
||||
|
||||
/**
|
||||
* Lookup the FrameMetrics shared by the compositor process with the
|
||||
* associated FrameMetrics::ViewID. The returned FrameMetrics is used
|
||||
* in progressive paint calculations.
|
||||
*/
|
||||
bool LookupCompositorFrameMetrics(const FrameMetrics::ViewID aId, FrameMetrics&);
|
||||
|
||||
/**
|
||||
* We're asked to create a new Compositor in response to an Opens()
|
||||
* or Bridge() request from our parent process. The Transport is to
|
||||
@ -41,7 +51,7 @@ public:
|
||||
static PCompositorChild*
|
||||
Create(Transport* aTransport, ProcessId aOtherProcess);
|
||||
|
||||
static PCompositorChild* Get();
|
||||
static CompositorChild* Get();
|
||||
|
||||
static bool ChildProcessHasCompositor() { return sCompositor != nullptr; }
|
||||
|
||||
@ -58,10 +68,44 @@ protected:
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool RecvSharedCompositorFrameMetrics(const mozilla::ipc::SharedMemoryBasic::Handle& metrics,
|
||||
const CrossProcessMutexHandle& handle,
|
||||
const uint32_t& aAPZCId) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool RecvReleaseSharedCompositorFrameMetrics(const ViewID& aId,
|
||||
const uint32_t& aAPZCId) MOZ_OVERRIDE;
|
||||
|
||||
private:
|
||||
// Class used to store the shared FrameMetrics, mutex, and APZCId in a hash table
|
||||
class SharedFrameMetricsData {
|
||||
public:
|
||||
SharedFrameMetricsData(
|
||||
const mozilla::ipc::SharedMemoryBasic::Handle& metrics,
|
||||
const CrossProcessMutexHandle& handle,
|
||||
const uint32_t& aAPZCId);
|
||||
|
||||
~SharedFrameMetricsData();
|
||||
|
||||
void CopyFrameMetrics(FrameMetrics* aFrame);
|
||||
FrameMetrics::ViewID GetViewID();
|
||||
uint32_t GetAPZCId();
|
||||
|
||||
private:
|
||||
// Pointer to the class that allows access to the shared memory that contains
|
||||
// the shared FrameMetrics
|
||||
mozilla::ipc::SharedMemoryBasic* mBuffer;
|
||||
CrossProcessMutex* mMutex;
|
||||
// Unique ID of the APZC that is sharing the FrameMetrics
|
||||
uint32_t mAPZCId;
|
||||
};
|
||||
|
||||
nsRefPtr<ClientLayerManager> mLayerManager;
|
||||
nsCOMPtr<nsIObserver> mMemoryPressureObserver;
|
||||
|
||||
// The ViewID of the FrameMetrics is used as the key for this hash table.
|
||||
// While this should be safe to use since the ViewID is unique
|
||||
nsClassHashtable<nsUint64HashKey, SharedFrameMetricsData> mFrameMetricsTable;
|
||||
|
||||
// When we're in a child process, this is the process-global
|
||||
// compositor that we use to forward transactions directly to the
|
||||
// compositor context in another process.
|
||||
|
@ -63,6 +63,7 @@ namespace layers {
|
||||
CompositorParent::LayerTreeState::LayerTreeState()
|
||||
: mParent(nullptr)
|
||||
, mLayerManager(nullptr)
|
||||
, mCrossProcessParent(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
@ -1105,6 +1106,7 @@ CrossProcessCompositorParent::AllocPLayerTransactionParent(const nsTArray<Layers
|
||||
MOZ_ASSERT(aId != 0);
|
||||
|
||||
if (sIndirectLayerTrees[aId].mLayerManager) {
|
||||
sIndirectLayerTrees[aId].mCrossProcessParent = this;
|
||||
LayerManagerComposite* lm = sIndirectLayerTrees[aId].mLayerManager;
|
||||
*aTextureFactoryIdentifier = lm->GetCompositor()->GetTextureFactoryIdentifier();
|
||||
*aSuccess = true;
|
||||
|
@ -205,6 +205,10 @@ public:
|
||||
nsRefPtr<GeckoContentController> mController;
|
||||
CompositorParent* mParent;
|
||||
LayerManagerComposite* mLayerManager;
|
||||
// Pointer to the CrossProcessCompositorParent. Used by APZCs to share
|
||||
// their FrameMetrics with the corresponding child process that holds
|
||||
// the PCompositorChild
|
||||
PCompositorParent* mCrossProcessParent;
|
||||
TargetConfig mTargetConfig;
|
||||
};
|
||||
|
||||
|
@ -13,7 +13,11 @@ 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::LayersBackend from "mozilla/layers/LayersTypes.h";
|
||||
using mozilla::CrossProcessMutexHandle from "mozilla/ipc/CrossProcessMutex.h";
|
||||
using mozilla::ipc::SharedMemoryBasic::Handle from "mozilla/ipc/SharedMemoryBasic.h";
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
@ -81,6 +85,12 @@ parent:
|
||||
|
||||
// Notify the compositor that a region of the screen has been invalidated.
|
||||
async NotifyRegionInvalidated(nsIntRegion region);
|
||||
|
||||
child:
|
||||
// Send back Compositor Frame Metrics from APZCs so tiled layers can
|
||||
// update progressively.
|
||||
async SharedCompositorFrameMetrics(Handle metrics, CrossProcessMutexHandle mutex, uint32_t aAPZCId);
|
||||
async ReleaseSharedCompositorFrameMetrics(ViewID aId, uint32_t aAPZCId);
|
||||
};
|
||||
|
||||
} // layers
|
||||
|
Loading…
Reference in New Issue
Block a user