зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
1d5382e878
Коммит
d93a690a00
|
@ -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());
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче