Bug 1724839 - Don't use BasicLayerManager to paint video elements. r=jrmuizel

Depends on D122172

Differential Revision: https://phabricator.services.mozilla.com/D122173
This commit is contained in:
Matt Woodrow 2021-08-10 03:38:41 +00:00
Родитель 1d5382e878
Коммит d93a690a00
1 изменённых файлов: 61 добавлений и 25 удалений

Просмотреть файл

@ -594,24 +594,19 @@ class nsDisplayVideo : public nsPaintedDisplayItem {
NS_DISPLAY_DECL_NAME("Video", TYPE_VIDEO)
virtual bool CreateWebRenderCommands(
mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const mozilla::layers::StackingContextHelper& aSc,
mozilla::layers::RenderRootStateManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder) override {
already_AddRefed<ImageContainer> GetImageContainer(gfxRect& aDestGFXRect) {
nsRect area = Frame()->GetContentRectRelativeToSelf() + ToReferenceFrame();
HTMLVideoElement* element =
static_cast<HTMLVideoElement*>(Frame()->GetContent());
Maybe<CSSIntSize> videoSizeInPx = element->GetVideoSize();
if (videoSizeInPx.isNothing() || area.IsEmpty()) {
return true;
return nullptr;
}
RefPtr<ImageContainer> container = element->GetImageContainer();
if (!container) {
return true;
return nullptr;
}
// Retrieve the size of the decoded video frame, before being scaled
@ -619,7 +614,7 @@ class nsDisplayVideo : public nsPaintedDisplayItem {
mozilla::gfx::IntSize frameSize = container->GetCurrentSize();
if (frameSize.width == 0 || frameSize.height == 0) {
// No image, or zero-sized image. Don't render.
return true;
return nullptr;
}
const auto aspectRatio = AspectRatio::FromSize(*videoSizeInPx);
@ -627,9 +622,26 @@ class nsDisplayVideo : public nsPaintedDisplayItem {
nsRect dest = nsLayoutUtils::ComputeObjectDestRect(
area, intrinsicSize, aspectRatio, Frame()->StylePosition());
gfxRect destGFXRect = Frame()->PresContext()->AppUnitsToGfxUnits(dest);
destGFXRect.Round();
if (destGFXRect.IsEmpty()) {
aDestGFXRect = Frame()->PresContext()->AppUnitsToGfxUnits(dest);
aDestGFXRect.Round();
if (aDestGFXRect.IsEmpty()) {
return nullptr;
}
return container.forget();
}
virtual bool CreateWebRenderCommands(
mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const mozilla::layers::StackingContextHelper& aSc,
mozilla::layers::RenderRootStateManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder) override {
HTMLVideoElement* element =
static_cast<HTMLVideoElement*>(Frame()->GetContent());
gfxRect destGFXRect;
RefPtr<ImageContainer> container = GetImageContainer(destGFXRect);
if (!container) {
return true;
}
@ -689,22 +701,46 @@ class nsDisplayVideo : public nsPaintedDisplayItem {
virtual void Paint(nsDisplayListBuilder* aBuilder,
gfxContext* aCtx) override {
// This currently uses BasicLayerManager to re-use the code for extracting
// the current Image and generating DrawTarget rendering commands for it.
// Ideally we'll factor out that code and use it directly soon.
RefPtr<BasicLayerManager> layerManager =
new BasicLayerManager(BasicLayerManager::BLM_OFFSCREEN);
layerManager->BeginTransactionWithTarget(aCtx);
RefPtr<Layer> layer =
BuildLayer(aBuilder, layerManager, ContainerLayerParameters());
if (!layer) {
layerManager->AbortTransaction();
HTMLVideoElement* element =
static_cast<HTMLVideoElement*>(Frame()->GetContent());
gfxRect destGFXRect;
RefPtr<ImageContainer> container = GetImageContainer(destGFXRect);
if (!container) {
return;
}
layerManager->SetRoot(layer);
layerManager->EndEmptyTransaction();
VideoInfo::Rotation rotationDeg = element->RotationDegrees();
Matrix preTransform = ComputeRotationMatrix(
destGFXRect.Width(), destGFXRect.Height(), rotationDeg);
Matrix transform =
preTransform * Matrix::Translation(destGFXRect.x, destGFXRect.y);
AutoLockImage autoLock(container);
Image* image = autoLock.GetImage(TimeStamp::Now());
if (!image) {
return;
}
RefPtr<gfx::SourceSurface> surface = image->GetAsSourceSurface();
if (!surface || !surface->IsValid()) {
return;
}
gfx::IntSize size = surface->GetSize();
IntSize scaleToSize(static_cast<int32_t>(destGFXRect.Width()),
static_cast<int32_t>(destGFXRect.Height()));
// scaleHint is set regardless of rotation, so swap w/h if needed.
SwapScaleWidthHeightForRotation(scaleToSize, rotationDeg);
transform.PreScale(scaleToSize.width / size.Width(),
scaleToSize.height / size.Height());
gfxContextMatrixAutoSaveRestore saveMatrix(aCtx);
aCtx->Multiply(ThebesMatrix(transform));
aCtx->GetDrawTarget()->FillRect(
Rect(0, 0, size.width, size.height),
SurfacePattern(surface, ExtendMode::CLAMP, Matrix(),
nsLayoutUtils::GetSamplingFilterForFrame(Frame())),
DrawOptions());
}
};