Bug 1377571 - Add fallback path for layers-free. r=jrmuizel

MozReview-Commit-ID: KOM7JXYljX2

--HG--
extra : rebase_source : 94a8c314ac311a05256a27bd61648815b0e42734
This commit is contained in:
Ethan Lin 2017-07-06 00:29:41 +08:00
Родитель ae76578b49
Коммит a11b08a3ac
5 изменённых файлов: 176 добавлений и 38 удалений

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

@ -13,6 +13,7 @@
#include "mozilla/layers/StackingContextHelper.h"
#include "mozilla/layers/TextureClient.h"
#include "mozilla/layers/WebRenderBridgeChild.h"
#include "mozilla/layers/UpdateImageHelper.h"
#include "WebRenderCanvasLayer.h"
#include "WebRenderColorLayer.h"
#include "WebRenderContainerLayer.h"
@ -223,7 +224,7 @@ WebRenderLayerManager::CreateWebRenderCommandsFromDisplayList(nsDisplayList* aDi
if (!item->CreateWebRenderCommands(aBuilder, aSc, mParentCommands, this,
aDisplayListBuilder)) {
// TODO: fallback
PushItemAsImage(item, aBuilder, aSc, aDisplayListBuilder);
}
}
aDisplayList->AppendToTop(&savedItems);
@ -304,49 +305,132 @@ WebRenderLayerManager::PushImage(nsDisplayItem* aItem,
return true;
}
static void
PaintItemByDrawTarget(nsDisplayItem* aItem,
DrawTarget* aDT,
const LayerRect& aImageRect,
const LayerPoint& aOffset,
nsDisplayListBuilder* aDisplayListBuilder)
{
aDT->ClearRect(aImageRect.ToUnknownRect());
RefPtr<gfxContext> context = gfxContext::CreateOrNull(aDT, aOffset.ToUnknownPoint());
MOZ_ASSERT(context);
aItem->Paint(aDisplayListBuilder, context);
if (gfxPrefs::WebRenderHighlightPaintedLayers()) {
aDT->SetTransform(Matrix());
aDT->FillRect(Rect(0, 0, aImageRect.width, aImageRect.height), ColorPattern(Color(1.0, 0.0, 0.0, 0.5)));
}
if (aItem->Frame()->PresContext()->GetPaintFlashing()) {
aDT->SetTransform(Matrix());
float r = float(rand()) / RAND_MAX;
float g = float(rand()) / RAND_MAX;
float b = float(rand()) / RAND_MAX;
aDT->FillRect(Rect(0, 0, aImageRect.width, aImageRect.height), ColorPattern(Color(r, g, b, 0.5)));
}
}
bool
WebRenderLayerManager::PushItemAsBlobImage(nsDisplayItem* aItem,
WebRenderLayerManager::PushItemAsImage(nsDisplayItem* aItem,
wr::DisplayListBuilder& aBuilder,
const StackingContextHelper& aSc,
nsDisplayListBuilder* aDisplayListBuilder)
{
const int32_t appUnitsPerDevPixel = aItem->Frame()->PresContext()->AppUnitsPerDevPixel();
RefPtr<WebRenderFallbackData> fallbackData = CreateOrRecycleWebRenderUserData<WebRenderFallbackData>(aItem);
bool snap;
nsRect itemBounds = aItem->GetBounds(aDisplayListBuilder, &snap);
nsRect clippedBounds = itemBounds;
const DisplayItemClip& clip = aItem->GetClip();
if (clip.HasClip()) {
clippedBounds = itemBounds.Intersect(clip.GetClipRect());
}
const int32_t appUnitsPerDevPixel = aItem->Frame()->PresContext()->AppUnitsPerDevPixel();
LayerRect bounds = ViewAs<LayerPixel>(
LayoutDeviceRect::FromAppUnits(aItem->GetBounds(aDisplayListBuilder, &snap), appUnitsPerDevPixel),
LayoutDeviceRect::FromAppUnits(clippedBounds, appUnitsPerDevPixel),
PixelCastJustification::WebRenderHasUnitResolution);
LayerIntSize imageSize = RoundedToInt(bounds.Size());
LayerRect imageRect;
imageRect.SizeTo(LayerSize(imageSize));
if (imageSize.width == 0 || imageSize.height == 0) {
return true;
}
nsPoint shift = clippedBounds.TopLeft() - itemBounds.TopLeft();
LayerPoint offset = ViewAs<LayerPixel>(
LayoutDevicePoint::FromAppUnits(aItem->ToReferenceFrame() + shift, appUnitsPerDevPixel),
PixelCastJustification::WebRenderHasUnitResolution);
nsRegion invalidRegion;
nsAutoPtr<nsDisplayItemGeometry> geometry = fallbackData->GetGeometry();
if (geometry) {
nsPoint shift = itemBounds.TopLeft() - geometry->mBounds.TopLeft();
geometry->MoveBy(shift);
aItem->ComputeInvalidationRegion(aDisplayListBuilder, geometry, &invalidRegion);
nsRect lastBounds = fallbackData->GetBounds();
lastBounds.MoveBy(shift);
if (!lastBounds.IsEqualInterior(clippedBounds)) {
invalidRegion.OrWith(lastBounds);
invalidRegion.OrWith(clippedBounds);
}
}
if (!geometry || !invalidRegion.IsEmpty()) {
if (gfxPrefs::WebRenderBlobImages()) {
RefPtr<gfx::DrawEventRecorderMemory> recorder = MakeAndAddRef<gfx::DrawEventRecorderMemory>();
RefPtr<gfx::DrawTarget> dummyDt =
gfx::Factory::CreateDrawTarget(gfx::BackendType::SKIA, gfx::IntSize(1, 1), gfx::SurfaceFormat::B8G8R8X8);
RefPtr<gfx::DrawTarget> dt = gfx::Factory::CreateRecordingDrawTarget(recorder, dummyDt, imageSize.ToUnknownSize());
LayerPoint offset = ViewAs<LayerPixel>(
LayoutDevicePoint::FromAppUnits(aItem->ToReferenceFrame(), appUnitsPerDevPixel),
PixelCastJustification::WebRenderHasUnitResolution);
{
dt->ClearRect(imageRect.ToUnknownRect());
RefPtr<gfxContext> context = gfxContext::CreateOrNull(dt, offset.ToUnknownPoint());
MOZ_ASSERT(context);
aItem->Paint(aDisplayListBuilder, context);
}
PaintItemByDrawTarget(aItem, dt, imageRect, offset, aDisplayListBuilder);
recorder->Finish();
wr::ByteBuffer bytes(recorder->mOutputStream.mLength, (uint8_t*)recorder->mOutputStream.mData);
wr::ImageKey key = WrBridge()->GetNextImageKey();
WrBridge()->SendAddBlobImage(key, imageSize.ToUnknownSize(), imageSize.width * 4, dt->GetFormat(), bytes);
fallbackData->SetKey(key);
} else {
fallbackData->CreateImageClientIfNeeded();
RefPtr<ImageClient> imageClient = fallbackData->GetImageClient();
RefPtr<ImageContainer> imageContainer = LayerManager::CreateImageContainer();
{
UpdateImageHelper helper(imageContainer, imageClient, imageSize.ToUnknownSize());
{
RefPtr<gfx::DrawTarget> dt = helper.GetDrawTarget();
PaintItemByDrawTarget(aItem, dt, imageRect, offset, aDisplayListBuilder);
}
if (!helper.UpdateImage()) {
return false;
}
}
// Force update the key in fallback data since we repaint the image in this path.
// If not force update, fallbackData may reuse the original key because it
// doesn't know UpdateImageHelper already updated the image container.
if (!fallbackData->UpdateImageKey(imageContainer, true)) {
return false;
}
}
geometry = aItem->AllocateGeometry(aDisplayListBuilder);
}
// Update current bounds to fallback data
fallbackData->SetGeometry(Move(geometry));
fallbackData->SetBounds(clippedBounds);
MOZ_ASSERT(fallbackData->GetKey());
WrRect dest = aSc.ToRelativeWrRect(imageRect + offset);
WrImageKey key = WrBridge()->GetNextImageKey();
WrBridge()->SendAddBlobImage(key, imageSize.ToUnknownSize(), imageSize.width * 4, dt->GetFormat(), bytes);
AddImageKeyForDiscard(key);
aBuilder.PushImage(dest,
dest,
wr::ImageRendering::Auto,
key);
fallbackData->GetKey().value());
return true;
}

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

