Bug 1922333 - Land view transition plumbing for live capture behind a default-off pref. r=view-transitions-reviewers,boris
It is mostly working, but there are some tests that hit crashes and asserts that we should sort out. For now, land it default-off. This does implement other bits that are on by default tho, like creating image frames for ::view-transition-new() pseudo-elements and so on. I think that is fine (it's just that for now they are all transparent). Differential Revision: https://phabricator.services.mozilla.com/D239382
This commit is contained in:
@@ -5,11 +5,17 @@
|
|||||||
#include "ViewTransition.h"
|
#include "ViewTransition.h"
|
||||||
|
|
||||||
#include "mozilla/gfx/2D.h"
|
#include "mozilla/gfx/2D.h"
|
||||||
|
#include "WindowRenderer.h"
|
||||||
|
#include "mozilla/layers/WebRenderLayerManager.h"
|
||||||
|
#include "mozilla/layers/RenderRootStateManager.h"
|
||||||
#include "mozilla/dom/BindContext.h"
|
#include "mozilla/dom/BindContext.h"
|
||||||
|
#include "mozilla/layers/WebRenderBridgeChild.h"
|
||||||
|
#include "mozilla/gfx/DataSurfaceHelpers.h"
|
||||||
#include "mozilla/dom/DocumentInlines.h"
|
#include "mozilla/dom/DocumentInlines.h"
|
||||||
#include "mozilla/dom/DocumentTimeline.h"
|
#include "mozilla/dom/DocumentTimeline.h"
|
||||||
#include "mozilla/dom/Promise-inl.h"
|
#include "mozilla/dom/Promise-inl.h"
|
||||||
#include "mozilla/dom/ViewTransitionBinding.h"
|
#include "mozilla/dom/ViewTransitionBinding.h"
|
||||||
|
#include "mozilla/image/WebRenderImageProvider.h"
|
||||||
#include "mozilla/webrender/WebRenderAPI.h"
|
#include "mozilla/webrender/WebRenderAPI.h"
|
||||||
#include "mozilla/AnimationEventDispatcher.h"
|
#include "mozilla/AnimationEventDispatcher.h"
|
||||||
#include "mozilla/EffectSet.h"
|
#include "mozilla/EffectSet.h"
|
||||||
@@ -18,9 +24,11 @@
|
|||||||
#include "mozilla/SVGIntegrationUtils.h"
|
#include "mozilla/SVGIntegrationUtils.h"
|
||||||
#include "mozilla/WritingModes.h"
|
#include "mozilla/WritingModes.h"
|
||||||
#include "nsDisplayList.h"
|
#include "nsDisplayList.h"
|
||||||
|
#include "nsFrameState.h"
|
||||||
#include "nsITimer.h"
|
#include "nsITimer.h"
|
||||||
#include "nsLayoutUtils.h"
|
#include "nsLayoutUtils.h"
|
||||||
#include "nsPresContext.h"
|
#include "nsPresContext.h"
|
||||||
|
#include "nsString.h"
|
||||||
#include "Units.h"
|
#include "Units.h"
|
||||||
|
|
||||||
namespace mozilla::dom {
|
namespace mozilla::dom {
|
||||||
@@ -84,8 +92,78 @@ static RefPtr<gfx::DataSourceSurface> CaptureFallbackSnapshot(
|
|||||||
return surf->GetDataSurface();
|
return surf->GetDataSurface();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static layers::RenderRootStateManager* GetWRStateManagerFor(nsIFrame* aFrame) {
|
||||||
|
if ((true)) {
|
||||||
|
// TODO(emilio): Enable this code-path.
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
nsIWidget* widget = aFrame->GetNearestWidget();
|
||||||
|
if (NS_WARN_IF(!widget)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
auto* renderer = widget->GetWindowRenderer();
|
||||||
|
if (NS_WARN_IF(!renderer)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
layers::WebRenderLayerManager* lm = renderer->AsWebRender();
|
||||||
|
if (NS_WARN_IF(!lm)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return lm->GetRenderRootStateManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr wr::ImageKey kNoKey{{0}, 0};
|
||||||
|
|
||||||
|
struct OldSnapshotData {
|
||||||
|
wr::ImageKey mImageKey = kNoKey;
|
||||||
|
nsSize mSize;
|
||||||
|
RefPtr<gfx::DataSourceSurface> mFallback;
|
||||||
|
RefPtr<layers::RenderRootStateManager> mManager;
|
||||||
|
|
||||||
|
OldSnapshotData() = default;
|
||||||
|
|
||||||
|
explicit OldSnapshotData(nsIFrame* aFrame)
|
||||||
|
: mSize(aFrame->InkOverflowRectRelativeToSelf().Size()),
|
||||||
|
mManager(GetWRStateManagerFor(aFrame)) {
|
||||||
|
if (mManager) {
|
||||||
|
mImageKey = mManager->WrBridge()->GetNextImageKey();
|
||||||
|
} else {
|
||||||
|
mFallback = CaptureFallbackSnapshot(aFrame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnsureKey(layers::RenderRootStateManager* aManager,
|
||||||
|
wr::IpcResourceUpdateQueue& aResources) {
|
||||||
|
if (mImageKey != kNoKey) {
|
||||||
|
MOZ_ASSERT(mManager == aManager, "Stale manager?");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (NS_WARN_IF(!mFallback)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
gfx::DataSourceSurface::ScopedMap map(mFallback,
|
||||||
|
gfx::DataSourceSurface::READ);
|
||||||
|
if (NS_WARN_IF(!map.IsMapped())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mManager = aManager;
|
||||||
|
mImageKey = aManager->WrBridge()->GetNextImageKey();
|
||||||
|
auto size = mFallback->GetSize();
|
||||||
|
auto format = mFallback->GetFormat();
|
||||||
|
wr::ImageDescriptor desc(size, format);
|
||||||
|
Range<uint8_t> bytes(map.GetData(), map.GetStride() * size.height);
|
||||||
|
Unused << NS_WARN_IF(!aResources.AddImage(mImageKey, desc, bytes));
|
||||||
|
}
|
||||||
|
|
||||||
|
~OldSnapshotData() {
|
||||||
|
if (mManager) {
|
||||||
|
mManager->AddImageKeyForDiscard(mImageKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct CapturedElementOldState {
|
struct CapturedElementOldState {
|
||||||
RefPtr<gfx::DataSourceSurface> mImage;
|
OldSnapshotData mSnapshot;
|
||||||
// Whether we tried to capture an image. Note we might fail to get a
|
// Whether we tried to capture an image. Note we might fail to get a
|
||||||
// snapshot, so this might not be the same as !!mImage.
|
// snapshot, so this might not be the same as !!mImage.
|
||||||
bool mTriedImage = false;
|
bool mTriedImage = false;
|
||||||
@@ -101,7 +179,7 @@ struct CapturedElementOldState {
|
|||||||
|
|
||||||
CapturedElementOldState(nsIFrame* aFrame,
|
CapturedElementOldState(nsIFrame* aFrame,
|
||||||
const nsSize& aSnapshotContainingBlockSize)
|
const nsSize& aSnapshotContainingBlockSize)
|
||||||
: mImage(CaptureFallbackSnapshot(aFrame)),
|
: mSnapshot(aFrame),
|
||||||
mTriedImage(true),
|
mTriedImage(true),
|
||||||
mSize(aFrame->Style()->IsRootElementStyle()
|
mSize(aFrame->Style()->IsRootElementStyle()
|
||||||
? aSnapshotContainingBlockSize
|
? aSnapshotContainingBlockSize
|
||||||
@@ -119,6 +197,8 @@ struct CapturedElementOldState {
|
|||||||
struct ViewTransition::CapturedElement {
|
struct ViewTransition::CapturedElement {
|
||||||
CapturedElementOldState mOldState;
|
CapturedElementOldState mOldState;
|
||||||
RefPtr<Element> mNewElement;
|
RefPtr<Element> mNewElement;
|
||||||
|
wr::SnapshotImageKey mNewSnapshotKey{kNoKey};
|
||||||
|
nsSize mNewSnapshotSize;
|
||||||
|
|
||||||
CapturedElement() = default;
|
CapturedElement() = default;
|
||||||
|
|
||||||
@@ -135,6 +215,14 @@ struct ViewTransition::CapturedElement {
|
|||||||
RefPtr<StyleLockedDeclarationBlock> mOldRule;
|
RefPtr<StyleLockedDeclarationBlock> mOldRule;
|
||||||
// The rules for ::view-transition-new(<name>).
|
// The rules for ::view-transition-new(<name>).
|
||||||
RefPtr<StyleLockedDeclarationBlock> mNewRule;
|
RefPtr<StyleLockedDeclarationBlock> mNewRule;
|
||||||
|
|
||||||
|
~CapturedElement() {
|
||||||
|
if (wr::AsImageKey(mNewSnapshotKey) != kNoKey) {
|
||||||
|
MOZ_ASSERT(mOldState.mSnapshot.mManager);
|
||||||
|
mOldState.mSnapshot.mManager->AddSnapshotImageKeyForDiscard(
|
||||||
|
mNewSnapshotKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline void ImplCycleCollectionTraverse(
|
static inline void ImplCycleCollectionTraverse(
|
||||||
@@ -164,12 +252,75 @@ ViewTransition::ViewTransition(Document& aDoc,
|
|||||||
|
|
||||||
ViewTransition::~ViewTransition() { ClearTimeoutTimer(); }
|
ViewTransition::~ViewTransition() { ClearTimeoutTimer(); }
|
||||||
|
|
||||||
gfx::DataSourceSurface* ViewTransition::GetOldSurface(nsAtom* aName) const {
|
Maybe<nsSize> ViewTransition::GetOldSize(nsAtom* aName) const {
|
||||||
|
auto* el = mNamedElements.Get(aName);
|
||||||
|
if (NS_WARN_IF(!el)) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return Some(el->mOldState.mSnapshot.mSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
Maybe<nsSize> ViewTransition::GetNewSize(nsAtom* aName) const {
|
||||||
|
auto* el = mNamedElements.Get(aName);
|
||||||
|
if (NS_WARN_IF(!el)) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return Some(el->mNewSnapshotSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
const wr::ImageKey* ViewTransition::GetOldImageKey(
|
||||||
|
nsAtom* aName, layers::RenderRootStateManager* aManager,
|
||||||
|
wr::IpcResourceUpdateQueue& aResources) const {
|
||||||
auto* el = mNamedElements.Get(aName);
|
auto* el = mNamedElements.Get(aName);
|
||||||
if (NS_WARN_IF(!el)) {
|
if (NS_WARN_IF(!el)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return el->mOldState.mImage;
|
el->mOldState.mSnapshot.EnsureKey(aManager, aResources);
|
||||||
|
return &el->mOldState.mSnapshot.mImageKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
const wr::ImageKey* ViewTransition::GetNewImageKey(nsAtom* aName) const {
|
||||||
|
auto* el = mNamedElements.Get(aName);
|
||||||
|
if (NS_WARN_IF(!el)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return &el->mNewSnapshotKey._0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const wr::ImageKey* ViewTransition::GetImageKeyForCapturedFrame(
|
||||||
|
nsIFrame* aFrame, layers::RenderRootStateManager* aManager,
|
||||||
|
wr::IpcResourceUpdateQueue& aResources) const {
|
||||||
|
MOZ_ASSERT(aFrame);
|
||||||
|
MOZ_ASSERT(aFrame->HasAnyStateBits(NS_FRAME_CAPTURED_IN_VIEW_TRANSITION));
|
||||||
|
|
||||||
|
if (!StaticPrefs::dom_viewTransitions_live_capture()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsAtom* name = aFrame->StyleUIReset()->mViewTransitionName._0.AsAtom();
|
||||||
|
if (NS_WARN_IF(name->IsEmpty())) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
const bool isOld = mPhase < Phase::Animating;
|
||||||
|
if (isOld) {
|
||||||
|
return GetOldImageKey(name, aManager, aResources);
|
||||||
|
}
|
||||||
|
auto* el = mNamedElements.Get(name);
|
||||||
|
if (NS_WARN_IF(!el)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
if (NS_WARN_IF(el->mNewElement != aFrame->GetContent())) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
if (wr::AsImageKey(el->mNewSnapshotKey) == kNoKey) {
|
||||||
|
MOZ_ASSERT(!el->mOldState.mSnapshot.mManager ||
|
||||||
|
el->mOldState.mSnapshot.mManager == aManager,
|
||||||
|
"Stale manager?");
|
||||||
|
el->mNewSnapshotKey = {aManager->WrBridge()->GetNextImageKey()};
|
||||||
|
el->mOldState.mSnapshot.mManager = aManager;
|
||||||
|
aResources.AddSnapshotImage(el->mNewSnapshotKey);
|
||||||
|
}
|
||||||
|
return &el->mNewSnapshotKey._0;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsIGlobalObject* ViewTransition::GetParentObject() const {
|
nsIGlobalObject* ViewTransition::GetParentObject() const {
|
||||||
@@ -262,7 +413,7 @@ void ViewTransition::CallUpdateCallback(ErrorResult& aRv) {
|
|||||||
// new state, so we need to flush frames. Do it here so that we deal
|
// new state, so we need to flush frames. Do it here so that we deal
|
||||||
// with other potential script execution skipping the transition or
|
// with other potential script execution skipping the transition or
|
||||||
// what not in a consistent way.
|
// what not in a consistent way.
|
||||||
aVt->mDocument->FlushPendingNotifications(FlushType::Frames);
|
aVt->mDocument->FlushPendingNotifications(FlushType::Layout);
|
||||||
if (aVt->mPhase == Phase::Done) {
|
if (aVt->mPhase == Phase::Done) {
|
||||||
// "Skip a transition" step 8. We need to resolve "finished" after
|
// "Skip a transition" step 8. We need to resolve "finished" after
|
||||||
// update-callback-done.
|
// update-callback-done.
|
||||||
@@ -604,15 +755,15 @@ bool ViewTransition::UpdatePseudoElementStyles(bool aNeedsInvalidation) {
|
|||||||
auto size = CSSPixel::FromAppUnits(newRect);
|
auto size = CSSPixel::FromAppUnits(newRect);
|
||||||
// NOTE(emilio): Intentionally not short-circuiting. Int cast is needed to
|
// NOTE(emilio): Intentionally not short-circuiting. Int cast is needed to
|
||||||
// silence warning.
|
// silence warning.
|
||||||
bool changed = int(SetProp(rule, mDocument, eCSSProperty_width, size.width,
|
bool groupStyleChanged = int(SetProp(rule, mDocument, eCSSProperty_width,
|
||||||
eCSSUnit_Pixel)) |
|
size.width, eCSSUnit_Pixel)) |
|
||||||
SetProp(rule, mDocument, eCSSProperty_height, size.height,
|
SetProp(rule, mDocument, eCSSProperty_height,
|
||||||
eCSSUnit_Pixel) |
|
size.height, eCSSUnit_Pixel) |
|
||||||
SetProp(rule, mDocument, eCSSProperty_transform,
|
SetProp(rule, mDocument, eCSSProperty_transform,
|
||||||
EffectiveTransform(frame));
|
EffectiveTransform(frame));
|
||||||
// TODO: writing-mode, direction, text-orientation, mix-blend-mode,
|
// TODO: writing-mode, direction, text-orientation, mix-blend-mode,
|
||||||
// backdrop-filter, color-scheme.
|
// backdrop-filter, color-scheme.
|
||||||
if (changed && aNeedsInvalidation) {
|
if (groupStyleChanged && aNeedsInvalidation) {
|
||||||
auto* pseudo = FindPseudo(PseudoStyleRequest(
|
auto* pseudo = FindPseudo(PseudoStyleRequest(
|
||||||
PseudoStyleType::viewTransitionGroup, transitionName));
|
PseudoStyleType::viewTransitionGroup, transitionName));
|
||||||
MOZ_ASSERT(pseudo);
|
MOZ_ASSERT(pseudo);
|
||||||
@@ -621,7 +772,16 @@ bool ViewTransition::UpdatePseudoElementStyles(bool aNeedsInvalidation) {
|
|||||||
nsLayoutUtils::PostRestyleEvent(pseudo, RestyleHint::RECASCADE_SELF,
|
nsLayoutUtils::PostRestyleEvent(pseudo, RestyleHint::RECASCADE_SELF,
|
||||||
nsChangeHint(0));
|
nsChangeHint(0));
|
||||||
}
|
}
|
||||||
// 5. TODO(emilio): Live capturing (probably nothing to do here)
|
|
||||||
|
// 5. Live capturing (nothing to do here regarding the capture itself, but
|
||||||
|
// if the size has changed, then we need to invalidate the new frame).
|
||||||
|
auto oldSize = capturedElement.mNewSnapshotSize;
|
||||||
|
capturedElement.mNewSnapshotSize =
|
||||||
|
frame->InkOverflowRectRelativeToSelf().Size();
|
||||||
|
if (oldSize != capturedElement.mNewSnapshotSize && aNeedsInvalidation) {
|
||||||
|
frame->PresShell()->FrameNeedsReflow(
|
||||||
|
frame, IntrinsicDirty::FrameAndAncestors, NS_FRAME_IS_DIRTY);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -931,6 +1091,8 @@ Maybe<SkipTransitionReason> ViewTransition::CaptureNewState() {
|
|||||||
auto& capturedElement = mNamedElements.LookupOrInsertWith(
|
auto& capturedElement = mNamedElements.LookupOrInsertWith(
|
||||||
name, [&] { return MakeUnique<CapturedElement>(); });
|
name, [&] { return MakeUnique<CapturedElement>(); });
|
||||||
capturedElement->mNewElement = aFrame->GetContent()->AsElement();
|
capturedElement->mNewElement = aFrame->GetContent()->AsElement();
|
||||||
|
capturedElement->mNewSnapshotSize =
|
||||||
|
aFrame->InkOverflowRectRelativeToSelf().Size();
|
||||||
aFrame->AddStateBits(NS_FRAME_CAPTURED_IN_VIEW_TRANSITION);
|
aFrame->AddStateBits(NS_FRAME_CAPTURED_IN_VIEW_TRANSITION);
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#ifndef mozilla_dom_ViewTransition_h
|
#ifndef mozilla_dom_ViewTransition_h
|
||||||
#define mozilla_dom_ViewTransition_h
|
#define mozilla_dom_ViewTransition_h
|
||||||
|
|
||||||
|
#include "mozilla/layers/IpcResourceUpdateQueue.h"
|
||||||
#include "nsRect.h"
|
#include "nsRect.h"
|
||||||
#include "nsWrapperCache.h"
|
#include "nsWrapperCache.h"
|
||||||
#include "nsAtomHashKeys.h"
|
#include "nsAtomHashKeys.h"
|
||||||
@@ -25,6 +26,15 @@ namespace gfx {
|
|||||||
class DataSourceSurface;
|
class DataSourceSurface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace layers {
|
||||||
|
class RenderRootStateManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace wr {
|
||||||
|
struct ImageKey;
|
||||||
|
class IpcResourceUpdateQueue;
|
||||||
|
} // namespace wr
|
||||||
|
|
||||||
namespace dom {
|
namespace dom {
|
||||||
|
|
||||||
class Document;
|
class Document;
|
||||||
@@ -69,7 +79,15 @@ class ViewTransition final : public nsISupports, public nsWrapperCache {
|
|||||||
void PerformPendingOperations();
|
void PerformPendingOperations();
|
||||||
|
|
||||||
Element* GetRoot() const { return mViewTransitionRoot; }
|
Element* GetRoot() const { return mViewTransitionRoot; }
|
||||||
gfx::DataSourceSurface* GetOldSurface(nsAtom* aName) const;
|
Maybe<nsSize> GetOldSize(nsAtom* aName) const;
|
||||||
|
Maybe<nsSize> GetNewSize(nsAtom* aName) const;
|
||||||
|
const wr::ImageKey* GetOldImageKey(nsAtom* aName,
|
||||||
|
layers::RenderRootStateManager*,
|
||||||
|
wr::IpcResourceUpdateQueue&) const;
|
||||||
|
const wr::ImageKey* GetNewImageKey(nsAtom* aName) const;
|
||||||
|
const wr::ImageKey* GetImageKeyForCapturedFrame(
|
||||||
|
nsIFrame* aFrame, layers::RenderRootStateManager*,
|
||||||
|
wr::IpcResourceUpdateQueue&) const;
|
||||||
|
|
||||||
Element* FindPseudo(const PseudoStyleRequest&) const;
|
Element* FindPseudo(const PseudoStyleRequest&) const;
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ using mozilla::wr::FontInstanceKey from "mozilla/webrender/WebRenderTypes.h";
|
|||||||
using mozilla::wr::FontKey from "mozilla/webrender/WebRenderTypes.h";
|
using mozilla::wr::FontKey from "mozilla/webrender/WebRenderTypes.h";
|
||||||
using mozilla::wr::ImageKey from "mozilla/webrender/WebRenderTypes.h";
|
using mozilla::wr::ImageKey from "mozilla/webrender/WebRenderTypes.h";
|
||||||
using mozilla::wr::BlobImageKey from "mozilla/webrender/WebRenderTypes.h";
|
using mozilla::wr::BlobImageKey from "mozilla/webrender/WebRenderTypes.h";
|
||||||
|
using mozilla::wr::SnapshotImageKey from "mozilla/webrender/WebRenderTypes.h";
|
||||||
using mozilla::wr::WrRotation from "mozilla/webrender/WebRenderTypes.h";
|
using mozilla::wr::WrRotation from "mozilla/webrender/WebRenderTypes.h";
|
||||||
using mozilla::wr::PipelineId from "mozilla/webrender/WebRenderTypes.h";
|
using mozilla::wr::PipelineId from "mozilla/webrender/WebRenderTypes.h";
|
||||||
using mozilla::LayoutDeviceRect from "Units.h";
|
using mozilla::LayoutDeviceRect from "Units.h";
|
||||||
@@ -114,6 +115,10 @@ struct OpAddBlobImage {
|
|||||||
BlobImageKey key;
|
BlobImageKey key;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct OpAddSnapshotImage {
|
||||||
|
SnapshotImageKey key;
|
||||||
|
};
|
||||||
|
|
||||||
struct OpUpdateImage {
|
struct OpUpdateImage {
|
||||||
ImageDescriptor descriptor;
|
ImageDescriptor descriptor;
|
||||||
OffsetRange bytes;
|
OffsetRange bytes;
|
||||||
@@ -143,6 +148,10 @@ struct OpDeleteImage {
|
|||||||
ImageKey key;
|
ImageKey key;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct OpDeleteSnapshotImage {
|
||||||
|
SnapshotImageKey key;
|
||||||
|
};
|
||||||
|
|
||||||
struct OpDeleteBlobImage {
|
struct OpDeleteBlobImage {
|
||||||
BlobImageKey key;
|
BlobImageKey key;
|
||||||
};
|
};
|
||||||
@@ -179,11 +188,13 @@ struct OpDeleteFontInstance {
|
|||||||
union OpUpdateResource {
|
union OpUpdateResource {
|
||||||
OpAddImage;
|
OpAddImage;
|
||||||
OpAddBlobImage;
|
OpAddBlobImage;
|
||||||
|
OpAddSnapshotImage;
|
||||||
OpUpdateImage;
|
OpUpdateImage;
|
||||||
OpUpdateBlobImage;
|
OpUpdateBlobImage;
|
||||||
OpSetBlobImageVisibleArea;
|
OpSetBlobImageVisibleArea;
|
||||||
OpDeleteImage;
|
OpDeleteImage;
|
||||||
OpDeleteBlobImage;
|
OpDeleteBlobImage;
|
||||||
|
OpDeleteSnapshotImage;
|
||||||
OpAddRawFont;
|
OpAddRawFont;
|
||||||
OpAddFontDescriptor;
|
OpAddFontDescriptor;
|
||||||
OpDeleteFont;
|
OpDeleteFont;
|
||||||
|
|||||||
@@ -322,6 +322,10 @@ bool IpcResourceUpdateQueue::AddImage(ImageKey key,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IpcResourceUpdateQueue::AddSnapshotImage(SnapshotImageKey aKey) {
|
||||||
|
mUpdates.AppendElement(layers::OpAddSnapshotImage(aKey));
|
||||||
|
}
|
||||||
|
|
||||||
bool IpcResourceUpdateQueue::AddBlobImage(BlobImageKey key,
|
bool IpcResourceUpdateQueue::AddBlobImage(BlobImageKey key,
|
||||||
const ImageDescriptor& aDescriptor,
|
const ImageDescriptor& aDescriptor,
|
||||||
Range<uint8_t> aBytes,
|
Range<uint8_t> aBytes,
|
||||||
@@ -393,6 +397,10 @@ void IpcResourceUpdateQueue::DeleteImage(ImageKey aKey) {
|
|||||||
mUpdates.AppendElement(layers::OpDeleteImage(aKey));
|
mUpdates.AppendElement(layers::OpDeleteImage(aKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IpcResourceUpdateQueue::DeleteSnapshotImage(SnapshotImageKey aKey) {
|
||||||
|
mUpdates.AppendElement(layers::OpDeleteSnapshotImage(aKey));
|
||||||
|
}
|
||||||
|
|
||||||
void IpcResourceUpdateQueue::DeleteBlobImage(BlobImageKey aKey) {
|
void IpcResourceUpdateQueue::DeleteBlobImage(BlobImageKey aKey) {
|
||||||
mUpdates.AppendElement(layers::OpDeleteBlobImage(aKey));
|
mUpdates.AppendElement(layers::OpDeleteBlobImage(aKey));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -132,6 +132,8 @@ class IpcResourceUpdateQueue {
|
|||||||
bool AddBlobImage(wr::BlobImageKey aKey, const ImageDescriptor& aDescriptor,
|
bool AddBlobImage(wr::BlobImageKey aKey, const ImageDescriptor& aDescriptor,
|
||||||
Range<uint8_t> aBytes, ImageIntRect aVisibleRect);
|
Range<uint8_t> aBytes, ImageIntRect aVisibleRect);
|
||||||
|
|
||||||
|
void AddSnapshotImage(wr::SnapshotImageKey aKey);
|
||||||
|
|
||||||
void AddSharedExternalImage(wr::ExternalImageId aExtId, wr::ImageKey aKey);
|
void AddSharedExternalImage(wr::ExternalImageId aExtId, wr::ImageKey aKey);
|
||||||
|
|
||||||
void PushExternalImageForTexture(wr::ExternalImageId aExtId,
|
void PushExternalImageForTexture(wr::ExternalImageId aExtId,
|
||||||
@@ -156,6 +158,8 @@ class IpcResourceUpdateQueue {
|
|||||||
|
|
||||||
void DeleteBlobImage(wr::BlobImageKey aKey);
|
void DeleteBlobImage(wr::BlobImageKey aKey);
|
||||||
|
|
||||||
|
void DeleteSnapshotImage(wr::SnapshotImageKey aKey);
|
||||||
|
|
||||||
bool AddRawFont(wr::FontKey aKey, Range<uint8_t> aBytes, uint32_t aIndex);
|
bool AddRawFont(wr::FontKey aKey, Range<uint8_t> aBytes, uint32_t aIndex);
|
||||||
|
|
||||||
bool AddFontDescriptor(wr::FontKey aKey, Range<uint8_t> aBytes,
|
bool AddFontDescriptor(wr::FontKey aKey, Range<uint8_t> aBytes,
|
||||||
|
|||||||
@@ -86,6 +86,11 @@ void RenderRootStateManager::AddBlobImageKeyForDiscard(wr::BlobImageKey key) {
|
|||||||
mBlobImageKeysToDelete.AppendElement(key);
|
mBlobImageKeysToDelete.AppendElement(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RenderRootStateManager::AddSnapshotImageKeyForDiscard(
|
||||||
|
wr::SnapshotImageKey key) {
|
||||||
|
mSnapshotImageKeysToDelete.AppendElement(key);
|
||||||
|
}
|
||||||
|
|
||||||
void RenderRootStateManager::DiscardImagesInTransaction(
|
void RenderRootStateManager::DiscardImagesInTransaction(
|
||||||
wr::IpcResourceUpdateQueue& aResources) {
|
wr::IpcResourceUpdateQueue& aResources) {
|
||||||
for (const auto& key : mImageKeysToDelete) {
|
for (const auto& key : mImageKeysToDelete) {
|
||||||
@@ -94,8 +99,12 @@ void RenderRootStateManager::DiscardImagesInTransaction(
|
|||||||
for (const auto& key : mBlobImageKeysToDelete) {
|
for (const auto& key : mBlobImageKeysToDelete) {
|
||||||
aResources.DeleteBlobImage(key);
|
aResources.DeleteBlobImage(key);
|
||||||
}
|
}
|
||||||
|
for (const auto& key : mSnapshotImageKeysToDelete) {
|
||||||
|
aResources.DeleteSnapshotImage(key);
|
||||||
|
}
|
||||||
mImageKeysToDelete.Clear();
|
mImageKeysToDelete.Clear();
|
||||||
mBlobImageKeysToDelete.Clear();
|
mBlobImageKeysToDelete.Clear();
|
||||||
|
mSnapshotImageKeysToDelete.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderRootStateManager::DiscardLocalImages() {
|
void RenderRootStateManager::DiscardLocalImages() {
|
||||||
@@ -104,6 +113,7 @@ void RenderRootStateManager::DiscardLocalImages() {
|
|||||||
// image keys but didn't tell the parent about them yet.
|
// image keys but didn't tell the parent about them yet.
|
||||||
mImageKeysToDelete.Clear();
|
mImageKeysToDelete.Clear();
|
||||||
mBlobImageKeysToDelete.Clear();
|
mBlobImageKeysToDelete.Clear();
|
||||||
|
mSnapshotImageKeysToDelete.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderRootStateManager::ClearCachedResources() {
|
void RenderRootStateManager::ClearCachedResources() {
|
||||||
|
|||||||
@@ -35,8 +35,9 @@ class RenderRootStateManager {
|
|||||||
WebRenderUserDataRefTable* GetWebRenderUserDataTable();
|
WebRenderUserDataRefTable* GetWebRenderUserDataTable();
|
||||||
WebRenderLayerManager* LayerManager() { return mLayerManager; }
|
WebRenderLayerManager* LayerManager() { return mLayerManager; }
|
||||||
|
|
||||||
void AddImageKeyForDiscard(wr::ImageKey key);
|
void AddImageKeyForDiscard(wr::ImageKey);
|
||||||
void AddBlobImageKeyForDiscard(wr::BlobImageKey key);
|
void AddBlobImageKeyForDiscard(wr::BlobImageKey);
|
||||||
|
void AddSnapshotImageKeyForDiscard(wr::SnapshotImageKey);
|
||||||
void DiscardImagesInTransaction(wr::IpcResourceUpdateQueue& aResources);
|
void DiscardImagesInTransaction(wr::IpcResourceUpdateQueue& aResources);
|
||||||
void DiscardLocalImages();
|
void DiscardLocalImages();
|
||||||
|
|
||||||
@@ -76,6 +77,7 @@ class RenderRootStateManager {
|
|||||||
Maybe<wr::IpcResourceUpdateQueue> mAsyncResourceUpdates;
|
Maybe<wr::IpcResourceUpdateQueue> mAsyncResourceUpdates;
|
||||||
nsTArray<wr::ImageKey> mImageKeysToDelete;
|
nsTArray<wr::ImageKey> mImageKeysToDelete;
|
||||||
nsTArray<wr::BlobImageKey> mBlobImageKeysToDelete;
|
nsTArray<wr::BlobImageKey> mBlobImageKeysToDelete;
|
||||||
|
nsTArray<wr::SnapshotImageKey> mSnapshotImageKeysToDelete;
|
||||||
std::unordered_map<uint64_t, RefPtr<SharedSurfacesAnimation>>
|
std::unordered_map<uint64_t, RefPtr<SharedSurfacesAnimation>>
|
||||||
mAsyncAnimations;
|
mAsyncAnimations;
|
||||||
|
|
||||||
|
|||||||
@@ -607,6 +607,24 @@ bool WebRenderBridgeParent::UpdateResources(
|
|||||||
wr::ToDeviceIntRect(op.area()));
|
wr::ToDeviceIntRect(op.area()));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case OpUpdateResource::TOpAddSnapshotImage: {
|
||||||
|
const auto& op = cmd.get_OpAddSnapshotImage();
|
||||||
|
if (!MatchesNamespace(wr::AsImageKey(op.key()))) {
|
||||||
|
MOZ_ASSERT_UNREACHABLE("Stale snapshot image key (add)!");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
aUpdates.AddSnapshotImage(op.key());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OpUpdateResource::TOpDeleteSnapshotImage: {
|
||||||
|
const auto& op = cmd.get_OpDeleteSnapshotImage();
|
||||||
|
if (!MatchesNamespace(wr::AsImageKey(op.key()))) {
|
||||||
|
MOZ_ASSERT_UNREACHABLE("Stale snapshot image key (remove)!");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
aUpdates.DeleteSnapshotImage(op.key());
|
||||||
|
break;
|
||||||
|
}
|
||||||
case OpUpdateResource::TOpAddSharedExternalImage: {
|
case OpUpdateResource::TOpAddSharedExternalImage: {
|
||||||
const auto& op = cmd.get_OpAddSharedExternalImage();
|
const auto& op = cmd.get_OpAddSharedExternalImage();
|
||||||
// gfxCriticalNote is called on error
|
// gfxCriticalNote is called on error
|
||||||
|
|||||||
@@ -236,6 +236,10 @@ class WebRenderBridgeParent final : public PWebRenderBridgeParent,
|
|||||||
return MatchesNamespace(wr::AsImageKey(aBlobKey));
|
return MatchesNamespace(wr::AsImageKey(aBlobKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MatchesNamespace(const wr::SnapshotImageKey& aSnapshotKey) const {
|
||||||
|
return MatchesNamespace(wr::AsImageKey(aSnapshotKey));
|
||||||
|
}
|
||||||
|
|
||||||
bool MatchesNamespace(const wr::FontKey& aFontKey) const {
|
bool MatchesNamespace(const wr::FontKey& aFontKey) const {
|
||||||
return aFontKey.mNamespace == mIdNamespace;
|
return aFontKey.mNamespace == mIdNamespace;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -144,6 +144,12 @@ inline auto TiedFields<mozilla::wr::BlobImageKey>(
|
|||||||
return std::tie(a._0);
|
return std::tie(a._0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline auto TiedFields<mozilla::wr::SnapshotImageKey>(
|
||||||
|
mozilla::wr::SnapshotImageKey& a) {
|
||||||
|
return std::tie(a._0);
|
||||||
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline auto TiedFields<mozilla::wr::FontKey>(mozilla::wr::FontKey& a) {
|
inline auto TiedFields<mozilla::wr::FontKey>(mozilla::wr::FontKey& a) {
|
||||||
return std::tie(a.mNamespace, a.mHandle);
|
return std::tie(a.mNamespace, a.mHandle);
|
||||||
@@ -340,6 +346,10 @@ template <>
|
|||||||
struct ParamTraits<mozilla::wr::BlobImageKey>
|
struct ParamTraits<mozilla::wr::BlobImageKey>
|
||||||
: public ParamTraits_TiedFields<mozilla::wr::BlobImageKey> {};
|
: public ParamTraits_TiedFields<mozilla::wr::BlobImageKey> {};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct ParamTraits<mozilla::wr::SnapshotImageKey>
|
||||||
|
: public ParamTraits_TiedFields<mozilla::wr::SnapshotImageKey> {};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct ParamTraits<mozilla::wr::FontKey>
|
struct ParamTraits<mozilla::wr::FontKey>
|
||||||
: public ParamTraits_TiedFields<mozilla::wr::FontKey> {};
|
: public ParamTraits_TiedFields<mozilla::wr::FontKey> {};
|
||||||
|
|||||||
@@ -113,9 +113,10 @@ template struct mozilla::wr::Box2D<int, mozilla::wr::LayoutPixel>;
|
|||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace wr {
|
namespace wr {
|
||||||
|
|
||||||
// Cast a blob image key into a regular image for use in
|
// Cast a blob image key into a regular image for use in a display item.
|
||||||
// a display item.
|
|
||||||
inline ImageKey AsImageKey(BlobImageKey aKey) { return aKey._0; }
|
inline ImageKey AsImageKey(BlobImageKey aKey) { return aKey._0; }
|
||||||
|
// Cast a snapshot image key into a regular image for use in a display item.
|
||||||
|
inline ImageKey AsImageKey(SnapshotImageKey aKey) { return aKey._0; }
|
||||||
|
|
||||||
} // namespace wr
|
} // namespace wr
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|||||||
@@ -221,7 +221,7 @@ nsIFrame* NS_NewXULImageFrame(PresShell*, ComputedStyle*);
|
|||||||
nsIFrame* NS_NewImageFrameForContentProperty(PresShell*, ComputedStyle*);
|
nsIFrame* NS_NewImageFrameForContentProperty(PresShell*, ComputedStyle*);
|
||||||
nsIFrame* NS_NewImageFrameForGeneratedContentIndex(PresShell*, ComputedStyle*);
|
nsIFrame* NS_NewImageFrameForGeneratedContentIndex(PresShell*, ComputedStyle*);
|
||||||
nsIFrame* NS_NewImageFrameForListStyleImage(PresShell*, ComputedStyle*);
|
nsIFrame* NS_NewImageFrameForListStyleImage(PresShell*, ComputedStyle*);
|
||||||
nsIFrame* NS_NewImageFrameForViewTransitionOld(PresShell*, ComputedStyle*);
|
nsIFrame* NS_NewImageFrameForViewTransition(PresShell*, ComputedStyle*);
|
||||||
|
|
||||||
// Returns true if aFrame is an anonymous flex/grid item.
|
// Returns true if aFrame is an anonymous flex/grid item.
|
||||||
static inline bool IsAnonymousItem(const nsIFrame* aFrame) {
|
static inline bool IsAnonymousItem(const nsIFrame* aFrame) {
|
||||||
@@ -3493,10 +3493,11 @@ nsCSSFrameConstructor::FindHTMLData(const Element& aElement,
|
|||||||
return &sComboboxLabelData;
|
return &sComboboxLabelData;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (aElement.GetPseudoElementType() == PseudoStyleType::viewTransitionOld) {
|
if (aStyle.GetPseudoType() == PseudoStyleType::viewTransitionOld ||
|
||||||
static constexpr FrameConstructionData sViewTransitionOldData(
|
aStyle.GetPseudoType() == PseudoStyleType::viewTransitionNew) {
|
||||||
NS_NewImageFrameForViewTransitionOld);
|
static constexpr FrameConstructionData sViewTransitionData(
|
||||||
return &sViewTransitionOldData;
|
NS_NewImageFrameForViewTransition);
|
||||||
|
return &sViewTransitionData;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
#include "mozilla/DisplayPortUtils.h"
|
#include "mozilla/DisplayPortUtils.h"
|
||||||
#include "mozilla/EventForwards.h"
|
#include "mozilla/EventForwards.h"
|
||||||
#include "mozilla/FocusModel.h"
|
#include "mozilla/FocusModel.h"
|
||||||
|
#include "mozilla/StaticPrefs_dom.h"
|
||||||
#include "mozilla/dom/CSSAnimation.h"
|
#include "mozilla/dom/CSSAnimation.h"
|
||||||
#include "mozilla/dom/CSSTransition.h"
|
#include "mozilla/dom/CSSTransition.h"
|
||||||
#include "mozilla/dom/ContentVisibilityAutoStateChangeEvent.h"
|
#include "mozilla/dom/ContentVisibilityAutoStateChangeEvent.h"
|
||||||
@@ -3366,16 +3367,11 @@ void nsIFrame::BuildDisplayListForStackingContext(
|
|||||||
// outside to inside.
|
// outside to inside.
|
||||||
enum class ContainerItemType : uint8_t {
|
enum class ContainerItemType : uint8_t {
|
||||||
None = 0,
|
None = 0,
|
||||||
OwnLayerIfNeeded,
|
|
||||||
BlendMode,
|
|
||||||
FixedPosition,
|
FixedPosition,
|
||||||
OwnLayerForTransformWithRoundedClip,
|
OwnLayerForTransformWithRoundedClip,
|
||||||
Perspective,
|
Perspective,
|
||||||
Transform,
|
Transform,
|
||||||
SeparatorTransforms,
|
|
||||||
Opacity,
|
|
||||||
Filter,
|
Filter,
|
||||||
BlendContainer
|
|
||||||
};
|
};
|
||||||
|
|
||||||
nsDisplayListBuilder::AutoContainerASRTracker contASRTracker(aBuilder);
|
nsDisplayListBuilder::AutoContainerASRTracker contASRTracker(aBuilder);
|
||||||
@@ -3579,6 +3575,18 @@ void nsIFrame::BuildDisplayListForStackingContext(
|
|||||||
createdContainer = true;
|
createdContainer = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: Ensure this is the right place to do this.
|
||||||
|
if (HasAnyStateBits(NS_FRAME_CAPTURED_IN_VIEW_TRANSITION) &&
|
||||||
|
StaticPrefs::dom_viewTransitions_live_capture()) {
|
||||||
|
resultList.AppendNewToTopWithIndex<nsDisplayOwnLayer>(
|
||||||
|
aBuilder, this,
|
||||||
|
/* aIndex = */ nsDisplayOwnLayer::OwnLayerForViewTransitionCapture,
|
||||||
|
&resultList, containerItemASR, nsDisplayOwnLayerFlags::None,
|
||||||
|
ScrollbarData{},
|
||||||
|
/* aForceActive = */ false, false);
|
||||||
|
createdContainer = true;
|
||||||
|
}
|
||||||
|
|
||||||
// If there are any SVG effects, wrap the list up in an SVG effects item
|
// If there are any SVG effects, wrap the list up in an SVG effects item
|
||||||
// (which also handles CSS group opacity). Note that we create an SVG effects
|
// (which also handles CSS group opacity). Note that we create an SVG effects
|
||||||
// item even if resultList is empty, since a filter can produce graphical
|
// item even if resultList is empty, since a filter can produce graphical
|
||||||
|
|||||||
@@ -107,6 +107,8 @@ using namespace mozilla::layers;
|
|||||||
|
|
||||||
using mozilla::layout::TextDrawTarget;
|
using mozilla::layout::TextDrawTarget;
|
||||||
|
|
||||||
|
static constexpr wr::ImageKey kNoKey{{0}, 0};
|
||||||
|
|
||||||
class nsDisplayGradient final : public nsPaintedDisplayItem {
|
class nsDisplayGradient final : public nsPaintedDisplayItem {
|
||||||
public:
|
public:
|
||||||
nsDisplayGradient(nsDisplayListBuilder* aBuilder, nsImageFrame* aFrame)
|
nsDisplayGradient(nsDisplayListBuilder* aBuilder, nsImageFrame* aFrame)
|
||||||
@@ -399,10 +401,10 @@ nsIFrame* NS_NewImageFrameForListStyleImage(PresShell* aPresShell,
|
|||||||
nsImageFrame::Kind::ListStyleImage);
|
nsImageFrame::Kind::ListStyleImage);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsIFrame* NS_NewImageFrameForViewTransitionOld(PresShell* aPresShell,
|
nsIFrame* NS_NewImageFrameForViewTransition(PresShell* aPresShell,
|
||||||
ComputedStyle* aStyle) {
|
ComputedStyle* aStyle) {
|
||||||
return new (aPresShell) nsImageFrame(aStyle, aPresShell->GetPresContext(),
|
return new (aPresShell) nsImageFrame(aStyle, aPresShell->GetPresContext(),
|
||||||
nsImageFrame::Kind::ViewTransitionOld);
|
nsImageFrame::Kind::ViewTransition);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nsImageFrame::ShouldShowBrokenImageIcon() const {
|
bool nsImageFrame::ShouldShowBrokenImageIcon() const {
|
||||||
@@ -471,7 +473,7 @@ a11y::AccType nsImageFrame::AccessibleType() {
|
|||||||
return a11y::eNoType;
|
return a11y::eNoType;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mKind == Kind::ViewTransitionOld) {
|
if (mKind == Kind::ViewTransition) {
|
||||||
// View transitions don't show up in the a11y tree.
|
// View transitions don't show up in the a11y tree.
|
||||||
return a11y::eNoType;
|
return a11y::eNoType;
|
||||||
}
|
}
|
||||||
@@ -538,13 +540,6 @@ void nsImageFrame::Destroy(DestroyContext& aContext) {
|
|||||||
BrokenImageIcon::RemoveObserver(this);
|
BrokenImageIcon::RemoveObserver(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mViewTransitionData.HasKey()) {
|
|
||||||
MOZ_ASSERT(mViewTransitionData.mManager);
|
|
||||||
mViewTransitionData.mManager->AddImageKeyForDiscard(
|
|
||||||
mViewTransitionData.mImageKey);
|
|
||||||
mViewTransitionData = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
nsAtomicContainerFrame::Destroy(aContext);
|
nsAtomicContainerFrame::Destroy(aContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -630,7 +625,7 @@ static bool SizeIsAvailable(imgIRequest* aRequest) {
|
|||||||
|
|
||||||
const StyleImage* nsImageFrame::GetImageFromStyle() const {
|
const StyleImage* nsImageFrame::GetImageFromStyle() const {
|
||||||
switch (mKind) {
|
switch (mKind) {
|
||||||
case Kind::ViewTransitionOld:
|
case Kind::ViewTransition:
|
||||||
break;
|
break;
|
||||||
case Kind::ImageLoadingContent:
|
case Kind::ImageLoadingContent:
|
||||||
break;
|
break;
|
||||||
@@ -750,7 +745,7 @@ void nsImageFrame::Init(nsIContent* aContent, nsContainerFrame* aParent,
|
|||||||
}
|
}
|
||||||
} else if (mKind == Kind::XULImage) {
|
} else if (mKind == Kind::XULImage) {
|
||||||
UpdateXULImage();
|
UpdateXULImage();
|
||||||
} else if (mKind == Kind::ViewTransitionOld) {
|
} else if (mKind == Kind::ViewTransition) {
|
||||||
// View transitions have a surface directly.
|
// View transitions have a surface directly.
|
||||||
} else {
|
} else {
|
||||||
const StyleImage* image = GetImageFromStyle();
|
const StyleImage* image = GetImageFromStyle();
|
||||||
@@ -881,13 +876,10 @@ IntrinsicSize nsImageFrame::ComputeIntrinsicSize(
|
|||||||
return FinishIntrinsicSize(containAxes, intrinsicSize);
|
return FinishIntrinsicSize(containAxes, intrinsicSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto* surf = GetViewTransitionSurface()) {
|
if (auto size = GetViewTransitionSnapshotSize()) {
|
||||||
IntrinsicSize intrinsicSize;
|
IntrinsicSize intrinsicSize;
|
||||||
auto devPx = LayoutDeviceIntSize::FromUnknownSize(surf->GetSize());
|
intrinsicSize.width.emplace(size->width);
|
||||||
auto size = LayoutDeviceIntSize::ToAppUnits(
|
intrinsicSize.height.emplace(size->height);
|
||||||
devPx, PresContext()->AppUnitsPerDevPixel());
|
|
||||||
intrinsicSize.width.emplace(size.width);
|
|
||||||
intrinsicSize.height.emplace(size.height);
|
|
||||||
return FinishIntrinsicSize(containAxes, intrinsicSize);
|
return FinishIntrinsicSize(containAxes, intrinsicSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -950,18 +942,47 @@ bool nsImageFrame::UpdateIntrinsicSize() {
|
|||||||
return mIntrinsicSize != oldIntrinsicSize;
|
return mIntrinsicSize != oldIntrinsicSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
gfx::DataSourceSurface* nsImageFrame::GetViewTransitionSurface() const {
|
nsAtom* nsImageFrame::GetViewTransitionName() const {
|
||||||
if (mKind != Kind::ViewTransitionOld) {
|
if (mKind != Kind::ViewTransition) {
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
auto* vt = PresContext()->Document()->GetActiveViewTransition();
|
|
||||||
if (NS_WARN_IF(!vt)) {
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
MOZ_ASSERT(GetContent()->AsElement()->HasName());
|
MOZ_ASSERT(GetContent()->AsElement()->HasName());
|
||||||
nsAtom* name =
|
return GetContent()
|
||||||
GetContent()->AsElement()->GetParsedAttr(nsGkAtoms::name)->GetAtomValue();
|
->AsElement()
|
||||||
return vt->GetOldSurface(name);
|
->GetParsedAttr(nsGkAtoms::name)
|
||||||
|
->GetAtomValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
Maybe<nsSize> nsImageFrame::GetViewTransitionSnapshotSize() const {
|
||||||
|
auto* name = GetViewTransitionName();
|
||||||
|
if (!name) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
auto* vt = PresContext()->Document()->GetActiveViewTransition();
|
||||||
|
if (NS_WARN_IF(!vt)) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return Style()->GetPseudoType() == PseudoStyleType::viewTransitionOld
|
||||||
|
? vt->GetOldSize(name)
|
||||||
|
: vt->GetNewSize(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
wr::ImageKey nsImageFrame::GetViewTransitionImageKey(
|
||||||
|
layers::RenderRootStateManager* aManager,
|
||||||
|
wr::IpcResourceUpdateQueue& aResources) const {
|
||||||
|
auto* name = GetViewTransitionName();
|
||||||
|
if (!name) {
|
||||||
|
return kNoKey;
|
||||||
|
}
|
||||||
|
auto* vt = PresContext()->Document()->GetActiveViewTransition();
|
||||||
|
if (NS_WARN_IF(!vt)) {
|
||||||
|
return kNoKey;
|
||||||
|
}
|
||||||
|
const auto* key =
|
||||||
|
Style()->GetPseudoType() == PseudoStyleType::viewTransitionOld
|
||||||
|
? vt->GetOldImageKey(name, aManager, aResources)
|
||||||
|
: vt->GetNewImageKey(name);
|
||||||
|
return key ? *key : kNoKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
AspectRatio nsImageFrame::ComputeIntrinsicRatioForImage(
|
AspectRatio nsImageFrame::ComputeIntrinsicRatioForImage(
|
||||||
@@ -976,8 +997,8 @@ AspectRatio nsImageFrame::ComputeIntrinsicRatioForImage(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto* surf = GetViewTransitionSurface()) {
|
if (auto size = GetViewTransitionSnapshotSize()) {
|
||||||
return AspectRatio::FromSize(surf->GetSize());
|
return AspectRatio::FromSize(*size);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ShouldUseMappedAspectRatio()) {
|
if (ShouldUseMappedAspectRatio()) {
|
||||||
@@ -2344,35 +2365,17 @@ void nsDisplayImage::MaybeCreateWebRenderCommandsForViewTransition(
|
|||||||
nsDisplayListBuilder* aDisplayListBuilder) {
|
nsDisplayListBuilder* aDisplayListBuilder) {
|
||||||
auto* frame = Frame();
|
auto* frame = Frame();
|
||||||
MOZ_ASSERT(!frame->mImage);
|
MOZ_ASSERT(!frame->mImage);
|
||||||
auto* surf = frame->GetViewTransitionSurface();
|
auto key = frame->GetViewTransitionImageKey(aManager, aResources);
|
||||||
if (NS_WARN_IF(!surf)) {
|
if (NS_WARN_IF(key == kNoKey)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!frame->mViewTransitionData.HasKey()) {
|
|
||||||
DataSourceSurface::ScopedMap map(surf, DataSourceSurface::READ);
|
|
||||||
if (NS_WARN_IF(!map.IsMapped())) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto key = aManager->WrBridge()->GetNextImageKey();
|
|
||||||
auto size = surf->GetSize();
|
|
||||||
auto format = surf->GetFormat();
|
|
||||||
wr::ImageDescriptor desc(size, format);
|
|
||||||
Range<uint8_t> bytes(map.GetData(), map.GetStride() * size.height);
|
|
||||||
if (NS_WARN_IF(!aResources.AddImage(key, desc, bytes))) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// TODO: Discard this image
|
|
||||||
frame->mViewTransitionData.mImageKey = key;
|
|
||||||
frame->mViewTransitionData.mManager = aManager;
|
|
||||||
}
|
|
||||||
const nsRect destAppUnits = GetDestRect();
|
const nsRect destAppUnits = GetDestRect();
|
||||||
const int32_t factor = mFrame->PresContext()->AppUnitsPerDevPixel();
|
const int32_t factor = mFrame->PresContext()->AppUnitsPerDevPixel();
|
||||||
const auto destRect =
|
const auto destRect =
|
||||||
wr::ToLayoutRect(LayoutDeviceRect::FromAppUnits(destAppUnits, factor));
|
wr::ToLayoutRect(LayoutDeviceRect::FromAppUnits(destAppUnits, factor));
|
||||||
auto rendering = wr::ToImageRendering(frame->UsedImageRendering());
|
auto rendering = wr::ToImageRendering(frame->UsedImageRendering());
|
||||||
aBuilder.PushImage(destRect, destRect, !BackfaceIsHidden(),
|
aBuilder.PushImage(destRect, destRect, !BackfaceIsHidden(),
|
||||||
/* aForceAntiAliasing = */ false, rendering,
|
/* aForceAntiAliasing = */ false, rendering, key);
|
||||||
frame->mViewTransitionData.mImageKey);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nsDisplayImage::CreateWebRenderCommands(
|
bool nsDisplayImage::CreateWebRenderCommands(
|
||||||
@@ -2576,7 +2579,7 @@ void nsImageFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||||||
aBuilder, this, clipFlags);
|
aBuilder, this, clipFlags);
|
||||||
|
|
||||||
if (!mComputedSize.IsEmpty()) {
|
if (!mComputedSize.IsEmpty()) {
|
||||||
const bool isViewTransition = mKind == Kind::ViewTransitionOld;
|
const bool isViewTransition = mKind == Kind::ViewTransition;
|
||||||
const bool imageOK = mKind != Kind::ImageLoadingContent ||
|
const bool imageOK = mKind != Kind::ImageLoadingContent ||
|
||||||
ImageOk(mContent->AsElement()->State());
|
ImageOk(mContent->AsElement()->State());
|
||||||
|
|
||||||
|
|||||||
@@ -196,8 +196,9 @@ class nsImageFrame : public nsAtomicContainerFrame, public nsIReflowCallback {
|
|||||||
ContentPropertyAtIndex,
|
ContentPropertyAtIndex,
|
||||||
// For a list-style-image ::marker.
|
// For a list-style-image ::marker.
|
||||||
ListStyleImage,
|
ListStyleImage,
|
||||||
// For a ::view-transition-old pseudo-element
|
// For a ::view-transition-old or ::view-transition-new pseudo-element.
|
||||||
ViewTransitionOld,
|
// Which one of the two is determined by the PseudoStyleType applying to us.
|
||||||
|
ViewTransition,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Creates a suitable continuing frame for this frame.
|
// Creates a suitable continuing frame for this frame.
|
||||||
@@ -216,8 +217,8 @@ class nsImageFrame : public nsAtomicContainerFrame, public nsIReflowCallback {
|
|||||||
ComputedStyle*);
|
ComputedStyle*);
|
||||||
friend nsIFrame* NS_NewImageFrameForListStyleImage(mozilla::PresShell*,
|
friend nsIFrame* NS_NewImageFrameForListStyleImage(mozilla::PresShell*,
|
||||||
ComputedStyle*);
|
ComputedStyle*);
|
||||||
friend nsIFrame* NS_NewImageFrameForViewTransitionOld(mozilla::PresShell*,
|
friend nsIFrame* NS_NewImageFrameForViewTransition(mozilla::PresShell*,
|
||||||
ComputedStyle*);
|
ComputedStyle*);
|
||||||
|
|
||||||
nsImageFrame(ComputedStyle* aStyle, nsPresContext* aPresContext, Kind aKind)
|
nsImageFrame(ComputedStyle* aStyle, nsPresContext* aPresContext, Kind aKind)
|
||||||
: nsImageFrame(aStyle, aPresContext, kClassID, aKind) {}
|
: nsImageFrame(aStyle, aPresContext, kClassID, aKind) {}
|
||||||
@@ -306,7 +307,11 @@ class nsImageFrame : public nsAtomicContainerFrame, public nsIReflowCallback {
|
|||||||
// and height="".
|
// and height="".
|
||||||
bool ShouldUseMappedAspectRatio() const;
|
bool ShouldUseMappedAspectRatio() const;
|
||||||
|
|
||||||
mozilla::gfx::DataSourceSurface* GetViewTransitionSurface() const;
|
nsAtom* GetViewTransitionName() const;
|
||||||
|
Maybe<nsSize> GetViewTransitionSnapshotSize() const;
|
||||||
|
mozilla::wr::ImageKey GetViewTransitionImageKey(
|
||||||
|
mozilla::layers::RenderRootStateManager*,
|
||||||
|
mozilla::wr::IpcResourceUpdateQueue&) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notification that aRequest will now be the current request.
|
* Notification that aRequest will now be the current request.
|
||||||
@@ -398,15 +403,6 @@ class nsImageFrame : public nsAtomicContainerFrame, public nsIReflowCallback {
|
|||||||
nsCOMPtr<imgIContainer> mImage;
|
nsCOMPtr<imgIContainer> mImage;
|
||||||
nsCOMPtr<imgIContainer> mPrevImage;
|
nsCOMPtr<imgIContainer> mPrevImage;
|
||||||
|
|
||||||
struct ViewTransitionData {
|
|
||||||
// The image key of our snapshot.
|
|
||||||
mozilla::wr::ImageKey mImageKey{{0}, 0};
|
|
||||||
// The owner of the key.
|
|
||||||
RefPtr<mozilla::layers::RenderRootStateManager> mManager;
|
|
||||||
|
|
||||||
bool HasKey() const { return mImageKey != mozilla::wr::ImageKey{{0}, 0}; }
|
|
||||||
} mViewTransitionData;
|
|
||||||
|
|
||||||
// The content-box size as if we are not fragmented, cached in the most recent
|
// The content-box size as if we are not fragmented, cached in the most recent
|
||||||
// reflow.
|
// reflow.
|
||||||
nsSize mComputedSize;
|
nsSize mComputedSize;
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
#include "mozilla/dom/HTMLCanvasElement.h"
|
#include "mozilla/dom/HTMLCanvasElement.h"
|
||||||
#include "mozilla/dom/RemoteBrowser.h"
|
#include "mozilla/dom/RemoteBrowser.h"
|
||||||
#include "mozilla/dom/Selection.h"
|
#include "mozilla/dom/Selection.h"
|
||||||
|
#include "mozilla/dom/ViewTransition.h"
|
||||||
#include "mozilla/dom/ServiceWorkerRegistrar.h"
|
#include "mozilla/dom/ServiceWorkerRegistrar.h"
|
||||||
#include "mozilla/dom/ServiceWorkerRegistration.h"
|
#include "mozilla/dom/ServiceWorkerRegistration.h"
|
||||||
#include "mozilla/dom/SVGElement.h"
|
#include "mozilla/dom/SVGElement.h"
|
||||||
@@ -5203,10 +5204,11 @@ bool nsDisplayOwnLayer::CreateWebRenderCommands(
|
|||||||
const StackingContextHelper& aSc, RenderRootStateManager* aManager,
|
const StackingContextHelper& aSc, RenderRootStateManager* aManager,
|
||||||
nsDisplayListBuilder* aDisplayListBuilder) {
|
nsDisplayListBuilder* aDisplayListBuilder) {
|
||||||
Maybe<wr::WrAnimationProperty> prop;
|
Maybe<wr::WrAnimationProperty> prop;
|
||||||
bool needsProp = aManager->LayerManager()->AsyncPanZoomEnabled() &&
|
Maybe<wr::SnapshotInfo> snapshot;
|
||||||
(IsScrollThumbLayer() || IsZoomingLayer() ||
|
const bool needsProp = aManager->LayerManager()->AsyncPanZoomEnabled() &&
|
||||||
ShouldGetFixedAnimationId() ||
|
(IsScrollThumbLayer() || IsZoomingLayer() ||
|
||||||
(IsRootScrollbarContainer() && HasDynamicToolbar()));
|
ShouldGetFixedAnimationId() ||
|
||||||
|
(IsRootScrollbarContainer() && HasDynamicToolbar()));
|
||||||
|
|
||||||
if (needsProp) {
|
if (needsProp) {
|
||||||
// APZ is enabled and this is a scroll thumb or zooming layer, so we need
|
// APZ is enabled and this is a scroll thumb or zooming layer, so we need
|
||||||
@@ -5228,12 +5230,33 @@ bool nsDisplayOwnLayer::CreateWebRenderCommands(
|
|||||||
params.animation = prop.ptrOr(nullptr);
|
params.animation = prop.ptrOr(nullptr);
|
||||||
params.clip =
|
params.clip =
|
||||||
wr::WrStackingContextClip::ClipChain(aBuilder.CurrentClipChainId());
|
wr::WrStackingContextClip::ClipChain(aBuilder.CurrentClipChainId());
|
||||||
if (IsScrollbarContainer() && IsRootScrollbarContainer()) {
|
const bool rootScrollbarContainer = IsRootScrollbarContainer();
|
||||||
|
if (rootScrollbarContainer) {
|
||||||
params.prim_flags |= wr::PrimitiveFlags::IS_SCROLLBAR_CONTAINER;
|
params.prim_flags |= wr::PrimitiveFlags::IS_SCROLLBAR_CONTAINER;
|
||||||
}
|
}
|
||||||
if (IsZoomingLayer() ||
|
if (mFrame->HasAnyStateBits(NS_FRAME_CAPTURED_IN_VIEW_TRANSITION)) {
|
||||||
(ShouldGetFixedAnimationId() ||
|
auto key = [&]() -> Maybe<wr::SnapshotImageKey> {
|
||||||
(IsRootScrollbarContainer() && HasDynamicToolbar()))) {
|
auto* vt = mFrame->PresContext()->Document()->GetActiveViewTransition();
|
||||||
|
if (NS_WARN_IF(!vt)) {
|
||||||
|
return Nothing();
|
||||||
|
}
|
||||||
|
const auto* key =
|
||||||
|
vt->GetImageKeyForCapturedFrame(mFrame, aManager, aResources);
|
||||||
|
return key ? Some(wr::SnapshotImageKey{*key}) : Nothing();
|
||||||
|
}();
|
||||||
|
if (key) {
|
||||||
|
float auPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
|
||||||
|
snapshot.emplace(wr::SnapshotInfo{
|
||||||
|
.key = *key,
|
||||||
|
.area = wr::ToLayoutRect(LayoutDeviceRect::FromAppUnits(
|
||||||
|
mFrame->InkOverflowRectRelativeToSelf(), auPerDevPixel)),
|
||||||
|
.detached = true,
|
||||||
|
});
|
||||||
|
params.snapshot = snapshot.ptr();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (IsZoomingLayer() || ShouldGetFixedAnimationId() ||
|
||||||
|
(rootScrollbarContainer && HasDynamicToolbar())) {
|
||||||
params.is_2d_scale_translation = true;
|
params.is_2d_scale_translation = true;
|
||||||
params.should_snap = true;
|
params.should_snap = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5380,7 +5380,7 @@ class nsDisplayOwnLayer : public nsDisplayWrapList {
|
|||||||
public:
|
public:
|
||||||
enum OwnLayerType {
|
enum OwnLayerType {
|
||||||
OwnLayerForTransformWithRoundedClip,
|
OwnLayerForTransformWithRoundedClip,
|
||||||
OwnLayerForStackingContext,
|
OwnLayerForViewTransitionCapture,
|
||||||
OwnLayerForScrollbar,
|
OwnLayerForScrollbar,
|
||||||
OwnLayerForScrollThumb,
|
OwnLayerForScrollThumb,
|
||||||
OwnLayerForSubdoc,
|
OwnLayerForSubdoc,
|
||||||
|
|||||||
@@ -4923,6 +4923,12 @@
|
|||||||
value: false
|
value: false
|
||||||
mirror: always
|
mirror: always
|
||||||
|
|
||||||
|
# Whether view transitions use webrender for live-capture
|
||||||
|
- name: dom.viewTransitions.live-capture
|
||||||
|
type: bool
|
||||||
|
value: false
|
||||||
|
mirror: always
|
||||||
|
|
||||||
# Is support for WebVR APIs enabled?
|
# Is support for WebVR APIs enabled?
|
||||||
# Disabled everywhere, but not removed.
|
# Disabled everywhere, but not removed.
|
||||||
- name: dom.vr.enabled
|
- name: dom.vr.enabled
|
||||||
|
|||||||
Reference in New Issue
Block a user