Manual rounding support in OpenGL media viewer.
This commit is contained in:
parent
b9e0c60adf
commit
24a1208b9a
7 changed files with 117 additions and 2 deletions
|
@ -46,6 +46,31 @@ uniform float transparentSize;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] ShaderPart FragmentRoundedCorners() {
|
||||||
|
return {
|
||||||
|
.header = R"(
|
||||||
|
uniform vec4 roundRect;
|
||||||
|
uniform float roundRadius;
|
||||||
|
|
||||||
|
float roundedCorner() {
|
||||||
|
vec2 rectHalf = roundRect.zw / 2.;
|
||||||
|
vec2 rectCenter = roundRect.xy + rectHalf;
|
||||||
|
vec2 fromRectCenter = abs(gl_FragCoord.xy - rectCenter);
|
||||||
|
vec2 vectorRadius = vec2(roundRadius + 0.5, roundRadius + 0.5);
|
||||||
|
vec2 fromCenterWithRadius = fromRectCenter + vectorRadius;
|
||||||
|
vec2 fromRoundingCenter = max(fromCenterWithRadius, rectHalf)
|
||||||
|
- rectHalf;
|
||||||
|
float rounded = length(fromRoundingCenter) - roundRadius;
|
||||||
|
|
||||||
|
return 1. - smoothstep(0., 1., rounded);
|
||||||
|
}
|
||||||
|
)",
|
||||||
|
.body = R"(
|
||||||
|
result = vec4(roundedCorner());
|
||||||
|
)",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
OverlayWidget::RendererGL::RendererGL(not_null<OverlayWidget*> owner)
|
OverlayWidget::RendererGL::RendererGL(not_null<OverlayWidget*> owner)
|
||||||
|
@ -69,7 +94,10 @@ void OverlayWidget::RendererGL::init(
|
||||||
constexpr auto kQuadVertices = kQuads * 4;
|
constexpr auto kQuadVertices = kQuads * 4;
|
||||||
constexpr auto kQuadValues = kQuadVertices * 4;
|
constexpr auto kQuadValues = kQuadVertices * 4;
|
||||||
constexpr auto kControlsValues = kControlsCount * kControlValues;
|
constexpr auto kControlsValues = kControlsCount * kControlValues;
|
||||||
constexpr auto kValues = kQuadValues + kControlsValues;
|
constexpr auto kRoundingQuads = 4;
|
||||||
|
constexpr auto kRoundingVertices = kRoundingQuads * 6;
|
||||||
|
constexpr auto kRoundingValues = kRoundingVertices * 2;
|
||||||
|
constexpr auto kValues = kQuadValues + kControlsValues + kRoundingValues;
|
||||||
|
|
||||||
_contentBuffer.emplace();
|
_contentBuffer.emplace();
|
||||||
_contentBuffer->setUsagePattern(QOpenGLBuffer::DynamicDraw);
|
_contentBuffer->setUsagePattern(QOpenGLBuffer::DynamicDraw);
|
||||||
|
@ -130,6 +158,12 @@ void OverlayWidget::RendererGL::init(
|
||||||
FragmentGlobalOpacity(),
|
FragmentGlobalOpacity(),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
_roundedCornersProgram.emplace();
|
||||||
|
LinkProgram(
|
||||||
|
&*_roundedCornersProgram,
|
||||||
|
VertexShader({ VertexViewportTransform() }),
|
||||||
|
FragmentShader({ FragmentRoundedCorners() }));
|
||||||
|
|
||||||
const auto renderer = reinterpret_cast<const char*>(
|
const auto renderer = reinterpret_cast<const char*>(
|
||||||
f.glGetString(GL_RENDERER));
|
f.glGetString(GL_RENDERER));
|
||||||
CrashReports::SetAnnotation(
|
CrashReports::SetAnnotation(
|
||||||
|
@ -598,6 +632,76 @@ void OverlayWidget::RendererGL::paintGroupThumbs(
|
||||||
}, kGroupThumbsOffset, true);
|
}, kGroupThumbsOffset, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OverlayWidget::RendererGL::paintRoundedCorners(int radius) {
|
||||||
|
const auto topLeft = transformRect(QRect(0, 0, radius, radius));
|
||||||
|
const auto topRight = transformRect(
|
||||||
|
QRect(_viewport.width() - radius, 0, radius, radius));
|
||||||
|
const auto bottomRight = transformRect(QRect(
|
||||||
|
_viewport.width() - radius,
|
||||||
|
_viewport.height() - radius,
|
||||||
|
radius,
|
||||||
|
radius));
|
||||||
|
const auto bottomLeft = transformRect(
|
||||||
|
QRect(0, _viewport.height() - radius, radius, radius));
|
||||||
|
const GLfloat coords[] = {
|
||||||
|
topLeft.left(), topLeft.top(),
|
||||||
|
topLeft.right(), topLeft.top(),
|
||||||
|
topLeft.right(), topLeft.bottom(),
|
||||||
|
topLeft.right(), topLeft.bottom(),
|
||||||
|
topLeft.left(), topLeft.bottom(),
|
||||||
|
topLeft.left(), topLeft.top(),
|
||||||
|
|
||||||
|
topRight.left(), topRight.top(),
|
||||||
|
topRight.right(), topRight.top(),
|
||||||
|
topRight.right(), topRight.bottom(),
|
||||||
|
topRight.right(), topRight.bottom(),
|
||||||
|
topRight.left(), topRight.bottom(),
|
||||||
|
topRight.left(), topRight.top(),
|
||||||
|
|
||||||
|
bottomRight.left(), bottomRight.top(),
|
||||||
|
bottomRight.right(), bottomRight.top(),
|
||||||
|
bottomRight.right(), bottomRight.bottom(),
|
||||||
|
bottomRight.right(), bottomRight.bottom(),
|
||||||
|
bottomRight.left(), bottomRight.bottom(),
|
||||||
|
bottomRight.left(), bottomRight.top(),
|
||||||
|
|
||||||
|
bottomLeft.left(), bottomLeft.top(),
|
||||||
|
bottomLeft.right(), bottomLeft.top(),
|
||||||
|
bottomLeft.right(), bottomLeft.bottom(),
|
||||||
|
bottomLeft.right(), bottomLeft.bottom(),
|
||||||
|
bottomLeft.left(), bottomLeft.bottom(),
|
||||||
|
bottomLeft.left(), bottomLeft.top(),
|
||||||
|
};
|
||||||
|
const auto offset = kControlsOffset
|
||||||
|
+ (kControlsCount * kControlValues) / 4;
|
||||||
|
const auto byteOffset = offset * 4 * sizeof(GLfloat);
|
||||||
|
_contentBuffer->write(byteOffset, coords, sizeof(coords));
|
||||||
|
_roundedCornersProgram->bind();
|
||||||
|
_roundedCornersProgram->setUniformValue("viewport", _uniformViewport);
|
||||||
|
const auto roundRect = transformRect(QRect(QPoint(), _viewport));
|
||||||
|
_roundedCornersProgram->setUniformValue("roundRect", Uniform(roundRect));
|
||||||
|
_roundedCornersProgram->setUniformValue(
|
||||||
|
"roundRadius",
|
||||||
|
GLfloat(radius * _factor));
|
||||||
|
|
||||||
|
_f->glEnable(GL_BLEND);
|
||||||
|
_f->glBlendFunc(GL_ZERO, GL_SRC_ALPHA);
|
||||||
|
|
||||||
|
GLint position = _roundedCornersProgram->attributeLocation("position");
|
||||||
|
_f->glVertexAttribPointer(
|
||||||
|
position,
|
||||||
|
2,
|
||||||
|
GL_FLOAT,
|
||||||
|
GL_FALSE,
|
||||||
|
2 * sizeof(GLfloat),
|
||||||
|
reinterpret_cast<const void*>(byteOffset));
|
||||||
|
_f->glEnableVertexAttribArray(position);
|
||||||
|
|
||||||
|
_f->glDrawArrays(GL_TRIANGLES, 0, base::array_size(coords) / 2);
|
||||||
|
|
||||||
|
_f->glDisableVertexAttribArray(position);
|
||||||
|
}
|
||||||
|
|
||||||
void OverlayWidget::RendererGL::invalidate() {
|
void OverlayWidget::RendererGL::invalidate() {
|
||||||
_trackFrameIndex = -1;
|
_trackFrameIndex = -1;
|
||||||
_streamedIndex = -1;
|
_streamedIndex = -1;
|
||||||
|
|
|
@ -68,6 +68,7 @@ private:
|
||||||
void paintFooter(QRect outer, float64 opacity) override;
|
void paintFooter(QRect outer, float64 opacity) override;
|
||||||
void paintCaption(QRect outer, float64 opacity) override;
|
void paintCaption(QRect outer, float64 opacity) override;
|
||||||
void paintGroupThumbs(QRect outer, float64 opacity) override;
|
void paintGroupThumbs(QRect outer, float64 opacity) override;
|
||||||
|
void paintRoundedCorners(int radius) override;
|
||||||
|
|
||||||
void invalidate();
|
void invalidate();
|
||||||
|
|
||||||
|
@ -110,6 +111,7 @@ private:
|
||||||
std::optional<QOpenGLShaderProgram> _nv12Program;
|
std::optional<QOpenGLShaderProgram> _nv12Program;
|
||||||
std::optional<QOpenGLShaderProgram> _fillProgram;
|
std::optional<QOpenGLShaderProgram> _fillProgram;
|
||||||
std::optional<QOpenGLShaderProgram> _controlsProgram;
|
std::optional<QOpenGLShaderProgram> _controlsProgram;
|
||||||
|
std::optional<QOpenGLShaderProgram> _roundedCornersProgram;
|
||||||
Ui::GL::Textures<4> _textures;
|
Ui::GL::Textures<4> _textures;
|
||||||
QSize _rgbaSize;
|
QSize _rgbaSize;
|
||||||
QSize _lumaSize;
|
QSize _lumaSize;
|
||||||
|
|
|
@ -190,4 +190,8 @@ void OverlayWidget::RendererSW::paintGroupThumbs(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OverlayWidget::RendererSW::paintRoundedCorners(int radius) {
|
||||||
|
// The RpWindow rounding overlay will do the job.
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Media::View
|
} // namespace Media::View
|
||||||
|
|
|
@ -50,6 +50,7 @@ private:
|
||||||
void paintFooter(QRect outer, float64 opacity) override;
|
void paintFooter(QRect outer, float64 opacity) override;
|
||||||
void paintCaption(QRect outer, float64 opacity) override;
|
void paintCaption(QRect outer, float64 opacity) override;
|
||||||
void paintGroupThumbs(QRect outer, float64 opacity) override;
|
void paintGroupThumbs(QRect outer, float64 opacity) override;
|
||||||
|
void paintRoundedCorners(int radius) override;
|
||||||
|
|
||||||
[[nodiscard]] static QRect TransformRect(QRectF geometry, int rotation);
|
[[nodiscard]] static QRect TransformRect(QRectF geometry, int rotation);
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,7 @@ public:
|
||||||
virtual void paintFooter(QRect outer, float64 opacity) = 0;
|
virtual void paintFooter(QRect outer, float64 opacity) = 0;
|
||||||
virtual void paintCaption(QRect outer, float64 opacity) = 0;
|
virtual void paintCaption(QRect outer, float64 opacity) = 0;
|
||||||
virtual void paintGroupThumbs(QRect outer, float64 opacity) = 0;
|
virtual void paintGroupThumbs(QRect outer, float64 opacity) = 0;
|
||||||
|
virtual void paintRoundedCorners(int radius) = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -3692,6 +3692,9 @@ void OverlayWidget::paint(not_null<Renderer*> renderer) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
checkGroupThumbsAnimation();
|
checkGroupThumbsAnimation();
|
||||||
|
if (const auto radius = _window->manualRoundingRadius()) {
|
||||||
|
renderer->paintRoundedCorners(radius);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OverlayWidget::checkGroupThumbsAnimation() {
|
void OverlayWidget::checkGroupThumbsAnimation() {
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit eb4d44ecd37815dc9465ec46b86f94191531b0c7
|
Subproject commit 3b69ec499ccc7f4208a6413fbeb6f5ebe84f3f55
|
Loading…
Reference in a new issue