@ -64,7 +64,7 @@ public:
mozilla::wr::DisplayListBuilder& aBuilder,
const StackingContextHelper& aSc,
const LayerRect& aRect);
bool PushItemAsBlobImage(nsDisplayItem* aItem,
bool PushItemAsImage(nsDisplayItem* aItem,
wr::DisplayListBuilder& aBuilder,
const StackingContextHelper& aSc,
nsDisplayListBuilder* aDisplayListBuilder);

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

@ -4,6 +4,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "WebRenderUserData.h"
#include "nsDisplayListInvalidation.h"
namespace mozilla {
namespace layers {
@ -35,7 +36,7 @@ WebRenderImageData::~WebRenderImageData()
}
Maybe<wr::ImageKey>
WebRenderImageData::UpdateImageKey(ImageContainer* aContainer)
WebRenderImageData::UpdateImageKey(ImageContainer* aContainer, bool aForceUpdate)
{
CreateImageClientIfNeeded();
CreateExternalImageIfNeeded();
@ -61,7 +62,7 @@ WebRenderImageData::UpdateImageKey(ImageContainer* aContainer)
}
// Reuse old key if generation is not updated.
if (oldCounter == imageClient->GetLastUpdateGenerationCounter() && mKey) {
if (!aForceUpdate && oldCounter == imageClient->GetLastUpdateGenerationCounter() && mKey) {
return mKey;
}
@ -77,6 +78,13 @@ WebRenderImageData::UpdateImageKey(ImageContainer* aContainer)
return mKey;
}
already_AddRefed<ImageClient>
WebRenderImageData::GetImageClient()
{
RefPtr<ImageClient> imageClient = mImageClient;
return imageClient.forget();
}
void
WebRenderImageData::CreateAsyncImageWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
ImageContainer* aContainer,
@ -140,5 +148,26 @@ WebRenderImageData::CreateExternalImageIfNeeded()
}
}
WebRenderFallbackData::~WebRenderFallbackData()
{
}
WebRenderFallbackData::WebRenderFallbackData(WebRenderLayerManager* aWRManager)
: WebRenderImageData(aWRManager)
{
}
nsAutoPtr<nsDisplayItemGeometry>
WebRenderFallbackData::GetGeometry()
{
return mGeometry;
}
void
WebRenderFallbackData::SetGeometry(nsAutoPtr<nsDisplayItemGeometry> aGeometry)
{
mGeometry = aGeometry;
}
} // namespace layers
} // namespace mozilla

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

