Diff
Modified: trunk/LayoutTests/ChangeLog (268922 => 268923)
--- trunk/LayoutTests/ChangeLog 2020-10-23 12:44:44 UTC (rev 268922)
+++ trunk/LayoutTests/ChangeLog 2020-10-23 12:53:42 UTC (rev 268923)
@@ -1,3 +1,14 @@
+2020-10-23 Miguel Gomez <[email protected]>
+
+ [GTK][WPE] Implement antialiased rounded rectangle clipping in TextureMapper
+ https://bugs.webkit.org/show_bug.cgi?id=174457
+
+ Reviewed by Carlos Garcia Campos.
+
+ Update expectations for passing test.
+
+ * platform/gtk/TestExpectations:
+
2020-10-22 Fujii Hironori <[email protected]>
[GTK] Unreviewed test gardening
Modified: trunk/LayoutTests/platform/gtk/TestExpectations (268922 => 268923)
--- trunk/LayoutTests/platform/gtk/TestExpectations 2020-10-23 12:44:44 UTC (rev 268922)
+++ trunk/LayoutTests/platform/gtk/TestExpectations 2020-10-23 12:53:42 UTC (rev 268923)
@@ -3328,7 +3328,6 @@
webkit.org/b/194384 compositing/clipping/border-radius-async-overflow-clipping-layer.html [ Failure ]
webkit.org/b/206000 compositing/clipping/border-radius-async-overflow-non-stacking.html [ ImageOnlyFailure ]
-webkit.org/b/211121 compositing/clipping/border-radius-on-webgl.html [ ImageOnlyFailure ]
webkit.org/b/194606 accessibility/set-value-not-work-for-disabled-sliders.html [ Failure ]
Modified: trunk/Source/WebCore/ChangeLog (268922 => 268923)
--- trunk/Source/WebCore/ChangeLog 2020-10-23 12:44:44 UTC (rev 268922)
+++ trunk/Source/WebCore/ChangeLog 2020-10-23 12:53:42 UTC (rev 268923)
@@ -1,3 +1,45 @@
+2020-10-23 Miguel Gomez <[email protected]>
+
+ [GTK][WPE] Implement antialiased rounded rectangle clipping in TextureMapper
+ https://bugs.webkit.org/show_bug.cgi?id=174457
+
+ Reviewed by Carlos Garcia Campos.
+
+ Implement rounded rectangle clipping in TextureMapperGL, supporting up to 10 simultaneous
+ rounded rectangle clips. TextureMapper::beginClip() now receives a rounded rectangle, and
+ it applies the appropriate clipping method as required.
+
+ The rounded rectangle clip implementation uses the fragment shader to calculate whether
+ each pixel is inside the defined rounded rectangles, and paints or skips it as needed.
+
+ * platform/graphics/texmap/ClipStack.cpp:
+ (WebCore::ClipStack::addRoundedRect):
+ * platform/graphics/texmap/ClipStack.h:
+ (WebCore::ClipStack::State::State):
+ (WebCore::ClipStack::roundedRectComponents const):
+ (WebCore::ClipStack::roundedRectInverseTransformComponents const):
+ (WebCore::ClipStack::roundedRectCount const):
+ (WebCore::ClipStack::isRoundedRectClipEnabled const):
+ (WebCore::ClipStack::isRoundedRectClipAllowed const):
+ * platform/graphics/texmap/TextureMapper.h:
+ * platform/graphics/texmap/TextureMapperGL.cpp:
+ (WebCore::prepareRoundedRectClip):
+ (WebCore::TextureMapperGL::drawTexture):
+ (WebCore::TextureMapperGL::drawTexturePlanarYUV):
+ (WebCore::TextureMapperGL::drawTextureSemiPlanarYUV):
+ (WebCore::TextureMapperGL::drawTexturePackedYUV):
+ (WebCore::TextureMapperGL::drawSolidColor):
+ (WebCore::TextureMapperGL::beginRoundedRectClip):
+ (WebCore::TextureMapperGL::beginClip):
+ * platform/graphics/texmap/TextureMapperGL.h:
+ * platform/graphics/texmap/TextureMapperLayer.cpp:
+ (WebCore::TextureMapperLayer::paintSelf):
+ (WebCore::TextureMapperLayer::paintSelfAndChildren):
+ (WebCore::TextureMapperLayer::paintUsingOverlapRegions):
+ * platform/graphics/texmap/TextureMapperShaderProgram.cpp:
+ (WebCore::TextureMapperShaderProgram::create):
+ * platform/graphics/texmap/TextureMapperShaderProgram.h:
+
2020-10-23 Zalan Bujtas <[email protected]>
[LFC][IFC] Fix inline box relative alignment when line-height is set
Modified: trunk/Source/WebCore/platform/graphics/texmap/ClipStack.cpp (268922 => 268923)
--- trunk/Source/WebCore/platform/graphics/texmap/ClipStack.cpp 2020-10-23 12:44:44 UTC (rev 268922)
+++ trunk/Source/WebCore/platform/graphics/texmap/ClipStack.cpp 2020-10-23 12:53:42 UTC (rev 268923)
@@ -62,6 +62,37 @@
clipStateDirty = true;
}
+void ClipStack::addRoundedRect(const FloatRoundedRect& roundedRect, const TransformationMatrix& matrix)
+{
+ if (clipState.roundedRectCount >= s_roundedRectMaxClips)
+ return;
+
+ // Ensure that the vectors holding the components have the required size.
+ m_roundedRectComponents.grow(s_roundedRectComponentsArraySize);
+ m_roundedRectInverseTransformComponents.grow(s_roundedRectInverseTransformComponentsArraySize);
+
+ // Copy the RoundedRect components to the appropriate position in the array.
+ int basePosition = clipState.roundedRectCount * s_roundedRectComponentsPerRect;
+ m_roundedRectComponents[basePosition] = roundedRect.rect().x();
+ m_roundedRectComponents[basePosition + 1] = roundedRect.rect().y();
+ m_roundedRectComponents[basePosition + 2] = roundedRect.rect().width();
+ m_roundedRectComponents[basePosition + 3] = roundedRect.rect().height();
+ m_roundedRectComponents[basePosition + 4] = roundedRect.radii().topLeft().width();
+ m_roundedRectComponents[basePosition + 5] = roundedRect.radii().topLeft().height();
+ m_roundedRectComponents[basePosition + 6] = roundedRect.radii().topRight().width();
+ m_roundedRectComponents[basePosition + 7] = roundedRect.radii().topRight().height();
+ m_roundedRectComponents[basePosition + 8] = roundedRect.radii().bottomLeft().width();
+ m_roundedRectComponents[basePosition + 9] = roundedRect.radii().bottomLeft().height();
+ m_roundedRectComponents[basePosition + 10] = roundedRect.radii().bottomRight().width();
+ m_roundedRectComponents[basePosition + 11] = roundedRect.radii().bottomRight().height();
+
+ // Copy the TransformationMatrix components to the appropriate position in the array.
+ basePosition = clipState.roundedRectCount * s_roundedRectInverseTransformComponentsPerRect;
+ memcpy(m_roundedRectInverseTransformComponents.data() + basePosition, matrix.toColumnMajorFloatArray().data(), s_roundedRectInverseTransformComponentsPerRect * sizeof(float));
+
+ clipState.roundedRectCount++;
+}
+
void ClipStack::apply()
{
if (clipState.scissorBox.isEmpty())
Modified: trunk/Source/WebCore/platform/graphics/texmap/ClipStack.h (268922 => 268923)
--- trunk/Source/WebCore/platform/graphics/texmap/ClipStack.h 2020-10-23 12:44:44 UTC (rev 268922)
+++ trunk/Source/WebCore/platform/graphics/texmap/ClipStack.h 2020-10-23 12:53:42 UTC (rev 268923)
@@ -21,22 +21,41 @@
#ifndef ClipStack_h
#define ClipStack_h
+#include "FloatRoundedRect.h"
#include "IntRect.h"
#include "IntSize.h"
+#include "TransformationMatrix.h"
#include <wtf/Vector.h>
namespace WebCore {
+// Because GLSL uniform arrays need to have a defined size, we need to put a limit to the number of simultaneous
+// rounded rectangle clips that we're going to allow. Currently this is defined to 10.
+// This value must be kept in sync with the sizes defined in TextureMapperShaderProgram.cpp.
+static const unsigned s_roundedRectMaxClips = 10;
+
+// When converting a rounded rectangle to an array of floats, we need 12 elements. So the size of the array
+// required to contain the 10 rectangles is 12 * 10 = 120.
+// This value must be kept in sync with the sizes defined in TextureMapperShaderProgram.cpp.
+static const unsigned s_roundedRectComponentsPerRect = 12;
+static const unsigned s_roundedRectComponentsArraySize = s_roundedRectMaxClips * s_roundedRectComponentsPerRect;
+
+// When converting a transformation matrix to an array of floats, we need 16 elements. So the size of the array
+// required to contain the 10 matrices is 16 * 10 = 160.
+// This value must be kept in sync with the sizes defined in TextureMapperShaderProgram.cpp.
+static const unsigned s_roundedRectInverseTransformComponentsPerRect = 16;
+static const unsigned s_roundedRectInverseTransformComponentsArraySize = s_roundedRectMaxClips * s_roundedRectInverseTransformComponentsPerRect;
+
class ClipStack {
public:
struct State {
- State(const IntRect& scissors = IntRect(), int stencil = 1)
+ explicit State(const IntRect& scissors = IntRect())
: scissorBox(scissors)
- , stencilIndex(stencil)
{ }
IntRect scissorBox;
- int stencilIndex;
+ int stencilIndex { 1 };
+ unsigned roundedRectCount { 0 };
};
// Y-axis should be inverted only when painting into the window.
@@ -54,6 +73,13 @@
void setStencilIndex(int);
int getStencilIndex() const { return clipState.stencilIndex; }
+ void addRoundedRect(const FloatRoundedRect&, const TransformationMatrix&);
+ const float* roundedRectComponents() const { return m_roundedRectComponents.data(); }
+ const float* roundedRectInverseTransformComponents() const { return m_roundedRectInverseTransformComponents.data(); }
+ unsigned roundedRectCount() const { return clipState.roundedRectCount; }
+ bool isRoundedRectClipEnabled() const { return !!clipState.roundedRectCount; }
+ bool isRoundedRectClipAllowed() const { return clipState.roundedRectCount < s_roundedRectMaxClips; }
+
void apply();
void applyIfNeeded();
@@ -65,6 +91,8 @@
IntSize size;
bool clipStateDirty { false };
YAxisMode yAxisMode { YAxisMode::Default };
+ Vector<float, s_roundedRectComponentsArraySize> m_roundedRectComponents;
+ Vector<float, s_roundedRectInverseTransformComponentsArraySize> m_roundedRectInverseTransformComponents;
};
} // namespace WebCore
Modified: trunk/Source/WebCore/platform/graphics/texmap/TextureMapper.h (268922 => 268923)
--- trunk/Source/WebCore/platform/graphics/texmap/TextureMapper.h 2020-10-23 12:44:44 UTC (rev 268922)
+++ trunk/Source/WebCore/platform/graphics/texmap/TextureMapper.h 2020-10-23 12:53:42 UTC (rev 268923)
@@ -37,6 +37,7 @@
class GraphicsLayer;
class TextureMapper;
class FilterOperations;
+class FloatRoundedRect;
class TextureMapper {
WTF_MAKE_FAST_ALLOCATED;
@@ -75,7 +76,7 @@
// makes a surface the target for the following drawTexture calls.
virtual void bindSurface(BitmapTexture* surface) = 0;
- virtual void beginClip(const TransformationMatrix&, const FloatRect&) = 0;
+ virtual void beginClip(const TransformationMatrix&, const FloatRoundedRect&) = 0;
virtual void endClip() = 0;
virtual IntRect clipBounds() = 0;
virtual void beginPreserves3D() { };
Modified: trunk/Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp (268922 => 268923)
--- trunk/Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp 2020-10-23 12:44:44 UTC (rev 268922)
+++ trunk/Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp 2020-10-23 12:53:42 UTC (rev 268923)
@@ -29,6 +29,7 @@
#include "ExtensionsGL.h"
#include "FilterOperations.h"
#include "FloatQuad.h"
+#include "FloatRoundedRect.h"
#include "GLContext.h"
#include "GraphicsContext.h"
#include "Image.h"
@@ -442,6 +443,15 @@
return matrix;
}
+static void prepareRoundedRectClip(TextureMapperShaderProgram& program, const float* rects, const float* transforms, int nRects)
+{
+ glUseProgram(program.programID());
+
+ glUniform1i(program.roundedRectNumberLocation(), nRects);
+ glUniform4fv(program.roundedRectLocation(), 3 * nRects, rects);
+ glUniformMatrix4fv(program.roundedRectInverseTransformMatrixLocation(), nRects, false, transforms);
+}
+
void TextureMapperGL::drawTexture(const BitmapTexture& texture, const FloatRect& targetRect, const TransformationMatrix& matrix, float opacity, unsigned exposedEdges)
{
if (!texture.isValid())
@@ -489,11 +499,19 @@
if (useAntialiasing || opacity < 1)
flags |= ShouldBlend;
+ if (clipStack().isRoundedRectClipEnabled()) {
+ options |= TextureMapperShaderProgram::RoundedRectClip;
+ flags |= ShouldBlend;
+ }
+
Ref<TextureMapperShaderProgram> program = data().getShaderProgram(options);
if (filter)
prepareFilterProgram(program.get(), *filter.get(), data().filterInfo->pass, textureSize, filterContentTextureID);
+ if (clipStack().isRoundedRectClipEnabled())
+ prepareRoundedRectClip(program.get(), clipStack().roundedRectComponents(), clipStack().roundedRectInverseTransformComponents(), clipStack().roundedRectCount());
+
drawTexturedQuadWithProgram(program.get(), texture, flags, textureSize, targetRect, modelViewMatrix, opacity);
}
@@ -552,11 +570,19 @@
if (useAntialiasing || opacity < 1)
flags |= ShouldBlend;
+ if (clipStack().isRoundedRectClipEnabled()) {
+ options |= TextureMapperShaderProgram::RoundedRectClip;
+ flags |= ShouldBlend;
+ }
+
Ref<TextureMapperShaderProgram> program = data().getShaderProgram(options);
if (filter)
prepareFilterProgram(program.get(), *filter.get(), data().filterInfo->pass, textureSize, filterContentTextureID);
+ if (clipStack().isRoundedRectClipEnabled())
+ prepareRoundedRectClip(program.get(), clipStack().roundedRectComponents(), clipStack().roundedRectInverseTransformComponents(), clipStack().roundedRectCount());
+
Vector<std::pair<GLuint, GLuint> > texturesAndSamplers = {
{ textures[0], program->samplerYLocation() },
{ textures[1], program->samplerULocation() },
@@ -602,11 +628,19 @@
if (useAntialiasing || opacity < 1)
flags |= ShouldBlend;
+ if (clipStack().isRoundedRectClipEnabled()) {
+ options |= TextureMapperShaderProgram::RoundedRectClip;
+ flags |= ShouldBlend;
+ }
+
Ref<TextureMapperShaderProgram> program = data().getShaderProgram(options);
if (filter)
prepareFilterProgram(program.get(), *filter.get(), data().filterInfo->pass, textureSize, filterContentTextureID);
+ if (clipStack().isRoundedRectClipEnabled())
+ prepareRoundedRectClip(program.get(), clipStack().roundedRectComponents(), clipStack().roundedRectInverseTransformComponents(), clipStack().roundedRectCount());
+
Vector<std::pair<GLuint, GLuint> > texturesAndSamplers = {
{ textures[0], program->samplerYLocation() },
{ textures[1], program->samplerULocation() }
@@ -650,11 +684,19 @@
if (useAntialiasing || opacity < 1)
flags |= ShouldBlend;
+ if (clipStack().isRoundedRectClipEnabled()) {
+ options |= TextureMapperShaderProgram::RoundedRectClip;
+ flags |= ShouldBlend;
+ }
+
Ref<TextureMapperShaderProgram> program = data().getShaderProgram(options);
if (filter)
prepareFilterProgram(program.get(), *filter.get(), data().filterInfo->pass, textureSize, filterContentTextureID);
+ if (clipStack().isRoundedRectClipEnabled())
+ prepareRoundedRectClip(program.get(), clipStack().roundedRectComponents(), clipStack().roundedRectInverseTransformComponents(), clipStack().roundedRectCount());
+
Vector<std::pair<GLuint, GLuint> > texturesAndSamplers = {
{ texture, program->samplerLocation() }
};
@@ -673,9 +715,17 @@
flags |= ShouldAntialias | (isBlendingAllowed ? ShouldBlend : 0);
}
+ if (clipStack().isRoundedRectClipEnabled()) {
+ options |= TextureMapperShaderProgram::RoundedRectClip;
+ flags |= ShouldBlend;
+ }
+
Ref<TextureMapperShaderProgram> program = data().getShaderProgram(options);
glUseProgram(program->programID());
+ if (clipStack().isRoundedRectClipEnabled())
+ prepareRoundedRectClip(program.get(), clipStack().roundedRectComponents(), clipStack().roundedRectInverseTransformComponents(), clipStack().roundedRectCount());
+
auto [r, g, b, a] = premultiplied(color.toSRGBALossy<float>());
glUniform4f(program->colorLocation(), r, g, b, a);
if (a < 1 && isBlendingAllowed)
@@ -884,12 +934,43 @@
return true;
}
-void TextureMapperGL::beginClip(const TransformationMatrix& modelViewMatrix, const FloatRect& targetRect)
+bool TextureMapperGL::beginRoundedRectClip(const TransformationMatrix& modelViewMatrix, const FloatRoundedRect& targetRect)
{
+ // This is implemented by telling the fragment shader to check whether each pixel is inside the rounded rectangle
+ // before painting it.
+ //
+ // Inside the shader, the math to check whether a point is inside the rounded rectangle requires the rectangle to
+ // be aligned to the X and Y axis, which is not guaranteed if the transformation matrix includes rotations. In order
+ // to avoid this, instead of applying the transformation to the rounded rectangle, we calculate the inverse
+ // of the transformation and apply it to the pixels before checking whether they are inside the rounded rectangle.
+ // This works fine as long as the transformation matrix is invertible.
+ //
+ // There is a limit to the number of rounded rectangle clippings that can be done, that happens because the GLSL
+ // arrays must have a predefined size. The limit is defined inside ClipStack, and that's why we need to call
+ // clipStack().isRoundedRectClipAllowed() before trying to add a new clip.
+
+ if (!targetRect.isRounded() || !targetRect.isRenderable() || targetRect.isEmpty() || !modelViewMatrix.isInvertible() || !clipStack().isRoundedRectClipAllowed())
+ return false;
+
+ FloatQuad quad = modelViewMatrix.projectQuad(targetRect.rect());
+ IntRect rect = quad.enclosingBoundingBox();
+
+ clipStack().addRoundedRect(targetRect, modelViewMatrix.inverse().value());
+ clipStack().intersect(rect);
+ clipStack().applyIfNeeded();
+
+ return true;
+}
+
+void TextureMapperGL::beginClip(const TransformationMatrix& modelViewMatrix, const FloatRoundedRect& targetRect)
+{
clipStack().push();
- if (beginScissorClip(modelViewMatrix, targetRect))
+ if (beginRoundedRectClip(modelViewMatrix, targetRect))
return;
+ if (beginScissorClip(modelViewMatrix, targetRect.rect()))
+ return;
+
data().initializeStencil();
Ref<TextureMapperShaderProgram> program = data().getShaderProgram(TextureMapperShaderProgram::SolidColor);
@@ -902,7 +983,7 @@
glVertexAttribPointer(program->vertexLocation(), 2, GL_FLOAT, false, 0, 0);
TransformationMatrix matrix(modelViewMatrix);
- matrix.multiply(TransformationMatrix::rectToRect(FloatRect(0, 0, 1, 1), targetRect));
+ matrix.multiply(TransformationMatrix::rectToRect(FloatRect(0, 0, 1, 1), targetRect.rect()));
static const TransformationMatrix fullProjectionMatrix = TransformationMatrix::rectToRect(FloatRect(0, 0, 1, 1), FloatRect(-1, -1, 2, 2));
Modified: trunk/Source/WebCore/platform/graphics/texmap/TextureMapperGL.h (268922 => 268923)
--- trunk/Source/WebCore/platform/graphics/texmap/TextureMapperGL.h 2020-10-23 12:44:44 UTC (rev 268922)
+++ trunk/Source/WebCore/platform/graphics/texmap/TextureMapperGL.h 2020-10-23 12:53:42 UTC (rev 268923)
@@ -75,7 +75,7 @@
void bindSurface(BitmapTexture* surface) override;
BitmapTexture* currentSurface();
- void beginClip(const TransformationMatrix&, const FloatRect&) override;
+ void beginClip(const TransformationMatrix&, const FloatRoundedRect&) override;
void beginPainting(PaintFlags = 0) override;
void endPainting() override;
void endClip() override;
@@ -100,6 +100,7 @@
void drawEdgeTriangles(TextureMapperShaderProgram&);
bool beginScissorClip(const TransformationMatrix&, const FloatRect&);
+ bool beginRoundedRectClip(const TransformationMatrix&, const FloatRoundedRect&);
void bindDefaultSurface();
ClipStack& clipStack();
inline TextureMapperGLData& data() { return *m_data; }
Modified: trunk/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.cpp (268922 => 268923)
--- trunk/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.cpp 2020-10-23 12:44:44 UTC (rev 268922)
+++ trunk/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.cpp 2020-10-23 12:53:42 UTC (rev 268923)
@@ -196,8 +196,7 @@
bool shouldClip = m_state.contentsClippingRect.isRounded() || !m_state.contentsClippingRect.rect().contains(m_state.contentsRect);
if (shouldClip) {
- // FIXME: TextureMapper::beginClip doesn't support FloatRoundedRect, so we need to convert m_state.contentsClippingRect to FloatRect.
- options.textureMapper.beginClip(transform, m_state.contentsClippingRect.rect());
+ options.textureMapper.beginClip(transform, m_state.contentsClippingRect);
}
m_contentsLayer->paintToTextureMapper(options.textureMapper, m_state.contentsRect, transform, options.opacity);
@@ -230,7 +229,7 @@
clipTransform.translate(options.offset.width(), options.offset.height());
clipTransform.multiply(options.transform);
clipTransform.multiply(m_layerTransforms.combined);
- options.textureMapper.beginClip(clipTransform, layerRect());
+ options.textureMapper.beginClip(clipTransform, FloatRoundedRect(layerRect()));
m_state.backdropLayer->paintRecursive(options);
options.textureMapper.endClip();
}
@@ -249,7 +248,7 @@
clipTransform.translate(options.offset.width(), options.offset.height());
clipTransform.multiply(options.transform);
clipTransform.multiply(m_layerTransforms.combined);
- options.textureMapper.beginClip(clipTransform, layerRect());
+ options.textureMapper.beginClip(clipTransform, FloatRoundedRect(layerRect()));
// If as a result of beginClip(), the clipping area is empty, it means that the intersection of the previous
// clipping area and the current one don't have any pixels in common. In this case we can skip painting the
@@ -405,7 +404,7 @@
if (!rect.intersects(options.textureMapper.clipBounds()))
continue;
- options.textureMapper.beginClip(TransformationMatrix(), rect);
+ options.textureMapper.beginClip(TransformationMatrix(), FloatRoundedRect(rect));
paintSelfAndChildrenWithReplica(options);
options.textureMapper.endClip();
}
Modified: trunk/Source/WebCore/platform/graphics/texmap/TextureMapperShaderProgram.cpp (268922 => 268923)
--- trunk/Source/WebCore/platform/graphics/texmap/TextureMapperShaderProgram.cpp 2020-10-23 12:44:44 UTC (rev 268922)
+++ trunk/Source/WebCore/platform/graphics/texmap/TextureMapperShaderProgram.cpp 2020-10-23 12:53:42 UTC (rev 268923)
@@ -68,6 +68,7 @@
varying vec2 v_texCoord;
varying vec2 v_transformedTexCoord;
varying float v_antialias;
+ varying vec4 v_nonProjectedPosition;
);
#if !USE(OPENGL_ES)
@@ -78,6 +79,7 @@
out vec2 v_texCoord;
out vec2 v_transformedTexCoord;
out float v_antialias;
+ out vec4 v_nonProjectedPosition;
);
#endif
@@ -133,7 +135,8 @@
v_texCoord = position;
vec4 clampedPosition = clamp(vec4(position, 0., 1.), 0., 1.);
v_transformedTexCoord = (u_textureSpaceMatrix * clampedPosition).xy;
- gl_Position = u_projectionMatrix * u_modelViewMatrix * vec4(position, 0., 1.);
+ v_nonProjectedPosition = u_modelViewMatrix * vec4(position, 0., 1.);
+ gl_Position = u_projectionMatrix * v_nonProjectedPosition;
}
);
@@ -168,6 +171,16 @@
GLSL_DIRECTIVE(define SamplerExternalOESType sampler2D) \
GLSL_DIRECTIVE(endif)
+// The max number of stacked rounded rectangle clips allowed is 10, which is also the
+// max number of transforms that we can get. We need 3 components for each rounded
+// rectangle so we need 30 components to receive the 10 rectangles.
+//
+// Keep this is sync with the values defined in ClipStack.h
+#define ROUNDED_RECT_CONSTANTS \
+ GLSL_DIRECTIVE(define ROUNDED_RECT_MAX_RECTS 10) \
+ GLSL_DIRECTIVE(define ROUNDED_RECT_ARRAY_SIZE 30) \
+ GLSL_DIRECTIVE(define ROUNDED_RECT_INVERSE_TRANSFORM_ARRAY_SIZE 10)
+
// Common header for all versions. We define the matrices variables here to keep the precision
// directives scope: the first one applies to the matrices variables and the next one to the
// rest of them. The precision is only used in GLES.
@@ -175,6 +188,7 @@
RECT_TEXTURE_DIRECTIVE
ANTIALIASING_TEX_COORD_DIRECTIVE
BLUR_CONSTANTS
+ ROUNDED_RECT_CONSTANTS
OES_EGL_IMAGE_EXTERNAL_DIRECTIVE
#if USE(OPENGL_ES)
TEXTURE_SPACE_MATRIX_PRECISION_DIRECTIVE
@@ -199,6 +213,7 @@
varying float v_antialias;
varying vec2 v_texCoord;
varying vec2 v_transformedTexCoord;
+ varying vec4 v_nonProjectedPosition;
);
#if !USE(OPENGL_ES)
@@ -208,6 +223,7 @@
in float v_antialias;
in vec2 v_texCoord;
in vec2 v_transformedTexCoord;
+ in vec4 v_nonProjectedPosition;
);
#endif
@@ -226,6 +242,9 @@
uniform vec2 u_shadowOffset;
uniform vec4 u_color;
uniform float u_gaussianKernel[GAUSSIAN_KERNEL_HALF_WIDTH];
+ uniform int u_roundedRectNumber;
+ uniform vec4 u_roundedRect[ROUNDED_RECT_ARRAY_SIZE];
+ uniform mat4 u_roundedRectInverseTransformMatrix[ROUNDED_RECT_INVERSE_TRANSFORM_ARRAY_SIZE];
void noop(inout vec4 dummyParameter) { }
void noop(inout vec4 dummyParameter, vec2 texCoord) { }
@@ -390,6 +409,70 @@
void applySolidColor(inout vec4 color) { color *= u_color; }
+ float ellipsisDist(vec2 p, vec2 radius)
+ {
+ if (radius == vec2(0, 0))
+ return 0.0;
+
+ vec2 p0 = p / radius;
+ vec2 p1 = 2.0 * p0 / radius;
+
+ return (dot(p0, p0) - 1.0) / length (p1);
+ }
+
+ float ellipsisCoverage(vec2 point, vec2 center, vec2 radius)
+ {
+ float d = ellipsisDist(point - center, radius);
+ return clamp(0.5 - d, 0.0, 1.0);
+ }
+
+ float roundedRectCoverage(vec2 p, int index)
+ {
+ vec4 bounds = vec4(u_roundedRect[index].xy, u_roundedRect[index].xy + u_roundedRect[index].zw);
+
+ if (p.x < bounds.x || p.y < bounds.y || p.x >= bounds.z || p.y >= bounds.w)
+ return 0.0;
+
+ vec2 topLeftRadii = u_roundedRect[index + 1].xy;
+ vec2 topRightRadii = u_roundedRect[index + 1].zw;
+ vec2 bottomLeftRadii = u_roundedRect[index + 2].xy;
+ vec2 bottomRightRadii = u_roundedRect[index + 2].zw;
+
+ vec2 topLeftCenter = bounds.xy + topLeftRadii;
+ vec2 topRightCenter = bounds.zy + (topRightRadii * vec2(-1, 1));
+ vec2 bottomLeftCenter = bounds.xw + (bottomLeftRadii * vec2(1, -1));
+ vec2 bottomRightCenter = bounds.zw + (bottomRightRadii * vec2(-1, -1));
+
+ if (p.x < topLeftCenter.x && p.y < topLeftCenter.y)
+ return ellipsisCoverage(p, topLeftCenter, topLeftRadii);
+
+ if (p.x > topRightCenter.x && p.y < topRightCenter.y)
+ return ellipsisCoverage(p, topRightCenter, topRightRadii);
+
+ if (p.x < bottomLeftCenter.x && p.y > bottomLeftCenter.y)
+ return ellipsisCoverage(p, bottomLeftCenter, bottomLeftRadii);
+
+ if (p.x > bottomRightCenter.x && p.y > bottomRightCenter.y)
+ return ellipsisCoverage(p, bottomRightCenter, bottomRightRadii);
+
+ return 1.0;
+ }
+
+ void applyRoundedRectClip(inout vec4 color)
+ {
+ // This works by checking whether the fragment position, once the transform is applied,
+ // is inside the defined rounded rectangle or not.
+ //
+ // We can't use gl_fragCoord for the fragment position because thats the projected point
+ // and the projection screws the Z component. We need the real 3D position that comes from
+ // the nonProjectedPosition variable.
+ int nRects = min(ROUNDED_RECT_MAX_RECTS, u_roundedRectNumber);
+ for (int rectIndex = 0; rectIndex < nRects; rectIndex++) {
+ vec4 fragCoord = u_roundedRectInverseTransformMatrix[rectIndex] * v_nonProjectedPosition;
+ color *= roundedRectCoverage(fragCoord.xy, rectIndex * 3);
+ }
+ }
+
void main(void)
{
vec4 color = vec4(1., 1., 1., 1.);
@@ -415,6 +498,7 @@
applyAlphaBlurIfNeeded(color, texCoord);
applyContentTextureIfNeeded(color, texCoord);
applyTextureExternalOESIfNeeded(color, texCoord);
+ applyRoundedRectClipIfNeeded(color);
gl_FragColor = color;
}
);
@@ -448,6 +532,7 @@
SET_APPLIER_FROM_OPTIONS(ContentTexture);
SET_APPLIER_FROM_OPTIONS(ManualRepeat);
SET_APPLIER_FROM_OPTIONS(TextureExternalOES);
+ SET_APPLIER_FROM_OPTIONS(RoundedRectClip);
StringBuilder vertexShaderBuilder;
Modified: trunk/Source/WebCore/platform/graphics/texmap/TextureMapperShaderProgram.h (268922 => 268923)
--- trunk/Source/WebCore/platform/graphics/texmap/TextureMapperShaderProgram.h 2020-10-23 12:44:44 UTC (rev 268922)
+++ trunk/Source/WebCore/platform/graphics/texmap/TextureMapperShaderProgram.h 2020-10-23 12:53:42 UTC (rev 268923)
@@ -48,6 +48,9 @@
macro(gaussianKernel) \
macro(blurRadius) \
macro(shadowOffset) \
+ macro(roundedRectNumber) \
+ macro(roundedRect) \
+ macro(roundedRectInverseTransformMatrix) \
#define TEXMAP_SAMPLER_VARIABLES(macro) \
macro(sampler) \
@@ -99,6 +102,7 @@
TextureNV21 = 1L << 20,
TexturePackedYUV = 1L << 21,
TextureExternalOES = 1L << 22,
+ RoundedRectClip = 1L << 23,
};
enum class VariableID {
Modified: trunk/Source/WebKit/ChangeLog (268922 => 268923)
--- trunk/Source/WebKit/ChangeLog 2020-10-23 12:44:44 UTC (rev 268922)
+++ trunk/Source/WebKit/ChangeLog 2020-10-23 12:53:42 UTC (rev 268923)
@@ -1,3 +1,15 @@
+2020-10-23 Miguel Gomez <[email protected]>
+
+ [GTK][WPE] Implement antialiased rounded rectangle clipping in TextureMapper
+ https://bugs.webkit.org/show_bug.cgi?id=174457
+
+ Reviewed by Carlos Garcia Campos.
+
+ Use the new TextureMapper::beginClip() method that receives a FloatRoundedRect.
+
+ * Shared/CoordinatedGraphics/CoordinatedGraphicsScene.cpp:
+ (WebKit::CoordinatedGraphicsScene::paintToCurrentGLContext):
+
2020-10-23 Michael Catanzaro <[email protected]>
[SOUP] Fix crash in WebSocketTask
Modified: trunk/Source/WebKit/Shared/CoordinatedGraphics/CoordinatedGraphicsScene.cpp (268922 => 268923)
--- trunk/Source/WebKit/Shared/CoordinatedGraphics/CoordinatedGraphicsScene.cpp 2020-10-23 12:44:44 UTC (rev 268922)
+++ trunk/Source/WebKit/Shared/CoordinatedGraphics/CoordinatedGraphicsScene.cpp 2020-10-23 12:53:42 UTC (rev 268923)
@@ -71,7 +71,7 @@
currentRootLayer->setTextureMapper(m_textureMapper.get());
bool sceneHasRunningAnimations = currentRootLayer->applyAnimationsRecursively(MonotonicTime::now());
m_textureMapper->beginPainting(PaintFlags);
- m_textureMapper->beginClip(TransformationMatrix(), clipRect);
+ m_textureMapper->beginClip(TransformationMatrix(), FloatRoundedRect(clipRect));
if (currentRootLayer->transform() != matrix)
currentRootLayer->setTransform(matrix);