Bug 1407753 - Factor out webrender border code for reuse. r?jrmuizel
Also explicitly disables the image-border and gradient-border cases,
which were already accidentally disabled. They are too bitrotted to turn
back on at the moment.
MozReview-Commit-ID: FRXqemXQHJN
--- a/layout/painting/nsCSSRendering.cpp
+++ b/layout/painting/nsCSSRendering.cpp
@@ -688,16 +688,104 @@ nsCSSRendering::CreateBorderRenderer(nsP
newStyleBorder.mBorderColor[side] = StyleComplexColor::FromColor(color);
}
return CreateBorderRendererWithStyleBorder(aPresContext, aDrawTarget,
aForFrame, aDirtyRect, aBorderArea,
newStyleBorder, aStyleContext,
aSkipSides);
}
+
+bool
+nsCSSRendering::CreateWebRenderCommandsForBorder(nsDisplayItem* aItem,
+ nsIFrame* aForFrame,
+ const nsRect& aBorderArea,
+ mozilla::wr::DisplayListBuilder& aBuilder,
+ mozilla::wr::IpcResourceUpdateQueue& aResources,
+ const mozilla::layers::StackingContextHelper& aSc,
+ mozilla::layers::WebRenderLayerManager* aManager,
+ nsDisplayListBuilder* aDisplayListBuilder)
+{
+ // First try to draw a normal border
+ {
+ Maybe<nsCSSBorderRenderer> br =
+ nsCSSRendering::CreateBorderRenderer(aForFrame->PresContext(),
+ nullptr,
+ aForFrame,
+ nsRect(),
+ aBorderArea,
+ aForFrame->StyleContext(),
+ aForFrame->GetSkipSides());
+
+ if (br) {
+ if (!br->CanCreateWebRenderCommands()) {
+ return false;
+ }
+ br->CreateWebRenderCommands(aBuilder, aResources, aSc);
+ return true;
+ }
+ }
+
+ // Next try to draw an image border
+ const nsStyleBorder *styleBorder = aForFrame->StyleContext()->StyleBorder();
+ const nsStyleImage* image = &styleBorder->mBorderImageSource;
+
+ // Filter out unsupported image/border types
+ if (!image) {
+ return false;
+ }
+
+ // All this code bitrotted too much (but is almost right); disabled for now.
+ bool imageTypeSupported = false;
+ // FIXME(1409773): fix this: image->GetType() == eStyleImageType_Image
+ // FIXME(1409774): fix this: image->GetType() == eStyleImageType_Gradient;
+
+ if (!imageTypeSupported) {
+ return false;
+ }
+
+ if (styleBorder->mBorderImageRepeatH == NS_STYLE_BORDER_IMAGE_REPEAT_ROUND ||
+ styleBorder->mBorderImageRepeatH == NS_STYLE_BORDER_IMAGE_REPEAT_SPACE ||
+ styleBorder->mBorderImageRepeatV == NS_STYLE_BORDER_IMAGE_REPEAT_ROUND ||
+ styleBorder->mBorderImageRepeatV == NS_STYLE_BORDER_IMAGE_REPEAT_SPACE) {
+ return false;
+ }
+
+
+ uint32_t flags = 0;
+ if (aDisplayListBuilder->ShouldSyncDecodeImages()) {
+ flags |= nsImageRenderer::FLAG_SYNC_DECODE_IMAGES;
+ }
+
+ image::DrawResult result;
+ Maybe<nsCSSBorderImageRenderer> bir =
+ nsCSSBorderImageRenderer::CreateBorderImageRenderer(aForFrame->PresContext(),
+ aForFrame,
+ aBorderArea,
+ *styleBorder,
+ aItem->GetVisibleRect(),
+ aForFrame->GetSkipSides(),
+ flags,
+ &result);
+
+ if (!bir) {
+ return false;
+ }
+
+ if (image->GetType() == eStyleImageType_Image &&
+ !bir->mImageRenderer.IsImageContainerAvailable(aManager, flags)) {
+ return false;
+ }
+
+ bir->CreateWebRenderCommands(aItem, aForFrame, aBuilder, aResources, aSc,
+ aManager, aDisplayListBuilder);
+
+ return true;
+}
+
nsCSSBorderRenderer
ConstructBorderRenderer(nsPresContext* aPresContext,
nsStyleContext* aStyleContext,
DrawTarget* aDrawTarget,
nsIFrame* aForFrame,
const nsRect& aDirtyRect,
const nsRect& aBorderArea,
const nsStyleBorder& aStyleBorder,
--- a/layout/painting/nsCSSRendering.h
+++ b/layout/painting/nsCSSRendering.h
@@ -207,16 +207,26 @@ struct nsCSSRendering {
static mozilla::Maybe<nsCSSBorderRenderer>
CreateBorderRendererForOutline(nsPresContext* aPresContext,
gfxContext* aRenderingContext,
nsIFrame* aForFrame,
const nsRect& aDirtyRect,
const nsRect& aBorderArea,
nsStyleContext* aStyleContext);
+
+ static bool CreateWebRenderCommandsForBorder(nsDisplayItem* aItem,
+ nsIFrame* aForFrame,
+ const nsRect& aBorderArea,
+ mozilla::wr::DisplayListBuilder& aBuilder,
+ mozilla::wr::IpcResourceUpdateQueue& aResources,
+ const mozilla::layers::StackingContextHelper& aSc,
+ mozilla::layers::WebRenderLayerManager* aManager,
+ nsDisplayListBuilder* aDisplayListBuilder);
+
/**
* Render the outline for an element using css rendering rules
* for borders.
*/
static void PaintOutline(nsPresContext* aPresContext,
gfxContext& aRenderingContext,
nsIFrame* aForFrame,
const nsRect& aDirtyRect,
--- a/layout/painting/nsCSSRenderingBorders.cpp
+++ b/layout/painting/nsCSSRenderingBorders.cpp
@@ -13,16 +13,17 @@
#include "mozilla/gfx/PathHelpers.h"
#include "BorderConsts.h"
#include "DashedCornerFinder.h"
#include "DottedCornerFinder.h"
#include "nsLayoutUtils.h"
#include "nsStyleConsts.h"
#include "nsContentUtils.h"
#include "nsCSSColorUtils.h"
+#include "nsCSSRenderingGradients.h"
#include "GeckoProfiler.h"
#include "nsExpirationTracker.h"
#include "RoundedRect.h"
#include "nsIScriptError.h"
#include "nsClassHashtable.h"
#include "nsPresContext.h"
#include "nsStyleStruct.h"
#include "mozilla/gfx/2D.h"
@@ -3848,16 +3849,132 @@ nsCSSBorderImageRenderer::DrawBorderImag
unitSize, j * (RIGHT + 1) + i,
svgViewportSize, hasIntrinsicRatio);
}
}
return result;
}
+
+void
+nsCSSBorderImageRenderer::CreateWebRenderCommands(nsDisplayItem* aItem,
+ nsIFrame* aForFrame,
+ mozilla::wr::DisplayListBuilder& aBuilder,
+ mozilla::wr::IpcResourceUpdateQueue& aResources,
+ const mozilla::layers::StackingContextHelper& aSc,
+ mozilla::layers::WebRenderLayerManager* aManager,
+ nsDisplayListBuilder* aDisplayListBuilder)
+{
+ if (!mImageRenderer.IsReady()) {
+ return;
+ }
+
+ float widths[4];
+ float slice[4];
+ float outset[4];
+ const int32_t appUnitsPerDevPixel = aForFrame->PresContext()->AppUnitsPerDevPixel();
+ NS_FOR_CSS_SIDES(i) {
+ slice[i] = (float)(mSlice.Side(i)) / appUnitsPerDevPixel;
+ widths[i] = (float)(mWidths.Side(i)) / appUnitsPerDevPixel;
+ outset[i] = (float)(mImageOutset.Side(i)) / appUnitsPerDevPixel;
+ }
+
+ LayoutDeviceRect destRect = LayoutDeviceRect::FromAppUnits(
+ mArea, appUnitsPerDevPixel);
+ wr::LayoutRect dest = aSc.ToRelativeLayoutRect(destRect);
+
+ wr::LayoutRect clip = dest;
+ if (!mClip.IsEmpty()) {
+ LayoutDeviceRect clipRect = LayoutDeviceRect::FromAppUnits(
+ mClip, appUnitsPerDevPixel);
+ clip = aSc.ToRelativeLayoutRect(clipRect);
+ }
+
+ switch (mImageRenderer.GetType()) {
+ case eStyleImageType_Image:
+ {
+ uint32_t flags = aDisplayListBuilder->ShouldSyncDecodeImages() ?
+ imgIContainer::FLAG_SYNC_DECODE :
+ imgIContainer::FLAG_NONE;
+
+ RefPtr<imgIContainer> img = mImageRenderer.GetImage();
+ RefPtr<layers::ImageContainer> container = img->GetImageContainer(aManager, flags);
+ if (!container) {
+ return;
+ }
+
+ gfx::IntSize size;
+ Maybe<wr::ImageKey> key = aManager->CommandBuilder().CreateImageKey(aItem, container, aBuilder,
+ aResources, aSc, size);
+ if (key.isNothing()) {
+ return;
+ }
+
+ aBuilder.PushBorderImage(dest,
+ clip,
+ !aItem->BackfaceIsHidden(),
+ wr::ToBorderWidths(widths[0], widths[1], widths[2], widths[3]),
+ key.value(),
+ wr::ToNinePatchDescriptor(
+ (float)(mImageSize.width) / appUnitsPerDevPixel,
+ (float)(mImageSize.height) / appUnitsPerDevPixel,
+ wr::ToSideOffsets2D_u32(slice[0], slice[1], slice[2], slice[3])),
+ wr::ToSideOffsets2D_f32(outset[0], outset[1], outset[2], outset[3]),
+ wr::ToRepeatMode(mRepeatModeHorizontal),
+ wr::ToRepeatMode(mRepeatModeVertical));
+ break;
+ }
+ case eStyleImageType_Gradient:
+ {
+ RefPtr<nsStyleGradient> gradientData = mImageRenderer.GetGradientData();
+ nsCSSGradientRenderer renderer =
+ nsCSSGradientRenderer::Create(aForFrame->PresContext(), gradientData,
+ mImageSize);
+
+ wr::ExtendMode extendMode;
+ nsTArray<wr::GradientStop> stops;
+ LayoutDevicePoint lineStart;
+ LayoutDevicePoint lineEnd;
+ LayoutDeviceSize gradientRadius;
+ renderer.BuildWebRenderParameters(1.0, extendMode, stops, lineStart, lineEnd, gradientRadius);
+
+ if (gradientData->mShape == NS_STYLE_GRADIENT_SHAPE_LINEAR) {
+ LayerPoint startPoint = LayerPoint(dest.origin.x, dest.origin.y);
+ startPoint = startPoint + ViewAs<LayerPixel>(lineStart, PixelCastJustification::WebRenderHasUnitResolution);
+ LayerPoint endPoint = LayerPoint(dest.origin.x, dest.origin.y);
+ endPoint = endPoint + ViewAs<LayerPixel>(lineEnd, PixelCastJustification::WebRenderHasUnitResolution);
+
+ aBuilder.PushBorderGradient(dest,
+ clip,
+ !aItem->BackfaceIsHidden(),
+ wr::ToBorderWidths(widths[0], widths[1], widths[2], widths[3]),
+ wr::ToLayoutPoint(startPoint),
+ wr::ToLayoutPoint(endPoint),
+ stops,
+ extendMode,
+ wr::ToSideOffsets2D_f32(outset[0], outset[1], outset[2], outset[3]));
+ } else {
+ aBuilder.PushBorderRadialGradient(dest,
+ clip,
+ !aItem->BackfaceIsHidden(),
+ wr::ToBorderWidths(widths[0], widths[1], widths[2], widths[3]),
+ wr::ToLayoutPoint(lineStart),
+ wr::ToLayoutSize(gradientRadius),
+ stops,
+ extendMode,
+ wr::ToSideOffsets2D_f32(outset[0], outset[1], outset[2], outset[3]));
+ }
+ break;
+ }
+ default:
+ MOZ_ASSERT_UNREACHABLE("Unsupport border image type");
+ }
+}
+
nsCSSBorderImageRenderer::nsCSSBorderImageRenderer(const nsCSSBorderImageRenderer& aRhs)
: mImageRenderer(aRhs.mImageRenderer)
, mImageSize(aRhs.mImageSize)
, mSlice(aRhs.mSlice)
, mWidths(aRhs.mWidths)
, mImageOutset(aRhs.mImageOutset)
, mArea(aRhs.mArea)
, mClip(aRhs.mClip)
--- a/layout/painting/nsCSSRenderingBorders.h
+++ b/layout/painting/nsCSSRenderingBorders.h
@@ -304,16 +304,24 @@ public:
uint32_t aFlags,
mozilla::image::DrawResult* aDrawResult);
mozilla::image::DrawResult
DrawBorderImage(nsPresContext* aPresContext,
gfxContext& aRenderingContext,
nsIFrame* aForFrame,
const nsRect& aDirtyRect);
+ void
+ CreateWebRenderCommands(nsDisplayItem* aItem,
+ nsIFrame* aForFrame,
+ mozilla::wr::DisplayListBuilder& aBuilder,
+ mozilla::wr::IpcResourceUpdateQueue& aResources,
+ const mozilla::layers::StackingContextHelper& aSc,
+ mozilla::layers::WebRenderLayerManager* aManager,
+ nsDisplayListBuilder* aDisplayListBuilder);
nsCSSBorderImageRenderer(const nsCSSBorderImageRenderer& aRhs);
nsCSSBorderImageRenderer& operator=(const nsCSSBorderImageRenderer& aRhs);
private:
nsCSSBorderImageRenderer(nsIFrame* aForFrame,
const nsRect& aBorderArea,
const nsStyleBorder& aStyleBorder,
@@ -327,16 +335,17 @@ private:
nsMargin mImageOutset;
nsRect mArea;
nsRect mClip;
uint8_t mRepeatModeHorizontal;
uint8_t mRepeatModeVertical;
uint8_t mFill;
friend class nsDisplayBorder;
+ friend struct nsCSSRendering;
};
namespace mozilla {
#ifdef DEBUG_NEW_BORDERS
#include <stdarg.h>
static inline void PrintAsString(const mozilla::gfx::Point& p) {
fprintf (stderr, "[%f,%f]", p.x, p.y);
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -4901,60 +4901,16 @@ nsDisplayBorder::GetLayerState(nsDisplay
mBorderRenderer = Nothing();
mBorderImageRenderer = Nothing();
if ((!image ||
image->GetType() != eStyleImageType_Image ||
image->GetType() != eStyleImageType_Gradient) && !br) {
return LAYER_NONE;
}
- LayersBackend backend = aManager->GetBackendType();
- if (backend == layers::LayersBackend::LAYERS_WR) {
- if (br) {
- if (!br->CanCreateWebRenderCommands()) {
- return LAYER_NONE;
- }
- mBorderRenderer = br;
- } else {
- if (styleBorder->mBorderImageRepeatH == NS_STYLE_BORDER_IMAGE_REPEAT_ROUND ||
- styleBorder->mBorderImageRepeatH == NS_STYLE_BORDER_IMAGE_REPEAT_SPACE ||
- styleBorder->mBorderImageRepeatV == NS_STYLE_BORDER_IMAGE_REPEAT_ROUND ||
- styleBorder->mBorderImageRepeatV == NS_STYLE_BORDER_IMAGE_REPEAT_SPACE) {
- // WebRender not supports this currently
- return LAYER_NONE;
- }
-
- uint32_t flags = 0;
- if (aBuilder->ShouldSyncDecodeImages()) {
- flags |= nsImageRenderer::FLAG_SYNC_DECODE_IMAGES;
- }
-
- image::DrawResult result;
- mBorderImageRenderer =
- nsCSSBorderImageRenderer::CreateBorderImageRenderer(mFrame->PresContext(),
- mFrame,
- nsRect(offset, mFrame->GetSize()),
- *(mFrame->StyleContext()->StyleBorder()),
- mVisibleRect,
- mFrame->GetSkipSides(),
- flags,
- &result);
-
- if (!mBorderImageRenderer) {
- return LAYER_NONE;
- }
-
- if (!mBorderImageRenderer->mImageRenderer.IsImageContainerAvailable(aManager, flags)) {
- return LAYER_NONE;
- }
- }
-
- return LAYER_ACTIVE;
- }
-
if (!br) {
return LAYER_NONE;
}
bool hasCompositeColors;
if (!br->AllBordersSolid(&hasCompositeColors) || hasCompositeColors) {
return LAYER_NONE;
}
@@ -5017,29 +4973,26 @@ nsDisplayBorder::BuildLayer(nsDisplayLis
bool
nsDisplayBorder::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc,
mozilla::layers::WebRenderLayerManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder)
{
- ContainerLayerParameters parameter;
- if (GetLayerState(aDisplayListBuilder, aManager, parameter) != LAYER_ACTIVE) {
- return false;
- }
-
- if (mBorderImageRenderer) {
- CreateBorderImageWebRenderCommands(aBuilder, aResources, aSc,
- aManager, aDisplayListBuilder);
- } else if (mBorderRenderer) {
- mBorderRenderer->CreateWebRenderCommands(aBuilder, aResources, aSc);
- }
-
- return true;
+ nsRect rect = nsRect(ToReferenceFrame(), mFrame->GetSize());
+
+ return nsCSSRendering::CreateWebRenderCommandsForBorder(this,
+ mFrame,
+ rect,
+ aBuilder,
+ aResources,
+ aSc,
+ aManager,
+ aDisplayListBuilder);
};
void
nsDisplayBorder::CreateBorderImageWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc,
mozilla::layers::WebRenderLayerManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder)