diff --git a/gfx/wr/webrender/res/brush.glsl b/gfx/wr/webrender/res/brush.glsl index a6956ff2feba..5b39dc75c159 100644 --- a/gfx/wr/webrender/res/brush.glsl +++ b/gfx/wr/webrender/res/brush.glsl @@ -112,7 +112,9 @@ void multi_brush_vs( #define BRUSH_FLAG_SEGMENT_RELATIVE 2 #define BRUSH_FLAG_SEGMENT_REPEAT_X 4 #define BRUSH_FLAG_SEGMENT_REPEAT_Y 8 -#define BRUSH_FLAG_TEXEL_RECT 16 +#define BRUSH_FLAG_SEGMENT_REPEAT_X_ROUND 16 +#define BRUSH_FLAG_SEGMENT_REPEAT_Y_ROUND 32 +#define BRUSH_FLAG_TEXEL_RECT 64 #define INVALID_SEGMENT_INDEX 0xffff diff --git a/gfx/wr/webrender/res/brush_image.glsl b/gfx/wr/webrender/res/brush_image.glsl index 6a9461dfae64..819930d2d84d 100644 --- a/gfx/wr/webrender/res/brush_image.glsl +++ b/gfx/wr/webrender/res/brush_image.glsl @@ -103,20 +103,35 @@ void image_brush_vs( uv0 = res.uv_rect.p0 + segment_data.xy * uv_size; uv1 = res.uv_rect.p0 + segment_data.zw * uv_size; + #ifdef WR_FEATURE_REPETITION if ((brush_flags & BRUSH_FLAG_SEGMENT_REPEAT_X) != 0) { stretch_size.x = local_rect.size.y / dy * dx; } if ((brush_flags & BRUSH_FLAG_SEGMENT_REPEAT_Y) != 0) { stretch_size.y = local_rect.size.x / dx * dy; } + #endif } else { + #ifdef WR_FEATURE_REPETITION if ((brush_flags & BRUSH_FLAG_SEGMENT_REPEAT_X) != 0) { stretch_size.x = dx; } if ((brush_flags & BRUSH_FLAG_SEGMENT_REPEAT_Y) != 0) { stretch_size.y = dy; } + #endif } + + #ifdef WR_FEATURE_REPETITION + if ((brush_flags & BRUSH_FLAG_SEGMENT_REPEAT_X_ROUND) != 0) { + float nx = max(1.0, round(segment_rect.size.x / stretch_size.x)); + stretch_size.x = segment_rect.size.x / nx; + } + if ((brush_flags & BRUSH_FLAG_SEGMENT_REPEAT_Y_ROUND) != 0) { + float ny = max(1.0, round(segment_rect.size.y / stretch_size.y)); + stretch_size.y = segment_rect.size.y / ny; + } + #endif } float perspective_interpolate = (brush_flags & BRUSH_FLAG_PERSPECTIVE_INTERPOLATION) != 0 ? 1.0 : 0.0; diff --git a/gfx/wr/webrender/src/border.rs b/gfx/wr/webrender/src/border.rs index d3c4bab55020..d9c644ce3a5c 100644 --- a/gfx/wr/webrender/src/border.rs +++ b/gfx/wr/webrender/src/border.rs @@ -1351,38 +1351,43 @@ impl NinePatchDescriptor { repeat_horizontal: RepeatMode, repeat_vertical: RepeatMode ) { - if uv_rect.uv1.x > uv_rect.uv0.x && - uv_rect.uv1.y > uv_rect.uv0.y { - - // Use segment relative interpolation for all - // instances in this primitive. - let mut brush_flags = - BrushFlags::SEGMENT_RELATIVE | - BrushFlags::SEGMENT_TEXEL_RECT; - - // Enable repeat modes on the segment. - if repeat_horizontal == RepeatMode::Repeat { - brush_flags |= BrushFlags::SEGMENT_REPEAT_X; - } - if repeat_vertical == RepeatMode::Repeat { - brush_flags |= BrushFlags::SEGMENT_REPEAT_Y; - } - - let segment = BrushSegment::new( - rect, - true, - EdgeAaSegmentMask::empty(), - [ - uv_rect.uv0.x, - uv_rect.uv0.y, - uv_rect.uv1.x, - uv_rect.uv1.y, - ], - brush_flags, - ); - - segments.push(segment); + if uv_rect.uv1.x < uv_rect.uv0.x || uv_rect.uv1.y < uv_rect.uv0.y { + return; } + + // Use segment relative interpolation for all + // instances in this primitive. + let mut brush_flags = + BrushFlags::SEGMENT_RELATIVE | + BrushFlags::SEGMENT_TEXEL_RECT; + + // Enable repeat modes on the segment. + if repeat_horizontal == RepeatMode::Repeat { + brush_flags |= BrushFlags::SEGMENT_REPEAT_X; + } else if repeat_horizontal == RepeatMode::Round { + brush_flags |= BrushFlags::SEGMENT_REPEAT_X | BrushFlags::SEGMENT_REPEAT_X_ROUND; + } + + if repeat_vertical == RepeatMode::Repeat { + brush_flags |= BrushFlags::SEGMENT_REPEAT_Y; + } else if repeat_vertical == RepeatMode::Round { + brush_flags |= BrushFlags::SEGMENT_REPEAT_Y | BrushFlags::SEGMENT_REPEAT_Y_ROUND; + } + + let segment = BrushSegment::new( + rect, + true, + EdgeAaSegmentMask::empty(), + [ + uv_rect.uv0.x, + uv_rect.uv0.y, + uv_rect.uv1.x, + uv_rect.uv1.y, + ], + brush_flags, + ); + + segments.push(segment); } // Build the list of image segments diff --git a/gfx/wr/webrender/src/gpu_types.rs b/gfx/wr/webrender/src/gpu_types.rs index 91dc46706de6..73f39025f6d5 100644 --- a/gfx/wr/webrender/src/gpu_types.rs +++ b/gfx/wr/webrender/src/gpu_types.rs @@ -403,16 +403,20 @@ bitflags! { #[derive(MallocSizeOf)] pub struct BrushFlags: u8 { /// Apply perspective interpolation to UVs - const PERSPECTIVE_INTERPOLATION = 0x1; + const PERSPECTIVE_INTERPOLATION = 1; /// Do interpolation relative to segment rect, /// rather than primitive rect. - const SEGMENT_RELATIVE = 0x2; + const SEGMENT_RELATIVE = 2; /// Repeat UVs horizontally. - const SEGMENT_REPEAT_X = 0x4; + const SEGMENT_REPEAT_X = 4; /// Repeat UVs vertically. - const SEGMENT_REPEAT_Y = 0x8; + const SEGMENT_REPEAT_Y = 8; + /// Horizontally follow border-image-repeat: round + const SEGMENT_REPEAT_X_ROUND = 16; + /// Vorizontally follow border-image-repeat: round + const SEGMENT_REPEAT_Y_ROUND = 32; /// The extra segment data is a texel rect. - const SEGMENT_TEXEL_RECT = 0x10; + const SEGMENT_TEXEL_RECT = 64; } } diff --git a/layout/painting/nsCSSRendering.cpp b/layout/painting/nsCSSRendering.cpp index 9d6c70e6ca26..bb74e2fe0811 100644 --- a/layout/painting/nsCSSRendering.cpp +++ b/layout/painting/nsCSSRendering.cpp @@ -715,9 +715,7 @@ ImgDrawResult nsCSSRendering::CreateWebRenderCommandsForBorderWithStyleBorder( return ImgDrawResult::NOT_SUPPORTED; } - if (aStyleBorder.mBorderImageRepeatH == StyleBorderImageRepeat::Round || - aStyleBorder.mBorderImageRepeatH == StyleBorderImageRepeat::Space || - aStyleBorder.mBorderImageRepeatV == StyleBorderImageRepeat::Round || + if (aStyleBorder.mBorderImageRepeatH == StyleBorderImageRepeat::Space || aStyleBorder.mBorderImageRepeatV == StyleBorderImageRepeat::Space) { return ImgDrawResult::NOT_SUPPORTED; }