Bug 1355570 - Update bindings and WebRender display list building for gradient tiling r?mattwoodrow
MozReview-Commit-ID: KwhCBc8XxCN
--- a/gfx/webrender_bindings/WebRenderAPI.cpp
+++ b/gfx/webrender_bindings/WebRenderAPI.cpp
@@ -575,38 +575,44 @@ DisplayListBuilder::PushRect(const WrRec
}
void
DisplayListBuilder::PushLinearGradient(const WrRect& aBounds,
const WrClipRegion& aClip,
const WrPoint& aStartPoint,
const WrPoint& aEndPoint,
const nsTArray<WrGradientStop>& aStops,
- wr::GradientExtendMode aExtendMode)
+ wr::GradientExtendMode aExtendMode,
+ const WrSize aTileSize,
+ const WrSize aTileSpacing)
{
wr_dp_push_linear_gradient(mWrState,
aBounds, aClip,
aStartPoint, aEndPoint,
aStops.Elements(), aStops.Length(),
- aExtendMode);
+ aExtendMode,
+ aTileSize, aTileSpacing);
}
void
DisplayListBuilder::PushRadialGradient(const WrRect& aBounds,
const WrClipRegion& aClip,
const WrPoint& aCenter,
const WrSize& aRadius,
const nsTArray<WrGradientStop>& aStops,
- wr::GradientExtendMode aExtendMode)
+ wr::GradientExtendMode aExtendMode,
+ const WrSize aTileSize,
+ const WrSize aTileSpacing)
{
wr_dp_push_radial_gradient(mWrState,
aBounds, aClip,
aCenter, aRadius,
aStops.Elements(), aStops.Length(),
- aExtendMode);
+ aExtendMode,
+ aTileSize, aTileSpacing);
}
void
DisplayListBuilder::PushImage(const WrRect& aBounds,
const WrClipRegion& aClip,
wr::ImageRendering aFilter,
wr::ImageKey aImage)
{
--- a/gfx/webrender_bindings/WebRenderAPI.h
+++ b/gfx/webrender_bindings/WebRenderAPI.h
@@ -159,24 +159,28 @@ public:
const WrClipRegion& aClip,
const WrColor& aColor);
void PushLinearGradient(const WrRect& aBounds,
const WrClipRegion& aClip,
const WrPoint& aStartPoint,
const WrPoint& aEndPoint,
const nsTArray<WrGradientStop>& aStops,
- wr::GradientExtendMode aExtendMode);
+ wr::GradientExtendMode aExtendMode,
+ const WrSize aTileSize,
+ const WrSize aTileSpacing);
void PushRadialGradient(const WrRect& aBounds,
const WrClipRegion& aClip,
const WrPoint& aCenter,
const WrSize& aRadius,
const nsTArray<WrGradientStop>& aStops,
- wr::GradientExtendMode aExtendMode);
+ wr::GradientExtendMode aExtendMode,
+ const WrSize aTileSize,
+ const WrSize aTileSpacing);
void PushImage(const WrRect& aBounds,
const WrClipRegion& aClip,
wr::ImageRendering aFilter,
wr::ImageKey aImage);
void PushImage(const WrRect& aBounds,
const WrClipRegion& aClip,
--- a/gfx/webrender_bindings/src/bindings.rs
+++ b/gfx/webrender_bindings/src/bindings.rs
@@ -1345,60 +1345,66 @@ pub extern "C" fn wr_dp_push_border_radi
#[no_mangle]
pub extern "C" fn wr_dp_push_linear_gradient(state: &mut WrState,
rect: WrRect,
clip: WrClipRegion,
start_point: WrPoint,
end_point: WrPoint,
stops: *const WrGradientStop,
stops_count: usize,
- extend_mode: WrGradientExtendMode) {
+ extend_mode: WrGradientExtendMode,
+ tile_size: WrSize,
+ tile_spacing: WrSize) {
assert!(unsafe { is_in_main_thread() });
let stops =
WrGradientStop::to_gradient_stops(unsafe { slice::from_raw_parts(stops, stops_count) });
let gradient = state.frame_builder.dl_builder.create_gradient(start_point.to_point(),
end_point.to_point(),
stops,
extend_mode.to_gradient_extend_mode());
let rect = rect.to_rect();
- let tile_size = rect.size.clone();
+ let tile_size = tile_size.to_size();
+ let tile_spacing = tile_spacing.to_size();
state.frame_builder.dl_builder.push_gradient(rect,
clip.to_clip_region(),
gradient,
tile_size,
- LayoutSize::new(0.0, 0.0));
+ tile_spacing);
}
#[no_mangle]
pub extern "C" fn wr_dp_push_radial_gradient(state: &mut WrState,
rect: WrRect,
clip: WrClipRegion,
center: WrPoint,
radius: WrSize,
stops: *const WrGradientStop,
stops_count: usize,
- extend_mode: WrGradientExtendMode) {
+ extend_mode: WrGradientExtendMode,
+ tile_size: WrSize,
+ tile_spacing: WrSize) {
assert!(unsafe { is_in_main_thread() });
let stops =
WrGradientStop::to_gradient_stops(unsafe { slice::from_raw_parts(stops, stops_count) });
let gradient = state.frame_builder.dl_builder.create_radial_gradient(center.to_point(),
radius.to_size(),
stops,
extend_mode.to_gradient_extend_mode());
let rect = rect.to_rect();
- let tile_size = rect.size.clone();
+ let tile_size = tile_size.to_size();
+ let tile_spacing = tile_spacing.to_size();
state.frame_builder.dl_builder.push_radial_gradient(rect,
clip.to_clip_region(),
gradient,
tile_size,
- LayoutSize::new(0.0, 0.0));
+ tile_spacing);
}
#[no_mangle]
pub extern "C" fn wr_dp_push_box_shadow(state: &mut WrState,
rect: WrRect,
clip: WrClipRegion,
box_bounds: WrRect,
offset: WrPoint,
--- a/gfx/webrender_bindings/webrender_ffi.h
+++ b/gfx/webrender_bindings/webrender_ffi.h
@@ -706,24 +706,26 @@ wr_dp_push_border_radial_gradient(WrStat
WrGradientExtendMode extendMode,
WrSideOffsets2Df32 outset)
WR_FUNC;
WR_INLINE void
wr_dp_push_linear_gradient(WrState* wrState, WrRect bounds, WrClipRegion clip,
WrPoint startPoint, WrPoint endPoint,
const WrGradientStop* stops, size_t stopsCount,
- WrGradientExtendMode extendMode)
+ WrGradientExtendMode extendMode,
+ WrSize tileSize, WrSize tileSpacing)
WR_FUNC;
WR_INLINE void
wr_dp_push_radial_gradient(WrState* wrState, WrRect bounds, WrClipRegion clip,
WrPoint center, WrSize radius,
const WrGradientStop* stops, size_t stopsCount,
- WrGradientExtendMode extendMode)
+ WrGradientExtendMode extendMode,
+ WrSize tileSize, WrSize tileSpacing)
WR_FUNC;
WR_INLINE void
wr_dp_push_box_shadow(WrState* wrState, WrRect rect, WrClipRegion clip,
WrRect box_bounds, WrPoint offset, WrColor color,
float blur_radius, float spread_radius, float border_radius,
WrBoxShadowClipMode clip_mode)
WR_FUNC;
--- a/layout/base/Units.h
+++ b/layout/base/Units.h
@@ -292,16 +292,22 @@ struct CSSPixel {
struct LayoutDevicePixel {
static LayoutDeviceRect FromAppUnits(const nsRect& aRect, nscoord aAppUnitsPerDevPixel) {
return LayoutDeviceRect(NSAppUnitsToFloatPixels(aRect.x, float(aAppUnitsPerDevPixel)),
NSAppUnitsToFloatPixels(aRect.y, float(aAppUnitsPerDevPixel)),
NSAppUnitsToFloatPixels(aRect.width, float(aAppUnitsPerDevPixel)),
NSAppUnitsToFloatPixels(aRect.height, float(aAppUnitsPerDevPixel)));
}
+ static LayoutDeviceSize FromAppUnits(const nsSize& aSize, nscoord aAppUnitsPerDevPixel) {
+ return LayoutDeviceSize(
+ NSAppUnitsToFloatPixels(aSize.width, aAppUnitsPerDevPixel),
+ NSAppUnitsToFloatPixels(aSize.height, aAppUnitsPerDevPixel));
+ }
+
static LayoutDevicePoint FromAppUnits(const nsPoint& aPoint, nscoord aAppUnitsPerDevPixel) {
return LayoutDevicePoint(NSAppUnitsToFloatPixels(aPoint.x, aAppUnitsPerDevPixel),
NSAppUnitsToFloatPixels(aPoint.y, aAppUnitsPerDevPixel));
}
static LayoutDeviceMargin FromAppUnits(const nsMargin& aMargin, nscoord aAppUnitsPerDevPixel) {
return LayoutDeviceMargin(NSAppUnitsToFloatPixels(aMargin.top, aAppUnitsPerDevPixel),
NSAppUnitsToFloatPixels(aMargin.right, aAppUnitsPerDevPixel),
--- a/layout/painting/nsCSSRenderingGradients.cpp
+++ b/layout/painting/nsCSSRenderingGradients.cpp
@@ -1043,59 +1043,53 @@ nsCSSGradientRenderer::BuildWebRenderDis
{
WrGradientExtendMode extendMode;
nsTArray<WrGradientStop> stops;
LayoutDevicePoint lineStart;
LayoutDevicePoint lineEnd;
LayoutDeviceSize gradientRadius;
BuildWebRenderParameters(aOpacity, extendMode, stops, lineStart, lineEnd, gradientRadius);
- // Do a naive tiling of the gradient by making multiple display items
- // TODO: this should be done on the WebRender side eventually
+ nscoord appUnitsPerDevPixel = mPresContext->AppUnitsPerDevPixel();
- nscoord appUnitsPerDevPixel = mPresContext->AppUnitsPerDevPixel();
+ // Translate the parameters into device coordinates
+ LayoutDeviceRect clipBounds = LayoutDevicePixel::FromAppUnits(mFillArea, appUnitsPerDevPixel);
LayoutDeviceRect firstTileBounds = LayoutDevicePixel::FromAppUnits(mDest, appUnitsPerDevPixel);
- LayoutDeviceRect clipBounds = LayoutDevicePixel::FromAppUnits(mFillArea, appUnitsPerDevPixel);
-
- // Make the units relative to the parent stacking context
- firstTileBounds = LayoutDeviceRect::FromUnknownRect(aLayer->RelativeToParent(firstTileBounds.ToUnknownRect()));
- clipBounds = LayoutDeviceRect::FromUnknownRect(aLayer->RelativeToParent(clipBounds.ToUnknownRect()));
+ LayoutDeviceSize tileRepeat = LayoutDevicePixel::FromAppUnits(mRepeatSize, appUnitsPerDevPixel);
- float xStart = 0;
- float yStart = 0;
- float xEnd = (mFillArea.XMost() - mDest.X()) / appUnitsPerDevPixel;
- float yEnd = (mFillArea.YMost() - mDest.Y()) / appUnitsPerDevPixel;
+ // Calculate the bounds of the gradient display item, which starts at the first
+ // tile and extends to the end of clip bounds
+ LayoutDevicePoint tileToClip = clipBounds.BottomRight() - firstTileBounds.TopLeft();
+ LayoutDeviceRect gradientBounds = LayoutDeviceRect(firstTileBounds.TopLeft(),
+ LayoutDeviceSize(tileToClip.x, tileToClip.y));
- float stepX = mRepeatSize.width / appUnitsPerDevPixel;
- float stepY = mRepeatSize.height / appUnitsPerDevPixel;
+ // Calculate the tile spacing, which is the repeat size minus the tile size
+ LayoutDeviceSize tileSpacing = tileRepeat - firstTileBounds.Size();
- for (float y = yStart; y < yEnd; y += stepY) {
- for (float x = xStart; x < xEnd; x += stepX) {
- LayoutDevicePoint tileOffset = firstTileBounds.TopLeft() + LayoutDevicePoint(x, y);
- LayoutDeviceRect tileRect = LayoutDeviceRect(tileOffset, firstTileBounds.Size());
+ // Make the rects relative to the parent stacking context
+ clipBounds = LayoutDeviceRect::FromUnknownRect(aLayer->RelativeToParent(clipBounds.ToUnknownRect()));
+ firstTileBounds = LayoutDeviceRect::FromUnknownRect(aLayer->RelativeToParent(firstTileBounds.ToUnknownRect()));
+ gradientBounds = LayoutDeviceRect::FromUnknownRect(aLayer->RelativeToParent(gradientBounds.ToUnknownRect()));
- if (mGradient->mShape == NS_STYLE_GRADIENT_SHAPE_LINEAR) {
- LayoutDevicePoint relativeGradientStart = lineStart + tileOffset;
- LayoutDevicePoint relativeGradientEnd = lineEnd + tileOffset;
-
- aBuilder.PushLinearGradient(
- mozilla::wr::ToWrRect(tileRect),
- aBuilder.BuildClipRegion(mozilla::wr::ToWrRect(clipBounds)),
- mozilla::wr::ToWrPoint(relativeGradientStart),
- mozilla::wr::ToWrPoint(relativeGradientEnd),
- stops,
- extendMode);
- } else {
- LayoutDevicePoint relativeGradientCenter = lineStart + tileOffset;
-
- aBuilder.PushRadialGradient(
- mozilla::wr::ToWrRect(tileRect),
- aBuilder.BuildClipRegion(mozilla::wr::ToWrRect(clipBounds)),
- mozilla::wr::ToWrPoint(relativeGradientCenter),
- mozilla::wr::ToWrSize(gradientRadius),
- stops,
- extendMode);
- }
- }
+ if (mGradient->mShape == NS_STYLE_GRADIENT_SHAPE_LINEAR) {
+ aBuilder.PushLinearGradient(
+ mozilla::wr::ToWrRect(gradientBounds),
+ aBuilder.BuildClipRegion(mozilla::wr::ToWrRect(clipBounds)),
+ mozilla::wr::ToWrPoint(lineStart),
+ mozilla::wr::ToWrPoint(lineEnd),
+ stops,
+ extendMode,
+ mozilla::wr::ToWrSize(firstTileBounds.Size()),
+ mozilla::wr::ToWrSize(tileSpacing));
+ } else {
+ aBuilder.PushRadialGradient(
+ mozilla::wr::ToWrRect(gradientBounds),
+ aBuilder.BuildClipRegion(mozilla::wr::ToWrRect(clipBounds)),
+ mozilla::wr::ToWrPoint(lineStart),
+ mozilla::wr::ToWrSize(gradientRadius),
+ stops,
+ extendMode,
+ mozilla::wr::ToWrSize(firstTileBounds.Size()),
+ mozilla::wr::ToWrSize(tileSpacing));
}
}
} // namespace mozilla