@ -9,6 +9,8 @@
#include "mozilla/layers/StackingContextHelper.h"
#include "mozilla/webrender/WebRenderAPI.h"
class nsDisplayItemGeometry;
namespace mozilla {
namespace layers {
class ImageClient;
@ -30,6 +32,7 @@ public:
enum class UserDataType {
eImage,
eFallback,
};
virtual UserDataType GetType() = 0;
@ -51,8 +54,11 @@ public:
virtual WebRenderImageData* AsImageData() override { return this; }
virtual UserDataType GetType() override { return UserDataType::eImage; }
static UserDataType Type() { return UserDataType::eImage; }
Maybe<wr::ImageKey> GetKey() { return mKey; }
void SetKey(const wr::ImageKey& aKey) { mKey = Some(aKey); }
already_AddRefed<ImageClient> GetImageClient();
Maybe<wr::ImageKey> UpdateImageKey(ImageContainer* aContainer);
Maybe<wr::ImageKey> UpdateImageKey(ImageContainer* aContainer, bool aForceUpdate = false);
void CreateAsyncImageWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
ImageContainer* aContainer,
@ -64,8 +70,9 @@ public:
const WrImageRendering& aFilter,
const WrMixBlendMode& aMixBlendMode);
protected:
void CreateImageClientIfNeeded();
protected:
void CreateExternalImageIfNeeded();
wr::MaybeExternalImageId mExternalImageId;
@ -75,6 +82,24 @@ protected:
RefPtr<ImageContainer> mContainer;
};
class WebRenderFallbackData : public WebRenderImageData
{
public:
explicit WebRenderFallbackData(WebRenderLayerManager* aWRManager);
virtual ~WebRenderFallbackData();
virtual UserDataType GetType() override { return UserDataType::eFallback; }
static UserDataType Type() { return UserDataType::eFallback; }
nsAutoPtr<nsDisplayItemGeometry> GetGeometry();
void SetGeometry(nsAutoPtr<nsDisplayItemGeometry> aGeometry);
nsRect GetBounds() { return mBounds; }
void SetBounds(const nsRect& aRect) { mBounds = aRect; }
protected:
nsAutoPtr<nsDisplayItemGeometry> mGeometry;
nsRect mBounds;
};
} // namespace layers
} // namespace mozilla

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

@ -490,7 +490,7 @@ BulletRenderer::CreateWebRenderCommandsForPath(nsDisplayItem* aItem,
{
MOZ_ASSERT(IsPathType());
if (!aManager->PushItemAsBlobImage(aItem, aBuilder, aSc, aDisplayListBuilder)) {
if (!aManager->PushItemAsImage(aItem, aBuilder, aSc, aDisplayListBuilder)) {
NS_WARNING("Fail to create WebRender commands for Bullet path.");
}
}